]> git.sur5r.net Git - cc65/blob - src/ca65/objcode.c
Allow conditional directives within .STRUCT7:UNION and .ENUM
[cc65] / src / ca65 / objcode.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 objcode.c                                 */
4 /*                                                                           */
5 /*             Objectcode management for the ca65 macroassembler             */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstraße 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     Emit0 (OPC);
66     EmitByte (Value);
67 }
68
69
70
71 void Emit2 (unsigned char OPC, ExprNode* Value)
72 /* Emit an instruction with a two byte argument */
73 {
74     Emit0 (OPC);
75     EmitWord (Value);
76 }
77
78
79
80 void Emit3 (unsigned char OPC, ExprNode* Expr)
81 /* Emit an instruction with a three byte argument */
82 {
83     Emit0 (OPC);
84     EmitFarAddr (Expr);
85 }
86
87
88
89 void Emit3b (unsigned char OPC, ExprNode* Expr, ExprNode* Bank)
90 /* Emit an instruction with a three byte argument and separate bank */
91 {
92     Emit0 (OPC);
93     EmitWord (Expr);
94     EmitByte (Bank);
95 }
96
97
98
99 void EmitSigned (ExprNode* Expr, unsigned Size)
100 /* Emit a signed expression with the given size */
101 {
102     Fragment* F = GenFragment (FRAG_SEXPR, Size);
103     F->V.Expr = Expr;
104 }
105
106
107
108 void EmitPCRel (unsigned char OPC, ExprNode* Expr, unsigned Size)
109 /* Emit an opcode with a PC relative argument of one or two bytes */
110 {
111     Emit0 (OPC);
112     EmitSigned (Expr, Size);
113 }
114
115
116
117 void EmitData (const unsigned char* Data, unsigned Size)
118 /* Emit data into the current segment */
119 {
120     /* Create lots of fragments for the data */
121     while (Size) {
122         Fragment* F;
123
124         /* Determine the length of the next fragment */
125         unsigned Len = Size;
126         if (Len > sizeof (F->V.Data)) {
127             Len = sizeof (F->V.Data);
128         }
129
130         /* Create a new fragment */
131         F = GenFragment (FRAG_LITERAL, Len);
132
133         /* Copy the data */
134         memcpy (F->V.Data, Data, Len);
135
136         /* Next chunk */
137         Data += Len;
138         Size -= Len;
139
140     }
141 }
142
143
144
145 void EmitByte (ExprNode* Expr)
146 /* Emit one byte */
147 {                  
148     long Val;
149     if (IsConstExpr (Expr, &Val)) {
150         /* Constant expression, emit literal byte */
151         FreeExpr (Expr);
152         if ((Val & ~0xFF) != 0) {
153             Error ("Range error");
154         }
155         Emit0 (Val & 0xFF);
156     } else {
157         /* Create a new fragment */
158         Fragment* F = GenFragment (FRAG_EXPR, 1);
159
160         /* Set the data */
161         F->V.Expr = Expr;
162     }
163 }
164
165
166
167 void EmitWord (ExprNode* Expr)
168 /* Emit one word */
169 {
170     long Val;
171     if (IsConstExpr (Expr, &Val)) {
172         /* Constant expression, emit literal byte */
173         FreeExpr (Expr);
174         if ((Val & ~0xFFFF) != 0) {
175             Error ("Range error");
176         }
177         Emit0 (Val & 0xFF);
178         Emit0 ((Val >> 8) & 0xFF);
179     } else {
180         /* Create a new fragment */
181         Fragment* F = GenFragment (FRAG_EXPR, 2);
182
183         /* Set the data */
184         F->V.Expr = Expr;
185     }
186 }
187
188
189
190 void EmitFarAddr (ExprNode* Expr)
191 /* Emit a 24 bit expression */
192 {
193     long Val;
194     if (IsConstExpr (Expr, &Val)) {
195         /* Constant expression, emit literal byte */
196         FreeExpr (Expr);
197         if ((Val & ~0xFFFFFF) != 0) {
198             Error ("Range error");
199         }
200         Emit0 (Val & 0xFF);
201         Emit0 ((Val >> 8) & 0xFF);
202         Emit0 ((Val >> 16) & 0xFF);
203     } else {
204         /* Create a new fragment */
205         Fragment* F = GenFragment (FRAG_EXPR, 3);
206
207         /* Set the data */
208         F->V.Expr = Expr;
209     }
210 }
211
212
213
214 void EmitDWord (ExprNode* Expr)
215 /* Emit one dword */
216 {
217     long Val;
218     if (IsConstExpr (Expr, &Val)) {
219         /* Constant expression, emit literal byte */
220         FreeExpr (Expr);
221         Emit0 (Val & 0xFF);
222         Emit0 ((Val >> 8) & 0xFF);
223         Emit0 ((Val >> 16) & 0xFF);
224         Emit0 ((Val >> 24) & 0xFF);
225     } else {
226         /* Create a new fragment */
227         Fragment* F = GenFragment (FRAG_EXPR, 4);
228
229         /* Set the data */
230         F->V.Expr = Expr;
231     }
232 }
233
234
235
236 void EmitFill (unsigned long Count)
237 /* Emit Count fill bytes */
238 {
239     while (Count) {
240         /* Calculate the size of the next chunk */
241         unsigned Chunk = (Count > 0xFFFF)? 0xFFFF : (unsigned) Count;
242         Count -= Chunk;
243
244         /* Emit one chunk */
245         GenFragment (FRAG_FILL, Chunk);
246     }
247 }
248
249
250