#include "lib9.h"#include "isa.h"#include "interp.h"#include "raise.h" enum{ RAX = 0, RCX = 1, /* Be careful with RCX, smashed in bra() */ RTA = 2, RTMP = 3, RFP = 4, RMP = 5, R7 = 7, DTMP = 0, DTMP1 = 1, DTMP2 = 2, DTMP3 = 3, Oadd = 0xD000, OaddaR = 0xD1E8, /* ADDA (d16,Rr), Rr */ Oaddi = 0x0600, OaddRD = 0xD0A8, OaslbD = 0xE120, OaslwD = 0xE1A0, OasrbD = 0xE020, OasrwD = 0xE0A0, Oand = 0xC000, Oandi = 0x0200, Obra = 0x6000, Obsr = 0x6100, OclrwD = 0x4280, OcmpiwR = 0x0CA8, /* cmpi.l offset(Rrm), imm.long */ OcmpwR = 0xB1E8, /* cmpa $offset(Rrm), Rr */ OcmpbD = 0xB028, /* cmp.b $offset(Rrm), Dr */ OcmpwD = 0xB0A8, /* cmp.l $offset(Rx), Dr */ OcmpwDD = 0xB080, /* cmp.l Dr, Dx */ Odbeq = 0x57C8, OdecrwRind = 0x53A8, /* SUBQ.L $0x1, offset(Rr) */ Odivs = 0x81C0, Oeor = 0xB000, Oeori = 0x0A00, OexgRR = 0xC148, /* exg Rx, Ry */ Oextw = 0x4880, /* EXT.W Dx extend byte to 16-bit */ Oextbw = 0x49C0, /* EXTB.L Dx extend byte to 32-bit */ OincrwR = 0x5288, /* ADDQ.L $0x1, Rr */ OincrwRind = 0x52A8, /* ADDQ.L $0x1, offset(Rr) */ Ojhi = 0x6200, /* BHI */ Ojhs = 0x6400, /* BCC(HS) */ Ojlo = 0x6500, /* BCS(LO) */ Ojls = 0x6300, /* BLS */ Ojeq = 0x6700, /* BEQ */ Ojge = 0x6C00, /* BGE */ Ojgt = 0x6E00, /* BGT */ Ojle = 0x6F00, /* BLE */ Ojlt = 0x6D00, /* BLT */ Ojne = 0x6600, /* BNE */ OjmpRind= 0x4ED0, /* jmp (Rn) */ OjmpRindoffs= 0x4EE8, /* jmp $offs(Rn) */ OjsrRind= 0x4E90, OldbD = 0x1028, /* $offset(Rrm).b -> Dr */ OldbR = 0x1058, /* $offset(Rrm).b -> Rr */ OldwD = 0x2028, /* $offset(Rrm) -> Dr */ OldwR = 0x2068, /* $offset(Rrm) -> Rr */ OleaR = 0x41E8, /* addr($offset(Rrm) -> Rr */ OlslD = 0xE388, Olsl2D = 0xE588, OlsrD = 0xE288, OlslbD = 0xE128, OlslwD = 0xE1A8, OlsrbD = 0xE028, OlsrwD = 0xE0A8, OmovelitwR= 0x207C, /* move $xx, Rr */ OmovelitwD= 0x203C, /* move $xx, Dr */ Omoveal = 0x2040, OmovwR = 0x217C, /* imm.long -> $offset(Rrm) */ OmovwRR = 0x2048, /* movea.l Rr, Rx */ OmovwRD = 0x2008, /* move.l Rr, Dx */ Omuls = 0xC1C0, OnegwD = 0x4480, Oor = 0x8000, Oori = 0x0000, OpopwR = 0x205F, /* MOVEA.L (A7)+, Rr */ OpushwR = 0x2F08, /* MOVE.L Rr, -(A7) */ Opushil = 0x2F3C, /* MOVE.L imm., -(A7) */ OroxlD = 0xE390, OroxrD = 0xE290, Orts = 0x4E75, OstbD = 0x1140, /* Dr.b -> $offset(Rrm) !!!!! ostbR does NOT exist */ OstwD = 0x2140, /* Dr -> $offset(Rrm) */ OstwR = 0x2148, /* Rr -> $offset(Rrm) */ Osub = 0x9000, Osubi = 0x0400, OaddqwR = 0x5088, Oswap = 0x4840, OtstbD = 0x4A00, /* tst.b Dr */ OtstwR = 0x4AA8, /* tst.l $offset(Rx) */ Oill = 0x4afc, /* illegal instruction trap */ Onop = 0x4E71, SRCOP = (1<<0), DSTOP = (1<<1), WRTPC = (1<<2), TCHECK = (1<<3), NEWPC = (1<<4), DBRAN = (1<<5), THREOP = (1<<6), ANDAND = 1, OROR = 2, EQAND = 3, MacFRP = 0, MacRET = 1, MacCASE = 2, MacCOLR = 3, MacMCAL = 4, MacFRAM = 5, MacMFRA = 6, NMACRO}; static uchar* code;static uchar* base;static ulong* patch;static int pass;static Module* mod;static uchar* tinit;static ulong* litpool;static int nlit;static void macfrp(void);static void macret(void);static void maccase(void);static void maccolr(void);static void macmcal(void);static void macfram(void);static void macmfra(void);static ulong macro[NMACRO]; void (*comvec)(void);extern void das(uchar*, int); extern void _mull(void);extern void _divsl(void); #define T(r) *((void**)(R.r)) struct{ int idx; void (*gen)(void);} mactab[] ={ MacFRP, macfrp, /* decrement and free pointer */ MacRET, macret, /* return instruction */ MacCASE, maccase, /* case instruction */ MacCOLR, maccolr, /* increment and color pointer */ MacMCAL, macmcal, /* mcall bottom half */ MacFRAM, macfram, /* frame instruction */ MacMFRA, macmfra, /* punt mframe because t->initialize==0 */}; static voidrdestroy(void){ destroy(R.s);} static voidrmcall(void){ Prog *p; Frame *f; f = (Frame*)R.FP; if(f == H) error(exModule); f->mr = nil; ((void(*)(Frame*))R.dt)(f); R.SP = (uchar*)f; R.FP = f->fp; if(f->t == nil) unextend(f); else freeptrs(f, f->t); p = currun(); if(p->kill != nil) error(p->kill);} static voidrmfram(void){ Type *t; Frame *f; uchar *nsp; t = (Type*)R.s; nsp = R.SP + t->size; if(nsp >= R.TS) { R.s = t; extend(); T(d) = R.s; return; } f = (Frame*)R.SP; R.SP = nsp; f->t = t; f->mr = nil; initmem(t, f); T(d) = f;} static intbc(int o){ if(o < 127 && o > -128) return 1; return 0;} static intwc(int o){ if(o < 65535 && o > -65536) return 1; return 0;} static voidurk(void){ error(exCompile);} static voidgen2(uchar o1, uchar o2){ code[0] = o1; code[1] = o2; code += 2;} static voidgenw(ulong o){ code[0] = (o>>8)&0xFF; code[1] = o&0xFF; code += 2;} static voidgenl(ulong o){ *(ulong*)code = o; code += 4;} static voidmodrm(int inst, ulong disp, int rm, int r){ switch (inst) { case OstwD: case OstwR: case OstbD: if (!disp) { inst&=0xfe3f; inst|=0x0080; } genw(inst | (rm<<9) | r); if (disp) genw(disp); break; case Oadd|0x28|(0x6<<6): case Oadd|0x28|(0x4<<6): case Osub|0x28|(0x6<<6): case Osub|0x28|(0x4<<6): case Oor|0x28|(0x6<<6): case Oor|0x28|(0x4<<6): case Oand|0x28|(0x6<<6): case Oand|0x28|(0x4<<6): case Oeor|0x28|(0x6<<6): case Oeor|0x28|(0x4<<6): case Oaddi|0x28|(0x2<<6): case Oori|0x28|(0x2<<6): case Oandi|0x28|(0x2<<6): case Oeori|0x28|(0x2<<6): case Osubi|0x28|(0x2<<6): case Oaddi|0x28: case Oori|0x28: case Oandi|0x28: case Oeori|0x28: case Osubi|0x28: case OldbD: case OldwD: case OldwR: case OldbR: case OleaR: case OaddRD: case OcmpwR: case OcmpwD: case OcmpbD: case OdecrwRind: case OincrwRind: case OtstwR: if (!disp) { inst&=0xffc7; inst|=0x0010; } genw(inst | (r<<9) | rm); if (disp) genw(disp); break; default: print("modrm: urk on opcode 0x%ux\n",inst); urk(); }} static voidconR(ulong o, int r){ if(o == 0) { genw(0x91C8|(r<<9)|r); /* SUBA Rr, Rr */ return; } genw(Omoveal|(r<<9)|0x7C); /* MOVEA.L $o,Rr */ genl(o);} static voidconD(ulong o, int r){ if(o == 0) { genw(OclrwD|r); /* CLR.L Dr */ return; } genw(OmovelitwD|(r<<9)); /* MOVEA.L $o,Dr */ genl(o);} static voidopwld(Inst *i, int mi, int r){ int ir, rta; switch(UXSRC(i->add)) { default: print("%D\n", i); urk(); case SRC(AFP): modrm(mi, i->s.ind, RFP, r); return; case SRC(AMP): modrm(mi, i->s.ind, RMP, r); return; case SRC(AIMM): conR(i->s.imm, r); return; case SRC(AIND|AFP): ir = RFP; break; case SRC(AIND|AMP): ir = RMP; break; } rta = RTA; if(mi == OleaR) rta = r; modrm(OldwR, i->s.i.f, ir, rta); modrm(mi, i->s.i.s, rta, r);} static voidopwldD(Inst *i, int mi, int r){ int ir, rta; switch(UXSRC(i->add)) { default: print("%D\n", i); urk(); case SRC(AFP): modrm(mi, i->s.ind, RFP, r); return; case SRC(AMP): modrm(mi, i->s.ind, RMP, r); return; case SRC(AIMM): conD(i->s.imm, r); return; case SRC(AIND|AFP): ir = RFP; break; case SRC(AIND|AMP): ir = RMP; break; } rta = RTA; modrm(OldwR, i->s.i.f, ir, rta); modrm(mi, i->s.i.s, rta, r);} static intopwst(Inst *i, int mi, int r){ int ir, rta; switch(UXDST(i->add)) { default: print("%D\n", i); urk(); case DST(AIMM): conR(i->d.imm, r); return 0; case DST(AFP): modrm(mi, i->d.ind, RFP, r); return i->d.ind; case DST(AMP): modrm(mi, i->d.ind, RMP, r); return i->d.ind; case DST(AIND|AFP): ir = RFP; break; case DST(AIND|AMP): ir = RMP; break; } rta = RTA; if(mi == OleaR) rta = r; modrm(OldwR, i->d.i.f, ir, rta); modrm(mi, i->d.i.s, rta, r); return i->d.i.s;} static voidopwstD(Inst *i, int mi, int r){ int ir, rta; switch(UXDST(i->add)) { default: print("%D\n", i); urk(); case DST(AIMM): conD(i->d.imm, r); return; case DST(AFP): modrm(mi, i->d.ind, RFP, r); return; case DST(AMP): modrm(mi, i->d.ind, RMP, r); return; case DST(AIND|AFP): ir = RFP; break; case DST(AIND|AMP): ir = RMP; break; } rta = RTA; if(mi == OleaR) rta = r; modrm(OldwR, i->d.i.f, ir, rta); modrm(mi, i->d.i.s, rta, r);} static intswapbraop(int b){ switch(b) { case Ojge: return Ojlt; case Ojle: return Ojgt; case Ojgt: return Ojle; case Ojlt: return Ojge; case Ojhi: return Ojls; case Ojlo: return Ojhs; case Ojhs: return Ojlo; case Ojls: return Ojhi; case Ojeq: return Ojne; case Ojne: return Ojeq; } return b;} static voidbra(ulong dst, int op){ ulong ddst; switch (op) { case Obsr:Lines 1–500 of 2074. Load more
#include "lib9.h" #include "isa.h" #include "interp.h" #include "raise.h" enum { RAX = 0, RCX = 1, /* Be careful with RCX, smashed in bra() */ RTA = 2, RTMP = 3, RFP = 4, RMP = 5, R7 = 7, DTMP = 0, DTMP1 = 1, DTMP2 = 2, DTMP3 = 3, Oadd = 0xD000, OaddaR = 0xD1E8, /* ADDA (d16,Rr), Rr */ Oaddi = 0x0600, OaddRD = 0xD0A8, OaslbD = 0xE120, OaslwD = 0xE1A0, OasrbD = 0xE020, OasrwD = 0xE0A0, Oand = 0xC000, Oandi = 0x0200, Obra = 0x6000, Obsr = 0x6100, OclrwD = 0x4280, OcmpiwR = 0x0CA8, /* cmpi.l offset(Rrm), imm.long */ OcmpwR = 0xB1E8, /* cmpa $offset(Rrm), Rr */ OcmpbD = 0xB028, /* cmp.b $offset(Rrm), Dr */ OcmpwD = 0xB0A8, /* cmp.l $offset(Rx), Dr */ OcmpwDD = 0xB080, /* cmp.l Dr, Dx */ Odbeq = 0x57C8, OdecrwRind = 0x53A8, /* SUBQ.L $0x1, offset(Rr) */ Odivs = 0x81C0, Oeor = 0xB000, Oeori = 0x0A00, OexgRR = 0xC148, /* exg Rx, Ry */ Oextw = 0x4880, /* EXT.W Dx extend byte to 16-bit */ Oextbw = 0x49C0, /* EXTB.L Dx extend byte to 32-bit */ OincrwR = 0x5288, /* ADDQ.L $0x1, Rr */ OincrwRind = 0x52A8, /* ADDQ.L $0x1, offset(Rr) */ Ojhi = 0x6200, /* BHI */ Ojhs = 0x6400, /* BCC(HS) */ Ojlo = 0x6500, /* BCS(LO) */ Ojls = 0x6300, /* BLS */ Ojeq = 0x6700, /* BEQ */ Ojge = 0x6C00, /* BGE */ Ojgt = 0x6E00, /* BGT */ Ojle = 0x6F00, /* BLE */ Ojlt = 0x6D00, /* BLT */ Ojne = 0x6600, /* BNE */ OjmpRind= 0x4ED0, /* jmp (Rn) */ OjmpRindoffs= 0x4EE8, /* jmp $offs(Rn) */ OjsrRind= 0x4E90, OldbD = 0x1028, /* $offset(Rrm).b -> Dr */ OldbR = 0x1058, /* $offset(Rrm).b -> Rr */ OldwD = 0x2028, /* $offset(Rrm) -> Dr */ OldwR = 0x2068, /* $offset(Rrm) -> Rr */ OleaR = 0x41E8, /* addr($offset(Rrm) -> Rr */ OlslD = 0xE388, Olsl2D = 0xE588, OlsrD = 0xE288, OlslbD = 0xE128, OlslwD = 0xE1A8, OlsrbD = 0xE028, OlsrwD = 0xE0A8, OmovelitwR= 0x207C, /* move $xx, Rr */ OmovelitwD= 0x203C, /* move $xx, Dr */ Omoveal = 0x2040, OmovwR = 0x217C, /* imm.long -> $offset(Rrm) */ OmovwRR = 0x2048, /* movea.l Rr, Rx */ OmovwRD = 0x2008, /* move.l Rr, Dx */ Omuls = 0xC1C0, OnegwD = 0x4480, Oor = 0x8000, Oori = 0x0000, OpopwR = 0x205F, /* MOVEA.L (A7)+, Rr */ OpushwR = 0x2F08, /* MOVE.L Rr, -(A7) */ Opushil = 0x2F3C, /* MOVE.L imm., -(A7) */ OroxlD = 0xE390, OroxrD = 0xE290, Orts = 0x4E75, OstbD = 0x1140, /* Dr.b -> $offset(Rrm) !!!!! ostbR does NOT exist */ OstwD = 0x2140, /* Dr -> $offset(Rrm) */ OstwR = 0x2148, /* Rr -> $offset(Rrm) */ Osub = 0x9000, Osubi = 0x0400, OaddqwR = 0x5088, Oswap = 0x4840, OtstbD = 0x4A00, /* tst.b Dr */ OtstwR = 0x4AA8, /* tst.l $offset(Rx) */ Oill = 0x4afc, /* illegal instruction trap */ Onop = 0x4E71, SRCOP = (1<<0), DSTOP = (1<<1), WRTPC = (1<<2), TCHECK = (1<<3), NEWPC = (1<<4), DBRAN = (1<<5), THREOP = (1<<6), ANDAND = 1, OROR = 2, EQAND = 3, MacFRP = 0, MacRET = 1, MacCASE = 2, MacCOLR = 3, MacMCAL = 4, MacFRAM = 5, MacMFRA = 6, NMACRO }; static uchar* code; static uchar* base; static ulong* patch; static int pass; static Module* mod; static uchar* tinit; static ulong* litpool; static int nlit; static void macfrp(void); static void macret(void); static void maccase(void); static void maccolr(void); static void macmcal(void); static void macfram(void); static void macmfra(void); static ulong macro[NMACRO]; void (*comvec)(void); extern void das(uchar*, int); extern void _mull(void); extern void _divsl(void); #define T(r) *((void**)(R.r)) struct { int idx; void (*gen)(void); } mactab[] = { MacFRP, macfrp, /* decrement and free pointer */ MacRET, macret, /* return instruction */ MacCASE, maccase, /* case instruction */ MacCOLR, maccolr, /* increment and color pointer */ MacMCAL, macmcal, /* mcall bottom half */ MacFRAM, macfram, /* frame instruction */ MacMFRA, macmfra, /* punt mframe because t->initialize==0 */ }; static void rdestroy(void) { destroy(R.s); } static void rmcall(void) { Prog *p; Frame *f; f = (Frame*)R.FP; if(f == H) error(exModule); f->mr = nil; ((void(*)(Frame*))R.dt)(f); R.SP = (uchar*)f; R.FP = f->fp; if(f->t == nil) unextend(f); else freeptrs(f, f->t); p = currun(); if(p->kill != nil) error(p->kill); } static void rmfram(void) { Type *t; Frame *f; uchar *nsp; t = (Type*)R.s; nsp = R.SP + t->size; if(nsp >= R.TS) { R.s = t; extend(); T(d) = R.s; return; } f = (Frame*)R.SP; R.SP = nsp; f->t = t; f->mr = nil; initmem(t, f); T(d) = f; } static int bc(int o) { if(o < 127 && o > -128) return 1; return 0; } static int wc(int o) { if(o < 65535 && o > -65536) return 1; return 0; } static void urk(void) { error(exCompile); } static void gen2(uchar o1, uchar o2) { code[0] = o1; code[1] = o2; code += 2; } static void genw(ulong o) { code[0] = (o>>8)&0xFF; code[1] = o&0xFF; code += 2; } static void genl(ulong o) { *(ulong*)code = o; code += 4; } static void modrm(int inst, ulong disp, int rm, int r) { switch (inst) { case OstwD: case OstwR: case OstbD: if (!disp) { inst&=0xfe3f; inst|=0x0080; } genw(inst | (rm<<9) | r); if (disp) genw(disp); break; case Oadd|0x28|(0x6<<6): case Oadd|0x28|(0x4<<6): case Osub|0x28|(0x6<<6): case Osub|0x28|(0x4<<6): case Oor|0x28|(0x6<<6): case Oor|0x28|(0x4<<6): case Oand|0x28|(0x6<<6): case Oand|0x28|(0x4<<6): case Oeor|0x28|(0x6<<6): case Oeor|0x28|(0x4<<6): case Oaddi|0x28|(0x2<<6): case Oori|0x28|(0x2<<6): case Oandi|0x28|(0x2<<6): case Oeori|0x28|(0x2<<6): case Osubi|0x28|(0x2<<6): case Oaddi|0x28: case Oori|0x28: case Oandi|0x28: case Oeori|0x28: case Osubi|0x28: case OldbD: case OldwD: case OldwR: case OldbR: case OleaR: case OaddRD: case OcmpwR: case OcmpwD: case OcmpbD: case OdecrwRind: case OincrwRind: case OtstwR: if (!disp) { inst&=0xffc7; inst|=0x0010; } genw(inst | (r<<9) | rm); if (disp) genw(disp); break; default: print("modrm: urk on opcode 0x%ux\n",inst); urk(); } } static void conR(ulong o, int r) { if(o == 0) { genw(0x91C8|(r<<9)|r); /* SUBA Rr, Rr */ return; } genw(Omoveal|(r<<9)|0x7C); /* MOVEA.L $o,Rr */ genl(o); } static void conD(ulong o, int r) { if(o == 0) { genw(OclrwD|r); /* CLR.L Dr */ return; } genw(OmovelitwD|(r<<9)); /* MOVEA.L $o,Dr */ genl(o); } static void opwld(Inst *i, int mi, int r) { int ir, rta; switch(UXSRC(i->add)) { default: print("%D\n", i); urk(); case SRC(AFP): modrm(mi, i->s.ind, RFP, r); return; case SRC(AMP): modrm(mi, i->s.ind, RMP, r); return; case SRC(AIMM): conR(i->s.imm, r); return; case SRC(AIND|AFP): ir = RFP; break; case SRC(AIND|AMP): ir = RMP; break; } rta = RTA; if(mi == OleaR) rta = r; modrm(OldwR, i->s.i.f, ir, rta); modrm(mi, i->s.i.s, rta, r); } static void opwldD(Inst *i, int mi, int r) { int ir, rta; switch(UXSRC(i->add)) { default: print("%D\n", i); urk(); case SRC(AFP): modrm(mi, i->s.ind, RFP, r); return; case SRC(AMP): modrm(mi, i->s.ind, RMP, r); return; case SRC(AIMM): conD(i->s.imm, r); return; case SRC(AIND|AFP): ir = RFP; break; case SRC(AIND|AMP): ir = RMP; break; } rta = RTA; modrm(OldwR, i->s.i.f, ir, rta); modrm(mi, i->s.i.s, rta, r); } static int opwst(Inst *i, int mi, int r) { int ir, rta; switch(UXDST(i->add)) { default: print("%D\n", i); urk(); case DST(AIMM): conR(i->d.imm, r); return 0; case DST(AFP): modrm(mi, i->d.ind, RFP, r); return i->d.ind; case DST(AMP): modrm(mi, i->d.ind, RMP, r); return i->d.ind; case DST(AIND|AFP): ir = RFP; break; case DST(AIND|AMP): ir = RMP; break; } rta = RTA; if(mi == OleaR) rta = r; modrm(OldwR, i->d.i.f, ir, rta); modrm(mi, i->d.i.s, rta, r); return i->d.i.s; } static void opwstD(Inst *i, int mi, int r) { int ir, rta; switch(UXDST(i->add)) { default: print("%D\n", i); urk(); case DST(AIMM): conD(i->d.imm, r); return; case DST(AFP): modrm(mi, i->d.ind, RFP, r); return; case DST(AMP): modrm(mi, i->d.ind, RMP, r); return; case DST(AIND|AFP): ir = RFP; break; case DST(AIND|AMP): ir = RMP; break; } rta = RTA; if(mi == OleaR) rta = r; modrm(OldwR, i->d.i.f, ir, rta); modrm(mi, i->d.i.s, rta, r); } static int swapbraop(int b) { switch(b) { case Ojge: return Ojlt; case Ojle: return Ojgt; case Ojgt: return Ojle; case Ojlt: return Ojge; case Ojhi: return Ojls; case Ojlo: return Ojhs; case Ojhs: return Ojlo; case Ojls: return Ojhi; case Ojeq: return Ojne; case Ojne: return Ojeq; } return b; } static void bra(ulong dst, int op) { ulong ddst; switch (op) { case Obsr: