Mercurial > hg > CbC > old > device
diff mc-code-mips.c @ 130:fea1b499d47b
fix register var save
author | kono |
---|---|
date | Fri, 04 Apr 2003 14:01:33 +0900 |
parents | |
children | 09379ec2a74b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mc-code-mips.c Fri Apr 04 14:01:33 2003 +0900 @@ -0,0 +1,2698 @@ +/* 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" + +#define TEXT_EMIT_MODE 0 +#define DATA_EMIT_MODE 1 +#define RODATA_EMIT_MODE 2 + +static void data_mode(char *name); +static void init_ptr_cache(); +static void ld_indexx(int byte, int n, int xreg); +static void local_table(void); +static void shift(char *op, int reg); +static int struct_push(int e4,int t,int arg); + +static int output_mode = TEXT_EMIT_MODE; +static int data_alignment = 0; + +static int code_disp_label; +static int code_setup; +static int r1_offset_label; +static int lvar_offset_label; + +static int reg_save; +static int freg_save; + +int size_of_int = 4; +int size_of_float = 4; +int size_of_double = 8; +int size_of_longlong = 8; +int endian = 1; + + +#define REG_fp 1 +#define REG_sp 30 +#define REG_VAR_BASE 29 +#define REG_VAR_MIN 22 +#define MIN_TMP_REG 3 +#define MAX_TMP_REG 15 + +#define PTRC_REG 3 + +#define FREG_VAR_BASE 31 +#define FREG_VAR_MIN 24 +#define MIN_TMP_FREG 1 +#define MAX_TMP_FREG 15 + +#define RET_REGISTER 3 +#define RET_FREGISTER 1 + +int MAX_REGISTER=30; /* PowerPCのレジスタを10個まで使う*/ +int MAX_FREGISTER=31; +#define REAL_MAX_REGISTER 32 /* PowerPCのレジスタが32ということ*/ +#define REAL_MAX_FREGISTER 32 /* PowerPCのレジスタが32ということ*/ + +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_CODE_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG; + +#define CREG_REGISTER MAX_TMP_REG +#define FREG_FREGISTER MAX_TMP_FREG + +int powerpc_regs[REAL_MAX_REGISTER]; +int powerpc_regv[REAL_MAX_REGISTER]; + +int *regv = powerpc_regv; +int *regs = powerpc_regs; + +int powerpc_fregs[REAL_MAX_FREGISTER]; +int powerpc_fregv[REAL_MAX_FREGISTER]; + +int *fregv = powerpc_fregv; +int *fregs = powerpc_fregs; + +static int max_reg_var, max_freg_var; +static int cond_reg=-1,cond_freg=-1; + +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" +}; + +static char *freg_name[] = { + "f0","f1","f2","f3","f4","f5","f6","f7","f8","f9", + "f10","f11","f12","f13","f14","f15","f16","f17","f18","f19", + "f20","f21","f22","f23","f24","f25","f26","f27","f28","f29", + "f30","f31" +}; + +#define register_name(i) reg_name[i] +#define fregister_name(i) freg_name[i] + +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); +static void code_save_stacks(); +static void code_save_input_registers(); +static void clear_ptr_cache_reg(int r); +static void set_creg(int,int); +static void set_freg(int,int); + +int max_func_args; +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 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 creg) { + lvar_intro(e2); + printf("\tla %s,",register_name(creg)); + lvar(e2); + regv[creg]=1; +} + +void +code_init(void) +{ + init_ptr_cache(); +} + +void +gexpr_code_init(void){ + regv[creg]=0; + fregv[freg]=0; +} + + +void +code_arg_register() +{ + if (is_function(fnptr)) + code_save_input_registers(); +} + +int +get_register(void) +{ /* 使われていないレジスタを調べる */ + int i,reg; + for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) { + if (regs[i]) continue; /* 使われている */ + regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ + return i; /* その場所を表す番号を返す */ + } + /* INPUT_REG か PTR_CACHE をつぶす */ + for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) { + if (regs[i]==PTRC_REG) { + clear_ptr_cache_reg(i); + } else + continue; + regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ + return i; /* その場所を表す番号を返す */ + } + /* search register stack */ + for(i=0;i<reg_sp;i++) { + if ((reg=reg_stack[i])>=0) { + code_assign_lvar( + (reg_stack[i]=new_lvar(size_of_int)),reg,0); + reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; + return reg; + } + } + /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ + error(-1); return creg; +} + +int +pop_register(void) +{ /* レジスタから値を取り出す */ + return reg_stack[--reg_sp]; +} + +int +get_fregister(void) +{ /* 使われていないレジスタを調べる */ + int i,reg; + for(i=MAX_TMP_FREG;i>MIN_TMP_FREG;i--) { + if (fregs[i]) continue; /* 使われている */ + fregs[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; + } + } + /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ + error(REG_ERR); return freg; +} + + +int +pop_fregister(void) +{ /* レジスタから値を取り出す */ + return freg_stack[--freg_sp]; +} + +void +emit_pop_free(int xreg) +{ + if (xreg>=0) + free_register(xreg); +} + +void +free_register(int i) { /* いらなくなったレジスタを開放 */ + if (i<0||MAX_REGISTER<i) error(-1); + regv[i]=regs[i]=0; +} + +void +free_fregister(int i) { /* いらなくなったレジスタを開放 */ + if (i<0||MAX_FREGISTER<i) error(-1); + fregv[i]=fregs[i]=0; +} + +int +get_input_fregister_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||MAX_FREGISTER<i+MIN_TMP_FREG) return 0; + return list3(DREGISTER,i+MIN_TMP_FREG,(int)n); + i = i+MIN_TMP_FREG; + } + return list3(DREGISTER,i,(int)n); +} + +int +get_input_register_var(int i,NMTBL *n,int is_code) +{ + if (is_code) { + if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0; + i = REG_VAR_BASE-i; + } else { + if (i<0||MAX_REGISTER<i+MIN_TMP_REG) return 0; + i = i+MIN_TMP_REG; + } + return list3(REGISTER,i,(int)n); +} + +int +free_register_count(void) +{ + int i,count,fcount; + fcount = count = 0; + for(i=0;i<MAX_REGISTER;i++) { + if (! regs[i] && ! regv[i]) count++; + } + for(i=0;i<MAX_FREGISTER;i++) { + if (! fregs[i] && ! fregv[i]) fcount++; + } + fprintf(stderr,"# free reg %d freg %d\n",count,fcount); + return count+fcount; +} + +int +register_full(void) +{ + int i; + for(i=0;i<MAX_REGISTER;i++) { + if (! regs[i]) { + return 0; + } + } + return 1; +} + +void +free_all_register(void) +{ + int i; + for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; regv[i]=0; } + for(i=0;i<MAX_FREGISTER;i++) { fregs[i]=0; fregv[i]=0; } + creg = get_register(); + freg = get_fregister(); + set_creg(CREG_REGISTER,0); + set_freg(FREG_FREGISTER,0); + return; +} + +void +register_usage(char *s) +{ +#if 0 + int i; +#endif + if (chk) return; + if (!lsrc) return; + printf("# %d: %s:",lineno,s); + printf(" creg=%s fgreg=%s",register_name(creg),fregister_name(freg)); +#if 0 + printf("\n# regs:"); + for(i=0;i<MAX_REGISTER;i++) { printf("%d",regv[i]); } + printf(":"); + for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); } + printf("\n# freg:"); + for(i=0;i<MAX_FREGISTER;i++) { printf("%d",fregs[i]); } + printf(" regs_stack",register_name(creg),register_name(dreg)); + for(i=reg_sp;i>=0;i--) { + if(reg_stack[i]>=0) + printf(" %s",register_name(reg_stack[i],0)); + } +#endif + printf("\n"); +} + +void +gexpr_init(void) +{ + while(reg_sp > 0) { + free_register(reg_stack[--reg_sp]); + } + if (cond_freg!=-1) { + if(car(cond_freg)==DREGISTER) free_fregister(cadr(cond_freg)); + cond_freg=-1; + } + if (cond_reg!=-1) { + if(car(cond_reg)==REGISTER) free_register(cadr(cond_reg)); + cond_reg=-1; + } + text_mode(); + gexpr_code_init(); + register_usage("gexpr_init"); +} + + +void +emit_init(void) +{ + free_all_register(); + max_reg_var=-1; max_freg_var=-1; + reg_sp = 0; + freg_sp = 0; + text_mode(); +} + +int +register_var(int r) { + return r; +} + + +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; /* そのレジスタを使うことを宣言し */ + regv[REG_VAR_BASE-i]=0; + if (i>max_reg_var) max_reg_var=i; + /* その場所を表す番号を返す */ + return list3(REGISTER,REG_VAR_BASE-i,(int)n); + } + } + return list2(LVAR,new_lvar(size_of_int)); +} + +int +fregister_var(int r) { + return r; +} + +int +get_fregister_var(NMTBL *n) +{ + int i; + for(i=0;i<FREG_VAR_BASE-REG_VAR_MIN;i++) { + if (! regs[FREG_VAR_BASE-i]) { /* 使われていないなら */ + regs[FREG_VAR_BASE-i]=USING_REG; /*そのレジスタを使うことを宣言し*/ + regv[FREG_VAR_BASE-i]=0; + if (i>max_freg_var) max_freg_var=i; + /* その場所を表す番号を返す */ + return list3(DREGISTER,FREG_VAR_BASE-i,(int)n); + } + } + return list2(LVAR,new_lvar(size_of_double)); +} + +void +emit_push() +{ + int new_reg; + if (reg_sp>MAX_MAX) error(-1); + new_reg = get_register(); + reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ + creg = new_reg; + regv[creg]=1; +} + +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; + regv[xreg]=1; + } + 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; +} + +void +code_label(int labelno) +{ + clear_ptr_cache(); + printf("L_%d:\n",labelno); +} + +void +code_gvar(int e1,int creg) { + int r; + r = get_ptr_cache((NMTBL*)cadr(e1)); + if(r!=creg) + printf("\tmr %s,%s\n",register_name(creg),register_name(r)); + regv[creg]=1; + return; +} + +void +code_rgvar(int e1,int creg) { + printf("\tlwz %s,0(%s)\n",register_name(creg), + register_name(get_ptr_cache((NMTBL*)cadr(e1)))); + regv[creg]=1; +} + +void +code_crgvar(int e1,int creg){ + char *crn = register_name(creg); + printf("\tlbz %s,0(%s)\n",crn, + register_name(get_ptr_cache((NMTBL*)cadr(e1)))); + printf("\textsb %s,%s\n",crn,crn); + regv[creg]=1; +} + + +void +code_register(int e2,int creg) { + if (creg!=e2) + printf("\tmr %s,%s\n",register_name(creg),register_name(e2)); + regv[creg]=1; +} + + +void +code_rlvar(int e2,int reg) { + lvar_intro(e2); + printf("\tlwz %s,",register_name(reg)); + lvar(e2); + regv[creg]=1; +} + + +void +code_crlvar(int e2,int reg) { + lvar_intro(e2); + printf("\tlbz %s,",register_name(reg)); + lvar(e2); + printf("\textsb %s,%s\n",register_name(reg),register_name(reg)); + regv[reg]=1; +} + + +void +code_fname(NMTBL *n,int creg) { + int r; + r = get_ptr_cache(n); + if(r!=creg) + printf("\tmr %s,%s\n",register_name(creg),register_name(r)); + regv[creg]=1; + return; +} + + +void +code_const(int e2,int creg) { + char *crn = register_name(creg); + 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); + } + regv[creg]=1; +} + + +void +code_neg(int creg) { + printf("\tneg %s,%s\n", register_name(creg), register_name(creg)); +} + + +void +code_not(int creg) { + printf("\tnor %s,%s,%s\n", + register_name(creg), register_name(creg),register_name(creg)); +} + + +void +code_lnot(int creg) { + 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 reg) { + char *xrn,*drn; + int i,dreg; + if (car(e2)==REGISTER) { + printf("\taddi %s,%s,%d\n", + register_name(cadr(e2)),register_name(cadr(e2)), caddr(e1)); + if (cadr(reg)!=e2) + printf("\tmr %s,%s\n",register_name(cadr(reg)),register_name(e2)); + regv[reg]=1; + return; + } + g_expr(e2); + xrn = register_name(creg); + dreg=get_register(); if (!dreg) error(-1); + drn = register_name(dreg); + printf("\tlwz %s,0(%s)\n",drn,xrn); + printf("\taddi %s,%s,%d\n",drn,drn,caddr(e1)); + printf("\tstw %s,0(%s)\n",drn,xrn); + i=creg;creg=dreg;dreg=i; + regv[creg]=1; + free_register(dreg); +} + + +void +code_postinc(int e1,int e2,int reg) { + char *xrn,*crn,*nrn; + int dreg,nreg,i; + if (car(e2)==REGISTER) { + 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)),caddr(e1)); + regv[reg]=1; + return; + } + g_expr(e2); + crn = register_name(creg); + dreg=get_register(); if (!dreg) error(-1); + xrn = register_name(dreg); + nreg=get_register(); if (!nreg) error(-1); + nrn = register_name(nreg); + printf("\tlwz %s,0(%s)\n",xrn,crn); + printf("\taddi %s,%s,%d\n",nrn,xrn,caddr(e1)); + printf("\tstw %s,0(%s)\n",nrn,crn); + i=creg;creg=dreg;dreg=i; + free_register(nreg); + free_register(dreg); + regv[creg]=1; +} + + +void +code_cpostinc(int e1,int e2,int reg) { + char *xrn,*crn,*nrn; + int i,nreg,dreg; + if (car(e2)==REGISTER) { + printf("\tlbz %s,0(%s)\n",register_name(reg),register_name(cadr(e2))); + printf("\textsb %s,%s\n",register_name(reg),register_name(reg)); + printf("\taddi %s,%s,%d\n", + register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1)); + regv[reg]=1; + return; + } + g_expr(e2); + crn = register_name(creg); + dreg=get_register(); if (!dreg) error(-1); + xrn = register_name(dreg); + nreg=get_register(); if (!nreg) error(-1); + nrn = register_name(nreg); + printf("\tlwz %s,0(%s)\n",xrn,crn); + printf("\tlbz %s,0(%s)\n",nrn,xrn); + printf("\textsb %s,%s\n",nrn,nrn); + printf("\taddi %s,%s,%d\n", xrn,xrn,caddr(e1)); + printf("\tstw %s,0(%s)\n",xrn,crn); + i=creg;creg=nreg;nreg=i; + free_register(nreg); + free_register(dreg); + regv[creg]=1; +} + + +void +code_cpreinc(int e1,int e2,int reg) { + char *xrn,*crn,*nrn; + int i,nreg,dreg; + if (car(e2)==REGISTER) { + printf("\tlbzu %s,%d(%s)\n",register_name(reg),caddr(e1),register_name(cadr(e2))); + printf("\textsb %s,%s\n",register_name(reg),register_name(reg)); + regv[reg]=1; + return; + } + g_expr(e2); + crn = register_name(creg); + dreg=get_register(); if (!dreg) error(-1); + xrn = register_name(dreg); + nreg=get_register(); if (!nreg) error(-1); + nrn = register_name(nreg); + printf("\tlwz %s,0(%s)\n",xrn,crn); + printf("\tlbzu %s,%d(%s)\n",nrn,caddr(e1),xrn); + printf("\tstw %s,0(%s)\n",xrn,crn); + printf("\textsb %s,%s\n",nrn,nrn); + i=creg;creg=nreg;nreg=i; + free_register(nreg); + free_register(dreg); + regv[creg]=1; +} + + +void +code_cpostdec(int e1,int e2,int reg) { + char *xrn,*crn,*nrn; + int i,nreg,dreg; + if (car(e2)==REGISTER) { + crn=register_name(reg); + xrn=register_name(cadr(e2)); + printf("\tlbz %s,0(%s)\n",crn,xrn); + printf("\taddi %s,%s,%d\n",xrn,xrn,caddr(e1)); + printf("\textsb %s,%s\n",crn,crn); + regv[reg]=1; + return; + } + g_expr(e2); + crn = register_name(creg); + dreg=get_register(); if (!dreg) error(-1); + xrn = register_name(dreg); + nreg=get_register(); if (!nreg) error(-1); + nrn = register_name(nreg); + printf("\tlwz %s,0(%s)\n",xrn,crn); + printf("\tlbz %s,0(%s)\n",nrn,xrn); + printf("\taddi %s,%s,%d\n",xrn,xrn,caddr(e1)); + printf("\tstw %s,0(%s)\n",xrn,crn); + printf("\textsb %s,%s\n",nrn,nrn); + i=creg;creg=nreg;nreg=i; + free_register(nreg); + free_register(dreg); + regv[creg]=1; +} + + +void +code_cpredec(int e1,int e2,int reg) { + char *xrn,*crn,*nrn; + int i,nreg,dreg; + if (car(e2)==REGISTER) { + crn=register_name(reg); + xrn=register_name(cadr(e2)); + printf("\tlbzu %s,%d(%s)\n",crn,caddr(e1),xrn); + printf("\textsb %s,%s\n",crn,crn); + regv[reg]=1; + return; + } + g_expr(e2); + crn = register_name(creg); + dreg=get_register(); if (!dreg) error(-1); + xrn = register_name(dreg); + nreg=get_register(); if (!nreg) error(-1); + nrn = register_name(nreg); + printf("\tlwz %s,0(%s)\n",xrn,crn); + printf("\tlbzu %s,%d(%s)\n",nrn,caddr(e1),xrn); + printf("\tstw %s,0(%s)\n",xrn,crn); + printf("\textsb %s,%s\n",nrn,nrn); + i=creg;creg=nreg;nreg=i; + free_register(nreg); + free_register(dreg); + regv[creg]=1; +} + + +void +code_return(int creg) { + char *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 */ +#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) { + char *xrn; + int e2,e3; + b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ + xrn = register_name(creg); + printf("\tli %s,0\n",xrn); + jmp(e3=fwdlabel()); + fwddef(e2); + printf("\tli %s,1\n",xrn); + fwddef(e3); +} + +char * +code_gt(int cond) { + return (cond?"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"); +} + +void +code_cmp_crgvar(int e1) { + int r; + char *crn = register_name(creg); + r = get_ptr_cache((NMTBL*)cadr(e1)); + printf("\tlbz %s,0(%s)\n",crn,register_name(r)); + printf("\tcmpwi cr0,%s,0\n",crn); + regv[creg]=0; +} + + +void +code_cmp_crlvar(int e2) { + char *crn = register_name(creg); + lvar_intro(e2); + printf("\tlbz %s,",crn); + lvar(e2); + code_cmp_register(creg); + regv[creg]=0; +} + + +void +code_cmp_rgvar(int e1) { + int r; + char *crn = register_name(creg); + r = get_ptr_cache((NMTBL*)cadr(e1)); + printf("\tlwz %s,0(%s)\n",crn,register_name(r)); + code_cmp_register(creg); + regv[creg]=0; +} + + +void +code_cmp_rlvar(int e2) { + char *crn = register_name(creg); + lvar_intro(e2); + printf("\tlwz %s,",crn); + lvar(e2); + code_cmp_register(creg); + regv[creg]=0; +} + + +void +code_cmp_register(int e2) { + printf("\tcmpwi cr0,%s,0\n",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; + 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 = register_name(from); + char *trn = register_name(to); + char *drn; + int fix = 0; + char *memmove = "memmove"; + int dreg = get_register(); if (!dreg) error(-1); + drn = register_name(dreg); + + /* length <0 means upward direction copy */ + switch (length) { + case 0: break; + case 1: case -1: + printf("\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 (-MAX_COPY_LEN<length && length <0) { + for(;length<=4;length+=4,offset-=4) + emit_copy(from,to,4,offset,0,det); + for(;length<=2;length+=2,offset-=2) + emit_copy(from,to,2,offset,0,det); + if(length>0) + emit_copy(from,to,length,offset,0,det); + break; + } else if (length <=MAX_COPY_LEN) { + for(;length>=4;length-=4,offset+=4) + emit_copy(from,to,4,offset,0,det); + for(;length>=2;length-=2,offset+=2) + emit_copy(from,to,2,offset,0,det); + if(length>0) + emit_copy(from,to,length,offset,0,det); + break; + } + clear_ptr_cache(); + code_save_stacks(); + printf("\tli 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_creg(RET_REGISTER,0); + if (creg!=to) { + free_register(to); to = creg; + } + break; + } + if (value) { + /* creg must point top of the destination data */ + /* this code is necessary for the value of assignment or function call */ + /* otherwise we don't need this */ + if (fix) printf("\taddi %s,%s,%d\n",trn,trn,fix); + if(creg!=to) { + free_register(creg); creg=to; + } + } + free_register(dreg); + regv[from]=regv[to]=regv[dreg]=0; + regv[creg]=1; +} + +int +struct_push(int e4,int t,int arg) +{ + int length,count; + int dreg,sreg; char *drn,*crn,*srn; + g_expr(e4); + length=size(t); + if(length%size_of_int) { + length += size_of_int - (length%size_of_int); + } + dreg = get_register(); if (!dreg) error(-1); + drn = register_name(dreg); + crn = register_name(creg); + if (length<MAX_COPY_LEN) { + sreg = get_register(); if (!sreg) error(-1); + srn = register_name(sreg); + code_lvar(cadr(arg),sreg); + for(count=0;length<MAX_COPY_LEN;count++,length-=size_of_int) { + if (length==0) { + free_register(sreg); + free_register(dreg); + return count; + } else { + printf("\tlwz %s,%d(%s)\n",drn,length-size_of_int,crn); + printf("\tstwu %s,%d(%s)\n",drn,-size_of_int,srn); + } + } + } + code_lvar(cadr(arg),dreg); + /* downward direction copy */ + emit_copy(creg,dreg,length,0,0,1); + if (dreg) free_register(dreg); + return length/size_of_int; +} + +void +set_creg(int reg,int mode) +{ + if (reg!=creg) { + clear_ptr_cache_reg(reg); + if (mode) + printf("\tmr %s,%s\n",register_name(reg),register_name(creg)); + free_register(creg); + creg = reg; + regs[creg]=1; + } +} + +void +set_freg(int reg,int mode) +{ + if (reg!=freg) { + if (mode) + printf("\tfmr %s,%s\n",fregister_name(reg),fregister_name(freg)); + free_fregister(freg); + freg = reg; + fregs[freg]=1; + } +} + +void +use_var(int arg) +{ + if (car(arg)==REGISTER) + regs[cadr(arg)]=USING_REG; + else if (car(arg)==DREGISTER) + fregs[cadr(arg)]=USING_REG; +} + +void +code_save_input_registers() +{ +#if 0 + 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; + + 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 = new_lvar(size_of_int); + t = INT; + reg += reg_offset; /* for duplicated floating point argument */ + } else if (tag==DREGISTER) { + /* fregs[reg]==INPUT_REG case should be considered */ + n->dsp = new_lvar(size_of_double); + t = DOUBLE; + reg_offset+=2; + } else + 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) { + free_register(reg); + } else if (tag==DREGISTER) { + free_fregister(reg); + } + } + my_func_args = 0; +#else + 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) { + /* fregs[reg]==INPUT_REG case should be considered */ + n->dsp = offset; + t = n->ty; + if(t==FLOAT) { offset+=size_of_float; reg_offset+=1; } + else if(t==DOUBLE) { offset+=size_of_double; reg_offset+=2; } + else error(-1); + } else { + offset += size(n->ty); + continue; + } + n->sc = LVAR; + lvar = list2(LVAR,n->dsp); + g_expr_u(assign_expr0(list2(LVAR,n->dsp),list3(tag,reg,(int)n),n->ty,t)); + if (tag==REGISTER) { + free_register(reg); + } else if (tag==DREGISTER) { + free_fregister(reg); + } + } + my_func_args = offset; +#endif +} + +int +simple_args(int e3) +{ + return + !contains_in_list(e3,FUNCTION) && + !contains_in_list(e3,CONV) && + !contains_in_list(e3,RSTRUCT) && + !contains_in_list(e3,SASS) + ; +} + +int +caller_arg_offset_v(int arg) +{ + return ARG_LVAR_OFFSET+arg*size_of_int; +} + +int +function(int e1) +{ + int e2,e3,e4,e5,nargs,t,r0,r1; + int arg,reg_arg,freg_arg,arg_assign; + int reg_arg_list=0,ret_type,special_lvar; + NMTBL *fn = 0; + int jmp = 0; + char *jrn; + + special_lvar = -1; + ret_type = cadddr(e1); + + e2 = cadr(e1); + if (car(e2) == FNAME) { + fn=(NMTBL *)cadr(e2); + } else { + jmp = get_register_var(0); + if (car(jmp)!=REGISTER) error(-1); + reg_arg_list = list2(jmp,reg_arg_list); + g_expr(e2); + code_register(creg,cadr(jmp)); + /* g_expr(assign_expr0(jmp,e2,INT,INT)); functions are lvalue */ + } + + /* now all input register vars are free */ + code_save_stacks(); + set_creg(CREG_REGISTER,0); + set_freg(FREG_FREGISTER,0); + + nargs = reg_arg = freg_arg = arg_assign = 0; + for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { + t=caddr(e3); + e4 = car(e3); + if(scalar(t)) { + if (reg_arg>=MAX_INPUT_REGISTER_VAR) { + arg = list2(LVAR,caller_arg_offset_v(nargs)); + } else if (!simple_args(e3) && cadr(e3)) { + arg = get_register_var(0); + arg_assign = list2( + assign_expr0(get_input_register_var(reg_arg,0,0),arg,t,t), + arg_assign); + } else { + arg = get_input_register_var(reg_arg,0,0); + } + use_var(arg); /* protect from input register free */ + reg_arg_list = list2(arg,reg_arg_list); + g_expr_u(assign_expr0(arg,e4,t,t)); + nargs ++ ; reg_arg++; + continue; + } else if (t==DOUBLE||t==FLOAT) { + if (reg_arg<MAX_INPUT_REGISTER_VAR) { + /* sigh... + printf requies floating value in integer registers + */ + 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,t,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=get_input_register_var(reg_arg+1,0,0); + use_var(r0); /* protect from input register free */ + use_var(r1); /* 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); + reg_arg += 2; + } + if (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_fregister_var(freg_arg,0,0),t,t), + arg_assign); + } + if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { + arg = list2(LVAR,caller_arg_offset_v(nargs)); + } else if (!simple_args(e3)) { + arg = get_fregister_var(0); + arg_assign = list2( + assign_expr0(get_input_fregister_var(freg_arg,0,0),arg,t,t), + arg_assign); + } else { + arg = get_input_fregister_var(freg_arg,0,0); + } + use_var(arg); /* protect from input register free */ + reg_arg_list = list2(arg,reg_arg_list); + g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */ + freg_arg++; + nargs += size(t)/size_of_int; + continue; + } else if (car(t)==STRUCT||car(t)==UNION) { + arg = list2(LVAR,caller_arg_offset_v(nargs)); + nargs += struct_push(e4,t,arg); + continue; + } else { + error(TYERR); + } + ++nargs; + } + 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)==DREGISTER) free_fregister(cadr(arg)); + else if (car(arg)==REGISTER) 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); + fregv[freg]=1; regv[creg]=0; + } else if (ret_type==VOID) { + fregv[freg]=0; regv[creg]=0; + } else { + set_creg(RET_REGISTER,0); + fregv[freg]=0; regv[creg]=1; + } + return ret_type; +} + +void +code_frame_pointer(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); +} + + +void +code_indirect_jmp(int e2) { + max_reg_var = REG_VAR_BASE-REG_VAR_MIN; + max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; + printf("\tmtctr %s\n",register_name(e2)); + printf("\tbctr\n"); +} + +int +rindirect(int e1) /* *(p +5 ) */ +{ + char *crn; + int e2,e3,e4,offset; + + offset=0; + e3 = cadr(e2 = cadr(e1)); + if (car(e2)==ADD) { + e4=caddr(e2); + if (car(e4)==CONST) { + offset=cadr(e4); + e2=e3; + } + } + g_expr(e2); + crn=register_name(creg); + switch (car(e1)) { + case FRINDIRECT: case DRINDIRECT: + printf("\t%s %s,%d(%s)\n",fload(car(e1)==DRINDIRECT), + fregister_name(freg),offset,crn); + regv[creg]=0; regv[freg]=1; + return DOUBLE; + case CRINDIRECT: + printf("\tlbz %s,%d(%s)\n",crn,offset,crn); + printf("\textsb %s,%s\n",crn,crn); + return CHAR; + case RINDIRECT: + printf("\tlwz %s,%d(%s)\n",crn,offset,crn); + return INT; + } + error(-1); return INT; +} + +void +code_assign_gvar(int e2,int creg,int byte) { + int r; + char *crn,*rrn; + r = get_ptr_cache((NMTBL*)cadr(e2)); + rrn=register_name(r); + crn=register_name(creg); + if (byte) { + printf("\tstb %s,0(%s)\n",crn,rrn); + } else { + printf("\tstw %s,0(%s)\n",crn,rrn); + } +} + +void +code_assign_lvar(int e2,int creg,int byte) { + char *crn; + crn=register_name(creg); + lvar_intro(e2); + if (byte) { + printf("\tstb %s,",crn); lvar(e2); + } else { + printf("\tstw %s,",crn); lvar(e2); + } +} + +void +code_assign_register(int e2,int byte,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=register_name(e2); + char *crn=register_name(creg); + + if (byte) { + printf("\tstb %s,0(%s)\n",crn,drn); + } else { + printf("\tstw %s,0(%s)\n",crn,drn); + } +} + + +void +code_register_assop(int e2,int op,int byte) { + int reg; + int xreg = creg; + creg = reg = e2; + tosop(op,xreg); + creg = xreg; + if (creg!=reg) + printf("\tmr %s,%s\n",register_name(creg),register_name(reg)); +} + + +void +code_assop(int op,int byte) { + char *xrn,*crn,*drn; + int xreg; + int edx = get_register(); if(!edx) error(-1); + xrn = register_name(xreg = emit_pop(0)); /* pop e3 value */ + regv[xreg]=regs[xreg]=1; + printf("# assop\n\tmr %s,%s\n",register_name(edx),register_name(creg)); + regv[edx]=1; + ld_indexx(byte,0,edx); + tosop(op,xreg); + crn = register_name(creg); + drn = register_name(edx); + if (byte) { + printf("\tstb %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 oreg) +{ + int dx; + char *orn,*crn,*drn; + + if(oreg==-1) { + error(-1); + } else if (oreg<= -REG_LVAR_OFFSET) { + dx = get_register(); if (dx<0) error(-1); + code_rlvar(oreg+REG_LVAR_OFFSET,dx); + oreg = dx; + regv[oreg]=1; + } + + switch(op) { + case LSHIFT: + case ULSHIFT: + shift("slw",oreg); + return; + case RSHIFT: + shift("srw",oreg); + return; + case URSHIFT: + shift("sraw",oreg); + 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 cr0,%s,%s\n",crn,orn); + break; + case BAND: + printf("\tand %s,%s,%s\n",crn,crn,orn); + break; + case EOR: + printf("\txor %s,%s,%s\n",crn,crn,orn); + break; + case BOR: + printf("\tor %s,%s,%s\n",crn,crn,orn); + break; + case MUL: + printf("\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); + free_register(dx); + 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); + free_register(dx); + break; + default: + error(-1); + } + if(oreg!=creg) free_register(oreg); +} + + +void +shift(char *op, int reg) +{ + char *crn = register_name(creg); + char *rrn = register_name(reg); + printf("\t%s %s,%s,%s\n",op,crn,rrn,crn); +} + +void +ld_indexx(int byte, int n, int xreg) +{ + char *crn = register_name(creg); + if (byte) { + printf("\tlbz %s,%d(%s)\n",register_name(creg),n, + register_name(xreg)); + printf("\textsb %s,%s\n",crn,crn); + } else + printf("\tlwz %s,%d(%s)\n",register_name(creg),n, + register_name(xreg)); +} + +int +code_csvalue() +{ + return creg; +} + +void +code_cmpdimm(int e, int csreg) +{ + /* used in dosiwtch() */ + if(chk) return; + printf("\tcmpwi cr0,%s,%d\n",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, char *s,int t) +{ + g_expr(list3(CMP,cadr(e1),caddr(e1))); + printf("\tb%s cr0,L_%d\n",s,l1); +} + + +void +jcond(int l, char cond) +{ + if (chk) return; + printf("\tb%s cr0,L_%d\n",cond?"ne":"eq",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_creg(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() +{ + set_creg(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,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 { + set_creg(RET_REGISTER,mode); + } +} + +void +code_set_fixed_creg(int mode,int type) { + if (type==FLOAT||type==DOUBLE) { + if (cond_freg== -1) { + cond_freg = get_fregister_var(0); + if(car(cond_freg)!=DREGISTER) error(-1); + } + set_freg(cadr(cond_freg),mode); + } else { + if (cond_reg== -1) { + cond_reg = get_register_var(0); + if(car(cond_reg)!=REGISTER) error(-1); + } + set_creg(cadr(cond_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; + double d; + float f; + char *name; + name = n->nm; + if(mode!=GDECL) { + 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) { + printf("\t.byte %d\n",cadr(e)); + if (data_alignment>0) + data_alignment++; + gpc += 1; + } else if (t==SHORT) { + printf("\t.word %d\n",cadr(e)); + if (data_alignment>0) data_alignment++; + gpc += 2; + } else { + printf("\t.long %d\n",cadr(e)); + gpc += size_of_int; + } + } 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); + } 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); + } +} + +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; + } + printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); + } + } +} + +void +text_mode(void) +{ + if (output_mode!=TEXT_EMIT_MODE) { + printf(".text\n"); + printf("\t.align 2\n"); + output_mode = TEXT_EMIT_MODE; + } +} + +void +data_mode(char *name) +{ + if (output_mode!=DATA_EMIT_MODE) { + printf(".data\n"); + output_mode = DATA_EMIT_MODE; + } +/* + if (name) + printf("\t.type\t%s,@object\n",name); + */ +} + +/* 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_fregister(int e2) +{ + char *frn,*rrn,*grn; + int greg,r; + grn = register_name(greg = get_fregister()); + frn = register_name(freg); + 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 cr0,%s,%s\n",grn,frn); + free_fregister(greg); + fregv[freg]=0; + return; +} + +void +code_fregister(int e2,int freg) +{ + if (freg!=e2) + printf("\tfmr %s,%s\n",fregister_name(freg),fregister_name(e2)); + fregv[freg]=1; +} + +void code_dassign_gvar(int e2,int freg,int d) +{ + int r; + r = get_ptr_cache((NMTBL*)cadr(e2)); + printf("\t%s %s,0(%s)\n",fstore(d),fregister_name(freg),register_name(r)); + fregv[freg]=1; +} + +void code_dassign_lvar(int e2,int freg,int d) +{ + lvar_intro(e2); + printf("\t%s %s,",fstore(d),fregister_name(freg)); + lvar(e2); + fregv[freg]=1; +} + +void code_dassign(int e2,int freg,int d) +{ + printf("\t%s %s,0(%s)\n",fstore(d),fregister_name(freg),register_name(e2)); + fregv[freg]=1; +} + +void +code_dassign_fregister(int e2,int d,int 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]; +} + +void code_dconst(int e2,int freg) +{ + int lb; + double d = dcadr(e2); + int r; + char *rrn,*frn; + frn = fregister_name(freg); + if (d==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 (d==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())); + printf(" \t.data\n\t.align 3\n"); + lb=fwdlabel(); + printf("L_%d:\n",lb); + printf("\t.long\t0x%x,0x%x\n",code_d2(d),code_d1(d)); + 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); + printf("\tlfd %s,0(%s)\n",frn,rrn); + free_register(r); + fregv[freg]=1; +} + +void code_dneg(int freg) +{ + char *frn = fregister_name(freg); + printf("\tfneg %s,%s\n",frn,frn); +} + +void code_d2i(int freg,int creg) +{ + char *frn = fregister_name(freg); + char *crn = register_name(creg); + int e2 = new_lvar(size_of_double); + 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); + fregs[freg]=0; + regs[creg]=1; +} + +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(int creg,int freg) +{ + i2d_lib_used = 1; + clear_ptr_cache(); + code_save_stacks(); + set_creg(RET_REGISTER,1); + printf("\tbl i2d_\n"); + set_freg(RET_FREGISTER,0); + fregs[freg]=1; + regs[creg]=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(int freg,int creg) +{ + code_save_stacks(); + clear_ptr_cache(); + d2u_lib_used=1; + set_freg(RET_FREGISTER,1); + printf("\tbl d2u_\n"); + set_creg(RET_REGISTER,0); + fregs[freg]=1; + regs[creg]=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(int creg,int freg) +{ + char *frn; + char *crn; + u2d_lib_used = 1; + code_save_stacks(); + clear_ptr_cache(); + frn = fregister_name(freg); + crn = register_name(creg); + + printf("\tmr r3,%s\n",crn); + printf("\tbl u2d_\n"); + printf("\tfmr %s,f1\n",frn); + fregs[freg]=1; + regs[creg]=0; +} + +void code_drgvar(int e2,int d,int freg) +{ + int r; + r = get_ptr_cache((NMTBL*)cadr(e2)); + printf("\t%s %s,0(%s)\n",fload(d),fregister_name(freg),register_name(r)); + fregv[freg]=1; +} + + +void code_drlvar(int e2,int d,int freg) +{ + lvar_intro(e2); + printf("\t%s %s,",fload(d),fregister_name(freg)); lvar(e2); + fregv[freg]=1; +} + +void code_cmp_drgvar(int e2) +{ + int r; + char *frn=fregister_name(freg); + int g=get_fregister(); + char *grn=fregister_name(g); + r = get_ptr_cache((NMTBL*)cadr(e2)); + printf("\t%s %s,0(%s)\n",fload(1),grn,register_name(r)); + printf("\tfcmpu cr0,%s,%s\n",frn,grn); + free_fregister(g); + fregv[freg]=0; +} + +void code_cmp_drlvar(int e2) +{ + char *frn=fregister_name(freg); + int g=get_fregister(); + char *grn=fregister_name(g); + + lvar_intro(e2); + printf("\t%s %s,",fload(1),grn); lvar(e2); + printf("\tfcmpu cr0,%s,%s\n",frn,grn); + free_fregister(g); + fregv[freg]=0; +} + +void dtosop(int op,int e1) +{ + char *opn=""; + char *frn=fregister_name(freg); + char *grn=fregister_name(e1); + fregv[freg]=1; + switch(op) { + case DADD: opn="fadd"; break; + case DSUB: opn="fsub"; break; + case DDIV: opn="fdiv"; break; + case DMUL: opn="fmul"; break; + case DCMP: + printf("\tfcmpu cr0,%s,%s\n",frn,grn); + free_fregister(e1); + return; + case DCMPGE: + printf("\tfcmpu cr7,%s,%s\n",frn,grn); + free_fregister(e1); + return; + } + printf("\t%s %s,%s,%s\n",opn,frn,frn,grn); + free_fregister(e1); +} + +void +code_dassop(int op,int d) { + /* we have lvalue in creg, applied floating value is in freg */ + char *frn=fregister_name(freg); + int xreg=emit_dpop(0); + char *crn=register_name(creg); + + printf("\t%s %s,0(%s)\n",fload(d),frn,crn); + dtosop(op,xreg); + printf("\t%s %s,0(%s)\n",fstore(d),frn,crn); + emit_dpop_free(xreg); + fregv[freg]=1; +} + + +void +code_dpreinc(int e1,int e2,int d,int reg) { + char *frn; + char *crn; + int g; + char *grn,*drn; + int r; + r = get_ptr_cache(&float_one); + float_one_lib_used=1; + + g_expr(e2); + + crn=register_name(creg); + frn=fregister_name(freg); + drn=register_name(r); + grn=fregister_name(g=get_fregister()); + + printf("\t%s %s,0(%s)\n",fload(d),frn,crn); + printf("\tlfs %s,0(%s)\n",grn,drn); + if (caddr(e1)>0) + printf("\tfadd %s,%s,%s\n",frn,frn,grn); + else + printf("\tfsub %s,%s,%s\n",frn,frn,grn); + printf("\t%s %s,0(%s)\n",fstore(d),frn,crn); + free_fregister(g); + fregv[freg]=1; +} + +void +code_dpostinc(int e1,int e2,int d,int reg) { + char *frn; + char *crn; + int g; + char *grn,*drn; + int r; + r = get_ptr_cache(&float_one); + float_one_lib_used=1; + + g_expr(e2); + + crn=register_name(creg); + frn=fregister_name(freg); + drn=register_name(r); + grn=fregister_name(g=get_fregister()); + + printf("\t%s %s,0(%s)\n",fload(d),frn,crn); + printf("\tlfs %s,0(%s)\n",grn,drn); + if (caddr(e1)>0) + printf("\tfadd %s,%s,%s\n",grn,frn,grn); + else + printf("\tfsub %s,%s,%s\n",grn,frn,grn); + printf("\t%s %s,0(%s)\n",fstore(d),grn,crn); + free_fregister(g); + fregv[freg]=1; +} + +void +drexpr(int e1, int e2,int l1, int op) +{ + g_expr(list3(((op==DOP+GE)?DCMPGE:DCMP),e1,e2)); + switch(op) { + case DOP+GE: + printf("\tcror 2,29,30\n"); + printf("\tbne\tcr0,L_%d\n",l1); + break; + case DOP+GT: + printf("\tble\tcr0,L_%d\n",l1); + break; + case DOP+EQ: + printf("\tbne\tcr0,L_%d\n",l1); + break; + case DOP+NEQ: + printf("\tbeq\tcr0,L_%d\n",l1); + break; + } +} + +int emit_dpop(int e1) +{ + int xreg,reg; + xreg=pop_fregister(); + if (xreg<= -REG_LVAR_OFFSET) { + reg = get_fregister(); + code_drlvar(REG_LVAR_OFFSET+xreg,1,reg); + free_lvar(REG_LVAR_OFFSET+xreg); + fregv[reg]=1; xreg=reg; + } + return xreg; +} + +void emit_dpop_free(int e1) +{ + free_fregister(e1); +} + +void emit_dpush() +{ + int new_reg; + if (freg_sp>MAX_MAX) error(-1); + new_reg = get_fregister(); + freg_stack[freg_sp++] = freg; /* push するかわりにレジスタを使う */ + freg = new_reg; + fregv[freg]=1; +} + +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; + } + } + 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; + } + } +} + +void +emit_lib(char *p[]) +{ + while(*p) { + printf("%s\n",*p++); + } +} + +void +code_closing() +{ + 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); + global_table(); + /* printf("\t.ident \"Micro-C compiled\"\n"); */ +} + +/* end */ +