ref: eae58edb5a6f912d3fd06c96e01499ba46f730da
dir: /sys/src/cmd/2l/asm.c/
#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 %lux sb %lux 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; 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; } 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(); } 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; } cflush(); } void asmins(Prog *p) { Optab *o; int t, a, b; long v; Prog *q; 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); /* hack to turn 3-word bsr into 2-word jsr */ if(a == 0xff && p->as == ABSR && p->pcond->pc < 32768L && p->pcond->pc >= 0) { op = opa + 1; t = o->opcode1; *op++ = p->pcond->pc; break; } 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 33: /* bcase */ q = copyp(p); q->as = ADATA; q->to.type = D_CONST; q->to.offset = p->pcond->pc - casepc - 2; q->from.displace = 2; q->link = datap; datap = q; if(debug['a']) Bprint(&bso, "%P\n", q); op = opa; return; 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; short *top; long v; if(a->index != D_NONE) goto index; 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) */ } *op++ = 0x170; /* is, no indirect */ *op++ = v>>16; *op++ = v; return t-D_A0-I_INDIR+060; /* (d,Ax) */ } 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) { *op++ = v>>16; *op++ = v; return 0xff; } 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; 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) */ } *op++ = 0x170; /* is, no indirect */ *op++ = v>>16; *op++ = v; return (6<<3) | 7; /* (d,A7) */ case I_INDIR|D_CONST: goto adr; 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) { v = a->sym->value + a->offset; *op++ = v>>16; *op++ = v; return (7<<3) | 1; } v = a->sym->value + a->offset - A6OFFSET; if(debug['6']) { v += INITDAT + A6OFFSET; goto adr; } if(v == 0) return (2<<3) | 6; if(v >= -32768L && v < 32768L) { *op++ = v; return (5<<3) | 6; } v += INITDAT + A6OFFSET; adr: if(v >= -32768L && v < 32768L) { *op++ = v; return (7<<3) | 0; } *op++ = v>>16; *op++ = v; return (7<<3) | 1; } if(!debug['a']) print("%P\n", p); diag("unknown addressing mode: %d in %s", t, TNAME); return 0; index: top = op++; t = a->index & D_MASK; f = (a->scale & 7) << 9; /* w/l scale */ f |= (t & 7) << 12; /* register */ if(t < D_R0 || t >= D_R0+8) { if(t >= D_A0 && t < D_A0+8) { f |= 0x8000; /* d/a */ } else if(t == D_NONE) f = 0x40; /* is */ else goto bad; } t = a->type; r = t & 7; v = a->offset; if(t < (I_INDIR|D_A0) || t >= (I_INDIR|(D_A0+8))) switch(t) { default: goto bad; case I_INDIR|D_NONE: f |= 0x80; /* bs */ r = 0; break; case D_AUTO: case D_PARAM: case D_STACK: r = 7; break; 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; } r = 6; v += a->sym->value - A6OFFSET; if(t == STEXT) { f |= 0x80; /* bs */ r = 0; v += A6OFFSET; goto bdlong; } if(debug['6']) { f |= 0x80; /* bs */ r = 0; v += INITDAT + A6OFFSET; } } if(v == 0) f |= 0x10; /* bd size = null */ else if(v >= -32768L && v < 32768L) { f |= 0x20; /* bd size = word */ *op++ = v; } else { bdlong: f |= 0x30; /* bd size = long */ *op++ = v>>16; *op++ = v; } v = a->displace; t = a->index & I_MASK; if(t != I_INDEX1) { /* non-memory index */ if(t == I_INDEX2) f |= 5; /* post indexing */ else if(t == I_INDEX3) f |= 1; /* pre indexing */ else goto bad; } if(v != 0) { if(v >= -32768L && v < 32768L) { f++; /* is size = word */ *op++ = v; } else { f += 2; /* is size = long */ *op++ = v>>16; *op++ = v; } } *top = f | 0x100; return (6<<3) | r; bad: if(!debug['a']) print("%P\n", p); diag("bad operand in %s", 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, "%lux:%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, "%lux:%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, "%lux:%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, "%lux:%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); } 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; }