📄 asm.c
字号:
#include "l.h"#define LPUT(c)\ {\ cbp[0] = (c)>>24;\ cbp[1] = (c)>>16;\ cbp[2] = (c)>>8;\ cbp[3] = (c);\ cbp += 4;\ cbc -= 4;\ if(cbc <= 0)\ cflush();\ }#define CPUT(c)\ {\ cbp[0] = (c);\ cbp++;\ cbc--;\ 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; long 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 + 4; } if(p->pc != pc) { diag("phase error %lux sb %lux", p->pc, pc); if(!debug['a']) prasm(curp); pc = p->pc; } curp = p; o = oplook(p); /* could probably avoid this call */ if(asmout(p, o, 0)) { p = p->link; pc += 4; } pc += o->size; } if(debug['a']) Bprint(&bso, "\n"); Bflush(&bso); cflush(); curtext = P; switch(HEADTYPE) { case 0: case 3: seek(cout, HEADR+textsize, 0); break; case 1: case 2: 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: case 3: seek(cout, HEADR+textsize+datsize, 0); break; case 2: case 1: seek(cout, HEADR+textsize+datsize, 0); break; } if(!debug['s']) asmsym(); if(debug['v']) Bprint(&bso, "%5.2f sp\n", cputime()); Bflush(&bso); if(!debug['s']) asmlc(); /* round up file length for boot image */ if(HEADTYPE == 0 || HEADTYPE == 3) if((symsize+lcsize) & 1) CPUT(0); cflush(); } seek(cout, 0L, 0); switch(HEADTYPE) { case 0: lput(0x1030107); /* magic and sections */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 1: break; case 2: lput(4*13*13+7); /* magic */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 3: lput(0x1030107); /* magic and sections */ lput(0x90100000);#define SPARC_NOOP 0x01000000 lput(SPARC_NOOP); lput(SPARC_NOOP); lput(SPARC_NOOP); lput(SPARC_NOOP); lput(SPARC_NOOP); lput(SPARC_NOOP); break; } cflush();}voidlput(long l){ LPUT(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->asym->name, 'z', a->aoffset, 0); else if(a->type == D_FILE1) putsymb(a->asym->name, 'Z', a->aoffset, 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+4, 0); for(a=p->to.autom; a; a=a->link) if(a->type == D_AUTO) putsymb(a->asym->name, 'a', -a->aoffset, 0); else if(a->type == D_PARAM) putsymb(a->asym->name, 'p', a->aoffset, 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++; LPUT(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+4]]; 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; } break; } } write(cout, buf.dbuf, n);}#define OP2(x) (0x80000000|((x)<<19))#define OP3(x) (0xc0000000|((x)<<19))#define OPB(x) (0x00800000|((x)<<25))#define OPT(x) (0x81d02000|((x)<<25))#define OPF1(x) (0x81a00000|((x)<<5))#define OPF2(x) (0x81a80000|((x)<<5))#define OPFB(x) (0x01800000|((x)<<25))#define OP_RRR(op,r1,r2,r3)\ (0x00000000 | op |\ (((r1)&31L)<<0) |\ (((r2)&31L)<<14) |\ (((r3)&31L)<<25))#define OP_IRR(op,i,r2,r3)\ (0x00002000L | (op) |\ (((i)&0x1fffL)<<0) |\ (((r2)&31L)<<14) |\ (((r3)&31L)<<25))#define OP_BRA(op,pc)\ ((op) |\ (((pc)&0x3fffff)<<0))intasmout(Prog *p, Optab *o, int aflag){ long o1, o2, o3, o4, o5, v; Prog *ct; int r; o1 = 0; o2 = 0; o3 = 0; o4 = 0; o5 = 0; switch(o->type) { default: if(aflag) return 0; diag("unknown type %d", o->type); if(!debug['a']) prasm(p); break; case 0: /* pseudo ops */ if(aflag) { if(p->link) { if(p->as == ATEXT) { ct = curtext; o2 = autosize; curtext = p; autosize = p->to.offset + 4; o1 = asmout(p->link, oplook(p->link), aflag); curtext = ct; autosize = o2; } else o1 = asmout(p->link, oplook(p->link), aflag); } return o1; } break; case 1: /* mov r1,r2 ==> OR r1,r0,r2 */ o1 = OP_RRR(opcode(AOR), p->from.reg, REGZERO, p->to.reg); break; case 2: /* mov $c,r ==> add r1,r0,r2 */ r = p->from.reg; if(r == NREG) r = o->param; v = regoff(&p->from); o1 = OP_IRR(opcode(AADD), v, r, p->to.reg); break; case 3: /* mov soreg, r */ r = p->from.reg; if(r == NREG) r = o->param; v = regoff(&p->from); if(v == 0 && p->reg != NREG) o1 = OP_RRR(opcode(p->as), p->reg, r, p->to.reg); else o1 = OP_IRR(opcode(p->as), v, r, p->to.reg); break; case 4: /* mov r, soreg */ r = p->to.reg; if(r == NREG) r = o->param; v = regoff(&p->to); if(v == 0 && p->reg != NREG) o1 = OP_RRR(opcode(p->as+AEND), p->reg, r, p->from.reg); else o1 = OP_IRR(opcode(p->as+AEND), v, r, p->from.reg); break; case 5: /* mov $lcon, reg => sethi, add */ v = regoff(&p->from); o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg); break; case 6: /* mov asi, r[+r] */ o1 = OP_RRR(opcode(p->as), p->reg, p->from.reg, p->to.reg); o1 |= (1<<23) | ((p->from.offset&0xff)<<5); break; case 7: /* mov [+r]r, asi */ o1 = OP_RRR(opcode(p->as+AEND), p->reg, p->to.reg, p->from.reg); o1 |= (1<<23) | ((p->to.offset&0xff)<<5); break; case 8: /* mov r, preg and mov preg, r */ if(p->to.type == D_PREG) { r = p->from.reg; switch(p->to.reg) { default: diag("unknown register P%d", p->to.reg); case D_Y: o1 = OP2(48); /* wry */ break; case D_PSR: o1 = OP2(49); /* wrpsr */ break; case D_WIM: o1 = OP2(50); /* wrwim */ break; case D_TBR: o1 = OP2(51); /* wrtbr */ break; } o1 = OP_IRR(o1, 0, r, 0); break; } if(p->from.type == D_PREG) { r = p->to.reg; switch(p->from.reg) { default: diag("unknown register P%d", p->to.reg); case D_Y:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -