OpenCores
URL https://opencores.org/ocsvn/c16/c16/trunk

Subversion Repositories c16

[/] [c16/] [trunk/] [compiler/] [Backend.cc] - Blame information for rev 29

Details | Compare with Previous | View Log

Line No. Rev Author Line
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
//-----------------------------------------------------------------------------

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.