Mercurial > hg > CbC > old > device
comparison mc-codegen.c @ 61:8ffb8ca3fe34
separation of architecture dependent part.
author | kono |
---|---|
date | Thu, 20 Feb 2003 03:29:15 +0900 |
parents | |
children | 0b068058dd67 |
comparison
equal
deleted
inserted
replaced
60:aa779bcffef7 | 61:8ffb8ca3fe34 |
---|---|
1 /* Micro-C Generic Code Generatation Part */ | |
2 /* $Id$ */ | |
3 | |
4 #define EXTERN extern | |
5 #include "mc.h" | |
6 #include "mc-codegen.h" | |
7 #include "mc-code.h" | |
8 | |
9 int creg; /* current register */ | |
10 int dreg; /* temporary register */ | |
11 int reg_sp; /* REGister Stack-Pointer */ | |
12 | |
13 /* | |
14 creg currrent virtual register | |
15 dreg spare virtual register | |
16 | |
17 rname[creg] currrent real register | |
18 rname[dreg] spare real register | |
19 | |
20 regs[] virtual register usage | |
21 regv[] value in virtual register flag | |
22 | |
23 reg_name[rname[creg]] | |
24 */ | |
25 | |
26 void remove0(int *parent,int e) ; | |
27 void remove0_all(int *parent,int e) ; | |
28 int is_same_type(int e1,int e2); | |
29 void jump(int e1, int env); | |
30 void machinop(int e1); | |
31 void sassign(int e1); | |
32 void assign(int e1); | |
33 void assop(int e1); | |
34 | |
35 int | |
36 get_register(void) | |
37 { /* 使われていないレジスタを調べる */ | |
38 int i; | |
39 for(i=0;i<MAX_REGISTER;i++) { | |
40 if (! regs[i]) { /* 使われていないなら */ | |
41 regs[i]=1; /* そのレジスタを使うことを宣言し */ | |
42 return i; /* その場所を表す番号を返す */ | |
43 } | |
44 } | |
45 return -1; /* 空いている場所がないなら、それを表す -1 を返す */ | |
46 } | |
47 | |
48 void | |
49 free_register(int i) { /* いらなくなったレジスタを開放 */ | |
50 regv[i]=regs[i]=0; | |
51 } | |
52 | |
53 int | |
54 register_full(void) | |
55 { | |
56 int i; | |
57 for(i=0;i<MAX_REGISTER;i++) { | |
58 if (! regs[i]) { | |
59 return 0; | |
60 } | |
61 } | |
62 return 1; | |
63 } | |
64 | |
65 int | |
66 free_register_count(void) | |
67 { | |
68 int i,count; | |
69 count = 0; | |
70 for(i=0;i<MAX_REGISTER;i++) { | |
71 if (! regs[i] && ! regv[i]) count++; | |
72 } | |
73 return count; | |
74 } | |
75 | |
76 void | |
77 free_all_register(void) | |
78 { | |
79 int i; | |
80 for(i=0;i<MAX_REGISTER;i++) { | |
81 regs[i]=regv[i]=0; | |
82 } | |
83 creg = get_register(); | |
84 dreg = get_register(); | |
85 return; | |
86 } | |
87 | |
88 void | |
89 use_register_var(int i) { | |
90 regv[i]=1; | |
91 } | |
92 | |
93 int creg_regvar = -1; | |
94 static int creg_regvar_back; | |
95 static int creg_back; | |
96 | |
97 void | |
98 creg_destroy() { | |
99 creg_back = creg; creg_regvar_back = creg_regvar; | |
100 if (creg_regvar>=0) | |
101 creg = creg_regvar; | |
102 creg_regvar=-1; | |
103 } | |
104 | |
105 void | |
106 creg_un_destroy() { | |
107 creg = creg_back; creg_regvar = creg_regvar_back; | |
108 } | |
109 | |
110 void | |
111 register_usage(char *s) | |
112 { | |
113 int i; | |
114 printf("# %d: %s:",lineno,s); | |
115 printf(" creg=%s dreg=%s ",register_name(creg,0),register_name(dreg,0)); | |
116 for(i=0;i<MAX_REGISTER;i++) { | |
117 printf("%d",regs[i]); | |
118 } | |
119 printf(":"); | |
120 for(i=0;i<MAX_REGISTER;i++) { | |
121 printf("%d",regv[i]); | |
122 } | |
123 #if 0 | |
124 printf(" regs_stack",register_name(creg,0),register_name(dreg,0)); | |
125 for(i=reg_sp;i>=0;i--) { | |
126 if(reg_stack[i]>=0) | |
127 printf(" %s",register_name(reg_stack[i],0)); | |
128 } | |
129 #endif | |
130 printf("\n"); | |
131 } | |
132 | |
133 void | |
134 gexpr_init(void) | |
135 { | |
136 while(reg_sp > 0) { | |
137 free_register(reg_stack[--reg_sp]); | |
138 } | |
139 text_mode(); | |
140 gexpr_code_init(); | |
141 register_usage("gexpr_init"); | |
142 } | |
143 | |
144 | |
145 void | |
146 emit_init(void) | |
147 { | |
148 int i; | |
149 for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; regv[i]=0;rname[i]=i;} | |
150 free_all_register(); | |
151 reg_sp = 0; | |
152 text_mode(); | |
153 } | |
154 | |
155 int | |
156 virtual(int real) | |
157 { | |
158 int real_v,i; | |
159 real_v = -1; | |
160 for(i=0;i<MAX_REGISTER;i++) { | |
161 if (rname[i]==real) { | |
162 real_v=i; | |
163 break; | |
164 } | |
165 } | |
166 return real_v; | |
167 } | |
168 | |
169 int | |
170 pop_register(void) | |
171 { /* レジスタから値を取り出す */ | |
172 return reg_stack[--reg_sp]; | |
173 } | |
174 | |
175 int | |
176 stack_used(void) { | |
177 return reg_stack[--reg_sp]<0; | |
178 } | |
179 | |
180 void | |
181 emit_pop_free(int xreg) | |
182 { | |
183 if (xreg==dreg) { | |
184 regv[dreg]=0; | |
185 } else if (xreg!=-1) { | |
186 free_register(xreg); | |
187 } | |
188 } | |
189 | |
190 void | |
191 gexpr(int e1) | |
192 { | |
193 gexpr_init(); | |
194 #if 0 | |
195 if(lineno==2862) { | |
196 g_expr(e1); /*break here*/ | |
197 return; | |
198 } | |
199 #endif | |
200 g_expr(e1); | |
201 } | |
202 | |
203 int | |
204 csvalue() | |
205 { | |
206 return rname[creg]; /* for switch value */ | |
207 } | |
208 | |
209 void | |
210 g_expr(int e1) | |
211 { | |
212 int e2,e3/*,e4*/; | |
213 NMTBL *n; | |
214 | |
215 if (chk) return; | |
216 e2 = cadr(e1); | |
217 switch (car(e1)){ | |
218 case GVAR: | |
219 code_gvar(e1); | |
220 regv[creg]=1; | |
221 return; | |
222 case RGVAR: | |
223 code_rgvar(e1); | |
224 regv[creg]=1; | |
225 return; | |
226 case CRGVAR: | |
227 code_crgvar(e1); | |
228 regv[creg]=1; | |
229 return; | |
230 case LVAR: | |
231 code_lvar(lvar(e2)); | |
232 regv[creg]=1; | |
233 return; | |
234 case REGISTER: | |
235 /* this is of course redundant... */ | |
236 /* we can use rname for this? */ | |
237 /* or why not creg=e2? */ | |
238 code_register(e2); | |
239 regv[creg]=1; | |
240 return; | |
241 case RLVAR: | |
242 code_rlvar(lvar(e2)); | |
243 regv[creg]=1; | |
244 return; | |
245 case CRLVAR: | |
246 code_crlvar(lvar(e2)); | |
247 regv[creg]=1; | |
248 return; | |
249 case FNAME: | |
250 code_fname(((NMTBL *)(e2))->nm); | |
251 regv[creg]=1; | |
252 return; | |
253 case CONST: /* 代入する値が0でも特別な処理はしない */ | |
254 code_const(e2); | |
255 regv[creg]=1; | |
256 return; | |
257 case STRING: | |
258 string(e1); | |
259 regv[creg]=1; | |
260 return; | |
261 case FUNCTION: | |
262 function(e1); | |
263 regv[creg]=1; | |
264 return; | |
265 case CODE: | |
266 jump(e2,caddr(e1)); | |
267 return; | |
268 case INDIRECT: | |
269 g_expr(e2); | |
270 return; | |
271 case RINDIRECT: case CRINDIRECT: | |
272 rindirect(e1); | |
273 return; | |
274 case ADDRESS: | |
275 g_expr(e2); | |
276 return; | |
277 case MINUS: /* レジスタに対し、neglを実行すれば実現可能 */ | |
278 g_expr(e2); | |
279 code_neg(); | |
280 return; | |
281 case BNOT: /* ~ */ | |
282 g_expr(e2); | |
283 code_not(); | |
284 return; | |
285 case LNOT: /* ! */ | |
286 g_expr(e2); | |
287 code_lnot(); | |
288 return; | |
289 case PREINC: | |
290 code_preinc(e1,e2); | |
291 return; | |
292 case POSTINC: | |
293 code_postinc(e1,e2); | |
294 return; | |
295 case CPOSTINC: | |
296 /* char *p; *p++ */ | |
297 code_cpostinc(e1,e2); | |
298 return; | |
299 case CPREINC: | |
300 code_cpreinc(e1,e2); | |
301 return; | |
302 case CPOSTDEC: | |
303 code_cpostdec(e1,e2); | |
304 return; | |
305 case CPREDEC: | |
306 code_cpredec(e1,e2); | |
307 return; | |
308 case MUL: case UMUL: | |
309 case DIV: case UDIV: | |
310 case MOD: case UMOD: | |
311 case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT: | |
312 case ADD: case SUB: case BAND: case EOR: case BOR: | |
313 machinop(e1); | |
314 return; | |
315 case COND: | |
316 e2=fwdlabel(); | |
317 b_expr(cadr(e1),0,e2,0); | |
318 code_set_fixed_creg(0); | |
319 g_expr(caddr(e1)); | |
320 /* e4 = rname[creg]; this is a bad idea */ | |
321 code_set_fixed_creg(1); | |
322 jmp(e3=fwdlabel()); | |
323 fwddef(e2); | |
324 code_set_fixed_creg(0); | |
325 g_expr(cadddr(e1)); | |
326 code_set_fixed_creg(1); | |
327 fwddef(e3); | |
328 return; | |
329 case SASS: | |
330 sassign(e1); | |
331 return; | |
332 case ASS: case CASS: | |
333 assign(e1); | |
334 return; | |
335 case ASSOP: case CASSOP: | |
336 assop(e1); | |
337 return; | |
338 case RSTRUCT: | |
339 g_expr(e2); | |
340 return; | |
341 case COMMA: | |
342 g_expr(e2); | |
343 g_expr(caddr(e1)); | |
344 return; | |
345 case RETURN: | |
346 n = (NMTBL *)e2; | |
347 if (retcont==0) | |
348 retcont=fwdlabel(); | |
349 code_return(creg); | |
350 regv[creg]=1; | |
351 return; | |
352 case ENVIRONMENT: | |
353 code_environment(creg); | |
354 regv[creg]=1; | |
355 return; | |
356 default: | |
357 code_bool(e1); | |
358 regv[creg]=1; | |
359 } | |
360 } | |
361 | |
362 void | |
363 bexpr(int e1, char cond, int l1) | |
364 { | |
365 gexpr_init(); | |
366 b_expr(e1,cond,l1,0); | |
367 } | |
368 | |
369 void | |
370 b_expr(int e1, char cond, int l1,int err) | |
371 { | |
372 int e2,l2; | |
373 if (chk) return; | |
374 e2=cadr(e1); | |
375 switch(car(e1)) { | |
376 case LNOT: | |
377 b_expr(e2,!cond,l1,0); | |
378 return; | |
379 case GT: | |
380 rexpr(e1,l1,code_gt(cond)); | |
381 return; | |
382 case UGT: | |
383 rexpr(e1,l1,code_ugt(cond)); | |
384 return; | |
385 case GE: | |
386 rexpr(e1,l1,code_ge(cond)); | |
387 return; | |
388 case UGE: | |
389 rexpr(e1,l1,code_uge(cond)); | |
390 return; | |
391 case LT: | |
392 rexpr(e1,l1,code_ge(!cond)); | |
393 return; | |
394 case ULT: | |
395 rexpr(e1,l1,code_uge(!cond)); | |
396 return; | |
397 case LE: | |
398 rexpr(e1,l1,code_gt(!cond)); | |
399 return; | |
400 case ULE: | |
401 rexpr(e1,l1,code_ugt(!cond)); | |
402 return; | |
403 case EQ: | |
404 rexpr(e1,l1,code_eq(cond)); | |
405 return; | |
406 case NEQ: | |
407 rexpr(e1,l1,code_eq(!cond)); | |
408 return; | |
409 case LAND: | |
410 b_expr(e2,0,cond?(l2=fwdlabel()):l1,0); | |
411 b_expr(caddr(e1),cond,l1,0); | |
412 if(cond) fwddef(l2); | |
413 return; | |
414 case LOR: | |
415 b_expr(e2,1,cond?l1:(l2=fwdlabel()),0); | |
416 b_expr(caddr(e1),cond,l1,0); | |
417 if(!cond) fwddef(l2); | |
418 return; | |
419 case CRGVAR: | |
420 code_cmp_crgvar(e1); | |
421 jcond(l1,cond); | |
422 return; | |
423 case CRLVAR: | |
424 code_cmp_crlvar(lvar(e2)); | |
425 jcond(l1,cond); | |
426 return; | |
427 case RGVAR: | |
428 code_cmp_rgvar(e1); | |
429 jcond(l1,cond); | |
430 return; | |
431 case RLVAR: | |
432 code_cmp_rlvar(lvar(e2)); | |
433 jcond(l1,cond); | |
434 return; | |
435 case REGISTER: | |
436 code_cmp_register(e2); | |
437 jcond(l1,cond); | |
438 return; | |
439 case CONST: | |
440 if((cond&&e2)||(!cond&&!e2)) jmp(l1); | |
441 return; | |
442 default: | |
443 if(err) { | |
444 error(-1); return; /* recursice g_expr/b_expr */ | |
445 } | |
446 g_expr(e1); | |
447 code_cmp_register(creg); | |
448 jcond(l1,cond); | |
449 return; | |
450 } | |
451 } | |
452 | |
453 | |
454 /* goto arguments list */ | |
455 /* target list4(list2(tag,disp),cdr,ty,source_expr) */ | |
456 /* source expr=listn(tag,...) */ | |
457 /* source (after) list2(tag,disp) */ | |
458 /* source list list3(e,cdr,sz) */ | |
459 | |
460 #define DEBUG_PARALLEL_ASSIGN 1 | |
461 | |
462 int | |
463 overrap(int t,int sz,int source) | |
464 { | |
465 int s,s0,s1; | |
466 int t0=cadr(t); | |
467 int t1=t0+sz; | |
468 for(;source;source=cadr(source)) { | |
469 s=car(source); s0=cadr(s); | |
470 if(car(s)==REGISTER && car(t)==REGISTER) { | |
471 if(s0==t0) return s; | |
472 } else if (is_same_type(s,t)) { | |
473 s1=s0+caddr(source); | |
474 #if DEBUG_PARALLEL_ASSIGN>1 | |
475 printf("# ovedrrap source %d t0 %d t1 %d\n",car(car(t)),t0,t1); | |
476 printf("# ovedrrap target %d s0 %d s1 %d\n",car(car(source)),s0,s1); | |
477 printf("# ovedrrap equal = %d\n",((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1))); | |
478 #endif | |
479 if((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1)) return s; | |
480 } | |
481 } | |
482 return 0; | |
483 } | |
484 | |
485 void | |
486 remove_target(int *target,int t,int *use) | |
487 { | |
488 int use0=*use; | |
489 while(use0) { | |
490 if (car(use0)==t) { | |
491 free_register(caddr(use0)); | |
492 break; | |
493 } | |
494 use0 = cadr(use0); | |
495 } | |
496 remove0(target,t); | |
497 } | |
498 | |
499 void | |
500 save_target(int t,int s,int *target,int *use,int sz,int ty) | |
501 { | |
502 int e1; | |
503 /*新しいレジスタ(or スタック)を取得する*/ | |
504 if (sz==size_of_int && (e1=get_register())!=-1) { | |
505 *use=list3(t,*use,e1); | |
506 e1=list2(REGISTER,e1); | |
507 g_expr(assign_expr0(e1,s,ty,ty)); | |
508 *target = append4(*target,t,ty,e1); | |
509 } else { | |
510 disp-=sz; | |
511 g_expr(assign_expr0((e1=list2(LVAR,disp)),s,ty,ty)); | |
512 *target = append4(*target,t,ty,e1); | |
513 } | |
514 } | |
515 | |
516 int | |
517 circular_dependency(int t,int s,int *target,int *source) | |
518 { | |
519 int target0=*target; | |
520 int t1,sz,ty,s1; | |
521 while(target0) { | |
522 if (cadddr(target0)==s) { | |
523 t1=car(target0); | |
524 s=cadddr(target0); | |
525 sz=size(ty=caddr(target0)); | |
526 if(t==t1) { | |
527 #if DEBUG_PARALLEL_ASSIGN | |
528 printf("# circular dependency %d ty %d+%d sz %d\n",car(t1),ty,cadr(t1),sz); | |
529 #endif | |
530 return 1; | |
531 } | |
532 if ((s1=overrap(t1,sz,*source))) { | |
533 /* another overrap start over */ | |
534 return circular_dependency(t,s1,target,source); | |
535 } | |
536 } | |
537 target0=cadr(target0); | |
538 } | |
539 return 0; | |
540 } | |
541 | |
542 void | |
543 parallel_assign(int *target,int *source,int *processing,int *use) | |
544 { | |
545 int t,s,sz,ty,target0,s1; | |
546 while(*target) { | |
547 target0=*target; | |
548 while(target0) { | |
549 t=car(target0); s=cadddr(target0); | |
550 sz=size(ty=caddr(target0)); | |
551 if(car(t)==car(s) && cadr(t)==cadr(s)) { | |
552 /*書き込み先が自分自身*/ | |
553 #if DEBUG_PARALLEL_ASSIGN | |
554 printf("# remove same %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); | |
555 #endif | |
556 remove_target(target,t,use); | |
557 /* 破壊されては困るので、source listからは除かない */ | |
558 } else if (!(s1=overrap(t,sz,*source))) { | |
559 /* 重なってないので安心して書き込める */ | |
560 #if DEBUG_PARALLEL_ASSIGN | |
561 printf("# normal assign %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); | |
562 #endif | |
563 g_expr(assign_expr0(t,s,ty,ty)); | |
564 remove_target(target,t,use); remove0(source,s); | |
565 } else { | |
566 if(circular_dependency(t,s1,target,source)) { | |
567 #if DEBUG_PARALLEL_ASSIGN | |
568 printf("# saving %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); | |
569 #endif | |
570 remove_target(target,t,use); remove0(source,s); | |
571 save_target(t,s,target,use,sz,ty); | |
572 } | |
573 } | |
574 target0=cadr(target0); | |
575 } | |
576 } | |
577 } | |
578 | |
579 void | |
580 remove0(int *parent,int e) | |
581 { | |
582 int list; | |
583 while ((list=*parent)) { | |
584 if (car(list)==e) { | |
585 *parent= cadr(list); return; | |
586 } else { | |
587 parent=&cadr(list); | |
588 } | |
589 } | |
590 } | |
591 | |
592 void | |
593 remove0_all(int *parent,int e) | |
594 { | |
595 int list; | |
596 while ((list=*parent)) { | |
597 if (car(list)==e) { | |
598 *parent= cadr(list); | |
599 } else { | |
600 parent=&cadr(list); | |
601 } | |
602 } | |
603 } | |
604 | |
605 int | |
606 is_simple(int e1) | |
607 { | |
608 return ( | |
609 e1==CONST || e1==FNAME || e1==LVAR || e1==REGISTER || | |
610 e1==GVAR || e1==RGVAR || e1==RLVAR || e1==CRLVAR || e1==CRGVAR | |
611 ); | |
612 } | |
613 | |
614 int | |
615 is_same_type(int e1,int e2) | |
616 { | |
617 int ce1=car(e1); | |
618 int ce2=car(e2); | |
619 return ( | |
620 (ce1==LVAR && (ce2==RLVAR||ce2==CRLVAR)) | |
621 || (ce2==LVAR && (ce1==RLVAR||ce1==CRLVAR)) | |
622 || (ce1==GVAR && (ce2==RGVAR||ce2==CRGVAR)) | |
623 || (ce2==GVAR && (ce1==RGVAR||ce1==CRGVAR)) | |
624 ); | |
625 } | |
626 | |
627 int | |
628 is_memory(int e1) | |
629 { | |
630 int ce1=car(e1); | |
631 return ( | |
632 ce1==LVAR ||ce1==RLVAR||ce1==CRLVAR || | |
633 ce1==GVAR ||ce1==RGVAR||ce1==CRGVAR || | |
634 ce1==REGISTER | |
635 ); | |
636 } | |
637 | |
638 void | |
639 jump(int e1, int env) | |
640 { | |
641 int e2,e3,e4,sz,arg_size,ty,max_regs,regs; | |
642 int t0,s0; | |
643 NMTBL *code0; | |
644 int target = 0; | |
645 int source = 0; | |
646 int processing = 0; | |
647 int use = 0; | |
648 | |
649 /* まず、サイズを計算しながら、決まった形に落す。 */ | |
650 | |
651 arg_size = 0; regs = 0; max_regs = MAX_REGISTER_VAR-1; | |
652 for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { | |
653 e2 = car(e3); sz = size(ty=caddr(e3)); | |
654 if (regs <= max_regs&&scalar(ty)) { | |
655 target=list4(list2(REGISTER,register_var(regs++)), target,ty,e2); | |
656 } else { | |
657 target=list4(list2(LVAR,0), target,ty,e2); | |
658 arg_size += sz; | |
659 } | |
660 #if DEBUG_PARALLEL_ASSIGN | |
661 printf("# target %d ty %d+%d sz %d\n",car(car(target)),ty,cadr(car(target)),sz); | |
662 #endif | |
663 } | |
664 | |
665 /* disp を飛び先似合わせて修正 */ | |
666 if (fnptr->sc==CODE) { | |
667 if (-arg_size<disp) disp = -arg_size; | |
668 } else { | |
669 if (disp_offset-arg_size<disp) disp = disp_offset-arg_size; | |
670 } | |
671 | |
672 /* 複雑な式を前もって計算しておく */ | |
673 /* 必要なら局所変数を用いる。 */ | |
674 /* 局所変数へのオフセットを覚えておく */ | |
675 | |
676 for (e2 = target; e2; e2 = cadr(e2)) { | |
677 t0=car(e2); s0=cadddr(e2); | |
678 sz=size(ty=caddr(e2)); | |
679 if(car(t0)==LVAR) { | |
680 /* ここで、書込先アドレスを決める */ | |
681 cadr(t0)=-arg_size; | |
682 arg_size-=sz; | |
683 } | |
684 if (!is_simple(car(s0))) { | |
685 disp-=sz; | |
686 g_expr(assign_expr0((e4=list2(LVAR,disp)),s0,ty,ty)); | |
687 cadddr(e2)=e4; | |
688 s0=e4; | |
689 } else if (is_same_type(t0,s0)) { | |
690 if(cadr(t0)==cadr(s0)) { | |
691 #if DEBUG_PARALLEL_ASSIGN | |
692 printf("# remove same memory %d ty %d+%d sz %d\n",car(t0),ty,cadr(t0),sz); | |
693 #endif | |
694 /* we should check size also (but currently useless */ | |
695 remove0(&target,t0); | |
696 /* still we have source to avoid overwrite */ | |
697 } | |
698 } | |
699 if(is_memory(s0)) { | |
700 source=list3(s0,source,sz); | |
701 #if DEBUG_PARALLEL_ASSIGN | |
702 printf("# source %d ty %d+%d sz %d\n",car(car(source)),ty,cadr(car(source)),sz); | |
703 #endif | |
704 } | |
705 } | |
706 | |
707 /* compute jump address */ | |
708 e2 = cadr(e1); | |
709 if (car(e2) == FNAME) { | |
710 code0=(NMTBL *)cadr(e2); | |
711 if (code0->sc!=CODE) { | |
712 error(TYERR); return; | |
713 } | |
714 } else { /* indirect */ | |
715 g_expr(e2); | |
716 emit_push(); | |
717 } | |
718 if (env) { | |
719 g_expr(env); | |
720 emit_push(); | |
721 } | |
722 | |
723 /* 並列代入を実行 */ | |
724 | |
725 parallel_assign(&target,&source,&processing,&use); | |
726 while (use) { | |
727 free_register(caddr(use)); use=cadr(use); | |
728 } | |
729 if(target) error(-1); | |
730 | |
731 if (env) { | |
732 /* change the frame pointer */ | |
733 e3 = emit_pop(0); | |
734 code_frame_pointer(e3); | |
735 emit_pop_free(e3); | |
736 } else if (fnptr->sc==FUNCTION) { | |
737 code_fix_frame_pointer(disp_offset); | |
738 } | |
739 | |
740 if (car(e2) == FNAME) { | |
741 code_jmp(code0->nm); | |
742 } else { | |
743 e2 = emit_pop(0); | |
744 code_indirect_jmp(e2); | |
745 emit_pop_free(e2); | |
746 } | |
747 } | |
748 | |
749 void | |
750 machinop(int e1) | |
751 { | |
752 int e2,e3,op; | |
753 | |
754 e2 = cadr(e1); | |
755 op = car(e1); | |
756 e3 = caddr(e1); | |
757 g_expr(e3); | |
758 emit_push(); | |
759 g_expr(e2); | |
760 tosop(car(e1),(e2=pop_register())); | |
761 emit_pop_free(e2); | |
762 regv[creg]=1; | |
763 return; | |
764 } | |
765 | |
766 | |
767 void | |
768 sassign(int e1) | |
769 { | |
770 int e2,e3,e4,sz,xreg,det; | |
771 | |
772 /* structure assignment */ | |
773 e2 = cadr(e1); /* pointer variable to the struct */ | |
774 e3 = cadr(e2); /* offset of the variable (distination) */ | |
775 e4 = caddr(e1); /* right value (source) */ | |
776 sz = cadddr(e1); /* size of struct or union */ | |
777 g_expr(e4); | |
778 emit_push(); | |
779 g_expr(e2); | |
780 xreg = emit_pop(0); | |
781 /* 一般的にはコピーのオーバラップの状況は実行時にしかわからない */ | |
782 /* しかし、わかる場合もある */ | |
783 if (car(e4)==RSTRUCT) e4=cadr(e4); | |
784 if (is_same_type(e2,e4)) { | |
785 if(cadr(e2)<cadr(e4)) sz=-sz; | |
786 det=1; | |
787 } else { | |
788 det = 0; | |
789 } | |
790 emit_copy(xreg,creg,sz,0,1,det); | |
791 emit_pop_free(xreg); | |
792 return; | |
793 } | |
794 | |
795 void | |
796 assign(int e1) | |
797 { | |
798 int e2,e3,e4,byte; | |
799 | |
800 byte=(car(e1) == CASS); | |
801 /* e2=e4 */ | |
802 e2 = cadr(e1); | |
803 e3 = cadr(e2); | |
804 e4 = caddr(e1); | |
805 switch(car(e2)) { | |
806 case GVAR: /* i=3 */ | |
807 g_expr(e4); | |
808 code_assign_gvar(e2,byte); | |
809 return; | |
810 case LVAR: | |
811 g_expr(e4); | |
812 code_assign_lvar(lvar(cadr(e2)),byte); | |
813 return; | |
814 case REGISTER: | |
815 g_expr(e4); | |
816 if (creg!=cadr(e2)) | |
817 code_assign_register(cadr(e2),byte); | |
818 return; | |
819 } | |
820 g_expr(e2); | |
821 emit_push(); | |
822 use_data_reg(creg,0); | |
823 g_expr(e4); | |
824 if (byte) use_data_reg(creg,1); | |
825 e2 = emit_pop(0); | |
826 code_assign(e2,byte); | |
827 emit_pop_free(e2); | |
828 regv[creg]=1; | |
829 return; | |
830 } | |
831 | |
832 void | |
833 assop(int e1) | |
834 { | |
835 int e2,e3,byte,op; | |
836 | |
837 /* e2 op= e3 */ | |
838 byte = (car(e1) == CASSOP); | |
839 e2 = cadr(e1); | |
840 if (car(e2)==INDIRECT) e2=cadr(e2); | |
841 e3 = caddr(e1); | |
842 op = cadddr(e1); | |
843 | |
844 g_expr(e3); | |
845 if (car(e2)==REGISTER) { | |
846 code_register_assop(cadr(e2),op,byte); | |
847 regv[creg]=1; | |
848 return; | |
849 } | |
850 emit_push(); | |
851 g_expr(e2); | |
852 code_assop(op,byte); | |
853 regv[creg]=1; | |
854 return; | |
855 } | |
856 | |
857 | |
858 int | |
859 fwdlabel(void) | |
860 { | |
861 return labelno++; | |
862 } | |
863 | |
864 void | |
865 fwddef(int l) | |
866 { | |
867 control=1; | |
868 printf("_%d:\n",l); | |
869 } | |
870 | |
871 int | |
872 backdef(void) | |
873 { | |
874 control=1; | |
875 printf("_%d:\n",labelno); | |
876 return labelno++; | |
877 } | |
878 | |
879 void | |
880 def_label(int cslabel, int dlabel) | |
881 { | |
882 int fl; | |
883 | |
884 fl = 0; | |
885 if (control) { | |
886 jmp(fl=fwdlabel()); | |
887 } | |
888 fwddef(cslabel); | |
889 if (dlabel) | |
890 jmp(dlabel); | |
891 if (fl) { | |
892 fwddef(fl); | |
893 } | |
894 } | |
895 | |
896 void | |
897 gen_source(char *s) | |
898 { | |
899 printf("%s",s); | |
900 } | |
901 | |
902 void | |
903 ret(void) | |
904 { | |
905 code_set_fixed_creg(1); | |
906 jmp(retlabel); | |
907 } | |
908 | |
909 /* end */ |