Mercurial > hg > CbC > old > device
view mc-mips.c @ 296:284aa4eaab0d
case merge for cascade, table.
author | kono |
---|---|
date | Sun, 06 Jun 2004 02:40:32 +0900 |
parents | 1c2a9232ea93 |
children |
line wrap: on
line source
/* Micro-C Code Generatation Part for Mips */ #define EXTERN extern #include "mc.h" #define REGISTERS6 0 void code_init(void); void free_register(int i); void emit_init(void); void emit_push(void); void gexpr(int e1); void g_expr(int e1); void bexpr(int e1, char cond, int l1); void b_expr(int e1, char cond, int l1); void string(int e1); void function(int e1); void machinop(int e1); void rindirect(int e1); void assign(int e1); void sassign(int e1); void assop(int e1); void tosop(int op); void shift(char *op, int reg) ; void ld_indexx(int byte, int n, char *xrn); void st_indexx(int byte, int n, char *xrn); void indexy(char *op, char *gvar); void cmpdimm(int e, int csreg); void global_table(void) ; void local_table(void) ; void opening(char *filename); void closing(void); void gen_gdecl(char *n, int gpc) ; void jmp_label(int l); void jmp_eq_label(int l); void rexpr(int e1, int l1, char *s); void jcond(int l, char cond); void jmp(int l); void def_label(int cslabel, int dlabel) ; void gen_comment(char *s); void gen_source(char *s); void code_enter(char *name) ; void code_leave(char *name) ; void enter(char *name, int disp) ; void enter_no(char *name,int disp); void enter1(int disp) ; void ret(void); void emit_data(int e, int t, NMTBL *n); void text_mode(void); void data_mode(char *name); int get_register_var(void); void jump(int e1, int env); int lvar(int l); int cadr(int e); int car(int e); int caddr(int e); int fwdlabel(void); void fwddef(int l); int cadddr(int e); int backdef(void); int error(int n); int size(int t); int list3(int e1, int e2, int e3); extern int scalar(int); extern int reverse0(int); #define TEXT_EMIT_MODE 0 #define DATA_EMIT_MODE 1 #define RODATA_EMIT_MODE 2 static output_mode = TEXT_EMIT_MODE; static data_alignment = 0; /* local1 <----24 local variable -20 <- disp_offset saved register .mask 0...0,-8 .fmask 0 $fp = $sp 0 $ip 4 <- arg_offset arg1 8 */ int arg_offset = 8; int code_arg_offset = -4; int disp_offset = -12; int func_disp_offset = -12; int code_disp_offset = -4; int size_of_int = 4; int endian = 0; int MAX_REGISTER=32; /* Mipsのレジスタを32つまで使う*/ int REAL_MAX_REGISTER=32; /* Mipsのレジスタが32つということ*/ int MAX_REGISTGER_VAR=20; int save_reg = 0; /*saveされたレジスタの回数*/ int save_reg1 = 0; static int creg; /* current register */ static char *crn; /* current register name */ static int lreg; /* operand register */ static char *lrn; /* operand register name */ static int dreg; /* temporary register */ static char *drn; /* temporary register name */ static int xreg; /* pointer register */ static int reg_sp; /* REGister Stack-Pointer */ #define REG_00 0 #define REG_01 1 #define REG_02 2 #define REG_03 3 #define REG_04 4 #define REG_05 5 #define REG_06 6 #define REG_07 7 #define REG_08 8 #define REG_09 9 #define REG_10 10 #define REG_11 11 #define REG_12 12 #define REG_13 13 #define REG_14 14 #define REG_15 15 #define REG_16 16 #define REG_17 17 #define REG_18 18 #define REG_19 19 #define REG_20 20 #define REG_21 21 #define REG_22 22 #define REG_23 23 #define REG_24 24 #define REG_25 25 #define REG_26 26 #define REG_27 27 #define REG_28 28 #define REG_29 29 #define REG_30 30 #define REG_31 31 static char *reg_name[32]; /* creg currrent virtual register lreg operand virtual register dreg spare virtual register rname[creg] currrent real register rname[lreg] operand real register rname[dreg] spare real register regs[] virtual register usage reg_name[rname[creg]] */ #define MAX_MAX 40 static int rname[MAX_MAX]; static int regs[MAX_MAX]; /* 使われているレジスタを示すフラグ */ static int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ void code_init(void) { int i; if (REGISTERS6) { arg_offset = 8; func_disp_offset = -20; disp_offset = -20; size_of_int = 4; endian = 0; MAX_REGISTER=32; } else { arg_offset = 8; func_disp_offset = -12; disp_offset = -12; size_of_int = 4; endian = 0; MAX_REGISTER=32; } MAX_REGISTER_VAR=2; reg_name[REG_00] = "$0"; reg_name[REG_01] = "$1"; reg_name[REG_02] = "$2"; reg_name[REG_03] = "$3"; reg_name[REG_04] = "$4"; reg_name[REG_05] = "$5"; reg_name[REG_06] = "$6"; reg_name[REG_07] = "$7"; reg_name[REG_08] = "$8"; reg_name[REG_09] = "$9"; reg_name[REG_10] = "$10"; reg_name[REG_11] = "$11"; reg_name[REG_12] = "$12"; reg_name[REG_13] = "$13"; reg_name[REG_14] = "$14"; reg_name[REG_15] = "$15"; reg_name[REG_16] = "$16"; reg_name[REG_17] = "$17"; reg_name[REG_18] = "$18"; reg_name[REG_19] = "$19"; reg_name[REG_20] = "$20"; reg_name[REG_21] = "$21"; reg_name[REG_22] = "$22"; reg_name[REG_23] = "$23"; reg_name[REG_24] = "$24"; reg_name[REG_25] = "$25"; reg_name[REG_26] = "$26"; reg_name[REG_27] = "$27"; reg_name[REG_28] = "$28"; reg_name[REG_29] = "$29"; reg_name[REG_30] = "$30"; reg_name[REG_31] = "$31"; } char * register_name(int i) { return reg_name[rname[i]]; } int get_register(void) { /* 使われていないレジスタを調べる */ int i; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i]) { /* 使われていないなら */ regs[i]=1; /* そのレジスタを使うことを宣言し */ return i; /* その場所を表す番号を返す */ } } return -1; /* 空いている場所がないなら、それを表す -1 を返す */ } void free_register(int i) { /* いらなくなったレジスタを開放 */ regs[i]=0; } int register_full(void) { int i; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i]) { return 0; } } return 1; } void gexpr_init(void) { int i; while(reg_sp > 0) { free_register(reg_stack[--reg_sp]); } text_mode(); } void emit_init(void) { int i; for(i=0;i<REAL_MAX_REGISTER;i++) regs[i]=0; for(i=0;i<REAL_MAX_REGISTER;i++) rname[i]=i; regs[REG_00] = 1; /* reserved */ regs[REG_01] = 1; /* reserved */ regs[REG_02] = 1; /* $v0 */ regs[REG_03] = 1; /* $v1 */ regs[REG_28] = 1; /* reserved */ regs[REG_29] = 1; /* reserved */ regs[REG_30] = 1; /* reserved */ regs[REG_31] = 1; /* reserved */ creg = get_register(); crn = reg_name[rname[creg]]; dreg = get_register(); drn = reg_name[rname[dreg]]; reg_sp = 0; text_mode(); } void set_crn(int i) { creg = i; crn = reg_name[rname[creg]]; } void set_drn(int i) { dreg = i; drn = reg_name[rname[dreg]]; } int virtual(int real) { int real_v,i; real_v = -1; for(i=0;i<MAX_REGISTER;i++) { if (rname[i]==real) { real_v=i; break; } } if (real_v == -1) error(-1); return real_v; } void use_register(int virt, int real, int move) { int real_v; char *move_op,*a,*b; if (rname[virt]==real) return; real_v = virtual(real); if (move || regs[real_v]) { if(regs[real_v]) { a=reg_name[real]; b=reg_name[rname[virt]]; printf("\txor \t%s,%s,%s\n",a,a,b); printf("\txor \t%s,%s,%s\n",b,a,b); printf("\txor \t%s,%s,%s\n",a,a,b); } else { printf("\tmove \t%s,%s\n",reg_name[real],reg_name[rname[virt]]); } } rname[real_v] = rname[virt]; rname[virt] = real; crn = reg_name[rname[creg]]; drn = reg_name[rname[dreg]]; lrn = reg_name[rname[lreg]]; save_reg++; } int pop_register(void) { /* レジスタから値を取り出す */ int i,j; j = creg; i = reg_stack[--reg_sp]; if(i<0) { return i; } else { free_register(i); lreg = i; lrn = reg_name[rname[lreg]]; regs[i]=0; return lreg; } } int stack_used(void) { return reg_stack[--reg_sp]<0; } void emit_push(void) { int new_reg; new_reg = get_register(); if(new_reg<0) { /* もうレジスタがない */ reg_stack[reg_sp++] = -1; printf("\tsubu $sp,$sp,%d\n",size_of_int); printf("\tsw \t%s,0($sp)\n",crn); } else { reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ set_crn(new_reg); } } char * emit_pop(int type) { char *xrn; if (pop_register()==-1) { printf("\tlw %s,0($sp)\n",drn); printf("\taddu $sp,$sp,%d\n",size_of_int); xrn = drn; xreg = dreg; } else { xrn = lrn; xreg = lreg; } return xrn; } int get_register_var(void) { int i; for(i=REG_05;i<REG_31;i++) { if (! regs[i]) { /* 使われていないなら */ regs[i]=1; /* そのレジスタを使うことを宣言し */ return i; /* その場所を表す番号を返す */ } } return -1; } void gexpr(int e1) { gexpr_init(); g_expr(e1); csvalue = rname[creg]; /* for siwtch value */ } void g_expr(int e1) { int e2,e3,e4; char *xrn; NMTBL *n; if (chk) return; e2 = cadr(e1); switch (car(e1)){ case GVAR: printf("\tla\t%s,%s\n",crn,caddr(e1)); return; case RGVAR: printf("\tlw\t%s,%s\n",crn,caddr(e1)); return; case CRGVAR: printf("\tlb\t%s,%s\n",crn,caddr(e1)); return; case LVAR: printf("\taddu\t%s,$fp,%d\n",crn,lvar(e2)); return; case REGISTER: /* this is of course redundant... */ printf("\tmove\t%s,%s\n",crn,register_name(e2)); return; case RLVAR: printf("\tlw\t%s,%d($fp)\n",crn,lvar(e2)); return; case CRLVAR: printf("\tlb\t%s,%d($fp)\n",crn,lvar(e2)); return; case FNAME: printf("\tla\t%s,%s\n",crn,((NMTBL *)e2)->nm); return; case CONST: /* 代入する値が0でも特別な処理はしない */ printf("\tli\t%s,%d\n",crn,e2); return; case STRING: string(e1); return; case FUNCTION: function(e1); return; case CODE: jump(e2,caddr(e1)); return; case INDIRECT: g_expr(e2); return; case RINDIRECT: case CRINDIRECT: rindirect(e1); return; case ADDRESS: g_expr(e2); return; case MINUS: /* レジスタに対し、引き算を実行すれば実現可能 */ g_expr(e2); printf("\tsubu\t%s,$0,%s\n",crn,crn); return; case BNOT: /* ~ */ g_expr(e2); /* use_data_reg(creg,1); */ printf("\tnor\t%s,$0,%s\n",crn,crn); return; case LNOT: /* ! */ g_expr(e2); /*use_data_reg(creg,1);*/ printf("\txori\t%s,%s,0x0000\n",drn,crn); printf("\tsltu\t%s,%s,1\n",crn,drn); return; case PREINC:/* ++q */ if (car(e2)==REGISTER) { printf("\taddu \t%s,%s,%d\n",register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1)); return; } g_expr(e2); printf("\taddu \t%s,%s,%d\n",crn,crn,caddr(e1)); return; case POSTINC:/* p++ */ if (car(e2)==REGISTER) { printf("\taddu \t%s,%s,%d\n",register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1)); return; } g_expr(e2); emit_push(); /* in case of register full we should copy crn to drn */ xrn = emit_pop(0); printf("\taddu \t%s,%s,%d\n",crn,xrn,caddr(e1)); return; case CPOSTINC: /* char *p; *p++ */ if (car(e2)==REGISTER) { printf("\tmove\t%s,%s\n",crn,register_name(cadr(e2))); printf("\taddu\t%s,%s,%d\n",register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1)); return; } g_expr(e2); emit_push(); /* in case of register full we should copy crn to drn */ xrn = emit_pop(0); printf("\tmovsbl (%s),%s\n",xrn,crn); printf("\tincl (%s)\n",xrn); return; case CPREINC: /* char *p; *++p */ if (car(e2)==REGISTER) { printf("\taddu\t%s,%s,%d\n",register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1)); printf("\tmove\t%s,%s\n",crn,register_name(cadr(e2))); return; } g_expr(e2); printf("\tincl (%s)\n",crn); printf("\tmovsbl (%s),%s\n",crn,crn); return; case CPOSTDEC:/* char *p; *p-- */ if (car(e2)==REGISTER) { printf("\tmove\t%s,%s\n",crn,register_name(cadr(e2))); printf("\tsubu\t%s,%s,1\n",register_name(cadr(e2)),register_name(cadr(e2))); return; } g_expr(e2); printf("\tmovsbl (%s),%s\n",crn,crn); printf("\tdecl (%s)\n",crn); return; case CPREDEC:/* char *p; *--p */ if (car(e2)==REGISTER) { printf("\tdecl %s\n",register_name(cadr(e2))); printf("\tmove\t%s,%s\n",crn,register_name(cadr(e2))); return; } g_expr(e2); emit_push(); xrn = emit_pop(0); printf("\tdecl (%s)\n",xrn); printf("\tmovsbl (%s),%s\n",xrn,crn); return; case MUL: case UMUL: case DIV: case UDIV: case MOD: case UMOD: case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT: case ADD: case SUB: case BAND: case EOR: case BOR: machinop(e1); return; case COND: e2=fwdlabel(); b_expr(cadr(e1),0,e2); g_expr(caddr(e1)); e4 = rname[creg]; jmp(e3=fwdlabel()); fwddef(e2); g_expr(cadddr(e1)); use_register(creg,e4,1); fwddef(e3); return; case STASS: sassign(e1); return; case ASS: case CASS: assign(e1); return; case ASSOP: case CASSOP: assop(e1); return; case COMMA: g_expr(e2); g_expr(caddr(e1)); return; case RETURN: n = (NMTBL *)e2; if (retcont==0) retcont=fwdlabel(); printf("\tla\t%s,$L%d\n",crn,retcont); return; case ENVIRONMENT: printf("\tmove\t%s,$fp\n",crn); return; default: b_expr(e1,1,e2=fwdlabel()); /* including > < ... */ /*printf("\txor \t%s,%s\n",crn,crn);*/ jmp(e3=fwdlabel()); fwddef(e2); printf("\tli \t%s,%d\n",crn,lvar(e2)); fwddef(e3); } } void bexpr(int e1, char cond, int l1) { gexpr_init(); b_expr(e1,cond,l1); } void b_expr(int e1, char cond, int l1) { int e2,l2; if (chk) return; e2=cadr(e1); switch(car(e1)) { case LNOT: b_expr(e2,!cond,l1); return; case GT: /*rexpr(e1,l1,cond?"bg":"ble");*/ return; case UGT: /*rexpr(e1,l1,cond?"ba":"bbe");*/ return; case GE: /*rexpr(e1,l1,cond?"bge":"bl");*/ return; case UGE: /*rexpr(e1,l1,cond?"bae":"bb");*/ return; case LT: /*rexpr(e1,l1,cond?"bl":"bge");*/ return; case ULT: /*rexpr(e1,l1,cond?"bb":"bae");*/ return; case LE: /*rexpr(e1,l1,cond?"ble":"bg");*/ return; case ULE: /*rexpr(e1,l1,cond?"bbe":"ba");*/ return; case EQ: rexpr(e1,l1,cond?"beq":"bne"); return; case NEQ: rexpr(e1,l1,cond?"bne":"beq"); return; case LAND: b_expr(e2,0,cond?(l2=fwdlabel()):l1); b_expr(caddr(e1),cond,l1); if(cond) fwddef(l2); return; case LOR: b_expr(e2,1,cond?l1:(l2=fwdlabel())); b_expr(caddr(e1),cond,l1); if(!cond) fwddef(l2); return; case CRGVAR: /*printf("\tcmpb $0,%s\n",caddr(e1));*/ jcond(l1,cond); return; case CRLVAR: /*printf("\tcmpb $0,%d($fp)\n",lvar(e2));*/ jcond(l1,cond); return; case RGVAR: /*printf("\tcmpl $0,%s\n",caddr(e1));*/ jcond(l1,cond); return; case RLVAR: /*printf("\tlw \t%s,%d($fp)\n",crn,lvar(e2));*/ jcond(l1,cond); return; case REGISTER: /*printf("\tcmpl $0,%s\n",register_name(e2));*/ jcond(l1,cond); return; case CONST: if((cond&&e2)||(!cond&&!e2)) jmp(l1); return; default: g_expr(e1); /*printf("\tcmpl $0,%s\n",crn);*/ jcond(l1,cond); return; } } 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("%c\n",34); } void string(int e1) { char *s; int i,lb; if (0) { s=(char *)cadr(e1); printf("\t.rdata\n"); printf("\t.align\t2\n"); lb=fwdlabel(); printf("\tj\t$L%d\n",lb); i=backdef(); ascii(s); printf("\t.align 2\n"); fwddef(lb); printf("\tla\t%s,$L%d\n",crn,i); } else { s=(char *)cadr(e1); printf("\t.rdata\n"); printf("\t.align\t2\n"); lb=fwdlabel(); printf("$L%d:\n",lb); ascii(s); if (output_mode==TEXT_EMIT_MODE) { printf("\t.text\n"); } else { text_mode(); } printf("\tla\t%s,$L%d\n",crn,lb); } } void function(int e1) { int e2,e3,e4,e5,nargs; NMTBL *n; e2 = cadr(e1); nargs = 0; for (e3 = caddr(e1); e3; e3 = cadr(e3)) { n=(NMTBL *)(e5=(cadr(e4 = car(e3)))); switch(car(e4)){ case FNAME: printf("\tlw\t%s,0(%s)\n",crn,n->nm); break; case ADDRESS: g_expr(e5); break; default:g_expr(e4); } ++nargs; } if (car(e2) == FNAME) { n=(NMTBL *)cadr(e2); use_register(creg,REG_04,0); printf("\tjal\t%s\n",n->nm); } else { g_expr(e2); use_register(creg,REG_04,0); printf("\tjal\t*%s\n",crn); } /*if (nargs) printf("\taddl $%d,%%esp\n",size_of_int*nargs);*/ } int arg_size(int e3,int *nargs0) { int i,nargs,offset_list,e,t; offset_list = 0; /* we should use prototypes's type */ for (i = nargs = 0; e3;e3 =cadr(e3)) { e = car(e3); t = caddr(e3); if (i < MAX_REGISTER_VAR && scalar(t)) { offset_list = list3(-(REG_05+i++),offset_list,e); } else { offset_list = list3(nargs,offset_list,e); nargs += (car(e3)==CHAR?size_of_int:size(t)); } } *nargs0 = -nargs; return offset_list; } void jump(int e1, int env) { int i,args,e2,e3,e4,e5,nargs,nargs0,regs; NMTBL *n,*code0; int new_disp,scode,disp1; char *xrn; /* We need three passes. Compute Stack size, Compute Arg, Copy it. */ /* count number of args */ args = caddr(e1); args = reverse0(args); nargs = arg_size(args,&new_disp); /* compute in normal order */ disp1 = (fnptr->sc==CODE)?0:-size_of_int; if (new_disp+disp1 < disp) { /* have to extend stack */ if (fnptr->sc==CODE) printf("\tlw\t$sp,%d($fp)\n",new_disp-size_of_int); else printf("\tlw\t$sp,%d($fp)\n",new_disp+disp_offset); } /* compute jump address */ e2 = cadr(e1); if (car(e2) == FNAME) { code0=(NMTBL *)cadr(e2); if (code0->sc!=CODE) { error(STERR); return; } } else { /* indirect */ g_expr(e2); emit_push(); } /* compute arguments in reverse order */ regs = 0; i=MAX_REGISTER_VAR; for (e3=nargs; e3;e3 =cadr(e3)) { n=(NMTBL *)(e5=(cadr(e4 = caddr(e3)))); switch(car(e4)) { case FNAME: printf("\tlw\t%s,0(%s)\n",crn,n->nm); emit_push(); break; case ADDRESS: g_expr(e5); emit_push(); break; case RLVAR: case CRLVAR: if (env==0 && fnptr->sc==CODE) { if (e5>=0 && e5==car(e3)) { /* The same positioned local variable. No need to copy */ reg_stack[reg_sp++] = -2; } break; } g_expr(e4); emit_push(); break; case REGISTER: if (i>0 && rname[e5]==REG_05+ --i) { /* The same register variable. No need to copy */ reg_stack[reg_sp++] = e5; break; } default: g_expr(e4); emit_push(); } regs++; } if (env) { /* change the frame pointer */ g_expr(env); printf("\tmove\t%s,$fp\n",crn); } else if (fnptr->sc==FUNCTION) { printf("\tlw\t$fp,%d($fp)\n",disp_offset); } /* force lvar offset mode to CODE */ scode = fnptr->sc; fnptr->sc = CODE; /* copy arguments to destination environment if necessary */ nargs = reverse0(nargs); /* pop in normal order */ i=0; for (e3=nargs; e3;e3 =cadr(e3)) { if ((e4=car(e3))<0) { /* register case */ if (reg_stack[--reg_sp]>=REG_05) { /* the same registger */ } else { if(reg_stack[reg_sp]<0) { /*printf("\tpopl %s\n",reg_name[rname[REG_05+i]]);*/ /* e4? */ } else { printf("\tmove\t%s,%s\n", reg_name[rname[REG_05+i]], reg_name[rname[reg_stack[reg_sp]]]); /* e4? */ free_register(reg_stack[reg_sp]); } i++; } } else { /* local variable case */ if (reg_stack[reg_sp-1]== -2) { /* same positioned variable */ reg_sp--; } else { xrn=emit_pop(0); printf("\tlw\t%s,%d($fp)\n",xrn, lvar(e4)); } } } if (car(e2) != FNAME) { xrn=emit_pop(0); } if (!env && new_disp+disp1>disp) { /* shrink stack if necessary */ printf("\tlw\t$sp,%d($fp)\n",new_disp-size_of_int); } if (car(e2) == FNAME) { printf("\tj\t%s\n",code0->nm); } else { printf("\tj\t*%s\n",xrn); } fnptr->sc = scode; } void machinop(int e1) { int e2,e3,op; e2 = cadr(e1); op = car(e1); e3 = caddr(e1); g_expr(e3); emit_push(); g_expr(e2); tosop(car(e1)); return; } void rindirect(int e1) /* *(p +5 ) */ { char *op; int e2,e3,byte; op = ((byte = (car(e1) == CRINDIRECT)) ? "lb" : "lw"); e3 = cadr(e2 = cadr(e1)); g_expr(e2); printf("\t%s \t%s,%d(%s)\n",op,crn,lvar(e3),crn); } void sassign(int e1) { int e2,e3,e4,sz; char *xrn; e2 = cadr(e1); e3 = cadr(e2); e4 = caddr(e1); sz = size(cadr(e2)); /* cld rep movsb */ g_expr(e4); emit_push(); g_expr(e2); xrn = emit_pop(0); return; } void assign(int e1) { char *op; int e2,e3,e4,byte; char *xrn; op = ((byte=(car(e1) == CASS))? "sb" : "sw"); /* e2=e4 */ e2 = cadr(e1); e3 = cadr(e2); e4 = caddr(e1); switch(car(e2)) { case GVAR: /* i=3 */ g_expr(e4); /*if (byte) use_data_reg(creg,1);*/ printf("\t%s \t%s,%s\n",op,crn,caddr(e2)); return; case LVAR: g_expr(e4); /*if (byte) use_data_reg(creg,1);*/ printf("\t%s \t%s,%d($fp)\n",op,crn,lvar(cadr(e2))*-1); return; case REGISTER: g_expr(e4); if (creg!=cadr(e2)) printf("\t%s \t%s,%s\n",op,crn,register_name(cadr(e2))); return; } g_expr(e4); emit_push(); g_expr(e2); xrn = emit_pop(0); /*if (byte) use_data_reg(creg,1);*/ printf("\t%s %s,(%s)\n",op,xrn,crn); printf("\tmove\t%s,%s\n",crn,xrn); return; } void assop(int e1) { int e2,e3,byte,op,new_reg; char *xrn; /* e2 op= e3 */ byte = (car(e1) == CASSOP); e2 = cadr(e1); if (car(e2)==INDIRECT) e2=cadr(e2); e3 = caddr(e1); op = cadddr(e1); g_expr(e3); emit_push(); if (car(e2)==REGISTER) { new_reg=creg; set_crn(cadr(e2)); tosop(op); set_crn(new_reg); printf("\tmove\t%s,%s\n",crn,register_name(cadr(e2))); return; } g_expr(e2); xrn = emit_pop(0); /* pop e3 value */ /*printf("\tpushl %s # assop \n",crn);*/ /* push e2 address */ ld_indexx(byte,0,crn); new_reg = get_register(); /* push e3 value */ if(new_reg<0) { /* もうレジスタがない */ reg_stack[reg_sp++] = -1; /*printf("\tpushl %s\n",xrn);*/ } else { reg_stack[reg_sp++] = xreg; /* push するかわりにレジスタを使う */ } tosop(op); if(new_reg>=0) free_register(new_reg); /*printf("\tpopl %s # assop \n",drn);*/ printf("\t%s\t%s,0(%s)\n",byte ? "lb" : "lw",crn,drn); return; } void tosop(int op) { int oreg; char *orn; oreg = pop_register(); switch(op) { case LSHIFT: case ULSHIFT: shift("sall",oreg); return; case RSHIFT: shift("sarl",oreg); return; case URSHIFT: shift("shrl",oreg); return; } if(oreg==-1) { oreg = dreg; } orn = reg_name[rname[oreg]]; switch(op) { case ADD: printf("\taddu \t%s,%s,%s\n",crn,crn,orn); return; case SUB: printf("\tsubu \t%s,%s,%s\n",crn,crn,orn); return; case BAND: printf("\tand \t%s,%s,%s\n",crn,crn,orn); return; case EOR: printf("\txor \t%s,%s,%s\n",crn,crn,orn); return; case BOR: printf("\tor \t%s,%s,%s\n",crn,crn,orn); return; case MUL: case UMUL: printf("\t%s\t%s,%s\n","mult",crn,orn); printf("\tmflo\t%s\n",crn); return; case DIV: case UDIV: if (op==DIV) printf("\tdiv\t%s,%s,%s\n",crn,crn,orn); else printf("\txor\t%s,%s,%s\n\tdiv\t%s,%s,%s\n",crn,crn,orn,crn,crn,orn); return; case MOD: case UMOD: if (op==MOD) printf("\trem\t%s,%s,%s\n",crn,crn,orn); else printf("\txor\t%s,%s,%s\n\tdiv\t%s,%s,%s\n",crn,crn,orn,crn,crn,orn); return; } } void shift(char *op, int reg) { if (reg>=0) { use_register(lreg,REG_03,1); } else { use_register(dreg,REG_03,0); } /*printf("\t%s %%cl,%s\n",op,crn);*/ } void ld_indexx(int byte, int n, char *xrn) { char *op; op = byte ? "lb" : "lw"; if (n) printf("\t%s\t%s,%d(%s)\n",op,crn,n,xrn); else printf("\t%s\t%s,0(%s)\n",op,crn,xrn); } void st_indexx(int byte, int n, char *xrn) { char *op; op = byte ? "sb" : "sw"; if (n) printf("\t%s\t%s,%d(%s)\n",op,crn,n,xrn); else printf("\t%s\t%s,0(%s)\n",op,crn,xrn); } void indexy(char *op, char *gvar) { printf("\t%s %s,%s\n",op,crn,gvar); } void cmpdimm(int e, int csreg) { /* used in dosiwtch() */ use_register(creg,csreg,0); /*printf("\tcmpl $%d,%s\n",e,crn);*/ } void opening(char *filename) { printf("\t.file \t1 \"%s\"\n",filename); printf(" # GNU C 2.7.2.2 [AL 1.1, MM 40] Sony PlayStation compiled by GNU C\n\n"); printf(" # Cc1 defaults:\n\n"); printf(" # Cc1 arguments (-G value = 8, Cpu = 3000, ISA = 1):\n"); printf(" # -msoft-float -quiet -dumpbase -o\n\n"); printf(" # gcc2_compiled.:\n"); printf(" # __gnu_compiled_c:\n"); printf("\t.text\n"); emit_init(); } void closing(void) { global_table(); } void jmp_label(int l) { printf("\tjmp\t_%d\n",l); } void jmp_eq_label(int l) { printf("\tj\t_%d\n",l); } void rexpr(int e1, int l1, char *s) { g_expr(list3(SUB,cadr(e1),caddr(e1))); printf("\t%s\t%s,%s,$L%d\n",s,crn,crn,l1); } void jcond(int l, char cond) { printf("\t%s\t%s,%s,$L%d\n",cond?"bne":"beq",crn,crn,l); } void jmp(int l) { control=0; printf("\tj\t$L%d\n",l); /* align? */ } int fwdlabel(void) { return labelno++; } void fwddef(int l) { control=1; printf("$L%d:\n",l); } int backdef(void) { control=1; printf("$L%d:\n",labelno); return labelno++; } void def_label(int cslabel, int dlabel) { int fl; fl = 0; if (control) { jmp(fl=fwdlabel()); } fwddef(cslabel); if (dlabel) jmp(dlabel); if (fl) { fwddef(fl); } } void gen_comment(char *s) { printf("# %s",s); } void gen_source(char *s) { 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 disp0,int args) { if(disp0) { printf("\tsubl $%d,%%esp\n",-disp0); } } void code_leave(char *name) { local_table(); printf("$L%d:\n",labelno); printf("\t.size\t%s,_%d-%s\n",name,labelno,name); labelno++; } void enter(char *name, int disp) { int a,b,i; a = b = 0; /*printf("\t.text\n"); printf("\t.align \t2\n"); if (stmode!=STATIC) printf("\t.globl \t%s\n",name);*/ printf("%s:\n",name); printf("\t.frame \t$fp,%d,$31\n",-disp+save_reg*size_of_int); if(disp) a = 8; printf("\t.mask \t0x%d0000000,-8\n",a); printf("\t.fmask \t0x00000000,0\n"); if(disp){ printf("\tsubu \t$sp,$sp,%d\n",-disp+save_reg*size_of_int); printf("\tsw\t$31,%d($sp)\n",-disp+4*save_reg1); save_reg1--; } for(i=save_reg1;i==0;i--) { printf("\tsw\t$%d,%d($sp)\n",16+i,-disp+4*i); } /*if(strcmp("main",name)) printf("\tjal \t%s_0\n",name); else printf("\tjal \t__%s_0\n",name);*/ printf("\tjal \t%s_0\n",name); printf("\t.end \t%s\n",name); printf("\t.sdata\n"); printf("\t.align 2\n"); save_reg = 0; save_reg1 = 0; } /* void enter_no(char *name, int disp) { printf("\t.align \t2\n"); if (stmode!=STATIC) printf("\t.globl \t%s\n",name); printf("\t.ent \t%s\n",name); printf("%s_0:\n",name); } */ void enter1(int disp) { if(disp) printf("\tsubu \t$sp,$sp,%d\n",-disp+save_reg*size_of_int); } void leave(int control, char *name) { int i; if (control) use_register(creg,REG_04,1); if (retcont) { if (control) jmp(retlabel); fwddef(retcont); use_register(creg,REG_04,0); printf("\tmove\t%s,%s\n",crn,reg_name[REG_05]); } fwddef(retlabel); use_register(creg,REG_04,0); save_reg1 = save_reg; printf("\tmove\t$sp,$fp\n"); printf("\tlw\t$31,%d($sp)\n",-disp+4*save_reg); save_reg--; for(i=save_reg;i==0;i--) { printf("\tlw\t$%d,%d($sp)\n",16+i,-disp+4*i); } if(disp) printf("\taddu \t$sp,$sp,%d\n",-disp+save_reg*size_of_int); printf("\tj\t$31\n"); local_table(); printf("$L%d:\n",labelno); labelno++; } void ret(void) { use_register(creg,REG_04,1); jmp(retlabel); } 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; char *name; name = n->nm; if(mode==GDECL) { /* global */ 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 { printf("\t.long %d\n",cadr(e)); gpc += size_of_int; } } else if(t!=CHAR) { gpc += size_of_int; if(car(e)==ADDRESS&&car(cadr(e))==GVAR) { printf("\t.word %s\n",caddr(cadr(e))); } else if(car(e)==FNAME) { printf("\t.word %s\n",((NMTBL *)cadr(e))->nm); } else if(car(e)==STRING) { if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) { l = fwdlabel(); printf("\t.word _%d\n",l); printf("$L%d:\n",l); output_mode = RODATA_EMIT_MODE; } ascii((char *)cadr(e)); } else error(TYERR); } } else { /* if (n->sc!=LVAR) { error(TYERR); return; } */ if(car(e)==CONST) { printf("\tmove\t%s,%d\n",crn,cadr(e)); printf("\t%s\t%s,%d($fp)\n",t==CHAR?"lb":"lw",crn,n->dsp); } else if(t!=CHAR) { if(car(e)==ADDRESS&&car(cadr(e))==GVAR) printf("\tlw\t%s,0(%s)\n",crn,caddr(e)); else if(car(e)==FNAME) printf("\tlw\t%s,0(%s)\n",crn,((NMTBL *)cadr(e))->nm); else if(car(e)==STRING) { string(e); } else error(TYERR); printf("\tlw\t%s,%d($fp)\n",crn,n->dsp); } } } void emit_data_closing(NMTBL *n) { int lb; if (mode=GDECL) { data_mode(0); lb=fwdlabel(); printf("$L%d:\n",lb); printf("\t.size\t%s,_%d-%s\n",n->nm,lb,n->nm); } } void global_table(void) { NMTBL *n; for(n=ntable;n < &ntable[GSYMS];n++) { if (n->sc == GVAR && n->dsp != -1) { /* n->dsp = -1 means initialized global */ printf("\n\t.comm \t%s,%d\n",n->nm,size(n->ty)); } } } void local_table(void) { NMTBL *n; /* static local variables */ for(n=ntable+GSYMS;n < &ntable[GSYMS+LSYMS];n++) { if (n->sc == GVAR) { 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 (l<0) { if (fnptr->sc==CODE) return l+code_disp_offset; else return l+disp_offset; } else { if (fnptr->sc==CODE) return -l+code_arg_offset; else return l+arg_offset; } } /* end */