From 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a Mon Sep 17 00:00:00 2001 From: "Charles.Forsyth" Date: Fri, 22 Dec 2006 21:39:35 +0000 Subject: 20060303 --- utils/8l/asm.c | 502 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 502 insertions(+) create mode 100644 utils/8l/asm.c (limited to 'utils/8l/asm.c') diff --git a/utils/8l/asm.c b/utils/8l/asm.c new file mode 100644 index 00000000..56eee141 --- /dev/null +++ b/utils/8l/asm.c @@ -0,0 +1,502 @@ +#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; ilink) { + 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; jto.ieee; + if(debug['a'] && i == 0) { + Bprint(&bso, pcstr, l+s+INITDAT); + for(j=0; jto.scon[j] & 0xff); + Bprint(&bso, "\t%P\n", curp); + } + for(; ito.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