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