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