📄 asm.c
字号:
#include "l.h"short opa[20];short *op;longentryvalue(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;}voidasmb(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();}voidasmins(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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -