Mercurial > hg > CbC > old > device
changeset 246:0dcc0ec81ed2
MIPS on going (90%)
author | kono |
---|---|
date | Mon, 10 May 2004 21:12:55 +0900 |
parents | 8a72b0afccfc |
children | 0252050601bd |
files | Changes mc-code-ia32.c mc-code-mips.c mc-code-powerpc.c mc-codegen.c mc.h |
diffstat | 6 files changed, 2794 insertions(+), 1340 deletions(-) [+] |
line wrap: on
line diff
--- a/Changes Thu May 06 11:38:56 2004 +0900 +++ b/Changes Mon May 10 21:12:55 2004 +0900 @@ -4118,3 +4118,21 @@ longlong/float のregressionはいいんだけど、もう少し 整合性があった方がいいかもね。 + +なんか、Linux のinclude directory って、どうにかなんないの? + +assop で、 + calc left exp + move creg,dreg + move const,creg + op creg,(dreg) +って、やっているのなんか変じゃない? + +a && b で、b のboolを計算しているのは変。use のフラグ +を見るのを追加したら。 + + +Sat May 8 21:29:32 JST 2004 + +浮動小数点やlong longの代入で同じ値は一つにまとめるべきだよね。 +連想 list を一つ持てば良いだけだし。
--- a/mc-code-ia32.c Thu May 06 11:38:56 2004 +0900 +++ b/mc-code-ia32.c Mon May 10 21:12:55 2004 +0900 @@ -12,6 +12,7 @@ "/usr/include/diet/", "/usr/lib/gcc-lib/i386-linux/2.95.4/include/", "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/", + "/usr/lib/dietlibc/include/", 0 }; @@ -1222,7 +1223,7 @@ crn = register_name(creg,0); use_int(reg); printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0)); - return us?UNSIGNED:INT; + return sign?INT:UNSIGNED; } int @@ -1235,7 +1236,7 @@ crn = register_name(creg,0); use_int(reg); printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0)); - return us?UCHAR:CHAR; + return sign?CHAR:UCHAR; } int @@ -1248,7 +1249,7 @@ crn = register_name(creg,0); use_int(reg); printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0)); - return us?USHORT:SHORT; + return sign?SHORT:USHORT; } #if FLOAT_CODE
--- a/mc-code-mips.c Thu May 06 11:38:56 2004 +0900 +++ b/mc-code-mips.c Mon May 10 21:12:55 2004 +0900 @@ -1,4 +1,4 @@ -/* Micro-C Code Generatation Part for MIPS (PS2Linux) */ +/* Micro-C Code Generatation Part for Power PC (Mac OS X) */ /* $Id$ */ #define EXTERN extern @@ -16,46 +16,54 @@ #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 init_ptr_cache(); +static void ld_indexx(int byte, int n, int xreg,int reg,int sign); static void local_table(void); -static void shift(char *op, int reg); +static void shift(char *op, int creg,int reg); static int struct_push(int e4,int t,int arg); +static int creg; + static int output_mode = TEXT_EMIT_MODE; static int data_alignment = 0; static int code_disp_label; -static int disp_label; +static int code_setup; 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]; /* 実際のレジスタの領域 */ +static int freg,ireg,lreg; +static int cmpreg; + +int code_lassop_p = 1; + +#define SIZE_OF_INT 4 +#define SIZE_OF_SHORT 2 +#define SIZE_OF_FLOAT 4 +#define SIZE_OF_DOUBLE 8 +#define SIZE_OF_LONGLONG 8 +#define ENDIAN 1 + +int size_of_int = SIZE_OF_INT; +int size_of_short = SIZE_OF_SHORT; +int size_of_float = SIZE_OF_FLOAT; +int size_of_double = SIZE_OF_DOUBLE; +int size_of_longlong = SIZE_OF_LONGLONG; +int endian = ENDIAN; + +static int reg_sp; /* REGister Stack-Pointer */ +static 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]; /* 実際のレジスタの領域 */ +static int freg_sp; /* floating point REGister Stack-Pointer */ +static int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ + +static int lreg_sp; /* longlong REGister Stack-Pointer */ +static int lreg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ #define REG_fp 1 #define REG_sp 30 @@ -64,31 +72,27 @@ #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 FREG_VAR_BASE 29 +#define FREG_VAR_MIN 18 +#define MIN_TMP_FREG 4 +#define MAX_TMP_FREG 17 + +int MAX_REGISTER=30; /* PowerPCのレジスタを10個まで使う*/ +int MAX_FREGISTER=31; +#define REAL_MAX_REGISTER 32 /* PowerPCのレジスタが32ということ*/ +#define REAL_MAX_FREGISTER 32 /* PowerPCのレジスタが32ということ*/ +#define REAL_MAX_LREGISTER 16 + +#define FREG_OFFSET REAL_MAX_REGISTER +#define LREG_OFFSET (REAL_MAX_REGISTER+REAL_MAX_FREGISTER) #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 ) +#define RET_LREGISTER_H 3 /* high word */ +#define RET_LREGISTER_L 4 /* low word */ +#define RET_LREGISTER LREG_OFFSET int MAX_INPUT_REGISTER_VAR = 7-MIN_TMP_REG; int MAX_CODE_INPUT_REGISTER_VAR = 7-MIN_TMP_REG; @@ -97,21 +101,20 @@ 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 powerpc_regs[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+ + REAL_MAX_LREGISTER]; +static int regv_h0[REAL_MAX_LREGISTER]; +static int regv_l0[REAL_MAX_LREGISTER]; +#define regv_h(i) regv_h0[(i)-LREG_OFFSET] +#define regv_l(i) regv_l0[(i)-LREG_OFFSET] static int *regs = powerpc_regs; +#define CREG_REGISTER (MAX_TMP_REG) +#define FREG_FREGISTER (MAX_TMP_FREG+FREG_OFFSET) +#define LREG_LREGISTER (MAX_TMP_REG+LREG_OFFSET) + + static int max_reg_var, max_freg_var; static char *reg_name[] = { @@ -125,71 +128,117 @@ "$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 register_name(i) reg_name[i] +#define fregister_name(i) reg_name[i] +#define lregister_name_low(i) reg_name[regv_l(i)] +#define lregister_name_high(i) reg_name[regv_h(i)] +static int emit_dpop_regvar(int d); + +char *r(i) { return register_name(i); } +char *f(i) { return fregister_name(i); } +char *ll(i) { return lregister_name_low(i); } +char *lh(i) { return lregister_name_high(i); } #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; +#define is_double_reg(i) (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER&®s[i]==USING_DREG) +#define is_longlong_reg(i) (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER&®s[i]==USING_REG) + +#define use_int(reg) if (reg==USE_CREG) reg=use_int0() +static +int use_int0() { + int i = creg; + if (!i||!ireg||!is_int_reg(i)) { + if (lreg) { free_register(lreg); lreg = 0; } + if (!ireg) ireg = get_register(); + // else if (ireg!=i) free_register(i); + i = ireg; + } + if (!regs[i]) regs[i]=USING_REG; + creg = i; return i; } -int use_float(int i) { - if (!is_float_reg(i)) i = freg; - if (!regs[i]) regs[i]=1; +#if LONGLONG_CODE +#define use_longlong(reg) if (reg==USE_CREG) reg=use_longlong0() + +static +int use_longlong0() { + int i = creg; + if (!is_longlong_reg(i)) { + if (ireg) { free_register(ireg); ireg=0; } + if (!lreg||!regs[lreg]) lreg = get_lregister(); + // else if (lreg!=i) free_register(i); + i = lreg; + } + if (!regv_l(i)) regv_l(i) = get_register(); + if (!regv_h(i)) regv_h(i) = get_register(); + if (!regs[i]) regs[i]=USING_REG; + if (!regs[regv_l(i)]) regs[regv_l(i)]=USING_REG; + if (!regs[regv_h(i)]) regs[regv_h(i)]=USING_REG; + creg = i; return i; } - -int use_double(int i) { - if (!is_double_reg(i)) i = dreg; - if (!regs[i]) regs[i]=1; +#endif + + +#if FLOAT_CODE +#define use_float(d,reg) if (reg==USE_CREG) reg=d?use_double0():use_float0() +static +int use_float0() { + int i = creg; + if (!is_float_reg(i)) { + if (lreg) { free_register(lreg); lreg = 0; } + if (!freg) freg = get_dregister(0); + else if (freg!=i) free_register(i); + i = freg; + } + if (!regs[i]) regs[i]=USING_REG; + creg = i; return i; } - -int use_longlong(int i) { +static +int use_double0() { + int i = creg; + if (!is_double_reg(i)) { + if (ireg) { free_register(ireg); ireg=0; } + if (!lreg||!regs[lreg]) lreg = get_lregister(); + // else if (lreg!=i) free_register(i); + i = lreg; + } + if (!regv_l(i)) regv_l(i) = get_register(); + if (!regv_h(i)) regv_h(i) = get_register(); + if (!regs[i]) regs[i]=USING_DREG; + if (!regs[regv_l(i)]) regs[regv_l(i)]=USING_REG; + if (!regs[regv_h(i)]) regs[regv_h(i)]=USING_REG; + creg = i; return i; } +#endif + #if FLOAT_CODE +static +NMTBL float_zero = {"_float_zero",STATIC,FLOAT,0}; +static +NMTBL float_one = {"_float_one",STATIC,FLOAT,0}; + + +static char * fload(int d); static int code_d1(double d); static int code_d2(double d); #endif +#if LONGLONG_CODE +static int code_l1(long long ll); +static int code_l2(long long ll); +#endif static void code_save_stacks(); static void code_save_input_registers(); -static void set_creg(int,int); +static void clear_ptr_cache_reg(int r); +static void set_ireg(int,int); static void set_freg(int,int); -static void set_dreg(int,int); +static void set_lreg(int,int); static int mask_label; static int mask1_label; @@ -199,12 +248,9 @@ 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. @@ -222,12 +268,12 @@ $f14,$f12 input register $f20-$f31 saved register variable -function call stack frame + 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 + reg_save disp max_func_args*SIZE_OF_INT lvar>0 lvar<0 lvar>0x1000 0000 code segment stack frame @@ -238,11 +284,12 @@ 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 + *SIZE_OF_INT *SIZE_OF_INT */ int arg_offset = 24; int arg_offset1 = 24; int disp_offset = -12; -#define func_disp_offset 60 +// #define func_disp_offset 60 +#define func_disp_offset 68 #define r1_offset func_disp_offset+12 int code_disp_offset = 0; int jump_offset = 0; #define CODE_LVAR l+code_disp_offset @@ -257,16 +304,16 @@ #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); + 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(".set L_%d,%d\n",lvar_offset_label,lvar_offsetv); + printf(".set 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 = 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; @@ -315,15 +362,23 @@ } } + +#define lvar_intro(e) /* do nothing */ + void -code_lvar(int e2,int creg) { - lvar_address(e2,creg); +code_lvar(int e2,int reg) { + use_int(reg); + lvar_address(e2,reg); } void code_init(void) { - /* this is called once program call */ + // macro_define("__BIG_ENDIAN__ 1\n"); + macro_define("__STDC__ 1\n"); + init_ptr_cache(); + regv_l(RET_LREGISTER) = RET_LREGISTER_L; + regv_h(RET_LREGISTER) = RET_LREGISTER_H; } void @@ -332,7 +387,7 @@ void code_gexpr(int e){ - if (is_int_reg(creg) && creg!=ireg) error(-1); + if (is_int_reg(creg) && creg!=ireg) error(-1); } @@ -345,6 +400,7 @@ int freg_var = 0; int type; int reg; + int i; int is_code0 = is_code(fnptr); while (args) { @@ -357,7 +413,7 @@ n->dsp = cadr(reg); regs[n->dsp]= INPUT_REG; reg_var++; - cadddr(args)=size_of_int; /* why we need this? */ + cadddr(args)=SIZE_OF_INT; } } else if (type==FLOAT) { if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) { @@ -365,15 +421,27 @@ n->dsp = cadr(reg); regs[n->dsp]= INPUT_REG; freg_var++; - cadddr(args)=size(type); /* why we need this? */ + cadddr(args)=size(type); } } else if (type==DOUBLE) { - if ((reg = get_input_dregister_var(reg_var,n,is_code0,1))) { + if ((reg = get_input_lregister_var(reg_var,n,is_code0))) { n->sc = DREGISTER; n->dsp = cadr(reg); - regs[n->dsp]= INPUT_REG; + regs[i=n->dsp]= INPUT_DREG; + regs[regv_l(i)]= INPUT_REG; + regs[regv_h(i)]= INPUT_REG; reg_var+=2; - cadddr(args)=size(type); /* why we need this? */ + cadddr(args)=size(type); + } + } else if (type==LONGLONG||type==ULONGLONG) { + if ((reg = get_input_lregister_var(reg_var,n,is_code0))) { + n->sc = LREGISTER; + n->dsp = cadr(reg); + regs[i=n->dsp]= INPUT_REG; + regs[regv_l(i)]= INPUT_REG; + regs[regv_h(i)]= INPUT_REG; + reg_var+=2; + cadddr(args)=size(type); } } args = cadr(args); @@ -382,33 +450,43 @@ code_save_input_registers(); } + int get_register(void) { /* 使われていないレジスタを調べる */ - int i,reg; + int i,j,reg; for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) { if (regs[i]) continue; /* 使われている */ regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ - return i; /* その場所を表す番号を返す */ + return i; /* その場所を表す番号を返す */ + } + /* PTR_CACHE をつぶす */ + for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) { + if (regs[i]==PTRC_REG) { + clear_ptr_cache_reg(i); + } else + 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; + (j=new_lvar(SIZE_OF_INT)),reg,0); + reg_stack[i]= j-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; +#if LONGLONG_CODE||FLOAT_CODE + /* search register stack */ + for(i=0;i<lreg_sp;i++) { + if ((reg=lreg_stack[i])>=0) { + code_lassign_lvar( + (j=new_lvar(SIZE_OF_LONGLONG)),reg); + lreg_stack[i]= j-REG_LVAR_OFFSET; free_register(reg); - return get_register(); /* 今度は必ずある */ + return get_register(); } } #endif @@ -417,13 +495,23 @@ if (! regs[reg]) { /* 使われていないなら */ regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */ if (i>max_reg_var) max_reg_var=i; - return reg; + return reg; /* その場所を表す番号を返す */ } } /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ error(HPERR); return creg; } +#if 0 +int +get_register(void) +{ + int i = get_register0(); + printf("# get_register %d\n",i); + return i; +} +#endif + int pop_register(void) { /* レジスタから値を取り出す */ @@ -431,69 +519,25 @@ } #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 +get_dregister(int d) { /* 使われていないレジスタを調べる */ int i,reg; + if (d) { + i = get_lregister(); + if (i!=-1) regs[i]=USING_DREG; + return i; + } for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) { if (regs[i]) continue; /* 使われている */ regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ - return i; /* その場所を表す番号を返す */ + 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]=new_lvar(SIZE_OF_DOUBLE)),reg,1); freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; return reg; } @@ -503,49 +547,95 @@ if (! regs[reg]) { /* 使われていないなら */ regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */ if (i>max_freg_var) max_freg_var=i; - return reg; + return reg; /* その場所を表す番号を返す */ } } /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ error(REG_ERR); return freg; } +#if 0 int get_dregister(int d) { - if (d) { - return get_dregister0(); - } else { - return get_fregister0(); - } + int i = get_dregister0(d); +printf("# get_dregister %d\n",i); + return i; } +#endif int pop_fregister(void) { /* レジスタから値を取り出す */ return freg_stack[--freg_sp]; } +#endif int -pop_dregister(void) -{ /* レジスタから値を取り出す */ - return dreg_stack[--dreg_sp]; +get_lregister0() +{ + int i; + for(i=LREG_OFFSET+1;i<REAL_MAX_LREGISTER+LREG_OFFSET;i++) { + if (regs[i]==0) { +// printf("# get_lregister %d\n",i); + return i; + } + } + return -1; } -#endif - -#if LONGLONG_CODE + int -get_lregister() { - return -1; +get_lregister() +{ + int h,l,i; + i = get_lregister0(); + if (i==-1) return -1; + h = get_register(); + if (h==-1) return -1; + regv_h(i) = h; + l = get_register(); + if (l==-1) { free_register(h); return -1; } + regv_l(i) = l; + regs[i]=USING_REG; + return i; } int get_lregister_var(NMTBL *n) { - return list2(LVAR,new_lvar(size_of_double)); + int i,j,ll; + int max_reg_var_save=max_reg_var; + ll = get_lregister0(); + if (ll==-1) return -1; + if (regs[ll]==0) { + 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; + for(j=0;j<REG_VAR_BASE-REG_VAR_MIN;j++) { + if (! regs[REG_VAR_BASE-j]) { + /* 使われていないなら */ + /* そのレジスタを使うことを宣言し */ + regs[REG_VAR_BASE-j]=USING_REG; + if (j>max_reg_var) max_reg_var=j; + /* その場所を表す番号を返す */ + regs[ll]=USING_REG; + regv_l(ll) = REG_VAR_BASE-j; + regv_h(ll) = REG_VAR_BASE-i; + return list3(LREGISTER,ll,(int)n); + } + } + /* ひとつしかなかった */ + regs[REG_VAR_BASE-i]=0; + max_reg_var=max_reg_var_save; + goto not_found; + } + } + } +not_found: + return list2(LVAR,new_lvar(SIZE_OF_LONGLONG)); } -#endif - void emit_pop_free(int xreg) @@ -554,41 +644,58 @@ free_register(xreg); } -void +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; +// printf("# free_register %d\n",i); + regs[i]=0; + if (is_longlong_reg(i)) { + regs[regv_l(i)]=0; + regs[regv_h(i)]=0; + //regv_l(i)=0; + //regv_h(i)=0; } - regs[i]=0; } int get_input_dregister_var(int i,NMTBL *n,int is_code,int d) { + int j; 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); + j = get_input_lregister_var(i,n,is_code); + if (car(j)==LREGISTER) { + if (regs[cadr(j)]=INPUT_REG) regs[cadr(j)]=INPUT_DREG; + car(j) = DREGISTER; + } + return j; + } + 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_DREGISTER_VAR) return 0; + i = i+MIN_TMP_FREG+FREG_OFFSET; + } + return list3(FREGISTER,i,(int)n); +} + +int +get_input_lregister_var(int i,NMTBL *n,int is_code) +{ + int ll; + ll = get_lregister0(); + if (i!=-1) { if (is_code) { - if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0; - i = FREG_VAR_BASE-i+FREG_OFFSET; + if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; + i = REG_VAR_BASE-i; } else { - if (i<0||i>=MAX_INPUT_FREGISTER_VAR) return 0; - i = i+MIN_TMP_FREG+FREG_OFFSET; + if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; + i = i+MIN_TMP_REG; } - return list3(FREGISTER,i,(int)n); - } + regv_h(ll)=i; + regv_l(ll)=i+1; + } else { error(-1); ll=LREG_OFFSET+2; } + return list3(LREGISTER,ll,(int)n); } int @@ -634,7 +741,8 @@ return d?fcount:count; } -int +#if 0 +static int register_full(void) { int i; @@ -645,54 +753,75 @@ } return 1; } +#endif void free_all_register(void) { int i; +// printf("# free_all register\n"); +#if LONGLONG_CODE + for(i=0;i<REAL_MAX_LREGISTER;i++) { + regs[i+LREG_OFFSET]=0; + regv_l(i+LREG_OFFSET) = 0; + regv_h(i+LREG_OFFSET) = 0; + } + lreg = 0; + // set_lreg(LREG_LREGISTER,0); +#endif 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; + freg = get_dregister(1); + set_freg(FREG_FREGISTER,0); #endif - set_creg(CREG_REGISTER,0); - set_freg(FREG_FREGISTER,0); - set_dreg(DREG_DREGISTER,0); + ireg = creg = get_register(); + set_ireg(CREG_REGISTER,0); return; } void register_usage(char *s) { -#if 0 +#if 1 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 + if (ireg) printf(" creg=%s",register_name(ireg)); + if (freg) printf(" freg=%s",fregister_name(freg)); + if (lreg) printf(" lreg=%s,%s",lregister_name_high(lreg), + lregister_name_low(lreg)); +#if 1 printf("\n# regs:"); - printf(":"); - for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); } + for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); } + printf(" stack "); + for(i=reg_sp;i>0;i--) { + if(reg_stack[i-1]>=0) + printf(" %s",register_name(reg_stack[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])); + for(i=0;i<MAX_FREGISTER;i++) { printf("%d",regs[i+FREG_OFFSET]); } + printf(" stack "); + for(i=freg_sp;i>0;i--) { + if(freg_stack[i-1]>=0) + printf(" %s",fregister_name(freg_stack[i])); + } + printf("\n# lreg:"); + for(i=0;i<REAL_MAX_LREGISTER;i++) { printf("%d",regs[i+LREG_OFFSET]); } + printf(" stack "); + for(i=lreg_sp;i>0;i--) { + if(lreg_stack[i-1]>=0) + printf(" %s",lregister_name_high(lreg_stack[i])); + printf(",%s",lregister_name_low(lreg_stack[i])); } #endif printf("\n"); } -void +void + gexpr_init(void) { while(reg_sp > 0) { @@ -701,27 +830,28 @@ while(freg_sp > 0) { free_register(freg_stack[--freg_sp]); } - while(dreg_sp > 0) { - free_register(dreg_stack[--dreg_sp]); + while(lreg_sp > 0) { + free_register(lreg_stack[--lreg_sp]); } - cmpreg = -1; + use_int0(); text_mode(); gexpr_code_init(); register_usage("gexpr_init"); } -void +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) { @@ -735,49 +865,42 @@ return list3(REGISTER,REG_VAR_BASE-i,(int)n); } } - return list2(LVAR,new_lvar(size_of_int)); -} - -int -fregister_var(int r) { - return r; + return list2(LVAR,new_lvar(SIZE_OF_INT)); } int get_dregister_var(NMTBL *n,int d) { - int i,j; + int i; 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)); + i = get_lregister_var(n,d); + if (car(i)==LREGISTER) { + car(i) = DREGISTER; + regs[i] = USING_DREG; + } + return i; } + + 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_DOUBLE)); } -void +void + emit_push() { int new_reg; + if (!is_int_reg(creg)) error(-1); if (reg_sp>MAX_MAX) error(-1); - new_reg = get_register(); + new_reg = get_register(); /* 絶対に取れる */ reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ ireg = creg = new_reg; } @@ -796,78 +919,196 @@ return xreg; } +static int code_base; + +#define MAX_PTR_CACHE 10 + +int ptr_cache=0; + +void +init_ptr_cache() +{ + int i; + for(i=0;i<MAX_PTR_CACHE;i++) { + ptr_cache=glist3(0,ptr_cache,0); + } +} + +void +clear_ptr_cache_reg(int r) +{ + int ptcptr=ptr_cache; + while(ptcptr) { + if(car(ptcptr)&&caddr(ptcptr)==r) { + car(ptcptr)=0; + caddr(ptcptr)=0; + free_register(r); + return; + } + ptcptr=cadr(ptcptr); + } +} + +void +clear_ptr_cache() +{ + int ptcptr=ptr_cache; + while(ptcptr) { + if(car(ptcptr)) + free_register(caddr(ptcptr)); + car(ptcptr)=0; + caddr(ptcptr)=0; + ptcptr=cadr(ptcptr); + } +} + + +int +get_ptr_cache(NMTBL *nptr) +{ + int r; + int ptcptr=ptr_cache; + int g = (int)nptr; + int p,p1; + char *rrn; + + p1 = ptcptr; p = cadr(p1); /* unnecesary, if ptcptr is initialized */ + while(ptcptr) { + if(car(ptcptr)==g) return caddr(ptcptr); + p1=p; p=ptcptr; + ptcptr=cadr(ptcptr); + } + cadr(p1)=0; /* remove the last one */ + cadr(p) = ptr_cache; /* connect current queue to the last one */ + ptr_cache = p; /* now the last one is the top */ + if (!caddr(p)) { + if((r=get_register())) { + caddr(p)=r; regs[r]=PTRC_REG; + } else { + error(-1); + r=creg; /* this can't happen */ + } + car(p)=g; + } else { + r = caddr(p); + } + rrn = register_name(r); + printf("\tla %s,%s\n",rrn,nptr->nm); + return r; +} + +static char *cload(int sz,int sign) { + if (sign) { + return sz==1?"lb":sz==SIZE_OF_SHORT?"lh":"lw"; + } else { + return sz==1?"lbu":sz==SIZE_OF_SHORT?"lhu":"lwu"; + } +} + +static char *cstore(int sz) { return sz==1?"sb":sz==SIZE_OF_SHORT?"sh":"sw"; } + +#define cext(sign,sz,reg) /* do nothing */ + + void code_label(int labelno) { + clear_ptr_cache(); printf("L_%d:\n",labelno); } void -code_gvar(int e1,int creg) { - printf("\tla %s,%s\n",register_name(creg),((NMTBL*)cadr(e1))->nm); +code_gvar(int e1,int reg) { + int r; + use_int(reg); + r = get_ptr_cache((NMTBL*)cadr(e1)); + if(r!=reg) + printf("\tmove %s,%s\n",register_name(reg),register_name(r)); + return; +} + +void +code_rgvar(int e1,int reg) { + use_int(reg); + printf("\tlw %s,0(%s)\n",register_name(reg), + register_name(get_ptr_cache((NMTBL*)cadr(e1)))); } void -code_rgvar(int e1,int creg) { - printf("\tlw %s,%s\n",register_name(creg),((NMTBL*)cadr(e1))->nm); +code_crgvar(int e1,int reg,int sign,int sz){ + char *crn; + use_int(reg); + crn = register_name(reg); + printf("\t%s %s,0(%s)\n",cload(sz,sign),crn, + register_name(get_ptr_cache((NMTBL*)cadr(e1)))); + cext(sign,sz,reg); } -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)); +code_register(int e2,int reg) { + use_int(reg); + if (reg!=e2) + printf("\tmove %s,%s\n",register_name(reg),register_name(e2)); } void code_rlvar(int e2,int reg) { + use_int(reg); + lvar_intro(e2); printf("\tlw %s,",register_name(reg)); lvar(e2); } +void +code_crlvar(int e2,int reg,int sign,int sz) { + use_int(reg); + lvar_intro(e2); + printf("\t%s %s,",cload(sz,sign),register_name(reg)); + lvar(e2); + cext(sign,sz,reg); +} + +void +code_fname(NMTBL *n,int reg) { + int r; + use_int(reg); + r = get_ptr_cache(n); + if(r!=reg) + printf("\tmove %s,%s\n",register_name(reg),register_name(r)); + return; +} + 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); +code_const(int e2,int reg) { + char *crn; + use_int(reg); + crn = register_name(reg); + printf("\tli %s,%d\n",crn,e2); } void code_neg(int creg) { + use_int(creg); printf("\tsubu %s,$0,%s\n", register_name(creg), register_name(creg)); } void code_not(int creg) { + use_int(creg); printf("\tnor %s,%s,%s\n", - register_name(creg), register_name(creg),register_name(creg)); + register_name(creg), register_name(creg),register_name(creg)); } void code_lnot(int creg) { - /* if non zero 1 else 0 */ + use_int(creg); int dreg = get_register(); printf("\txori %s,%s,0x0\n", register_name(dreg),register_name(creg)); @@ -879,57 +1120,67 @@ 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; + use_int(reg); + 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); + if (!is_int_reg(creg)) error(-1); 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); + if (reg==USE_CREG) { + reg=get_register(); if (!reg) error(-1); + drn = register_name(reg); + set_ireg(reg,0); + } else { + drn = register_name(reg); + } + printf("\t%s %s,0(%s)\n",cload(sz,sign),drn,xrn); + if (use) cext(sign,sz,reg); + printf("\taddi %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; + int nreg; 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; + use_int(reg); + 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); + if (!is_int_reg(creg)) error(-1); 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); + if (reg==USE_CREG) { + reg=get_register(); if (!reg) error(-1); + xrn = register_name(reg); + set_ireg(reg,0); + } else { + xrn = register_name(reg); + } + printf("\t%s %s,0(%s)\n",cload(sz,sign),xrn,crn); + if (use) cext(sign,sz,reg); + printf("\taddi %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); + char *crn; + use_int(creg); + crn = register_name(creg); printf("\tla %s,L_%d\n",crn,retcont); } @@ -938,6 +1189,7 @@ void code_environment(int creg) { /* save frame pointer */ + use_int(creg); #if R1SAVE printf("\tlw %s,0($fp)\n",register_name(creg)); #else @@ -948,12 +1200,12 @@ } void -code_bool(int e1) { +code_bool(int e1,int reg) { char *xrn; int e2,e3; b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ - creg = use_int(creg); - xrn = register_name(creg); + use_int(reg); + xrn = register_name(reg); printf("\tli %s,0\n",xrn); jmp(e3=fwdlabel()); fwddef(e2); @@ -963,65 +1215,85 @@ 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"); + return (cond?"eq":"ne"); } 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"); + return code_gt(cond); } 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"); + return code_gt(!cond); } 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"); + return code_gt(!cond); } char * code_eq(int cond) { - return (cond?"\tbeq %s,%s,L_%d\n":"\tbne %s,%s,L_%d\n"); + return cond?"":0; } + void -code_cmp_crgvar(int e1,int sz) { - if (cmpreg==-1) cmpreg = get_register(); - code_crgvar(cadr(e1),cmpreg,1,sz); +code_cmp_crgvar(int e1,int reg,int sz) { + int r; + char *crn; + use_int(reg); + crn = register_name(reg); + r = get_ptr_cache((NMTBL*)cadr(e1)); + printf("\t%s %s,0(%s)\n",cload(sz,sign),crn,register_name(r)); + cext(0,sz,r); + cmpreg = reg; + // printf("\tcmpwi cr0,%s,0\n",crn); } void -code_cmp_crlvar(int e2,int sz) { - if (cmpreg==-1) cmpreg = get_register(); - code_crlvar(e2,cmpreg,1,sz); +code_cmp_crlvar(int e2,int reg, int sz) { + char *crn; + use_int(reg); + crn = register_name(reg); + lvar_intro(e2); + printf("\t%s %s,",cload(sz,sign),crn); + lvar(e2); + cext(0,sz,reg); + code_cmp_register(reg); } void -code_cmp_rgvar(int e1) { - if (cmpreg==-1) cmpreg = get_register(); - code_rgvar(e1,cmpreg); +code_cmp_rgvar(int e1,int reg) { + int r; + char *crn; + use_int(reg); + crn = register_name(reg); + r = get_ptr_cache((NMTBL*)cadr(e1)); + printf("\tlw %s,0(%s)\n",crn,register_name(r)); + code_cmp_register(reg); } void -code_cmp_rlvar(int e2) { - if (cmpreg==-1) cmpreg = get_register(); - code_rlvar(e2,cmpreg); +code_cmp_rlvar(int e2,int reg) { + char *crn; + use_int(reg); + crn = register_name(reg); + lvar_intro(e2); + printf("\tlw %s,",crn); + lvar(e2); + code_cmp_register(reg); } void code_cmp_register(int e2) { - cmpreg = e2; - /* prevent cmpreg freeing */ + use_int(e2); + cmpreg = reg; // used by jcond, beq $reg,$0,L_xx } @@ -1050,7 +1322,9 @@ { char *s,*crn; int lb; - crn=register_name(creg); + + use_int(creg); + crn = register_name(creg); s=(char *)cadr(e1); printf("\t.rdata\n\t.align 2\n"); @@ -1058,80 +1332,88 @@ printf("L_%d:\n",lb); ascii(s); if (output_mode==TEXT_EMIT_MODE) { - printf(".text\n"); + printf(".text\n"); } else { - text_mode(); + text_mode(); } printf("\tla %s,L_%d\n",crn,lb); } #define MAX_COPY_LEN 20 -void +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 *frn; + char *trn; char *drn; int fix = 0; char *memmove = "memmove"; int dreg = get_register(); if (!dreg) error(-1); + drn = register_name(dreg); + use_int(from); + use_int(to); + frn = register_name(from); + trn = register_name(to); /* length <0 means upward direction copy */ switch (length) { - case 0: break; + 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; + 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; + 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; + 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); + 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; + } + clear_ptr_cache(); + code_save_stacks(); + printf("\tli $6,%d\n",length); + printf("\tmove $5,%s\n",frn); + printf("\tmove $4,%s\n",trn); /* overrap must be allowed */ - printf("\tbl L_%s$stub\n",memmove); + printf("\tjal L_%s$stub\n",memmove); + extern_define(memmove,0,FUNCTION,1); fix=0; - set_creg(RET_REGISTER,0); - if (creg!=to) { - free_register(to); to = creg; - } - break; + set_ireg(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; - } + if (fix) printf("\taddu %s,%s,%d\n",trn,trn,fix); + if(creg!=to) { + free_register(creg); creg=to; ireg=to; + } } free_register(dreg); } @@ -1142,9 +1424,10 @@ int length,count; int dreg,sreg; char *drn,*crn,*srn; g_expr(e4); + if (!is_int_reg(creg)) error(-1); length=size(t); - if(length%size_of_int) { - length += size_of_int - (length%size_of_int); + if(length%SIZE_OF_INT) { + length += SIZE_OF_INT - (length%SIZE_OF_INT); } dreg = get_register(); if (!dreg) error(-1); drn = register_name(dreg); @@ -1153,14 +1436,14 @@ 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) { + 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); + printf("\tlw %s,%d(%s)\n",drn,length-SIZE_OF_INT,crn); + printf("\tsw %s,%d(%s)\n",drn,-SIZE_OF_INT,srn); } } } @@ -1168,20 +1451,25 @@ /* downward direction copy */ emit_copy(creg,dreg,length,0,0,1); if (dreg) free_register(dreg); - return length/size_of_int; + return length/SIZE_OF_INT; } void -set_creg(int reg,int mode) +set_ireg(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)); + clear_ptr_cache_reg(reg); + if (ireg && reg!=ireg ) { + free_register(ireg); + if (mode) { + printf("\tmove %s,%s\n",register_name(reg),register_name(ireg)); + } + } free_register(creg); - creg = ireg = reg; - regs[creg]=1; + regs[reg]=USING_REG; } + creg = ireg = reg; } void @@ -1189,52 +1477,93 @@ { 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)); + if (freg && reg!=freg) { + free_register(freg); + if (mode) { + printf("\tmov.s %s,%s\n",fregister_name(reg),fregister_name(freg)); + } + } + // if (creg!=ireg) free_register(creg); + regs[reg]=USING_REG; + } + creg = freg = reg; +} + +void +set_lreg(int reg,int mode) +{ + if (reg==RET_LREGISTER) { + regv_l(reg) = RET_LREGISTER_L; + regv_h(reg) = RET_LREGISTER_H; + } + if (!is_longlong_reg(reg)) error(-1); + if (reg!=creg) { + if (lreg && reg!=lreg) { + if (mode) { + printf("\tmove %s,%s\n", + lregister_name_low(reg),lregister_name_low(lreg)); + printf("\tmove %s,%s\n", + lregister_name_high(reg),lregister_name_high(lreg)); + } + free_register(lreg); } free_register(creg); - creg = freg = reg; - regs[freg]=1; + regs[reg]=USING_REG; + clear_ptr_cache_reg(regv_l(reg)); + regs[regv_l(reg)]=USING_REG; + clear_ptr_cache_reg(regv_h(reg)); + regs[regv_h(reg)]=USING_REG; } -} - -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)); - } + creg = lreg = reg; } 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; + set_lreg(reg,mode); + regs[regv_l(reg)]=USING_DREG; + clear_ptr_cache_reg(regv_h(reg)); + regs[regv_h(reg)]=USING_DREG; +} + +void +set_lreg_operand(int reg,int mode) +{ + // save_stack,clear_ptr_cache is assmued + if (!is_longlong_reg(reg)) { error(-1); return; } + if (mode) { + if (regv_l(reg)!=6) + printf("\tmove $6,%s\n", lregister_name_high(reg)); + if (regv_l(reg)!=7) + printf("\tmove $7,%s\n", lregister_name_low(reg)); } } +void +set_dreg_operand(int reg,int mode) +{ + set_lreg_operand(reg,mode); +} void -use_var(int arg) +use_reg(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; +// printf("# use reg %d\n",arg); + if (arg<0||arg> REAL_MAX_REGISTER+REAL_MAX_FREGISTER+ REAL_MAX_LREGISTER) + error(-1); + clear_ptr_cache_reg(arg); + regs[arg]=USING_REG; + if (is_longlong_reg(arg)) { + clear_ptr_cache_reg(regv_l(arg)); + regs[regv_l(arg)]=USING_REG; + clear_ptr_cache_reg(regv_h(arg)); + regs[regv_h(arg)]=USING_REG; + } else if (is_double_reg(arg)) { + clear_ptr_cache_reg(regv_l(arg)); + regs[regv_l(arg)]=USING_DREG; + clear_ptr_cache_reg(regv_h(arg)); + regs[regv_h(arg)]=USING_DREG; + } } void @@ -1258,23 +1587,26 @@ if (tag==REGISTER) { /* regs[reg]==INPUT_REG case should be considered */ n->dsp = offset; - offset+=size_of_int; + 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 if (tag==FREGISTER) { + /* regs[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) { + /* regs[reg]==INPUT_REG case should be considered */ + n->dsp = offset; + t = n->ty; + offset+=SIZE_OF_DOUBLE; reg_offset+=2; + } else if (tag==LREGISTER) { + /* regs[reg]==INPUT_REG case should be considered */ + n->dsp = offset; + t = n->ty; + offset+=SIZE_OF_LONGLONG; reg_offset+=2; } else { offset += size(n->ty); continue; @@ -1282,41 +1614,88 @@ 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) { + if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER||tag==LREGISTER) { free_register(reg); } } my_func_args = offset; } +static int +not_simple_p(int e3) +{ + return (e3==FUNCTION||e3==CONV||e3==RSTRUCT||e3==STASS|| + (((e3/100)==LOP)&&(e3!=LREGISTER||e3!=LADD||e3!=LSUB))); +} + 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) - ; + return !contains_in_list_p(e3,not_simple_p); } int caller_arg_offset_v(int arg) { - return ARG_LVAR_OFFSET+arg*size_of_int; + return ARG_LVAR_OFFSET+arg*SIZE_OF_INT; +} + +void +use_input_reg(int reg,int mode) +{ + if (is_int_reg(reg)) { + if (ireg&® == ireg) { + if (creg==ireg) creg = 0; + ireg = 0; + } + if (lreg) { + if (regv_l(lreg)==reg) { + regs[lreg]=0; + if (regv_h(lreg)>reg&& + (regs[regv_h(lreg)]==USING_REG|| + regs[regv_h(lreg)]==USING_DREG)) + { + free_register(regv_h(lreg)); + } + if (creg==lreg) creg = 0; + lreg = 0; + } else if (regv_h(lreg)==reg) { + regs[lreg]=0; + if (regv_h(lreg)>reg&& + (regs[regv_l(lreg)]==USING_DREG) || + (regs[regv_l(lreg)]==USING_DREG) ) + { + free_register(regv_l(lreg)); + } + if (creg==lreg) creg = 0; + lreg = 0; + } + } + } else if (is_longlong_reg(reg)) { + use_input_reg(regv_h(reg),0); + use_input_reg(regv_l(reg),0); + } else if (is_double_reg(reg)) { + use_input_reg(regv_h(reg),0); + use_input_reg(regv_l(reg),0); + } else if (is_float_reg(reg)) { + if (freg&® == freg) { + if (creg==freg) creg = 0; + freg = 0; + } + } + if (mode) use_reg(reg); } int function(int e1) { - int e2,e3,e4,nargs,t; + int e2,e3,e4,e5,nargs,t,r0,r1; 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)); @@ -1340,15 +1719,16 @@ if (car(jmp)!=REGISTER) error(-1); reg_arg_list = list2(jmp,reg_arg_list); g_expr(e2); + if (!is_int_reg(creg)) error(-1); 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_lreg(LREG_LREGISTER,0); set_freg(FREG_FREGISTER,0); - set_dreg(DREG_DREGISTER,0); + set_ireg(CREG_REGISTER,0); nargs = reg_arg = freg_arg = arg_assign = 0; for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { @@ -1366,13 +1746,38 @@ } 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); + /* protect from input register free */ + if (car(arg)==REGISTER) + use_input_reg(cadr(arg),1); + g_expr_u(assign_expr0(arg,e4,t,t)); + nargs ++ ; reg_arg++; + continue; + } else if (t==LONGLONG||t==ULONGLONG||t==DOUBLE) { + if (reg_arg>=MAX_INPUT_REGISTER_VAR) { + arg = list2(LVAR,caller_arg_offset_v(nargs)); + } else if (!simple_args(e3) && cadr(e3)) { + arg = get_lregister_var(0); + arg_assign = list2( + assign_expr0(r0= + (t==DOUBLE? + get_input_dregister_var(reg_arg,0,0): + get_input_lregister_var(reg_arg,0,0) + ), + arg,t,t), + arg_assign); + use_input_reg(cadr(r0),1); + } else { + arg = get_input_lregister_var(reg_arg,0,0); + use_input_reg(cadr(arg),1); + } reg_arg_list = list2(arg,reg_arg_list); g_expr_u(assign_expr0(arg,e4,t,t)); - nargs ++ ; reg_arg++; iargs += size_of_int; + nargs ++ ; reg_arg++; + nargs ++ ; reg_arg++; continue; - } else if (t==DOUBLE||t==FLOAT) { - if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { + } else if (t==FLOAT) { + if (freg_arg>=MAX_INPUT_FREGISTER_VAR) { arg = list2(LVAR,caller_arg_offset_v(nargs)); } else if (!simple_args(e3) && cadr(e3)) { arg = get_dregister_var(0,1); @@ -1383,17 +1788,16 @@ } 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); + if (car(arg)==FREGISTER) + use_input_reg(cadr(arg),1); /* protect from input register free */ g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */ freg_arg++; - nargs += size(t)/size_of_int; - if (t==DOUBLE) iargs += size(t); + nargs += size(t)/SIZE_OF_INT; continue; - } else if (car(t)==STRUCT||car(t)==UNION) { + } else if (t>=0&&(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); @@ -1401,35 +1805,41 @@ ++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)); } + clear_ptr_cache(); if (car(e2) == FNAME) { - printf("\tbl\tL_%s$stub\n",fn->nm); + printf("\tjal\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) + if (car(arg)==REGISTER||car(arg)==DREGISTER||car(arg)==FREGISTER + ||car(arg)==LREGISTER) 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) { + use_reg(RET_DREGISTER); + } else if (ret_type==DOUBLE||ret_type==FLOAT) { set_freg(RET_FREGISTER,0); + } else if (ret_type==ULONGLONG||ret_type==LONGLONG) { + set_lreg(RET_LREGISTER,0); + use_reg(RET_LREGISTER); } else if (ret_type==VOID) { } else { - set_creg(RET_REGISTER,0); + set_ireg(RET_REGISTER,0); } return ret_type; } void code_frame_pointer(int e3) { + use_int(e3); #if R1SAVE printf("\tmove $fp,%s\n",register_name(e3)); #else @@ -1457,168 +1867,192 @@ code_indirect_jmp(int e2) { max_reg_var = REG_VAR_BASE-REG_VAR_MIN; max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; + use_int(e2); printf("\tj %s\n",register_name(e2)); } int -code_rindirect(int e1, int offset, int us) +code_rindirect(int e1, int reg,int offset, int us) { - char *crn; + char *crn,*rrn; g_expr(e1); + if (!is_int_reg(creg)) error(-1); crn=register_name(creg); - printf("\tlw %s,%d(%s)\n",crn,offset,crn); - return INT; + use_int(reg); + rrn=register_name(reg); + printf("\tlw %s,%d(%s)\n",rrn,offset,crn); + return us?UNSIGNED:INT; } int -code_crindirect(int e1, int offset, int us) +code_crindirect(int e1, int reg,int offset, int sign) { - char *crn; + char *crn,*rrn; g_expr(e1); + if (!is_int_reg(creg)) error(-1); 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; + use_int(reg); + rrn=register_name(reg); + printf("\t%s %s,%d(%s)\n",cload(1,sign),rrn,offset,crn); + if (sign) { + cext(sign,1,reg); + return CHAR; } + return UCHAR; } int -code_srindirect(int e1, int offset, int us) +code_srindirect(int e1, int reg,int offset, int sign) { - char *crn; + char *crn,*rrn; g_expr(e1); + if (!is_int_reg(creg)) error(-1); 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; + use_int(reg); + rrn = register_name(reg); + printf("\t%s %s,%d(%s)\n",cload(SIZE_OF_SHORT,sign),rrn,offset,crn); + if (sign) { + cext(sign,SIZE_OF_SHORT,reg); + return SHORT; } + return USHORT; } #if FLOAT_CODE int -code_drindirect(int e1, int offset, int d) +code_drindirect(int e1, int reg,int offset, int d) { - char *crn; - g_expr(e1); - crn=register_name(creg); + char *crn; 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; + code_lrindirect(e1,reg,offset,1); + use_float(d,reg); + // regs[reg==USE_CREG?lreg:reg]=USING_DREG; + return DOUBLE; } + g_expr(e1); + if (!is_int_reg(creg)) error(-1); + crn=register_name(creg); + use_float(d,reg); + printf("\t%s %s,%d(%s)\n",fload(d), + fregister_name(reg),offset,crn); + return FLOAT; } #endif #if LONGLONG_CODE int -code_lrindirect(int e1, int offset, int us) +code_lrindirect(int e1, int reg, int offset, int us) { char *crn; + int creg0; + g_expr(e1); - crn=register_name(creg); - return LONGLONG; + if (!is_int_reg(creg)) error(-1); + crn=register_name(creg0=creg); + use_longlong(reg); + if (creg0!=regv_h(reg)) { + printf("\tlw %s,%d(%s)\n",lregister_name_high(reg),offset,crn); + printf("\tlw %s,%d(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn); + } else { + printf("\tlw %s,%d(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn); + printf("\tlw %s,%d(%s)\n",lregister_name_high(reg),offset,crn); + } + return us?ULONGLONG: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); - } + int r; + use_int(creg); + r = get_ptr_cache((NMTBL*)cadr(e2)); + code_assign(r,byte,creg); } void code_assign_lvar(int e2,int creg,int byte) { char *crn; + use_int(creg); crn=register_name(creg); + lvar_intro(e2); if (byte==1) { - printf("\tsb %s,",crn); - } else if (byte==size_of_short) { - printf("\tsh %s,",crn); + printf("\tsb %s,",crn); + } else if (byte==SIZE_OF_SHORT) { + printf("\tsh %s,",crn); } else { - printf("\tsw %s,",crn); + printf("\tsw %s,",crn); } lvar(e2); } void code_assign_register(int e2,int byte,int creg) { + use_int(creg); if (e2!=creg) - printf("\tmove %s,%s\n",register_name(e2),register_name(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); + char *drn; + char *crn; + use_int(e2); + drn=register_name(e2); + use_int(creg); + 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); + 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); + 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)); +code_register_assop(int e2,int reg, int op,int byte) { + // reg <= reg(e2) op=reg + use_int(reg); + tosop(op,e2,reg); } - void -code_assop(int op,int byte,int sign) { +code_assop(int op,int creg, int byte,int sign) { char *xrn,*crn,*drn; int xreg; int edx = get_register(); if(!edx) error(-1); + // (*creg) op = pop() + + use_int(creg); 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); + printf("# assop\n\tmove %s,%s\n",register_name(edx),register_name(creg)); + ld_indexx(byte,0,edx,creg,sign); + tosop(op,creg,xreg); crn = register_name(creg); drn = register_name(edx); - printf("\t%s %s,0(%s)\n",cstore(byte),crn,drn); + 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); + } free_register(edx); emit_pop_free(xreg); } void -tosop(int op,int oreg) +tosop(int op,int creg,int oreg) { - int dx; - char *orn,*crn; - + int dx = -1; + char *orn,*crn,*drn; + // creg = creg op oreg + + use_int(creg); if(oreg==-1) { error(-1); } else if (oreg<= -REG_LVAR_OFFSET) { @@ -1630,13 +2064,13 @@ switch(op) { case LSHIFT: case ULSHIFT: - shift("sll",oreg); + shift("sll",creg,oreg); return; case RSHIFT: - shift("srl",oreg); + shift("sra",creg,oreg); return; case URSHIFT: - shift("sra",oreg); + shift("srl",creg,oreg); return; } orn = register_name(oreg); @@ -1649,7 +2083,18 @@ printf("\tsubu %s,%s,%s\n",crn,crn,orn); break; case CMP: - printf("\tslt %s,%s\n",crn,orn); + printf("\tslt %s,%s,%s\n",crn,orn,crn); + cmpreg = creg; + break; + case UCMP: + printf("\tsltu %s,%s,%s\n",crn,orn,crn); + cmpreg = creg; + break; + case CMPEQ: + printf("\tbeq %s,%s",crn,orn); // beq $2,$3,L1 + break; + case CMPNEQ: + printf("\tbne %s,%s",crn,orn); // beq $2,$3,L1 break; case BAND: printf("\tand %s,%s,%s\n",crn,crn,orn); @@ -1681,37 +2126,72 @@ 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); + if(dx!=-1) free_register(dx); } int code_const_op_p(int op,int v) { - if (op==BAND||op==DIV||op==UDIV||op==MOD||op==UMOD) return 0; - return 0; + if (car(v)!=CONST) return 0; + if (op==BAND||op==DIV||op==UDIV||op==MOD||op==UMOD||op==XOR||op==MUL||op==UMUL) return 0; + v = cadr(v); + return (-32766<v&&v<32767); } -void -oprtc(int op,int v) -{ -} - - void -ld_indexx(int byte, int n, int xreg,int sign) +oprtc(int op,int creg, int v) +{ + char *crn; + use_int(creg); + crn = register_name(creg); + v = cadr(v); + + switch(op) { + case LSHIFT: + case ULSHIFT: + printf("\tsll %s,%s,%d\n",crn,crn,v); + return; + case RSHIFT: + printf("\tsra %s,%s,%d\n",crn,crn,v); + return; + case URSHIFT: + printf("\tsrl %s,%s,%d\n",crn,crn,v); + return; + case ADD: + printf("\taddu %s,%s,%d\n",crn,crn,v); + break; + case SUB: + printf("\taddu %s,%s,-%d\n",crn,crn,v); + break; + case CMP: + printf("\tslt %s,%s,%d\n",crn,crn,v); + break; + case BOR: + printf("\tori %s,%s,%d\n",crn,crn,v); + break; + default: + error(-1); + } +} + +void +shift(char *op, int creg, int reg) +{ + char *crn; + char *rrn = register_name(reg); + use_int(creg); + crn = register_name(creg); + printf("\t%s %s,%s,%s\n",op,crn,crn,rrn); +} + +void +ld_indexx(int byte, int n, int xreg,int creg, int sign) { - char *crn = register_name(creg); - printf("\t%s %s,%d(%s)\n",cload(sign,byte),crn,n, - register_name(xreg)); + char *crn; + use_int(creg); + crn = register_name(creg); + printf("\t%s %s,%d(%s)\n",cload(byte,sign),register_name(creg),n, + register_name(xreg)); } int @@ -1724,24 +2204,22 @@ code_cmpdimm(int e, int csreg) { /* used in dosiwtch() */ + int reg; + char *rn; if(chk) return; - creg = use_int(creg); - printf("\tli %s,%d\n",register_name(creg),e); - cmpreg = csreg; + rn = register_name(reg = get_register()); + printf("\tli %s,%d\n",rn,e); + printf("\tsltu %s,%s,%s\n",rn,register_name(csreg),rn); } void -code_opening(char *s) +code_opening(char *filename) { - /* this is called once per month */ + /* this is called once per file */ 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"); - + printf("\t.file \"%s\"\n",filename); + printf(".abicalls\n"); + printf(".text\n"); if (asi) { fclose(asi); asi = 0; @@ -1761,41 +2239,27 @@ 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); - } + int op; + if (car(e1)==EQ||car(e1)==NEQ) { + op = s?CMPEQ:CMPNEQ; + g_expr(list3(op,cadr(e1),caddr(e1))); + printf(",L_%d\n",l1); } else { - /* beq $2,$3,L1 */ - printf(s,crn,drn,l1); + op = t==INT?CMP:UCMP; + g_expr(list3(op,cadr(e1),caddr(e1))); + printf("\tb%s %s,%0,L_%d\n",s,register_name(cmpreg),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; + if (cmpreg==CMP_C1T) + printf("\tbc1%s L_%d\n",cond?"f":"t",l); + else + printf("\tb%s %s,$0,L_%d\n",register_name(cmpreg),cond?"ne":"eq",l); } void @@ -1820,12 +2284,13 @@ text_mode(); else printf("\t.align 3\n"); - /* if (stmode!=STATIC) - printf(".globl _%s\n",name); */ - printf(".ent %s\n",name); + if (stmode!=STATIC) + printf(".globl _%s\n",name); +#ifdef DOT_SIZE + printf("\t.type\t%s,@function\n",name); +#endif printf("_%s:\n",name); code_disp_label=fwdlabel(); - printf("\t.set noreorder\n"); printf("\t.cpload $25\n"); printf("\t.set reorder\n"); @@ -1840,22 +2305,21 @@ void code_enter1(int args) { - set_creg(CREG_REGISTER,0); + // set_lreg(LREG_LREGISTER,0); + set_ireg(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); - + disp&= -SIZE_OF_INT; + r1_offsetv = -disp+max_func_args*SIZE_OF_INT+code_disp_offset; + + printf(".set L_%d,%d\n",code_disp_label,-r1_offsetv); local_table(); - free_all_register(); + // free_all_register(); } void @@ -1865,8 +2329,6 @@ 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); @@ -1890,15 +2352,15 @@ printf("\t.cprestore L_%d\n",cprestore_label); max_func_args = 0; max_func_iargs = 0; - } void enter1() { - set_creg(CREG_REGISTER,0); + text_mode(); + // set_lreg(LREG_LREGISTER,0); + set_ireg(CREG_REGISTER,0); set_freg(FREG_FREGISTER,0); - set_dreg(DREG_DREGISTER,0); } static unsigned int @@ -2004,13 +2466,13 @@ void code_set_return_register(int mode) { - if (cadr(fnptr->ty)==DOUBLE) { - set_dreg(RET_DREGISTER,mode); - } else if (cadr(fnptr->ty)==FLOAT) { + if (cadr(fnptr->ty)==DOUBLE||cadr(fnptr->ty)==FLOAT) { set_freg(RET_FREGISTER,mode); + } else if (cadr(fnptr->ty)==LONGLONG||cadr(fnptr->ty)==ULONGLONG) { + set_lreg(RET_LREGISTER,mode); } else if (cadr(fnptr->ty)==VOID) { } else { - set_creg(RET_REGISTER,mode); + set_ireg(RET_REGISTER,mode); } } @@ -2021,24 +2483,27 @@ 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); + if (type==FLOAT||type==DOUBLE) { + set_freg(reg,mode); + } else if (type==LONGLONG||type==ULONGLONG) { + set_lreg(reg,mode); + // use_reg(reg); } else { - set_creg(reg,mode); + set_ireg(reg,mode); } } - void gen_gdecl(char *n, int gpc) { + /* if (stmode!=STATIC) - printf("\t.globl _%s\n",n); + printf(".globl _%s\n",n); + */ } -void +void + align(int t) { if (t!=CHAR) { @@ -2056,15 +2521,18 @@ double d; float f; #endif +#if LONGLONG_CODE + long long ll; +#endif char *name; name = n->nm; - if(mode!=GDECL&&mode!=STADECL) { + 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); */ + printf(".globl\t_%s\n",name); data_mode(name); align(t); printf("_%s:\n",name); @@ -2080,36 +2548,41 @@ } else if (t==SHORT||t==USHORT) { printf("\t.short %d\n",cadr(e)); if (data_alignment>0) data_alignment++; - gpc += 2; + gpc += SIZE_OF_SHORT; } else { - printf("\t.word %d\n",cadr(e)); - gpc += size_of_int; + printf("\t.long %d\n",cadr(e)); + gpc += SIZE_OF_INT; } +#if LONGLONG_CODE + } else if(t==LONGLONG||t==ULONGLONG) { + ll = lcadr(e); + printf("\t.long\t0x%x,0x%x\n",code_l2(ll),code_l1(ll)); +#endif #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)); + d = dcadr(e); + printf("\t.long\t0x%x,0x%x\n",code_d2(d),code_d1(d)); } else if(t==FLOAT) { - f = dcadr(e); - printf("\t.word\t0x%x\n",*(int *)&f); + f = dcadr(e); + printf("\t.long\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)); + gpc += SIZE_OF_INT; + if(car(e)==ADDRESS&&car(cadr(e))==GVAR) { + printf("\t.long _%s\n",((NMTBL *)cadr(cadr(e)))->nm); + } else if(car(e)==FNAME) { + printf("\t.long _%s\n",((NMTBL *)cadr(e))->nm); + } else if(car(e)==GVAR) { + printf("\t.long _%s\n",((NMTBL *)cadr(e))->nm); + } else if(car(e)==STRING) { + if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) { + l = fwdlabel(); + printf("\t.long L_%d\n",l); + printf(".cstring\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); } @@ -2135,24 +2608,24 @@ global_table(void) { NMTBL *n; - int init; + int init; char *extrn; 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)); - } + 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)); + } } } @@ -2169,8 +2642,8 @@ 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)); + if (n->dsp != -1) /* initialized static */ + printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); } } } @@ -2196,114 +2669,97 @@ printf("\t.type\t%s,@object\n",name); } -#if FLOAT_CODE - -char * -fstore(int d) +static void +extern_conv(char *conv) { - return (d?"stfd":"stfs"); + code_save_stacks(); + clear_ptr_cache(); + extern_define(conv,0,FUNCTION,1); + printf("\tjal %s\n",conv); + if (max_func_iargs<16) max_func_iargs=16; } -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); -} +#if FLOAT_CODE + +/* floating point */ + +#define set_double(freg) regs[freg]=USING_DREG 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); + clear_ptr_cache(); + set_dreg(RET_DREGISTER,1); + printf("\tli.d $6,%g\n",0.0); + extern_conv("dpcmp"); return; } + grn = register_name(greg = get_dregister(d)); + frn = register_name(e2); + printf("\tmtc1 $0,%s\n",grn); + 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); + use_float(d,freg); 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); + code_lregister(e2,freg,0); set_bouble(freg); return; } -} - -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)); + if (freg!=e2) { + if (is_int_reg(e2)) error(-1); + printf("\tmov.s %s,%s\n",fregister_name(freg),fregister_name(e2)); } } void +code_dassign_gvar(int e2,int freg,int d) +{ + int r; + use_float(d,freg); + if (d) { + code_lassign_gvar(e2,freg,0); set_double(freg); return; + } + r = get_ptr_cache((NMTBL*)cadr(e2)); + printf("\ts.s %s,0(%s)\n",fregister_name(freg),register_name(r)); +} + +void +code_dassign_lvar(int e2,int freg,int d) +{ + use_float(d,freg); + if (d) { + code_lassign_lvar(e2,freg,0); set_double(freg); return; + } + lvar_intro(e2); + printf("\ts.s %s,",fregister_name(freg)); + lvar(e2); +} + +void +code_dassign(int e2,int freg,int d) +{ + use_float(d,freg); + if (d) { + code_lassign(e2,freg,0); set_double(freg); return; + } + printf("\ts.s %s,0(%s)\n",fstore(d),fregister_name(freg),register_name(e2)); +} + +void code_dassign_dregister(int e2,int d,int freg) { - /* これってさ、code_dregister と同じ? */ + use_float(d,freg); + if (d) { + code_lassign_lregister(e2,0,freg); set_double(freg); return; + } 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)); - } + printf("\tmov.s %s,%s\n",fregister_name(e2),fregister_name(freg)); } - } static double d0 = 1.0; @@ -2330,276 +2786,488 @@ return *j; } -void +void + code_dconst(int e2,int freg,int d) { + int lb; double value = dcadr(e2); - char *frn; + int r; + char *rrn,*frn; + + use_float(d,freg); if (d) { - printf("\tli.d %s,%g\n",dregister_name0(freg),value); + printf("\t.li %s,%g\n",lregister_name_high(freg),code_d2(value)); + printf("\t.li %s,%g\n",lregister_name_low(freg),code_d1(value)); + free_register(r); } 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); + printf("\t.lis %s,%g\n",frn,value); } } -void code_d2i(int freg0) + +void +code_dneg(int freg,int d) { + char *frn; + use_float(d,freg); + if (d) { + code_save_stacks(); + clear_ptr_cache(); + set_dreg(RET_DREGISTER,1); + /// set_dreg_operand(oreg,1); + extern_conv("dpneg"); + return; + } + frn = fregister_name(freg); + printf("\tfneg %s,%s\n",frn,frn); +} + +void +code_d2i(int reg) +{ + use_float(reg,1); code_save_stacks(); + clear_ptr_cache(); set_dreg(RET_DREGISTER,1); - code_dpfunc("dptoli"); + extern_conv("dptoli"); set_creg(RET_REGISTER,0); + return; } -void code_i2d(int creg0) +void +code_i2d(int reg) { - 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"); + clear_ptr_cache(); + extern_conv("litodp"); set_dreg(RET_DREGISTER,0); + use_float(reg,1); + return; } -void code_d2f(int freg) { +void +code_d2u(int reg) +{ + use_float(reg,1); code_save_stacks(); + clear_ptr_cache(); set_dreg(RET_DREGISTER,1); - code_dpfunc("dptofp"); - set_freg(RET_FREGISTER,0); + extern_conv("dptoul"); + set_creg(RET_REGISTER,0); + return; } -void code_f2d(int freg) { +void +code_u2d(int reg) +{ + set_creg(RET_REGISTER,1); code_save_stacks(); - set_freg(RET_FREGISTER,1); - code_dpfunc("fptodp"); + clear_ptr_cache(); + extern_conv("ultodp"); set_dreg(RET_DREGISTER,0); + use_float(reg,1); + return; } -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_d2f(int reg) { + set_dreg(RET_DREGISTER,1); + code_save_stacks(); + clear_ptr_cache(); + extern_conv("dptofp"); + set_freg(RET_FREGISTER,0); + use_float(reg,0); + return; } -void code_f2u(int freg) { +void +code_f2d(int reg) { + set_freg(RET_FREGISTER,1); + code_save_stacks(); + clear_ptr_cache(); + extern_conv("fptodp"); + set_dreg(RET_DREGISTER,0); + use_float(reg,1); + return; +} + +void +code_f2i(int reg) { + use_int(reg); 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_f2u(int reg) { + int freg0 = freg; + int_freg1 = get_dregister(0); + int_freg2 = get_dregister(0); + int_ireg1 = get_register(); + char *fr0 = dregister_name(freg0); + char *fr1 = dregister_name(freg1); + char *fr2 = dregister_name(freg2); + char *r1 = register_name(ireg1); + char *r0; + int lb1,lb2; + + use_int(reg); + r0 = register_name(ireg); + + printf("\tli.s %s,2.14748364800000000000e9\n",fr1); + printf("\tc.le.s %s,%s\n",fr1,fr0); + printf("\tbc1t L_%d\n",lb1=fwdlabel()); + printf("\ttrunc.w.s %s,%s,%s\n",fr2,fr0,r0); + printf("\tmfc1 %s,%s\n",r0,fr2); + printf("\tj L_%d\n",lb2=fwdlabel()); + printf("\t.p2align 2\n"); + fwddef(lb1); + printf("\tsub.s %s,%s,%s\n",fr0,fr0,fr1); + printf("\tli $3,-2147483648 # 0x80000000\n"); + printf("\ttrunc.w.s %s,%s,%s\n",fr1,fr0,r1); + printf("\tmfc1 %s,%s\n",r1,fr1); + printf("\tor %s,%s,%s\n",r1,r1,r0); + fwddef(lb2); + free_register(freg1); + free_register(freg2); + free_register(reg1); } -void code_u2f(int creg0) { - printf("\tcvt.s.w %s,%s\n",register_name(freg),register_name(freg)); - creg = freg; +void +code_i2f(int reg) { + int n = new_lvar(SIZE_OF_FLOAT); + code_assign_lvar(n,ireg); + use_float(reg,0); + code_drlvar(n,reg); + printf("\tcvt.s.w %s,%s\n",register_name(freg),register_name(freg)); } -void code_drgvar(int e2,int d,int freg) +void +code_u2f(int reg) { + int n = new_lvar(SIZE_OF_FLOAT); + int reg0; + int lb1; + char *frn; + code_assign_lvar(n,ireg); + printf("\tbltz %s,L_%d\n",r0=register_name(ireg),lb1=fwdlabel()); + use_float(reg,0); + code_drlvar(n,reg,0); + reg0 = get_register(); + reg1 = get_register(); + frn = dregister_name(reg); + printf("\tcvt.s.w %s,%s\n",frn,frn); + printf("\tj L_%d\n",lb2=fwdlabel()); + printf("\t.p2align 2\n"); + fwddef(lb1); + printf("\tandi %s,%s,0x1\n",r1,r0); + printf("\tsrl %s,%s,1\n",r0,r0); + printf("\tor %s,%s,%s\n",r1,r0); + printf("\tmtc1 %s,%s\n",r1,frn); + printf("\tcvt.s.w %s,%s\n",frn,frn); + printf("\tadd.s %s,%s,%s\n",frn,frn,frn); + fwddef(lb2); + free_register(reg0); + free_register(reg1); +} + +void +code_drgvar(int e2,int d,int freg) { - char *name = ((NMTBL*)cadr(e2))->nm; + int r; 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); + code_lrgvar(e2,0,freg); + set_double(freg); + return; } + r = get_ptr_cache((NMTBL*)cadr(e2)); + use_float(d,freg); + printf("\tl.s %s,0(%s)\n",fregister_name(freg),register_name(r)); } -void code_drlvar(int e2,int d,int freg) +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); + code_lrlvar(e2,0,freg); + set_double(freg); + return; } + use_float(d,freg); + lvar_intro(e2); + printf("\tl.s %s,",fregister_name(freg)); lvar(e2); } -void code_cmp_drgvar(int e2,int d) +void +code_cmp_drgvar(int e2,int reg,int d) { - char *frn; + int r; + char *frn,*fr1; int g; + use_float(d,reg); + + r = get_ptr_cache((NMTBL*)cadr(e2)); + if (d) { code_save_stacks(); - set_dreg(RET_DREGISTER,1); - code_drgvar(e2,d,RET_DREGISTER+2); - code_dpfunc("dcmp"); + set_dreg(RET_DREGISTER,0); + code_drgvar(e2,d,RET_DREGISTER); + clear_ptr_cache(); + printf("\tmove $6,$0\n"); + printf("\tmove $7,$0\n"); + extern_conv("dcmp"); + cmpreg = 2; } 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)); + code_drgvar(e2,d,USE_CREG); + frn = fregister_name(freg); + fr1=dregister_name(g = get_dregister(0)); + printf("\tmtc1 $0,%s\n",fr1); + printf("\tfc.eq.s %s,%s\n",frn,fr1); + cmpreg = CMP_C1T; 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); +code_cmp_drlvar(int e2,int reg,int d) +{ + char *frn,*fr1; + int g; + use_float(d,reg); 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; + code_save_stacks(); + set_dreg(RET_DREGISTER,0); + code_drlvar(e2,d,RET_DREGISTER); + clear_ptr_cache(); + printf("\tmove $6,$0\n"); + printf("\tmove $7,$0\n"); + extern_conv("dcmp"); + cmpreg = 2; + } else { + code_drlvar(e2,d,USE_CREG); + frn = fregister_name(freg); + fr1=dregister_name(g = get_dregister(0)); + printf("\tmtc1 $0,%s\n",fr1); + printf("\tfc.eq.s %s,%s\n",frn,fr1); + cmpreg = CMP_C1T; + free_register(g); + } +} + +static +longlong_lib(char *opc,int reg,int e1) +{ + use_longlong(reg); + code_save_stacks(); + clear_ptr_cache(); + if (reg!=REG_LREGISTER) { + lmove(REG_LREGISTER,reg); + } + if (e1!=-1) { + if (regv_h(e1)!=6) { + printf("move $6,%s\n",lregister_name_high(e1)); + } + if (regv_h(e1)!=7) { + printf("move $7,%s\n",lregister_name_high(e1)); + } + } + set_lreg(RET_LREGISTER,0); + extern_define(opc,0,FUNCTION,1); + printf("\tjal L_%s\n",opc); + if (max_func_iargs<16) max_func_iargs=16; +} + +static +double_lib(char *opc,int reg,int e1) +{ + longlong_lib(opc,reg,e1); + regv[reg]=USING_DREG; +} + +void +dtosop(int op,int reg,int e1) +{ + char *opn=""; + char *opc=""; + int d; + int cmp; + + if ((d=(op<FOP))) { // double case + use_float(reg,d); } 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; + use_float(reg,d); + } + switch(op) { + case FADD: opn="add.s"; break; + case DADD: opc="dpadd"; break; + case FSUB: opn="sub.s"; break; + case DSUB: opc="dpsub"; break; + case FDIV: opc="div.s"; break; + case DDIV: opn="dpdiv"; break; + case FMUL: opc="mul.s"; break; + case DMUL: opn="dpmul"; break; + case FCMP: opn="c.lt.s"; cmp=1; break; + case DCMP: opc="dpcmp"; cmp=1; break; + case FCMPGE: opn="c.le.s"; break; + case FCMPEQ: opn="c.eq.s"; break; + default: + error(-1); return; + } + if (opn && !d) { + grn = fregister_name(e1); + frn = fregister_name(reg); + if (cmp) { + cmpreg=CMP_C1T; + printf("\t%s %s,%s\n",opn,frn,grn); + } else { + printf("\t%s %s,%s,%s\n",opn,frn,frn,grn); + } + } else if (opc && d) { + double_lib(opc,reg,e1); + } else error(-1); +} + +void +code_dassop(int op,int reg,int d) { + /* we have lvalue in creg, applied floating value is in freg */ + // (*creg) op = pop() + int xreg; + char *crn; + char *frn; + int edx,edx0; + + if (!d) { + int xreg=emit_dpop(d); + crn=register_name(ireg); + use_float(d,reg); + frn =fregister_name(reg); + + printf("\tl.s %s,0(%s)\n",frn,crn); + dtosop(op,reg,xreg); + printf("\ts.s %s,0(%s)\n",frn,crn); + emit_dpop_free(xreg,d); + } else { + xreg = emit_lpop(0); /* pop e3 value */ + if (!is_int_reg(creg)) error(-1); + edx = ireg; + emit_push(); + use_float(d,reg); + if (regv_l(lreg)==edx || regv_h(lreg)==edx) { + edx0 = get_register(); if(!edx0) error(-1); + printf("# dassop\n\tmr %s,%s\n",register_name(edx0),register_name(edx)); + edx = edx0; + } + printf("\tlw %s,0(%s)\n",lregister_name_high(reg), + register_name(edx)); + printf("\tlw %s,%d(%s)\n",lregister_name_low(reg), + SIZE_OF_INT,register_name(edx)); + free_register(edx); + dtosop(op,reg,xreg); + edx = emit_pop(0); + printf("\tsw %s,0(%s)\n",lregister_name_high(reg), + register_name(edx)); + printf("\tsw %s,%d(%s)\n",lregister_name_low(reg), + SIZE_OF_INT,register_name(edx)); + free_register(edx); + emit_lpop_free(xreg); + set_double(reg); } } void code_register_dassop(int reg,int op,int d) { - error(-1); + // reg op= dpop() + int xreg; + if (!d) { + xreg=emit_dpop(d); + dtosop(op,reg,xreg); + emit_dpop_free(xreg,d); + } else { + xreg=emit_lpop(); + dtosop(op,reg,xreg); + emit_lpop_free(xreg); + set_double(lreg); + } } +static void +double_lib_c(char *opc,double value); +{ + extern_define(opc,0,FUNCTION,1); + if (max_func_iargs<16) max_func_iargs=16; + printf("\tli.d $6,%g\n",value); + printf("\tjal L_%s\n",opc); +} 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); - + char *grn,*drn; + int r; + int dir=caddr(e1); + + if (!d) { + if (car(e2)==FREGISTER) { + crn=register_name(cadr(e2)); + } else { + g_expr(e2); + if (!is_int_reg(creg)) error(-1); + crn=register_name(ireg); + } + + use_float(d,reg); + + frn=fregister_name(reg); + grn=fregister_name(g=get_dregister(d)); + printf("\tli.s %s,1.0\n",grn); + + if (car(e2)==FREGISTER) { + printf("\tmov.s %s,%s\n",crn,frn); + printf("\t%s %s,%s,%s\n",(dir>0)?"add.s":"sub.s",crn,frn,grn); + } else { + printf("\tl.s %s,0(%s)\n",frn,crn); + printf("\t%s %s,%s,%s\n",(dir>0)?"add.s":"sub.s",frn,frn,grn); + printf("\ts.s %s,0(%s)\n",frn,crn); + } + free_register(g); + } else { + if (car(e2)==DREGISTER) { + use_float(d,reg); 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; + clear_ptr_cache(); + lmove(DREGISTER_OPERAND_1,cadr(e2)); + double_lib_c(dir>0?"dpadd":"dpsub",1.0); + free_register(g); + if (reg!=RET_DREGISTER) { + lmove(RET_DREGISTER,cadr(reg)); + } + return; + } + g_expr(e2); + if(!is_int_reg(creg)) error(-1); + emit_push(); + code_save_stacks(); + clear_ptr_cache(); + set_dreg(RET_DREGISTER,0); + xreg = emit_pop_regvar(0); + xrn = register_name(xreg); + printf("\tlw $4,%d(%s)\n",SIZE_OF_INT,xrn); + printf("\tlw $5,0(%s)\n",xrn); + double_lib_c(dir>0?"dpadd":"dpsub",1.0); + use_float(d,reg); + if (use) { + printf("\tlw %s,%d(%s)\n",lregister_name_high(reg),SIZE_OF_INT,xrn); + printf("\tlw %s,0(%s)\n",lregister_name_low(reg),xrn); + } + printf("\tsw $2,%d(%s)\n",SIZE_OF_INT,xrn); + printf("\tsw %3,0(%s)\n",xrn); + emit_pop_free(xreg); } } @@ -2608,113 +3276,1100 @@ 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; + char *grn,*drn; + int dir=caddr(e1); + + if (!d) { + if (car(e2)==FREGISTER) { + crn=register_name(cadr(e2)); + } else { + g_expr(e2); + if (!is_int_reg(creg)) error(-1); + crn=register_name(creg); + } + + use_float(d,reg); + + frn=fregister_name(reg); + grn=fregister_name(g=get_dregister(d)); + printf("\tli.s %s,1.0\n",grn); + + if (car(e2)==FREGISTER) { + printf("\t%s %s,%s,%s\n",(dir>0)?"add.s":"sub.s",frn,crn,grn); + printf("\tmov.s %s,%s\n",frn,crn); + } else { + printf("\tl.s %s,0(%s)\n",fload(d),frn,crn); + printf("\t%s %s,%s,%s\n",(dir>0)?"add.s":"sub.s",grn,frn,grn); + printf("\ts.s %s,0(%s)\n",fstore(d),grn,crn); + } + free_register(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; + if (car(e2)==DREGISTER) { + use_float(d,reg); + code_save_stacks(); + clear_ptr_cache(); + lmove(DREGISTER_OPERAND_1,cadr(e2)); + double_lib_c(dir>0?"dpadd":"dpsub",1.0); + if (use && reg!=RET_DREGISTER) { + lmove(reg,RET_DREGISTER); + } + if (cadr(e2)!=RET_DREGISTER) { + lmove(cadr(e2),RET_DREGISTER); + } + return; + } + g_expr(e2); + if(!is_int_reg(creg)) error(-1); + emit_push(); + code_save_stacks(); + clear_ptr_cache(); + set_dreg(RET_LREGISTER,0); + xreg = emit_pop_regvar(0); + xrn = register_name(xreg); + printf("\tlw $4,%d(%s)\n",SIZE_OF_INT,xrn); + printf("\tlw $5,0(%s)\n",xrn); + double_lib_c(dir>0?"dpadd":"dpsub",1.0); + printf("\tsw $2,%d(%s)\n",SIZE_OF_INT,xrn); + printf("\tsw %3,0(%s)\n",xrn); + emit_pop_free(xreg); + if (use) { + printf("\tlw %s,%d(%s)\n",lregister_name_high(reg),SIZE_OF_INT,xrn); + printf("\tlw %s,0(%s)\n",lregister_name_low(reg),xrn); + } } - } void -drexpr(int e1, int e2,int l1, int op) -{ - g_expr(list3(((op==FOP+EQ||op==FOP+NEQ)?DCMP:FCMPGE),e1,e2)); +drexpr(int e1, int e2,int l1, int op,int cond) +{ + int dop; + if (!cond) { + switch(op) { + case FOP+GT: + drexpr(e2,e1,l1,FOP+GE,1); return; + case FOP+GE: + drexpr(e2,e1,l1,FOP+GT,1); return; + case FOP+EQ: + op=FOP+NEQ; break; + case FOP+NEQ: + op=FOP+EQ; break; + case DOP+GT: + drexpr(e2,e1,l1,DOP+GE,1); return; + case DOP+GE: + drexpr(e2,e1,l1,DOP+GT,1); return; + case DOP+EQ: + op=DOP+NEQ; break; + case DOP+NEQ: + op=DOP+EQ; break; + } + } + dop>FOP?FOP:DOP; 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; + case FOP+GT: op=FOP+CMP; break; + case DOP+GT: op=DOP+CMP; break; + case FOP+GE: op=FOP+CMPGE; break; + case DOP+GE: op=DOP+CMPGE; break; + case FOP+EQ: op=FOP+CMPEQ; break; + case DOP+EQ: op=DOP+CMP; break; + case FOP+NEQ: op=FOP+CMPEQ; break; + case DOP+NEQ: op=DOP+CMP; break; + default: error(-1); + } + g_expr(list3(op,e2,e1)); + switch(op) { + case DOP+GT: printf("\tbgez\t$2,L_%d\n",l1);break; + case FOP+GT: printf("\tbc1t\tL_%d\n",l1);break; + case DOP+GE: printf("\tbltz\t$2,L_%d\n",l1);break; + case FOP+GE: printf("\tbc1t\t$2,L_%d\n",l1);break; + case DOP+EQ: printf("\tbeq\t$2,$0,L_%d\n",l1);break; + case FOP+EQ: printf("\tbc1t\tL_%d\n",l1);break; + case DOP+NEQ: printf("\tbne\t$2,$0,L_%d\n",l1);break; + case FOP+NEQ: printf("\tbc1t\tL_%d\n",l1);break; } } int emit_dpop(int d) { int xreg,reg; - if (d) - xreg=pop_dregister(); - else - xreg=pop_fregister(); + xreg=pop_fregister(); if (xreg<= -REG_LVAR_OFFSET) { reg = get_dregister(d); - code_drlvar(REG_LVAR_OFFSET+xreg,d,reg); + code_drlvar(REG_LVAR_OFFSET+xreg,1,reg); free_lvar(REG_LVAR_OFFSET+xreg); xreg=reg; } return xreg; } -void emit_dpop_free(int e1,int d) +int emit_dpop_regvar(int d) +{ + int xreg,reg; + xreg=pop_fregister(); + reg = cadr(get_dregister_var(d)); + if (xreg<= -REG_LVAR_OFFSET) { + code_drlvar(REG_LVAR_OFFSET+xreg,1,reg); + free_lvar(REG_LVAR_OFFSET+xreg); + xreg=reg; + } else { + code_dassign_register(reg,d,xreg); + } + return xreg; +} + +void +emit_dpop_free(int e1,int d) { free_register(e1); } -void emit_dpush(int d) +void +emit_dpush(int d) { int new_reg; + if (!is_float_reg(creg)) error(-1); if (freg_sp>MAX_MAX) error(-1); - new_reg = get_dregister(d); - if (d) { - dreg_stack[dreg_sp++] = dreg; /* push するかわりにレジスタを使う */ - creg = dreg = new_reg; + new_reg = get_dregister(1); /* 絶対に取れる */ + freg_stack[freg_sp++] = freg; /* push するかわりにレジスタを使う */ + creg = freg = new_reg; +} + +#endif + +#if LONGLONG_CODE + + +/* 64bit int part */ +static void +lmove(int to,int from) +{ + int tmp; + if (regv_h(to)==regv_l(from)&&(regv_l(to)==regv_h(from))) { + tmp = get_register(); + printf("\tmove %s,%s\n",register_name(tmp),lregister_name_low(from)); + printf("\tmove %s,%s\n",lregister_name_high(to),lregister_name_high(from)); + printf("\tmove %s,%s\n",lregister_name_low(to),register_name(tmp)); + free_register(tmp); + } else if (regv_h(to)==regv_l(from)) { + printf("\tmove %s,%s\n",lregister_name_low(to),lregister_name_low(from)); + printf("\tmove %s,%s\n",lregister_name_high(to),lregister_name_high(from)); + } else { + printf("\tmove %s,%s\n",lregister_name_high(to),lregister_name_high(from)); + printf("\tmove %s,%s\n",lregister_name_low(to),lregister_name_low(from)); + } +} + +static void +pcond(int op,char *s,int l1) +{ + if (op==EQ||op==NEQ) { + printf(",L_%d\n",l1); + } else { + printf("\tb%s %s,$0,L_%d\n",s,register_name(cmpreg),l1); + } +} + +static int +lcmp(int op,int cond) +{ + if (op==EQ||op==NEQ) { + if (!cond) { op=(op==EQ)?CMPNEQ:CMPEQ; } } else { - freg_stack[freg_sp++] = freg; /* push するかわりにレジスタを使う */ - creg = freg = new_reg; + op = (op==UGT||op==UGE)?UCMP:CMP; + } + return op; +} + +void +lrexpr(int e1, int e2,int l1, int op,int cond) +{ + int reg; + int e3,op1; + g_expr(e1); + emit_lpush(); + g_expr(e2); + e3 = emit_lpop(); + if (!is_longlong_reg(creg)) error(-1); + reg = lreg; + + tosop(op1=lcmp(op,cond),regv_h(reg),regv_h(e3)); + switch(op) { + case LOP+GT: + pcond(op,code_gt(cond),l1); break; + case LOP+GE: + pcond(op,code_ge(cond),l1); break; + case LOP+EQ: + pcond(op,code_eq(cond),l1); break; + case LOP+NEQ: + pcond(op,code_eq(!cond),l1); break; + case LOP+LT: + pcond(op,code_ge(!cond),l1); break; + case LOP+LE: + pcond(op,code_gt(!cond),l1); break; + case LOP+UGT: + pcond(op,code_ugt(cond),l1); break; + case LOP+UGE: + pcond(op,code_uge(cond),l1); break; + default: + error(-1); + } + tosop(op1,regv_l(reg),regv_l(e3)); + switch(op) { + case LOP+GT: + pcond(op,code_gt(cond),l1); break; + case LOP+GE: + pcond(op,code_ge(cond),l1); break; + case LOP+EQ: + pcond(op,code_eq(cond),l1); break; + case LOP+NEQ: + pcond(op,code_eq(!cond),l1); break; + case LOP+LT: + pcond(op,code_ge(!cond),l1); break; + case LOP+LE: + pcond(op,code_gt(!cond),l1); break; + case LOP+UGT: + pcond(op,code_ugt(cond),l1); break; + case LOP+UGE: + pcond(op,code_uge(cond),l1); break; + default: + error(-1); + } + emit_lpop_free(e3); +} + +int +emit_lpop() +{ + int xreg,reg; + xreg=lreg_stack[--lreg_sp]; + if (xreg<= -REG_LVAR_OFFSET) { + reg = get_lregister(); + code_lrlvar(REG_LVAR_OFFSET+xreg,reg); + free_lvar(REG_LVAR_OFFSET+xreg); + xreg = reg; + } + return xreg; +} + +void +code_lregister(int e2,int reg) +{ + use_longlong(reg); + if (reg!=e2) { + lmove(reg,e2); + } +} + +void +code_cmp_lregister(int reg) +{ + use_longlong(reg); + printf("\tor %s,%s,%s\n", + lregister_name_low(reg), + lregister_name_low(reg), + lregister_name_high(reg)); + printf("\tbeq %s,$0\n",lregister_name_low(reg)); +} + +void +code_cmp_lrgvar(int e1,int creg) +{ + use_longlong(creg); + code_lrgvar(e1,creg); + code_cmp_lregister(creg); +} + +void +code_cmp_lrlvar(int e1,int creg) +{ + use_longlong(creg); + code_lrlvar(e1,creg); + code_cmp_lregister(creg); +} + +void +code_lassign(int e2,int creg) +{ + char *drn = register_name(e2); + char *crn_h; + char *crn_l; + + use_longlong(creg); + crn_h = lregister_name_high(creg); + crn_l = lregister_name_low(creg); + + if (e2==regv_h(creg)) { + printf("\tsw %s,%d(%s)\n",crn_l,SIZE_OF_INT,drn); + printf("\tsw %s,0(%s)\n",crn_h,drn); + } else { + printf("\tsw %s,0(%s)\n",crn_h,drn); + printf("\tsw %s,%d(%s)\n",crn_l,SIZE_OF_INT,drn); + } +} + +void +code_lassign_gvar(int e2,int creg) +{ + int r; + r = get_ptr_cache((NMTBL*)cadr(e2)); + code_lassign(r,creg); +} + +void +code_lassign_lvar(int e2,int creg) +{ + char *crn_h; + char *crn_l; + + use_longlong(creg); + crn_h = lregister_name_high(creg); + crn_l = lregister_name_low(creg); + lvar_intro(e2); + printf("\tsw %s,",crn_h);lvar(e2); + printf("\tsw %s,",crn_l);lvar(e2+SIZE_OF_INT); +} + +void +code_lassign_lregister(int e2,int reg) +{ + use_longlong(reg); + if (e2!=reg) { + lmove(e2,reg); } } +static long long ll0 = 1LL; + +static int +code_l1(long long d) +{ + int *i = (int *)&ll0; int *j = (int *)&d; + return (i[1] == 1)?j[1]:j[0]; +} + +static int +code_l2(long long d) +{ + int *i = (int *)&ll0; int *j = (int *)&d; + return (i[1] == 1)?j[0]:j[1]; +} + +void +code_lconst(int e1,int creg) +{ + use_longlong(creg); + code_const(code_l1(lcadr(e1)),regv_l(creg)); + code_const(code_l2(lcadr(e1)),regv_h(creg)); +} + +void +code_lneg(int creg) +{ + int dreg; + char *rh,*rl,*dh,*dl; + use_longlong(creg); + rl=lregister_name_low(creg); + rh=lregister_name_high(creg); + dreg = get_lregister(); + dl=lregister_name_low(dreg); + dh=lregister_name_high(dreg); + printf("\tsubu %s,$0,%s\n",dl,rl); + printf("\tsubu %s,$0,%s\n",dh,rh); + printf("\tsltu %s,$0,%s\n",rl,dl); + printf("\tsubu %s,%s,%s\n",dh,dh); + free_register(lreg); + set_lreg(dreg,0); +} + +void +code_lrgvar(int e1,int creg) +{ + int r; + char *crn_h; + char *crn_l; + use_longlong(creg); + crn_h = lregister_name_high(creg); + crn_l = lregister_name_low(creg); + r = get_ptr_cache((NMTBL*)cadr(e1)); + printf("\tlw %s,0(%s)\n",crn_h,register_name(r)); + printf("\tlw %s,%d(%s)\n",crn_l,SIZE_OF_INT,register_name(r)); +} + +void +code_lrlvar(int e1,int creg) +{ + char *crn_h; + char *crn_l; + use_longlong(creg); + crn_h = lregister_name_high(creg); + crn_l = lregister_name_low(creg); + lvar_intro(e1); + printf("\tlw %s,",crn_h); lvar(e1); + printf("\tlw %s,",crn_l); lvar(e1+SIZE_OF_INT); +} + + + +static void +code_asld_lib(int oreg) +{ + char *ch,*cl,*oh,*ol,*dh,*dl; + // 5 4 7 3 2 6 + int dreg = get_lregister(); + ch = lregister_name_high(creg); + cl = lregister_name_low(creg); + oh = lregister_name_high(oreg); + ol = lregister_name_low(oreg); + dh = lregister_name_high(dreg); + dl = lregister_name_low(dreg); + + printf("\tsll %s,%s,26\n",dh,ol); + printf("\tbgez %s,1f\n",dh); + printf("\tsll %s,%s,%s\n",oh,cl,ol); + printf("\t.set noreorder\n"); + printf("\tb 3f\n"); + printf("\tmove %s,$0\n",dl); + printf("\t.set reorder\n"); + printf("\t1:\n"); + printf("\t.set noreorder\n"); + printf("\tbeq %s,$0,2f\n",dh); + printf("\tsll %s,%s,%s\n",oh,ch,ol); + printf("\t.set reorder\n"); + printf("\tsubu %s,%s,%s\n",dh,ol); + printf("\tsrl %s,%s,%s\n",dh,cl,dh); + printf("\tor %s,%s,%s\n",oh,oh,dh); + printf("\t2:\n"); + printf("\tsll %s,%s,%s\n",dl,cl,ol); + printf("\t3:\n"); + printf("\tmove %s,%s\n",cl,dl); + printf("\tmove %s,%s\n",ch,oh); + free_register(dreg); +} + +static void +code_asrd_lib(int oreg) // ___ashrdi3$stub +{ + char *ch,*cl,*oh,*ol,*dh,*dl; + // 5 4 2 3 9 8 + int dreg = get_lregister(); + ch = lregister_name_high(creg); + cl = lregister_name_low(creg); + oh = lregister_name_high(oreg); + ol = lregister_name_low(oreg); + dh = lregister_name_high(dreg); + dl = lregister_name_low(dreg); + + printf("\tsll %s,%s,26\n",oh,ol); + printf("\tbgez %s,1f\n",oh); + printf("\tsra %s,%s,%s\n",dl,ch,ol); + printf("\t.set noreorder\n"); + printf("\tb 3f\n"); + printf("\tsra %s,%s,31\n",dh,ch); + printf("\t.set reorder\n"); + printf("\t1:\n"); + printf("\t.set noreorder\n"); + printf("\tbeq %s,$0,2f\n",oh); + printf("\tsrl %s,%s,%s\n",dl,cl,ol); + printf("\t.set reorder\n"); + printf("\tsubu %s,$0,%s\n",oh,ol); + printf("\tsll %s,%s,%s\n",oh,ch,oh); + printf("\tor %s,%s,%s\n",dl,dl,oh); + printf("\t2:\n"); + printf("\tsra %s,%s,%s\n",dh,ch,ol); + printf("\t3:\n"); + printf("\tmove %s,%s\n",cl,dl); + printf("\tmove %s,%s\n",ch,dh); + free_register(dreg); +} + +static void +code_lsrd_lib(int oreg) // ___lshrdi3$stub +{ + char *ch,*cl,*oh,*ol,*dh,*dl; + // 5 4 2 3 9 8 + int dreg = get_lregister(); + ch = lregister_name_high(creg); + cl = lregister_name_low(creg); + oh = lregister_name_high(oreg); + ol = lregister_name_low(oreg); + dh = lregister_name_high(dreg); + dl = lregister_name_low(dreg); + + printf("\tsll %s,%s,26\n",oh,ol); + printf("\tbgez %s,1f\n",oh); + printf("\tsrl %s,%s,%s\n",dl,ch,ol); + printf("\t.set noreorder\n"); + printf("\tb 3f\n"); + printf("\tmove %s,$0\n",dh); + printf("\t.set reorder\n"); + printf("\t\n"); + printf("\t1:\n"); + printf("\t.set noreorder\n"); + printf("\tbeq %s,$0,2f\n",oh); + printf("\tsrl %s,%s,%s\n",dl,cl,ol); + printf("\t.set reorder\n"); + printf("\t\n"); + printf("\tsubu %s,$0,%s\n",oh,ol); + printf("\tsll %s,%s,%s\n",oh,ch,oh); + printf("\tor %s,%s,%s\n",dl,dl,oh); + printf("\t2:\n"); + printf("\tsrl %s,%s,%s\n",dh,ch,ol); + printf("\t3:\n"); + printf("\tmove %s,%s\n",cl,dl); + printf("\tmove %s,%s\n",ch,dh); +} + +static void +code_ldiv_lib(int oreg) // ___divdi3$stub +{ + code_save_stacks(); + clear_ptr_cache(); + set_lreg(LREGISTER_OPERAND,1); + set_lreg_operand(oreg,1); + extern_conv("__divdi3"); +} + +static void +code_ludiv_lib(int oreg) // ___udivdi3$stub +{ + code_save_stacks(); + clear_ptr_cache(); + set_lreg(LREGISTER_OPERAND,1); + set_lreg_operand(oreg,1); + extern_conv("__udivdi3"); +} + +static void +code_lmod_lib(int oreg) // ___moddi3$stub +{ + code_save_stacks(); + clear_ptr_cache(); + set_lreg(LREGISTER_OPERAND,1); + set_lreg_operand(oreg,1); + extern_conv("__moddi3"); +} + +static void +code_lumod_lib(int oreg) // ___umoddi3$stub +{ + code_save_stacks(); + clear_ptr_cache(); + set_lreg(LREGISTER_OPERAND,1); + set_lreg_operand(oreg,1); + extern_conv("__umoddi3"); +} + +#define check_lreg(reg) if (reg!=lreg) { lmove(reg,lreg); } + +void +ltosop(int op,int reg,int oreg) +{ + int dx = -1; + char *orn_h,*crn_h,*drn_h; + char *orn_l,*crn_l,*drn_l; + // creg = creg op oreg + + use_longlong(reg); + if(oreg==-1) { + error(-1); + } else if (oreg<= -REG_LVAR_OFFSET) { + dx = get_lregister(); if (dx<0) error(-1); + use_reg(dx); + code_rlvar(oreg+REG_LVAR_OFFSET,dx); + oreg = dx; + } + + switch(op) { + case LLSHIFT: + case LULSHIFT: + code_asld_lib(oreg); // ___ashldi3$stub + check_lreg(reg); + return; + case LRSHIFT: + code_asrd_lib(oreg); // ___ashrdi3$stub + check_lreg(reg); + return; + case LURSHIFT: + code_lsrd_lib(oreg); // ___lshrdi3$stub + check_lreg(reg); + return; + } + orn_h = lregister_name_high(oreg); + orn_l = lregister_name_low(oreg); + crn_h = lregister_name_high(reg); + crn_l = lregister_name_low(reg); + switch(op) { + case LADD: + drn = register_name(dx = get_register()); + printf("\taddu %s,%s,%s\n",crn_l,crn_l,orn_l); + printf("\tsltu %s,%s,%s\n",drn,crn_l,orn_l); + printf("\taddu %s,%s,%s\n",crn_h,crn_h,orn_h); + printf("\taddu %s,%s,%s\n",crn_h,crn_h,drn); + break; + case LSUB: + drn = register_name(dx = get_register()); + printf("\tsltu %s,%s,%s\n",drn,orn_l,crn_l); + printf("\tsubu %s,%s,%s\n",crn_l,orn_l,crn_l); + printf("\tsubu %s,%s,%s\n",crn_h,orn_h,crn_h); + printf("\tsubu %s,%s,%s\n",crn_h,crn_h,drn); + break; + case LCMP: + error(-1); + break; + case LBAND: + printf("\tand %s,%s,%s\n",crn_l,crn_l,orn_l); + printf("\tand %s,%s,%s\n",crn_h,crn_h,orn_h); + break; + case LEOR: + printf("\txor %s,%s,%s\n",crn_l,crn_l,orn_l); + printf("\txor %s,%s,%s\n",crn_h,crn_h,orn_h); + break; + case LBOR: + printf("\tor %s,%s,%s\n",crn_l,crn_l,orn_l); + printf("\tor %s,%s,%s\n",crn_h,crn_h,orn_h); + break; + case LMUL: + case LUMUL: + code_save_stacks(); + clear_ptr_cache(); + dx=get_lregister(); + use_reg(dx); + drn_l = lregister_name_low(dx); + drn_h = lregister_name_high(dx); + /* + drn_l = l32( crn_l * orn_l); + drn_h = h32( crn_l * orn_l); + orn_l = l32( crn_h * orn_l); + drn_h = drn_h + orn_l; + crn_l = l32( crn_l * orn_h); + crn_h = drn_h + crn_l; + crn_l = drn_l; + */ + printf("\tlw $5,96($fp)\n"); + printf("\tsra $4,$5,31\n"); + printf("\tlw $2,96($fp)\n"); + printf("\tmove $3,$4\n"); + printf("\tlw $6,48($fp)\n"); + printf("\tmultu $6,$2\n"); + printf("\tmfhi $5\n"); + printf("\tmflo $4\n"); + printf("\tlw $7,48($fp)\n"); + printf("\tmult $6,$7,$3\n"); + printf("\taddu $5,$5,$6\n"); + printf("\tlw $6,52($fp)\n"); + printf("\tmult $2,$2,$6\n"); + printf("\taddu $5,$5,$2\n"); + break; + case LDIV: + code_ldiv_lib(oreg); // ___divdi3$stub + check_lreg(reg); + break; + case LUDIV: + code_ludiv_lib(oreg); // ___udivdi3$stub + check_lreg(reg); + break; + case LMOD: + code_lmod_lib(oreg); // ___moddi3$stub + check_lreg(reg); + break; + case LUMOD: + code_lumod_lib(oreg); // ___umoddi3$stub + check_lreg(reg); + break; + default: + error(-1); + } + if(dx!=-1) free_register(dx); +} + +int +code_lconst_op_p(int op,int e) +{ + int v; + if (car(e)==LCONST) { + if (!(-32766<lcadr(e)&&lcadr(e)<32767)) return 0; + v = lcaddr(e); + } else if (car(e)==CONST) { + if (!(-32766<cadr(e)&&cadr(e)<32767)) return 0; + v = caddr(e); + } else return 0; + + switch(op) { + case LLSHIFT: + case LULSHIFT: + case LRSHIFT: + case LURSHIFT: + return (0<v&&v<31); + case LADD: + case LSUB: + return 1; + case LBOR: + return (v>0); + default: + return 0; + } +} + +void +loprtc(int op,int creg,int e) +{ + char *crn_h; + char *crn_l; + char *grn; + int v; + int greg; + + use_longlong(creg); + crn_h = lregister_name_high(creg); + crn_l = lregister_name_low(creg); + + if (car(e)==LCONST) v = lcadr(e); + else if (car(e)==CONST) v = cadr(e); + + switch(op) { + case LLSHIFT: + case LULSHIFT: + greg = get_register(); + use_reg(greg); + grn = register_name(greg); + printf("\tsrwi %s,%s,%d\n",grn,crn_l,32-v); + printf("\tslwi %s,%s,%d\n",crn_h,crn_h,v); + printf("\tor %s,%s,%s\n",crn_h,grn,crn_h); + printf("\tslwi %s,%s,%d\n",crn_l,crn_l,v); + free_register(greg); + return; + case LRSHIFT: + greg = get_register(); + use_reg(greg); + grn = register_name(greg); + printf("\tsrwi %s,%s,%d\n",grn,crn_l,v); + printf("\tinsrwi %s,%s,%d,0\n",grn,crn_h,v); + printf("\tsrawi %s,%s,%d\n",crn_h,crn_h,v); + printf("\tmr %s,%s\n",crn_l,grn); + free_register(greg); + return; + case LURSHIFT: + greg = get_register(); + use_reg(greg); + grn = register_name(greg); + printf("\tslwi %s,%s,%d\n",grn,crn_h,32-v); + printf("\tsrwi %s,%s,%d\n",crn_l,crn_l,v); + printf("\tor %s,%s,%s\n",crn_l,grn,crn_l); + printf("\tsrwi %s,%s,%d\n",crn_h,crn_h,v); + free_register(greg); + return; + case LSUB: + v = -v; + case LADD: + printf("\taddic %s,%s,%d\n",crn_l,crn_l,v); + if (v<0) + printf("\taddme %s,%s\n",crn_h,crn_h); + else + printf("\taddze %s,%s\n",crn_h,crn_h); + break; + case LBOR: + printf("\tori %s,%s,lo16(%d)\n",crn_l,crn_l,v); + break; + default: + error(-1); + } +} + + +void +emit_lpop_free(int xreg) +{ + if (xreg>=0) + free_register(xreg); +} + +void +emit_lpush() +{ + int new_reg; + if (!is_longlong_reg(creg)) error(-1); + if (lreg_sp>MAX_MAX) error(-1); + new_reg = get_lregister(); /* 絶対に取れる(?) */ + lreg_stack[lreg_sp++] = creg; /* push するかわりにレジスタを使う */ + lreg = creg = new_reg; +} + +void +code_i2ll(int reg) +{ + char *crn,*crn_h,*crn_l; + int reg0; + crn = register_name(reg0 = ireg); + use_longlong(reg); + crn_h = lregister_name_high(lreg); + crn_l = lregister_name_low(lreg); + if (reg0!=regv_l(lreg)) + printf("\tmr %s,%s\n",crn_l,crn); + printf("\tsrawi %s,%s,31\n",crn_h,crn_l); +} + +void +code_i2ull(int reg) +{ + code_i2ll(reg); +} + +void +code_u2ll(int reg) +{ + char *crn,*crn_h,*crn_l; + int reg0; + crn = register_name(reg0 = ireg); + use_longlong(reg); + crn_h = lregister_name_high(lreg); + crn_l = lregister_name_low(lreg); + if (reg0!=regv_l(lreg)) + printf("\tmr %s,%s\n",crn_l,crn); + printf("\tli %s,0\n",crn_h); +} + +void +code_u2ull(int creg) +{ + code_u2ll(creg); +} + +void +code_ll2i(int reg) +{ + char *crn_l; + int reg0; + crn_l = lregister_name_low(reg0=lreg); + use_int(reg); + if (ireg!=regv_l(reg0)) + printf("\tmr %s,%s\n",register_name(ireg),crn_l); +} + +void +code_ll2u(int creg) +{ + code_ll2i(creg); +} + +void +code_ull2i(int creg) +{ + code_ll2i(creg); +} + +void +code_ull2u(int creg) +{ + code_ll2i(creg); +} + +#if FLOAT_CODE + +void +code_d2ll(int reg) +{ + // fixdfdi$stub + set_freg(RET_FREGISTER,1); + extern_conv("__fixdfdi"); + set_lreg(RET_LREGISTER,0); + if (reg!=USE_CREG&®!=RET_LREGISTER) + use_longlong(reg); +} + +void +code_d2ull(int reg) +{ + set_freg(RET_FREGISTER,1); + extern_conv("__fixunsdfdi"); + set_lreg(RET_LREGISTER,0); + if (reg!=USE_CREG&®!=RET_LREGISTER) + use_longlong(reg); +} + +void +code_f2ll(int reg) +{ + set_freg(RET_FREGISTER,1); + extern_conv("__fixdfdi"); + set_lreg(RET_LREGISTER,0); + if (reg!=USE_CREG&®!=RET_LREGISTER) + use_longlong(reg); +} + +void +code_f2ull(int reg) +{ + set_freg(RET_FREGISTER,1); + extern_conv("__fixsfdi"); + set_lreg(RET_LREGISTER,0); + if (reg!=USE_CREG&®!=RET_LREGISTER) + use_longlong(reg); +} + +void +code_ll2d(int reg) +{ + set_lreg(RET_LREGISTER,1); + extern_conv("__floatdidf"); + set_freg(RET_FREGISTER,0); + if (reg!=USE_CREG&®!=RET_FREGISTER) + use_float(1,reg); +} + + +void +code_ll2f(int reg) +{ + set_lreg(RET_LREGISTER,1); + extern_conv("__floatdisf"); + set_freg(RET_FREGISTER,0); + if (reg!=USE_CREG&®!=RET_FREGISTER) + use_float(0,reg); +} + +void +code_ull2d(int creg) +{ + code_ll2d(creg); +} + +void +code_ull2f(int creg) +{ + code_ll2f(creg); +} + +#endif + +static char * +addze(int dir) +{ + return dir>0?"ze":"me"; +} + +void +code_lpreinc(int e1,int e2,int reg) +{ + char *xrn,*drn_h,*drn_l; + int dreg,xreg; + int dir=caddr(e1); + if (car(e2)==LREGISTER) { + use_longlong(reg); + printf("\taddic %s,%s,%d\n", + lregister_name_low(cadr(e2)),lregister_name_low(cadr(e2)), dir); + printf("\tadd%s %s,%s\n", addze(dir), + lregister_name_high(cadr(e2)),lregister_name_high(cadr(e2))); + if (cadr(reg)!=cadr(e2)) { + lmove(cadr(reg),cadr(e2)); + } + return; + } + g_expr(e2); + if(!is_int_reg(creg)) error(-1); + emit_push(); + if (reg==USE_CREG) { + dreg=get_lregister(); if (!dreg) error(-1); + drn_h = lregister_name_high(dreg); + drn_l = lregister_name_low(dreg); + set_lreg(dreg,0); // free old lreg==creg + } else { + drn_h = lregister_name_high(reg); + drn_l = lregister_name_low(reg); + } + xreg = emit_pop(0); + xrn = register_name(xreg); + printf("\tlwz %s,%d(%s)\n",drn_l,SIZE_OF_INT,xrn); + printf("\tlwz %s,0(%s)\n",drn_h,xrn); + printf("\taddic %s,%s,%d\n",drn_l,drn_l,dir); + printf("\tadd%s %s,%s\n",addze(dir),drn_h,drn_h); + printf("\tstw %s,%d(%s)\n",drn_l,SIZE_OF_INT,xrn); + printf("\tstw %s,0(%s)\n",drn_h,xrn); + emit_pop_free(xreg); +} + +void +code_lpostinc(int e1,int e2,int reg) +{ + char *xrn,*drn_h,*drn_l; + char *nrn_h,*nrn_l; + int dreg,nreg,xreg; + int dir=caddr(e1); + if (car(e2)==LREGISTER) { + use_longlong(reg); + lmove(cadr(reg),cadr(e2)); + printf("\taddic %s,%s,%d\n", + lregister_name_low(cadr(e2)),lregister_name_low(cadr(e2)), dir); + printf("\tadd%s %s,%s\n", addze(dir), + lregister_name_high(cadr(e2)),lregister_name_high(cadr(e2))); + return; + } + g_expr(e2); + if(!is_int_reg(creg)) error(-1); + emit_push(); + nreg=get_lregister(); if (!nreg) error(-1); + nrn_h = lregister_name_high(nreg); + nrn_l = lregister_name_low(nreg); + if (reg==USE_CREG) { + dreg=get_lregister(); if (!dreg) error(-1); + drn_h = lregister_name_high(dreg); + drn_l = lregister_name_low(dreg); + set_lreg(dreg,0); // free old lreg==creg + } else { + drn_h = lregister_name_high(reg); + drn_l = lregister_name_low(reg); + } + xreg = emit_pop(0); + xrn = register_name(xreg); + printf("\tlwz %s,%d(%s)\n",drn_l,SIZE_OF_INT,xrn); + printf("\tlwz %s,0(%s)\n",drn_h,xrn); + printf("\taddic %s,%s,%d\n",nrn_l,drn_l,dir); + printf("\tadd%s %s,%s\n",addze(dir),nrn_h,drn_h); + printf("\tstw %s,%d(%s)\n",nrn_l,SIZE_OF_INT,xrn); + printf("\tstw %s,0(%s)\n",nrn_h,xrn); + emit_pop_free(xreg); + free_register(nreg); +} + +void +code_lassop(int op,int reg) +{ + int xreg; + int edx,edx0=-1; + + // (*creg) op = pop() + xreg = emit_lpop(0); /* pop e3 value */ + if (!is_int_reg(creg)) error(-1); + edx = ireg; + emit_push(); + use_longlong(reg); + if (regv_l(lreg)==edx || regv_h(lreg)==edx) { + edx0 = get_register(); if(!edx0) error(-1); + printf("# lassop\n\tmr %s,%s\n",register_name(edx0),register_name(edx)); + edx = edx0; + } + printf("\tlwz %s,0(%s)\n",lregister_name_high(reg), + register_name(edx)); + printf("\tlwz %s,%d(%s)\n",lregister_name_low(reg), + SIZE_OF_INT,register_name(edx)); + free_register(edx); + ltosop(op,reg,xreg); + edx = emit_pop(0); + printf("\tstw %s,0(%s)\n",lregister_name_high(reg), + register_name(edx)); + printf("\tstw %s,%d(%s)\n",lregister_name_low(reg), + SIZE_OF_INT,register_name(edx)); + free_register(edx); + emit_lpop_free(xreg); +} + +void +code_register_lassop(int reg,int op) { + // reg op = pop() + int xreg=emit_lpop(); + ltosop(op,reg,xreg); + emit_lpop_free(xreg); +} + + #endif void @@ -2724,26 +4379,28 @@ 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]=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]=new_lvar(SIZE_OF_DOUBLE)),reg,1); freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; } } #endif +#if LONGLONG_CODE + for(i=0;i<lreg_sp;i++) { + if ((reg=lreg_stack[i])>=0) { + code_lassign_lvar( + (lreg_stack[i]=new_lvar(SIZE_OF_LONGLONG)),reg); + lreg_stack[i]= lreg_stack[i]-REG_LVAR_OFFSET; + } + } +#endif } void @@ -2759,223 +4416,7 @@ { 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 */
--- a/mc-code-powerpc.c Thu May 06 11:38:56 2004 +0900 +++ b/mc-code-powerpc.c Mon May 10 21:12:55 2004 +0900 @@ -2234,19 +2234,9 @@ char *crn; use_int(creg); crn = register_name(creg); - if (byte==1) { - printf("\tlbz %s,%d(%s)\n",register_name(creg),n, + printf("\t%s %s,%d(%s)\n",cload(byte),register_name(creg),n, register_name(xreg)); - if (sign) - printf("\textsb %s,%s\n",crn,crn); - } else if (byte==SIZE_OF_SHORT) { - printf("\tlhz %s,%d(%s)\n",register_name(creg),n, - register_name(xreg)); - if (sign) - printf("\textsh %s,%s\n",crn,crn); - } else - printf("\tlwz %s,%d(%s)\n",register_name(creg),n, - register_name(xreg)); + cext(sign,byte,creg); } int
--- a/mc-codegen.c Thu May 06 11:38:56 2004 +0900 +++ b/mc-codegen.c Mon May 10 21:12:55 2004 +0900 @@ -339,7 +339,8 @@ 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 ADD: case SUB: case BAND: case EOR: case BOR: case CMP: case CMPGE: + case UCMP: case CMPEQ: case CMPNEQ: machinop(e1); return INT; #if FLOAT_CODE
--- a/mc.h Thu May 06 11:38:56 2004 +0900 +++ b/mc.h Mon May 10 21:12:55 2004 +0900 @@ -233,13 +233,16 @@ #define LAND 55 #define LOR 56 #define ASS 57 -#define CMPGE 58 -#define ASSOP 59 -#define COMMA 60 +#define UCMP 58 +#define CMPGE 59 +#define CMPEQ 60 +#define CMPNEQ 61 +#define ASSOP 62 +#define COMMA 63 -#define CASS 61 -#define CASSOP 62 -#define CUASSOP 63 +#define CASS 64 +#define CASSOP 65 +#define CUASSOP 66 #define SASS (SOP+CASS) #define SASSOP (SOP+CASSOP) @@ -290,13 +293,13 @@ #define LBOR (LOP+BOR) -#define STASS 64 +#define STASS 67 #define BINARY_ARGS(i) (MUL<=(i%SOP)&&(i%SOP)<=STASS) /* tarnary argments */ -#define COND 65 +#define COND 68 #define SCOND (SOP+COND) #define DCOND (DOP+COND) #define FCOND (FOP+COND) @@ -306,19 +309,19 @@ /* not appeared as tags */ -#define I2I 66 -#define I2U 67 -#define I2D 68 -#define I2F 69 -#define I2LL 70 -#define I2ULL 71 +#define I2I 69 +#define I2U 70 +#define I2D 71 +#define I2F 72 +#define I2LL 73 +#define I2ULL 74 -#define U2I 72 -#define U2U 73 -#define U2D 74 -#define U2F 75 -#define U2LL 76 -#define U2ULL 77 +#define U2I 75 +#define U2U 76 +#define U2D 77 +#define U2F 78 +#define U2LL 79 +#define U2ULL 80 #define D2I (DOP+I2I) #define D2U (DOP+I2U) @@ -348,17 +351,17 @@ #define ULL2LL (LOP+U2LL) #define ULL2ULL (LOP+U2ULL) -#define LPAR 78 -#define RPAR 79 -#define LBRA 80 -#define RBRA 81 -#define LC 82 -#define RC 83 -#define COLON 84 -#define SM 85 -#define PERIOD 86 -#define ARROW 87 -#define CNAME 88 +#define LPAR 81 +#define RPAR 82 +#define LBRA 83 +#define RBRA 84 +#define LC 85 +#define RC 86 +#define COLON 87 +#define SM 88 +#define PERIOD 89 +#define ARROW 90 +#define CNAME 91 /* tree node tags end */