#include #include #include "8i.h" typedef struct Optab Optab; struct Optab { uchar op; uchar arg1; uchar arg2; uchar arg3; }; static uchar needmodrm[NAMODE] = { [AEb] 1, [AEv] 1, [AGb] 1, [AGv] 1, [AM] 1, [AMp] 1, [ASw] 1, }; static uchar small[NAMODE] = { [ANONE] 1, [AEb] 1, [AGb] 1, [AOb] 1, [AXb] 1, [AYb] 1, [AIb] 1, [AAL] 1, [ABL] 1, [ACL] 1, [ADL] 1, [AAH] 1, [ABH] 1, [ACH] 1, [ADH] 1, }; static Optab optab[256] = { //00 {OADD, AEb, AGb}, {OADD, AEv, AGv}, {OADD, AGb, AEb}, {OADD, AGv, AEv}, {OADD, AAL, AIb}, {OADD, AAX, AIv}, {OPUSH, AES, }, {OPOP, AES }, {OOR, AEb, AGb}, {OOR, AEv, AGv}, {OOR, AGb, AEb}, {OOR, AGv, AEv}, {OOR, AAL, AIb}, {OOR, AAX, AIv}, {OPUSH, ACS, }, {O0F, }, //10 {OADC, AEb, AGb}, {OADC, AEv, AGv}, {OADC, AGb, AEb}, {OADC, AGv, AEv}, {OADC, AAL, AIb}, {OADC, AAX, AIv}, {OPUSH, ASS, }, {OPOP, ASS, }, {OSBB, AEb, AGb}, {OSBB, AEv, AGv}, {OSBB, AGb, AEb}, {OSBB, AGv, AEv}, {OSBB, AAL, AIb}, {OSBB, AAX, AIv}, {OPUSH, ADS, }, {OPOP, ADS, }, //20 {OAND, AEb, AGb}, {OAND, AEv, AGv}, {OAND, AGb, AEb}, {OAND, AGv, AEv}, {OAND, AAL, AIb}, {OAND, AAX, AIv}, {OSEG, AES, }, {ODAA, }, {OSUB, AEb, AGb}, {OSUB, AEv, AGv}, {OSUB, AGb, AEb}, {OSUB, AGv, AEv}, {OSUB, AAL, AIb}, {OSUB, AAX, AIv}, {OSEG, ACS, }, {ODAS, }, //30 {OXOR, AEb, AGb}, {OXOR, AEv, AGv}, {OXOR, AGb, AEb}, {OXOR, AGv, AEv}, {OXOR, AAL, AIb}, {OXOR, AAX, AIv}, {OSEG, ASS, }, {OAAA, }, {OCMP, AEb, AGb}, {OCMP, AEv, AGv}, {OCMP, AGb, AEb}, {OCMP, AGv, AEv}, {OCMP, AAL, AIb}, {OCMP, AAX, AIv}, {OSEG, ADS, }, {OAAS, }, //40 {OINC, AAX, }, {OINC, ACX, }, {OINC, ADX, }, {OINC, ABX, }, {OINC, ASP, }, {OINC, ABP, }, {OINC, ASI, }, {OINC, ADI, }, {ODEC, AAX, }, {ODEC, ACX, }, {ODEC, ADX, }, {ODEC, ABX, }, {ODEC, ASP, }, {ODEC, ABP, }, {ODEC, ASI, }, {ODEC, ADI, }, //50 {OPUSH, AAX, }, {OPUSH, ACX, }, {OPUSH, ADX, }, {OPUSH, ABX, }, {OPUSH, ASP, }, {OPUSH, ABP, }, {OPUSH, ASI, }, {OPUSH, ADI, }, {OPOP, AAX, }, {OPOP, ACX, }, {OPOP, ADX, }, {OPOP, ABX, }, {OPOP, ASP, }, {OPOP, ABP, }, {OPOP, ASI, }, {OPOP, ADI, }, //60 {OPUSHA, }, {OPOPA, }, {OBOUND,AGv,AMa,AMa2}, {OARPL, AEw, AGw}, {OSEG, AFS, }, {OSEG, AGS, }, {OOSIZE, }, {OASIZE, }, {OPUSH, AIv, }, {OIMUL,AGv,AEv,AIv},{OPUSH, AIb, }, {OIMUL,AGv,AEv,AIb}, {OINS, AYb, ADX}, {OINS, AYv, ADX}, {OOUTS, ADX, AXb}, {OOUTS, ADX, AXv}, //70 {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, //80 {OGP1, AEb, AIb}, {OGP1, AEv, AIv}, {OGP1, AEv, AIc}, {OGP1, AEv, AIc}, {OTEST, AEb, AGb}, {OTEST, AEv, AGv}, {OXCHG, AEb, AGb}, {OXCHG, AEv, AGv}, {OMOV, AEb, AGb}, {OMOV, AEv, AGv}, {OMOV, AGb, AEb}, {OMOV, AGv, AEv}, {OMOV, AEw, ASw}, {OLEA, AGv, AM }, {OMOV, ASw, AEw}, {OPOP, AEv, }, //90 {ONOP, }, {OXCHG, AAX, ACX}, {OXCHG, AAX, ADX}, {OXCHG, AAX, ABX}, {OXCHG, AAX, ASP}, {OXCHG, AAX, ABP}, {OXCHG, AAX, ASI}, {OXCHG, AAX, ADI}, {OCBW, }, {OCWD, }, {OCALL, AAp, }, {OWAIT, }, {OPUSHF,AFv, }, {OPOPF, AFv, }, {OSAHF, AAH, }, {OLAHF, AAH, }, //A0 {OMOV, AAL, AOb}, {OMOV, AAX, AOv}, {OMOV, AOb, AAL}, {OMOV, AOv, AAX}, {OMOVS, AXb, AYb}, {OMOVS, AXv, AYv}, {OCMPS, AXb, AYb}, {OCMPS, AXv, AYv}, {OTEST, AAL, AIb}, {OTEST, AAX, AIv}, {OSTOS, AYb, AAL}, {OSTOS, AYv, AAX}, {OLODS, AAL, AXb}, {OLODS, AAX, AXv}, {OSCAS, AAL, AYb}, {OSCAS, AAX, AYv}, //B0 {OMOV, AAL, AIb}, {OMOV, ACL, AIb}, {OMOV, ADL, AIb}, {OMOV, ABL, AIb}, {OMOV, AAH, AIb}, {OMOV, ACH, AIb}, {OMOV, ADH, AIb}, {OMOV, ABH, AIb}, {OMOV, AAX, AIv}, {OMOV, ACX, AIv}, {OMOV, ADX, AIv}, {OMOV, ABX, AIv}, {OMOV, ASP, AIv}, {OMOV, ABP, AIv}, {OMOV, ASI, AIv}, {OMOV, ADI, AIv}, //C0 {OGP2, AEb, AIb}, {OGP2, AEv, AIb}, {ORET, AIw, }, {ORET, A0, }, {OLFP,AES,AGv,AMp},{OLFP,ADS,AGv,AMp},{OMOV, AEb, AIb}, {OMOV, AEv, AIv}, {OENTER,AIw, AIb}, {OLEAVE, }, {ORETF, AIw, }, {ORETF, A0, }, {OINT, A3, }, {OINT, AIb, }, {OINT, A4, }, {OIRET, }, //D0 {OGP2, AEb, A1 }, {OGP2, AEv, A1 }, {OGP2, AEb, ACL}, {OGP2, AEv, ACL}, {OAAM, AIb, }, {OAAD, AIb, }, {OBAD, }, {OXLAT, AAL, ABX}, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //E0 {OLOOPNZ,AJb,ACX}, {OLOOPZ,AJb, ACX}, {OLOOP, AJb, ACX}, {OJUMP, AJb, ACX}, {OIN, AAL, AIb}, {OIN, AAX, AIb}, {OOUT, AIb, AAL}, {OOUT, AIb, AAX}, {OCALL, AJv, }, {OJUMP, AJv, }, {OJUMP, AAp, }, {OJUMP, AJb, }, {OIN, AAL, ADX}, {OIN, AAX, ADX}, {OOUT, ADX, AAL}, {OOUT, ADX, AAX}, //F0 {OLOCK, }, {OBAD, }, {OREPNE, }, {OREPE, }, {OHLT, }, {OCMC, }, {OGP3b, }, {OGP3v, }, {OCLC, }, {OSTC, }, {OCLI, }, {OSTI, }, {OCLD, }, {OSTD, }, {OGP4, }, {OGP5, }, }; static Optab optab0F[256] = { //00 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //10 - mostly floating point and quadword moves {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //20 - doubleword <-> control register moves, other arcana {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //30 - wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //40 - conditional moves {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, //50 - floating point, mmx stuff {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //60 - floating point, mmx stuff {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //70 - floating point, mmx stuff {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //80 - long-displacement jumps {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, //90 - conditional byte set {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, //A0 {OPUSH, AFS, }, {OPOP, AFS, }, {OBAD, }, {OBT, AEv, AGv}, {OSHLD,AEv,AGv,AIb}, {OSHLD,AEv,AGv,ACL}, {OBAD, }, {OBAD, }, {OPUSH, AGS, }, {OPOP, AGS, }, {OBAD, }, {OBTS, AEv, AGv}, {OSHRD,AEv,AGv,AIb}, {OSHRD,AEv,AGv,ACL}, {OBAD, }, {OIMUL, AGv,AGv,AEv}, //B0 - mostly arcana {OBAD, }, {OBAD, }, {OLFP,ASS,AGv,AMp},{OBAD, }, {OLFP,AFS,AGv,AMp},{OLFP,AGS,AGv,AMp},{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //C0 - more arcana {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //D0 - mmx {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //E0 - mmx {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, //F0 - mmx {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, }; /* some operands map to whole groups; group numbers from intel opcode map */ /* args filled in already (in OGP1 entries) */ static Optab optabgp1[8] = { {OADD, }, {OOR, }, {OADC, }, {OSBB, }, {OAND, }, {OSUB, }, {OXOR, }, {OCMP, }, }; /* args filled in already (in OGP2 entries) */ static Optab optabgp2[8] = { {OROL, }, {OROR, }, {ORCL, }, {ORCR, }, {OSHL, }, {OSHR, }, {OBAD, }, {OSAR, }, }; static Optab optabgp3b[8] = { {OTEST, AEb, AIb}, {OBAD, }, {ONOT, AEb, }, {ONEG, AEb, }, {OMUL,AAX,AAL,AEb},{OIMUL,AAX,AAL,AEb},{ODIV, AEb, }, {OIDIV, AEb, }, }; static Optab optabgp3v[8] = { {OTEST, AEv, AIv}, {OBAD, }, {ONOT, AEv, }, {ONEG, AEv, }, {OMUL,AAX,AAX,AEv},{OIMUL,AAX,AAX,AEv},{ODIV, AEv, }, {OIDIV, AEv, }, }; static Optab optabgp4[8] = { {OINC, AEb, }, {ODEC, AEb, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, }; static Optab optabgp5[8] = { {OINC, AEv, }, {ODEC, AEv, }, {OCALL, AEv, }, {OCALL, AEp }, {OJUMP, AEv, }, {OJUMP, AEp, }, {OPUSH, AEv, }, {OBAD, }, }; /* optabg6 unimplemented - mostly segment manipulation */ /* optabg7 unimplemented - more segment manipulation */ /* optabg8 unimplemented - bit tests */ /* * most of optabg9 - optabg16 decode differently depending on the mod value of * the modrm byte. they're mostly arcane instructions so they're not * implemented. */ static Optab *optabgp[NUMOP] = { [OGP1] optabgp1, [OGP2] optabgp2, [OGP3b] optabgp3b, [OGP3v] optabgp3v, [OGP4] optabgp4, [OGP5] optabgp5, }; static void crackarg(Cpu*, Inst*, Iarg*, Wordop*); static void crackmodrm(Cpu*, Inst*, Wordop*); void nextinst(Cpu *cpu, Inst *inst) { Optab *gtab, tab, tab2; Wordop *wop; memset(inst, 0, sizeof *inst); inst->epc = cpu->pc; inst->spc = cpu->pc; inst->addrsize = cpu->addrsize; inst->opsize = cpu->opsize; /* loop through prefixes */ for(;;){ inst->i = wop8.fetch(cpu, wop16.rreg(cpu, RCS, 0), inst->epc++); tab = optab[inst->i]; switch(tab.op){ case OOSIZE: inst->opsize = 48 - cpu->opsize; continue; case OASIZE: inst->addrsize = 48 - cpu->addrsize; continue; case OREPE: case OREPNE: inst->repeat = tab.op; continue; case OSEG: inst->sreg = "ECSD"[tab.arg1-AES]; inst->seg = wop16.rreg(cpu, tab.arg1-AES+RES, 0); continue; } break; } if(inst->opsize == 16) wop = &wop16; else wop = &wop32; /* check 0F */ if(tab.op == O0F){ inst->i = wop8.fetch(cpu, wop16.rreg(cpu, RCS, 0), inst->epc++); tab = optab0F[inst->i]; } /* check instruction group information */ if(gtab = optabgp[tab.op]){ crackmodrm(cpu, inst, wop); inst->havemodrm = 1; tab2 = gtab[inst->rop]; tab.op = tab2.op; if(tab2.arg1) tab.arg1 = tab2.arg1; if(tab2.arg2) tab.arg2 = tab2.arg2; if(tab2.arg3) tab.arg3 = tab2.arg3; } /* fetch modrm if necessary */ if(!inst->havemodrm && (needmodrm[tab.arg1]||needmodrm[tab.arg2]||needmodrm[tab.arg3])) crackmodrm(cpu, inst, wop); if(inst->sreg == 0){ inst->sreg = 'D'; inst->seg = wop16.rreg(cpu, RDS, 0); } /* cobble together arguments */ inst->op = tab.op; inst->arg1.atype = tab.arg1; inst->arg2.atype = tab.arg2; inst->arg3.atype = tab.arg3; crackarg(cpu, inst, &inst->arg1, wop); crackarg(cpu, inst, &inst->arg2, wop); crackarg(cpu, inst, &inst->arg3, wop); switch(inst->op){ case OPUSH: case OPOP: break; default: if(tab.arg1 != ANONE && small[tab.arg1] && small[tab.arg2] && small[tab.arg3]){ assert(inst->opsize == cpu->opsize); inst->opsize = 8; } if((tab.op == OIN || tab.op == OOUT) && (tab.arg1 == AAL || tab.arg2 == AAL)) inst->opsize = 8; break; } } static void crackmodrm(Cpu *cpu, Inst *inst, Wordop *wop) { uchar i; int s; i = wop8.fetch(cpu, wop16.rreg(cpu, RCS, 0), inst->epc++); inst->mod = i>>6; inst->rop = (i>>3)&7; inst->rm = i&7; if(inst->mod == 3) /* denotes register, get it later */ return; if(inst->mod == 0 && inst->rm == 6){ inst->off = inst->disp = wop16.fetch(cpu, wop16.rreg(cpu, RCS, 0), inst->epc); inst->epc += 2; return; } switch(inst->rm){ default: abort(); case 0: /* [BX+SI] */ s = RDS; inst->off = wop->rreg(cpu, RBX, 0)+wop->rreg(cpu, RSI, 0); break; case 1: /* [BX+DI] */ s = RDS; inst->off = wop->rreg(cpu, RBX, 0)+wop->rreg(cpu, RDI, 0); break; case 2: /* [BP+SI] */ s = RSS; inst->off = wop->rreg(cpu, RBP, 0)+wop->rreg(cpu, RSI, 0); break; case 3: /* [BP+DI] */ s = RSS; inst->off = wop->rreg(cpu, RBP, 0)+wop->rreg(cpu, RDI, 0); break; case 4: /* [SI] */ s = RDS; inst->off = wop->rreg(cpu, RSI, 0); break; case 5: /* [DI] */ s = RDS; inst->off = wop->rreg(cpu, RDI, 0); break; case 6: /* [BP] */ s = RSS; inst->off = wop->rreg(cpu, RBP, 0); break; case 7: /* [BX] */ s = RDS; inst->off = wop->rreg(cpu, RBX, 0); break; } switch(inst->mod){ case 0: break; case 1: inst->off += (inst->disp = wop8.fetchs(cpu, wop16.rreg(cpu, RCS, 0), inst->epc++)); break; case 2: inst->off += (inst->disp = wop16.fetchs(cpu, wop16.rreg(cpu, RCS, 0), inst->epc)); inst->epc += 2; break; } if(inst->sreg == 0){ inst->sreg = "ECSD"[s-RES]; inst->seg = wop16.rreg(cpu, s, 0); } } static void regarg(Cpu *cpu, Wordop *wop, Iarg *iarg, int r) { iarg->val = wop->rreg(cpu, r, 0); iarg->seg = r; iarg->w = wop->wreg; } /* * BUG: we should avoid fetches when not necessary to avoid bogus faults * that would require a bitmap of which operators need which arguments * to be read in. */ static void crackarg(Cpu *cpu, Inst *inst, Iarg *iarg, Wordop *wop) { long t; iarg->w = (void*)abort; switch(iarg->atype){ default: print("bad type %d\n", iarg->atype); abort(); case ANONE: /* no argument */ break; case A0: /* constant 0 */ iarg->val = 0; break; case A1: /* constant 1 */ iarg->val = 1; break; case A3: /* constant 3 */ iarg->val = 3; break; case A4: /* constant 4 */ iarg->val = 4; break; case AAp: /* 32-bit or 48-bit direct address */ iarg->sreg = 0; iarg->seg = wop16.fetch(cpu, wop16.rreg(cpu, RCS, 0), inst->epc); inst->epc += 2; iarg->off = wop->fetch(cpu, wop16.rreg(cpu, RCS, 0), inst->epc); inst->epc += wop->len; break; case AEp: /* r/m-ptr from modrm byte */ if(inst->mod == 3) trap(cpu, TBADOP); iarg->sreg = inst->sreg; iarg->seg = wop16.fetch(cpu, inst->seg, inst->off); iarg->off = wop16.fetch(cpu, inst->seg, inst->off+2); //ADDRSIZE break; case AEb: /* r/m8 from modrm byte */ wop = &wop8; goto AE; case AEw: /* r/m16 from modrm byte */ wop = &wop16; /* fall through */ case AEv: /* r/m16 or r/m32 from modrm byte */ AE: if(inst->mod == 3) /* register */ regarg(cpu, wop, iarg, inst->rm); else{ iarg->sreg = inst->sreg; iarg->seg = inst->seg; iarg->off = inst->off; iarg->val = wop->fetch(cpu, inst->seg, inst->off); iarg->w = wop->store; } break; case AFv: iarg->val = cpu->flags; iarg->w = putflags; break; case AM: /* memory address from modrm */ case AMa: /* weird thing for bound */ case AMp: /* memory address from modrm */ if(inst->mod == 3) trap(cpu, TBADOP); iarg->sreg = inst->sreg; iarg->seg = inst->seg; iarg->off = inst->off; break; case AMa2: /* weird thing for bound */ iarg->sreg = inst->sreg; iarg->seg = inst->seg; iarg->off = inst->off+2; break; /* case AMp: see case AAp above */ case AGw: /* r16 from modrm byte */ wop = &wop16; goto AG; case AGb: /* r8 from modrm byte */ wop = &wop8; /* fall through */ case AGv: /* r16 or r32 from modrm byte */ AG: regarg(cpu, wop, iarg, inst->rop); break; case AIb: /* immediate byte */ wop = &wop8; goto AI; case AIw: /* immediate 16-bit word */ wop = &wop16; /* fall through */ case AIv: /* immediate 16-bit or 32-bit word */ AI: iarg->val = wop->fetch(cpu, wop16.rreg(cpu, RCS, 0), inst->epc); inst->epc += wop->len; break; case AIc: /* immediate byte sign-extend */ iarg->val = wop8.fetchs(cpu, wop16.rreg(cpu, RCS, 0), inst->epc); inst->epc++; break; case AJb: /* relative offset byte */ wop = &wop8; /* fall through */ case AJv: /* relative offset 16-bit or 32-bit word */ iarg->sreg = 'C'; iarg->seg = wop16.rreg(cpu, RCS, 0); t = wop->fetchs(cpu, wop16.rreg(cpu, RCS, 0), inst->epc); inst->epc += wop->len; iarg->off = inst->epc + t; break; case AJr: if(inst->mod != 3) trap(cpu, TBADOP); inst->sreg = 'C'; inst->seg = wop16.rreg(cpu, RCS, 0); inst->off = wop->rreg(cpu, inst->rm, 0); break; case AOb: /* immediate word-sized offset to a byte */ wop = &wop8; /* fall through */ case AOv: /* immediate word-size offset to a word */ iarg->sreg = inst->sreg; iarg->seg = inst->seg; iarg->off = wop16.fetchs(cpu, wop16.rreg(cpu, RCS, 0), inst->epc); inst->epc += wop16.len; iarg->val = wop->fetch(cpu, iarg->seg, iarg->off); iarg->w = wop->store; break; case ASw: /* segment register selected by r field of modrm */ regarg(cpu, &wop16, iarg, RES+inst->rop); break; case AXb: /* byte at DS:SI */ wop = &wop8; /* fall through */ case AXv: /* word at DS:SI */ iarg->sreg = 'D'; iarg->seg = wop16.rreg(cpu, RDS, 0); iarg->off = wop16.rreg(cpu, RSI, 0); //ADDRSIZE iarg->val = wop->fetch(cpu, iarg->seg, iarg->off); iarg->w = wop->store; iarg->p = bumpdssi; break; case AYb: /* byte at ES:DI */ wop = &wop8; /* fall through */ case AYv: /* word at ES:DI */ iarg->sreg = 'E'; iarg->seg = wop16.rreg(cpu, RES, 0); iarg->off = wop16.rreg(cpu, RDI, 0); //ADDRSIZE iarg->val = wop->fetch(cpu, iarg->seg, iarg->off); iarg->w = wop->store; iarg->p = bumpesdi; break; case AAL: case AAH: case ABL: case ABH: case ACL: case ACH: case ADL: case ADH: iarg->seg = iarg->atype - AAL; iarg->val = wop8.rreg(cpu, iarg->atype - AAL, 0); iarg->w = wop8.wreg; break; case AAX: case ABX: case ACX: case ADX: case ABP: case ASP: case ADI: case ASI: case AES: case ACS: case ASS: case ADS: case AFS: case AGS: iarg->seg = iarg->atype - AAX; iarg->val = wop->rreg(cpu, iarg->atype - AAX, 0); iarg->w = wop->wreg; break; } }