/* Micro-C Code Generatation Part for intel386 */ #define EXTERN extern #include "mc.h" #define REGISTERS6 0 void code_init(); void free_register(); void emit_init(); void emit_push(); void gexpr(); void g_expr(); void bexpr(); void b_expr(); void string(); void function(); void machinop(); void rindirect(); void assign(); void assop(); void oprt_assop(); void oprt_assop_reg(); void oprt(); void oprt1(); void oprt_div(); void asld(); void tosop(); char *div_setup() ; void div_cleanup() ; void shift() ; void shift_1() ; void lddim() ; void ldx(); void ld_indexx(); void st_indexx(); void ld_index(); void st_index(); void indexy(); void ld_indir(); void cmpdimm(); void global_table() ; void local_table() ; void opening(); void closing(); void gen_gdecl() ; void jmp_label(); void jmp_eq_label(); void rexpr(); void jcond(); void jmp(); void def_label() ; void gen_comment(); void gen_source(); void enter() ; void enter1() ; void ret(); void emit_data(); void text_mode(); void data_mode(); int cadr(); int car(); int caddr(); int fwdlabel(); void fwddef(); int cadddr(); int backdef(); int simpop(); int simpop_mul(); int simpoperand(); int error(); int size(); int list3(); void increment(); void asrd(); void andd(); #define TEXT_EMIT_MODE 0 #define DATA_EMIT_MODE 1 static output_mode = TEXT_EMIT_MODE; static data_alignment = 0; /* local1 <----24 local variable %esi -20 <- disp_offset %edi -16 %edx -12 %ecx -8 %ebx -4 %ebp = %esp 0 %eip 4 <- arg_offset arg1 8 see enter/enter1/leave */ int arg_offset = 4; int disp_offset = -20; int int_size = 4; int endian = 0; int MAX_REGISTER=6; /* intel386のレジスタが6つということ*/ int MAX_DATA_REG=4; int MAX_POINTER=3; 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; /* emit_poped register */ /* static char *xrn; pointer register name */ static int reg_sp; /* REGister Stack-Pointer */ #define REG_EAX 0 #define REG_ECX 1 #define REG_EDX 2 #define REG_EBX 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]; /* 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 10 static char rname[MAX_MAX]; static char regs[MAX_MAX]; /* 使われているレジスタを示すフラグ */ static char reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ void code_init() { if (REGISTERS6) { arg_offset = 4; disp_offset = -20; int_size = 4; endian = 0; MAX_REGISTER=6; MAX_DATA_REG=4; MAX_POINTER=3; } else { arg_offset = 4; disp_offset = -12; int_size = 4; endian = 0; MAX_REGISTER=4; MAX_DATA_REG=4; MAX_POINTER=1; } 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"; } char * regster(i) { return reg_name[rname[i]]; } int get_register() { /* 使われていないレジスタを調べる */ int i; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i]) { /* 使われていないなら */ regs[i]=1; /* そのレジスタを使うことを宣言し */ return i; /* その場所を表す番号を返す */ } } return -1; /* 空いている場所がないなら、それを表す -1 を返す */ } void free_register(i) { /* いらなくなったレジスタを開放 */ regs[i]=0; } int register_full() { int i; for(i=0;i<MAX_REGISTER;i++) { if (! regs[i]) { return 0; } } return 1; } void emit_init() { int i; for(i=0;i<MAX_REGISTER;i++) regs[i]=0; for(i=0;i<MAX_REGISTER;i++) rname[i]=i; creg = get_register(); xreg = dreg = get_register(); crn = reg_name[rname[creg]]; drn = reg_name[rname[dreg]]; reg_sp = 0; text_mode(); } void set_crn(i) int i; { creg = i; crn = reg_name[rname[creg]]; } void set_drn(i) int i; { dreg = i; drn = reg_name[rname[dreg]]; } void change(reg1,reg2) int reg1,reg2; { int tmp; /* Change role of two register No copy happens. Name change only */ tmp = rname[reg1]; rname[reg1] = rname[reg2]; rname[reg2] = tmp; crn = reg_name[rname[creg]]; drn = reg_name[rname[dreg]]; lrn = reg_name[rname[lreg]]; } virtual(real) 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(virt,real,move) int virt,real,move; { int i,k,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 || regs[real_v]) { printf(move_op,reg_name[rname[virt]],reg_name[real]); } rname[real_v] = rname[virt]; rname[virt] = real; crn = reg_name[rname[creg]]; drn = reg_name[rname[dreg]]; lrn = reg_name[rname[lreg]]; } void use_pointer(virt,move) int virt,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(virt,move) int virt,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() { /* レジスタから値を取り出す */ int i,j; j = creg; i = reg_stack[--reg_sp]; if(i<0) { return i; } else { lreg = i; lrn = reg_name[rname[lreg]]; regs[i]=0; return lreg; } } int stack_used() { return reg_stack[--reg_sp]<0; } void emit_push() { int new_reg; new_reg = get_register(); if(new_reg<0) { /* もうレジスタがない */ reg_stack[reg_sp++] = -1; printf("\tpushl %s\n",crn); } else { reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ set_crn(new_reg); } } char * emit_pop(type) int type; { char *xrn; if (pop_register()==-1) { if (type==POINTER_REG) use_pointer(dreg,0); else if (type==DATA_REG) use_data_reg(dreg,0); printf("\tpopl %s\n",drn); xrn = drn; xreg = dreg; } else { xrn = lrn; xreg = lreg; } return xrn; } void gexpr(e1) int e1; { emit_init(); if (debug && lsrc) tree_print(e1); g_expr(e1); csvalue = rname[creg]; /* for siwtch value */ } void g_expr(e1) int e1; { int e2,e3,e4; char *xrn; if (chk) return; e2 = cadr(e1); switch (car(e1)){ case GVAR: /* use_pointer(creg,0); */ printf("\tmovl $%s,%s\n",caddr(e1),crn); return; case RGVAR: /* use_pointer(creg,0); */ printf("\tmovl %s,%s\n",caddr(e1),crn); return; case CRGVAR: printf("\tmovsbl %s,%s\n",caddr(e1),crn); return; case LVAR: /* use_pointer(creg,0); */ printf("\tlea %d(%%ebp),%s\n",e2,crn); return; case RLVAR: printf("\tmovl %d(%%ebp),%s\n",e2,crn); return; case CRLVAR: printf("\tmovsbl %d(%%ebp),%s\n",e2,crn); return; case FNAME: printf("\tmovl $%s,%s\n",((NMTBL *)e2)->nm,crn); return; case CONST: /* 代入する値が0でも特別な処理はしない */ printf("\tmovl $%d,%s\n",e2,crn); return; case STRING: string(e1); return; case FUNCTION: function(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", crn); return; case BNOT: /* ~ */ g_expr(e2); /* use_data_reg(creg,1); */ printf("\tnotl %s\n", crn); return; case LNOT: /* ! */ g_expr(e2); use_data_reg(creg,1); printf("\tcmpl $0,%s\n", crn); printf("\tsete %s\n", reg_name_l[rname[creg]]); printf("\tmovzbl %s,%s\n", reg_name_l[rname[creg]],crn); return; case PREINC: switch (car(e2)) { case GVAR: e3 = caddr(e2); increment(e2,caddr(e1)); printf("\tmovl %s,%s\n",e3,crn); return; case LVAR: e3 = cadr(e2); increment(e2,caddr(e1)); printf("\tmovl %d(%%ebp),%s\n",e3,crn); return; default: g_expr(e2); if (caddr(e1)==1) { printf("\tincl (%s)\n",crn); printf("\tmovl (%s),%s\n",crn,crn); return; } printf("\taddl $%d,(%s)\n",caddr(e1),crn); printf("\tmovl (%s),%s\n",crn,crn); return; } case POSTINC: switch (car(e2)) { case GVAR: printf("\tmovl %s,%s\n",caddr(e2),crn); increment(e2,caddr(e1)); return; case LVAR: printf("\tmovl %d(%%ebp),%s\n",cadr(e2),crn); increment(e2,caddr(e1)); return; default: g_expr(e2); emit_push(); xrn = emit_pop(0); printf("\tmovl (%s),%s\n",xrn,crn); if (caddr(e1)==1) { printf("\tincl (%s)\n",xrn); return; } printf("\taddl $%d,(%s)\n",caddr(e1),xrn); return; } case CPOSTINC: /* char *p; *p++ */ emit_push(); g_expr(e2); xrn = emit_pop(0); printf("\tmovsbl (%s),%s\n",xrn,crn); printf("\tincl (%s)\n",xrn); return; case CPREINC: g_expr(e2); printf("\tincl (%s)\n",crn); printf("\tmovsbl (%s),%s\n",crn,crn); return; case CPOSTDEC: g_expr(e2); printf("\tmovsbl (%s),%s\n",crn,crn); printf("\tdecl (%s)\n",crn); return; case CPREDEC: emit_push(); g_expr(e2); xrn = emit_pop(0); printf("\tdecl (%s)\n",xrn); printf("\tmovsbl (%s),%s\n",xrn,crn); return; case MUL: case UMUL: if (car(e3=caddr(e1)) == CONST) { if (0 < (e3 = cadr(e3)) && e3 <= 10) { g_expr(e2); switch (e3) { case 8: asld(3); return; case 4: asld(2); return; case 2: asld(1); return; case 1: return; case 10: asld(1); case 5: printf("\tmovl %s,%s\n",crn,drn); asld(2); printf("\taddl %s,%s\n",drn,crn); return; case 6: asld(1); case 3: printf("\tmovl %s,%s\n",crn,drn); asld(1); printf("\taddl %s,%s\n",drn,crn); return; case 9: case 7: printf("\tmovl %s,%s\n",crn,drn); asld(3); if (e3 == 9) printf("\taddl %s,%s\n",drn,crn); else printf("\tsubl %s,%s\n",drn,crn); return; } } } machinop(e1); return; case DIV: case UDIV: if (car(e3=caddr(e1)) == CONST) { switch (cadr(e3)) { case 32:e4=5;break; case 16:e4=4;break; case 8:e4=3;break; case 4:e4=2;break; case 2:e4=1;break; case 1:e4=0;break; default: machinop(e1);return; } g_expr(e2); asrd(car(e1),e4); return; } machinop(e1); return; case MOD: case UMOD: if (car(e3=caddr(e1)) == CONST) { switch (e3) { case 32:g_expr(e2); andd(0x1f);return; case 16:g_expr(e2); andd(0xf); return; case 8 :g_expr(e2); andd(0x7); return; case 4 :g_expr(e2); andd(0x3); return; case 2 :g_expr(e2); andd(0x1); return; case 1 :g_expr(e2); andd(0x0); return; } } machinop(e1); return; 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 ASS: case CASS: assign(e1); return; case ASSOP: case CASSOP: assop(e1); return; case COMMA: g_expr(e2); g_expr(caddr(e1)); return; default: b_expr(e1,1,e2=fwdlabel()); /* including > < ... */ printf("\txorl %s,%s\n",crn,crn); jmp(e3=fwdlabel()); fwddef(e2); printf("\tmovl $1,%s\n",crn); fwddef(e3); } } void bexpr(e1,cond,l1) int e1,l1; char cond; { emit_init(); b_expr(e1,cond,l1); } void b_expr(e1,cond,l1) int e1,l1; char cond; { 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?"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); 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(%%ebp)\n",e2); jcond(l1,cond); return; case RGVAR: printf("\tcmpl $0,%s\n",caddr(e1)); jcond(l1,cond); return; case RLVAR: printf("\tcmpl $0,%d(%%ebp)\n",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(s) 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%c%c\n",92,'0',34); } void string(e1) 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,crn); } 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,crn); } } void function(e1) 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("\tlea $%s,%s\n",n->nm,crn); printf("\tpushl %s\n",crn); break; case ADDRESS: g_expr(e5); printf("\tpushl %s\n",crn); break; default:g_expr(e4); printf("\tpushl %s\n",crn); } ++nargs; } if (car(e2) == FNAME) { n=(NMTBL *)cadr(e2); use_register(creg,REG_EAX,0); printf("\tcall\t%s\n",n->nm); } else { g_expr(e2); use_register(creg,REG_EAX,0); printf("\tcall\t*%s\n",crn); } if (nargs) printf("\taddl $%d,%%esp\n",4*nargs); } void machinop(e1) int e1; { int e2,e3,op; e2 = cadr(e1); op = car(e1); switch (car(e3 = caddr(e1))) { case RGVAR: case RLVAR: case CONST: g_expr(e2); if (simpop(op)) oprt(op,e3); else oprt_div(op,e3); return; default: g_expr(e3); emit_push(); g_expr(e2); tosop(car(e1)); return; } } void increment(e,inc) int e,inc; { if (inc==1) { if (car(e)==GVAR) printf("\tincl %s\n",caddr(e)); else printf("\tincl %d(%%ebp)\n",cadr(e)); } else { if (car(e)==GVAR) printf("\taddl $%d,%s\n",inc,caddr(e)); else printf("\taddl $%d,%d(%%ebp)\n",inc,cadr(e)); } } void rindirect(e1) /* *(p +5 ) */ int e1; { char *op,*xrn; int e2,e3,e4,e5,byte,l; op = ((byte = (car(e1) == CRINDIRECT)) ? "movsbl" : "movl"); e3 = cadr(e2 = cadr(e1)); switch (car(e2)) { case RGVAR: /* movl _i,%esi movsbl (%esi),%eax */ printf("\tmovl %s,%s\n",caddr(e2),drn); printf("\t%s (%s),%s\n",op,drn,crn); return; case RLVAR: /* movl -6(%ebp),%esi movsbl (%esi),%eax */ printf("\tmovl %d(%%ebp),%s\n",cadr(e2),drn); printf("\t%s (%s),%s\n",op,drn,crn); return; case ADD: /* movsbl (%esi+%eax),%eax */ e4=caddr(e2); if(car(e3)==ADDRESS) { e3 = cadr(e3); } if (e5=e4,doubleindex(&e5)) { /* *((int *)q+i+j) =3 */ g_expr(e3); emit_push(); g_expr(cadr(e4)); xrn = emit_pop(); printf("\t%s (%s,%s,%d),%s\n",op,xrn,crn,e5,crn); return; } else if (e5=e3,doubleindex(&e5)) { g_expr(e4); emit_push(); g_expr(cadr(e3)); xrn = emit_pop(); printf("\t%s (%s,%s,%d),%s\n",op,xrn,crn,e5,crn); return; } switch(car(e4)) { /* *(p+3) */ case RGVAR: /* movl _i,%esi movsbl (%esi+%eax),%eax */ g_expr(e3); printf("\tmovl %s,%s\n",caddr(e4),drn); printf("\t%s (%s,%s),%s\n",op,crn,drn,crn); return; case RLVAR: /* movl -6(%ebp),%esi movsbl (%esi+%eax),%eax */ g_expr(e3); printf("\tmovl %d(%%ebp),%s\n",cadr(e4),drn); printf("\t%s (%s,%s),%s\n",op,crn,drn,crn); return; case CONST: switch (car(e3)) { /* *(1+xx) */ case RGVAR: printf("\tmovl %s,%s\n",caddr(e3),drn); printf("\t%s %d(%s),%s\n",op,cadr(e4),drn,crn); return; case RLVAR: /* movl -6(%ebp),%esi movsbl 12(%esi),%eax */ printf("\tmovl %d(%%ebp),%s\n",cadr(e3),drn); printf("\t%s %d(%s),%s\n",op,cadr(e4),drn,crn); return; } default: g_expr(e3); emit_push(); g_expr(e4); xrn = emit_pop(0); printf("\t%s (%s,%s),%s\n",op,crn,xrn,crn); return; } case PREINC: /* *++p */ switch (car(e3)) { case GVAR: increment(e3,caddr(e2)); printf("\tmovl %s,%s\n",caddr(e3),drn); printf("\t%s (%s),%s\n",op,drn,crn); return; case LVAR: increment(e3,caddr(e2)); printf("\tmovl %d(%%ebp),%s\n",cadr(e3),drn); printf("\t%s (%s),%s\n",op,drn,crn); return; } break; case POSTINC: /* *p++ */ switch (car(e3)) { case GVAR: printf("\tmovl %s,%s\n",caddr(e3),drn); increment(e3,caddr(e2)); printf("\t%s (%s),%s\n",op,drn,crn); return; case LVAR: printf("\tmovl %d(%%ebp),%s\n",cadr(e3),drn); increment(e3,caddr(e2)); printf("\t%s (%s),%s\n",op,drn,crn); return; } } g_expr(e2); printf("\t%s (%s),%s\n",op,crn,crn); } void assign(e1) int e1; { char *op; int e2,e3,e4,e5,l,byte; char *inc,*xrn,*xrn1; op = ((byte=(car(e1) == CASS))? "movb" : "movl"); 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,crn,caddr(e2)); return; case LVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\t%s %s,%d(%%ebp)\n",op,crn,cadr(e2)); return; case INDIRECT: /* *i = 3 */ switch(car(e3)) { case RGVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\tmovl %s,%s\n",caddr(e3),drn); printf("\t%s %s,(%s)\n",op,crn,drn); return; case RLVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\tmovl %d(%%ebp),%s\n",cadr(e3),drn); printf("\t%s %s,(%s)\n",op,crn,drn); return; case ADD:/* i[3] = 3 */ if (car(e5=caddr(e3)) == CONST) { switch (car(e5=cadr(e3))) { case RGVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\tmovl %s,%s\n",caddr(e5),drn); printf("\t%s %s,%d(%s)\n",op,crn,cadr(caddr(e3)),drn); return; case RLVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\tmovl %d(%%ebp),%s\n",cadr(e5),drn); printf("\t%s %s,%d(%s)\n",op,crn,cadr(caddr(e3)),drn); return; } } else if (doubleindex(&e5)) { /* indirect add address (mul expr const)=value*/ /* e3 e5 e4 */ g_expr(e4); /* assign value */ /* dindex(op,address,suffix,multi,byte) */ dindex(op,cadr(e3),cadr(caddr(e3)),e5,byte); return; } else if (e5=cadr(e3),doubleindex(&e5)) { g_expr(e4); /* assign value */ /* dindex(op,address,suffix,multi,byte) */ dindex(op,caddr(e3),cadr(cadr(e3)),e5,byte); return; } break; case PREINC:/* *++i = 3 */ if ((l = caddr(e3)) == -1 || l == 1) { inc = l==1?"incl":"decl"; switch (car(e5=cadr(e3))) { case GVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\t%s %s\n",inc,caddr(e5)); printf("\tmovl %s,%s\n",caddr(e5),drn); printf("\t%s %s,(%s)\n",op,crn,drn); return; case LVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\t%s %d(%%ebp)\n",inc,cadr(e5)); printf("\tmovl %d(%%ebp),%s\n",cadr(e5),drn); printf("\t%s %s,(%s)\n",op,crn,drn); return; } } else { switch (car(e5=cadr(e3))) { case GVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\taddl $%d,%s\n",l,caddr(e5)); printf("\tmovl %s,%s\n",caddr(e5),drn); printf("\t%s %s,(%s)\n",op,crn,drn); return; case LVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\taddl $%d,%d(%%ebp)\n",l,cadr(e5)); printf("\tmovl %d(%%ebp),%s\n",cadr(e5),drn); printf("\t%s %s,(%s)\n",op,crn,drn); return; } } break; case POSTINC:/* *i++ = 3 */ if ((l = caddr(e3)) == -1 || l == 1) { inc = l==1?"incl":"decl"; switch (car(e5=cadr(e3))) { case GVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\tmovl %s,%s\n",caddr(e5),drn); printf("\t%s %s\n",inc,caddr(e5)); printf("\t%s %s,(%s)\n",op,crn,drn); return; case LVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\tmovl %d(%%ebp),%s\n",cadr(e5),drn); printf("\t%s %d(%%ebp)\n",inc,cadr(e5)); printf("\t%s %s,(%s)\n",op,crn,drn); return; } } else { switch (car(e5=cadr(e3))) { case GVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\tmovl %s,%s\n",caddr(e5),drn); printf("\taddl $%d,%s\n",l,caddr(e5)); printf("\t%s %s,(%s)\n",op,crn,drn); return; case LVAR: g_expr(e4); if (byte) use_data_reg(creg,1); printf("\tmovl %d(%%ebp),%s\n",cadr(e5),drn); printf("\taddl $%d,%d(%%ebp)\n",l,cadr(e5)); printf("\t%s %s,(%s)\n",op,crn,drn); return; } } break; } } g_expr(e4); emit_push(); g_expr(e2); if(car(e4)==CONST) { printf("\t%s $%d,(%s)\n",op,cadr(e4),crn); return; } if (byte) use_data_reg(creg,1); xrn = emit_pop(0); printf("\t%s %s,(%s)\n",op,xrn,crn); change(creg,xreg); /* now xrn becomes crn */ return; } void assop(e1) int e1; { int e2,e3,e4,e5,byte,op; 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); switch (car(e2)) { case GVAR: case LVAR: if(car(e3)==CONST) { if (simpop(op)) { oprt_assop(op,byte,e3,e2); } else { use_register(creg,REG_EAX,0); ld_index(byte,e2); oprt_div(op,e3); st_index(byte,e2); } return; } else { if (simpop(op)) { g_expr(e3); oprt_assop_reg(op,byte,crn,e2); } else { g_expr(e3); emit_push(); ld_index(byte,e2); tosop(op); st_index(byte,e2); } return; } case ADD: if (simpop(op)) { if (car(e3)==CONST) { if(car((e4=caddr(e2)))==CONST) { /* a[const] += const */ g_expr(cadr(e2)); /* oprt1(op,byte,e,ind,disp,reg); */ oprt1(op,byte,e3,1,cadr(e4),0); return; } else if (e5=e4,doubleindex(&e5)) { /* indirect add address (mul expr const)op=const*/ oprt1(op,byte,e3,5,list3(cadr(e2),cadr(e4),e5),0); return; } else if (e5=cadr(e2),doubleindex(&e5)) { /* indirect add address (mul expr const)op=const*/ oprt1(op,byte,e3,5,list3(e4,cadr(cadr(e2)),e5),0); return; } else { /* a[expr] += const */ g_expr(e4); emit_push(); g_expr(cadr(e2)); /* oprt1(op,byte,e,ind,disp,reg); */ oprt1(op,byte,e3,2,0,0); return; } } else { if(car((e4=caddr(e2)))==CONST) { /* a[const] += value */ g_expr(e3); emit_push(); g_expr(cadr(e2)); xrn = emit_pop(); /* oprt1(op,byte,e,ind,disp,reg); */ oprt1(op,byte,e3,1,cadr(e4),xrn); return; } else if (e5=e4,doubleindex(&e5)) { g_expr(e3); /* indirect add address (mul expr const)op=const*/ oprt1(op,byte,e3,5,list3(cadr(e2),cadr(e4),e5),0); return; } else if (e5=cadr(e2),doubleindex(&e5)) { g_expr(e3); /* indirect add address (mul expr const)op=const*/ oprt1(op,byte,e3,5,list3(e4,cadr(cadr(e2)),e5),0); return; } else { /* a[value] += value */ g_expr(e3); emit_push(); g_expr(e4); emit_push(); g_expr(cadr(e2)); xrn = emit_pop(); /* oprt1(op,byte,e,ind,disp,reg) */ oprt1(op,byte,e3,2,0,xrn); return; } } } default: if (simpop(op)) { if (car(e3)==CONST) { /* *(complex e2) += const */ g_expr(e2); /* oprt1(op,byte,e,ind,disp,reg) */ oprt1(op,byte,e3,1,0,0); return; } else { /* *(complex e2) += value */ g_expr(e3); emit_push(); g_expr(e2); xrn = emit_pop(); /* oprt1(op,byte,e,ind,disp,reg) */ oprt1(op,byte,e3,3,0,xrn); return; } } if (op==UMUL||op==MUL) { /* e2 op= e3 */ if (car(e3)==CONST) { /* *(complex e2) *= const */ g_expr(e2); printf("\timul%c $%d,(%s),%s\n",byte?'b':'l',cadr(e3),crn,crn); st_indexx(byte,0,crn); return; } else { /* *(complex e2) *= value */ g_expr(e3); emit_push(); g_expr(e2); xrn = emit_pop(); printf("\timul%c (%s),%s\n",byte?'b':'l',crn,xrn); st_indexx(byte,0,crn); return; } } /* divie case */ switch (car(e3)) { case RGVAR: case RLVAR: case CONST: g_expr(e2); xrn = crn; emit_push(); ld_indexx(byte,0,xrn); if (simpop(op)) { oprt(op,e3); } else { oprt_div(op,e3); } xrn = emit_pop(); st_indexx(byte,0,xrn); break; default: g_expr(e3); emit_push(); g_expr(e2); emit_push(); xrn = emit_pop(); ld_indexx(byte,0,xrn); tosop(op); emit_push(); /* we prefer compute e3 before e2 but this is slightly difficult */ /* with out computing e2 twice, sine xrn might be lost */ /* but cleary compile e2 twice is wrong */ g_expr(e2); xrn = emit_pop(); printf("\t%s %s,(%s)\n",byte ? "movb" : "movl",xrn,crn); change(creg,xreg); return; } } } int simpop(op) int op; { return (op == ADD || op == SUB || op == BAND || op == EOR || op == BOR || op == LNOT || op == LSHIFT || op == ULSHIFT || op == RSHIFT || op==URSHIFT); } int simpop_mul(op) int op; { return (op == ADD || op == SUB || op == BAND || op == EOR || op == BOR || op == LNOT || op == LSHIFT || op == ULSHIFT || op == RSHIFT || op==URSHIFT); } int doubleindex(e5) int *e5; { int e; if (car(e=*e5)==MUL) /* mul expr const */ if (car(e=caddr(e))==CONST) if((e=cadr(e))==2 || e==4 || e==8) { *e5 = e; return 1; } return 0; } void oprt1(op,byte,e,ind,disp,reg) int op,byte,e,ind,disp; char *reg; { char *xrn,*xrn1,*shift,b; int use,xreg,xreg1; if (ind==2) { if (reg) { xreg = lreg; xrn = emit_pop(); /* pop offset */ xrn1 = reg; reg = xrn; xrn = xrn1; } else { xrn = emit_pop(); /* pop value */ xreg = lreg; } } else if (ind==5||ind==6) { emit_push(); g_expr(cadr(disp)); /* suffix */ emit_push(); g_expr(car(disp)); /* address */ xrn = emit_pop(); /* suffix */ xreg = lreg; if (use=stack_used()) { /* dreg (=xrn) may lost if expr use stack */ printf("\tlea (%s,%s,%d),%s\n",crn,xrn,caddr(disp),crn); xrn = emit_pop(); /* value */ xreg = lreg; } else { xrn1 = emit_pop(); /* value */ xreg1 = lreg; } } else if (ind==7) { xrn = reg; } b = byte?'b':'l'; switch (op) { case LSHIFT: case ULSHIFT: shift = "sal"; goto shift_case; case RSHIFT: shift = "sar"; goto shift_case; case URSHIFT: shift = "shr"; shift_case: if (ind==5||ind==6) { if (car(e)==CONST) { if (use) { printf("\t%s%c $%d,(%s)\n",shift,b,cadr(e),crn); if (byte) use_data_reg(creg,1); printf("\t%s (%s),%s\n", b=='b'?"movsbl":"movl", crn,crn); } else { printf("\t%s%c $%d,(%s,%s,%d)\n",shift,b, cadr(e),crn,xrn,caddr(disp)); if (byte) use_data_reg(creg,1); printf("\t%s (%s,%s,%d),%s\n", b=='b'?"movsbl":"movl", crn,xrn,caddr(disp),crn); creg = lreg; crn = lrn; } return; } if (use) { use_register(xreg,REG_ECX,0); printf("\t%s%c %s,(%s)\n",shift,b,reg_name_l[REG_ECX],crn); if (byte) use_data_reg(creg,1); printf("\t%s (%s),%s\n", b=='b'?"movsbl":"movl", crn,crn); } else { use_register(xreg1,REG_ECX,0); printf("\t%s%c %s,(%s,%s,%d)\n",shift,b, reg_name_l[REG_ECX],crn,xrn,caddr(disp)); if (byte) use_data_reg(creg,1); printf("\t%s (%s,%s,%d),%s\n", b=='b'?"movsbl":"movl", crn,xrn,caddr(disp),crn); } return; } else { if (car(e)==CONST) { printf("\t%s%c $%d,",shift,b,cadr(e)); operand2(ind,disp,xrn,byte,1); if (byte) use_data_reg(creg,1); /* xrn? */ printf("\t%s ",b=='b'?"movsbl":"movl"); operand2(ind,disp,xrn,byte,0); printf(",%s\n",crn); return; } use_register(dreg,REG_ECX,0); printf("\tmovl "); operand1(reg,e); printf("%s\n",drn); printf("\t%s%c %%cl,",shift,b); operand2(ind,disp,xrn,byte,1); if (ind) { if (byte) use_data_reg(creg,1); /* xrn? */ printf("\t%s ",b=='b'?"movsbl":"movl"); operand2(ind,disp,xrn,byte,0); printf(",%s\n",crn); } return; } case MUL: case UMUL: printf("\t%s%c ",op==MUL?"imul":"imul",b); break; case ADD: printf("\tadd%c ",b); break; case SUB: printf("\tsub%c ",b); break; case BAND: printf("\tand%c ",b); break; case EOR: printf("\txor%c ",b); break; case BOR: printf("\tor%c ",b); break; default: error(-1); } if (ind==5||ind==6) { if (use) { printf("\t%s,(%s)\n",xrn,crn); if (byte) use_data_reg(creg,1); printf("\t%s (%s),%s\n",byte?"movsbl":"movl",xrn,crn); } else { printf("\t%s,(%s,%s,%d)\n",xrn1,crn,xrn,caddr(disp)); if (byte) use_data_reg(creg,1); printf("\t%s (%s,%s,%d),%s\n",byte?"movsbl":"movl",crn,xrn,caddr(disp),crn); } } else { operand1(reg,e); operand2(ind,disp,xrn,byte,1); if (ind) { if (byte) use_data_reg(creg,1); /* xrn? */ printf("\t%s ",b=='b'?"movsbl":"movl"); operand2(ind,disp,xrn,byte,0); printf(",%s\n",crn); } } } int simpoperand(e1) int e1; { return (e1==RGVAR ||e1==RLVAR||e1==CONST); } operand1(reg,e) char *reg; int e; { int e1; e1 = car(e); if (reg) { printf("%s,",reg); } else if (e1==RGVAR) { printf("%s,",caddr(e)); } else if (e1==RLVAR) { printf("%d(%%ebp),",cadr(e)); } else if (e1==CONST) { printf("$%d,",cadr(e)); } else { error(-1); } } operand2(ind,disp,reg,byte,nl) int ind,disp,byte,nl; char *reg; { char *xrn; if (ind==1 && disp) printf("%d(%s)",disp,crn); else if (ind==1 || ind==3) printf("(%s)",crn); else if (ind==2) { printf("(%s,%s)",crn,reg); } else if (ind==7 || ind==8) { switch(car(disp)) { case GVAR: printf("%s",caddr(disp)); break; case LVAR: printf("%d(%%ebp)",cadr(disp)); break; default: printf("%s",crn); if (nl) printf("\n"); return; } } else { printf("%s",crn); } if (nl) printf("\n"); } dindex(op,address,suffix,multi,byte) int op,address,suffix,multi,byte; { char *xrn,*xrn1; emit_push(); g_expr(suffix); /* suffix */ emit_push(); g_expr(address); /* address */ xrn = emit_pop(); /* suffix */ if (stack_used()) { /* dreg (=xrn) may lost if expr use stack */ printf("\tlea (%s,%s,%d),%s\n",crn,xrn,multi,crn); xrn = emit_pop(); /* value */ if (byte) use_data_reg(lreg,1); printf("\t%s %s,(%s)\n",op,xrn,crn); } else { xrn1 = emit_pop(); /* value */ if (byte) use_data_reg(lreg,1); printf("\t%s %s,(%s,%s,%d)\n",op,xrn1,crn,xrn,multi); } creg = lreg; crn = lrn; } /* simple one operand operation */ void oprt(op,e) int op,e; { /* oprt1(op,byte,e,ind,disp,reg) */ oprt1(op,0,e,0,0,0,0); } void oprt_assop(op,byte,e1,e2) int op,byte,e1,e2; { /* oprt1(op,byte,e,ind,disp,reg) */ /* op e1,e2 */ oprt1(op,byte,e1,7,e2,0); } void oprt_assop_reg(op,byte,reg,e) char *reg; int op,byte,e; { /* oprt1(op,byte,e,ind,disp,reg) */ /* op reg,e2 */ oprt1(op,byte,0,7,e,reg); } void oprt_div(op,e) int op,e; { int e1,const_reg,i; e1 = car(e); const_reg = -1; if (op!=MUL && op!=UMUL) { div_setup(-1); /* free hands on ECX or ECX? */ if (e1==CONST) { if(regs[virtual(REG_EBX)]) { const_reg = REG_ECX; if (regs[virtual(REG_ECX)]) { printf("\tpushl %%ecx\n"); } } else const_reg = REG_EBX; printf("\tmovl $%d,%s\n",cadr(e),reg_name[const_reg]); } } switch (op) { case DIV: case MOD: printf("\tcltd\n\tidivl "); break; case UDIV: case UMOD: printf("\txor %%edx,%%edx\n\tdivl "); break; case MUL: case UMUL: printf("\timull "); break; default: error(-1); } if (e1==RGVAR) { printf("%s",caddr(e)); } else if (e1==RLVAR) { printf("%d(%%ebp)",cadr(e)); } else if (e1==CONST) { if (const_reg!=-1) printf("%s",reg_name[const_reg]); else printf("$%d",cadr(e)); } else { error(-1); } if (op==MUL || op==UMUL) { printf(",%s\n",crn); } else { printf("\n"); } if(const_reg == REG_ECX && regs[virtual(REG_ECX)]) printf("\tpopl %%ecx\n"); if (op==MOD || op==UMOD) { rname[creg]=REG_EDX; crn=reg_name[REG_EDX]; rname[dreg]=REG_EAX; drn=reg_name[REG_EAX]; } } void asld(d) int d; { printf("\tsall $%d,%s\n",d,crn); } void andd(d) int d; { printf("\tandl $%d,%s\n",d,crn); } void asrd(type,d) int type; int d; { char *op; op = type==DIV?"\tsarl $%d,%s\n":"larl $%d,%s\n"; printf(op,d,crn); } void tosop(op) 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) { printf("\tpopl %s\n",drn); oreg = dreg; } orn = reg_name[rname[oreg]]; switch(op) { case ADD: printf("\taddl %s,%s\n",orn,crn); return; case SUB: printf("\tsubl %s,%s\n",orn,crn); return; case BAND: printf("\tandl %s,%s\n",orn,crn); return; case EOR: printf("\txorl %s,%s\n",orn,crn); return; case BOR: printf("\torl %s,%s\n",orn,crn); return; case MUL: case UMUL: /* use_register(dreg,REG_EDX,0); */ printf("\t%s %s,%s\n","imull",orn,crn); return; case DIV: case MOD: printf("\tcltd\n\tidivl %s\n",div_setup(oreg)); if (op==MOD) change(creg,dreg); div_cleanup(); break; case UDIV: case UMOD: printf("\txor %%edx,%%edx\n\tidivl %s\n",div_setup(oreg)); if (op==UMOD) change(creg,dreg); div_cleanup(); break; } return; } static char *dvi_push = "(%esp)"; char * div_setup(oreg) int oreg; { if (oreg<0) { use_register(creg,REG_EAX,1); use_register(dreg,REG_EDX,0); return 0; } if (register_full()) { printf("\tpushl %s\n",reg_name[rname[oreg]]); use_register(creg,REG_EAX,1); use_register(oreg,REG_EDX,0); return dvi_push; } regs[oreg]=1; use_register(creg,REG_EAX,1); use_register(dreg,REG_EDX,0); regs[oreg]=0; return reg_name[rname[oreg]]; } void div_cleanup(orn) char *orn; { if (orn==dvi_push) printf("\taddl $4,%%esp\n"); } void shift(op,reg) char *op,*reg; { if (reg>=0) { use_register(lreg,REG_ECX,1); } else { use_register(dreg,REG_ECX,0); printf("\tpopl %%ecx\n"); } printf("\t%s %%cl,%s\n",op,crn); } void lddim(n) /* modified */ int n; { printf("\tmovl $%d,%s\n",n,crn); } void ldx(e) int e; { switch (car(e)) { case GVAR: case RGVAR: printf("\tmovl %s,%s\n",caddr(e),crn); return; case LVAR: case RLVAR: printf("\tmovl %d(%%ebp),%s\n",cadr(e),crn); return; default: DEBUG; } } void stx(e) int e; { switch (car(e)) { case GVAR: case RGVAR: printf("\tmovl %s,%s\n",crn,caddr(e)); return; case LVAR: case RLVAR: printf("\tmovl %s,%d(%%ebp)\n",crn,cadr(e)); return; default: DEBUG; } } void ld_indexx(byte,n,xrn) int byte,n; char *xrn; { char *op; op = byte ? "movsbl" : "movl"; if (n) printf("\t%s %d(%s),%s\n",op,n,xrn,crn); else printf("\t%s (%s),%s\n",op,xrn,crn); } void st_indexx(byte,n,xrn) int byte,n; char *xrn; { char *op; op = byte ? "movb" : "movl"; if (n) printf("\t%s %s,%d(%s)\n",op,crn,n,xrn); else printf("\t%s %s,(%s)\n",op,crn,xrn); } void ld_index(byte,e) int byte,e; { char *op; op = byte ? "movsbl" : "movl"; switch (car(e)) { case GVAR: printf("\t%s %s,%s\n",op,caddr(e),crn); return; case LVAR: printf("\t%s %d(%%ebp),%s\n",op,cadr(e),crn); return; default: DEBUG; } } void st_index(byte,e) int byte,e; { char *op; op = byte ? "movb" : "movl"; switch (car(e)) { case GVAR: printf("\t%s %s,%s\n",op,crn,caddr(e)); return; case LVAR: printf("\t%s %s,%d(%%ebp)\n",op,crn,cadr(e)); return; default: DEBUG; } } void indexy(op,gvar) char *op; char *gvar; { printf("\t%s %s,%s\n",op,crn,gvar); } void ld_indir(op,e) char *op; int e; { switch (car(e)) { case RGVAR: /* indiry(op,cadr(e)); */ printf("\t%s\t(%s),%s\n",op,caddr(e),crn); return; case RLVAR: /* indiru(op,cadr(e)); */ printf("\t%s\t%s(%%epb),%s\n",op,cadr(e),crn); return; default: DEBUG; } } void cmpdimm(e,csreg) int e,csreg; { use_register(creg,csreg,0); printf("\tcmpl $%d,%s\n",e,crn); } void opening(filename) char *filename; { printf("\t.file \"%s\"\n",filename); printf(".text\n"); emit_init(); } void closing() { global_table(); } void jmp_label(l) int l; { printf("\tjmp\t_%d\n",l); } void jmp_eq_label(l) int l; { printf("\tje\t_%d\n",l); } void rexpr(e1,l1,s) int e1,l1; char *s; { g_expr(list3(SUB,cadr(e1),caddr(e1))); printf("\tj%s\t_%d\n",s,l1); } void jcond(l,cond) int l; char cond; { printf("\tj%s\t_%d\n",cond?"ne":"e",l); } void jmp(l) int l; { control=0; printf("\tjmp\t_%d\n",l); /* align? */ } int fwdlabel() { return labelno++; } void fwddef(l) int l; { control=1; printf("_%d:\n",l); } int backdef() { control=1; printf("_%d:\n",labelno); return labelno++; } void def_label(cslabel,dlabel) int cslabel,dlabel; { int fl; fl = 0; if (control) { jmp(fl=fwdlabel()); } fwddef(cslabel); if (dlabel) jmp(dlabel); if (fl) { fwddef(fl); } } void gen_comment(s) char *s; { printf("# %s",s); } void gen_source(s) char *s; { printf("%s",s); } void enter(name) char *name; { text_mode(); 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 %%ecx\n"); printf("\tpushl %%edx\n"); if (REGISTERS6) { printf("\tpushl %%edi\n"); printf("\tpushl %%esi\n"); } } void enter1(disp) int disp; { if(disp) printf("\tsubl $%d,%%esp\n",-disp); } void leave(control,name) int control; char *name; { fwddef(retlabel); use_register(creg,REG_EAX,1); if (REGISTERS6) { printf("\tpopl %%esi\n"); printf("\tpopl %%edi\n"); } if(disp) printf("\taddl $%d,%%esp\n",-disp); printf("\tpopl %%edx\n"); printf("\tpopl %%ecx\n"); printf("\tpopl %%ebx\n"); printf("\tleave\n"); printf("\tret\n"); local_table(); printf("_%d:\n",labelno); printf("\t.size\t%s,_%d-%s\n",name,labelno,name); labelno++; } void ret() { use_register(creg,REG_EAX,1); jmp(retlabel); } void gen_gdecl(n,gpc) char *n; int gpc; { /* if (stmode!=STATIC) printf(".globl %s\n",n); */ } void align() { if (data_alignment & 1) printf("\t.align 2\n"); data_alignment = 0; } void emit_data(e,t,n) int e,t; NMTBL *n; { int l; char *name; name = n->nm; if(mode==GDECL) { /* global */ n->dsp = -1; /* initiallized flag */ printf(".globl\t%s\n",name); if(car(e)==CONST) { data_mode(name); if (t==CHAR) { printf("%s:\n",name); printf("\t.byte %d\n",cadr(e)); if (data_alignment>0) data_alignment++; } else { align(); printf("%s:\n",name); printf("\t.long %d\n",cadr(e)); } } else if(t!=CHAR) { if(car(e)==ADDRESS&&car(cadr(e))==GVAR) { data_mode(name); align(); printf("%s:\n",name); printf("\t.long %s\n",caddr(cadr(e))); } else if(car(e)==FNAME) { data_mode(name); align(); printf("%s:\n",name); printf("\t.long %s\n",((NMTBL *)cadr(e))->nm); } else if(car(e)==STRING) { text_mode(); l = backdef(); ascii((char *)cadr(e)); data_mode(name); align(); printf("%s:\n",name); printf("\t.long _%d\n",l); } else error(TYERR); } } else { if(car(e)==CONST) { lddim(cadr(e)); indexy(t==CHAR?"movsbl":"movl",name); } else if(t!=CHAR) { if(car(e)==ADDRESS&&car(cadr(e))==GVAR) printf("\tlea %s,%s\n",caddr(e),crn); else if(car(e)==FNAME) printf("\tlea %s,%s\n",((NMTBL *)cadr(e))->nm,crn); else if(car(e)==STRING) { string(e); } else error(TYERR); printf("\tmovl %s,%s\n",crn,name); } } } void global_table() { NMTBL *n; for(n=ntable;n < &ntable[GSYMS];n++) { if (n->sc == GVAR && n->dsp != -1) { /* n->dsp = -1 means initialized global */ printf(".comm %s,%d\n",n->nm,size(n->ty)); } } } void local_table() { 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() { if (output_mode!=TEXT_EMIT_MODE) { printf(".text\n"); printf("\t.align 2\n"); output_mode = TEXT_EMIT_MODE; } } void data_mode(name) char *name; { if (output_mode!=DATA_EMIT_MODE) { printf(".data\n"); output_mode = DATA_EMIT_MODE; } printf("\t.type\t%s,@object\n",name); } /* end */