80386 0x0F opcodes more or less fleshed out
This commit is contained in:
parent
f9cb8a5bec
commit
177032223c
4 changed files with 452 additions and 15 deletions
|
|
@ -426,6 +426,7 @@ X86CPU.CYCLES_80286 = {
|
|||
};
|
||||
|
||||
X86CPU.CYCLES_80386 = {
|
||||
nOpCyclesBitScan: 11,
|
||||
nOpCyclesBitSetR: 6,
|
||||
nOpCyclesBitSetM: 8,
|
||||
nOpCyclesBitSetMExtra: 5, // extra cycle cost for non-immediate BTC/BTR/BTS opcodes
|
||||
|
|
@ -434,6 +435,8 @@ X86CPU.CYCLES_80386 = {
|
|||
nOpCyclesBitTestMExtra: 6, // extra cycle cost for non-immediate BT opcode
|
||||
nOpCyclesIMulR: 9,
|
||||
nOpCyclesIMulM: 12,
|
||||
nOpCyclesMovXR: 3,
|
||||
nOpCyclesMovXM: 6,
|
||||
nOpCyclesSetR: 4,
|
||||
nOpCyclesSetM: 5,
|
||||
nOpCyclesShiftDR: 3,
|
||||
|
|
@ -770,8 +773,11 @@ X86CPU.prototype.initProcessor = function()
|
|||
|
||||
this.OPFLAG_NOINTR_8086 = 0; // used with instructions that should *not* set NOINTR on an 80286 (eg, non-SS segment loads)
|
||||
|
||||
this.aOps0F = X86.aOps0F;
|
||||
this.aOps[0x0F] = X86.op0F;
|
||||
this.aOps[0x0F] = X86.op0F;
|
||||
this.aOps0F = X86.aOps0F.slice();
|
||||
for (var i = 0; i < this.aOps0F.length; i++) {
|
||||
if (!this.aOps0F[i]) this.aOps0F[i] = X86.opUndefined;
|
||||
}
|
||||
this.aOps[X86.OPCODE.PUSHSP] = X86.opPUSHSP; // 0x54
|
||||
this.aOps[X86.OPCODE.ARPL] = X86.opARPL; // 0x63
|
||||
|
||||
|
|
@ -781,7 +787,6 @@ X86CPU.prototype.initProcessor = function()
|
|||
this.aOps[X86.OPCODE.GS] = X86.opGS; // 0x65
|
||||
this.aOps[X86.OPCODE.OS] = X86.opOS; // 0x66
|
||||
this.aOps[X86.OPCODE.AS] = X86.opAS; // 0x67
|
||||
this.aOps0F = X86.aOps0F.slice();
|
||||
for (bOpcode in X86.aOps0F386) {
|
||||
this.aOps0F[+bOpcode] = X86.aOps0F386[bOpcode];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,6 +204,76 @@ X86.fnBOUND = function BOUND(dst, src)
|
|||
return dst;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnBSF(dst, src)
|
||||
*
|
||||
* Scan src starting at bit 0. If a set bit is found, the bit index is stored in dst and ZF is cleared;
|
||||
* otherwise, ZF is set and dst is unchanged.
|
||||
*
|
||||
* NOTES: Early versions of the 80386 manuals misstated how ZF was set/cleared. Also, Intel insists that
|
||||
* dst is undefined whenever ZF is set, but in fact, the 80386 leaves dst unchanged when that happens;
|
||||
* unfortunately, some early 80486s would always modify dst, so it is unsafe to rely on dst when ZF is set.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} dst
|
||||
* @param {number} src
|
||||
* @return {number}
|
||||
*/
|
||||
X86.fnBSF = function BSF(dst, src)
|
||||
{
|
||||
if (!src) {
|
||||
this.setZF();
|
||||
} else {
|
||||
this.clearZF();
|
||||
var i = 0, bit = 0x1;
|
||||
while (bit & this.dataMask) {
|
||||
if (src & bit) {
|
||||
dst = i;
|
||||
break;
|
||||
}
|
||||
bit <<= 1;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
this.nStepCycles -= X86CPU.CYCLES_80386.nOpCyclesBitScan + i * 3;
|
||||
return dst;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnBSR(dst, src)
|
||||
*
|
||||
* Scan src starting from the highest bit. If a set bit is found, the bit index is stored in dst and ZF is
|
||||
* cleared; otherwise, ZF is set and dst is unchanged.
|
||||
*
|
||||
* NOTES: Early versions of the 80386 manuals misstated how ZF was set/cleared. Also, Intel insists that
|
||||
* dst is undefined whenever ZF is set, but in fact, the 80386 leaves dst unchanged when that happens;
|
||||
* unfortunately, some early 80486s would always modify dst, so it is unsafe to rely on dst when ZF is set.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} dst
|
||||
* @param {number} src
|
||||
* @return {number}
|
||||
*/
|
||||
X86.fnBSR = function BSR(dst, src)
|
||||
{
|
||||
if (!src) {
|
||||
this.setZF();
|
||||
} else {
|
||||
this.clearZF();
|
||||
var i = (this.dataSize == 2? 15 : 31), j = i, bit = 1 << i;
|
||||
while (bit) {
|
||||
if (src & bit) {
|
||||
dst = i;
|
||||
break;
|
||||
}
|
||||
bit >>>= 1;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
this.nStepCycles -= X86CPU.CYCLES_80386.nOpCyclesBitScan + (j - i) * 3;
|
||||
return dst;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnBT(dst, src)
|
||||
*
|
||||
|
|
@ -1052,6 +1122,25 @@ X86.fnLES = function LES(dst, src)
|
|||
return src;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnLFS(dst, src)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} dst
|
||||
* @param {number} src
|
||||
* @return {number}
|
||||
*/
|
||||
X86.fnLFS = function LFS(dst, src)
|
||||
{
|
||||
if (this.regEA === X86.ADDR_INVALID) {
|
||||
X86.opUndefined.call(this);
|
||||
return dst;
|
||||
}
|
||||
this.setFS(this.getShort(this.regEA + 2));
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLS;
|
||||
return src;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnLGDT(dst, src)
|
||||
*
|
||||
|
|
@ -1079,6 +1168,25 @@ X86.fnLGDT = function LGDT(dst, src)
|
|||
return dst;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnLGS(dst, src)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} dst
|
||||
* @param {number} src
|
||||
* @return {number}
|
||||
*/
|
||||
X86.fnLGS = function LGS(dst, src)
|
||||
{
|
||||
if (this.regEA === X86.ADDR_INVALID) {
|
||||
X86.opUndefined.call(this);
|
||||
return dst;
|
||||
}
|
||||
this.setGS(this.getShort(this.regEA + 2));
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLS;
|
||||
return src;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnLIDT(dst, src)
|
||||
*
|
||||
|
|
@ -1173,6 +1281,25 @@ X86.fnLSL = function LSL(dst, src)
|
|||
return dst;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnLSS(dst, src)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} dst
|
||||
* @param {number} src
|
||||
* @return {number}
|
||||
*/
|
||||
X86.fnLSS = function LSS(dst, src)
|
||||
{
|
||||
if (this.regEA === X86.ADDR_INVALID) {
|
||||
X86.opUndefined.call(this);
|
||||
return dst;
|
||||
}
|
||||
this.setSS(this.getShort(this.regEA + 2));
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLS;
|
||||
return src;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnLTR(dst, src)
|
||||
*
|
||||
|
|
@ -1208,6 +1335,19 @@ X86.fnMOV = function MOV(dst, src)
|
|||
return src;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnMOVX(dst, src)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} dst (current value, ignored)
|
||||
* @param {number} src (new value)
|
||||
* @return {number} dst (updated value, from src)
|
||||
*/
|
||||
X86.fnMOVX = function MOVX(dst, src)
|
||||
{
|
||||
return src;
|
||||
};
|
||||
|
||||
/**
|
||||
* fnMOVn(dst, src)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ X86.opMOVrcr = function MOVrcr()
|
|||
}
|
||||
*/
|
||||
var reg = (bModRM & 0x38) >> 3;
|
||||
switch (reg) {
|
||||
switch(reg) {
|
||||
case 0x0:
|
||||
this.regMD16 = this.regCR0;
|
||||
break;
|
||||
|
|
@ -288,7 +288,7 @@ X86.opMOVcrr = function MOVcrr()
|
|||
return;
|
||||
}
|
||||
this.aOpModRegWord[bModRM].call(this, X86.fnMOV);
|
||||
switch (reg) {
|
||||
switch(reg) {
|
||||
case 0x0:
|
||||
reg = this.regEAX;
|
||||
this.regEAX = temp;
|
||||
|
|
@ -958,6 +958,20 @@ X86.opIMUL = function IMUL()
|
|||
this.aOpModRegWord[this.getIPByte()].call(this, this.dataSize == 2? X86.fnIMULrw : X86.fnIMULrd);
|
||||
};
|
||||
|
||||
/**
|
||||
* opLSS()
|
||||
*
|
||||
* op=0x0F,0xB2 (LSS reg,word)
|
||||
*
|
||||
* This is like a "MOV reg,rm" operation, but it also loads SS from the next word.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opLSS = function LSS()
|
||||
{
|
||||
this.aOpModRegWord[this.getIPByte()].call(this, X86.fnLSS);
|
||||
};
|
||||
|
||||
/**
|
||||
* opBTR()
|
||||
*
|
||||
|
|
@ -971,6 +985,146 @@ X86.opBTR = function BTR()
|
|||
if (this.regEA !== X86.ADDR_INVALID) this.nStepCycles -= X86CPU.CYCLES_80386.nOpCyclesBitSetMExtra;
|
||||
};
|
||||
|
||||
/**
|
||||
* opLFS()
|
||||
*
|
||||
* op=0x0F,0xB4 (LFS reg,word)
|
||||
*
|
||||
* This is like a "MOV reg,rm" operation, but it also loads FS from the next word.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opLFS = function LFS()
|
||||
{
|
||||
this.aOpModRegWord[this.getIPByte()].call(this, X86.fnLFS);
|
||||
};
|
||||
|
||||
/**
|
||||
* opLGS()
|
||||
*
|
||||
* op=0x0F,0xB5 (LGS reg,word)
|
||||
*
|
||||
* This is like a "MOV reg,rm" operation, but it also loads GS from the next word.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opLGS = function LGS()
|
||||
{
|
||||
this.aOpModRegWord[this.getIPByte()].call(this, X86.fnLGS);
|
||||
};
|
||||
|
||||
/**
|
||||
* opMOVZXb()
|
||||
*
|
||||
* op=0x0F,0xB6 (MOVZX reg,byte)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opMOVZXb = function MOVZXb()
|
||||
{
|
||||
/*
|
||||
* The ModRegByte handlers update the registers in the 1st column, but we need to update those in the 2nd column.
|
||||
*
|
||||
* 000: AL -> 000: AX
|
||||
* 001: CL -> 001: CX
|
||||
* 010: DL -> 010: DX
|
||||
* 011: BL -> 011: BX
|
||||
* 100: AH -> 100: SP
|
||||
* 101: CH -> 101: BP
|
||||
* 110: DH -> 110: SI
|
||||
* 111: BH -> 111: DI
|
||||
*/
|
||||
var temp;
|
||||
var bModRM = this.getIPByte();
|
||||
var reg = (bModRM & 0x38) >> 3;
|
||||
switch(reg) {
|
||||
case 0x4:
|
||||
temp = this.regEAX;
|
||||
break;
|
||||
case 0x5:
|
||||
temp = this.regECX;
|
||||
break;
|
||||
case 0x6:
|
||||
temp = this.regEDX;
|
||||
break;
|
||||
case 0x7:
|
||||
temp = this.regEBX;
|
||||
break;
|
||||
}
|
||||
this.aOpModRegByte[bModRM].call(this, X86.fnMOVX);
|
||||
switch(reg) {
|
||||
case 0x0:
|
||||
this.regEAX = (this.regEAX & ~this.dataMask) | (this.regEAX & 0xff);
|
||||
break;
|
||||
case 0x1:
|
||||
this.regECX = (this.regECX & ~this.dataMask) | (this.regECX & 0xff);
|
||||
break;
|
||||
case 0x2:
|
||||
this.regEDX = (this.regEDX & ~this.dataMask) | (this.regEDX & 0xff);
|
||||
break;
|
||||
case 0x3:
|
||||
this.regEBX = (this.regEBX & ~this.dataMask) | (this.regEBX & 0xff);
|
||||
break;
|
||||
case 0x4:
|
||||
this.regESP = (this.regESP & ~this.dataMask) | ((this.regEAX >> 8) & 0xff);
|
||||
this.regEAX = temp;
|
||||
break;
|
||||
case 0x5:
|
||||
this.regEBP = (this.regEBP & ~this.dataMask) | ((this.regECX >> 8) & 0xff);
|
||||
this.regECX = temp;
|
||||
break;
|
||||
case 0x6:
|
||||
this.regESI = (this.regESI & ~this.dataMask) | ((this.regEDX >> 8) & 0xff);
|
||||
this.regEDX = temp;
|
||||
break;
|
||||
case 0x7:
|
||||
this.regEDI = (this.regEDI & ~this.dataMask) | ((this.regEBX >> 8) & 0xff);
|
||||
this.regEBX = temp;
|
||||
break;
|
||||
}
|
||||
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? X86CPU.CYCLES_80386.nOpCyclesMovXR : X86CPU.CYCLES_80386.nOpCyclesMovXM);
|
||||
};
|
||||
|
||||
/**
|
||||
* opMOVZXw()
|
||||
*
|
||||
* op=0x0F,0xB7 (MOVZX reg,word)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opMOVZXw = function MOVZXw()
|
||||
{
|
||||
var bModRM = this.getIPByte();
|
||||
this.aOpModRegWord[bModRM].call(this, X86.fnMOVX);
|
||||
switch((bModRM & 0x38) >> 3) {
|
||||
case 0x0:
|
||||
this.regEAX = (this.regEAX & 0xffff);
|
||||
break;
|
||||
case 0x1:
|
||||
this.regECX = (this.regECX & 0xffff);
|
||||
break;
|
||||
case 0x2:
|
||||
this.regEDX = (this.regEDX & 0xffff);
|
||||
break;
|
||||
case 0x3:
|
||||
this.regEBX = (this.regEBX & 0xffff);
|
||||
break;
|
||||
case 0x4:
|
||||
this.regESP = (this.regESP & 0xffff);
|
||||
break;
|
||||
case 0x5:
|
||||
this.regEBP = (this.regEBP & 0xffff);
|
||||
break;
|
||||
case 0x6:
|
||||
this.regESI = (this.regESI & 0xffff);
|
||||
break;
|
||||
case 0x7:
|
||||
this.regEDI = (this.regEDI & 0xffff);
|
||||
break;
|
||||
}
|
||||
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? X86CPU.CYCLES_80386.nOpCyclesMovXR : X86CPU.CYCLES_80386.nOpCyclesMovXM);
|
||||
};
|
||||
|
||||
/**
|
||||
* op=0x0F,0xBA (GRP8 mem/reg) (80386 and up)
|
||||
*
|
||||
|
|
@ -994,6 +1148,142 @@ X86.opBTC = function BTC()
|
|||
if (this.regEA !== X86.ADDR_INVALID) this.nStepCycles -= X86CPU.CYCLES_80386.nOpCyclesBitSetMExtra;
|
||||
};
|
||||
|
||||
/**
|
||||
* opBSF()
|
||||
*
|
||||
* op=0x0F,0xBB (BSF reg,mem/reg)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opBSF = function BSF()
|
||||
{
|
||||
this.aOpModRegWord[this.getIPByte()].call(this, X86.fnBSF);
|
||||
};
|
||||
|
||||
/**
|
||||
* opBSR()
|
||||
*
|
||||
* op=0x0F,0xBC (BSR reg,mem/reg)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opBSR = function BSR()
|
||||
{
|
||||
this.aOpModRegWord[this.getIPByte()].call(this, X86.fnBSR);
|
||||
};
|
||||
|
||||
/**
|
||||
* opMOVSXb()
|
||||
*
|
||||
* op=0x0F,0xBE (MOVSX reg,byte)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opMOVSXb = function MOVSXb()
|
||||
{
|
||||
/*
|
||||
* The ModRegByte handlers update the registers in the 1st column, but we need to update those in the 2nd column.
|
||||
*
|
||||
* 000: AL -> 000: AX
|
||||
* 001: CL -> 001: CX
|
||||
* 010: DL -> 010: DX
|
||||
* 011: BL -> 011: BX
|
||||
* 100: AH -> 100: SP
|
||||
* 101: CH -> 101: BP
|
||||
* 110: DH -> 110: SI
|
||||
* 111: BH -> 111: DI
|
||||
*/
|
||||
var temp;
|
||||
var bModRM = this.getIPByte();
|
||||
var reg = (bModRM & 0x38) >> 3;
|
||||
switch(reg) {
|
||||
case 0x4:
|
||||
temp = this.regEAX;
|
||||
break;
|
||||
case 0x5:
|
||||
temp = this.regECX;
|
||||
break;
|
||||
case 0x6:
|
||||
temp = this.regEDX;
|
||||
break;
|
||||
case 0x7:
|
||||
temp = this.regEBX;
|
||||
break;
|
||||
}
|
||||
this.aOpModRegByte[bModRM].call(this, X86.fnMOVX);
|
||||
switch(reg) {
|
||||
case 0x0:
|
||||
this.regEAX = (this.regEAX & ~this.dataMask) | ((((this.regEAX & 0xff) << 24) >> 24) & this.dataMask);
|
||||
break;
|
||||
case 0x1:
|
||||
this.regECX = (this.regECX & ~this.dataMask) | ((((this.regECX & 0xff) << 24) >> 24) & this.dataMask);
|
||||
break;
|
||||
case 0x2:
|
||||
this.regEDX = (this.regEDX & ~this.dataMask) | ((((this.regEDX & 0xff) << 24) >> 24) & this.dataMask);
|
||||
break;
|
||||
case 0x3:
|
||||
this.regEBX = (this.regEBX & ~this.dataMask) | ((((this.regEBX & 0xff) << 24) >> 24) & this.dataMask);
|
||||
break;
|
||||
case 0x4:
|
||||
this.regESP = (this.regESP & ~this.dataMask) | (((this.regEAX << 16) >> 24) & this.dataMask);
|
||||
this.regEAX = temp;
|
||||
break;
|
||||
case 0x5:
|
||||
this.regEBP = (this.regEBP & ~this.dataMask) | (((this.regECX << 16) >> 24) & this.dataMask);
|
||||
this.regECX = temp;
|
||||
break;
|
||||
case 0x6:
|
||||
this.regESI = (this.regESI & ~this.dataMask) | (((this.regEDX << 16) >> 24) & this.dataMask);
|
||||
this.regEDX = temp;
|
||||
break;
|
||||
case 0x7:
|
||||
this.regEDI = (this.regEDI & ~this.dataMask) | (((this.regEBX << 16) >> 24) & this.dataMask);
|
||||
this.regEBX = temp;
|
||||
break;
|
||||
}
|
||||
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? X86CPU.CYCLES_80386.nOpCyclesMovXR : X86CPU.CYCLES_80386.nOpCyclesMovXM);
|
||||
};
|
||||
|
||||
/**
|
||||
* opMOVSXw()
|
||||
*
|
||||
* op=0x0F,0xBF (MOVSX reg,word)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opMOVSXw = function MOVSXw()
|
||||
{
|
||||
var bModRM = this.getIPByte();
|
||||
this.aOpModRegWord[bModRM].call(this, X86.fnMOVX);
|
||||
switch((bModRM & 0x38) >> 3) {
|
||||
case 0x0:
|
||||
this.regEAX = ((this.regEAX << 16) >> 16);
|
||||
break;
|
||||
case 0x1:
|
||||
this.regECX = ((this.regECX << 16) >> 16);
|
||||
break;
|
||||
case 0x2:
|
||||
this.regEDX = ((this.regEDX << 16) >> 16);
|
||||
break;
|
||||
case 0x3:
|
||||
this.regEBX = ((this.regEBX << 16) >> 16);
|
||||
break;
|
||||
case 0x4:
|
||||
this.regESP = ((this.regESP << 16) >> 16);
|
||||
break;
|
||||
case 0x5:
|
||||
this.regEBP = ((this.regEBP << 16) >> 16);
|
||||
break;
|
||||
case 0x6:
|
||||
this.regESI = ((this.regESI << 16) >> 16);
|
||||
break;
|
||||
case 0x7:
|
||||
this.regEDI = ((this.regEDI << 16) >> 16);
|
||||
break;
|
||||
}
|
||||
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? X86CPU.CYCLES_80386.nOpCyclesMovXR : X86CPU.CYCLES_80386.nOpCyclesMovXM);
|
||||
};
|
||||
|
||||
X86.aOps0F = new Array(256);
|
||||
|
||||
X86.aOps0F[0x00] = X86.opGRP6;
|
||||
|
|
@ -1009,10 +1299,6 @@ X86.aOps0F[0x06] = X86.opCLTS;
|
|||
*/
|
||||
X86.aOps0F[0x0B] = X86.opInvalid;
|
||||
|
||||
for (var i = 0; i < X86.aOps0F.length; i++) {
|
||||
if (!X86.aOps0F[i]) X86.aOps0F[i] = X86.opUndefined;
|
||||
}
|
||||
|
||||
if (I386) {
|
||||
X86.aOps0F386 = [];
|
||||
X86.aOps0F386[0x20] = X86.opMOVrcr;
|
||||
|
|
@ -1060,9 +1346,17 @@ if (I386) {
|
|||
X86.aOps0F386[0xAC] = X86.opSHRDn;
|
||||
X86.aOps0F386[0xAD] = X86.opSHRDcl;
|
||||
X86.aOps0F386[0xAF] = X86.opIMUL;
|
||||
X86.aOps0F386[0xB2] = X86.opLSS;
|
||||
X86.aOps0F386[0xB3] = X86.opBTR;
|
||||
X86.aOps0F386[0xB4] = X86.opLFS;
|
||||
X86.aOps0F386[0xB5] = X86.opLGS;
|
||||
X86.aOps0F386[0xB6] = X86.opMOVZXb;
|
||||
X86.aOps0F386[0xB7] = X86.opMOVZXw;
|
||||
X86.aOps0F386[0xBA] = X86.opGRP8;
|
||||
X86.aOps0F386[0xBB] = X86.opBTC;
|
||||
X86.aOps0F386[0xBC] = X86.opBSF;
|
||||
X86.aOps0F386[0xBE] = X86.opMOVSXb;
|
||||
X86.aOps0F386[0xBF] = X86.opMOVSXw;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -3318,26 +3318,24 @@ X86.opRET = function RET()
|
|||
/**
|
||||
* op=0xC4 (LES reg,word)
|
||||
*
|
||||
* This is like a "MOV reg,rm" operation, but it also loads ES from the next word.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opLES = function LES()
|
||||
{
|
||||
/*
|
||||
* This is like a "MOV reg,rm" operation, but it also loads ES from the next word.
|
||||
*/
|
||||
this.aOpModRegWord[this.getIPByte()].call(this, X86.fnLES);
|
||||
};
|
||||
|
||||
/**
|
||||
* op=0xC5 (LDS reg,word)
|
||||
*
|
||||
* This is like a "MOV reg,rm" operation, but it also loads DS from the next word.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86.opLDS = function LDS()
|
||||
{
|
||||
/*
|
||||
* This is like a "MOV reg,rm" operation, but it also loads DS from the next word.
|
||||
*/
|
||||
this.aOpModRegWord[this.getIPByte()].call(this, X86.fnLDS);
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue