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
53void 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
62void 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
94void 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
127void 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
136void 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
145void 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
154void 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
185void 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
194void 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
219void 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
245void 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
257void 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
269void 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}
281