1 |
2 |
jsauermann |
|
2 |
|
|
#include <stdio.h>
|
3 |
|
|
#include <string.h>
|
4 |
|
|
#include <assert.h>
|
5 |
|
|
|
6 |
|
|
#include "Backend.hh"
|
7 |
|
|
#include "Node.hh"
|
8 |
|
|
|
9 |
|
|
extern bool is_loader;
|
10 |
|
|
extern int memtop;
|
11 |
|
|
|
12 |
|
|
int Backend::stack_pointer = 0;
|
13 |
|
|
int Backend::label_num = 1;
|
14 |
|
|
int Backend::function_num = 1;
|
15 |
|
|
|
16 |
|
|
//-----------------------------------------------------------------------------
|
17 |
|
|
int Backend::check_size(int size, const char * function)
|
18 |
|
|
{
|
19 |
|
|
if (size == 1) return 8;
|
20 |
|
|
if (size == 2) return 16;
|
21 |
29 |
jsauermann |
fprintf(stderr, "Backend::%s does not support %d bits\n",
|
22 |
|
|
function, size * 8);
|
23 |
2 |
jsauermann |
return 0;
|
24 |
|
|
}
|
25 |
|
|
//-----------------------------------------------------------------------------
|
26 |
|
|
int Backend::check_size(SUW suw, const char * function)
|
27 |
|
|
{
|
28 |
|
|
if (suw == SB) return 8;
|
29 |
|
|
else if (suw == UB) return 8;
|
30 |
|
|
else if (suw == WO) return 16;
|
31 |
|
|
assert(0);
|
32 |
|
|
}
|
33 |
|
|
//-----------------------------------------------------------------------------
|
34 |
|
|
void Backend::file_header()
|
35 |
|
|
{
|
36 |
|
|
if (is_loader)
|
37 |
|
|
fprintf(out,
|
38 |
|
|
"IN_RX_DATA\t= 0x00\t\t\t;\n"
|
39 |
|
|
"IN_STATUS\t= 0x01\t\t\t;\n"
|
40 |
|
|
"\n"
|
41 |
|
|
"MEMTOP\t\t= 0x%4.4X\n"
|
42 |
|
|
"\n"
|
43 |
|
|
"OUT_TX_DATA\t= 0x00\t\t\t;\n"
|
44 |
|
|
";---------------------------------------;\n"
|
45 |
|
|
"RELOC_SRC\t= start+Cend_text-stack\t;\n"
|
46 |
|
|
";---------------------------------------;\n"
|
47 |
|
|
"\t\t\t\t\t;\n"
|
48 |
|
|
"\tMOVE\t#reloc_rr, RR\t\t;\n"
|
49 |
|
|
"\tMOVE\tRR, SP\t\t\t;\n"
|
50 |
|
|
"\tMOVE\t#MEMTOP, LL\t\t; destination\n"
|
51 |
|
|
"reloc:\t\t\t\t\t;\n"
|
52 |
|
|
"\tMOVE\t(SP)+, RR\t\t; restore source\n"
|
53 |
|
|
"\tMOVE\t-(RR), -(LL)\t\t;\n"
|
54 |
|
|
"\tMOVE\tRR, -(SP)\t\t; save source\n"
|
55 |
|
|
"\tSHI\tRR, #start\t\t;\n"
|
56 |
|
|
"\tJMP\tRRNZ, reloc\t\t;\n"
|
57 |
|
|
"\tMOVE\t#stack, RR\t\t;\n"
|
58 |
|
|
"\tMOVE\tRR, SP\t\t\t;\n"
|
59 |
|
|
"\tCALL\tCmain\t\t\t;\n"
|
60 |
|
|
"halt:\t\t\t\t\t;\n"
|
61 |
|
|
"\tHALT\t\t\t\t;\n"
|
62 |
|
|
"reloc_rr:\t\t\t\t; source\n"
|
63 |
|
|
"\t.WORD\tRELOC_SRC\t\t;\n"
|
64 |
|
|
";---------------------------------------;\n"
|
65 |
|
|
"start:\t\t\t\t\t;\n"
|
66 |
|
|
"\t.OFFSET\tMEMTOP\t\t\t;\n"
|
67 |
|
|
"stack:\t\t\t\t\t;\n"
|
68 |
|
|
";---------------------------------------;\n", memtop);
|
69 |
|
|
else
|
70 |
|
|
fprintf(out,
|
71 |
|
|
"IN_RX_DATA\t\t= 0x00\t\t;\n"
|
72 |
|
|
"IN_STATUS\t\t= 0x01\t\t;\n"
|
73 |
|
|
"IN_TEMPERAT\t\t= 0x02\t\t;\n"
|
74 |
|
|
"IN_DIP_SWITCH\t\t= 0x03\t\t;\n"
|
75 |
|
|
"IN_CLK_CTR_LOW\t\t= 0x05\t\t;\n"
|
76 |
|
|
"IN_CLK_CTR_HIGH\t\t= 0x06\t\t;\n"
|
77 |
|
|
"\n"
|
78 |
|
|
"MEMTOP\t=0x%4.4X\n"
|
79 |
|
|
"\n"
|
80 |
|
|
"OUT_TX_DATA\t\t= 0x00\t\t;\n"
|
81 |
|
|
"OUT_LEDS\t\t= 0x02\t\t;\n"
|
82 |
|
|
"OUT_INT_MASK\t\t= 0x03\t\t;\n"
|
83 |
|
|
"OUT_RESET_TIMER\t\t= 0x04\t\t;\n"
|
84 |
|
|
"OUT_START_CLK_CTR\t= 0x05\t\t;\n"
|
85 |
|
|
"OUT_STOP_CLK_CTR\t= 0x06\t\t;\n"
|
86 |
|
|
";---------------------------------------;\n"
|
87 |
|
|
"\tMOVE\t#MEMTOP, RR\t\t;\n"
|
88 |
|
|
"\tMOVE\tRR, SP\t\t\t;\n"
|
89 |
|
|
"\tEI\t\t\t\t;\n"
|
90 |
|
|
"\tJMP\tCmain\t\t\t;\n"
|
91 |
|
|
"\tJMP\tCinterrupt\t\t;\n"
|
92 |
|
|
";---------------------------------------;\n"
|
93 |
|
|
"mult_div:\t\t\t\t;\n"
|
94 |
|
|
"\tMD_STP\t\t\t\t; 1\n"
|
95 |
|
|
"\tMD_STP\t\t\t\t; 2\n"
|
96 |
|
|
"\tMD_STP\t\t\t\t; 3\n"
|
97 |
|
|
"\tMD_STP\t\t\t\t; 4\n"
|
98 |
|
|
"\tMD_STP\t\t\t\t; 5\n"
|
99 |
|
|
"\tMD_STP\t\t\t\t; 6\n"
|
100 |
|
|
"\tMD_STP\t\t\t\t; 7\n"
|
101 |
|
|
"\tMD_STP\t\t\t\t; 8\n"
|
102 |
|
|
"\tMD_STP\t\t\t\t; 9\n"
|
103 |
|
|
"\tMD_STP\t\t\t\t; 10\n"
|
104 |
|
|
"\tMD_STP\t\t\t\t; 11\n"
|
105 |
|
|
"\tMD_STP\t\t\t\t; 12\n"
|
106 |
|
|
"\tMD_STP\t\t\t\t; 13\n"
|
107 |
|
|
"\tMD_STP\t\t\t\t; 14\n"
|
108 |
|
|
"\tMD_STP\t\t\t\t; 15\n"
|
109 |
|
|
"\tMD_STP\t\t\t\t; 16\n"
|
110 |
|
|
"\tRET\t\t\t\t;\n"
|
111 |
|
|
";---------------------------------------;\n", memtop);
|
112 |
|
|
}
|
113 |
|
|
//-----------------------------------------------------------------------------
|
114 |
|
|
void Backend::file_footer()
|
115 |
|
|
{
|
116 |
|
|
fprintf(out, "Cend_text:\t\t\t\t;\n");
|
117 |
|
|
}
|
118 |
|
|
//-----------------------------------------------------------------------------
|
119 |
|
|
int Backend::new_function(const char * fname)
|
120 |
|
|
{
|
121 |
|
|
fprintf(out, "C%s:\n", fname);
|
122 |
|
|
fflush(out);
|
123 |
|
|
assert(stack_pointer == 0);
|
124 |
|
|
function_num++;
|
125 |
|
|
}
|
126 |
|
|
//-----------------------------------------------------------------------------
|
127 |
|
|
void Backend::asmbl(const char * asm_string)
|
128 |
|
|
{
|
129 |
|
|
if (*asm_string == ' ') fprintf(out, "\t%s\n", asm_string + 1);
|
130 |
|
|
else fprintf(out, "%s\n", asm_string);
|
131 |
|
|
|
132 |
|
|
char buffer[256];
|
133 |
|
|
int bufidx = 0;
|
134 |
|
|
bool inside = true;
|
135 |
|
|
|
136 |
|
|
for (;;)
|
137 |
|
|
{
|
138 |
|
|
char c = *asm_string++;
|
139 |
|
|
switch(c)
|
140 |
|
|
{
|
141 |
|
|
case 0:
|
142 |
|
|
case '\r':
|
143 |
|
|
case '\n': buffer[bufidx] = 0;
|
144 |
|
|
asm_adjust(buffer);
|
145 |
|
|
bufidx = 0;
|
146 |
|
|
inside = true;
|
147 |
|
|
if (c == 0) return;
|
148 |
|
|
break;
|
149 |
|
|
|
150 |
|
|
case ';' : inside = false;
|
151 |
|
|
break;
|
152 |
|
|
|
153 |
|
|
case ' ': break; // ignore spaces
|
154 |
|
|
|
155 |
|
|
default: assert(bufidx < (sizeof(buffer) - 3));
|
156 |
|
|
if (inside) buffer[bufidx++] = c;
|
157 |
|
|
}
|
158 |
|
|
}
|
159 |
|
|
}
|
160 |
|
|
//-----------------------------------------------------------------------------
|
161 |
|
|
void Backend::asm_adjust(const char * asm_line)
|
162 |
|
|
{
|
163 |
|
|
int osp = stack_pointer;
|
164 |
|
|
bool need_adjust = false;
|
165 |
|
|
|
166 |
|
|
if (strstr(asm_line, "-(SP)"))
|
167 |
|
|
{
|
168 |
|
|
need_adjust = true;
|
169 |
|
|
if (strstr(asm_line, "RR,")) stack_pointer -= 2;
|
170 |
|
|
else if (strstr(asm_line, "R,")) stack_pointer -= 1;
|
171 |
|
|
else if (strstr(asm_line, "CLRW")) stack_pointer -= 2;
|
172 |
|
|
else if (strstr(asm_line, "CLRB")) stack_pointer -= 1;
|
173 |
|
|
}
|
174 |
|
|
|
175 |
|
|
if (strstr(asm_line, "(SP)+"))
|
176 |
|
|
{
|
177 |
|
|
need_adjust = true;
|
178 |
|
|
if (strstr(asm_line, ",RR")) stack_pointer += 2;
|
179 |
|
|
else if (strstr(asm_line, ",RS")) stack_pointer += 1;
|
180 |
|
|
else if (strstr(asm_line, ",RU")) stack_pointer += 1;
|
181 |
|
|
else if (strstr(asm_line, ",LL")) stack_pointer += 2;
|
182 |
|
|
else if (strstr(asm_line, ",LS")) stack_pointer += 1;
|
183 |
|
|
else if (strstr(asm_line, ",LU")) stack_pointer += 1;
|
184 |
|
|
}
|
185 |
|
|
|
186 |
|
|
if (need_adjust && osp == stack_pointer)
|
187 |
|
|
{
|
188 |
|
|
fprintf(out, "Bad ASM()\n");
|
189 |
|
|
Node::Error();
|
190 |
|
|
}
|
191 |
|
|
}
|
192 |
|
|
//-----------------------------------------------------------------------------
|
193 |
|
|
void Backend::load_rr_string(int snum, int offset)
|
194 |
|
|
{
|
195 |
|
|
fprintf(out, ";--\tload_rr_string\n");
|
196 |
|
|
|
197 |
|
|
if (offset) fprintf(out, "\tMOVE\t#Cstr_%d + %d, RR\n", snum, offset);
|
198 |
|
|
else fprintf(out, "\tMOVE\t#Cstr_%d, RR\n", snum);
|
199 |
|
|
}
|
200 |
|
|
//-----------------------------------------------------------------------------
|
201 |
|
|
void Backend::load_ll_string(int snum, int offset)
|
202 |
|
|
{
|
203 |
|
|
fprintf(out, ";--\tload_ll_string\n");
|
204 |
|
|
|
205 |
|
|
if (offset) fprintf(out, "\tMOVE\t#Cstr_%d + %d, LL\n", snum, offset);
|
206 |
|
|
else fprintf(out, "\tMOVE\t#Cstr_%d, LL\n", snum);
|
207 |
|
|
}
|
208 |
|
|
//-----------------------------------------------------------------------------
|
209 |
|
|
void Backend::load_rr_constant(int constant)
|
210 |
|
|
{
|
211 |
|
|
fprintf(out, ";--\tload_rr_constant\n");
|
212 |
|
|
fprintf(out, "\tMOVE\t#0x%4.4X, RR\n", constant & 0xFFFF);
|
213 |
|
|
}
|
214 |
|
|
//-----------------------------------------------------------------------------
|
215 |
|
|
void Backend::load_ll_constant(int constant)
|
216 |
|
|
{
|
217 |
|
|
fprintf(out, ";--\tload_ll_constant\n");
|
218 |
|
|
fprintf(out, "\tMOVE\t#0x%4.4X, LL\n", constant & 0xFFFF);
|
219 |
|
|
}
|
220 |
|
|
//-----------------------------------------------------------------------------
|
221 |
|
|
void Backend::load_rr_var(const char * name, SUW suw)
|
222 |
|
|
{
|
223 |
|
|
fprintf(out, ";--\tload_rr_var %s, (%d bit)\n",
|
224 |
|
|
name, check_size(suw, "load_rr_var"));
|
225 |
|
|
if (suw == SB) fprintf(out, "\tMOVE\t(C%s), RS\n", name);
|
226 |
|
|
else if (suw == UB) fprintf(out, "\tMOVE\t(C%s), RU\n", name);
|
227 |
|
|
else fprintf(out, "\tMOVE\t(C%s), RR\n", name);
|
228 |
|
|
}
|
229 |
|
|
//-----------------------------------------------------------------------------
|
230 |
|
|
void Backend::load_ll_var(const char * name, SUW suw)
|
231 |
|
|
{
|
232 |
|
|
fprintf(out, ";--\tload_ll_var %s, (%d bit)\n",
|
233 |
|
|
name, check_size(suw, "load_ll_var"));
|
234 |
|
|
if (suw == SB) fprintf(out, "\tMOVE\t(C%s), LS\n", name);
|
235 |
|
|
else if (suw == UB) fprintf(out, "\tMOVE\t(C%s), LU\n", name);
|
236 |
|
|
else fprintf(out, "\tMOVE\t(C%s), LL\n", name);
|
237 |
|
|
}
|
238 |
|
|
//-----------------------------------------------------------------------------
|
239 |
|
|
void Backend::load_rr_var(const char * name, int sp_off, SUW suw)
|
240 |
|
|
{
|
241 |
|
|
fprintf(out, ";--\tload_rr_var %s = %d(FP), SP at %d (%d bit)\n",
|
242 |
|
|
name, sp_off, GetSP(), check_size(suw, "load_rr_var"));
|
243 |
|
|
|
244 |
|
|
sp_off -= GetSP();
|
245 |
|
|
if (suw == SB) fprintf(out, "\tMOVE\t%d(SP), RS\n", sp_off);
|
246 |
|
|
else if (suw == UB) fprintf(out, "\tMOVE\t%d(SP), RU\n", sp_off);
|
247 |
|
|
else fprintf(out, "\tMOVE\t%d(SP), RR\n", sp_off);
|
248 |
|
|
}
|
249 |
|
|
//-----------------------------------------------------------------------------
|
250 |
|
|
void Backend::load_ll_var(const char * name, int sp_off, SUW suw)
|
251 |
|
|
{
|
252 |
|
|
fprintf(out, ";--\tload_ll_var %s = %d(FP), SP at %d (%d bit)\n",
|
253 |
|
|
name, sp_off, GetSP(), check_size(suw, "load_ll_var"));
|
254 |
|
|
|
255 |
|
|
sp_off -= GetSP();
|
256 |
|
|
if (suw == SB) fprintf(out, "\tMOVE\t%d(SP), LS\n", sp_off);
|
257 |
|
|
else if (suw == UB) fprintf(out, "\tMOVE\t%d(SP), LU\n", sp_off);
|
258 |
|
|
else fprintf(out, "\tMOVE\t%d(SP), LL\n", sp_off);
|
259 |
|
|
}
|
260 |
|
|
//-----------------------------------------------------------------------------
|
261 |
|
|
void Backend::store_rr_var(const char * name, SUW suw)
|
262 |
|
|
{
|
263 |
|
|
fprintf(out, ";--\tstore_rr_var %s\n", name);
|
264 |
|
|
if (suw == WO) fprintf(out, "\tMOVE\tRR, (C%s)\n", name);
|
265 |
|
|
else fprintf(out, "\tMOVE\tR, (C%s)\n", name);
|
266 |
|
|
}
|
267 |
|
|
//-----------------------------------------------------------------------------
|
268 |
|
|
void Backend::store_rr_var(const char * name, int sp_off, SUW suw)
|
269 |
|
|
{
|
270 |
|
|
fprintf(out, ";--\tstore_rr_var %s = %d(FP), SP at %d\n",
|
271 |
|
|
name, sp_off, GetSP());
|
272 |
|
|
|
273 |
|
|
sp_off -= GetSP();
|
274 |
|
|
if (suw == WO) fprintf(out, "\tMOVE\tRR, %d(SP)\n", sp_off);
|
275 |
|
|
else fprintf(out, "\tMOVE\tR, %d(SP)\n", sp_off);
|
276 |
|
|
}
|
277 |
|
|
//-----------------------------------------------------------------------------
|
278 |
|
|
void Backend::load_address(const char * name)
|
279 |
|
|
{
|
280 |
|
|
fprintf(out, ";--\tload_address %s\n", name);
|
281 |
|
|
fprintf(out, "\tMOVE\t#C%s, RR\n", name);
|
282 |
|
|
}
|
283 |
|
|
//-----------------------------------------------------------------------------
|
284 |
|
|
void Backend::load_address(const char * name, int sp_offset)
|
285 |
|
|
{
|
286 |
|
|
fprintf(out, ";--\tload_address %s = %d(FP), SP at %d\n",
|
287 |
|
|
name, sp_offset, GetSP());
|
288 |
|
|
fprintf(out, "\tLEA\t%d(SP), RR\n", sp_offset - GetSP());
|
289 |
|
|
}
|
290 |
|
|
//-----------------------------------------------------------------------------
|
291 |
|
|
void Backend::add_address(const char * name)
|
292 |
|
|
{
|
293 |
|
|
fprintf(out, ";--\tadd_address %s\n", name);
|
294 |
|
|
fprintf(out, "\tADD\tRR, #C%s\n", name);
|
295 |
|
|
}
|
296 |
|
|
//-----------------------------------------------------------------------------
|
297 |
|
|
void Backend::assign(int size)
|
298 |
|
|
{
|
299 |
|
|
fprintf(out, ";--\tassign (%d bit)\n", check_size(size, "assign"));
|
300 |
|
|
if (size == 1) fprintf(out, "\tMOVE\tR, (LL)\n");
|
301 |
|
|
else fprintf(out, "\tMOVE\tRR, (LL)\n");
|
302 |
|
|
}
|
303 |
|
|
//-----------------------------------------------------------------------------
|
304 |
|
|
void Backend::call(const char * name)
|
305 |
|
|
{
|
306 |
|
|
fprintf(out, ";--\tcall\n");
|
307 |
|
|
fprintf(out, "\tCALL\tC%s\n", name);
|
308 |
|
|
}
|
309 |
|
|
//-----------------------------------------------------------------------------
|
310 |
|
|
void Backend::call_ptr()
|
311 |
|
|
{
|
312 |
|
|
fprintf(out, ";--\tcall_ptr\n");
|
313 |
|
|
fprintf(out, "\tCALL\t(RR)\n");
|
314 |
|
|
}
|
315 |
|
|
//-----------------------------------------------------------------------------
|
316 |
7 |
jsauermann |
void Backend::ret()
|
317 |
2 |
jsauermann |
{
|
318 |
|
|
fprintf(out, ";--\tret\n");
|
319 |
7 |
jsauermann |
|
320 |
|
|
assert(stack_pointer <= 0);
|
321 |
|
|
// pop, but don't update stack_pointer
|
322 |
|
|
|
323 |
|
|
if (stack_pointer) fprintf(out, "\tADD\tSP, #%d\n", -stack_pointer);
|
324 |
2 |
jsauermann |
fprintf(out, "\tRET\n");
|
325 |
|
|
}
|
326 |
|
|
//-----------------------------------------------------------------------------
|
327 |
|
|
void Backend::push_rr(SUW suw)
|
328 |
|
|
{
|
329 |
|
|
fprintf(out, ";--\tpush_rr (%d bit)\n", check_size(suw, "push_rr"));
|
330 |
|
|
if (suw == WO) fprintf(out, "\tMOVE\tRR, -(SP)\n");
|
331 |
|
|
else fprintf(out, "\tMOVE\tR, -(SP)\n");
|
332 |
|
|
|
333 |
|
|
stack_pointer--;
|
334 |
|
|
if (suw == WO) stack_pointer--;
|
335 |
|
|
}
|
336 |
|
|
//-----------------------------------------------------------------------------
|
337 |
|
|
void Backend::pop_rr(SUW suw)
|
338 |
|
|
{
|
339 |
|
|
fprintf(out, ";--\tpop_rr (%d bit)\n", check_size(suw, "pop_rr"));
|
340 |
|
|
if (suw == SB) fprintf(out, "\tMOVE\t(SP)+, RS\n");
|
341 |
|
|
else if (suw == UB) fprintf(out, "\tMOVE\t(SP)+, RU\n");
|
342 |
|
|
else fprintf(out, "\tMOVE\t(SP)+, RR\n");
|
343 |
|
|
|
344 |
|
|
stack_pointer++;
|
345 |
|
|
if (suw == WO) stack_pointer++;
|
346 |
|
|
}
|
347 |
|
|
//-----------------------------------------------------------------------------
|
348 |
|
|
void Backend::pop_ll(SUW suw)
|
349 |
|
|
{
|
350 |
|
|
fprintf(out, ";--\tpop_ll (%d bit)\n", check_size(suw, "pop_ll"));
|
351 |
|
|
if (suw == SB) fprintf(out, "\tMOVE\t(SP)+, LS\n");
|
352 |
|
|
else if (suw == UB) fprintf(out, "\tMOVE\t(SP)+, LU\n");
|
353 |
|
|
else fprintf(out, "\tMOVE\t(SP)+, LL\n");
|
354 |
|
|
|
355 |
|
|
stack_pointer++;
|
356 |
|
|
if (suw == WO) stack_pointer++;
|
357 |
|
|
}
|
358 |
|
|
//-----------------------------------------------------------------------------
|
359 |
|
|
void Backend::pop(int pushed)
|
360 |
|
|
{
|
361 |
|
|
fprintf(out, ";--\tpop %d bytes\n", pushed);
|
362 |
|
|
assert(pushed >= 0);
|
363 |
|
|
stack_pointer += pushed;
|
364 |
|
|
|
365 |
|
|
if (pushed) fprintf(out, "\tADD\tSP, #%d\n", pushed);
|
366 |
|
|
}
|
367 |
|
|
//-----------------------------------------------------------------------------
|
368 |
7 |
jsauermann |
void Backend::pop_jump(int diff)
|
369 |
|
|
{
|
370 |
|
|
fprintf(out, ";--\tpop (break/continue) %d bytes\n", diff);
|
371 |
|
|
assert(diff >= 0);
|
372 |
|
|
// don't update stack_pointer !
|
373 |
|
|
|
374 |
|
|
if (diff) fprintf(out, "\tADD\tSP, #%d\n", diff);
|
375 |
|
|
}
|
376 |
|
|
//-----------------------------------------------------------------------------
|
377 |
2 |
jsauermann |
void Backend::pop_return(int ret_bytes)
|
378 |
|
|
{
|
379 |
|
|
fprintf(out, ";--\tpop_return %d bytes\n", ret_bytes);
|
380 |
|
|
if (ret_bytes > 4) pop(ret_bytes);
|
381 |
|
|
}
|
382 |
|
|
//-----------------------------------------------------------------------------
|
383 |
|
|
int Backend::push_return(int ret_bytes)
|
384 |
|
|
{
|
385 |
|
|
fprintf(out, ";--\tpush %d bytes\n", ret_bytes);
|
386 |
|
|
if (ret_bytes <= 4) return 0;
|
387 |
|
|
push_zero(ret_bytes);
|
388 |
|
|
return ret_bytes;
|
389 |
|
|
}
|
390 |
|
|
//-----------------------------------------------------------------------------
|
391 |
|
|
void Backend::push_zero(int bytes)
|
392 |
|
|
{
|
393 |
|
|
fprintf(out, ";--\tpush_zero %d bytes\n", bytes);
|
394 |
|
|
stack_pointer -= bytes; // doesn't really matter
|
395 |
|
|
|
396 |
|
|
for (; bytes > 1; bytes -= 2) fprintf(out, "\tCLRW\t-(SP)\n");
|
397 |
|
|
if (bytes) fprintf(out, "\tCLRB\t-(SP)\n");
|
398 |
|
|
}
|
399 |
|
|
//-----------------------------------------------------------------------------
|
400 |
|
|
void Backend::move_rr_to_ll()
|
401 |
|
|
{
|
402 |
|
|
fprintf(out, ";--\tmove_rr_to_ll\n");
|
403 |
|
|
fprintf(out, "\tMOVE\tRR, LL\n");
|
404 |
|
|
}
|
405 |
|
|
//-----------------------------------------------------------------------------
|
406 |
|
|
void Backend::label(int lab)
|
407 |
|
|
{
|
408 |
|
|
fprintf(out, "L%d_%d:\n", function_num, lab);
|
409 |
|
|
}
|
410 |
|
|
//-----------------------------------------------------------------------------
|
411 |
|
|
void Backend::label(const char * name)
|
412 |
|
|
{
|
413 |
|
|
fprintf(out, "L%d_%s:\n", function_num, name);
|
414 |
|
|
}
|
415 |
|
|
//-----------------------------------------------------------------------------
|
416 |
|
|
void Backend::label(const char * name, int loop)
|
417 |
|
|
{
|
418 |
|
|
fprintf(out, "L%d_%s_%d:\n", function_num, name, loop);
|
419 |
|
|
}
|
420 |
|
|
//-----------------------------------------------------------------------------
|
421 |
|
|
void Backend::label(const char * name, int loop, int value)
|
422 |
|
|
{
|
423 |
|
|
fprintf(out, "L%d_%s_%d_%4.4X:\n", function_num, name, loop, value & 0xFFFF);
|
424 |
|
|
}
|
425 |
|
|
//-----------------------------------------------------------------------------
|
426 |
|
|
void Backend::branch(int lab)
|
427 |
|
|
{
|
428 |
|
|
fprintf(out, ";--\tbranch\n");
|
429 |
|
|
fprintf(out, "\tJMP\tL%d_%d\n", function_num, lab);
|
430 |
|
|
}
|
431 |
|
|
//-----------------------------------------------------------------------------
|
432 |
|
|
void Backend::branch(const char * name)
|
433 |
|
|
{
|
434 |
|
|
fprintf(out, ";--\tbranch\n");
|
435 |
|
|
fprintf(out, "\tJMP\tL%d_%s\n", function_num, name);
|
436 |
|
|
}
|
437 |
|
|
//-----------------------------------------------------------------------------
|
438 |
|
|
void Backend::branch(const char * name, int loop)
|
439 |
|
|
{
|
440 |
|
|
fprintf(out, ";--\tbranch\n");
|
441 |
|
|
fprintf(out, "\tJMP\tL%d_%s_%d\n", function_num, name, loop);
|
442 |
|
|
}
|
443 |
|
|
//-----------------------------------------------------------------------------
|
444 |
|
|
void Backend::branch_true(const char * name, int loop, int size)
|
445 |
|
|
{
|
446 |
|
|
fprintf(out, ";--\tbranch_true\n");
|
447 |
|
|
fprintf(out, "\tJMP\tRRNZ, L%d_%s_%d\n", function_num, name, loop);
|
448 |
|
|
}
|
449 |
|
|
//-----------------------------------------------------------------------------
|
450 |
|
|
void Backend::branch_false(const char * name, int loop, int size)
|
451 |
|
|
{
|
452 |
|
|
fprintf(out, ";--\tbranch_false\n");
|
453 |
|
|
fprintf(out, "\tJMP\tRRZ, L%d_%s_%d\n", function_num, name, loop);
|
454 |
|
|
}
|
455 |
|
|
//-----------------------------------------------------------------------------
|
456 |
|
|
void Backend::branch_case(const char * name, int loop, int size, int value)
|
457 |
|
|
{
|
458 |
|
|
int bits = check_size(size, "branch_case");
|
459 |
|
|
|
460 |
|
|
fprintf(out, ";--\tbranch_case (%d bit)\n", bits);
|
461 |
|
|
fprintf(out, "\tSEQ\tLL, #0x%4.4X\n", value & 0xFFFF);
|
462 |
|
|
fprintf(out, "\tJMP\tRRNZ, L%d_%s_%d_%4.4X\n",
|
463 |
|
|
function_num, name, loop, value & 0xFFFF);
|
464 |
|
|
}
|
465 |
|
|
//-----------------------------------------------------------------------------
|
466 |
|
|
void Backend::compute_unary(int what, const char * pretty)
|
467 |
|
|
{
|
468 |
|
|
const char * opc = "???";
|
469 |
|
|
|
470 |
|
|
fprintf(out, ";--\t16 bit %s\n", pretty);
|
471 |
|
|
switch(what)
|
472 |
|
|
{
|
473 |
|
|
case ET_LOG_NOT: opc = "LNOT"; break;
|
474 |
|
|
case ET_NEGATE: opc = "NEG"; break;
|
475 |
|
|
case ET_COMPLEMENT: opc = "NOT"; break;
|
476 |
|
|
|
477 |
|
|
default:
|
478 |
|
|
assert(0 && "Bad unary what");
|
479 |
|
|
break;
|
480 |
|
|
}
|
481 |
|
|
fprintf(out, "\t%s\tRR\n", opc);
|
482 |
|
|
}
|
483 |
|
|
//-----------------------------------------------------------------------------
|
484 |
|
|
// constant right side (non-constant operand in RR !)
|
485 |
|
|
//
|
486 |
|
|
void Backend::compute_binary(int what, bool uns, const char * pretty, int value)
|
487 |
|
|
{
|
488 |
|
|
const char * opc = "???";
|
489 |
|
|
|
490 |
|
|
fprintf(out, ";--\t%s\n", pretty);
|
491 |
|
|
switch(what)
|
492 |
|
|
{
|
493 |
|
|
case ET_BIT_OR: opc = "OR"; break;
|
494 |
|
|
case ET_BIT_AND: opc = "AND"; break;
|
495 |
|
|
case ET_BIT_XOR: opc = "XOR"; break;
|
496 |
|
|
case ET_LEFT: opc = "LSL"; break;
|
497 |
|
|
case ET_EQUAL: opc = "SEQ"; break;
|
498 |
|
|
case ET_NOT_EQUAL: opc = "SNE"; break;
|
499 |
|
|
case ET_LESS_EQUAL: opc = uns ? "SLS" : "SLE"; break;
|
500 |
|
|
case ET_LESS: opc = uns ? "SLO" : "SLT"; break;
|
501 |
|
|
case ET_GREATER_EQUAL: opc = uns ? "SHS" : "SGE"; break;
|
502 |
|
|
case ET_GREATER: opc = uns ? "SHI" : "SGT"; break;
|
503 |
|
|
case ET_RIGHT: opc = uns ? "LSR" : "ASR"; break;
|
504 |
|
|
|
505 |
|
|
case ET_ADD: if (value == 0) return;
|
506 |
|
|
opc = "ADD";
|
507 |
|
|
if (value > 0) break;
|
508 |
|
|
opc = "SUB";
|
509 |
|
|
value = - value; break;
|
510 |
|
|
|
511 |
|
|
case ET_SUB: if (value == 0) return;
|
512 |
|
|
opc = "SUB";
|
513 |
|
|
if (value > 0) break;
|
514 |
|
|
opc = "ADD";
|
515 |
|
|
value = - value; break;
|
516 |
|
|
|
517 |
|
|
|
518 |
|
|
case ET_MULT: // expr * const
|
519 |
|
|
switch(value & 0xFFFF) // special cases
|
520 |
|
|
{
|
521 |
|
|
case 0x0000: fprintf(out, "\tMOVE\t#0, RR\n");
|
522 |
|
|
return;
|
523 |
|
|
|
524 |
|
|
case 0x0001: case 0x0002: case 0x0004: case 0x0008:
|
525 |
|
|
case 0x0010: case 0x0020: case 0x0040: case 0x0080:
|
526 |
|
|
case 0x0100: case 0x0200: case 0x0400: case 0x0800:
|
527 |
|
|
case 0x1000: case 0x2000: case 0x4000:
|
528 |
|
|
mult_shift(value, false);
|
529 |
|
|
return;
|
530 |
|
|
|
531 |
|
|
case 0xFFFF: case 0xFFFE: case 0xFFFC: case 0xFFF8:
|
532 |
|
|
case 0xFFF0: case 0xFFE0: case 0xFFC0: case 0xFF80:
|
533 |
|
|
case 0xFF00: case 0xFE00: case 0xFC00: case 0xF800:
|
534 |
|
|
case 0xF000: case 0xE000: case 0xC000: case 0x8000:
|
535 |
|
|
mult_shift(-value, true);
|
536 |
|
|
return;
|
537 |
|
|
}
|
538 |
|
|
|
539 |
|
|
fprintf(out, "\tMOVE\tRR, LL\n");
|
540 |
|
|
fprintf(out, "\tMOVE\t#0x%4.4X, RR\n", value & 0xFFFF);
|
541 |
|
|
compute_binary(what, uns, pretty);
|
542 |
|
|
return;
|
543 |
|
|
|
544 |
|
|
case ET_DIV: // expr / const
|
545 |
|
|
switch(value & 0xFFFF) // special cases
|
546 |
|
|
{
|
547 |
|
|
case 0x0000: assert(0 && "Division by 0");
|
548 |
|
|
|
549 |
|
|
case 0x0001: case 0x0002: case 0x0004: case 0x0008:
|
550 |
|
|
case 0x0010: case 0x0020: case 0x0040: case 0x0080:
|
551 |
|
|
case 0x0100: case 0x0200: case 0x0400: case 0x0800:
|
552 |
|
|
case 0x1000: case 0x2000: case 0x4000:
|
553 |
|
|
div_shift(value, false, uns);
|
554 |
|
|
return;
|
555 |
|
|
|
556 |
|
|
case 0xFFFF: case 0xFFFE: case 0xFFFC: case 0xFFF8:
|
557 |
|
|
case 0xFFF0: case 0xFFE0: case 0xFFC0: case 0xFF80:
|
558 |
|
|
case 0xFF00: case 0xFE00: case 0xFC00: case 0xF800:
|
559 |
|
|
case 0xF000: case 0xE000: case 0xC000: case 0x8000:
|
560 |
|
|
div_shift(-value, true, uns);
|
561 |
|
|
return;
|
562 |
|
|
}
|
563 |
|
|
|
564 |
|
|
fprintf(out, "\tMOVE\tRR, LL\n");
|
565 |
|
|
fprintf(out, "\tMOVE\t#0x%4.4X, RR\n", value & 0xFFFF);
|
566 |
|
|
compute_binary(what, uns, pretty);
|
567 |
|
|
return;
|
568 |
|
|
|
569 |
|
|
case ET_MOD: // expr % const
|
570 |
|
|
switch(value & 0xFFFF) // special cases
|
571 |
|
|
{
|
572 |
|
|
case 0x0000: assert(0 && "Division by 0");
|
573 |
|
|
|
574 |
|
|
case 0x0001: case 0x0002: case 0x0004: case 0x0008:
|
575 |
|
|
case 0x0010: case 0x0020: case 0x0040: case 0x0080:
|
576 |
|
|
case 0x0100: case 0x0200: case 0x0400: case 0x0800:
|
577 |
|
|
case 0x1000: case 0x2000: case 0x4000:
|
578 |
|
|
mod_and(value, false, uns);
|
579 |
|
|
return;
|
580 |
|
|
|
581 |
|
|
case 0xFFFF: case 0xFFFE: case 0xFFFC: case 0xFFF8:
|
582 |
|
|
case 0xFFF0: case 0xFFE0: case 0xFFC0: case 0xFF80:
|
583 |
|
|
case 0xFF00: case 0xFE00: case 0xFC00: case 0xF800:
|
584 |
|
|
case 0xF000: case 0xE000: case 0xC000: case 0x8000:
|
585 |
|
|
mod_and(-value, true, uns);
|
586 |
|
|
return;
|
587 |
|
|
}
|
588 |
|
|
|
589 |
|
|
fprintf(out, "\tMOVE\tRR, LL\n");
|
590 |
|
|
fprintf(out, "\tMOVE\t#0x%4.4X, RR\n", value & 0xFFFF);
|
591 |
|
|
compute_binary(what, uns, pretty);
|
592 |
|
|
return;
|
593 |
|
|
|
594 |
|
|
default:
|
595 |
|
|
assert(0 && "Bad what");
|
596 |
|
|
return;
|
597 |
|
|
}
|
598 |
|
|
|
599 |
|
|
fprintf(out, "\t%s\tRR, #0x%4.4X\n", opc, value & 0xFFFF);
|
600 |
|
|
}
|
601 |
|
|
//-----------------------------------------------------------------------------
|
602 |
|
|
void Backend::mult_shift(int value, bool negative)
|
603 |
|
|
{
|
604 |
|
|
assert(value >= 0);
|
605 |
|
|
if (negative) fprintf(out, "\tNEG\tRR\n");
|
606 |
|
|
|
607 |
|
|
switch(value) // special cases
|
608 |
|
|
{
|
609 |
|
|
case 0x0001: return;
|
610 |
|
|
case 0x0002: fprintf(out, "\tLSL\tRR, #1\n"); return;
|
611 |
|
|
case 0x0004: fprintf(out, "\tLSL\tRR, #2\n"); return;
|
612 |
|
|
case 0x0008: fprintf(out, "\tLSL\tRR, #3\n"); return;
|
613 |
|
|
case 0x0010: fprintf(out, "\tLSL\tRR, #4\n"); return;
|
614 |
|
|
case 0x0020: fprintf(out, "\tLSL\tRR, #5\n"); return;
|
615 |
|
|
case 0x0040: fprintf(out, "\tLSL\tRR, #6\n"); return;
|
616 |
|
|
case 0x0080: fprintf(out, "\tLSL\tRR, #7\n"); return;
|
617 |
|
|
case 0x0100: fprintf(out, "\tLSL\tRR, #8\n"); return;
|
618 |
|
|
case 0x0200: fprintf(out, "\tLSL\tRR, #9\n"); return;
|
619 |
|
|
case 0x0400: fprintf(out, "\tLSL\tRR, #10\n"); return;
|
620 |
|
|
case 0x0800: fprintf(out, "\tLSL\tRR, #11\n"); return;
|
621 |
|
|
case 0x1000: fprintf(out, "\tLSL\tRR, #12\n"); return;
|
622 |
|
|
case 0x2000: fprintf(out, "\tLSL\tRR, #13\n"); return;
|
623 |
|
|
case 0x4000: fprintf(out, "\tLSL\tRR, #14\n"); return;
|
624 |
|
|
case 0x8000: fprintf(out, "\tLSL\tRR, #15\n"); return;
|
625 |
|
|
default: assert(0);
|
626 |
|
|
}
|
627 |
|
|
}
|
628 |
|
|
//-----------------------------------------------------------------------------
|
629 |
|
|
void Backend::div_shift(int value, bool negative, bool uns)
|
630 |
|
|
{
|
631 |
|
|
assert(value >= 0);
|
632 |
|
|
if (negative) fprintf(out, "\tNEG\tRR\n");
|
633 |
|
|
|
634 |
|
|
const char * op = "ASR";
|
635 |
|
|
if (uns) op = "LSR";
|
636 |
|
|
|
637 |
|
|
switch(value) // special cases
|
638 |
|
|
{
|
639 |
|
|
case 0x0001: return;
|
640 |
|
|
case 0x0002: fprintf(out, "\t%s\tRR, #1\n", op); return;
|
641 |
|
|
case 0x0004: fprintf(out, "\t%s\tRR, #2\n", op); return;
|
642 |
|
|
case 0x0008: fprintf(out, "\t%s\tRR, #3\n", op); return;
|
643 |
|
|
case 0x0010: fprintf(out, "\t%s\tRR, #4\n", op); return;
|
644 |
|
|
case 0x0020: fprintf(out, "\t%s\tRR, #5\n", op); return;
|
645 |
|
|
case 0x0040: fprintf(out, "\t%s\tRR, #6\n", op); return;
|
646 |
|
|
case 0x0080: fprintf(out, "\t%s\tRR, #7\n", op); return;
|
647 |
|
|
case 0x0100: fprintf(out, "\t%s\tRR, #8\n", op); return;
|
648 |
|
|
case 0x0200: fprintf(out, "\t%s\tRR, #9\n", op); return;
|
649 |
|
|
case 0x0400: fprintf(out, "\t%s\tRR, #10\n", op); return;
|
650 |
|
|
case 0x0800: fprintf(out, "\t%s\tRR, #11\n", op); return;
|
651 |
|
|
case 0x1000: fprintf(out, "\t%s\tRR, #12\n", op); return;
|
652 |
|
|
case 0x2000: fprintf(out, "\t%s\tRR, #13\n", op); return;
|
653 |
|
|
case 0x4000: fprintf(out, "\t%s\tRR, #14\n", op); return;
|
654 |
|
|
case 0x8000: fprintf(out, "\t%s\tRR, #15\n", op); return;
|
655 |
|
|
default: assert(0);
|
656 |
|
|
}
|
657 |
|
|
}
|
658 |
|
|
//-----------------------------------------------------------------------------
|
659 |
|
|
void Backend::mod_and(int value, bool negative, bool uns)
|
660 |
|
|
{
|
661 |
|
|
assert(value >= 0);
|
662 |
|
|
if (negative) fprintf(out, "\tNEG\tRR\n");
|
663 |
|
|
|
664 |
|
|
switch(value) // special cases
|
665 |
|
|
{
|
666 |
|
|
case 0x0001: fprintf(out, "\tMOVE\t#0, RR\n"); return;
|
667 |
|
|
case 0x0002: fprintf(out, "\tAND\tRR, #0x0001\n"); return;
|
668 |
|
|
case 0x0004: fprintf(out, "\tAND\tRR, #0x0003\n"); return;
|
669 |
|
|
case 0x0008: fprintf(out, "\tAND\tRR, #0x0007\n"); return;
|
670 |
|
|
case 0x0010: fprintf(out, "\tAND\tRR, #0x000F\n"); return;
|
671 |
|
|
case 0x0020: fprintf(out, "\tAND\tRR, #0x001F\n"); return;
|
672 |
|
|
case 0x0040: fprintf(out, "\tAND\tRR, #0x003F\n"); return;
|
673 |
|
|
case 0x0080: fprintf(out, "\tAND\tRR, #0x007F\n"); return;
|
674 |
|
|
case 0x0100: fprintf(out, "\tAND\tRR, #0x00FF\n"); return;
|
675 |
|
|
case 0x0200: fprintf(out, "\tAND\tRR, #0x01FF\n"); return;
|
676 |
|
|
case 0x0400: fprintf(out, "\tAND\tRR, #0x03FF\n"); return;
|
677 |
|
|
case 0x0800: fprintf(out, "\tAND\tRR, #0x07FF\n"); return;
|
678 |
|
|
case 0x1000: fprintf(out, "\tAND\tRR, #0x0FFF\n"); return;
|
679 |
|
|
case 0x2000: fprintf(out, "\tAND\tRR, #0x1FFF\n"); return;
|
680 |
|
|
case 0x4000: fprintf(out, "\tAND\tRR, #0x3FFF\n"); return;
|
681 |
|
|
case 0x8000: fprintf(out, "\tAND\tRR, #0x7FFF\n"); return;
|
682 |
|
|
default: assert(0);
|
683 |
|
|
}
|
684 |
|
|
}
|
685 |
|
|
//-----------------------------------------------------------------------------
|
686 |
|
|
// constant left side (non-constant operand in RR !)
|
687 |
|
|
//
|
688 |
|
|
void Backend::compute_binary(int what, bool uns, int value, const char * pretty)
|
689 |
|
|
{
|
690 |
|
|
// symmetric operators: exchange left and right...
|
691 |
|
|
//
|
692 |
|
|
switch(what)
|
693 |
|
|
{
|
694 |
|
|
case ET_BIT_OR:
|
695 |
|
|
case ET_BIT_AND:
|
696 |
|
|
case ET_BIT_XOR:
|
697 |
|
|
case ET_ADD:
|
698 |
|
|
case ET_MULT:
|
699 |
|
|
case ET_EQUAL:
|
700 |
|
|
case ET_NOT_EQUAL:
|
701 |
|
|
compute_binary(what, uns, pretty, value); return;
|
702 |
|
|
|
703 |
|
|
case ET_LESS_EQUAL:
|
704 |
|
|
compute_binary(ET_GREATER, uns, ">", value); return;
|
705 |
|
|
|
706 |
|
|
case ET_LESS:
|
707 |
|
|
compute_binary(ET_GREATER_EQUAL, uns, ">=", value); return;
|
708 |
|
|
|
709 |
|
|
case ET_GREATER_EQUAL:
|
710 |
|
|
compute_binary(ET_LESS, uns, "<", value); return;
|
711 |
|
|
|
712 |
|
|
case ET_GREATER:
|
713 |
|
|
compute_binary(ET_LESS_EQUAL, uns, "<=", value); return;
|
714 |
|
|
}
|
715 |
|
|
|
716 |
|
|
// assymmetric operators: load constant and call non-const operator
|
717 |
|
|
//
|
718 |
|
|
switch(what)
|
719 |
|
|
{
|
720 |
|
|
case ET_SUB:
|
721 |
|
|
case ET_LEFT:
|
722 |
|
|
case ET_RIGHT:
|
723 |
|
|
case ET_DIV:
|
724 |
|
|
case ET_MOD:
|
725 |
|
|
fprintf(out, "\tMOVE\t#0x%4.4X, LL\n", value & 0xFFFF);
|
726 |
|
|
compute_binary(what, uns, pretty);
|
727 |
|
|
return;
|
728 |
|
|
}
|
729 |
|
|
|
730 |
|
|
assert(0 && "Bad what");
|
731 |
|
|
}
|
732 |
|
|
//-----------------------------------------------------------------------------
|
733 |
|
|
void Backend::compute_binary(int what, bool uns, const char * pretty)
|
734 |
|
|
{
|
735 |
|
|
const char * opc = "???";
|
736 |
|
|
|
737 |
|
|
fprintf(out, ";--\t%s\n", pretty);
|
738 |
|
|
switch(what)
|
739 |
|
|
{
|
740 |
|
|
case ET_BIT_OR: opc = "OR"; break;
|
741 |
|
|
case ET_BIT_AND: opc = "AND"; break;
|
742 |
|
|
case ET_BIT_XOR: opc = "XOR"; break;
|
743 |
|
|
case ET_ADD: opc = "ADD"; break;
|
744 |
|
|
case ET_SUB: opc = "SUB"; break;
|
745 |
|
|
case ET_EQUAL: opc = "SEQ"; break;
|
746 |
|
|
case ET_NOT_EQUAL: opc = "SNE"; break;
|
747 |
|
|
case ET_LESS_EQUAL: opc = uns ? "SLS" : "SLE"; break;
|
748 |
|
|
case ET_LESS: opc = uns ? "SLO" : "SLT"; break;
|
749 |
|
|
case ET_GREATER_EQUAL: opc = uns ? "SHS" : "SGE"; break;
|
750 |
|
|
case ET_GREATER: opc = uns ? "SHI" : "SGT"; break;
|
751 |
|
|
|
752 |
|
|
case ET_MULT: // expr * expr
|
753 |
|
|
fprintf(out, "\tDI\n");
|
754 |
|
|
if (uns) fprintf(out, "\tMUL_IU\n");
|
755 |
|
|
else fprintf(out, "\tMUL_IS\n");
|
756 |
|
|
fprintf(out, "\tCALL\tmult_div\n");
|
757 |
|
|
fprintf(out, "\tMD_FIN\n");
|
758 |
|
|
fprintf(out, "\tEI\n");
|
759 |
|
|
return;
|
760 |
|
|
|
761 |
|
|
case ET_DIV: // expr / expr
|
762 |
|
|
fprintf(out, "\tDI\n");
|
763 |
|
|
if (uns) fprintf(out, "\tDIV_IU\n");
|
764 |
|
|
else fprintf(out, "\tDIV_IS\n");
|
765 |
|
|
fprintf(out, "\tCALL\tmult_div\n");
|
766 |
|
|
fprintf(out, "\tMD_FIN\n");
|
767 |
|
|
fprintf(out, "\tEI\n");
|
768 |
|
|
return;
|
769 |
|
|
|
770 |
|
|
case ET_MOD: // expr % expr
|
771 |
|
|
fprintf(out, "\tDI\n");
|
772 |
|
|
if (uns) fprintf(out, "\tDIV_IU\n");
|
773 |
|
|
else fprintf(out, "\tDIV_IS\n");
|
774 |
|
|
fprintf(out, "\tCALL\tmult_div\n");
|
775 |
|
|
fprintf(out, "\tMOD_FIN\n");
|
776 |
|
|
fprintf(out, "\tEI\n");
|
777 |
|
|
return;
|
778 |
|
|
|
779 |
|
|
default:
|
780 |
|
|
assert(0 && "Bad what");
|
781 |
|
|
break;
|
782 |
|
|
}
|
783 |
|
|
|
784 |
|
|
fprintf(out, "\t%s\tLL, RR\n", opc);
|
785 |
|
|
}
|
786 |
|
|
//-----------------------------------------------------------------------------
|
787 |
|
|
void Backend::content(SUW suw)
|
788 |
|
|
{
|
789 |
|
|
check_size(suw, "content");
|
790 |
|
|
fprintf(out, ";--\tcontent\n");
|
791 |
|
|
if (suw == SB) fprintf(out, "\tMOVE\t(RR), RS\n");
|
792 |
|
|
else if (suw == UB) fprintf(out, "\tMOVE\t(RR), RU\n");
|
793 |
|
|
else fprintf(out, "\tMOVE\t(RR), RR\n");
|
794 |
|
|
}
|
795 |
|
|
//-----------------------------------------------------------------------------
|
796 |
|
|
void Backend::scale_rr(int size)
|
797 |
|
|
{
|
798 |
|
|
assert(size > 0);
|
799 |
|
|
fprintf(out, ";--\tscale_rr *%d\n", size);
|
800 |
|
|
|
801 |
|
|
if (size == 1) return;
|
802 |
|
|
check_size(size, "scale_rr");
|
803 |
|
|
|
804 |
|
|
compute_binary(ET_MULT, false, "*", size);
|
805 |
|
|
// fprintf(out, "\tLSL\tRR, #%d\n", size);
|
806 |
|
|
}
|
807 |
|
|
//-----------------------------------------------------------------------------
|
808 |
|
|
void Backend::unscale_rr(int size, bool uns)
|
809 |
|
|
{
|
810 |
|
|
assert(size > 0);
|
811 |
|
|
fprintf(out, ";--\tscale *%d\n", size);
|
812 |
|
|
|
813 |
|
|
if (size == 1) return;
|
814 |
|
|
check_size(size, "unscale_rr");
|
815 |
|
|
|
816 |
|
|
compute_binary(ET_DIV, uns, "/", size);
|
817 |
|
|
// if (uns) fprintf(out, "\tLSR\tRR, #%d\n", size);
|
818 |
|
|
// else fprintf(out, "\tASR\tRR, #%d\n", size);
|
819 |
|
|
}
|
820 |
|
|
//-----------------------------------------------------------------------------
|