]> git.sur5r.net Git - cc65/blob - src/ca65/objcode.c
Fixed _textcolor definition.
[cc65] / src / ca65 / objcode.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 objcode.c                                 */
4 /*                                                                           */
5 /*             Objectcode management for the ca65 macroassembler             */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2011, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37 #include <errno.h>
38
39 /* cc65 */
40 #include "error.h"
41 #include "fragment.h"
42 #include "objcode.h"
43 #include "segment.h"
44
45
46
47 /*****************************************************************************/
48 /*                                   Code                                    */
49 /*****************************************************************************/
50
51
52
53 void Emit0 (unsigned char OPC)
54 /* Emit an instruction with a zero sized operand */
55 {
56     Fragment* F = GenFragment (FRAG_LITERAL, 1);
57     F->V.Data[0] = OPC;
58 }
59
60
61
62 void Emit1 (unsigned char OPC, ExprNode* Value)
63 /* Emit an instruction with an one byte argument */
64 {
65     long V;
66     Fragment* F;
67
68     if (IsEasyConst (Value, &V)) {
69
70         /* Must be in byte range */
71         if (!IsByteRange (V)) {
72             Error ("Range error (%ld not in [0..255])", V);
73         }
74
75         /* Create a literal fragment */
76         F = GenFragment (FRAG_LITERAL, 2);
77         F->V.Data[0] = OPC;
78         F->V.Data[1] = (unsigned char) V;
79         FreeExpr (Value);
80
81     } else {
82
83         /* Emit the opcode */
84         Emit0 (OPC);
85
86         /* Emit the argument as an expression */
87         F = GenFragment (FRAG_EXPR, 1);
88         F->V.Expr = Value;
89     }
90 }
91
92
93
94 void Emit2 (unsigned char OPC, ExprNode* Value)
95 /* Emit an instruction with a two byte argument */
96 {
97     long V;
98     Fragment* F;
99
100     if (IsEasyConst (Value, &V)) {
101
102         /* Must be in byte range */
103         if (!IsWordRange (V)) {
104             Error ("Range error (%ld not in [0..65535])", V);
105         }
106
107         /* Create a literal fragment */
108         F = GenFragment (FRAG_LITERAL, 3);
109         F->V.Data[0] = OPC;
110         F->V.Data[1] = (unsigned char) V;
111         F->V.Data[2] = (unsigned char) (V >> 8);
112         FreeExpr (Value);
113
114     } else {
115
116         /* Emit the opcode */
117         Emit0 (OPC);
118
119         /* Emit the argument as an expression */
120         F = GenFragment (FRAG_EXPR, 2);
121         F->V.Expr = Value;
122     }
123 }
124
125
126
127 void Emit3 (unsigned char OPC, ExprNode* Expr)
128 /* Emit an instruction with a three byte argument */
129 {
130     Emit0 (OPC);
131     EmitFarAddr (Expr);
132 }
133
134
135
136 void EmitSigned (ExprNode* Expr, unsigned Size)
137 /* Emit a signed expression with the given size */
138 {
139     Fragment* F = GenFragment (FRAG_SEXPR, Size);
140     F->V.Expr = Expr;
141 }
142
143
144
145 void EmitPCRel (unsigned char OPC, ExprNode* Expr, unsigned Size)
146 /* Emit an opcode with a PC relative argument of one or two bytes */
147 {
148     Emit0 (OPC);
149     EmitSigned (Expr, Size);
150 }
151
152
153
154 void EmitData (const void* D, unsigned Size)
155 /* Emit data into the current segment */
156 {
157     /* Make a useful pointer from Data */
158     const unsigned char* Data = D;
159
160     /* Create lots of fragments for the data */
161     while (Size) {
162         Fragment* F;
163
164         /* Determine the length of the next fragment */
165         unsigned Len = Size;
166         if (Len > sizeof (F->V.Data)) {
167             Len = sizeof (F->V.Data);
168         }
169
170         /* Create a new fragment */
171         F = GenFragment (FRAG_LITERAL, Len);
172
173         /* Copy the data */
174         memcpy (F->V.Data, Data, Len);
175
176         /* Next chunk */
177         Data += Len;
178         Size -= Len;
179
180     }
181 }
182
183
184
185 void EmitStrBuf (const StrBuf* Data)
186 /* Emit a string into the current segment */
187 {
188     /* Use EmitData to output the data */
189     EmitData (SB_GetConstBuf (Data), SB_GetLen (Data));
190 }
191
192
193
194 void EmitByte (ExprNode* Expr)
195 /* Emit one byte */
196 {
197     long V;
198     Fragment* F;
199
200     if (IsEasyConst (Expr, &V)) {
201         /* Must be in byte range */
202         if (!IsByteRange (V)) {
203             Error ("Range error (%ld not in [0..255])", V);
204         }
205
206         /* Create a literal fragment */
207         F = GenFragment (FRAG_LITERAL, 1);
208         F->V.Data[0] = (unsigned char) V;
209         FreeExpr (Expr);
210     } else {
211         /* Emit the argument as an expression */
212         F = GenFragment (FRAG_EXPR, 1);
213         F->V.Expr = Expr;
214     }
215 }
216
217
218
219 void EmitWord (ExprNode* Expr)
220 /* Emit one word */
221 {
222     long V;
223     Fragment* F;
224
225     if (IsEasyConst (Expr, &V)) {
226         /* Must be in byte range */
227         if (!IsWordRange (V)) {
228             Error ("Range error (%ld not in [0..65535])", V);
229         }
230
231         /* Create a literal fragment */
232         F = GenFragment (FRAG_LITERAL, 2);
233         F->V.Data[0] = (unsigned char) V;
234         F->V.Data[1] = (unsigned char) (V >> 8);
235         FreeExpr (Expr);
236     } else {
237         /* Emit the argument as an expression */
238         Fragment* F = GenFragment (FRAG_EXPR, 2);
239         F->V.Expr = Expr;
240     }
241 }
242
243
244
245 void EmitFarAddr (ExprNode* Expr)
246 /* Emit a 24 bit expression */
247 {
248     /* Create a new fragment */
249     Fragment* F = GenFragment (FRAG_EXPR, 3);
250
251     /* Set the data */
252     F->V.Expr = Expr;
253 }
254
255
256
257 void EmitDWord (ExprNode* Expr)
258 /* Emit one dword */
259 {
260     /* Create a new fragment */
261     Fragment* F = GenFragment (FRAG_EXPR, 4);
262
263     /* Set the data */
264     F->V.Expr = Expr;
265 }
266
267
268
269 void EmitFill (unsigned long Count)
270 /* Emit Count fill bytes */
271 {
272     while (Count) {
273         /* Calculate the size of the next chunk */
274         unsigned Chunk = (Count > 0xFFFF)? 0xFFFF : (unsigned) Count;
275         Count -= Chunk;
276
277         /* Emit one chunk */
278         GenFragment (FRAG_FILL, Chunk);
279     }
280 }