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