comparison mc-mips.c @ 51:c2ef3a2fbe88

*** empty log message ***
author kono
date Sun, 16 Feb 2003 22:21:23 +0900
parents
children 1c2a9232ea93
comparison
equal deleted inserted replaced
50:1ec39b34ed98 51:c2ef3a2fbe88
1 /* Micro-C Code Generatation Part for Mips */
2
3 #define EXTERN extern
4 #include "mc.h"
5
6 #define REGISTERS6 0
7
8 void code_init(void);
9 void free_register(int i);
10 void emit_init(void);
11 void emit_push(void);
12 void gexpr(int e1);
13 void g_expr(int e1);
14 void bexpr(int e1, char cond, int l1);
15 void b_expr(int e1, char cond, int l1);
16 void string(int e1);
17 void function(int e1);
18 void machinop(int e1);
19 void rindirect(int e1);
20 void assign(int e1);
21 void sassign(int e1);
22 void assop(int e1);
23 void tosop(int op);
24 void shift(char *op, int reg) ;
25 void ld_indexx(int byte, int n, char *xrn);
26 void st_indexx(int byte, int n, char *xrn);
27 void indexy(char *op, char *gvar);
28 void cmpdimm(int e, int csreg);
29 void global_table(void) ;
30 void local_table(void) ;
31 void opening(char *filename);
32 void closing(void);
33 void gen_gdecl(char *n, int gpc) ;
34 void jmp_label(int l);
35 void jmp_eq_label(int l);
36 void rexpr(int e1, int l1, char *s);
37 void jcond(int l, char cond);
38 void jmp(int l);
39 void def_label(int cslabel, int dlabel) ;
40 void gen_comment(char *s);
41 void gen_source(char *s);
42 void code_enter(char *name) ;
43 void code_leave(char *name) ;
44 void enter(char *name, int disp) ;
45 void enter_no(char *name,int disp);
46 void enter1(int disp) ;
47 void ret(void);
48 void emit_data(int e, int t, NMTBL *n);
49 void text_mode(void);
50 void data_mode(char *name);
51 int get_register_var(void);
52 void jump(int e1, int env);
53 int lvar(int l);
54
55 int cadr(int e);
56 int car(int e);
57 int caddr(int e);
58 int fwdlabel(void);
59 void fwddef(int l);
60 int cadddr(int e);
61 int backdef(void);
62 int error(int n);
63 int size(int t);
64 int list3(int e1, int e2, int e3);
65 extern int scalar(int);
66 extern int reverse0(int);
67
68 #define TEXT_EMIT_MODE 0
69 #define DATA_EMIT_MODE 1
70 #define RODATA_EMIT_MODE 2
71
72 static output_mode = TEXT_EMIT_MODE;
73 static data_alignment = 0;
74
75 /*
76 local1 <----24 local variable
77 -20 <- disp_offset
78 saved register
79 .mask 0...0,-8
80 .fmask 0
81 $fp = $sp 0
82 $ip 4 <- arg_offset
83 arg1 8
84 */
85 int arg_offset = 8;
86 int code_arg_offset = -4;
87 int disp_offset = -12;
88 int func_disp_offset = -12;
89 int code_disp_offset = -4;
90 int size_of_int = 4;
91 int endian = 0;
92 int MAX_REGISTER=32; /* Mipsのレジスタを32つまで使う*/
93 int REAL_MAX_REGISTER=32; /* Mipsのレジスタが32つということ*/
94 int MAX_REGISTGER_VAR=20;
95
96 int save_reg = 0; /*saveされたレジスタの回数*/
97 int save_reg1 = 0;
98
99 static int creg; /* current register */
100 static char *crn; /* current register name */
101 static int lreg; /* operand register */
102 static char *lrn; /* operand register name */
103 static int dreg; /* temporary register */
104 static char *drn; /* temporary register name */
105 static int xreg; /* pointer register */
106 static int reg_sp; /* REGister Stack-Pointer */
107
108
109 #define REG_00 0
110 #define REG_01 1
111 #define REG_02 2
112 #define REG_03 3
113 #define REG_04 4
114 #define REG_05 5
115 #define REG_06 6
116 #define REG_07 7
117 #define REG_08 8
118 #define REG_09 9
119 #define REG_10 10
120 #define REG_11 11
121 #define REG_12 12
122 #define REG_13 13
123 #define REG_14 14
124 #define REG_15 15
125 #define REG_16 16
126 #define REG_17 17
127 #define REG_18 18
128 #define REG_19 19
129 #define REG_20 20
130 #define REG_21 21
131 #define REG_22 22
132 #define REG_23 23
133 #define REG_24 24
134 #define REG_25 25
135 #define REG_26 26
136 #define REG_27 27
137 #define REG_28 28
138 #define REG_29 29
139 #define REG_30 30
140 #define REG_31 31
141
142 static char *reg_name[32];
143
144 /*
145 creg currrent virtual register
146 lreg operand virtual register
147 dreg spare virtual register
148
149 rname[creg] currrent real register
150 rname[lreg] operand real register
151 rname[dreg] spare real register
152
153 regs[] virtual register usage
154
155 reg_name[rname[creg]]
156 */
157
158 #define MAX_MAX 40
159 static int rname[MAX_MAX];
160 static int regs[MAX_MAX]; /* 使われているレジスタを示すフラグ */
161 static int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
162
163 void
164 code_init(void)
165 {
166 int i;
167
168 if (REGISTERS6) {
169 arg_offset = 8;
170 func_disp_offset = -20;
171 disp_offset = -20;
172 size_of_int = 4;
173 endian = 0;
174 MAX_REGISTER=32;
175 } else {
176 arg_offset = 8;
177 func_disp_offset = -12;
178 disp_offset = -12;
179 size_of_int = 4;
180 endian = 0;
181 MAX_REGISTER=32;
182 }
183 MAX_REGISTER_VAR=2;
184
185 reg_name[REG_00] = "$0";
186 reg_name[REG_01] = "$1";
187 reg_name[REG_02] = "$2";
188 reg_name[REG_03] = "$3";
189 reg_name[REG_04] = "$4";
190 reg_name[REG_05] = "$5";
191 reg_name[REG_06] = "$6";
192 reg_name[REG_07] = "$7";
193 reg_name[REG_08] = "$8";
194 reg_name[REG_09] = "$9";
195 reg_name[REG_10] = "$10";
196 reg_name[REG_11] = "$11";
197 reg_name[REG_12] = "$12";
198 reg_name[REG_13] = "$13";
199 reg_name[REG_14] = "$14";
200 reg_name[REG_15] = "$15";
201 reg_name[REG_16] = "$16";
202 reg_name[REG_17] = "$17";
203 reg_name[REG_18] = "$18";
204 reg_name[REG_19] = "$19";
205 reg_name[REG_20] = "$20";
206 reg_name[REG_21] = "$21";
207 reg_name[REG_22] = "$22";
208 reg_name[REG_23] = "$23";
209 reg_name[REG_24] = "$24";
210 reg_name[REG_25] = "$25";
211 reg_name[REG_26] = "$26";
212 reg_name[REG_27] = "$27";
213 reg_name[REG_28] = "$28";
214 reg_name[REG_29] = "$29";
215 reg_name[REG_30] = "$30";
216 reg_name[REG_31] = "$31";
217
218 }
219
220 char *
221 register_name(int i)
222 {
223 return reg_name[rname[i]];
224 }
225
226 int
227 get_register(void)
228 { /* 使われていないレジスタを調べる */
229 int i;
230 for(i=0;i<MAX_REGISTER;i++) {
231 if (! regs[i]) { /* 使われていないなら */
232 regs[i]=1; /* そのレジスタを使うことを宣言し */
233 return i; /* その場所を表す番号を返す */
234 }
235 }
236
237 return -1; /* 空いている場所がないなら、それを表す -1 を返す */
238 }
239
240 void
241 free_register(int i) { /* いらなくなったレジスタを開放 */
242 regs[i]=0;
243 }
244
245 int
246 register_full(void)
247 {
248 int i;
249 for(i=0;i<MAX_REGISTER;i++) {
250 if (! regs[i]) {
251 return 0;
252 }
253 }
254 return 1;
255 }
256
257 void
258 gexpr_init(void)
259 {
260 int i;
261 while(reg_sp > 0) {
262 free_register(reg_stack[--reg_sp]);
263 }
264 text_mode();
265 }
266
267 void
268 emit_init(void)
269 {
270 int i;
271 for(i=0;i<REAL_MAX_REGISTER;i++) regs[i]=0;
272 for(i=0;i<REAL_MAX_REGISTER;i++) rname[i]=i;
273 regs[REG_00] = 1; /* reserved */
274 regs[REG_01] = 1; /* reserved */
275 regs[REG_02] = 1; /* $v0 */
276 regs[REG_03] = 1; /* $v1 */
277 regs[REG_28] = 1; /* reserved */
278 regs[REG_29] = 1; /* reserved */
279 regs[REG_30] = 1; /* reserved */
280 regs[REG_31] = 1; /* reserved */
281 creg = get_register();
282 crn = reg_name[rname[creg]];
283 dreg = get_register();
284 drn = reg_name[rname[dreg]];
285 reg_sp = 0;
286 text_mode();
287 }
288
289 void
290 set_crn(int i)
291 {
292 creg = i;
293 crn = reg_name[rname[creg]];
294 }
295
296 void
297 set_drn(int i)
298 {
299 dreg = i;
300 drn = reg_name[rname[dreg]];
301 }
302
303 int
304 virtual(int real)
305 {
306 int real_v,i;
307 real_v = -1;
308 for(i=0;i<MAX_REGISTER;i++) {
309 if (rname[i]==real) {
310 real_v=i;
311 break;
312 }
313 }
314 if (real_v == -1)
315 error(-1);
316 return real_v;
317 }
318
319 void
320 use_register(int virt, int real, int move)
321 {
322 int real_v;
323 char *move_op,*a,*b;
324 if (rname[virt]==real)
325 return;
326 real_v = virtual(real);
327 if (move || regs[real_v]) {
328 if(regs[real_v]) {
329 a=reg_name[real];
330 b=reg_name[rname[virt]];
331 printf("\txor \t%s,%s,%s\n",a,a,b);
332 printf("\txor \t%s,%s,%s\n",b,a,b);
333 printf("\txor \t%s,%s,%s\n",a,a,b);
334 } else {
335 printf("\tmove \t%s,%s\n",reg_name[real],reg_name[rname[virt]]);
336 }
337 }
338 rname[real_v] = rname[virt];
339 rname[virt] = real;
340 crn = reg_name[rname[creg]];
341 drn = reg_name[rname[dreg]];
342 lrn = reg_name[rname[lreg]];
343
344 save_reg++;
345 }
346
347 int
348 pop_register(void)
349 { /* レジスタから値を取り出す */
350 int i,j;
351
352 j = creg;
353 i = reg_stack[--reg_sp];
354
355 if(i<0) {
356 return i;
357 } else {
358 free_register(i);
359 lreg = i;
360 lrn = reg_name[rname[lreg]];
361 regs[i]=0;
362 return lreg;
363 }
364 }
365
366 int
367 stack_used(void) {
368 return reg_stack[--reg_sp]<0;
369 }
370
371 void
372 emit_push(void)
373 {
374 int new_reg;
375 new_reg = get_register();
376 if(new_reg<0) { /* もうレジスタがない */
377 reg_stack[reg_sp++] = -1;
378 printf("\tsubu $sp,$sp,%d\n",size_of_int);
379 printf("\tsw \t%s,0($sp)\n",crn);
380 } else {
381 reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */
382 set_crn(new_reg);
383 }
384 }
385
386 char *
387 emit_pop(int type)
388 {
389 char *xrn;
390 if (pop_register()==-1) {
391 printf("\tlw %s,0($sp)\n",drn);
392 printf("\taddu $sp,$sp,%d\n",size_of_int);
393 xrn = drn;
394 xreg = dreg;
395 } else {
396 xrn = lrn;
397 xreg = lreg;
398 }
399 return xrn;
400 }
401
402 int
403 get_register_var(void)
404 {
405 int i;
406 for(i=REG_05;i<REG_31;i++) {
407 if (! regs[i]) { /* 使われていないなら */
408 regs[i]=1; /* そのレジスタを使うことを宣言し */
409 return i; /* その場所を表す番号を返す */
410 }
411 }
412 return -1;
413 }
414
415 void
416 gexpr(int e1)
417 {
418 gexpr_init();
419 g_expr(e1);
420 csvalue = rname[creg]; /* for siwtch value */
421 }
422
423 void
424 g_expr(int e1)
425 {
426 int e2,e3,e4;
427 char *xrn;
428 NMTBL *n;
429
430 if (chk) return;
431 e2 = cadr(e1);
432 switch (car(e1)){
433 case GVAR:
434 printf("\tla\t%s,%s\n",crn,caddr(e1));
435 return;
436 case RGVAR:
437 printf("\tlw\t%s,%s\n",crn,caddr(e1));
438 return;
439 case CRGVAR:
440 printf("\tlb\t%s,%s\n",crn,caddr(e1));
441 return;
442 case LVAR:
443 printf("\taddu\t%s,$fp,%d\n",crn,lvar(e2));
444 return;
445 case REGISTER:
446 /* this is of course redundant... */
447 printf("\tmove\t%s,%s\n",crn,register_name(e2));
448 return;
449 case RLVAR:
450 printf("\tlw\t%s,%d($fp)\n",crn,lvar(e2));
451 return;
452 case CRLVAR:
453 printf("\tlb\t%s,%d($fp)\n",crn,lvar(e2));
454 return;
455 case FNAME:
456 printf("\tla\t%s,%s\n",crn,((NMTBL *)e2)->nm);
457 return;
458 case CONST: /* 代入する値が0でも特別な処理はしない */
459 printf("\tli\t%s,%d\n",crn,e2);
460 return;
461 case STRING:
462 string(e1);
463 return;
464 case FUNCTION:
465 function(e1);
466 return;
467 case CODE:
468 jump(e2,caddr(e1));
469 return;
470 case INDIRECT:
471 g_expr(e2);
472 return;
473 case RINDIRECT: case CRINDIRECT:
474 rindirect(e1);
475 return;
476 case ADDRESS:
477 g_expr(e2);
478 return;
479 case MINUS: /* レジスタに対し、引き算を実行すれば実現可能 */
480 g_expr(e2);
481 printf("\tsubu\t%s,$0,%s\n",crn,crn);
482 return;
483 case BNOT: /* ~ */
484 g_expr(e2);
485 /* use_data_reg(creg,1); */
486 printf("\tnor\t%s,$0,%s\n",crn,crn);
487 return;
488 case LNOT: /* ! */
489 g_expr(e2);
490 /*use_data_reg(creg,1);*/
491 printf("\txori\t%s,%s,0x0000\n",drn,crn);
492 printf("\tsltu\t%s,%s,1\n",crn,drn);
493 return;
494 case PREINC:/* ++q */
495 if (car(e2)==REGISTER) {
496 printf("\taddu \t%s,%s,%d\n",register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
497 return;
498 }
499 g_expr(e2);
500 printf("\taddu \t%s,%s,%d\n",crn,crn,caddr(e1));
501 return;
502 case POSTINC:/* p++ */
503 if (car(e2)==REGISTER) {
504 printf("\taddu \t%s,%s,%d\n",register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
505 return;
506 }
507 g_expr(e2);
508 emit_push();
509 /* in case of register full we should copy crn to drn */
510 xrn = emit_pop(0);
511 printf("\taddu \t%s,%s,%d\n",crn,xrn,caddr(e1));
512 return;
513 case CPOSTINC:
514 /* char *p; *p++ */
515 if (car(e2)==REGISTER) {
516 printf("\tmove\t%s,%s\n",crn,register_name(cadr(e2)));
517 printf("\taddu\t%s,%s,%d\n",register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
518 return;
519 }
520 g_expr(e2);
521 emit_push(); /* in case of register full we should copy crn to drn */
522 xrn = emit_pop(0);
523 printf("\tmovsbl (%s),%s\n",xrn,crn);
524 printf("\tincl (%s)\n",xrn);
525 return;
526 case CPREINC: /* char *p; *++p */
527 if (car(e2)==REGISTER) {
528 printf("\taddu\t%s,%s,%d\n",register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
529 printf("\tmove\t%s,%s\n",crn,register_name(cadr(e2)));
530 return;
531 }
532 g_expr(e2);
533 printf("\tincl (%s)\n",crn);
534 printf("\tmovsbl (%s),%s\n",crn,crn);
535 return;
536 case CPOSTDEC:/* char *p; *p-- */
537 if (car(e2)==REGISTER) {
538 printf("\tmove\t%s,%s\n",crn,register_name(cadr(e2)));
539 printf("\tsubu\t%s,%s,1\n",register_name(cadr(e2)),register_name(cadr(e2)));
540 return;
541 }
542 g_expr(e2);
543 printf("\tmovsbl (%s),%s\n",crn,crn);
544 printf("\tdecl (%s)\n",crn);
545 return;
546 case CPREDEC:/* char *p; *--p */
547 if (car(e2)==REGISTER) {
548 printf("\tdecl %s\n",register_name(cadr(e2)));
549 printf("\tmove\t%s,%s\n",crn,register_name(cadr(e2)));
550 return;
551 }
552 g_expr(e2);
553 emit_push();
554 xrn = emit_pop(0);
555 printf("\tdecl (%s)\n",xrn);
556 printf("\tmovsbl (%s),%s\n",xrn,crn);
557 return;
558 case MUL: case UMUL:
559 case DIV: case UDIV:
560 case MOD: case UMOD:
561 case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT:
562 case ADD: case SUB: case BAND: case EOR: case BOR:
563 machinop(e1);
564 return;
565 case COND:
566 e2=fwdlabel();
567 b_expr(cadr(e1),0,e2);
568 g_expr(caddr(e1));
569 e4 = rname[creg];
570 jmp(e3=fwdlabel());
571 fwddef(e2);
572 g_expr(cadddr(e1));
573 use_register(creg,e4,1);
574 fwddef(e3);
575 return;
576 case SASS:
577 sassign(e1);
578 return;
579 case ASS: case CASS:
580 assign(e1);
581 return;
582 case ASSOP: case CASSOP:
583 assop(e1);
584 return;
585 case COMMA:
586 g_expr(e2);
587 g_expr(caddr(e1));
588 return;
589 case RETURN:
590 n = (NMTBL *)e2;
591 if (retcont==0)
592 retcont=fwdlabel();
593 printf("\tla\t%s,$L%d\n",crn,retcont);
594 return;
595 case ENVIRONMENT:
596 printf("\tmove\t%s,$fp\n",crn);
597 return;
598 default:
599 b_expr(e1,1,e2=fwdlabel()); /* including > < ... */
600 /*printf("\txor \t%s,%s\n",crn,crn);*/
601 jmp(e3=fwdlabel());
602 fwddef(e2);
603 printf("\tli \t%s,%d\n",crn,lvar(e2));
604 fwddef(e3);
605 }
606 }
607
608 void
609 bexpr(int e1, char cond, int l1)
610 {
611 gexpr_init();
612 b_expr(e1,cond,l1);
613 }
614
615 void
616 b_expr(int e1, char cond, int l1)
617 {
618 int e2,l2;
619 if (chk) return;
620 e2=cadr(e1);
621 switch(car(e1)) {
622 case LNOT:
623 b_expr(e2,!cond,l1);
624 return;
625 case GT:
626 /*rexpr(e1,l1,cond?"bg":"ble");*/
627 return;
628 case UGT:
629 /*rexpr(e1,l1,cond?"ba":"bbe");*/
630 return;
631 case GE:
632 /*rexpr(e1,l1,cond?"bge":"bl");*/
633 return;
634 case UGE:
635 /*rexpr(e1,l1,cond?"bae":"bb");*/
636 return;
637 case LT:
638 /*rexpr(e1,l1,cond?"bl":"bge");*/
639 return;
640 case ULT:
641 /*rexpr(e1,l1,cond?"bb":"bae");*/
642 return;
643 case LE:
644 /*rexpr(e1,l1,cond?"ble":"bg");*/
645 return;
646 case ULE:
647 /*rexpr(e1,l1,cond?"bbe":"ba");*/
648 return;
649 case EQ:
650 rexpr(e1,l1,cond?"beq":"bne");
651 return;
652 case NEQ:
653 rexpr(e1,l1,cond?"bne":"beq");
654 return;
655 case LAND:
656 b_expr(e2,0,cond?(l2=fwdlabel()):l1);
657 b_expr(caddr(e1),cond,l1);
658 if(cond) fwddef(l2);
659 return;
660 case LOR:
661 b_expr(e2,1,cond?l1:(l2=fwdlabel()));
662 b_expr(caddr(e1),cond,l1);
663 if(!cond) fwddef(l2);
664 return;
665 case CRGVAR:
666 /*printf("\tcmpb $0,%s\n",caddr(e1));*/
667 jcond(l1,cond);
668 return;
669 case CRLVAR:
670 /*printf("\tcmpb $0,%d($fp)\n",lvar(e2));*/
671 jcond(l1,cond);
672 return;
673 case RGVAR:
674 /*printf("\tcmpl $0,%s\n",caddr(e1));*/
675 jcond(l1,cond);
676 return;
677 case RLVAR:
678 /*printf("\tlw \t%s,%d($fp)\n",crn,lvar(e2));*/
679 jcond(l1,cond);
680 return;
681 case REGISTER:
682 /*printf("\tcmpl $0,%s\n",register_name(e2));*/
683 jcond(l1,cond);
684 return;
685 case CONST:
686 if((cond&&e2)||(!cond&&!e2)) jmp(l1);
687 return;
688 default:
689 g_expr(e1);
690 /*printf("\tcmpl $0,%s\n",crn);*/
691 jcond(l1,cond);
692 return;
693 }
694 }
695
696 void
697 ascii(char *s)
698 {
699 printf("\t.ascii \"");
700 while(*s) {
701 if (*s=='\n')
702 printf("%cn",92);
703 else if (*s<' ')
704 printf("%c%03o",92,*s);
705 else if (*s==34)
706 printf("%c%c",92,34);
707 else
708 printf("%c",*s);
709 s++;
710 }
711 printf("%c\n",34);
712 }
713
714 void
715 string(int e1)
716 {
717 char *s;
718 int i,lb;
719
720 if (0) {
721 s=(char *)cadr(e1);
722 printf("\t.rdata\n");
723 printf("\t.align\t2\n");
724 lb=fwdlabel();
725 printf("\tj\t$L%d\n",lb);
726 i=backdef();
727 ascii(s);
728 printf("\t.align 2\n");
729 fwddef(lb);
730 printf("\tla\t%s,$L%d\n",crn,i);
731 } else {
732 s=(char *)cadr(e1);
733 printf("\t.rdata\n");
734 printf("\t.align\t2\n");
735 lb=fwdlabel();
736 printf("$L%d:\n",lb);
737 ascii(s);
738 if (output_mode==TEXT_EMIT_MODE) {
739 printf("\t.text\n");
740 } else {
741 text_mode();
742 }
743 printf("\tla\t%s,$L%d\n",crn,lb);
744 }
745 }
746
747 void
748 function(int e1)
749 {
750 int e2,e3,e4,e5,nargs;
751 NMTBL *n;
752
753 e2 = cadr(e1);
754 nargs = 0;
755 for (e3 = caddr(e1); e3; e3 = cadr(e3)) {
756 n=(NMTBL *)(e5=(cadr(e4 = car(e3))));
757 switch(car(e4)){
758 case FNAME:
759 printf("\tlw\t%s,0(%s)\n",crn,n->nm);
760 break;
761 case ADDRESS:
762 g_expr(e5);
763 break;
764 default:g_expr(e4);
765 }
766 ++nargs;
767 }
768 if (car(e2) == FNAME) {
769 n=(NMTBL *)cadr(e2);
770 use_register(creg,REG_04,0);
771 printf("\tjal\t%s\n",n->nm);
772 } else {
773 g_expr(e2);
774 use_register(creg,REG_04,0);
775 printf("\tjal\t*%s\n",crn);
776 }
777 /*if (nargs) printf("\taddl $%d,%%esp\n",size_of_int*nargs);*/
778 }
779
780 int
781 arg_size(int e3,int *nargs0)
782 {
783 int i,nargs,offset_list,e,t;
784
785 offset_list = 0;
786 /* we should use prototypes's type */
787 for (i = nargs = 0; e3;e3 =cadr(e3)) {
788 e = car(e3); t = caddr(e3);
789 if (i < MAX_REGISTER_VAR && scalar(t)) {
790 offset_list = list3(-(REG_05+i++),offset_list,e);
791 } else {
792 offset_list =
793 list3(nargs,offset_list,e);
794 nargs += (car(e3)==CHAR?size_of_int:size(t));
795 }
796 }
797 *nargs0 = -nargs;
798 return offset_list;
799 }
800
801 void
802 jump(int e1, int env)
803 {
804 int i,args,e2,e3,e4,e5,nargs,nargs0,regs;
805 NMTBL *n,*code0;
806 int new_disp,scode,disp1;
807 char *xrn;
808
809 /* We need three passes. Compute Stack size, Compute Arg, Copy it. */
810 /* count number of args */
811 args = caddr(e1);
812 args = reverse0(args);
813 nargs = arg_size(args,&new_disp); /* compute in normal order */
814 disp1 = (fnptr->sc==CODE)?0:-size_of_int;
815 if (new_disp+disp1 < disp) { /* have to extend stack */
816 if (fnptr->sc==CODE)
817 printf("\tlw\t$sp,%d($fp)\n",new_disp-size_of_int);
818 else
819 printf("\tlw\t$sp,%d($fp)\n",new_disp+disp_offset);
820 }
821 /* compute jump address */
822 e2 = cadr(e1);
823 if (car(e2) == FNAME) {
824 code0=(NMTBL *)cadr(e2);
825 if (code0->sc!=CODE) {
826 error(STERR); return;
827 }
828 } else { /* indirect */
829 g_expr(e2);
830 emit_push();
831 }
832 /* compute arguments in reverse order */
833 regs = 0;
834 i=MAX_REGISTER_VAR;
835 for (e3=nargs; e3;e3 =cadr(e3)) {
836 n=(NMTBL *)(e5=(cadr(e4 = caddr(e3))));
837 switch(car(e4)) {
838 case FNAME:
839 printf("\tlw\t%s,0(%s)\n",crn,n->nm);
840 emit_push();
841 break;
842 case ADDRESS:
843 g_expr(e5);
844 emit_push();
845 break;
846 case RLVAR:
847 case CRLVAR:
848 if (env==0 && fnptr->sc==CODE) {
849 if (e5>=0 && e5==car(e3)) {
850 /* The same positioned local variable. No need to copy */
851 reg_stack[reg_sp++] = -2;
852 }
853 break;
854 }
855 g_expr(e4);
856 emit_push();
857 break;
858 case REGISTER:
859 if (i>0 && rname[e5]==REG_05+ --i) {
860 /* The same register variable. No need to copy */
861 reg_stack[reg_sp++] = e5;
862 break;
863 }
864 default:
865 g_expr(e4);
866 emit_push();
867 }
868 regs++;
869 }
870 if (env) {
871 /* change the frame pointer */
872 g_expr(env);
873 printf("\tmove\t%s,$fp\n",crn);
874 } else if (fnptr->sc==FUNCTION) {
875 printf("\tlw\t$fp,%d($fp)\n",disp_offset);
876 }
877 /* force lvar offset mode to CODE */
878 scode = fnptr->sc; fnptr->sc = CODE;
879 /* copy arguments to destination environment if necessary */
880 nargs = reverse0(nargs); /* pop in normal order */
881 i=0;
882 for (e3=nargs; e3;e3 =cadr(e3)) {
883 if ((e4=car(e3))<0) {
884 /* register case */
885 if (reg_stack[--reg_sp]>=REG_05) {
886 /* the same registger */
887 } else {
888 if(reg_stack[reg_sp]<0) {
889 /*printf("\tpopl %s\n",reg_name[rname[REG_05+i]]);*/ /* e4? */
890 } else {
891 printf("\tmove\t%s,%s\n",
892 reg_name[rname[REG_05+i]],
893 reg_name[rname[reg_stack[reg_sp]]]); /* e4? */
894 free_register(reg_stack[reg_sp]);
895 }
896 i++;
897 }
898 } else {
899 /* local variable case */
900 if (reg_stack[reg_sp-1]== -2) {
901 /* same positioned variable */
902 reg_sp--;
903 } else {
904 xrn=emit_pop(0);
905 printf("\tlw\t%s,%d($fp)\n",xrn, lvar(e4));
906 }
907 }
908 }
909 if (car(e2) != FNAME) {
910 xrn=emit_pop(0);
911 }
912 if (!env && new_disp+disp1>disp) {
913 /* shrink stack if necessary */
914 printf("\tlw\t$sp,%d($fp)\n",new_disp-size_of_int);
915 }
916 if (car(e2) == FNAME) {
917 printf("\tj\t%s\n",code0->nm);
918 } else {
919 printf("\tj\t*%s\n",xrn);
920 }
921 fnptr->sc = scode;
922 }
923
924
925 void
926 machinop(int e1)
927 {
928 int e2,e3,op;
929
930 e2 = cadr(e1);
931 op = car(e1);
932 e3 = caddr(e1);
933 g_expr(e3);
934 emit_push();
935 g_expr(e2);
936 tosop(car(e1));
937 return;
938 }
939
940
941 void
942 rindirect(int e1) /* *(p +5 ) */
943
944 {
945 char *op;
946 int e2,e3,byte;
947
948 op = ((byte = (car(e1) == CRINDIRECT)) ? "lb" : "lw");
949 e3 = cadr(e2 = cadr(e1));
950 g_expr(e2);
951 printf("\t%s \t%s,%d(%s)\n",op,crn,lvar(e3),crn);
952 }
953
954 void
955 sassign(int e1)
956 {
957 int e2,e3,e4,sz;
958 char *xrn;
959
960 e2 = cadr(e1);
961 e3 = cadr(e2);
962 e4 = caddr(e1);
963 sz = size(cadr(e2)); /* cld rep movsb */
964 g_expr(e4);
965 emit_push();
966 g_expr(e2);
967 xrn = emit_pop(0);
968 return;
969 }
970
971 void
972 assign(int e1)
973 {
974 char *op;
975 int e2,e3,e4,byte;
976 char *xrn;
977
978 op = ((byte=(car(e1) == CASS))? "sb" : "sw");
979 /* e2=e4 */
980 e2 = cadr(e1);
981 e3 = cadr(e2);
982 e4 = caddr(e1);
983 switch(car(e2)) {
984 case GVAR: /* i=3 */
985 g_expr(e4);
986 /*if (byte) use_data_reg(creg,1);*/
987 printf("\t%s \t%s,%s\n",op,crn,caddr(e2));
988 return;
989 case LVAR:
990 g_expr(e4);
991 /*if (byte) use_data_reg(creg,1);*/
992 printf("\t%s \t%s,%d($fp)\n",op,crn,lvar(cadr(e2))*-1);
993 return;
994 case REGISTER:
995 g_expr(e4);
996 if (creg!=cadr(e2))
997 printf("\t%s \t%s,%s\n",op,crn,register_name(cadr(e2)));
998 return;
999 }
1000 g_expr(e4);
1001 emit_push();
1002 g_expr(e2);
1003 xrn = emit_pop(0);
1004 /*if (byte) use_data_reg(creg,1);*/
1005 printf("\t%s %s,(%s)\n",op,xrn,crn);
1006 printf("\tmove\t%s,%s\n",crn,xrn);
1007 return;
1008 }
1009
1010 void
1011 assop(int e1)
1012 {
1013 int e2,e3,byte,op,new_reg;
1014 char *xrn;
1015
1016 /* e2 op= e3 */
1017 byte = (car(e1) == CASSOP);
1018 e2 = cadr(e1);
1019 if (car(e2)==INDIRECT) e2=cadr(e2);
1020 e3 = caddr(e1);
1021 op = cadddr(e1);
1022
1023 g_expr(e3);
1024 emit_push();
1025 if (car(e2)==REGISTER) {
1026 new_reg=creg;
1027 set_crn(cadr(e2));
1028 tosop(op);
1029 set_crn(new_reg);
1030 printf("\tmove\t%s,%s\n",crn,register_name(cadr(e2)));
1031 return;
1032 }
1033 g_expr(e2);
1034 xrn = emit_pop(0); /* pop e3 value */
1035 /*printf("\tpushl %s # assop \n",crn);*/ /* push e2 address */
1036 ld_indexx(byte,0,crn);
1037 new_reg = get_register();
1038 /* push e3 value */
1039 if(new_reg<0) { /* もうレジスタがない */
1040 reg_stack[reg_sp++] = -1;
1041 /*printf("\tpushl %s\n",xrn);*/
1042 } else {
1043 reg_stack[reg_sp++] = xreg; /* push するかわりにレジスタを使う */
1044 }
1045 tosop(op);
1046 if(new_reg>=0) free_register(new_reg);
1047 /*printf("\tpopl %s # assop \n",drn);*/
1048 printf("\t%s\t%s,0(%s)\n",byte ? "lb" : "lw",crn,drn);
1049 return;
1050
1051 }
1052
1053
1054 void
1055 tosop(int op)
1056 {
1057 int oreg;
1058 char *orn;
1059
1060 oreg = pop_register();
1061 switch(op) {
1062 case LSHIFT:
1063 case ULSHIFT:
1064 shift("sall",oreg);
1065 return;
1066 case RSHIFT:
1067 shift("sarl",oreg);
1068 return;
1069 case URSHIFT:
1070 shift("shrl",oreg);
1071 return;
1072 }
1073 if(oreg==-1) {
1074 oreg = dreg;
1075 }
1076 orn = reg_name[rname[oreg]];
1077 switch(op) {
1078 case ADD:
1079 printf("\taddu \t%s,%s,%s\n",crn,crn,orn);
1080 return;
1081 case SUB:
1082 printf("\tsubu \t%s,%s,%s\n",crn,crn,orn);
1083 return;
1084 case BAND:
1085 printf("\tand \t%s,%s,%s\n",crn,crn,orn);
1086 return;
1087 case EOR:
1088 printf("\txor \t%s,%s,%s\n",crn,crn,orn);
1089 return;
1090 case BOR:
1091 printf("\tor \t%s,%s,%s\n",crn,crn,orn);
1092 return;
1093 case MUL:
1094 case UMUL:
1095 printf("\t%s\t%s,%s\n","mult",crn,orn);
1096 printf("\tmflo\t%s\n",crn);
1097 return;
1098 case DIV:
1099 case UDIV:
1100 if (op==DIV)
1101 printf("\tdiv\t%s,%s,%s\n",crn,crn,orn);
1102 else
1103 printf("\txor\t%s,%s,%s\n\tdiv\t%s,%s,%s\n",crn,crn,orn,crn,crn,orn);
1104 return;
1105 case MOD:
1106 case UMOD:
1107 if (op==MOD)
1108 printf("\trem\t%s,%s,%s\n",crn,crn,orn);
1109 else
1110 printf("\txor\t%s,%s,%s\n\tdiv\t%s,%s,%s\n",crn,crn,orn,crn,crn,orn);
1111 return;
1112 }
1113 }
1114
1115 void
1116 shift(char *op, int reg)
1117 {
1118 if (reg>=0) {
1119 use_register(lreg,REG_03,1);
1120 } else {
1121 use_register(dreg,REG_03,0);
1122 }
1123 /*printf("\t%s %%cl,%s\n",op,crn);*/
1124 }
1125
1126 void
1127 ld_indexx(int byte, int n, char *xrn)
1128 {
1129 char *op;
1130
1131 op = byte ? "lb" : "lw";
1132 if (n)
1133 printf("\t%s\t%s,%d(%s)\n",op,crn,n,xrn);
1134 else
1135 printf("\t%s\t%s,0(%s)\n",op,crn,xrn);
1136 }
1137
1138 void
1139 st_indexx(int byte, int n, char *xrn)
1140 {
1141 char *op;
1142
1143 op = byte ? "sb" : "sw";
1144 if (n)
1145 printf("\t%s\t%s,%d(%s)\n",op,crn,n,xrn);
1146 else
1147 printf("\t%s\t%s,0(%s)\n",op,crn,xrn);
1148 }
1149
1150 void
1151 indexy(char *op, char *gvar)
1152 {
1153 printf("\t%s %s,%s\n",op,crn,gvar);
1154 }
1155
1156 void
1157 cmpdimm(int e, int csreg)
1158 {
1159 /* used in dosiwtch() */
1160 use_register(creg,csreg,0);
1161 /*printf("\tcmpl $%d,%s\n",e,crn);*/
1162 }
1163
1164 void
1165 opening(char *filename)
1166 {
1167 printf("\t.file \t1 \"%s\"\n",filename);
1168 printf(" # GNU C 2.7.2.2 [AL 1.1, MM 40] Sony PlayStation compiled by GNU C\n\n");
1169 printf(" # Cc1 defaults:\n\n");
1170 printf(" # Cc1 arguments (-G value = 8, Cpu = 3000, ISA = 1):\n");
1171 printf(" # -msoft-float -quiet -dumpbase -o\n\n");
1172 printf(" # gcc2_compiled.:\n");
1173 printf(" # __gnu_compiled_c:\n");
1174
1175 printf("\t.text\n");
1176 emit_init();
1177 }
1178
1179 void
1180 closing(void)
1181 {
1182 global_table();
1183 }
1184
1185 void
1186 jmp_label(int l)
1187 {
1188 printf("\tjmp\t_%d\n",l);
1189 }
1190
1191 void
1192 jmp_eq_label(int l)
1193 {
1194 printf("\tj\t_%d\n",l);
1195 }
1196
1197 void
1198 rexpr(int e1, int l1, char *s)
1199 {
1200 g_expr(list3(SUB,cadr(e1),caddr(e1)));
1201 printf("\t%s\t%s,%s,$L%d\n",s,crn,crn,l1);
1202 }
1203
1204 void
1205 jcond(int l, char cond)
1206 {
1207 printf("\t%s\t%s,%s,$L%d\n",cond?"bne":"beq",crn,crn,l);
1208 }
1209
1210 void
1211 jmp(int l)
1212 {
1213 control=0;
1214 printf("\tj\t$L%d\n",l);
1215 /* align? */
1216 }
1217
1218 int
1219 fwdlabel(void)
1220 {
1221 return labelno++;
1222 }
1223
1224 void
1225 fwddef(int l)
1226 {
1227 control=1;
1228 printf("$L%d:\n",l);
1229 }
1230
1231 int
1232 backdef(void)
1233 {
1234 control=1;
1235 printf("$L%d:\n",labelno);
1236 return labelno++;
1237 }
1238
1239 void
1240 def_label(int cslabel, int dlabel)
1241 {
1242 int fl;
1243
1244 fl = 0;
1245 if (control) {
1246 jmp(fl=fwdlabel());
1247 }
1248 fwddef(cslabel);
1249 if (dlabel)
1250 jmp(dlabel);
1251 if (fl) {
1252 fwddef(fl);
1253 }
1254 }
1255
1256 void
1257 gen_comment(char *s)
1258 {
1259 printf("# %s",s);
1260 }
1261
1262 void
1263 gen_source(char *s)
1264 {
1265 printf("%s",s);
1266 }
1267
1268 void
1269 code_enter(char *name)
1270 {
1271 printf("\t.align 4\n");
1272 if (stmode!=STATIC)
1273 printf(".globl %s\n",name);
1274 printf("\t.type\t%s,@function\n",name);
1275 printf("%s:\n",name);
1276 }
1277
1278 void
1279 code_enter1(int disp0,int args)
1280 {
1281 if(disp0) {
1282 printf("\tsubl $%d,%%esp\n",-disp0);
1283 }
1284 }
1285
1286 void
1287 code_leave(char *name)
1288 {
1289 local_table();
1290 printf("$L%d:\n",labelno);
1291 printf("\t.size\t%s,_%d-%s\n",name,labelno,name);
1292 labelno++;
1293 }
1294
1295 void
1296 enter(char *name, int disp)
1297 {
1298 int a,b,i;
1299 a = b = 0;
1300
1301 /*printf("\t.text\n");
1302 printf("\t.align \t2\n");
1303 if (stmode!=STATIC)
1304 printf("\t.globl \t%s\n",name);*/
1305 printf("%s:\n",name);
1306
1307 printf("\t.frame \t$fp,%d,$31\n",-disp+save_reg*size_of_int);
1308
1309
1310 if(disp) a = 8;
1311
1312 printf("\t.mask \t0x%d0000000,-8\n",a);
1313 printf("\t.fmask \t0x00000000,0\n");
1314
1315 if(disp){
1316 printf("\tsubu \t$sp,$sp,%d\n",-disp+save_reg*size_of_int);
1317 printf("\tsw\t$31,%d($sp)\n",-disp+4*save_reg1);
1318 save_reg1--;
1319 }
1320 for(i=save_reg1;i==0;i--) {
1321 printf("\tsw\t$%d,%d($sp)\n",16+i,-disp+4*i);
1322 }
1323
1324 /*if(strcmp("main",name))
1325 printf("\tjal \t%s_0\n",name);
1326 else
1327 printf("\tjal \t__%s_0\n",name);*/
1328
1329 printf("\tjal \t%s_0\n",name);
1330
1331 printf("\t.end \t%s\n",name);
1332 printf("\t.sdata\n");
1333 printf("\t.align 2\n");
1334
1335 save_reg = 0;
1336 save_reg1 = 0;
1337 }
1338
1339 /* void
1340 enter_no(char *name, int disp)
1341 {
1342
1343 printf("\t.align \t2\n");
1344 if (stmode!=STATIC)
1345 printf("\t.globl \t%s\n",name);
1346
1347 printf("\t.ent \t%s\n",name);
1348 printf("%s_0:\n",name);
1349 }
1350
1351 */
1352 void
1353 enter1(int disp)
1354 {
1355 if(disp) printf("\tsubu \t$sp,$sp,%d\n",-disp+save_reg*size_of_int);
1356
1357 }
1358
1359 void
1360 leave(int control, char *name)
1361 {
1362 int i;
1363
1364 if (control)
1365 use_register(creg,REG_04,1);
1366 if (retcont) {
1367 if (control)
1368 jmp(retlabel);
1369 fwddef(retcont);
1370 use_register(creg,REG_04,0);
1371 printf("\tmove\t%s,%s\n",crn,reg_name[REG_05]);
1372 }
1373 fwddef(retlabel);
1374 use_register(creg,REG_04,0);
1375 save_reg1 = save_reg;
1376 printf("\tmove\t$sp,$fp\n");
1377
1378 printf("\tlw\t$31,%d($sp)\n",-disp+4*save_reg);
1379 save_reg--;
1380 for(i=save_reg;i==0;i--) {
1381 printf("\tlw\t$%d,%d($sp)\n",16+i,-disp+4*i);
1382 }
1383
1384
1385 if(disp) printf("\taddu \t$sp,$sp,%d\n",-disp+save_reg*size_of_int);
1386 printf("\tj\t$31\n");
1387
1388 local_table();
1389 printf("$L%d:\n",labelno);
1390 labelno++;
1391 }
1392
1393
1394 void
1395 ret(void)
1396 {
1397 use_register(creg,REG_04,1);
1398 jmp(retlabel);
1399 }
1400
1401 void
1402 gen_gdecl(char *n, int gpc)
1403 {
1404 /*
1405 if (stmode!=STATIC)
1406 printf(".globl %s\n",n);
1407 */
1408 }
1409
1410 void
1411 align(int t)
1412 {
1413 if (t!=CHAR) {
1414 if (data_alignment & 1)
1415 printf("\t.align 2\n");
1416 data_alignment = 0;
1417 }
1418 }
1419
1420 void
1421 emit_data(int e, int t, NMTBL *n)
1422 {
1423 int l;
1424 char *name;
1425 name = n->nm;
1426 if(mode==GDECL) { /* global */
1427 if (n->dsp != -1) {
1428 n->dsp = -1; /* initiallized flag */
1429 printf(".globl\t%s\n",name);
1430 data_mode(name);
1431 align(t);
1432 printf("%s:\n",name);
1433 } else {
1434 data_mode(0);
1435 }
1436 if(car(e)==CONST) {
1437 if (t==CHAR) {
1438 printf("\t.byte %d\n",cadr(e));
1439 if (data_alignment>0)
1440 data_alignment++;
1441 gpc += 1;
1442 } else {
1443 printf("\t.long %d\n",cadr(e));
1444 gpc += size_of_int;
1445 }
1446 } else if(t!=CHAR) {
1447 gpc += size_of_int;
1448 if(car(e)==ADDRESS&&car(cadr(e))==GVAR) {
1449 printf("\t.word %s\n",caddr(cadr(e)));
1450 } else if(car(e)==FNAME) {
1451 printf("\t.word %s\n",((NMTBL *)cadr(e))->nm);
1452 } else if(car(e)==STRING) {
1453 if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) {
1454 l = fwdlabel();
1455 printf("\t.word _%d\n",l);
1456 printf("$L%d:\n",l);
1457 output_mode = RODATA_EMIT_MODE;
1458 }
1459 ascii((char *)cadr(e));
1460 } else error(TYERR);
1461 }
1462 } else {
1463 /* if (n->sc!=LVAR) { error(TYERR); return; } */
1464 if(car(e)==CONST) {
1465 printf("\tmove\t%s,%d\n",crn,cadr(e));
1466 printf("\t%s\t%s,%d($fp)\n",t==CHAR?"lb":"lw",crn,n->dsp);
1467 } else if(t!=CHAR) {
1468 if(car(e)==ADDRESS&&car(cadr(e))==GVAR)
1469 printf("\tlw\t%s,0(%s)\n",crn,caddr(e));
1470 else if(car(e)==FNAME)
1471 printf("\tlw\t%s,0(%s)\n",crn,((NMTBL *)cadr(e))->nm);
1472 else if(car(e)==STRING) {
1473 string(e);
1474 } else error(TYERR);
1475 printf("\tlw\t%s,%d($fp)\n",crn,n->dsp);
1476 }
1477 }
1478 }
1479
1480 void
1481 emit_data_closing(NMTBL *n)
1482 {
1483 int lb;
1484 if (mode=GDECL) {
1485 data_mode(0);
1486 lb=fwdlabel();
1487 printf("$L%d:\n",lb);
1488 printf("\t.size\t%s,_%d-%s\n",n->nm,lb,n->nm);
1489 }
1490 }
1491
1492 void
1493 global_table(void)
1494 {
1495 NMTBL *n;
1496 for(n=ntable;n < &ntable[GSYMS];n++) {
1497 if (n->sc == GVAR && n->dsp != -1) {
1498 /* n->dsp = -1 means initialized global */
1499 printf("\n\t.comm \t%s,%d\n",n->nm,size(n->ty));
1500 }
1501 }
1502 }
1503
1504 void
1505 local_table(void)
1506 {
1507 NMTBL *n;
1508 /* static local variables */
1509 for(n=ntable+GSYMS;n < &ntable[GSYMS+LSYMS];n++) {
1510 if (n->sc == GVAR) {
1511 printf(".lcomm %s,%d\n",n->nm,size(n->ty));
1512 }
1513 }
1514 }
1515
1516 void
1517 text_mode(void)
1518 {
1519 if (output_mode!=TEXT_EMIT_MODE) {
1520 printf(".text\n");
1521 printf("\t.align 2\n");
1522 output_mode = TEXT_EMIT_MODE;
1523 }
1524 }
1525
1526 void
1527 data_mode(char *name)
1528 {
1529 if (output_mode!=DATA_EMIT_MODE) {
1530 printf(".data\n");
1531 output_mode = DATA_EMIT_MODE;
1532 }
1533 if (name)
1534 printf("\t.type\t%s,@object\n",name);
1535 }
1536
1537 int
1538 lvar(int l)
1539 {
1540 if (l<0) {
1541 if (fnptr->sc==CODE)
1542 return l+code_disp_offset;
1543 else
1544 return l+disp_offset;
1545 } else {
1546 if (fnptr->sc==CODE)
1547 return -l+code_arg_offset;
1548 else
1549 return l+arg_offset;
1550 }
1551 }
1552
1553 /* end */