Mercurial > hg > CbC > old > device
view mc-codegen.c @ 111:7aa449aff3e6
floating point
author | kono |
---|---|
date | Wed, 19 Mar 2003 18:33:25 +0900 |
parents | e09f9de6f5d3 |
children | b14ff9671c90 |
line wrap: on
line source
/* Micro-C Generic Code Generatation Part */ /* $Id$ */ #define EXTERN extern #include "mc.h" #include "mc-codegen.h" #include "mc-code.h" int creg; /* current register */ int reg_sp; /* REGister Stack-Pointer */ int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ /* floating point registers */ int freg; /* current floating point register */ int freg_sp; /* floating point REGister Stack-Pointer */ int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ int use; /* generated value will be used */ /* creg currrent virtual register regs[] virtual register usage regv[] value in virtual register flag freg current floating point register fregv calue in floating point register */ static void remove0(int *parent,int e) ; /* static void remove0_all(int *parent,int e) ; */ static int is_same_type(int e1,int e2); static void jump(int e1, int env); static void machinop(int e1); static void sassign(int e1); static void assign(int e1); static void assop(int e1); static int g_expr0(int e1); static int register_to_lvar(int e); void codegen_init() { code_init(); } int gexpr(int e1,int use0) { if (chk) return INT; gexpr_init(); use = use0; #if 0 if(lineno==2862) { return g_expr0(e1); /*break here*/ } #endif return g_expr0(e1); } int g_expr_u(int e1) { int t; int suse = use; use=0; t=g_expr0(e1); use=suse; return t; } int g_expr(int e1) { int t; int suse = use; use=1; t=g_expr0(e1); use=suse; return t; } int g_expr0(int e1) { int e2,e3,t; NMTBL *n; e2 = cadr(e1); switch (car(e1)){ case GVAR: code_gvar(e1,creg); return ADDRESS; case RGVAR: code_rgvar(e1,creg); return INT; case CRGVAR: code_crgvar(e1,creg); return CHAR; case LVAR: code_lvar(lvar(e2),creg); return ADDRESS; case REGISTER: code_register(e2,creg); return INT; case DREGISTER: code_fregister(e2,freg); return DOUBLE; case RLVAR: code_rlvar(lvar(e2),creg); return INT; case CRLVAR: code_crlvar(lvar(e2),creg); return CHAR; case FRLVAR: code_drlvar(lvar(e2),0,freg); return FLOAT; case FRGVAR: code_drgvar(e1,0,freg); return FLOAT; case DRLVAR: code_drlvar(lvar(e2),1,freg); return DOUBLE; case DRGVAR: code_drgvar(e1,1,freg); return DOUBLE; case FNAME: code_fname((NMTBL *)(e2),creg); return ADDRESS; case CONST: /* 代入する値が0でも特別な処理はしない */ code_const(e2,creg); return INT; case DCONST: code_dconst(e1,freg); return DOUBLE; case STRING: code_string(e1,creg); return ADDRESS; case FUNCTION: t = function(e1); return t; case CODE: jump(e2,caddr(e1)); return VOID; case INDIRECT: return g_expr0(e2); case RINDIRECT: case CRINDIRECT: case DRINDIRECT: case FRINDIRECT: return rindirect(e1); case ADDRESS: if (car(e2)==REGISTER||car(e2)==DREGISTER) return register_to_lvar(e2); else return g_expr0(e2); case MINUS: /* レジスタに対し、neglを実行すれば実現可能 */ g_expr0(e2); code_neg(creg); return INT; case DMINUS: g_expr0(e2); code_dneg(freg); return DOUBLE; case CONV: g_expr0(e2); switch(caddr(e1)) { case I2D: code_i2d(creg,freg); return DOUBLE; case D2I: code_d2i(freg,creg); return INT; case U2D: code_u2d(creg,freg); return DOUBLE; case D2U: code_d2u(freg,creg); return UNSIGNED; default: error(-1); return INT; } case BNOT: /* ~ */ g_expr0(e2); code_not(creg); return INT; case LNOT: /* ! */ g_expr0(e2); code_lnot(creg); return INT; case PREINC: code_preinc(e1,e2,creg); return INT; case POSTINC: code_postinc(e1,e2,creg); return INT; case DPREINC: code_dpreinc(e1,e2,1,freg); return DOUBLE; case DPOSTINC: code_dpostinc(e1,e2,1,freg); return DOUBLE; case FPREINC: code_dpreinc(e1,e2,0,freg); return FLOAT; case FPOSTINC: code_dpostinc(e1,e2,0,freg); return FLOAT; case CPOSTINC: /* char *p; *p++ */ code_cpostinc(e1,e2,creg); return CHAR; case CPREINC: code_cpreinc(e1,e2,creg); return CHAR; case CPOSTDEC: code_cpostdec(e1,e2,creg); return CHAR; case CPREDEC: code_cpredec(e1,e2,creg); return CHAR; case MUL: case UMUL: case DIV: case UDIV: case MOD: case UMOD: case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT: case ADD: case SUB: case BAND: case EOR: case BOR: case CMP: machinop(e1); return INT; case DMUL: case DDIV: case DADD: case DSUB: case DCMP: case DCMPGE: dmachinop(e1); return DOUBLE; case COND: e2=fwdlabel(); b_expr(cadr(e1),0,e2,0); code_set_fixed_creg(0,INT); t = g_expr0(caddr(e1)); code_set_fixed_creg(1,t); jmp(e3=fwdlabel()); fwddef(e2); code_set_fixed_creg(0,INT); t = g_expr0(cadddr(e1)); code_set_fixed_creg(1,t); fwddef(e3); return t; case DCOND: e2=fwdlabel(); b_expr(cadr(e1),0,e2,0); code_set_fixed_creg(0,DOUBLE); t = g_expr0(caddr(e1)); code_set_fixed_creg(1,t); jmp(e3=fwdlabel()); fwddef(e2); code_set_fixed_creg(0,DOUBLE); t = g_expr0(cadddr(e1)); code_set_fixed_creg(1,t); fwddef(e3); return t; case SASS: sassign(e1); return RSTRUCT; case ASS: case CASS: assign(e1); return INT; case FASS: case DASS: case LASS: dassign(e1); return DOUBLE; case ASSOP: case CASSOP: assop(e1); return INT; case DASSOP: case FASSOP: dassop(e1); return DOUBLE; case RSTRUCT: g_expr0(e2); return RSTRUCT; case COMMA: g_expr_u(e2); return g_expr0(caddr(e1)); case RETURN: n = (NMTBL *)e2; if (retcont==0) retcont=fwdlabel(); code_return(creg); return VOID; case ENVIRONMENT: code_environment(creg); return ADDRESS; default: code_bool(e1,creg); /* type? */ return INT; } } #define dual_ops(op) \ (op==GT|| op==UGT|| op==GE|| op==UGE|| op==LT|| \ op==ULT|| op==LE|| op==ULE|| \ op==DOP+GT|| op==DOP+GE|| op==DOP+LT|| op==DOP+LE || \ op==EQ|| op==NEQ|| op==DOP+EQ|| op==DOP+NEQ) int rop_dual(op) { if (op==GT) return LT; if (op==UGT) return ULT; if (op==GE) return LE; if (op==UGE) return ULE; if (op==LT) return GT; if (op==ULT) return UGT; if (op==LE) return GE; if (op==ULE) return UGE; if (op==DOP+GT) return DOP+LT; if (op==DOP+GE) return DOP+LE; if (op==DOP+LT) return DOP+GT; if (op==DOP+LE) return DOP+GE; return op; } void bexpr(int e1, char cond, int l1) { int op = car(e1); if (chk) return; gexpr_init(); if (dual_ops(op) && (car(caddr(e1))==CONST||(car(caddr(e1))==DCONST))) b_expr(list3(rop_dual(op),caddr(e1),cadr(e1)),cond,l1,0); else b_expr(e1,cond,l1,0); } void b_expr(int e1, char cond, int l1,int err) { int e2,l2,t; e2=cadr(e1); switch(car(e1)) { case LNOT: b_expr(e2,!cond,l1,0); return; case GT: rexpr(e1,l1,code_gt(cond),INT); return; case UGT: rexpr(e1,l1,code_ugt(cond),UNSIGNED); return; case GE: rexpr(e1,l1,code_ge(cond),INT); return; case UGE: rexpr(e1,l1,code_uge(cond),UNSIGNED); return; case LT: rexpr(e1,l1,code_ge(!cond),INT); return; case ULT: rexpr(e1,l1,code_uge(!cond),UNSIGNED); return; case LE: rexpr(e1,l1,code_gt(!cond),INT); return; case ULE: rexpr(e1,l1,code_ugt(!cond),UNSIGNED); return; case EQ: rexpr(e1,l1,code_eq(cond),INT); return; case NEQ: rexpr(e1,l1,code_eq(!cond),INT); return; case DOP+GT: drexpr(cadr(e1),caddr(e1),l1,DOP+GT); return; case DOP+GE: drexpr(cadr(e1),caddr(e1),l1,DOP+GE); return; case DOP+LT: drexpr(caddr(e1),cadr(e1),l1,DOP+GT); return; case DOP+LE: drexpr(caddr(e1),cadr(e1),l1,DOP+GE); return; case DOP+EQ: drexpr(cadr(e1),caddr(e1),l1,DOP+EQ); return; case DOP+NEQ: drexpr(cadr(e1),caddr(e1),l1,DOP+NEQ); return; case LAND: b_expr(e2,0,cond?(l2=fwdlabel()):l1,0); b_expr(caddr(e1),cond,l1,0); if(cond) fwddef(l2); return; case LOR: b_expr(e2,1,cond?l1:(l2=fwdlabel()),0); b_expr(caddr(e1),cond,l1,0); if(!cond) fwddef(l2); return; case CRGVAR: code_cmp_crgvar(e1); jcond(l1,cond); return; case CRLVAR: code_cmp_crlvar(lvar(e2)); jcond(l1,cond); return; case RGVAR: code_cmp_rgvar(e1); jcond(l1,cond); return; case RLVAR: code_cmp_rlvar(lvar(e2)); jcond(l1,cond); return; case DRLVAR: code_cmp_drlvar(lvar(e2)); jcond(l1,cond); return; case DRGVAR: code_cmp_drgvar(lvar(e2)); jcond(l1,cond); return; case REGISTER: code_cmp_register(e2); jcond(l1,cond); return; case DREGISTER: code_cmp_fregister(e2); jcond(l1,cond); return; case CONST: if((cond&&e2)||(!cond&&!e2)) jmp(l1); return; case DCONST: if((dcadr(e2)!=0.0)^cond) jmp(l1); return; default: if(err) { error(-1); return; /* recursive g_expr/b_expr */ } t=g_expr(e1); if(t==FLOAT||t==DOUBLE) code_cmp_fregister(freg); else code_cmp_register(creg); jcond(l1,cond); return; } } void arg_register(NMTBL *fnptr) { int args = fnptr->dsp; NMTBL *n; int reg_var = 0; int freg_var = 0; int type; int max_input_register_var; int max_input_fregister_var; if (is_function(fnptr)) { max_input_register_var = MAX_INPUT_REGISTER_VAR; max_input_fregister_var = MAX_INPUT_DREGISTER_VAR; } else { max_input_register_var = MAX_CODE_INPUT_REGISTER_VAR; max_input_fregister_var = MAX_CODE_INPUT_DREGISTER_VAR; } while (args) { /* process in reverse order */ n = (NMTBL*)caddr(args); type = n->ty; if (scalar(type)) { if(reg_var<max_input_register_var) { n->sc = REGISTER; n->dsp = cadr(get_input_register_var(reg_var,n)); regv[n->dsp]= 1; regs[n->dsp]= INPUT_REG; reg_var++; cadddr(args)=size_of_int; /* why we need this? */ } } else if (type==FLOAT||type==DOUBLE) { if(freg_var<max_input_fregister_var) { n->sc = DREGISTER; n->dsp = cadr(get_input_fregister_var(freg_var,n)); fregv[n->dsp]= 1; fregs[n->dsp]= INPUT_REG; freg_var++; cadddr(args)=size_of_double; /* why we need this? */ } } args = cadr(args); } code_arg_register(); } static int register_to_lvar(int e) { error(REG_ERR); return 0; #if 0 途中でレジスタからLVARに変更しても、間に合わない。 NMTBL *n = (NMTBL*)caddr(e); int reg = cadr(e); int tag = car(e); int lvar; int t; if (!n||n==&null_nptr) error(REG_ERR); if (tag==REGISTER) { /* regs[reg]==INPUT_REG case should be considered */ n->dsp = new_lvar(size_of_int); t = INT; } else if (tag==DREGISTER) { /* fregs[reg]==INPUT_REG case should be considered */ n->dsp = new_lvar(size_of_double); t = DOUBLE; } else error(-1); n->sc = LVAR; lvar = list2(LVAR,n->dsp); g_expr_u(assign_expr0(list2(LVAR,n->dsp),list3(tag,reg,(int)n),t,t)); if (tag==REGISTER) { free_register(reg); } else if (tag==DREGISTER) { free_fregister(reg); } return g_expr0(lvar); #endif } /* goto arguments list */ /* target list4(list2(tag,disp),cdr,ty,source_expr) */ /* source expr=listn(tag,...) */ /* source (after) list2(tag,disp) */ /* source list list3(e,cdr,sz) */ #define DEBUG_PARALLEL_ASSIGN 1 int overrap(int t,int sz,int source) { int s,s0,s1; int t0=cadr(t); int t1=t0+sz; for(;source;source=cadr(source)) { s=car(source); s0=cadr(s); if(car(s)==REGISTER && car(t)==REGISTER) { if(s0==t0) return s; } else if (is_same_type(s,t)) { s1=s0+caddr(source); #if DEBUG_PARALLEL_ASSIGN>1 printf("# ovedrrap source %d t0 %d t1 %d\n",car(car(t)),t0,t1); printf("# ovedrrap target %d s0 %d s1 %d\n",car(car(source)),s0,s1); printf("# ovedrrap equal = %d\n",((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1))); #endif if((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1)) return s; } } return 0; } void remove_target(int *target,int t,int *use) { int use0=*use; while(use0) { if (car(use0)==t) { if (car(caddr(use0))==REGISTER) free_register(cadr(caddr(use0))); else if (car(caddr(use0))==DREGISTER) free_fregister(cadr(caddr(use0))); break; } use0 = cadr(use0); } remove0(target,t); } void save_target(int t,int s,int *target,int *use,int sz,int ty) { int e1; /*新しいレジスタ(or スタック)を取得する*/ if (sz==size_of_int && (e1=get_register())!=-1) { e1=list3(REGISTER,e1,0); *use=list3(t,*use,e1); g_expr_u(assign_expr0(e1,s,ty,ty)); *target = append4(*target,t,ty,e1); } else if (sz==size_of_double && (e1=get_fregister())!=-1) { e1=list3(DREGISTER,e1,0); *use=list3(t,*use,e1); g_expr_u(assign_expr0(e1,s,ty,ty)); *target = append4(*target,t,ty,e1); } else { g_expr_u(assign_expr0((e1=list2(LVAR,new_lvar(sz))),s,ty,ty)); *target = append4(*target,t,ty,e1); } } int circular_dependency(int t,int s,int *target,int *source) { int target0=*target; int t1,sz,ty,s1; while(target0) { if (cadddr(target0)==s) { t1=car(target0); s=cadddr(target0); sz=size(ty=caddr(target0)); if(t==t1) { #if DEBUG_PARALLEL_ASSIGN printf("# circular dependency %d ty %d+%d sz %d\n",car(t1),ty,cadr(t1),sz); #endif return 1; } if ((s1=overrap(t1,sz,*source))) { /* another overrap start over */ return circular_dependency(t,s1,target,source); } } target0=cadr(target0); } return 0; } void parallel_assign(int *target,int *source,int *processing,int *use) { int t,s,sz,ty,target0,s1; while(*target) { target0=*target; while(target0) { t=car(target0); s=cadddr(target0); sz=size(ty=caddr(target0)); if(car(t)==car(s) && cadr(t)==cadr(s)) { /*書き込み先が自分自身*/ #if DEBUG_PARALLEL_ASSIGN printf("# remove same %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); #endif remove_target(target,t,use); /* 破壊されては困るので、source listからは除かない */ } else if (!(s1=overrap(t,sz,*source))) { /* 重なってないので安心して書き込める */ #if DEBUG_PARALLEL_ASSIGN printf("# normal assign %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); #endif g_expr_u(assign_expr0(t,s,ty,ty)); remove_target(target,t,use); remove0(source,s); } else { if(circular_dependency(t,s1,target,source)) { #if DEBUG_PARALLEL_ASSIGN printf("# saving %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); #endif remove_target(target,t,use); remove0(source,s); save_target(t,s,target,use,sz,ty); } } target0=cadr(target0); } } } void remove0(int *parent,int e) { int list; while ((list=*parent)) { if (car(list)==e) { *parent= cadr(list); return; } else { parent=&cadr(list); } } } /* void remove0_all(int *parent,int e) { int list; while ((list=*parent)) { if (car(list)==e) { *parent= cadr(list); } else { parent=&cadr(list); } } } */ int is_simple(int e1) { return ( e1==CONST || e1==FNAME || e1==LVAR || e1==REGISTER ||e1==DREGISTER || e1==GVAR || e1==RGVAR || e1==RLVAR || e1==CRLVAR || e1==CRGVAR || e1==DRLVAR || e1==FRLVAR ); } int is_same_type(int e1,int e2) { int ce1=car(e1); int ce2=car(e2); return ( (ce1==LVAR && (ce2==RLVAR||ce2==CRLVAR||ce2==FRLVAR||ce2==DRLVAR)) || (ce2==LVAR && (ce1==RLVAR||ce1==CRLVAR||ce1==FRLVAR||ce1==DRLVAR)) || (ce1==GVAR && (ce2==RGVAR||ce2==CRGVAR||ce2==FRGVAR||ce2==DRGVAR)) || (ce2==GVAR && (ce1==RGVAR||ce1==CRGVAR||ce1==FRGVAR||ce1==DRGVAR)) ); } int is_memory(int e1) { int ce1=car(e1); return ( ce1==LVAR ||ce1==RLVAR||ce1==CRLVAR || ce1==DRLVAR || ce1==GVAR ||ce1==RGVAR||ce1==CRGVAR || ce1==DRGVAR || ce1==REGISTER|| ce1==DREGISTER ); } int is_code(NMTBL *fnptr) { int type = fnptr->ty; return type==CODE|| (type>0 && car(type)==CODE); } int is_function(NMTBL *fnptr) { int type = fnptr->ty; return type==FUNCTION || (type>0 && car(type)==FUNCTION); } void jump(int e1, int env) { int e2,e3,e4,sz,arg_size,ty,regs,fregs; int t0,s0; NMTBL *code0; int target = 0; int source = 0; int processing = 0; int use = 0; /* まず、サイズを計算しながら、決まった形に落す。 */ arg_size = 0; regs = 0; fregs = 0; for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { e2 = car(e3); sz = size(ty=caddr(e3)); if (scalar(ty) && regs < MAX_CODE_INPUT_REGISTER_VAR) { target=list4(get_input_register_var(regs++,0), target,ty,e2); } else if ((ty==DOUBLE||ty==FLOAT) && fregs < MAX_CODE_INPUT_DREGISTER_VAR) { target=list4(get_input_fregister_var(fregs++,0), target,ty,e2); } else { target=list4(list2(LVAR,0), target,ty,e2); arg_size += sz; } #if DEBUG_PARALLEL_ASSIGN printf("# target %d ty %d+%d sz %d\n",car(car(target)),ty,cadr(car(target)),sz); #endif } /* disp を飛び先似合わせて修正 */ if (is_code(fnptr)) { if (-arg_size<disp) disp = -arg_size; } else { if (disp_offset-arg_size<disp) disp = disp_offset-arg_size; } /* 複雑な式を前もって計算しておく */ /* 必要なら局所変数を用いる。 */ /* 局所変数へのオフセットを覚えておく */ for (e2 = target; e2; e2 = cadr(e2)) { t0=car(e2); s0=cadddr(e2); sz=size(ty=caddr(e2)); if(car(t0)==LVAR) { /* ここで、書込先アドレスを決める */ cadr(t0)=-arg_size; arg_size-=sz; } if (!is_simple(car(s0))) { g_expr_u(assign_expr0((e4=list2(LVAR,new_lvar(sz))),s0,ty,ty)); cadddr(e2)=e4; s0=e4; } else if (is_same_type(t0,s0)) { if(cadr(t0)==cadr(s0)) { #if DEBUG_PARALLEL_ASSIGN printf("# remove same memory %d ty %d+%d sz %d\n",car(t0),ty,cadr(t0),sz); #endif /* we should check size also (but currently useless */ remove0(&target,t0); /* still we have source to avoid overwrite */ } } if(is_memory(s0)) { source=list3(s0,source,sz); #if DEBUG_PARALLEL_ASSIGN printf("# source %d ty %d+%d sz %d\n",car(car(source)),ty,cadr(car(source)),sz); #endif } } /* compute jump address */ e2 = cadr(e1); if (car(e2) == FNAME) { code0=(NMTBL *)cadr(e2); if (!is_code(code0)) { error(TYERR); return; } } else { /* indirect */ g_expr(e2); emit_push(); } if (env) { g_expr(env); emit_push(); } /* 並列代入を実行 */ parallel_assign(&target,&source,&processing,&use); while (use) { if (car(caddr(use))==REGISTER) free_register(cadr(caddr(use))); else if (car(caddr(use))==DREGISTER) free_fregister(cadr(caddr(use))); use=cadr(use); } if(target) error(-1); if (env) { /* change the frame pointer */ e3 = emit_pop(0); code_frame_pointer(e3); emit_pop_free(e3); } else if (is_function(fnptr)) { code_fix_frame_pointer(disp_offset); } if (car(e2) == FNAME) { code_jmp(code0->nm); } else { e2 = emit_pop(0); code_indirect_jmp(e2); emit_pop_free(e2); } } void machinop(int e1) { int e2,e3,op; e2 = cadr(e1); op = car(e1); e3 = caddr(e1); g_expr(e3); emit_push(); g_expr(e2); tosop(car(e1),(e2=pop_register())); emit_pop_free(e2); regv[creg]=1; return; } void dmachinop(int e1) { int e2,e3,op; e2 = cadr(e1); op = car(e1); e3 = caddr(e1); g_expr(e3); emit_dpush(); g_expr(e2); dtosop(car(e1),(e2=emit_dpop(1))); emit_dpop_free(e2); fregv[freg]=1; return; } void sassign(int e1) { int e2,e3,e4,sz,xreg,det; /* structure assignment */ e2 = cadr(e1); /* pointer variable to the struct */ e3 = cadr(e2); /* offset of the variable (distination) */ e4 = caddr(e1); /* right value (source) */ sz = cadddr(e1); /* size of struct or union */ g_expr(e4); emit_push(); g_expr(e2); xreg = emit_pop(0); /* 一般的にはコピーのオーバラップの状況は実行時にしかわからない */ /* しかし、わかる場合もある */ if (car(e4)==RSTRUCT) e4=cadr(e4); if (is_same_type(e2,e4)) { if(cadr(e2)<cadr(e4)) sz=-sz; det=1; } else { det = 0; } emit_copy(xreg,creg,sz,0,1,det); emit_pop_free(xreg); return; } void assign(int e1) { int e2,e3,e4,byte; byte=(car(e1) == CASS); /* e2=e4 */ e2 = cadr(e1); e3 = cadr(e2); e4 = caddr(e1); switch(car(e2)) { case GVAR: /* i=3 */ g_expr(e4); code_assign_gvar(e2,creg,byte); return; case LVAR: g_expr(e4); code_assign_lvar(lvar(cadr(e2)),creg,byte); return; case REGISTER: g_expr(e4); if (creg!=cadr(e2)) code_assign_register(cadr(e2),byte,creg); return; } g_expr(e2); emit_push(); g_expr(e4); e2 = emit_pop(0); code_assign(e2,byte); emit_pop_free(e2); regv[creg]=1; return; } void dassign(int e1) { int e2,e3,e4,d; /* e2=e4 */ e2 = cadr(e1); e3 = cadr(e2); e4 = caddr(e1); d = (car(e1)==LASS)?2:(car(e1)==DASS)?1:0; switch(car(e2)) { case GVAR: g_expr(e4); code_dassign_gvar(e2,freg,d); return; case LVAR: g_expr(e4); code_dassign_lvar(lvar(cadr(e2)),freg,d); return; case DREGISTER: g_expr(e4); if (freg!=cadr(e2)) code_dassign_fregister(cadr(e2),d,freg); return; } g_expr(e2); emit_push(); g_expr(e4); e2 = emit_pop(0); code_dassign(e2,freg,d); emit_pop_free(e2); return; } void assop(int e1) { int e2,e3,byte,op; /* e2 op= e3 */ byte = (car(e1) == CASSOP); e2 = cadr(e1); if (car(e2)==INDIRECT) e2=cadr(e2); e3 = caddr(e1); op = cadddr(e1); g_expr(e3); if (car(e2)==REGISTER) { code_register_assop(cadr(e2),op,byte); regv[creg]=1; return; } emit_push(); g_expr(e2); code_assop(op,byte); regv[creg]=1; return; } void dassop(int e1) { int e2,e3,op,d; /* e2 op= e3 */ d = (car(e1) == DASSOP); e2 = cadr(e1); if (car(e2)==INDIRECT) e2=cadr(e2); e3 = caddr(e1); op = cadddr(e1); g_expr(e3); emit_dpush(); g_expr(e2); code_dassop(op,d); regv[creg]=1; return; } void cmpdimm(int e, int csreg) { code_cmpdimm(e, csreg); } int csvalue() { return code_csvalue(); } int fwdlabel(void) { return labelno++; } void fwddef(int l) { control=1; if (!chk) code_label(l); } int backdef(void) { control=1; if (!chk) code_label(labelno); return labelno++; } void def_label(int cslabel, int dlabel) { int fl; fl = 0; if (control) { jmp(fl=fwdlabel()); } fwddef(cslabel); if (dlabel) jmp(dlabel); if (fl) { fwddef(fl); } } void gen_source(char *s) { printf("%s",s); } void ret(void) { code_set_return_register(1); jmp(retlabel); } void opening(char *filename) { emit_init(); if (!chk) code_opening(filename); } void closing() { if (!chk) code_closing(); } int contains_in_list(int e,int type) { while(e) { if(contains(car(e),type)) return 1; e = cadr(e); } return 0; } int contains(int e,int type) { while(e) { if (car(e)==type) return 1; switch (car(e)){ /* list arguments */ case FUNCTION: case CODE: return contains_in_list(caddr(e),type); /* unary operators */ case INDIRECT: case RINDIRECT: case CRINDIRECT: case DRINDIRECT: case FRINDIRECT: case ADDRESS: case MINUS: case DMINUS: case I2D: case D2I: case U2D: case D2U: case BNOT: case LNOT: case PREINC: case POSTINC: case DPREINC: case DPOSTINC: case FPREINC: case FPOSTINC: case CPOSTINC: case CPREINC: case CPOSTDEC: case CPREDEC: case RSTRUCT: e = cadr(e); continue; /* biary operators */ case MUL: case UMUL: case DIV: case UDIV: case MOD: case UMOD: case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT: case ADD: case SUB: case BAND: case EOR: case BOR: case CMP: case DMUL: case DDIV: case DADD: case DSUB: case DCMP: case DCMPGE: case SASS: case ASS: case CASS: case FASS: case DASS: case LASS: case ASSOP: case CASSOP: case DASSOP: case FASSOP: case COMMA: if (contains(cadr(e),type)) return 1; e = caddr(e); continue; /* tarary operators */ case COND: if (contains(cadr(e), type)) return 1; if (contains(caddr(e),type)) return 1; e = cadddr(e); continue; default: /* nullary operators case GVAR: case RGVAR: case CRGVAR: case LVAR: case REGISTER: case DREGISTER: case RLVAR: case CRLVAR: case FRLVAR: case FRGVAR: case DRLVAR: case DRGVAR: case FNAME: case CONST: case DCONST: case STRING: case RETURN: case ENVIRONMENT: */ return 0; } } return 0; } /* end */