/* 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 tosop(); char *div_setup() ; void shift() ; void lddim() ; void ld_indexx(); void st_indexx(); void indexy(); 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 error(); int size(); int list3(); #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; /* pointer 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]; /* 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 int rname[MAX_MAX]; static int regs[MAX_MAX]; /* 使われているレジスタを示すフラグ */ static int 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) int 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(); crn = reg_name[rname[creg]]; drn = reg_name[rname[dreg]]; dreg = get_register(); 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]]; } int 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 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(); 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: g_expr(e2); printf("\taddl $%d,(%s)\n",caddr(e1),crn); printf("\tmovl (%s),%s\n",crn,crn); return; case POSTINC: g_expr(e2); emit_push(); /* in case of register full we should copy crn to drn */ xrn = emit_pop(0); printf("\tmovl (%s),%s\n",xrn,crn); printf("\taddl $%d,(%s)\n",caddr(e1),xrn); return; case CPOSTINC: /* char *p; *p++ */ 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: 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: 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 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 (regs[2]&&creg!=2) printf("# unsaved register %s %d\n",reg_name[2],lineno); if (regs[3]&&creg!=3) printf("# unsaved register %s %d\n",reg_name[3],lineno); if (regs[4]&&creg!=4) printf("# unsaved register %s %d\n",reg_name[4],lineno); if (regs[5]&&creg!=5) printf("# unsaved register %s %d\n",reg_name[5],lineno); */ if (nargs) printf("\taddl $%d,%%esp\n",4*nargs); } void machinop(e1) 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(e1) /* *(p +5 ) */ int e1; { 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,crn,crn); } void assign(e1) int e1; { char *op; int e2,e3,e4,byte; char *xrn; 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,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; } 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("\tmovl %s,%s\n",xrn,crn); return; } void assop(e1) int e1; { int e2,e3,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); g_expr(e3); emit_push(); g_expr(e2); emit_push(); xrn = emit_pop(); ld_indexx(byte,0,xrn); tosop(op); emit_push(); g_expr(e2); xrn = emit_pop(); printf("\t%s %s,(%s)\n",byte ? "movb" : "movl",xrn,crn); printf("\tmovl %s,%s\n",xrn,crn); return; } 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 UDIV: orn = div_setup(oreg); if (op==DIV) printf("\tcltd\n\tdivl %s\n",orn); else printf("\txor %%edx,%%edx\n\tidivl %s\n",orn); div_cleanup(orn); return; case MOD: case UMOD: orn = div_setup(oreg); if (op==DIV) printf("\tcltd\n\tdivl %s\n",orn); else printf("\txor %%edx,%%edx\n\tidivl %s\n",orn); rname[creg]=REG_EDX; crn=reg_name[REG_EDX]; rname[dreg]=REG_EAX; drn=reg_name[REG_EAX]; div_cleanup(orn); 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]]; } div_cleanup(orn) char *orn; { if (orn==dvi_push) printf("\taddl $4,%%esp\n"); } void shift(op,reg) char *op; int 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 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 indexy(op,gvar) char *op; char *gvar; { printf("\t%s %s,%s\n",op,crn,gvar); } void cmpdimm(e,csreg) int e,csreg; { /* used in dosiwtch() */ use_register(creg,csreg,0); printf("\tcmpl $%d,%s\n",e,crn); } void opening(filename) 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() { global_table(); printf("\t.ident \"Micro-C compiled\"\n"); } 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 */