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/1l |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/1l')
-rwxr-xr-x | sys/src/cmd/1l/asm.c | 1529 | ||||
-rwxr-xr-x | sys/src/cmd/1l/compat.c | 50 | ||||
-rwxr-xr-x | sys/src/cmd/1l/cputime.c | 12 | ||||
-rwxr-xr-x | sys/src/cmd/1l/l.h | 271 | ||||
-rwxr-xr-x | sys/src/cmd/1l/list.c | 334 | ||||
-rwxr-xr-x | sys/src/cmd/1l/mkfile | 22 | ||||
-rwxr-xr-x | sys/src/cmd/1l/obj.c | 1413 | ||||
-rwxr-xr-x | sys/src/cmd/1l/optab.c | 444 | ||||
-rwxr-xr-x | sys/src/cmd/1l/pass.c | 673 | ||||
-rwxr-xr-x | sys/src/cmd/1l/span.c | 515 |
10 files changed, 5263 insertions, 0 deletions
diff --git a/sys/src/cmd/1l/asm.c b/sys/src/cmd/1l/asm.c new file mode 100755 index 000000000..6cf02ed8c --- /dev/null +++ b/sys/src/cmd/1l/asm.c @@ -0,0 +1,1529 @@ +#include "l.h" + +short opa[20]; +short *op; + +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; + if(s->type != STEXT) + diag("entry not text: %s", s->name); + return s->value; +} + +void +asmb(void) +{ + Prog *p; + long v; + int a; + short *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 %.4lux sb %.4lux in %s", p->pc, pc, TNAME); + pc = p->pc; + } + curp = p; + if(debug['a']) + Bprint(&bso, "%lux:%P\n", pc, curp); + asmins(p); + if(cbc < sizeof(opa)) + cflush(); + for(op1 = opa; op1 < op; op1++) { + a = *op1; + *cbp++ = a >> 8; + *cbp++ = a; + } + a = 2*(op - opa); + pc += a; + cbc -= a; + if(debug['a']) { + for(op1 = opa; op1 < op; op1++) + if(op1 == opa) + Bprint(&bso, "\t\t%4ux", *op1 & 0xffff); + else + Bprint(&bso, " %4ux", *op1 & 0xffff); + if(op != opa) + Bprint(&bso, "\n"); + } + } + cflush(); + switch(HEADTYPE) { + case 0: /* this is garbage */ + seek(cout, rnd(HEADR+textsize, 8192), 0); + break; + case 1: /* plan9 boot data goes into text */ + seek(cout, rnd(HEADR+textsize, INITRND), 0); + break; + case 2: /* plan 9 */ + seek(cout, HEADR+textsize, 0); + break; + case 3: /* next boot */ + seek(cout, HEADR+rnd(textsize, INITRND), 0); + break; + case 4: /* preprocess pilot */ + seek(cout, HEADR+textsize, 0); + break; + } + + if(debug['v']) + Bprint(&bso, "%5.2f datblk\n", cputime()); + Bflush(&bso); + + for(v = 0; v < datsize; v += sizeof(buf)-100) { + if(datsize-v > sizeof(buf)-100) + datblk(v, sizeof(buf)-100); + else + datblk(v, datsize-v); + } + + symsize = 0; + spsize = 0; + lcsize = 0; + relocsize = 0; + + Bflush(&bso); + + switch(HEADTYPE) { + default: + seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0); + break; + case 1: /* plan9 boot data goes into text */ + seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); + break; + case 2: /* plan 9 */ + seek(cout, HEADR+textsize+datsize, 0); + break; + case 3: /* next boot */ + seek(cout, HEADR+rnd(textsize, INITRND)+datsize, 0); + break; + case 4: /* preprocess pilot */ + seek(cout, HEADR+textsize+datsize, 0); + break; + } + if(!debug['s']) { + if(debug['v']) + Bprint(&bso, "%5.2f sym\n", cputime()); + asmsym(); + } + Bflush(&bso); + if(!debug['s']) { + if(debug['v']) + Bprint(&bso, "%5.2f sp\n", cputime()); + asmsp(); + } + Bflush(&bso); + if(!debug['s']) { + if(debug['v']) + Bprint(&bso, "%5.2f pc\n", cputime()); + asmlc(); + } + Bflush(&bso); + if(!debug['s']) { + if(debug['v']) + Bprint(&bso, "%5.2f reloc\n", cputime()); + asmreloc(); + } + cflush(); + + if(debug['v']) + Bprint(&bso, "%5.2f headr\n", cputime()); + Bflush(&bso); + seek(cout, 0L, 0); + switch(HEADTYPE) { + default: + 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: /* plan9 boot data goes into text */ + lput(0407); /* magic */ + lput(rnd(HEADR+textsize, INITRND)-HEADR+datsize); /* sizes */ + lput(0); + lput(bsssize); + lput(symsize); /* nsyms */ + lput(entryvalue()); /* va of entry */ + lput(spsize); /* sp offsets */ + lput(lcsize); /* line offsets */ + break; + case 2: /* plan 9 */ + lput(0407); /* 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: /* next boot */ + /* header */ + lput(0xfeedfaceL); /* magic */ + lput(6); /* 68040 */ + lput(1); /* more 68040 */ + lput(5); /* file type 'boot' */ + lput(HEADTYPE); /* number commands */ + lput(HEADR-7*4); /* sizeof commands */ + lput(1); /* no undefineds */ + /* command 1 text */ + lput(1); /* command = 'segment' */ + lput(124); /* command size */ + s16put("__TEXT"); + /* botch?? entryvalue() */ + lput(INITTEXT); /* va of start */ + lput(rnd(textsize, 8192)); /* va size */ + lput(HEADR); /* file offset */ + lput(rnd(textsize, 8192)); /* file size */ + lput(7); /* max prot */ + lput(7); /* init prot */ + lput(1); /* number of sections */ + lput(0); /* flags */ + /* text section */ + s16put("__text"); + s16put("__TEXT"); + /* botch?? entryvalue() */ + lput(INITTEXT); /* va of start */ + lput(textsize); /* va size */ + lput(HEADR); /* file offset */ + lput(2); /* align */ + lput(0); /* reloff */ + lput(0); /* nreloc */ + lput(0); /* flags */ + lput(0); /* reserved1 */ + lput(0); /* reserved2 */ + /* command 1 data */ + lput(1); /* command = 'segment' */ + lput(192); /* command size */ + s16put("__DATA"); + lput(INITDAT); /* va of start */ + lput(rnd(datsize, 8192)); /* va size */ + lput(HEADR+rnd(textsize, 8192)); /* file offset */ + lput(rnd(datsize, 8192)); /* file size */ + lput(7); /* max prot */ + lput(7); /* init prot */ + lput(2); /* number of sections */ + lput(0); /* flags */ + /* data section */ + s16put("__data"); + s16put("__DATA"); + lput(INITDAT); /* va of start */ + lput(datsize); /* va size */ + lput(HEADR+rnd(textsize, 8192)); /* file offset */ + lput(2); /* align */ + lput(0); /* reloff */ + lput(0); /* nreloc */ + lput(0); /* flags */ + lput(0); /* reserved1 */ + lput(0); /* reserved2 */ + /* bss section */ + s16put("__bss"); + s16put("__DATA"); + lput(INITDAT+datsize); /* va of start */ + lput(bsssize); /* va size */ + lput(0); /* file offset */ + lput(2); /* align */ + lput(0); /* reloff */ + lput(0); /* nreloc */ + lput(1); /* flags = zero fill */ + lput(0); /* reserved1 */ + lput(0); /* reserved2 */ + /* command 2 symbol */ + lput(2); /* command = 'symbol' */ + lput(24); /* command size */ + lput(HEADR+rnd(textsize, INITRND) + +datsize); /* symoff */ + lput(symsize); /* nsyms */ + lput(spsize); /* sp offsets */ + lput(lcsize); /* line offsets */ + break; + case 4: /* preprocess pilot */ + lput(0407); /* magic */ + lput(textsize); /* sizes */ + lput(datsize); + lput(bsssize); + lput(symsize); /* nsyms */ + lput(entryvalue()); /* va of entry */ + lput(spsize); /* sp offsets */ + lput(lcsize); /* line offsets */ + lput(relocsize); /* relocation */ + break; + } + cflush(); +} + +void +asmins(Prog *p) +{ + Optab *o; + int t, a, b; + long v; + + op = opa + 1; + if(special[p->from.type]) + switch(p->from.type) { + + case D_CCR: + if(p->as != AMOVW) + goto bad; + a = asmea(p, &p->to); + if((a & 0170) == 010) + goto bad; + opa[0] = 0x42c0 | a; /* mov from ccr */ + return; + + case D_SR: + if(p->as != AMOVW) + goto bad; + a = asmea(p, &p->to); + if((a & 0170) == 010) + goto bad; + opa[0] = 0x40c0 | a; /* mov from sr */ + return; + + case D_USP: + if(p->as != AMOVL) + goto bad; + a = asmea(p, &p->to); + if((a & 0170) == 010) { + opa[0] = 0x4e68|(a&7); /* mov usp An */ + return; + } + t = 0x800; + goto movec1; + + case D_SFC: + t = 0x000; + goto movec1; + + case D_DFC: + t = 0x001; + goto movec1; + + case D_CACR: + t = 0x002; + goto movec1; + + case D_TC: + t = 0x003; + goto movec1; + + case D_ITT0: + t = 0x004; + goto movec1; + + case D_ITT1: + t = 0x005; + goto movec1; + + case D_DTT0: + t = 0x006; + goto movec1; + + case D_DTT1: + t = 0x007; + goto movec1; + + case D_VBR: + t = 0x801; + goto movec1; + + case D_CAAR: + t = 0x802; + goto movec1; + + case D_MSP: + t = 0x803; + goto movec1; + + case D_ISP: + t = 0x804; + goto movec1; + + case D_MMUSR: + t = 0x805; + goto movec1; + + case D_URP: + t = 0x806; + goto movec1; + + case D_SRP: + t = 0x807; + goto movec1; + + movec1: + if(p->as != AMOVL) + goto bad; + opa[0] = 0x4e7a; /* mov spc Dn */ + a = asmea(p, &p->to); + b = a & 0170; + if(b == 0 || b == 010) { + *op++ = (a<<12) | t; + return; + } + goto bad; + + case D_FPCR: + t = 0xb000; + goto movec3; + + case D_FPSR: + t = 0xa800; + goto movec3; + + case D_FPIAR: + t = 0xa400; + + movec3: + if(p->as != AMOVL) + goto bad; + op++; + a = asmea(p, &p->to); + opa[0] = optab[AFMOVEL].opcode0 | a; + opa[1] = t; + return; + } + if(special[p->to.type]) + switch(p->to.type) { + + case D_CCR: + if(p->as != AMOVW) /* botch, needs and, eor etc. */ + goto bad; + a = asmea(p, &p->from); + if((a & 0170) == 010) + goto bad; + opa[0] = 0x44c0 | a; /* mov to ccr */ + return; + + case D_SR: + if(p->as != AMOVW) /* botch, needs and, eor etc. */ + goto bad; + a = asmea(p, &p->from); + if((a & 0170) == 010) + goto bad; + opa[0] = 0x46c0 | a; /* mov to sr */ + return; + + case D_USP: + if(p->as != AMOVL) + goto bad; + a = asmea(p, &p->from); + if((a & 0170) == 010) { + opa[0] = 0x4e60|(a&7); /* mov An usp */ + return; + } + t = 0x800; + goto movec2; + + case D_SFC: + t = 0x000; + goto movec2; + + case D_DFC: + t = 0x001; + goto movec2; + + case D_CACR: + t = 0x002; + goto movec2; + + case D_TC: + t = 0x003; + goto movec2; + + case D_ITT0: + t = 0x004; + goto movec2; + + case D_ITT1: + t = 0x005; + goto movec2; + + case D_DTT0: + t = 0x006; + goto movec2; + + case D_DTT1: + t = 0x007; + goto movec2; + + case D_VBR: + t = 0x801; + goto movec2; + + case D_CAAR: + t = 0x802; + goto movec2; + + case D_MSP: + t = 0x803; + goto movec2; + + case D_ISP: + t = 0x804; + goto movec2; + + case D_MMUSR: + t = 0x805; + goto movec2; + + case D_URP: + t = 0x806; + goto movec2; + + case D_SRP: + t = 0x807; + goto movec2; + + movec2: + if(p->as != AMOVL) + goto bad; + opa[0] = 0x4e7b; /* mov Dn spc */ + a = asmea(p, &p->from); + b = a & 0170; + if(b == 0 || b == 010) { + *op++ = (a<<12) | t; + return; + } + goto bad; + + case D_FPCR: + t = 0x9000; + goto movec4; + + case D_FPSR: + t = 0x8800; + goto movec4; + + case D_FPIAR: + t = 0x8400; + + movec4: + if(p->as != AMOVL) + goto bad; + op++; + a = asmea(p, &p->from); + opa[0] = optab[AFMOVEL].opcode0 | a; + opa[1] = t; + return; + } + + o = &optab[p->as]; + t = o->opcode0; + switch(o->optype) { + case 0: /* pseudo ops */ + if(p->as != ATEXT && p->as != ANOP) { + if(!debug['a']) + print("%P\n", p); + diag("unimplemented instruction in %s", TNAME); + return; + } + op = opa; + return; + + case 1: /* branches */ + if(p->to.type != D_BRANCH) + goto bad; + a = asmea(p, &p->to); + if(a == 071) + t = o->opcode1; + t |= a; + break; + + case 2: /* move */ + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((a & 0170) == 0110) { /* src quick */ + t = o->opcode1; + if((b & 0170) != 0) + goto bad; + t |= a >> 7; + t |= b << 9; + break; + } + t |= a; + t |= (b&7) << 9; + t |= (b&070) << 3; + break; + + case 3: /* add */ + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((a & 0170) == 0110) { /* src quick */ + t = o->opcode1; + t |= (a&01600) << 2; + t |= b; + break; + } + if((b & 0170) == 0) { /* dst Dn */ + t |= a; + t |= (b & 7) << 9; + break; + } + if((b & 0170) == 010) { /* dst An */ + if((t & 0xc0) == 0) + goto bad; + t = o->opcode2; + t |= a; + t |= (b & 7) << 9; + break; + } + if((a & 0170) == 0) { /* src Dn */ + t |= 0x100; + t |= (a & 7) << 9; + t |= b; + break; + } + if((a & 0177) == 074) { /* src immed */ + t = o->opcode3; + t |= b; + break; + } + goto bad; + + case 4: /* no operands */ + break; + + case 5: /* tst */ + t |= asmea(p, &p->to); + if((t&0170) == 010) + goto bad; + break; + + case 6: /* lea */ + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((b & 0170) != 010) + goto bad; + t |= a; + t |= (b & 7) << 9; + break; + + case 7: /* cmp */ + b = asmea(p, &p->to); + a = asmea(p, &p->from); + if((a & 0170) == 010) { /* dst An */ + t = o->opcode1; + if(t == 0) /* cmpb illegal */ + goto bad; + t |= 0xc0; + t |= b; + t |= (a & 7) << 9; + break; + } + if((b & 0177) == 074) { /* src immed */ + t = o->opcode2; + t |= a; + break; + } + if((a & 0170) == 0) { /* dst Dn */ + t |= b; + t |= (a&7) << 9; + break; + } + if((b&0170) == 030 && (a&0170) == 030) { /* (A)+,(A)+ */ + t = o->opcode3; + t |= b & 7; + t |= (a & 7) << 9; + break; + } + goto bad; + + case 8: /* svc */ + *op++ = optab[ARTS].opcode0; + break; + + case 9: /* and */ + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((a & 0170) == 010) + goto bad; + if((b & 0170) == 0) { /* dst Dn */ + t |= a; + t |= (b&7) << 9; + break; + } + if((a & 0170) == 0) { /* src Dn */ + t = o->opcode1; + t |= b; + t |= (a&7) << 9; + break; + } + if((a & 0177) == 074) { /* src immed */ + t = o->opcode2; + t |= b; + break; + } + goto bad; + + case 10: /* eor */ + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((a & 0170) == 010) + goto bad; + if((a & 0170) == 0) { /* src Dn */ + t |= b; + t |= (a&7) << 9; + break; + } + if((a & 0177) == 074) { /* src immed */ + t = o->opcode1; + t |= b; + break; + } + goto bad; + + case 11: /* ext */ + b = asmea(p, &p->to); + if((b & 0170) == 0) { /* dst Dn */ + t |= b; + break; + } + goto bad; + + case 12: /* shift */ + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((b & 0170) == 0) { /* dst Dn */ + if((a & 0177) == 0110) { /* src quick */ + t |= (a & 01600) << 2; + t |= b; + break; + } + if((a & 0170) == 0) { /* src Dn */ + t |= 0x20; + t |= a << 9; + t |= b; + break; + } + goto bad; + } + goto bad; + + case 13: /* mul, div short */ + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((b & 0170) == 0) { /* dst Dn */ + if((a & 0170) == 010) + goto bad; + t |= a; + t |= b << 9; + break; + } + goto bad; + + case 14: /* mul, div long */ + *op++ = o->opcode1; + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((b & 0170) == 0) { /* dst Dn */ + if((a & 0170) == 010) + goto bad; + t |= a; + opa[1] |= b << 12; + opa[1] |= b+1; + break; + } + goto bad; + + case 15: /* dec and branch */ + if(p->to.type != D_BRANCH) + goto bad; + v = p->pcond->pc - p->pc - 2; + if(v < -32768L || v >= 32768L) + goto bad; + *op++ = v; + a = asmea(p, &p->from); + if((a & 0170) != 0) + goto bad; + t |= a; + break; + + case 16: /* fmove */ + *op++ = o->opcode1; + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((a & 0170) == 0100) { /* src Fn */ + if((b & 0170) == 0100) { /* both Fn */ + opa[1] |= (a&7) << 10; + opa[1] |= (b&7) << 7; + break; + } + t |= b; + opa[1] = o->opcode2; + opa[1] |= (a&7) << 7; + break; + } + if((b & 0170) != 0100) /* dst Fn */ + goto bad; + t |= a; + opa[1] = o->opcode3; + opa[1] |= (b&7) << 7; + break; + + case 17: /* floating ea,Fn */ + *op++ = o->opcode1; + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((b & 0170) != 0100) /* dst Fn */ + goto bad; + if((a & 0170) == 0100) { /* both Fn */ + opa[1] |= (a&7) << 10; + opa[1] |= (b&7) << 7; + break; + } + t |= a; + opa[1] = o->opcode2; + opa[1] |= (b&7) << 7; + break; + + case 18: /* floating branchs */ + if(p->to.type != D_BRANCH) + goto bad; + v = p->pcond->pc - p->pc - 2; + if(v < -32768L || v >= 32768L) + goto bad; + *op++ = v; + break; + + case 19: /* floating dec and branch */ + if(p->to.type != D_BRANCH) + goto bad; + *op++ = o->opcode1; + v = p->pcond->pc - p->pc - 2; + if(v < -32768L || v >= 32768L) + goto bad; + *op++ = v; + a = asmea(p, &p->from); + if((a & 0170) != 0) + goto bad; + t |= a; + break; + + case 20: /* ftst ea */ + *op++ = o->opcode1; + if(p->from.type != D_NONE) + goto bad; + a = asmea(p, &p->to); + if((a & 0170) == 0100) { /* Fn */ + opa[1] |= (a&7) << 10; + break; + } + t |= a; + opa[1] = o->opcode2; + break; + + case 21: /* fneg */ + *op++ = o->opcode1; + if(p->from.type == D_NONE) { + b = asmea(p, &p->to); + a = b; + } else { + a = asmea(p, &p->from); + b = asmea(p, &p->to); + } + if((b & 0170) != 0100) /* dst Fn */ + goto bad; + if((a & 0170) == 0100) { /* both Fn */ + opa[1] |= (a&7) << 10; + opa[1] |= (b&7) << 7; + break; + } + t |= a; + opa[1] = o->opcode2; + opa[1] |= (b&7) << 7; + break; + + case 22: /* floating cmp Fn,ea */ + *op++ = o->opcode1; + a = asmea(p, &p->from); + b = asmea(p, &p->to); + if((a & 0170) != 0100) /* dst Fn */ + goto bad; + if((b & 0170) == 0100) { /* both Fn */ + opa[1] |= (b&7) << 10; + opa[1] |= (a&7) << 7; + break; + } + t |= b; + opa[1] = o->opcode2; + opa[1] |= (a&7) << 7; + break; + + case 23: /* word, long */ + op = opa; + a = asmea(p, &p->to); + if(a == ((7<<3)|4)) + return; + if(a == ((7<<3)|1)) { + if(p->as == AWORD) { + op = opa; + *op++ = opa[1]; + } + return; + } + if(a == ((7<<3)|0)) { + if(p->as == ALONG) { + *op++ = opa[0]; + opa[0] = 0; + } + return; + } + goto bad; + + case 24: /* bit field */ + a = ((p->to.field&31)<<6) | (p->from.field&31); + if(p->as == ABFINS) { + b = asmea(p, &p->from); + if((b&0170) != 0) + goto bad; + a |= b<<12; + *op++ = a; + a = asmea(p, &p->to); + } else { + if(p->to.type != D_NONE) { + b = asmea(p, &p->to); + if((b&0170) != 0) + goto bad; + a |= b<<12; + } + *op++ = a; + a = asmea(p, &p->from); + } + t |= a; + a &= 0170; + if(a == 010 || a == 030 || a == 040 || a == 074) + goto bad; + break; + + case 25: /* movem */ + if(p->from.type == D_CONST) { /* registers -> memory */ + asmea(p, &p->from); + a = asmea(p, &p->to); + if(a == 074) + goto bad; + b = a & 0170; + if(b == 000 || b == 010 || b == 030) + goto bad; + t |= a; + break; + } + if(p->to.type == D_CONST) { /* memory -> registers */ + t |= 0x400; + asmea(p, &p->to); + a = asmea(p, &p->from); + if(a == 074) + goto bad; + b = a & 0170; + if(b == 000 || b == 010 || b == 040) + goto bad; + t |= a; + break; + } + goto bad; + + case 26: /* chk */ + a = asmea(p, &p->from); + if((a&0170) == 010) + goto bad; + b = asmea(p, &p->to); + if((b&0170) != 0) + goto bad; + t |= a; + t |= b<<9; + break; + + case 27: /* btst */ + a = asmea(p, &p->from); + if(a == 074) { + t = o->opcode1; + } else + if((a&0170) != 0) + goto bad; + b = asmea(p, &p->to); + if(b == 074 || (b&0170) == 010) + goto bad; + t |= b; + break; + + case 28: /* fmovem */ + if(p->from.type == D_CONST) { /* registers -> memory */ + b = p->from.offset & 0xff; + b |= 0xf000; /* control or postinc */ + *op++ = b; + a = asmea(p, &p->to); + if(a == 074) + goto bad; + b = a & 0170; + if(b == 000 || b == 010 || b == 030) + goto bad; + if(b == 040) + op[-1] &= ~0x1000; /* predec */ + t |= a; + break; + } + if(p->to.type == D_CONST) { /* memory -> registers */ + b = p->to.offset & 0xff; + b |= 0xd000; /* control or postinc */ + *op++ = b; + a = asmea(p, &p->from); + if(a == 074) + goto bad; + b = a & 0170; + if(b == 000 || b == 010 || b == 040) + goto bad; + t |= a; + break; + } + goto bad; + + case 29: /* fmovemc */ + if(p->from.type == D_CONST) { /* registers -> memory */ + b = (p->from.offset & 0x7) << 10; + b |= 0xa000; + *op++ = b; + a = asmea(p, &p->to); + if(a == 074) + goto bad; + b = a & 0170; + if(b == 000 || b == 010 || b == 030) + goto bad; + t |= a; + break; + } + if(p->to.type == D_CONST) { /* memory -> registers */ + b = (p->to.offset & 0x7) << 10; + b |= 0x8000; + *op++ = b; + a = asmea(p, &p->from); + if(a == 074) + goto bad; + b = a & 0170; + if(b == 000 || b == 010 || b == 040) + goto bad; + t |= a; + break; + } + goto bad; + + case 30: /* trap */ + if(p->to.type == D_CONST) { + t |= p->to.offset & 0xf; + break; + } + goto bad; + + case 31: /* chk2, cmp2 */ + b = asmea(p, &p->to); + a = b & 0170; + if(a == 000 || a == 010) { + *op++ = o->opcode1 | (b << 12); + t |= asmea(p, &p->from); + break; + } + goto bad; + + case 32: /* casew */ + /* jmp (0,pc,r0.w*1) */ + casepc = p->pc; + *op++ = o->opcode1; + break; + + case 34: /* moves */ + op++; + a = asmea(p, &p->from); + b = a & 0170; + if(b == 0 || b == 010) { + opa[1] = (a << 12) | 0x800; + b = asmea(p, &p->to); + a = b & 0170; + if(a == 0 || a == 010) + goto bad; + t |= b; + break; + } + t |= a; + b = asmea(p, &p->to); + a = b & 0170; + if(a != 0 && a != 010) + goto bad; + opa[1] = (b << 12); + break; + + case 35: /* swap */ + a = asmea(p, &p->to); + if((a & 0170) == 0) { + t |= a; + break; + } + goto bad; + } + opa[0] = t; + return; + +bad: + if(!debug['a']) + print("%P\n", p); + diag("bad combination of addressing in %s", TNAME); + opa[0] = 0; +} + +int +asmea(Prog *p, Adr *a) +{ + Optab *o; + int f, t, r, i; + long v; + + t = a->type; + r = simple[t]; + v = a->offset; + if(r != 0177) { + if(v == 0) + return r; + if((r & 070) != 020) + return r; + if(v >= -32768L && v < 32768L) { + *op++ = v; + return t-D_A0-I_INDIR+050; /* d(Ax) */ + } + goto toobig; + } + f = 0; + if(a == &p->from) + f++; + o = &optab[p->as]; + switch(t) { + case D_TOS: + if(f) { + if(o->srcsp) + return (3<<3) | 7; /* (A7)+ */ + } else + if(o->dstsp) + return (4<<3) | 7; /* -(A7) */ + return (2<<3) | 7; /* (A7) */ + + case D_BRANCH: + v = p->pcond->pc - p->pc - 2; + if(v < -32768L || v >= 32768L) { + if(p->as == ABSR || p->as == ABRA) { + v = p->pcond->pc; + *op++ = v>>16; + *op++ = v; + return (7<<3) | 1; + } + goto toobig; + } + if(v < -128 || v >= 128 || p->mark == 4) { + *op++ = v; + return 0; + } + return v & 0xff; + + case I_ADDR|D_STATIC: + case I_ADDR|D_EXTERN: + t = a->sym->type; + if(t == 0 || t == SXREF) { + diag("undefined external: %s in %s", + a->sym->name, TNAME); + a->sym->type = SDATA; + } + v = a->sym->value + a->offset; + if(t != STEXT) + v += INITDAT; + if(strcmp(a->sym->name, "a6base")) + break; + + case D_CONST: + switch(f? o->srcsp: o->dstsp) { + case 4: + *op++ = v>>16; + + case 2: + *op++ = v; + break; + + default: + diag("unknown srcsp asmea in %s", TNAME); + } + return (7<<3) | 4; + + case D_FCONST: + r = f? o->srcsp: o->dstsp; + for(i=0; i<r; i++) + ((char*)op)[i] = gnuxi(&a->ieee, i, r); + op += r/2; + return (7<<3) | 4; + + case D_QUICK: + v = a->offset & 0xff; + return 0110 | (v<<7); + + case D_STACK: + case D_AUTO: + case D_PARAM: + if(v == 0) + return (2<<3) | 7; /* (A7) */ + if(v >= -32768L && v < 32768L) { + *op++ = v; + return (5<<3) | 7; /* d(A7) */ + } + goto toobig; + + case I_INDIR|D_CONST: + if(v >= -32768L && v < 32768L) { + *op++ = v; + return (7<<3) | 0; + } + *op++ = v>>16; + *op++ = v; + return (7<<3) | 1; + + case D_STATIC: + case D_EXTERN: + t = a->sym->type; + if(t == 0 || t == SXREF) { + diag("undefined external: %s in %s", + a->sym->name, TNAME); + a->sym->type = SDATA; + } + if(t == STEXT) { + if(HEADTYPE == 4) { + v = a->sym->value + a->offset - p->pc - 2; + if(v >= -32768L && v < 32768L) { + *op++ = v; + return (7<<3) | 2; + } + goto toobig; + } + v = a->sym->value + a->offset; + *op++ = v>>16; + *op++ = v; + return (7<<3) | 1; + } + v = a->sym->value + a->offset - A6OFFSET; + if(v < -32768L || v >= 32768L) { + v += INITDAT + A6OFFSET; + if(v >= -32768L && v < 32768L) { + *op++ = v; + return (7<<3) | 0; + } + *op++ = v>>16; + *op++ = v; + return (7<<3) | 1; + } + if(v == 0) + return (2<<3) | 6; + *op++ = v; + return (5<<3) | 6; + } + if(!debug['a']) + print("%P\n", p); + diag("unknown addressing mode: %d in %s", t, TNAME); + return 0; + +toobig: + if(!debug['a']) + print("%P\n", p); + diag("addressing mode >> 2^16: %d in %s", t, TNAME); + return 0; +} + +void +lput(long l) +{ + + CPUT(l>>24) + CPUT(l>>16) + CPUT(l>>8) + CPUT(l) +} + +void +s16put(char *n) +{ + char name[16]; + 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+100); + for(p = datap; p != P; p = p->link) { + curp = p; + l = p->from.sym->value + p->from.offset - s; + c = p->from.displace; + i = 0; + if(l < 0) { + if(l+c <= 0) + continue; + while(l < 0) { + l++; + i++; + } + } + if(l >= n) + continue; + 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, "%lux:%P\n\t\t", l+s+INITDAT, curp); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux", cast[fnuxi8[j+4]] & 0xff); + Bprint(&bso, "\n"); + } + for(; i<c; i++) { + buf.dbuf[l] = cast[fnuxi8[i+4]]; + l++; + } + break; + case 8: + cast = (char*)&p->to.ieee; + if(debug['a'] && i == 0) { + Bprint(&bso, "%lux:%P\n\t\t", l+s+INITDAT, curp); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff); + Bprint(&bso, "\n"); + } + for(; i<c; i++) { + buf.dbuf[l] = cast[fnuxi8[i]]; + l++; + } + break; + } + break; + + case D_SCONST: + if(debug['a'] && i == 0) { + Bprint(&bso, "%.4lux:%P\n\t\t", l+s+INITDAT, curp); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff); + Bprint(&bso, "\n"); + } + for(; i<c; i++) { + buf.dbuf[l] = p->to.scon[i]; + l++; + } + break; + default: + fl = p->to.offset; + if(p->to.sym) { + if(p->to.sym->type == STEXT) + fl += p->to.sym->value; + if(p->to.sym->type == SDATA) + fl += p->to.sym->value + INITDAT; + if(p->to.sym->type == SBSS) + fl += p->to.sym->value + INITDAT; + } + + 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, "%.4lux:%P\n\t\t", l+s+INITDAT, curp); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux",cast[inuxi1[j]] & 0xff); + Bprint(&bso, "\n"); + } + for(; i<c; i++) { + buf.dbuf[l] = cast[inuxi1[i]]; + l++; + } + break; + case 2: + if(debug['a'] && i == 0) { + Bprint(&bso, "%.4lux:%P\n\t\t", l+s+INITDAT, curp); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux",cast[inuxi2[j]] & 0xff); + Bprint(&bso, "\n"); + } + for(; i<c; i++) { + buf.dbuf[l] = cast[inuxi2[i]]; + l++; + } + break; + case 4: + if(debug['a'] && i == 0) { + Bprint(&bso, "%.4lux:%P\n\t\t", l+s+INITDAT, curp); + for(j=0; j<c; j++) + Bprint(&bso, "%.2ux",cast[inuxi4[j]] & 0xff); + Bprint(&bso, "\n"); + } + for(; i<c; i++) { + buf.dbuf[l] = cast[inuxi4[i]]; + l++; + } + break; + } + break; + } + } + write(cout, buf.dbuf, n); +} + +void +asmreloc(void) +{ + Prog *p; + Sym *s1, *s2; + int c1, c2, c3; + long v; + + if(HEADTYPE != 4) + return; + for(p = datap; p != P; p = p->link) { + curp = p; + s1 = p->to.sym; + if(s1 == S) + continue; + c1 = 'D'; + c3 = p->from.displace; + s2 = p->from.sym; + v = s2->value + INITDAT; + switch(s1->type) { + default: + diag("unknown reloc %d", s1->type); + continue; + case STEXT: + c2 = 'T'; + break; + + case SDATA: + c2 = 'D'; + break; + + case SBSS: + c2 = 'B'; + break; + } + CPUT(c1); + CPUT(c2); + CPUT(c3); + lput(v); + if(debug['a']) + Bprint(&bso, "r %c%c%d %.8lux %s $%s\n", + c1, c2, c3, v, s2->name, s1->name); + relocsize += 7; + } +} + +int +gnuxi(Ieee *d, int i, int c) +{ + char *p; + long l; + + switch(c) { + default: + diag("bad nuxi %d %d\n%P", c, i, curp); + return 0; + + /* + * 2301 vax + * 0123 68k + */ + case 4: + l = ieeedtof(d); + p = (char*)&l; + i = gnuxi8[i+4]; + break; + + /* + * 67452301 vax + * 45670123 68k + */ + case 8: + p = (char*)d; + i = gnuxi8[i]; + break; + } + return p[i]; +} + +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; +} diff --git a/sys/src/cmd/1l/compat.c b/sys/src/cmd/1l/compat.c new file mode 100755 index 000000000..d01de9b3f --- /dev/null +++ b/sys/src/cmd/1l/compat.c @@ -0,0 +1,50 @@ +#include "l.h" + +/* + * fake malloc + */ +void* +malloc(ulong n) +{ + void *p; + + while(n & 7) + n++; + while(nhunk < n) + gethunk(); + p = hunk; + nhunk -= n; + hunk += n; + return p; +} + +void +free(void *p) +{ + USED(p); +} + +void* +calloc(ulong m, ulong n) +{ + void *p; + + n *= m; + p = malloc(n); + memset(p, 0, n); + return p; +} + +void* +realloc(void *p, ulong n) +{ + fprint(2, "realloc(0x%p, %ld) called\n", p, n); + abort(); + return 0; +} + +void* +mysbrk(ulong size) +{ + return sbrk(size); +} diff --git a/sys/src/cmd/1l/cputime.c b/sys/src/cmd/1l/cputime.c new file mode 100755 index 000000000..3ef54a10e --- /dev/null +++ b/sys/src/cmd/1l/cputime.c @@ -0,0 +1,12 @@ +double +cputime(void) +{ + long t[4]; + long times(long*); + int i; + + times(t); + for(i=1; i<4; i++) + t[0] += t[i]; + return t[0] / 100.; +} diff --git a/sys/src/cmd/1l/l.h b/sys/src/cmd/1l/l.h new file mode 100755 index 000000000..41ec65685 --- /dev/null +++ b/sys/src/cmd/1l/l.h @@ -0,0 +1,271 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include "../2c/2.out.h" + +#ifndef EXTERN +#define EXTERN extern +#endif + +#define P ((Prog*)0) +#define S ((Sym*)0) +#define TNAME (curtext?curtext->from.sym->name:noname) +#define CPUT(c)\ + { *cbp++ = c;\ + if(--cbc <= 0)\ + cflush(); } + +typedef struct Adr Adr; +typedef struct Prog Prog; +typedef struct Sym Sym; +typedef struct Auto Auto; +typedef struct Optab Optab; + +struct Adr +{ + short type; + uchar field; + union + { + struct + { + long u0displace; + long u0offset; + } s0; + char u0scon[8]; + Prog *u0cond; /* not used, but should be D_BRANCH */ + Ieee u0ieee; + } u0; + union + { + Auto* u1autom; + Sym* u1sym; + } u1; +}; + +#define displace u0.s0.u0displace +#define offset u0.s0.u0offset +#define scon u0.u0scon +#define cond u0.u0cond +#define ieee u0.u0ieee + +#define autom u1.u1autom +#define sym u1.u1sym + +struct Prog +{ + Adr from; + Adr to; + union + { + long u0stkoff; + Prog *u0forwd; + } u0; + Prog* link; + Prog* pcond; /* work on this */ + long pc; + long line; + short as; + uchar mark; /* work on these */ + uchar back; +}; + +#define stkoff u0.u0stkoff +#define forwd u0.u0forwd + +struct Auto +{ + Sym* asym; + Auto* link; + long aoffset; + short type; +}; +struct Sym +{ + char *name; + short type; + short version; + short become; + short frame; + long value; + Sym* link; +}; +struct Optab +{ + short as; + short fas; + short srcsp; + short dstsp; + ushort optype; + ushort opcode0; + ushort opcode1; + ushort opcode2; + ushort opcode3; +}; + +enum +{ + STEXT = 1, + SDATA, + SBSS, + SDATA1, + SXREF, + SAUTO, + SPARAM, + SFILE, + NHASH = 10007, + NHUNK = 100000, + MINSIZ = 4, + STRINGSZ = 200, + MAXIO = 8192, + MAXHIST = 20, /* limit of path elements for history symbols */ + A6OFFSET = 32766, +}; + +EXTERN union +{ + struct + { + char obuf[MAXIO]; /* output buffer */ + uchar ibuf[MAXIO]; /* input buffer */ + } u; + char dbuf[1]; +} buf; + +#define cbuf u.obuf +#define xbuf u.ibuf + +#pragma varargck type "A" int +#pragma varargck type "D" Adr* +#pragma varargck type "P" Prog* +#pragma varargck type "R" int +#pragma varargck type "S" char* + +#pragma varargck argpos diag 1 + +EXTERN long HEADR; +EXTERN long HEADTYPE; +EXTERN long INITDAT; +EXTERN long INITRND; +EXTERN long INITTEXT; +EXTERN char* INITENTRY; /* entry point */ +EXTERN Biobuf bso; +EXTERN long bsssize; +EXTERN long casepc; +EXTERN int cbc; +EXTERN char* cbp; +EXTERN int cout; +EXTERN Auto* curauto; +EXTERN Auto* curhist; +EXTERN Prog* curp; +EXTERN Prog* curtext; +EXTERN Prog* datap; +EXTERN long datsize; +EXTERN char debug[128]; +EXTERN Prog* etextp; +EXTERN Prog* firstp; +EXTERN Prog* prog_divsl; +EXTERN Prog* prog_divul; +EXTERN Prog* prog_mull; +EXTERN Prog* prog_ccr; +EXTERN char fnuxi8[8]; +EXTERN char gnuxi8[8]; +EXTERN Sym* hash[NHASH]; +EXTERN Sym* histfrog[MAXHIST]; +EXTERN int histfrogp; +EXTERN int histgen; +EXTERN char* library[50]; +EXTERN char* libraryobj[50]; +EXTERN int libraryp; +EXTERN int xrefresolv; +EXTERN char* hunk; +EXTERN char inuxi1[1]; +EXTERN char inuxi2[2]; +EXTERN char inuxi4[4]; +EXTERN Prog* lastp; +EXTERN long lcsize; +EXTERN long relocsize; +EXTERN long ndata; +EXTERN int nerrors; +EXTERN long nhunk; +EXTERN long nsymbol; +EXTERN char* noname; +EXTERN short* op; +EXTERN char* outfile; +EXTERN long pc; +EXTERN char simple[I_MASK]; +EXTERN char special[I_MASK]; +EXTERN long spsize; +EXTERN Sym* symlist; +EXTERN long symsize; +EXTERN Prog* textp; +EXTERN long textsize; +EXTERN long thunk; +EXTERN int version; +EXTERN Prog zprg; + +extern Optab optab[]; +extern char mmsize[]; +extern char* anames[]; + +int Aconv(Fmt*); +int Dconv(Fmt*); +int Pconv(Fmt*); +int Rconv(Fmt*); +int Sconv(Fmt*); +int Xconv(Fmt*); +void addhist(long, int); +int andsize(Prog*, Adr*); +void asmb(void); +int asmea(Prog*, Adr*); +void asmins(Prog*); +void asmlc(void); +void asmsp(void); +void asmsym(void); +void asmreloc(void); +long atolwhex(char*); +Prog* brchain(Prog*); +Prog* brloop(Prog*); +void cflush(void); +Prog* copyp(Prog*); +double cputime(void); +void datblk(long, long); +void diag(char*, ...); +void dodata(void); +void doprof1(void); +void doprof2(void); +void dostkoff(void); +long entryvalue(void); +void errorexit(void); +int find1(long, int); +int find2(long, int); +void follow(void); +void gethunk(void); +int gnuxi(Ieee*, int, int); +void histtoauto(void); +double ieeedtod(Ieee*); +long ieeedtof(Ieee*); +void initmuldiv1(void); +void initmuldiv2(void); +void ldobj(int, long, char*); +void loadlib(void); +void listinit(void); +Sym* lookup(char*, int); +void lput(long); +void main(int, char*[]); +void mkfwd(void); +void* mysbrk(ulong); +void nuxiinit(void); +void objfile(char*); +void patch(void); +Prog* prg(void); +Prog* nprg(Prog*); +int relinv(int); +long reuse(Prog*, Sym*); +long rnd(long, long); +void s16put(char*); +void span(void); +void undef(void); +void xdefine(char*, int, long); +void xfol(Prog*); +int zaddr(uchar*, Adr*, Sym*[]); diff --git a/sys/src/cmd/1l/list.c b/sys/src/cmd/1l/list.c new file mode 100755 index 000000000..f02c3efa7 --- /dev/null +++ b/sys/src/cmd/1l/list.c @@ -0,0 +1,334 @@ +#include "l.h" + +void +listinit(void) +{ + + fmtinstall('R', Rconv); + fmtinstall('A', Aconv); + fmtinstall('D', Dconv); + fmtinstall('S', Sconv); + fmtinstall('P', Pconv); +} + +static Prog *bigP; + +int +Pconv(Fmt *fp) +{ + char str[STRINGSZ], s[20]; + Prog *p; + + p = va_arg(fp->args, Prog*); + bigP = p; + sprint(str, "(%ld) %A %D,%D", + p->line, p->as, &p->from, &p->to); + if(p->from.field) { + sprint(s, ",%d,%d", p->to.field, p->from.field); + strcat(str, s); + } + bigP = P; + return fmtstrcpy(fp, str); +} + +int +Aconv(Fmt *fp) +{ + + return fmtstrcpy(fp, anames[va_arg(fp->args, int)]); +} + +int +Dconv(Fmt *fp) +{ + char str[40], s[20]; + Adr *a; + int i, j; + long d; + + a = va_arg(fp->args, Adr*); + i = a->type; + j = i & I_MASK; + if(j) { + a->type = i & D_MASK; + d = a->offset; + a->offset = 0; + switch(j) { + case I_INDINC: + sprint(str, "(%D)+", a); + break; + + case I_INDDEC: + sprint(str, "-(%D)", a); + break; + + case I_INDIR: + if(d) + sprint(str, "%ld(%D)", d, a); + else + sprint(str, "(%D)", a); + break; + + case I_ADDR: + a->offset = d; + sprint(str, "$%D", a); + break; + } + a->type = i; + a->offset = d; + goto out; + } + switch(i) { + + default: + sprint(str, "%R", i); + break; + + case D_NONE: + str[0] = 0; + break; + + case D_BRANCH: + if(bigP != P && bigP->pcond != P) + if(a->sym != S) + sprint(str, "%lux+%s", bigP->pcond->pc, + a->sym->name); + else + sprint(str, "%lux", bigP->pcond->pc); + else + sprint(str, "%ld(PC)", a->offset); + break; + + case D_EXTERN: + sprint(str, "%s+%ld(SB)", a->sym->name, a->offset); + break; + + case D_STATIC: + sprint(str, "%s<%d>+%ld(SB)", a->sym->name, + a->sym->version, a->offset); + break; + + case D_AUTO: + sprint(str, "%s+%ld(SP)", a->sym->name, a->offset); + break; + + case D_PARAM: + if(a->sym) + sprint(str, "%s+%ld(FP)", a->sym->name, a->offset); + else + sprint(str, "%ld(FP)", a->offset); + break; + + case D_CONST: + sprint(str, "$%ld", a->offset); + break; + + case D_STACK: + sprint(str, "TOS+%ld", a->offset); + break; + + case D_QUICK: + sprint(str, "$Q%ld", a->offset); + break; + + case D_FCONST: + sprint(str, "$(%.8lux,%.8lux)", a->ieee.h, a->ieee.l); + goto out; + + case D_SCONST: + sprint(str, "$\"%S\"", a->scon); + goto out; + } + if(a->displace) { + sprint(s, "/%ld", a->displace); + strcat(str, s); + } +out: + return fmtstrcpy(fp, str); +} + +int +Rconv(Fmt *fp) +{ + char str[20]; + int r; + + r = va_arg(fp->args, int); + if(r >= D_R0 && r < D_R0+NREG) + sprint(str, "R%d", r-D_R0); + else + if(r >= D_A0 && r < D_A0+NREG) + sprint(str, "A%d", r-D_A0); + else + if(r >= D_F0 && r < D_F0+NREG) + sprint(str, "F%d", r-D_F0); + else + switch(r) { + + default: + sprint(str, "gok(%d)", r); + break; + + case D_NONE: + sprint(str, "NONE"); + break; + + case D_TOS: + sprint(str, "TOS"); + break; + + case D_CCR: + sprint(str, "CCR"); + break; + + case D_SR: + sprint(str, "SR"); + break; + + case D_SFC: + sprint(str, "SFC"); + break; + + case D_DFC: + sprint(str, "DFC"); + break; + + case D_CACR: + sprint(str, "CACR"); + break; + + case D_USP: + sprint(str, "USP"); + break; + + case D_VBR: + sprint(str, "VBR"); + break; + + case D_CAAR: + sprint(str, "CAAR"); + break; + + case D_MSP: + sprint(str, "MSP"); + break; + + case D_ISP: + sprint(str, "ISP"); + break; + + case D_FPCR: + sprint(str, "FPCR"); + break; + + case D_FPSR: + sprint(str, "FPSR"); + break; + + case D_FPIAR: + sprint(str, "FPIAR"); + break; + + case D_TREE: + sprint(str, "TREE"); + break; + + case D_TC: + sprint(str, "TC"); + break; + + case D_ITT0: + sprint(str, "ITT0"); + break; + + case D_ITT1: + sprint(str, "ITT1"); + break; + + case D_DTT0: + sprint(str, "DTT0"); + break; + + case D_DTT1: + sprint(str, "DTT1"); + break; + + case D_MMUSR: + sprint(str, "MMUSR"); + break; + case D_URP: + sprint(str, "URP"); + break; + + case D_SRP: + sprint(str, "SRP"); + break; + } + return fmtstrcpy(fp, str); +} + +int +Sconv(Fmt *fp) +{ + int i, c; + char str[30], *p, *a; + + a = va_arg(fp->args, char*); + p = str; + for(i=0; i<sizeof(double); i++) { + c = a[i] & 0xff; + if(c >= 'a' && c <= 'z' || + c >= 'A' && c <= 'Z' || + c >= '0' && c <= '9') { + *p++ = c; + continue; + } + *p++ = '\\'; + switch(c) { + default: + if(c < 040 || c >= 0177) + break; /* not portable */ + p[-1] = c; + continue; + case 0: + *p++ = 'z'; + continue; + case '\\': + case '"': + *p++ = c; + continue; + case '\n': + *p++ = 'n'; + continue; + case '\t': + *p++ = 't'; + continue; + } + *p++ = (c>>6) + '0'; + *p++ = ((c>>3) & 7) + '0'; + *p++ = (c & 7) + '0'; + } + *p = 0; + return fmtstrcpy(fp, str); +} + +void +diag(char *fmt, ...) +{ + char buf[STRINGSZ], *tn; + va_list arg; + + tn = "??none??"; + if(curtext != P && curtext->from.sym != S) + tn = curtext->from.sym->name; + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + print("%s: %s\n", tn, buf); + + nerrors++; + if(nerrors > 10) { + print("too many errors\n"); + errorexit(); + } +} diff --git a/sys/src/cmd/1l/mkfile b/sys/src/cmd/1l/mkfile new file mode 100755 index 000000000..c56fcb5e6 --- /dev/null +++ b/sys/src/cmd/1l/mkfile @@ -0,0 +1,22 @@ +</$objtype/mkfile + +TARG=1l +OFILES=\ + asm.$O\ + obj.$O\ + optab.$O\ + pass.$O\ + span.$O\ + list.$O\ + enam.$O\ + compat.$O\ + +HFILES=\ + l.h\ + ../2c/2.out.h\ + +BIN=/$objtype/bin +</sys/src/cmd/mkone + +enam.$O: ../2c/enam.c + $CC $CFLAGS ../2c/enam.c diff --git a/sys/src/cmd/1l/obj.c b/sys/src/cmd/1l/obj.c new file mode 100755 index 000000000..0622ba37a --- /dev/null +++ b/sys/src/cmd/1l/obj.c @@ -0,0 +1,1413 @@ +#define EXTERN +#include "l.h" +#include <ar.h> + +#ifndef DEFAULT +#define DEFAULT '9' +#endif + +char symname[] = SYMDEF; +char thechar = '1'; +char *thestring = "68000"; + +/* + * -H0 -T0x40004C -D0x10000000 is garbage unix + * -H1 -T0x80020000 -R4 is garbage format + * -H2 -T8224 -R8192 is plan9 format + * -H3 -Tx -Rx is next boot + * -H4 -T0 -D0 is pilot relocatable + */ + +void +main(int argc, char *argv[]) +{ + int i, c; + char *a; + + Binit(&bso, 1, OWRITE); + cout = -1; + listinit(); + memset(debug, 0, sizeof(debug)); + nerrors = 0; + outfile = "1.out"; + HEADTYPE = -1; + INITTEXT = -1; + INITDAT = -1; + INITRND = -1; + INITENTRY = 0; + + ARGBEGIN { + default: + c = ARGC(); + if(c >= 0 && c < sizeof(debug)) + debug[c]++; + break; + case 'o': /* output to (next arg) */ + outfile = ARGF(); + break; + case 'E': + a = ARGF(); + if(a) + INITENTRY = a; + break; + case 'H': + a = ARGF(); + if(a) + HEADTYPE = atolwhex(a); + break; + case 'T': + a = ARGF(); + if(a) + INITTEXT = atolwhex(a); + break; + case 'D': + a = ARGF(); + if(a) + INITDAT = atolwhex(a); + break; + case 'R': + a = ARGF(); + if(a) + INITRND = atolwhex(a); + break; + } ARGEND + + USED(argc); + + if(*argv == 0) { + diag("usage: 1l [-options] objects"); + errorexit(); + } + if(!debug['9'] && !debug['U'] && !debug['B']) + debug[DEFAULT] = 1; + if(HEADTYPE == -1) { + if(debug['U']) + HEADTYPE = 2; + if(debug['B']) + HEADTYPE = 2; + if(debug['9']) + HEADTYPE = 2; + } + if(INITDAT != -1 && INITRND == -1) + INITRND = 0; + switch(HEADTYPE) { + default: + diag("unknown -H option %ld", HEADTYPE); + errorexit(); + + case 0: /* this is garbage */ + HEADR = 20L+56L; + if(INITTEXT == -1) + INITTEXT = 0x40004CL; + if(INITDAT == -1) + INITDAT = 0x10000000L; + if(INITDAT != 0 && INITRND == -1) + INITRND = 0; + if(INITRND == -1) + INITRND = 0; + break; + case 1: /* plan9 boot data goes into text */ + HEADR = 32L; + if(INITTEXT == -1) + INITTEXT = 8224; + if(INITDAT == -1) + INITDAT = 0; + if(INITDAT != 0 && INITRND == -1) + INITRND = 0; + if(INITRND == -1) + INITRND = 8192; + break; + case 2: /* plan 9 */ + HEADR = 32L; + if(INITTEXT == -1) + INITTEXT = 8224; + if(INITDAT == -1) + INITDAT = 0; + if(INITDAT != 0 && INITRND == -1) + INITRND = 0; + if(INITRND == -1) + INITRND = 8192; + break; + case 3: /* next boot */ + HEADR = 28+124+192+24; + if(INITTEXT == -1) + INITTEXT = 0x04002000; + if(INITDAT == -1) + INITDAT = 0; + if(INITDAT != 0 && INITRND == -1) + INITRND = 0; + if(INITRND == -1) + INITRND = 8192L; + break; + case 4: /* preprocess pilot */ + HEADR = 36L; + if(INITTEXT == -1) + INITTEXT = 0; + if(INITDAT == -1) + INITDAT = 0; + if(INITRND == -1) + INITRND = 0; + break; + } + if(INITDAT != 0 && INITRND != 0) + print("warning: -D0x%lux is ignored because of -R0x%lux\n", + INITDAT, INITRND); + if(debug['v']) + Bprint(&bso, "HEADER = -H0x%ld -T0x%lux -D0x%lux -R0x%lux\n", + HEADTYPE, INITTEXT, INITDAT, INITRND); + Bflush(&bso); + for(i=1; optab[i].as; i++) + if(i != optab[i].as) { + diag("phase error in optab: %d", i); + errorexit(); + } + + zprg.link = P; + zprg.pcond = P; + zprg.back = 2; + zprg.as = AGOK; + zprg.from.type = D_NONE; + zprg.to = zprg.from; + + memset(special, 0, sizeof(special)); + special[D_CCR] = 1; + special[D_SR] = 1; + special[D_SFC] = 1; + special[D_CACR] = 1; + special[D_USP] = 1; + special[D_VBR] = 1; + special[D_CAAR] = 1; + special[D_MSP] = 1; + special[D_ISP] = 1; + special[D_DFC] = 1; + special[D_FPCR] = 1; + special[D_FPSR] = 1; + special[D_FPIAR] = 1; + special[D_TC] = 1; + special[D_ITT0] = 1; + special[D_ITT1] = 1; + special[D_DTT0] = 1; + special[D_DTT1] = 1; + special[D_MMUSR] = 1; + special[D_URP] = 1; + special[D_SRP] = 1; + memset(simple, 0177, sizeof(simple)); + for(i=0; i<8; i++) { + simple[D_R0+i] = i; + simple[D_F0+i] = i+0100; + simple[D_A0+i] = i+010; + simple[D_A0+I_INDIR+i] = i+020; + simple[D_A0+I_INDINC+i] = i+030; + simple[D_A0+I_INDDEC+i] = i+040; + } + nuxiinit(); + histgen = 0; + textp = P; + datap = P; + pc = 0; + cout = create(outfile, 1, 0775); + if(cout < 0) { + diag("cannot create %s", outfile); + errorexit(); + } + version = 0; + cbp = buf.cbuf; + cbc = sizeof(buf.cbuf); + firstp = prg(); + lastp = firstp; + + if(INITENTRY == 0) { + INITENTRY = "_main"; + if(debug['p']) + INITENTRY = "_mainp"; + if(!debug['l']) + lookup(INITENTRY, 0)->type = SXREF; + } else + lookup(INITENTRY, 0)->type = SXREF; + + initmuldiv1(); + while(*argv) + objfile(*argv++); + if(!debug['l']) + loadlib(); + firstp = firstp->link; + if(firstp == P) + errorexit(); + patch(); + if(debug['p']) + if(debug['1']) + doprof1(); + else + doprof2(); + initmuldiv2(); + follow(); + dodata(); + dostkoff(); + span(); + asmb(); + undef(); + if(debug['v']) { + Bprint(&bso, "%5.2f cpu time\n", cputime()); + Bprint(&bso, "%ld data statements\n", ndata); + Bprint(&bso, "%ld symbols\n", nsymbol); + Bprint(&bso, "%ld memory used\n", thunk); + Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); + Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); + } + Bflush(&bso); + + errorexit(); +} + +void +loadlib(void) +{ + int i; + long h; + Sym *s; + +loop: + xrefresolv = 0; + for(i=0; i<libraryp; i++) { + if(debug['v']) + Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]); + objfile(library[i]); + } + if(xrefresolv) + for(h=0; h<nelem(hash); h++) + for(s = hash[h]; s != S; s = s->link) + if(s->type == SXREF) + goto loop; +} + +void +errorexit(void) +{ + + if(nerrors) { + if(cout >= 0) + remove(outfile); + exits("error"); + } + exits(0); +} + +void +objfile(char *file) +{ + long off, esym, cnt, l; + int f, work; + Sym *s; + char magbuf[SARMAG]; + char name[100], pname[150]; + struct ar_hdr arhdr; + char *e, *start, *stop; + + if(file[0] == '-' && file[1] == 'l') { + sprint(name, "/%s/lib/lib", thestring); + strcat(name, file+2); + strcat(name, ".a"); + file = name; + } + if(debug['v']) + Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file); + Bflush(&bso); + f = open(file, 0); + if(f < 0) { + diag("cannot open file: %s", file); + errorexit(); + } + l = read(f, magbuf, SARMAG); + if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){ + /* load it as a regular file */ + l = seek(f, 0L, 2); + seek(f, 0L, 0); + ldobj(f, l, file); + close(f); + return; + } + + l = read(f, &arhdr, SAR_HDR); + if(l != SAR_HDR) { + diag("%s: short read on archive file symbol header", file); + goto out; + } + if(strncmp(arhdr.name, symname, strlen(symname))) { + diag("%s: first entry not symbol header", file); + goto out; + } + + esym = SARMAG + SAR_HDR + atolwhex(arhdr.size); + off = SARMAG + SAR_HDR; + + /* + * just bang the whole symbol file into memory + */ + seek(f, off, 0); + cnt = esym - off; + start = malloc(cnt + 10); + cnt = read(f, start, cnt); + if(cnt <= 0){ + close(f); + return; + } + stop = &start[cnt]; + memset(stop, 0, 10); + + work = 1; + while(work){ + if(debug['v']) + Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file); + Bflush(&bso); + work = 0; + for(e = start; e < stop; e = strchr(e+5, 0) + 1) { + s = lookup(e+5, 0); + if(s->type != SXREF) + continue; + sprint(pname, "%s(%s)", file, s->name); + if(debug['v']) + Bprint(&bso, "%5.2f library: %s\n", cputime(), pname); + Bflush(&bso); + l = e[1] & 0xff; + l |= (e[2] & 0xff) << 8; + l |= (e[3] & 0xff) << 16; + l |= (e[4] & 0xff) << 24; + seek(f, l, 0); + l = read(f, &arhdr, SAR_HDR); + if(l != SAR_HDR) + goto bad; + if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag))) + goto bad; + l = atolwhex(arhdr.size); + ldobj(f, l, pname); + if(s->type == SXREF) { + diag("%s: failed to load: %s", file, s->name); + errorexit(); + } + work = 1; + xrefresolv = 1; + } + } + return; + +bad: + diag("%s: bad or out of date archive", file); +out: + close(f); +} + +int +zaddr(uchar *p, Adr *a, Sym *h[]) +{ + int c, t, i; + long l; + Sym *s; + Auto *u; + + t = p[0]; + + /* + * first try the high-time formats + */ + if(t == 0) { + a->type = p[1]; + return 2; + } + if(t == T_OFFSET) { + a->offset = p[1] | (p[2]<<8) | (p[3]<<16) | (p[4]<<24); + a->type = p[5]; + return 6; + } + if(t == (T_OFFSET|T_SYM)) { + a->offset = p[1] | (p[2]<<8) | (p[3]<<16) | (p[4]<<24); + s = h[p[5]]; + a->sym = s; + a->type = p[6]; + c = 7; + goto dosym; + } + if(t == T_SYM) { + s = h[p[1]]; + a->sym = s; + a->type = p[2]; + c = 3; + goto dosym; + } + if(t == (T_INDEX|T_OFFSET|T_SYM)) { + a->displace = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24); + a->offset = p[8] | (p[9]<<8) | (p[10]<<16) | (p[11]<<24); + s = h[p[12]]; + a->sym = s; + a->type = p[13]; + c = 14; + goto dosym; + } + + /* + * now do it the hard way + */ + c = 1; + if(t & T_FIELD) { + a->field = p[c] | (p[c+1]<<8); + c += 2; + } + if(t & T_INDEX) { + a->displace = p[c+3] | (p[c+4]<<8) | (p[c+5]<<16) | (p[c+6]<<24); + c += 7; + } + if(t & T_OFFSET) { + a->offset = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); + c += 4; + } + if(t & T_SYM) { + a->sym = h[p[c]]; + c += 1; + } + if(t & T_FCONST) { + a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); + a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24); + c += 8; + a->type = D_FCONST; + } else + if(t & T_SCONST) { + for(i=0; i<NSNAME; i++) + a->scon[i] = p[c+i]; + c += NSNAME; + a->type = D_SCONST; + } else + if(t & T_TYPE) { + a->type = p[c] | (p[c+1]<<8); + c += 2; + } else { + a->type = p[c]; + c++; + } + s = a->sym; + if(s == S) + return c; + +dosym: + t = a->type & D_MASK; + if(t != D_AUTO && t != D_PARAM) + return c; + l = a->offset; + for(u=curauto; u; u=u->link) { + if(u->asym == s) + if(u->type == t) { + if(u->aoffset > l) + u->aoffset = l; + return c; + } + } + + while(nhunk < sizeof(Auto)) + gethunk(); + u = (Auto*)hunk; + nhunk -= sizeof(Auto); + hunk += sizeof(Auto); + + u->link = curauto; + curauto = u; + u->asym = s; + u->aoffset = l; + u->type = t; + return c; +} + +void +addlib(char *obj) +{ + char name[1024], comp[256], *p; + int i; + + if(histfrogp <= 0) + return; + + if(histfrog[0]->name[1] == '/') { + sprint(name, ""); + i = 1; + } else + if(histfrog[0]->name[1] == '.') { + sprint(name, "."); + i = 0; + } else { + if(debug['9']) + sprint(name, "/%s/lib", thestring); + else + sprint(name, "/usr/%clib", thechar); + i = 0; + } + + for(; i<histfrogp; i++) { + snprint(comp, sizeof comp, histfrog[i]->name+1); + for(;;) { + p = strstr(comp, "$O"); + if(p == 0) + break; + memmove(p+1, p+2, strlen(p+2)+1); + p[0] = thechar; + } + for(;;) { + p = strstr(comp, "$M"); + if(p == 0) + break; + if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) { + diag("library component too long"); + return; + } + memmove(p+strlen(thestring), p+2, strlen(p+2)+1); + memmove(p, thestring, strlen(thestring)); + } + if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) { + diag("library component too long"); + return; + } + strcat(name, "/"); + strcat(name, comp); + } + for(i=0; i<libraryp; i++) + if(strcmp(name, library[i]) == 0) + return; + if(libraryp == nelem(library)){ + diag("too many autolibs; skipping %s", name); + return; + } + + p = malloc(strlen(name) + 1); + strcpy(p, name); + library[libraryp] = p; + p = malloc(strlen(obj) + 1); + strcpy(p, obj); + libraryobj[libraryp] = p; + libraryp++; +} +void +addhist(long line, int type) +{ + Auto *u; + Sym *s; + int i, j, k; + + u = malloc(sizeof(Auto)); + s = malloc(sizeof(Sym)); + s->name = malloc(2*(histfrogp+1) + 1); + + u->asym = s; + u->type = type; + u->aoffset = line; + u->link = curhist; + curhist = u; + + j = 1; + for(i=0; i<histfrogp; i++) { + k = histfrog[i]->value; + s->name[j+0] = k>>8; + s->name[j+1] = k; + j += 2; + } +} + +void +histtoauto(void) +{ + Auto *l; + + while(l = curhist) { + curhist = l->link; + l->link = curauto; + curauto = l; + } +} + +void +collapsefrog(Sym *s) +{ + int i; + + /* + * bad encoding of path components only allows + * MAXHIST components. if there is an overflow, + * first try to collapse xxx/.. + */ + for(i=1; i<histfrogp; i++) + if(strcmp(histfrog[i]->name+1, "..") == 0) { + memmove(histfrog+i-1, histfrog+i+1, + (histfrogp-i-1)*sizeof(histfrog[0])); + histfrogp--; + goto out; + } + + /* + * next try to collapse . + */ + for(i=0; i<histfrogp; i++) + if(strcmp(histfrog[i]->name+1, ".") == 0) { + memmove(histfrog+i, histfrog+i+1, + (histfrogp-i-1)*sizeof(histfrog[0])); + goto out; + } + + /* + * last chance, just truncate from front + */ + memmove(histfrog+0, histfrog+1, + (histfrogp-1)*sizeof(histfrog[0])); + +out: + histfrog[histfrogp-1] = s; +} + +uchar* +readsome(int f, uchar *buf, uchar *good, uchar *stop, int max) +{ + int n; + + n = stop - good; + memmove(buf, good, stop - good); + stop = buf + n; + n = MAXIO - n; + if(n > max) + n = max; + n = read(f, stop, n); + if(n <= 0) + return 0; + return stop + n; +} + +void +ldobj(int f, long c, char *pn) +{ + Prog *p; + Sym *h[NSYM], *s; + int v, o, r; + long ipc, lv; + double dv; + uchar *bloc, *bsize, *stop; + + bsize = buf.xbuf; + bloc = buf.xbuf; + +newloop: + memset(h, 0, sizeof(h)); + version++; + histfrogp = 0; + ipc = pc; + +loop: + if(c <= 0) + goto eof; + r = bsize - bloc; + if(r < 100 && r < c) { /* enough for largest prog */ + bsize = readsome(f, buf.xbuf, bloc, bsize, c); + if(bsize == 0) + goto eof; + bloc = buf.xbuf; + goto loop; + } + o = bloc[0] | (bloc[1] << 8); + if(o <= AXXX || o >= ALAST) { + if(o < 0) + goto eof; + diag("%s: opcode out of range %d", pn, o); + print(" probably not a .%c file\n", thechar); + errorexit(); + } + + if(o == ANAME || o == ASIGNAME) { + if(o == ASIGNAME) { + bloc += 4; + c -= 4; + } + stop = memchr(&bloc[4], 0, bsize-&bloc[4]); + if(stop == 0){ + bsize = readsome(f, buf.xbuf, bloc, bsize, c); + if(bsize == 0) + goto eof; + bloc = buf.xbuf; + stop = memchr(&bloc[4], 0, bsize-&bloc[4]); + if(stop == 0){ + fprint(2, "%s: name too long\n", pn); + errorexit(); + } + } + v = bloc[2]; /* type */ + o = bloc[3]; /* sym */ + bloc += 4; + c -= 4; + + r = 0; + if(v == D_STATIC) + r = version; + s = lookup((char*)bloc, r); + c -= &stop[1] - bloc; + bloc = stop + 1; + + if(debug['W']) + print(" ANAME %s\n", s->name); + h[o] = s; + if((v == D_EXTERN || v == D_STATIC) && s->type == 0) + s->type = SXREF; + if(v == D_FILE) { + if(s->type != SFILE) { + histgen++; + s->type = SFILE; + s->value = histgen; + } + if(histfrogp < MAXHIST) { + histfrog[histfrogp] = s; + histfrogp++; + } else + collapsefrog(s); + } + goto loop; + } + + while(nhunk < sizeof(Prog)) + gethunk(); + p = (Prog*)hunk; + nhunk -= sizeof(Prog); + hunk += sizeof(Prog); + + p->as = o; + p->line = bloc[2] | (bloc[3] << 8) | (bloc[4] << 16) | (bloc[5] << 24); + p->back = 2; + r = zaddr(bloc+6, &p->from, h) + 6; + r += zaddr(bloc+r, &p->to, h); + bloc += r; + c -= r; + + if(debug['W']) + print("%P\n", p); + + switch(p->as) { + case AHISTORY: + if(p->to.offset == -1) { + addlib(pn); + histfrogp = 0; + goto loop; + } + addhist(p->line, D_FILE); /* 'z' */ + if(p->to.offset) + addhist(p->to.offset, D_FILE1); /* 'Z' */ + histfrogp = 0; + goto loop; + + case AEND: + histtoauto(); + if(curtext != P) + curtext->to.autom = curauto; + curauto = 0; + curtext = P; + if(c) + goto newloop; + return; + + case AGLOBL: + s = p->from.sym; + if(s->type == 0 || s->type == SXREF) { + s->type = SBSS; + s->value = 0; + } + if(s->type != SBSS) { + diag("%s: redefinition: %s in %s", + pn, s->name, TNAME); + s->type = SBSS; + s->value = 0; + } + if(p->to.offset > s->value) + s->value = p->to.offset; + goto loop; + + case ADATA: + p->link = datap; + datap = p; + ndata++; + goto loop; + + case AGOK: + diag("%s: unknown opcode in %s", pn, TNAME); + pc++; + goto loop; + + case ATEXT: + if(curtext != P) { + histtoauto(); + curtext->to.autom = curauto; + curauto = 0; + } + curtext = p; + lastp->link = p; + lastp = p; + p->pc = pc; + s = p->from.sym; + if(s->type != 0 && s->type != SXREF) + diag("%s: redefinition: %s", pn, s->name); + s->type = STEXT; + s->value = p->pc; + pc++; + p->pcond = P; + if(textp == P) { + textp = p; + etextp = p; + goto loop; + } + etextp->pcond = p; + etextp = p; + goto loop; + + case AJSR: + p->as = ABSR; + + case ABSR: + if(p->to.type != D_EXTERN && p->to.type != D_STATIC) + p->as = AJSR; + goto casdef; + + case AMOVL: + case AMOVB: + case AMOVW: + if(p->from.type != D_CONST) + goto casdef; + lv = p->from.offset; + if(lv >= -128 && lv < 128) + if(p->to.type >= D_R0 && p->to.type < D_R0+8) { + p->from.type = D_QUICK; + goto casdef; + } + + if(lv >= -0x7fff && lv <= 0x7fff) + if(p->to.type >= D_A0 && p->to.type < D_A0+8) + if(p->as == AMOVL) + p->as = AMOVW; + goto casdef; + + case AADDB: + case AADDL: + case AADDW: + if(p->from.type != D_CONST) + goto casdef; + lv = p->from.offset; + if(lv < 0) { + lv = -lv; + p->from.offset = lv; + if(p->as == AADDB) + p->as = ASUBB; + else + if(p->as == AADDW) + p->as = ASUBW; + else + if(p->as == AADDL) + p->as = ASUBL; + } + if(lv > 0) + if(lv <= 8) + p->from.type = D_QUICK; + goto casdef; + + case ASUBB: + case ASUBL: + case ASUBW: + if(p->from.type != D_CONST) + goto casdef; + lv = p->from.offset; + if(lv < 0) { + lv = -lv; + p->from.offset = lv; + if(p->as == ASUBB) + p->as = AADDB; + else + if(p->as == ASUBW) + p->as = AADDW; + else + if(p->as == ASUBL) + p->as = AADDL; + } + if(lv > 0) + if(lv <= 8) + p->from.type = D_QUICK; + goto casdef; + + case AROTRB: + case AROTRL: + case AROTRW: + case AROTLB: + case AROTLL: + case AROTLW: + + case AASLB: + case AASLL: + case AASLW: + case AASRB: + case AASRL: + case AASRW: + case ALSLB: + case ALSLL: + case ALSLW: + case ALSRB: + case ALSRL: + case ALSRW: + if(p->from.type == D_CONST) + if(p->from.offset > 0) + if(p->from.offset <= 8) + p->from.type = D_QUICK; + goto casdef; + + case ATSTL: + if(p->to.type >= D_A0 && p->to.type < D_A0+8) { + p->as = ACMPW; + p->from = p->to; + p->to.type = D_CONST; + p->to.offset = 0; + } + goto casdef; + + case ACMPL: + if(p->to.type != D_CONST) + goto casdef; + lv = p->to.offset; + if(lv >= -0x7fff && lv <= 0x7fff) + if(p->from.type >= D_A0 && p->from.type < D_A0+8) + p->as = ACMPW; + goto casdef; + + case ACLRL: + if(p->to.type >= D_A0 && p->to.type < D_A0+8) { + p->as = AMOVW; + p->from.type = D_CONST; + p->from.offset = 0; + } + goto casdef; + + casdef: + default: + if(p->from.type == D_FCONST) + if(optab[p->as].fas != AXXX) { + dv = ieeedtod(&p->from.ieee); + if(dv >= -(1L<<30) && dv <= (1L<<30)) { + lv = dv; + if(lv == dv) { + p->as = optab[p->as].fas; + p->from.type = D_CONST; + p->from.offset = lv; + p->from.displace = 0; + } + } + } + if(p->to.type == D_BRANCH) + p->to.offset += ipc; + lastp->link = p; + lastp = p; + p->pc = pc; + pc++; + goto loop; + } + /* not reached */ + +eof: + diag("%s: truncated object file in %s", pn, TNAME); +} + +Sym* +lookup(char *symb, int v) +{ + Sym *s; + char *p; + long h; + int l, c; + + h = v; + for(p=symb; c = *p; p++) + h = h+h+h + c; + l = (p - symb) + 1; + if(h < 0) + h = ~h; + h %= NHASH; + for(s = hash[h]; s != S; s = s->link) + if(s->version == v) + if(memcmp(s->name, symb, l) == 0) + return s; + + while(nhunk < sizeof(Sym)) + gethunk(); + s = (Sym*)hunk; + nhunk -= sizeof(Sym); + hunk += sizeof(Sym); + + s->name = malloc(l + 1); + memmove(s->name, symb, l); + + s->link = hash[h]; + s->type = 0; + s->version = v; + s->value = 0; + hash[h] = s; + nsymbol++; + return s; +} + +Prog* +prg(void) +{ + Prog *p; + + while(nhunk < sizeof(Prog)) + gethunk(); + p = (Prog*)hunk; + nhunk -= sizeof(Prog); + hunk += sizeof(Prog); + + *p = zprg; + return p; +} + +Prog* +nprg(Prog *p) +{ + Prog *q; + + q = prg(); + q->line = p->line; + q->pc = p->pc; + q->stkoff = p->stkoff; + q->link = p->link; + p->link = q; + return q; +} + +Prog* +copyp(Prog *q) +{ + Prog *p; + + p = prg(); + *p = *q; + return p; +} + +void +gethunk(void) +{ + char *h; + long nh; + + nh = NHUNK; + if(thunk >= 5L*NHUNK) { + nh = 5L*NHUNK; + if(thunk >= 25L*NHUNK) + nh = 25L*NHUNK; + } + h = mysbrk(nh); + if(h == (char*)-1) { + diag("out of memory"); + errorexit(); + } + hunk = h; + nhunk = nh; + thunk += nh; +} + +void +doprof1(void) +{ + Sym *s; + long n; + Prog *p, *q; + + if(debug['v']) + Bprint(&bso, "%5.2f profile 1\n", cputime()); + Bflush(&bso); + s = lookup("__mcount", 0); + n = 1; + for(p = firstp->link; p != P; p = p->link) { + if(p->as == ATEXT) { + q = prg(); + q->as = AADDL; + q->line = p->line; + q->pc = p->pc; + q->link = p->link; + p->link = q; + q->from.type = D_CONST; + q->from.offset = 1; + q->to.type = D_EXTERN; + q->to.sym = s; + q->to.offset = n*4 + 4; + + q = prg(); + q->as = ADATA; + q->line = p->line; + q->link = datap; + datap = q; + q->from.type = D_EXTERN; + q->from.sym = s; + q->from.offset = n*4; + q->from.displace = 4; + q->to.type = D_EXTERN; + q->to.sym = p->from.sym; + n += 2; + continue; + } + } + q = prg(); + q->line = 0; + q->as = ADATA; + q->link = datap; + datap = q; + q->from.type = D_EXTERN; + q->from.sym = s; + q->from.displace = 4; + q->to.type = D_CONST; + q->to.offset = n; + s->type = SBSS; + s->value = n*4; +} + +void +doprof2(void) +{ + Sym *s2, *s4; + Prog *p, *q, *q2, *ps2, *ps4; + + if(debug['v']) + Bprint(&bso, "%5.2f profile 2\n", cputime()); + Bflush(&bso); + + if(debug['e']){ + s2 = lookup("_tracein", 0); + s4 = lookup("_traceout", 0); + }else{ + s2 = lookup("_profin", 0); + s4 = lookup("_profout", 0); + } + if(s2->type != STEXT || s4->type != STEXT) { + if(debug['e']) + diag("_tracein/_traceout not defined %d %d", s2->type, s4->type); + else + diag("_profin/_profout not defined"); + return; + } + + ps2 = P; + ps4 = P; + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) { + if(p->from.sym == s2) { + ps2 = p; + p->from.displace = 1; + } + if(p->from.sym == s4) { + ps4 = p; + p->from.displace = 1; + } + } + } + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) { + if(p->from.displace != 0) { + for(;;) { + q = p->link; + if(q == P) + break; + if(q->as == ATEXT) + break; + p = q; + } + continue; + } + + q = prg(); + q->line = p->line; + q->pc = p->pc; + q->link = p->link; + if(debug['e']){ /* embedded tracing */ + q2 = prg(); + p->link = q2; + q2->link = q; + + q2->line = p->line; + q2->pc = p->pc; + + q2->as = AJMP; + q2->to.type = D_BRANCH; + q2->to.sym = p->to.sym; + q2->pcond = q->link; + }else + p->link = q; + p = q; + p->as = ABSR; + p->to.type = D_BRANCH; + p->pcond = ps2; + p->to.sym = s2; + + continue; + } + if(p->as == ARTS) { + /* + * RTS (default) + */ + if(debug['e']){ /* embedded tracing */ + q = prg(); + q->line = p->line; + q->pc = p->pc; + q->link = p->link; + p->link = q; + p = q; + } + /* + * RTS + */ + q = prg(); + q->as = ARTS; + q->from = p->from; + q->to = p->to; + q->link = p->link; + p->link = q; + + /* + * BSR profout + */ + p->as = ABSR; + p->from = zprg.from; + p->to = zprg.to; + p->to.type = D_BRANCH; + p->pcond = ps4; + p->to.sym = s4; + + p = q; + + continue; + } + } +} + +long +reuse(Prog *r, Sym *s) +{ + Prog *p; + + + if(r == P) + return 0; + for(p = datap; p != r; p = p->link) + if(p->to.sym == s) + return p->from.offset; + return 0; +} + +void +nuxiinit(void) +{ + int i, c; + + for(i=0; i<4; i++) { + c = find1(0x01020304L, i+1); + if(i >= 2) + inuxi2[i-2] = c; + if(i >= 3) + inuxi1[i-3] = c; + inuxi4[i] = c; + fnuxi8[i] = c+4; + fnuxi8[i+4] = c; + c = find2(0x01020304L, i+1); + gnuxi8[i] = c+4; + gnuxi8[i+4] = c; + } + if(debug['v']) { + Bprint(&bso, "inuxi = "); + for(i=0; i<1; i++) + Bprint(&bso, "%d", inuxi1[i]); + Bprint(&bso, " "); + for(i=0; i<2; i++) + Bprint(&bso, "%d", inuxi2[i]); + Bprint(&bso, " "); + for(i=0; i<4; i++) + Bprint(&bso, "%d", inuxi4[i]); + Bprint(&bso, "\n[fg]nuxi = "); + for(i=0; i<8; i++) + Bprint(&bso, "%d", fnuxi8[i]); + Bprint(&bso, " "); + for(i=0; i<8; i++) + Bprint(&bso, "%d", gnuxi8[i]); + Bprint(&bso, "\n"); + } + Bflush(&bso); +} + +int +find1(long l, int c) +{ + char *p; + int i; + + p = (char*)&l; + for(i=0; i<4; i++) + if(*p++ == c) + return i; + return 0; +} + +int +find2(long l, int c) +{ + short *p; + int i; + + p = (short*)&l; + for(i=0; i<4; i+=2) { + if(((*p >> 8) & 0xff) == c) + return i; + if((*p++ & 0xff) == c) + return i+1; + } + return 0; +} + +long +ieeedtof(Ieee *e) +{ + int exp; + long v; + + if(e->h == 0) + return 0; + exp = (e->h>>20) & ((1L<<11)-1L); + exp -= (1L<<10) - 2L; + v = (e->h & 0xfffffL) << 3; + v |= (e->l >> 29) & 0x7L; + if((e->l >> 28) & 1) { + v++; + if(v & 0x800000L) { + v = (v & 0x7fffffL) >> 1; + exp++; + } + } + if(exp <= -126 || exp >= 130) + diag("double fp to single fp overflow"); + v |= ((exp + 126) & 0xffL) << 23; + v |= e->h & 0x80000000L; + return v; +} + +double +ieeedtod(Ieee *ieeep) +{ + Ieee e; + double fr; + int exp; + + if(ieeep->h & (1L<<31)) { + e.h = ieeep->h & ~(1L<<31); + e.l = ieeep->l; + return -ieeedtod(&e); + } + if(ieeep->l == 0 && ieeep->h == 0) + return 0; + fr = ieeep->l & ((1L<<16)-1L); + fr /= 1L<<16; + fr += (ieeep->l>>16) & ((1L<<16)-1L); + fr /= 1L<<16; + fr += (ieeep->h & (1L<<20)-1L) | (1L<<20); + fr /= 1L<<21; + exp = (ieeep->h>>20) & ((1L<<11)-1L); + exp -= (1L<<10) - 2L; + return ldexp(fr, exp); +} diff --git a/sys/src/cmd/1l/optab.c b/sys/src/cmd/1l/optab.c new file mode 100755 index 000000000..2109b478a --- /dev/null +++ b/sys/src/cmd/1l/optab.c @@ -0,0 +1,444 @@ +#include "l.h" + +#define X1 0 +#define X2 0 +#define X3 0 +#define C 0xf200 + +Optab optab[] = +/* as, fas, srcsp, dstsp, optype, opcode */ +{ + { AXXX }, + { AABCD, AXXX, X1, X2, X3, 0x4e71 }, + { AADDB, AXXX, 2, 0, 3, 0xd000, 0x5000, 0, 0x0600 }, + { AADDL, AXXX, 4, 0, 3, 0xd080, 0x5080, 0xd1c0, 0x0680 }, + { AADDW, AXXX, 2, 0, 3, 0xd040, 0x5040, 0xd0c0, 0x0640 }, + { AADDXB }, + { AADDXL }, + { AADDXW }, + { AADJSP }, + { AANDB, AXXX, 2, 0, 9, 0xc000, 0xc100, 0x0200 }, + { AANDL, AXXX, 4, 0, 9, 0xc080, 0xc180, 0x0280 }, + { AANDW, AXXX, 2, 0, 9, 0xc040, 0xc140, 0x0240 }, + { AASLB, AXXX, 0, 2, 12, 0xe100 }, + { AASLL, AXXX, 0, 4, 12, 0xe180 }, + { AASLW, AXXX, 0, 2, 12, 0xe140 }, + { AASRB, AXXX, 0, 2, 12, 0xe000 }, + { AASRL, AXXX, 0, 4, 12, 0xe080 }, + { AASRW, AXXX, 0, 2, 12, 0xe040 }, + { ABCASE }, + { ABCC, AXXX, 0, 0, 1, 0x6400 }, + { ABCHG, AXXX, 2, 2, 27, 0x0140, 0x0840 }, + { ABCLR, AXXX, 2, 2, 27, 0x0180, 0x0880 }, + { ABCS, AXXX, 0, 0, 1, 0x6500 }, + { ABEQ, AXXX, 0, 0, 1, 0x6700 }, + { ABFCHG }, + { ABFCLR }, + { ABFEXTS }, + { ABFEXTU }, + { ABFFFO }, + { ABFINS }, + { ABFSET }, + { ABFTST }, + { ABGE, AXXX, 0, 0, 1, 0x6c00 }, + { ABGT, AXXX, 0, 0, 1, 0x6e00 }, + { ABHI, AXXX, 0, 0, 1, 0x6200 }, + { ABKPT }, + { ABLE, AXXX, 0, 0, 1, 0x6f00 }, + { ABLS, AXXX, 0, 0, 1, 0x6300 }, + { ABLT, AXXX, 0, 0, 1, 0x6d00 }, + { ABMI, AXXX, 0, 0, 1, 0x6b00 }, + { ABNE, AXXX, 0, 0, 1, 0x6600 }, + { ABPL, AXXX, 0, 0, 1, 0x6a00 }, + { ABRA, AXXX, 0, 0, 1, 0x6000, 0x4ec0 }, + { ABSET, AXXX, 2, 2, 27, 0x01c0, 0x08c0 }, + { ABSR, AXXX, 0, 0, 1, 0x6100, 0x4e80 }, + { ABTST, AXXX, 2, 2, 27, 0x0100, 0x0800 }, + { ABVC, AXXX, 0, 0, 1, 0x6800 }, + { ABVS, AXXX, 0, 0, 1, 0x6900 }, + { ACALLM }, + { ACAS2B }, + { ACAS2L }, + { ACAS2W }, + { ACASB }, + { ACASEW }, + { ACASL }, + { ACASW }, + { ACHK2B }, + { ACHK2L }, + { ACHK2W }, + { ACHKL, AXXX, 4, 4, 26, 0x4100 }, + { ACHKW, AXXX, 2, 2, 26, 0x4180 }, + { ACLRB, AXXX, 0, -2, 5, 0x4200 }, + { ACLRL, AXXX, 0, -4, 5, 0x4280 }, + { ACLRW, AXXX, 0, -2, 5, 0x4240 }, + { ACMP2B }, + { ACMP2L }, + { ACMP2W }, + { ACMPB, AXXX, 2, 2, 7, 0xb000, 0, 0x0c00, 0xb108 }, + { ACMPL, AXXX, 4, 4, 7, 0xb080, 0xb100, 0x0c80, 0xb188 }, + { ACMPW, AXXX, 2, 2, 7, 0xb040, 0xb080, 0x0c40, 0xb148 }, + { ADATA }, + { ADBCC, AXXX, 0, 0, 15, 0x54c8 }, + { ADBCS, AXXX, 0, 0, 15, 0x55c8 }, + { ADBEQ, AXXX, 0, 0, 15, 0x57c8 }, + { ADBF, AXXX, 0, 0, 15, 0x51c8 }, + { ADBGE, AXXX, 0, 0, 15, 0x5cc8 }, + { ADBGT, AXXX, 0, 0, 15, 0x5ec8 }, + { ADBHI, AXXX, 0, 0, 15, 0x52c8 }, + { ADBLE, AXXX, 0, 0, 15, 0x5fc8 }, + { ADBLS, AXXX, 0, 0, 15, 0x53c8 }, + { ADBLT, AXXX, 0, 0, 15, 0x5dc8 }, + { ADBMI, AXXX, 0, 0, 15, 0x5bc8 }, + { ADBNE, AXXX, 0, 0, 15, 0x56c8 }, + { ADBPL, AXXX, 0, 0, 15, 0x5ac8 }, + { ADBT, AXXX, 0, 0, 15, 0x50c8 }, + { ADBVC, AXXX, 0, 0, 15, 0x58c8 }, + { ADBVS, AXXX, 0, 0, 15, 0x59c8 }, + { ADIVSL, AXXX, 4, 0, 14, 0x4c40, 0x0800 }, + { ADIVSW, AXXX, 2, 0, 13, 0x81c0 }, + { ADIVUL, AXXX, 4, 0, 14, 0x4c40, 0x0000 }, + { ADIVUW, AXXX, 2, 0, 13, 0x80c0 }, + { AEND }, + { AEORB, AXXX, 2, 0, 10, 0xb100, 0x0a00 }, + { AEORL, AXXX, 4, 0, 10, 0xb180, 0x0a80 }, + { AEORW, AXXX, 2, 0, 10, 0xb140, 0x0a40 }, + { AEXG }, + { AEXTBL }, + { AEXTBW, AXXX, 0, 0, 11, 0x4880 }, + { AEXTWL, AXXX, 0, 0, 11, 0x48c0 }, + { AFABSB, AXXX, 2, 0, 17, C, 0x0018, 0x5818 }, + { AFABSD, AFABSL, 8, 0, 17, C, 0x0018, 0x5418 }, + { AFABSF, AFABSL, 4, 0, 17, C, 0x0018, 0x4418 }, + { AFABSL, AXXX, 4, 0, 17, C, 0x0018, 0x4018 }, + { AFABSW, AXXX, 2, 0, 17, C, 0x0018, 0x5018 }, + { AFACOSB, AXXX, 2, 0, 17, C, 0x001c, 0x581c }, + { AFACOSD, AFACOSL, 8, 0, 17, C, 0x001c, 0x541c }, + { AFACOSF, AFACOSL, 4, 0, 17, C, 0x001c, 0x441c }, + { AFACOSL, AXXX, 4, 0, 17, C, 0x001c, 0x401c }, + { AFACOSW, AXXX, 2, 0, 17, C, 0x001c, 0x501c }, + { AFADDB, AXXX, 2, 0, 17, C, 0x0022, 0x5822 }, + { AFADDD, AFADDL, 8, 0, 17, C, 0x0022, 0x5422 }, + { AFADDF, AFADDL, 4, 0, 17, C, 0x0022, 0x4422 }, + { AFADDL, AXXX, 4, 0, 17, C, 0x0022, 0x4022 }, + { AFADDW, AXXX, 2, 0, 17, C, 0x0022, 0x5022 }, + { AFASINB, AXXX, 2, 0, 17, C, 0x000c, 0x580c }, + { AFASIND, AFASINL, 8, 0, 17, C, 0x000c, 0x540c }, + { AFASINF, AFASINL, 4, 0, 17, C, 0x000c, 0x440c }, + { AFASINL, AXXX, 4, 0, 17, C, 0x000c, 0x400c }, + { AFASINW, AXXX, 2, 0, 17, C, 0x000c, 0x500c }, + { AFATANB, AXXX, 2, 0, 17, C, 0x000a, 0x580a }, + { AFATAND, AFATANL, 8, 0, 17, C, 0x000a, 0x540a }, + { AFATANF, AFATANL, 4, 0, 17, C, 0x000a, 0x440a }, + { AFATANHB, AXXX, 2, 0, 17, C, 0x000d, 0x580d }, + { AFATANHD, AFATANHL, 8, 0, 17, C, 0x000d, 0x540d }, + { AFATANHF, AFATANHL, 4, 0, 17, C, 0x000d, 0x440d }, + { AFATANHL, AXXX, 4, 0, 17, C, 0x000d, 0x400d }, + { AFATANHW, AXXX, 2, 0, 17, C, 0x000d, 0x500d }, + { AFATANL, AXXX, 4, 0, 17, C, 0x000a, 0x400a }, + { AFATANW, AXXX, 2, 0, 17, C, 0x000a, 0x500a }, + { AFBEQ, AXXX, 0, 0, 18, C+0x81 }, + { AFBF, AXXX, 0, 0, 18, C+0x8f }, + { AFBGE, AXXX, 0, 0, 18, C+0x93 }, + { AFBGT, AXXX, 0, 0, 18, C+0x92 }, + { AFBLE, AXXX, 0, 0, 18, C+0x95 }, + { AFBLT, AXXX, 0, 0, 18, C+0x94 }, + { AFBNE, AXXX, 0, 0, 18, C+0x8e }, + { AFBT, AXXX, 0, 0, 18, C+0x80 }, + { AFCMPB, AXXX, 0, 2, 22, C, 0x0038, 0x5838 }, + { AFCMPD, AFCMPL, 0, 8, 22, C, 0x0038, 0x5438 }, + { AFCMPF, AFCMPL, 0, 4, 22, C, 0x0038, 0x4438 }, + { AFCMPL, AXXX, 0, 4, 22, C, 0x0038, 0x4038 }, + { AFCMPW, AXXX, 0, 2, 22, C, 0x0038, 0x5038 }, + { AFCOSB, AXXX, 2, 0, 17, C, 0x001d, 0x581d }, + { AFCOSD, AFCOSL, 8, 0, 17, C, 0x001d, 0x541d }, + { AFCOSF, AFCOSL, 4, 0, 17, C, 0x001d, 0x441d }, + { AFCOSHB, AXXX, 2, 0, 17, C, 0x0019, 0x5819 }, + { AFCOSHD, AFCOSHL, 8, 0, 17, C, 0x0019, 0x5419 }, + { AFCOSHF, AFCOSHL, 4, 0, 17, C, 0x0019, 0x4419 }, + { AFCOSHL, AXXX, 4, 0, 17, C, 0x0019, 0x4019 }, + { AFCOSHW, AXXX, 2, 0, 17, C, 0x0019, 0x5019 }, + { AFCOSL, AXXX, 4, 0, 17, C, 0x001d, 0x401d }, + { AFCOSW, AXXX, 2, 0, 17, C, 0x001d, 0x501d }, + { AFDBEQ, AXXX, 0, 0, 19, C+0x48, 0x01 }, + { AFDBF, AXXX, 0, 0, 19, C+0x48, 0x0f }, + { AFDBGE, AXXX, 0, 0, 19, C+0x48, 0x13 }, + { AFDBGT, AXXX, 0, 0, 19, C+0x48, 0x12 }, + { AFDBLE, AXXX, 0, 0, 19, C+0x48, 0x15 }, + { AFDBLT, AXXX, 0, 0, 19, C+0x48, 0x14 }, + { AFDBNE, AXXX, 0, 0, 19, C+0x48, 0x0e }, + { AFDBT, AXXX, 0, 0, 19, C+0x48, 0x00 }, + { AFDIVB, AXXX, 2, 0, 17, C, 0x0020, 0x5820 }, + { AFDIVD, AFDIVL, 8, 0, 17, C, 0x0020, 0x5420 }, + { AFDIVF, AFDIVL, 4, 0, 17, C, 0x0020, 0x4420 }, + { AFDIVL, AXXX, 4, 0, 17, C, 0x0020, 0x4020 }, + { AFDIVW, AXXX, 2, 0, 17, C, 0x0020, 0x5020 }, + { AFETOXB, AXXX, 2, 0, 17, C, 0x0010, 0x5810 }, + { AFETOXD, AFETOXL, 8, 0, 17, C, 0x0010, 0x5410 }, + { AFETOXF, AFETOXL, 4, 0, 17, C, 0x0010, 0x4410 }, + { AFETOXL, AXXX, 4, 0, 17, C, 0x0010, 0x4010 }, + { AFETOXM1B, AXXX, 2, 0, 17, C, 0x0008, 0x5808 }, + { AFETOXM1D, AFETOXM1L, 8, 0, 17, C, 0x0008, 0x5408 }, + { AFETOXM1F, AFETOXM1L, 4, 0, 17, C, 0x0008, 0x4408 }, + { AFETOXM1L, AXXX, 4, 0, 17, C, 0x0008, 0x4008 }, + { AFETOXM1W, AXXX, 2, 0, 17, C, 0x0008, 0x5008 }, + { AFETOXW, AXXX, 2, 0, 17, C, 0x0010, 0x5010 }, + { AFGETEXPB, AXXX, 2, 0, 17, C, 0x001e, 0x581e }, + { AFGETEXPD, AFGETEXPL, 8, 0, 17, C, 0x001e, 0x541e }, + { AFGETEXPF, AFGETEXPL, 4, 0, 17, C, 0x001e, 0x441e }, + { AFGETEXPL, AXXX, 4, 0, 17, C, 0x001e, 0x401e }, + { AFGETEXPW, AXXX, 2, 0, 17, C, 0x001e, 0x501e }, + { AFGETMANB, AXXX, 2, 0, 17, C, 0x001f, 0x581f }, + { AFGETMAND, AFGETMANL, 8, 0, 17, C, 0x001f, 0x541f }, + { AFGETMANF, AFGETMANL, 4, 0, 17, C, 0x001f, 0x441f }, + { AFGETMANL, AXXX, 4, 0, 17, C, 0x001f, 0x401f }, + { AFGETMANW, AXXX, 2, 0, 17, C, 0x001f, 0x501f }, + { AFINTB, AXXX, 2, 0, 17, C, 0x0001, 0x5801 }, + { AFINTD, AFINTL, 8, 0, 17, C, 0x0001, 0x5401 }, + { AFINTF, AFINTL, 4, 0, 17, C, 0x0001, 0x4401 }, + { AFINTL, AXXX, 4, 0, 17, C, 0x0001, 0x4001 }, + { AFINTRZB, AXXX, 2, 0, 17, C, 0x0003, 0x5803 }, + { AFINTRZD, AFINTRZL, 8, 0, 17, C, 0x0003, 0x5403 }, + { AFINTRZF, AFINTRZL, 4, 0, 17, C, 0x0003, 0x4403 }, + { AFINTRZL, AXXX, 4, 0, 17, C, 0x0003, 0x4003 }, + { AFINTRZW, AXXX, 2, 0, 17, C, 0x0003, 0x5003 }, + { AFINTW, AXXX, 2, 0, 17, C, 0x0001, 0x5001 }, + { AFLOG10B, AXXX, 2, 0, 17, C, 0x0015, 0x5815 }, + { AFLOG10D, AFLOG10L, 8, 0, 17, C, 0x0015, 0x5415 }, + { AFLOG10F, AFLOG10L, 4, 0, 17, C, 0x0015, 0x4415 }, + { AFLOG10L, AXXX, 4, 0, 17, C, 0x0015, 0x4015 }, + { AFLOG10W, AXXX, 2, 0, 17, C, 0x0015, 0x5015 }, + { AFLOG2B, AXXX, 2, 0, 17, C, 0x0016, 0x5816 }, + { AFLOG2D, AFLOG2L, 8, 0, 17, C, 0x0016, 0x5416 }, + { AFLOG2F, AFLOG2L, 4, 0, 17, C, 0x0016, 0x4416 }, + { AFLOG2L, AXXX, 4, 0, 17, C, 0x0016, 0x4016 }, + { AFLOG2W, AXXX, 2, 0, 17, C, 0x0016, 0x5016 }, + { AFLOGNB, AXXX, 2, 0, 17, C, 0x0014, 0x5814 }, + { AFLOGND, AFLOGNL, 8, 0, 17, C, 0x0014, 0x5414 }, + { AFLOGNF, AFLOGNL, 4, 0, 17, C, 0x0014, 0x4414 }, + { AFLOGNL, AXXX, 4, 0, 17, C, 0x0014, 0x4014 }, + { AFLOGNP1B, AXXX, 2, 0, 17, C, 0x0006, 0x5806 }, + { AFLOGNP1D, AFLOGNP1L, 8, 0, 17, C, 0x0006, 0x5406 }, + { AFLOGNP1F, AFLOGNP1L, 4, 0, 17, C, 0x0006, 0x4406 }, + { AFLOGNP1L, AXXX, 4, 0, 17, C, 0x0006, 0x4006 }, + { AFLOGNP1W, AXXX, 2, 0, 17, C, 0x0006, 0x5006 }, + { AFLOGNW, AXXX, 2, 0, 17, C, 0x0014, 0x5014 }, + { AFMODB, AXXX, 2, 0, 17, C, 0x0021, 0x5821 }, + { AFMODD, AFMODL, 8, 0, 17, C, 0x0021, 0x5421 }, + { AFMODF, AFMODL, 4, 0, 17, C, 0x0021, 0x4421 }, + { AFMODL, AXXX, 4, 0, 17, C, 0x0021, 0x4021 }, + { AFMODW, AXXX, 2, 0, 17, C, 0x0021, 0x5021 }, + { AFMOVEB, AXXX, 2, -2, 16, C, 0x0000, 0x7800, 0x5800 }, + { AFMOVED, AFMOVEL, 8, -8, 16, C, 0x0000, 0x7400, 0x5400 }, + { AFMOVEF, AFMOVEL, 4, -4, 16, C, 0x0000, 0x6400, 0x4400 }, + { AFMOVEL, AXXX, 4, -4, 16, C, 0x0000, 0x6000, 0x4000 }, + { AFMOVEM, AXXX, 2, 2, 28, C }, + { AFMOVEMC, AXXX, 2, 2, 29, C }, + { AFMOVEW, AXXX, 2, -2, 16, C, 0x0000, 0x7000, 0x5000 }, + { AFMULB, AXXX, 2, 0, 17, C, 0x0023, 0x5823 }, + { AFMULD, AFMULL, 8, 0, 17, C, 0x0023, 0x5423 }, + { AFMULF, AFMULL, 4, 0, 17, C, 0x0023, 0x4423 }, + { AFMULL, AXXX, 4, 0, 17, C, 0x0023, 0x4023 }, + { AFMULW, AXXX, 2, 0, 17, C, 0x0023, 0x5023 }, + { AFNEGB, AXXX, 2, 0, 21, C, 0x001a, 0x581a }, + { AFNEGD, AFNEGL, 8, 0, 21, C, 0x001a, 0x541a }, + { AFNEGF, AFNEGL, 4, 0, 21, C, 0x001a, 0x441a }, + { AFNEGL, AXXX, 4, 0, 21, C, 0x001a, 0x401a }, + { AFNEGW, AXXX, 2, 0, 21, C, 0x001a, 0x501a }, + { AFREMB, AXXX, 2, 0, 17, C, 0x0025, 0x5825 }, + { AFREMD, AFREML, 8, 0, 17, C, 0x0025, 0x5425 }, + { AFREMF, AFREML, 4, 0, 17, C, 0x0025, 0x4425 }, + { AFREML, AXXX, 4, 0, 17, C, 0x0025, 0x4025 }, + { AFREMW, AXXX, 2, 0, 17, C, 0x0025, 0x5025 }, + { AFRESTORE, AXXX, 0, 2, 5, C+0x0140 }, + { AFSAVE, AXXX, 0, 2, 5, C+0x0100 }, + { AFSCALEB, AXXX, 2, 0, 17, C, 0x0026, 0x5826 }, + { AFSCALED, AFSCALEL, 8, 0, 17, C, 0x0026, 0x5426 }, + { AFSCALEF, AFSCALEL, 4, 0, 17, C, 0x0026, 0x4426 }, + { AFSCALEL, AXXX, 4, 0, 17, C, 0x0026, 0x4026 }, + { AFSCALEW, AXXX, 2, 0, 17, C, 0x0026, 0x5026 }, + { AFSEQ, AXXX, X1, X2, X3, 0xffff }, + { AFSF, AXXX, 4, X2, X3, 0xffff }, + { AFSGE, AXXX, X1, X2, X3, 0xffff }, + { AFSGT, AXXX, X1, X2, X3, 0xffff }, + { AFSINB, AXXX, 2, 0, 17, C, 0x000e, 0x580e }, + { AFSIND, AFSINL, 8, 0, 17, C, 0x000e, 0x540e }, + { AFSINF, AFSINL, 4, 0, 17, C, 0x000e, 0x440e }, + { AFSINHB, AXXX, 2, 0, 17, C, 0x0002, 0x5802 }, + { AFSINHD, AFSINHL, 8, 0, 17, C, 0x0002, 0x5402 }, + { AFSINHF, AFSINHL, 4, 0, 17, C, 0x0002, 0x4402 }, + { AFSINHL, AXXX, 4, 0, 17, C, 0x0002, 0x4002 }, + { AFSINHW, AXXX, 2, 0, 17, C, 0x0002, 0x5002 }, + { AFSINL, AXXX, 4, 0, 17, C, 0x000e, 0x400e }, + { AFSINW, AXXX, 2, 0, 17, C, 0x000e, 0x500e }, + { AFSLE, AXXX, X1, X2, X3, 0xffff }, + { AFSLT, AXXX, X1, X2, X3, 0xffff }, + { AFSNE, AXXX, X1, X2, X3, 0xffff }, + { AFSQRTB, AXXX, 2, 0, 17, C, 0x0004, 0x5804 }, + { AFSQRTD, AFSQRTL, 8, 0, 17, C, 0x0004, 0x5404 }, + { AFSQRTF, AFSQRTL, 4, 0, 17, C, 0x0004, 0x4404 }, + { AFSQRTL, AXXX, 4, 0, 17, C, 0x0004, 0x4004 }, + { AFSQRTW, AXXX, 2, 0, 17, C, 0x0004, 0x5004 }, + { AFST, AXXX, X1, X2, X3, 0xffff }, + { AFSUBB, AXXX, 2, 0, 17, C, 0x0028, 0x5828 }, + { AFSUBD, AFSUBL, 8, 0, 17, C, 0x0028, 0x5428 }, + { AFSUBF, AFSUBL, 4, 0, 17, C, 0x0028, 0x4428 }, + { AFSUBL, AXXX, 4, 0, 17, C, 0x0028, 0x4028 }, + { AFSUBW, AXXX, 2, 0, 17, C, 0x0028, 0x5028 }, + { AFTANB, AXXX, 2, 0, 17, C, 0x000f, 0x580f }, + { AFTAND, AFTANL, 8, 0, 17, C, 0x000f, 0x540f }, + { AFTANF, AFTANL, 4, 0, 17, C, 0x000f, 0x440f }, + { AFTANHB, AXXX, 2, 0, 17, C, 0x0009, 0x5809 }, + { AFTANHD, AFTANHL, 8, 0, 17, C, 0x0009, 0x5409 }, + { AFTANHF, AFTANHL, 4, 0, 17, C, 0x0009, 0x4409 }, + { AFTANHL, AXXX, 4, 0, 17, C, 0x0009, 0x4009 }, + { AFTANHW, AXXX, 2, 0, 17, C, 0x0009, 0x5009 }, + { AFTANL, AXXX, 4, 0, 17, C, 0x000f, 0x400f }, + { AFTANW, AXXX, 2, 0, 17, C, 0x000f, 0x500f }, + { AFTENTOXB, AXXX, 2, 0, 17, C, 0x0012, 0x5812 }, + { AFTENTOXD, AFTENTOXL, 8, 0, 17, C, 0x0012, 0x5412 }, + { AFTENTOXF, AFTENTOXL, 4, 0, 17, C, 0x0012, 0x4412 }, + { AFTENTOXL, AXXX, 4, 0, 17, C, 0x0012, 0x4012 }, + { AFTENTOXW, AXXX, 2, 0, 17, C, 0x0012, 0x5012 }, + { AFTSTB, AXXX, 0, 2, 20, C, 0x003a, 0x583a }, + { AFTSTD, AFTSTL, 0, 8, 20, C, 0x003a, 0x543a }, + { AFTSTF, AFTSTL, 0, 4, 20, C, 0x003a, 0x443a }, + { AFTSTL, AXXX, 0, 4, 20, C, 0x003a, 0x403a }, + { AFTSTW, AXXX, 0, 2, 20, C, 0x003a, 0x503a }, + { AFTWOTOXB, AXXX, 2, 0, 17, C, 0x0011, 0x5811 }, + { AFTWOTOXD, AFTWOTOXL, 8, 0, 17, C, 0x0011, 0x5411 }, + { AFTWOTOXF, AFTWOTOXL, 4, 0, 17, C, 0x0011, 0x4411 }, + { AFTWOTOXL, AXXX, 4, 0, 17, C, 0x0011, 0x4011 }, + { AFTWOTOXW, AXXX, 2, 0, 17, C, 0x0011, 0x5011 }, + { AGLOBL }, + { AGOK }, + { AHISTORY }, + { AILLEG, AXXX, 0, 0, 4, 0x4efc }, + { AINSTR }, + { AJMP, AXXX, 0, 0, 5, 0x4ec0 }, + { AJSR, AXXX, 0, 0, 5, 0x4e80 }, + { ALEA, AXXX, 0, 0, 6, 0x41c0 }, + { ALINKL }, + { ALINKW }, + { ALOCATE }, + { ALONG, AXXX, 0, 4, 23 }, + { ALSLB, AXXX, 0, 2, 12, 0xe108 }, + { ALSLL, AXXX, 0, 4, 12, 0xe188 }, + { ALSLW, AXXX, 0, 2, 12, 0xe148 }, + { ALSRB, AXXX, 0, 2, 12, 0xe008 }, + { ALSRL, AXXX, 0, 4, 12, 0xe088 }, + { ALSRW, AXXX, 0, 2, 12, 0xe048 }, + { AMOVB, AXXX, 2, -2, 2, 0x1000, 0x7000 }, + { AMOVEM, AXXX, 2, 2, 25, 0x48c0 }, + { AMOVEPL }, + { AMOVEPW }, + { AMOVESB }, + { AMOVESL }, + { AMOVESW, }, + { AMOVL, AXXX, 4, -4, 2, 0x2000, 0x7000 }, + { AMOVW, AXXX, 2, -2, 2, 0x3000, 0x7000 }, + { AMULSL, AXXX, 4, 0, 14, 0x4c00, 0x0800 }, + { AMULSW, AXXX, 2, 0, 13, 0xc1c0 }, + { AMULUL, AXXX, 4, 0, 14, 0x4c00, 0x0000 }, + { AMULUW, AXXX, 2, 0, 13, 0xc0c0 }, + { ANAME }, + { ANBCD }, + { ANEGB, AXXX, 0, 0, 5, 0x4400 }, + { ANEGL, AXXX, 0, 0, 5, 0x4480 }, + { ANEGW, AXXX, 0, 0, 5, 0x4440 }, + { ANEGXB }, + { ANEGXL }, + { ANEGXW }, + { ANOP }, + { ANOTB, AXXX, 0, 0, 5, 0x4600 }, + { ANOTL, AXXX, 0, 0, 5, 0x4680 }, + { ANOTW, AXXX, 0, 0, 5, 0x4640 }, + { AORB, AXXX, 2, 0, 9, 0x8000, 0x8100, 0x0000 }, + { AORL, AXXX, 4, 0, 9, 0x8080, 0x8180, 0x0080 }, + { AORW, AXXX, 2, 0, 9, 0x8040, 0x8140, 0x0040 }, + { APACK }, + { APEA, AXXX, 0, 0, 5, 0x4840 }, + { ARESET }, + { AROTLB, AXXX, 0, 2, 12, 0xe118 }, + { AROTLL, AXXX, 0, 4, 12, 0xe198 }, + { AROTLW, AXXX, 0, 2, 12, 0xe158 }, + { AROTRB, AXXX, 0, 2, 12, 0xe018 }, + { AROTRL, AXXX, 0, 4, 12, 0xe098 }, + { AROTRW, AXXX, 0, 2, 12, 0xe058 }, + { AROXLB }, + { AROXLL }, + { AROXLW }, + { AROXRB }, + { AROXRL }, + { AROXRW }, + { ARTD }, + { ARTE, AXXX, 0, 0, 4, 0x4e73 }, + { ARTM }, + { ARTR }, + { ARTS, AXXX, 0, 0, 4, 0x4e75 }, + { ASBCD }, + { ASCC }, + { ASCS }, + { ASEQ }, + { ASF }, + { ASGE }, + { ASGT }, + { ASHI }, + { ASLE }, + { ASLS }, + { ASLT }, + { ASMI }, + { ASNE }, + { ASPL }, + { AST }, + { ASTOP }, + { ASUBB, AXXX, 2, 0, 3, 0x9000, 0x5100, 0, 0x0400 }, + { ASUBL, AXXX, 4, 0, 3, 0x9080, 0x5180, 0x91c0, 0x0480 }, + { ASUBW, AXXX, 2, 0, 3, 0x9040, 0x5140, 0x90c0, 0x0440 }, + { ASUBXB }, + { ASUBXL }, + { ASUBXW }, + { ASVC }, + { ASVS }, + { ASWAP, AXXX, 0, 0, 35, 0x4840 }, + { ASYS, AXXX, 0, 2, 8, 0x4e40 }, + { ATAS, AXXX, 0, 2, 5, 0x4ac0 }, + { ATEXT }, + { ATRAP, AXXX, 0, 0, 30, 0x4e40 }, + { ATRAPCC }, + { ATRAPCS }, + { ATRAPEQ }, + { ATRAPF }, + { ATRAPGE }, + { ATRAPGT }, + { ATRAPHI }, + { ATRAPLE }, + { ATRAPLS }, + { ATRAPLT }, + { ATRAPMI }, + { ATRAPNE }, + { ATRAPPL }, + { ATRAPT }, + { ATRAPV }, + { ATRAPVC }, + { ATRAPVS }, + { ATSTB, AXXX, 0, 2, 5, 0x4a00 }, + { ATSTL, AXXX, 0, 4, 5, 0x4a80 }, + { ATSTW, AXXX, 0, 2, 5, 0x4a40 }, + { AUNLK }, + { AUNPK }, + { AWORD, AXXX, 0, 2, 23 }, + { AXXX } +}; + +char mmsize[] = +{ + /* 0 */ 0, 2, 2, 2, 2, + /* 5 */ 2, 2, 2, 4, 2, + /* 10 */ 2, 2, 2, 2, 4, + /* 15 */ 4, 4, 4, 4, 6, + /* 20 */ 4, 4, 4, 0, 4, + /* 25 */ 2, 2, 2, 2, 2, + /* 30 */ 2, 4, 4, 0, 4, + /* 35 */ 2, 0, 0, 0, 0, +}; diff --git a/sys/src/cmd/1l/pass.c b/sys/src/cmd/1l/pass.c new file mode 100755 index 000000000..349026b1c --- /dev/null +++ b/sys/src/cmd/1l/pass.c @@ -0,0 +1,673 @@ +#include "l.h" + +void +dodata(void) +{ + int i; + Sym *s; + Prog *p; + long t, u; + + if(debug['v']) + Bprint(&bso, "%5.2f dodata\n", cputime()); + Bflush(&bso); + for(p = datap; p != P; p = p->link) { + s = p->from.sym; + if(s->type == SBSS) + s->type = SDATA; + if(s->type != SDATA) + diag("initialize non-data (%d): %s\n%P", + s->type, s->name, p); + t = p->from.offset + p->from.displace; + if(t > s->value) + diag("initialize bounds (%ld): %s\n%P", + s->value, s->name, p); + } + + /* allocate small guys */ + datsize = 0; + for(i=0; i<NHASH; i++) + for(s = hash[i]; s != S; s = s->link) { + if(s->type != SDATA) + if(s->type != SBSS) + continue; + t = s->value; + if(t == 0) { + diag("%s: no size", s->name); + t = 1; + } + t = rnd(t, 4);; + s->value = t; + if(t > MINSIZ) + continue; + s->value = datsize; + datsize += t; + s->type = SDATA1; + } + + /* allocate the rest of the data */ + for(i=0; i<NHASH; i++) + for(s = hash[i]; s != S; s = s->link) { + if(s->type != SDATA) { + if(s->type == SDATA1) + s->type = SDATA; + continue; + } + t = s->value; + s->value = datsize; + datsize += t; + } + + if(debug['j']) { + /* + * pad data with bss that fits up to next + * 8k boundary, then push data to 8k + */ + u = rnd(datsize, 8192); + u -= datsize; + for(i=0; i<NHASH; i++) + for(s = hash[i]; s != S; s = s->link) { + if(s->type != SBSS) + continue; + t = s->value; + if(t > u) + continue; + u -= t; + s->value = datsize; + s->type = SDATA; + datsize += t; + } + datsize += u; + } + + /* now the bss */ + bsssize = 0; + for(i=0; i<NHASH; i++) + for(s = hash[i]; s != S; s = s->link) { + if(s->type != SBSS) + continue; + t = s->value; + s->value = bsssize + datsize; + bsssize += t; + } + xdefine("bdata", SDATA, 0L); + xdefine("edata", SDATA, datsize); + xdefine("end", SBSS, datsize+bsssize); +} + +Prog* +brchain(Prog *p) +{ + int i; + + for(i=0; i<20; i++) { + if(p == P || p->as != ABRA) + return p; + p = p->pcond; + } + return P; +} + +void +follow(void) +{ + Prog *p; + long o; + + if(debug['v']) + Bprint(&bso, "%5.2f follow\n", cputime()); + Bflush(&bso); + firstp = prg(); + lastp = firstp; + xfol(textp); + lastp->link = P; + firstp = firstp->link; + o = 0; /* set */ + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) + curtext = p; + + p->stkoff = -1; /* initialization for stkoff */ + if(p->as == ATEXT) { + p->stkoff = 0; + o = p->to.offset; + continue; + } + if(p->as == AADJSP && p->from.offset == 0) { + p->stkoff = o; + continue; + } + } +} + +void +xfol(Prog *p) +{ + Prog *q; + int i; + enum as a; + +loop: + if(p == P) + return; + if(p->as == ATEXT) + curtext = p; + if(p->as == ABRA) + if((q = p->pcond) != P) { + p->mark = 1; + p = q; + if(p->mark == 0) + goto loop; + } + if(p->mark) { + /* copy up to 4 instructions to avoid branch */ + for(i=0,q=p; i<4; i++,q=q->link) { + if(q == P) + break; + if(q == lastp) + break; + a = q->as; + if(a == ANOP) { + i--; + continue; + } + if(a == ABRA || a == ARTS || a == ARTE) + break; + if(q->pcond == P || q->pcond->mark) + continue; + if(a == ABSR || a == ADBF) + continue; + for(;;) { + if(p->as == ANOP) { + p = p->link; + continue; + } + q = copyp(p); + p = p->link; + q->mark = 1; + lastp->link = q; + lastp = q; + if(q->as != a || q->pcond == P || q->pcond->mark) + continue; + q->as = relinv(q->as); + p = q->pcond; + q->pcond = q->link; + q->link = p; + xfol(q->link); + p = q->link; + if(p->mark) + return; + goto loop; + } + } /* */ + q = prg(); + q->as = ABRA; + q->line = p->line; + q->to.type = D_BRANCH; + q->to.offset = p->pc; + q->pcond = p; + p = q; + } + p->mark = 1; + lastp->link = p; + lastp = p; + a = p->as; + if(a == ARTS || a == ABRA || a == ARTE) + return; + if(p->pcond != P) + if(a != ABSR) { + q = brchain(p->link); + if(q != P && q->mark) + if(a != ADBF) { + p->as = relinv(a); + p->link = p->pcond; + p->pcond = q; + } + xfol(p->link); + q = brchain(p->pcond); + if(q->mark) { + p->pcond = q; + return; + } + p = q; + goto loop; + } + p = p->link; + goto loop; +} + +int +relinv(int a) +{ + + switch(a) { + case ABEQ: return ABNE; + case ABNE: return ABEQ; + case ABLE: return ABGT; + case ABLS: return ABHI; + case ABLT: return ABGE; + case ABMI: return ABPL; + case ABGE: return ABLT; + case ABPL: return ABMI; + case ABGT: return ABLE; + case ABHI: return ABLS; + case ABCS: return ABCC; + case ABCC: return ABCS; + case AFBEQ: return AFBNE; + case AFBF: return AFBT; + case AFBGE: return AFBLT; + case AFBGT: return AFBLE; + case AFBLE: return AFBGT; + case AFBLT: return AFBGE; + case AFBNE: return AFBEQ; + case AFBT: return AFBF; + } + diag("unknown relation: %s in %s", anames[a], TNAME); + return a; +} + +void +patch(void) +{ + long c; + Prog *p, *q; + Sym *s; + long vexit; + + if(debug['v']) + Bprint(&bso, "%5.2f mkfwd\n", cputime()); + Bflush(&bso); + mkfwd(); + if(debug['v']) + Bprint(&bso, "%5.2f patch\n", cputime()); + Bflush(&bso); + s = lookup("exit", 0); + vexit = s->value; + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) + curtext = p; + if((p->as == ABSR || p->as == ARTS) && p->to.sym != S) { + s = p->to.sym; + if(s->type != STEXT) { + diag("undefined: %s in %s", s->name, TNAME); + s->type = STEXT; + s->value = vexit; + } + p->to.offset = s->value; + p->to.type = D_BRANCH; + } + if(p->to.type != D_BRANCH) + continue; + c = p->to.offset; + for(q = firstp; q != P;) { + if(q->forwd != P) + if(c >= q->forwd->pc) { + q = q->forwd; + continue; + } + if(c == q->pc) + break; + q = q->link; + } + if(q == P) { + diag("branch out of range in %s\n%P", TNAME, p); + p->to.type = D_NONE; + } + p->pcond = q; + } + + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) + curtext = p; + p->mark = 0; /* initialization for follow */ + if(p->pcond != P) { + p->pcond = brloop(p->pcond); + if(p->pcond != P) + if(p->to.type == D_BRANCH) + p->to.offset = p->pcond->pc; + } + } +} + +#define LOG 5 +void +mkfwd(void) +{ + Prog *p; + int i; + long dwn[LOG], cnt[LOG]; + Prog *lst[LOG]; + + for(i=0; i<LOG; i++) { + if(i == 0) + cnt[i] = 1; else + cnt[i] = LOG * cnt[i-1]; + dwn[i] = 1; + lst[i] = P; + } + i = 0; + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) + curtext = p; + i--; + if(i < 0) + i = LOG-1; + p->forwd = P; + dwn[i]--; + if(dwn[i] <= 0) { + dwn[i] = cnt[i]; + if(lst[i] != P) + lst[i]->forwd = p; + lst[i] = p; + } + } +} + +Prog* +brloop(Prog *p) +{ + int c; + Prog *q; + + c = 0; + for(q = p; q != P; q = q->pcond) { + if(q->as != ABRA) + break; + c++; + if(c >= 5000) + return P; + } + return q; +} + +void +dostkoff(void) +{ + Prog *p, *q, *qq; + long s, t; + int a; + Optab *o; + + if(debug['v']) + Bprint(&bso, "%5.2f stkoff\n", cputime()); + Bflush(&bso); + s = 0; + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) { + curtext = p; + s = p->to.offset; + if(s == 0) + continue; + p = nprg(p); + p->as = AADJSP; + p->from.type = D_CONST; + p->from.offset = s; + p->stkoff = 0; + continue; + } + t = 0; + for(q = p; q != P; q = q->pcond) { + if(q->as == ATEXT) + break; + if(q->stkoff >= 0) + if(q->stkoff != s) + diag("stack offset %ld is %ld sb %ld in %s\n%P", + q->pc, q->stkoff, s, TNAME, p); + q->stkoff = s; + if(t++ > 100) { + diag("loop in stack offset 1: %P", p); + break; + } + } + o = &optab[p->as]; + if(p->to.type == D_TOS) + s -= o->dstsp; + if(p->from.type == D_TOS) + s -= o->srcsp; + if(p->as == AADJSP) + s += p->from.offset; + if(p->as == APEA) + s += 4; + t = 0; + for(q = p->link; q != P; q = q->pcond) { + if(q->as == ATEXT) { + q = P; + break; + } + if(q->stkoff >= 0) + break; + if(t++ > 100) { + diag("loop in stack offset 2: %P", p); + break; + } + } + if(q == P || q->stkoff == s) + continue; + if(p->as == ABRA || p->as == ARTS || p->as == ARTE) { + s = q->stkoff; + continue; + } + t = q->stkoff - s; + s = q->stkoff; + p = nprg(p); + p->as = AADJSP; + p->stkoff = s - t; + p->from.type = D_CONST; + p->from.offset = t; + } + + if(debug['v']) + Bprint(&bso, "%5.2f rewrite\n", cputime()); + Bflush(&bso); + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) + curtext = p; + a = p->from.type & D_MASK; + if(a == D_AUTO) + p->from.offset += p->stkoff; + if(a == D_PARAM) + p->from.offset += p->stkoff + 4; + a = p->to.type & D_MASK; + if(a == D_AUTO) + p->to.offset += p->stkoff; + if(a == D_PARAM) + p->to.offset += p->stkoff + 4; + switch(p->as) { + default: + continue; + + case AMOVW: + if(p->from.type != D_CCR) + continue; + a = p->to.type; + if((a < D_R0 || a > D_R0+7) && a != D_TOS) + diag("bad dest for MOVCC %P", p); + p->as = ALEA; + p->from.type = I_INDIR|(D_A0+7); + p->from.offset = -2; + p->to.type = D_A0+7; + + p = nprg(p); + p->as = ABSR; + p->to.type = D_BRANCH; + p->pcond = prog_ccr; + p->to.sym = prog_ccr->from.sym; + + if(a != D_TOS) { + p = nprg(p); + p->as = AMOVW; + p->from.type = D_TOS; + p->to.type = a; + } + continue; + + case AEXTBL: + a = p->to.type; + if(a < D_R0 || a > D_R0+7) + diag("bad dest for EXTB"); + p->as = AEXTBW; + + p = nprg(p); + p->as = AEXTWL; + p->to.type = a; + continue; + + case AMULSL: + case AMULUL: + qq = prog_mull; + goto mdcom; + case ADIVSL: + qq = prog_divsl; + goto mdcom; + case ADIVUL: + qq = prog_divul; + mdcom: + if(debug['m']) + continue; + a = p->to.type; + if(a < D_R0 || a > D_R0+7) + diag("bad dest for mul/div"); + p->as = AMOVL; + p->to.type = D_TOS; + + p = nprg(p); + p->as = AMOVL; + p->from.type = a; + p->to.type = D_TOS; + + p = nprg(p); + p->as = ABSR; + p->to.type = D_BRANCH; + p->pcond = qq; + p->to.sym = qq->from.sym; + + p = nprg(p); + p->as = AMOVL; + p->from.type = D_TOS; + p->to.type = a; + + p = nprg(p); + p->as = AMOVL; + p->from.type = D_TOS; + p->to.type = a+1; + if(qq == prog_mull) + p->to.type = a; + continue; + + case ARTS: + break; + } + if(p->stkoff == 0) + continue; + + p->as = AADJSP; + p->from.type = D_CONST; + p->from.offset = -p->stkoff; + + p = nprg(p); + p->as = ARTS; + p->stkoff = 0; + } +} + +long +atolwhex(char *s) +{ + long n; + int f; + + n = 0; + f = 0; + while(*s == ' ' || *s == '\t') + s++; + if(*s == '-' || *s == '+') { + if(*s++ == '-') + f = 1; + while(*s == ' ' || *s == '\t') + s++; + } + if(s[0]=='0' && s[1]){ + if(s[1]=='x' || s[1]=='X'){ + s += 2; + for(;;){ + if(*s >= '0' && *s <= '9') + n = n*16 + *s++ - '0'; + else if(*s >= 'a' && *s <= 'f') + n = n*16 + *s++ - 'a' + 10; + else if(*s >= 'A' && *s <= 'F') + n = n*16 + *s++ - 'A' + 10; + else + break; + } + } else + while(*s >= '0' && *s <= '7') + n = n*8 + *s++ - '0'; + } else + while(*s >= '0' && *s <= '9') + n = n*10 + *s++ - '0'; + if(f) + n = -n; + return n; +} + +void +undef(void) +{ + int i; + Sym *s; + + for(i=0; i<NHASH; i++) + for(s = hash[i]; s != S; s = s->link) + if(s->type == SXREF) + diag("%s: not defined", s->name); +} + +void +initmuldiv1(void) +{ + lookup("_mull", 0)->type = SXREF; + lookup("_divsl", 0)->type = SXREF; + lookup("_divul", 0)->type = SXREF; + lookup("_ccr", 0)->type = SXREF; +} + +void +initmuldiv2(void) +{ + Sym *s1, *s2, *s3, *s4; + Prog *p; + + if(prog_mull != P) + return; + s1 = lookup("_mull", 0); + s2 = lookup("_divsl", 0); + s3 = lookup("_divul", 0); + s4 = lookup("_ccr", 0); + for(p = firstp; p != P; p = p->link) + if(p->as == ATEXT) { + if(p->from.sym == s1) + prog_mull = p; + if(p->from.sym == s2) + prog_divsl = p; + if(p->from.sym == s3) + prog_divul = p; + if(p->from.sym == s4) + prog_ccr = p; + } + if(prog_mull == P) { + diag("undefined: %s", s1->name); + prog_mull = curtext; + } + if(prog_divsl == P) { + diag("undefined: %s", s2->name); + prog_divsl = curtext; + } + if(prog_divul == P) { + diag("undefined: %s", s3->name); + prog_divul = curtext; + } + if(prog_ccr == P) { + diag("undefined: %s", s4->name); + prog_ccr = curtext; + } +} diff --git a/sys/src/cmd/1l/span.c b/sys/src/cmd/1l/span.c new file mode 100755 index 000000000..d8baa3625 --- /dev/null +++ b/sys/src/cmd/1l/span.c @@ -0,0 +1,515 @@ +#include "l.h" + +void +span(void) +{ + Prog *p, *q; + long v, c, idat; + Optab *o; + int m, n; + + xdefine("etext", STEXT, 0L); + xdefine("a6base", STEXT, 0L); + idat = INITDAT; + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) + curtext = p; + n = 0; + if((q = p->pcond) != P) + if(q->back != 2) + n = 1; + p->back = n; + if(p->as == AADJSP) { + p->to.type = D_A0+7; + v = -p->from.offset; + p->from.offset = v; + if((v < -8 && v >= -32768L) || (v > 8 && v < 32768L)) { + p->as = ALEA; + p->from.type = I_INDIR | (D_A0+7); + continue; + } + p->as = AADDL; + if(v < 0) { + p->as = ASUBL; + v = -v; + p->from.offset = v; + } + if(v >= 0 && v <= 8) + p->from.type = D_QUICK; + if(v == 0) + p->as = ANOP; + } + } + n = 0; + +start: + if(debug['v']) + Bprint(&bso, "%5.2f span\n", cputime()); + Bflush(&bso); + c = INITTEXT; + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) + curtext = p; + o = &optab[p->as]; + p->pc = c; + m = mmsize[o->optype]; + if(m == 0) { + if(p->as == AWORD) + m = 2; + if(p->as == ALONG) + m = 4; + p->mark = m; + c += m; + continue; + } + if(p->from.type != D_NONE) + m += andsize(p, &p->from); + if(p->to.type == D_BRANCH) { + if(p->pcond == P) + p->pcond = p; + c += m; + if(m == 2) + m |= 0100; + p->mark = m; + continue; + } + if(p->to.type != D_NONE) + m += andsize(p, &p->to); + p->mark = m; + c += m; + } + +loop: + n++; + if(debug['v']) + Bprint(&bso, "%5.2f span %d\n", cputime(), n); + Bflush(&bso); + if(n > 60) { + diag("span must be looping"); + errorexit(); + } + c = INITTEXT; + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) + curtext = p; + if((m = p->mark) & 0100) { + q = p->pcond; + v = q->pc - 2; + if(p->back) + v -= c; + else + v -= p->pc; + p->pc = c; + if(v < -32768L || v >= 32768L) { + c += 6; /* only jsr and jmp can do this */ + } else + if(v < -128 || v >= 128) + c += 4; + else + if(v == 0) { + c += 4; + p->mark = 4; + } else + c += 2; + continue; + } + p->pc = c; + c += m; + } + if(c != textsize) { + textsize = c; + goto loop; + } + if(INITRND) + INITDAT = rnd(c, INITRND); + if(INITDAT != idat) { + idat = INITDAT; + goto start; + } + xdefine("etext", STEXT, c); + xdefine("a6base", STEXT, INITDAT+A6OFFSET); + if(debug['v']) + Bprint(&bso, "etext = %lux\n", c); + Bflush(&bso); + for(p = textp; p != P; p = p->pcond) + p->from.sym->value = p->pc; + textsize = c - INITTEXT; +} + +void +xdefine(char *p, int t, long v) +{ + Sym *s; + + s = lookup(p, 0); + if(s->type == 0 || s->type == SXREF) { + s->type = t; + s->value = v; + } + if(s->type == STEXT && s->value == 0) + s->value = v; +} + +int +andsize(Prog *p, Adr *ap) +{ + int t, n; + long v; + Optab *o; + + t = ap->type; + n = simple[t]; + if(n != 0177) { + v = ap->offset; + if(v == 0) + return 0; + if((n&070) != 020) /* D_INDIR */ + return 0; + if(v == 0) + return 0; + return 2; + } + if((t&I_MASK) == I_ADDR) + t = D_CONST; + switch(t) { + + default: + return 0; + + case D_STACK: + case D_AUTO: + case D_PARAM: + v = ap->offset; + if(v == 0) + return 0; + return 2; + + case I_INDIR|D_CONST: + v = ap->offset; + if(v < -32768L || v >= 32768L) + return 4; + return 2; + + case D_STATIC: + case D_EXTERN: + if(ap->sym->type == STEXT) { + if(HEADTYPE == 4) + return 2; + return 4; + } + v = ap->sym->value + ap->offset - A6OFFSET; + if(v == 0) + return 0; + if(v < -32768L || v >= 32768L) + return 4; + return 2; + + case D_CONST: + case D_FCONST: + o = &optab[p->as]; + if(ap == &(p->from)) + return o->srcsp; + return o->dstsp; + + case D_CCR: + case D_SR: + if(p->as == AMOVW) + return 0; + return 2; + + case D_USP: + t = p->from.type; + if(t >= D_A0 && t <= D_A0+8) + return 0; + t = p->to.type; + if(t >= D_A0 && t <= D_A0+8) + return 0; + + case D_SFC: + case D_DFC: + case D_CACR: + case D_VBR: + case D_CAAR: + case D_MSP: + case D_ISP: + case D_FPCR: + case D_FPSR: + case D_FPIAR: + case D_TC: + case D_ITT0: + case D_ITT1: + case D_DTT0: + case D_DTT1: + case D_MMUSR: + case D_URP: + case D_SRP: + return 2; + } +} + +void +putsymb(Sym *s, int t, long v) +{ + int i, f; + char *n; + + n = s->name; + if(t == 'f') + n++; + lput(v); + if(s->version) + t += 'a' - 'A'; + CPUT(t+0x80); /* 0x80 is variable length */ + + if(t == 'Z' || t == 'z') { + CPUT(n[0]); + for(i=1; n[i] != 0 || n[i+1] != 0; i += 2) { + CPUT(n[i]); + CPUT(n[i+1]); + } + CPUT(0); + CPUT(0); + i++; + } + else { + for(i=0; n[i]; i++) + CPUT(n[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; n[i] != 0 || n[i+1] != 0; i+=2) { + f = ((n[i]&0xff) << 8) | (n[i+1]&0xff); + Bprint(&bso, "/%x", f); + } + Bprint(&bso, "\n"); + return; + } + if(s->version) + Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, n, s->version); + else + Bprint(&bso, "%c %.8lux %s\n", t, v, n); + } +} + +void +asmsym(void) +{ + Prog *p; + Auto *a; + Sym *s; + int h; + + s = lookup("etext", 0); + if(s->type == STEXT) + putsymb(s, 'T', s->value); + s = lookup("a6base", 0); + if(s->type == STEXT) + putsymb(s, 'D', s->value); + + for(h=0; h<NHASH; h++) + for(s=hash[h]; s!=S; s=s->link) + switch(s->type) { + case SDATA: + putsymb(s, 'D', s->value+INITDAT); + continue; + + case SBSS: + putsymb(s, 'B', s->value+INITDAT); + continue; + + case SFILE: + putsymb(s, 'f', s->value); + continue; + } + + for(p=textp; p!=P; p=p->pcond) { + s = p->from.sym; + if(s->type != STEXT) + continue; + + /* filenames first */ + for(a=p->to.autom; a; a=a->link) + if(a->type == D_FILE) + putsymb(a->asym, 'z', a->aoffset); + else + if(a->type == D_FILE1) + putsymb(a->asym, 'Z', a->aoffset); + + putsymb(s, 'T', s->value); + + /* auto and param after */ + for(a=p->to.autom; a; a=a->link) + if(a->type == D_AUTO) + putsymb(a->asym, 'a', -a->aoffset); + else + if(a->type == D_PARAM) + putsymb(a->asym, 'p', a->aoffset); + } + if(debug['v'] || debug['n']) + Bprint(&bso, "symsize = %lud\n", symsize); + Bflush(&bso); +} + +#define MINLC 2 +void +asmsp(void) +{ + long oldpc, oldsp; + Prog *p; + int s; + long v; + + oldpc = INITTEXT; + oldsp = 0; + for(p = firstp; p != P; p = p->link) { + if(p->stkoff == oldsp || p->as == ATEXT || p->as == ANOP) { + if(p->as == ATEXT) + curtext = p; + if(debug['G']) + Bprint(&bso, "%6lux %4ld%P\n", + p->pc, p->stkoff, p); + continue; + } + if(debug['G']) + Bprint(&bso, "\t\t%6ld", spsize); + v = (p->pc - oldpc) / MINLC; + while(v) { + s = 127; + if(v < 127) + s = v; + CPUT(s+128); /* 129-255 +pc */ + if(debug['G']) + Bprint(&bso, " pc+%d*2(%d)", s, s+128); + v -= s; + spsize++; + } + v = p->stkoff - oldsp; + oldsp = p->stkoff; + oldpc = p->pc + MINLC; + if(v & 3 || v > 64L*4L || v < -64L*4L) { + CPUT(0); /* 0 vvvv +sp */ + lput(v); + if(debug['G']) { + if(v > 0) + Bprint(&bso, " sp+%ld*1(%d,%ld)\n", + v, 0, v); + else + Bprint(&bso, " sp%ld*1(%d,%ld)\n", + v, 0, v); + Bprint(&bso, "%6lux %4ld%P\n", + p->pc, p->stkoff, p); + } + spsize += 5; + continue; + } + s = v/4; + if(s > 0) { + CPUT(0+s); /* 1-64 +sp */ + if(debug['G']) { + Bprint(&bso, " sp+%d*4(%d)\n", s, 0+s); + Bprint(&bso, "%6lux %4ld%P\n", + p->pc, p->stkoff, p); + } + } else { + CPUT(64-s); /* 65-128 -sp */ + if(debug['G']) { + Bprint(&bso, " sp%d*4(%d)\n", s, 64-s); + Bprint(&bso, "%6lux %4ld%P\n", + p->pc, p->stkoff, p); + } + } + spsize++; + } + while(spsize & 1) { + s = 129; + CPUT(s); + spsize++; + } + if(debug['v'] || debug['G']) + Bprint(&bso, "stsize = %ld\n", spsize); + Bflush(&bso); +} + +void +asmlc(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); +} |