#include <u.h>
#include <libc.h>
#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;
}
}
|