📄 asm.c
字号:
#include "l.h"#define LPUT(c)\ {\ cbp[0] = (c);\ cbp[1] = (c)>>8;\ cbp[2] = (c)>>16;\ cbp[3] = (c)>>24;\ cbp += 4;\ cbc -= 4;\ if(cbc <= 0)\ cflush();\ }#define CPUT(c)\ {\ cbp[0] = (c);\ cbp++;\ cbc--;\ if(cbc <= 0)\ cflush();\ }#define VLPUT(c)\ {\ cbp[0] = (c);\ cbp[1] = (c)>>8;\ cbp[2] = (c)>>16;\ cbp[3] = (c)>>24;\ cbp[4] = (c)>>32;\ cbp[5] = (c)>>40;\ cbp[6] = (c)>>48;\ cbp[7] = (c)>>56;\ cbp += 8;\ cbc -= 8;\ if(cbc <= 0)\ cflush();\ }#define LPUTBE(c)\ {\ cbp[0] = (c)>>24;\ cbp[1] = (c)>>16;\ cbp[2] = (c)>>8;\ cbp[3] = (c);\ cbp += 4;\ cbc -= 4;\ if(cbc <= 0)\ cflush();\ }longentryvalue(void){ char *a; Sym *s; a = INITENTRY; if(*a >= '0' && *a <= '9') return atolwhex(a); s = lookup(a, 0); if(s->type == 0) return INITTEXT; if(s->type != STEXT && s->type != SLEAF) diag("entry not text: %s", s->name); return s->value;}voidasmb(void){ Prog *p; vlong t; Optab *o; if(debug['v']) Bprint(&bso, "%5.2f asm\n", cputime()); Bflush(&bso); seek(cout, HEADR, 0); pc = INITTEXT; for(p = firstp; p != P; p = p->link) { if(p->as == ATEXT) { curtext = p; autosize = p->to.offset + 8; } if(p->pc != pc) { diag("phase error %lux sb %lux", p->pc, pc); if(!debug['a']) prasm(curp); pc = p->pc; } if (p->as == AMOVQ || p->as == AMOVT) { if ((p->from.reg == REGSP) && (p->from.offset&7) != 0 || (p->to.reg == REGSP) && (p->to.offset&7) != 0) diag("bad stack alignment: %P", p); if ((p->from.reg == REGSB) && (p->from.offset&7) != 0 || (p->to.reg == REGSB) && (p->to.offset&7) != 0) diag("bad global alignment: %P", p); } curp = p; o = oplook(p); /* could probably avoid this call */ if(asmout(p, o)) { p = p->link; pc += 4; } pc += o->size; } if(debug['a']) Bprint(&bso, "\n"); Bflush(&bso); cflush(); curtext = P; switch(HEADTYPE) { case 0: seek(cout, rnd(HEADR+textsize, 8192), 0); break; case 1: case 2: case 3: seek(cout, HEADR+textsize, 0); break; } for(t = 0; t < datsize; t += sizeof(buf)-100) { if(datsize-t > sizeof(buf)-100) datblk(t, sizeof(buf)-100); else datblk(t, datsize-t); } symsize = 0; lcsize = 0; if(!debug['s']) { if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { case 0: seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0); break; case 2: case 1: case 3: seek(cout, HEADR+textsize+datsize, 0); break; } if(!debug['s']) asmsym(); if(debug['v']) Bprint(&bso, "%5.2f pc\n", cputime()); Bflush(&bso); if(!debug['s']) asmlc(); cflush(); } if(debug['v']) Bprint(&bso, "%5.2f header\n", cputime()); Bflush(&bso); seek(cout, 0L, 0); switch(HEADTYPE) { case 0: lput(0x0183L); /* magic and sections */ lput(0L); /* time and date */ vlput(rnd(HEADR+textsize, 8192)+datsize); lput(symsize); /* nsyms */ lput(0x50L|(7L<<16)); /* size of optional hdr and flags */ lput(0413|(0x101L<<16)); /* magic and version */ lput(-1); /* pad for alignment */ vlput(rnd(HEADR+textsize, 8192)); /* sizes */ vlput(datsize); vlput(bsssize); vlput(entryvalue()); /* va of entry */ vlput(INITTEXT-HEADR); /* va of base of text */ vlput(INITDAT); /* va of base of data */ vlput(INITDAT+datsize); /* va of base of bss */ lput(~0L); /* gp reg mask */ /* dubious stuff starts here */ lput(0L); lput(0L); lput(0L); lput(0L); lput(~0L); /* gp value ?? */ break; case 1: lput(0x0183L); /* magic and sections */ lput(0L); /* time and date */ vlput(HEADR+textsize+datsize); lput(symsize); /* nsyms */ lput(0x54L|(7L<<16)); /* size of optional hdr and flags */ lput(0407|(0x101L<<16)); /* magic and version */ lput(-1); /* pad for alignment */ vlput(textsize); /* sizes */ vlput(datsize); vlput(bsssize); vlput(entryvalue()); /* va of entry */ vlput(INITTEXT); /* va of base of text */ vlput(INITDAT); /* va of base of data */ vlput(INITDAT+datsize); /* va of base of bss */ lput(~0L); /* gp reg mask */ /* dubious stuff starts here */ lput(lcsize); lput(0L); lput(0L); lput(0L); lput(~0L); /* gp value ?? */ lput(0L); /* complete mystery */ break; case 2: lputbe(0x84b); /* magic */ lputbe(textsize); /* sizes */ lputbe(datsize); lputbe(bsssize); lputbe(symsize); /* nsyms */ lputbe(entryvalue()); /* va of entry */ lputbe(0L); lputbe(lcsize); break; case 3: /* ``headerless'' boot image -- magic no is a branch */ lput(0xc3e00007); /* magic (branch) */ lputbe(textsize); /* sizes */ lputbe(datsize); lputbe(bsssize); lputbe(symsize); /* nsyms */ lputbe(entryvalue()); /* va of entry */ lputbe(0L); lputbe(lcsize); break; } cflush();}voidlput(long l){ LPUT(l);}voidlputbe(long l){ LPUTBE(l);}voidvlput(vlong l){ VLPUT(l);}voidcflush(void){ int n; n = sizeof(buf.cbuf) - cbc; if(n) write(cout, buf.cbuf, n); cbp = buf.cbuf; cbc = sizeof(buf.cbuf);}voidasmsym(void){ Prog *p; Auto *a; Sym *s; int h; s = lookup("etext", 0); if(s->type == STEXT) putsymb(s->name, 'T', s->value, s->version); for(h=0; h<NHASH; h++) for(s=hash[h]; s!=S; s=s->link) switch(s->type) { case SCONST: putsymb(s->name, 'D', s->value, s->version); continue; case SDATA: putsymb(s->name, 'D', s->value+INITDAT, s->version); continue; case SBSS: putsymb(s->name, 'B', s->value+INITDAT, s->version); continue; case SFILE: putsymb(s->name, 'f', s->value, s->version); continue; } for(p=textp; p!=P; p=p->cond) { s = p->from.sym; if(s->type != STEXT && s->type != SLEAF) continue; /* filenames first */ for(a=p->to.autom; a; a=a->link) if(a->type == D_FILE) putsymb(a->sym->name, 'z', a->offset, 0); else if(a->type == D_FILE1) putsymb(a->sym->name, 'Z', a->offset, 0); if(s->type == STEXT) putsymb(s->name, 'T', s->value, s->version); else putsymb(s->name, 'L', s->value, s->version); /* frame, auto and param after */ putsymb(".frame", 'm', p->to.offset+8, 0); for(a=p->to.autom; a; a=a->link) if(a->type == D_AUTO) putsymb(a->sym->name, 'a', -a->offset, 0); else if(a->type == D_PARAM) putsymb(a->sym->name, 'p', a->offset, 0); } if(debug['v'] || debug['n']) Bprint(&bso, "symsize = %lud\n", symsize); Bflush(&bso);}voidputsymb(char *s, int t, long v, int ver){ int i, f; if(t == 'f') s++; LPUTBE(v); if(ver) t += 'a' - 'A'; CPUT(t+0x80); /* 0x80 is variable length */ if(t == 'Z' || t == 'z') { CPUT(s[0]); for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { CPUT(s[i]); CPUT(s[i+1]); } CPUT(0); CPUT(0); i++; } else { for(i=0; s[i]; i++) CPUT(s[i]); CPUT(0); } symsize += 4 + 1 + i + 1; if(debug['n']) { if(t == 'z' || t == 'Z') { Bprint(&bso, "%c %.8lux ", t, v); for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) { f = ((s[i]&0xff) << 8) | (s[i+1]&0xff); Bprint(&bso, "/%x", f); } Bprint(&bso, "\n"); return; } if(ver) Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver); else Bprint(&bso, "%c %.8lux %s\n", t, v, s); }}#define MINLC 4voidasmlc(void){ long oldpc, oldlc; Prog *p; long v, s; oldpc = INITTEXT; oldlc = 0; for(p = firstp; p != P; p = p->link) { if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) { if(p->as == ATEXT) curtext = p; if(debug['L']) Bprint(&bso, "%6lux %P\n", p->pc, p); continue; } if(debug['L']) Bprint(&bso, "\t\t%6ld", lcsize); v = (p->pc - oldpc) / MINLC; while(v) { s = 127; if(v < 127) s = v; CPUT(s+128); /* 129-255 +pc */ if(debug['L']) Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128); v -= s; lcsize++; } s = p->line - oldlc; oldlc = p->line; oldpc = p->pc + MINLC; if(s > 64 || s < -64) { CPUT(0); /* 0 vv +lc */ CPUT(s>>24); CPUT(s>>16); CPUT(s>>8); CPUT(s); if(debug['L']) { if(s > 0) Bprint(&bso, " lc+%ld(%d,%ld)\n", s, 0, s); else Bprint(&bso, " lc%ld(%d,%ld)\n", s, 0, s); Bprint(&bso, "%6lux %P\n", p->pc, p); } lcsize += 5; continue; } if(s > 0) { CPUT(0+s); /* 1-64 +lc */ if(debug['L']) { Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s); Bprint(&bso, "%6lux %P\n", p->pc, p); } } else { CPUT(64-s); /* 65-128 -lc */ if(debug['L']) { Bprint(&bso, " lc%ld(%ld)\n", s, 64-s); Bprint(&bso, "%6lux %P\n", p->pc, p); } } lcsize++; } while(lcsize & 1) { s = 129; CPUT(s); lcsize++; } if(debug['v'] || debug['L']) Bprint(&bso, "lcsize = %ld\n", lcsize); Bflush(&bso);}voiddatblk(long s, long n){ Prog *p; char *cast; long l, fl, j, d; int i, c; memset(buf.dbuf, 0, n+100); for(p = datap; p != P; p = p->link) { curp = p; l = p->from.sym->value + p->from.offset - s; c = p->reg; i = 0; if(l < 0) { if(l+c <= 0) continue; while(l < 0) { l++; i++; } } if(l >= n) continue; if(p->as != AINIT && p->as != ADYNT) { for(j=l+(c-i)-1; j>=l; j--) if(buf.dbuf[j]) { print("%P\n", p); diag("multiple initialization"); break; } } switch(p->to.type) { default: diag("unknown mode in initialization\n%P", p); break; case D_FCONST: switch(c) { default: case 4: fl = ieeedtof(p->to.ieee); cast = (char*)&fl; for(; i<c; i++) { buf.dbuf[l] = cast[fnuxi8[i]]; l++; } break; case 8: cast = (char*)p->to.ieee; for(; i<c; i++) { buf.dbuf[l] = cast[fnuxi8[i]]; l++; } break; } break; case D_SCONST: for(; i<c; i++) { buf.dbuf[l] = p->to.sval[i]; l++; } break; case D_CONST: d = p->to.offset; if(p->to.sym) { if(p->to.sym->type == STEXT || p->to.sym->type == SLEAF) d += p->to.sym->value; if(p->to.sym->type == SDATA) d += p->to.sym->value + INITDAT; if(p->to.sym->type == SBSS) d += p->to.sym->value + INITDAT; } cast = (char*)&d; switch(c) { default: diag("bad nuxi %d %d\n%P", c, i, curp); break; case 1: for(; i<c; i++) { buf.dbuf[l] = cast[inuxi1[i]]; l++; } break; case 2: for(; i<c; i++) { buf.dbuf[l] = cast[inuxi2[i]]; l++; } break; case 4: for(; i<c; i++) { buf.dbuf[l] = cast[inuxi4[i]]; l++; } break; case 8: for(; i<4; i++) { buf.dbuf[l] = cast[inuxi4[i]]; l++; } d = p->to.offset >> 32; for(; i<c; i++) { buf.dbuf[l] = cast[inuxi4[i-4]]; l++; } break; } break; } } write(cout, buf.dbuf, n);}#define OP_RRR(op,r1,r2,r3)\ (op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|((r3)&31L))#define OP_IRR(op,i,r2,r3)\ (op|(((i)&255L)<<13)|0x1000|(((r2)&31L)<<21)|((r3)&31L))#define OP_MEM(op,d,r1,r2)\ (op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|((d)&0xffff))#define OP_BR(op,d,r1)\ (op|((d)&0x1fffff)|(((r1)&31L)<<21))intasmout(Prog *p, Optab *o){ long o1, o2, o3, o4, o5, o6; vlong v; int r, a; o1 = 0; o2 = 0; o3 = 0; o4 = 0; o5 = 0; o6 = 0; switch(o->type) { default: diag("unknown type %d", o->type); if(!debug['a']) prasm(p); break; case 0: /* pseudo ops */ break; case 1: /* register-register moves */ if(p->as == AMOVB || p->as == AMOVW) /* noop should rewrite */ diag("forbidden SEX: %P", p); if(p->as == AMOVBU || p->as == AMOVWU) { v = 1; if (p->as == AMOVWU)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -