#include "lib9.h"#include "isa.h"#include "interp.h"#include "raise.h" #define DOT ((ulong)code) #define RESCHED 1 /* check for interpreter reschedule */ enum{ RAX = 0, RAH = 4, RCX = 1, RDX = 2, RBX = 3, RSP = 4, RBP = 5, RSI = 6, RDI = 7, RFP = RSI, RMP = RDI, RTA = RDX, RTMP = RBX, Omovzxb = 0xb6, Omovzxw = 0xb7, Osal = 0xd1, Oaddf = 0xdc, Ocall = 0xe8, Ocallrm = 0xff, Ocdq = 0x99, Ocld = 0xfc, Ocmpb = 0x38, Ocmpw = 0x39, Ocmpi = 0x83, Odecrm = 0xff, Oincr = 0x40, Oincrm = 0xff, Ojccl = 0x83, Ojcsl = 0x82, Ojeqb = 0x74, Ojeql = 0x84, Ojgel = 0x8d, Ojgtl = 0x8f, Ojhil = 0x87, Ojlel = 0x8e, Ojlsl = 0x86, Ojltl = 0x8c, Ojol = 0x80, Ojnol = 0x81, Ojbl = 0x82, Ojael = 0x83, Ojal = 0x87, Ojnel = 0x85, Ojbel = 0x86, Ojneb = 0x75, Ojgtb = 0x7f, Ojgeb = 0x7d, Ojleb = 0x7e, Ojltb = 0x7c, Ojmp = 0xe9, Ojmpb = 0xeb, Ojmprm = 0xff, Oldb = 0x8a, Olds = 0x89, Oldw = 0x8b, Olea = 0x8d, Otestib = 0xf6, Oshld = 0xa5, Oshrd = 0xad, Osar = 0xd3, Osarimm = 0xc1, Omov = 0xc7, Omovf = 0xdd, Omovimm = 0xb8, Omovsb = 0xa4, Orep = 0xf3, Oret = 0xc3, Oshl = 0xd3, Oshr = 0xd1, Ostb = 0x88, Ostw = 0x89, Osubf = 0xdc, Oxchg = 0x87, OxchgAX = 0x90, Oxor = 0x31, Opopl = 0x58, Opushl = 0x50, Opushrm = 0xff, Oneg = 0xf7, 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, MacRELQ = 7, 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 void macrelq(void);static ulong macro[NMACRO]; void (*comvec)(void);extern void das(uchar*, int); #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 */ MacRELQ, macrelq, /* reschedule */}; static voidbounds(void){ error(exBounds);} static voidrdestroy(void){ destroy(R.s);} static voidrmcall(void){ Prog *p; Frame *f; if((void*)R.dt == H) error(exModule); 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; if(t == H) error(exModule); 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 voidurk(void){ error(exCompile);} static voidgenb(uchar o){ *code++ = o;} static voidgen2(uchar o1, uchar o2){ code[0] = o1; code[1] = o2; code += 2;} static voidgenw(ulong o){ *(ulong*)code = o; code += 4;} static voidmodrm(int inst, ulong disp, int rm, int r){ *code++ = inst; if(disp == 0) { *code++ = (0<<6)|(r<<3)|rm; return; } if(bc(disp)) { code[0] = (1<<6)|(r<<3)|rm; code[1] = disp; code += 2; return; } *code++ = (2<<6)|(r<<3)|rm; *(ulong*)code = disp; code += 4;} static voidcon(ulong o, int r){ if(o == 0) { gen2(Oxor, (3<<6)|(r<<3)|r); return; } genb(Omovimm+r); genw(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): con(i->s.imm, r); return; case SRC(AIND|AFP): ir = RFP; break; case SRC(AIND|AMP): ir = RMP; break; } rta = RTA; if(mi == Olea) rta = r; modrm(Oldw, i->s.i.f, ir, rta); modrm(mi, i->s.i.s, rta, r);} static voidopwst(Inst *i, int mi, int r){ int ir, rta; switch(UXDST(i->add)) { default: print("%D\n", i); urk(); case DST(AIMM): con(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 == Olea) rta = r; modrm(Oldw, i->d.i.f, ir, rta); modrm(mi, i->d.i.s, rta, r);} static voidbra(ulong dst, int op){ dst -= (DOT+5); genb(op); genw(dst);} static voidrbra(ulong dst, int op){ dst += (ulong)base; dst -= DOT+5; genb(op); genw(dst);} static voidliteral(ulong imm, int roff){ nlit++; genb(Omovimm+RAX); genw((ulong)litpool); modrm(Ostw, roff, RTMP, RAX); if(pass == 0) return; *litpool = imm; litpool++; } static voidpunt(Inst *i, int m, void (*fn)(void)){ ulong pc; con((ulong)&R, RTMP); if(m & SRCOP) { if(UXSRC(i->add) == SRC(AIMM)) literal(i->s.imm, O(REG, s)); else { opwld(i, Olea, RAX); modrm(Ostw, O(REG, s), RTMP, RAX); } } if(m & DSTOP) { opwst(i, Olea, 0); modrm(Ostw, O(REG, d), RTMP, RAX); } if(m & WRTPC) { modrm(Omov, O(REG, PC), RTMP, 0); pc = patch[i-mod->prog+1]; genw((ulong)base + pc); } if(m & DBRAN) { pc = patch[(Inst*)i->d.imm-mod->prog]; literal((ulong)base+pc, O(REG, d)); } switch(i->add&ARM) { case AXNON: if(m & THREOP) { modrm(Oldw, O(REG, d), RTMP, RAX); modrm(Ostw, O(REG, m), RTMP, RAX); } break; case AXIMM: literal((short)i->reg, O(REG, m)); break; case AXINF: modrm(Olea, i->reg, RFP, RAX); modrm(Ostw, O(REG, m), RTMP, RAX); break; case AXINM: modrm(Olea, i->reg, RMP, RAX); modrm(Ostw, O(REG, m), RTMP, RAX); break; } modrm(Ostw, O(REG, FP), RTMP, RFP); bra((ulong)fn, Ocall); con((ulong)&R, RTMP); if(m & TCHECK) { modrm(Ocmpi, O(REG, t), RTMP, 7);// CMPL $0, R.t genb(0x00); gen2(Ojeqb, 0x06); // JEQ .+6 genb(Opopl+RDI); genb(Opopl+RSI); genb(Opopl+RDX); genb(Opopl+RCX); genb(Opopl+RBX); genb(Oret); } modrm(Oldw, O(REG, FP), RTMP, RFP); modrm(Oldw, O(REG, MP), RTMP, RMP); if(m & NEWPC) { modrm(Oldw, O(REG, PC), RTMP, RAX); gen2(Ojmprm, (3<<6)|(4<<3)|RAX); }} static voidmid(Inst *i, uchar mi, int r){ int ir; switch(i->add&ARM) { default: opwst(i, mi, r); return; case AXIMM: con((short)i->reg, r); return; case AXINF: ir = RFP; break; case AXINM: ir = RMP; break; } modrm(mi, i->reg, ir, r);} static voidarith(Inst *i, int op2, int rm){ if(UXSRC(i->add) != SRC(AIMM)) { if(i->add&ARM) { mid(i, Oldw, RAX); opwld(i, op2|2, 0); opwst(i, Ostw, 0); return; } opwld(i, Oldw, RAX); opwst(i, op2, 0); return; } if(i->add&ARM) { mid(i, Oldw, RAX); if(bc(i->s.imm)) { gen2(0x83, (3<<6)|(rm<<3)|RAX); genb(i->s.imm); } else { gen2(0x81, (3<<6)|(rm<<3)|RAX); genw(i->s.imm);Lines 1–500 of 1975. Load more
#include "lib9.h" #include "isa.h" #include "interp.h" #include "raise.h" #define DOT ((ulong)code) #define RESCHED 1 /* check for interpreter reschedule */ enum { RAX = 0, RAH = 4, RCX = 1, RDX = 2, RBX = 3, RSP = 4, RBP = 5, RSI = 6, RDI = 7, RFP = RSI, RMP = RDI, RTA = RDX, RTMP = RBX, Omovzxb = 0xb6, Omovzxw = 0xb7, Osal = 0xd1, Oaddf = 0xdc, Ocall = 0xe8, Ocallrm = 0xff, Ocdq = 0x99, Ocld = 0xfc, Ocmpb = 0x38, Ocmpw = 0x39, Ocmpi = 0x83, Odecrm = 0xff, Oincr = 0x40, Oincrm = 0xff, Ojccl = 0x83, Ojcsl = 0x82, Ojeqb = 0x74, Ojeql = 0x84, Ojgel = 0x8d, Ojgtl = 0x8f, Ojhil = 0x87, Ojlel = 0x8e, Ojlsl = 0x86, Ojltl = 0x8c, Ojol = 0x80, Ojnol = 0x81, Ojbl = 0x82, Ojael = 0x83, Ojal = 0x87, Ojnel = 0x85, Ojbel = 0x86, Ojneb = 0x75, Ojgtb = 0x7f, Ojgeb = 0x7d, Ojleb = 0x7e, Ojltb = 0x7c, Ojmp = 0xe9, Ojmpb = 0xeb, Ojmprm = 0xff, Oldb = 0x8a, Olds = 0x89, Oldw = 0x8b, Olea = 0x8d, Otestib = 0xf6, Oshld = 0xa5, Oshrd = 0xad, Osar = 0xd3, Osarimm = 0xc1, Omov = 0xc7, Omovf = 0xdd, Omovimm = 0xb8, Omovsb = 0xa4, Orep = 0xf3, Oret = 0xc3, Oshl = 0xd3, Oshr = 0xd1, Ostb = 0x88, Ostw = 0x89, Osubf = 0xdc, Oxchg = 0x87, OxchgAX = 0x90, Oxor = 0x31, Opopl = 0x58, Opushl = 0x50, Opushrm = 0xff, Oneg = 0xf7, 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, MacRELQ = 7, 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 void macrelq(void); static ulong macro[NMACRO]; void (*comvec)(void); extern void das(uchar*, int); #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 */ MacRELQ, macrelq, /* reschedule */ }; static void bounds(void) { error(exBounds); } static void rdestroy(void) { destroy(R.s); } static void rmcall(void) { Prog *p; Frame *f; if((void*)R.dt == H) error(exModule); 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; if(t == H) error(exModule); 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 void urk(void) { error(exCompile); } static void genb(uchar o) { *code++ = o; } static void gen2(uchar o1, uchar o2) { code[0] = o1; code[1] = o2; code += 2; } static void genw(ulong o) { *(ulong*)code = o; code += 4; } static void modrm(int inst, ulong disp, int rm, int r) { *code++ = inst; if(disp == 0) { *code++ = (0<<6)|(r<<3)|rm; return; } if(bc(disp)) { code[0] = (1<<6)|(r<<3)|rm; code[1] = disp; code += 2; return; } *code++ = (2<<6)|(r<<3)|rm; *(ulong*)code = disp; code += 4; } static void con(ulong o, int r) { if(o == 0) { gen2(Oxor, (3<<6)|(r<<3)|r); return; } genb(Omovimm+r); genw(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): con(i->s.imm, r); return; case SRC(AIND|AFP): ir = RFP; break; case SRC(AIND|AMP): ir = RMP; break; } rta = RTA; if(mi == Olea) rta = r; modrm(Oldw, i->s.i.f, ir, rta); modrm(mi, i->s.i.s, rta, r); } static void opwst(Inst *i, int mi, int r) { int ir, rta; switch(UXDST(i->add)) { default: print("%D\n", i); urk(); case DST(AIMM): con(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 == Olea) rta = r; modrm(Oldw, i->d.i.f, ir, rta); modrm(mi, i->d.i.s, rta, r); } static void bra(ulong dst, int op) { dst -= (DOT+5); genb(op); genw(dst); } static void rbra(ulong dst, int op) { dst += (ulong)base; dst -= DOT+5; genb(op); genw(dst); } static void literal(ulong imm, int roff) { nlit++; genb(Omovimm+RAX); genw((ulong)litpool); modrm(Ostw, roff, RTMP, RAX); if(pass == 0) return; *litpool = imm; litpool++; } static void punt(Inst *i, int m, void (*fn)(void)) { ulong pc; con((ulong)&R, RTMP); if(m & SRCOP) { if(UXSRC(i->add) == SRC(AIMM)) literal(i->s.imm, O(REG, s)); else { opwld(i, Olea, RAX); modrm(Ostw, O(REG, s), RTMP, RAX); } } if(m & DSTOP) { opwst(i, Olea, 0); modrm(Ostw, O(REG, d), RTMP, RAX); } if(m & WRTPC) { modrm(Omov, O(REG, PC), RTMP, 0); pc = patch[i-mod->prog+1]; genw((ulong)base + pc); } if(m & DBRAN) { pc = patch[(Inst*)i->d.imm-mod->prog]; literal((ulong)base+pc, O(REG, d)); } switch(i->add&ARM) { case AXNON: if(m & THREOP) { modrm(Oldw, O(REG, d), RTMP, RAX); modrm(Ostw, O(REG, m), RTMP, RAX); } break; case AXIMM: literal((short)i->reg, O(REG, m)); break; case AXINF: modrm(Olea, i->reg, RFP, RAX); modrm(Ostw, O(REG, m), RTMP, RAX); break; case AXINM: modrm(Olea, i->reg, RMP, RAX); modrm(Ostw, O(REG, m), RTMP, RAX); break; } modrm(Ostw, O(REG, FP), RTMP, RFP); bra((ulong)fn, Ocall); con((ulong)&R, RTMP); if(m & TCHECK) { modrm(Ocmpi, O(REG, t), RTMP, 7);// CMPL $0, R.t genb(0x00); gen2(Ojeqb, 0x06); // JEQ .+6 genb(Opopl+RDI); genb(Opopl+RSI); genb(Opopl+RDX); genb(Opopl+RCX); genb(Opopl+RBX); genb(Oret); } modrm(Oldw, O(REG, FP), RTMP, RFP); modrm(Oldw, O(REG, MP), RTMP, RMP); if(m & NEWPC) { modrm(Oldw, O(REG, PC), RTMP, RAX); gen2(Ojmprm, (3<<6)|(4<<3)|RAX); } } static void mid(Inst *i, uchar mi, int r) { int ir; switch(i->add&ARM) { default: opwst(i, mi, r); return; case AXIMM: con((short)i->reg, r); return; case AXINF: ir = RFP; break; case AXINM: ir = RMP; break; } modrm(mi, i->reg, ir, r); } static void arith(Inst *i, int op2, int rm) { if(UXSRC(i->add) != SRC(AIMM)) { if(i->add&ARM) { mid(i, Oldw, RAX); opwld(i, op2|2, 0); opwst(i, Ostw, 0); return; } opwld(i, Oldw, RAX); opwst(i, op2, 0); return; } if(i->add&ARM) { mid(i, Oldw, RAX); if(bc(i->s.imm)) { gen2(0x83, (3<<6)|(rm<<3)|RAX); genb(i->s.imm); } else { gen2(0x81, (3<<6)|(rm<<3)|RAX); genw(i->s.imm);