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