diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/8l/asm.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/8l/asm.c')
-rwxr-xr-x | sys/src/cmd/8l/asm.c | 554 |
1 files changed, 554 insertions, 0 deletions
diff --git a/sys/src/cmd/8l/asm.c b/sys/src/cmd/8l/asm.c new file mode 100755 index 000000000..a1bb36ba6 --- /dev/null +++ b/sys/src/cmd/8l/asm.c @@ -0,0 +1,554 @@ +#include "l.h" + +#define Dbufslop 100 + +#define PADDR(a) ((ulong)(a) & ~0xF0000000) + +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 +wputl(ushort w) +{ + cput(w); + cput(w>>8); +} + +void +wput(ushort w) +{ + cput(w>>8); + cput(w); +} + +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 +strnput(char *s, int n) +{ + for(; *s && n > 0; s++){ + cput(*s); + n--; + } + while(n > 0){ + cput(0); + n--; + } +} + +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 %ld", 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: + case 5: + 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: + case 5: + 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; + 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 + */ + strnput(".text", 8); + 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 + */ + strnput(".data", 8); + 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 + */ + strnput(".bss", 8); + 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 + */ + strnput(".comment", 8); + 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; + wputl(0x5A4D); /* 'MZ' */ + wputl(v % 512); /* bytes in last page */ + wputl(rnd(v, 512)/512); /* total number of pages */ + wputl(0x0000); /* number of reloc items */ + v = rnd(HEADR-(INITTEXT & 0xFFFF), 16); + wputl(v/16); /* size of header */ + wputl(0x0000); /* minimum allocation */ + wputl(0xFFFF); /* maximum allocation */ + wputl(0x0000); /* initial ss value */ + wputl(0x0100); /* initial sp value */ + wputl(0x0000); /* complemented checksum */ + v = entryvalue(); + wputl(v); /* initial ip value (!) */ + wputl(0x0000); /* initial cs value */ + wputl(0x0000); + wputl(0x0000); + wputl(0x003E); /* reloc table offset */ + wputl(0x0000); /* overlay number */ + break; + case 5: + strnput("\177ELF", 4); /* e_ident */ + cput(1); /* class = 32 bit */ + cput(1); /* data = LSB */ + cput(1); /* version = CURRENT */ + strnput("", 9); + wputl(2); /* type = EXEC */ + wputl(3); /* machine = 386 */ + lputl(1L); /* version = CURRENT */ + lputl(PADDR(entryvalue())); /* entry vaddr */ + lputl(52L); /* offset to first phdr */ + lputl(0L); /* offset to first shdr */ + lputl(0L); /* flags = 386 */ + wputl(52); /* Ehdr size */ + wputl(32); /* Phdr size */ + wputl(3); /* # of Phdrs */ + wputl(0); /* Shdr size */ + wputl(0); /* # of Shdrs */ + wputl(0); /* Shdr string size */ + + lputl(1L); /* text - type = PT_LOAD */ + lputl(HEADR); /* file offset */ + lputl(INITTEXT); /* vaddr */ + lputl(PADDR(INITTEXT)); /* paddr */ + lputl(textsize); /* file size */ + lputl(textsize); /* memory size */ + lputl(0x05L); /* protections = RX */ + lputl(INITRND); /* alignment */ + + lputl(1L); /* data - type = PT_LOAD */ + lputl(HEADR+textsize); /* file offset */ + lputl(INITDAT); /* vaddr */ + lputl(PADDR(INITDAT)); /* paddr */ + lputl(datsize); /* file size */ + lputl(datsize+bsssize); /* memory size */ + lputl(0x06L); /* protections = RW */ + lputl(INITRND); /* alignment */ + + lputl(0L); /* data - type = PT_NULL */ + lputl(HEADR+textsize+datsize); /* file offset */ + lputl(0L); + lputl(0L); + lputl(symsize); /* symbol table size */ + lputl(lcsize); /* line number size */ + lputl(0x04L); /* protections = R */ + lputl(0x04L); /* alignment */ + break; + } + cflush(); +} + +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; +} |