Mercurial > hg > CbC > old > device
comparison mc-code-powerpc.c @ 89:917947ffeb7c
power pc version
author | kono |
---|---|
date | Thu, 06 Mar 2003 23:47:42 +0900 |
parents | |
children | 07e3113c3c13 |
comparison
equal
deleted
inserted
replaced
88:5c8553d7f984 | 89:917947ffeb7c |
---|---|
1 /* Micro-C Code Generatation Part for Power PC (Mac OS X) */ | |
2 /* $Id$ */ | |
3 | |
4 #define EXTERN extern | |
5 #include "mc.h" | |
6 #include "mc-codegen.h" | |
7 | |
8 #define TEXT_EMIT_MODE 0 | |
9 #define DATA_EMIT_MODE 1 | |
10 #define RODATA_EMIT_MODE 2 | |
11 | |
12 static int output_mode = TEXT_EMIT_MODE; | |
13 static int data_alignment = 0; | |
14 | |
15 static int code_disp_label; | |
16 static int func_disp_label; | |
17 | |
18 /* | |
19 -16 -8 local2 <-- r30 | |
20 -12 -4 local1 | |
21 -8 8 arg3 | |
22 -4 4 arg2 | |
23 0 0 arg1 | |
24 local2 -20 4 0 (r5) | |
25 local1 <-- -16 0 local variable 0 (r4) | |
26 -12 <- disp_offset %ebp | |
27 r30 (sp) -8 | |
28 0 <- r1 | |
29 r1 (fp) 8 <- arg_offset | |
30 arg1 8 0 | |
31 arg2 12 4 | |
32 see enter/enter1/leave see code_enter | |
33 | |
34 r0 link register | |
35 r30 stack pointer | |
36 r31 0 | |
37 r1 frame pointer | |
38 */ | |
39 int arg_offset = 8; | |
40 int disp_offset = -12; | |
41 int func_disp_offset = -12; | |
42 int code_disp_offset = 0; | |
43 int jump_offset = 0; | |
44 | |
45 int size_of_int = 4; | |
46 int size_of_float = 4; | |
47 int size_of_double = 8; | |
48 int size_of_longlong = 8; | |
49 int endian = 0; | |
50 int MAX_REGISTER=30; /* PowerPCのレジスタを10個まで使う*/ | |
51 int REAL_MAX_REGISTER=32; /* PowerPCのレジスタが32ということ*/ | |
52 int MAX_REGISTGER_VAR=30-10; | |
53 int MAX_FREGISTER=30; | |
54 | |
55 #define REG_fp 1 | |
56 #define REG_sp 30 | |
57 #define REG_VAR_BASE 30 | |
58 #define REG_ARG_BASE 3 | |
59 #define REG_ARG_MAX 10 | |
60 #define FREG_ARG_BASE 1 | |
61 #define FREG_ARG_MAX 13 | |
62 | |
63 int reg_sp=REG_sp; | |
64 | |
65 static char *reg_name[] = { | |
66 "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9", | |
67 "r10","r11","r12","r13","r14","r15","r16","r17","r18","r19", | |
68 "r20","r21","r22","r23","r24","r25","r26","r27","r28","r29", | |
69 "r30","r31" | |
70 }; | |
71 | |
72 static char *freg_name[] = { | |
73 "f0","f1","f2","f3","f4","f5","f6","f7","f8","f9", | |
74 "f10","f11","f12","f13","f14","f15","f16","f17","f18","f19", | |
75 "f20","f21","f22","f23","f24","f25","f26","f27","f28","f29", | |
76 "f30","f31" | |
77 }; | |
78 | |
79 static char *creg_name[] = { | |
80 "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7" | |
81 }; | |
82 | |
83 void use_register(int virt, int real, int move); | |
84 void code_preinc(int e1,int e2) ; | |
85 void code_cmp_register(int e2) ; | |
86 void code_assign_gvar(int e2,int byte) ; | |
87 void tosop(int op,int oreg); | |
88 void edx_cleanup(); | |
89 void shift(char *op, int reg); | |
90 void ld_indexx(int byte, int n, int xreg); | |
91 void jmp(int l); | |
92 void local_table(void); | |
93 void text_mode(void); | |
94 void data_mode(char *name); | |
95 | |
96 char *register_name(int i,int byte); | |
97 int register_var(int r); | |
98 int get_register_var(void); | |
99 void emit_push(void); | |
100 int emit_pop(int type); | |
101 void code_crlvar(int e2); | |
102 void code_preinc(int e1,int e2); | |
103 void code_postinc(int e1,int e2); | |
104 void code_bool(int e1); | |
105 void string(int e1); | |
106 void emit_copy(int from,int to,int length,int offset,int value,int det); | |
107 int struct_push(int e4,int t); | |
108 void function(int e1); | |
109 void code_assop(int op,int byte); | |
110 int edx_setup(); | |
111 void code_opening(char *filename); | |
112 void code_closing(); | |
113 void code_leave(char *name); | |
114 int lvar(int l); | |
115 void global_table(void); | |
116 | |
117 char * fstore(int d); | |
118 char * fload(int d); | |
119 int code_d1(double d); | |
120 int code_d2(double d); | |
121 | |
122 void | |
123 code_init(void) | |
124 { | |
125 arg_offset = 8; | |
126 func_disp_offset = -12; | |
127 disp_offset = -12; | |
128 size_of_int = 4; | |
129 endian = 1; | |
130 } | |
131 | |
132 #define register_name(i) reg_name[i] | |
133 | |
134 void | |
135 gexpr_code_init(void){ | |
136 regv[creg]=0; | |
137 } | |
138 | |
139 int virtual(int real); | |
140 char * fload(int d); | |
141 int code_d1(double d); | |
142 int code_d2(double d); | |
143 | |
144 | |
145 int | |
146 get_register(void) | |
147 { /* 使われていないレジスタを調べる */ | |
148 int i; | |
149 for(i=0;i<MAX_REGISTER;i++) { | |
150 if (! regs[i]) { /* 使われていないなら */ | |
151 regs[i]=1; /* そのレジスタを使うことを宣言し */ | |
152 return i; /* その場所を表す番号を返す */ | |
153 } | |
154 } | |
155 return -1; /* 空いている場所がないなら、それを表す -1 を返す */ | |
156 } | |
157 | |
158 void | |
159 free_register(int i) { /* いらなくなったレジスタを開放 */ | |
160 regv[i]=regs[i]=0; | |
161 } | |
162 | |
163 int | |
164 register_full(void) | |
165 { | |
166 int i; | |
167 for(i=0;i<MAX_REGISTER;i++) { | |
168 if (! regs[i]) { | |
169 return 0; | |
170 } | |
171 } | |
172 return 1; | |
173 } | |
174 | |
175 int | |
176 free_register_count(void) | |
177 { | |
178 int i,count; | |
179 count = 0; | |
180 for(i=0;i<MAX_REGISTER;i++) { | |
181 if (! regs[i] && ! regv[i]) count++; | |
182 } | |
183 return count; | |
184 } | |
185 | |
186 void | |
187 free_all_register(void) | |
188 { | |
189 int i; | |
190 for(i=0;i<MAX_REGISTER;i++) { | |
191 regs[i]=regv[i]=0; | |
192 } | |
193 creg = get_register(); | |
194 dreg = get_register(); | |
195 return; | |
196 } | |
197 | |
198 void | |
199 use_register_var(int i) { | |
200 regv[i]=1; | |
201 } | |
202 | |
203 void | |
204 set_register_var() { | |
205 } | |
206 | |
207 void | |
208 code_arg_register(int args) | |
209 { | |
210 NMTBL *n; | |
211 if (args) { | |
212 /* process in reverse order */ | |
213 n = (NMTBL*)caddr(args); | |
214 if(n->sc==REGISTER) { | |
215 if ((n->dsp = get_register_var()) <0) { | |
216 error(-1); return; | |
217 } | |
218 use_register_var(n->dsp); /* it has now value in it */ | |
219 } | |
220 code_arg_register(cadr(args)); | |
221 } | |
222 } | |
223 | |
224 | |
225 void | |
226 register_usage(char *s) | |
227 { | |
228 int i; | |
229 if (chk) return; | |
230 printf("# %d: %s:",lineno,s); | |
231 printf(" creg=%s dreg=%s ",register_name(creg,0),register_name(dreg,0)); | |
232 for(i=0;i<MAX_REGISTER;i++) { | |
233 printf("%d",regs[i]); | |
234 } | |
235 printf(":"); | |
236 for(i=0;i<MAX_REGISTER;i++) { | |
237 printf("%d",regv[i]); | |
238 } | |
239 #if 0 | |
240 printf(" regs_stack",register_name(creg,0),register_name(dreg,0)); | |
241 for(i=reg_sp;i>=0;i--) { | |
242 if(reg_stack[i]>=0) | |
243 printf(" %s",register_name(reg_stack[i],0)); | |
244 } | |
245 #endif | |
246 printf("\n"); | |
247 } | |
248 | |
249 void | |
250 gexpr_init(void) | |
251 { | |
252 while(reg_sp > 0) { | |
253 free_register(reg_stack[--reg_sp]); | |
254 } | |
255 text_mode(); | |
256 gexpr_code_init(); | |
257 register_usage("gexpr_init"); | |
258 } | |
259 | |
260 | |
261 void | |
262 emit_init(void) | |
263 { | |
264 int i; | |
265 for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; regv[i]=0;rname[i]=i;} | |
266 free_all_register(); | |
267 reg_sp = 0; | |
268 text_mode(); | |
269 } | |
270 | |
271 int | |
272 register_var(int r) { | |
273 return virtual(REG_VAR_BASE-r); | |
274 } | |
275 | |
276 int | |
277 get_register_var(void) | |
278 { | |
279 int i; | |
280 for(i=0;i<MAX_REGISTGER_VAR;i++) { | |
281 if (REG_VAR_Base-i<=REG_ARG_MAX) | |
282 return -1; | |
283 if (! regs[REG_VAR_Base-i]) { /* 使われていないなら */ | |
284 regs[REG_VAR_Base-i]=1; /* そのレジスタを使うことを宣言し */ | |
285 regv[REG_VAR_Base-i]=0; | |
286 return i; /* その場所を表す番号を返す */ | |
287 } | |
288 } | |
289 return -1; | |
290 } | |
291 | |
292 void | |
293 emit_push(void) | |
294 { | |
295 int new_reg; | |
296 new_reg = get_register(); | |
297 if(new_reg<0) { /* もうレジスタがない */ | |
298 if (reg_sp>=MAX_MAX) error(-1); | |
299 reg_stack[reg_sp++] = -1; | |
300 printf("\tstwu %s,-%d(%s)\n",register_name(creg), | |
301 size_of_int,register_name(reg_sp)); | |
302 /* creg is used soon, don't regv[creg]=0 */ | |
303 } else { | |
304 reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ | |
305 creg = new_reg; | |
306 regv[creg]=1; | |
307 } | |
308 } | |
309 | |
310 int | |
311 emit_pop() | |
312 { | |
313 int xreg; | |
314 if ((xreg=pop_register())==-1) { | |
315 xreg=get_register(); | |
316 if(!xreg) error(-1); | |
317 printf("\tlwz %s,(%s)\n",register_name(xreg),register_name(reg_sp); | |
318 printf("\taddis %s,%s,%d\n", | |
319 register_name(reg_sp),register_name(reg_sp),size_of_int; | |
320 regv[xreg]=1; | |
321 } | |
322 return xreg; | |
323 } | |
324 | |
325 static char *code_base; | |
326 | |
327 #define MAX_PTR_CACHE 10 | |
328 | |
329 int ptr_cache=0; | |
330 | |
331 int | |
332 clear_ptr_cache() | |
333 { | |
334 int ptcptr=ptr_cache; | |
335 while(ptcptr) { | |
336 if(car(ptcptr)) | |
337 free_register(caddr(ptcptr)); | |
338 car(ptcptr)=0; | |
339 caddr(ptcptr)=0; | |
340 ptcptr=cadr(ptcptr); | |
341 } | |
342 } | |
343 | |
344 int | |
345 init_ptr_cache() | |
346 { | |
347 int i; | |
348 for(i=0;i<MAX_PTR_CACHE;i++) { | |
349 ptr_cache=glist3(0,ptr_cache,0); | |
350 } | |
351 } | |
352 | |
353 | |
354 int | |
355 get_ptr_cache(char *name) | |
356 { | |
357 int r; | |
358 int ptcptr=ptr_cache; | |
359 int cache; | |
360 int i = 0; | |
361 int g = (int)name; | |
362 int p,p1; | |
363 | |
364 while(ptcptr) { | |
365 if(car(ptcptr)==g) return caddr(ptcptr); | |
366 p1=p; p=ptcptr; | |
367 ptcptr=cadr(ptcptr); | |
368 } | |
369 cadr(p1)=0; /* remove the last one */ | |
370 cadr(p) = ptr_cache; /* connect current queue to the last one */ | |
371 ptr_cache = p; /* now the last one is the top */ | |
372 if (!caddr(p)) { | |
373 if((r=get_register())) { | |
374 caddr(p)=r; | |
375 else | |
376 r=creg; | |
377 } | |
378 rrn = register_name(r); | |
379 printf("\taddis %s,r31,ha16(L_%s$non_lazy_ptr-%s)\n", | |
380 rrn,(char *)g,code_base); | |
381 printf("\tlzw %s,lo16(L_%s$non_lazy_ptr-%s)(%s)\n", | |
382 rrn,(char *)g,code_base,rrn); | |
383 return r; | |
384 } | |
385 | |
386 void | |
387 code_gvar(int e1) { | |
388 int r; | |
389 r = get_ptr_cache((char*)caddr(e1)); | |
390 if(r!=creg) | |
391 printf("\tmr %s,%s\n",register_name(creg),register_name(r)); | |
392 return; | |
393 } | |
394 | |
395 void | |
396 code_rgvar(int e1) { | |
397 printf("\tlwz %s,(%s)\n",register_name(creg), | |
398 register_name(get_ptr_cache((char*)caddr(e1)))); | |
399 } | |
400 | |
401 void | |
402 code_crgvar(e1){ | |
403 printf("\tlbz %s,(%s)\n",register_name(creg), | |
404 register_name(get_ptr_cache((char*)caddr(e1)))); | |
405 printf("\textsb %s,%s\n",register_name(creg),register_name(creg)); | |
406 } | |
407 | |
408 void | |
409 code_lvar(int e2) { | |
410 printf("\tla %d(r1),%s\n",e2,register_name(creg)); | |
411 } | |
412 | |
413 | |
414 void | |
415 code_register(int e2) { | |
416 printf("\tmr %s,%s\n",register_name(creg),register_name(e2)); | |
417 } | |
418 | |
419 | |
420 void | |
421 code_rlvar(int e2) { | |
422 printf("\tlwz %d(r1),%s\n",e2,register_name(creg)); | |
423 } | |
424 | |
425 | |
426 void | |
427 code_crlvar(int e2) { | |
428 printf("\tlbz %d(r1),%s\n",e2,register_name(creg)); | |
429 printf("\textsb %s,%s\n",register_name(creg),register_name(creg)); | |
430 } | |
431 | |
432 | |
433 void | |
434 code_fname(char *e2) { | |
435 int r; | |
436 r = get_ptr_cache(e2); | |
437 if(r!=creg) | |
438 printf("\tmr %s,%s\n",register_name(creg),register_name(e2)); | |
439 return; | |
440 } | |
441 | |
442 | |
443 void | |
444 code_const(int e2) { | |
445 char *crn = register_name(creg); | |
446 if (-32768<e2&&e2<32768) | |
447 printf("\tli %s,%d\n",crn,e2); | |
448 else { | |
449 printf("\tlis %s,ha16(%d)\n",crn,e2); | |
450 printf("\taddi %s,%s,lo16(%d)\n",crn,crn,e2); | |
451 } | |
452 } | |
453 | |
454 | |
455 void | |
456 code_neg() { | |
457 printf("\tneg %s,%s\n", register_name(creg), register_name(creg); | |
458 } | |
459 | |
460 | |
461 void | |
462 code_not() { | |
463 printf("\tnor %s,%s,%s\n", | |
464 register_name(creg), register_name(creg),register_name(creg)); | |
465 } | |
466 | |
467 | |
468 void | |
469 code_lnot() { | |
470 printf("\tsubfic r0,%s,0\n", register_name(creg)); | |
471 printf("\tadde %s,r0,%s\n", register_name(creg),register_name(creg)); | |
472 } | |
473 | |
474 void | |
475 code_preinc(int e1,int e2) { | |
476 char *xrn,*drn; | |
477 int i,dreg; | |
478 if (car(e2)==REGISTER) { | |
479 printf("\taddi %s,%s,%d\n", register_name(cadr(e2))); | |
480 printf("\tmr %s,%s\n",register_name(cadr(creg)),register_name(e2)); | |
481 return; | |
482 } | |
483 g_expr(e2); | |
484 xrn = register_name(creg); | |
485 dreg=get_register(); if (!dreg) error(-1); | |
486 drn = register_name(dreg); | |
487 printf("\tlwz %s,(%s)\n",drn,xrn); | |
488 printf("\taddi %s,%s,%d\n",drn,drn,caddr(e1)); | |
489 printf("\tstw %s,(%s)\n",drn,xrn); | |
490 i=creg;creg=dreg;dreg=i; | |
491 regv[creg=1]; | |
492 free_register(dreg); | |
493 } | |
494 | |
495 | |
496 void | |
497 code_postinc(int e1,int e2) { | |
498 char *xrn,*crn,*nrn; | |
499 int dreg,nreg; | |
500 if (car(e2)==REGISTER) { | |
501 printf("\tmr %s,%s\n",register_name(creg),register_name(cadr(e2))); | |
502 printf("\taddi %s,%s,%d\n", | |
503 register_name(cadr(e2)),register_name(cadr(e2))); | |
504 return; | |
505 } | |
506 g_expr(e2); | |
507 dreg=get_register(); if (!dreg) error(-1); | |
508 xrn = register_name(dreg); | |
509 nreg=get_register(); if (!nreg) error(-1); | |
510 nrn = register_name(nreg); | |
511 printf("\tlwz %s,(%s)\n",xrn,crn); | |
512 printf("\taddi %s,%s,%d\n",nrn,xrn,caddr(e1)); | |
513 printf("\tstw %s,(%s)\n",nrn,crn); | |
514 i=creg;creg=dreg;dreg=i; | |
515 free_register(nreg); | |
516 free_register(dreg); | |
517 regv[creg]=1; | |
518 } | |
519 | |
520 | |
521 void | |
522 code_cpostinc(int e1,int e2) { | |
523 char *xrn,*crn; | |
524 int i,nreg,dreg; | |
525 if (car(e2)==REGISTER) { | |
526 printf("\tlbz %s,(%s)\n",register_name(creg),register_name(cadr(e2))); | |
527 printf("\textsb %s,%s\n",register_name(creg),register_name(creg)); | |
528 printf("\taddi %s,%s,%d\n", | |
529 register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1)); | |
530 return; | |
531 } | |
532 g_expr(e2); | |
533 crn = register_name(creg); | |
534 dreg=get_register(); if (!dreg) error(-1); | |
535 xrn = register_name(dreg); | |
536 nreg=get_register(); if (!nreg) error(-1); | |
537 nrn = register_name(nreg); | |
538 printf("\tlwz %s,(%s)\n",xrn,crn); | |
539 printf("\tlbz %s,(%s)\n",nrn,xrn); | |
540 printf("\textsb %s,%s\n",nrn,nrn); | |
541 printf("\taddi %s,%s,%d\n", xrn,xrn); | |
542 printf("\tstw %s,(%s)\n",xrn,crn); | |
543 i=creg;creg=nreg;nreg=i; | |
544 free_register(nreg); | |
545 free_register(dreg); | |
546 regv[creg]=1; | |
547 } | |
548 | |
549 | |
550 void | |
551 code_cpreinc(int e1,int e2) { | |
552 char *xrn,*crn; | |
553 int i,nreg,dreg; | |
554 if (car(e2)==REGISTER) { | |
555 printf("\tlbzu %s,%d(%s)\n",register_name(creg),caddr(e1),register_name(cadr(e2))); | |
556 printf("\textsb %s,%s\n",register_name(creg),register_name(creg)); | |
557 return; | |
558 } | |
559 g_expr(e2); | |
560 crn = register_name(creg); | |
561 dreg=get_register(); if (!dreg) error(-1); | |
562 xrn = register_name(dreg); | |
563 nreg=get_register(); if (!nreg) error(-1); | |
564 nrn = register_name(nreg); | |
565 printf("\tlwz %s,(%s)\n",xrn,crn); | |
566 printf("\tlbzu %s,%d(%s)\n",nrn,caddr(e1),xrn); | |
567 printf("\tstw %s,(%s)\n",xrn,crn); | |
568 printf("\textsb %s,%s\n",nrn,nrn); | |
569 i=creg;creg=nreg;nreg=i; | |
570 free_register(nreg); | |
571 free_register(dreg); | |
572 regv[creg]=1; | |
573 } | |
574 | |
575 | |
576 void | |
577 code_cpostdec(int e1,int e2) { | |
578 char *xrn,*crn; | |
579 int i,nreg,dreg; | |
580 if (car(e2)==REGISTER) { | |
581 crn=register_name(creg); | |
582 xrn=register_name(cadr(e2)); | |
583 printf("\tlbz %s,(%s)\n",crn,xrn); | |
584 printf("\taddi %s,%s,%d\n",xrn,xrn,caddr(e1)); | |
585 printf("\textsb %s,%s\n",crn,crn); | |
586 return; | |
587 } | |
588 g_expr(e2); | |
589 crn = register_name(creg); | |
590 dreg=get_register(); if (!dreg) error(-1); | |
591 xrn = register_name(dreg); | |
592 nreg=get_register(); if (!nreg) error(-1); | |
593 nrn = register_name(nreg); | |
594 printf("\tlwz %s,(%s)\n",xrn,crn); | |
595 printf("\tlbz %s,(%s)\n",nrn,xrn); | |
596 printf("\taddi %s,%s,%d\n",xrn,xrn,caddr(e1)); | |
597 printf("\tstw %s,(%s)\n",xrn,crn); | |
598 printf("\textsb %s,%s\n",nrn,nrn); | |
599 i=creg;creg=nreg;nreg=i; | |
600 free_register(nreg); | |
601 free_register(dreg); | |
602 regv[creg]=1; | |
603 } | |
604 | |
605 | |
606 void | |
607 code_cpredec(int e1,int e2) { | |
608 char *xrn,*crn; | |
609 int i,nreg,dreg; | |
610 if (car(e2)==REGISTER) { | |
611 crn=register_name(creg); | |
612 xrn=register_name(cadr(e2)); | |
613 printf("\tlbzu %s,%d(%s)\n",crn,caddr(e1),xrn); | |
614 printf("\textsb %s,%s\n",crn,crn); | |
615 return; | |
616 } | |
617 g_expr(e2); | |
618 crn = register_name(creg); | |
619 dreg=get_register(); if (!dreg) error(-1); | |
620 xrn = register_name(dreg); | |
621 nreg=get_register(); if (!nreg) error(-1); | |
622 nrn = register_name(nreg); | |
623 printf("\tlwz %s,(%s)\n",xrn,crn); | |
624 printf("\tlbzu %s,%d(%s)\n",nrn,caddr(e1),xrn); | |
625 printf("\tstw %s,(%s)\n",xrn,crn); | |
626 printf("\textsb %s,%s\n",nrn,nrn); | |
627 i=creg;creg=nreg;nreg=i; | |
628 free_register(nreg); | |
629 free_register(dreg); | |
630 regv[creg]=1; | |
631 } | |
632 | |
633 | |
634 void | |
635 code_return() { | |
636 int r; | |
637 printf("\taddis %s,r31,ha16(_%d-%s)\n",crn,retcont,code_base); | |
638 printf("\tla %s,lo16(_%d-%s)(%s)\n",crn,retcont,code_base,crn); | |
639 } | |
640 | |
641 | |
642 void | |
643 code_environment() { | |
644 printf("\tmr %s,r1\n",register_name(creg)); | |
645 } | |
646 | |
647 | |
648 void | |
649 code_bool(int e1) { | |
650 char *xrn; | |
651 int e2,e3; | |
652 b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ | |
653 xrn = register_name(creg); | |
654 printf("\tli %s,0\n",xrn); | |
655 jmp(e3=fwdlabel()); | |
656 fwddef(e2); | |
657 printf("\tli %s,1\n",xrn); | |
658 fwddef(e3); | |
659 } | |
660 | |
661 char * | |
662 code_gt(int cond) { | |
663 return (cond?"gt":"le"); | |
664 } | |
665 | |
666 char * | |
667 code_ugt(int cond) { | |
668 return (cond?"gt":"le"); | |
669 } | |
670 | |
671 char * | |
672 code_ge(int cond) { | |
673 return (cond?"ge":"lt"); | |
674 } | |
675 | |
676 char * | |
677 code_uge(int cond) { | |
678 return (cond?"ge":"lt"); | |
679 } | |
680 | |
681 char * | |
682 code_eq(int cond) { | |
683 return (cond?"eq":"ne"); | |
684 } | |
685 | |
686 void | |
687 code_cmp_crgvar(int e1) { | |
688 int r; | |
689 char *crn = register_name(creg); | |
690 r = get_ptr_cache((char *)caddr(e1)); | |
691 printf("\tlbz %s,(%s)\n",crn,register_name(r)); | |
692 printf("\tcmpwi cr0,%s,0\n",crn); | |
693 } | |
694 | |
695 | |
696 void | |
697 code_cmp_crlvar(int e1) { | |
698 char *crn = register_name(creg); | |
699 printf("\tlbz %s,%d(r1)\n",crn,e1); | |
700 printf("\tcmpwi cr0,%s,0\n",crn); | |
701 } | |
702 | |
703 | |
704 void | |
705 code_cmp_rgvar(int e1) { | |
706 int r; | |
707 char *crn = register_name(creg); | |
708 r = get_ptr_cache((char *)caddr(e1)); | |
709 printf("\tlwz %s,(%s)\n",crn,register_name(r)); | |
710 code_cmp_register(creg); | |
711 } | |
712 | |
713 | |
714 void | |
715 code_cmp_rlvar(int e1) { | |
716 char *crn = register_name(creg); | |
717 printf("\tlwz %s,%d(r1)\n",crn,e1); | |
718 code_cmp_register(creg); | |
719 } | |
720 | |
721 | |
722 void | |
723 code_cmp_register(int e2) { | |
724 printf("\tcmpwi cr0,%s,0\n",register_name(e2)); | |
725 } | |
726 | |
727 | |
728 void | |
729 ascii(char *s) | |
730 { | |
731 printf("\t.ascii \""); | |
732 while(*s) { | |
733 if (*s=='\n') | |
734 printf("%cn",92); | |
735 else if (*s<' ') | |
736 printf("%c%03o",92,*s); | |
737 else if (*s==34) | |
738 printf("%c%c",92,34); | |
739 else | |
740 printf("%c",*s); | |
741 s++; | |
742 } | |
743 printf("\\0%c\n",34); | |
744 } | |
745 | |
746 void | |
747 string(int e1) | |
748 { | |
749 char *s; | |
750 int i,lb; | |
751 | |
752 s=(char *)cadr(e1); | |
753 printf(".data\t.cstring\n\t.align 2\n"); | |
754 lb=fwdlabel(); | |
755 printf("_%d:\n",lb); | |
756 ascii(s); | |
757 if (output_mode==TEXT_EMIT_MODE) { | |
758 printf(".text\n"); | |
759 } else { | |
760 text_mode(); | |
761 } | |
762 printf("\taddis %s,r31,ha16(_%d-%s)\n",crn,lb,code_base); | |
763 printf("\tla %s,lo16(_%d-%s)(%s)\n",crn,lb,code_base,crn); | |
764 } | |
765 | |
766 #define MAX_COPY_LEN 20 | |
767 | |
768 void | |
769 emit_copy(int from,int to,int length,int offset,int value,int det) | |
770 { | |
771 char *frn = register_name(from); | |
772 char *trn = register_name(to); | |
773 char *drn; | |
774 int fix = 0; | |
775 char *bcopy = "bcopy"; | |
776 int dreg = get_regiter(); if (!dreg) error(-1); | |
777 drn = register_name(dreg); | |
778 | |
779 /* length <0 means upward direction copy */ | |
780 switch (length) { | |
781 case 0: break; | |
782 case 1: case -1: | |
783 printf("\tlbz %s,%d(%s)\n",drn,offset,frn); | |
784 printf("\tstb %s,%d(%s)\n",drn,offset,trn); | |
785 break; | |
786 case 2: case -2: | |
787 printf("\tlhz %s,%d(%s)\n",drn,offset,frn); | |
788 printf("\tsth %s,%d(%s)\n",drn,offset,trn); | |
789 break; | |
790 case 4: case -4: | |
791 printf("\tlwz %s,%d(%s)\n",drn,offset,frn); | |
792 printf("\tstw %s,%d(%s)\n",drn,offset,trn); | |
793 break; | |
794 default: | |
795 if (-MAX_COPY_LEN<length && length <0) { | |
796 for(;length<=4;length+=4,offset-=4) | |
797 emit_copy(from,to,4,offset,0,det); | |
798 for(;length<=2;length+=2,offset-=2) | |
799 emit_copy(from,to,2,offset,0,det); | |
800 if(length>0) | |
801 emit_copy(from,to,length,offset,0,det); | |
802 break; | |
803 } else if (length <=MAX_COPY_LEN) { | |
804 for(;length>=4;length-=4,offset+=4) | |
805 emit_copy(from,to,4,offset,0,det); | |
806 for(;length>=2;length-=2,offset+=2) | |
807 emit_copy(from,to,2,offset,0,det); | |
808 if(length>0) | |
809 emit_copy(from,to,length,offset,0,det); | |
810 break; | |
811 } | |
812 if (det) { | |
813 printf("\tli r5,%d\n",length); | |
814 printf("\tmr r4,%s\n",trn); | |
815 printf("\tmr r3,%s\n",frn); | |
816 printf("\tbl L_%s$stub\n",bcopy); | |
817 regist_extern_function(bcopy); | |
818 break; | |
819 } | |
820 } | |
821 if (value) { | |
822 /* creg must point top of the destination data */ | |
823 /* this code is necessary for the value of assignment or function call */ | |
824 /* otherwise we don't need this */ | |
825 if (fix) printf("\taddi %s,%s,%d\n",trn,trn,fix); | |
826 if(creg!=to) { | |
827 free_register(creg); creg=to; | |
828 } | |
829 } | |
830 free_register(dreg); | |
831 regv[from]=regv[to]=regv[dreg]=0; | |
832 regv[creg]=1; | |
833 } | |
834 | |
835 int | |
836 struct_push(int e4,int t) | |
837 { | |
838 int length,save,count; | |
839 int dreg; char *drn,*crn,*srn; | |
840 g_expr(e4); | |
841 length=size(t); | |
842 if(length%size_of_int) { | |
843 length += size_of_int - (length%size_of_int); | |
844 } | |
845 dreg = get_regiter(); if (!dreg) error(-1); | |
846 drn = register_name(dreg); | |
847 crn = register_name(dreg); | |
848 srn = register_name(reg_sp); | |
849 for(count=0;length<MAX_COPY_LEN;count++,length-=size_of_int) { | |
850 if (length==0) { | |
851 free_register(dreg); | |
852 return count; | |
853 } else { | |
854 printf("\tlwz %s,%d(%s)\n",drn,length-size_of_int,crn); | |
855 printf("\tstwu %s,%d(%s)\n",drn,-size_of_int,srn); | |
856 } | |
857 } | |
858 printf("\taddis %s,%s,ha16(%d)\n",srn,,srn,length); | |
859 printf("\taddi %s,%s,lo16(%d)\n",srn,,srn,length); | |
860 /* downward direction copy */ | |
861 printf("\tmr %s,%s\n",drn,srn); | |
862 emit_copy(creg,dreg,length,0,0,1); | |
863 /* we have value in creg, it may be changed */ | |
864 if (dreg!=creg) free_register(dreg); | |
865 return length/size_of_int; | |
866 } | |
867 | |
868 int | |
869 arg_offset(int arg) | |
870 { | |
871 } | |
872 | |
873 void | |
874 function(int e1) | |
875 { | |
876 int e2,e3,e4,e5,nargs,t; | |
877 int reg_arg,freg_arg; | |
878 NMTBL *n; | |
879 e2 = cadr(e1); | |
880 nargs = 0; | |
881 reg_arg = REG_ARG_BASE; | |
882 freg_arg = FREG_ARG_BASE; | |
883 for (e3 = caddr(e1); e3; e3 = cadr(e3)) { | |
884 t=caddr(e3); | |
885 n=(NMTBL *)(e5=(cadr(e4 = car(e3)))); | |
886 if(scalar(t)) { | |
887 g_expr(e4); | |
888 if (reg_arg<REG_ARG_MAX) | |
889 printf("\tmr %s,%s\n",register_name(reg_arg), | |
890 register_name(creg)); | |
891 else { | |
892 printf("\tstw %s,%d(r1)\n",register_name(creg), | |
893 arg_offset(nargs)); | |
894 } | |
895 nargs ++ ; reg_arg++; | |
896 } else if (t==DOUBLE||t==FLOAT) { | |
897 g_expr(e4); | |
898 nargs += size_of_double/size_of_int; | |
899 if (fregv[freg_arg]) | |
900 save_freg(freg_arg); | |
901 fregv[freg_arg]=1; | |
902 if (freg_arg<FREG_ARG_MAX) | |
903 printf("\tmr %s,%s\n",register_name(reg_arg++), | |
904 register_name(freg)); | |
905 else if(t==DOUBLE) { | |
906 printf("\tstfd %s,%d(r1)\n",register_name(freg), | |
907 arg_offset(nargs)); | |
908 nargs+=size_of_double/size_of_int; | |
909 } else { | |
910 printf("\tstfs %s,%d(r1)\n",register_name(freg), | |
911 arg_offset(nargs)); | |
912 nargs+=size_of_float/size_of_int; | |
913 } | |
914 freg_arg++; | |
915 continue; | |
916 } else if (car(t)==STRUCT||car(t)==UNION) { | |
917 nargs += struct_push(e4,t); | |
918 continue; | |
919 } else { | |
920 error(TYERR); | |
921 } | |
922 ++nargs; | |
923 } | |
924 if (car(e2) == FNAME) { | |
925 n=(NMTBL *)cadr(e2); | |
926 regv[creg]=0; | |
927 } else { | |
928 g_expr(e2); | |
929 regv[creg]=1; | |
930 } | |
931 | |
932 if (car(e2) == FNAME) { | |
933 printf("\tbl\tL_%s$stub\n",n->nm); | |
934 } else { | |
935 jmp=get_tmp_register(); | |
936 jrn = register_name(jmp); | |
937 printf("\tmr %s,%s\n",jrn,crn); | |
938 printf("\tmtctr %s\n",jrn); | |
939 printf("\tbctrl\n"); | |
940 free_register(jmp); | |
941 } | |
942 regv[creg]=1; | |
943 } | |
944 | |
945 void | |
946 code_frame_pointer(int e3) { | |
947 printf("\tmovl %s,r1\n",register_name(e3,0)); | |
948 } | |
949 | |
950 | |
951 void | |
952 code_fix_frame_pointer(int disp_offset) { | |
953 printf("\tla r1,%d(r1)\n",disp_offset); | |
954 } | |
955 | |
956 | |
957 void | |
958 code_jmp(char *s) { | |
959 printf("\tb L_%s$stub\n",s); | |
960 } | |
961 | |
962 | |
963 void | |
964 code_indirect_jmp(int e2) { | |
965 printf("\tmtctr %s\n",register_name(e2)); | |
966 printf("\tbctr\n"); | |
967 } | |
968 | |
969 void | |
970 rindirect(int e1) /* *(p +5 ) */ | |
971 { | |
972 char *op; | |
973 int e2,e3,byte; | |
974 e3 = cadr(e2 = cadr(e1)); | |
975 g_expr(e2); | |
976 switch (car(e1)) { | |
977 case FRINDIRECT: case DRINDIRECT: | |
978 printf("\t%s (%s)\n",fload(car(e1)==DRINDIRECT),register_name(creg)); | |
979 break; | |
980 case CRINDIRECT: case RINDIRECT: | |
981 op = ((byte = (car(e1) == CRINDIRECT)) ? "movsbl" : "movl"); | |
982 printf("\t%s (%s),%s\n",op,register_name(creg),register_name(creg)); | |
983 } | |
984 } | |
985 | |
986 | |
987 void | |
988 code_assign_gvar(int e2,int byte) { | |
989 if (byte) use_data_reg(creg,1); | |
990 printf("\t%s %s,%s\n",move(byte),register_name(creg,byte),(char *)caddr(e2)); | |
991 } | |
992 | |
993 void | |
994 code_assign_lvar(int e2,int byte) { | |
995 if (byte) use_data_reg(creg,1); | |
996 printf("\t%s %s,%d(%%ebp)\n",move(byte),register_name(creg,byte),e2); | |
997 } | |
998 | |
999 void | |
1000 code_assign_register(int e2,int byte) { | |
1001 printf("\tmovl %s,%s\n",register_name(creg),register_name(e2,0)); | |
1002 } | |
1003 | |
1004 void | |
1005 code_assign(int e2,int byte) { | |
1006 printf("\t%s %s,(%s)\n",move(byte),register_name(creg,byte),register_name(e2,0)); | |
1007 } | |
1008 | |
1009 | |
1010 void | |
1011 code_register_assop(int e2,int op,int byte) { | |
1012 int reg; | |
1013 int xreg = creg; | |
1014 creg = reg = e2; | |
1015 tosop(op,xreg); | |
1016 creg = xreg; | |
1017 printf("\tmovl %s,%s\n",register_name(reg,0),register_name(creg)); | |
1018 } | |
1019 | |
1020 | |
1021 void | |
1022 code_assop(int op,int byte) { | |
1023 char *xrn; | |
1024 int xreg; | |
1025 int edx = edx_setup(); | |
1026 xrn = register_name(xreg = emit_pop(0),0); /* pop e3 value */ | |
1027 regv[xreg]=regs[xreg]=1; | |
1028 printf("\tmovl %s,%s # assop \n",register_name(creg),register_name(edx,0)); | |
1029 regv[edx]=1; | |
1030 ld_indexx(byte,0,edx); | |
1031 tosop(op,xreg); | |
1032 printf("\t%s %s,(%s)\n",byte ? "movb" : "movl",register_name(creg,byte),register_name(edx,0)); | |
1033 edx_cleanup(); | |
1034 emit_pop_free(xreg); | |
1035 } | |
1036 | |
1037 | |
1038 void | |
1039 tosop(int op,int oreg) | |
1040 { | |
1041 int dx; | |
1042 char *orn,*crn; | |
1043 | |
1044 switch(op) { | |
1045 case LSHIFT: | |
1046 case ULSHIFT: | |
1047 shift("sall",oreg); | |
1048 return; | |
1049 case RSHIFT: | |
1050 shift("sarl",oreg); | |
1051 return; | |
1052 case URSHIFT: | |
1053 shift("shrl",oreg); | |
1054 return; | |
1055 } | |
1056 if(oreg==-1) { | |
1057 printf("\tpopl %s\n",register_name(dreg,0)); | |
1058 oreg = dreg; | |
1059 regv[dreg]=1; | |
1060 } | |
1061 regv[oreg]=1; regs[oreg]=1; | |
1062 orn = register_name(oreg,0); | |
1063 crn = register_name(creg); | |
1064 switch(op) { | |
1065 case ADD: | |
1066 printf("\taddl %s,%s\n",orn,crn); | |
1067 break; | |
1068 case SUB: | |
1069 printf("\tsubl %s,%s\n",orn,crn); | |
1070 break; | |
1071 case BAND: | |
1072 printf("\tandl %s,%s\n",orn,crn); | |
1073 break; | |
1074 case EOR: | |
1075 printf("\txorl %s,%s\n",orn,crn); | |
1076 break; | |
1077 case BOR: | |
1078 printf("\torl %s,%s\n",orn,crn); | |
1079 break; | |
1080 case MUL: | |
1081 case UMUL: | |
1082 printf("\t%s %s,%s\n","imull",orn,crn); | |
1083 break; | |
1084 case DIV: | |
1085 case UDIV: | |
1086 use_register(creg,REG_EAX,1); | |
1087 edx_setup(); | |
1088 orn = register_name(oreg,0); | |
1089 if (op==DIV) | |
1090 printf("\tcltd\n\tdivl %s\n",orn); | |
1091 else | |
1092 printf("\txor %%edx,%%edx\n\tidivl %s\n",orn); | |
1093 edx_cleanup(); | |
1094 break; | |
1095 case MOD: | |
1096 case UMOD: | |
1097 use_register(creg,REG_EAX,1); | |
1098 edx_setup(); | |
1099 orn = register_name(oreg,0); | |
1100 if (op==DIV) | |
1101 printf("\tcltd\n\tdivl %s\n",orn); | |
1102 else | |
1103 printf("\txor %%edx,%%edx\n\tidivl %s\n",orn); | |
1104 dx = virtual(REG_EDX); | |
1105 if (dx!=creg) { | |
1106 rname[dx]=rname[creg]; | |
1107 rname[creg]=REG_EDX; | |
1108 } | |
1109 edx_cleanup(); | |
1110 break; | |
1111 } | |
1112 if (oreg!=dreg&&oreg>=0) | |
1113 free_register(oreg); | |
1114 } | |
1115 | |
1116 static int edx_stack=0; | |
1117 | |
1118 int | |
1119 edx_setup() | |
1120 { | |
1121 int edx_save; | |
1122 /* make real EDX register empty */ | |
1123 if (free_register_count()<1) { | |
1124 for(edx_save = 0;edx_save==dreg||edx_save==creg;edx_save++); | |
1125 printf("\tpushl %s\n",register_name(edx_save,0)); | |
1126 edx_stack = list3(edx_save,edx_stack,0); | |
1127 } else { | |
1128 edx_save = get_register(); | |
1129 edx_stack = list3(edx_save,edx_stack,1); | |
1130 } | |
1131 regv[edx_save]=0; | |
1132 use_register(edx_save,REG_EDX,0); | |
1133 return edx_save; | |
1134 } | |
1135 | |
1136 | |
1137 void | |
1138 edx_cleanup() | |
1139 { | |
1140 if (caddr(edx_stack)==0) { | |
1141 printf("\tpopl %s\n",register_name(car(edx_stack),0)); | |
1142 } else | |
1143 free_register(car(edx_stack)); | |
1144 edx_stack = cadr(edx_stack); | |
1145 } | |
1146 | |
1147 void | |
1148 shift(char *op, int reg) | |
1149 { | |
1150 if (reg>=0) { | |
1151 use_register(reg,REG_ECX,1); | |
1152 } else { | |
1153 use_register(dreg,REG_ECX,0); | |
1154 printf("\tpopl %%ecx\n"); | |
1155 } | |
1156 printf("\t%s %%cl,%s\n",op,register_name(creg)); | |
1157 } | |
1158 | |
1159 void | |
1160 ld_indexx(int byte, int n, int xreg) | |
1161 { | |
1162 char *op; | |
1163 | |
1164 op = byte ? "movsbl" : "movl"; | |
1165 if (n) | |
1166 printf("\t%s %d(%s),%s\n",op,n,register_name(xreg,0),register_name(creg,byte)); | |
1167 else | |
1168 printf("\t%s (%s),%s\n",op,register_name(xreg,0),register_name(creg,byte)); | |
1169 } | |
1170 | |
1171 void | |
1172 cmpdimm(int e, int csreg) | |
1173 { | |
1174 /* used in dosiwtch() */ | |
1175 if(chk) return; | |
1176 use_register(creg,csreg,0); | |
1177 printf("\tcmpl $%d,%s\n",e,register_name(creg)); | |
1178 } | |
1179 | |
1180 void | |
1181 code_opening(char *filename) | |
1182 { | |
1183 printf("\t.file \"%s\"\n",filename); | |
1184 printf("\t.version\t\"01.01\"\n"); | |
1185 /* printf("gcc2_compiled.:\n"); */ | |
1186 printf(".text\n"); | |
1187 } | |
1188 | |
1189 void | |
1190 code_closing() | |
1191 { | |
1192 global_table(); | |
1193 printf("\t.ident \"Micro-C compiled\"\n"); | |
1194 } | |
1195 | |
1196 void | |
1197 rexpr(int e1, int l1, char *s) | |
1198 { | |
1199 g_expr(list3(SUB,cadr(e1),caddr(e1))); | |
1200 printf("\tj%s\t_%d\n",s,l1); | |
1201 } | |
1202 | |
1203 | |
1204 void | |
1205 jcond(int l, char cond) | |
1206 { | |
1207 if (chk) return; | |
1208 printf("\tj%s\t_%d\n",cond?"ne":"e",l); | |
1209 } | |
1210 | |
1211 void | |
1212 jmp(int l) | |
1213 { | |
1214 control=0; | |
1215 if (chk) return; | |
1216 printf("\tjmp\t_%d\n",l); | |
1217 /* align? */ | |
1218 /* | |
1219 this is not allowed because of ? operator | |
1220 regv[creg]=regv[dreg]=0; | |
1221 use_register(creg,REG_EAX,0); | |
1222 use_register(dreg,REG_EBX,0); | |
1223 */ | |
1224 } | |
1225 | |
1226 void | |
1227 gen_comment(char *s) | |
1228 { | |
1229 if (chk) return; | |
1230 printf("## %s",s); | |
1231 } | |
1232 | |
1233 | |
1234 void | |
1235 code_enter(char *name) | |
1236 { | |
1237 printf("\t.align 4\n"); | |
1238 if (stmode!=STATIC) | |
1239 printf(".globl %s\n",name); | |
1240 printf("\t.type\t%s,@function\n",name); | |
1241 printf("%s:\n",name); | |
1242 } | |
1243 | |
1244 | |
1245 void | |
1246 code_enter1(int args) | |
1247 { | |
1248 code_disp_label=fwdlabel(); | |
1249 printf("\tlea _%d(%%ebp),%%esp\n",code_disp_label); | |
1250 | |
1251 printf("## args %d disp %d code_arg_offset=%d code_disp_offset=%d\n",args,disp,code_arg_offset,code_disp_offset); | |
1252 } | |
1253 | |
1254 void | |
1255 code_leave(char *name) | |
1256 { | |
1257 disp&= -size_of_int; | |
1258 printf("\t.set _%d,%d\n",code_disp_label,disp+code_disp_offset); | |
1259 printf("_%d:\n",labelno); | |
1260 printf("\t.size\t%s,_%d-%s\n",name,labelno,name); | |
1261 local_table(); | |
1262 labelno++; | |
1263 free_all_register(); | |
1264 } | |
1265 | |
1266 void | |
1267 enter(char *name) | |
1268 { | |
1269 printf("\t.align 2\n"); | |
1270 if (stmode!=STATIC) | |
1271 printf(".globl %s\n",name); | |
1272 printf("%s:\n",name); | |
1273 printf("\t.type\t%s,@function\n",name); | |
1274 printf("\tpushl %%ebp\n"); | |
1275 printf("\tmovl %%esp,%%ebp\n"); | |
1276 printf("\tpushl %%ebx\n"); | |
1277 printf("\tpushl %%esi\n"); | |
1278 printf("\tpushl %%edi\n"); | |
1279 } | |
1280 | |
1281 void | |
1282 enter1() | |
1283 { | |
1284 func_disp_label=fwdlabel(); | |
1285 printf("\tlea _%d(%%ebp),%%esp\n",func_disp_label); | |
1286 /* if(disp) printf("\tsubl $%d,%%esp\n",-disp); */ | |
1287 } | |
1288 | |
1289 void | |
1290 leave(int control, char *name) | |
1291 { | |
1292 if (control) | |
1293 use_register(creg,REG_EAX,1); | |
1294 if (retcont) { | |
1295 if (control) | |
1296 jmp(retlabel); | |
1297 fwddef(retcont); | |
1298 use_register(creg,REG_EAX,0); | |
1299 printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg)); | |
1300 /* printf("\tleave\n"); */ | |
1301 } | |
1302 fwddef(retlabel); | |
1303 /* use_register(creg,REG_EAX,0); too late */ | |
1304 /* if(disp) printf("\taddl $%d,%%esp\n",-disp); */ | |
1305 disp &= -size_of_int; | |
1306 | |
1307 printf("\tlea %d(%%ebp),%%esp\n",disp_offset); | |
1308 printf("\tpopl %%edi\n"); | |
1309 printf("\tpopl %%esi\n"); | |
1310 printf("\tpopl %%ebx\n"); | |
1311 printf("\tleave\n"); | |
1312 printf("\tret\n"); | |
1313 printf("\t.set _%d,%d\n",func_disp_label,disp+disp_offset); | |
1314 printf("_%d:\n",labelno); | |
1315 printf("\t.size\t%s,_%d-%s\n",name,labelno,name); | |
1316 local_table(); | |
1317 labelno++; | |
1318 free_all_register(); | |
1319 } | |
1320 | |
1321 | |
1322 void | |
1323 code_set_fixed_creg(int mode) { | |
1324 use_register(creg,REG_EAX,mode); | |
1325 } | |
1326 | |
1327 void | |
1328 gen_gdecl(char *n, int gpc) | |
1329 { | |
1330 /* | |
1331 if (stmode!=STATIC) | |
1332 printf(".globl %s\n",n); | |
1333 */ | |
1334 } | |
1335 | |
1336 void | |
1337 align(int t) | |
1338 { | |
1339 if (t!=CHAR) { | |
1340 if (data_alignment & 1) | |
1341 printf("\t.align 2\n"); | |
1342 data_alignment = 0; | |
1343 } | |
1344 } | |
1345 | |
1346 void | |
1347 emit_data(int e, int t, NMTBL *n) | |
1348 { | |
1349 int l; | |
1350 double d; | |
1351 float f; | |
1352 char *name; | |
1353 name = n->nm; | |
1354 if(mode!=GDECL) { | |
1355 error(-1); return; | |
1356 } | |
1357 if (chk) return; | |
1358 if (n->dsp != -1) { | |
1359 n->dsp = -1; /* initiallized flag */ | |
1360 printf(".globl\t%s\n",name); | |
1361 data_mode(name); | |
1362 align(t); | |
1363 printf("%s:\n",name); | |
1364 } else { | |
1365 data_mode(0); | |
1366 } | |
1367 if(car(e)==CONST) { | |
1368 if (t==CHAR) { | |
1369 printf("\t.byte %d\n",cadr(e)); | |
1370 if (data_alignment>0) | |
1371 data_alignment++; | |
1372 gpc += 1; | |
1373 } else if (t==SHORT) { | |
1374 printf("\t.word %d\n",cadr(e)); | |
1375 if (data_alignment>0) data_alignment++; | |
1376 gpc += 2; | |
1377 } else { | |
1378 printf("\t.long %d\n",cadr(e)); | |
1379 gpc += size_of_int; | |
1380 } | |
1381 } else if(t==DOUBLE) { | |
1382 d = dcadr(e); | |
1383 printf("\t.long\t0x%x,0x%x\n",code_d1(d),code_d2(d)); | |
1384 } else if(t==FLOAT) { | |
1385 f = dcadr(e); | |
1386 printf("\t.long\t0x%x\n",*(int *)&f); | |
1387 } else if(t!=CHAR) { | |
1388 gpc += size_of_int; | |
1389 if(car(e)==ADDRESS&&car(cadr(e))==GVAR) { | |
1390 printf("\t.long %s\n",(char *)caddr(cadr(e))); | |
1391 } else if(car(e)==FNAME) { | |
1392 printf("\t.long %s\n",((NMTBL *)cadr(e))->nm); | |
1393 } else if(car(e)==STRING) { | |
1394 if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) { | |
1395 l = fwdlabel(); | |
1396 printf("\t.long _%d\n",l); | |
1397 printf(".section\t.rodata\n"); | |
1398 printf("_%d:\n",l); | |
1399 output_mode = RODATA_EMIT_MODE; | |
1400 } | |
1401 ascii((char *)cadr(e)); | |
1402 } else error(TYERR); | |
1403 } | |
1404 } | |
1405 | |
1406 void | |
1407 emit_data_closing(NMTBL *n) | |
1408 { | |
1409 int lb; | |
1410 if (chk) return; | |
1411 if (mode==GDECL) { | |
1412 data_mode(0); | |
1413 lb=fwdlabel(); | |
1414 printf("_%d:\n",lb); | |
1415 printf("\t.size\t%s,_%d-%s\n",n->nm,lb,n->nm); | |
1416 } | |
1417 } | |
1418 | |
1419 void | |
1420 global_table(void) | |
1421 { | |
1422 NMTBL *n; | |
1423 int init; | |
1424 init=0; | |
1425 for(n=ntable;n < &ntable[GSYMS];n++) { | |
1426 if (n->sc == GVAR && n->dsp != -1) { | |
1427 /* n->dsp = -1 means initialized global */ | |
1428 if (init==0) { | |
1429 data_mode(0); | |
1430 init=1; | |
1431 } | |
1432 printf(".comm %s,%d\n",n->nm,size(n->ty)); | |
1433 } | |
1434 } | |
1435 } | |
1436 | |
1437 void | |
1438 local_table(void) | |
1439 { | |
1440 NMTBL *n; | |
1441 int init; | |
1442 init=0; | |
1443 /* static local variables */ | |
1444 for(n=ntable+GSYMS;n < &ntable[GSYMS+LSYMS];n++) { | |
1445 if (n->sc == GVAR) { | |
1446 if (init==0) { | |
1447 data_mode(0); | |
1448 init=1; | |
1449 } | |
1450 printf(".lcomm %s,%d\n",n->nm,size(n->ty)); | |
1451 } | |
1452 } | |
1453 } | |
1454 | |
1455 void | |
1456 text_mode(void) | |
1457 { | |
1458 if (output_mode!=TEXT_EMIT_MODE) { | |
1459 printf(".text\n"); | |
1460 printf("\t.align 2\n"); | |
1461 output_mode = TEXT_EMIT_MODE; | |
1462 } | |
1463 } | |
1464 | |
1465 void | |
1466 data_mode(char *name) | |
1467 { | |
1468 if (output_mode!=DATA_EMIT_MODE) { | |
1469 printf(".data\n"); | |
1470 output_mode = DATA_EMIT_MODE; | |
1471 } | |
1472 if (name) | |
1473 printf("\t.type\t%s,@object\n",name); | |
1474 } | |
1475 | |
1476 int | |
1477 lvar(int l) | |
1478 { | |
1479 if (fnptr->sc==CODE) { | |
1480 return l+code_disp_offset; | |
1481 } else if (l<0) { | |
1482 return l+disp_offset; | |
1483 } else { | |
1484 return l+arg_offset; | |
1485 } | |
1486 } | |
1487 | |
1488 /* floating point */ | |
1489 | |
1490 | |
1491 char * | |
1492 fstore(int d) | |
1493 { | |
1494 return use? | |
1495 (d?"fstl":"fsts"): | |
1496 (d?"fstpl":"fstps") | |
1497 ; | |
1498 } | |
1499 | |
1500 char * | |
1501 fstore_u(int d) | |
1502 { | |
1503 return d?"fstpl":"fstps"; | |
1504 } | |
1505 | |
1506 char * | |
1507 fload(int d) | |
1508 { | |
1509 return d?"fldl":"flds"; | |
1510 } | |
1511 | |
1512 | |
1513 void code_dassign_gvar(int e2,int d) | |
1514 { | |
1515 printf("\t%s %s\n",fstore(d),(char *)caddr(e2)) ; | |
1516 } | |
1517 | |
1518 void code_dassign_lvar(int e2,int d) | |
1519 { | |
1520 printf("\t%s %d(%%ebp)\n",fstore(d),e2); | |
1521 } | |
1522 | |
1523 void code_dassign(int e2,int d) | |
1524 { | |
1525 printf("\t%s (%s)\n",fstore(d),register_name(e2,0)); | |
1526 } | |
1527 | |
1528 static double d0 = 1.0; | |
1529 | |
1530 int | |
1531 code_d1(double d) | |
1532 { | |
1533 int *i = (int *)&d0; int *j = (int *)&d; | |
1534 return (i[1] == 0x3ff00000)?j[0]:j[1]; | |
1535 } | |
1536 | |
1537 int | |
1538 code_d2(double d) | |
1539 { | |
1540 int *i = (int *)&d0; int *j = (int *)&d; | |
1541 return (i[1] == 0x3ff00000)?j[1]:j[0]; | |
1542 } | |
1543 | |
1544 void code_dconst(int e2) | |
1545 { | |
1546 int lb; | |
1547 double d = dcadr(e2); | |
1548 | |
1549 if (d==0.0) { | |
1550 printf("\tfldz\n"); return; | |
1551 } | |
1552 if (d==1.0) { | |
1553 printf("\tfld1\n"); return; | |
1554 } | |
1555 printf(" \t.section\t.rodata\n\t.align 8\n"); | |
1556 lb=fwdlabel(); | |
1557 printf("_%d:\n",lb); | |
1558 printf("\t.long\t0x%x,0x%x\n",code_d1(d),code_d2(d)); | |
1559 if (output_mode==TEXT_EMIT_MODE) { | |
1560 printf(".text\n"); | |
1561 } else { | |
1562 text_mode(); | |
1563 } | |
1564 printf("\tfldl _%d\n",lb); | |
1565 } | |
1566 | |
1567 void code_dneg() | |
1568 { | |
1569 printf("\tfchs\n"); | |
1570 } | |
1571 | |
1572 void code_d2i() | |
1573 { | |
1574 /* fuck you! */ | |
1575 printf("\tlea -%d(%%esp),%%esp\n",size_of_int*2); | |
1576 printf("\tfnstcw (%%esp)\n"); | |
1577 printf("\tmovl (%%esp), %s\n",register_name(creg)); | |
1578 printf("\tmovb $12, 1(%%esp)\n"); | |
1579 printf("\tfldcw (%%esp)\n"); | |
1580 printf("\tmovl %s, (%%ebp)\n",register_name(creg)); | |
1581 printf("\tfistpl %d(%%esp)\n",size_of_int); | |
1582 printf("\tfldcw (%%esp)\n"); | |
1583 printf("\tpopl %s\n",register_name(creg)); | |
1584 printf("\tpopl %s\n",register_name(creg)); | |
1585 } | |
1586 | |
1587 void code_i2d() | |
1588 { | |
1589 printf("\tpushl %s\n",register_name(creg)); | |
1590 printf("\tfildl (%%esp)\n"); | |
1591 printf("\tlea %d(%%esp),%%esp\n",size_of_int); | |
1592 } | |
1593 | |
1594 void code_d2u() | |
1595 { | |
1596 /* fuck you! */ | |
1597 printf("\tlea -%d(%%esp),%%esp\n",size_of_int*3); | |
1598 printf("\tfnstcw (%%esp)\n"); | |
1599 printf("\tmovl (%%esp), %s\n",register_name(creg)); | |
1600 printf("\tmovb $12, 1(%%esp)\n"); | |
1601 printf("\tfldcw (%%esp)\n"); | |
1602 printf("\tmovl %s, (%%ebp)\n",register_name(creg)); | |
1603 printf("\tfistpll %d(%%esp)\n",size_of_int); | |
1604 printf("\tfldcw (%%esp)\n"); | |
1605 printf("\tmovl %d(%%esp),%s\n",size_of_int,register_name(creg)); | |
1606 printf("\tlea %d(%%esp),%%esp\n",size_of_int*3); | |
1607 } | |
1608 | |
1609 void code_u2d() | |
1610 { | |
1611 printf("\tpushl %s\n",register_name(creg)); | |
1612 printf("\tpushl %s\n",register_name(creg)); | |
1613 printf("\tmovl $0, %d(%%esp)\n",size_of_int); | |
1614 printf("\tfildll (%%esp)\n"); | |
1615 printf("\tlea %d(%%esp),%%esp\n",size_of_int*2); | |
1616 } | |
1617 | |
1618 void code_drgvar(int e2,int d) | |
1619 { | |
1620 printf("\t%s %s\n",fload(d),(char *)caddr(e2)) ; | |
1621 } | |
1622 | |
1623 | |
1624 void code_drlvar(int e2,int d) | |
1625 { | |
1626 printf("\t%s %d(%%ebp)\n",fload(d),e2); | |
1627 } | |
1628 | |
1629 void code_cmp_drgvar(int e2) | |
1630 { | |
1631 printf("\tfcomp %s\n",(char *)caddr(e2)) ; | |
1632 } | |
1633 | |
1634 void code_cmp_drlvar(int e2) | |
1635 { | |
1636 printf("\tfcomp %d(%%ebp)\n",e2); | |
1637 } | |
1638 | |
1639 void dtosop(int op,int e1) | |
1640 { | |
1641 switch(op) { | |
1642 case DADD: printf("\tfaddp %%st,%%st(1)\n"); break; | |
1643 case DSUB: printf("\tfsubp %%st,%%st(1)\n"); break; | |
1644 case DDIV: printf("\tfdivp %%st,%%st(1)\n"); break; | |
1645 case DMUL: printf("\tfmulp %%st,%%st(1)\n"); break; | |
1646 case DCOMP: | |
1647 /* printf("\tfxch\t%%st(1)\n"); */ | |
1648 printf("\tfucompp\n"); | |
1649 printf("\tfnstsw\t%%ax\n"); | |
1650 break; | |
1651 } | |
1652 } | |
1653 | |
1654 void | |
1655 code_dassop(int op,int d) { | |
1656 /* we have lvalue in creg, applied floating value is in %st(0) */ | |
1657 printf("\t%s (%s)\n",fload(d),register_name(creg)); | |
1658 dtosop(op,0); | |
1659 printf("\t%s (%s)\n",fstore(d),register_name(creg)); | |
1660 } | |
1661 | |
1662 void | |
1663 code_dpreinc(int e1,int e2,int d) { | |
1664 g_expr(e2); | |
1665 printf("\t%s (%s)\n",fload(d),register_name(creg)); | |
1666 printf("\tfld1\n"); | |
1667 if (caddr(e1)>0) | |
1668 printf("\tfaddp %%st,%%st(1)\n"); | |
1669 else | |
1670 printf("\tfsubrp %%st,%%st(1)\n"); | |
1671 printf("\t%s (%s)\n",fstore(d),register_name(creg)); | |
1672 } | |
1673 | |
1674 void | |
1675 code_dpostinc(int e1,int e2,int d) { | |
1676 g_expr(e2); | |
1677 printf("\t%s (%s)\n",fload(d),register_name(creg)); | |
1678 if (use) | |
1679 printf("\t%s (%s)\n",fload(d),register_name(creg)); | |
1680 printf("\tfld1\n"); | |
1681 if (caddr(e1)>0) | |
1682 printf("\tfaddp %%st,%%st(1)\n"); | |
1683 else | |
1684 printf("\tfsubrp %%st,%%st(1)\n"); | |
1685 printf("\t%s (%s)\n",(use?fstore_u(d):fstore(d)),register_name(creg)); | |
1686 } | |
1687 | |
1688 void | |
1689 drexpr(int e1, int e2,int l1, int op) | |
1690 { | |
1691 g_expr(list3(DCOMP,e1,e2)); | |
1692 switch(op) { | |
1693 case DOP+GE: | |
1694 printf("\ttestb\t$5,%%ah\n"); | |
1695 printf("\tjne\t_%d\n",l1); | |
1696 break; | |
1697 case DOP+GT: | |
1698 printf("\ttestb\t$69,%%ah\n"); | |
1699 printf("\tjne\t_%d\n",l1); | |
1700 break; | |
1701 case DOP+EQ: | |
1702 printf("\tandb\t$69,%%ah\n"); | |
1703 printf("\txorb\t$64,%%ah\n"); | |
1704 printf("\tjne\t_%d\n",l1); | |
1705 break; | |
1706 case DOP+NEQ: | |
1707 printf("\tandb\t$69,%%ah\n"); | |
1708 printf("\txorb\t$64,%%ah\n"); | |
1709 printf("\tje\t_%d\n",l1); | |
1710 break; | |
1711 } | |
1712 } | |
1713 | |
1714 int dpop_register() | |
1715 { | |
1716 return 1; | |
1717 } | |
1718 | |
1719 int emit_dpop(int e1) | |
1720 { | |
1721 return 1; | |
1722 } | |
1723 | |
1724 void emit_dpop_free(int e1) | |
1725 { | |
1726 } | |
1727 | |
1728 void emit_dpush() | |
1729 { | |
1730 } | |
1731 | |
1732 /* end */ | |
1733 |