diff options
Diffstat (limited to 'src/cmd/8l/asm.c')
-rw-r--r-- | src/cmd/8l/asm.c | 532 |
1 files changed, 532 insertions, 0 deletions
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c new file mode 100644 index 000000000..87188967f --- /dev/null +++ b/src/cmd/8l/asm.c @@ -0,0 +1,532 @@ +// Inferno utils/8l/asm.c +// http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.c +// +// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. +// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) +// Portions Copyright © 1997-1999 Vita Nuova Limited +// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) +// Portions Copyright © 2004,2006 Bruce Ellis +// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) +// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others +// Portions Copyright © 2009 The Go Authors. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "l.h" + +#define Dbufslop 100 + +long +entryvalue(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; + switch(s->type) { + case STEXT: + break; + case SDATA: + if(dlm) + return s->value+INITDAT; + default: + diag("entry not text: %s", s->name); + } + return s->value; +} + +void +wput(ushort w) +{ + cput(w); + cput(w>>8); +} + +void +wputb(ushort w) +{ + cput(w>>8); + cput(w); +} + +void +asmb(void) +{ + Prog *p; + long v, magic; + int a; + uchar *op1; + + if(debug['v']) + Bprint(&bso, "%5.2f asmb\n", cputime()); + Bflush(&bso); + + seek(cout, HEADR, 0); + pc = INITTEXT; + curp = firstp; + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) + curtext = p; + if(p->pc != pc) { + if(!debug['a']) + print("%P\n", curp); + diag("phase error %lux sb %lux in %s", p->pc, pc, TNAME); + pc = p->pc; + } + curp = p; + asmins(p); + if(cbc < sizeof(and)) + cflush(); + a = (andptr - and); + if(debug['a']) { + Bprint(&bso, pcstr, pc); + for(op1 = and; op1 < andptr; op1++) + Bprint(&bso, "%.2ux", *op1 & 0xff); + Bprint(&bso, "\t%P\n", curp); + } + if(dlm) { + if(p->as == ATEXT) + reloca = nil; + else if(reloca != nil) + diag("reloc failure: %P", curp); + } + memmove(cbp, and, a); + cbp += a; + pc += a; + cbc -= a; + } + cflush(); + switch(HEADTYPE) { + default: + diag("unknown header type %d", HEADTYPE); + case 0: + seek(cout, rnd(HEADR+textsize, 8192), 0); + break; + case 1: + textsize = rnd(HEADR+textsize, 4096)-HEADR; + seek(cout, textsize+HEADR, 0); + break; + case 2: + seek(cout, HEADR+textsize, 0); + break; + case 3: + case 4: + seek(cout, HEADR+rnd(textsize, INITRND), 0); + break; + } + + if(debug['v']) + Bprint(&bso, "%5.2f datblk\n", cputime()); + Bflush(&bso); + + if(dlm){ + char buf[8]; + + write(cout, buf, INITDAT-textsize); + textsize = INITDAT; + } + + for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) { + if(datsize-v > sizeof(buf)-Dbufslop) + datblk(v, sizeof(buf)-Dbufslop); + else + datblk(v, datsize-v); + } + + symsize = 0; + spsize = 0; + lcsize = 0; + if(!debug['s']) { + if(debug['v']) + Bprint(&bso, "%5.2f sym\n", cputime()); + Bflush(&bso); + switch(HEADTYPE) { + default: + case 0: + seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0); + break; + case 1: + seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); + break; + case 2: + seek(cout, HEADR+textsize+datsize, 0); + break; + case 3: + case 4: + debug['s'] = 1; + break; + } + if(!debug['s']) + asmsym(); + if(debug['v']) + Bprint(&bso, "%5.2f sp\n", cputime()); + Bflush(&bso); + if(debug['v']) + Bprint(&bso, "%5.2f pc\n", cputime()); + Bflush(&bso); + if(!debug['s']) + asmlc(); + if(dlm) + asmdyn(); + cflush(); + } + else if(dlm){ + seek(cout, HEADR+textsize+datsize, 0); + asmdyn(); + cflush(); + } + if(debug['v']) + Bprint(&bso, "%5.2f headr\n", cputime()); + Bflush(&bso); + seek(cout, 0L, 0); + switch(HEADTYPE) { + default: + case 0: /* garbage */ + lput(0x160L<<16); /* magic and sections */ + lput(0L); /* time and date */ + lput(rnd(HEADR+textsize, 4096)+datsize); + lput(symsize); /* nsyms */ + lput((0x38L<<16)|7L); /* size of optional hdr and flags */ + lput((0413<<16)|0437L); /* magic and version */ + lput(rnd(HEADR+textsize, 4096)); /* sizes */ + lput(datsize); + lput(bsssize); + lput(entryvalue()); /* va of entry */ + lput(INITTEXT-HEADR); /* va of base of text */ + lput(INITDAT); /* va of base of data */ + lput(INITDAT+datsize); /* va of base of bss */ + lput(~0L); /* gp reg mask */ + lput(0L); + lput(0L); + lput(0L); + lput(0L); + lput(~0L); /* gp value ?? */ + break; + lputl(0); /* x */ + case 1: /* unix coff */ + /* + * file header + */ + lputl(0x0004014c); /* 4 sections, magic */ + lputl(0); /* unix time stamp */ + lputl(0); /* symbol table */ + lputl(0); /* nsyms */ + lputl(0x0003001c); /* flags, sizeof a.out header */ + /* + * a.out header + */ + lputl(0x10b); /* magic, version stamp */ + lputl(rnd(textsize, INITRND)); /* text sizes */ + lputl(datsize); /* data sizes */ + lputl(bsssize); /* bss sizes */ + lput(entryvalue()); /* va of entry */ + lputl(INITTEXT); /* text start */ + lputl(INITDAT); /* data start */ + /* + * text section header + */ + s8put(".text"); + lputl(HEADR); /* pa */ + lputl(HEADR); /* va */ + lputl(textsize); /* text size */ + lputl(HEADR); /* file offset */ + lputl(0); /* relocation */ + lputl(0); /* line numbers */ + lputl(0); /* relocation, line numbers */ + lputl(0x20); /* flags text only */ + /* + * data section header + */ + s8put(".data"); + lputl(INITDAT); /* pa */ + lputl(INITDAT); /* va */ + lputl(datsize); /* data size */ + lputl(HEADR+textsize); /* file offset */ + lputl(0); /* relocation */ + lputl(0); /* line numbers */ + lputl(0); /* relocation, line numbers */ + lputl(0x40); /* flags data only */ + /* + * bss section header + */ + s8put(".bss"); + lputl(INITDAT+datsize); /* pa */ + lputl(INITDAT+datsize); /* va */ + lputl(bsssize); /* bss size */ + lputl(0); /* file offset */ + lputl(0); /* relocation */ + lputl(0); /* line numbers */ + lputl(0); /* relocation, line numbers */ + lputl(0x80); /* flags bss only */ + /* + * comment section header + */ + s8put(".comment"); + lputl(0); /* pa */ + lputl(0); /* va */ + lputl(symsize+lcsize); /* comment size */ + lputl(HEADR+textsize+datsize); /* file offset */ + lputl(HEADR+textsize+datsize); /* offset of syms */ + lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */ + lputl(0); /* relocation, line numbers */ + lputl(0x200); /* flags comment only */ + break; + case 2: /* plan9 */ + magic = 4*11*11+7; + if(dlm) + magic |= 0x80000000; + lput(magic); /* magic */ + lput(textsize); /* sizes */ + lput(datsize); + lput(bsssize); + lput(symsize); /* nsyms */ + lput(entryvalue()); /* va of entry */ + lput(spsize); /* sp offsets */ + lput(lcsize); /* line offsets */ + break; + case 3: + /* MS-DOS .COM */ + break; + case 4: + /* fake MS-DOS .EXE */ + v = rnd(HEADR+textsize, INITRND)+datsize; + wput(0x5A4D); /* 'MZ' */ + wput(v % 512); /* bytes in last page */ + wput(rnd(v, 512)/512); /* total number of pages */ + wput(0x0000); /* number of reloc items */ + v = rnd(HEADR-(INITTEXT & 0xFFFF), 16); + wput(v/16); /* size of header */ + wput(0x0000); /* minimum allocation */ + wput(0xFFFF); /* maximum allocation */ + wput(0x0000); /* initial ss value */ + wput(0x0100); /* initial sp value */ + wput(0x0000); /* complemented checksum */ + v = entryvalue(); + wput(v); /* initial ip value (!) */ + wput(0x0000); /* initial cs value */ + wput(0x0000); + wput(0x0000); + wput(0x003E); /* reloc table offset */ + wput(0x0000); /* overlay number */ + break; + } + cflush(); +} + +void +lput(long l) +{ + cput(l>>24); + cput(l>>16); + cput(l>>8); + cput(l); +} + +void +lputl(long l) +{ + cput(l); + cput(l>>8); + cput(l>>16); + cput(l>>24); +} + +void +s8put(char *n) +{ + char name[8]; + int i; + + strncpy(name, n, sizeof(name)); + for(i=0; i<sizeof(name); i++) + cput(name[i]); +} + +void +cflush(void) +{ + int n; + + n = sizeof(buf.cbuf) - cbc; + if(n) + write(cout, buf.cbuf, n); + cbp = buf.cbuf; + cbc = sizeof(buf.cbuf); +} + +void +datblk(long s, long n) +{ + Prog *p; + char *cast; + long l, fl, j; + int i, c; + + memset(buf.dbuf, 0, n+Dbufslop); + for(p = datap; p != P; p = p->link) { + curp = p; + l = p->from.sym->value + p->from.offset - s; + c = p->from.scale; + 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) { + case D_FCONST: + switch(c) { + default: + case 4: + fl = ieeedtof(&p->to.ieee); + cast = (char*)&fl; + if(debug['a'] && i == 0) { + Bprint(&bso, pcstr, l+s+INITDAT); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff); + Bprint(&bso, "\t%P\n", curp); + } + for(; i<c; i++) { + buf.dbuf[l] = cast[fnuxi4[i]]; + l++; + } + break; + case 8: + cast = (char*)&p->to.ieee; + if(debug['a'] && i == 0) { + Bprint(&bso, pcstr, l+s+INITDAT); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff); + Bprint(&bso, "\t%P\n", curp); + } + for(; i<c; i++) { + buf.dbuf[l] = cast[fnuxi8[i]]; + l++; + } + break; + } + break; + + case D_SCONST: + if(debug['a'] && i == 0) { + Bprint(&bso, pcstr, l+s+INITDAT); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff); + Bprint(&bso, "\t%P\n", curp); + } + for(; i<c; i++) { + buf.dbuf[l] = p->to.scon[i]; + l++; + } + break; + default: + fl = p->to.offset; + if(p->to.type == D_ADDR) { + if(p->to.index != D_STATIC && p->to.index != D_EXTERN) + diag("DADDR type%P", p); + if(p->to.sym) { + if(p->to.sym->type == SUNDEF) + ckoff(p->to.sym, fl); + fl += p->to.sym->value; + if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF) + fl += INITDAT; + if(dlm) + dynreloc(p->to.sym, l+s+INITDAT, 1); + } + } + cast = (char*)&fl; + switch(c) { + default: + diag("bad nuxi %d %d\n%P", c, i, curp); + break; + case 1: + if(debug['a'] && i == 0) { + Bprint(&bso, pcstr, l+s+INITDAT); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux", cast[inuxi1[j]] & 0xff); + Bprint(&bso, "\t%P\n", curp); + } + for(; i<c; i++) { + buf.dbuf[l] = cast[inuxi1[i]]; + l++; + } + break; + case 2: + if(debug['a'] && i == 0) { + Bprint(&bso, pcstr, l+s+INITDAT); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff); + Bprint(&bso, "\t%P\n", curp); + } + for(; i<c; i++) { + buf.dbuf[l] = cast[inuxi2[i]]; + l++; + } + break; + case 4: + if(debug['a'] && i == 0) { + Bprint(&bso, pcstr, l+s+INITDAT); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff); + Bprint(&bso, "\t%P\n", curp); + } + for(; i<c; i++) { + buf.dbuf[l] = cast[inuxi4[i]]; + l++; + } + break; + } + break; + } + } + write(cout, buf.dbuf, n); +} + +long +rnd(long v, long r) +{ + long c; + + if(r <= 0) + return v; + v += r - 1; + c = v % r; + if(c < 0) + c += r; + v -= c; + return v; +} |