Mercurial > hg > CbC > old > device
annotate mc-code-ia32.c @ 341:ca34f02b2056
ptr cache speed up
author | kono |
---|---|
date | Sat, 26 Jun 2004 11:09:11 +0900 (2004-06-26) |
parents | 0150de6a3244 |
children | 2b3946ee4fc9 |
rev | line source |
---|---|
326 | 1 /* Micro-C Code Generation Part for intel386 */ |
61 | 2 /* $Id$ */ |
3 | |
327 | 4 #include <stdio.h> |
61 | 5 #include "mc.h" |
327 | 6 #include "mc-parse.h" |
61 | 7 #include "mc-codegen.h" |
93 | 8 #include "mc-code.h" |
61 | 9 |
173 | 10 char *l_include_path[] = { |
11 "/usr/include/", | |
182 | 12 "/usr/include/linux/", |
225 | 13 "/usr/include/diet/", |
14 "/usr/lib/gcc-lib/i386-linux/2.95.4/include/", | |
183 | 15 "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/", |
246 | 16 "/usr/lib/dietlibc/include/", |
173 | 17 0 |
18 }; | |
19 | |
340 | 20 int data_alignment = 0; |
173 | 21 |
245 | 22 #define SIZE_OF_INT 4 |
23 #define SIZE_OF_SHORT 2 | |
24 #define SIZE_OF_FLOAT 4 | |
25 #define SIZE_OF_DOUBLE 8 | |
26 #define SIZE_OF_LONGLONG 8 | |
27 #define ENDIAN 0 | |
28 | |
94 | 29 #define SAVE_STACKS 1 |
30 | |
61 | 31 #define TEXT_EMIT_MODE 0 |
32 #define DATA_EMIT_MODE 1 | |
33 #define RODATA_EMIT_MODE 2 | |
34 | |
340 | 35 #define DOT_SIZE 1 |
36 | |
61 | 37 static int output_mode = TEXT_EMIT_MODE; |
38 | |
224 | 39 static int creg; |
239 | 40 static int lreg; |
224 | 41 |
238 | 42 int code_lassop_p = 0; |
43 | |
239 | 44 static int MAX_REGISTER=6; /* intel386�Υ쥸������6�ĤޤǻȤ�*/ |
119 | 45 #define REAL_MAX_REGISTER 8 /* intel386�Υ쥸������8�ĤȤ�������*/ |
239 | 46 static int MAX_DATA_REG=4; |
47 static int MAX_POINTER=3; | |
327 | 48 int MAX_REGISTER_VAR=2; |
239 | 49 // static int MAX_FREGISTER=1; |
119 | 50 |
51 #define MAX_FPU_STACK 7 | |
239 | 52 #define REG_VAR 3 |
119 | 53 |
239 | 54 // static int MAX_INPUT_REGISTER_VAR = 0; |
55 static int MAX_CODE_INPUT_REGISTER_VAR = 2; | |
56 // static int MAX_INPUT_DREGISTER_VAR = 0; | |
57 // static int MAX_INPUT_FREGISTER_VAR = 0; | |
58 // static int MAX_CODE_INPUT_DREGISTER_VAR = 0; | |
61 | 59 |
239 | 60 static int reg_sp; /* REGister Stack-Pointer */ |
61 static int reg_stack[MAX_MAX]; /* �ºݤΥ쥸�������ΰ� */ | |
328 | 62 static int stack_depth = 0; |
138 | 63 |
64 /* floating point registers */ | |
65 | |
239 | 66 static int freg_sp; /* floating point REGister Stack-Pointer */ |
67 static int freg_stack[MAX_MAX]; /* �ºݤΥ쥸�������ΰ� */ | |
68 | |
69 static int reg_var; | |
70 static int regvar[2]; | |
138 | 71 |
72 | |
61 | 73 /* |
128 | 74 -28 -8 local2 |
75 -24 -4 local1 | |
76 -20 8 arg3 | |
77 -16 4 arg2 | |
78 -12 0 arg1 | |
79 local2 -20 4 -8 (%edi) | |
80 local1 <-- -16 0 local variable -4 (%esi) | |
61 | 81 %edi -12 <- disp_offset %ebp |
82 %esi -8 | |
83 %ebx -4 | |
84 %ebp = %esp 0 | |
85 %eip 4 <- arg_offset | |
86 arg1 8 0 | |
87 arg2 12 4 | |
88 see enter/enter1/leave see code_enter | |
89 */ | |
327 | 90 static int arg_offset; |
328 | 91 int disp_offset = -12; |
244 | 92 #define func_disp_offset -12 |
93 #define code_disp_offset 0 | |
239 | 94 // static int jump_offset = 0; |
61 | 95 |
119 | 96 static int code_disp_label; |
97 static int func_disp_label; | |
61 | 98 |
263 | 99 |
119 | 100 static int |
101 lvar(int l) | |
102 { | |
103 if (is_code(fnptr)) { | |
104 return l+code_disp_offset; | |
105 } else if (l<0) { | |
106 return l+disp_offset; | |
107 } else { | |
108 return l+arg_offset; | |
109 } | |
110 } | |
99 | 111 |
95 | 112 /* |
326 | 113 creg current virtual register |
95 | 114 dreg spare virtual register |
115 | |
326 | 116 rname[creg] current real register |
95 | 117 rname[dreg] spare real register |
118 | |
119 regs[] virtual register usage | |
120 regv[] value in virtual register flag | |
121 | |
122 reg_name[rname[creg]] | |
123 | |
124 freg current floating point register | |
326 | 125 fregv value in floating point register |
95 | 126 */ |
127 | |
128 static int dreg; /* general temporal register */ | |
129 | |
239 | 130 #define REAL_MAX_LREGISTER 2 |
238 | 131 static int ia32regs[REAL_MAX_REGISTER+REAL_MAX_LREGISTER]; |
132 static int ia32regv[REAL_MAX_REGISTER+REAL_MAX_LREGISTER]; | |
133 static int ia32rname[REAL_MAX_REGISTER+REAL_MAX_LREGISTER]; | |
95 | 134 |
205 | 135 static int *regv = ia32regv; |
136 static int *regs = ia32regs; | |
95 | 137 static int *rname = ia32rname; |
138 | |
205 | 139 static int ia32fregs[1]; |
140 static int ia32fregv[1]; | |
95 | 141 |
205 | 142 static int freg; |
143 static int *fregv = ia32fregv; | |
144 static int *fregs = ia32fregs; | |
95 | 145 |
61 | 146 |
147 #define REG_EAX 0 | |
148 #define REG_EBX 1 | |
149 #define REG_ECX 2 | |
150 #define REG_EDX 3 | |
151 #define REG_ESI 4 | |
152 #define REG_EDI 5 | |
153 #define REG_EBP 6 | |
154 #define REG_ESP 7 | |
239 | 155 #define is_int_reg(reg) (reg<REG_EBP) |
156 #define REG_LCREG 8 | |
157 #define REG_L 9 | |
61 | 158 |
159 | |
160 #define DATA_REG 0 | |
161 #define POINTER_REG 3 | |
162 static char *reg_name[8]; | |
163 static char *reg_name_l[4]; | |
164 static char *reg_name_w[4]; | |
165 | |
93 | 166 static void use_register(int virt, int real, int move); |
167 static int virtual(int real); | |
235 | 168 static void shift(char *op, int reg,int creg); |
169 static void ld_indexx(int byte, int n, int xreg,int reg,int sign); | |
93 | 170 static void data_mode(char *name); |
263 | 171 static void text_mode(); |
237 | 172 static int edx_setup(int rreg); |
93 | 173 static void edx_cleanup(); |
174 static void local_table(void); | |
195 | 175 #if FLOAT_CODE |
93 | 176 static char * fload(int d); |
177 static int code_d1(double d); | |
178 static int code_d2(double d); | |
195 | 179 static void code_save_fstacks(); |
180 #endif | |
94 | 181 static void code_save_stacks(); |
287 | 182 static void jcond(int l, char cond); |
340 | 183 #if LONGLONG_CODE |
184 static int code_l1(long long d); | |
185 static int code_l2(long long d); | |
186 #endif | |
82 | 187 |
235 | 188 #define use_int(reg) if (reg==-1) reg=use_int0() |
242 | 189 static int use_int0() { lreg = 0; if (!is_int_reg(creg)) { creg = virtual(REG_EBX); regs[creg]=1;} return creg; } |
239 | 190 |
191 #define use_longlong(reg) reg=use_longlong0(reg) | |
192 static int | |
193 use_longlong0(int reg) | |
194 { | |
195 int i; | |
196 if (reg==USE_CREG) | |
197 reg = REG_LCREG; | |
198 if (!lreg) { | |
199 code_save_stacks(); | |
200 // make edx,eax free | |
240 | 201 use_register(creg,REG_EBX,regv[creg]); |
202 use_register(dreg,REG_ECX,regv[dreg]); | |
239 | 203 for(i=0;i<reg_var;i++) |
204 use_register(regvar[i],REG_ESI+i,1); | |
205 } | |
240 | 206 creg = lreg = reg; |
239 | 207 return lreg; |
208 } | |
209 | |
210 char * | |
211 l_edx(int i) { | |
212 return i==REG_L?"%edi":"%edx"; | |
213 } | |
214 char * | |
215 l_eax(int i) { | |
216 return i==REG_L?"%esi":"%eax"; | |
217 } | |
218 | |
327 | 219 static |
220 char *init_src0 = "\ | |
307 | 221 #define va_list int\n\ |
222 #define va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\ | |
223 #define va_arg(ap,type) (*((type *)ap)++)\n\ | |
224 #define va_end\n\ | |
225 #define __i386__ 1\n\ | |
226 #define __LITTLE_ENDIAN__ 1\n\ | |
227 #define __STDC__ 1\n\ | |
228 #define size_t int\n\ | |
229 #define __externsion__\n\ | |
315 | 230 #define __restrict\n\ |
231 #define __gnuc_va_list int\n\ | |
307 | 232 #define __flexarr\n\ |
315 | 233 #define __const const\n\ |
234 #define __THORW\n\ | |
235 #define __attribute__(a)\n\ | |
307 | 236 #define wchar_t int\n\ |
313 | 237 #define __GNUC__ 2\n\ |
307 | 238 "; |
235 | 239 |
327 | 240 extern void |
61 | 241 code_init(void) |
242 { | |
173 | 243 |
327 | 244 /* called only once */ |
245 | |
246 init_src = init_src0; | |
247 size_of_int = SIZE_OF_INT; | |
248 size_of_short = SIZE_OF_SHORT; | |
249 size_of_float = SIZE_OF_FLOAT; | |
250 size_of_double = SIZE_OF_DOUBLE; | |
251 size_of_longlong = SIZE_OF_LONGLONG; | |
252 endian = ENDIAN; | |
253 | |
61 | 254 arg_offset = 8; |
244 | 255 // func_disp_offset = -12; |
61 | 256 disp_offset = -12; |
257 MAX_REGISTER=6; | |
258 MAX_DATA_REG=4; | |
259 MAX_POINTER=3; | |
260 MAX_REGISTER_VAR=2; | |
261 | |
262 reg_name[REG_EAX] = "%eax"; | |
263 reg_name[REG_EBX] = "%ebx"; | |
264 reg_name[REG_ECX] = "%ecx"; | |
265 reg_name[REG_EDX] = "%edx"; | |
266 reg_name[REG_ESI] = "%esi"; | |
267 reg_name[REG_EDI] = "%edi"; | |
268 reg_name[REG_EBP] = "%ebp"; | |
269 reg_name[REG_ESP] = "%esp"; | |
270 reg_name_l[REG_EAX] = "%al"; | |
271 reg_name_l[REG_EBX] = "%bl"; | |
272 reg_name_l[REG_ECX] = "%cl"; | |
273 reg_name_l[REG_EDX] = "%dl"; | |
274 reg_name_w[REG_EAX] = "%ax"; | |
275 reg_name_w[REG_EBX] = "%bx"; | |
276 reg_name_w[REG_ECX] = "%cx"; | |
277 reg_name_w[REG_EDX] = "%dx"; | |
278 | |
279 } | |
280 | |
327 | 281 extern void |
282 emit_reinit() | |
283 { | |
284 /* called for each file */ | |
285 } | |
286 | |
287 | |
61 | 288 char * |
289 register_name(int i,int byte) | |
290 { | |
291 if (i<0) { | |
292 error(REG_ERR); | |
293 return "%eax"; | |
294 } | |
165 | 295 if (byte==1 && rname[i] <= REG_EDX) { |
61 | 296 return reg_name_l[rname[i]]; |
245 | 297 } else if (byte==SIZE_OF_SHORT && rname[i] <= REG_EDX) { |
165 | 298 return reg_name_w[rname[i]]; |
61 | 299 } else { |
168 | 300 return reg_name[rname[i]]; /* 0 or 4 means int */ |
61 | 301 } |
302 } | |
303 | |
235 | 304 /* |
147 | 305 int use_int(int i) { return i;} |
306 int use_float(int i) { return i;} | |
307 int use_double(int i) { return i;} | |
195 | 308 int use_longlong(int i) { return i; } |
235 | 309 */ |
195 | 310 |
147 | 311 |
61 | 312 void |
313 gexpr_code_init(void){ | |
314 use_register(creg,REG_EAX,0); | |
94 | 315 regv[creg]=0; |
61 | 316 regv[dreg]=0; |
317 } | |
318 | |
147 | 319 void |
320 code_gexpr(int e){ | |
321 } | |
322 | |
89 | 323 int |
324 get_register(void) | |
325 { /* �Ȥ��Ƥ��ʤ��쥸������Ĵ�٤� */ | |
326 int i; | |
327 for(i=0;i<MAX_REGISTER;i++) { | |
328 if (! regs[i]) { /* �Ȥ��Ƥ��ʤ��ʤ� */ | |
329 regs[i]=1; /* ���Υ쥸������Ȥ����Ȥ������ */ | |
330 return i; /* ���ξ���ɽ���ֹ���֤� */ | |
331 } | |
332 } | |
333 return -1; /* �����Ƥ����꤬�ʤ��ʤ顢�����ɽ�� -1 ���֤� */ | |
334 } | |
335 | |
336 void | |
337 free_register(int i) { /* ����ʤ��ʤä��쥸�������� */ | |
338 regv[i]=regs[i]=0; | |
238 | 339 if(i==REAL_MAX_REGISTER) { |
239 | 340 regv[virtual(REG_ESI)]=regv[virtual(REG_EDI)]=0; |
238 | 341 } |
89 | 342 } |
343 | |
341 | 344 extern void |
345 use_ptr_cache(int r) | |
346 { | |
347 error(-1); | |
348 } | |
349 | |
350 extern void | |
351 code_ptr_cache_def(int r,NMTBL *nptr) | |
352 { | |
353 error(-1); | |
354 } | |
355 | |
99 | 356 int |
126 | 357 get_input_register_var(int i,NMTBL *nptr,int is_code) |
99 | 358 { |
126 | 359 if (is_code) { |
360 if (i>=MAX_CODE_INPUT_REGISTER_VAR) return 0; | |
361 i = virtual(i+REG_ESI); | |
239 | 362 regs[i]=regv[i]=INPUT_REG; |
126 | 363 return list3(REGISTER,i,(int)nptr); |
364 } else { | |
365 return 0; | |
366 } | |
99 | 367 } |
103 | 368 |
99 | 369 int |
138 | 370 get_input_dregister_var(int i,NMTBL *nptr,int is_code,int d) |
99 | 371 { |
126 | 372 return 0; |
99 | 373 } |
374 | |
375 int | |
138 | 376 get_dregister(int d) |
99 | 377 { |
378 return -1; | |
379 } | |
380 | |
195 | 381 int |
382 get_lregister_var(NMTBL *n) | |
383 { | |
238 | 384 int h,l; |
385 h = virtual(REG_ESI); | |
386 l = virtual(REG_EDI); | |
387 if (regv[REAL_MAX_REGISTER]==0&®s[h]==0&®s[l]==0) { | |
239 | 388 regs[h]=regs[l]=REG_VAR; |
389 regv[h]=regv[l]=REG_VAR; | |
238 | 390 regv[REAL_MAX_REGISTER]=1; |
239 | 391 reg_var=2; regvar[0]=h; regvar[1]=l; |
240 | 392 return list2(LREGISTER,REG_L); |
238 | 393 } |
245 | 394 return list2(LVAR,new_lvar(SIZE_OF_LONGLONG)); |
195 | 395 } |
396 | |
205 | 397 int |
398 get_lregister() | |
399 { | |
400 return -1; | |
401 } | |
402 | |
403 | |
89 | 404 int |
405 register_full(void) | |
406 { | |
407 int i; | |
408 for(i=0;i<MAX_REGISTER;i++) { | |
409 if (! regs[i]) { | |
410 return 0; | |
411 } | |
412 } | |
413 return 1; | |
414 } | |
415 | |
416 int | |
137 | 417 free_register_count(int d) |
89 | 418 { |
419 int i,count; | |
420 count = 0; | |
421 for(i=0;i<MAX_REGISTER;i++) { | |
422 if (! regs[i] && ! regv[i]) count++; | |
423 } | |
137 | 424 return d?0:count; |
89 | 425 } |
426 | |
427 void | |
428 free_all_register(void) | |
429 { | |
430 int i; | |
243 | 431 for(i=0;i<MAX_REGISTER+REAL_MAX_LREGISTER;i++) { |
89 | 432 regs[i]=regv[i]=0; |
433 } | |
434 creg = get_register(); | |
435 dreg = get_register(); | |
239 | 436 reg_var = 0; |
89 | 437 return; |
438 } | |
439 | |
440 | |
441 void | |
442 register_usage(char *s) | |
443 { | |
444 int i; | |
445 if (chk) return; | |
446 printf("# %d: %s:",lineno,s); | |
447 printf(" creg=%s dreg=%s ",register_name(creg,0),register_name(dreg,0)); | |
448 for(i=0;i<MAX_REGISTER;i++) { | |
449 printf("%d",regs[i]); | |
450 } | |
451 printf(":"); | |
452 for(i=0;i<MAX_REGISTER;i++) { | |
453 printf("%d",regv[i]); | |
454 } | |
455 #if 0 | |
456 printf(" regs_stack",register_name(creg,0),register_name(dreg,0)); | |
457 for(i=reg_sp;i>=0;i--) { | |
458 if(reg_stack[i]>=0) | |
459 printf(" %s",register_name(reg_stack[i],0)); | |
460 } | |
461 #endif | |
94 | 462 printf(" f:%d",freg_sp); |
89 | 463 printf("\n"); |
464 } | |
465 | |
109 | 466 void |
137 | 467 code_arg_register(NMTBL *fnptr) |
109 | 468 { |
137 | 469 int args = fnptr->dsp; |
470 NMTBL *n; | |
471 int reg_var = 0; | |
472 int freg_var = 0; | |
473 int type; | |
474 int reg; | |
475 int is_code0 = is_code(fnptr); | |
476 | |
477 while (args) { | |
478 /* process in reverse order */ | |
479 n = (NMTBL*)caddr(args); | |
480 type = n->ty; | |
481 if (scalar(type)) { | |
482 if ((reg = get_input_register_var(reg_var,n,is_code0))) { | |
483 n->sc = REGISTER; | |
484 n->dsp = cadr(reg); | |
485 regv[n->dsp]= 1; | |
486 regs[n->dsp]= INPUT_REG; | |
487 reg_var++; | |
245 | 488 cadddr(args)=SIZE_OF_INT; /* why we need this? */ |
137 | 489 } |
490 } else if (type==FLOAT||type==DOUBLE) { | |
138 | 491 if ((reg = get_input_dregister_var(freg_var,n,is_code0,1))) { |
137 | 492 n->sc = DREGISTER; |
493 n->dsp = cadr(reg); | |
494 fregv[n->dsp]= 1; | |
495 fregs[n->dsp]= INPUT_REG; | |
496 freg_var++; | |
497 cadddr(args)=size(type); /* why we need this? */ | |
498 } | |
499 } | |
500 args = cadr(args); | |
501 } | |
109 | 502 } |
503 | |
89 | 504 void |
505 gexpr_init(void) | |
506 { | |
292 | 507 if (reg_sp>0) error(-1); |
508 if (freg_sp>0) error(-1); | |
509 reg_sp = 0; | |
94 | 510 freg_sp = 0; |
313 | 511 stack_depth = 0; |
89 | 512 text_mode(); |
513 gexpr_code_init(); | |
514 register_usage("gexpr_init"); | |
515 } | |
516 | |
517 | |
518 void | |
519 emit_init(void) | |
520 { | |
521 int i; | |
522 for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; regv[i]=0;rname[i]=i;} | |
523 free_all_register(); | |
524 reg_sp = 0; | |
94 | 525 freg_sp = 0; |
89 | 526 text_mode(); |
527 } | |
528 | |
529 int | |
530 virtual(int real) | |
531 { | |
532 int real_v,i; | |
533 real_v = -1; | |
534 for(i=0;i<MAX_REGISTER;i++) { | |
535 if (rname[i]==real) { | |
536 real_v=i; | |
537 break; | |
538 } | |
539 } | |
540 return real_v; | |
541 } | |
542 | |
543 int | |
544 pop_register(void) | |
545 { /* �쥸���������ͤ���Ф� */ | |
546 return reg_stack[--reg_sp]; | |
547 } | |
548 | |
549 void | |
550 emit_pop_free(int xreg) | |
551 { | |
159 | 552 if (xreg==dreg||xreg==creg) { |
89 | 553 regv[dreg]=0; |
98 | 554 } else if (xreg>=0) { |
89 | 555 free_register(xreg); |
556 } | |
557 } | |
558 | |
559 | |
61 | 560 int |
105 | 561 get_register_var(NMTBL *nptr) |
61 | 562 { |
563 int i; | |
235 | 564 for(i=REG_ESI;i<REG_EBP;i++) { |
61 | 565 if (! regs[i]) { /* �Ȥ��Ƥ��ʤ��ʤ� */ |
239 | 566 regs[i]=REG_VAR; /* ���Υ쥸������Ȥ����Ȥ������ */ |
61 | 567 regv[i]=0; |
239 | 568 regvar[reg_var++]=i; |
105 | 569 return list3(REGISTER,i,(int)nptr); /* ���ξ���ɽ���ֹ���֤� */ |
61 | 570 } |
571 } | |
245 | 572 return list2(LVAR,new_lvar(SIZE_OF_INT)); |
104 | 573 } |
574 | |
575 int | |
138 | 576 get_dregister_var(NMTBL *nptr,int d) |
104 | 577 { |
245 | 578 return list2(LVAR,new_lvar(d?SIZE_OF_DOUBLE:SIZE_OF_FLOAT)); |
137 | 579 } |
580 | |
61 | 581 void |
582 use_register(int virt, int real, int move) | |
583 { | |
584 int real_v; | |
585 char *move_op; | |
586 if (rname[virt]==real) | |
587 return; | |
588 real_v = virtual(real); | |
589 move_op = regs[real_v]?"\txchg %s,%s\n":"\tmovl %s,%s\n"; | |
590 if (move || (regv[real_v])) { | |
591 printf(move_op,reg_name[rname[virt]],reg_name[real]); | |
592 } | |
593 rname[real_v] = rname[virt]; | |
594 rname[virt] = real; | |
595 } | |
596 | |
597 void | |
598 use_pointer(int virt, int move) | |
599 { | |
600 int i; | |
601 if (rname[virt]>=POINTER_REG) | |
602 return; | |
603 for(i=POINTER_REG;i<MAX_REGISTER;i++) { | |
604 if (!regs[virtual(i)]) { | |
605 use_register(virt,i,move); | |
606 return; | |
607 } | |
608 } | |
609 /* we prefer EBX */ | |
610 use_register(virt,REG_EBX,move); | |
611 } | |
612 | |
613 void | |
614 use_data_reg(int virt, int move) | |
615 { | |
616 int i; | |
617 if (rname[virt]<MAX_DATA_REG) | |
618 return; | |
619 for(i=0;i<MAX_DATA_REG;i++) { | |
620 if (!regs[virtual(i)]) { | |
621 use_register(virt,i,move); | |
622 return; | |
623 } | |
624 } | |
625 /* we prefer EBX */ | |
626 use_register(virt,REG_EBX,move); | |
627 } | |
628 | |
629 | |
630 void | |
107 | 631 emit_push() |
61 | 632 { |
633 int new_reg; | |
634 new_reg = get_register(); | |
159 | 635 if (new_reg==creg) error(-1); |
61 | 636 if(new_reg<0) { /* �⤦�쥸�������ʤ� */ |
83 | 637 if (reg_sp>=MAX_MAX) error(-1); |
61 | 638 reg_stack[reg_sp++] = -1; |
639 printf("\tpushl %s\n",register_name(creg,0)); | |
313 | 640 stack_depth += SIZE_OF_INT; |
61 | 641 /* creg is used soon, don't regv[creg]=0 */ |
642 } else { | |
643 reg_stack[reg_sp++] = creg; /* push ���뤫���˥쥸������Ȥ� */ | |
644 creg = new_reg; | |
645 regv[creg]=1; | |
646 } | |
647 } | |
648 | |
649 int | |
650 emit_pop(int type) | |
651 { | |
652 int xreg; | |
653 if ((xreg=pop_register())==-1) { | |
654 if (type==POINTER_REG) | |
655 use_pointer(dreg,0); | |
656 else if (type==DATA_REG) | |
657 use_data_reg(dreg,0); | |
658 if (regv[dreg]) { | |
659 printf("# emit_pop dreg conflict\n"); | |
94 | 660 error(-1); |
61 | 661 } |
662 printf("\tpopl %s\n",register_name(dreg,0)); | |
94 | 663 regv[dreg]=1; |
313 | 664 stack_depth -= SIZE_OF_INT; |
94 | 665 return dreg; |
666 } else if (xreg<= -REG_LVAR_OFFSET) { | |
119 | 667 code_rlvar(xreg+REG_LVAR_OFFSET,dreg); |
117 | 668 free_lvar(xreg+REG_LVAR_OFFSET); |
94 | 669 regv[dreg]=1; |
670 return dreg; | |
671 } | |
61 | 672 return xreg; |
673 } | |
674 | |
186 | 675 int |
676 stack_top(int type) | |
677 { | |
678 int xreg; | |
679 if (type==INT) { | |
680 xreg = reg_stack[reg_sp]; | |
681 if (xreg<= -REG_LVAR_OFFSET) { | |
682 return list2(LVAR,REG_LVAR_OFFSET+xreg); | |
683 } else { | |
684 return list2(REGISTER,xreg); | |
685 } | |
686 } else { | |
687 xreg = freg_stack[freg_sp]; | |
688 if (xreg<= -REG_LVAR_OFFSET) { | |
689 return list2(LVAR,REG_LVAR_OFFSET+xreg); | |
187 | 690 } else { |
186 | 691 return list2(DREGISTER,xreg); |
692 } | |
693 } | |
694 return xreg; | |
695 } | |
696 | |
697 | |
698 | |
92 | 699 void |
700 code_label(int labelno) | |
701 { | |
702 printf("_%d:\n",labelno); | |
703 } | |
61 | 704 |
705 void | |
107 | 706 code_gvar(int e1,int creg) { |
235 | 707 use_int(creg); |
109 | 708 printf("\tmovl $%s,%s\n",((NMTBL*)cadr(e1))->nm,register_name(creg,0)); |
107 | 709 regv[creg]=1; |
61 | 710 } |
711 | |
712 | |
713 void | |
107 | 714 code_rgvar(int e1,int creg) { |
235 | 715 use_int(creg); |
109 | 716 printf("\tmovl %s,%s\n",((NMTBL*)cadr(e1))->nm,register_name(creg,0)); |
107 | 717 regv[creg]=1; |
61 | 718 } |
235 | 719 |
245 | 720 static char *cload(int sign,int sz) { return sz==1?(sign?"movsbl":"movzbl"):sz==SIZE_OF_SHORT?(sign?"movswl":"movzwl"):"movl"; } |
235 | 721 |
61 | 722 void |
165 | 723 code_crgvar(int e1,int creg,int sign,int sz){ |
235 | 724 use_int(creg); |
165 | 725 printf("\t%s %s,%s\n",cload(sign,sz), |
163 | 726 ((NMTBL*)cadr(e1))->nm,register_name(creg,0)); |
107 | 727 regv[creg]=1; |
61 | 728 } |
729 | |
730 | |
731 void | |
107 | 732 code_lvar(int e2,int creg) { |
235 | 733 use_int(creg); |
119 | 734 printf("\tlea %d(%%ebp),%s\n",lvar(e2),register_name(creg,0)); |
107 | 735 regv[creg]=1; |
61 | 736 } |
737 | |
738 | |
739 void | |
107 | 740 code_register(int e2,int creg) { |
235 | 741 use_int(creg); |
61 | 742 printf("\tmovl %s,%s\n",register_name(e2,0),register_name(creg,0)); |
107 | 743 regv[creg]=1; |
61 | 744 } |
745 | |
746 | |
747 void | |
94 | 748 code_rlvar(int e2,int reg) { |
235 | 749 use_int(reg); |
119 | 750 printf("\tmovl %d(%%ebp),%s\n",lvar(e2),register_name(reg,0)); |
107 | 751 regv[creg]=1; |
61 | 752 } |
753 | |
754 | |
755 void | |
165 | 756 code_crlvar(int e2,int reg,int sign,int sz) { |
235 | 757 use_int(reg); |
165 | 758 printf("\t%s %d(%%ebp),%s\n",cload(sign,sz),lvar(e2),register_name(reg,0)); |
107 | 759 regv[creg]=1; |
61 | 760 } |
761 | |
762 | |
763 void | |
109 | 764 code_fname(NMTBL *n,int creg) { |
235 | 765 use_int(creg); |
109 | 766 printf("\tmovl $%s,%s\n",n->nm,register_name(creg,0)); |
107 | 767 regv[creg]=1; |
61 | 768 } |
769 | |
770 | |
771 void | |
107 | 772 code_const(int e2,int creg) { |
235 | 773 use_int(creg); |
61 | 774 printf("\tmovl $%d,%s\n",e2,register_name(creg,0)); |
107 | 775 regv[creg]=1; |
61 | 776 } |
777 | |
778 | |
779 void | |
107 | 780 code_neg(int creg) { |
235 | 781 use_int(creg); |
61 | 782 printf("\tnegl %s\n", register_name(creg,0)); |
783 } | |
784 | |
785 | |
786 void | |
107 | 787 code_not(int creg) { |
235 | 788 use_int(creg); |
61 | 789 printf("\tnotl %s\n", register_name(creg,0)); |
790 } | |
791 | |
792 | |
793 void | |
107 | 794 code_lnot(int creg) { |
61 | 795 char *xrn; |
235 | 796 use_int(creg); |
61 | 797 use_data_reg(creg,1); |
798 xrn = register_name(creg,1); | |
799 printf("\tcmpl $0,%s\n", register_name(creg,0)); | |
800 printf("\tsete %s\n", xrn); | |
801 printf("\tmovzbl %s,%s\n", xrn,register_name(creg,0)); | |
802 } | |
803 | |
804 void | |
168 | 805 code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) { |
61 | 806 char *xrn; |
807 if (car(e2)==REGISTER) { | |
235 | 808 use_int(reg); |
168 | 809 printf("\taddl $%d,%s\n",dir,register_name(cadr(e2),0)); |
107 | 810 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(reg,0)); |
811 regv[reg]=1; | |
61 | 812 return; |
813 } | |
814 g_expr(e2); | |
815 xrn = register_name(creg,0); | |
235 | 816 use_int(reg); |
245 | 817 printf("\t%s $%d,(%s)\n",(sz==1)?"addb":(sz==SIZE_OF_SHORT)?"addw":"addl",dir,xrn); |
235 | 818 printf("\t%s (%s),%s\n",cload(sign,sz),xrn,register_name(reg,0)); |
61 | 819 } |
820 | |
821 | |
822 void | |
168 | 823 code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) { |
61 | 824 char *xrn; |
825 if (car(e2)==REGISTER) { | |
235 | 826 use_int(reg); |
107 | 827 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(reg,0)); |
168 | 828 printf("\taddl $%d,%s\n",dir,register_name(cadr(e2),0)); |
107 | 829 regv[reg]=1; |
61 | 830 return; |
831 } | |
832 g_expr(e2); | |
833 emit_push(); | |
834 xrn = register_name((e2=emit_pop(0)),0); | |
235 | 835 use_int(reg); |
836 printf("\t%s (%s),%s\n",cload(sign,sz),xrn,register_name(reg,0)); | |
245 | 837 printf("\t%s $%d,(%s)\n",(sz==1)?"addb":(sz==SIZE_OF_SHORT)?"addw":"addl",dir,xrn); |
61 | 838 emit_pop_free(e2); |
839 } | |
840 | |
841 | |
842 | |
843 void | |
107 | 844 code_return(int creg) { |
235 | 845 use_int(creg); |
61 | 846 printf("\tleal _%d,%s\n",retcont,register_name(creg,0)); |
107 | 847 regv[creg]=1; |
61 | 848 } |
849 | |
850 | |
851 void | |
107 | 852 code_environment(int creg) { |
235 | 853 use_int(creg); |
61 | 854 printf("\tmovl %%ebp,%s\n",register_name(creg,0)); |
107 | 855 regv[creg]=1; |
61 | 856 } |
857 | |
291 | 858 static int rexpr_bool(int e1,int reg); |
859 static int drexpr_bool(int e1,int reg); | |
61 | 860 |
861 void | |
225 | 862 code_bool(int e1,int reg) { |
61 | 863 char *xrn; |
864 int e2,e3; | |
291 | 865 if (rexpr_bool(e1,reg)) return; |
866 #if FLOAT_CODE | |
867 if (drexpr_bool(e1,reg)) return; | |
868 #endif | |
61 | 869 b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ |
289 | 870 if (use) { |
871 use_int(reg); | |
872 xrn = register_name(reg,0); | |
873 printf("\txorl %s,%s\n",xrn,xrn); | |
874 jmp(e3=fwdlabel()); | |
875 fwddef(e2); | |
876 printf("\tmovl $1,%s\n",xrn); | |
877 fwddef(e3); | |
878 regv[reg]=1; | |
879 } else { | |
880 fwddef(e2); | |
881 } | |
61 | 882 } |
883 | |
884 char * | |
885 code_gt(int cond) { | |
886 return (cond?"g":"le"); | |
887 } | |
888 | |
889 char * | |
890 code_ugt(int cond) { | |
891 return (cond?"a":"be"); | |
892 } | |
893 | |
894 char * | |
895 code_ge(int cond) { | |
896 return (cond?"ge":"l"); | |
897 } | |
898 | |
899 char * | |
900 code_uge(int cond) { | |
901 return (cond?"ae":"b"); | |
902 } | |
903 | |
904 char * | |
905 code_eq(int cond) { | |
906 return (cond?"e":"ne"); | |
907 } | |
908 | |
909 void | |
287 | 910 code_cmp_crgvar(int e1,int reg,int sz,int label,int cond) { |
235 | 911 use_int(reg); |
167 | 912 if (sz==1) |
913 printf("\tcmpb $0,%s\n",((NMTBL*)cadr(e1))->nm); | |
245 | 914 else if (sz==SIZE_OF_SHORT) |
167 | 915 printf("\tcmpw $0,%s\n",((NMTBL*)cadr(e1))->nm); |
287 | 916 jcond(label,cond); |
61 | 917 } |
918 | |
919 | |
920 void | |
287 | 921 code_cmp_crlvar(int e1,int reg,int sz,int label,int cond) { |
235 | 922 use_int(reg); |
167 | 923 if (sz==1) |
924 printf("\tcmpb $0,%d(%%ebp)\n",lvar(e1)); | |
245 | 925 else if (sz==SIZE_OF_SHORT) |
167 | 926 printf("\tcmpw $0,%d(%%ebp)\n",lvar(e1)); |
287 | 927 jcond(label,cond); |
61 | 928 } |
929 | |
930 | |
931 void | |
287 | 932 code_cmp_rgvar(int e1,int reg,int label,int cond) { |
235 | 933 use_int(reg); |
109 | 934 printf("\tcmpl $0,%s\n",((NMTBL*)cadr(e1))->nm); |
287 | 935 jcond(label,cond); |
61 | 936 } |
937 | |
938 | |
939 void | |
287 | 940 code_cmp_rlvar(int e1,int reg,int label,int cond) { |
235 | 941 use_int(reg); |
119 | 942 printf("\tcmpl $0,%d(%%ebp)\n",lvar(e1)); |
287 | 943 jcond(label,cond); |
61 | 944 } |
945 | |
946 | |
947 void | |
287 | 948 code_cmp_register(int e2,int label,int cond) { |
235 | 949 use_int(e2); |
61 | 950 printf("\tcmpl $0,%s\n",register_name(e2,0)); |
287 | 951 jcond(label,cond); |
61 | 952 } |
953 | |
954 | |
955 void | |
107 | 956 code_string(int e1,int creg) |
61 | 957 { |
958 char *s; | |
320 | 959 int lb; |
61 | 960 |
235 | 961 use_int(creg); |
320 | 962 s=(char *)cadr(e1); |
963 lb = emit_string_label(); | |
964 ascii(s); | |
965 if (output_mode==TEXT_EMIT_MODE) { | |
966 printf(".text\n"); | |
61 | 967 } else { |
320 | 968 text_mode(); |
61 | 969 } |
320 | 970 printf("\tlea _%d,%s\n",lb,register_name(creg,0)); |
61 | 971 } |
972 | |
973 #define MAX_COPY_LEN 20 | |
974 | |
975 void | |
976 emit_copy(int from,int to,int length,int offset,int value,int det) | |
977 { | |
978 int fix = 0; | |
979 /* length <0 means upward direction copy */ | |
235 | 980 use_int(from); |
981 use_int(to); | |
61 | 982 switch (length) { |
983 case 0: break; | |
984 case 1: case -1: | |
985 printf("\tmovb %d(%s),%s\n",offset, | |
986 register_name(from,0), reg_name_l[rname[dreg]] ); | |
987 printf("\tmovb %s,%d(%s)\n",reg_name_l[rname[dreg]] ,offset, | |
988 register_name(to,0)); | |
989 break; | |
990 case 2: case -2: | |
991 printf("\tmovw %d(%s),%s\n",offset, | |
992 register_name(from,0), reg_name_w[rname[dreg]] ); | |
993 printf("\tmovw %s,%d(%s)\n",reg_name_w[rname[dreg]] ,offset, | |
994 register_name(to,0)); | |
995 break; | |
996 case 4: case -4: | |
997 printf("\tmovl %d(%s),%s\n",offset, | |
998 register_name(from,0), register_name(dreg,0)); | |
999 printf("\tmovl %s,%d(%s)\n",register_name(dreg,0), offset, | |
1000 register_name(to,0)); | |
1001 break; | |
1002 default: | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1003 if (length <0) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1004 if (length > -MAX_COPY_LEN) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1005 for(;length<=-4;length+=4,offset-=4) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1006 emit_copy(from,to,-4,offset-4,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1007 for(;length<=-2;length+=2,offset-=2) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1008 emit_copy(from,to,-2,offset-2,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1009 if(length<0) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1010 emit_copy(from,to,length,offset-1,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1011 break; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1012 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1013 } else if (length <=MAX_COPY_LEN) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1014 for(;length>=4;length-=4,offset+=4) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1015 emit_copy(from,to,4,offset,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1016 for(;length>=2;length-=2,offset+=2) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1017 emit_copy(from,to,2,offset,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1018 if(length>0) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1019 emit_copy(from,to,length,offset,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1020 break; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1021 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1022 /* |
61 | 1023 if (det) { |
1024 call bcopy | |
1025 g_expr(list3(FUNCTION,,); | |
1026 break; | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1027 } |
61 | 1028 */ |
1029 use_register(from,REG_ESI,1); | |
1030 use_register(to, REG_EDI,1); | |
1031 use_register(dreg,REG_ECX,0); | |
1032 if (length<0) { | |
1033 printf("\tmovl $%d,%%ecx\n",-length/4); | |
1034 printf("\taddl $%d,%%esi\n",-length); | |
1035 printf("\taddl $%d,%%edi\n",-length); | |
1036 printf("\tstd\n\trep\n\tmovsl\n"); | |
1037 if(length%4) { | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1038 emit_copy(from,to,length,offset+length/SIZE_OF_INT,0,det); |
61 | 1039 } |
1040 } else { | |
1041 printf("\tmovl $%d,%%ecx\n",length/4); | |
1042 fix = (length/4)*4; | |
1043 printf("\tcld\n\trep\n\tmovsl\n"); | |
1044 if(length%4) { | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
254
diff
changeset
|
1045 emit_copy(from,to,length,offset+length/SIZE_OF_INT,0,det); |
61 | 1046 } |
1047 } | |
1048 } | |
1049 if (value) { | |
1050 /* creg must point top of the destination data */ | |
1051 /* this code is necessary for the value of assignment or function call */ | |
1052 /* otherwise we don't need this */ | |
1053 if (fix) printf("\tsubl $%d,%s\n",fix,register_name(to,0)); | |
1054 if(creg!=to) { | |
1055 if (to==dreg) | |
1056 printf("\tmovl %s,%s\n",register_name(to,0),register_name(creg,0)); | |
1057 else { | |
1058 free_register(creg); creg=to; | |
1059 } | |
1060 } | |
1061 } | |
1062 regv[from]=regv[to]=regv[dreg]=0; | |
1063 regv[creg]=1; | |
1064 } | |
1065 | |
1066 int | |
1067 struct_push(int e4,int t) | |
1068 { | |
81 | 1069 int length,xreg,save,lreg,count; |
61 | 1070 g_expr(e4); |
1071 length=size(t); | |
245 | 1072 if(length%SIZE_OF_INT) { |
1073 length += SIZE_OF_INT - (length%SIZE_OF_INT); | |
61 | 1074 } |
245 | 1075 for(count=0;length<MAX_COPY_LEN;count++,length-=SIZE_OF_INT) { |
81 | 1076 if (length==0) return count; |
1077 else { | |
1078 printf("\tpushl %d(%s)\n", | |
245 | 1079 length-SIZE_OF_INT,register_name(creg,0)); |
81 | 1080 } |
61 | 1081 } |
1082 printf("\tsubl $%d,%%esp\n",length); | |
1083 if (register_full()) { | |
1084 save = 1; | |
1085 for(lreg=0;lreg==creg||lreg==dreg;lreg++); | |
1086 printf("\tpushl %s\n",register_name(lreg,0)); | |
1087 xreg = lreg; regv[xreg]=0; | |
1088 } else { | |
1089 save=0; | |
1090 xreg = get_register(); | |
1091 } | |
1092 if (save) | |
245 | 1093 printf("\tlea %d(%%esp),%s\n",SIZE_OF_INT,register_name(xreg,0)); |
61 | 1094 else |
1095 printf("\tmovl %%esp,%s\n",register_name(xreg,0)); | |
1096 regv[xreg]=1; | |
1097 /* downward direction copy */ | |
1098 emit_copy(creg,xreg,length,0,0,1); | |
1099 /* we have value in creg, it may be changed */ | |
1100 if (save) { | |
1101 if(creg==xreg) { | |
1102 creg = get_register(); /* creg is freed in emit_copy */ | |
1103 } | |
1104 printf("\tpopl %s\n",register_name(xreg,0)); | |
1105 regv[xreg]=1; | |
1106 } else | |
1107 free_register(xreg); | |
313 | 1108 stack_depth += length*SIZE_OF_INT; |
245 | 1109 return length/SIZE_OF_INT; |
61 | 1110 } |
1111 | |
94 | 1112 int |
61 | 1113 function(int e1) |
1114 { | |
127 | 1115 int e2,e3,e4,nargs,t,ret_type; |
1116 NMTBL *n=0; | |
61 | 1117 int save,saved; |
313 | 1118 int stack_depth_save = stack_depth; |
1119 | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
1120 ret_type = cadr(cadddr(e1)); |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
1121 if (ret_type==CHAR) ret_type=INT; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
1122 |
94 | 1123 #ifdef SAVE_STACKS |
1124 code_save_stacks(); | |
237 | 1125 #if FLOAT_CODE |
1126 code_save_fstacks(); | |
1127 #endif | |
94 | 1128 #endif |
137 | 1129 if (free_register_count(0)<1) { |
61 | 1130 for(save = 0;save==dreg||save==creg;save++); |
1131 printf("\tpushl %s\n",register_name(save,0)); | |
1132 saved = 1; | |
1133 } else { | |
1134 save = get_register(); | |
1135 saved = 0; | |
1136 } | |
1137 regv[save]=0; | |
1138 e2 = cadr(e1); | |
1139 nargs = 0; | |
1140 for (e3 = caddr(e1); e3; e3 = cadr(e3)) { | |
1141 t=caddr(e3); | |
127 | 1142 e4 = car(e3); |
61 | 1143 if(scalar(t)) { |
240 | 1144 if (car(e4)==REGISTER) { |
1145 printf("\tpushl %s\n",register_name(cadr(e4),0)); | |
1146 } else { | |
1147 g_expr(e4); | |
1148 printf("\tpushl %s\n",register_name(creg,0)); | |
1149 } | |
313 | 1150 stack_depth += SIZE_OF_INT; |
237 | 1151 } else if (t==LONGLONG||t==ULONGLONG) { |
240 | 1152 if (car(e4)==LREGISTER) { |
1153 printf("\tpushl %s\n\tpushl %s\n",l_edx(cadr(e4)),l_eax(cadr(e4))); | |
1154 } else { | |
1155 g_expr(e4); | |
1156 printf("\tpushl %%edx\n\tpushl %%eax\n"); | |
1157 } | |
241 | 1158 ++nargs; |
313 | 1159 stack_depth += SIZE_OF_INT*2; |
82 | 1160 } else if (t==DOUBLE) { |
1161 g_expr(e4); | |
1162 printf("\tleal\t-8(%%esp),%%esp\n\tfstpl\t(%%esp)\n"); | |
245 | 1163 nargs += SIZE_OF_DOUBLE/SIZE_OF_INT; |
83 | 1164 fregv[freg]=0; |
313 | 1165 stack_depth += SIZE_OF_DOUBLE; |
82 | 1166 continue; |
1167 } else if (t==FLOAT) { | |
1168 g_expr(e4); | |
1169 printf("\tleal\t-4(%%esp),%%esp\n\tfstps\t(%%esp)\n"); | |
245 | 1170 nargs += SIZE_OF_FLOAT/SIZE_OF_INT; |
83 | 1171 fregv[freg]=0; |
313 | 1172 stack_depth += SIZE_OF_FLOAT; |
82 | 1173 continue; |
61 | 1174 } else if (car(t)==STRUCT||car(t)==UNION) { |
1175 nargs += struct_push(e4,t); | |
1176 continue; | |
1177 } else { | |
1178 error(TYERR); | |
1179 } | |
1180 ++nargs; | |
1181 } | |
1182 if (car(e2) == FNAME) { | |
1183 n=(NMTBL *)cadr(e2); | |
78 | 1184 regv[creg]=0; |
1185 use_register(creg,REG_EAX,0); /* will be destroyed */ | |
61 | 1186 } else { |
1187 g_expr(e2); | |
78 | 1188 regv[creg]=1; |
1189 use_register(creg,REG_EAX,1); /* will be destroyed */ | |
61 | 1190 } |
1191 | |
1192 /* we don't have to save creg nor dreg */ | |
1193 regs[creg]=0; regs[dreg]=0; | |
78 | 1194 regv[dreg]= regv[save]= 0; |
239 | 1195 use_register(dreg,REG_EBX,0); /* will be destroyed */ |
61 | 1196 use_register(save,REG_ECX,0); /* will be destroyed */ |
1197 regs[creg]=1; regs[dreg]=1; | |
1198 | |
1199 if (car(e2) == FNAME) { | |
1200 printf("\tcall\t%s\n",n->nm); | |
1201 } else { | |
1202 printf("\tcall\t*%s\n",register_name(creg,0)); | |
1203 } | |
245 | 1204 if (nargs) printf("\taddl $%d,%%esp\n",SIZE_OF_INT*nargs); |
61 | 1205 if (saved) { |
1206 printf("\tpopl %s\n",register_name(save,0)); | |
1207 } else { | |
1208 free_register(save); | |
1209 } | |
1210 regv[save]=0; | |
105 | 1211 if (ret_type==DOUBLE||ret_type==FLOAT) { |
239 | 1212 } else if (ret_type==LONGLONG||ret_type==ULONGLONG) { |
243 | 1213 use_longlong0(USE_CREG); |
1214 regv[creg]=1; | |
105 | 1215 } else if (ret_type==VOID) { |
243 | 1216 regv[freg]=0; regv[creg]=0; |
94 | 1217 } else { |
243 | 1218 use_register(creg,REG_EAX,0); |
94 | 1219 fregv[freg]=0; regv[creg]=1; |
1220 } | |
313 | 1221 stack_depth = stack_depth_save; |
105 | 1222 return ret_type; |
61 | 1223 } |
1224 | |
1225 void | |
313 | 1226 code_alloca(int e1,int reg) |
1227 { | |
1228 char *crn,*drn; | |
1229 int edx; | |
1230 | |
1231 g_expr(list3(BAND,list3(ADD,e1,list2(CONST,15)),list2(CONST,~15))); | |
1232 use_int(reg); | |
1233 if (stack_depth>0) { | |
1234 edx = edx_setup(-1); | |
1235 crn = register_name(reg,0); | |
1236 drn = register_name(edx,0); | |
1237 printf("\tmovl %%esp,%s\n",drn); | |
1238 printf("\tsubl %s,%%esp\n",crn); | |
1239 printf("\tmovl %%esp,%s\n",crn); | |
1240 emit_copy(edx,creg,stack_depth,0,1,1); | |
1241 printf("\taddl $%d,%s\n",stack_depth,register_name(creg,0)); | |
1242 edx_cleanup(); | |
1243 } else { | |
1244 crn = register_name(reg,0); | |
1245 printf("\tsubl %s,%%esp\n",crn); | |
1246 printf("\tmovl %%esp,%s\n",crn); | |
1247 } | |
1248 } | |
1249 | |
1250 void | |
61 | 1251 code_frame_pointer(int e3) { |
235 | 1252 use_int(e3); |
61 | 1253 printf("\tmovl %s,%%ebp\n",register_name(e3,0)); |
1254 } | |
1255 | |
1256 | |
1257 void | |
62 | 1258 code_fix_frame_pointer(int disp_offset) { |
61 | 1259 printf("\tlea %d(%%ebp),%%ebp\n",disp_offset); |
1260 } | |
1261 | |
1262 | |
1263 void | |
1264 code_jmp(char *s) { | |
1265 printf("\tjmp %s\n",s); | |
1266 } | |
1267 | |
1268 | |
1269 void | |
1270 code_indirect_jmp(int e2) { | |
1271 printf("\tjmp *%s\n",register_name(e2,0)); | |
1272 } | |
1273 | |
94 | 1274 int |
245 | 1275 code_rindirect(int e1, int reg,int offset, int sign) |
196 | 1276 { |
1277 char *crn,*op; | |
1278 int byte; | |
1279 g_expr(e1); | |
1280 byte = 0; op="movl"; | |
1281 crn = register_name(creg,0); | |
235 | 1282 use_int(reg); |
1283 printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0)); | |
246 | 1284 return sign?INT:UNSIGNED; |
196 | 1285 } |
1286 | |
1287 int | |
245 | 1288 code_crindirect(int e1, int reg,int offset, int sign) |
61 | 1289 { |
196 | 1290 char *crn,*op; |
1291 int byte; | |
1292 g_expr(e1); | |
245 | 1293 byte = 0; op=sign?"movsbl":"movzbl"; |
196 | 1294 crn = register_name(creg,0); |
235 | 1295 use_int(reg); |
1296 printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0)); | |
246 | 1297 return sign?CHAR:UCHAR; |
196 | 1298 } |
1299 | |
1300 int | |
245 | 1301 code_srindirect(int e1, int reg,int offset, int sign) |
196 | 1302 { |
1303 char *crn,*op; | |
1304 int byte; | |
1305 g_expr(e1); | |
245 | 1306 byte = 0; op=sign?"movswl":"movzwl"; |
196 | 1307 crn = register_name(creg,0); |
235 | 1308 use_int(reg); |
1309 printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0)); | |
246 | 1310 return sign?SHORT:USHORT; |
196 | 1311 } |
1312 | |
195 | 1313 #if FLOAT_CODE |
196 | 1314 int |
225 | 1315 code_drindirect(int e1, int reg,int offset, int d) |
196 | 1316 { |
1317 g_expr(e1); | |
1318 printf("\t%s (%s)\n",fload(d),register_name(creg,0)); | |
1319 return DOUBLE; | |
1320 } | |
195 | 1321 #endif |
196 | 1322 |
1323 #if LONGLONG_CODE | |
237 | 1324 |
1325 static void | |
239 | 1326 lload(int creg,int offset,int reg) |
237 | 1327 { |
1328 char *crn = register_name(creg,0); | |
239 | 1329 use_longlong(reg); |
1330 if((reg==REG_L&&rname[creg]==REG_ESI)||(rname[creg]==REG_EAX)) { | |
245 | 1331 printf("\tmovl %d(%s),%s\n",offset+SIZE_OF_INT,crn,l_edx(reg)); |
240 | 1332 printf("\tmovl %d(%s),%s\n",offset,crn,l_eax(reg)); |
237 | 1333 } else { |
239 | 1334 printf("\tmovl %d(%s),%s\n",offset,crn,l_eax(reg)); |
245 | 1335 printf("\tmovl %d(%s),%s\n",offset+SIZE_OF_INT,crn,l_edx(reg)); |
237 | 1336 } |
1337 } | |
1338 | |
196 | 1339 int |
225 | 1340 code_lrindirect(int e1, int reg, int offset, int us) |
196 | 1341 { |
240 | 1342 int reg0; |
237 | 1343 g_expr(e1); |
240 | 1344 regv[reg0=creg]=1; |
237 | 1345 use_longlong(reg); |
240 | 1346 lload(reg0,offset,reg); |
203 | 1347 return LONGLONG; |
61 | 1348 } |
196 | 1349 #endif |
61 | 1350 |
1351 char * | |
1352 move(int byte) | |
1353 { | |
245 | 1354 return byte==1?"movb":byte==SIZE_OF_SHORT?"movw":"movl"; |
61 | 1355 } |
1356 | |
1357 void | |
103 | 1358 code_assign_gvar(int e2,int creg,int byte) { |
235 | 1359 use_int(creg); |
61 | 1360 if (byte) use_data_reg(creg,1); |
109 | 1361 printf("\t%s %s,%s\n",move(byte),register_name(creg,byte),((NMTBL*)cadr(e2))->nm); |
61 | 1362 } |
1363 | |
1364 void | |
103 | 1365 code_assign_lvar(int e2,int creg,int byte) { |
235 | 1366 use_int(creg); |
61 | 1367 if (byte) use_data_reg(creg,1); |
119 | 1368 printf("\t%s %s,%d(%%ebp)\n",move(byte),register_name(creg,byte),lvar(e2)); |
61 | 1369 } |
1370 | |
1371 void | |
111 | 1372 code_assign_register(int e2,int byte,int creg) { |
235 | 1373 use_int(creg); |
286 | 1374 if (creg!=e2) |
1375 printf("\tmovl %s,%s\n",register_name(creg,0),register_name(e2,0)); | |
61 | 1376 } |
1377 | |
1378 void | |
118 | 1379 code_assign(int e2,int byte,int creg) { |
235 | 1380 use_int(e2); |
1381 use_int(creg); | |
95 | 1382 if (byte) use_data_reg(creg,1); |
61 | 1383 printf("\t%s %s,(%s)\n",move(byte),register_name(creg,byte),register_name(e2,0)); |
144 | 1384 regv[creg]=1; |
61 | 1385 } |
1386 | |
1387 void | |
225 | 1388 code_register_assop(int e2,int reg0,int op,int byte) { |
61 | 1389 int reg; |
1390 int xreg = creg; | |
1391 creg = reg = e2; | |
225 | 1392 tosop(op,reg,xreg); |
61 | 1393 creg = xreg; |
286 | 1394 // printf("\tmovl %s,%s\n",register_name(reg,0),register_name(creg,0)); |
159 | 1395 regs[creg]=regv[creg]=1; |
61 | 1396 } |
1397 | |
1398 | |
1399 void | |
225 | 1400 code_assop(int op,int reg,int byte,int sign) { |
61 | 1401 char *xrn; |
1402 int xreg; | |
237 | 1403 int edx = edx_setup(-1); |
235 | 1404 use_int(reg); |
61 | 1405 xrn = register_name(xreg = emit_pop(0),0); /* pop e3 value */ |
1406 regv[xreg]=regs[xreg]=1; | |
235 | 1407 printf("\tmovl %s,%s # assop \n",register_name(reg,0),register_name(edx,0)); |
61 | 1408 regv[edx]=1; |
235 | 1409 ld_indexx(byte,0,edx,reg,sign); |
225 | 1410 tosop(op,reg,xreg); |
235 | 1411 printf("\t%s %s,(%s)\n",move(byte),register_name(reg,byte),register_name(edx,0)); |
61 | 1412 edx_cleanup(); |
1413 emit_pop_free(xreg); | |
144 | 1414 regv[creg]=1; |
61 | 1415 } |
1416 | |
1417 | |
1418 void | |
225 | 1419 tosop(int op,int reg,int oreg) |
61 | 1420 { |
1421 int dx; | |
1422 char *orn,*crn; | |
235 | 1423 use_int(reg); |
61 | 1424 |
1425 switch(op) { | |
1426 case LSHIFT: | |
1427 case ULSHIFT: | |
235 | 1428 shift("sall",oreg,reg); |
144 | 1429 regv[creg]=1; |
61 | 1430 return; |
1431 case RSHIFT: | |
235 | 1432 shift("sarl",oreg,reg); |
144 | 1433 regv[creg]=1; |
61 | 1434 return; |
1435 case URSHIFT: | |
235 | 1436 shift("shrl",oreg,reg); |
144 | 1437 regv[creg]=1; |
61 | 1438 return; |
1439 } | |
1440 if(oreg==-1) { | |
1441 printf("\tpopl %s\n",register_name(dreg,0)); | |
1442 oreg = dreg; | |
1443 regv[dreg]=1; | |
94 | 1444 } else if (oreg<= -REG_LVAR_OFFSET) { |
119 | 1445 code_rlvar(oreg+REG_LVAR_OFFSET,dreg); |
117 | 1446 free_lvar(oreg+REG_LVAR_OFFSET); |
94 | 1447 oreg = dreg; |
1448 regv[dreg]=1; | |
61 | 1449 } |
1450 regv[oreg]=1; regs[oreg]=1; | |
1451 orn = register_name(oreg,0); | |
1452 crn = register_name(creg,0); | |
1453 switch(op) { | |
1454 case ADD: | |
1455 printf("\taddl %s,%s\n",orn,crn); | |
1456 break; | |
89 | 1457 case SUB: case CMP: |
61 | 1458 printf("\tsubl %s,%s\n",orn,crn); |
1459 break; | |
1460 case BAND: | |
1461 printf("\tandl %s,%s\n",orn,crn); | |
1462 break; | |
1463 case EOR: | |
1464 printf("\txorl %s,%s\n",orn,crn); | |
1465 break; | |
1466 case BOR: | |
1467 printf("\torl %s,%s\n",orn,crn); | |
1468 break; | |
1469 case MUL: | |
1470 case UMUL: | |
1471 printf("\t%s %s,%s\n","imull",orn,crn); | |
1472 break; | |
1473 case DIV: | |
1474 case UDIV: | |
1475 use_register(creg,REG_EAX,1); | |
237 | 1476 edx_setup(REG_EDX); |
61 | 1477 orn = register_name(oreg,0); |
1478 if (op==DIV) | |
127 | 1479 printf("\tcltd\n\tidivl %s\n",orn); |
61 | 1480 else |
127 | 1481 printf("\txor %%edx,%%edx\n\tdivl %s\n",orn); |
61 | 1482 edx_cleanup(); |
1483 break; | |
1484 case MOD: | |
1485 case UMOD: | |
1486 use_register(creg,REG_EAX,1); | |
237 | 1487 edx_setup(REG_EDX); |
61 | 1488 orn = register_name(oreg,0); |
235 | 1489 if (op==MOD) |
127 | 1490 printf("\tcltd\n\tidivl %s\n",orn); |
61 | 1491 else |
127 | 1492 printf("\txor %%edx,%%edx\n\tdivl %s\n",orn); |
61 | 1493 dx = virtual(REG_EDX); |
1494 if (dx!=creg) { | |
1495 rname[dx]=rname[creg]; | |
1496 rname[creg]=REG_EDX; | |
1497 } | |
1498 edx_cleanup(); | |
1499 break; | |
1500 } | |
159 | 1501 if (oreg!=dreg&&oreg!=creg&&oreg>=0) |
61 | 1502 free_register(oreg); |
94 | 1503 else if (oreg==dreg) regv[dreg]=0; |
144 | 1504 regv[creg]=1; |
61 | 1505 } |
1506 | |
189 | 1507 int |
240 | 1508 code_const_op_p(int op,int e) |
189 | 1509 { |
240 | 1510 if (car(e)!=CONST) return 0; |
190 | 1511 if (op==DIV||op==UDIV||op==MOD||op==UMOD) return 0; |
189 | 1512 else return 1; |
1513 } | |
1514 | |
1515 void | |
225 | 1516 oprtc(int op,int reg,int orn) |
189 | 1517 { |
235 | 1518 char *crn; |
313 | 1519 int datareg; |
235 | 1520 use_int(reg); |
1521 crn = register_name(reg,0); | |
240 | 1522 orn = cadr(orn); |
313 | 1523 datareg=(rname[reg]<MAX_DATA_REG); |
189 | 1524 |
1525 switch(op) { | |
1526 case LSHIFT: | |
1527 case ULSHIFT: | |
1528 printf("\tsall $%d,%s\n",orn,crn); | |
1529 return; | |
1530 case RSHIFT: | |
1531 printf("\tsarl $%d,%s\n",orn,crn); | |
1532 return; | |
1533 case URSHIFT: | |
1534 printf("\tshrl $%d,%s\n",orn,crn); | |
1535 return; | |
1536 case ADD: | |
1537 printf("\taddl $%d,%s\n",orn,crn); | |
1538 break; | |
1539 case SUB: case CMP: | |
1540 printf("\tsubl $%d,%s\n",orn,crn); | |
1541 break; | |
1542 case BAND: | |
313 | 1543 if (datareg&&(orn & ~255)==~255) |
1544 printf("\tandb $%d,%s\n",orn,register_name(reg,1)); | |
1545 else if (datareg&&(orn & ~65535)==~65535) | |
1546 printf("\tandw $%d,%s\n",orn,register_name(reg,2)); | |
1547 else | |
1548 printf("\tandl $%d,%s\n",orn,crn); | |
189 | 1549 break; |
1550 case EOR: | |
1551 printf("\txorl $%d,%s\n",orn,crn); | |
1552 break; | |
1553 case BOR: | |
313 | 1554 if (datareg&&(orn & ~255)==0) |
1555 printf("\tor $%d,%s\n",orn,register_name(reg,1)); | |
1556 else if (datareg&&(orn & ~65535)==0) | |
1557 printf("\tor $%d,%s\n",orn,register_name(reg,2)); | |
1558 else | |
1559 printf("\torl $%d,%s\n",orn,crn); | |
189 | 1560 break; |
1561 case MUL: | |
1562 case UMUL: | |
1563 printf("\t%s $%d,%s\n","imull",orn,crn); | |
1564 break; | |
1565 default: | |
1566 error(-1); | |
1567 } | |
1568 } | |
1569 | |
1570 | |
61 | 1571 static int edx_stack=0; |
1572 | |
1573 int | |
237 | 1574 edx_setup(int rreg) |
61 | 1575 { |
1576 int edx_save; | |
302 | 1577 /* make real EDX (or rreg) register empty */ |
137 | 1578 if (free_register_count(0)<1) { |
61 | 1579 for(edx_save = 0;edx_save==dreg||edx_save==creg;edx_save++); |
1580 printf("\tpushl %s\n",register_name(edx_save,0)); | |
1581 edx_stack = list3(edx_save,edx_stack,0); | |
1582 } else { | |
1583 edx_save = get_register(); | |
1584 edx_stack = list3(edx_save,edx_stack,1); | |
1585 } | |
1586 regv[edx_save]=0; | |
237 | 1587 if (rreg!=-1) |
1588 use_register(edx_save,rreg,0); | |
61 | 1589 return edx_save; |
1590 } | |
1591 | |
1592 | |
1593 void | |
1594 edx_cleanup() | |
1595 { | |
1596 if (caddr(edx_stack)==0) { | |
1597 printf("\tpopl %s\n",register_name(car(edx_stack),0)); | |
1598 } else | |
1599 free_register(car(edx_stack)); | |
1600 edx_stack = cadr(edx_stack); | |
1601 } | |
1602 | |
1603 void | |
235 | 1604 shift(char *op, int reg,int creg) |
61 | 1605 { |
235 | 1606 use_int(creg); |
61 | 1607 if (reg>=0) { |
1608 use_register(reg,REG_ECX,1); | |
103 | 1609 } else if (reg<= -REG_LVAR_OFFSET) { |
1610 use_register(dreg,REG_ECX,0); | |
119 | 1611 code_rlvar(reg+REG_LVAR_OFFSET,dreg); |
103 | 1612 reg = dreg; |
1613 regv[dreg]=0; | |
61 | 1614 } else { |
1615 use_register(dreg,REG_ECX,0); | |
1616 printf("\tpopl %%ecx\n"); | |
103 | 1617 regv[dreg]=0; |
61 | 1618 } |
1619 printf("\t%s %%cl,%s\n",op,register_name(creg,0)); | |
1620 } | |
1621 | |
1622 void | |
235 | 1623 ld_indexx(int byte, int n, int xreg,int reg,int sign) |
61 | 1624 { |
1625 char *op; | |
1626 | |
235 | 1627 use_int(reg); |
166 | 1628 op = byte ? (sign?"movsbl":"movzbl") : "movl"; |
61 | 1629 if (n) |
95 | 1630 printf("\t%s %d(%s),%s\n",op,n, |
235 | 1631 register_name(xreg,0),register_name(reg,byte)); |
61 | 1632 else |
95 | 1633 printf("\t%s (%s),%s\n",op, |
235 | 1634 register_name(xreg,0),register_name(reg,byte)); |
95 | 1635 } |
1636 | |
1637 int | |
1638 code_csvalue() | |
1639 { | |
123 | 1640 return rname[creg]; /* for switch value */ |
61 | 1641 } |
1642 | |
1643 void | |
287 | 1644 code_cmpdimm(int e, int csreg,int label,int cond) |
61 | 1645 { |
1646 /* used in dosiwtch() */ | |
66 | 1647 if(chk) return; |
123 | 1648 use_register(creg,csreg,0); |
61 | 1649 printf("\tcmpl $%d,%s\n",e,register_name(creg,0)); |
287 | 1650 jcond(label,cond); |
61 | 1651 } |
1652 | |
1653 void | |
66 | 1654 code_opening(char *filename) |
61 | 1655 { |
1656 printf("\t.file \"%s\"\n",filename); | |
1657 printf("\t.version\t\"01.01\"\n"); | |
66 | 1658 /* printf("gcc2_compiled.:\n"); */ |
61 | 1659 printf(".text\n"); |
1660 } | |
1661 | |
1662 void | |
66 | 1663 code_closing() |
61 | 1664 { |
78 | 1665 global_table(); |
61 | 1666 printf("\t.ident \"Micro-C compiled\"\n"); |
1667 } | |
1668 | |
291 | 1669 static char * |
1670 code_cond(int op,int cond) | |
1671 { | |
1672 switch(op) { | |
1673 case GT: return code_gt(cond); | |
1674 case UGT: return code_ugt(cond); | |
1675 case GE: return code_ge(cond); | |
1676 case UGE: return code_uge(cond); | |
1677 case LT: return code_ge(!cond); | |
1678 case ULT: return code_uge(!cond); | |
1679 case LE: return code_gt(!cond); | |
1680 case ULE: return code_ugt(!cond); | |
1681 case EQ: return code_eq(cond); | |
1682 case NEQ: return code_eq(!cond); | |
1683 default: return 0; | |
1684 } | |
1685 } | |
1686 | |
1687 static int | |
1688 rexpr_bool(int e1,int reg) | |
1689 { | |
1690 char *s; | |
1691 if (!(s=code_cond(car(e1),1))) return 0; | |
1692 g_expr(list3(CMP,cadr(e1),caddr(e1))); | |
1693 use_int(reg); | |
1694 use_data_reg(reg,0); | |
1695 printf("\tset%s\t%s\n",s,register_name(reg,1)); | |
1696 printf("\tmovzbl %s,%s\n",register_name(reg,1),register_name(reg,0)); | |
1697 return 1; | |
1698 } | |
1699 | |
61 | 1700 void |
280 | 1701 rexpr(int e1, int l1, int cond,int t) |
1702 { | |
89 | 1703 g_expr(list3(CMP,cadr(e1),caddr(e1))); |
291 | 1704 printf("\tj%s\t_%d\n",code_cond(car(e1),cond),l1); |
61 | 1705 } |
1706 | |
82 | 1707 |
287 | 1708 static void |
61 | 1709 jcond(int l, char cond) |
1710 { | |
66 | 1711 if (chk) return; |
302 | 1712 printf("\tj%s\t_%d\n",cond==LT?code_ge(0):cond?"ne":"e",l); |
61 | 1713 } |
1714 | |
1715 void | |
1716 jmp(int l) | |
1717 { | |
1718 control=0; | |
66 | 1719 if (chk) return; |
61 | 1720 printf("\tjmp\t_%d\n",l); |
1721 /* align? */ | |
1722 /* | |
1723 this is not allowed because of ? operator | |
1724 regv[creg]=regv[dreg]=0; | |
1725 use_register(creg,REG_EAX,0); | |
1726 use_register(dreg,REG_EBX,0); | |
1727 */ | |
1728 } | |
1729 | |
1730 void | |
1731 gen_comment(char *s) | |
1732 { | |
66 | 1733 if (chk) return; |
1734 printf("## %s",s); | |
61 | 1735 } |
1736 | |
1737 | |
1738 void | |
1739 code_enter(char *name) | |
1740 { | |
1741 printf("\t.align 4\n"); | |
1742 if (stmode!=STATIC) | |
1743 printf(".globl %s\n",name); | |
1744 printf("\t.type\t%s,@function\n",name); | |
1745 printf("%s:\n",name); | |
1746 } | |
1747 | |
77 | 1748 |
61 | 1749 void |
1750 code_enter1(int args) | |
1751 { | |
1752 code_disp_label=fwdlabel(); | |
1753 printf("\tlea _%d(%%ebp),%%esp\n",code_disp_label); | |
1754 | |
327 | 1755 printf("## args %d disp %d code_disp_offset=%d\n",args,disp,code_disp_offset); |
61 | 1756 } |
1757 | |
1758 void | |
1759 code_leave(char *name) | |
1760 { | |
245 | 1761 disp &= -SIZE_OF_INT; |
61 | 1762 printf("\t.set _%d,%d\n",code_disp_label,disp+code_disp_offset); |
1763 printf("_%d:\n",labelno); | |
1764 printf("\t.size\t%s,_%d-%s\n",name,labelno,name); | |
1765 local_table(); | |
1766 labelno++; | |
1767 free_all_register(); | |
1768 } | |
1769 | |
1770 void | |
1771 enter(char *name) | |
1772 { | |
1773 printf("\t.align 2\n"); | |
1774 if (stmode!=STATIC) | |
1775 printf(".globl %s\n",name); | |
1776 printf("%s:\n",name); | |
1777 printf("\t.type\t%s,@function\n",name); | |
1778 printf("\tpushl %%ebp\n"); | |
1779 printf("\tmovl %%esp,%%ebp\n"); | |
1780 printf("\tpushl %%ebx\n"); | |
1781 printf("\tpushl %%esi\n"); | |
1782 printf("\tpushl %%edi\n"); | |
1783 } | |
1784 | |
1785 void | |
1786 enter1() | |
1787 { | |
182 | 1788 text_mode(); |
61 | 1789 func_disp_label=fwdlabel(); |
1790 printf("\tlea _%d(%%ebp),%%esp\n",func_disp_label); | |
1791 /* if(disp) printf("\tsubl $%d,%%esp\n",-disp); */ | |
1792 } | |
1793 | |
1794 void | |
1795 leave(int control, char *name) | |
1796 { | |
128 | 1797 int sz; |
1798 | |
245 | 1799 disp &= -SIZE_OF_INT; |
61 | 1800 if (control) |
108 | 1801 code_set_return_register(1); |
61 | 1802 if (retcont) { |
1803 if (control) | |
1804 jmp(retlabel); | |
1805 fwddef(retcont); | |
128 | 1806 if (cadr(fnptr->ty)==FLOAT||cadr(fnptr->ty)==DOUBLE) { |
245 | 1807 printf("\tfldl %d(%%ebp)\n",-SIZE_OF_DOUBLE); |
128 | 1808 } else if (cadr(fnptr->ty)>0&&( |
1809 car(cadr(fnptr->ty))==STRUCT || | |
1810 car(cadr(fnptr->ty))==UNION)) { | |
1811 sz = size(cadr(fnptr->ty)); | |
1812 printf("\tlea %d(%%ebp),%s\n",-sz,register_name(dreg,0)); | |
245 | 1813 printf("\tmovl %d(%%ebp),%s\n",disp-SIZE_OF_INT, |
128 | 1814 register_name(creg,0)); |
1815 emit_copy(dreg,creg,sz,0,1,1); | |
1816 } else if (cadr(fnptr->ty)!=VOID) { | |
1817 use_register(creg,REG_EAX,0); | |
1818 printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg,0)); | |
1819 } | |
61 | 1820 } |
1821 fwddef(retlabel); | |
63 | 1822 |
61 | 1823 printf("\tlea %d(%%ebp),%%esp\n",disp_offset); |
1824 printf("\tpopl %%edi\n"); | |
1825 printf("\tpopl %%esi\n"); | |
1826 printf("\tpopl %%ebx\n"); | |
1827 printf("\tleave\n"); | |
1828 printf("\tret\n"); | |
1829 printf("\t.set _%d,%d\n",func_disp_label,disp+disp_offset); | |
1830 printf("_%d:\n",labelno); | |
1831 printf("\t.size\t%s,_%d-%s\n",name,labelno,name); | |
1832 local_table(); | |
1833 labelno++; | |
1834 free_all_register(); | |
1835 } | |
1836 | |
187 | 1837 int |
1838 code_get_fixed_creg(int reg,int type) { | |
1839 if (type==FLOAT||type==DOUBLE) { | |
1840 return 0; | |
239 | 1841 } else if (type==LONGLONG||type==ULONGLONG) { |
1842 use_longlong(reg); | |
1843 return reg; | |
187 | 1844 } else { |
236 | 1845 use_int(reg); |
187 | 1846 return rname[reg]; |
1847 } | |
1848 } | |
61 | 1849 |
1850 void | |
187 | 1851 code_set_fixed_creg(int reg,int mode,int type) { |
108 | 1852 if (type==FLOAT||type==DOUBLE) { |
239 | 1853 } else if (type==LONGLONG||type==ULONGLONG) { |
187 | 1854 } else { |
1855 use_register(creg,reg,mode); | |
1856 } | |
61 | 1857 } |
1858 | |
1859 void | |
107 | 1860 code_set_return_register(int mode) { |
1861 if (fnptr->ty==DOUBLE||fnptr->ty==FLOAT) { | |
239 | 1862 } else if (fnptr->ty==LONGLONG||fnptr->ty==ULONGLONG) { |
243 | 1863 use_longlong0(USE_CREG); |
107 | 1864 } else { |
1865 use_register(creg,REG_EAX,mode); | |
1866 } | |
1867 } | |
1868 | |
1869 void | |
61 | 1870 gen_gdecl(char *n, int gpc) |
1871 { | |
1872 /* | |
1873 if (stmode!=STATIC) | |
1874 printf(".globl %s\n",n); | |
1875 */ | |
1876 } | |
1877 | |
340 | 1878 extern void |
1879 ascii(char *s) | |
1880 { | |
1881 printf("\t.string \""); | |
1882 while(*s) { | |
1883 if (*s=='\n') | |
1884 printf("%cn",92); | |
1885 else if (*s<' ') | |
1886 printf("%c%03o",92,*s); | |
1887 else if (*s==34) | |
1888 printf("%c%c",92,34); | |
1889 else | |
1890 printf("%c",*s); | |
1891 s++; | |
1892 } | |
1893 printf("%c\n",34); | |
1894 } | |
1895 | |
1896 extern int | |
1897 emit_string_label() | |
1898 { | |
1899 int lb; | |
1900 printf(".section\t.rodata\n"); | |
1901 lb=fwdlabel(); | |
1902 printf("_%d:\n",lb); | |
1903 output_mode = RODATA_EMIT_MODE; | |
1904 return lb; | |
1905 } | |
1906 | |
61 | 1907 void |
1908 align(int t) | |
1909 { | |
1910 if (t!=CHAR) { | |
1911 if (data_alignment & 1) | |
1912 printf("\t.align 2\n"); | |
1913 data_alignment = 0; | |
1914 } | |
1915 } | |
1916 | |
340 | 1917 extern void |
1918 emit_global(char *name,int t) | |
1919 { | |
1920 printf(".globl\t%s\n",name); | |
1921 data_mode(name); | |
1922 align(t); | |
1923 printf("%s:\n",name); | |
1924 } | |
1925 | |
1926 extern void | |
1927 emit_space(int sp) | |
1928 { | |
1929 data_mode(0); | |
1930 printf("\t.space\t%d\n",sp); | |
1931 } | |
1932 | |
1933 extern void | |
1934 emit_char(int d) | |
1935 { | |
1936 data_mode(0); | |
1937 printf("\t.byte %d\n",d); | |
1938 } | |
1939 | |
1940 extern void | |
1941 emit_short(int d) | |
1942 { | |
1943 data_mode(0); | |
1944 printf("\t.short %d\n",d); | |
1945 } | |
1946 | |
1947 extern void | |
1948 emit_int(int d) | |
1949 { | |
1950 data_mode(0); | |
1951 printf("\t.long %d\n",d); | |
1952 } | |
1953 | |
1954 extern void | |
1955 emit_longlong(int e) | |
1956 { | |
1957 #if LONGLONG_CODE | |
1958 long long ll = lcadr(e); | |
1959 data_mode(0); | |
1960 #if (ENDIAN==0) | |
1961 printf("\t.long\t0x%x,0x%x\n",code_l1(ll),code_l2(ll)); | |
1962 #else | |
1963 printf("\t.long\t0x%x,0x%x\n",code_l2(ll),code_l1(ll)); | |
1964 #endif | |
1965 #endif | |
1966 } | |
1967 | |
1968 extern void | |
1969 emit_double(int e) | |
1970 { | |
1971 #if FLOAT_CODE | |
1972 double d = dcadr(e); | |
1973 data_mode(0); | |
1974 #if (ENDIAN==0) | |
1975 printf("\t.long\t0x%x,0x%x\n",code_d1(d),code_d2(d)); | |
1976 #else | |
1977 printf("\t.long\t0x%x,0x%x\n",code_d2(d),code_d1(d)); | |
1978 #endif | |
1979 #endif | |
1980 } | |
1981 | |
1982 extern void | |
1983 emit_float(int e) | |
1984 { | |
1985 #if FLOAT_CODE | |
1986 float f = dcadr(e); | |
1987 data_mode(0); | |
1988 printf("\t.long\t0x%x\n",*(int *)&f); | |
1989 #endif | |
1990 } | |
1991 | |
1992 extern void | |
1993 emit_address(char *s) | |
1994 { | |
1995 data_mode(0); | |
1996 printf("\t.long %s\n",s); | |
1997 } | |
1998 | |
1999 extern void | |
2000 emit_label(int labelno) | |
2001 { | |
2002 data_mode(0); | |
2003 printf("\t.long _%d\n",labelno); | |
2004 } | |
2005 | |
2006 extern void | |
2007 emit_data_closing(NMTBL *n) | |
2008 { | |
2009 #ifdef DOT_SIZE | |
2010 int lb; | |
2011 #endif | |
2012 if (chk) return; | |
2013 if (mode==GDECL) { | |
2014 data_mode(0); | |
2015 #ifdef DOT_SIZE | |
2016 lb=fwdlabel(); | |
2017 printf("_%d:\n",lb); | |
2018 printf("\t.size\t%s,_%d-%s\n",n->nm,lb,n->nm); | |
2019 #endif | |
2020 } | |
2021 } | |
2022 | |
239 | 2023 #if LONGLONG_CODE |
2024 static long long ll0 = 1LL; | |
2025 | |
2026 static int | |
2027 code_l1(long long d) | |
2028 { | |
2029 int *i = (int *)&ll0; int *j = (int *)&d; | |
2030 return (i[1] == 1)?j[1]:j[0]; | |
2031 } | |
2032 | |
2033 static int | |
2034 code_l2(long long d) | |
2035 { | |
2036 int *i = (int *)&ll0; int *j = (int *)&d; | |
2037 return (i[1] == 1)?j[0]:j[1]; | |
2038 } | |
2039 #endif | |
2040 | |
61 | 2041 void |
2042 global_table(void) | |
2043 { | |
2044 NMTBL *n; | |
2045 int init; | |
2046 init=0; | |
2047 for(n=ntable;n < &ntable[GSYMS];n++) { | |
117 | 2048 if ((n->sc == GVAR||n->sc == STATIC) && n->dsp != -1) { |
61 | 2049 /* n->dsp = -1 means initialized global */ |
2050 if (init==0) { | |
2051 data_mode(0); | |
2052 init=1; | |
2053 } | |
2054 printf(".comm %s,%d\n",n->nm,size(n->ty)); | |
2055 } | |
2056 } | |
2057 } | |
2058 | |
2059 void | |
2060 local_table(void) | |
2061 { | |
2062 NMTBL *n; | |
2063 int init; | |
2064 init=0; | |
2065 /* static local variables */ | |
2066 for(n=ntable+GSYMS;n < &ntable[GSYMS+LSYMS];n++) { | |
2067 if (n->sc == GVAR) { | |
2068 if (init==0) { | |
2069 data_mode(0); | |
2070 init=1; | |
2071 } | |
156 | 2072 if (n->dsp!= -1) /* -1 means initialized global */ |
2073 printf(".lcomm %s,%d\n",n->nm,size(n->ty)); | |
61 | 2074 } |
2075 } | |
2076 } | |
2077 | |
2078 void | |
2079 text_mode(void) | |
2080 { | |
2081 if (output_mode!=TEXT_EMIT_MODE) { | |
2082 printf(".text\n"); | |
2083 printf("\t.align 2\n"); | |
2084 output_mode = TEXT_EMIT_MODE; | |
2085 } | |
2086 } | |
2087 | |
2088 void | |
2089 data_mode(char *name) | |
2090 { | |
2091 if (output_mode!=DATA_EMIT_MODE) { | |
2092 printf(".data\n"); | |
2093 output_mode = DATA_EMIT_MODE; | |
2094 } | |
2095 if (name) | |
2096 printf("\t.type\t%s,@object\n",name); | |
2097 } | |
2098 | |
195 | 2099 #if FLOAT_CODE |
2100 | |
81 | 2101 /* floating point */ |
2102 | |
2103 | |
82 | 2104 char * |
2105 fstore(int d) | |
2106 { | |
83 | 2107 return use? |
2108 (d?"fstl":"fsts"): | |
2109 (d?"fstpl":"fstps") | |
2110 ; | |
2111 } | |
2112 | |
2113 char * | |
2114 fstore_u(int d) | |
2115 { | |
82 | 2116 return d?"fstpl":"fstps"; |
2117 } | |
81 | 2118 |
82 | 2119 char * |
2120 fload(int d) | |
2121 { | |
2122 return d?"fldl":"flds"; | |
2123 } | |
81 | 2124 |
2125 | |
103 | 2126 void code_dassign_gvar(int e2,int freg,int d) |
82 | 2127 { |
109 | 2128 printf("\t%s %s\n",fstore(d),((NMTBL*)cadr(e2))->nm); |
82 | 2129 } |
2130 | |
103 | 2131 void code_dassign_lvar(int e2,int freg,int d) |
82 | 2132 { |
119 | 2133 printf("\t%s %d(%%ebp)\n",fstore(d),lvar(e2)); |
82 | 2134 } |
2135 | |
138 | 2136 void code_dassign_dregister(int e,int d,int freg) |
111 | 2137 { |
2138 error(-1); | |
2139 } | |
2140 | |
103 | 2141 void code_dassign(int e2,int freg,int d) |
82 | 2142 { |
2143 printf("\t%s (%s)\n",fstore(d),register_name(e2,0)); | |
2144 } | |
2145 | |
2146 static double d0 = 1.0; | |
81 | 2147 |
340 | 2148 static int |
82 | 2149 code_d1(double d) |
2150 { | |
2151 int *i = (int *)&d0; int *j = (int *)&d; | |
2152 return (i[1] == 0x3ff00000)?j[0]:j[1]; | |
2153 } | |
2154 | |
340 | 2155 static int |
82 | 2156 code_d2(double d) |
2157 { | |
2158 int *i = (int *)&d0; int *j = (int *)&d; | |
2159 return (i[1] == 0x3ff00000)?j[1]:j[0]; | |
2160 } | |
2161 | |
138 | 2162 void code_dconst(int e2,int freg,int d) |
82 | 2163 { |
2164 int lb; | |
138 | 2165 double value = dcadr(e2); |
81 | 2166 |
138 | 2167 if (value==0.0) { |
82 | 2168 printf("\tfldz\n"); return; |
2169 } | |
138 | 2170 if (value==1.0) { |
82 | 2171 printf("\tfld1\n"); return; |
2172 } | |
2173 printf(" \t.section\t.rodata\n\t.align 8\n"); | |
2174 lb=fwdlabel(); | |
2175 printf("_%d:\n",lb); | |
138 | 2176 printf("\t.long\t0x%x,0x%x\n",code_d1(value),code_d2(value)); |
82 | 2177 if (output_mode==TEXT_EMIT_MODE) { |
2178 printf(".text\n"); | |
2179 } else { | |
2180 text_mode(); | |
2181 } | |
2182 printf("\tfldl _%d\n",lb); | |
2183 } | |
2184 | |
138 | 2185 void code_dneg(int freg,int d) |
82 | 2186 { |
2187 printf("\tfchs\n"); | |
2188 } | |
81 | 2189 |
239 | 2190 void code_d2i(int reg) |
82 | 2191 { |
239 | 2192 use_int(reg); |
245 | 2193 printf("\tlea -%d(%%esp),%%esp\n",SIZE_OF_INT*2); |
82 | 2194 printf("\tfnstcw (%%esp)\n"); |
2195 printf("\tmovl (%%esp), %s\n",register_name(creg,0)); | |
2196 printf("\tmovb $12, 1(%%esp)\n"); | |
2197 printf("\tfldcw (%%esp)\n"); | |
245 | 2198 printf("\tfistpl %d(%%esp)\n",SIZE_OF_INT); |
127 | 2199 printf("\tmovl %s, (%%esp)\n",register_name(creg,0)); |
85 | 2200 printf("\tfldcw (%%esp)\n"); |
82 | 2201 printf("\tpopl %s\n",register_name(creg,0)); |
2202 printf("\tpopl %s\n",register_name(creg,0)); | |
2203 } | |
81 | 2204 |
239 | 2205 void code_i2d(int reg) |
82 | 2206 { |
2207 printf("\tpushl %s\n",register_name(creg,0)); | |
2208 printf("\tfildl (%%esp)\n"); | |
245 | 2209 printf("\tlea %d(%%esp),%%esp\n",SIZE_OF_INT); |
82 | 2210 } |
2211 | |
239 | 2212 void code_d2u(int reg) |
85 | 2213 { |
239 | 2214 use_int(reg); |
245 | 2215 printf("\tlea -%d(%%esp),%%esp\n",SIZE_OF_INT*3); |
85 | 2216 printf("\tfnstcw (%%esp)\n"); |
239 | 2217 printf("\tmovl (%%esp), %s\n",register_name(reg,0)); |
85 | 2218 printf("\tmovb $12, 1(%%esp)\n"); |
2219 printf("\tfldcw (%%esp)\n"); | |
239 | 2220 printf("\tmovl %s, (%%esp)\n",register_name(reg,0)); |
245 | 2221 printf("\tfistpll %d(%%esp)\n",SIZE_OF_INT); |
85 | 2222 printf("\tfldcw (%%esp)\n"); |
245 | 2223 printf("\tmovl %d(%%esp),%s\n",SIZE_OF_INT,register_name(reg,0)); |
2224 printf("\tlea %d(%%esp),%%esp\n",SIZE_OF_INT*3); | |
85 | 2225 } |
2226 | |
239 | 2227 void code_u2d(int reg) |
85 | 2228 { |
86 | 2229 printf("\tpushl %s\n",register_name(creg,0)); |
2230 printf("\tpushl %s\n",register_name(creg,0)); | |
245 | 2231 printf("\tmovl $0, %d(%%esp)\n",SIZE_OF_INT); |
86 | 2232 printf("\tfildll (%%esp)\n"); |
245 | 2233 printf("\tlea %d(%%esp),%%esp\n",SIZE_OF_INT*2); |
85 | 2234 } |
2235 | |
239 | 2236 void code_d2f(int reg) { } |
2237 void code_f2d(int reg) { } | |
2238 void code_f2i(int reg) { code_d2i(reg); } | |
2239 void code_f2u(int reg) { code_d2u(reg); } | |
2240 void code_i2f(int reg) { code_i2d(reg); } | |
2241 void code_u2f(int reg) { code_u2d(reg); } | |
133 | 2242 |
107 | 2243 void code_drgvar(int e2,int d,int freg) |
82 | 2244 { |
109 | 2245 printf("\t%s %s\n",fload(d),((NMTBL*)cadr(e2))->nm); |
82 | 2246 } |
81 | 2247 |
2248 | |
107 | 2249 void code_drlvar(int e2,int d,int freg) |
82 | 2250 { |
119 | 2251 printf("\t%s %d(%%ebp)\n",fload(d),lvar(e2)); |
82 | 2252 } |
2253 | |
287 | 2254 void code_cmp_drgvar(int e2,int reg,int d,int label,int cond) |
82 | 2255 { |
109 | 2256 printf("\tfcomp %s\n",((NMTBL*)cadr(e2))->nm); |
287 | 2257 jcond(label,cond); |
82 | 2258 } |
2259 | |
287 | 2260 void code_cmp_drlvar(int e2,int reg,int d,int label,int cond) |
82 | 2261 { |
119 | 2262 printf("\tfcomp %d(%%ebp)\n",lvar(e2)); |
287 | 2263 jcond(label,cond); |
82 | 2264 } |
2265 | |
225 | 2266 void dtosop(int op,int reg,int e1) |
94 | 2267 { |
82 | 2268 switch(op) { |
133 | 2269 case FADD: |
82 | 2270 case DADD: printf("\tfaddp %%st,%%st(1)\n"); break; |
133 | 2271 case FSUB: |
85 | 2272 case DSUB: printf("\tfsubp %%st,%%st(1)\n"); break; |
133 | 2273 case FDIV: |
85 | 2274 case DDIV: printf("\tfdivp %%st,%%st(1)\n"); break; |
133 | 2275 case FMUL: |
82 | 2276 case DMUL: printf("\tfmulp %%st,%%st(1)\n"); break; |
133 | 2277 case FCMP: |
89 | 2278 case DCMP: |
82 | 2279 printf("\tfucompp\n"); |
2280 printf("\tfnstsw\t%%ax\n"); | |
2281 break; | |
2282 } | |
2283 } | |
81 | 2284 |
83 | 2285 void |
225 | 2286 code_dassop(int op,int reg,int d) { |
83 | 2287 /* we have lvalue in creg, applied floating value is in %st(0) */ |
102 | 2288 emit_dpop(d); /* do nothing for 387 */ |
83 | 2289 printf("\t%s (%s)\n",fload(d),register_name(creg,0)); |
225 | 2290 dtosop(op,reg,0); |
83 | 2291 printf("\t%s (%s)\n",fstore(d),register_name(creg,0)); |
2292 } | |
2293 | |
2294 void | |
219 | 2295 code_register_dassop(int reg,int op,int d) { |
2296 error(-1); | |
2297 } | |
2298 | |
2299 void | |
107 | 2300 code_dpreinc(int e1,int e2,int d,int freg) { |
83 | 2301 g_expr(e2); |
2302 printf("\t%s (%s)\n",fload(d),register_name(creg,0)); | |
2303 printf("\tfld1\n"); | |
87 | 2304 if (caddr(e1)>0) |
83 | 2305 printf("\tfaddp %%st,%%st(1)\n"); |
2306 else | |
2307 printf("\tfsubrp %%st,%%st(1)\n"); | |
2308 printf("\t%s (%s)\n",fstore(d),register_name(creg,0)); | |
2309 } | |
2310 | |
2311 void | |
107 | 2312 code_dpostinc(int e1,int e2,int d,int freg) { |
83 | 2313 g_expr(e2); |
2314 printf("\t%s (%s)\n",fload(d),register_name(creg,0)); | |
2315 if (use) | |
86 | 2316 printf("\t%s (%s)\n",fload(d),register_name(creg,0)); |
83 | 2317 printf("\tfld1\n"); |
87 | 2318 if (caddr(e1)>0) |
83 | 2319 printf("\tfaddp %%st,%%st(1)\n"); |
2320 else | |
2321 printf("\tfsubrp %%st,%%st(1)\n"); | |
87 | 2322 printf("\t%s (%s)\n",(use?fstore_u(d):fstore(d)),register_name(creg,0)); |
83 | 2323 } |
2324 | |
291 | 2325 #define COND_BRANCH 1 |
2326 #define COND_VALUE 2 | |
2327 | |
2328 int | |
2329 drexpr0(int e1, int e2,int l1, int op,int cond,int reg,int mode) | |
84 | 2330 { |
291 | 2331 char *s; |
236 | 2332 if (!cond) { |
230 | 2333 switch(op) { |
236 | 2334 case FOP+GT: |
291 | 2335 return drexpr0(e2,e1,l1,FOP+GE,1,reg,mode); |
236 | 2336 case FOP+GE: |
291 | 2337 return drexpr0(e2,e1,l1,FOP+GT,1,reg,mode); |
236 | 2338 case FOP+EQ: |
2339 op=FOP+NEQ; break; | |
2340 case FOP+NEQ: | |
2341 op=FOP+EQ; break; | |
2342 case DOP+GT: | |
291 | 2343 return drexpr0(e2,e1,l1,DOP+GE,1,reg,mode); |
236 | 2344 case DOP+GE: |
291 | 2345 return drexpr0(e2,e1,l1,DOP+GT,1,reg,mode); |
236 | 2346 case DOP+EQ: |
2347 op=DOP+NEQ; break; | |
2348 case DOP+NEQ: | |
2349 op=DOP+EQ; break; | |
291 | 2350 default: return 0; |
230 | 2351 } |
2352 } | |
291 | 2353 s = "e"; |
84 | 2354 switch(op) { |
2355 case DOP+GE: | |
133 | 2356 case FOP+GE: |
291 | 2357 g_expr(list3(DCMP,e1,e2)); |
84 | 2358 printf("\ttestb\t$5,%%ah\n"); |
2359 break; | |
2360 case DOP+GT: | |
133 | 2361 case FOP+GT: |
291 | 2362 g_expr(list3(DCMP,e1,e2)); |
84 | 2363 printf("\ttestb\t$69,%%ah\n"); |
2364 break; | |
2365 case DOP+EQ: | |
133 | 2366 case FOP+EQ: |
291 | 2367 g_expr(list3(DCMP,e1,e2)); |
84 | 2368 printf("\tandb\t$69,%%ah\n"); |
2369 printf("\txorb\t$64,%%ah\n"); | |
2370 break; | |
2371 case DOP+NEQ: | |
133 | 2372 case FOP+NEQ: |
291 | 2373 g_expr(list3(DCMP,e1,e2)); |
84 | 2374 printf("\tandb\t$69,%%ah\n"); |
2375 printf("\txorb\t$64,%%ah\n"); | |
291 | 2376 s = "ne"; |
84 | 2377 break; |
291 | 2378 default: |
2379 return 0; | |
84 | 2380 } |
291 | 2381 if (mode==COND_BRANCH) { |
2382 printf("\tj%s\t_%d\n",s,l1); | |
2383 } else { | |
2384 use_int(reg); use_data_reg(reg,0); | |
2385 printf("\tset%s\t%s\n",s,register_name(reg,1)); | |
2386 printf("\tmovzbl\t%s,%s\n", | |
2387 register_name(reg,1),register_name(reg,0)); | |
2388 } | |
2389 return 1; | |
84 | 2390 } |
2391 | |
291 | 2392 void |
2393 drexpr(int e1, int e2,int l1, int op,int cond) | |
2394 { | |
2395 drexpr0(e1, e2,l1, op,cond,USE_CREG,COND_BRANCH); | |
2396 } | |
2397 | |
2398 static int | |
2399 drexpr_bool(int e1, int reg) | |
2400 { | |
2401 return drexpr0(cadr(e1), caddr(e1),0, car(e1),1,reg,COND_VALUE); | |
2402 } | |
2403 | |
2404 | |
94 | 2405 void |
138 | 2406 code_dregister(int e2,int freg,int d) |
94 | 2407 { |
2408 error(-1); | |
2409 } | |
2410 | |
138 | 2411 void |
287 | 2412 code_cmp_dregister(int e2,int d,int label,int cond) |
94 | 2413 { |
235 | 2414 if (e2!=USE_CREG) |
2415 error(-1); | |
236 | 2416 printf("\tfldz\n"); |
235 | 2417 printf("\tfucompp\n"); |
2418 printf("\tfnstsw\t%%ax\n"); | |
2419 printf("\tandb\t$69,%%ah\n"); | |
2420 printf("\txorb\t$64,%%ah\n"); | |
287 | 2421 jcond(label,cond); |
82 | 2422 } |
81 | 2423 |
97 | 2424 int pop_fregister() |
82 | 2425 { |
94 | 2426 if (freg_sp<0) { error(-1); return -1;} |
2427 printf("# fpop: %d\n",freg_sp-1); | |
2428 return freg_stack[--freg_sp]; | |
82 | 2429 } |
81 | 2430 |
94 | 2431 int |
138 | 2432 emit_dpop(int d) |
94 | 2433 { |
2434 int xreg; | |
97 | 2435 if ((xreg=pop_fregister())==-1) { |
94 | 2436 } else if (xreg<= -REG_LVAR_OFFSET) { |
119 | 2437 code_drlvar(REG_LVAR_OFFSET+xreg,1,freg); |
117 | 2438 free_lvar(xreg+REG_LVAR_OFFSET); |
326 | 2439 /* pushed order is reversed. We don't need this for commutable |
94 | 2440 operator, but it is ok to do this. */ |
2441 printf("\tfxch\t%%st(1)\n"); | |
2442 } | |
2443 return xreg; | |
2444 } | |
2445 | |
2446 | |
138 | 2447 void emit_dpop_free(int e1,int d) |
82 | 2448 { |
2449 } | |
81 | 2450 |
133 | 2451 void emit_dpush(int type) |
82 | 2452 { |
119 | 2453 if (freg_sp>=MAX_FPU_STACK) code_save_fstacks(); |
94 | 2454 if (freg_sp>MAX_MAX) error(-1); |
107 | 2455 freg_stack[freg_sp++]=-1; |
94 | 2456 printf("# fpush:%d\n",freg_sp); |
2457 } | |
2458 | |
195 | 2459 #endif |
2460 | |
94 | 2461 void |
2462 code_save_stacks() | |
2463 { | |
2464 /* temporal registers or stacks in fpu are saved in local variable */ | |
2465 int xreg,sp,screg; | |
2466 sp=reg_sp; | |
2467 while(sp-->0) { | |
2468 if ((xreg=reg_stack[sp])>=0) { | |
2469 screg=creg; | |
2470 if(creg!=xreg) { | |
2471 if (xreg!=dreg) free_register(xreg); | |
2472 creg = xreg; | |
2473 } | |
2474 code_assign_lvar( | |
245 | 2475 (reg_stack[sp]=new_lvar(SIZE_OF_INT)),creg,0); |
94 | 2476 reg_stack[sp]= reg_stack[sp]-REG_LVAR_OFFSET; |
2477 regv[xreg]=0; | |
2478 creg=screg; | |
2479 } | |
2480 } | |
107 | 2481 } |
2482 | |
195 | 2483 #if FLOAT_CODE |
107 | 2484 void |
2485 code_save_fstacks() | |
2486 { | |
127 | 2487 int xreg,sp,uses; |
2488 uses = use; use = 0; | |
94 | 2489 sp=freg_sp; |
2490 while(sp-->0) { | |
2491 if ((xreg=freg_stack[sp])==-1) { | |
2492 code_dassign_lvar( | |
245 | 2493 (freg_stack[sp]=new_lvar(SIZE_OF_DOUBLE)),freg,1); |
94 | 2494 freg_stack[sp]= freg_stack[sp]-REG_LVAR_OFFSET; |
2495 } | |
2496 } | |
127 | 2497 use = uses; |
82 | 2498 } |
195 | 2499 #endif |
2500 | |
2501 | |
2502 | |
2503 #if LONGLONG_CODE | |
2504 | |
2505 | |
2506 /* 64bit int part */ | |
2507 | |
237 | 2508 static void |
2509 pcond(char *s,int l1) | |
195 | 2510 { |
237 | 2511 printf("\tj%s\t_%d\n",s,l1); |
195 | 2512 } |
2513 | |
240 | 2514 void |
2515 lrexpr(int e1, int e2,int l1, int op,int cond) | |
195 | 2516 { |
280 | 2517 int l2; |
2518 code_save_stacks(); | |
237 | 2519 g_expr(e1); |
2520 emit_lpush(); | |
2521 g_expr(e2); | |
280 | 2522 // we are sure %ecx,%ebx is free |
2523 printf("\tpopl %%ecx\n"); // LSW | |
2524 printf("\tpopl %%ebx\n"); // MSW | |
2525 printf("\tsubl %%edx,%%ebx\n"); | |
2526 l2 = fwdlabel(); | |
2527 // cond==0 jump on false condtion ( if(x) => rexpr(.. cond=0 ...) ) | |
237 | 2528 switch(op) { |
2529 case LOP+GT: | |
2530 case LOP+GE: | |
280 | 2531 pcond(code_gt(1),cond?l1:l2); |
2532 pcond(code_eq(0),cond?l2:l1); | |
2533 break; | |
2534 case LOP+UGT: | |
2535 case LOP+UGE: | |
2536 pcond(code_ugt(1),cond?l1:l2); | |
2537 pcond(code_eq(0), cond?l2:l1); | |
2538 break; | |
237 | 2539 case LOP+EQ: |
280 | 2540 pcond(code_eq(0),(cond?l2:l1)); |
2541 pcond(code_eq(cond),l1); | |
2542 break; | |
237 | 2543 case LOP+NEQ: |
280 | 2544 pcond(code_eq(0),(cond?l1:l2)); |
2545 pcond(code_eq(!cond),l1); | |
2546 break; | |
237 | 2547 default: |
2548 error(-1); | |
2549 } | |
280 | 2550 printf("\tsubl %%eax,%%ecx\n"); |
2551 switch(op) { | |
2552 case LOP+GT: pcond(code_gt(cond), l1); break; | |
2553 case LOP+GE: pcond(code_ge(cond), l1); break; | |
2554 case LOP+UGT: pcond(code_ugt(cond), l1); break; | |
2555 case LOP+UGE: pcond(code_uge(cond), l1); break; | |
2556 } | |
2557 fwddef(l2); | |
195 | 2558 } |
2559 | |
2560 int emit_lpop() | |
2561 { | |
237 | 2562 return 0; |
195 | 2563 } |
2564 | |
2565 void code_lregister(int e2,int reg) | |
2566 { | |
238 | 2567 use_longlong(reg); |
239 | 2568 if (reg!=REG_L) { |
240 | 2569 printf("\tmovl %%esi,%s\n",l_eax(reg)); |
239 | 2570 printf("\tmovl %%edi,%s\n",l_edx(reg)); |
2571 } | |
195 | 2572 } |
2573 | |
287 | 2574 void code_cmp_lregister(int reg,int label,int cond) |
195 | 2575 { |
238 | 2576 char *crn; |
2577 use_int(reg); | |
2578 crn = register_name(reg,0); | |
239 | 2579 printf("\tmovl %%esi,%s\n",crn); |
2580 printf("\torl %%edi,%s\n",crn); | |
238 | 2581 printf("\ttestl %s,%s\n",crn,crn); |
287 | 2582 jcond(label,cond); |
195 | 2583 } |
2584 | |
287 | 2585 void code_cmp_lrgvar(int e1,int e2,int label,int cond) |
195 | 2586 { |
237 | 2587 char *n,*crn; |
2588 n = ((NMTBL*)cadr(e1))->nm; | |
2589 use_int(e2); | |
2590 crn = register_name(e2,0); | |
2591 printf("\tmovl %s,%s\n",n,crn); | |
2592 printf("\torl %s+4,%s\n",n,crn); | |
238 | 2593 printf("\ttestl %s,%s\n",crn,crn); |
287 | 2594 jcond(label,cond); |
195 | 2595 } |
2596 | |
287 | 2597 void code_cmp_lrlvar(int e1,int e2,int label,int cond) |
195 | 2598 { |
237 | 2599 char *crn; |
2600 use_int(e2); | |
2601 crn = register_name(e2,0); | |
239 | 2602 printf("\tmovl %d(%%ebp),%s\n",lvar(e1),crn); |
2603 printf("\torl %d(%%ebp),%s\n",lvar(e1)+4,crn); | |
2604 printf("\ttestl %s,%s\n",crn,crn); | |
287 | 2605 jcond(label,cond); |
195 | 2606 } |
2607 | |
2608 void code_lassign(int e1,int e2) | |
2609 { | |
237 | 2610 char *rn; |
2611 // e1 = e2 | |
2612 use_longlong(e2); | |
239 | 2613 rn = register_name(e1,0); |
2614 printf("\tmovl %s,(%s)\n",l_eax(e2),rn); | |
2615 printf("\tmovl %s,4(%s)\n",l_edx(e2),rn); | |
195 | 2616 } |
2617 | |
2618 void code_lassign_gvar(int e1,int e2) | |
2619 { | |
239 | 2620 char *n; |
237 | 2621 n = ((NMTBL*)cadr(e1))->nm; |
2622 use_longlong(e2); | |
239 | 2623 printf("\tmovl %s,%s\n",l_eax(e2),n); |
2624 printf("\tmovl %s,%s+4\n",l_edx(e2),n); | |
195 | 2625 } |
2626 | |
2627 void code_lassign_lvar(int e1,int e2) | |
2628 { | |
237 | 2629 use_longlong(e2); |
239 | 2630 printf("\tmovl %s,%d(%%ebp)\n",l_eax(e2),lvar(e1)); |
2631 printf("\tmovl %s,%d(%%ebp)\n",l_edx(e2),lvar(e1)+4); | |
195 | 2632 } |
2633 | |
2634 void code_lassign_lregister(int e2,int reg) | |
2635 { | |
242 | 2636 // e2 = reg |
238 | 2637 use_longlong(reg); |
239 | 2638 if (e2!=reg) { |
242 | 2639 printf("\tmovl %s,%s\n",l_eax(reg),l_eax(e2)); |
2640 printf("\tmovl %s,%s\n",l_edx(reg),l_edx(e2)); | |
239 | 2641 } |
237 | 2642 } |
195 | 2643 |
237 | 2644 void |
2645 code_lconst(int e1,int creg) | |
2646 { | |
2647 use_longlong(creg); | |
239 | 2648 printf("\tmovl $%d,%s\n",code_l1(lcadr(e1)),l_eax(creg)); |
2649 printf("\tmovl $%d,%s\n",code_l2(lcadr(e1)),l_edx(creg)); | |
195 | 2650 } |
2651 | |
212 | 2652 void code_lneg(int e1) |
195 | 2653 { |
239 | 2654 use_longlong(e1); |
2655 printf("\tnegl %s\n",l_eax(e1)); | |
2656 printf("\tadcl $0,%s\n",l_edx(e1)); | |
2657 printf("\tnegl %s\n",l_edx(e1)); | |
195 | 2658 } |
2659 | |
2660 void code_lrgvar(int e1,int e2) | |
2661 { | |
239 | 2662 char *n; |
237 | 2663 n = ((NMTBL*)cadr(e1))->nm; |
2664 use_longlong(e2); | |
239 | 2665 printf("\tmovl %s,%s\n",n,l_eax(e2)); |
2666 printf("\tmovl %s+4,%s\n",n,l_edx(e2)); | |
195 | 2667 } |
2668 | |
2669 void code_lrlvar(int e1,int e2) | |
2670 { | |
237 | 2671 use_longlong(e2); |
239 | 2672 printf("\tmovl %d(%%ebp),%s\n",lvar(e1),l_eax(e2)); |
2673 printf("\tmovl %d(%%ebp),%s\n",lvar(e1)+4,l_edx(e2)); | |
195 | 2674 } |
2675 | |
242 | 2676 #define check_lreg(reg) if (reg==REG_L) code_lassign_lregister(reg,REG_LCREG) |
239 | 2677 |
240 | 2678 void |
2679 ltosop(int op,int reg,int e2) | |
195 | 2680 { |
237 | 2681 char *opl,*oph,*call; |
2682 int lb; | |
195 | 2683 |
239 | 2684 // e2 (operand) is on the top of the stack |
237 | 2685 use_longlong(reg); |
2686 opl = 0; call=0; | |
313 | 2687 stack_depth -= SIZE_OF_INT * 2; |
237 | 2688 |
2689 switch(op) { | |
2690 case LLSHIFT: | |
2691 case LULSHIFT: | |
239 | 2692 printf("\tmovl %%ecx,4(%%esp)\n"); |
2693 printf("\tpopl %%ecx\n"); | |
237 | 2694 printf("\tshldl %%eax,%%edx\n"); |
2695 printf("\tsall %%cl,%%eax\n"); | |
2696 printf("\ttestb $32,%%cl\n"); | |
2697 printf("\tje\t_%d\n",(lb=fwdlabel())); | |
2698 printf("\tmovl %%eax,%%edx\n"); | |
2699 printf("\txorl %%eax,%%eax\n"); | |
2700 fwddef(lb); | |
2701 printf("\tpopl %%ecx\n"); | |
242 | 2702 check_lreg(reg); |
237 | 2703 return; |
2704 case LRSHIFT: | |
239 | 2705 printf("\tmovl %%ecx,4(%%esp)\n"); |
2706 printf("\tpopl %%ecx\n"); | |
240 | 2707 printf("\tshrdl %%edx,%%eax\n"); |
237 | 2708 printf("\tsarl %%cl,%%eax\n"); |
2709 printf("\ttestb $32,%%cl\n"); | |
2710 printf("\tje\t_%d\n",(lb=fwdlabel())); | |
2711 printf("\tmovl %%edx,%%eax\n"); | |
2712 printf("\tsarl $31,%%edx\n"); | |
2713 fwddef(lb); | |
2714 printf("\tpopl %%ecx\n"); | |
242 | 2715 check_lreg(reg); |
237 | 2716 return; |
2717 case LURSHIFT: | |
239 | 2718 printf("\tmovl %%ecx,4(%%esp)\n"); |
2719 printf("\tpopl %%ecx\n"); | |
240 | 2720 printf("\tshrdl %%edx,%%eax\n"); |
237 | 2721 printf("\tshrl %%cl,%%eax\n"); |
2722 printf("\ttestb $32,%%cl\n"); | |
2723 printf("\tje\t_%d\n",(lb=fwdlabel())); | |
2724 printf("\tmovl %%edx,%%eax\n"); | |
2725 printf("\txorl %%edx,%%edx\n"); | |
2726 fwddef(lb); | |
2727 printf("\tpopl %%ecx\n"); | |
242 | 2728 check_lreg(reg); |
237 | 2729 return; |
2730 } | |
2731 switch(op) { | |
239 | 2732 case LADD: opl="addl";oph="adcl"; break; |
2733 case LSUB: opl="subl";oph="sbbl"; break; | |
237 | 2734 case LBAND: opl=oph="andl"; break; |
2735 case LEOR: opl=oph="xorl"; break; | |
2736 case LBOR: opl=oph="orl"; break; | |
2737 case LMUL: | |
2738 case LUMUL: | |
239 | 2739 printf("\tpushl %%edx\n"); |
2740 printf("\tpushl %%eax\n"); | |
2741 printf("\tpushl %%ecx\n"); | |
242 | 2742 // 0 saved ecx |
237 | 2743 // 4 c_l |
2744 // 8 c_h | |
2745 // 12 o_l | |
2746 // 16 o_h | |
2747 printf("\tmull 12(%%esp)\n"); // c_l*o_l -> %edx,%eax | |
2748 printf("\tmovl 4(%%esp),%%ecx\n"); // c_l->%ecx | |
2749 printf("\timull 16(%%esp),%%ecx\n"); // c_l*o_h->%ecx | |
239 | 2750 printf("\taddl %%ecx,%%edx\n"); // %edx+%ecx->%edx |
237 | 2751 printf("\tmovl 8(%%esp),%%ecx\n"); // c_h->%ecx |
2752 printf("\timull 12(%%esp),%%ecx\n"); // c_h*o_l->%ecx | |
239 | 2753 printf("\taddl %%ecx,%%edx\n"); // %edx+%ecx->%edx |
237 | 2754 printf("\tpopl %%ecx\n"); |
242 | 2755 // printf("\taddl $8,%%esp\n"); |
2756 printf("\tlea 16(%%esp),%%esp\n"); | |
237 | 2757 return; |
2758 case LDIV: call="__divdi3"; break; | |
2759 case LUDIV: call="__udivdi3"; break; | |
2760 case LMOD: call="__moddi3"; break; | |
2761 case LUMOD: call="__umoddi3"; break; | |
2762 default: error(-1); | |
2763 } | |
2764 if (opl) { | |
2765 printf("\t%s (%%esp),%%eax\n\t%s 4(%%esp),%%edx\n",opl,oph); | |
242 | 2766 printf("\tlea 8(%%esp),%%esp\n"); |
2767 check_lreg(reg); | |
239 | 2768 } else if (call) { |
2769 printf("\tpushl %%edx\n"); | |
2770 printf("\tpushl %%eax\n"); | |
237 | 2771 printf("\tcall %s\n",call); |
242 | 2772 // printf("\taddl $8,%%esp\n"); |
2773 printf("\tlea 16(%%esp),%%esp\n"); | |
2774 check_lreg(reg); | |
239 | 2775 } else { |
2776 error(-1); | |
237 | 2777 } |
195 | 2778 } |
2779 | |
237 | 2780 int code_lconst_op_p(int op,int e) { |
240 | 2781 long long l; |
2782 if (car(e)==CONST) l = cadr(e); | |
2783 else if (car(e)==LCONST) l = lcadr(e); | |
2784 else return 0; | |
2785 | |
237 | 2786 switch(op) { |
2787 case LLSHIFT: | |
2788 case LULSHIFT: | |
2789 case LRSHIFT: | |
2790 case LURSHIFT: | |
2791 return (0<=l&&l<=32); | |
2792 case LADD: | |
2793 case LSUB: | |
239 | 2794 case LBAND: |
237 | 2795 case LEOR: |
2796 case LBOR: | |
2797 return 1; | |
2798 default: | |
2799 return 0; | |
2800 } | |
2801 } | |
2802 | |
2803 void loprtc(int op,int reg,int e) { | |
2804 char *opl,*oph; | |
240 | 2805 int vl; |
2806 int vh; | |
2807 long long l; | |
2808 | |
2809 if (car(e)==CONST) l = cadr(e); | |
2810 else if (car(e)==LCONST) l = lcadr(e); | |
2811 else error(-1); | |
2812 | |
2813 vl = code_l1(l); | |
2814 vh = code_l2(l); | |
237 | 2815 |
2816 use_longlong(reg); | |
2817 opl = 0; | |
2818 | |
2819 switch(op) { | |
2820 case LLSHIFT: | |
2821 case LULSHIFT: | |
286 | 2822 printf("\tshldl $%d,%s,%s\n",vl,l_eax(reg),l_edx(reg)); |
2823 printf("\tsall $%d,%s\n",vl,l_eax(reg)); | |
237 | 2824 return; |
2825 case LRSHIFT: | |
286 | 2826 printf("\tshrdl $%d,%s,%s\n",vl,l_edx(reg),l_eax(reg)); |
2827 printf("\tsarl $%d,%s\n",vl,l_edx(reg)); | |
237 | 2828 return; |
2829 case LURSHIFT: | |
286 | 2830 printf("\tshrdl $%d,%s,%s\n",vl,l_edx(reg),l_eax(reg)); |
2831 printf("\tshrl $%d,%s\n",vl,l_edx(reg)); | |
237 | 2832 return; |
2833 } | |
2834 switch(op) { | |
2835 case LADD: opl="addl";oph="adcl"; break; | |
239 | 2836 case LSUB: opl="subl";oph="sbbl"; break; |
237 | 2837 case LEOR: opl=oph="xorl"; break; |
2838 case LBOR: opl=oph="orl"; break; | |
313 | 2839 case LBAND: opl=oph="andl"; break; |
237 | 2840 default: error(-1); |
2841 } | |
286 | 2842 printf("\t%s $%d,%s\n\t%s $%d,%s\n",opl,vl,l_eax(reg),oph,vh,l_edx(reg)); |
237 | 2843 } |
213 | 2844 |
195 | 2845 void emit_lpop_free(int e1) |
2846 { | |
242 | 2847 // printf("\taddl $8,%%esp\n"); |
195 | 2848 } |
2849 | |
2850 void emit_lpush() | |
2851 { | |
313 | 2852 stack_depth += SIZE_OF_INT * 2; |
241 | 2853 printf("\tpushl %%edx\n\tpushl %%eax\n"); |
195 | 2854 } |
2855 | |
239 | 2856 void code_i2ll(int reg) |
195 | 2857 { |
240 | 2858 int reg0 = USE_CREG; |
2859 use_register(creg,REG_EAX,1); | |
2860 regv[creg]=0; | |
2861 use_longlong(reg0); | |
237 | 2862 printf("\tcltd\n"); |
242 | 2863 check_lreg(reg); |
240 | 2864 lreg = creg = reg0; |
195 | 2865 } |
2866 | |
239 | 2867 void code_i2ull(int reg) |
195 | 2868 { |
239 | 2869 code_i2ll(reg); |
195 | 2870 } |
2871 | |
239 | 2872 void code_u2ll(int reg) |
195 | 2873 { |
240 | 2874 int reg0 = USE_CREG; |
2875 use_register(creg,REG_EAX,1); | |
2876 regv[creg]=0; | |
2877 use_longlong(reg0); | |
237 | 2878 printf("\txorl %%edx,%%edx\n"); |
242 | 2879 check_lreg(reg); |
240 | 2880 lreg = creg = reg0; |
195 | 2881 } |
2882 | |
239 | 2883 void code_u2ull(int reg) |
195 | 2884 { |
239 | 2885 code_u2ll(reg); |
195 | 2886 } |
2887 | |
239 | 2888 void code_ll2i(int reg) |
195 | 2889 { |
239 | 2890 use_int(reg); |
237 | 2891 if (virtual(REG_EAX)!=reg) |
2892 printf("\tmovl %%eax,%s\n",register_name(creg,0)); | |
195 | 2893 } |
2894 | |
239 | 2895 void code_ll2u(int reg) |
195 | 2896 { |
239 | 2897 code_ll2i(reg); |
195 | 2898 } |
2899 | |
239 | 2900 void code_ull2i(int reg) |
195 | 2901 { |
239 | 2902 code_ll2i(reg); |
195 | 2903 } |
2904 | |
239 | 2905 void code_ull2u(int reg) |
195 | 2906 { |
239 | 2907 code_ll2i(reg); |
195 | 2908 } |
2909 | |
2910 #if FLOAT_CODE | |
239 | 2911 void code_d2ll(int reg) |
195 | 2912 { |
239 | 2913 use_longlong(reg); |
237 | 2914 printf("\tsubl $40,%%esp\n"); |
2915 printf("\tfnstcw 2(%%esp)\n"); | |
2916 printf("\tmovw 2(%%esp),%%ax\n"); | |
2917 printf("\torw $3072,%%ax\n"); | |
2918 printf("\tmovw %%ax,0(%%esp)\n"); | |
2919 printf("\tfldcw 0(%%esp)\n"); | |
2920 printf("\tfistpll 12(%%esp)\n"); | |
2921 printf("\tfldcw 2(%%esp)\n"); | |
239 | 2922 printf("\tmovl 12(%%esp),%%eax\n"); |
2923 printf("\tmovl 16(%%esp),%%edx\n"); | |
237 | 2924 printf("\taddl $40,%%esp\n"); |
195 | 2925 } |
2926 | |
239 | 2927 void code_d2ull(int reg) |
195 | 2928 { |
239 | 2929 use_longlong(reg); |
237 | 2930 printf("\tsubl $16,%%esp\n"); |
2931 printf("\tfstpl (%%esp)\n"); | |
2932 printf("\tcall __fixunsdfdi\n"); | |
2933 printf("\taddl $16,%%esp\n"); | |
195 | 2934 } |
2935 | |
239 | 2936 void code_f2ll(int reg) |
195 | 2937 { |
239 | 2938 code_d2ll(reg); |
195 | 2939 } |
2940 | |
239 | 2941 void code_f2ull(int reg) |
195 | 2942 { |
239 | 2943 use_longlong(reg); |
237 | 2944 printf("\tsubl $16,%%esp\n"); |
242 | 2945 printf("\tfstps (%%esp)\n"); |
237 | 2946 printf("\tcall __fixunssfdi\n"); |
2947 printf("\taddl $16,%%esp\n"); | |
195 | 2948 } |
2949 | |
239 | 2950 void code_ll2d(int reg) |
195 | 2951 { |
237 | 2952 printf("\tsubl $8,%%esp\n"); |
2953 printf("\tmovl %%eax,(%%esp)\n"); | |
2954 printf("\tmovl %%edx,4(%%esp)\n"); | |
2955 printf("\tfildll (%%esp)\n"); | |
2956 printf("\taddl $8,%%esp\n"); | |
195 | 2957 } |
2958 | |
239 | 2959 void code_ll2f(int reg) |
195 | 2960 { |
239 | 2961 code_ll2d(reg); |
195 | 2962 } |
2963 | |
239 | 2964 void code_ull2d(int reg) |
195 | 2965 { |
239 | 2966 code_ll2d(reg); |
195 | 2967 } |
2968 | |
239 | 2969 void code_ull2f(int reg) |
195 | 2970 { |
239 | 2971 code_ll2d(reg); |
195 | 2972 } |
2973 | |
2974 #endif | |
2975 | |
2976 | |
2977 void code_lpreinc(int e1,int e2,int reg) | |
2978 { | |
238 | 2979 int dir = caddr(e1); |
2980 int creg0; | |
2981 char *crn; | |
2982 if (car(e2)==LREGISTER) { | |
2983 use_longlong(reg); | |
239 | 2984 printf("\taddl $%d,%%esi\n",dir); |
2985 printf("\tadcl $%d,%%edi\n",dir>0?0:-1); | |
2986 if (reg!=REG_L) { | |
2987 code_lregister(REG_L,reg); | |
2988 } | |
238 | 2989 return; |
2990 } | |
2991 g_expr(e2); | |
2992 crn = register_name(creg0=creg,0); | |
2993 printf("\taddl $%d,(%s)\n",dir,crn); | |
239 | 2994 printf("\tadcl $%d,4(%s)\n",dir>0?0:-1,crn); |
238 | 2995 use_longlong(reg); |
239 | 2996 lload(creg0,0,reg); |
195 | 2997 } |
2998 | |
2999 void code_lpostinc(int e1,int e2,int reg) | |
3000 { | |
238 | 3001 int dir = caddr(e1); |
3002 int creg0; | |
3003 char *crn; | |
3004 if (car(e2)==LREGISTER) { | |
3005 use_longlong(reg); | |
239 | 3006 if (reg!=REG_L) { |
3007 code_lregister(REG_L,reg); | |
3008 } | |
3009 printf("\taddl $%d,%%esi\n",dir); | |
3010 printf("\tadcl $%d,%%edi\n",dir>0?0:-1); | |
238 | 3011 return; |
3012 } | |
3013 g_expr(e2); | |
3014 crn = register_name(creg0=creg,0); | |
3015 printf("\taddl $%d,(%s)\n",dir,crn); | |
239 | 3016 printf("\tadcl $%d,4(%s)\n",dir>0?0:-1,crn); |
238 | 3017 use_longlong(reg); |
239 | 3018 lload(creg0,0,reg); |
3019 printf("\taddl $%d,%s\n",-dir,l_eax(reg)); | |
3020 printf("\tadcl $%d,%s\n",-dir>0?0:-1,l_edx(reg)); | |
195 | 3021 } |
3022 | |
225 | 3023 void code_lassop(int op,int reg) |
195 | 3024 { |
238 | 3025 error(-1); |
195 | 3026 } |
3027 | |
219 | 3028 void |
3029 code_register_lassop(int reg,int op) { | |
238 | 3030 error(-1); |
219 | 3031 } |
3032 | |
195 | 3033 |
3034 #endif | |
81 | 3035 |
301 | 3036 |
3037 | |
3038 | |
3039 | |
3040 #if CASE_CODE | |
3041 | |
3042 int | |
3043 code_table_jump_p() { return 1; } | |
3044 | |
3045 void | |
302 | 3046 code_table_jump(int l,int csvalue,int delta,int max,int min,int dlabel) |
301 | 3047 { |
3048 char *crn; | |
3049 use_register(creg,csvalue,0); | |
3050 crn = register_name(creg,0); | |
3051 printf("\tsubl\t$%d,%s\n",min,crn); | |
302 | 3052 printf("\tcmpl\t$%d,%s\n",max-min,crn); |
3053 printf("\tja\t_%d\n",dlabel); | |
3054 if (delta==1) { | |
3055 printf("\tjmp\t*_%d(,%s,4)\n",l,crn); | |
3056 return; | |
3057 } | |
3058 use_register(creg,REG_EAX,1); | |
3059 edx_setup(-1); | |
301 | 3060 switch(delta) { |
302 | 3061 case 2: |
3062 printf("\tmovl\t$1,%%edx\n"); | |
320 | 3063 printf("\tandl\t%%eax,%%edx\n"); |
302 | 3064 printf("\tjne\t_%d\n",dlabel); |
3065 printf("\tjmp\t*_%d(,%%eax,2)\n",l); break; | |
3066 case 4: | |
3067 printf("\tmovl\t$3,%%edx\n"); | |
320 | 3068 printf("\tandl\t%%eax,%%edx\n"); |
302 | 3069 printf("\tjne\t_%d\n",dlabel); |
3070 printf("\tjmp\t*_%d(%%eax)\n",l); break; | |
301 | 3071 default: |
302 | 3072 printf("\tmovl $%d,%%ecx\n",delta); |
3073 printf("\txor %%edx,%%edx\n\tdivl %%ecx\n"); | |
3074 printf("\tandl\t%%edx,%%edx\n"); | |
3075 printf("\tjne\t_%d\n",dlabel); | |
3076 printf("\tjmp\t*_%d(,%%eax,4)\n",l); break; | |
301 | 3077 } |
302 | 3078 edx_cleanup(); |
301 | 3079 } |
3080 | |
3081 void | |
3082 code_table_open(int l) | |
3083 { | |
3084 output_mode=DATA_EMIT_MODE; | |
3085 printf(" \t.section\t.rodata\n\t.align 4\n"); | |
3086 fwddef(l); | |
3087 } | |
3088 | |
3089 void | |
3090 code_table_value(int label,int table_top) | |
3091 { | |
3092 printf("\t.long _%d\n",label); | |
3093 } | |
3094 | |
3095 void | |
3096 code_table_close() | |
3097 { | |
3098 text_mode(); | |
3099 } | |
3100 | |
3101 #endif | |
3102 | |
3103 | |
320 | 3104 #if ASM_CODE |
3105 | |
3106 /* | |
3107 print an operand | |
3108 */ | |
3109 | |
3110 static void | |
3111 emit_asm_operand(int rstr) | |
3112 { | |
3113 if (car(rstr)==REGISTER) { | |
3114 printf("%s",register_name(cadr(rstr),0)); | |
3115 } else if (car(rstr)==CONST) { | |
3116 printf("%d",cadr(rstr)); | |
3117 } else if (car(rstr)==FNAME) { | |
3118 printf("%s",(char*)cadr(rstr)); | |
3119 } else if (car(rstr)==STRING) { | |
3120 printf("_%d",cadr(rstr)); | |
3121 } else { | |
3122 error(-1); | |
3123 } | |
3124 } | |
3125 | |
3126 /* | |
3127 prepare asm operands | |
3128 | |
326 | 3129 char *constraints string |
3130 int operand expr | |
320 | 3131 int mode (ASM_INPUT,ASM_OUTPUT) |
3132 int replacement list | |
3133 int output operands count | |
3134 int output operands replacement list | |
3135 | |
3136 retrun replacement list | |
3137 list3( operands, next, clobber ) | |
3138 0 can be shared in input/output | |
3139 1 can't be used in input | |
3140 */ | |
3141 | |
3142 int | |
328 | 3143 code_asm_operand(char *p,int e1,int mode,int repl,int n,int repl0) |
320 | 3144 { |
3145 int r; | |
3146 int c; | |
3147 int val; | |
3148 int clobber = 0; | |
3149 | |
3150 printf("# constraint %s\n",p); | |
3151 if (*p=='=') { | |
3152 // output register | |
3153 p++; | |
3154 } | |
3155 if (*p=='&') { | |
3156 // earlyclobber | |
3157 p++; | |
3158 clobber = 1; | |
3159 } | |
3160 c = *p; | |
3161 if (c=='r') { | |
3162 if (mode==ASM_INPUT) { | |
3163 for(;repl0;repl0 = cadr(repl0)) { | |
3164 if (car(car(repl0))==REGISTER && caddr(repl0)==0) { | |
3165 r = cadr(car(repl0)); | |
3166 caddr(repl0) = ASM_USED; | |
3167 break; | |
3168 } | |
3169 } | |
3170 r = get_register(); | |
3171 } else { | |
3172 r = get_register(); | |
3173 } | |
3174 repl = list3(list2(REGISTER,r),repl,clobber); | |
3175 } else if (c=='m') { | |
3176 repl = list3(list2(0,0),repl,clobber); | |
3177 } else if (c=='i') { | |
3178 if (car(e1)==GVAR||car(e1)==FNAME) { | |
3179 e1=list3(FNAME,(int)(((NMTBL *)cadr(e1))->nm),0); | |
3180 } else if (car(e1)==STRING) { | |
3181 val = emit_string_label(); | |
3182 ascii((char*)cadr(e1)); | |
3183 e1=list3(STRING,val,0); | |
3184 } else if (car(e1)==CONST) { | |
3185 } else error(-1); | |
3186 repl = list3(e1,repl,clobber); | |
3187 } else if (digit(c)) { | |
3188 val = 0; | |
3189 do { val = val*10 + c-'0'; } while (digit(c=*p++)); | |
3190 if (val>MAX_ASM_REG) error(-1); // too large register | |
3191 if (n-val<0) error(-1); | |
3192 repl = list3(car(nth(n-val-1,repl0)),repl,clobber); | |
3193 } else error(-1); | |
3194 return repl; | |
3195 } | |
3196 | |
3197 void | |
328 | 3198 code_free_asm_operand(int repl) |
320 | 3199 { |
3200 for(;repl;repl=cadr(repl)) { | |
3201 if (car(car(repl))==REGISTER) | |
3202 free_register(cadr(car(repl))); | |
3203 } | |
3204 } | |
3205 | |
3206 | |
3207 extern void | |
328 | 3208 code_asm(char *asm_str,int repl) |
320 | 3209 { |
3210 int c,i,rstr,val; | |
3211 char *p; | |
3212 int reg[MAX_ASM_REG]; | |
3213 | |
3214 text_mode(); | |
3215 c = *asm_str; | |
3216 if (c!='\t'&&c!=' ') printf("\t"); | |
3217 for(i=0;repl && i<MAX_ASM_REG;i++) { | |
3218 reg[i] = car(repl); | |
3219 repl = cadr(repl); | |
3220 } | |
3221 p = asm_str; | |
3222 while((c = *p++)) { | |
3223 if (c=='%') { | |
3224 c = *p++; | |
3225 if (!c) { break; | |
3226 } else if (c=='%') { | |
3227 printf("%%"); continue; | |
3228 } else if (!digit(c)) { | |
3229 printf("%%%c",c); continue; | |
3230 } | |
3231 val = 0; | |
3232 do { val = val*10 + c-'0'; } while (digit(c=*p++)) ; | |
3233 p--; | |
3234 if (val>MAX_ASM_REG) error(-1); // too large register | |
3235 rstr = reg[val]; | |
3236 emit_asm_operand(rstr); | |
3237 } else { | |
3238 printf("%c",c); | |
3239 } | |
3240 } | |
3241 printf("\n"); | |
3242 } | |
3243 | |
3244 #endif | |
3245 | |
3246 | |
336 | 3247 #if BIT_FIELD_CODE |
3248 | |
3249 /* bit field alignment calcuration */ | |
3250 | |
3251 static void | |
3252 set_bitsz(int type,int *psign,int *pbitsz,int *palign,int *pl) | |
3253 { | |
3254 int sign=0,bitsz; | |
3255 int align,l=0; | |
3256 switch(cadr(type)) { | |
3257 case INT: sign=1; bitsz=32; align=4;break; | |
3258 case UNSIGNED: bitsz=32; align=4;break; | |
3259 case CHAR: sign=1; bitsz= 8; align=1;break; | |
3260 case UCHAR: bitsz= 8; align=1;break; | |
3261 case SHORT: sign=1; bitsz=16; align=2;break; | |
3262 case USHORT: sign=1; bitsz=16; align=2;break; | |
3263 case LONGLONG: sign=1; bitsz=64; align=4;l=1; break; | |
3264 case ULONGLONG: bitsz=64; align=4;l=1; break; | |
3265 default: error(-1); | |
3266 } | |
3267 *psign = sign; | |
3268 *pbitsz = bitsz; | |
3269 *palign = align; | |
3270 *pl = l; | |
3271 } | |
3272 | |
3273 /* | |
3274 bit field alignment calcuration | |
3275 this is architecture depenedent | |
3276 */ | |
3277 | |
3278 extern int | |
3279 code_bit_field_disp(int type,int *poffset,int *bfd,int *sz) | |
3280 { | |
3281 int sign,bitsz,align; | |
3282 int i; | |
3283 int bitpos = *bfd; | |
3284 int offset = *poffset; | |
3285 int l; | |
3286 int bitsize = cadddr(type); | |
3287 set_bitsz(type,&sign,&bitsz,&align,&l); | |
3288 | |
3289 if (bitsize>bitsz) { error(BTERR); bitsize = i; } | |
3290 | |
3291 /* bfd means previous bit field bit offset */ | |
3292 if (bitpos) { | |
3293 /* previous field is bit field and spaces may remain */ | |
3294 /* calc previsous offset */ | |
3295 | |
3296 i= offset-(bitpos+7)/8; | |
3297 | |
3298 for(l = bitpos;l>0;l -= 8,i++) { | |
3299 if ((i & (align-1))==0 && l+bitsize <= bitsz) { | |
3300 /* alignment is correct and space remains */ | |
3301 *poffset=offset=i; | |
3302 i = l+bitsize; | |
3303 *bfd = i; | |
3304 *sz = (i+7)/8; | |
338 | 3305 // printf("# bitpos=%d bitsize=%d bitsz=%d offset=%d\n",l,bitsize,bitsz,*poffset); |
336 | 3306 return l; |
3307 } | |
3308 } | |
3309 } | |
3310 | |
3311 /* first bit-field */ | |
3312 | |
3313 if ((i=(offset & (align-1)))) { | |
3314 *poffset = (offset += (align-i)); | |
3315 } | |
3316 bitpos = 0; | |
3317 *bfd = bitsize; | |
3318 *sz = (bitsize+7)/8; | |
3319 | |
338 | 3320 // printf("# bitpos=%d bitsize=%d bitsz=%d offset=%d\n",bitpos,bitsize,bitsz,*poffset); |
336 | 3321 return bitpos; |
3322 } | |
3323 | |
3324 /* bit field value */ | |
3325 | |
3326 /* reg contains container value, result should be in reg */ | |
3327 extern void | |
3328 code_bit_field(int type,int bitpos,int reg) | |
3329 { | |
3330 int sign,bitsz,l,align; | |
3331 int bitsize = cadddr(type); | |
3332 int i; | |
3333 set_bitsz(type,&sign,&bitsz,&align,&l); | |
338 | 3334 // printf("# %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); |
336 | 3335 /* this implementation returns -1 for int i:1; */ |
3336 if (l==1) { | |
3337 use_longlong(reg); | |
3338 /* shift left */ | |
338 | 3339 if ((i=bitsz-bitsize-bitpos)) |
3340 loprtc(LLSHIFT,reg,list2(CONST,i)); | |
336 | 3341 /* shift right */ |
3342 if ((i=bitsz-bitsize)) | |
3343 loprtc(sign?LRSHIFT:LURSHIFT,reg,list2(CONST,i)); | |
3344 } else { | |
3345 use_int(reg); | |
3346 /* shift left */ | |
338 | 3347 if ((i=32-bitsize-bitpos)) |
336 | 3348 oprtc(LSHIFT,reg,list2(CONST,i)); |
3349 /* shift right */ | |
338 | 3350 if ((i=32-bitsize)) |
336 | 3351 oprtc(sign?RSHIFT:URSHIFT,reg,list2(CONST,i)); |
3352 } | |
3353 } | |
3354 | |
3355 /* bit field replacement */ | |
3356 | |
3357 static void | |
338 | 3358 make_mask_and_or(int mask,int reg,int lreg) |
336 | 3359 { |
3360 printf("# mask 0x%08x ~0x%08x\n",mask,~mask); | |
338 | 3361 printf("\tpushl %s\n",register_name(reg,0)); |
336 | 3362 /* make and-mask */ |
338 | 3363 oprtc(BOR,reg,list2(CONST,~mask)); |
336 | 3364 /* do conjunction */ |
338 | 3365 if (lreg==-1) { |
3366 printf("\tandl %s,4(%%esp)\n",register_name(reg,0)); | |
3367 } else if (lreg==-2) { | |
3368 printf("\tandl %s,8(%%esp)\n",register_name(reg,0)); | |
3369 } else { | |
3370 printf("\tandl %s,%s\n",register_name(reg,0),register_name(lreg,0)); | |
3371 } | |
336 | 3372 /* make or-mask */ |
338 | 3373 printf("\tpopl %s\n",register_name(reg,0)); |
3374 oprtc(BAND,reg,list2(CONST,mask)); | |
336 | 3375 /* do disjunction */ |
338 | 3376 if (lreg==-1) { |
3377 printf("\torl %s,0(%%esp)\n",register_name(reg,0)); | |
3378 } else if (lreg==-2) { | |
3379 printf("\torl %s,4(%%esp)\n",register_name(reg,0)); | |
3380 } else { | |
3381 printf("\torl %s,%s\n",register_name(reg,0),register_name(lreg,0)); | |
3382 printf("\txchg %s,%s\n",register_name(reg,0),register_name(lreg,0)); | |
3383 } | |
336 | 3384 } |
3385 | |
3386 extern void | |
3387 code_bit_replace(int value,int lvalue,int type,int bitpos) | |
3388 { | |
3389 int sign,bitsz,l,align; | |
3390 int bitsize = cadddr(type); | |
3391 int mask = 0; | |
3392 set_bitsz(type,&sign,&bitsz,&align,&l); | |
3393 // printf("# %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); | |
3394 if (l) { | |
3395 use_longlong(value); | |
3396 /* shift left */ | |
338 | 3397 if (bitpos) |
3398 loprtc(LLSHIFT,value,list2(CONST,bitpos)); | |
336 | 3399 if (bitpos+bitsize>=32) { |
338 | 3400 /* make and-mask upper */ |
3401 mask = make_mask(64-bitpos-bitsize,bitpos>=32?63-bitpos:31); | |
3402 make_mask_and_or(mask,virtual(value==REG_L?REG_EDI:REG_EDX),-2); | |
336 | 3403 } |
3404 if (bitpos<32) { | |
338 | 3405 /* make and-mask lower */ |
3406 mask = make_mask(bitpos+bitsize>=32?0:32-bitpos-bitsize,31-bitpos); | |
3407 make_mask_and_or(mask,virtual(value==REG_L?REG_ESI:REG_EAX),-1); | |
336 | 3408 } |
338 | 3409 printf("\tpopl %s\n",l_eax(value)); |
3410 printf("\tpopl %s\n",l_edx(value)); | |
336 | 3411 } else { |
3412 use_int(value); | |
3413 /* shift left */ | |
338 | 3414 if (bitpos) |
3415 oprtc(LSHIFT,value,list2(CONST,bitpos)); | |
336 | 3416 /* make and-mask */ |
338 | 3417 mask = make_mask(32-bitpos-bitsize,31-bitpos); |
3418 make_mask_and_or(mask,value,lvalue); | |
336 | 3419 } |
3420 } | |
3421 | |
3422 #endif | |
3423 | |
61 | 3424 /* end */ |