comparison mc-code-ia32.c @ 61:8ffb8ca3fe34

separation of architecture dependent part.
author kono
date Thu, 20 Feb 2003 03:29:15 +0900
parents
children 129f4802b027
comparison
equal deleted inserted replaced
60:aa779bcffef7 61:8ffb8ca3fe34
1 /* Micro-C Code Generatation Part for intel386 */
2 /* $Id$ */
3
4 #define EXTERN extern
5 #include "mc.h"
6 #include "mc-codegen.h"
7
8 #define TEXT_EMIT_MODE 0
9 #define DATA_EMIT_MODE 1
10 #define RODATA_EMIT_MODE 2
11
12 static int output_mode = TEXT_EMIT_MODE;
13 static int data_alignment = 0;
14
15 static int code_disp_label;
16 static int func_disp_label;
17
18 /*
19 -16 -8 local2
20 -12 -4 local1
21 -8 8 arg3
22 -4 4 arg2
23 0 0 arg1
24 local2 -20 4 0 (%edi)
25 local1 <-- -16 0 local variable 0 (%esi)
26 %edi -12 <- disp_offset %ebp
27 %esi -8
28 %ebx -4
29 %ebp = %esp 0
30 %eip 4 <- arg_offset
31 arg1 8 0
32 arg2 12 4
33 see enter/enter1/leave see code_enter
34 */
35 int arg_offset = 8;
36 int disp_offset = -12;
37 int func_disp_offset = -12;
38 int code_disp_offset = 0;
39 int jump_offset = 0;
40
41 int size_of_int = 4;
42 int endian = 0;
43 int MAX_REGISTER=6; /* intel386のレジスタを4つまで使う*/
44 int REAL_MAX_REGISTER=8; /* intel386のレジスタが8つということ*/
45 int MAX_DATA_REG=4;
46 int MAX_POINTER=3;
47 int MAX_REGISTGER_VAR=2;
48
49 EXTERN int creg; /* current register */
50 EXTERN int dreg; /* temporary register */
51 EXTERN int reg_sp; /* REGister Stack-Pointer */
52
53
54 #define REG_EAX 0
55 #define REG_EBX 1
56 #define REG_ECX 2
57 #define REG_EDX 3
58 #define REG_ESI 4
59 #define REG_EDI 5
60 #define REG_EBP 6
61 #define REG_ESP 7
62
63
64 #define DATA_REG 0
65 #define POINTER_REG 3
66 static char *reg_name[8];
67 static char *reg_name_l[4];
68 static char *reg_name_w[4];
69
70 extern int creg; /* current register */
71 extern int dreg; /* temporary register */
72 extern int reg_sp; /* REGister Stack-Pointer */
73
74 #define MAX_MAX 10
75 int rname[MAX_MAX];
76 int regs[MAX_MAX]; /* 使われているレジスタを示すフラグ */
77 int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
78 int regv[MAX_MAX]; /* 値が入っているかどうか */
79
80
81 void use_register(int virt, int real, int move);
82 void code_preinc(int e1,int e2) ;
83 void code_cmp_register(int e2) ;
84 void code_assign_gvar(int e2,int byte) ;
85 void tosop(int op,int oreg);
86 void edx_cleanup();
87 void shift(char *op, int reg);
88 void ld_indexx(int byte, int n, int xreg);
89 void jmp(int l);
90 void global_table(void);
91 void local_table(void);
92 void text_mode(void);
93 void data_mode(char *name);
94
95 char *register_name(int i,int byte);
96 int register_var(int r);
97 int get_register_var(void);
98 void emit_push(void);
99 void emit_push_x(int xreg);
100 int emit_pop(int type);
101 void code_crlvar(int e2);
102 void code_preinc(int e1,int e2);
103 void code_postinc(int e1,int e2);
104 void code_bool(int e1);
105 void string(int e1);
106 void emit_copy(int from,int to,int length,int offset,int value,int det);
107 int struct_push(int e4,int t);
108 void function(int e1);
109 void code_assop(int op,int byte);
110 int edx_setup();
111 void opening(char *filename);
112 void code_leave(char *name);
113 int lvar(int l);
114
115 void
116 code_init(void)
117 {
118 arg_offset = 8;
119 func_disp_offset = -12;
120 disp_offset = -12;
121 size_of_int = 4;
122 endian = 0;
123 MAX_REGISTER=6;
124 MAX_DATA_REG=4;
125 MAX_POINTER=3;
126 MAX_REGISTER_VAR=2;
127
128 reg_name[REG_EAX] = "%eax";
129 reg_name[REG_EBX] = "%ebx";
130 reg_name[REG_ECX] = "%ecx";
131 reg_name[REG_EDX] = "%edx";
132 reg_name[REG_ESI] = "%esi";
133 reg_name[REG_EDI] = "%edi";
134 reg_name[REG_EBP] = "%ebp";
135 reg_name[REG_ESP] = "%esp";
136 reg_name_l[REG_EAX] = "%al";
137 reg_name_l[REG_EBX] = "%bl";
138 reg_name_l[REG_ECX] = "%cl";
139 reg_name_l[REG_EDX] = "%dl";
140 reg_name_w[REG_EAX] = "%ax";
141 reg_name_w[REG_EBX] = "%bx";
142 reg_name_w[REG_ECX] = "%cx";
143 reg_name_w[REG_EDX] = "%dx";
144
145 }
146
147 char *
148 register_name(int i,int byte)
149 {
150 if (i<0) {
151 error(REG_ERR);
152 return "%eax";
153 }
154 if (byte && rname[i] <= REG_EDX) {
155 return reg_name_l[rname[i]];
156 } else {
157 return reg_name[rname[i]]; /* should be error */
158 }
159 }
160
161 extern int rname[MAX_MAX];
162 extern int regs[MAX_MAX]; /* 使われているレジスタを示すフラグ */
163 extern int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
164 extern int regv[MAX_MAX]; /* 値が入っているかどうか */
165
166 extern int creg_regvar;
167
168 void
169 gexpr_code_init(void){
170 use_register(creg,REG_EAX,0);
171 regv[dreg]=0;
172 creg_regvar = -1;
173 }
174
175 int
176 register_var(int r) {
177 return virtual(r+REG_ESI);
178 }
179
180 int
181 get_register_var(void)
182 {
183 int i;
184 for(i=REG_ESI;i<REG_ESP;i++) {
185 if (! regs[i]) { /* 使われていないなら */
186 regs[i]=1; /* そのレジスタを使うことを宣言し */
187 regv[i]=0;
188 return i; /* その場所を表す番号を返す */
189 }
190 }
191 return -1;
192 }
193
194 void
195 use_register(int virt, int real, int move)
196 {
197 int real_v;
198 char *move_op;
199 if (rname[virt]==real)
200 return;
201 real_v = virtual(real);
202 move_op = regs[real_v]?"\txchg %s,%s\n":"\tmovl %s,%s\n";
203 if (move || (regv[real_v])) {
204 printf(move_op,reg_name[rname[virt]],reg_name[real]);
205 }
206 rname[real_v] = rname[virt];
207 rname[virt] = real;
208 }
209
210 void
211 use_pointer(int virt, int move)
212 {
213 int i;
214 if (rname[virt]>=POINTER_REG)
215 return;
216 for(i=POINTER_REG;i<MAX_REGISTER;i++) {
217 if (!regs[virtual(i)]) {
218 use_register(virt,i,move);
219 return;
220 }
221 }
222 /* we prefer EBX */
223 use_register(virt,REG_EBX,move);
224 }
225
226 void
227 use_data_reg(int virt, int move)
228 {
229 int i;
230 if (rname[virt]<MAX_DATA_REG)
231 return;
232 for(i=0;i<MAX_DATA_REG;i++) {
233 if (!regs[virtual(i)]) {
234 use_register(virt,i,move);
235 return;
236 }
237 }
238 /* we prefer EBX */
239 use_register(virt,REG_EBX,move);
240 }
241
242
243 void
244 emit_push(void)
245 {
246 int new_reg;
247 new_reg = get_register();
248 if(new_reg<0) { /* もうレジスタがない */
249 reg_stack[reg_sp++] = -1;
250 printf("\tpushl %s\n",register_name(creg,0));
251 /* creg is used soon, don't regv[creg]=0 */
252 } else {
253 reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */
254 creg = new_reg;
255 regv[creg]=1;
256 }
257 }
258
259 void
260 emit_push_x(int xreg)
261 {
262 int new_reg;
263 new_reg = get_register();
264 if(new_reg<0) { /* もうレジスタがない */
265 reg_stack[reg_sp++] = -1;
266 printf("\tpushl %s\n",register_name(xreg,0));
267 /* creg is used soon, don't regv[xreg]=0 */
268 } else {
269 reg_stack[reg_sp++] = xreg; /* push するかわりにレジスタを使う */
270 xreg = new_reg;
271 regv[xreg]=1;
272 }
273 }
274
275 int
276 emit_pop(int type)
277 {
278 int xreg;
279 if ((xreg=pop_register())==-1) {
280 if (type==POINTER_REG)
281 use_pointer(dreg,0);
282 else if (type==DATA_REG)
283 use_data_reg(dreg,0);
284 if (regv[dreg]) {
285 printf("# emit_pop dreg conflict\n");
286 }
287 printf("\tpopl %s\n",register_name(dreg,0));
288 xreg = dreg;
289 regv[xreg]=1;
290 }
291 return xreg;
292 }
293
294
295 void
296 code_gvar(int e1) {
297 printf("\tmovl $%s,%s\n",(char *)caddr(e1),register_name(creg,0));
298 }
299
300
301 void
302 code_rgvar(int e1) {
303 printf("\tmovl %s,%s\n",(char *)caddr(e1),register_name(creg,0));
304 }
305
306 void
307 code_crgvar(e1){
308 printf("\tmovsbl %s,%s\n",(char *)caddr(e1),register_name(creg,0));
309 }
310
311
312 void
313 code_lvar(int e2) {
314 printf("\tlea %d(%%ebp),%s\n",e2,register_name(creg,0));
315 }
316
317
318 void
319 code_register(int e2) {
320 printf("\tmovl %s,%s\n",register_name(e2,0),register_name(creg,0));
321 }
322
323
324 void
325 code_rlvar(int e2) {
326 printf("\tmovl %d(%%ebp),%s\n",e2,register_name(creg,0));
327 }
328
329
330 void
331 code_crlvar(int e2) {
332 printf("\tmovsbl %d(%%ebp),%s\n",lvar(e2),register_name(creg,0));
333 }
334
335
336 void
337 code_fname(char *e2) {
338 printf("\tmovl $%s,%s\n",e2,register_name(creg,0));
339 }
340
341
342 void
343 code_const(int e2) {
344 printf("\tmovl $%d,%s\n",e2,register_name(creg,0));
345 }
346
347
348 void
349 code_neg() {
350 printf("\tnegl %s\n", register_name(creg,0));
351 }
352
353
354 void
355 code_not() {
356 printf("\tnotl %s\n", register_name(creg,0));
357 }
358
359
360 void
361 code_lnot() {
362 char *xrn;
363 use_data_reg(creg,1);
364 xrn = register_name(creg,1);
365 printf("\tcmpl $0,%s\n", register_name(creg,0));
366 printf("\tsete %s\n", xrn);
367 printf("\tmovzbl %s,%s\n", xrn,register_name(creg,0));
368 }
369
370 void
371 code_preinc(int e1,int e2) {
372 char *xrn;
373 if (car(e2)==REGISTER) {
374 printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0));
375 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0));
376 return;
377 }
378 g_expr(e2);
379 xrn = register_name(creg,0);
380 printf("\taddl $%d,(%s)\n",caddr(e1),xrn);
381 printf("\tmovl (%s),%s\n",xrn,xrn);
382 }
383
384
385 void
386 code_postinc(int e1,int e2) {
387 char *xrn;
388 if (car(e2)==REGISTER) {
389 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0));
390 printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0));
391 return;
392 }
393 g_expr(e2);
394 emit_push();
395 xrn = register_name((e2=emit_pop(0)),0);
396 printf("\tmovl (%s),%s\n",xrn,register_name(creg,0));
397 printf("\taddl $%d,(%s)\n",caddr(e1),xrn);
398 emit_pop_free(e2);
399 }
400
401
402 void
403 code_cpostinc(int e1,int e2) {
404 char *xrn;
405 if (car(e2)==REGISTER) {
406 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0));
407 printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0));
408 return;
409 }
410 g_expr(e2);
411 emit_push();
412 xrn = register_name((e2=emit_pop(0)),1);
413 printf("\tmovsbl (%s),%s\n",xrn,register_name(creg,0));
414 printf("\tincl (%s)\n",xrn);
415 emit_pop_free(e2);
416 }
417
418
419 void
420 code_cpreinc(int e1,int e2) {
421 if (car(e2)==REGISTER) {
422 printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0));
423 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0));
424 return;
425 }
426 g_expr(e2);
427 printf("\tincl (%s)\n",register_name(creg,0));
428 printf("\tmovsbl (%s),%s\n",register_name(creg,0),register_name(creg,0));
429 }
430
431
432 void
433 code_cpostdec(int e1,int e2) {
434 if (car(e2)==REGISTER) {
435 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0));
436 printf("\tdecl %s\n",register_name(cadr(e2),0));
437 return;
438 }
439 g_expr(e2);
440 printf("\tmovsbl (%s),%s\n",register_name(creg,0),register_name(creg,0));
441 printf("\tdecl (%s)\n",register_name(creg,0));
442 }
443
444
445 void
446 code_cpredec(int e1,int e2) {
447 if (car(e2)==REGISTER) {
448 printf("\tdecl %s\n",register_name(cadr(e2),0));
449 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0));
450 return;
451 }
452 g_expr(e2);
453 emit_push();
454 e2 = emit_pop(0);
455 printf("\tdecl (%s)\n",register_name(e2,0));
456 printf("\tmovsbl (%s),%s\n",register_name(e2,0),register_name(creg,0));
457 emit_pop_free(e2);
458 }
459
460
461 void
462 code_return() {
463 printf("\tleal _%d,%s\n",retcont,register_name(creg,0));
464 }
465
466
467 void
468 code_environment() {
469 printf("\tmovl %%ebp,%s\n",register_name(creg,0));
470 }
471
472
473 void
474 code_bool(int e1) {
475 char *xrn;
476 int e2,e3;
477 b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */
478 xrn = register_name(creg,0);
479 printf("\txorl %s,%s\n",xrn,xrn);
480 jmp(e3=fwdlabel());
481 fwddef(e2);
482 printf("\tmovl $1,%s\n",xrn);
483 fwddef(e3);
484 }
485
486 char *
487 code_gt(int cond) {
488 return (cond?"g":"le");
489 }
490
491 char *
492 code_ugt(int cond) {
493 return (cond?"a":"be");
494 }
495
496 char *
497 code_ge(int cond) {
498 return (cond?"ge":"l");
499 }
500
501 char *
502 code_uge(int cond) {
503 return (cond?"ae":"b");
504 }
505
506 char *
507 code_eq(int cond) {
508 return (cond?"e":"ne");
509 }
510
511 void
512 code_cmp_crgvar(int e1) {
513 printf("\tcmpb $0,%s\n",(char *)caddr(e1));
514 }
515
516
517 void
518 code_cmp_crlvar(int e1) {
519 printf("\tcmpb $0,%d(%%ebp)\n",e1);
520 }
521
522
523 void
524 code_cmp_rgvar(int e1) {
525 printf("\tcmpl $0,%s\n",(char *)caddr(e1));
526 }
527
528
529 void
530 code_cmp_rlvar(int e1) {
531 printf("\tcmpl $0,%d(%%ebp)\n",e1);
532 }
533
534
535 void
536 code_cmp_register(int e2) {
537 printf("\tcmpl $0,%s\n",register_name(e2,0));
538 }
539
540
541 void
542 ascii(char *s)
543 {
544 printf("\t.string \"");
545 while(*s) {
546 if (*s=='\n')
547 printf("%cn",92);
548 else if (*s<' ')
549 printf("%c%03o",92,*s);
550 else if (*s==34)
551 printf("%c%c",92,34);
552 else
553 printf("%c",*s);
554 s++;
555 }
556 printf("%c\n",34);
557 }
558
559 void
560 string(int e1)
561 {
562 char *s;
563 int i,lb;
564
565 if (0) {
566 s=(char *)cadr(e1);
567 lb=fwdlabel();
568 printf("\tjmp _%d\n",lb);
569 i=backdef();
570 ascii(s);
571 printf("\t.align 2\n");
572 fwddef(lb);
573 printf("\tlea _%d,%s\n",i,register_name(creg,0));
574 } else {
575 s=(char *)cadr(e1);
576 printf(".section\t.rodata\n");
577 lb=fwdlabel();
578 printf("_%d:\n",lb);
579 ascii(s);
580 if (output_mode==TEXT_EMIT_MODE) {
581 printf(".text\n");
582 } else {
583 text_mode();
584 }
585 printf("\tlea _%d,%s\n",lb,register_name(creg,0));
586 }
587 }
588
589 #define MAX_COPY_LEN 20
590
591 void
592 emit_copy(int from,int to,int length,int offset,int value,int det)
593 {
594 int fix = 0;
595 /* length <0 means upward direction copy */
596 switch (length) {
597 case 0: break;
598 case 1: case -1:
599 printf("\tmovb %d(%s),%s\n",offset,
600 register_name(from,0), reg_name_l[rname[dreg]] );
601 printf("\tmovb %s,%d(%s)\n",reg_name_l[rname[dreg]] ,offset,
602 register_name(to,0));
603 break;
604 case 2: case -2:
605 printf("\tmovw %d(%s),%s\n",offset,
606 register_name(from,0), reg_name_w[rname[dreg]] );
607 printf("\tmovw %s,%d(%s)\n",reg_name_w[rname[dreg]] ,offset,
608 register_name(to,0));
609 break;
610 case 4: case -4:
611 printf("\tmovl %d(%s),%s\n",offset,
612 register_name(from,0), register_name(dreg,0));
613 printf("\tmovl %s,%d(%s)\n",register_name(dreg,0), offset,
614 register_name(to,0));
615 break;
616 default:
617 if (-MAX_COPY_LEN<length && length <0) {
618 for(;length<=4;length+=4,offset-=4)
619 emit_copy(from,to,4,offset,0,det);
620 for(;length<=2;length+=2,offset-=2)
621 emit_copy(from,to,2,offset,0,det);
622 if(length>0)
623 emit_copy(from,to,length,offset,0,det);
624 break;
625 } else if (length <=MAX_COPY_LEN) {
626 for(;length>=4;length-=4,offset+=4)
627 emit_copy(from,to,4,offset,0,det);
628 for(;length>=2;length-=2,offset+=2)
629 emit_copy(from,to,2,offset,0,det);
630 if(length>0)
631 emit_copy(from,to,length,offset,0,det);
632 break;
633 }
634 if (det) {
635 /*
636 call bcopy
637 g_expr(list3(FUNCTION,,);
638 break;
639 */
640 }
641 use_register(from,REG_ESI,1);
642 use_register(to, REG_EDI,1);
643 use_register(dreg,REG_ECX,0);
644 if (length<0) {
645 printf("\tmovl $%d,%%ecx\n",-length/4);
646 printf("\taddl $%d,%%esi\n",-length);
647 printf("\taddl $%d,%%edi\n",-length);
648 printf("\tstd\n\trep\n\tmovsl\n");
649 if(length%4) {
650 emit_copy(from,to,length,offset+length/4,0,det);
651 }
652 } else {
653 printf("\tmovl $%d,%%ecx\n",length/4);
654 fix = (length/4)*4;
655 printf("\tcld\n\trep\n\tmovsl\n");
656 if(length%4) {
657 emit_copy(from,to,length,offset+length/4,0,det);
658 }
659 }
660 }
661 if (value) {
662 /* creg must point top of the destination data */
663 /* this code is necessary for the value of assignment or function call */
664 /* otherwise we don't need this */
665 if (fix) printf("\tsubl $%d,%s\n",fix,register_name(to,0));
666 if(creg!=to) {
667 if (to==dreg)
668 printf("\tmovl %s,%s\n",register_name(to,0),register_name(creg,0));
669 else {
670 free_register(creg); creg=to;
671 }
672 }
673 }
674 regv[from]=regv[to]=regv[dreg]=0;
675 regv[creg]=1;
676 }
677
678 int
679 struct_push(int e4,int t)
680 {
681 int length,xreg,save,lreg;
682 g_expr(e4);
683 length=size(t);
684 if(length%size_of_int) {
685 length += size_of_int - (length%size_of_int);
686 }
687 if (length==4) {
688 printf("\tpushl (%s)\n",register_name(creg,0)); return 1;
689 }
690 if (length==8) {
691 printf("\tpushl 4(%s)\n",register_name(creg,0));
692 printf("\tpushl (%s)\n",register_name(creg,0)); return 2;
693 }
694 printf("\tsubl $%d,%%esp\n",length);
695 if (register_full()) {
696 save = 1;
697 for(lreg=0;lreg==creg||lreg==dreg;lreg++);
698 printf("\tpushl %s\n",register_name(lreg,0));
699 xreg = lreg; regv[xreg]=0;
700 } else {
701 save=0;
702 xreg = get_register();
703 }
704 if (save)
705 printf("\tlea %d(%%esp),%s\n",size_of_int,register_name(xreg,0));
706 else
707 printf("\tmovl %%esp,%s\n",register_name(xreg,0));
708 regv[xreg]=1;
709 /* downward direction copy */
710 emit_copy(creg,xreg,length,0,0,1);
711 /* we have value in creg, it may be changed */
712 if (save) {
713 if(creg==xreg) {
714 creg = get_register(); /* creg is freed in emit_copy */
715 }
716 printf("\tpopl %s\n",register_name(xreg,0));
717 regv[xreg]=1;
718 } else
719 free_register(xreg);
720 return length/size_of_int;
721 }
722
723 void
724 function(int e1)
725 {
726 int e2,e3,e4,e5,nargs,t;
727 NMTBL *n;
728 int save,saved;
729 if (free_register_count()<1) {
730 for(save = 0;save==dreg||save==creg;save++);
731 printf("\tpushl %s\n",register_name(save,0));
732 saved = 1;
733 } else {
734 save = get_register();
735 saved = 0;
736 }
737 regv[save]=0;
738 e2 = cadr(e1);
739 nargs = 0;
740 for (e3 = caddr(e1); e3; e3 = cadr(e3)) {
741 t=caddr(e3);
742 n=(NMTBL *)(e5=(cadr(e4 = car(e3))));
743 if(scalar(t)) {
744 g_expr(e4);
745 printf("\tpushl %s\n",register_name(creg,0));
746 } else if (car(t)==STRUCT||car(t)==UNION) {
747 nargs += struct_push(e4,t);
748 continue;
749 } else {
750 error(TYERR);
751 }
752 ++nargs;
753 }
754 if (car(e2) == FNAME) {
755 n=(NMTBL *)cadr(e2);
756 } else {
757 use_register(creg,REG_EAX,0);
758 g_expr(e2);
759 }
760
761 /* we don't have to save creg nor dreg */
762 regs[creg]=0; regs[dreg]=0;
763 regv[creg]= regv[dreg]= regv[save]= 0;
764 use_register(creg,REG_EAX,0);
765 use_register(dreg,REG_EDX,0); /* will be destroyed */
766 use_register(save,REG_ECX,0); /* will be destroyed */
767 regs[creg]=1; regs[dreg]=1;
768
769 if (car(e2) == FNAME) {
770 printf("\tcall\t%s\n",n->nm);
771 } else {
772 printf("\tcall\t*%s\n",register_name(creg,0));
773 }
774 if (nargs) printf("\taddl $%d,%%esp\n",size_of_int*nargs);
775 if (saved) {
776 printf("\tpopl %s\n",register_name(save,0));
777 } else {
778 free_register(save);
779 }
780 regv[save]=0;
781 regv[creg]=1;
782 }
783
784 void
785 code_frame_pointer(int e3) {
786 printf("\tmovl %s,%%ebp\n",register_name(e3,0));
787 }
788
789
790 void
791 code_fix_frame_pointer(disp_offset) {
792 printf("\tlea %d(%%ebp),%%ebp\n",disp_offset);
793 }
794
795
796 void
797 code_jmp(char *s) {
798 printf("\tjmp %s\n",s);
799 }
800
801
802 void
803 code_indirect_jmp(int e2) {
804 printf("\tjmp *%s\n",register_name(e2,0));
805 }
806
807 void
808 rindirect(int e1) /* *(p +5 ) */
809 {
810 char *op;
811 int e2,e3,byte;
812
813 op = ((byte = (car(e1) == CRINDIRECT)) ? "movsbl" : "movl");
814 e3 = cadr(e2 = cadr(e1));
815 g_expr(e2);
816 printf("\t%s (%s),%s\n",op,register_name(creg,0),register_name(creg,0));
817 }
818
819 char *
820 move(int byte)
821 {
822 return byte?"movb":"movl";
823 }
824
825 void
826 code_assign_gvar(int e2,int byte) {
827 if (byte) use_data_reg(creg,1);
828 printf("\t%s %s,%s\n",move(byte),register_name(creg,byte),(char *)caddr(e2));
829 }
830
831 void
832 code_assign_lvar(int e2,int byte) {
833 if (byte) use_data_reg(creg,1);
834 printf("\t%s %s,%d(%%ebp)\n",move(byte),register_name(creg,byte),e2);
835 }
836
837 void
838 code_assign_register(int e2,int byte) {
839 printf("\tmovl %s,%s\n",register_name(creg,0),register_name(e2,0));
840 }
841
842 void
843 code_assign(int e2,int byte) {
844 printf("\t%s %s,(%s)\n",move(byte),register_name(creg,byte),register_name(e2,0));
845 }
846
847
848 void
849 code_register_assop(int e2,int op,int byte) {
850 int reg;
851 int xreg = creg;
852 creg = reg = e2;
853 tosop(op,xreg);
854 creg = xreg;
855 printf("\tmovl %s,%s\n",register_name(reg,0),register_name(creg,0));
856 }
857
858
859 void
860 code_assop(int op,int byte) {
861 char *xrn;
862 int xreg;
863 int edx = edx_setup();
864 xrn = register_name(xreg = emit_pop(0),0); /* pop e3 value */
865 regv[xreg]=regs[xreg]=1;
866 printf("\tmovl %s,%s # assop \n",register_name(creg,0),register_name(edx,0));
867 regv[edx]=1;
868 ld_indexx(byte,0,edx);
869 tosop(op,xreg);
870 printf("\t%s %s,(%s)\n",byte ? "movb" : "movl",register_name(creg,byte),register_name(edx,0));
871 edx_cleanup();
872 emit_pop_free(xreg);
873 }
874
875
876 void
877 tosop(int op,int oreg)
878 {
879 int dx;
880 char *orn,*crn;
881
882 switch(op) {
883 case LSHIFT:
884 case ULSHIFT:
885 shift("sall",oreg);
886 return;
887 case RSHIFT:
888 shift("sarl",oreg);
889 return;
890 case URSHIFT:
891 shift("shrl",oreg);
892 return;
893 }
894 if(oreg==-1) {
895 printf("\tpopl %s\n",register_name(dreg,0));
896 oreg = dreg;
897 regv[dreg]=1;
898 }
899 regv[oreg]=1; regs[oreg]=1;
900 orn = register_name(oreg,0);
901 crn = register_name(creg,0);
902 switch(op) {
903 case ADD:
904 printf("\taddl %s,%s\n",orn,crn);
905 break;
906 case SUB:
907 printf("\tsubl %s,%s\n",orn,crn);
908 break;
909 case BAND:
910 printf("\tandl %s,%s\n",orn,crn);
911 break;
912 case EOR:
913 printf("\txorl %s,%s\n",orn,crn);
914 break;
915 case BOR:
916 printf("\torl %s,%s\n",orn,crn);
917 break;
918 case MUL:
919 case UMUL:
920 printf("\t%s %s,%s\n","imull",orn,crn);
921 break;
922 case DIV:
923 case UDIV:
924 use_register(creg,REG_EAX,1);
925 edx_setup();
926 orn = register_name(oreg,0);
927 if (op==DIV)
928 printf("\tcltd\n\tdivl %s\n",orn);
929 else
930 printf("\txor %%edx,%%edx\n\tidivl %s\n",orn);
931 edx_cleanup();
932 break;
933 case MOD:
934 case UMOD:
935 use_register(creg,REG_EAX,1);
936 edx_setup();
937 orn = register_name(oreg,0);
938 if (op==DIV)
939 printf("\tcltd\n\tdivl %s\n",orn);
940 else
941 printf("\txor %%edx,%%edx\n\tidivl %s\n",orn);
942 dx = virtual(REG_EDX);
943 if (dx!=creg) {
944 rname[dx]=rname[creg];
945 rname[creg]=REG_EDX;
946 }
947 edx_cleanup();
948 break;
949 }
950 if (oreg!=dreg&&oreg>=0)
951 free_register(oreg);
952 }
953
954 static int edx_stack=0;
955
956 int
957 edx_setup()
958 {
959 int edx_save;
960 /* make real EDX register empty */
961 if (free_register_count()<1) {
962 for(edx_save = 0;edx_save==dreg||edx_save==creg;edx_save++);
963 printf("\tpushl %s\n",register_name(edx_save,0));
964 edx_stack = list3(edx_save,edx_stack,0);
965 } else {
966 edx_save = get_register();
967 edx_stack = list3(edx_save,edx_stack,1);
968 }
969 regv[edx_save]=0;
970 use_register(edx_save,REG_EDX,0);
971 return edx_save;
972 }
973
974
975 void
976 edx_cleanup()
977 {
978 if (caddr(edx_stack)==0) {
979 printf("\tpopl %s\n",register_name(car(edx_stack),0));
980 } else
981 free_register(car(edx_stack));
982 edx_stack = cadr(edx_stack);
983 }
984
985 void
986 shift(char *op, int reg)
987 {
988 if (reg>=0) {
989 use_register(reg,REG_ECX,1);
990 } else {
991 use_register(dreg,REG_ECX,0);
992 printf("\tpopl %%ecx\n");
993 }
994 printf("\t%s %%cl,%s\n",op,register_name(creg,0));
995 }
996
997 void
998 ld_indexx(int byte, int n, int xreg)
999 {
1000 char *op;
1001
1002 op = byte ? "movsbl" : "movl";
1003 if (n)
1004 printf("\t%s %d(%s),%s\n",op,n,register_name(xreg,0),register_name(creg,byte));
1005 else
1006 printf("\t%s (%s),%s\n",op,register_name(xreg,0),register_name(creg,byte));
1007 }
1008
1009 void
1010 cmpdimm(int e, int csreg)
1011 {
1012 /* used in dosiwtch() */
1013 use_register(creg,csreg,0);
1014 printf("\tcmpl $%d,%s\n",e,register_name(creg,0));
1015 }
1016
1017 void
1018 opening(char *filename)
1019 {
1020 printf("\t.file \"%s\"\n",filename);
1021 printf("\t.version\t\"01.01\"\n");
1022 printf("gcc2_compiled.:\n");
1023 printf(".text\n");
1024 emit_init();
1025 }
1026
1027 void
1028 closing(void)
1029 {
1030 global_table();
1031 printf("\t.ident \"Micro-C compiled\"\n");
1032 }
1033
1034 void
1035 rexpr(int e1, int l1, char *s)
1036 {
1037 g_expr(list3(SUB,cadr(e1),caddr(e1)));
1038 printf("\tj%s\t_%d\n",s,l1);
1039 }
1040
1041 void
1042 jcond(int l, char cond)
1043 {
1044 printf("\tj%s\t_%d\n",cond?"ne":"e",l);
1045 }
1046
1047 void
1048 jmp(int l)
1049 {
1050 control=0;
1051 printf("\tjmp\t_%d\n",l);
1052 /* align? */
1053 /*
1054 this is not allowed because of ? operator
1055 regv[creg]=regv[dreg]=0;
1056 use_register(creg,REG_EAX,0);
1057 use_register(dreg,REG_EBX,0);
1058 */
1059 }
1060
1061 void
1062 gen_comment(char *s)
1063 {
1064 printf("## %s",s);
1065 }
1066
1067
1068 void
1069 code_enter(char *name)
1070 {
1071 printf("\t.align 4\n");
1072 if (stmode!=STATIC)
1073 printf(".globl %s\n",name);
1074 printf("\t.type\t%s,@function\n",name);
1075 printf("%s:\n",name);
1076 }
1077
1078 void
1079 code_enter1(int args)
1080 {
1081 code_disp_label=fwdlabel();
1082 printf("\tlea _%d(%%ebp),%%esp\n",code_disp_label);
1083
1084 printf("## args %d disp %d code_arg_offset=%d code_disp_offset=%d\n",args,disp,code_arg_offset,code_disp_offset);
1085 }
1086
1087 void
1088 code_leave(char *name)
1089 {
1090 printf("\t.set _%d,%d\n",code_disp_label,disp+code_disp_offset);
1091 printf("_%d:\n",labelno);
1092 printf("\t.size\t%s,_%d-%s\n",name,labelno,name);
1093 local_table();
1094 labelno++;
1095 free_all_register();
1096 }
1097
1098 void
1099 enter(char *name)
1100 {
1101 printf("\t.align 2\n");
1102 if (stmode!=STATIC)
1103 printf(".globl %s\n",name);
1104 printf("%s:\n",name);
1105 printf("\t.type\t%s,@function\n",name);
1106 printf("\tpushl %%ebp\n");
1107 printf("\tmovl %%esp,%%ebp\n");
1108 printf("\tpushl %%ebx\n");
1109 printf("\tpushl %%esi\n");
1110 printf("\tpushl %%edi\n");
1111 }
1112
1113 void
1114 enter1()
1115 {
1116 func_disp_label=fwdlabel();
1117 printf("\tlea _%d(%%ebp),%%esp\n",func_disp_label);
1118 /* if(disp) printf("\tsubl $%d,%%esp\n",-disp); */
1119 }
1120
1121 void
1122 leave(int control, char *name)
1123 {
1124 if (control)
1125 use_register(creg,REG_EAX,1);
1126 if (retcont) {
1127 if (control)
1128 jmp(retlabel);
1129 fwddef(retcont);
1130 use_register(creg,REG_EAX,0);
1131 printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg,0));
1132 /* printf("\tleave\n"); */
1133 }
1134 fwddef(retlabel);
1135 /* use_register(creg,REG_EAX,0); too late */
1136 /* if(disp) printf("\taddl $%d,%%esp\n",-disp); */
1137 printf("\tlea %d(%%ebp),%%esp\n",disp_offset);
1138 printf("\tpopl %%edi\n");
1139 printf("\tpopl %%esi\n");
1140 printf("\tpopl %%ebx\n");
1141 printf("\tleave\n");
1142 printf("\tret\n");
1143 printf("\t.set _%d,%d\n",func_disp_label,disp+disp_offset);
1144 printf("_%d:\n",labelno);
1145 printf("\t.size\t%s,_%d-%s\n",name,labelno,name);
1146 local_table();
1147 labelno++;
1148 free_all_register();
1149 }
1150
1151
1152 void
1153 code_set_fixed_creg(int mode) {
1154 use_register(creg,REG_EAX,mode);
1155 }
1156
1157 void
1158 gen_gdecl(char *n, int gpc)
1159 {
1160 /*
1161 if (stmode!=STATIC)
1162 printf(".globl %s\n",n);
1163 */
1164 }
1165
1166 void
1167 align(int t)
1168 {
1169 if (t!=CHAR) {
1170 if (data_alignment & 1)
1171 printf("\t.align 2\n");
1172 data_alignment = 0;
1173 }
1174 }
1175
1176 void
1177 emit_data(int e, int t, NMTBL *n)
1178 {
1179 int l;
1180 char *name;
1181 name = n->nm;
1182 if(mode!=GDECL) {
1183 error(-1); return;
1184 }
1185 if (n->dsp != -1) {
1186 n->dsp = -1; /* initiallized flag */
1187 printf(".globl\t%s\n",name);
1188 data_mode(name);
1189 align(t);
1190 printf("%s:\n",name);
1191 } else {
1192 data_mode(0);
1193 }
1194 if(car(e)==CONST) {
1195 if (t==CHAR) {
1196 printf("\t.byte %d\n",cadr(e));
1197 if (data_alignment>0)
1198 data_alignment++;
1199 gpc += 1;
1200 } else {
1201 printf("\t.long %d\n",cadr(e));
1202 gpc += size_of_int;
1203 }
1204 } else if(t!=CHAR) {
1205 gpc += size_of_int;
1206 if(car(e)==ADDRESS&&car(cadr(e))==GVAR) {
1207 printf("\t.long %s\n",(char *)caddr(cadr(e)));
1208 } else if(car(e)==FNAME) {
1209 printf("\t.long %s\n",((NMTBL *)cadr(e))->nm);
1210 } else if(car(e)==STRING) {
1211 if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) {
1212 l = fwdlabel();
1213 printf("\t.long _%d\n",l);
1214 printf(".section\t.rodata\n");
1215 printf("_%d:\n",l);
1216 output_mode = RODATA_EMIT_MODE;
1217 }
1218 ascii((char *)cadr(e));
1219 } else error(TYERR);
1220 }
1221 }
1222
1223 void
1224 emit_data_closing(NMTBL *n)
1225 {
1226 int lb;
1227 if (mode==GDECL) {
1228 data_mode(0);
1229 lb=fwdlabel();
1230 printf("_%d:\n",lb);
1231 printf("\t.size\t%s,_%d-%s\n",n->nm,lb,n->nm);
1232 }
1233 }
1234
1235 void
1236 global_table(void)
1237 {
1238 NMTBL *n;
1239 int init;
1240 init=0;
1241 for(n=ntable;n < &ntable[GSYMS];n++) {
1242 if (n->sc == GVAR && n->dsp != -1) {
1243 /* n->dsp = -1 means initialized global */
1244 if (init==0) {
1245 data_mode(0);
1246 init=1;
1247 }
1248 printf(".comm %s,%d\n",n->nm,size(n->ty));
1249 }
1250 }
1251 }
1252
1253 void
1254 local_table(void)
1255 {
1256 NMTBL *n;
1257 int init;
1258 init=0;
1259 /* static local variables */
1260 for(n=ntable+GSYMS;n < &ntable[GSYMS+LSYMS];n++) {
1261 if (n->sc == GVAR) {
1262 if (init==0) {
1263 data_mode(0);
1264 init=1;
1265 }
1266 printf(".lcomm %s,%d\n",n->nm,size(n->ty));
1267 }
1268 }
1269 }
1270
1271 void
1272 text_mode(void)
1273 {
1274 if (output_mode!=TEXT_EMIT_MODE) {
1275 printf(".text\n");
1276 printf("\t.align 2\n");
1277 output_mode = TEXT_EMIT_MODE;
1278 }
1279 }
1280
1281 void
1282 data_mode(char *name)
1283 {
1284 if (output_mode!=DATA_EMIT_MODE) {
1285 printf(".data\n");
1286 output_mode = DATA_EMIT_MODE;
1287 }
1288 if (name)
1289 printf("\t.type\t%s,@object\n",name);
1290 }
1291
1292 int
1293 lvar(int l)
1294 {
1295 if (fnptr->sc==CODE) {
1296 return l+code_disp_offset;
1297 } else if (l<0) {
1298 return l+disp_offset;
1299 } else {
1300 return l+arg_offset;
1301 }
1302 }
1303
1304 /* end */