Mercurial > hg > CbC > old > device
view mc-code-mips.c @ 234:eccea7c904ee
float powerpc drexp done (?)
author | kono |
---|---|
date | Thu, 29 Apr 2004 19:40:43 +0900 |
parents | 6190d24e178c |
children | 0dcc0ec81ed2 |
line wrap: on
line source
/* Micro-C Code Generatation Part for MIPS (PS2Linux) */ /* $Id$ */ #define EXTERN extern #include "mc.h" #include "mc-code.h" #include "mc-codegen.h" char *l_include_path[] = { "/usr/include/", 0 }; #define TEXT_EMIT_MODE 0 #define DATA_EMIT_MODE 1 #define RODATA_EMIT_MODE 2 static void data_mode(char *name); static void ld_indexx(int byte, int n, int xreg,int sign); static void local_table(void); static void shift(char *op, int reg); static int struct_push(int e4,int t,int arg); static int output_mode = TEXT_EMIT_MODE; static int data_alignment = 0; static int code_disp_label; static int disp_label; static int r1_offset_label; static int lvar_offset_label; static int cprestore_label; static int reg_save; static int freg_save; static int freg,ireg,dreg; /* mips requires two registers for compare */ static int cmpreg = -1; int size_of_int = 4; int size_of_float = 4; int size_of_double = 8; int size_of_longlong = 8; int endian = 1; int reg_sp; /* REGister Stack-Pointer */ int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ /* floating point registers */ int freg_sp; /* floating point REGister Stack-Pointer */ int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ /* double floating point registers */ int dreg_sp; /* floating point REGister Stack-Pointer */ int dreg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ #define REG_fp 1 #define REG_sp 30 #define REG_VAR_BASE 29 #define REG_VAR_MIN 18 #define MIN_TMP_REG 4 #define MAX_TMP_REG 11 #define DREG_VAR_BASE 29 #define DREG_VAR_MIN 18 #define MIN_TMP_DREG 4 #define MAX_TMP_DREG 17 #define PTRC_REG 3 #define FREG_VAR_BASE 31 #define FREG_VAR_MIN 20 #define MIN_TMP_FREG 1 #define MAX_TMP_FREG 14 #define RET_REGISTER 3 #define RET_FREGISTER (1+FREG_OFFSET) #define RET_DREGISTER (1+DREG_OFFSET) int MAX_REGISTER=30; /* PowerPCのレジスタを10個まで使う*/ int MAX_FREGISTER=31; int MAX_DREGISTER=16; #define REAL_MAX_REGISTER 32 /* PowerPCのレジスタが32ということ*/ #define REAL_MAX_FREGISTER 32 /* PowerPCのFレジスタが32ということ*/ #define REAL_MAX_DREGISTER 31 /* PowerPCのDレジスタ番号が31ということ*/ #define FREG_OFFSET REAL_MAX_REGISTER #define DREG_OFFSET (REAL_MAX_REGISTER+REAL_MAX_FREGISTER ) int MAX_INPUT_REGISTER_VAR = 7-MIN_TMP_REG; int MAX_CODE_INPUT_REGISTER_VAR = 7-MIN_TMP_REG; int MAX_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG; int MAX_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG; int MAX_CODE_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG; int MAX_CODE_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG; #define CREG_REGISTER MAX_TMP_REG #define FREG_FREGISTER (MAX_TMP_FREG+FREG_OFFSET) #define DREG_DREGISTER (2+DREG_OFFSET) static int powerpc_regs[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+REAL_MAX_DREGISTER]; static int dreg_pair0[REAL_MAX_DREGISTER] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 }; static int dreg_pair1[REAL_MAX_DREGISTER] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 }; static int *regs = powerpc_regs; static int max_reg_var, max_freg_var; static char *reg_name[] = { "$0","$1","$2","$3","$4","$5","$6","$7","$8","$9", "$10","$11","$12","$13","$14","$15","$16","$17","$18","$19", "$20","$21","$22","$23","$24","$25","$26","$27","$28","$29", "$30","$31", "$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7","$f8","$f9", "$f10","$f11","$f12","$f13","$f14","$f15","$f16","$f17","$f18","$f19", "$f20","$f21","$f22","$f23","$f24","$f25","$f26","$f27","$f28","$f29", "$f30","$f31" }; #define register_name(i) reg_name0(i) #define fregister_name(i) reg_name0(i) #define dregister_name0(i) reg_name1(i,dreg_pair0) #define dregister_name1(i) reg_name1(i,dreg_pair1) static char * reg_name0(int i) { if (i<=REAL_MAX_REGISTER+REAL_MAX_FREGISTER) return reg_name[i]; else { error(-1); return reg_name[0]; } } static char * reg_name1(int i,int *d) { if (i<=REAL_MAX_REGISTER+REAL_MAX_FREGISTER) { error(-1); return reg_name[0]; } else return reg_name[d[i-DREG_OFFSET]]; } #define is_int_reg(i) (0<=i&&i<REAL_MAX_REGISTER) #define is_float_reg(i) (REAL_MAX_REGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER) #define is_double_reg(i) (REAL_MAX_REGISTER+REAL_MAX_FREGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER+REAL_MAX_DREGISTER) int use_int(int i) { if (!is_int_reg(i)) i = ireg; if (!regs[i]) regs[i]=1; return i; } int use_float(int i) { if (!is_float_reg(i)) i = freg; if (!regs[i]) regs[i]=1; return i; } int use_double(int i) { if (!is_double_reg(i)) i = dreg; if (!regs[i]) regs[i]=1; return i; } int use_longlong(int i) { return i; } #if FLOAT_CODE static int code_d1(double d); static int code_d2(double d); #endif static void code_save_stacks(); static void code_save_input_registers(); static void set_creg(int,int); static void set_freg(int,int); static void set_dreg(int,int); static int mask_label; static int mask1_label; static int fmask_label; static int fmask1_label; static FILE *asi; static int max_func_args; static int max_func_iargs; static int my_func_args; #define ARG_LVAR_OFFSET 0x10000000 #define DOT_SIZE 1 /* Reorder is automatically done in assembler. delayed slot done within .set noreorder. r0 return value etc. $2,$3 return value. (dpcmp return value on $2) $0 special register $4-$7 input register r22-r29 saved register variable (input register for code segement) $31 stack pointer $fp frame pointer $f0 return value etc. $f14,$f12 input register $f20-$f31 saved register variable function call stack frame <------r1_offset------------------------------> <------------lvar_offset-------> r+ +------------+---+---------------+----------+--------------+----+ - callee arg xx register save local caller arg xx reg_save disp max_func_args*size_of_int lvar>0 lvar<0 lvar>0x1000 0000 code segment stack frame * gotoを呼び出した関数のr1 ! r1(goto前のr1) # * r30 <---r1_offset---------> r1 r+ +----------+--+----------+----------------+-----------+----------+----+ cousin arg xx reg save !callee arg !code local caller arg xx r20-r29 lvar>0 lvar<0 lvar>0x1000 000 f20-f31 <-my_func_args--><--disp-----><-max_func_arg-> *size_of_int *size_of_int */ int arg_offset = 24; int arg_offset1 = 24; int disp_offset = -12; #define func_disp_offset 60 #define r1_offset func_disp_offset+12 int code_disp_offset = 0; int jump_offset = 0; #define CODE_LVAR l+code_disp_offset #define CODE_CALLER_ARG (l-ARG_LVAR_OFFSET)+arg_offset1 #define FUNC_LVAR l+disp_offset #define CALLER_ARG (l-ARG_LVAR_OFFSET)+arg_offset1 #define CALLEE_ARG l+arg_offset void code_offset_set() { #if 0 int l; #endif int lvar_offsetv = -disp+max_func_args*size_of_int+func_disp_offset; int r1_offsetv = -disp+max_func_args*size_of_int-reg_save+r1_offset; printf("L_%d = %d\n",lvar_offset_label,lvar_offsetv); printf("L_%d = %d\n",r1_offset_label,r1_offsetv); #if 0 printf("# function %s\n",fnptr->nm); l = ARG_LVAR_OFFSET; printf("# offset call0\t%d\n",CALLER_ARG); l = ARG_LVAR_OFFSET+max_func_args*size_of_int; printf("# offset calln\t%d %d\n",CALLER_ARG,max_func_args*size_of_int); l = disp; printf("# offset lvarn\t%d %d\n",FUNC_LVAR+lvar_offsetv,disp); l = 0; printf("# offset lvar0\t%d\n",FUNC_LVAR+lvar_offsetv); l = -reg_save; printf("# offset regs\t%d\n",FUNC_LVAR+lvar_offsetv); printf("# offset r1off\t%d\n",r1_offsetv); l = 0; printf("# offset carg0\t%d\n",CALLEE_ARG+r1_offsetv); l = my_func_args; printf("# offset cargn\t%d %d\n",CALLEE_ARG+r1_offsetv,my_func_args); #endif } static void lvar(int l) { if (fnptr->sc==CODE) { if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ printf("%d($fp)\n",CODE_CALLER_ARG); } else printf("%d($fp)\n",CODE_LVAR); } else if (l<0) { /* local variable */ printf("%d+L_%d($fp)\n",FUNC_LVAR,lvar_offset_label); } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ printf("%d($fp)\n",CALLER_ARG); } else { /* callee's arguments */ printf("%d+L_%d($fp)\n",CALLEE_ARG,r1_offset_label); } } static void lvar_address(int l,int creg) { if (fnptr->sc==CODE) { if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_CALLER_ARG); } else printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_LVAR); } else if (l<0) { /* local variable */ printf("\taddu\t%s,$fp,%d+L_%d\n",register_name(creg),FUNC_LVAR,lvar_offset_label); } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ printf("\taddu\t%s,$fp,%d\n",register_name(creg),CALLER_ARG); } else { /* callee's arguments */ printf("\taddu\t%s,$fp,%d+L_%d\n",register_name(creg),CALLEE_ARG,r1_offset_label); } } void code_lvar(int e2,int creg) { lvar_address(e2,creg); } void code_init(void) { /* this is called once program call */ } void gexpr_code_init(void){ } void code_gexpr(int e){ if (is_int_reg(creg) && creg!=ireg) error(-1); } void code_arg_register(NMTBL *fnptr) { int args = fnptr->dsp; NMTBL *n; int reg_var = 0; int freg_var = 0; int type; int reg; int is_code0 = is_code(fnptr); while (args) { /* process in reverse order */ n = (NMTBL*)caddr(args); type = n->ty; if (scalar(type)) { if ((reg = get_input_register_var(reg_var,n,is_code0))) { n->sc = REGISTER; n->dsp = cadr(reg); regs[n->dsp]= INPUT_REG; reg_var++; cadddr(args)=size_of_int; /* why we need this? */ } } else if (type==FLOAT) { if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) { n->sc = FREGISTER; n->dsp = cadr(reg); regs[n->dsp]= INPUT_REG; freg_var++; cadddr(args)=size(type); /* why we need this? */ } } else if (type==DOUBLE) { if ((reg = get_input_dregister_var(reg_var,n,is_code0,1))) { n->sc = DREGISTER; n->dsp = cadr(reg); regs[n->dsp]= INPUT_REG; reg_var+=2; cadddr(args)=size(type); /* why we need this? */ } } args = cadr(args); } if (is_function(fnptr)) code_save_input_registers(); } int get_register(void) { /* 使われていないレジスタを調べる */ int i,reg; for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) { if (regs[i]) continue; /* 使われている */ regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ return i; /* その場所を表す番号を返す */ } /* search register stack */ for(i=0;i<reg_sp;i++) { if ((reg=reg_stack[i])>=0) { code_assign_lvar( (reg_stack[i]=new_lvar(size_of_int)),reg,0); reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; return reg; } } #if FLOAT_CODE /* search dregister stack */ for(i=0;i<dreg_sp;i++) { if ((reg=dreg_stack[i])>=0) { code_dassign_lvar( (dreg_stack[i]=new_lvar(size_of_double)),reg,1); dreg_stack[i]= dreg_stack[i]-REG_LVAR_OFFSET; free_register(reg); return get_register(); /* 今度は必ずある */ } } #endif for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { reg =REG_VAR_BASE-i; if (! regs[reg]) { /* 使われていないなら */ regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */ if (i>max_reg_var) max_reg_var=i; return reg; } } /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ error(HPERR); return creg; } int pop_register(void) { /* レジスタから値を取り出す */ return reg_stack[--reg_sp]; } #if FLOAT_CODE static int get_dregister1() { int i; for(i=MAX_TMP_DREG+DREG_OFFSET;i>MIN_TMP_DREG+DREG_OFFSET;i--) { if (regs[i]) continue; /* 使われている */ if (regs[dreg_pair0[i-DREG_OFFSET]]) continue; if (regs[dreg_pair1[i-DREG_OFFSET]]) continue; regs[dreg_pair0[i-DREG_OFFSET]]=USING_REG; regs[dreg_pair1[i-DREG_OFFSET]]=USING_REG; regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ return i; /* その場所を表す番号を返す */ } return -1; } static int get_dregister0() { int reg,i; /* とりあえず、空き int register pair を探す */ if ((i=get_dregister1())!=-1) { return i; } /* search dregister stack */ for(i=0;i<dreg_sp;i++) { if ((reg=dreg_stack[i])>=0) { code_dassign_lvar( (dreg_stack[i]=new_lvar(size_of_double)),reg,1); dreg_stack[i]= dreg_stack[i]-REG_LVAR_OFFSET; return reg; } } /* clear integer register stack */ for(i=0;i<reg_sp;i++) { if ((reg=reg_stack[i])>=0) { code_assign_lvar( (reg_stack[i]=new_lvar(size_of_int)),reg,0); reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; free_register(reg); } } if ((i=get_dregister1())!=-1) { return i; } error(REG_ERR); return dreg; } static int get_fregister0() { /* 使われていないレジスタを調べる */ int i,reg; for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) { if (regs[i]) continue; /* 使われている */ regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ return i; /* その場所を表す番号を返す */ } /* search register stack */ for(i=0;i<freg_sp;i++) { if ((reg=freg_stack[i])>=0) { code_dassign_lvar( (freg_stack[i]=new_lvar(size_of_float)),reg,0); freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; return reg; } } for(i=0;i<FREG_VAR_BASE-REG_VAR_MIN;i++) { reg =FREG_VAR_BASE-i+FREG_OFFSET; if (! regs[reg]) { /* 使われていないなら */ regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */ if (i>max_freg_var) max_freg_var=i; return reg; } } /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ error(REG_ERR); return freg; } int get_dregister(int d) { if (d) { return get_dregister0(); } else { return get_fregister0(); } } int pop_fregister(void) { /* レジスタから値を取り出す */ return freg_stack[--freg_sp]; } int pop_dregister(void) { /* レジスタから値を取り出す */ return dreg_stack[--dreg_sp]; } #endif #if LONGLONG_CODE int get_lregister() { return -1; } int get_lregister_var(NMTBL *n) { return list2(LVAR,new_lvar(size_of_double)); } #endif void emit_pop_free(int xreg) { if (xreg>=0) free_register(xreg); } void free_register(int i) { /* いらなくなったレジスタを開放 */ int i0,i1; if (i<0||MAX_FREGISTER+FREG_OFFSET+REAL_MAX_DREGISTER<i) error(-1); if (is_double_reg(i)) { i0 = dreg_pair0[i-DREG_OFFSET]; regs[i0]=0; i1 = dreg_pair1[i-DREG_OFFSET]; regs[i1]=0; } regs[i]=0; } int get_input_dregister_var(int i,NMTBL *n,int is_code,int d) { if (d) { if (is_code) { if(!(i<DREG_VAR_BASE-DREG_VAR_MIN)) return 0; i = DREG_VAR_BASE-i+DREG_OFFSET; } else { if (i<0||i>=MAX_INPUT_DREGISTER_VAR) return 0; i = i+MIN_TMP_DREG+DREG_OFFSET; } return list3(DREGISTER,i,(int)n); } else { if (is_code) { if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0; i = FREG_VAR_BASE-i+FREG_OFFSET; } else { if (i<0||i>=MAX_INPUT_FREGISTER_VAR) return 0; i = i+MIN_TMP_FREG+FREG_OFFSET; } return list3(FREGISTER,i,(int)n); } } int get_input_register_var(int i,NMTBL *n,int is_code) { if (is_code) { if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; i = REG_VAR_BASE-i; } else { if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; i = i+MIN_TMP_REG; } return list3(REGISTER,i,(int)n); } /* double register case? */ int get_input_register_var_1(int i,NMTBL *n,int is_code) { if (is_code) { if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; i = REG_VAR_BASE-i; } else { if (i<0||i>=MAX_INPUT_REGISTER_VAR+1) return 0; i = i+MIN_TMP_REG; } return list3(REGISTER,i,(int)n); } int free_register_count(int d) { int i,count,fcount; fcount = count = 0; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i]) count++; } for(i=0;i<MAX_FREGISTER;i++) { if (! regs[i+FREG_OFFSET]) fcount++; } printf("# free reg %d freg %d\n",count,fcount); return d?fcount:count; } int register_full(void) { int i; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i]) { return 0; } } return 1; } void free_all_register(void) { int i; for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; } for(i=0;i<MAX_FREGISTER;i++) { regs[i+FREG_OFFSET]=0; } for(i=0;i<MAX_DREGISTER;i++) { regs[i+DREG_OFFSET]=0; } creg = get_register(); #if FLOAT_CODE freg = get_dregister(0); dreg = DREG_DREGISTER; #endif set_creg(CREG_REGISTER,0); set_freg(FREG_FREGISTER,0); set_dreg(DREG_DREGISTER,0); return; } void register_usage(char *s) { #if 0 int i; #endif if (chk) return; if (!lsrc) return; printf("# %d: %s:",lineno,s); printf(" creg=%s ireg=%s freg=%s dreg=%s", is_int_reg(creg)?register_name(creg): is_float_reg(creg)?fregister_name(creg): is_double_reg(creg)?dregister_name0(creg):"bad", register_name(ireg),fregister_name(freg),dregister_name0(dreg)); #if 0 printf("\n# regs:"); printf(":"); for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); } printf("\n# freg:"); for(i=0;i<MAX_FREGISTER;i++) { printf("%d",regs[i+FREG_OFFSET]); } for(i=reg_sp;i>=0;i--) { if(reg_stack[i]>=0) printf(" %s",register_name(reg_stack[i])); } #endif printf("\n"); } void gexpr_init(void) { while(reg_sp > 0) { free_register(reg_stack[--reg_sp]); } while(freg_sp > 0) { free_register(freg_stack[--freg_sp]); } while(dreg_sp > 0) { free_register(dreg_stack[--dreg_sp]); } cmpreg = -1; text_mode(); gexpr_code_init(); register_usage("gexpr_init"); } void emit_init(void) { free_all_register(); max_reg_var=-1; max_freg_var=-1; reg_sp = 0; freg_sp = 0; dreg_sp = 0; text_mode(); } int get_register_var(NMTBL *n) { int i; for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { if (! regs[REG_VAR_BASE-i]) { /* 使われていないなら */ /* そのレジスタを使うことを宣言し */ regs[REG_VAR_BASE-i]=USING_REG; if (i>max_reg_var) max_reg_var=i; /* その場所を表す番号を返す */ return list3(REGISTER,REG_VAR_BASE-i,(int)n); } } return list2(LVAR,new_lvar(size_of_int)); } int fregister_var(int r) { return r; } int get_dregister_var(NMTBL *n,int d) { int i,j; if (d) { for(i=0;i<DREG_VAR_BASE-DREG_VAR_MIN;i++) { if (! regs[j=(DREG_VAR_BASE-i+DREG_OFFSET)]) { /* 使われていないなら */ if (regs[dreg_pair0[j]] || regs[dreg_pair1[j]]) continue; regs[DREG_VAR_BASE-i+DREG_OFFSET]=USING_REG; /*そのレジスタを使うことを宣言し*/ regs[dreg_pair0[j]] = regs[dreg_pair1[j]] = USING_REG; if (dreg_pair1[j]>max_reg_var) max_reg_var=dreg_pair1[j]; /* その場所を表す番号を返す */ return list3(DREGISTER,DREG_VAR_BASE-i+DREG_OFFSET,(int)n); } } return list2(LVAR,new_lvar(size_of_double)); } else { for(i=0;i<FREG_VAR_BASE-FREG_VAR_MIN;i++) { if (! regs[FREG_VAR_BASE-i+FREG_OFFSET]) { /* 使われていないなら */ regs[FREG_VAR_BASE-i+FREG_OFFSET]=USING_REG; /*そのレジスタを使うことを宣言し*/ if (i>max_freg_var) max_freg_var=i; /* その場所を表す番号を返す */ return list3(FREGISTER,FREG_VAR_BASE-i+FREG_OFFSET,(int)n); } } return list2(LVAR,new_lvar(size_of_float)); } } void emit_push() { int new_reg; if (reg_sp>MAX_MAX) error(-1); new_reg = get_register(); reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ ireg = creg = new_reg; } int emit_pop(int type) { int xreg,reg; xreg=pop_register(); if (xreg<= -REG_LVAR_OFFSET) { reg = get_register(); code_rlvar(REG_LVAR_OFFSET+xreg,reg); free_lvar(REG_LVAR_OFFSET+xreg); xreg = reg; } return xreg; } void code_label(int labelno) { printf("L_%d:\n",labelno); } void code_gvar(int e1,int creg) { printf("\tla %s,%s\n",register_name(creg),((NMTBL*)cadr(e1))->nm); } void code_rgvar(int e1,int creg) { printf("\tlw %s,%s\n",register_name(creg),((NMTBL*)cadr(e1))->nm); } char *cload(int sign,int sz) { return sz==1?(sign?"lbu":"lb"):(sz==size_of_short?(sign?"lhu":"lh"):"lw");} char *cstore(int sz) { return sz==1?"sb":(sz==size_of_short)?"sh":"sw";} void code_crgvar(int e1,int creg,int sign,int sz){ printf("\t%s %s,%s\n",cload(sign,sz),register_name(creg),((NMTBL*)cadr(e1))->nm); } void code_register(int e2,int creg) { if (creg!=e2) printf("\tmove %s,%s\n",register_name(creg),register_name(e2)); } void code_rlvar(int e2,int reg) { printf("\tlw %s,",register_name(reg)); lvar(e2); } void code_crlvar(int e2,int reg,int sign,int sz) { printf("\t%s %s,",cload(sign,sz),register_name(reg)); lvar(e2); } void code_fname(NMTBL *n,int creg) { printf("\tla %s,%s\n",register_name(creg),n->nm); } void code_const(int e2,int creg) { printf("\tli %s,%d\n",register_name(creg),e2); } void code_neg(int creg) { printf("\tsubu %s,$0,%s\n", register_name(creg), register_name(creg)); } void code_not(int creg) { printf("\tnor %s,%s,%s\n", register_name(creg), register_name(creg),register_name(creg)); } void code_lnot(int creg) { /* if non zero 1 else 0 */ int dreg = get_register(); printf("\txori %s,%s,0x0\n", register_name(dreg),register_name(creg)); printf("\tsltu %s,%s,1\n", register_name(creg),register_name(dreg)); free_register(dreg); } void code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) { char *xrn,*drn; int i,dreg; if (car(e2)==REGISTER) { printf("\taddu %s,%s,%d\n", register_name(cadr(e2)),register_name(cadr(e2)), dir); if (cadr(reg)!=e2) printf("\tmove %s,%s\n",register_name(cadr(reg)),register_name(e2)); return; } g_expr(e2); xrn = register_name(creg); dreg=get_register(); if (!dreg) error(-1); drn = register_name(dreg); printf("\t%s %s,0(%s)\n",cload(sign,sz),drn,xrn); printf("\taddu %s,%s,%d\n",drn,drn,dir); printf("\t%s %s,0(%s)\n",cstore(sz),drn,xrn); i=creg;creg=dreg;dreg=i; ireg=creg; free_register(dreg); } void code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) { char *xrn,*crn,*nrn; int dreg,nreg,i; if (car(e2)==REGISTER) { printf("\tmove %s,%s\n",register_name(reg),register_name(cadr(e2))); printf("\taddu %s,%s,%d\n", register_name(cadr(e2)),register_name(cadr(e2)),dir); return; } g_expr(e2); crn = register_name(creg); dreg=get_register(); if (!dreg) error(-1); xrn = register_name(dreg); nreg=get_register(); if (!nreg) error(-1); nrn = register_name(nreg); printf("\t%s %s,0(%s)\n",cload(sign,sz),xrn,crn); printf("\taddu %s,%s,%d\n",nrn,xrn,dir); printf("\t%s %s,0(%s)\n",cstore(sz),nrn,crn); i=creg;creg=dreg;dreg=i; free_register(nreg); free_register(dreg); ireg=creg; } void code_return(int creg) { char *crn = register_name(creg); printf("\tla %s,L_%d\n",crn,retcont); } #define R1SAVE 1 void code_environment(int creg) { /* save frame pointer */ #if R1SAVE printf("\tlw %s,0($fp)\n",register_name(creg)); #else int l = 0; printf("\taddu %s,",register_name(creg)); printf("$fp,%d+L_%d\n",FUNC_LVAR,lvar_offset_label); #endif } void code_bool(int e1) { char *xrn; int e2,e3; b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ creg = use_int(creg); xrn = register_name(creg); printf("\tli %s,0\n",xrn); jmp(e3=fwdlabel()); fwddef(e2); printf("\tli %s,1\n",xrn); fwddef(e3); } char * code_gt(int cond) { return (cond?"\tslt %s,%s,%s\n\tbeq %s,$0,L_%d\n": "\tslt %s,%s,%s\n\tbne %s,$0,L_%d\n"); } char * code_ugt(int cond) { return (cond?"\tsltu %s,%s,%s\n\tbeq %s,$0,L_%d\n": "\tsltu %s,%s,%s\n\tbne %s,$0,L_%d\n"); } char * code_ge(int cond) { return (cond?"\tslt %s,%s,%s\n\txori %s,%s,0x1\n\tbeq %s,$0,L_%d\n": "\tslt %s,%s,%s\n\txori %s,%s,0x1\n\tbne %s,$0,L_%d\n"); } char * code_uge(int cond) { return (cond?"\tsltu %s,%s,%s\n\txori %s,%s,0x1\n\tbeq %s,$0,L_%d\n": "\tsltu %s,%s,%s\n\txori %s,%s,0x1\n\tbne %s,$0,L_%d\n"); } char * code_eq(int cond) { return (cond?"\tbeq %s,%s,L_%d\n":"\tbne %s,%s,L_%d\n"); } void code_cmp_crgvar(int e1,int sz) { if (cmpreg==-1) cmpreg = get_register(); code_crgvar(cadr(e1),cmpreg,1,sz); } void code_cmp_crlvar(int e2,int sz) { if (cmpreg==-1) cmpreg = get_register(); code_crlvar(e2,cmpreg,1,sz); } void code_cmp_rgvar(int e1) { if (cmpreg==-1) cmpreg = get_register(); code_rgvar(e1,cmpreg); } void code_cmp_rlvar(int e2) { if (cmpreg==-1) cmpreg = get_register(); code_rlvar(e2,cmpreg); } void code_cmp_register(int e2) { cmpreg = e2; /* prevent cmpreg freeing */ } void ascii(char *s) { printf("\t.ascii \""); while(*s) { if (*s=='\n') printf("%cn",92); else if (*s<' ') printf("%c%03o",92,*s); else if (*s=='\\') printf("\\\\"); else if (*s==34) printf("%c%c",92,34); else printf("%c",*s); s++; } printf("\\0%c\n\t.align 2\n",34); } void code_string(int e1,int creg) { char *s,*crn; int lb; crn=register_name(creg); s=(char *)cadr(e1); printf("\t.rdata\n\t.align 2\n"); lb=fwdlabel(); printf("L_%d:\n",lb); ascii(s); if (output_mode==TEXT_EMIT_MODE) { printf(".text\n"); } else { text_mode(); } printf("\tla %s,L_%d\n",crn,lb); } #define MAX_COPY_LEN 20 void emit_copy(int from,int to,int length,int offset,int value,int det) { char *frn = register_name(from); char *trn = register_name(to); char *drn; int fix = 0; char *memmove = "memmove"; int dreg = get_register(); if (!dreg) error(-1); drn = register_name(dreg); /* length <0 means upward direction copy */ switch (length) { case 0: break; case 1: case -1: printf("\tlb %s,%d(%s)\n",drn,offset,frn); printf("\tsb %s,%d(%s)\n",drn,offset,trn); break; case 2: case -2: printf("\tlh %s,%d(%s)\n",drn,offset,frn); printf("\tsh %s,%d(%s)\n",drn,offset,trn); break; case 4: case -4: printf("\tlw %s,%d(%s)\n",drn,offset,frn); printf("\tsw %s,%d(%s)\n",drn,offset,trn); break; default: if (-MAX_COPY_LEN<length && length <0) { for(;length<=4;length+=4,offset-=4) emit_copy(from,to,4,offset,0,det); for(;length<=2;length+=2,offset-=2) emit_copy(from,to,2,offset,0,det); if(length>0) emit_copy(from,to,length,offset,0,det); break; } else if (length <=MAX_COPY_LEN) { for(;length>=4;length-=4,offset+=4) emit_copy(from,to,4,offset,0,det); for(;length>=2;length-=2,offset+=2) emit_copy(from,to,2,offset,0,det); if(length>0) emit_copy(from,to,length,offset,0,det); break; } code_save_stacks(); printf("\tli $6,%d\n",length); printf("\tmr $5,%s\n",frn); printf("\tmr $4,%s\n",trn); /* overrap must be allowed */ printf("\tbl L_%s$stub\n",memmove); fix=0; set_creg(RET_REGISTER,0); if (creg!=to) { free_register(to); to = creg; } break; } if (value) { /* creg must point top of the destination data */ /* this code is necessary for the value of assignment or function call */ /* otherwise we don't need this */ if (fix) printf("\taddi %s,%s,%d\n",trn,trn,fix); if(creg!=to) { free_register(creg); creg=to; } } free_register(dreg); } int struct_push(int e4,int t,int arg) { int length,count; int dreg,sreg; char *drn,*crn,*srn; g_expr(e4); length=size(t); if(length%size_of_int) { length += size_of_int - (length%size_of_int); } dreg = get_register(); if (!dreg) error(-1); drn = register_name(dreg); crn = register_name(creg); if (length<MAX_COPY_LEN) { sreg = get_register(); if (!sreg) error(-1); srn = register_name(sreg); code_lvar(cadr(arg),sreg); for(count=0;length<MAX_COPY_LEN;count++,length-=size_of_int) { if (length==0) { free_register(sreg); free_register(dreg); return count; } else { printf("\tlw %s,%d(%s)\n",drn,length-size_of_int,crn); printf("\tsw %s,%d(%s)\n",drn,length-size_of_int,srn); } } } code_lvar(cadr(arg),dreg); /* downward direction copy */ emit_copy(creg,dreg,length,0,0,1); if (dreg) free_register(dreg); return length/size_of_int; } void set_creg(int reg,int mode) { if (!is_int_reg(reg)) error(-1); if (reg!=creg) { if (reg!=ireg && mode) printf("\tmove %s,%s\n",register_name(reg),register_name(ireg)); free_register(creg); creg = ireg = reg; regs[creg]=1; } } void set_freg(int reg,int mode) { if (!is_float_reg(reg)) error(-1); if (reg!=creg) { if (reg!=freg && mode) { printf("\tfmove %s,%s\n",fregister_name(reg),fregister_name(freg)); } free_register(creg); creg = freg = reg; regs[freg]=1; } } static void move_dreg(int reg,int dreg) { if (reg!=dreg) { printf("\tmove %s,%s\n",dregister_name0(reg), dregister_name0(dreg)); printf("\tmove %s,%s\n",dregister_name1(reg), dregister_name1(dreg)); } } void set_dreg(int reg,int mode) { if (!is_double_reg(reg)) error(-1); if (reg!=creg) { if (mode) { move_dreg(reg,dreg); } free_register(creg); creg = dreg = reg; regs[dreg]=1; regs[dreg_pair0[dreg-DREG_OFFSET]]=1; regs[dreg_pair1[dreg-DREG_OFFSET]]=1; } } void use_var(int arg) { if (car(arg)==REGISTER) regs[cadr(arg)]=USING_REG; else if (car(arg)==FREGISTER) regs[cadr(arg)]=USING_REG; else if (car(arg)==DREGISTER) regs[cadr(arg)]=USING_REG; } void code_save_input_registers() { int args; NMTBL *n; int reg; int tag; int lvar; int t; /* fnptr->dsp=list4(type,fnptr->dsp,(int)n,0); */ int reg_offset = 0; int offset = 0; for(args = fnptr->dsp;args;args = cadr(args)) { n = (NMTBL *)caddr(args); tag = n->sc; reg = n->dsp; if (!n||n==&null_nptr) error(REG_ERR); if (tag==REGISTER) { /* regs[reg]==INPUT_REG case should be considered */ n->dsp = offset; offset+=size_of_int; t = INT; reg += reg_offset; /* for duplicated floating point argument */ } else if (tag==FREGISTER) { /* fregs[reg]==INPUT_REG case should be considered */ n->dsp = offset; t = n->ty; if(t==FLOAT) { offset+=size_of_float; reg_offset+=1; } else if(t==DOUBLE) { offset+=size_of_double; reg_offset+=2; } else error(-1); } else if (tag==DREGISTER) { /* fregs[reg]==INPUT_REG case should be considered */ n->dsp = offset; t = n->ty; if(t==FLOAT) { offset+=size_of_float; reg_offset+=1; } else if(t==DOUBLE) { offset+=size_of_double; reg_offset+=2; } else error(-1); } else { offset += size(n->ty); continue; } n->sc = LVAR; lvar = list2(LVAR,n->dsp); g_expr_u(assign_expr0(list2(LVAR,n->dsp),list3(tag,reg,(int)n),n->ty,t)); if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER) { free_register(reg); } } my_func_args = offset; } int simple_args(int e3) { return !contains_in_list(e3,FUNCTION) && !contains_in_list(e3,CONV) && !contains_in_list(e3,RSTRUCT) && !contains_in_list(e3,STASS) ; } int caller_arg_offset_v(int arg) { return ARG_LVAR_OFFSET+arg*size_of_int; } int function(int e1) { int e2,e3,e4,nargs,t; int arg,reg_arg,freg_arg,arg_assign; int dots; int reg_arg_list=0,ret_type,special_lvar; NMTBL *fn = 0; int jmp = 0; char *jrn; int iargs=0; special_lvar = -1; ret_type = cadr(cadddr(e1)); if (ret_type==CHAR) ret_type=INT; /* check argments type is DOTS? */ t = caddr(cadddr(e1)); if (t==0 || t==DOTS) dots = 1; else { dots = 0; for(t = caddr(cadddr(e1));t;t = cadr(t)) { if (car(t)==DOTS) dots = 1; } } e2 = cadr(e1); if (car(e2) == FNAME) { fn=(NMTBL *)cadr(e2); } else { jmp = get_register_var(0); if (car(jmp)!=REGISTER) error(-1); reg_arg_list = list2(jmp,reg_arg_list); g_expr(e2); code_register(creg,cadr(jmp)); /* g_expr(assign_expr0(jmp,e2,INT,INT)); functions are lvalue */ } /* now all input register vars are free */ code_save_stacks(); set_creg(CREG_REGISTER,0); set_freg(FREG_FREGISTER,0); set_dreg(DREG_DREGISTER,0); nargs = reg_arg = freg_arg = arg_assign = 0; for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { t=caddr(e3); e4 = car(e3); if(scalar(t)) { if (reg_arg>=MAX_INPUT_REGISTER_VAR) { arg = list2(LVAR,caller_arg_offset_v(nargs)); } else if (!simple_args(e3) && cadr(e3)) { arg = get_register_var(0); arg_assign = list2( assign_expr0(get_input_register_var(reg_arg,0,0), arg,t,t), arg_assign); } else { arg = get_input_register_var(reg_arg,0,0); } use_var(arg); /* protect from input register free */ reg_arg_list = list2(arg,reg_arg_list); g_expr_u(assign_expr0(arg,e4,t,t)); nargs ++ ; reg_arg++; iargs += size_of_int; continue; } else if (t==DOUBLE||t==FLOAT) { if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { arg = list2(LVAR,caller_arg_offset_v(nargs)); } else if (!simple_args(e3) && cadr(e3)) { arg = get_dregister_var(0,1); arg_assign = list2( assign_expr0(get_input_dregister_var(freg_arg,0,0,1), arg,t,t), arg_assign); } else { arg = get_input_dregister_var(freg_arg,0,0,1); } use_var(arg); /* protect from input register free */ reg_arg_list = list2(arg,reg_arg_list); g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */ freg_arg++; nargs += size(t)/size_of_int; if (t==DOUBLE) iargs += size(t); continue; } else if (car(t)==STRUCT||car(t)==UNION) { arg = list2(LVAR,caller_arg_offset_v(nargs)); nargs += struct_push(e4,t,arg); iargs += ((size(t)+3)/size_of_int)*size_of_int; continue; } else { error(TYERR); } ++nargs; } if (max_func_args<nargs) max_func_args=nargs; if (max_func_iargs<iargs) max_func_iargs=iargs; for(;arg_assign;arg_assign=cadr(arg_assign)) { g_expr_u(car(arg_assign)); } if (car(e2) == FNAME) { printf("\tbl\tL_%s$stub\n",fn->nm); } else { jrn = register_name(cadr(jmp)); printf("\tj %s\n",jrn); } for(;reg_arg_list;reg_arg_list=cadr(reg_arg_list)) { arg = car(reg_arg_list); if (car(arg)==REGISTER||car(arg)==DREGISTER||car(arg)==FREGISTER) free_register(cadr(arg)); else if (car(arg)==LVAR&&cadr(arg)<0) free_lvar(cadr(arg)); } if (ret_type==DOUBLE) { set_dreg(RET_DREGISTER,0); } else if (ret_type==FLOAT) { set_freg(RET_FREGISTER,0); } else if (ret_type==VOID) { } else { set_creg(RET_REGISTER,0); } return ret_type; } void code_frame_pointer(int e3) { #if R1SAVE printf("\tmove $fp,%s\n",register_name(e3)); #else printf("\tmove $fp,%s\n",register_name(e3)); #endif } void code_fix_frame_pointer(int disp_offset) { int l = 0; printf("\tla $fp,"); printf("%d+L_%d($sp)\n",FUNC_LVAR,lvar_offset_label); } void code_jmp(char *s) { max_reg_var = REG_VAR_BASE-REG_VAR_MIN; max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; printf("\tj L_%s\n",s); } void code_indirect_jmp(int e2) { max_reg_var = REG_VAR_BASE-REG_VAR_MIN; max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; printf("\tj %s\n",register_name(e2)); } int code_rindirect(int e1, int offset, int us) { char *crn; g_expr(e1); crn=register_name(creg); printf("\tlw %s,%d(%s)\n",crn,offset,crn); return INT; } int code_crindirect(int e1, int offset, int us) { char *crn; g_expr(e1); crn=register_name(creg); if (us) { printf("\tlbu %s,%d(%s)\n",crn,offset,crn); return UCHAR; } else { printf("\tlb %s,%d(%s)\n",crn,offset,crn); return CHAR; } } int code_srindirect(int e1, int offset, int us) { char *crn; g_expr(e1); crn=register_name(creg); if (us) { printf("\tlhu %s,%d(%s)\n",crn,offset,crn); return USHORT; } else { printf("\tlh %s,%d(%s)\n",crn,offset,crn); return SHORT; } } #if FLOAT_CODE int code_drindirect(int e1, int offset, int d) { char *crn; g_expr(e1); crn=register_name(creg); if (d) { printf("\tlw %s,%d(%s)\n", dregister_name0(dreg),offset,crn); printf("\tlw %s,%d(%s)\n", dregister_name1(dreg),offset+size_of_int,crn); creg = dreg; return DOUBLE; } else { printf("\tl.s %s,%d(%s)\n", fregister_name(freg),offset,crn); creg = freg; return FLOAT; } } #endif #if LONGLONG_CODE int code_lrindirect(int e1, int offset, int us) { char *crn; g_expr(e1); crn=register_name(creg); return LONGLONG; } #endif void code_assign_gvar(int e2,int creg,int byte) { char *crn,*name; name = ((NMTBL*)cadr(e2))->nm; crn=register_name(creg); if (byte==1) { printf("\tsb %s,%s\n",crn,name); } if (byte==size_of_short) { printf("\tsh %s,%s\n",crn,name); } else { printf("\tsw %s,%s\n",crn,name); } } void code_assign_lvar(int e2,int creg,int byte) { char *crn; crn=register_name(creg); if (byte==1) { printf("\tsb %s,",crn); } else if (byte==size_of_short) { printf("\tsh %s,",crn); } else { printf("\tsw %s,",crn); } lvar(e2); } void code_assign_register(int e2,int byte,int creg) { if (e2!=creg) printf("\tmove %s,%s\n",register_name(e2),register_name(creg)); } void code_assign(int e2,int byte,int creg) { char *drn=register_name(e2); char *crn=register_name(creg); if (byte==1) { printf("\tsb %s,0(%s)\n",crn,drn); } else if (byte==size_of_short) { printf("\tsh %s,0(%s)\n",crn,drn); } else { printf("\tsw %s,0(%s)\n",crn,drn); } } void code_register_assop(int e2,int op,int byte) { int reg; int xreg = creg; creg = reg = e2; tosop(op,xreg); creg = xreg; if (creg!=reg) printf("\tmove %s,%s\n",register_name(creg),register_name(reg)); } void code_assop(int op,int byte,int sign) { char *xrn,*crn,*drn; int xreg; int edx = get_register(); if(!edx) error(-1); xrn = register_name(xreg = emit_pop(0)); /* pop e3 value */ regs[xreg]=1; printf("# assop\n\tmr %s,%s\n",register_name(edx),register_name(creg)); ld_indexx(byte,0,edx,sign); tosop(op,xreg); crn = register_name(creg); drn = register_name(edx); printf("\t%s %s,0(%s)\n",cstore(byte),crn,drn); free_register(edx); emit_pop_free(xreg); } void tosop(int op,int oreg) { int dx; char *orn,*crn; if(oreg==-1) { error(-1); } else if (oreg<= -REG_LVAR_OFFSET) { dx = get_register(); if (dx<0) error(-1); code_rlvar(oreg+REG_LVAR_OFFSET,dx); oreg = dx; } switch(op) { case LSHIFT: case ULSHIFT: shift("sll",oreg); return; case RSHIFT: shift("srl",oreg); return; case URSHIFT: shift("sra",oreg); return; } orn = register_name(oreg); crn = register_name(creg); switch(op) { case ADD: printf("\taddu %s,%s,%s\n",crn,crn,orn); break; case SUB: printf("\tsubu %s,%s,%s\n",crn,crn,orn); break; case CMP: printf("\tslt %s,%s\n",crn,orn); break; case BAND: printf("\tand %s,%s,%s\n",crn,crn,orn); break; case EOR: printf("\txor %s,%s,%s\n",crn,crn,orn); break; case BOR: printf("\tor %s,%s,%s\n",crn,crn,orn); break; case MUL: printf("\tmult %s,%s,%s\n",crn,crn,orn); break; case UMUL: printf("\tmultu %s,%s,%s\n",crn,crn,orn); break; case DIV: printf("\tdivw %s,%s,%s\n",crn,crn,orn); break; case UDIV: case MOD: case UMOD: printf("\t%s $0,%s,%s\n",(op==UDIV||op==UMOD)?"divu":"div",crn,orn); printf("\t%s %s\n",(op==MOD||op==UMOD)?"mflo":"mfhi",crn); printf("\t.set noreorder\n"); printf("\tbeql %s,$0,1f\n",orn); printf("\tbreak 7\n"); printf("1:\n"); printf("\t.set reorder\n"); break; default: error(-1); } if(oreg!=creg) free_register(oreg); } void shift(char *op, int reg) { char *crn = register_name(creg); char *rrn = register_name(reg); printf("\t%s %s,%s,%s\n",op,crn,rrn,crn); } int code_const_op_p(int op,int v) { if (op==BAND||op==DIV||op==UDIV||op==MOD||op==UMOD) return 0; return 0; } void oprtc(int op,int v) { } void ld_indexx(int byte, int n, int xreg,int sign) { char *crn = register_name(creg); printf("\t%s %s,%d(%s)\n",cload(sign,byte),crn,n, register_name(xreg)); } int code_csvalue() { return creg; } void code_cmpdimm(int e, int csreg) { /* used in dosiwtch() */ if(chk) return; creg = use_int(creg); printf("\tli %s,%d\n",register_name(creg),e); cmpreg = csreg; } void code_opening(char *s) { /* this is called once per month */ char *p=cheapp; printf("\t.file \"%s\"\n",s); /* printf("\t.version\t\"01.01\"\n"); */ /* printf("gcc2_compiled.:\n"); */ printf("\t.abicalls\n"); printf("\t.text\n"); if (asi) { fclose(asi); asi = 0; } while ((*cheapp++ = *s++)) { if (*s=='.') { *cheapp++=*s++; *cheapp++='i'; *cheapp++=0; break; } } asi = fopen(p,"w"); printf(".include \"%s\"\n",p); if (!asi) error(-1); } void rexpr(int e1, int l1, char *s,int t) { char *crn,*drn; if (cmpreg>=0) { free_register(cmpreg); cmpreg = -1; } g_expr(cadr(e1)); emit_push(); g_expr(caddr(e1)); cmpreg = emit_pop(0); crn = register_name(creg); drn = register_name(cmpreg); if (s[1] == 's') { if (s[16]=='x') { /* slt $2,$2,$3; xroi $2,$2,0x1; beq $2,$0,L1 */ printf(s,crn,drn,drn,crn,crn,crn,l1); } else { /* slt $2,$2,$3; beq $2,$0,L1 */ printf(s,crn,drn,drn,crn,l1); } } else { /* beq $2,$3,L1 */ printf(s,crn,drn,l1); } free_register(cmpreg) ; cmpreg = -1; } void jcond(int l, char cond) { if (chk) return; if (cmpreg==-1) error(-1); printf("\tb%s %s,%s,L_%d\n", cond?"ne":"eq", register_name(creg),register_name(cmpreg), l); free_register(cmpreg); cmpreg = -1; } void jmp(int l) { control=0; if (chk) return; printf("\tj\tL_%d\n",l); } void gen_comment(char *s) { if (chk) return; printf("## %s",s); } void code_enter(char *name) { if (output_mode!=TEXT_EMIT_MODE) text_mode(); else printf("\t.align 3\n"); /* if (stmode!=STATIC) printf(".globl _%s\n",name); */ printf(".ent %s\n",name); printf("_%s:\n",name); code_disp_label=fwdlabel(); printf("\t.set noreorder\n"); printf("\t.cpload $25\n"); printf("\t.set reorder\n"); printf("\tsubu $sp,$sp,L_%d\n",code_disp_label); printf("\t.cprestore L_%d\n",cprestore_label); max_func_args = 0; max_func_iargs = 0; } void code_enter1(int args) { set_creg(CREG_REGISTER,0); set_freg(FREG_FREGISTER,0); set_dreg(DREG_DREGISTER,0); } void code_leave(char *name) { int r1_offsetv; disp&= -size_of_int; r1_offsetv = -disp+max_func_args*size_of_int+code_disp_offset; fprintf(asi,"L_%d=%d\n",code_disp_label,-r1_offsetv); local_table(); free_all_register(); } void enter(char *name) { if (output_mode!=TEXT_EMIT_MODE) text_mode(); else printf("\t.align 2\n"); /* if (stmode!=STATIC) printf(".globl _%s\n",name); */ printf(".ent %s\n",name); printf("_%s:\n",name); r1_offset_label = fwdlabel(); lvar_offset_label = fwdlabel(); disp_label = fwdlabel(); mask_label = fwdlabel(); mask1_label = fwdlabel(); fmask_label = fwdlabel(); fmask1_label = fwdlabel(); cprestore_label = fwdlabel(); printf("\t.frame $fp,L_%d,$31\n",r1_offset_label); printf("\t.mask L_%d,L_%d\n",mask_label,mask1_label); printf("\t.fmask L_%d,L_%d\n",fmask_label,fmask1_label); printf("\t.set noreorder\n"); printf("\t.cpload $25\n"); printf("\t.set reorder\n"); printf("\tsubu $sp,$sp,L_%d\n",disp_label); printf("\t.cprestore L_%d\n",cprestore_label); max_func_args = 0; max_func_iargs = 0; } void enter1() { set_creg(CREG_REGISTER,0); set_freg(FREG_FREGISTER,0); set_dreg(DREG_DREGISTER,0); } static unsigned int code_mask_label() { int i; unsigned int mask=0; for(i=0;i<32;i++) { if (i==28||i==31||(REG_VAR_MIN<=i&&i<=REG_VAR_MIN+max_reg_var)) { mask |= (1<<i); } } return mask; } static unsigned int code_fmask_label() { int i; unsigned int mask=0; for(i=0;i<32;i++) { if (FREG_VAR_MIN<=i&&i<=FREG_VAR_MIN+max_freg_var) { mask |= (1<<i); } } return mask; } void leave(int control, char *name) { int retcont1=0,sz; int r1_offsetv; if (max_freg_var>=0 && max_freg_var<=3) max_freg_var=3; reg_save = (REAL_MAX_REGISTER-(REG_VAR_BASE-max_reg_var))*size_of_int; freg_save = (REAL_MAX_FREGISTER-(FREG_VAR_BASE-max_freg_var))*size_of_float; if (control) { code_set_return_register(1); } if (retcont) { /* return from CbC segement */ if (control) jmp(retlabel); retcont1 = fwdlabel(); fwddef(retcont); if (cadr(fnptr->ty)==FLOAT) { if (freg!=RET_FREGISTER) printf("\tmov.s %s,%s\n",register_name(RET_FREGISTER), register_name(freg)); } else if (cadr(fnptr->ty)==DOUBLE) { move_dreg(RET_DREGISTER,dreg); } else if (cadr(fnptr->ty)>0&&( car(cadr(fnptr->ty))==STRUCT || car(cadr(fnptr->ty))==UNION)) { sz = size(cadr(fnptr->ty)); printf("\tli $4,%d\n",sz); printf("\tsubl $5,$4,$fp\n"); printf("\tlw $3,(%d)($fp)\n",(my_func_args-1)*size_of_int); emit_copy(6,3,sz,0,1,1); } else if (cadr(fnptr->ty)!=VOID) { if (creg!=RET_REGISTER) printf("\tmove $3,%s\n",register_name(creg)); } printf("\tj L_%d\n",retcont1); } fwddef(retlabel); if (retcont) { fwddef(retcont1); } if (max_freg_var>=0) { } else { } fprintf(asi,"L_%d=%d\n",r1_offset_label,0); fprintf(asi,"L_%d=%d\n",lvar_offset_label,0); fprintf(asi,"L_%d=0x%x\n",mask_label,code_mask_label()); fprintf(asi,"L_%d=%d\n",mask1_label,0); fprintf(asi,"L_%d=0x%x\n",fmask_label ,code_fmask_label()); fprintf(asi,"L_%d=%d\n",fmask1_label,0); fprintf(asi,"L_%d=%d\n",cprestore_label ,max_func_iargs); disp &= -size_of_int; r1_offsetv = 0; printf("\tmove $sp,$fp\n"); printf("\tlw $31,%d($sp)\n",-disp); printf("\tlw $fp,%d($sp)\n",-disp-4); printf("\taddu $sp,$sp,%d\n",r1_offsetv); printf("\tj $31\n"); printf("\t.end print\n"); fprintf(asi,"L_%d=%d\n",disp_label,-r1_offsetv); code_offset_set(); local_table(); labelno++; free_all_register(); } void code_set_return_register(int mode) { if (cadr(fnptr->ty)==DOUBLE) { set_dreg(RET_DREGISTER,mode); } else if (cadr(fnptr->ty)==FLOAT) { set_freg(RET_FREGISTER,mode); } else if (cadr(fnptr->ty)==VOID) { } else { set_creg(RET_REGISTER,mode); } } int code_get_fixed_creg(int reg,int type) { return creg; } void code_set_fixed_creg(int reg,int mode,int type) { if (type==FLOAT) { set_freg(reg,mode); } else if (type==DOUBLE) { set_dreg(reg,mode); } else { set_creg(reg,mode); } } void gen_gdecl(char *n, int gpc) { if (stmode!=STATIC) printf("\t.globl _%s\n",n); } void align(int t) { if (t!=CHAR) { if (data_alignment & 1) printf("\t.align 2\n"); data_alignment = 0; } } void emit_data(int e, int t, NMTBL *n) { int l; #if FLOAT_CODE double d; float f; #endif char *name; name = n->nm; if(mode!=GDECL&&mode!=STADECL) { error(-1); return; } if (chk) return; if (n->dsp != -1) { n->dsp = -1; /* initiallized flag */ /* printf(".globl\t_%s\n",name); */ data_mode(name); align(t); printf("_%s:\n",name); } else { data_mode(0); } if(car(e)==CONST) { if (t==CHAR||t==UCHAR) { printf("\t.byte %d\n",cadr(e)); if (data_alignment>0) data_alignment++; gpc += 1; } else if (t==SHORT||t==USHORT) { printf("\t.short %d\n",cadr(e)); if (data_alignment>0) data_alignment++; gpc += 2; } else { printf("\t.word %d\n",cadr(e)); gpc += size_of_int; } #if FLOAT_CODE } else if(t==DOUBLE) { d = dcadr(e); printf("\t.word\t0x%x\n\t.word\t0x%x\n",code_d1(d),code_d2(d)); } else if(t==FLOAT) { f = dcadr(e); printf("\t.word\t0x%x\n",*(int *)&f); #endif } else if(t!=CHAR) { gpc += size_of_int; if(car(e)==ADDRESS&&car(cadr(e))==GVAR) { printf("\t.word _%s\n",((NMTBL *)cadr(cadr(e)))->nm); } else if(car(e)==FNAME) { printf("\t.word _%s\n",((NMTBL *)cadr(e))->nm); } else if(car(e)==GVAR) { printf("\t.word _%s\n",((NMTBL *)cadr(e))->nm); } else if(car(e)==STRING) { if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) { l = fwdlabel(); printf("\t.word L_%d\n",l); printf(".rdata\n\t.align 2\n"); printf("L_%d:\n",l); output_mode = RODATA_EMIT_MODE; } ascii((char *)cadr(e)); } else error(TYERR); } else error(TYERR); } void emit_data_closing(NMTBL *n) { #ifdef DOT_SIZE int lb; #endif if (chk) return; if (mode==GDECL) { data_mode(0); #ifdef DOT_SIZE lb=fwdlabel(); printf("L_%d:\n",lb); printf("\t.size\t%s,L_%d-%s\n",n->nm,lb,n->nm); #endif } } void global_table(void) { NMTBL *n; int init; init=0; for(n=ntable;n < &ntable[GSYMS];n++) { if ((n->sc == GVAR) && n->dsp != -1) { /* n->dsp = -1 means initialized global */ if (init==0) { data_mode(0); init=1; } printf(".comm _%s,%d\n",n->nm,size(n->ty)); } else if ((n->sc==STATIC) && n->dsp != -1) { /* n->dsp = -1 means initialized global */ if (init==0) { data_mode(0); init=1; } printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); } } } void local_table(void) { NMTBL *n; int init; init=0; /* static local variables */ for(n=ntable+GSYMS;n < &ntable[GSYMS+LSYMS];n++) { if (n->sc == GVAR) { if (init==0) { data_mode(0); init=1; } if (n->dsp!=-1) /* n->dsp = -1 means initialized global */ printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); } } } void text_mode(void) { if (output_mode!=TEXT_EMIT_MODE) { printf(".text\n"); printf("\t.align 2\n"); output_mode = TEXT_EMIT_MODE; } } void data_mode(char *name) { if (output_mode!=DATA_EMIT_MODE) { printf(".data\n"); output_mode = DATA_EMIT_MODE; } if (name) printf("\t.type\t%s,@object\n",name); } #if FLOAT_CODE char * fstore(int d) { return (d?"stfd":"stfs"); } char * fload(int d) { return d?"lfd":"lfs"; } static void code_dpfunc(char *f) { if (max_func_iargs<16) max_func_iargs=16; printf("\tjal %s\n",f); } void code_cmp_dregister(int e2,int d) { char *frn,*grn; int greg; if (d) { printf("\tli.d $6,%g\n",0.0); code_save_stacks(); move_dreg(4+DREG_OFFSET,freg); code_dpfunc("dpcmp"); if (max_func_iargs<16) max_func_iargs=16; set_dreg(RET_DREGISTER,0); return; } else { grn = register_name(greg = get_dregister(d)); frn = register_name(e2); printf("\tli.s %s,%g\n",grn,0.0); printf("\tc.eq.s %s,%s\n",grn,frn); free_register(greg); return; } } void code_dregister(int e2,int freg,int d) { if (freg!=e2) { if (d) { if (!is_double_reg(e2)) error(-1); move_dreg(freg,e2); } else { if (!is_float_reg(e2)) error(-1); printf("\tfmr %s,%s\n",fregister_name(freg),fregister_name(e2)); } } } void code_dassign_gvar(int e2,int freg,int d) { NMTBL *n = (NMTBL*)cadr(e2); if (d) { if (!is_double_reg(freg)) error(-1); printf("\tsw %s,0(%s)\n",dregister_name0(freg),n->nm); printf("\tsw %s,0(%s)\n",dregister_name1(freg),n->nm); } else { printf("\ts.s %s,0(%s)\n",fregister_name(freg),n->nm); } } void code_dassign_lvar(int e2,int freg,int d) { if (d) { if (!is_double_reg(freg)) error(-1); printf("\tsw %s,",dregister_name0(freg)); lvar(e2); printf("\tsw %s,",dregister_name1(freg)); e2 += size_of_double/2; } else { printf("\ts.s %s,",fregister_name(freg)); } lvar(e2); } void code_dassign(int e2,int freg,int d) { if (d) { if (!is_double_reg(freg)) error(-1); printf("\tsw %s,0(%s)\n",dregister_name0(freg),register_name(e2)); printf("\tsw %s,4(%s)\n",dregister_name1(freg),register_name(e2)); } else { printf("\ts.s %s,0(%s)\n",fregister_name(freg),register_name(e2)); } } void code_dassign_dregister(int e2,int d,int freg) { /* これってさ、code_dregister と同じ? */ if (e2!=freg) { if (d) { if (!is_double_reg(freg)) error(-1); move_dreg(freg,e2); } else { printf("\tmov.s %s,%s\n",fregister_name(e2),fregister_name(freg)); } } } static double d0 = 1.0; int code_d1(double d) { int *i = (int *)&d0; int *j = (int *)&d; return (i[1] == 0x3ff00000)?j[0]:j[1]; } int code_d2(double d) { int *i = (int *)&d0; int *j = (int *)&d; return (i[1] == 0x3ff00000)?j[1]:j[0]; } int code_f(double d) { float f = d; int *j = (int *)&f; return *j; } void code_dconst(int e2,int freg,int d) { double value = dcadr(e2); char *frn; if (d) { printf("\tli.d %s,%g\n",dregister_name0(freg),value); } else { frn = fregister_name(freg); printf("\tli.s %s,%g\n",frn,value); } } void code_dneg(int freg,int d) { char *frn; if (d) { code_save_stacks(); move_dreg(4+DREG_OFFSET,freg); code_dpfunc("dpneg"); set_dreg(RET_DREGISTER,0); } else { frn = fregister_name(freg); printf("\tfneg %s,%s\n",frn,frn); } } void code_d2i(int freg0) { code_save_stacks(); set_dreg(RET_DREGISTER,1); code_dpfunc("dptoli"); set_creg(RET_REGISTER,0); } void code_i2d(int creg0) { code_save_stacks(); set_creg(RET_REGISTER,1); code_dpfunc("litodp"); set_dreg(RET_DREGISTER,0); } void code_d2u(int freg0) { code_save_stacks(); set_dreg(RET_DREGISTER,1); code_dpfunc("dptoul"); set_creg(RET_REGISTER,0); } void code_u2d(int creg0) { code_save_stacks(); set_creg(RET_REGISTER,1); code_dpfunc("ultodp"); set_dreg(RET_DREGISTER,0); } void code_d2f(int freg) { code_save_stacks(); set_dreg(RET_DREGISTER,1); code_dpfunc("dptofp"); set_freg(RET_FREGISTER,0); } void code_f2d(int freg) { code_save_stacks(); set_freg(RET_FREGISTER,1); code_dpfunc("fptodp"); set_dreg(RET_DREGISTER,0); } void code_f2i(int freg) { printf("\ttrunc.w.s %s,%s,%s\n",register_name(freg), register_name(freg),register_name(ireg)); creg = ireg; } void code_f2u(int freg) { printf("\ttrunc.w.s %s,%s,%s\n",register_name(freg), register_name(freg),register_name(ireg)); creg = ireg; } void code_i2f(int creg0) { printf("\tcvt.s.w %s,%s\n",register_name(freg),register_name(freg)); creg = freg; } void code_u2f(int creg0) { printf("\tcvt.s.w %s,%s\n",register_name(freg),register_name(freg)); creg = freg; } void code_drgvar(int e2,int d,int freg) { char *name = ((NMTBL*)cadr(e2))->nm; if (d) { printf("\tlw %s,%s\n",dregister_name0(freg),name); printf("\tlw %s,%s\n",dregister_name1(freg),name); } else { printf("\tl.s %s,%s\n",fregister_name(freg),name); } } void code_drlvar(int e2,int d,int freg) { if (d) { printf("\tlw %s,",dregister_name0(freg)); lvar(e2); printf("\tlw %s,",dregister_name1(freg)); lvar(e2+size_of_double/2); } else { printf("\tl.s %s,",fregister_name(freg)); lvar(e2); } } void code_cmp_drgvar(int e2,int d) { char *frn; int g; if (d) { code_save_stacks(); set_dreg(RET_DREGISTER,1); code_drgvar(e2,d,RET_DREGISTER+2); code_dpfunc("dcmp"); } else { frn=fregister_name(freg); g=get_dregister(d); code_drgvar(e2,d,g); printf("\tfc.eq.s %s,%s\n",frn,fregister_name(g)); free_register(g); } } void code_cmp_drlvar(int e2,int d) { char *frn=fregister_name(freg); int g; if (d) { code_save_stacks(); set_dreg(RET_DREGISTER,1); code_drgvar(e2,d,RET_DREGISTER+2); code_dpfunc("dcmp"); } else { g=get_dregister(d); code_drlvar(e2,d,g); printf("\tc.eq.s %s,%s\n",frn,fregister_name(g)); free_register(g); } } static void dtosop0(char *opn,int e1,int d,int cmp) { char *frn; char *grn; if (d) { code_save_stacks(); set_dreg(RET_DREGISTER,1); move_dreg(RET_DREGISTER+2,e1); code_dpfunc(opn); } else { frn=fregister_name(freg); grn=fregister_name(e1); if (cmp) { printf("\t%s %s,%s\n",opn,frn,grn); } else { printf("\t%s %s,%s,%s\n",opn,frn,frn,grn); } } free_register(e1); } void dtosop(int op,int e1) { switch(op) { case FADD: dtosop0("fadd",e1,0,0); return; case DADD: dtosop0("dpadd",e1,1,0); return; case FSUB: dtosop0("fadd",e1,0,0); return; case DSUB: dtosop0("dpsub",e1,1,0); return; case FDIV: dtosop0("fadd",e1,0,0); return; case DDIV: dtosop0("dpdiv",e1,1,0); return; case FMUL: dtosop0("fadd",e1,0,0); return; case DMUL: dtosop0("dpmul",e1,1,0); return; case DCMPGE: case DCMP: dtosop0("dpcmp",e1,1,1); return; case FCMPGE: dtosop0("c.le.s",e1,0,1); return; case FCMP: dtosop0("c.eq.s",e1,0,1); return; default: error(-1); return; } } void code_dassop(int op,int d) { /* we have lvalue in creg, applied floating value is in freg */ char *frn; int xreg; char *crn=register_name(creg); if (d) { xreg=emit_dpop(d); printf("\tlw %s,0(%s)\n",dregister_name0(freg),crn); printf("\tlw %s,%d(%s)\n",dregister_name1(freg),size_of_int,crn); dtosop(op,xreg); printf("\tsw %s,0(%s)\n",dregister_name0(freg),crn); printf("\tsw %s,%d(%s)\n",dregister_name1(freg),size_of_int,crn); emit_dpop_free(xreg,d); creg = dreg; } else { xreg=emit_dpop(d); frn=fregister_name(freg); crn=register_name(creg); printf("\tl.s %s,0(%s)\n",frn,crn); dtosop(op,xreg); printf("\ts.s %s,0(%s)\n",frn,crn); emit_dpop_free(xreg,d); creg = freg; } } void code_register_dassop(int reg,int op,int d) { error(-1); } void code_dpreinc(int e1,int e2,int d,int reg) { char *frn; char *crn; int g; char *grn; g_expr(e2); if (d) { crn=register_name(creg); frn=fregister_name(freg); code_save_stacks(); set_dreg(RET_DREGISTER,0); printf("\tlw $4,0(%s)\n",crn); printf("\tlw $5,%d(%s)\n",size_of_int,crn); printf("\tli.d $6,1.0\n"); if (caddr(e1)>0) code_dpfunc("dpadd"); else code_dpfunc("dpsub"); printf("\tsw $2,0(%s)\n",crn); printf("\tsw $3,%d(%s)\n",size_of_int,crn); creg = dreg; } else { crn=register_name(creg); frn=fregister_name(freg); grn=fregister_name(g=get_dregister(d)); printf("\tl.s %s,0(%s)\n",frn,crn); printf("\tli.s %s,1.0\n",grn); if (caddr(e1)>0) printf("\tfadd %s,%s,%s\n",frn,frn,grn); else printf("\tfsub %s,%s,%s\n",frn,frn,grn); printf("\ts.s %s,0(%s)\n",frn,crn); free_register(g); creg = freg; } } void code_dpostinc(int e1,int e2,int d,int reg) { char *frn; char *crn; int g; char *grn; g_expr(e2); if (d) { crn=register_name(creg); g = get_dregister(d); set_dreg(RET_DREGISTER,0); printf("\tlw $4,0(%s)\n",crn); printf("\tlw $5,%d(%s)\n",size_of_int,crn); move_dreg(g,4+DREG_OFFSET); printf("\tli.d $6,1.0\n"); if (caddr(e1)>0) code_dpfunc("dpadd"); else code_dpfunc("dpsub"); set_dreg(RET_DREGISTER,0); printf("\tsw $2,0(%s)\n",crn); printf("\tsw $3,%d(%s)\n",size_of_int,crn); free_register(dreg); set_dreg(g,0); creg = g; } else { crn=register_name(creg); frn=fregister_name(freg); grn=fregister_name(g=get_dregister(d)); printf("\tl.s %s,0(%s)\n",frn,crn); printf("\tli.s %s,1.0\n",grn); if (caddr(e1)>0) printf("\tfadd %s,%s,%s\n",frn,frn,grn); else printf("\tfsub %s,%s,%s\n",frn,frn,grn); printf("\ts.s %s,0(%s)\n",grn,crn); free_register(g); creg = freg; } } void drexpr(int e1, int e2,int l1, int op) { g_expr(list3(((op==FOP+EQ||op==FOP+NEQ)?DCMP:FCMPGE),e1,e2)); switch(op) { case DOP+GE: printf("\tbgez\tL_%d\n",l1); break; case DOP+GT: printf("\tbltz\tL_%d\n",l1); break; case DOP+EQ: printf("\tbeq\tL_%d\n",l1); break; case DOP+NEQ: printf("\tbne\tL_%d\n",l1); break; case FOP+GE: printf("\tbc1tl\tL_%d\n",l1); break; case FOP+GT: printf("\tbc1tl\tL_%d\n",l1); break; case FOP+EQ: printf("\tbc1f\tL_%d\n",l1); break; case FOP+NEQ: printf("\tbc1f\tL_%d\n",l1); break; } } int emit_dpop(int d) { int xreg,reg; if (d) xreg=pop_dregister(); else xreg=pop_fregister(); if (xreg<= -REG_LVAR_OFFSET) { reg = get_dregister(d); code_drlvar(REG_LVAR_OFFSET+xreg,d,reg); free_lvar(REG_LVAR_OFFSET+xreg); xreg=reg; } return xreg; } void emit_dpop_free(int e1,int d) { free_register(e1); } void emit_dpush(int d) { int new_reg; if (freg_sp>MAX_MAX) error(-1); new_reg = get_dregister(d); if (d) { dreg_stack[dreg_sp++] = dreg; /* push するかわりにレジスタを使う */ creg = dreg = new_reg; } else { freg_stack[freg_sp++] = freg; /* push するかわりにレジスタを使う */ creg = freg = new_reg; } } #endif void code_save_stacks() { int i,reg; for(i=0;i<reg_sp;i++) { if ((reg=reg_stack[i])>=0) { code_assign_lvar( (reg_stack[i]=new_lvar(size_of_int)),reg,0); reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; } } #if FLOAT_CODE for(i=0;i<dreg_sp;i++) { if ((reg=dreg_stack[i])>=0) { code_dassign_lvar( (dreg_stack[i]=new_lvar(size_of_double)),reg,1); dreg_stack[i]= dreg_stack[i]-REG_LVAR_OFFSET; } } for(i=0;i<freg_sp;i++) { if ((reg=freg_stack[i])>=0) { code_dassign_lvar( (freg_stack[i]=new_lvar(size_of_float)),reg,0); freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; } } #endif } void emit_lib(char *p[]) { while(*p) { printf("%s\n",*p++); } } void code_closing() { global_table(); /* printf("\t.ident \"Micro-C compiled\"\n"); */ fclose(asi); } #if LONGLONG_CODE /* 64bit int part */ void lrexpr(int e1, int e2,int l1, int op) { } int lpop_register() { return 0; } int emit_lpop() { return 0; } void code_lregister(int e2,int reg) { } void code_cmp_lregister(int reg) { } void code_cmp_lrgvar(int e1,int e2) { } void code_cmp_lrlvar(int e1,int e2) { } void code_lassign(int e1,int e2) { } void code_lassign_gvar(int e1,int e2) { } void code_lassign_lvar(int e1,int e2) { } void code_lassign_lregister(int e2,int reg) { } void code_lconst(int e1,int e2) { } void code_lneg(int e1) { } void code_lrgvar(int e1,int e2) { } void code_lrlvar(int e1,int e2) { } void ltosop(int e1,int e2) { } int code_lconst_op_p(int op,int e) {return 0;} void loprtc(int op,int e) {} void emit_lpop_free(int e1) { } void emit_lpush() { } void code_i2ll(int creg) { } void code_i2ull(int creg) { } void code_u2ll(int creg) { } void code_u2ull(int creg) { } void code_ll2i(int creg) { } void code_ll2u(int creg) { } void code_ull2i(int creg) { } void code_ull2u(int creg) { } #if FLOAT_CODE void code_d2ll(int creg) { } void code_d2ull(int creg) { } void code_f2ll(int creg) { } void code_f2ull(int creg) { } void code_ll2d(int creg) { } void code_ll2f(int creg) { } void code_ull2d(int creg) { } void code_ull2f(int creg) { } void code_ull2ll(int creg) { } void code_ull2ull(int creg) { } #endif void code_lpreinc(int e1,int e2,int reg) { } void code_lpostinc(int e1,int e2,int reg) { } void code_lassop(int op) { } void code_register_lassop(int reg,int op) { } #endif /* end */