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