Mercurial > hg > CbC > old > device
annotate mc-nop-386.c @ 50:1ec39b34ed98
goto
author | kono |
---|---|
date | Sun, 16 Feb 2003 06:34:12 +0900 |
parents | 884c74e6a2f7 |
children | c2ef3a2fbe88 |
rev | line source |
---|---|
0 | 1 /* Micro-C Code Generatation Part for intel386 */ |
1 | 2 /* $Id$ */ |
0 | 3 |
4 #define EXTERN extern | |
5 #include "mc.h" | |
6 | |
18 | 7 extern int get_register_var(void); |
8 extern void bexpr(int e1, char cond, int l1); | |
9 extern void closing(void); | |
10 extern void cmpdimm(int e, int csreg); | |
11 extern void code_enter(char *name) ; | |
50 | 12 extern void code_enter1(int args); |
18 | 13 extern void code_init(void); |
50 | 14 extern void code_leave(char *name) ; |
15 extern void leave(int control,char *name) ; | |
18 | 16 extern void def_label(int cslabel, int dlabel) ; |
17 extern void emit_data(int e, int t, NMTBL *n); | |
18 extern void emit_init(void); | |
19 extern void enter(char *name) ; | |
50 | 20 extern void enter1() ; |
18 | 21 extern void g_expr(int e1); |
22 extern void gen_comment(char *s); | |
23 extern void gen_gdecl(char *n, int gpc) ; | |
24 extern void gen_source(char *s); | |
25 extern void gexpr(int e1); | |
26 extern void jcond(int l, char cond); | |
27 extern void jmp(int l); | |
28 extern void opening(char *filename); | |
29 extern void ret(void); | |
49 | 30 extern int assign_expr0(int e,int e1,int type,int type1); |
31 extern int integral(int t); | |
50 | 32 extern void tree_print_t(int e,int t); |
33 extern int rvalue_t(int e,int t); | |
0 | 34 |
42 | 35 static int edx_setup() ; |
18 | 36 static int lvar(int l); |
50 | 37 static int cvar(int l); |
18 | 38 static void jump(int e1, int env); |
39 static void data_mode(char *name); | |
40 static void text_mode(void); | |
41 static void assign(int e1); | |
42 static void assop(int e1); | |
43 static void b_expr(int e1, char cond, int l1); | |
44 static void emit_push(void); | |
45 static void free_register(int i); | |
46 static void function(int e1); | |
47 static void global_table(void) ; | |
48 /* static void indexy(char *op, char *gvar); */ | |
49 /* static void jmp_eq_label(int l); */ | |
50 /* static void jmp_label(int l); */ | |
51 static void ld_indexx(int byte, int n, int xreg); | |
52 static void local_table(void) ; | |
53 static void machinop(int e1); | |
54 static void rexpr(int e1, int l1, char *s); | |
55 static void rindirect(int e1); | |
56 static void sassign(int e1); | |
57 static void shift(char *op, int xreg) ; | |
58 /* static void st_indexx(int byte, int n, int xreg); */ | |
59 static void string(int e1); | |
43 | 60 static void tosop(int op,int reg); |
42 | 61 static void edx_cleanup(); |
26 | 62 static void use_register(int virt, int real, int move); |
47 | 63 static void emit_copy(int from,int to,int length,int offset,int value); |
18 | 64 |
65 extern int error(int n); | |
66 extern int fwdlabel(void); | |
67 extern void fwddef(int l); | |
68 extern int backdef(void); | |
69 extern int size(int t); | |
49 | 70 extern int list4(int e1, int e2, int e3,int e4); |
18 | 71 extern int list3(int e1, int e2, int e3); |
49 | 72 extern int list2(int e1, int e2); |
2 | 73 extern int scalar(int); |
74 extern int reverse0(int); | |
49 | 75 extern void remove0(int *list,int element); |
0 | 76 |
77 #define TEXT_EMIT_MODE 0 | |
78 #define DATA_EMIT_MODE 1 | |
79 #define RODATA_EMIT_MODE 2 | |
80 | |
18 | 81 static int output_mode = TEXT_EMIT_MODE; |
82 static int data_alignment = 0; | |
0 | 83 |
36 | 84 static int code_disp_label; |
85 static int func_disp_label; | |
86 | |
0 | 87 /* |
50 | 88 -16 local2 |
89 -12 local1 | |
90 -8 arg1 | |
91 -4 arg2 | |
92 0 arg3 | |
93 0 (%edi) | |
94 local1 <----14 local variable 0 (%esi) | |
95 %edi -12 <- disp_offset %ebp | |
96 %esi -8 | |
0 | 97 %ebx -4 |
98 %ebp = %esp 0 | |
99 %eip 4 <- arg_offset | |
100 arg1 8 | |
50 | 101 see enter/enter1/leave see code_enter |
0 | 102 */ |
103 int arg_offset = 8; | |
6 | 104 int code_arg_offset = -4; |
3 | 105 int disp_offset = -12; |
106 int func_disp_offset = -12; | |
107 int code_disp_offset = -4; | |
108 int size_of_int = 4; | |
0 | 109 int endian = 0; |
110 int MAX_REGISTER=6; /* intel386¤Î¥ì¥¸¥¹¥¿¤ò4¤Ä¤Þ¤Ç»È¤¦*/ | |
111 int REAL_MAX_REGISTER=8; /* intel386¤Î¥ì¥¸¥¹¥¿¤¬8¤Ä¤È¤¤¤¦¤³¤È*/ | |
112 int MAX_DATA_REG=4; | |
113 int MAX_POINTER=3; | |
114 int MAX_REGISTGER_VAR=2; | |
115 | |
116 static int creg; /* current register */ | |
117 static int dreg; /* temporary register */ | |
118 static int reg_sp; /* REGister Stack-Pointer */ | |
50 | 119 static int vdisp; |
0 | 120 |
121 | |
122 #define REG_EAX 0 | |
123 #define REG_EBX 1 | |
124 #define REG_ECX 2 | |
125 #define REG_EDX 3 | |
126 #define REG_ESI 4 | |
127 #define REG_EDI 5 | |
128 #define REG_EBP 6 | |
129 #define REG_ESP 7 | |
130 | |
131 | |
132 #define DATA_REG 0 | |
133 #define POINTER_REG 3 | |
134 static char *reg_name[8]; | |
135 static char *reg_name_l[4]; | |
13 | 136 static char *reg_name_w[4]; |
0 | 137 |
138 /* | |
139 creg currrent virtual register | |
140 dreg spare virtual register | |
141 | |
142 rname[creg] currrent real register | |
143 rname[dreg] spare real register | |
144 | |
145 regs[] virtual register usage | |
40 | 146 regv[] value in virtual register flag |
0 | 147 |
148 reg_name[rname[creg]] | |
149 */ | |
150 | |
151 #define MAX_MAX 10 | |
152 static int rname[MAX_MAX]; | |
153 static int regs[MAX_MAX]; /* »È¤ï¤ì¤Æ¤¤¤ë¥ì¥¸¥¹¥¿¤ò¼¨¤¹¥Õ¥é¥° */ | |
154 static int reg_stack[MAX_MAX]; /* ¼ÂºÝ¤Î¥ì¥¸¥¹¥¿¤ÎÎΰè */ | |
40 | 155 static int regv[MAX_MAX]; /* Ãͤ¬Æþ¤Ã¤Æ¤¤¤ë¤«¤É¤¦¤« */ |
0 | 156 |
157 void | |
158 code_init(void) | |
159 { | |
24 | 160 arg_offset = 8; |
161 func_disp_offset = -12; | |
162 disp_offset = -12; | |
163 size_of_int = 4; | |
164 endian = 0; | |
165 MAX_REGISTER=6; | |
166 MAX_DATA_REG=4; | |
167 MAX_POINTER=3; | |
0 | 168 MAX_REGISTER_VAR=2; |
169 | |
170 reg_name[REG_EAX] = "%eax"; | |
171 reg_name[REG_EBX] = "%ebx"; | |
172 reg_name[REG_ECX] = "%ecx"; | |
173 reg_name[REG_EDX] = "%edx"; | |
174 reg_name[REG_ESI] = "%esi"; | |
175 reg_name[REG_EDI] = "%edi"; | |
176 reg_name[REG_EBP] = "%ebp"; | |
177 reg_name[REG_ESP] = "%esp"; | |
178 reg_name_l[REG_EAX] = "%al"; | |
179 reg_name_l[REG_EBX] = "%bl"; | |
180 reg_name_l[REG_ECX] = "%cl"; | |
181 reg_name_l[REG_EDX] = "%dl"; | |
13 | 182 reg_name_w[REG_EAX] = "%ax"; |
183 reg_name_w[REG_EBX] = "%bx"; | |
184 reg_name_w[REG_ECX] = "%cx"; | |
185 reg_name_w[REG_EDX] = "%dx"; | |
0 | 186 |
187 } | |
188 | |
189 char * | |
18 | 190 register_name(int i,int byte) |
0 | 191 { |
38 | 192 if (i<0) { |
193 error(REG_ERR); | |
194 return "%eax"; | |
195 } | |
24 | 196 if (byte && rname[i] <= REG_EDX) { |
18 | 197 return reg_name_l[rname[i]]; |
198 } else { | |
24 | 199 return reg_name[rname[i]]; /* should be error */ |
18 | 200 } |
0 | 201 } |
202 | |
203 int | |
204 get_register(void) | |
205 { /* »È¤ï¤ì¤Æ¤¤¤Ê¤¤¥ì¥¸¥¹¥¿¤òÄ´¤Ù¤ë */ | |
206 int i; | |
207 for(i=0;i<MAX_REGISTER;i++) { | |
208 if (! regs[i]) { /* »È¤ï¤ì¤Æ¤¤¤Ê¤¤¤Ê¤é */ | |
209 regs[i]=1; /* ¤½¤Î¥ì¥¸¥¹¥¿¤ò»È¤¦¤³¤È¤òÀë¸À¤· */ | |
210 return i; /* ¤½¤Î¾ì½ê¤òɽ¤¹ÈÖ¹æ¤òÊÖ¤¹ */ | |
211 } | |
212 } | |
213 return -1; /* ¶õ¤¤¤Æ¤¤¤ë¾ì½ê¤¬¤Ê¤¤¤Ê¤é¡¢¤½¤ì¤òɽ¤¹ -1 ¤òÊÖ¤¹ */ | |
214 } | |
215 | |
216 void | |
217 free_register(int i) { /* ¤¤¤é¤Ê¤¯¤Ê¤Ã¤¿¥ì¥¸¥¹¥¿¤ò³«Êü */ | |
40 | 218 regv[i]=regs[i]=0; |
0 | 219 } |
220 | |
221 int | |
222 register_full(void) | |
223 { | |
224 int i; | |
225 for(i=0;i<MAX_REGISTER;i++) { | |
226 if (! regs[i]) { | |
227 return 0; | |
228 } | |
229 } | |
230 return 1; | |
231 } | |
232 | |
23 | 233 static |
234 int | |
235 free_register_count(void) | |
236 { | |
237 int i,count; | |
238 count = 0; | |
239 for(i=0;i<MAX_REGISTER;i++) { | |
42 | 240 if (! regs[i] && ! regv[i]) count++; |
23 | 241 } |
242 return count; | |
243 } | |
244 | |
42 | 245 static void |
246 free_all_register(void) | |
247 { | |
248 int i; | |
249 for(i=0;i<MAX_REGISTER;i++) { | |
250 regs[i]=regv[i]=0; | |
251 } | |
252 creg = get_register(); | |
253 dreg = get_register(); | |
254 return; | |
255 } | |
256 | |
40 | 257 void |
258 use_register_var(int i) { | |
259 regv[i]=1; | |
260 } | |
261 | |
262 static int creg_regvar = -1; | |
263 static int creg_regvar_back; | |
264 static int creg_back; | |
265 | |
266 void | |
267 creg_destroy() { | |
268 creg_back = creg; creg_regvar_back = creg_regvar; | |
269 if (creg_regvar>=0) | |
270 creg = creg_regvar; | |
271 creg_regvar=-1; | |
272 } | |
273 | |
274 void | |
275 creg_un_destroy() { | |
276 creg = creg_back; creg_regvar = creg_regvar_back; | |
277 } | |
278 | |
42 | 279 void |
280 register_usage(char *s) | |
281 { | |
282 int i; | |
283 printf("# %d: %s:",lineno,s); | |
284 printf(" creg=%s dreg=%s ",register_name(creg,0),register_name(dreg,0)); | |
285 for(i=0;i<MAX_REGISTER;i++) { | |
286 printf("%d",regs[i]); | |
287 } | |
288 printf(":"); | |
289 for(i=0;i<MAX_REGISTER;i++) { | |
290 printf("%d",regv[i]); | |
291 } | |
292 #if 0 | |
293 printf(" regs_stack",register_name(creg,0),register_name(dreg,0)); | |
294 for(i=reg_sp;i>=0;i--) { | |
295 if(reg_stack[i]>=0) | |
296 printf(" %s",register_name(reg_stack[i],0)); | |
297 } | |
298 #endif | |
299 printf("\n"); | |
300 } | |
23 | 301 |
0 | 302 void |
303 gexpr_init(void) | |
304 { | |
305 while(reg_sp > 0) { | |
306 free_register(reg_stack[--reg_sp]); | |
307 } | |
308 text_mode(); | |
26 | 309 use_register(creg,REG_EAX,0); |
42 | 310 regv[dreg]=0; |
40 | 311 creg_regvar = -1; |
42 | 312 register_usage("gexpr_init"); |
0 | 313 } |
314 | |
42 | 315 |
0 | 316 void |
317 emit_init(void) | |
318 { | |
319 int i; | |
40 | 320 for(i=0;i<REAL_MAX_REGISTER;i++) { regs[i]=0; regv[i]=0;rname[i]=i;} |
42 | 321 free_all_register(); |
0 | 322 reg_sp = 0; |
323 text_mode(); | |
324 } | |
325 | |
326 int | |
327 virtual(int real) | |
328 { | |
329 int real_v,i; | |
330 real_v = -1; | |
331 for(i=0;i<MAX_REGISTER;i++) { | |
332 if (rname[i]==real) { | |
333 real_v=i; | |
334 break; | |
335 } | |
336 } | |
23 | 337 /* if (real_v == -1) |
338 error(-1); */ | |
0 | 339 return real_v; |
340 } | |
341 | |
342 void | |
343 use_register(int virt, int real, int move) | |
344 { | |
345 int real_v; | |
346 char *move_op; | |
347 if (rname[virt]==real) | |
348 return; | |
349 real_v = virtual(real); | |
350 move_op = regs[real_v]?"\txchg %s,%s\n":"\tmovl %s,%s\n"; | |
41 | 351 if (move || (regv[real_v])) { |
0 | 352 printf(move_op,reg_name[rname[virt]],reg_name[real]); |
353 } | |
354 rname[real_v] = rname[virt]; | |
355 rname[virt] = real; | |
356 } | |
357 | |
358 void | |
359 use_pointer(int virt, int move) | |
360 { | |
361 int i; | |
362 if (rname[virt]>=POINTER_REG) | |
363 return; | |
364 for(i=POINTER_REG;i<MAX_REGISTER;i++) { | |
365 if (!regs[virtual(i)]) { | |
366 use_register(virt,i,move); | |
367 return; | |
368 } | |
369 } | |
370 /* we prefer EBX */ | |
371 use_register(virt,REG_EBX,move); | |
372 } | |
373 | |
374 void | |
375 use_data_reg(int virt, int move) | |
376 { | |
377 int i; | |
378 if (rname[virt]<MAX_DATA_REG) | |
379 return; | |
380 for(i=0;i<MAX_DATA_REG;i++) { | |
381 if (!regs[virtual(i)]) { | |
382 use_register(virt,i,move); | |
383 return; | |
384 } | |
385 } | |
386 /* we prefer EBX */ | |
387 use_register(virt,REG_EBX,move); | |
388 } | |
389 | |
390 int | |
391 pop_register(void) | |
392 { /* ¥ì¥¸¥¹¥¿¤«¤éÃͤò¼è¤ê½Ð¤¹ */ | |
42 | 393 return reg_stack[--reg_sp]; |
0 | 394 } |
395 | |
396 int | |
397 stack_used(void) { | |
398 return reg_stack[--reg_sp]<0; | |
399 } | |
400 | |
401 void | |
402 emit_push(void) | |
403 { | |
404 int new_reg; | |
405 new_reg = get_register(); | |
406 if(new_reg<0) { /* ¤â¤¦¥ì¥¸¥¹¥¿¤¬¤Ê¤¤ */ | |
407 reg_stack[reg_sp++] = -1; | |
18 | 408 printf("\tpushl %s\n",register_name(creg,0)); |
42 | 409 /* creg is used soon, don't regv[creg]=0 */ |
0 | 410 } else { |
411 reg_stack[reg_sp++] = creg; /* push ¤¹¤ë¤«¤ï¤ê¤Ë¥ì¥¸¥¹¥¿¤ò»È¤¦ */ | |
18 | 412 creg = new_reg; |
42 | 413 regv[creg]=1; |
0 | 414 } |
42 | 415 } |
416 | |
417 void | |
418 emit_push_x(int xreg) | |
419 { | |
420 int new_reg; | |
421 new_reg = get_register(); | |
422 if(new_reg<0) { /* ¤â¤¦¥ì¥¸¥¹¥¿¤¬¤Ê¤¤ */ | |
423 reg_stack[reg_sp++] = -1; | |
424 printf("\tpushl %s\n",register_name(xreg,0)); | |
425 /* creg is used soon, don't regv[xreg]=0 */ | |
426 } else { | |
427 reg_stack[reg_sp++] = xreg; /* push ¤¹¤ë¤«¤ï¤ê¤Ë¥ì¥¸¥¹¥¿¤ò»È¤¦ */ | |
428 xreg = new_reg; | |
429 regv[xreg]=1; | |
430 } | |
0 | 431 } |
432 | |
18 | 433 int |
0 | 434 emit_pop(int type) |
435 { | |
18 | 436 int xreg; |
42 | 437 if ((xreg=pop_register())==-1) { |
0 | 438 if (type==POINTER_REG) |
439 use_pointer(dreg,0); | |
440 else if (type==DATA_REG) | |
441 use_data_reg(dreg,0); | |
42 | 442 if (regv[dreg]) { |
443 printf("# emit_pop dreg conflict\n"); | |
444 } | |
18 | 445 printf("\tpopl %s\n",register_name(dreg,0)); |
0 | 446 xreg = dreg; |
42 | 447 regv[xreg]=1; |
448 } | |
449 return xreg; | |
450 } | |
451 | |
452 static void | |
453 emit_pop_free(int xreg) | |
454 { | |
455 if (xreg==dreg) { | |
456 regv[dreg]=0; | |
43 | 457 } else if (xreg!=-1) { |
42 | 458 free_register(xreg); |
0 | 459 } |
460 } | |
461 | |
462 int | |
463 get_register_var(void) | |
464 { | |
465 int i; | |
466 for(i=REG_ESI;i<REG_ESP;i++) { | |
467 if (! regs[i]) { /* »È¤ï¤ì¤Æ¤¤¤Ê¤¤¤Ê¤é */ | |
468 regs[i]=1; /* ¤½¤Î¥ì¥¸¥¹¥¿¤ò»È¤¦¤³¤È¤òÀë¸À¤· */ | |
41 | 469 regv[i]=0; |
0 | 470 return i; /* ¤½¤Î¾ì½ê¤òɽ¤¹ÈÖ¹æ¤òÊÖ¤¹ */ |
471 } | |
472 } | |
473 return -1; | |
474 } | |
475 | |
476 void | |
477 gexpr(int e1) | |
478 { | |
479 gexpr_init(); | |
24 | 480 #if 0 |
32 | 481 if(lineno==2862) { |
24 | 482 g_expr(e1); /*break here*/ |
483 return; | |
484 } | |
485 #endif | |
0 | 486 g_expr(e1); |
42 | 487 } |
488 | |
489 int | |
490 csvalue() | |
491 { | |
492 return rname[creg]; /* for siwtch value */ | |
0 | 493 } |
494 | |
495 void | |
496 g_expr(int e1) | |
497 { | |
22 | 498 int e2,e3/*,e4*/; |
0 | 499 char *xrn; |
500 NMTBL *n; | |
501 | |
502 if (chk) return; | |
503 e2 = cadr(e1); | |
504 switch (car(e1)){ | |
505 case GVAR: | |
506 /* use_pointer(creg,0); */ | |
18 | 507 printf("\tmovl $%s,%s\n",(char *)caddr(e1),register_name(creg,0)); |
42 | 508 regv[creg]=1; |
0 | 509 return; |
510 case RGVAR: | |
511 /* use_pointer(creg,0); */ | |
18 | 512 printf("\tmovl %s,%s\n",(char *)caddr(e1),register_name(creg,0)); |
42 | 513 regv[creg]=1; |
0 | 514 return; |
515 case CRGVAR: | |
27 | 516 printf("\tmovsbl %s,%s\n",(char *)caddr(e1),register_name(creg,0)); |
42 | 517 regv[creg]=1; |
0 | 518 return; |
519 case LVAR: | |
520 /* use_pointer(creg,0); */ | |
18 | 521 printf("\tlea %d(%%ebp),%s\n",lvar(e2),register_name(creg,0)); |
42 | 522 regv[creg]=1; |
0 | 523 return; |
524 case REGISTER: | |
525 /* this is of course redundant... */ | |
18 | 526 /* we can use rname for this? */ |
527 /* or why not creg=e2? */ | |
528 printf("\tmovl %s,%s\n",register_name(e2,0),register_name(creg,0)); | |
42 | 529 regv[creg]=1; |
0 | 530 return; |
531 case RLVAR: | |
18 | 532 printf("\tmovl %d(%%ebp),%s\n",lvar(e2),register_name(creg,0)); |
42 | 533 regv[creg]=1; |
0 | 534 return; |
535 case CRLVAR: | |
21 | 536 printf("\tmovsbl %d(%%ebp),%s\n",lvar(e2),register_name(creg,0)); |
42 | 537 regv[creg]=1; |
0 | 538 return; |
539 case FNAME: | |
18 | 540 printf("\tmovl $%s,%s\n",((NMTBL *)e2)->nm,register_name(creg,0)); |
42 | 541 regv[creg]=1; |
0 | 542 return; |
543 case CONST: /* ÂåÆþ¤¹¤ëÃͤ¬0¤Ç¤âÆÃÊ̤ʽèÍý¤Ï¤·¤Ê¤¤ */ | |
18 | 544 printf("\tmovl $%d,%s\n",e2,register_name(creg,0)); |
42 | 545 regv[creg]=1; |
0 | 546 return; |
547 case STRING: | |
548 string(e1); | |
42 | 549 regv[creg]=1; |
0 | 550 return; |
551 case FUNCTION: | |
552 function(e1); | |
42 | 553 regv[creg]=1; |
0 | 554 return; |
555 case CODE: | |
556 jump(e2,caddr(e1)); | |
557 return; | |
558 case INDIRECT: | |
559 g_expr(e2); | |
560 return; | |
561 case RINDIRECT: case CRINDIRECT: | |
562 rindirect(e1); | |
563 return; | |
564 case ADDRESS: | |
565 g_expr(e2); | |
566 return; | |
567 case MINUS: /* ¥ì¥¸¥¹¥¿¤ËÂФ·¡¢negl¤ò¼Â¹Ô¤¹¤ì¤Ð¼Â¸½²Äǽ */ | |
568 g_expr(e2); | |
569 /* use_data_reg(creg,1); */ | |
18 | 570 printf("\tnegl %s\n", register_name(creg,0)); |
0 | 571 return; |
572 case BNOT: /* ~ */ | |
573 g_expr(e2); | |
574 /* use_data_reg(creg,1); */ | |
18 | 575 printf("\tnotl %s\n", register_name(creg,0)); |
0 | 576 return; |
577 case LNOT: /* ! */ | |
578 g_expr(e2); | |
579 use_data_reg(creg,1); | |
18 | 580 xrn = register_name(creg,1); |
581 printf("\tcmpl $0,%s\n", register_name(creg,0)); | |
582 printf("\tsete %s\n", xrn); | |
583 printf("\tmovzbl %s,%s\n", xrn,register_name(creg,0)); | |
0 | 584 return; |
585 case PREINC: | |
586 if (car(e2)==REGISTER) { | |
18 | 587 printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0)); |
588 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); | |
0 | 589 return; |
590 } | |
591 g_expr(e2); | |
18 | 592 xrn = register_name(creg,0); |
593 printf("\taddl $%d,(%s)\n",caddr(e1),xrn); | |
594 printf("\tmovl (%s),%s\n",xrn,xrn); | |
0 | 595 return; |
596 case POSTINC: | |
597 if (car(e2)==REGISTER) { | |
18 | 598 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); |
599 printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0)); | |
0 | 600 return; |
601 } | |
602 g_expr(e2); | |
603 emit_push(); | |
41 | 604 xrn = register_name((e2=emit_pop(0)),0); |
18 | 605 printf("\tmovl (%s),%s\n",xrn,register_name(creg,0)); |
0 | 606 printf("\taddl $%d,(%s)\n",caddr(e1),xrn); |
42 | 607 emit_pop_free(e2); |
0 | 608 return; |
609 case CPOSTINC: | |
610 /* char *p; *p++ */ | |
611 if (car(e2)==REGISTER) { | |
18 | 612 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); |
613 printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0)); | |
0 | 614 return; |
615 } | |
616 g_expr(e2); | |
42 | 617 emit_push(); |
41 | 618 xrn = register_name((e2=emit_pop(0)),1); |
18 | 619 printf("\tmovsbl (%s),%s\n",xrn,register_name(creg,0)); |
0 | 620 printf("\tincl (%s)\n",xrn); |
42 | 621 emit_pop_free(e2); |
0 | 622 return; |
623 case CPREINC: | |
624 if (car(e2)==REGISTER) { | |
18 | 625 printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0)); |
626 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); | |
0 | 627 return; |
628 } | |
629 g_expr(e2); | |
18 | 630 printf("\tincl (%s)\n",register_name(creg,0)); |
21 | 631 printf("\tmovsbl (%s),%s\n",register_name(creg,0),register_name(creg,0)); |
0 | 632 return; |
633 case CPOSTDEC: | |
634 if (car(e2)==REGISTER) { | |
18 | 635 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); |
636 printf("\tdecl %s\n",register_name(cadr(e2),0)); | |
0 | 637 return; |
638 } | |
639 g_expr(e2); | |
21 | 640 printf("\tmovsbl (%s),%s\n",register_name(creg,0),register_name(creg,0)); |
18 | 641 printf("\tdecl (%s)\n",register_name(creg,0)); |
0 | 642 return; |
643 case CPREDEC: | |
644 if (car(e2)==REGISTER) { | |
18 | 645 printf("\tdecl %s\n",register_name(cadr(e2),0)); |
646 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); | |
0 | 647 return; |
648 } | |
649 g_expr(e2); | |
650 emit_push(); | |
18 | 651 e2 = emit_pop(0); |
652 printf("\tdecl (%s)\n",register_name(e2,0)); | |
21 | 653 printf("\tmovsbl (%s),%s\n",register_name(e2,0),register_name(creg,0)); |
42 | 654 emit_pop_free(e2); |
0 | 655 return; |
656 case MUL: case UMUL: | |
657 case DIV: case UDIV: | |
658 case MOD: case UMOD: | |
659 case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT: | |
660 case ADD: case SUB: case BAND: case EOR: case BOR: | |
661 machinop(e1); | |
662 return; | |
663 case COND: | |
664 e2=fwdlabel(); | |
665 b_expr(cadr(e1),0,e2); | |
22 | 666 use_register(creg,REG_EAX,0); |
0 | 667 g_expr(caddr(e1)); |
22 | 668 /* e4 = rname[creg]; this is a bad idea */ |
669 use_register(creg,REG_EAX,1); | |
0 | 670 jmp(e3=fwdlabel()); |
671 fwddef(e2); | |
22 | 672 use_register(creg,REG_EAX,0); |
0 | 673 g_expr(cadddr(e1)); |
22 | 674 /* use_register(creg,e4,1); */ |
675 use_register(creg,REG_EAX,1); | |
0 | 676 fwddef(e3); |
677 return; | |
37 | 678 case RSTRUCT: |
679 g_expr(e2); | |
680 return; | |
0 | 681 case SASS: |
682 sassign(e1); | |
683 return; | |
684 case ASS: case CASS: | |
685 assign(e1); | |
686 return; | |
687 case ASSOP: case CASSOP: | |
688 assop(e1); | |
689 return; | |
690 case COMMA: | |
691 g_expr(e2); | |
692 g_expr(caddr(e1)); | |
693 return; | |
694 case RETURN: | |
695 n = (NMTBL *)e2; | |
696 if (retcont==0) | |
697 retcont=fwdlabel(); | |
18 | 698 printf("\tleal _%d,%s\n",retcont,register_name(creg,0)); |
42 | 699 regv[creg]=1; |
0 | 700 return; |
701 case ENVIRONMENT: | |
18 | 702 printf("\tmovl %%ebp,%s\n",register_name(creg,0)); |
42 | 703 regv[creg]=1; |
0 | 704 return; |
705 default: | |
706 b_expr(e1,1,e2=fwdlabel()); /* including > < ... */ | |
18 | 707 xrn = register_name(creg,0); |
708 printf("\txorl %s,%s\n",xrn,xrn); | |
0 | 709 jmp(e3=fwdlabel()); |
710 fwddef(e2); | |
18 | 711 printf("\tmovl $1,%s\n",xrn); |
0 | 712 fwddef(e3); |
42 | 713 regv[creg]=1; |
0 | 714 } |
715 } | |
716 | |
717 void | |
718 bexpr(int e1, char cond, int l1) | |
719 { | |
720 gexpr_init(); | |
721 b_expr(e1,cond,l1); | |
722 } | |
723 | |
724 void | |
725 b_expr(int e1, char cond, int l1) | |
726 { | |
727 int e2,l2; | |
728 if (chk) return; | |
729 e2=cadr(e1); | |
730 switch(car(e1)) { | |
731 case LNOT: | |
732 b_expr(e2,!cond,l1); | |
733 return; | |
734 case GT: | |
735 rexpr(e1,l1,cond?"g":"le"); | |
736 return; | |
737 case UGT: | |
738 rexpr(e1,l1,cond?"a":"be"); | |
739 return; | |
740 case GE: | |
741 rexpr(e1,l1,cond?"ge":"l"); | |
742 return; | |
743 case UGE: | |
744 rexpr(e1,l1,cond?"ae":"b"); | |
745 return; | |
746 case LT: | |
747 rexpr(e1,l1,cond?"l":"ge"); | |
748 return; | |
749 case ULT: | |
750 rexpr(e1,l1,cond?"b":"ae"); | |
751 return; | |
752 case LE: | |
753 rexpr(e1,l1,cond?"le":"g"); | |
754 return; | |
755 case ULE: | |
756 rexpr(e1,l1,cond?"be":"a"); | |
757 return; | |
758 case EQ: | |
759 rexpr(e1,l1,cond?"e":"ne"); | |
760 return; | |
761 case NEQ: | |
762 rexpr(e1,l1,cond?"ne":"e"); | |
763 return; | |
764 case LAND: | |
765 b_expr(e2,0,cond?(l2=fwdlabel()):l1); | |
766 b_expr(caddr(e1),cond,l1); | |
767 if(cond) fwddef(l2); | |
768 return; | |
769 case LOR: | |
770 b_expr(e2,1,cond?l1:(l2=fwdlabel())); | |
771 b_expr(caddr(e1),cond,l1); | |
772 if(!cond) fwddef(l2); | |
773 return; | |
774 case CRGVAR: | |
18 | 775 printf("\tcmpb $0,%s\n",(char *)caddr(e1)); |
0 | 776 jcond(l1,cond); |
777 return; | |
778 case CRLVAR: | |
779 printf("\tcmpb $0,%d(%%ebp)\n",lvar(e2)); | |
780 jcond(l1,cond); | |
781 return; | |
782 case RGVAR: | |
18 | 783 printf("\tcmpl $0,%s\n",(char *)caddr(e1)); |
0 | 784 jcond(l1,cond); |
785 return; | |
786 case RLVAR: | |
787 printf("\tcmpl $0,%d(%%ebp)\n",lvar(e2)); | |
788 jcond(l1,cond); | |
789 return; | |
790 case REGISTER: | |
18 | 791 printf("\tcmpl $0,%s\n",register_name(e2,0)); |
0 | 792 jcond(l1,cond); |
793 return; | |
794 case CONST: | |
795 if((cond&&e2)||(!cond&&!e2)) jmp(l1); | |
796 return; | |
797 default: | |
798 g_expr(e1); | |
18 | 799 printf("\tcmpl $0,%s\n",register_name(creg,0)); |
0 | 800 jcond(l1,cond); |
801 return; | |
802 } | |
803 } | |
804 | |
805 void | |
806 ascii(char *s) | |
807 { | |
808 printf("\t.string \""); | |
809 while(*s) { | |
810 if (*s=='\n') | |
811 printf("%cn",92); | |
812 else if (*s<' ') | |
813 printf("%c%03o",92,*s); | |
814 else if (*s==34) | |
815 printf("%c%c",92,34); | |
816 else | |
817 printf("%c",*s); | |
818 s++; | |
819 } | |
820 printf("%c\n",34); | |
821 } | |
822 | |
823 void | |
824 string(int e1) | |
825 { | |
826 char *s; | |
827 int i,lb; | |
828 | |
829 if (0) { | |
830 s=(char *)cadr(e1); | |
831 lb=fwdlabel(); | |
832 printf("\tjmp _%d\n",lb); | |
833 i=backdef(); | |
834 ascii(s); | |
835 printf("\t.align 2\n"); | |
836 fwddef(lb); | |
18 | 837 printf("\tlea _%d,%s\n",i,register_name(creg,0)); |
0 | 838 } else { |
839 s=(char *)cadr(e1); | |
840 printf(".section\t.rodata\n"); | |
841 lb=fwdlabel(); | |
842 printf("_%d:\n",lb); | |
843 ascii(s); | |
844 if (output_mode==TEXT_EMIT_MODE) { | |
845 printf(".text\n"); | |
846 } else { | |
847 text_mode(); | |
848 } | |
18 | 849 printf("\tlea _%d,%s\n",lb,register_name(creg,0)); |
0 | 850 } |
851 } | |
852 | |
13 | 853 #define MAX_COPY_LEN 20 |
854 | |
855 void | |
47 | 856 emit_copy(int from,int to,int length,int offset,int value) |
13 | 857 { |
39 | 858 int fix = 0; |
859 if (length<=0) return; | |
13 | 860 switch (length) { |
861 case 0: break; | |
862 case 1: | |
38 | 863 printf("\tmovb %d(%s),%s\n",offset,register_name(from,0), reg_name_l[rname[dreg]] ); |
864 printf("\tmovb %s,%d(%s)\n",reg_name_l[rname[dreg]] ,offset,register_name(to,0)); | |
13 | 865 break; |
866 case 2: | |
38 | 867 printf("\tmovw %d(%s),%s\n",offset,register_name(from,0), reg_name_w[rname[dreg]] ); |
868 printf("\tmovw %s,%d(%s)\n",reg_name_w[rname[dreg]] ,offset,register_name(to,0)); | |
13 | 869 break; |
870 case 4: | |
38 | 871 printf("\tmovl %d(%s),%s\n",offset,register_name(from,0), register_name(dreg,0)); |
872 printf("\tmovl %s,%d(%s)\n",register_name(dreg,0), offset,register_name(to,0)); | |
13 | 873 break; |
874 default: | |
875 if (length <=MAX_COPY_LEN) { | |
14 | 876 for(;length>=4;length-=4,offset+=4) |
47 | 877 emit_copy(from,to,4,offset,0); |
14 | 878 for(;length>=2;length-=2,offset+=2) |
47 | 879 emit_copy(from,to,2,offset,0); |
13 | 880 if(length>0) |
47 | 881 emit_copy(from,to,length,offset,0); |
39 | 882 break; |
13 | 883 } |
39 | 884 use_register(from,REG_ESI,1); |
885 use_register(to, REG_EDI,1); | |
886 use_register(dreg,REG_ECX,0); | |
14 | 887 printf("\tmovl $%d,%%ecx\n",length/4); |
39 | 888 fix = (length/4)*4; |
13 | 889 printf("\tcld\n\trep\n\tmovsl\n"); |
14 | 890 if(length%4) { |
47 | 891 emit_copy(from,to,length,offset+length/4,0); |
14 | 892 } |
13 | 893 } |
47 | 894 if (value) { |
39 | 895 /* this code is necessary for the value of assignment or function call */ |
896 /* otherwise we don't need this */ | |
47 | 897 if (fix) printf("\tsubl $%d,%s\n",fix,register_name(to,0)); |
898 if(creg!=to) { | |
899 if (to==dreg) | |
900 printf("\tmovl %s,%s\n",register_name(to,0),register_name(creg,0)); | |
901 else { | |
902 free_register(creg); creg=to; | |
903 } | |
45 | 904 } |
39 | 905 } |
41 | 906 regv[from]=regv[to]=regv[dreg]=0; |
42 | 907 regv[creg]=1; |
13 | 908 } |
909 | |
910 int | |
911 struct_push(int e4,int t) | |
912 { | |
42 | 913 int length,xreg,save,lreg; |
13 | 914 g_expr(e4); |
14 | 915 length=size(t); |
916 if(length%size_of_int) { | |
917 length += size_of_int - (length%size_of_int); | |
13 | 918 } |
40 | 919 if (length==4) { |
920 printf("\tpushl (%s)\n",register_name(creg,0)); return 1; | |
921 } | |
922 if (length==8) { | |
923 printf("\tpushl 4(%s)\n",register_name(creg,0)); | |
924 printf("\tpushl (%s)\n",register_name(creg,0)); return 2; | |
925 } | |
38 | 926 /* I think, after g_expr, at least two registers are free */ |
14 | 927 printf("\tsubl $%d,%%esp\n",length); |
38 | 928 if (register_full()) { |
929 /* this is wrong assumption */ | |
930 save = 1; | |
46
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
931 for(lreg=0;lreg==creg||lreg==dreg;lreg++); |
38 | 932 printf("\tpushl %s\n",register_name(lreg,0)); |
46
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
933 xreg = lreg; regv[xreg]=0; |
38 | 934 } else { |
935 save=0; | |
936 xreg = get_register(); | |
13 | 937 } |
46
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
938 if (save) |
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
939 printf("\tlea %d(%%esp),%s\n",size_of_int,register_name(xreg,0)); |
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
940 else |
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
941 printf("\tmovl %%esp,%s\n",register_name(xreg,0)); |
41 | 942 regv[xreg]=1; |
47 | 943 emit_copy(creg,xreg,length,0,0); |
46
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
944 /* we have value in creg, it may be changed */ |
38 | 945 if (save) { |
46
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
946 if(creg==xreg) { |
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
947 creg = get_register(); /* creg is freed in emit_copy */ |
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
948 } |
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
949 printf("\tpopl %s\n",register_name(xreg,0)); |
b1c8ac8c308d
fix cascading struct retrun. Now it should be compatible with gcc
kono
parents:
45
diff
changeset
|
950 regv[xreg]=1; |
38 | 951 } else |
952 free_register(xreg); | |
14 | 953 return length/size_of_int; |
13 | 954 } |
955 | |
0 | 956 void |
957 function(int e1) | |
958 { | |
13 | 959 int e2,e3,e4,e5,nargs,t; |
0 | 960 NMTBL *n; |
23 | 961 int save,saved; |
962 if (free_register_count()<1) { | |
963 for(save = 0;save==dreg||save==creg;save++); | |
964 printf("\tpushl %s\n",register_name(save,0)); | |
965 saved = 1; | |
966 } else { | |
967 save = get_register(); | |
968 saved = 0; | |
969 } | |
41 | 970 regv[save]=0; |
0 | 971 e2 = cadr(e1); |
972 nargs = 0; | |
973 for (e3 = caddr(e1); e3; e3 = cadr(e3)) { | |
13 | 974 t=caddr(e3); |
0 | 975 n=(NMTBL *)(e5=(cadr(e4 = car(e3)))); |
976 switch(car(e4)) { | |
50 | 977 /* |
0 | 978 case FNAME: |
18 | 979 printf("\tlea %s,%s\n",n->nm,register_name(creg,0)); |
980 printf("\tpushl %s\n",register_name(creg,0)); | |
0 | 981 break; |
982 case ADDRESS: | |
983 g_expr(e5); | |
18 | 984 printf("\tpushl %s\n",register_name(creg,0)); |
0 | 985 break; |
50 | 986 */ |
13 | 987 default: |
988 if(scalar(t)) { | |
989 g_expr(e4); | |
18 | 990 printf("\tpushl %s\n",register_name(creg,0)); |
13 | 991 } else if (car(t)==STRUCT||car(t)==UNION) { |
992 nargs += struct_push(e4,t); | |
993 continue; | |
994 } else { | |
995 error(TYERR); | |
996 } | |
0 | 997 } |
998 ++nargs; | |
999 } | |
1000 if (car(e2) == FNAME) { | |
1001 n=(NMTBL *)cadr(e2); | |
23 | 1002 } else { |
44 | 1003 use_register(creg,REG_EAX,0); |
23 | 1004 g_expr(e2); |
1005 } | |
1006 | |
26 | 1007 /* we don't have to save creg nor dreg */ |
41 | 1008 regs[creg]=0; regs[dreg]=0; |
1009 regv[creg]= regv[dreg]= regv[save]= 0; | |
23 | 1010 use_register(creg,REG_EAX,0); |
1011 use_register(dreg,REG_EDX,0); /* will be destroyed */ | |
1012 use_register(save,REG_ECX,0); /* will be destroyed */ | |
41 | 1013 regs[creg]=1; regs[dreg]=1; |
23 | 1014 |
1015 if (car(e2) == FNAME) { | |
0 | 1016 printf("\tcall\t%s\n",n->nm); |
23 | 1017 } else { |
18 | 1018 printf("\tcall\t*%s\n",register_name(creg,0)); |
0 | 1019 } |
6 | 1020 if (nargs) printf("\taddl $%d,%%esp\n",size_of_int*nargs); |
23 | 1021 if (saved) { |
1022 printf("\tpopl %s\n",register_name(save,0)); | |
1023 } else { | |
1024 free_register(save); | |
1025 } | |
41 | 1026 regv[save]=0; |
1027 regv[creg]=1; | |
0 | 1028 } |
1029 | |
48 | 1030 /* goto arguments list */ |
49 | 1031 /* target list3(list2(tag,disp),cdr,ty) */ |
1032 /* source list3(expr,cdr,ty) expr=listn(tag,...) */ | |
1033 /* source (after) list3(list2(tag,disp),cdr,ty) */ | |
48 | 1034 |
1035 int | |
1036 overrap(int t,int source) | |
1037 { | |
1038 int s0,s1; | |
1039 int t0=cadr(car(t)); | |
1040 int t1=size(caddr(t)); | |
1041 for(;source;source=cadr(source)) { | |
1042 s0=cadr(caddr(source)); | |
1043 if(car(source)==REGISTER && car(car(t))==REGISTER) { | |
1044 if(s0==t0) return 1; | |
1045 } else if(car(source)==car(car(t))) { | |
1046 s1=s0+size(cadddr(source)); | |
1047 if((t0<=s0&&s0<=t1)||(t0<=s1&&s1<=t1)) return 1; | |
1048 } | |
1049 } | |
1050 return 0; | |
1051 } | |
1052 | |
1053 int | |
49 | 1054 parallel_assign(int *source,int *target,int *processing) |
48 | 1055 { |
49 | 1056 int t,s,e1,p,sz,ty; |
48 | 1057 while(*target) { |
1058 t=car(*target); | |
49 | 1059 s=car(*source); |
1060 sz=size(ty=caddr(*target)); | |
48 | 1061 for(p=*processing;p;p=cadr(p)) { |
1062 if(car(p)==t) { /*¥¿¡¼¥²¥Ã¥È¤¬½èÍý¥ê¥¹¥ÈÃæ¤Ë¤¢¤ë*/ | |
49 | 1063 remove0(target,t); remove0(source,s); remove0(processing,p); |
48 | 1064 /*¿·¤·¤¤¥ì¥¸¥¹¥¿(or ¥¹¥¿¥Ã¥¯)¤ò¼èÆÀ¤¹¤ë*/ |
49 | 1065 if (sz==size_of_int && (e1=get_register())!=-1) { |
48 | 1066 e1=list2(REGISTER,e1); |
49 | 1067 g_expr(assign_expr0(e1,s,ty,ty)); |
1068 return list2(assign_expr0(t,e1,ty,ty),e1); | |
48 | 1069 } else { |
50 | 1070 disp-=sz; |
1071 g_expr(assign_expr0((e1=list2(LVAR,cvar(disp))),s,ty,ty)); | |
49 | 1072 return list2(assign_expr0(t,e1,ty,ty),-1); |
48 | 1073 } |
1074 } | |
1075 } | |
1076 if(car(t)==car(s) && cadr(t)==cadr(s)) { | |
1077 /*½ñ¤¹þ¤ßÀ褬¼«Ê¬¼«¿È*/ | |
49 | 1078 remove0(target,t); remove0(source,s); |
1079 } else if (overrap(*target,*source)) { | |
48 | 1080 /*½ñ¤¹þ¤ßÀ褬¥½¡¼¥¹¤È½Å¤Ê¤Ã¤Æ¤¤¤ë*/ |
49 | 1081 *processing=list2(t,*processing); |
1082 remove0(target,t); remove0(source,s); | |
48 | 1083 /*¾¤Î¤òÀè¤Ë¤¹¤ë*/ |
49 | 1084 e1=parallel_assign(source,target,processing); |
48 | 1085 /* ¤³¤ì¤Ç¶õ¤¤¤¿¤Ï¤º*/ |
49 | 1086 g_expr(assign_expr0(t,car(s),ty,ty)); |
48 | 1087 /* ²£¤Ë¤è¤±¤¿¤â¤Î¤¬¤¢¤ì¤Ð¡¢¸å»ÏËö¤ò¤¹¤ë*/ |
49 | 1088 if(e1) { |
1089 if(car(e1)) | |
1090 g_expr(e1); | |
1091 if(cadr(e1)>0) { | |
1092 free_register(cadr(e1)); | |
1093 } | |
1094 } | |
48 | 1095 } else { |
49 | 1096 g_expr(assign_expr0(t,s,ty,ty)); |
1097 remove0(target,t); remove0(source,s); | |
48 | 1098 } |
1099 } | |
1100 return 0; | |
1101 } | |
1102 | |
49 | 1103 void |
1104 remove0(int *parent,int e) | |
48 | 1105 { |
1106 int list; | |
49 | 1107 while ((list=*parent)) { |
48 | 1108 if (car(list)==e) { |
1109 *parent= cadr(list); | |
1110 } else { | |
1111 parent=&cadr(list); | |
1112 } | |
1113 } | |
1114 } | |
1115 | |
49 | 1116 int |
1117 is_simple(int e1) | |
1118 { | |
1119 return ( | |
1120 e1==CONST || e1==FNAME || e1==LVAR || e1==REGISTER || | |
50 | 1121 e1==GVAR || RGVAR || RLVAR || CRLVAR || CRGVAR |
49 | 1122 ); |
1123 } | |
1124 | |
1125 int | |
1126 is_same(int e1,int e2) | |
1127 { | |
50 | 1128 if( (car(e1)==LVAR && (car(e2)==RLVAR||car(e2)==CRLVAR)) |
1129 || (car(e1)==GVAR && (car(e2)==RGVAR||car(e2)==CRGVAR))) | |
49 | 1130 return cadr(e1)==cadr(e2); |
1131 return 0; | |
1132 } | |
1133 | |
48 | 1134 void |
1135 jump(int e1, int env) | |
1136 { | |
50 | 1137 int e2,e3,e4,ce2,ce3,sz,arg_size,ty,max_regs,regs; |
48 | 1138 NMTBL *code0; |
1139 int target = 0; | |
1140 int source = 0; | |
1141 int processing = 0; | |
50 | 1142 int sdisp = disp; |
48 | 1143 |
1144 /* ¤Þ¤º¡¢¥µ¥¤¥º¤ò·×»»¤·¤Ê¤¬¤é¡¢·è¤Þ¤Ã¤¿·Á¤ËÍ¡£ */ | |
50 | 1145 arg_size = 0; regs = 0; max_regs = MAX_REGISTER_VAR-1; |
1146 for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { | |
49 | 1147 e2 = car(e3); sz = size(ty=caddr(e3)); |
48 | 1148 if (regs <= max_regs&&integral(ty)) { |
50 | 1149 target=list3(list2(REGISTER,virtual((regs++)+REG_ESI)),target,ty); |
48 | 1150 } else { |
50 | 1151 target=list3(list2(LVAR,cvar(arg_size)),target,ty); |
49 | 1152 arg_size += sz; |
48 | 1153 } |
49 | 1154 source = list3(e2,source,ty); |
48 | 1155 } |
1156 | |
1157 /* disp ¤òÈô¤ÓÀè»÷¹ç¤ï¤»¤Æ½¤Àµ */ | |
50 | 1158 if (fnptr->sc==CODE) { |
1159 if (-arg_size<disp) disp = -arg_size; | |
1160 } else { | |
1161 if (disp_offset-arg_size<disp) disp = disp_offset-arg_size; | |
1162 } | |
48 | 1163 |
1164 /* Ê£»¨¤Ê¼°¤òÁ°¤â¤Ã¤Æ·×»»¤·¤Æ¤ª¤¯ */ | |
1165 /* ɬÍפʤé¶É½êÊÑ¿ô¤òÍѤ¤¤ë¡£ */ | |
1166 /* ¶É½êÊÑ¿ô¤Ø¤Î¥ª¥Õ¥»¥Ã¥È¤ò³Ð¤¨¤Æ¤ª¤¯ */ | |
1167 /* ¤Ä¤¤¤Ç¤Ë¡¢Æ±¤¸¤â¤Î¤¬¤¢¤ì¤Ð¡¢½ü¤¯ */ | |
1168 | |
1169 for (e3 = source,e2 = target; e3; e3 = cadr(e3),e2 = cadr(e2)) { | |
50 | 1170 ce3=car(e3);ce2=car(e2); |
1171 if (!is_simple(car(ce3))) { | |
1172 disp-=size(ty=caddr(e3)); | |
1173 g_expr(assign_expr0((e4=list2(LVAR,cvar(disp))),ce3,ty,ty)); | |
49 | 1174 car(e3)=e4; |
50 | 1175 } else if (is_same(ce2,ce3)) { |
1176 remove0(&source,ce3);remove0(&target,ce2); | |
48 | 1177 } |
1178 } | |
1179 | |
1180 /* compute jump address */ | |
1181 e2 = cadr(e1); | |
1182 if (car(e2) == FNAME) { | |
1183 code0=(NMTBL *)cadr(e2); | |
1184 if (code0->sc!=CODE) { | |
1185 error(TYERR); return; | |
1186 } | |
1187 } else { /* indirect */ | |
1188 g_expr(e2); | |
1189 emit_push(); | |
1190 } | |
50 | 1191 if (env) { |
1192 g_expr(env); | |
1193 emit_push(); | |
1194 } | |
48 | 1195 |
1196 /* ÊÂÎóÂåÆþ¤ò¼Â¹Ô */ | |
1197 | |
49 | 1198 parallel_assign(&source,&target,&processing); |
48 | 1199 |
50 | 1200 if (env) { |
1201 /* change the frame pointer */ | |
1202 e3 = emit_pop(0); | |
1203 printf("\tmovl %s,%%ebp\n",register_name(e3,0)); | |
1204 emit_pop_free(e3); | |
1205 } else if (fnptr->sc==FUNCTION) { | |
1206 printf("\tlea %d(%%ebp),%%ebp\n",disp_offset); | |
1207 } | |
1208 | |
48 | 1209 /* shrink stack if necessary */ |
50 | 1210 /* |
1211 if (!env && -arg_size<disp) { | |
1212 printf("\tleal %d(%%ebp),%%esp\n",-arg_size); | |
1213 } Why we need this? | |
1214 */ | |
1215 | |
48 | 1216 if (car(e2) == FNAME) { |
1217 printf("\tjmp %s\n",code0->nm); | |
1218 } else { | |
1219 e2 = emit_pop(0); | |
1220 printf("\tjmp *%s\n",register_name(e2,0)); | |
1221 emit_pop_free(e2); | |
1222 } | |
50 | 1223 if (vdisp<disp) vdisp=disp; |
1224 disp=sdisp; | |
48 | 1225 } |
1226 | |
1227 #if 0 | |
2 | 1228 int |
3 | 1229 arg_size(int e3,int *nargs0) |
2 | 1230 { |
1231 int i,nargs,offset_list,e,t; | |
1232 | |
1233 offset_list = 0; | |
1234 /* we should use prototypes's type */ | |
1235 for (i = nargs = 0; e3;e3 =cadr(e3)) { | |
1236 e = car(e3); t = caddr(e3); | |
3 | 1237 if (i < MAX_REGISTER_VAR && scalar(t)) { |
5 | 1238 offset_list = list3(-(REG_ESI+i++),offset_list,e); |
2 | 1239 } else { |
1240 offset_list = | |
5 | 1241 list3(nargs,offset_list,e); |
3 | 1242 nargs += (car(e3)==CHAR?size_of_int:size(t)); |
2 | 1243 } |
1244 } | |
3 | 1245 *nargs0 = -nargs; |
2 | 1246 return offset_list; |
1247 } | |
1248 | |
18 | 1249 |
1250 void | |
0 | 1251 jump(int e1, int env) |
1252 { | |
18 | 1253 int i,args,e2,e3,e4,e5,nargs,regs; |
0 | 1254 NMTBL *n,*code0; |
42 | 1255 int new_disp,scode,disp1,xreg; |
0 | 1256 char *xrn; |
1257 | |
2 | 1258 /* We need three passes. Compute Stack size, Compute Arg, Copy it. */ |
0 | 1259 /* count number of args */ |
2 | 1260 args = caddr(e1); |
3 | 1261 args = reverse0(args); |
1262 nargs = arg_size(args,&new_disp); /* compute in normal order */ | |
5 | 1263 disp1 = (fnptr->sc==CODE)?0:-size_of_int; |
1264 if (new_disp+disp1 < disp) { /* have to extend stack */ | |
6 | 1265 if (fnptr->sc==CODE) |
1266 printf("\tleal %d(%%ebp),%%esp\n",new_disp-size_of_int); | |
1267 else | |
1268 printf("\tleal %d(%%ebp),%%esp\n",new_disp+disp_offset); | |
0 | 1269 } |
1270 /* compute jump address */ | |
1271 e2 = cadr(e1); | |
1272 if (car(e2) == FNAME) { | |
1273 code0=(NMTBL *)cadr(e2); | |
1274 if (code0->sc!=CODE) { | |
1275 error(STERR); return; | |
1276 } | |
1277 } else { /* indirect */ | |
1278 g_expr(e2); | |
1279 emit_push(); | |
1280 } | |
2 | 1281 /* compute arguments in reverse order */ |
21 | 1282 /* printf("## jump code_arg_offset=%d code_disp_offset=%d\n",code_arg_offset,code_disp_offset); */ |
2 | 1283 regs = 0; |
4 | 1284 i=MAX_REGISTER_VAR; |
2 | 1285 for (e3=nargs; e3;e3 =cadr(e3)) { |
1286 n=(NMTBL *)(e5=(cadr(e4 = caddr(e3)))); | |
0 | 1287 switch(car(e4)) { |
1288 case FNAME: | |
18 | 1289 printf("\tlea %s,%s\n",n->nm,register_name(creg,0)); |
0 | 1290 emit_push(); |
1291 break; | |
1292 case ADDRESS: | |
1293 g_expr(e5); | |
1294 emit_push(); | |
1295 break; | |
1296 case RLVAR: | |
1297 case CRLVAR: | |
4 | 1298 if (env==0 && fnptr->sc==CODE) { |
21 | 1299 /* printf("## e5=%d car(e3)=%d\n",e5,car(e3)); */ |
5 | 1300 if (e5>=0 && e5==car(e3)) { |
2 | 1301 /* The same positioned local variable. No need to copy */ |
1302 reg_stack[reg_sp++] = -2; | |
1303 } | |
4 | 1304 break; |
0 | 1305 } |
3 | 1306 g_expr(e4); |
1307 emit_push(); | |
1308 break; | |
0 | 1309 case REGISTER: |
21 | 1310 /* printf("## i=%d rname[e5]=%d\n",i,rname[e5]); */ |
4 | 1311 if (i>0 && rname[e5]==REG_ESI+ --i) { |
3 | 1312 /* The same register variable. No need to copy */ |
2 | 1313 reg_stack[reg_sp++] = e5; |
4 | 1314 break; |
0 | 1315 } |
1316 default: | |
1317 g_expr(e4); | |
1318 emit_push(); | |
1319 } | |
2 | 1320 regs++; |
0 | 1321 } |
1322 if (env) { | |
2 | 1323 /* change the frame pointer */ |
0 | 1324 g_expr(env); |
18 | 1325 printf("\tmovl %s,%%ebp\n",register_name(creg,0)); |
3 | 1326 } else if (fnptr->sc==FUNCTION) { |
1327 printf("\tlea %d(%%ebp),%%ebp\n",disp_offset); | |
1328 } | |
1329 /* force lvar offset mode to CODE */ | |
1330 scode = fnptr->sc; fnptr->sc = CODE; | |
21 | 1331 /* printf("## jump2 code_arg_offset=%d code_disp_offset=%d\n",code_arg_offset,code_disp_offset); */ |
0 | 1332 /* copy arguments to destination environment if necessary */ |
3 | 1333 nargs = reverse0(nargs); /* pop in normal order */ |
1334 i=0; | |
1335 for (e3=nargs; e3;e3 =cadr(e3)) { | |
5 | 1336 if ((e4=car(e3))<0) { |
2 | 1337 /* register case */ |
1338 if (reg_stack[--reg_sp]>=REG_ESI) { | |
1339 /* the same registger */ | |
1340 } else { | |
1341 if(reg_stack[reg_sp]<0) { | |
5 | 1342 printf("\tpopl %s\n",reg_name[rname[REG_ESI+i]]); /* e4? */ |
2 | 1343 } else { |
1344 printf("\tmovl %s,%s\n", | |
1345 reg_name[rname[reg_stack[reg_sp]]], | |
5 | 1346 reg_name[rname[REG_ESI+i]]); /* e4? */ |
2 | 1347 free_register(reg_stack[reg_sp]); |
1348 } | |
3 | 1349 i++; |
2 | 1350 } |
1351 } else { | |
1352 /* local variable case */ | |
0 | 1353 if (reg_stack[reg_sp-1]== -2) { |
1354 /* same positioned variable */ | |
1355 reg_sp--; | |
1356 } else { | |
42 | 1357 printf("\tmovl %s,%d(%%ebp)\n",register_name((xreg=emit_pop(0)),0), lvar(e4)); |
0 | 1358 } |
1359 } | |
1360 } | |
42 | 1361 free_register(xreg); |
0 | 1362 if (car(e2) != FNAME) { |
42 | 1363 xrn=register_name((xreg=emit_pop(0)),0); |
0 | 1364 } |
42 | 1365 free_register(xreg); |
6 | 1366 if (!env && new_disp+disp1>disp) { |
0 | 1367 /* shrink stack if necessary */ |
5 | 1368 printf("\tleal %d(%%ebp),%%esp\n",new_disp-size_of_int); |
0 | 1369 } |
1370 if (car(e2) == FNAME) { | |
1371 printf("\tjmp %s\n",code0->nm); | |
1372 } else { | |
1373 printf("\tjmp *%s\n",xrn); | |
1374 } | |
3 | 1375 fnptr->sc = scode; |
0 | 1376 } |
48 | 1377 #endif |
0 | 1378 |
1379 void | |
1380 machinop(int e1) | |
1381 { | |
1382 int e2,e3,op; | |
1383 | |
1384 e2 = cadr(e1); | |
1385 op = car(e1); | |
1386 e3 = caddr(e1); | |
1387 g_expr(e3); | |
1388 emit_push(); | |
1389 g_expr(e2); | |
43 | 1390 tosop(car(e1),(e2=pop_register())); |
1391 emit_pop_free(e2); | |
42 | 1392 regv[creg]=1; |
0 | 1393 return; |
1394 } | |
1395 | |
1396 | |
1397 void | |
1398 rindirect(int e1) /* *(p +5 ) */ | |
1399 | |
1400 { | |
1401 char *op; | |
1402 int e2,e3,byte; | |
1403 | |
1404 op = ((byte = (car(e1) == CRINDIRECT)) ? "movsbl" : "movl"); | |
1405 e3 = cadr(e2 = cadr(e1)); | |
1406 g_expr(e2); | |
21 | 1407 printf("\t%s (%s),%s\n",op,register_name(creg,0),register_name(creg,0)); |
0 | 1408 } |
1409 | |
1410 void | |
1411 sassign(int e1) | |
1412 { | |
38 | 1413 int e2,e3,e4,sz,xreg; |
0 | 1414 |
18 | 1415 /* structure assignment */ |
37 | 1416 e2 = cadr(e1); /* pointer variable to the struct */ |
1417 e3 = cadr(e2); /* offset of the variable (distination) */ | |
39 | 1418 e4 = caddr(e1); /* right value (source) */ |
37 | 1419 sz = cadddr(e1); /* size of struct or union */ |
0 | 1420 g_expr(e4); |
1421 emit_push(); | |
1422 g_expr(e2); | |
38 | 1423 xreg = emit_pop(0); |
47 | 1424 emit_copy(xreg,creg,sz,0,1); |
42 | 1425 emit_pop_free(xreg); |
0 | 1426 return; |
1427 } | |
1428 | |
1429 void | |
1430 assign(int e1) | |
1431 { | |
1432 char *op; | |
1433 int e2,e3,e4,byte; | |
1434 | |
1435 op = ((byte=(car(e1) == CASS))? "movb" : "movl"); | |
1436 /* e2=e4 */ | |
1437 e2 = cadr(e1); | |
1438 e3 = cadr(e2); | |
1439 e4 = caddr(e1); | |
1440 switch(car(e2)) { | |
1441 case GVAR: /* i=3 */ | |
1442 g_expr(e4); | |
1443 if (byte) use_data_reg(creg,1); | |
18 | 1444 printf("\t%s %s,%s\n",op,register_name(creg,byte),(char *)caddr(e2)); |
0 | 1445 return; |
1446 case LVAR: | |
1447 g_expr(e4); | |
1448 if (byte) use_data_reg(creg,1); | |
18 | 1449 printf("\t%s %s,%d(%%ebp)\n",op,register_name(creg,byte),lvar(cadr(e2))); |
0 | 1450 return; |
1451 case REGISTER: | |
1452 g_expr(e4); | |
1453 if (creg!=cadr(e2)) | |
23 | 1454 printf("\tmovl %s,%s\n",register_name(creg,0),register_name(cadr(e2),0)); |
0 | 1455 return; |
1456 } | |
23 | 1457 g_expr(e2); |
0 | 1458 emit_push(); |
23 | 1459 use_data_reg(creg,0); |
1460 g_expr(e4); | |
0 | 1461 if (byte) use_data_reg(creg,1); |
23 | 1462 e2 = emit_pop(0); |
1463 printf("\t%s %s,(%s)\n",op,register_name(creg,byte),register_name(e2,0)); | |
42 | 1464 emit_pop_free(e2); |
1465 regv[creg]=1; | |
0 | 1466 return; |
1467 } | |
1468 | |
1469 void | |
1470 assop(int e1) | |
1471 { | |
43 | 1472 int e2,e3,byte,op,reg; |
0 | 1473 char *xrn; |
42 | 1474 int xreg,edx; |
0 | 1475 |
1476 /* e2 op= e3 */ | |
1477 byte = (car(e1) == CASSOP); | |
1478 e2 = cadr(e1); | |
1479 if (car(e2)==INDIRECT) e2=cadr(e2); | |
1480 e3 = caddr(e1); | |
1481 op = cadddr(e1); | |
1482 | |
1483 g_expr(e3); | |
1484 if (car(e2)==REGISTER) { | |
43 | 1485 xreg = creg; |
1486 creg = reg = cadr(e2); | |
1487 tosop(op,xreg); | |
1488 creg = xreg; | |
1489 printf("\tmovl %s,%s\n",register_name(reg,0),register_name(creg,0)); | |
42 | 1490 regv[creg]=1; |
0 | 1491 return; |
1492 } | |
43 | 1493 emit_push(); |
0 | 1494 g_expr(e2); |
42 | 1495 edx = edx_setup(); |
18 | 1496 xrn = register_name(xreg = emit_pop(0),0); /* pop e3 value */ |
42 | 1497 regv[xreg]=regs[xreg]=1; |
1498 printf("\tmovl %s,%s # assop \n",register_name(creg,0),register_name(edx,0)); | |
1499 regv[edx]=1; | |
1500 ld_indexx(byte,0,edx); | |
43 | 1501 tosop(op,xreg); |
42 | 1502 printf("\t%s %s,(%s)\n",byte ? "movb" : "movl",register_name(creg,byte),register_name(edx,0)); |
1503 edx_cleanup(); | |
1504 emit_pop_free(xreg); | |
1505 regv[creg]=1; | |
0 | 1506 return; |
1507 } | |
1508 | |
1509 | |
1510 void | |
43 | 1511 tosop(int op,int oreg) |
0 | 1512 { |
43 | 1513 int dx; |
18 | 1514 char *orn,*crn; |
0 | 1515 |
1516 switch(op) { | |
1517 case LSHIFT: | |
1518 case ULSHIFT: | |
1519 shift("sall",oreg); | |
1520 return; | |
1521 case RSHIFT: | |
1522 shift("sarl",oreg); | |
1523 return; | |
1524 case URSHIFT: | |
1525 shift("shrl",oreg); | |
1526 return; | |
1527 } | |
1528 if(oreg==-1) { | |
18 | 1529 printf("\tpopl %s\n",register_name(dreg,0)); |
0 | 1530 oreg = dreg; |
42 | 1531 regv[dreg]=1; |
0 | 1532 } |
42 | 1533 regv[oreg]=1; regs[oreg]=1; |
18 | 1534 orn = register_name(oreg,0); |
1535 crn = register_name(creg,0); | |
0 | 1536 switch(op) { |
1537 case ADD: | |
1538 printf("\taddl %s,%s\n",orn,crn); | |
41 | 1539 break; |
0 | 1540 case SUB: |
1541 printf("\tsubl %s,%s\n",orn,crn); | |
41 | 1542 break; |
0 | 1543 case BAND: |
1544 printf("\tandl %s,%s\n",orn,crn); | |
41 | 1545 break; |
0 | 1546 case EOR: |
1547 printf("\txorl %s,%s\n",orn,crn); | |
41 | 1548 break; |
0 | 1549 case BOR: |
1550 printf("\torl %s,%s\n",orn,crn); | |
41 | 1551 break; |
0 | 1552 case MUL: |
1553 case UMUL: | |
1554 printf("\t%s %s,%s\n","imull",orn,crn); | |
41 | 1555 break; |
0 | 1556 case DIV: |
1557 case UDIV: | |
42 | 1558 use_register(creg,REG_EAX,1); |
1559 edx_setup(); | |
1560 orn = register_name(oreg,0); | |
0 | 1561 if (op==DIV) |
1562 printf("\tcltd\n\tdivl %s\n",orn); | |
1563 else | |
1564 printf("\txor %%edx,%%edx\n\tidivl %s\n",orn); | |
42 | 1565 edx_cleanup(); |
41 | 1566 break; |
0 | 1567 case MOD: |
1568 case UMOD: | |
42 | 1569 use_register(creg,REG_EAX,1); |
1570 edx_setup(); | |
1571 orn = register_name(oreg,0); | |
0 | 1572 if (op==DIV) |
1573 printf("\tcltd\n\tdivl %s\n",orn); | |
1574 else | |
1575 printf("\txor %%edx,%%edx\n\tidivl %s\n",orn); | |
42 | 1576 dx = virtual(REG_EDX); |
1577 if (dx!=creg) { | |
1578 rname[dx]=rname[creg]; | |
1579 rname[creg]=REG_EDX; | |
1580 } | |
1581 edx_cleanup(); | |
41 | 1582 break; |
0 | 1583 } |
42 | 1584 if (oreg!=dreg&&oreg>=0) |
1585 free_register(oreg); | |
0 | 1586 } |
1587 | |
42 | 1588 static int edx_stack=0; |
0 | 1589 |
42 | 1590 int |
1591 edx_setup() | |
0 | 1592 { |
42 | 1593 int edx_save; |
1594 /* make real EDX register empty */ | |
1595 if (free_register_count()<1) { | |
1596 for(edx_save = 0;edx_save==dreg||edx_save==creg;edx_save++); | |
1597 printf("\tpushl %s\n",register_name(edx_save,0)); | |
1598 edx_stack = list3(edx_save,edx_stack,0); | |
1599 } else { | |
1600 edx_save = get_register(); | |
1601 edx_stack = list3(edx_save,edx_stack,1); | |
0 | 1602 } |
42 | 1603 regv[edx_save]=0; |
1604 use_register(edx_save,REG_EDX,0); | |
1605 return edx_save; | |
0 | 1606 } |
1607 | |
18 | 1608 |
1609 void | |
42 | 1610 edx_cleanup() |
0 | 1611 { |
42 | 1612 if (caddr(edx_stack)==0) { |
1613 printf("\tpopl %s\n",register_name(car(edx_stack),0)); | |
1614 } else | |
1615 free_register(car(edx_stack)); | |
1616 edx_stack = cadr(edx_stack); | |
0 | 1617 } |
1618 | |
1619 void | |
1620 shift(char *op, int reg) | |
1621 { | |
1622 if (reg>=0) { | |
42 | 1623 use_register(reg,REG_ECX,1); |
0 | 1624 } else { |
1625 use_register(dreg,REG_ECX,0); | |
1626 printf("\tpopl %%ecx\n"); | |
1627 } | |
18 | 1628 printf("\t%s %%cl,%s\n",op,register_name(creg,0)); |
0 | 1629 } |
1630 | |
1631 void | |
18 | 1632 ld_indexx(int byte, int n, int xreg) |
0 | 1633 { |
1634 char *op; | |
1635 | |
1636 op = byte ? "movsbl" : "movl"; | |
1637 if (n) | |
18 | 1638 printf("\t%s %d(%s),%s\n",op,n,register_name(xreg,0),register_name(creg,byte)); |
0 | 1639 else |
18 | 1640 printf("\t%s (%s),%s\n",op,register_name(xreg,0),register_name(creg,byte)); |
0 | 1641 } |
1642 | |
18 | 1643 /* |
0 | 1644 void |
18 | 1645 st_indexx(int byte, int n, int xreg) |
0 | 1646 { |
1647 char *op; | |
1648 | |
1649 op = byte ? "movb" : "movl"; | |
1650 if (n) | |
18 | 1651 printf("\t%s %s,%d(%s)\n",op,register_name(creg,byte),n,register_name(xreg,0)); |
0 | 1652 else |
18 | 1653 printf("\t%s %s,(%s)\n",op,register_name(creg,byte),register_name(xreg,0)); |
0 | 1654 } |
1655 | |
1656 void | |
1657 indexy(char *op, char *gvar) | |
1658 { | |
18 | 1659 printf("\t%s %s,%s\n",op,register_name(creg,0),gvar); |
0 | 1660 } |
18 | 1661 */ |
0 | 1662 |
1663 void | |
1664 cmpdimm(int e, int csreg) | |
1665 { | |
1666 /* used in dosiwtch() */ | |
1667 use_register(creg,csreg,0); | |
18 | 1668 printf("\tcmpl $%d,%s\n",e,register_name(creg,0)); |
0 | 1669 } |
1670 | |
1671 void | |
1672 opening(char *filename) | |
1673 { | |
1674 printf("\t.file \"%s\"\n",filename); | |
1675 printf("\t.version\t\"01.01\"\n"); | |
1676 printf("gcc2_compiled.:\n"); | |
1677 printf(".text\n"); | |
1678 emit_init(); | |
1679 } | |
1680 | |
1681 void | |
1682 closing(void) | |
1683 { | |
1684 global_table(); | |
1685 printf("\t.ident \"Micro-C compiled\"\n"); | |
1686 } | |
1687 | |
1688 void | |
1689 rexpr(int e1, int l1, char *s) | |
1690 { | |
1691 g_expr(list3(SUB,cadr(e1),caddr(e1))); | |
1692 printf("\tj%s\t_%d\n",s,l1); | |
1693 } | |
1694 | |
1695 void | |
1696 jcond(int l, char cond) | |
1697 { | |
1698 printf("\tj%s\t_%d\n",cond?"ne":"e",l); | |
1699 } | |
1700 | |
1701 void | |
1702 jmp(int l) | |
1703 { | |
1704 control=0; | |
1705 printf("\tjmp\t_%d\n",l); | |
1706 /* align? */ | |
42 | 1707 /* |
1708 this is not allowed because of ? operator | |
1709 regv[creg]=regv[dreg]=0; | |
1710 use_register(creg,REG_EAX,0); | |
1711 use_register(dreg,REG_EBX,0); | |
1712 */ | |
0 | 1713 } |
1714 | |
1715 int | |
1716 fwdlabel(void) | |
1717 { | |
1718 return labelno++; | |
1719 } | |
1720 | |
1721 void | |
1722 fwddef(int l) | |
1723 { | |
1724 control=1; | |
1725 printf("_%d:\n",l); | |
1726 } | |
1727 | |
1728 int | |
1729 backdef(void) | |
1730 { | |
1731 control=1; | |
1732 printf("_%d:\n",labelno); | |
1733 return labelno++; | |
1734 } | |
1735 | |
1736 void | |
1737 def_label(int cslabel, int dlabel) | |
1738 { | |
1739 int fl; | |
1740 | |
1741 fl = 0; | |
1742 if (control) { | |
1743 jmp(fl=fwdlabel()); | |
1744 } | |
1745 fwddef(cslabel); | |
1746 if (dlabel) | |
1747 jmp(dlabel); | |
1748 if (fl) { | |
1749 fwddef(fl); | |
1750 } | |
1751 } | |
1752 | |
1753 void | |
1754 gen_comment(char *s) | |
1755 { | |
21 | 1756 printf("## %s",s); |
0 | 1757 } |
1758 | |
1759 void | |
1760 gen_source(char *s) | |
1761 { | |
1762 printf("%s",s); | |
1763 } | |
1764 | |
1765 void | |
1766 code_enter(char *name) | |
1767 { | |
1768 printf("\t.align 4\n"); | |
1769 if (stmode!=STATIC) | |
1770 printf(".globl %s\n",name); | |
1771 printf("\t.type\t%s,@function\n",name); | |
1772 printf("%s:\n",name); | |
42 | 1773 free_all_register(); |
0 | 1774 } |
1775 | |
1776 void | |
50 | 1777 code_enter1(int args) |
0 | 1778 { |
36 | 1779 code_disp_label=fwdlabel(); |
50 | 1780 vdisp = disp; |
1781 printf("\tlea _%d(%%ebp),%%esp\n",code_disp_label); | |
36 | 1782 /* |
6 | 1783 if(disp0) { |
50 | 1784 printf("\tsubl $%d,%%esp\n",disp0); |
0 | 1785 } |
36 | 1786 */ |
21 | 1787 printf("## args %d disp %d code_arg_offset=%d code_disp_offset=%d\n",args,disp,code_arg_offset,code_disp_offset); |
0 | 1788 } |
1789 | |
1790 void | |
50 | 1791 code_leave(char *name) |
0 | 1792 { |
50 | 1793 printf("\t.set _%d,%d\n",code_disp_label,cvar(vdisp)); |
0 | 1794 printf("_%d:\n",labelno); |
1795 printf("\t.size\t%s,_%d-%s\n",name,labelno,name); | |
12 | 1796 local_table(); |
0 | 1797 labelno++; |
1798 } | |
1799 | |
1800 void | |
1801 enter(char *name) | |
1802 { | |
50 | 1803 vdisp = disp; |
0 | 1804 printf("\t.align 2\n"); |
1805 if (stmode!=STATIC) | |
1806 printf(".globl %s\n",name); | |
1807 printf("%s:\n",name); | |
1808 printf("\t.type\t%s,@function\n",name); | |
1809 printf("\tpushl %%ebp\n"); | |
1810 printf("\tmovl %%esp,%%ebp\n"); | |
1811 printf("\tpushl %%ebx\n"); | |
24 | 1812 printf("\tpushl %%esi\n"); |
1813 printf("\tpushl %%edi\n"); | |
42 | 1814 free_all_register(); |
0 | 1815 } |
1816 | |
1817 void | |
50 | 1818 enter1() |
0 | 1819 { |
50 | 1820 vdisp = disp; |
36 | 1821 func_disp_label=fwdlabel(); |
50 | 1822 printf("\tlea _%d(%%ebp),%%esp\n",func_disp_label); |
36 | 1823 /* if(disp) printf("\tsubl $%d,%%esp\n",-disp); */ |
0 | 1824 } |
1825 | |
1826 void | |
50 | 1827 leave(int control, char *name) |
0 | 1828 { |
1829 if (control) | |
1830 use_register(creg,REG_EAX,1); | |
1831 if (retcont) { | |
1832 if (control) | |
1833 jmp(retlabel); | |
1834 fwddef(retcont); | |
1835 use_register(creg,REG_EAX,0); | |
18 | 1836 printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg,0)); |
0 | 1837 /* printf("\tleave\n"); */ |
1838 } | |
1839 fwddef(retlabel); | |
42 | 1840 /* use_register(creg,REG_EAX,0); too late */ |
50 | 1841 /* if(disp) printf("\taddl $%d,%%esp\n",-vdisp); */ |
0 | 1842 printf("\tlea %d(%%ebp),%%esp\n",disp_offset); |
24 | 1843 printf("\tpopl %%edi\n"); |
1844 printf("\tpopl %%esi\n"); | |
0 | 1845 printf("\tpopl %%ebx\n"); |
1846 printf("\tleave\n"); | |
1847 printf("\tret\n"); | |
50 | 1848 printf("\t.set _%d,%d\n",func_disp_label,lvar(vdisp)); |
0 | 1849 printf("_%d:\n",labelno); |
1850 printf("\t.size\t%s,_%d-%s\n",name,labelno,name); | |
12 | 1851 local_table(); |
0 | 1852 labelno++; |
1853 } | |
1854 | |
1855 | |
1856 void | |
1857 ret(void) | |
1858 { | |
1859 use_register(creg,REG_EAX,1); | |
1860 jmp(retlabel); | |
1861 } | |
1862 | |
1863 void | |
1864 gen_gdecl(char *n, int gpc) | |
1865 { | |
1866 /* | |
1867 if (stmode!=STATIC) | |
1868 printf(".globl %s\n",n); | |
1869 */ | |
1870 } | |
1871 | |
1872 void | |
1873 align(int t) | |
1874 { | |
1875 if (t!=CHAR) { | |
1876 if (data_alignment & 1) | |
1877 printf("\t.align 2\n"); | |
1878 data_alignment = 0; | |
1879 } | |
1880 } | |
1881 | |
1882 void | |
1883 emit_data(int e, int t, NMTBL *n) | |
1884 { | |
1885 int l; | |
1886 char *name; | |
1887 name = n->nm; | |
13 | 1888 if(mode!=GDECL) { |
1889 error(-1); return; | |
1890 } | |
1891 if (n->dsp != -1) { | |
1892 n->dsp = -1; /* initiallized flag */ | |
1893 printf(".globl\t%s\n",name); | |
1894 data_mode(name); | |
1895 align(t); | |
1896 printf("%s:\n",name); | |
1897 } else { | |
1898 data_mode(0); | |
1899 } | |
1900 if(car(e)==CONST) { | |
1901 if (t==CHAR) { | |
1902 printf("\t.byte %d\n",cadr(e)); | |
1903 if (data_alignment>0) | |
1904 data_alignment++; | |
1905 gpc += 1; | |
0 | 1906 } else { |
13 | 1907 printf("\t.long %d\n",cadr(e)); |
3 | 1908 gpc += size_of_int; |
13 | 1909 } |
1910 } else if(t!=CHAR) { | |
1911 gpc += size_of_int; | |
1912 if(car(e)==ADDRESS&&car(cadr(e))==GVAR) { | |
18 | 1913 printf("\t.long %s\n",(char *)caddr(cadr(e))); |
13 | 1914 } else if(car(e)==FNAME) { |
1915 printf("\t.long %s\n",((NMTBL *)cadr(e))->nm); | |
1916 } else if(car(e)==STRING) { | |
1917 if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) { | |
1918 l = fwdlabel(); | |
1919 printf("\t.long _%d\n",l); | |
1920 printf(".section\t.rodata\n"); | |
1921 printf("_%d:\n",l); | |
1922 output_mode = RODATA_EMIT_MODE; | |
1923 } | |
1924 ascii((char *)cadr(e)); | |
1925 } else error(TYERR); | |
0 | 1926 } |
1927 } | |
1928 | |
1929 void | |
1930 emit_data_closing(NMTBL *n) | |
1931 { | |
1932 int lb; | |
18 | 1933 if (mode==GDECL) { |
0 | 1934 data_mode(0); |
1935 lb=fwdlabel(); | |
1936 printf("_%d:\n",lb); | |
1937 printf("\t.size\t%s,_%d-%s\n",n->nm,lb,n->nm); | |
1938 } | |
1939 } | |
1940 | |
1941 void | |
1942 global_table(void) | |
1943 { | |
1944 NMTBL *n; | |
12 | 1945 int init; |
1946 init=0; | |
0 | 1947 for(n=ntable;n < &ntable[GSYMS];n++) { |
1948 if (n->sc == GVAR && n->dsp != -1) { | |
1949 /* n->dsp = -1 means initialized global */ | |
12 | 1950 if (init==0) { |
1951 data_mode(0); | |
1952 init=1; | |
1953 } | |
0 | 1954 printf(".comm %s,%d\n",n->nm,size(n->ty)); |
1955 } | |
1956 } | |
1957 } | |
1958 | |
1959 void | |
1960 local_table(void) | |
1961 { | |
1962 NMTBL *n; | |
12 | 1963 int init; |
1964 init=0; | |
0 | 1965 /* static local variables */ |
1966 for(n=ntable+GSYMS;n < &ntable[GSYMS+LSYMS];n++) { | |
1967 if (n->sc == GVAR) { | |
12 | 1968 if (init==0) { |
1969 data_mode(0); | |
1970 init=1; | |
1971 } | |
0 | 1972 printf(".lcomm %s,%d\n",n->nm,size(n->ty)); |
1973 } | |
1974 } | |
1975 } | |
1976 | |
1977 void | |
1978 text_mode(void) | |
1979 { | |
1980 if (output_mode!=TEXT_EMIT_MODE) { | |
1981 printf(".text\n"); | |
1982 printf("\t.align 2\n"); | |
1983 output_mode = TEXT_EMIT_MODE; | |
1984 } | |
1985 } | |
1986 | |
1987 void | |
1988 data_mode(char *name) | |
1989 { | |
1990 if (output_mode!=DATA_EMIT_MODE) { | |
1991 printf(".data\n"); | |
1992 output_mode = DATA_EMIT_MODE; | |
1993 } | |
1994 if (name) | |
1995 printf("\t.type\t%s,@object\n",name); | |
1996 } | |
1997 | |
1998 int | |
1999 lvar(int l) | |
2000 { | |
50 | 2001 if (fnptr->sc==CODE) { |
2002 return (l<0)? l+code_disp_offset: -l+code_arg_offset; | |
2003 } else if (l<0) { | |
2004 return l+disp_offset; | |
0 | 2005 } else { |
50 | 2006 return l+arg_offset; |
0 | 2007 } |
2008 } | |
2009 | |
50 | 2010 int |
2011 cvar(int l) | |
2012 { | |
2013 return (fnptr->sc==CODE)?l:l+disp_offset; | |
2014 } | |
2015 | |
0 | 2016 /* end */ |