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 */