Mercurial > hg > CbC > old > device
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 */ |