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

Subversion Repositories c16

[/] [c16/] [tags/] [V10/] [compiler/] [Backend.cc] - Blame information for rev 26

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

powered by: WebSVN 2.1.0

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