645 lines
19 KiB
C
645 lines
19 KiB
C
#include <u.h>
|
|
#include <lib9.h>
|
|
#include "dat.h"
|
|
#include "fns.h"
|
|
|
|
typedef struct Optab Optab;
|
|
struct Optab {
|
|
unsigned char op;
|
|
unsigned char a1, a2, a3;
|
|
};
|
|
|
|
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, AEb, AIb}, {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}, {OGP10, },
|
|
//90
|
|
{ONOP, }, {OXCHG, ACX, AAX}, {OXCHG, ADX, AAX}, {OXCHG, ABX, AAX},
|
|
{OXCHG, ASP, AAX}, {OXCHG, ABP, AAX}, {OXCHG, ASI, AAX}, {OXCHG, ADI, AAX},
|
|
{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, AYb, AXb}, {OMOVS, AYv, AXv}, {OCMPS, AYb, AXb}, {OCMPS, AYv, AXv},
|
|
{OTEST, AAL, AIb}, {OTEST, AAX, AIv}, {OSTOS, AYb, AAL}, {OSTOS, AYv, AAX},
|
|
{OLODS, AAL, AXb}, {OLODS, AAX, AXv}, {OSCAS, AYb, AAL}, {OSCAS, AYv, AAX},
|
|
//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},{OGP12, AEb, AIb}, {OGP12, 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, }, {OLOOPZ,AJb, }, {OLOOP, AJb, }, {OJUMP, AJb, },
|
|
{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, }, {OCPUID, }, {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},{OBTR,AEv,AGv },
|
|
{OLFP,AFS,AGv,AMp},{OLFP,AGS,AGv,AMp},{OMOVZX,AGv,AEb }, {OMOVZX,AGv,AEw },
|
|
{OBAD, }, {OBAD, }, {OGP8, }, {OBAD, },
|
|
{OBSF,AGv,AEv }, {OBSR,AGv,AEv }, {OMOVSX,AGv,AEb }, {OMOVSX,AGv,AEw },
|
|
//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, AMp },
|
|
{OJUMP, AEv, }, {OJUMP, AMp, }, {OPUSH, AEv, }, {OBAD, },
|
|
};
|
|
|
|
static Optab optabgp8[8] = {
|
|
{OMOV, }, {OBAD, }, {OBAD, }, {OBAD, },
|
|
{OBT, AEv, AIb }, {OBTS, AEv, AIb }, {OBTR, AEv, AIb }, {OBTC, AEv, AIb },
|
|
};
|
|
|
|
static Optab optabgp10[8] = {
|
|
{OPOP, AEv, }, {OBAD, }, {OBAD, }, {OBAD, },
|
|
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
|
|
};
|
|
|
|
static Optab optabgp12[8] = {
|
|
{OMOV, }, {OBAD, }, {OBAD, }, {OBAD, },
|
|
{OBAD, }, {OBAD, }, {OBAD, }, {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,
|
|
[OGP8] optabgp8,
|
|
[OGP10] optabgp10,
|
|
[OGP12] optabgp12,
|
|
};
|
|
|
|
static unsigned char modrmarg[NATYPE] = {
|
|
[AEb] 1,
|
|
[AEw] 1,
|
|
[AEv] 1,
|
|
[AGb] 1,
|
|
[AGw] 1,
|
|
[AGv] 1,
|
|
[AM] 1,
|
|
[AMp] 1,
|
|
[AMa] 1,
|
|
[AMa2] 1,
|
|
[ASw] 1,
|
|
[AJr] 1,
|
|
};
|
|
|
|
static void
|
|
getmodrm16(Iarg *ip, Inst *i)
|
|
{
|
|
print_func_entry();
|
|
Iarg *p;
|
|
unsigned char b;
|
|
|
|
b = ar(ip); ip->off++;
|
|
|
|
i->mod = b>>6;
|
|
i->reg = (b>>3)&7;
|
|
i->rm = b&7;
|
|
|
|
if(i->mod == 3) {
|
|
print_func_exit();
|
|
return;
|
|
}
|
|
|
|
switch(i->rm){
|
|
case 0:
|
|
i->off = ar(areg(ip->cpu, 2, RBX)) + ar(areg(ip->cpu, 2, RSI));
|
|
i->off &= 0xFFFF;
|
|
break;
|
|
case 1:
|
|
i->off = ar(areg(ip->cpu, 2, RBX)) + ar(areg(ip->cpu, 2, RDI));
|
|
i->off &= 0xFFFF;
|
|
break;
|
|
case 2:
|
|
i->dsreg = RSS;
|
|
i->off = ar(areg(ip->cpu, 2, RBP)) + ar(areg(ip->cpu, 2, RSI));
|
|
i->off &= 0xFFFF;
|
|
break;
|
|
case 3:
|
|
i->dsreg = RSS;
|
|
i->off = ar(areg(ip->cpu, 2, RBP)) + ar(areg(ip->cpu, 2, RDI));
|
|
i->off &= 0xFFFF;
|
|
break;
|
|
case 4:
|
|
i->off = ar(areg(ip->cpu, 2, RSI));
|
|
break;
|
|
case 5:
|
|
i->off = ar(areg(ip->cpu, 2, RDI));
|
|
break;
|
|
case 6:
|
|
if(i->mod == 0){
|
|
p = adup(ip); ip->off += 2;
|
|
p->len = 2;
|
|
i->off = ar(p);
|
|
print_func_exit();
|
|
return;
|
|
}
|
|
i->dsreg = RSS;
|
|
i->off = ar(areg(ip->cpu, 2, RBP));
|
|
break;
|
|
case 7:
|
|
i->off = ar(areg(ip->cpu, 2, RBX));
|
|
break;
|
|
}
|
|
switch(i->mod){
|
|
case 1:
|
|
i->off += (i->disp = ars(ip)); ip->off++;
|
|
i->off &= 0xFFFF;
|
|
break;
|
|
case 2:
|
|
p = adup(ip); ip->off += 2;
|
|
p->len = 2;
|
|
i->off += (i->disp = ars(p));
|
|
i->off &= 0xFFFF;
|
|
break;
|
|
}
|
|
print_func_exit();
|
|
}
|
|
|
|
static void
|
|
getmodrm32(Iarg *ip, Inst *i)
|
|
{
|
|
print_func_entry();
|
|
static unsigned char scaler[] = {1, 2, 4, 8};
|
|
Iarg *p;
|
|
unsigned char b;
|
|
|
|
b = ar(ip); ip->off++;
|
|
|
|
i->mod = b>>6;
|
|
i->reg = (b>>3)&7;
|
|
i->rm = b&7;
|
|
|
|
if(i->mod == 3) {
|
|
print_func_exit();
|
|
return;
|
|
}
|
|
|
|
switch(i->rm){
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 6:
|
|
case 7:
|
|
i->off = ar(areg(ip->cpu, 4, i->rm + RAX));
|
|
break;
|
|
case 4:
|
|
b = ar(ip); ip->off++;
|
|
i->scale = b>>6;
|
|
i->index = (b>>3)&7;
|
|
i->base = b&7;
|
|
|
|
if(i->base != 5){
|
|
i->off = ar(areg(ip->cpu, 4, i->base + RAX));
|
|
break;
|
|
}
|
|
case 5:
|
|
if(i->mod == 0){
|
|
p = adup(ip); ip->off += 4;
|
|
p->len = 4;
|
|
i->off = ar(p);
|
|
} else {
|
|
i->dsreg = RSS;
|
|
i->off = ar(areg(ip->cpu, 4, RBP));
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(i->rm == 4 && i->index != 4)
|
|
i->off += ar(areg(ip->cpu, 4, i->index + RAX)) * scaler[i->scale];
|
|
|
|
switch(i->mod){
|
|
case 1:
|
|
i->off += (i->disp = ars(ip)); ip->off++;
|
|
break;
|
|
case 2:
|
|
p = adup(ip); ip->off += 4;
|
|
p->len = 4;
|
|
i->off += (i->disp = ars(p));
|
|
break;
|
|
}
|
|
print_func_exit();
|
|
}
|
|
|
|
static Iarg*
|
|
getarg(Iarg *ip, Inst *i, unsigned char atype)
|
|
{
|
|
print_func_entry();
|
|
Iarg *a;
|
|
unsigned char len, reg;
|
|
|
|
len = i->olen;
|
|
switch(atype){
|
|
default:
|
|
abort();
|
|
|
|
case A0:
|
|
case A1:
|
|
case A2:
|
|
case A3:
|
|
case A4:
|
|
a = acon(ip->cpu, len, atype - A0);
|
|
break;
|
|
|
|
case AEb:
|
|
len = 1;
|
|
if(0){
|
|
case AEw:
|
|
len = 2;
|
|
}
|
|
case AEv:
|
|
if(i->mod == 3){
|
|
reg = i->rm;
|
|
goto REG;
|
|
}
|
|
goto MEM;
|
|
|
|
case AM:
|
|
case AMp:
|
|
case AMa:
|
|
case AMa2:
|
|
if(i->mod == 3)
|
|
trap(ip->cpu, EBADOP);
|
|
MEM:
|
|
a = amem(ip->cpu, len, i->sreg, i->off);
|
|
if(atype == AMa2)
|
|
a->off += i->olen;
|
|
break;
|
|
|
|
case AGb:
|
|
len = 1;
|
|
if(0){
|
|
case AGw:
|
|
len = 2;
|
|
}
|
|
case AGv:
|
|
reg = i->reg;
|
|
REG:
|
|
a = areg(ip->cpu, len, reg + RAX);
|
|
if(len == 1 && reg >= 4){
|
|
a->reg -= 4;
|
|
a->tag |= TH;
|
|
}
|
|
break;
|
|
|
|
case AIb:
|
|
case AIc:
|
|
len = 1;
|
|
if(0){
|
|
case AIw:
|
|
len = 2;
|
|
}
|
|
case AIv:
|
|
a = adup(ip); ip->off += len;
|
|
a->len = len;
|
|
break;
|
|
|
|
case AJb:
|
|
len = 1;
|
|
case AJv:
|
|
a = adup(ip); ip->off += len;
|
|
a->len = len;
|
|
a->off = ip->off + ars(a);
|
|
break;
|
|
|
|
case AJr:
|
|
if(i->mod != 3)
|
|
trap(ip->cpu, EBADOP);
|
|
a = adup(ip);
|
|
a->off = ar(areg(ip->cpu, i->olen, i->rm + RAX));
|
|
break;
|
|
|
|
case AAp:
|
|
a = afar(ip, ip->len, len); ip->off += 2+len;
|
|
break;
|
|
|
|
case AOb:
|
|
len = 1;
|
|
case AOv:
|
|
a = adup(ip); ip->off += i->alen;
|
|
a->len = i->alen;
|
|
a = amem(ip->cpu, len, i->sreg, ar(a));
|
|
break;
|
|
|
|
case ASw:
|
|
reg = i->reg;
|
|
SREG:
|
|
a = areg(ip->cpu, 2, reg + RES);
|
|
break;
|
|
|
|
case AXb:
|
|
len = 1;
|
|
case AXv:
|
|
a = amem(ip->cpu, len, i->sreg, ar(areg(ip->cpu, i->alen, RSI)));
|
|
break;
|
|
|
|
case AYb:
|
|
len = 1;
|
|
case AYv:
|
|
a = amem(ip->cpu, len, RES, ar(areg(ip->cpu, i->alen, RDI)));
|
|
break;
|
|
|
|
case AFv:
|
|
a = areg(ip->cpu, len, RFL);
|
|
break;
|
|
|
|
case AAL:
|
|
case ACL:
|
|
case ADL:
|
|
case ABL:
|
|
case AAH:
|
|
case ACH:
|
|
case ADH:
|
|
case ABH:
|
|
len = 1;
|
|
reg = atype - AAL;
|
|
goto REG;
|
|
|
|
case AAX:
|
|
case ACX:
|
|
case ADX:
|
|
case ABX:
|
|
case ASP:
|
|
case ABP:
|
|
case ASI:
|
|
case ADI:
|
|
reg = atype - AAX;
|
|
goto REG;
|
|
|
|
case AES:
|
|
case ACS:
|
|
case ASS:
|
|
case ADS:
|
|
case AFS:
|
|
case AGS:
|
|
reg = atype - AES;
|
|
goto SREG;
|
|
}
|
|
a->atype = atype;
|
|
print_func_exit();
|
|
return a;
|
|
}
|
|
|
|
static int
|
|
otherlen(int a)
|
|
{
|
|
print_func_entry();
|
|
if(a == 2) {
|
|
print_func_exit();
|
|
return 4;
|
|
}
|
|
else if(a == 4) {
|
|
print_func_exit();
|
|
return 2;
|
|
}
|
|
abort();
|
|
print_func_exit();
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
decode(Iarg *ip, Inst *i)
|
|
{
|
|
print_func_entry();
|
|
Optab *t, *t2;
|
|
Cpu *cpu;
|
|
|
|
cpu = ip->cpu;
|
|
|
|
i->op = 0;
|
|
i->rep = 0;
|
|
i->sreg = 0;
|
|
i->dsreg = RDS;
|
|
i->olen = cpu->olen;
|
|
i->alen = cpu->alen;
|
|
i->a1 = i->a2 = i->a3 = nil;
|
|
|
|
for(;;){
|
|
i->code = ar(ip); ip->off++;
|
|
t = optab + i->code;
|
|
switch(t->op){
|
|
case OOSIZE:
|
|
i->olen = otherlen(cpu->olen);
|
|
continue;
|
|
case OASIZE:
|
|
i->alen = otherlen(cpu->alen);
|
|
continue;
|
|
case OREPE:
|
|
case OREPNE:
|
|
i->rep = t->op;
|
|
continue;
|
|
case OLOCK:
|
|
continue;
|
|
case OSEG:
|
|
i->sreg = t->a1-AES+RES;
|
|
continue;
|
|
case O0F:
|
|
i->code = ar(ip); ip->off++;
|
|
t = optab0F + i->code;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
t2 = optabgp[t->op];
|
|
if(t2 || modrmarg[t->a1] || modrmarg[t->a2] || modrmarg[t->a3])
|
|
if(i->alen == 2)
|
|
getmodrm16(ip, i);
|
|
else
|
|
getmodrm32(ip, i);
|
|
if(i->sreg == 0)
|
|
i->sreg = i->dsreg;
|
|
|
|
for(;;){
|
|
if(t->a1)
|
|
i->a1 = getarg(ip, i, t->a1);
|
|
if(t->a2)
|
|
i->a2 = getarg(ip, i, t->a2);
|
|
if(t->a3)
|
|
i->a3 = getarg(ip, i, t->a3);
|
|
if(t2 == nil)
|
|
break;
|
|
t = t2 + i->reg;
|
|
t2 = nil;
|
|
}
|
|
i->op = t->op;
|
|
print_func_exit();
|
|
}
|