Mercurial > hg > CbC > old > device
view mc-code-powerpc.c @ 93:8f5d61239b93
*** empty log message ***
author | kono |
---|---|
date | Sun, 09 Mar 2003 18:31:00 +0900 |
parents | e7f8515ba882 |
children | 185d2cc6a3a9 |
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" #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 void use_register(int virt, int real, int move); static void use_register_var(int i); static int output_mode = TEXT_EMIT_MODE; static int data_alignment = 0; static int code_disp_label; static int func_disp_label; /* -16 -8 local2 <-- r30 -12 -4 local1 -8 8 arg3 -4 4 arg2 0 0 arg1 local2 -20 4 0 (r5) local1 <-- -16 0 local variable 0 (r4) -12 <- disp_offset %ebp r30 (sp) -8 0 <- r1 r1 (fp) 8 <- arg_offset arg1 8 0 arg2 12 4 see enter/enter1/leave see code_enter r0 link register r30 stack pointer r31 0 r1 frame pointer */ int arg_offset = 8; int disp_offset = -12; int func_disp_offset = -12; int code_disp_offset = 0; int jump_offset = 0; int size_of_int = 4; int size_of_float = 4; int size_of_double = 8; int size_of_longlong = 8; int endian = 0; int MAX_REGISTER=30; /* PowerPCのレジスタを10個まで使う*/ int REAL_MAX_REGISTER=32; /* PowerPCのレジスタが32ということ*/ int MAX_REGISTGER_VAR=30-10; int MAX_FREGISTER=30; #define REG_fp 1 #define REG_sp 30 #define REG_VAR_BASE 30 #define REG_ARG_BASE 3 #define REG_ARG_MAX 10 #define FREG_ARG_BASE 1 #define FREG_ARG_MAX 13 int reg_sp=REG_sp; 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" }; static char *creg_name[] = { "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7" }; void code_init(void) { arg_offset = 8; func_disp_offset = -12; disp_offset = -12; size_of_int = 4; endian = 1; } #define register_name(i) reg_name[i] void gexpr_code_init(void){ regv[creg]=0; } int virtual(int real); char * fload(int d); int code_d1(double d); int code_d2(double d); int get_register(void) { /* 使われていないレジスタを調べる */ int i; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i]) { /* 使われていないなら */ regs[i]=1; /* そのレジスタを使うことを宣言し */ return i; /* その場所を表す番号を返す */ } } return -1; /* 空いている場所がないなら、それを表す -1 を返す */ } int pop_register(void) { /* レジスタから値を取り出す */ return reg_stack[--reg_sp]; } int stack_used(void) { return reg_stack[--reg_sp]<0; } void emit_pop_free(int xreg) { if (xreg==dreg) { regv[dreg]=0; } else if (xreg!=-1) { free_register(xreg); } } void free_register(int i) { /* いらなくなったレジスタを開放 */ regv[i]=regs[i]=0; } int register_full(void) { int i; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i]) { return 0; } } return 1; } int free_register_count(void) { int i,count; count = 0; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i] && ! regv[i]) count++; } return count; } void free_all_register(void) { int i; for(i=0;i<MAX_REGISTER;i++) { regs[i]=regv[i]=0; } creg = get_register(); dreg = get_register(); return; } void use_register_var(int i) { regv[i]=1; } void set_register_var() { } void code_arg_register(int args) { NMTBL *n; if (args) { /* process in reverse order */ n = (NMTBL*)caddr(args); if(n->sc==REGISTER) { if ((n->dsp = get_register_var()) <0) { error(-1); return; } use_register_var(n->dsp); /* it has now value in it */ } code_arg_register(cadr(args)); } } void register_usage(char *s) { int i; if (chk) return; printf("# %d: %s:",lineno,s); printf(" creg=%s dreg=%s ",register_name(creg),register_name(dreg)); for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); } printf(":"); for(i=0;i<MAX_REGISTER;i++) { printf("%d",regv[i]); } #if 0 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]); } text_mode(); gexpr_code_init(); register_usage("gexpr_init"); } void emit_init(void) { int i; for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; regv[i]=0;rname[i]=i;} free_all_register(); init_ptr_cache(); reg_sp = 0; text_mode(); } int register_var(int r) { return virtual(REG_VAR_BASE-r); } int get_register_var(void) { int i; for(i=0;i<MAX_REGISTGER_VAR;i++) { if (REG_VAR_BASE-i<=REG_ARG_MAX) return -1; if (! regs[REG_VAR_BASE-i]) { /* 使われていないなら */ regs[REG_VAR_BASE-i]=1; /* そのレジスタを使うことを宣言し */ regv[REG_VAR_BASE-i]=0; return i; /* その場所を表す番号を返す */ } } return -1; } void emit_push(void) { int new_reg; new_reg = get_register(); if(new_reg<0) { /* もうレジスタがない */ if (reg_sp>=MAX_MAX) error(-1); reg_stack[reg_sp++] = -1; printf("\tstwu %s,-%d(%s)\n",register_name(creg), size_of_int,register_name(reg_sp)); /* creg is used soon, don't regv[creg]=0 */ } else { reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ creg = new_reg; regv[creg]=1; } } int emit_pop(int type) { int xreg; if ((xreg=pop_register())==-1) { xreg=get_register(); if(!xreg) error(-1); printf("\tlwz %s,(%s)\n",register_name(xreg),register_name(reg_sp)); printf("\taddis %s,%s,%d\n", register_name(reg_sp),register_name(reg_sp),size_of_int); regv[xreg]=1; } return xreg; } static char *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); } } int 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(char *name) { int r; int ptcptr=ptr_cache; int cache; int i = 0; int g = (int)name; int p,p1; 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; else r=creg; } rrn = register_name(r); printf("\taddis %s,r31,ha16(L_%s$non_lazy_ptr-%s)\n", rrn,(char *)g,code_base); printf("\tlzw %s,lo16(L_%s$non_lazy_ptr-%s)(%s)\n", rrn,(char *)g,code_base,rrn); return r; } void code_label(int labelno) { clear_ptr_cache(); printf("_%d:\n",labelno); } void code_gvar(int e1) { int r; r = get_ptr_cache((char*)caddr(e1)); if(r!=creg) printf("\tmr %s,%s\n",register_name(creg),register_name(r)); return; } void code_rgvar(int e1) { printf("\tlwz %s,(%s)\n",register_name(creg), register_name(get_ptr_cache((char*)caddr(e1)))); } void code_crgvar(e1){ printf("\tlbz %s,(%s)\n",register_name(creg), register_name(get_ptr_cache((char*)caddr(e1)))); printf("\textsb %s,%s\n",register_name(creg),register_name(creg)); } void code_lvar(int e2) { printf("\tla %s,%d(r1),%s\n",register_name(creg),e2); } void code_register(int e2) { if (creg!=e2) printf("\tmr %s,%s\n",register_name(creg),register_name(e2)); } void code_rlvar(int e2) { printf("\tlwz %s,%d(r1),%s\n",register_name(creg),e2); } void code_crlvar(int e2) { printf("\tlbz %s,%d(r1),%s\n",register_name(creg),e2); printf("\textsb %s,%s\n",register_name(creg),register_name(creg)); } void code_fname(char *e2) { int r; r = get_ptr_cache(e2); if(r!=creg) printf("\tmr %s,%s\n",register_name(creg),register_name(e2)); return; } void code_const(int e2) { 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); } } void code_neg() { printf("\tneg %s,%s\n", register_name(creg), register_name(creg)); } void code_not() { printf("\tnor %s,%s,%s\n", register_name(creg), register_name(creg),register_name(creg)); } void code_lnot() { 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) { char *xrn,*drn; int i,dreg; if (car(e2)==REGISTER) { printf("\taddi %s,%s,%d\n", register_name(cadr(e2))); printf("\tmr %s,%s\n",register_name(cadr(creg)),register_name(e2)); return; } g_expr(e2); xrn = register_name(creg); dreg=get_register(); if (!dreg) error(-1); drn = register_name(dreg); printf("\tlwz %s,(%s)\n",drn,xrn); printf("\taddi %s,%s,%d\n",drn,drn,caddr(e1)); printf("\tstw %s,(%s)\n",drn,xrn); i=creg;creg=dreg;dreg=i; regv[creg=1]; free_register(dreg); } void code_postinc(int e1,int e2) { char *xrn,*crn,*nrn; int dreg,nreg; if (car(e2)==REGISTER) { printf("\tmr %s,%s\n",register_name(creg),register_name(cadr(e2))); printf("\taddi %s,%s,%d\n", register_name(cadr(e2)),register_name(cadr(e2))); return; } g_expr(e2); 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,(%s)\n",xrn,crn); printf("\taddi %s,%s,%d\n",nrn,xrn,caddr(e1)); printf("\tstw %s,(%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) { char *xrn,*crn; int i,nreg,dreg; if (car(e2)==REGISTER) { printf("\tlbz %s,(%s)\n",register_name(creg),register_name(cadr(e2))); printf("\textsb %s,%s\n",register_name(creg),register_name(creg)); printf("\taddi %s,%s,%d\n", register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1)); 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,(%s)\n",xrn,crn); printf("\tlbz %s,(%s)\n",nrn,xrn); printf("\textsb %s,%s\n",nrn,nrn); printf("\taddi %s,%s,%d\n", xrn,xrn); printf("\tstw %s,(%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) { char *xrn,*crn; int i,nreg,dreg; if (car(e2)==REGISTER) { printf("\tlbzu %s,%d(%s)\n",register_name(creg),caddr(e1),register_name(cadr(e2))); printf("\textsb %s,%s\n",register_name(creg),register_name(creg)); 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,(%s)\n",xrn,crn); printf("\tlbzu %s,%d(%s)\n",nrn,caddr(e1),xrn); printf("\tstw %s,(%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) { char *xrn,*crn; int i,nreg,dreg; if (car(e2)==REGISTER) { crn=register_name(creg); xrn=register_name(cadr(e2)); printf("\tlbz %s,(%s)\n",crn,xrn); printf("\taddi %s,%s,%d\n",xrn,xrn,caddr(e1)); printf("\textsb %s,%s\n",crn,crn); 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,(%s)\n",xrn,crn); printf("\tlbz %s,(%s)\n",nrn,xrn); printf("\taddi %s,%s,%d\n",xrn,xrn,caddr(e1)); printf("\tstw %s,(%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) { char *xrn,*crn; int i,nreg,dreg; if (car(e2)==REGISTER) { crn=register_name(creg); xrn=register_name(cadr(e2)); printf("\tlbzu %s,%d(%s)\n",crn,caddr(e1),xrn); printf("\textsb %s,%s\n",crn,crn); 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,(%s)\n",xrn,crn); printf("\tlbzu %s,%d(%s)\n",nrn,caddr(e1),xrn); printf("\tstw %s,(%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 r; printf("\taddis %s,r31,ha16(_%d-%s)\n",crn,retcont,code_base); printf("\tla %s,lo16(_%d-%s)(%s)\n",crn,retcont,code_base,crn); } void code_environment() { printf("\tmr %s,r1\n",register_name(creg)); } 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((char *)caddr(e1)); printf("\tlbz %s,(%s)\n",crn,register_name(r)); printf("\tcmpwi cr0,%s,0\n",crn); } void code_cmp_crlvar(int e1) { char *crn = register_name(creg); printf("\tlbz %s,%d(r1)\n",crn,e1); printf("\tcmpwi cr0,%s,0\n",crn); } void code_cmp_rgvar(int e1) { int r; char *crn = register_name(creg); r = get_ptr_cache((char *)caddr(e1)); printf("\tlwz %s,(%s)\n",crn,register_name(r)); code_cmp_register(creg); } void code_cmp_rlvar(int e1) { char *crn = register_name(creg); printf("\tlwz %s,%d(r1)\n",crn,e1); code_cmp_register(creg); } 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==34) printf("%c%c",92,34); else printf("%c",*s); s++; } printf("\\0%c\n",34); } void string(int e1) { char *s; int i,lb; s=(char *)cadr(e1); printf(".data\t.cstring\n\t.align 2\n"); lb=fwdlabel(); printf("_%d:\n",lb); ascii(s); if (output_mode==TEXT_EMIT_MODE) { printf(".text\n"); } else { text_mode(); } printf("\taddis %s,r31,ha16(_%d-%s)\n",crn,lb,code_base); printf("\tla %s,lo16(_%d-%s)(%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 *bcopy = "bcopy"; int dreg = get_regiter(); 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; } if (det) { printf("\tli r5,%d\n",length); printf("\tmr r4,%s\n",trn); printf("\tmr r3,%s\n",frn); printf("\tbl L_%s$stub\n",bcopy); regist_extern_function(bcopy); 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 length,save,count; int dreg; 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_regiter(); if (!dreg) error(-1); drn = register_name(dreg); crn = register_name(dreg); srn = register_name(reg_sp); for(count=0;length<MAX_COPY_LEN;count++,length-=size_of_int) { if (length==0) { 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); } } printf("\taddis %s,%s,ha16(%d)\n",srn,srn,length); printf("\taddi %s,%s,lo16(%d)\n",srn,srn,length); /* downward direction copy */ printf("\tmr %s,%s\n",drn,srn); emit_copy(creg,dreg,length,0,0,1); /* we have value in creg, it may be changed */ if (dreg!=creg) free_register(dreg); return length/size_of_int; } int arg_offset(int arg) { } void function(int e1) { int e2,e3,e4,e5,nargs,t; int reg_arg,freg_arg; NMTBL *n; e2 = cadr(e1); nargs = 0; reg_arg = REG_ARG_BASE; freg_arg = FREG_ARG_BASE; for (e3 = caddr(e1); e3; e3 = cadr(e3)) { t=caddr(e3); n=(NMTBL *)(e5=(cadr(e4 = car(e3)))); if(scalar(t)) { g_expr(e4); if (reg_arg<REG_ARG_MAX) printf("\tmr %s,%s\n",register_name(reg_arg), register_name(creg)); else { printf("\tstw %s,%d(r1)\n",register_name(creg), arg_offset(nargs)); } nargs ++ ; reg_arg++; } else if (t==DOUBLE||t==FLOAT) { g_expr(e4); nargs += size_of_double/size_of_int; if (fregv[freg_arg]) save_freg(freg_arg); fregv[freg_arg]=1; if (freg_arg<FREG_ARG_MAX) printf("\tmr %s,%s\n",register_name(reg_arg++), register_name(freg)); else if(t==DOUBLE) { printf("\tstfd %s,%d(r1)\n",register_name(freg), arg_offset(nargs)); nargs+=size_of_double/size_of_int; } else { printf("\tstfs %s,%d(r1)\n",register_name(freg), arg_offset(nargs)); nargs+=size_of_float/size_of_int; } freg_arg++; continue; } else if (car(t)==STRUCT||car(t)==UNION) { nargs += struct_push(e4,t); continue; } else { error(TYERR); } ++nargs; } if (car(e2) == FNAME) { n=(NMTBL *)cadr(e2); regv[creg]=0; } else { g_expr(e2); regv[creg]=1; } if (car(e2) == FNAME) { printf("\tbl\tL_%s$stub\n",n->nm); } else { jmp=get_tmp_register(); jrn = register_name(jmp); printf("\tmr %s,%s\n",jrn,crn); printf("\tmtctr %s\n",jrn); printf("\tbctrl\n"); free_register(jmp); } regv[creg]=1; clear_ptr_cache(); } void code_frame_pointer(int e3) { printf("\tmovl %s,r1\n",register_name(e3)); } void code_fix_frame_pointer(int disp_offset) { printf("\tla r1,%d(r1)\n",disp_offset); } void code_jmp(char *s) { printf("\tb L_%s$stub\n",s); } void code_indirect_jmp(int e2) { printf("\tmtctr %s\n",register_name(e2)); printf("\tbctr\n"); } void rindirect(int e1) /* *(p +5 ) */ { char *op,*crn; int e2,e3,byte; e3 = cadr(e2 = cadr(e1)); g_expr(e2); crn=register_name(creg); switch (car(e1)) { case FRINDIRECT: case DRINDIRECT: printf("\t%s %s,(%s)\n",fload(car(e1)==DRINDIRECT), register_name(freg),crn); regv[creg]=0; regv[freg]=1; break; case CRINDIRECT: printf("\tlbz %s,(%s)\n",crn,crn); printf("\textsb %s,%s\n",crn,crn); break; case RINDIRECT: printf("\tlwz %s,(%s)\n",crn,crn); break; } } void code_assign_gvar(int e2,int byte) { int r; char *crn,*rrn; r = get_ptr_cache((char*)caddr(e2)); rrn=register_name(r); crn=register_name(creg); if (byte) { printf("\tstb %s,(%s)\n",crn,rrn); } else { printf("\tstw %s,(%s)\n",crn,rrn); } } void code_assign_lvar(int e2,int byte) { char *crn; crn=register_name(creg); if (byte) { printf("\tstb %s,%d(r1)\n",crn,e2); } else { printf("\tstw %s,%d(r1)\n",crn,e2); } } void code_assign_register(int e2,int byte) { printf("\tmr %s,%s\n",register_name(e2),register_name(creg)); } void code_assign(int e2,int byte) { char *drn=register_name(dreg); if (byte) { printf("\tstb %s,(%s)\n",crn,drn); } else { printf("\tstw %s,(%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; 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("\tmovl %s,%s # assop \n",register_name(creg),register_name(edx)); regv[edx]=1; ld_indexx(byte,0,edx); tosop(op,xreg); crn = register_name(creg); drn = register_name(edx); if (byte) { printf("\tstb %s,(%s)\n",crn,drn); } else { printf("\tstw %s,(%s)\n",crn,drn); } free_register(edx); emit_pop_free(xreg); } void tosop(int op,int oreg) { int dx; char *orn,*crn; 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,orn,crn); break; case SUB: printf("\tsub %s,%s,%s\n",crn,orn,crn); break; case BAND: printf("\tand %s,%s,%s\n",crn,orn,crn); break; case EOR: printf("\txor %s,%s,%s\n",crn,orn,crn); break; case BOR: printf("\torl %s,%s,%s\n",crn,orn,crn); break; case MUL: case UMUL: printf("\t%mullw %s,%s,%s\n",crn,orn,crn); break; case DIV: printf("\t%divw %s,%s,%s\n",crn,orn,crn); break; case UDIV: printf("\t%divwu %s,%s,%s\n",crn,orn,crn); break; case MOD: dx=get_register(); drn = register_name(drn); printf("\t%divwu %s,%s,%s\n",drn,orn,crn); printf("\t%mullw %s,%s,%s\n",drn,drn,crn); printf("\t%subf %s,%s,%s\n",drn,drn,orn); free_register(creg); creg=dx; break; case UMOD: dx=get_register(); drn = register_name(drn); printf("\t%divwu %s,%s,%s\n",drn,orn,crn); printf("\t%mullw %s,%s,%s\n",drn,drn,crn); printf("\t%subf %s,%s,%s\n",drn,drn,orn); free_register(creg); creg=dx; break; } if(oreg!=cre) 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 *op; if (byte) { printf("\tlbz %s,%d(%s),%s\n",register_name(creg),n, register_name(xreg)); printf("\textsb %s,%s\n",crn,crn); } else printf("\tlwz %s,%d(%s),%s\n",register_name(creg),n, register_name(xreg)); } void cmpdimm(int e, int csreg) { /* used in dosiwtch() */ if(chk) return; printf("\tcmpw 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 code_closing() { global_table(); printf("\t.ident \"Micro-C compiled\"\n"); } void rexpr(int e1, int l1, char *s) { g_expr(list3(CMP,cadr(e1),caddr(e1))); printf("\tb%s cr0,_%d\n",s,l1); } void jcond(int l, char cond) { if (chk) return; printf("\tb%s cr0,_%d\n",cond?"ne":"eq",l); } void jmp(int l) { control=0; if (chk) return; printf("\tb\t_%d\n",l); } void gen_comment(char *s) { if (chk) return; printf("## %s",s); } void code_enter(char *name) { printf("\t.align 4\n"); if (stmode!=STATIC) printf(".globl %s\n",name); printf("\t.type\t%s,@function\n",name); printf("%s:\n",name); } void code_enter1(int args) { code_disp_label=fwdlabel(); printf("\tlea _%d(%%ebp),%%esp\n",code_disp_label); printf("## args %d disp %d code_arg_offset=%d code_disp_offset=%d\n",args,disp,code_arg_offset,code_disp_offset); } void code_leave(char *name) { disp&= -size_of_int; printf("\t.set _%d,%d\n",code_disp_label,disp+code_disp_offset); printf("_%d:\n",labelno); printf("\t.size\t%s,_%d-%s\n",name,labelno,name); local_table(); labelno++; free_all_register(); } void enter(char *name) { printf("\t.align 2\n"); if (stmode!=STATIC) printf(".globl %s\n",name); printf("%s:\n",name); printf("\t.type\t%s,@function\n",name); printf("\tpushl %%ebp\n"); printf("\tmovl %%esp,%%ebp\n"); printf("\tpushl %%ebx\n"); printf("\tpushl %%esi\n"); printf("\tpushl %%edi\n"); } void enter1() { func_disp_label=fwdlabel(); printf("\tlea _%d(%%ebp),%%esp\n",func_disp_label); /* if(disp) printf("\tsubl $%d,%%esp\n",-disp); */ } void leave(int control, char *name) { if (control) use_register(creg,REG_EAX,1); if (retcont) { if (control) jmp(retlabel); fwddef(retcont); use_register(creg,REG_EAX,0); printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg)); /* printf("\tleave\n"); */ } fwddef(retlabel); /* use_register(creg,REG_EAX,0); too late */ /* if(disp) printf("\taddl $%d,%%esp\n",-disp); */ disp &= -size_of_int; printf("\tlea %d(%%ebp),%%esp\n",disp_offset); printf("\tpopl %%edi\n"); printf("\tpopl %%esi\n"); printf("\tpopl %%ebx\n"); printf("\tleave\n"); printf("\tret\n"); printf("\t.set _%d,%d\n",func_disp_label,disp+disp_offset); printf("_%d:\n",labelno); printf("\t.size\t%s,_%d-%s\n",name,labelno,name); local_table(); labelno++; free_all_register(); } void code_set_fixed_creg(int mode) { creg=11; } 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_d1(d),code_d2(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",(char *)caddr(cadr(e))); } else if(car(e)==FNAME) { 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 _%d\n",l); printf(".section\t.rodata\n"); printf("_%d:\n",l); output_mode = RODATA_EMIT_MODE; } ascii((char *)cadr(e)); } else error(TYERR); } } void emit_data_closing(NMTBL *n) { int lb; if (chk) return; if (mode==GDECL) { data_mode(0); lb=fwdlabel(); printf("_%d:\n",lb); printf("\t.size\t%s,_%d-%s\n",n->nm,lb,n->nm); } } void global_table(void) { NMTBL *n; int init; init=0; for(n=ntable;n < &ntable[GSYMS];n++) { if (n->sc == GVAR && n->dsp != -1) { /* n->dsp = -1 means initialized global */ if (init==0) { data_mode(0); init=1; } printf(".comm %s,%d\n",n->nm,size(n->ty)); } } } 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); } int lvar(int l) { if (fnptr->sc==CODE) { return l+code_disp_offset; } else if (l<0) { return l+disp_offset; } else { return l+arg_offset; } } /* floating point */ char * fstore(int d) { return (d?"stfd":"stfs"); } char * fload(int d) { return d?"lfd":"lfs"; } void code_dassign_gvar(int e2,int d) { int r; r = get_ptr_cache((char*)caddr(e1)); printf("\t%s %s,(%s)\n",fstore(d),register_name(freg),register_name(r)); } void code_dassign_lvar(int e2,int d) { printf("\t%s %s,%d(r1)\n",fstore(d),register_name(creg),e2); } void code_dassign(int e2,int d) { printf("\t%s %s,(%s)\n",fstore(d),register_name(creg),register_name(e2)); } 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 lb; double d = dcadr(e2); int r; char *rrn; rrn = register_name((r=get_register())); if (d==0.0) { printf("\tfldz\n"); return; } if (d==1.0) { printf("\tfld1\n"); return; } printf(" \t.section\t.rodata\n\t.align 8\n"); lb=fwdlabel(); printf("_%d:\n",lb); printf("\t.long\t0x%x,0x%x\n",code_d1(d),code_d2(d)); if (output_mode==TEXT_EMIT_MODE) { printf(".text\n"); } else { text_mode(); } printf("\taddis %s,r31,ha16(_%d-%s)\n",rrn,lb,code_base); printf("\tla %s,lo16(_%d-%s)(%s)\n",rrn,lb,code_base,rrn); printf("\tlfd %s,%(s)\n",register_name(freg),rrn); free_register(r); } void code_dneg() { char *frn = register_name(freg); printf("\tfneg %s,%s\n",freg); } void code_d2i() { char *frn = register_name(freg); disp-=size_of_double; printf("\tfctiwz %s,%s\n",frn,frn); printf("\tstfd %s,%d(r1)\n",disp); printf("\tlwz %s,%d(r1)\n",crn,disp+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(r1)", " lis r0,0x4330", " stw r0,-32(r1)", " lfd f0,-32(r1)", " addis r9,r10,ha16(__i2dLC0-__i2dL1$pb)", " lfd f1,lo16(__i2dLC0-__i2dL1$pb)(r9)", " fsub f1,f0,f1", " blr", 0 }; void code_i2d() { d2u_lib_used=1; char *frn = register_name(freg); char *crn = register_name(creg); printf("\tmr r3,%s\n",crn); printf("\tbl i2d_\n"); printf("\tfmr %s,f1\n",frn); 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(r1)", " lwz r3,-28(r1)", " 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(r1)", " lwz r3,-20(r1)", " xoris r3,r3,0x8000", " blr", 0 }; void code_d2u() { d2u_lib_used=1; char *frn = register_name(freg); char *crn = register_name(creg); printf("\tfmr f1,%s\n",frn); printf("\tbl d2u\n"); printf("\tmr %s,r3\n",crn); 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(r1)", " lis r0,0x4330", " stw r0,-32(r1)", " lfd f0,-32(r1)", " addis r9,r10,ha16(__u2dLC1-__u2dL2$pb)", " lfd f1,lo16(__u2dLC1-__u2dL2$pb)(r9)", " fsub f1,f0,f1", " blr", 0 }; void code_u2d() { u2d_lib_used=1; char *frn = register_name(freg); char *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 r; r = get_ptr_cache((char*)caddr(e1)); printf("\t%s %s,(%s)\n",fload(d),register_name(freg),register_name(r)); } void code_drlvar(int e2,int d) { printf("\t%s %s,%d(r1)\n",fload(d),register_name(freg),e2); } void code_cmp_drgvar(int e2) { int r; char *frn=register_name(freg); int g=get_fregister(); char *grn=register_name(g); r = get_ptr_cache((char*)caddr(e1)); printf("\t%s,(%s)\n",fload(d),grn,register_name(r)); printf("\tfcmpu cr0,%s,%s\n",frn,grn); free_fregister(g); } void code_cmp_drlvar(int e2) { printf("\tfcmpu %d(%%ebp)\n",e2); char *frn=register_name(freg); int g=get_fregister(); char *grn=register_name(g); printf("\t%s,%d(r1)\n",fload(d),grn,e2); printf("\tfcmpu cr0,%s,%s\n",frn,grn); free_fregister(g); } void dtosop(int op,int e1) { char *opn; char *frn=register_name(freg); char *grn=register_name(e1); switch(op) { case DADD: opn="fadd"; break; case DSUB: opn="fadd"; break; case DDIV: opn="fadd"; break; case DMUL: opn="fadd"; break; case DCMP: printf("\tfcompu cr0,%s,%s\n",opn,frn,grn); fgree_register(e1); break; case DCMPGE: printf("\tfcompu cr7,%s,%s\n",opn,frn,grn); fgree_register(e1); break; } printf("\t%s %s,%s,%s\n",opn,frn,frn,grn); fgree_register(e1); } void code_dassop(int op,int d) { /* we have lvalue in creg, applied floating value is in freg */ char *frn=register_name(freg); int e1=get_fregister(); char *grn=register_name(e1); char *crn=register_name(creg); printf("\t%s %s,(%s)\n",fload(d),grn,crn); dtosop(op,e1); printf("\t%s %s,(%s)\n",fstore(d),frn,crn); } static int use_float_one=0; void code_dpreinc(int e1,int e2,int d) { char *frn; char *crn; int g; char *grn,*drn; int r; r = get_ptr_cache("float_one"); use_float_one=1; g_expr(e2); crn=register_name(creg); frn=register_name(freg); drn=register_name(r); grn=register_name(g); printf("\t%s %s,(%s)\n",fload(d),frn,crn); printf("\tfls %s,(%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,(%s)\n",fstore(d),frn,crn); } void code_dpostinc(int e1,int e2,int d) { char *frn; char *crn; int g; char *grn,*drn; int r; r = get_ptr_cache("float_one"); use_float_one=1; g_expr(e2); crn=register_name(creg); frn=register_name(freg); drn=register_name(r); grn=register_name(g); printf("\t%s %s,(%s)\n",fload(d),frn,crn); printf("\tfls %s,(%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,(%s)\n",fstore(d),grn,crn); } 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("\tbeq\tcr0,_%d\n",l1); break; case DOP+GT: printf("\tbgt\tcr0,_%d\n",l1); break; case DOP+EQ: printf("\tbeq\tcr0,_%d\n",l1); break; case DOP+NEQ: printf("\tbne\tcr0,_%d\n",l1); break; } } int dpop_register() { return 1; } int emit_dpop(int e1) { return 1; } void emit_dpop_free(int e1) { } void emit_dpush() { } /* end */