Mercurial > hg > CbC > old > device
view mc-code-powerpc.c @ 283:230a3b98b843 mips-done
MIPS jump work.
author | kono |
---|---|
date | Mon, 24 May 2004 13:21:22 +0900 |
parents | affb054fe920 |
children | 912b54949344 |
line wrap: on
line source
/* Micro-C Code Generatation Part for Power PC (Mac OS X) */ /* $Id$ */ #define EXTERN extern #include "mc.h" #include "mc-code.h" #include "mc-codegen.h" char *l_include_path[] = { "/usr/include/", 0 }; #define TEXT_EMIT_MODE 0 #define DATA_EMIT_MODE 1 #define RODATA_EMIT_MODE 2 static void data_mode(char *name); static void text_mode(); 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 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 code_setup; static int r1_offset_label; static int lvar_offset_label; static int reg_save; static int freg_save; static int freg,ireg,lreg; 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 */ 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 #define REG_VAR_BASE 29 #define REG_VAR_MIN 18 #define MIN_TMP_REG 3 #define MAX_TMP_REG 11 #define PTRC_REG 3 #define FREG_VAR_BASE 31 #define FREG_VAR_MIN 20 #define MIN_TMP_FREG 1 #define MAX_TMP_FREG 14 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_LREGISTER_H 3 /* high word */ #define RET_LREGISTER_L 4 /* low word */ #define RET_LREGISTER LREG_OFFSET int MAX_INPUT_REGISTER_VAR = 11-MIN_TMP_REG; int MAX_CODE_INPUT_REGISTER_VAR = 11-MIN_TMP_REG; int MAX_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG; int MAX_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG; int MAX_CODE_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG; int MAX_CODE_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG; 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[] = { "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9", "r10","r11","r12","r13","r14","r15","r16","r17","r18","r19", "r20","r21","r22","r23","r24","r25","r26","r27","r28","r29", "r30","r31", "f0","f1","f2","f3","f4","f5","f6","f7","f8","f9", "f10","f11","f12","f13","f14","f15","f16","f17","f18","f19", "f20","f21","f22","f23","f24","f25","f26","f27","f28","f29", "f30","f31" }; #define round4(i) ((i+(SIZE_OF_INT-1))&~(SIZE_OF_INT-1)) #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)] 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_longlong_reg(i) (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER) #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; } #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; } #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; } static int use_double0() { int i = creg; if (!is_float_reg(i)) { if (lreg) { free_register(lreg); lreg = 0; } if (!freg) freg = get_dregister(1); else if (freg!=i) free_register(i); i = freg; } if (!regs[i]) regs[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 clear_ptr_cache_reg(int r); static void set_ireg(int,int); static void set_freg(int,int); static void set_lreg(int,int); static int max_func_args; static int my_func_args; #define ARG_LVAR_OFFSET 0x10000000 /* r0 return value etc. r3-r10 input register r22-r29 saved register variable (input register for code segement) r30 stack pointer r31 0 r1 frame pointer f0 return value etc. f1-r8 input register f24-f31 saved register variable function call stack frame <------r1_offset------------------------------> <------------lvar_offset-------> r+ +------------+---+---------------+----------+--------------+----+ - callee arg xx register save local caller arg xx reg_save disp max_func_args*SIZE_OF_INT lvar>0 lvar<0 lvar>0x1000 0000 code segment stack frame * gotoを呼び出した関数のr1 ! r1(goto前のr1) # * r30 <---r1_offset---------> r1 r+ +----------+--+----------+----------------+-----------+----------+----+ cousin arg xx reg save !callee arg !code local caller arg xx r20-r29 lvar>0 lvar<0 lvar>0x1000 000 f20-f31 <-my_func_args--><--disp-----><-max_func_arg-> *SIZE_OF_INT *SIZE_OF_INT */ int arg_offset = 24; int arg_offset1 = 24; int disp_offset = -12; // #define func_disp_offset 60 #define 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 #define CODE_CALLER_ARG (l-ARG_LVAR_OFFSET)+arg_offset1 #define FUNC_LVAR l+disp_offset #define CALLER_ARG (l-ARG_LVAR_OFFSET)+arg_offset1 #define CALLEE_ARG l+arg_offset void code_offset_set() { #if 0 int l; #endif int lvar_offsetv = -disp+max_func_args*SIZE_OF_INT+func_disp_offset; int r1_offsetv = -disp+max_func_args*SIZE_OF_INT-reg_save+r1_offset; printf(".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 = disp; printf("# offset lvarn\t%d %d\n",FUNC_LVAR+lvar_offsetv,disp); l = 0; printf("# offset lvar0\t%d\n",FUNC_LVAR+lvar_offsetv); l = -reg_save; printf("# offset regs\t%d\n",FUNC_LVAR+lvar_offsetv); printf("# offset r1off\t%d\n",r1_offsetv); l = 0; printf("# offset carg0\t%d\n",CALLEE_ARG+r1_offsetv); l = my_func_args; printf("# offset cargn\t%d %d\n",CALLEE_ARG+r1_offsetv,my_func_args); #endif } static void lvar8(int l) { if (fnptr->sc==CODE) { if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ printf("lo16(%d)(r1)\n",CODE_CALLER_ARG); } else printf("lo16(%d)(r30)\n",CODE_LVAR); } else if (l<0) { /* local variable */ printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label); } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ printf("lo16(%d)(r30)\n",CALLER_ARG); } else { /* callee's arguments */ printf("lo16(%d+L_%d)(r30)\n",CALLEE_ARG,r1_offset_label); } } /* if size of local variables / input variables is more then 64k, lo16 does not work. We have to use ha16 also. But we can't know the exact size in one path compile. We may safely use lvar16ha if disp or max_func_args > 32k. Of course this is reduantant for smaller offset. But who cares who use very large local variables? */ #define LARGE_LVAR (disp<-32765||max_func_args>32765) static void lvar16ha(int l) { if (fnptr->sc==CODE) { if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ printf("la r0,ha16(%d)(r1)\n",CODE_CALLER_ARG); } else printf("la r0,ha16(%d)(r30)\n",CODE_LVAR); } else if (l<0) { /* local variable */ printf("la r0,ha16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label); } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ if (CALLER_ARG>32765) printf("la r0,ha16(%d)(r30)\n",CALLER_ARG); } else { /* callee's arguments */ printf("la r0,ha16(%d+L_%d)(r30)\n",CALLEE_ARG,r1_offset_label); } } static void lvar16lo(int l) { if (fnptr->sc==CODE) { if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ printf("lo16(%d)(r0)\n",CODE_CALLER_ARG); } else printf("lo16(%d)(r0)\n",CODE_LVAR); } else if (l<0) { /* local variable */ printf("lo16(%d+L_%d)(r0)\n",FUNC_LVAR,lvar_offset_label); } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ if (CALLER_ARG>32765) printf("lo16(%d)(r0)\n",CALLER_ARG); else printf("lo16(%d)(r30)\n",CALLER_ARG); } else { /* callee's arguments */ printf("lo16(%d+L_%d)(r0)\n",CALLEE_ARG,r1_offset_label); } } #define lvar_intro(i) if (LARGE_LVAR) lvar16ha(i) #define lvar(i) if (LARGE_LVAR) lvar16lo(i); else lvar8(i) void code_lvar(int e2,int reg) { use_int(reg); lvar_intro(e2); printf("\tla %s,",register_name(reg)); lvar(e2); } void code_init(void) { macro_define("__ppc__ 1\n"); macro_define("__BIG_ENDIAN__ 1\n"); // macro_define("_BSD_CT_RUNE_T_ int\n"); macro_define("__STDC__ 1\n"); init_ptr_cache(); regv_l(RET_LREGISTER) = RET_LREGISTER_L; regv_h(RET_LREGISTER) = RET_LREGISTER_H; } void gexpr_code_init(void){ #if 0 int new_reg,old_reg,dm; /* register shuffling */ if (is_int_reg(creg)) { dm = get_register(); new_reg = get_register(); old_reg = creg; ireg = creg = new_reg; free_register(old_reg); free_register(dm); } else if (is_float_reg(creg)) { dm = get_dregister(1); new_reg = get_dregister(1); old_reg = creg; freg = creg = new_reg; free_register(old_reg); free_register(dm); } #endif } void code_gexpr(int e){ // if (is_int_reg(creg) && creg!=ireg) error(-1); } void code_arg_register(NMTBL *fnptr) { int args = fnptr->dsp; NMTBL *n; int reg_var = 0; int freg_var = 0; int type; int reg; int i; int is_code0 = is_code(fnptr); while (args) { /* process in reverse order */ n = (NMTBL*)caddr(args); type = n->ty; if (scalar(type)) { if ((reg = get_input_register_var(reg_var,n,is_code0))) { n->sc = REGISTER; n->dsp = cadr(reg); regs[n->dsp]= INPUT_REG; reg_var++; cadddr(args)=SIZE_OF_INT; } } else if (type==FLOAT) { if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) { n->sc = DREGISTER; n->dsp = cadr(reg); regs[n->dsp]= INPUT_REG; freg_var++; cadddr(args)=size(type); } } else if (type==DOUBLE) { if ((reg = get_input_dregister_var(freg_var,n,is_code0,1))) { n->sc = DREGISTER; n->dsp = cadr(reg); regs[n->dsp]= INPUT_REG; freg_var++; 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); } if (is_function(fnptr)) code_save_input_registers(); } int get_register(void) { /* 使われていないレジスタを調べる */ int i,j,reg; for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) { if (regs[i]) continue; /* 使われている */ regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ 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( (j=new_lvar(SIZE_OF_INT)),reg,0); reg_stack[i]= j-REG_LVAR_OFFSET; return reg; } } #if LONGLONG_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(); } } #endif for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { reg =REG_VAR_BASE-i; if (! regs[reg]) { /* 使われていないなら */ regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */ if (i>max_reg_var) max_reg_var=i; return reg; /* その場所を表す番号を返す */ } } /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ error(HPERR); return creg; } #if 0 int get_register(void) { int i = get_register0(); printf("# get_register %d\n",i); return i; } #endif int pop_register(void) { /* レジスタから値を取り出す */ return reg_stack[--reg_sp]; } #if FLOAT_CODE int get_dregister(int d) { /* 使われていないレジスタを調べる */ int i,reg; for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) { if (regs[i]) continue; /* 使われている */ regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ return i; /* その場所を表す番号を返す */ } /* search register stack */ for(i=0;i<freg_sp;i++) { if ((reg=freg_stack[i])>=0) { code_dassign_lvar( (freg_stack[i]=new_lvar(SIZE_OF_DOUBLE)),reg,1); freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; return reg; } } for(i=0;i<FREG_VAR_BASE-REG_VAR_MIN;i++) { reg =FREG_VAR_BASE-i+FREG_OFFSET; if (! regs[reg]) { /* 使われていないなら */ regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */ if (i>max_freg_var) max_freg_var=i; return reg; /* その場所を表す番号を返す */ } } /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ error(REG_ERR); return freg; } #if 0 int get_dregister(int d) { 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 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; } int 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) { int i,j,ll; int max_reg_var_save=max_reg_var; ll = get_lregister0(); if (ll==-1) goto not_found; 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)); } void emit_pop_free(int xreg) { if (xreg>=0) free_register(xreg); } void free_register(int i) { /* いらなくなったレジスタを開放 */ // 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; } } int get_input_dregister_var(int i,NMTBL *n,int is_code,int d) { 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(DREGISTER,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<REG_VAR_BASE-REG_VAR_MIN)) return 0; i = REG_VAR_BASE-i; } else { if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; i = i+MIN_TMP_REG; } regv_h(ll)=i; regv_l(ll)=i+1; } else { error(-1); ll=LREG_OFFSET+2; } return list3(LREGISTER,ll,(int)n); } int get_input_register_var(int i,NMTBL *n,int is_code) { if (is_code) { if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; i = REG_VAR_BASE-i; } else { if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; i = i+MIN_TMP_REG; } return list3(REGISTER,i,(int)n); } /* double register case? */ int get_input_register_var_1(int i,NMTBL *n,int is_code) { if (is_code) { if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; i = REG_VAR_BASE-i; } else { if (i<0||i>=MAX_INPUT_REGISTER_VAR+1) return 0; i = i+MIN_TMP_REG; } return list3(REGISTER,i,(int)n); } int free_register_count(int d) { int i,count,fcount; fcount = count = 0; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i]) count++; } for(i=0;i<MAX_FREGISTER;i++) { if (! regs[i+FREG_OFFSET]) fcount++; } printf("# free reg %d freg %d\n",count,fcount); return d?fcount:count; } #if 0 static int register_full(void) { int i; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i]) { return 0; } } 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; } #if FLOAT_CODE freg = get_dregister(1); set_freg(FREG_FREGISTER,0); #endif ireg = creg = get_register(); set_ireg(CREG_REGISTER,0); return; } void register_usage(char *s) { #if 1 int i,j; #endif #define USAGE_MAX 4 if (chk) return; if (!lsrc) return; printf("# %d: %s:",lineno,s); 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 for(j=0,i=0;i<MAX_REGISTER;i++) if (regs[i]) j++; if (j>USAGE_MAX) { printf("\n# regs:"); for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); } } if (reg_sp>0) { printf(" stack "); for(i=reg_sp;i>0;i--) { if(reg_stack[i-1]>=0) { printf(" %s",register_name(reg_stack[i-1])); } else printf(",%d",reg_stack[i-1]); } } for(j=0,i=0;i<MAX_FREGISTER;i++) if (regs[i+FREG_OFFSET]) j++; if (j>USAGE_MAX) { printf("\n# freg:"); for(i=0;i<MAX_FREGISTER;i++) { printf("%d",regs[i+FREG_OFFSET]); } } if (freg_sp>0) { printf(" fstack "); for(i=freg_sp;i>0;i--) { if(freg_stack[i-1]>=0) { printf(" %s",fregister_name(freg_stack[i-1])); } else printf(",%d",freg_stack[i-1]); } } for(j=0,i=0;i<REAL_MAX_LREGISTER;i++) if (regs[i+LREG_OFFSET]) j++; if (j>USAGE_MAX) { printf("\n# lreg:"); for(i=0;i<REAL_MAX_LREGISTER;i++) { printf("%d",regs[i+LREG_OFFSET]); } } if (lreg_sp>0) { printf(" lstack "); for(i=lreg_sp;i>0;i--) { if(lreg_stack[i-1]>=0) { printf(" %s",lregister_name_high(lreg_stack[i-1])); printf(",%s",lregister_name_low(lreg_stack[i-1])); } else printf(",%d",lreg_stack[i-1]); } } #endif printf("\n"); } #if 0 void register_usage(char *s) { #if 1 int i; #endif if (chk) return; if (!lsrc) return; printf("# %d: %s:",lineno,s); 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:"); 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]); } 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"); } #endif void gexpr_init(void) { while(reg_sp > 0) { free_register(reg_stack[--reg_sp]); } while(freg_sp > 0) { free_register(freg_stack[--freg_sp]); } while(lreg_sp > 0) { free_register(lreg_stack[--lreg_sp]); } use_int0(); text_mode(); gexpr_code_init(); register_usage("gexpr_init"); } void emit_init(void) { free_all_register(); max_reg_var=-1; max_freg_var=-1; reg_sp = 0; freg_sp = 0; text_mode(); } int get_register_var(NMTBL *n) { int i; for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { if (! regs[REG_VAR_BASE-i]) { /* 使われていないなら */ /* そのレジスタを使うことを宣言し */ regs[REG_VAR_BASE-i]=USING_REG; if (i>max_reg_var) max_reg_var=i; /* その場所を表す番号を返す */ return list3(REGISTER,REG_VAR_BASE-i,(int)n); } } return list2(LVAR,new_lvar(SIZE_OF_INT)); } int get_dregister_var(NMTBL *n,int d) { int 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(DREGISTER, FREG_VAR_BASE-i+FREG_OFFSET,(int)n); } } return list2(LVAR,new_lvar(SIZE_OF_DOUBLE)); } void emit_push() { int new_reg; if (!is_int_reg(creg)) error(-1); if (reg_sp>MAX_MAX) error(-1); new_reg = get_register(); /* 絶対に取れる */ reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ ireg = creg = new_reg; } int emit_pop(int type) { int xreg,reg; xreg=pop_register(); if (xreg<= -REG_LVAR_OFFSET) { reg = get_register(); code_rlvar(REG_LVAR_OFFSET+xreg,reg); free_lvar(REG_LVAR_OFFSET+xreg); xreg = reg; } return xreg; } 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); if (nptr->sc==STATIC) { printf("\taddis %s,r31,ha16(_%s-L_%d)\n", rrn,nptr->nm,code_base); printf("\tla %s,lo16(_%s-L_%d)(%s)\n", rrn,nptr->nm,code_base,rrn); } else { printf("\taddis %s,r31,ha16(L_%s$non_lazy_ptr-L_%d)\n", rrn,nptr->nm,code_base); printf("\tlwz %s,lo16(L_%s$non_lazy_ptr-L_%d)(%s)\n", rrn,nptr->nm,code_base,rrn); } return r; } static char *cload(int sz) { return sz==1?"lbz":sz==SIZE_OF_SHORT?"lhz":"lwz"; } static char *cstore(int sz) { return sz==1?"stb":sz==SIZE_OF_SHORT?"sth":"stw"; } static void cext(int sign,int sz,int reg) { char *crn = register_name(reg); if (sign) { if (sz==1) printf("\textsb %s,%s\n",crn,crn); else if (sz==SIZE_OF_SHORT) printf("\textsh %s,%s\n",crn,crn); } else { if (sz==1) printf("\trlwinm %s,%s,0,0xff\n",crn,crn); else if (sz==SIZE_OF_SHORT) printf("\trlwinm %s,%s,0,0xffff\n",crn,crn); } } void code_label(int labelno) { clear_ptr_cache(); printf("L_%d:\n",labelno); } void code_gvar(int e1,int reg) { int r; use_int(reg); r = get_ptr_cache((NMTBL*)cadr(e1)); if(r!=reg) printf("\tmr %s,%s\n",register_name(reg),register_name(r)); return; } void code_rgvar(int e1,int reg) { use_int(reg); printf("\tlwz %s,0(%s)\n",register_name(reg), register_name(get_ptr_cache((NMTBL*)cadr(e1)))); } void 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),crn, register_name(get_ptr_cache((NMTBL*)cadr(e1)))); cext(sign,sz,reg); } void code_register(int e2,int reg) { use_int(reg); if (reg!=e2) printf("\tmr %s,%s\n",register_name(reg),register_name(e2)); } void code_rlvar(int e2,int reg) { use_int(reg); lvar_intro(e2); printf("\tlwz %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),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("\tmr %s,%s\n",register_name(reg),register_name(r)); return; } void code_const(int e2,int reg) { char *crn; use_int(reg); crn = register_name(reg); if (-32768<e2&&e2<32768) printf("\tli %s,%d\n",crn,e2); else { printf("\tlis %s,ha16(%d)\n",crn,e2); printf("\taddi %s,%s,lo16(%d)\n",crn,crn,e2); } } void code_neg(int creg) { use_int(creg); printf("\tneg %s,%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)); } void code_lnot(int creg) { use_int(creg); printf("\tsubfic r0,%s,0\n", register_name(creg)); printf("\tadde %s,r0,%s\n", register_name(creg),register_name(creg)); } void code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) { char *xrn,*drn; if (car(e2)==REGISTER) { use_int(reg); printf("\taddi %s,%s,%d\n", register_name(cadr(e2)),register_name(cadr(e2)), dir); if (cadr(e2)!=reg) printf("\tmr %s,%s\n",register_name(reg),register_name(cadr(e2))); return; } g_expr(e2); if (!is_int_reg(creg)) error(-1); xrn = register_name(creg); 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),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); } void code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) { char *xrn,*crn,*nrn; int nreg; if (car(e2)==REGISTER) { use_int(reg); printf("\tmr %s,%s\n",register_name(reg),register_name(cadr(e2))); printf("\taddi %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); nreg=get_register(); if (!nreg) error(-1); nrn = register_name(nreg); 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),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); free_register(nreg); } void code_return(int creg) { char *crn; use_int(creg); crn = register_name(creg); printf("\taddis %s,r31,ha16(L_%d-L_%d)\n",crn,retcont,code_base); printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",crn,retcont,code_base,crn); } #define R1SAVE 1 void code_environment(int creg) { /* save frame pointer */ use_int(creg); #if R1SAVE printf("\tlwz %s,0(r1)\n",register_name(creg)); #else int l = 0; printf("\tla %s,",register_name(creg)); printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label); #endif } void code_bool(int e1,int reg) { char *xrn; int e2,e3; b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ use_int(reg); xrn = register_name(reg); printf("\tli %s,0\n",xrn); jmp(e3=fwdlabel()); fwddef(e2); printf("\tli %s,1\n",xrn); fwddef(e3); } char * code_gt(int cond) { return (cond?"gt":"le"); } char * code_ugt(int cond) { return (cond?"gt":"le"); } char * code_ge(int cond) { return (cond?"ge":"lt"); } char * code_uge(int cond) { return (cond?"ge":"lt"); } char * code_eq(int cond) { return (cond?"eq":"ne"); } static int cmpflag = 0; static void inc_cmpflag() { cmpflag = (cmpflag+1)%7; } void 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),crn,register_name(r)); cext(0,sz,r); printf("\tcmpwi cr%d,%s,0\n",cmpflag,crn); } void 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),crn); lvar(e2); cext(0,sz,reg); code_cmp_register(reg); } void 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("\tlwz %s,0(%s)\n",crn,register_name(r)); code_cmp_register(reg); } void code_cmp_rlvar(int e2,int reg) { char *crn; use_int(reg); crn = register_name(reg); lvar_intro(e2); printf("\tlwz %s,",crn); lvar(e2); code_cmp_register(reg); } void code_cmp_register(int e2) { use_int(e2); printf("\tcmpwi cr%d,%s,0\n",cmpflag,register_name(e2)); } void ascii(char *s) { printf("\t.ascii \""); while(*s) { if (*s=='\n') printf("%cn",92); else if (*s<' ') printf("%c%03o",92,*s); else if (*s=='\\') printf("\\\\"); else if (*s==34) printf("%c%c",92,34); else printf("%c",*s); s++; } printf("\\0%c\n\t.align 2\n",34); } void code_string(int e1,int creg) { char *s,*crn; int lb; use_int(creg); crn = register_name(creg); s=(char *)cadr(e1); printf(".data\t\n.cstring\n\t.align 2\n"); lb=fwdlabel(); printf("L_%d:\n",lb); ascii(s); if (output_mode==TEXT_EMIT_MODE) { printf(".text\n"); } else { text_mode(); } printf("\taddis %s,r31,ha16(L_%d-L_%d)\n",crn,lb,code_base); printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",crn,lb,code_base,crn); } #define MAX_COPY_LEN 20 void emit_copy(int from,int to,int length,int offset,int value,int det) { 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 1: case -1: printf("\tlbz %s,%d(%s)\n",drn,offset,frn); printf("\tstb %s,%d(%s)\n",drn,offset,trn); break; case 2: case -2: printf("\tlhz %s,%d(%s)\n",drn,offset,frn); printf("\tsth %s,%d(%s)\n",drn,offset,trn); break; case 4: case -4: printf("\tlwz %s,%d(%s)\n",drn,offset,frn); printf("\tstw %s,%d(%s)\n",drn,offset,trn); break; default: if (length <0) { if (length > -MAX_COPY_LEN) { for(;length<=-4;length+=4,offset-=4) emit_copy(from,to,-4,offset-4,0,det); for(;length<=-2;length+=2,offset-=2) emit_copy(from,to,-2,offset-2,0,det); if(length<0) emit_copy(from,to,length,offset-1,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 r5,%d\n",length); printf("\tmr r4,%s\n",frn); printf("\tmr r3,%s\n",trn); /* overrap must be allowed */ printf("\tbl L_%s$stub\n",memmove); extern_define(memmove,0,FUNCTION,1); fix=0; 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; ireg=to; } } free_register(dreg); } int struct_push(int e4,int t,int arg) { int length,count; int dreg,sreg; char *drn,*crn,*srn; g_expr(e4); if (!is_int_reg(creg)) error(-1); length=size(t); if(length%SIZE_OF_INT) { length += SIZE_OF_INT - (length%SIZE_OF_INT); } dreg = get_register(); if (!dreg) error(-1); drn = register_name(dreg); crn = register_name(creg); if (length<MAX_COPY_LEN) { sreg = get_register(); if (!sreg) error(-1); srn = register_name(sreg); code_lvar(cadr(arg),dreg); for(count=0;count<length;count+=SIZE_OF_INT) { printf("\tlwz %s,%d(%s)\n",srn,count,crn); printf("\tstwu %s,%d(%s)\n",srn,count,drn); } free_register(sreg); free_register(dreg); return length/SIZE_OF_INT; } else { code_lvar(cadr(arg),dreg); /* downward direction copy */ emit_copy(creg,dreg,length,0,0,1); } free_register(dreg); return length/SIZE_OF_INT; } void set_ireg(int reg,int mode) { if (!is_int_reg(reg)) error(-1); if (reg!=creg) { clear_ptr_cache_reg(reg); if (ireg && reg!=ireg ) { free_register(ireg); if (mode) { printf("\tmr %s,%s\n",register_name(reg),register_name(ireg)); } } free_register(creg); regs[reg]=USING_REG; } creg = ireg = reg; } void set_freg(int reg,int mode) { if (!is_float_reg(reg)) error(-1); if (reg!=creg) { if (freg && reg!=freg) { free_register(freg); if (mode) { printf("\tfmr %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("\tmr %s,%s\n", lregister_name_low(reg),lregister_name_low(lreg)); printf("\tmr %s,%s\n", lregister_name_high(reg),lregister_name_high(lreg)); } free_register(lreg); } free_register(creg); 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; } creg = lreg = reg; } 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)!=3) printf("\tmr r3,%s\n", lregister_name_high(reg)); if (regv_l(reg)!=4) printf("\tmr r4,%s\n", lregister_name_low(reg)); } } void set_lreg_operand1(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)!=5) printf("\tmr r5,%s\n", lregister_name_high(reg)); if (regv_l(reg)!=6) printf("\tmr r6,%s\n", lregister_name_low(reg)); } } void use_reg(int arg) { // 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; } } void code_save_input_registers() { int args; NMTBL *n; int reg; int tag; int lvar; int t; /* fnptr->dsp=list4(type,fnptr->dsp,(int)n,0); */ int reg_offset = 0; int offset = 0; for(args = fnptr->dsp;args;args = cadr(args)) { n = (NMTBL *)caddr(args); tag = n->sc; reg = n->dsp; if (!n||n==&null_nptr) error(REG_ERR); if (tag==REGISTER) { /* regs[reg]==INPUT_REG case should be considered */ n->dsp = offset; offset+=SIZE_OF_INT; t = INT; reg += reg_offset; /* for duplicated floating point argument */ } else if (tag==DREGISTER) { /* 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==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; } 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||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==LLSHIFT||e3==LULSHIFT||e3==LRSHIFT||e3==LURSHIFT|| e3==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD||e3==LASSOP; } static int simple_arg(int e3) { return !contains_p(e3,not_simple_p); } int caller_arg_offset_v(int arg) { 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&®s[regv_h(lreg)]==USING_REG) { 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&®s[regv_l(lreg)]==USING_REG) { 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_float_reg(reg)) { if (freg&® == freg) { if (creg==freg) creg = 0; freg = 0; } } if (mode) use_reg(reg); } static int compute_complex_arg(int e3,int reg_arg_list,int arg) { int t=caddr(e3); int e4 = car(e3); reg_arg_list = list2(arg,reg_arg_list); g_expr_u(assign_expr0(arg,e4,t,t)); if (car(arg)==REGISTER||car(arg)==DREGISTER|| car(arg)==FREGISTER||car(arg)==LREGISTER) use_input_reg(cadr(arg),1); car(e3) = arg; return reg_arg_list; } static void increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) { int nargs=0,reg_arg=0,freg_arg=0; int t=caddr(e3); if(scalar(t)) { nargs ++ ; reg_arg++; } else if (t==LONGLONG||t==ULONGLONG) { nargs ++ ; reg_arg++; nargs ++ ; reg_arg++; } else if (t==DOUBLE||t==FLOAT) { if (*preg_arg<MAX_INPUT_REGISTER_VAR) { reg_arg += 2; } freg_arg++; nargs += size(t)/SIZE_OF_INT; } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { nargs += round4(size(t))/SIZE_OF_INT; } else { error(TYERR); nargs ++ ; } *pnargs += nargs; *preg_arg += reg_arg; *pfreg_arg += freg_arg; } #define AS_SAVE 1 #define AS_ARG 0 static int get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg) { if(scalar(t)) { if (mode==AS_SAVE) { return get_register_var(0); } else if (reg_arg>=MAX_INPUT_REGISTER_VAR) { return list2(LVAR,caller_arg_offset_v(nargs)); } else return get_input_register_var(reg_arg,0,0); } else if (t==LONGLONG||t==ULONGLONG) { if (mode==AS_SAVE) { return get_lregister_var(0); } else if (reg_arg+1>=MAX_INPUT_REGISTER_VAR) { return list2(LVAR,caller_arg_offset_v(nargs)); } else return get_input_lregister_var(reg_arg,0,0); } else if (t==FLOAT) { if (mode==AS_SAVE) { return get_dregister_var(0,0); } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { return list2(LVAR,caller_arg_offset_v(nargs)); } else return get_input_dregister_var(freg_arg,0,0,0); } else if (t==DOUBLE) { if (mode==AS_SAVE) { return get_dregister_var(0,1); } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { return list2(LVAR,caller_arg_offset_v(nargs)); } else return get_input_dregister_var(freg_arg,0,0,1); } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { if (mode==AS_SAVE) { return get_register_var(0); } else return list2(LVAR,caller_arg_offset_v(nargs)); } else { error(-1); return get_register_var(0); } } int function(int e1) { 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 complex_; int pnargs,preg_arg,pfreg_arg; int stargs; special_lvar = -1; ret_type = cadr(cadddr(e1)); if (ret_type==CHAR) ret_type=INT; /* check argments type is DOTS? */ t = caddr(cadddr(e1)); if (t==0 || t==DOTS) dots = 1; else { dots = 0; for(t = caddr(cadddr(e1));t;t = cadr(t)) { if (car(t)==DOTS) dots = 1; } } e2 = cadr(e1); if (car(e2) == FNAME) { fn=(NMTBL *)cadr(e2); } else { jmp = get_register_var(0); if (car(jmp)!=REGISTER) error(-1); reg_arg_list = list2(jmp,reg_arg_list); g_expr(e2); if (!is_int_reg(creg)) error(-1); code_register(creg,cadr(jmp)); /* g_expr(assign_expr0(jmp,e2,INT,INT)); functions are lvalue */ } /* first we execute complex argument to avoid interaction with input variables */ stargs = 0; complex_ = 0; nargs = reg_arg = freg_arg = 0; for (e3 = e1 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { t=caddr(e3); if ((e5= !simple_arg(car(e3)))) { if (complex_) { arg = get_input_arg(caddr(complex_),AS_SAVE, pnargs,preg_arg,pfreg_arg); reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); } pnargs=nargs;preg_arg=reg_arg;pfreg_arg=freg_arg; complex_ = e3; } if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { // The struct should be pushed after complex arguments. if (e5) { // compute address only, complex_ is me now. Clear it. complex_ = 0; e4 = car(e3); if (car(e4)!=RSTRUCT) error(-1); if (!simple_arg(cadr(e4))) { // Calculate complex struct address here. // If simple, leave it. arg = get_register_var(0); g_expr_u(assign_expr0(arg,list2(ADDRESS,car(e3)),INT,INT)); car(e3)=arg; reg_arg_list = list2(arg,reg_arg_list); if (car(arg)==REGISTER) use_input_reg(cadr(arg),1); } } stargs = list4(e3,stargs,nargs,reg_arg); } increment_function_arg(e3,&nargs,®_arg,&freg_arg); } /* now all input register vars are free */ code_save_stacks(); // set_lreg(LREG_LREGISTER,0); set_freg(FREG_FREGISTER,0); set_ireg(CREG_REGISTER,0); // Struct arguments need emit_copy. it destructs 3 input registers. // But it returns no value on a register. So calcurate it here. // We cannot do this in the previous loop, because the copied struct may be // override by other complex arguments. But bofore this we have to check // complex_. if (stargs) { if (complex_) { arg = get_input_arg(caddr(complex_),AS_SAVE, pnargs,preg_arg,pfreg_arg); reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); } for(stargs=reverse0(stargs);stargs;stargs = cadr(stargs)) { e3 = car(stargs); e4 = car(e3); t = caddr(e3); arg = get_input_arg(t,AS_ARG,caddr(stargs),cadddr(stargs),0); struct_push(e4,t,arg); car(e3)=0; // done } } else { // last complex argument can use input register if (complex_) { arg = get_input_arg(caddr(complex_),AS_ARG,pnargs,preg_arg,pfreg_arg); reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); } } nargs = reg_arg = freg_arg = arg_assign = 0; // calc stack arguments first, it may requires extra registers, // and we can still use input registers now. for (e3 = e1; e3; increment_function_arg(e3,&nargs,®_arg,&freg_arg), e3 = cadr(e3)) { if (!(e4=car(e3))) continue; t=caddr(e3); arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg); if (car(arg)!=LVAR) continue; g_expr_u(assign_expr0(arg,e4,t,t)); if (t==LONGLONG||t==ULONGLONG) { if (reg_arg+1==MAX_INPUT_REGISTER_VAR) { // half register, half memory case arg_assign = list2( assign_expr0(r0=get_input_register_var(reg_arg,0,0), arg,INT,INT), arg_assign); use_input_reg(cadr(r0),1); } } car(e3)=0; // done } nargs = reg_arg = freg_arg = 0; for (e3 = e1; e3; increment_function_arg(e3,&nargs,®_arg,&freg_arg), e3 = cadr(e3)) { if (!(e4=car(e3))) continue; t=caddr(e3); arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg); if(scalar(t)) { 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)); } else if (t==LONGLONG||t==ULONGLONG) { if (reg_arg+1==MAX_INPUT_REGISTER_VAR) { // half register, half memory case // put whole long long anyway arg_assign = list2( assign_expr0(r0=get_input_register_var(reg_arg,0,0), arg,INT,INT), arg_assign); use_input_reg(cadr(r0),1); } else { if (car(arg)==LREGISTER) use_input_reg(cadr(arg),1); } reg_arg_list = list2(arg,reg_arg_list); g_expr_u(assign_expr0(arg,e4,t,t)); } else if (t==DOUBLE||t==FLOAT) { if (reg_arg<MAX_INPUT_REGISTER_VAR) { /* sigh... printf requies floating value in integer registers */ if (dots) { if (car(e4)==DRLVAR) { special_lvar = cadr(e4); e5 = list2(LVAR,special_lvar); } else { special_lvar = new_lvar(SIZE_OF_DOUBLE); g_expr(assign_expr0( (e5=list2(LVAR,special_lvar)),e4,DOUBLE,t)); reg_arg_list = list2(e5,reg_arg_list); e4 = list2(DREGISTER,freg); /* freg should not change until XXX */ } r0=get_input_register_var(reg_arg,0,0); r1 = reg_arg+1+MIN_TMP_REG; if (regs[r1]==PTRC_REG) clear_ptr_cache_reg(list2(REGISTER,r1)); /* else if (regs[r1]) error(-1); */ r1=get_input_register_var_1(reg_arg+1,0,0); use_input_reg(cadr(r0),1); /* protect from input register free */ use_input_reg(cadr(r1),1); /* protect from input register free */ reg_arg_list = list2(r0,reg_arg_list); reg_arg_list = list2(r1,reg_arg_list); arg_assign = list2( assign_expr0(r0,e5,INT,INT), arg_assign); arg_assign = list2( assign_expr0(r1, list2(LVAR,special_lvar+SIZE_OF_INT), INT,INT), arg_assign); } } if (dots && freg_arg>=4 && freg_arg<MAX_INPUT_DREGISTER_VAR) { /* oh my god! it requies integer register and floating register and stack value. You are crazy. */ arg_assign = list2( assign_expr0(list2(LVAR,caller_arg_offset_v(nargs)), get_input_dregister_var(freg_arg,0,0,1),t,t), arg_assign); } reg_arg_list = list2(arg,reg_arg_list); if (car(arg)==DREGISTER) use_input_reg(cadr(arg),1); /* protect from input register free */ g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */ } // structs are finished } if (max_func_args<nargs) max_func_args=nargs; 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); } else { jrn = register_name(cadr(jmp)); printf("\tmtctr %s\n",jrn); printf("\tbctrl\n"); } 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 ||car(arg)==LREGISTER) free_register(cadr(arg)); else if (car(arg)==LVAR&&cadr(arg)<0) free_lvar(cadr(arg)); } 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_ireg(RET_REGISTER,0); } return ret_type; } void code_frame_pointer(int e3) { use_int(e3); #if R1SAVE printf("\tmr r1,%s\n",register_name(e3)); #else printf("\tmr r30,%s\n",register_name(e3)); #endif } void code_fix_frame_pointer(int disp_offset) { int l = 0; printf("\tla r30,"); printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label); } void code_jmp(char *s) { max_reg_var = REG_VAR_BASE-REG_VAR_MIN; max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; printf("\tb L_%s$stub\n",s); control=0; } void 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("\tmtctr %s\n",register_name(e2)); printf("\tbctr\n"); control=0; } int code_rindirect(int e1, int reg,int offset, int us) { char *crn,*rrn; g_expr(e1); if (!is_int_reg(creg)) error(-1); crn=register_name(creg); use_int(reg); rrn=register_name(reg); printf("\tlwz %s,%d(%s)\n",rrn,offset,crn); return us?UNSIGNED:INT; } int code_crindirect(int e1, int reg,int offset, int sign) { char *crn,*rrn; g_expr(e1); if (!is_int_reg(creg)) error(-1); crn=register_name(creg); use_int(reg); rrn=register_name(reg); printf("\tlbz %s,%d(%s)\n",rrn,offset,crn); if (sign) { cext(sign,1,reg); return CHAR; } return UCHAR; } int code_srindirect(int e1, int reg,int offset, int sign) { char *crn,*rrn; g_expr(e1); if (!is_int_reg(creg)) error(-1); crn=register_name(creg); use_int(reg); rrn = register_name(reg); printf("\tlhz %s,%d(%s)\n",rrn,offset,crn); if (sign) { cext(sign,SIZE_OF_SHORT,reg); return SHORT; } return USHORT; } #if FLOAT_CODE int code_drindirect(int e1, int reg,int offset, int d) { char *crn; 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 d?DOUBLE:FLOAT; } #endif static void lload(int creg,int reg,int offset) { char *crn = register_name(creg); if (creg!=regv_h(reg)) { printf("\tlwz %s,%d(%s)\n",lregister_name_high(reg),offset,crn); printf("\tlwz %s,%d(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn); } else { printf("\tlwz %s,%d(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn); printf("\tlwz %s,%d(%s)\n",lregister_name_high(reg),offset,crn); } } #if LONGLONG_CODE int code_lrindirect(int e1, int reg, int offset, int us) { char *crn; int creg0; g_expr(e1); if (!is_int_reg(creg)) error(-1); crn=register_name(creg0=creg); use_longlong(reg); lload(creg0,reg,offset); return us?ULONGLONG:LONGLONG; } #endif void code_assign_gvar(int e2,int creg,int byte) { 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("\tstb %s,",crn); } else if (byte==SIZE_OF_SHORT) { printf("\tsth %s,",crn); } else { printf("\tstw %s,",crn); } lvar(e2); } void code_assign_register(int e2,int byte,int creg) { use_int(creg); if (e2!=creg) printf("\tmr %s,%s\n",register_name(e2),register_name(creg)); } void code_assign(int e2,int byte,int creg) { char *drn; char *crn; use_int(e2); drn=register_name(e2); use_int(creg); crn=register_name(creg); if (byte==1) { printf("\tstb %s,0(%s)\n",crn,drn); } else if (byte==SIZE_OF_SHORT) { printf("\tsth %s,0(%s)\n",crn,drn); } else { printf("\tstw %s,0(%s)\n",crn,drn); } } void 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 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 */ printf("# assop\n\tmr %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); if (byte==1) { printf("\tstb %s,0(%s)\n",crn,drn); } else if (byte==SIZE_OF_SHORT) { printf("\tsth %s,0(%s)\n",crn,drn); } else { printf("\tstw %s,0(%s)\n",crn,drn); } free_register(edx); emit_pop_free(xreg); } void tosop(int op,int creg,int oreg) { int dx = -1; int ox = -1; char *orn,*crn,*drn; // creg = creg op oreg use_int(creg); if(oreg==-1) { error(-1); } else if (oreg<= -REG_LVAR_OFFSET) { ox = get_register(); if (ox<0) error(-1); code_rlvar(oreg+REG_LVAR_OFFSET,ox); oreg = ox; } switch(op) { case LSHIFT: case ULSHIFT: shift("slw",creg,oreg); if(ox!=-1) free_register(ox); return; case RSHIFT: shift("sraw",creg,oreg); if(ox!=-1) free_register(ox); return; case URSHIFT: shift("srw",creg,oreg); if(ox!=-1) free_register(ox); return; } orn = register_name(oreg); crn = register_name(creg); switch(op) { case ADD: printf("\tadd %s,%s,%s\n",crn,crn,orn); break; case SUB: printf("\tsub %s,%s,%s\n",crn,crn,orn); break; case CMP: printf("\tcmpw cr%d,%s,%s\n",cmpflag,crn,orn); break; case UCMP: printf("\tcmplw cr%d,%s,%s\n",cmpflag,crn,orn); break; case BAND: printf("\tand %s,%s,%s\n",crn,crn,orn); break; case EOR: printf("\txor %s,%s,%s\n",crn,crn,orn); break; case BOR: printf("\tor %s,%s,%s\n",crn,crn,orn); break; case MUL: printf("\tmullw %s,%s,%s\n",crn,crn,orn); break; case UMUL: printf("\tmullw %s,%s,%s\n",crn,crn,orn); break; case DIV: printf("\tdivw %s,%s,%s\n",crn,crn,orn); break; case UDIV: printf("\tdivwu %s,%s,%s\n",crn,crn,orn); break; case MOD: dx=get_register(); drn = register_name(dx); printf("\tdivw %s,%s,%s\n",drn,crn,orn); printf("\tmullw %s,%s,%s\n",drn,drn,orn); printf("\tsubf %s,%s,%s\n",crn,drn,crn); break; case UMOD: dx=get_register(); drn = register_name(dx); printf("\tdivwu %s,%s,%s\n",drn,crn,orn); printf("\tmullw %s,%s,%s\n",drn,drn,orn); printf("\tsubf %s,%s,%s\n",crn,drn,crn); break; default: error(-1); } if(dx!=-1) free_register(dx); if(ox!=-1) free_register(ox); } int code_const_op_p(int op,int v) { if (car(v)!=CONST) return 0; if (op==BAND||op==DIV||op==UDIV||op==MOD||op==UMOD) return 0; v = cadr(v); return (-32766<v&&v<32767); } void 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("\tslwi %s,%s,%d\n",crn,crn,v); return; case RSHIFT: printf("\tsrawi %s,%s,%d\n",crn,crn,v); return; case URSHIFT: printf("\tsrwi %s,%s,%d\n",crn,crn,v); return; case ADD: printf("\taddi %s,%s,lo16(%d)\n",crn,crn,v); break; case SUB: printf("\taddi %s,%s,lo16(-%d)\n",crn,crn,v); break; case CMP: printf("\tcmpwi cr%d,%s,lo16(%d)\n",cmpflag,crn,v); break; case EOR: printf("\txori %s,%s,lo16(%d)\n",crn,crn,v); break; case BOR: printf("\tori %s,%s,lo16(%d)\n",crn,crn,v); break; case MUL: printf("\tmulli %s,%s,lo16(%d)\n",crn,crn,v); break; case UMUL: printf("\tmulli %s,%s,lo16(%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; use_int(creg); crn = register_name(creg); printf("\t%s %s,%d(%s)\n",cload(byte),register_name(creg),n, register_name(xreg)); cext(sign,byte,creg); } int code_csvalue() { return creg; } void code_cmpdimm(int e, int csreg) { /* used in dosiwtch() */ if(chk) return; printf("\tcmpwi cr%d,%s,%d\n",cmpflag,register_name(csreg),e); } void code_opening(char *filename) { printf("\t.file \"%s\"\n",filename); /* printf("\t.version\t\"01.01\"\n"); */ /* printf("gcc2_compiled.:\n"); */ printf(".text\n"); } void rexpr(int e1, int l1, int cond,int t) { char *s; switch(car(e1)) { case GT: s=code_gt(cond); break; case UGT: s=code_ugt(cond); break; case GE: s=code_ge(cond); break; case UGE: s=code_uge(cond); break; case LT: s=code_ge(!cond); break; case ULT: s=code_uge(!cond);break; case LE: s=code_gt(!cond); break; case ULE: s=code_ugt(!cond);break; case EQ: s=code_eq(cond); break; case NEQ: s=code_eq(!cond); break; default: error(-1); } g_expr(list3((t==INT?CMP:UCMP),cadr(e1),caddr(e1))); printf("\tb%s cr%d,L_%d\n",s,cmpflag,l1); } void jcond(int l, char cond) { if (chk) return; printf("\tb%s cr%d,L_%d\n",cond?"ne":"eq",cmpflag,l); } void jmp(int l) { control=0; if (chk) return; printf("\tb\tL_%d\n",l); } void gen_comment(char *s) { if (chk) return; printf("## %s",s); } void code_enter(char *name) { if (output_mode!=TEXT_EMIT_MODE) text_mode(); else printf("\t.align 2\n"); 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("\tla r1,lo16(L_%d)(r30)\n",code_disp_label); printf("\tbcl 20,31,L_%d\n",code_base = fwdlabel()); fwddef(code_base); printf("\tmflr r31\n"); max_func_args = 0; } void code_enter1(int args) { // set_lreg(LREG_LREGISTER,0); set_ireg(CREG_REGISTER,0); set_freg(FREG_FREGISTER,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; printf(".set L_%d,%d\n",code_disp_label,-r1_offsetv); local_table(); // free_all_register(); } void enter(char *name) { if (output_mode!=TEXT_EMIT_MODE) text_mode(); else printf("\t.align 2\n"); if (stmode!=STATIC) printf(".globl _%s\n",name); /* printf("\t.type\t%s,@function\n",name); */ printf("_%s:\n",name); code_setup=fwdlabel(); printf("\tmflr r0\n"); printf("\tbl L_%d\n",code_setup); code_base=fwdlabel(); fwddef(code_base); r1_offset_label = fwdlabel(); lvar_offset_label = fwdlabel(); printf("\tstwu r1,lo16(-L_%d)(r1)\n",r1_offset_label); printf("\tmr r30,r1\n"); printf("\tmflr r31\n"); max_func_args = 0; } void enter1() { text_mode(); // set_lreg(LREG_LREGISTER,0); set_ireg(CREG_REGISTER,0); set_freg(FREG_FREGISTER,0); } int reg_save_offset() { return -( (REAL_MAX_REGISTER-(REG_VAR_BASE-max_reg_var))*SIZE_OF_INT+ (REAL_MAX_FREGISTER-(FREG_VAR_BASE-max_freg_var))*SIZE_OF_DOUBLE ); } void leave(int control, char *name) { int retcont1=0,sz; if (max_freg_var>=0 && max_freg_var<=3) max_freg_var=3; reg_save = reg_save_offset(); if (control) { code_set_return_register(1); } if (retcont) { if (control) jmp(retlabel); retcont1 = fwdlabel(); fwddef(retcont); if (cadr(fnptr->ty)==FLOAT||cadr(fnptr->ty)==DOUBLE) { printf("\tfmr f1,f31\n"); } else if (cadr(fnptr->ty)>0&&( car(cadr(fnptr->ty))==STRUCT || car(cadr(fnptr->ty))==UNION)) { sz = size(cadr(fnptr->ty)); printf("\tli r7,%d\n",sz); printf("\tsubl r6,r7,r30\n"); printf("\tlwz r3,lo16(%d)(r30)\n",(my_func_args-1)*SIZE_OF_INT); emit_copy(6,3,sz,0,1,1); } else if (cadr(fnptr->ty)!=VOID) { printf("\tmr r3,r29\n"); } #if !R1SAVE printf("\tla r1,lo16(%d)(r30)\n", -reg_save+my_func_args*SIZE_OF_INT); #endif printf("\tb L_%d\n",retcont1); } fwddef(retlabel); printf("\tlwz r1,0(r1)\n"); if (retcont) { fwddef(retcont1); } if (max_freg_var>=0) { printf("\tlmw r%d,%d(r1)\n", REG_VAR_BASE-max_reg_var,reg_save); freg_save = 72-(REAL_MAX_FREGISTER-(FREG_VAR_BASE-max_freg_var))*4; printf("\tb restFP+%d ; restore f%d-f31\n", freg_save, FREG_VAR_BASE-max_freg_var); } else { printf("\tlwz r0,8(r1)\n"); printf("\tmtlr r0\n"); printf("\tlmw r%d,%d(r1)\n", REG_VAR_BASE-max_reg_var,reg_save); printf("\tblr\n"); } disp &= -SIZE_OF_INT; fwddef(code_setup); printf("\tstmw r%d,%d(r1)\n", REG_VAR_BASE-max_reg_var,reg_save); printf("\tstw r0,8(r1)\n"); if (max_freg_var>=0) printf("\tb saveFP+%d ; save f%d-f31\n", freg_save, FREG_VAR_BASE-max_freg_var); else { printf("\tblr\n"); } code_offset_set(); local_table(); labelno++; // free_all_register(); } void code_set_return_register(int mode) { 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_ireg(RET_REGISTER,mode); } } int code_get_fixed_creg(int reg,int type) { return creg; } void code_set_fixed_creg(int reg,int mode,int type) { if (type==FLOAT||type==DOUBLE) { set_freg(reg,mode); } else if (type==LONGLONG||type==ULONGLONG) { set_lreg(reg,mode); // use_reg(reg); } else { set_ireg(reg,mode); } } void gen_gdecl(char *n, int gpc) { /* if (stmode!=STATIC) printf(".globl _%s\n",n); */ } void align(int t) { if (t!=CHAR) { if (data_alignment & 1) printf("\t.align 2\n"); data_alignment = 0; } } void emit_data(int e, int t, NMTBL *n) { int l; #if FLOAT_CODE double d; float f; #endif #if LONGLONG_CODE long long ll; #endif char *name; name = n->nm; if(mode!=GDECL && mode!=STADECL) { error(-1); return; } if (chk) return; if (n->dsp != -1) { n->dsp = -1; /* initiallized flag */ printf(".globl\t_%s\n",name); data_mode(name); align(t); printf("_%s:\n",name); } else { data_mode(0); } if(car(e)==CONST) { if (t==CHAR||t==UCHAR) { printf("\t.byte %d\n",cadr(e)); if (data_alignment>0) data_alignment++; gpc += 1; } else if (t==SHORT||t==USHORT) { printf("\t.short %d\n",cadr(e)); if (data_alignment>0) data_alignment++; gpc += SIZE_OF_SHORT; } else { 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.long\t0x%x,0x%x\n",code_d2(d),code_d1(d)); } else if(t==FLOAT) { 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.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); } void emit_data_closing(NMTBL *n) { #ifdef DOT_SIZE int lb; #endif if (chk) return; if (mode==GDECL) { data_mode(0); #ifdef DOT_SIZE lb=fwdlabel(); printf("L_%d:\n",lb); printf("\t.size\t%s,L_%d-%s\n",n->nm,lb,n->nm); #endif } } void global_table(void) { NMTBL *n; int init; 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)); } } for(n=ntable;n < &ntable[GSYMS];n++) { if (is_code(n)||is_function(n)) { extrn = n->nm; if (n->sc==EXTRN1) { data_mode(0); printf(".picsymbol_stub\n"); printf("L_%s$stub:\n",extrn); printf("\t.indirect_symbol _%s\n",extrn); printf("\tmflr r0\n"); printf("\tbcl 20,31,L0$_%s\n",extrn); printf("L0$_%s:\n",extrn); printf("\tmflr r11\n"); printf("\taddis r11,r11,ha16(L_%s$lazy_ptr-L0$_%s)\n",extrn,extrn); printf("\tmtlr r0\n"); printf("\tlwz r12,lo16(L_%s$lazy_ptr-L0$_%s)(r11)\n",extrn,extrn); printf("\tmtctr r12\n"); printf("\taddi r11,r11,lo16(L_%s$lazy_ptr-L0$_%s)\n",extrn,extrn); printf("\tbctr\n"); printf(".data\n"); printf(".lazy_symbol_pointer\n"); printf("L_%s$lazy_ptr:\n",extrn); printf("\t.indirect_symbol _%s\n",extrn); printf("\t.long dyld_stub_binding_helper\n"); } else if (n->sc==FUNCTION||n->sc==CODE) { text_mode(); printf("\t.set L_%s$stub,_%s\n",extrn,extrn); data_mode(0); printf("L_%s$non_lazy_ptr:\n\t.long\t_%s\n",extrn,extrn); } } } init=0; for(n=ntable;n < &ntable[GSYMS];n++) { if (n->sc == GVAR) { if (init==0) { printf(".data\n"); init=1; } printf("L_%s$non_lazy_ptr:\n\t.long\t_%s\n",n->nm,n->nm); } } init = 0; for(n=ntable;n < &ntable[GSYMS];n++) { if (is_code(n)||is_function(n)) continue; if (n->sc==EXTRN1) { if(init==0) { printf(".data\n"); printf(".non_lazy_symbol_pointer\n"); init=1; } printf("L_%s$non_lazy_ptr:\n",n->nm); printf("\t.indirect_symbol _%s\n",n->nm); printf("\t.long\t0\n"); } } } void local_table(void) { NMTBL *n; int init; init=0; /* static local variables */ for(n=ntable+GSYMS;n < &ntable[GSYMS+LSYMS];n++) { if (n->sc == GVAR) { if (init==0) { data_mode(0); init=1; } if (n->dsp != -1) /* initialized static */ printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); printf("L_%s$non_lazy_ptr:\n\t.long\t_%s\n",n->nm,n->nm); } } } void text_mode(void) { if (output_mode!=TEXT_EMIT_MODE) { printf(".text\n"); printf("\t.align 2\n"); output_mode = TEXT_EMIT_MODE; } } void data_mode(char *name) { if (output_mode!=DATA_EMIT_MODE) { printf(".data\n"); output_mode = DATA_EMIT_MODE; } /* if (name) printf("\t.type\t%s,@object\n",name); */ } #if FLOAT_CODE /* floating point */ static int float_one_lib_used=0; static char *float_one_lib[] = { ".data", /* ".literal8", */ " .align 3", "__float_one:", " .long 1065353216", ".text", /* ".set L__float_one$non_lazy_ptr,__float_one", */ 0 }; static int float_zero_lib_used=0; static char *float_zero_lib[] = { ".data", /* ".literal8", */ " .align 3", "__float_zero:", " .long 0", ".text", /* ".set L__float_zero$non_lazy_ptr,__float_zero", */ 0 }; char * fstore(int d) { return (d?"stfd":"stfs"); } char * fload(int d) { return d?"lfd":"lfs"; } void code_cmp_dregister(int e2,int d) { char *frn,*rrn,*grn; int greg,r; grn = register_name(greg = get_dregister(d)); use_float(d,e2); frn = register_name(e2); float_zero_lib_used=1; r = get_ptr_cache(&float_zero); rrn = register_name(r); printf("\tlfs %s,0(%s)\n",grn,rrn); printf("\tfcmpu cr%d,%s,%s\n",cmpflag,grn,frn); free_register(greg); return; } void code_dregister(int e2,int freg,int d) { use_float(d,freg); if (freg!=e2) { if (is_int_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) { int r; use_float(d,freg); r = get_ptr_cache((NMTBL*)cadr(e2)); printf("\t%s %s,0(%s)\n",fstore(d),fregister_name(freg),register_name(r)); } void code_dassign_lvar(int e2,int freg,int d) { use_float(d,freg); lvar_intro(e2); printf("\t%s %s,",fstore(d),fregister_name(freg)); lvar(e2); } void code_dassign(int e2,int freg,int d) { use_float(d,freg); printf("\t%s %s,0(%s)\n",fstore(d),fregister_name(freg),register_name(e2)); } void code_dassign_dregister(int e2,int d,int freg) { use_float(d,freg); if (e2!=freg) { printf("\tfmr %s,%s\n",fregister_name(e2),fregister_name(freg)); } } static double d0 = 1.0; int code_d1(double d) { int *i = (int *)&d0; int *j = (int *)&d; return (i[1] == 0x3ff00000)?j[0]:j[1]; } int code_d2(double d) { int *i = (int *)&d0; int *j = (int *)&d; return (i[1] == 0x3ff00000)?j[1]:j[0]; } int code_f(double d) { float f = d; int *j = (int *)&f; return *j; } void code_dconst(int e2,int freg,int d) { int lb; double value = dcadr(e2); int r; char *rrn,*frn; use_float(d,freg); frn = fregister_name(freg); if (value==0.0) { float_zero_lib_used=1; r = get_ptr_cache(&float_zero); rrn = register_name(r); printf("\tlfs %s,0(%s)\n",frn,rrn); return; } if (value==1.0) { float_one_lib_used=1; r = get_ptr_cache(&float_one); rrn = register_name(r); printf("\tlfs %s,0(%s)\n",frn,rrn); return; } rrn = register_name((r=get_register())); use_reg(r); // to clear ptr cache printf(" \t.data\n\t.align 3\n"); lb=fwdlabel(); printf("L_%d:\n",lb); if (d) { printf("\t.long\t0x%x,0x%x\n",code_d2(value),code_d1(value)); } else { printf("\t.long\t0x%x\n",code_f(value)); } if (output_mode==TEXT_EMIT_MODE) { printf(".text\n"); } else { text_mode(); } printf("\taddis %s,r31,ha16(L_%d-L_%d)\n",rrn,lb,code_base); printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",rrn,lb,code_base,rrn); if (d) { printf("\tlfd %s,0(%s)\n",frn,rrn); } else { printf("\tlfs %s,0(%s)\n",frn,rrn); } free_register(r); } void code_dneg(int freg,int d) { char *frn; use_float(d,freg); frn = fregister_name(freg); printf("\tfneg %s,%s\n",frn,frn); } void code_d2i() { char *frn; char *crn; int e2 = new_lvar(SIZE_OF_DOUBLE); use_double0(); frn = fregister_name(freg); use_int0(); crn = register_name(creg); free_lvar(e2); printf("\tfctiwz %s,%s\n",frn,frn); lvar_intro(e2); printf("\tstfd %s,",frn); lvar(e2); lvar_intro(e2+SIZE_OF_DOUBLE-SIZE_OF_INT); printf("\tlwz %s,",crn); lvar(e2+SIZE_OF_DOUBLE-SIZE_OF_INT); } static int i2d_lib_used=0; static char *i2d_lib[] = { ".data", /* ".literal8", */ " .align 3", "__i2dLC0:", " .long 1127219200", " .long -2147483648", ".text", " .align 2", "i2d_:", " mflr r0", " bcl 20,31,__i2dL1$pb", "__i2dL1$pb:", " mflr r10", " mtlr r0", " xoris r3,r3,0x8000", " stw r3,-28(r30)", " lis r0,0x4330", " stw r0,-32(r30)", " lfd f0,-32(r30)", " addis r9,r10,ha16(__i2dLC0-__i2dL1$pb)", " lfd f1,lo16(__i2dLC0-__i2dL1$pb)(r9)", " fsub f1,f0,f1", " blr", 0 }; void code_i2d() { i2d_lib_used = 1; clear_ptr_cache(); code_save_stacks(); set_ireg(RET_REGISTER,1); printf("\tbl i2d_\n"); set_freg(RET_FREGISTER,0); } static int d2u_lib_used=0; static char *d2u_lib[] = { /* ".literal8", */ " .align 3", "__d2uLC0:", " .long 1105199104", " .long 0", ".text", " .align 2", "d2u_:", " mflr r0", " bcl 20,31,__d2uL1$pb", "__d2uL1$pb:", " mflr r10", " mtlr r0", " addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)", " lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)", " fcmpu cr0,f1,f0", " cror 2,1,2", " beq- cr0,__d2uL2", " fctiwz f0,f1", " stfd f0,-32(r30)", " lwz r3,-28(r30)", " blr", "__d2uL2:", " addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)", " lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)", " fsub f0,f1,f0", " fctiwz f0,f0", " stfd f0,-24(r30)", " lwz r3,-20(r30)", " xoris r3,r3,0x8000", " blr", 0 }; void code_d2u() { code_save_stacks(); clear_ptr_cache(); d2u_lib_used=1; set_freg(RET_FREGISTER,1); printf("\tbl d2u_\n"); set_ireg(RET_REGISTER,0); } static int u2d_lib_used=0; static char *u2d_lib[] = { ".data", /* ".literal8", */ " .align 3", "__u2dLC1:", " .long 1127219200", " .long 0", ".text", " .align 2", "u2d_:", " mflr r0", " bcl 20,31,__u2dL2$pb", "__u2dL2$pb:", " mflr r10", " mtlr r0", " stw r3,-28(r30)", " lis r0,0x4330", " stw r0,-32(r30)", " lfd f0,-32(r30)", " addis r9,r10,ha16(__u2dLC1-__u2dL2$pb)", " lfd f1,lo16(__u2dLC1-__u2dL2$pb)(r9)", " fsub f1,f0,f1", " blr", 0 }; void code_u2d() { code_save_stacks(); clear_ptr_cache(); u2d_lib_used = 1; set_ireg(RET_REGISTER,1); printf("\tbl u2d_\n"); set_freg(RET_FREGISTER,0); } void code_d2f() { } void code_f2d() { } void code_f2i() { code_d2i(); } void code_f2u() { code_d2u(); } void code_i2f() { code_i2d(); } void code_u2f() { code_u2d(); } void code_drgvar(int e2,int d,int freg) { int r; r = get_ptr_cache((NMTBL*)cadr(e2)); use_float(d,freg); printf("\t%s %s,0(%s)\n",fload(d),fregister_name(freg),register_name(r)); } void code_drlvar(int e2,int d,int freg) { use_float(d,freg); lvar_intro(e2); printf("\t%s %s,",fload(d),fregister_name(freg)); lvar(e2); } void code_cmp_drgvar(int e2,int reg,int d) { int r; char *frn; int g=get_dregister(d); char *grn=fregister_name(g); use_float(d,reg); frn=fregister_name(reg); r = get_ptr_cache((NMTBL*)cadr(e2)); printf("\t%s %s,0(%s)\n",fload(1),grn,register_name(r)); printf("\tfcmpu cr%d,%s,%s\n",cmpflag,frn,grn); free_register(g); } void code_cmp_drlvar(int e2,int reg,int d) { char *frn; int g=get_dregister(d); char *grn=fregister_name(g); use_float(d,reg); frn=fregister_name(reg); lvar_intro(e2); printf("\t%s %s,",fload(1),grn); lvar(e2); printf("\tfcmpu cr%d,%s,%s\n",cmpflag,frn,grn); free_register(g); } void dtosop(int op,int reg,int oreg) { char *opn=""; char *frn; char *grn; int ox = -1; use_float(1,reg); if(oreg==-1) { error(-1); } else if (oreg<= -REG_LVAR_OFFSET) { ox = get_dregister(1); if (ox<0) error(-1); use_reg(ox); code_drlvar(oreg+REG_LVAR_OFFSET,1,ox); oreg = ox; } grn=fregister_name(oreg); frn=fregister_name(reg); switch(op) { case FADD: case DADD: opn="fadd"; break; case FSUB: case DSUB: opn="fsub"; break; case FDIV: case DDIV: opn="fdiv"; break; case FMUL: case DMUL: opn="fmul"; break; case FCMP: case DCMP: printf("\tfcmpu cr7,%s,%s\n",frn,grn); if (ox!=-1) free_register(ox); return; case FCMPGE: case DCMPGE: printf("\tfcmpu cr7,%s,%s\n",frn,grn); if (ox!=-1) free_register(ox); return; default: error(-1); return; } printf("\t%s %s,%s,%s\n",opn,frn,frn,grn); if (ox!=-1) free_register(ox); } 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=emit_dpop(d); char *crn; char *frn; crn=register_name(ireg); use_float(d,reg); frn =fregister_name(reg); printf("\t%s %s,0(%s)\n",fload(d),frn,crn); dtosop(op,reg,xreg); printf("\t%s %s,0(%s)\n",fstore(d),frn,crn); emit_dpop_free(xreg,d); } void code_register_dassop(int reg,int op,int d) { // reg op= dpop() int xreg=emit_dpop(d); dtosop(op,reg,xreg); emit_dpop_free(xreg,d); } static int code_dload_1(int d) { int r,g; char *drn,*grn; // load 1 float_one_lib_used=1; r = get_ptr_cache(&float_one); drn=register_name(r); grn=fregister_name(g=get_dregister(d)); printf("\tlfs %s,0(%s)\n",grn,drn); return g; } void code_dpreinc(int e1,int e2,int d,int reg) { char *frn,*crn,*grn; int g; if (car(e2)==DREGISTER||car(e2)==FREGISTER) { crn=register_name(cadr(e2)); grn = fregister_name(g = code_dload_1(d)); if (reg==USE_CREG) { reg=get_dregister(d); if (!reg) error(-1); set_freg(reg,0); } frn=fregister_name(reg); printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",crn,crn,grn); if (use && reg!=cadr(e2)) printf("\tfmr %s,%s\n",frn,crn); } else { g_expr(e2); if (!is_int_reg(creg)) error(-1); crn=register_name(ireg); if (reg==USE_CREG) { reg=get_dregister(d); if (!reg) error(-1); set_freg(reg,0); } frn=fregister_name(reg); grn = fregister_name(g = code_dload_1(d)); printf("\t%s %s,0(%s)\n",fload(d),frn,crn); printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",frn,frn,grn); printf("\t%s %s,0(%s)\n",fstore(d),frn,crn); } free_register(g); } void code_dpostinc(int e1,int e2,int d,int reg) { char *frn,*crn,*grn; int g; if (car(e2)==DREGISTER||car(e2)==FREGISTER) { crn=register_name(cadr(e2)); grn = fregister_name(g = code_dload_1(d)); if (reg==USE_CREG) { reg=get_dregister(d); if (!reg) error(-1); set_freg(reg,0); } frn=fregister_name(reg); if (use && reg!=cadr(e2)) printf("\tfmr %s,%s\n",frn,crn); printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",crn,crn,grn); } else { g_expr(e2); if (!is_int_reg(creg)) error(-1); crn=register_name(ireg); if (reg==USE_CREG) { reg=get_dregister(d); if (!reg) error(-1); set_freg(reg,0); } frn=fregister_name(reg); grn = fregister_name(g = code_dload_1(d)); printf("\t%s %s,0(%s)\n",fload(d),frn,crn); printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",grn,frn,grn); printf("\t%s %s,0(%s)\n",fstore(d),grn,crn); } free_register(g); } void drexpr(int e1, int e2,int l1, int op,int cond) { 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; } } // g_expr(list3( ((op==DOP+GE||op==FOP+GE)?DCMPGE:DCMP), e2,e1)); g_expr(list3(DCMP, e1,e2)); switch(op) { case DOP+GT: case FOP+GT: printf("\tbgt\tcr7,L_%d\n",l1); break; case DOP+GE: case FOP+GE: // printf("\tcrnor 30,29,30\n"); // printf("\tbeq\tcr7,L_%d\n",l1); printf("\tbge\tcr7,L_%d\n",l1); break; case DOP+EQ: case FOP+EQ: printf("\tbeq\tcr7,L_%d\n",l1); break; case DOP+NEQ: case FOP+NEQ: printf("\tbne\tcr7,L_%d\n",l1); break; } } int emit_dpop(int d) { int xreg,reg; xreg=pop_fregister(); if (xreg<= -REG_LVAR_OFFSET) { reg = get_dregister(d); 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) { free_register(e1); } 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(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) // to = from { int tmp; if (regv_h(to)==regv_l(from)&&(regv_l(to)==regv_h(from))) { tmp = get_register(); printf("\tmr %s,%s\n",register_name(tmp),lregister_name_low(from)); printf("\tmr %s,%s\n",lregister_name_high(to),lregister_name_high(from)); printf("\tmr %s,%s\n",lregister_name_low(to),register_name(tmp)); free_register(tmp); } else if (regv_h(to)==regv_l(from)) { printf("\tmr %s,%s\n",lregister_name_low(to),lregister_name_low(from)); printf("\tmr %s,%s\n",lregister_name_high(to),lregister_name_high(from)); } else { printf("\tmr %s,%s\n",lregister_name_high(to),lregister_name_high(from)); printf("\tmr %s,%s\n",lregister_name_low(to),lregister_name_low(from)); } } static void pcond(char *s,int cmpflag,int l1) { printf("\tb%s cr%d,L_%d\n",s,cmpflag,l1); } static int lcmp(int op,int cond) { if (op==LOP+UGT||op==LOP+UGE) { return UCMP; } else if (op==LOP+LE||op==LOP+GE) { return CMP; } else { return CMP; } } void lrexpr(int e1, int e2,int l1, int op,int cond) { int reg; int e3; int l2; int op1,cr0,cr1; g_expr(e1); emit_lpush(); g_expr(e2); e3 = emit_lpop(); if (!is_longlong_reg(creg)) error(-1); reg = lreg; op1 = lcmp(op,cond); tosop(op1,regv_h(e3),regv_h(reg)); cr0 = cmpflag; inc_cmpflag(); cr1 = cmpflag; tosop(op1,regv_l(e3),regv_l(reg)); l2 = fwdlabel(); // cond==0 jump on false condtion ( if(x) => rexpr(.. cond=0 ...) ) switch(op) { case LOP+GT: case LOP+GE: pcond(code_gt(1),cr0,cond?l1:l2); pcond(code_eq(0),cr0,cond?l2:l1); break; case LOP+UGT: case LOP+UGE: pcond(code_ugt(1),cr0,cond?l1:l2); pcond(code_eq(0), cr0,cond?l2:l1); break; case LOP+EQ: pcond(code_eq(0),cr0,(cond?l2:l1)); pcond(code_eq(cond),cr1,l1); break; case LOP+NEQ: pcond(code_eq(0),cr0,(cond?l1:l2)); pcond(code_eq(!cond),cr1,l1); break; default: error(-1); } switch(op) { case LOP+GT: pcond(code_gt(cond), cr1,l1); break; case LOP+GE: pcond(code_ge(cond), cr1,l1); break; case LOP+UGT: pcond(code_ugt(cond), cr1,l1); break; case LOP+UGE: pcond(code_uge(cond), cr1,l1); break; } fwddef(l2); 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("\tcmpwi cr%d,%s,0\n",cmpflag,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); printf("\tstw %s,0(%s)\n",crn_h,drn); printf("\tstw %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("\tstw %s,",crn_h);lvar(e2); printf("\tstw %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) { use_longlong(creg); printf("\tsubfic %s,%s,0\n", lregister_name_low(creg),lregister_name_low(creg)); printf("\tsubfze %s,%s\n", lregister_name_high(creg),lregister_name_high(creg)); } 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("\tlwz %s,0(%s)\n",crn_h,register_name(r)); printf("\tlwz %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("\tlwz %s,",crn_h); lvar(e1); printf("\tlwz %s,",crn_l); lvar(e1+SIZE_OF_INT); } #if 0 static int lumod_lib_used=0; static char *lumod_lib[] = { }; static int lmod_lib_used=0; static char *lmod_lib[] = { }; static int ludiv_lib_used=0; static char *ludiv_lib[] = { }; static int ldiv_lib_used=0; static char *ldiv_lib[] = { }; #endif static int lsrd_lib_used=0; static char *lsrd_lib[] = { ".text", " .align 2", "lsrd__:", " mr. r5,r5", " beqlr", " subfic r2,r5,32", " stw r3,-32(r1)", " stw r4,-28(r1)", " cmpwi cr7,r2,0", " bgt+ cr7,L__lsrd1", " neg r0,r2", " lwz r2,-32(r1)", " li r9,0", " srw r2,r2,r0", " stw r9,-48(r1)", " b L__lsrd2", "L__lsrd1: lwz r0,-32(r1)", " slw r9,r0,r2", " lwz r2,-28(r1)", " srw r0,r0,r5", " srw r2,r2,r5", " stw r0,-48(r1)", " or r2,r2,r9", "L__lsrd2: stw r2,-44(r1)", " lwz r3,-48(r1)", " lwz r4,-44(r1)", " blr", 0 }; static int asld_lib_used=0; static char *asld_lib[] = { ".text", " .align 2", "asld__:", " mr. r5,r5", " beqlr", " subfic r2,r5,32", " stw r3,-32(r1)", " stw r4,-28(r1)", " cmpwi cr7,r2,0", " bgt+ cr7,L__asld1", " neg r0,r2", " lwz r2,-28(r1)", " li r9,0", " slw r2,r2,r0", " stw r9,-44(r1)", " b L__asld2", "L__asld1: lwz r0,-28(r1)", " srw r9,r0,r2", " lwz r2,-32(r1)", " slw r0,r0,r5", " slw r2,r2,r5", " stw r0,-44(r1)", " or r2,r2,r9", "L__asld2: stw r2,-48(r1)", " lwz r3,-48(r1)", " lwz r4,-44(r1)", " blr", 0 }; static int asrd_lib_used=0; static char *asrd_lib[] = { ".text", " .align 2", "asrd__:", " mr. r5,r5", " beqlr", " subfic r2,r5,32", " stw r3,-32(r1)", " stw r4,-28(r1)", " cmpwi cr7,r2,0", " bgt+ cr7,L__asrd1", " lwz r0,-32(r1)", " neg r2,r2", " sraw r2,r0,r2", " srawi r0,r0,31", " b L__asrd2", "L__asrd1: lwz r0,-32(r1)", " slw r9,r0,r2", " lwz r2,-28(r1)", " sraw r0,r0,r5", " srw r2,r2,r5", " or r2,r2,r9", "L__asrd2: stw r0,-48(r1)", " stw r2,-44(r1)", " lwz r3,-48(r1)", " lwz r4,-44(r1)", " blr", 0 }; static void extern_conv(char *conv) { code_save_stacks(); clear_ptr_cache(); extern_define(conv,0,FUNCTION,1); printf("\tbl L_%s$stub\n",conv); } #if FLOAT_CODE #if 0 static int d2ll_lib_used=0; static char *d2ll_lib[] = { }; static int d2ull_lib_used=0; static char *d2ull_lib[] = { }; static int f2ll_lib_used=0; static char *f2ll_lib[] = { }; static int f2ull_lib_used=0; static char *f2ull_lib[] = { }; static int ll2d_lib_used=0; static char *ll2d_lib[] = { }; static int ll2f_lib_used=0; static char *ll2f_lib[] = { }; #endif #endif static void code_asld_lib(int reg,int oreg) { code_save_stacks(); clear_ptr_cache(); asld_lib_used = 1; set_lreg_operand(reg,1); set_lreg(RET_LREGISTER,0); if (regv_l(oreg)!=5) { printf("\tmr r5,%s\n", lregister_name_low(oreg)); } printf("\tbl asld__\n"); } static void code_asrd_lib(int reg,int oreg) // ___ashrdi3$stub { code_save_stacks(); clear_ptr_cache(); asrd_lib_used = 1; set_lreg_operand(reg,1); set_lreg(RET_LREGISTER,0); if (regv_l(oreg)!=5) { printf("\tmr r5,%s\n", lregister_name_low(oreg)); } printf("\tbl asrd__\n"); } static void code_lsrd_lib(int reg,int oreg) // ___lshrdi3$stub { code_save_stacks(); clear_ptr_cache(); lsrd_lib_used = 1; set_lreg_operand(reg,1); set_lreg(RET_LREGISTER,0); if (regv_l(oreg)!=5) { printf("\tmr r5,%s\n", lregister_name_low(oreg)); } printf("\tbl lsrd__\n"); } static void code_ldiv_lib(int reg,int oreg) // ___divdi3$stub { code_save_stacks(); clear_ptr_cache(); set_lreg_operand(reg,1); set_lreg(RET_LREGISTER,0); set_lreg_operand1(oreg,1); extern_conv("__divdi3"); } static void code_ludiv_lib(int reg,int oreg) // ___udivdi3$stub { code_save_stacks(); clear_ptr_cache(); set_lreg_operand(reg,1); set_lreg(RET_LREGISTER,0); set_lreg_operand1(oreg,1); extern_conv("__udivdi3"); } static void code_lmod_lib(int reg,int oreg) // ___moddi3$stub { code_save_stacks(); clear_ptr_cache(); set_lreg_operand(reg,1); set_lreg(RET_LREGISTER,0); set_lreg_operand1(oreg,1); extern_conv("__moddi3"); } static void code_lumod_lib(int reg,int oreg) // ___umoddi3$stub { code_save_stacks(); clear_ptr_cache(); set_lreg(RET_LREGISTER,0); set_lreg_operand(reg,1); set_lreg_operand1(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; int ox = -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) { ox = get_lregister(); if (ox<0) error(-1); use_reg(ox); code_lrlvar(oreg+REG_LVAR_OFFSET,ox); oreg = ox; } switch(op) { case LLSHIFT: case LULSHIFT: code_asld_lib(reg,oreg); // ___ashldi3$stub check_lreg(reg); if(ox!=-1) free_register(ox); return; case LRSHIFT: code_asrd_lib(reg,oreg); // ___ashrdi3$stub check_lreg(reg); if(ox!=-1) free_register(ox); return; case LURSHIFT: code_lsrd_lib(reg,oreg); // ___lshrdi3$stub check_lreg(reg); if(ox!=-1) free_register(ox); 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: printf("\taddc %s,%s,%s\n",crn_l,crn_l,orn_l); printf("\tadde %s,%s,%s\n",crn_h,crn_h,orn_h); break; case LSUB: printf("\tsubfc %s,%s,%s\n",crn_l,orn_l,crn_l); printf("\tsubfe %s,%s,%s\n",crn_h,orn_h,crn_h); 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("\tmulhwu %s,%s,%s\n",drn_h,crn_l,orn_l); printf("\tmullw %s,%s,%s\n", drn_l,crn_l,orn_l); printf("\tmullw %s,%s,%s\n", orn_l,crn_h,orn_l); printf("\tadd %s,%s,%s\n", drn_h,drn_h,orn_l); printf("\tmullw %s,%s,%s\n", crn_l,orn_h,crn_l); printf("\tadd %s,%s,%s\n", crn_h,drn_h,crn_l); printf("\tmr %s,%s\n", crn_l,drn_l); break; case LDIV: code_ldiv_lib(reg,oreg); // ___divdi3$stub check_lreg(reg); break; case LUDIV: code_ludiv_lib(reg,oreg); // ___udivdi3$stub check_lreg(reg); break; case LMOD: code_lmod_lib(reg,oreg); // ___moddi3$stub check_lreg(reg); break; case LUMOD: code_lumod_lib(reg,oreg); // ___umoddi3$stub check_lreg(reg); break; default: error(-1); } if(ox!=-1) free_register(dx); 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 void ladd(int creg,int reg,int dir) // creg=reg+dir { printf("\taddic %s,%s,%d\n", lregister_name_low(creg),lregister_name_low(reg), dir); printf("\tadd%s %s,%s\n", dir>0?"ze":"me", lregister_name_high(creg),lregister_name_high(reg)); } void code_lpreinc(int e1,int e2,int reg) { int dreg,xreg; int dir=caddr(e1); if (car(e2)==LREGISTER) { use_longlong(reg); ladd(cadr(e2),cadr(e2),dir); if (reg!=cadr(e2)) { lmove(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); set_lreg(dreg,0); // free old lreg==creg } else { dreg = reg; } xreg = emit_pop(0); lload(xreg,dreg,0); ladd(dreg,dreg,dir); code_lassign(xreg,dreg); emit_pop_free(xreg); } void code_lpostinc(int e1,int e2,int reg) { int dreg,nreg,xreg; int dir=caddr(e1); if (car(e2)==LREGISTER) { use_longlong(reg); if (reg!=cadr(e2)) lmove(reg,cadr(e2)); ladd(cadr(e2),cadr(e2),dir); return; } g_expr(e2); if(!is_int_reg(creg)) error(-1); emit_push(); nreg=get_lregister(); if (!nreg) error(-1); if (reg==USE_CREG) { dreg=get_lregister(); if (!dreg) error(-1); set_lreg(dreg,0); // free old lreg==creg } else { dreg = reg; } xreg = emit_pop(0); lload(xreg,dreg,0); ladd(nreg,dreg,dir); code_lassign(xreg,nreg); 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; } lload(edx0=edx,reg,0); ltosop(op,reg,xreg); use_reg(reg); edx = emit_pop(0); code_lassign(edx,reg); if (edx0!=-1) free_register(edx0); emit_pop_free(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 code_save_stacks() { int i,reg; for(i=0;i<reg_sp;i++) { if ((reg=reg_stack[i])>=0) { code_assign_lvar( (reg_stack[i]=new_lvar(SIZE_OF_INT)),reg,0); reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; } } #if FLOAT_CODE for(i=0;i<freg_sp;i++) { if ((reg=freg_stack[i])>=0) { code_dassign_lvar( (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 emit_lib(char *p[]) { while(*p) { printf("%s\n",*p++); } } void code_closing() { #if FLOAT_CODE if (d2u_lib_used) emit_lib(d2u_lib); if (u2d_lib_used) emit_lib(u2d_lib); if (float_one_lib_used) emit_lib(float_one_lib); if (float_zero_lib_used) emit_lib(float_zero_lib); if (i2d_lib_used) emit_lib(i2d_lib); #endif #if LONGLONG_CODE if (asld_lib_used) emit_lib(asld_lib); if (lsrd_lib_used) emit_lib(lsrd_lib); if (asrd_lib_used) emit_lib(asrd_lib); #if 0 if (lumod_lib_used) emit_lib(lumod_lib); if (lmod_lib_used) emit_lib(lmod_lib); if (ludiv_lib_used) emit_lib(ludiv_lib); if (ldiv_lib_used) emit_lib(ldiv_lib); #endif #if FLOAT_CODE #if 0 if (dl2ll_lib_used) emit_lib(dl2ll_lib); if (d2ull_lib_used) emit_lib(d2ull_lib); if (f2ll_lib_used) emit_lib(f2ll_lib); if (f2ull_lib_used) emit_lib(f2ull_lib); if (ll2d_lib_used) emit_lib(ll2d_lib); if (ll2f_lib_used) emit_lib(ll2f_lib); #endif #endif #endif global_table(); /* printf("\t.ident \"Micro-C compiled\"\n"); */ } /* end */