Mercurial > hg > CbC > old > device
changeset 643:f5c0371c9401
*** empty log message ***
author | kono |
---|---|
date | Wed, 01 Nov 2006 15:55:24 +0900 |
parents | e9622935a621 |
children | ac1285a0f69f |
files | mc-mips.c mc-nop-386.c |
diffstat | 2 files changed, 0 insertions(+), 3515 deletions(-) [+] |
line wrap: on
line diff
--- a/mc-mips.c Wed Nov 01 15:33:37 2006 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1553 +0,0 @@ -/* 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 */
--- a/mc-nop-386.c Wed Nov 01 15:33:37 2006 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1962 +0,0 @@ -/* Micro-C Code Generatation Part for intel386 */ -/* $Id$ */ - -#define EXTERN extern -#include "mc.h" - -extern int get_register_var(void); -extern void bexpr(int e1, char cond, int l1); -extern void closing(void); -extern void cmpdimm(int e, int csreg); -extern void code_enter(char *name) ; -extern void code_enter1(int args); -extern void code_init(void); -extern void code_leave(char *name) ; -extern void leave(int control,char *name) ; -extern void def_label(int cslabel, int dlabel) ; -extern void emit_data(int e, int t, NMTBL *n); -extern void emit_init(void); -extern void enter(char *name) ; -extern void enter1() ; -extern void g_expr(int e1); -extern void gen_comment(char *s); -extern void gen_gdecl(char *n, int gpc) ; -extern void gen_source(char *s); -extern void gexpr(int e1); -extern void jcond(int l, char cond); -extern void jmp(int l); -extern void opening(char *filename); -extern void ret(void); -extern int assign_expr0(int e,int e1,int type,int type1); -extern int integral(int t); -extern void tree_print_t(int e,int t); -extern int rvalue_t(int e,int t); - -static int edx_setup() ; -static int lvar(int l); -static void jump(int e1, int env); -static void data_mode(char *name); -static void text_mode(void); -static void assign(int e1); -static void assop(int e1); -static void b_expr(int e1, char cond, int l1,int err); -static void emit_push(void); -static void free_register(int i); -static void function(int e1); -static void global_table(void) ; -/* static void indexy(char *op, char *gvar); */ -/* static void jmp_eq_label(int l); */ -/* static void jmp_label(int l); */ -static void ld_indexx(int byte, int n, int xreg); -static void local_table(void) ; -static void machinop(int e1); -static void rexpr(int e1, int l1, char *s); -static void rindirect(int e1); -static void sassign(int e1); -static void shift(char *op, int xreg) ; -/* static void st_indexx(int byte, int n, int xreg); */ -static void string(int e1); -static void tosop(int op,int reg); -static void edx_cleanup(); -static void use_register(int virt, int real, int move); -static void emit_copy(int from,int to,int length,int offset,int value,int det); -static int is_same_type(int s,int t); - -extern void error(int n); -extern int fwdlabel(void); -extern void fwddef(int l); -extern int backdef(void); -extern int size(int t); -extern int list4(int e1, int e2, int e3,int e4); -extern int list3(int e1, int e2, int e3); -extern int list2(int e1, int e2); -extern int scalar(int); -extern int reverse0(int); -extern void remove0(int *list,int element); -extern int append4(int target,int t,int ty,int e1); - -#define TEXT_EMIT_MODE 0 -#define DATA_EMIT_MODE 1 -#define RODATA_EMIT_MODE 2 - -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 - -12 -4 local1 - -8 8 arg3 - -4 4 arg2 - 0 0 arg1 - local2 -20 4 0 (%edi) - local1 <-- -16 0 local variable 0 (%esi) - %edi -12 <- disp_offset %ebp - %esi -8 - %ebx -4 - %ebp = %esp 0 - %eip 4 <- arg_offset - arg1 8 0 - arg2 12 4 - see enter/enter1/leave see code_enter - */ -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 endian = 0; -int MAX_REGISTER=6; /* intel386のレジスタを4つまで使う*/ -int REAL_MAX_REGISTER=8; /* intel386のレジスタが8つということ*/ -int MAX_DATA_REG=4; -int MAX_POINTER=3; -int MAX_REGISTGER_VAR=2; - -static int creg; /* current register */ -static int dreg; /* temporary register */ -static int reg_sp; /* REGister Stack-Pointer */ - - -#define REG_EAX 0 -#define REG_EBX 1 -#define REG_ECX 2 -#define REG_EDX 3 -#define REG_ESI 4 -#define REG_EDI 5 -#define REG_EBP 6 -#define REG_ESP 7 - - -#define DATA_REG 0 -#define POINTER_REG 3 -static char *reg_name[8]; -static char *reg_name_l[4]; -static char *reg_name_w[4]; - -/* - creg currrent virtual register - dreg spare virtual register - - rname[creg] currrent real register - rname[dreg] spare real register - - regs[] virtual register usage - regv[] value in virtual register flag - - reg_name[rname[creg]] - */ - -#define MAX_MAX 10 -static int rname[MAX_MAX]; -static int regs[MAX_MAX]; /* 使われているレジスタを示すフラグ */ -static int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ -static int regv[MAX_MAX]; /* 値が入っているかどうか */ - -void -code_init(void) -{ - arg_offset = 8; - func_disp_offset = -12; - disp_offset = -12; - size_of_int = 4; - endian = 0; - MAX_REGISTER=6; - MAX_DATA_REG=4; - MAX_POINTER=3; - MAX_REGISTER_VAR=2; - - reg_name[REG_EAX] = "%eax"; - reg_name[REG_EBX] = "%ebx"; - reg_name[REG_ECX] = "%ecx"; - reg_name[REG_EDX] = "%edx"; - reg_name[REG_ESI] = "%esi"; - reg_name[REG_EDI] = "%edi"; - reg_name[REG_EBP] = "%ebp"; - reg_name[REG_ESP] = "%esp"; - reg_name_l[REG_EAX] = "%al"; - reg_name_l[REG_EBX] = "%bl"; - reg_name_l[REG_ECX] = "%cl"; - reg_name_l[REG_EDX] = "%dl"; - reg_name_w[REG_EAX] = "%ax"; - reg_name_w[REG_EBX] = "%bx"; - reg_name_w[REG_ECX] = "%cx"; - reg_name_w[REG_EDX] = "%dx"; - -} - -char * -register_name(int i,int byte) -{ - if (i<0) { - error(REG_ERR); - return "%eax"; - } - if (byte && rname[i] <= REG_EDX) { - return reg_name_l[rname[i]]; - } else { - return reg_name[rname[i]]; /* should be error */ - } -} - -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) { /* いらなくなったレジスタを開放 */ - 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; -} - -static -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; -} - -static 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; -} - -static int creg_regvar = -1; -static int creg_regvar_back; -static int creg_back; - -void -creg_destroy() { - creg_back = creg; creg_regvar_back = creg_regvar; - if (creg_regvar>=0) - creg = creg_regvar; - creg_regvar=-1; -} - -void -creg_un_destroy() { - creg = creg_back; creg_regvar = creg_regvar_back; -} - -void -register_usage(char *s) -{ - int i; - printf("# %d: %s:",lineno,s); - printf(" creg=%s dreg=%s ",register_name(creg,0),register_name(dreg,0)); - 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,0),register_name(dreg,0)); - 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(); - use_register(creg,REG_EAX,0); - regv[dreg]=0; - creg_regvar = -1; - register_usage("gexpr_init"); -} - - -void -emit_init(void) -{ - int i; - for(i=0;i<REAL_MAX_REGISTER;i++) { regs[i]=0; regv[i]=0;rname[i]=i;} - free_all_register(); - reg_sp = 0; - text_mode(); -} - -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; - if (rname[virt]==real) - return; - real_v = virtual(real); - move_op = regs[real_v]?"\txchg %s,%s\n":"\tmovl %s,%s\n"; - if (move || (regv[real_v])) { - printf(move_op,reg_name[rname[virt]],reg_name[real]); - } - rname[real_v] = rname[virt]; - rname[virt] = real; -} - -void -use_pointer(int virt, int move) -{ - int i; - if (rname[virt]>=POINTER_REG) - return; - for(i=POINTER_REG;i<MAX_REGISTER;i++) { - if (!regs[virtual(i)]) { - use_register(virt,i,move); - return; - } - } - /* we prefer EBX */ - use_register(virt,REG_EBX,move); -} - -void -use_data_reg(int virt, int move) -{ - int i; - if (rname[virt]<MAX_DATA_REG) - return; - for(i=0;i<MAX_DATA_REG;i++) { - if (!regs[virtual(i)]) { - use_register(virt,i,move); - return; - } - } - /* we prefer EBX */ - use_register(virt,REG_EBX,move); -} - -int -pop_register(void) -{ /* レジスタから値を取り出す */ - return reg_stack[--reg_sp]; -} - -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("\tpushl %s\n",register_name(creg,0)); - /* creg is used soon, don't regv[creg]=0 */ - } else { - reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ - creg = new_reg; - regv[creg]=1; - } -} - -void -emit_push_x(int xreg) -{ - int new_reg; - new_reg = get_register(); - if(new_reg<0) { /* もうレジスタがない */ - reg_stack[reg_sp++] = -1; - printf("\tpushl %s\n",register_name(xreg,0)); - /* creg is used soon, don't regv[xreg]=0 */ - } else { - reg_stack[reg_sp++] = xreg; /* push するかわりにレジスタを使う */ - xreg = new_reg; - regv[xreg]=1; - } -} - -int -emit_pop(int type) -{ - int xreg; - if ((xreg=pop_register())==-1) { - if (type==POINTER_REG) - use_pointer(dreg,0); - else if (type==DATA_REG) - use_data_reg(dreg,0); -if (regv[dreg]) { - printf("# emit_pop dreg conflict\n"); -} - printf("\tpopl %s\n",register_name(dreg,0)); - xreg = dreg; - regv[xreg]=1; - } - return xreg; -} - -static void -emit_pop_free(int xreg) -{ - if (xreg==dreg) { - regv[dreg]=0; - } else if (xreg!=-1) { - free_register(xreg); - } -} - -int -get_register_var(void) -{ - int i; - for(i=REG_ESI;i<REG_ESP;i++) { - if (! regs[i]) { /* 使われていないなら */ - regs[i]=1; /* そのレジスタを使うことを宣言し */ - regv[i]=0; - return i; /* その場所を表す番号を返す */ - } - } - return -1; -} - -void -gexpr(int e1) -{ - gexpr_init(); -#if 0 - if(lineno==2862) { - g_expr(e1); /*break here*/ - return; - } -#endif - g_expr(e1); -} - -int -csvalue() -{ - return rname[creg]; /* for switch 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: - /* use_pointer(creg,0); */ - printf("\tmovl $%s,%s\n",(char *)caddr(e1),register_name(creg,0)); - regv[creg]=1; - return; - case RGVAR: - /* use_pointer(creg,0); */ - printf("\tmovl %s,%s\n",(char *)caddr(e1),register_name(creg,0)); - regv[creg]=1; - return; - case CRGVAR: - printf("\tmovsbl %s,%s\n",(char *)caddr(e1),register_name(creg,0)); - regv[creg]=1; - return; - case LVAR: - /* use_pointer(creg,0); */ - printf("\tlea %d(%%ebp),%s\n",lvar(e2),register_name(creg,0)); - regv[creg]=1; - return; - case REGISTER: - /* this is of course redundant... */ - /* we can use rname for this? */ - /* or why not creg=e2? */ - printf("\tmovl %s,%s\n",register_name(e2,0),register_name(creg,0)); - regv[creg]=1; - return; - case RLVAR: - printf("\tmovl %d(%%ebp),%s\n",lvar(e2),register_name(creg,0)); - regv[creg]=1; - return; - case CRLVAR: - printf("\tmovsbl %d(%%ebp),%s\n",lvar(e2),register_name(creg,0)); - regv[creg]=1; - return; - case FNAME: - printf("\tmovl $%s,%s\n",((NMTBL *)e2)->nm,register_name(creg,0)); - regv[creg]=1; - return; - case CONST: /* 代入する値が0でも特別な処理はしない */ - printf("\tmovl $%d,%s\n",e2,register_name(creg,0)); - regv[creg]=1; - return; - case STRING: - string(e1); - regv[creg]=1; - return; - case FUNCTION: - function(e1); - regv[creg]=1; - 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: /* レジスタに対し、neglを実行すれば実現可能 */ - g_expr(e2); - /* use_data_reg(creg,1); */ - printf("\tnegl %s\n", register_name(creg,0)); - return; - case BNOT: /* ~ */ - g_expr(e2); - /* use_data_reg(creg,1); */ - printf("\tnotl %s\n", register_name(creg,0)); - return; - case LNOT: /* ! */ - g_expr(e2); - use_data_reg(creg,1); - xrn = register_name(creg,1); - printf("\tcmpl $0,%s\n", register_name(creg,0)); - printf("\tsete %s\n", xrn); - printf("\tmovzbl %s,%s\n", xrn,register_name(creg,0)); - return; - case PREINC: - if (car(e2)==REGISTER) { - printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0)); - printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); - return; - } - g_expr(e2); - xrn = register_name(creg,0); - printf("\taddl $%d,(%s)\n",caddr(e1),xrn); - printf("\tmovl (%s),%s\n",xrn,xrn); - return; - case POSTINC: - if (car(e2)==REGISTER) { - printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); - printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0)); - return; - } - g_expr(e2); - emit_push(); - xrn = register_name((e2=emit_pop(0)),0); - printf("\tmovl (%s),%s\n",xrn,register_name(creg,0)); - printf("\taddl $%d,(%s)\n",caddr(e1),xrn); - emit_pop_free(e2); - return; - case CPOSTINC: - /* char *p; *p++ */ - if (car(e2)==REGISTER) { - printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); - printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0)); - return; - } - g_expr(e2); - emit_push(); - xrn = register_name((e2=emit_pop(0)),1); - printf("\tmovsbl (%s),%s\n",xrn,register_name(creg,0)); - printf("\tincl (%s)\n",xrn); - emit_pop_free(e2); - return; - case CPREINC: - if (car(e2)==REGISTER) { - printf("\taddl $%d,%s\n",caddr(e1),register_name(cadr(e2),0)); - printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); - return; - } - g_expr(e2); - printf("\tincl (%s)\n",register_name(creg,0)); - printf("\tmovsbl (%s),%s\n",register_name(creg,0),register_name(creg,0)); - return; - case CPOSTDEC: - if (car(e2)==REGISTER) { - printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); - printf("\tdecl %s\n",register_name(cadr(e2),0)); - return; - } - g_expr(e2); - printf("\tmovsbl (%s),%s\n",register_name(creg,0),register_name(creg,0)); - printf("\tdecl (%s)\n",register_name(creg,0)); - return; - case CPREDEC: - if (car(e2)==REGISTER) { - printf("\tdecl %s\n",register_name(cadr(e2),0)); - printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(creg,0)); - return; - } - g_expr(e2); - emit_push(); - e2 = emit_pop(0); - printf("\tdecl (%s)\n",register_name(e2,0)); - printf("\tmovsbl (%s),%s\n",register_name(e2,0),register_name(creg,0)); - emit_pop_free(e2); - 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,0); - use_register(creg,REG_EAX,0); - g_expr(caddr(e1)); - /* e4 = rname[creg]; this is a bad idea */ - use_register(creg,REG_EAX,1); - jmp(e3=fwdlabel()); - fwddef(e2); - use_register(creg,REG_EAX,0); - g_expr(cadddr(e1)); - /* use_register(creg,e4,1); */ - use_register(creg,REG_EAX,1); - fwddef(e3); - return; - case STASS: - sassign(e1); - return; - case ASS: case CASS: - assign(e1); - return; - case ASSOP: case CASSOP: - assop(e1); - return; - case RSTRUCT: - g_expr(e2); - return; - case COMMA: - g_expr(e2); - g_expr(caddr(e1)); - return; - case RETURN: - n = (NMTBL *)e2; - if (retcont==0) - retcont=fwdlabel(); - printf("\tleal _%d,%s\n",retcont,register_name(creg,0)); - regv[creg]=1; - return; - case ENVIRONMENT: - printf("\tmovl %%ebp,%s\n",register_name(creg,0)); - regv[creg]=1; - return; - default: - b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ - xrn = register_name(creg,0); - printf("\txorl %s,%s\n",xrn,xrn); - jmp(e3=fwdlabel()); - fwddef(e2); - printf("\tmovl $1,%s\n",xrn); - fwddef(e3); - regv[creg]=1; - } -} - -void -bexpr(int e1, char cond, int l1) -{ - gexpr_init(); - b_expr(e1,cond,l1,0); -} - -void -b_expr(int e1, char cond, int l1,int err) -{ - int e2,l2; - if (chk) return; - e2=cadr(e1); - switch(car(e1)) { - case LNOT: - b_expr(e2,!cond,l1,0); - return; - case GT: - rexpr(e1,l1,cond?"g":"le"); - return; - case UGT: - rexpr(e1,l1,cond?"a":"be"); - return; - case GE: - rexpr(e1,l1,cond?"ge":"l"); - return; - case UGE: - rexpr(e1,l1,cond?"ae":"b"); - return; - case LT: - rexpr(e1,l1,cond?"l":"ge"); - return; - case ULT: - rexpr(e1,l1,cond?"b":"ae"); - return; - case LE: - rexpr(e1,l1,cond?"le":"g"); - return; - case ULE: - rexpr(e1,l1,cond?"be":"a"); - return; - case EQ: - rexpr(e1,l1,cond?"e":"ne"); - return; - case NEQ: - rexpr(e1,l1,cond?"ne":"e"); - return; - case LAND: - b_expr(e2,0,cond?(l2=fwdlabel()):l1,0); - b_expr(caddr(e1),cond,l1,0); - if(cond) fwddef(l2); - return; - case LOR: - b_expr(e2,1,cond?l1:(l2=fwdlabel()),0); - b_expr(caddr(e1),cond,l1,0); - if(!cond) fwddef(l2); - return; - case CRGVAR: - printf("\tcmpb $0,%s\n",(char *)caddr(e1)); - jcond(l1,cond); - return; - case CRLVAR: - printf("\tcmpb $0,%d(%%ebp)\n",lvar(e2)); - jcond(l1,cond); - return; - case RGVAR: - printf("\tcmpl $0,%s\n",(char *)caddr(e1)); - jcond(l1,cond); - return; - case RLVAR: - printf("\tcmpl $0,%d(%%ebp)\n",lvar(e2)); - jcond(l1,cond); - return; - case REGISTER: - printf("\tcmpl $0,%s\n",register_name(e2,0)); - jcond(l1,cond); - return; - case CONST: - if((cond&&e2)||(!cond&&!e2)) jmp(l1); - return; - default: - if(err) { - error(-1); return; /* recursice g_expr/b_expr */ - } - g_expr(e1); - printf("\tcmpl $0,%s\n",register_name(creg,0)); - jcond(l1,cond); - return; - } -} - -void -ascii(char *s) -{ - printf("\t.string \""); - 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); - lb=fwdlabel(); - printf("\tjmp _%d\n",lb); - i=backdef(); - ascii(s); - printf("\t.align 2\n"); - fwddef(lb); - printf("\tlea _%d,%s\n",i,register_name(creg,0)); - } else { - s=(char *)cadr(e1); - printf(".section\t.rodata\n"); - lb=fwdlabel(); - printf("_%d:\n",lb); - ascii(s); - if (output_mode==TEXT_EMIT_MODE) { - printf(".text\n"); - } else { - text_mode(); - } - printf("\tlea _%d,%s\n",lb,register_name(creg,0)); - } -} - -#define MAX_COPY_LEN 20 - -void -emit_copy(int from,int to,int length,int offset,int value,int det) -{ - int fix = 0; - /* length <0 means upward direction copy */ - switch (length) { - case 0: break; - case 1: case -1: - printf("\tmovb %d(%s),%s\n",offset,register_name(from,0), reg_name_l[rname[dreg]] ); - printf("\tmovb %s,%d(%s)\n",reg_name_l[rname[dreg]] ,offset,register_name(to,0)); - break; - case 2: case -2: - printf("\tmovw %d(%s),%s\n",offset,register_name(from,0), reg_name_w[rname[dreg]] ); - printf("\tmovw %s,%d(%s)\n",reg_name_w[rname[dreg]] ,offset,register_name(to,0)); - break; - case 4: case -4: - printf("\tmovl %d(%s),%s\n",offset,register_name(from,0), register_name(dreg,0)); - printf("\tmovl %s,%d(%s)\n",register_name(dreg,0), offset,register_name(to,0)); - 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) { -/* - call bcopy - g_expr(list3(FUNCTION,,); - break; - */ - } - use_register(from,REG_ESI,1); - use_register(to, REG_EDI,1); - use_register(dreg,REG_ECX,0); - if (length<0) { - printf("\tmovl $%d,%%ecx\n",-length/4); - printf("\taddl $%d,%%esi\n",-length); - printf("\taddl $%d,%%edi\n",-length); - printf("\tstd\n\trep\n\tmovsl\n"); - if(length%4) { - emit_copy(from,to,length,offset+length/4,0,det); - } - } else { - printf("\tmovl $%d,%%ecx\n",length/4); - fix = (length/4)*4; - printf("\tcld\n\trep\n\tmovsl\n"); - if(length%4) { - emit_copy(from,to,length,offset+length/4,0,det); - } - } - } - 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("\tsubl $%d,%s\n",fix,register_name(to,0)); - if(creg!=to) { - if (to==dreg) - printf("\tmovl %s,%s\n",register_name(to,0),register_name(creg,0)); - else { - free_register(creg); creg=to; - } - } - } - regv[from]=regv[to]=regv[dreg]=0; - regv[creg]=1; -} - -int -struct_push(int e4,int t) -{ - int length,xreg,save,lreg; - g_expr(e4); - length=size(t); - if(length%size_of_int) { - length += size_of_int - (length%size_of_int); - } - if (length==4) { - printf("\tpushl (%s)\n",register_name(creg,0)); return 1; - } - if (length==8) { - printf("\tpushl 4(%s)\n",register_name(creg,0)); - printf("\tpushl (%s)\n",register_name(creg,0)); return 2; - } - printf("\tsubl $%d,%%esp\n",length); - if (register_full()) { - save = 1; - for(lreg=0;lreg==creg||lreg==dreg;lreg++); - printf("\tpushl %s\n",register_name(lreg,0)); - xreg = lreg; regv[xreg]=0; - } else { - save=0; - xreg = get_register(); - } - if (save) - printf("\tlea %d(%%esp),%s\n",size_of_int,register_name(xreg,0)); - else - printf("\tmovl %%esp,%s\n",register_name(xreg,0)); - regv[xreg]=1; - /* downward direction copy */ - emit_copy(creg,xreg,length,0,0,1); - /* we have value in creg, it may be changed */ - if (save) { - if(creg==xreg) { - creg = get_register(); /* creg is freed in emit_copy */ - } - printf("\tpopl %s\n",register_name(xreg,0)); - regv[xreg]=1; - } else - free_register(xreg); - return length/size_of_int; -} - -void -function(int e1) -{ - int e2,e3,e4,e5,nargs,t; - NMTBL *n; - int save,saved; - if (free_register_count()<1) { - for(save = 0;save==dreg||save==creg;save++); - printf("\tpushl %s\n",register_name(save,0)); - saved = 1; - } else { - save = get_register(); - saved = 0; - } - regv[save]=0; - e2 = cadr(e1); - nargs = 0; - for (e3 = caddr(e1); e3; e3 = cadr(e3)) { - t=caddr(e3); - n=(NMTBL *)(e5=(cadr(e4 = car(e3)))); - if(scalar(t)) { - g_expr(e4); - printf("\tpushl %s\n",register_name(creg,0)); - } 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); - } else { - use_register(creg,REG_EAX,0); - g_expr(e2); - } - - /* we don't have to save creg nor dreg */ - regs[creg]=0; regs[dreg]=0; - regv[creg]= regv[dreg]= regv[save]= 0; - use_register(creg,REG_EAX,0); - use_register(dreg,REG_EDX,0); /* will be destroyed */ - use_register(save,REG_ECX,0); /* will be destroyed */ - regs[creg]=1; regs[dreg]=1; - - if (car(e2) == FNAME) { - printf("\tcall\t%s\n",n->nm); - } else { - printf("\tcall\t*%s\n",register_name(creg,0)); - } - if (nargs) printf("\taddl $%d,%%esp\n",size_of_int*nargs); - if (saved) { - printf("\tpopl %s\n",register_name(save,0)); - } else { - free_register(save); - } - regv[save]=0; - regv[creg]=1; -} - -/* goto arguments list */ -/* target list4(list2(tag,disp),cdr,ty,source_expr) */ -/* source expr=listn(tag,...) */ -/* source (after) list2(tag,disp) */ -/* source list list3(e,cdr,sz) */ - -#define DEBUG_PARALLEL_ASSIGN 1 - -int -overrap(int t,int sz,int source) -{ - int s,s0,s1; - int t0=cadr(t); - int t1=t0+sz; - for(;source;source=cadr(source)) { - s=car(source); s0=cadr(s); - if(car(s)==REGISTER && car(t)==REGISTER) { - if(s0==t0) return s; - } else if (is_same_type(s,t)) { - s1=s0+caddr(source); -#if DEBUG_PARALLEL_ASSIGN>1 -printf("# ovedrrap source %d t0 %d t1 %d\n",car(car(t)),t0,t1); -printf("# ovedrrap target %d s0 %d s1 %d\n",car(car(source)),s0,s1); -printf("# ovedrrap equal = %d\n",((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1))); -#endif - if((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1)) return s; - } - } - return 0; -} - -void -remove_target(int *target,int t,int *use) -{ - int use0=*use; - while(use0) { - if (car(use0)==t) { - free_register(caddr(use0)); - break; - } - use0 = cadr(use0); - } - remove0(target,t); -} - -void -save_target(int t,int s,int *target,int *use,int sz,int ty) -{ - int e1; - /*新しいレジスタ(or スタック)を取得する*/ - if (sz==size_of_int && (e1=get_register())!=-1) { - *use=list3(t,*use,e1); - e1=list2(REGISTER,e1); - g_expr(assign_expr0(e1,s,ty,ty)); - *target = append4(*target,t,ty,e1); - } else { - disp-=sz; - g_expr(assign_expr0((e1=list2(LVAR,disp)),s,ty,ty)); - *target = append4(*target,t,ty,e1); - } -} - -int -circular_dependency(int t,int s,int *target,int *source) -{ - int target0=*target; - int t1,sz,ty,s1; - while(target0) { - if (cadddr(target0)==s) { - t1=car(target0); - s=cadddr(target0); - sz=size(ty=caddr(target0)); - if(t==t1) { -#if DEBUG_PARALLEL_ASSIGN -printf("# circular dependency %d ty %d+%d sz %d\n",car(t1),ty,cadr(t1),sz); -#endif - return 1; - } - if ((s1=overrap(t1,sz,*source))) { - /* another overrap start over */ - return circular_dependency(t,s1,target,source); - } - } - target0=cadr(target0); - } - return 0; -} - -void -parallel_assign(int *target,int *source,int *processing,int *use) -{ - int t,s,sz,ty,target0,s1; - while(*target) { - target0=*target; - while(target0) { - t=car(target0); s=cadddr(target0); - sz=size(ty=caddr(target0)); - if(car(t)==car(s) && cadr(t)==cadr(s)) { - /*書き込み先が自分自身*/ -#if DEBUG_PARALLEL_ASSIGN -printf("# remove same %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); -#endif - remove_target(target,t,use); - /* 破壊されては困るので、source listからは除かない */ - } else if (!(s1=overrap(t,sz,*source))) { - /* 重なってないので安心して書き込める */ -#if DEBUG_PARALLEL_ASSIGN -printf("# normal assign %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); -#endif - g_expr(assign_expr0(t,s,ty,ty)); - remove_target(target,t,use); remove0(source,s); - } else { - if(circular_dependency(t,s1,target,source)) { -#if DEBUG_PARALLEL_ASSIGN - printf("# saving %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); -#endif - remove_target(target,t,use); remove0(source,s); - save_target(t,s,target,use,sz,ty); - } - } - target0=cadr(target0); - } - } -} - -void -remove0(int *parent,int e) -{ - int list; - while ((list=*parent)) { - if (car(list)==e) { - *parent= cadr(list); return; - } else { - parent=&cadr(list); - } - } -} - -void -remove0_all(int *parent,int e) -{ - int list; - while ((list=*parent)) { - if (car(list)==e) { - *parent= cadr(list); - } else { - parent=&cadr(list); - } - } -} - -int -is_simple(int e1) -{ - return ( - e1==CONST || e1==FNAME || e1==LVAR || e1==REGISTER || - e1==GVAR || e1==RGVAR || e1==RLVAR || e1==CRLVAR || e1==CRGVAR - ); -} - -int -is_same_type(int e1,int e2) -{ - int ce1=car(e1); - int ce2=car(e2); - return ( - (ce1==LVAR && (ce2==RLVAR||ce2==CRLVAR)) - || (ce2==LVAR && (ce1==RLVAR||ce1==CRLVAR)) - || (ce1==GVAR && (ce2==RGVAR||ce2==CRGVAR)) - || (ce2==GVAR && (ce1==RGVAR||ce1==CRGVAR)) - ); -} - -int -is_memory(int e1) -{ - int ce1=car(e1); - return ( - ce1==LVAR ||ce1==RLVAR||ce1==CRLVAR || - ce1==GVAR ||ce1==RGVAR||ce1==CRGVAR || - ce1==REGISTER - ); -} - -void -jump(int e1, int env) -{ - int e2,e3,e4,sz,arg_size,ty,max_regs,regs; - int t0,s0; - NMTBL *code0; - int target = 0; - int source = 0; - int processing = 0; - int use = 0; - - /* まず、サイズを計算しながら、決まった形に落す。 */ - - arg_size = 0; regs = 0; max_regs = MAX_REGISTER_VAR-1; - for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { - e2 = car(e3); sz = size(ty=caddr(e3)); - if (regs <= max_regs&&scalar(ty)) { - target=list4(list2(REGISTER,virtual((regs++)+REG_ESI)), - target,ty,e2); - } else { - target=list4(list2(LVAR,0), - target,ty,e2); - arg_size += sz; - } -#if DEBUG_PARALLEL_ASSIGN -printf("# target %d ty %d+%d sz %d\n",car(car(target)),ty,cadr(car(target)),sz); -#endif - } - - /* disp を飛び先似合わせて修正 */ - if (fnptr->sc==CODE) { - if (-arg_size<disp) disp = -arg_size; - jump_offset = 0; - } else { - if (disp_offset-arg_size<disp) disp = disp_offset-arg_size; - jump_offset = 0; - } - - /* 複雑な式を前もって計算しておく */ - /* 必要なら局所変数を用いる。 */ - /* 局所変数へのオフセットを覚えておく */ - - for (e2 = target; e2; e2 = cadr(e2)) { - t0=car(e2); s0=cadddr(e2); - sz=size(ty=caddr(e2)); - if(car(t0)==LVAR) { - /* ここで、書込先アドレスを決める */ - cadr(t0)=-arg_size+jump_offset; - arg_size-=sz; - } - if (!is_simple(car(s0))) { - disp-=sz; - g_expr(assign_expr0((e4=list2(LVAR,disp)),s0,ty,ty)); - cadddr(e2)=e4; - s0=e4; - } else if (is_same_type(t0,s0)) { - if(cadr(t0)==cadr(s0)) { -#if DEBUG_PARALLEL_ASSIGN -printf("# remove same memory %d ty %d+%d sz %d\n",car(t0),ty,cadr(t0),sz); -#endif - /* we should check size also (but currently useless */ - remove0(&target,t0); - /* still we have source to avoid overwrite */ - } - } - if(is_memory(s0)) { - source=list3(s0,source,sz); -#if DEBUG_PARALLEL_ASSIGN -printf("# source %d ty %d+%d sz %d\n",car(car(source)),ty,cadr(car(source)),sz); -#endif - } - } - - /* compute jump address */ - e2 = cadr(e1); - if (car(e2) == FNAME) { - code0=(NMTBL *)cadr(e2); - if (code0->sc!=CODE) { - error(TYERR); return; - } - } else { /* indirect */ - g_expr(e2); - emit_push(); - } - if (env) { - g_expr(env); - emit_push(); - } - - /* 並列代入を実行 */ - - parallel_assign(&target,&source,&processing,&use); - while (use) { - free_register(caddr(use)); use=cadr(use); - } - if(target) error(-1); - - if (env) { - /* change the frame pointer */ - e3 = emit_pop(0); - printf("\tmovl %s,%%ebp\n",register_name(e3,0)); - emit_pop_free(e3); - } else if (fnptr->sc==FUNCTION) { - printf("\tlea %d(%%ebp),%%ebp\n",disp_offset); - } - - if (car(e2) == FNAME) { - printf("\tjmp %s\n",code0->nm); - } else { - e2 = emit_pop(0); - printf("\tjmp *%s\n",register_name(e2,0)); - emit_pop_free(e2); - } -} - -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),(e2=pop_register())); - emit_pop_free(e2); - regv[creg]=1; - return; -} - - -void -rindirect(int e1) /* *(p +5 ) */ - -{ - char *op; - int e2,e3,byte; - - op = ((byte = (car(e1) == CRINDIRECT)) ? "movsbl" : "movl"); - e3 = cadr(e2 = cadr(e1)); - g_expr(e2); - printf("\t%s (%s),%s\n",op,register_name(creg,0),register_name(creg,0)); -} - -void -sassign(int e1) -{ - int e2,e3,e4,sz,xreg,det; - - /* structure assignment */ - e2 = cadr(e1); /* pointer variable to the struct */ - e3 = cadr(e2); /* offset of the variable (distination) */ - e4 = caddr(e1); /* right value (source) */ - sz = cadddr(e1); /* size of struct or union */ - g_expr(e4); - emit_push(); - g_expr(e2); - xreg = emit_pop(0); - /* 一般的にはコピーのオーバラップの状況は実行時にしかわからない */ - /* しかし、わかる場合もある */ - if (car(e4)==RSTRUCT) e4=cadr(e4); - if (is_same_type(e2,e4)) { - if(cadr(e2)<cadr(e4)) sz=-sz; - det=1; - } else { - det = 0; - } - emit_copy(xreg,creg,sz,0,1,det); - emit_pop_free(xreg); - return; -} - -void -assign(int e1) -{ - char *op; - int e2,e3,e4,byte; - - op = ((byte=(car(e1) == CASS))? "movb" : "movl"); - /* 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 %s,%s\n",op,register_name(creg,byte),(char *)caddr(e2)); - return; - case LVAR: - g_expr(e4); - if (byte) use_data_reg(creg,1); - printf("\t%s %s,%d(%%ebp)\n",op,register_name(creg,byte),lvar(cadr(e2))); - return; - case REGISTER: - g_expr(e4); - if (creg!=cadr(e2)) - printf("\tmovl %s,%s\n",register_name(creg,0),register_name(cadr(e2),0)); - return; - } - g_expr(e2); - emit_push(); - use_data_reg(creg,0); - g_expr(e4); - if (byte) use_data_reg(creg,1); - e2 = emit_pop(0); - printf("\t%s %s,(%s)\n",op,register_name(creg,byte),register_name(e2,0)); - emit_pop_free(e2); - regv[creg]=1; - return; -} - -void -assop(int e1) -{ - int e2,e3,byte,op,reg; - char *xrn; - int xreg,edx; - - /* 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); - if (car(e2)==REGISTER) { - xreg = creg; - creg = reg = cadr(e2); - tosop(op,xreg); - creg = xreg; - printf("\tmovl %s,%s\n",register_name(reg,0),register_name(creg,0)); - regv[creg]=1; - return; - } - emit_push(); - g_expr(e2); - edx = edx_setup(); - xrn = register_name(xreg = emit_pop(0),0); /* pop e3 value */ - regv[xreg]=regs[xreg]=1; - printf("\tmovl %s,%s # assop \n",register_name(creg,0),register_name(edx,0)); - regv[edx]=1; - ld_indexx(byte,0,edx); - tosop(op,xreg); - printf("\t%s %s,(%s)\n",byte ? "movb" : "movl",register_name(creg,byte),register_name(edx,0)); - edx_cleanup(); - emit_pop_free(xreg); - regv[creg]=1; - return; -} - - -void -tosop(int op,int oreg) -{ - int dx; - char *orn,*crn; - - 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) { - printf("\tpopl %s\n",register_name(dreg,0)); - oreg = dreg; - regv[dreg]=1; - } - regv[oreg]=1; regs[oreg]=1; - orn = register_name(oreg,0); - crn = register_name(creg,0); - switch(op) { - case ADD: - printf("\taddl %s,%s\n",orn,crn); - break; - case SUB: - printf("\tsubl %s,%s\n",orn,crn); - break; - case BAND: - printf("\tandl %s,%s\n",orn,crn); - break; - case EOR: - printf("\txorl %s,%s\n",orn,crn); - break; - case BOR: - printf("\torl %s,%s\n",orn,crn); - break; - case MUL: - case UMUL: - printf("\t%s %s,%s\n","imull",orn,crn); - break; - case DIV: - case UDIV: - use_register(creg,REG_EAX,1); - edx_setup(); - orn = register_name(oreg,0); - if (op==DIV) - printf("\tcltd\n\tdivl %s\n",orn); - else - printf("\txor %%edx,%%edx\n\tidivl %s\n",orn); - edx_cleanup(); - break; - case MOD: - case UMOD: - use_register(creg,REG_EAX,1); - edx_setup(); - orn = register_name(oreg,0); - if (op==DIV) - printf("\tcltd\n\tdivl %s\n",orn); - else - printf("\txor %%edx,%%edx\n\tidivl %s\n",orn); - dx = virtual(REG_EDX); - if (dx!=creg) { - rname[dx]=rname[creg]; - rname[creg]=REG_EDX; - } - edx_cleanup(); - break; - } - if (oreg!=dreg&&oreg>=0) - free_register(oreg); -} - -static int edx_stack=0; - -int -edx_setup() -{ - int edx_save; - /* make real EDX register empty */ - if (free_register_count()<1) { - for(edx_save = 0;edx_save==dreg||edx_save==creg;edx_save++); - printf("\tpushl %s\n",register_name(edx_save,0)); - edx_stack = list3(edx_save,edx_stack,0); - } else { - edx_save = get_register(); - edx_stack = list3(edx_save,edx_stack,1); - } - regv[edx_save]=0; - use_register(edx_save,REG_EDX,0); - return edx_save; -} - - -void -edx_cleanup() -{ - if (caddr(edx_stack)==0) { - printf("\tpopl %s\n",register_name(car(edx_stack),0)); - } else - free_register(car(edx_stack)); - edx_stack = cadr(edx_stack); -} - -void -shift(char *op, int reg) -{ - if (reg>=0) { - use_register(reg,REG_ECX,1); - } else { - use_register(dreg,REG_ECX,0); - printf("\tpopl %%ecx\n"); - } - printf("\t%s %%cl,%s\n",op,register_name(creg,0)); -} - -void -ld_indexx(int byte, int n, int xreg) -{ - char *op; - - op = byte ? "movsbl" : "movl"; - if (n) - printf("\t%s %d(%s),%s\n",op,n,register_name(xreg,0),register_name(creg,byte)); - else - printf("\t%s (%s),%s\n",op,register_name(xreg,0),register_name(creg,byte)); -} - -void -cmpdimm(int e, int csreg) -{ - /* used in dosiwtch() */ - use_register(creg,csreg,0); - printf("\tcmpl $%d,%s\n",e,register_name(creg,0)); -} - -void -opening(char *filename) -{ - printf("\t.file \"%s\"\n",filename); - printf("\t.version\t\"01.01\"\n"); - printf("gcc2_compiled.:\n"); - printf(".text\n"); - emit_init(); -} - -void -closing(void) -{ - global_table(); - printf("\t.ident \"Micro-C compiled\"\n"); -} - -void -rexpr(int e1, int l1, char *s) -{ - g_expr(list3(SUB,cadr(e1),caddr(e1))); - printf("\tj%s\t_%d\n",s,l1); -} - -void -jcond(int l, char cond) -{ - printf("\tj%s\t_%d\n",cond?"ne":"e",l); -} - -void -jmp(int l) -{ - control=0; - printf("\tjmp\t_%d\n",l); - /* align? */ - /* - this is not allowed because of ? operator - regv[creg]=regv[dreg]=0; - use_register(creg,REG_EAX,0); - use_register(dreg,REG_EBX,0); - */ -} - -int -fwdlabel(void) -{ - return labelno++; -} - -void -fwddef(int l) -{ - control=1; - printf("_%d:\n",l); -} - -int -backdef(void) -{ - control=1; - printf("_%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 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=(disp-(size_of_int-1))&(-(size_of_int-1)); - 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,0)); - /* printf("\tleave\n"); */ - } - fwddef(retlabel); - /* use_register(creg,REG_EAX,0); too late */ - /* if(disp) printf("\taddl $%d,%%esp\n",-disp); */ - 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"); - disp=(disp-(size_of_int-1))&(-(size_of_int-1)); - 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 -ret(void) -{ - use_register(creg,REG_EAX,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) { - error(-1); 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 { - 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.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 (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; - } -} - - -/* end */