Some performance tweaks

This commit is contained in:
Jeff Parsons 2015-01-31 16:10:16 -08:00 committed by jeffpar
commit da58c2aeaf
11 changed files with 19094 additions and 1478 deletions

View file

@ -57,10 +57,11 @@ try {
* See p. 3-41 of "The 8086 Book" for more details.
*/
var f16Only = true;
var aDst = ["Mem", "Reg"];
var aSize = ["Byte", "Word"];
var aOpPrefix = ["B", "W"];
var aAddrPrefix = ["", "32"];
var aAddrPrefix = [f16Only? "" : "16", "32"];
var aDisp = ["8", "16"];
/*
@ -215,12 +216,17 @@ else {
var sOpMods, sOpMod, sContainer;
print('"use strict";\n');
print("var X86ModB = {};");
print("var X86ModW = {};");
print("var X86ModB32 = {};");
print("var X86ModW32 = {};\n");
if (f16Only) {
print("var X86ModB = {};");
print("var X86ModW = {};\n");
} else {
print("var X86ModB16 = {};");
print("var X86ModW16 = {};");
print("var X86ModB32 = {};");
print("var X86ModW32 = {};\n");
}
for (var a = 0; a <= 1 && !sError; a++) {
for (var a = 0; a <= (f16Only? 0 : 1) && !sError; a++) {
for (w = 0; w <= 1 && !sError; w++) {
@ -259,13 +265,14 @@ else {
}
}
sContainer = "X86ModSIB" + ".aOpModSIB";
print(sContainer + " = [");
for (var sib = 0x00; sib <= 0xff && !sError; sib++) {
genSIB(sib);
if (!f16Only) {
sContainer = "X86ModSIB" + ".aOpModSIB";
print(sContainer + " = [");
for (var sib = 0x00; sib <= 0xff && !sError; sib++) {
genSIB(sib);
}
print("];\n");
}
print("];\n");
if (sEAFuncs) {
print("var X86Mods = {\n" + sEAFuncs + "};\n");
@ -329,26 +336,26 @@ function genMode(a, d, w, mrm, sGroup, sRO) {
sRegBTLo = "this.backTrack.btiBL";
break;
case 4:
sRegGet = "(this.regEAX >> 8) & 0xff";
sRegSet = "this.regEAX = (this.regEAX & ~0xff00) | ";
sRegGet = f16Only? "this.regEAX >> 8" : "(this.regEAX >> 8) & 0xff";
sRegSet = f16Only? "this.regEAX = (this.regEAX & 0xff) | " : "this.regEAX = (this.regEAX & ~0xff00) | ";
sRegSetEnd = " << 8";
sRegBTLo = "this.backTrack.btiAH";
break;
case 5:
sRegGet = "(this.regECX >> 8) & 0xff";
sRegSet = "this.regECX = (this.regECX & ~0xff00) | ";
sRegGet = f16Only? "this.regECX >> 8" : "(this.regECX >> 8) & 0xff";
sRegSet = f16Only? "this.regECX = (this.regECX & 0xff) | " : "this.regECX = (this.regECX & ~0xff00) | ";
sRegSetEnd = " << 8";
sRegBTLo = "this.backTrack.btiCH";
break;
case 6:
sRegGet = "(this.regEDX >> 8) & 0xff";
sRegSet = "this.regEDX = (this.regEDX & ~0xff00) | ";
sRegGet = f16Only? "this.regEDX >> 8" : "(this.regEDX >> 8) & 0xff";
sRegSet = f16Only? "this.regEDX = (this.regEDX & 0xff) | " : "this.regEDX = (this.regEDX & ~0xff00) | ";
sRegSetEnd = " << 8";
sRegBTLo = "this.backTrack.btiDH";
break;
case 7:
sRegGet = "(this.regEBX >> 8) & 0xff";
sRegSet = "this.regEBX = (this.regEBX & ~0xff00) | ";
sRegGet = f16Only? "this.regEBX >> 8" : "(this.regEBX >> 8) & 0xff";
sRegSet = f16Only? "this.regEBX = (this.regEBX & 0xff) | " : "this.regEBX = (this.regEBX & ~0xff00) | ";
sRegSetEnd = " << 8";
sRegBTLo = "this.backTrack.btiBH";
break;
@ -360,50 +367,50 @@ function genMode(a, d, w, mrm, sGroup, sRO) {
else {
switch (reg) {
case 0:
sRegGet = "this.regEAX & this.dataMask";
sRegSet = "this.regEAX = (this.regEAX & ~this.dataMask) | ";
sRegGet = f16Only? "this.regEAX" : "this.regEAX & this.dataMask";
sRegSet = f16Only? "" : "this.regEAX = (this.regEAX & ~this.dataMask) | ";
sRegBTLo = "this.backTrack.btiAL";
sRegBTHi = "this.backTrack.btiAH";
break;
case 1:
sRegGet = "this.regECX & this.dataMask";
sRegSet = "this.regECX = (this.regECX & ~this.dataMask) | ";
sRegGet = f16Only? "this.regECX" : "this.regECX & this.dataMask";
sRegSet = f16Only? "" : "this.regECX = (this.regECX & ~this.dataMask) | ";
sRegBTLo = "this.backTrack.btiCL";
sRegBTHi = "this.backTrack.btiCH";
break;
case 2:
sRegGet = "this.regEDX & this.dataMask";
sRegSet = "this.regEDX = (this.regEDX & ~this.dataMask) | ";
sRegGet = f16Only? "this.regEDX" : "this.regEDX & this.dataMask";
sRegSet = f16Only? "" : "this.regEDX = (this.regEDX & ~this.dataMask) | ";
sRegBTLo = "this.backTrack.btiDL";
sRegBTHi = "this.backTrack.btiDH";
break;
case 3:
sRegGet = "this.regEBX & this.dataMask";
sRegSet = "this.regEBX = (this.regEBX & ~this.dataMask) | ";
sRegGet = f16Only? "this.regEBX" : "this.regEBX & this.dataMask";
sRegSet = f16Only? "" : "this.regEBX = (this.regEBX & ~this.dataMask) | ";
sRegBTLo = "this.backTrack.btiBL";
sRegBTHi = "this.backTrack.btiBH";
break;
case 4:
sRegGet = "this.regESP & this.dataMask";
sRegSet = "this.regESP = (this.regESP & ~this.dataMask) | ";
sRegGet = f16Only? "this.regESP" : "this.regESP & this.dataMask";
sRegSet = f16Only? "" : "this.regESP = (this.regESP & ~this.dataMask) | ";
sRegBTLo = "X86.BACKTRACK.SP_LO";
sRegBTHi = "X86.BACKTRACK.SP_HI";
break;
case 5:
sRegGet = "this.regEBP & this.dataMask";
sRegSet = "this.regEBP = (this.regEBP & ~this.dataMask) | ";
sRegGet = f16Only? "this.regEBP" : "this.regEBP & this.dataMask";
sRegSet = f16Only? "" : "this.regEBP = (this.regEBP & ~this.dataMask) | ";
sRegBTLo = "this.backTrack.btiBPLo";
sRegBTHi = "this.backTrack.btiBPHi";
break;
case 6:
sRegGet = "this.regESI & this.dataMask";
sRegSet = "this.regESI = (this.regESI & ~this.dataMask) | ";
sRegGet = f16Only? "this.regESI" : "this.regESI & this.dataMask";
sRegSet = f16Only? "" : "this.regESI = (this.regESI & ~this.dataMask) | ";
sRegBTLo = "this.backTrack.btiSILo";
sRegBTHi = "this.backTrack.btiSIHi";
break;
case 7:
sRegGet = "this.regEDI & this.dataMask";
sRegSet = "this.regEDI = (this.regEDI & ~this.dataMask) | ";
sRegGet = f16Only? "this.regEDI" : "this.regEDI & this.dataMask";
sRegSet = f16Only? "" : "this.regEDI = (this.regEDI & ~this.dataMask) | ";
sRegBTLo = "this.backTrack.btiDILo";
sRegBTHi = "this.backTrack.btiDIHi";
break;
@ -604,26 +611,26 @@ function genMode(a, d, w, mrm, sGroup, sRO) {
sModRegBTLo = "this.backTrack.btiBL";
break;
case 4:
sModRegGet = "(this.regEAX >> 8) & 0xff";
sModRegSet = "this.regEAX = (this.regEAX & ~0xff00) | ";
sModRegGet = f16Only? "(this.regEAX >> 8)" : "(this.regEAX >> 8) & 0xff";
sModRegSet = f16Only? "this.regEAX = (this.regEAX & 0xff) | " : "this.regEAX = (this.regEAX & ~0xff00) | ";
sModRegSetEnd = " << 8";
sModRegBTLo = "this.backTrack.btiAH";
break;
case 5:
sModRegGet = "(this.regECX >> 8) & 0xff";
sModRegSet = "this.regECX = (this.regECX & ~0xff00) | ";
sModRegGet = f16Only? "(this.regECX >> 8)" : "(this.regECX >> 8) & 0xff";
sModRegSet = f16Only? "this.regECX = (this.regECX & 0xff) | " : "this.regECX = (this.regECX & ~0xff00) | ";
sModRegSetEnd = " << 8";
sModRegBTLo = "this.backTrack.btiCH";
break;
case 6:
sModRegGet = "(this.regEDX >> 8) & 0xff";
sModRegSet = "this.regEDX = (this.regEDX & ~0xff00) | ";
sModRegGet = f16Only? "(this.regEDX >> 8)" : "(this.regEDX >> 8) & 0xff";
sModRegSet = f16Only? "this.regEDX = (this.regEDX & 0xff) | " : "this.regEDX = (this.regEDX & ~0xff00) | ";
sModRegSetEnd = " << 8";
sModRegBTLo = "this.backTrack.btiDH";
break;
case 7:
sModRegGet = "(this.regEBX >> 8) & 0xff";
sModRegSet = "this.regEBX = (this.regEBX & ~0xff00) | ";
sModRegGet = f16Only? "(this.regEBX >> 8)" : "(this.regEBX >> 8) & 0xff";
sModRegSet = f16Only? "this.regEBX = (this.regEBX & 0xff) | " : "this.regEBX = (this.regEBX & ~0xff00) | ";
sModRegSetEnd = " << 8";
sModRegBTLo = "this.backTrack.btiBH";
break;
@ -635,50 +642,50 @@ function genMode(a, d, w, mrm, sGroup, sRO) {
else {
switch (r_m) {
case 0:
sModRegGet = "this.regEAX & this.dataMask";
sModRegSet = "this.regEAX = (this.regEAX & ~this.dataMask) | ";
sModRegGet = f16Only? "this.regEAX" : "this.regEAX & this.dataMask";
sModRegSet = f16Only? "" : "this.regEAX = (this.regEAX & ~this.dataMask) | ";
sModRegBTLo = "this.backTrack.btiAL";
sModRegBTHi = "this.backTrack.btiAH";
break;
case 1:
sModRegGet = "this.regECX & this.dataMask";
sModRegSet = "this.regECX = (this.regECX & ~this.dataMask) | ";
sModRegGet = f16Only? "this.regECX" : "this.regECX & this.dataMask";
sModRegSet = f16Only? "" : "this.regECX = (this.regECX & ~this.dataMask) | ";
sModRegBTLo = "this.backTrack.btiCL";
sModRegBTHi = "this.backTrack.btiCH";
break;
case 2:
sModRegGet = "this.regEDX & this.dataMask";
sModRegSet = "this.regEDX = (this.regEDX & ~this.dataMask) | ";
sModRegGet = f16Only? "this.regEDX" : "this.regEDX & this.dataMask";
sModRegSet = f16Only? "" : "this.regEDX = (this.regEDX & ~this.dataMask) | ";
sModRegBTLo = "this.backTrack.btiDL";
sModRegBTHi = "this.backTrack.btiDH";
break;
case 3:
sModRegGet = "this.regEBX & this.dataMask";
sModRegSet = "this.regEBX = (this.regEBX & ~this.dataMask) | ";
sModRegGet = f16Only? "this.regEBX" : "this.regEBX & this.dataMask";
sModRegSet = f16Only? "" : "this.regEBX = (this.regEBX & ~this.dataMask) | ";
sModRegBTLo = "this.backTrack.btiBL";
sModRegBTHi = "this.backTrack.btiBH";
break;
case 4:
sModRegGet = "this.regESP & this.dataMask";
sModRegSet = "this.regESP = (this.regESP & ~this.dataMask) | ";
sModRegGet = f16Only? "this.regESP" : "this.regESP & this.dataMask";
sModRegSet = f16Only? "" : "this.regESP = (this.regESP & ~this.dataMask) | ";
sModRegBTLo = "X86.BACKTRACK.SP_LO";
sModRegBTHi = "X86.BACKTRACK.SP_HI";
break;
case 5:
sModRegGet = "this.regEBP & this.dataMask";
sModRegSet = "this.regEBP = (this.regEBP & ~this.dataMask) | ";
sModRegGet = f16Only? "this.regEBP" : "this.regEBP & this.dataMask";
sModRegSet = f16Only? "" : "this.regEBP = (this.regEBP & ~this.dataMask) | ";
sModRegBTLo = "this.backTrack.btiBPLo";
sModRegBTHi = "this.backTrack.btiBPHi";
break;
case 6:
sModRegGet = "this.regESI & this.dataMask";
sModRegSet = "this.regESI = (this.regESI & ~this.dataMask) | ";
sModRegGet = f16Only? "this.regESI" : "this.regESI & this.dataMask";
sModRegSet = f16Only? "" : "this.regESI = (this.regESI & ~this.dataMask) | ";
sModRegBTLo = "this.backTrack.btiSILo";
sModRegBTHi = "this.backTrack.btiSIHi";
break;
case 7:
sModRegGet = "this.regEDI & this.dataMask";
sModRegSet = "this.regEDI = (this.regEDI & ~this.dataMask) | ";
sModRegGet = f16Only? "this.regEDI" : "this.regEDI & this.dataMask";
sModRegSet = f16Only? "" : "this.regEDI = (this.regEDI & ~this.dataMask) | ";
sModRegBTLo = "this.backTrack.btiDILo";
sModRegBTHi = "this.backTrack.btiDIHi";
break;

View file

@ -4746,7 +4746,7 @@ if (DEBUGGER) {
if (this.cmp) this.cmp.reset();
return true;
case "ver":
this.println((APPNAME || "PCjs") + " version " + APPVERSION + " (" + (I386? "80386" : "80286") + (COMPILED? ",RELEASE" : (DEBUG? ",DEBUG" : ",NODEBUG")) + (PREFETCH? ",PREFETCH" : ",NOPREFETCH") + (TYPEDARRAYS? ",TYPEDARRAYS" : (FATARRAYS? ",FATARRAYS" : ",LONGARRAYS")) + (BACKTRACK? ",BACKTRACK" : "") + ")");
this.println((APPNAME || "PCjs") + " version " + APPVERSION + " (" + this.cpu.model + (COMPILED? ",RELEASE" : (DEBUG? ",DEBUG" : ",NODEBUG")) + (PREFETCH? ",PREFETCH" : ",NOPREFETCH") + (TYPEDARRAYS? ",TYPEDARRAYS" : (FATARRAYS? ",FATARRAYS" : ",LONGARRAYS")) + (BACKTRACK? ",BACKTRACK" : ",NOBACKTRACK") + ")");
return true;
default:
ch0 = sCmd.charAt(0);

View file

@ -53,6 +53,7 @@ if (typeof module !== 'undefined') {
var Component = require("../../shared/lib/component");
var Messages = require("./messages");
}
/**
* @class DataView
* @property {function(number,boolean):number} getUint8
@ -63,6 +64,12 @@ if (typeof module !== 'undefined') {
* @property {function(number,number,boolean)} setInt32
*/
var littleEndian = (function() {
var buffer = new ArrayBuffer(2);
new DataView(buffer).setUint16(0, 256, true);
return new Uint16Array(buffer)[0] === 256;
})();
/**
* Memory(addr, size, type, controller)
*
@ -163,11 +170,14 @@ function Memory(addr, size, type, controller)
this.buffer = new ArrayBuffer(size);
this.dv = new DataView(this.buffer, 0, size);
/*
* We could also use dv.getUint8() and dv.setUint8(), but using ab[] to get/set bytes
* in this.buffer is more convenient and presents no "endianness" issues.
* If littleEndian is true, we can use ab[], aw[] and adw[] directly; well, we can use them
* whenever the offset is a multiple of 1, 2 or 4, respectively. Otherwise, we must fallback to
* dv.getUint8()/dv.setUint8(), dv.getUint16()/dv.setUint16() and db.getInt32()/dv.setInt32().
*/
this.ab = new Uint8Array(this.buffer, 0, size);
this.setAccess(Memory.afnTypedArray);
this.aw = new Uint16Array(this.buffer, 0, size >> 1);
this.adw = new Int32Array(this.buffer, 0, size >> 2);
this.setAccess(littleEndian? Memory.afnLittleEndian : Memory.afnBigEndian);
} else {
if (FATARRAYS) {
this.ab = new Array(size);
@ -473,86 +483,199 @@ Memory.writeLongChecked = function writeLongChecked(off, l)
};
/**
* readByteTypedArray(off)
* readByteBigEndian(off)
*
* @this {Memory}
* @param {number} off
* @return {number}
*/
Memory.readByteTypedArray = function readByteTypedArray(off)
Memory.readByteBigEndian = function readByteBigEndian(off)
{
Component.assert(off >= 0 && off < this.size);
return this.ab[off];
};
/**
* readShortTypedArray(off)
* readByteLittleEndian(off)
*
* @this {Memory}
* @param {number} off
* @return {number}
*/
Memory.readShortTypedArray = function readShortTypedArray(off)
Memory.readByteLittleEndian = function readByteLittleEndian(off)
{
Component.assert(off >= 0 && off < this.size);
return this.ab[off];
};
/**
* readShortBigEndian(off)
*
* @this {Memory}
* @param {number} off
* @return {number}
*/
Memory.readShortBigEndian = function readShortBigEndian(off)
{
Component.assert(off >= 0 && off < this.size - 1);
return this.dv.getUint16(off, true);
};
/**
* readLongTypedArray(off)
* readShortLittleEndian(off)
*
* @this {Memory}
* @param {number} off
* @return {number}
*/
Memory.readLongTypedArray = function readLongTypedArray(off)
Memory.readShortLittleEndian = function readShortLittleEndian(off)
{
Component.assert(off >= 0 && off < this.size - 1);
/*
* TODO: It remains to be seen if there's any advantage to checking the offset
* for an aligned read vs. always reading the bytes separately; it seems a safe bet
* for longs, but it's less clear for shorts.
*/
return (off & 0x1)? (this.ab[off] | (this.ab[off+1] << 8)) : this.aw[off >> 1];
};
/**
* readLongBigEndian(off)
*
* @this {Memory}
* @param {number} off
* @return {number}
*/
Memory.readLongBigEndian = function readLongBigEndian(off)
{
Component.assert(off >= 0 && off < this.size - 3);
return this.dv.getInt32(off, true);
};
/**
* writeByteTypedArray(off, b)
* readLongLittleEndian(off)
*
* @this {Memory}
* @param {number} off
* @return {number}
*/
Memory.readLongLittleEndian = function readLongLittleEndian(off)
{
Component.assert(off >= 0 && off < this.size - 3);
/*
* TODO: It remains to be seen if there's any advantage to checking the offset
* for an aligned read vs. always reading the bytes separately; it seems a safe bet
* for longs, but it's less clear for shorts.
*/
return (off & 0x3)? (this.ab[off] | (this.ab[off+1] << 8) | (this.ab[off+2] << 16) | (this.ab[off+3] << 24)) : this.adw[off >> 2];
};
/**
* writeByteBigEndian(off, b)
*
* @this {Memory}
* @param {number} off
* @param {number} b
*/
Memory.writeByteTypedArray = function writeByteTypedArray(off, b)
Memory.writeByteBigEndian = function writeByteBigEndian(off, b)
{
Component.assert(off >= 0 && off < this.size && (b & 0xff) == b);
Component.assert(off >= 0 && off < this.size);
this.ab[off] = b;
this.fDirty = true;
};
/**
* writeShortTypedArray(off, w)
* writeByteLittleEndian(off, b)
*
* @this {Memory}
* @param {number} off
* @param {number} b
*/
Memory.writeByteLittleEndian = function writeByteLittleEndian(off, b)
{
Component.assert(off >= 0 && off < this.size);
this.ab[off] = b;
this.fDirty = true;
};
/**
* writeShortBigEndian(off, w)
*
* @this {Memory}
* @param {number} off
* @param {number} w
*/
Memory.writeShortTypedArray = function writeShortTypedArray(off, w)
Memory.writeShortBigEndian = function writeShortBigEndian(off, w)
{
Component.assert(off >= 0 && off < this.size - 1 && (w & 0xffff) == w);
Component.assert(off >= 0 && off < this.size - 1);
this.dv.setUint16(off, w, true);
this.fDirty = true;
};
/**
* writeLongTypedArray(off, l)
* writeShortLittleEndian(off, w)
*
* @this {Memory}
* @param {number} off
* @param {number} w
*/
Memory.writeShortLittleEndian = function writeShortLittleEndian(off, w)
{
Component.assert(off >= 0 && off < this.size - 1);
/*
* TODO: It remains to be seen if there's any advantage to checking the offset
* for an aligned write vs. always writing the bytes separately; it seems a safe bet
* for longs, but it's less clear for shorts.
*/
if (off & 0x1) {
this.ab[off] = w;
this.ab[off+1] = w >> 8;
} else {
this.aw[off >> 1] = w;
}
this.fDirty = true;
};
/**
* writeLongBigEndian(off, l)
*
* @this {Memory}
* @param {number} off
* @param {number} l
*/
Memory.writeLongTypedArray = function writeLongTypedArray(off, l)
Memory.writeLongBigEndian = function writeLongBigEndian(off, l)
{
Component.assert(off >= 0 && off < this.size - 3);
this.dv.setInt32(off, l, true);
this.fDirty = true;
};
/**
* writeLongLittleEndian(off, l)
*
* @this {Memory}
* @param {number} off
* @param {number} l
*/
Memory.writeLongLittleEndian = function writeLongLittleEndian(off, l)
{
Component.assert(off >= 0 && off < this.size - 3);
/*
* TODO: It remains to be seen if there's any advantage to checking the offset
* for an aligned write vs. always writing the bytes separately; it seems a safe bet
* for longs, but it's less clear for shorts.
*/
if (off & 0x3) {
this.ab[off] = l;
this.ab[off+1] = (l >> 8);
this.ab[off+2] = (l >> 16);
this.ab[off+3] = (l >> 24);
} else {
this.adw[off >> 2] = l;
}
this.fDirty = true;
};
/**
* readBackTrackNone(off)
*
@ -635,7 +758,8 @@ Memory.afnMemory = [Memory.readByteMemory, Memory.readShortMemory, Mem
Memory.afnChecked = [Memory.readByteChecked, Memory.readShortChecked, Memory.readLongChecked, Memory.writeByteChecked, Memory.writeShortChecked, Memory.writeLongChecked];
if (TYPEDARRAYS) {
Memory.afnTypedArray = [Memory.readByteTypedArray, Memory.readShortTypedArray, Memory.readLongTypedArray, Memory.writeByteTypedArray, Memory.writeShortTypedArray, Memory.writeLongTypedArray];
Memory.afnBigEndian = [Memory.readByteBigEndian, Memory.readShortBigEndian, Memory.readLongBigEndian, Memory.writeByteBigEndian, Memory.writeShortBigEndian, Memory.writeLongBigEndian];
Memory.afnLittleEndian = [Memory.readByteLittleEndian, Memory.readShortLittleEndian, Memory.readLongLittleEndian, Memory.writeByteLittleEndian, Memory.writeShortLittleEndian, Memory.writeLongLittleEndian];
}
Memory.prototype = {

View file

@ -52,6 +52,8 @@ if (typeof module !== 'undefined') {
if (I386) {
if (typeof module !== 'undefined') {
var X86ModB16 = require("./x86modb16");
var X86ModW16 = require("./x86modw16");
var X86ModB32 = require("./x86modb32");
var X86ModW32 = require("./x86modw32");
var X86ModSIB = require("./x86modsib");
@ -970,7 +972,6 @@ X86CPU.prototype.resetRegs = function()
*/
this.addrSize = this.segCS.addrSize;
this.addrMask = this.segCS.addrMask;
/*
* It's also worth noting that instructions that implicitly use the stack also rely on something called STACK size,
* which is based on the BIG bit of the last descriptor loaded into SS; use the following segSS properties:
@ -986,7 +987,7 @@ X86CPU.prototype.resetRegs = function()
* The memory dispatch tables; opMem refers to the active set, based on the current OPERAND size (dataSize),
* which is based foremost on segCS.dataSize, but can also be overridden by an OPERAND size instruction prefix.
*/
this.aaOpMem = new Array(5);
this.aaOpMem = [];
this.aaOpMem[2] = {
getWord: this.getShort.bind(this),
setWord: this.setShort.bind(this)
@ -998,31 +999,43 @@ X86CPU.prototype.resetRegs = function()
};
}
this.opMem = this.aaOpMem[this.segCS.dataSize];
this.setOpMod();
};
/*
* The ModRM dispatch tables; opMod refers to the active set, based on the current ADDRESS size (addrSize),
* which is based foremost on segCS.addrSize, but can also be overridden by an ADDRESS size instruction prefix.
*/
this.aaOpMod = new Array(5);
this.aaOpMod[2] = {
aOpModRegByte: X86ModB.aOpModReg,
aOpModMemByte: X86ModB.aOpModMem,
aOpModGrpByte: X86ModB.aOpModGrp,
aOpModRegWord: X86ModW.aOpModReg,
aOpModMemWord: X86ModW.aOpModMem,
aOpModGrpWord: X86ModW.aOpModGrp
};
if (I386) {
this.aaOpMod[4] = {
aOpModRegByte: X86ModB32.aOpModReg,
aOpModMemByte: X86ModB32.aOpModMem,
aOpModGrpByte: X86ModB32.aOpModGrp,
aOpModRegWord: X86ModW32.aOpModReg,
aOpModMemWord: X86ModW32.aOpModMem,
aOpModGrpWord: X86ModW32.aOpModGrp
};
/**
* setOpMod()
*
* Select the appropriate ModRM dispatch tables, based on the current ADDRESS size (addrSize), which
* is based foremost on segCS.addrSize, but can also be overridden by an ADDRESS size instruction prefix.
*
* @this {X86CPU}
*/
X86CPU.prototype.setOpMod = function()
{
if (!I386) {
this.aOpModRegByte = X86ModB.aOpModReg;
this.aOpModMemByte = X86ModB.aOpModMem;
this.aOpModGrpByte = X86ModB.aOpModGrp;
this.aOpModRegWord = X86ModW.aOpModReg;
this.aOpModMemWord = X86ModW.aOpModMem;
this.aOpModGrpWord = X86ModW.aOpModGrp;
} else {
if (this.addrSize == 2) {
this.aOpModRegByte = X86ModB16.aOpModReg;
this.aOpModMemByte = X86ModB16.aOpModMem;
this.aOpModGrpByte = X86ModB16.aOpModGrp;
this.aOpModRegWord = X86ModW16.aOpModReg;
this.aOpModMemWord = X86ModW16.aOpModMem;
this.aOpModGrpWord = X86ModW16.aOpModGrp;
} else {
this.aOpModRegByte = X86ModB32.aOpModReg;
this.aOpModMemByte = X86ModB32.aOpModMem;
this.aOpModGrpByte = X86ModB32.aOpModGrp;
this.aOpModRegWord = X86ModW32.aOpModReg;
this.aOpModMemWord = X86ModW32.aOpModMem;
this.aOpModGrpWord = X86ModW32.aOpModGrp;
}
}
this.opMod = this.aaOpMod[this.segCS.addrSize];
};
/**
@ -1378,7 +1391,7 @@ X86CPU.prototype.setES = function(sel)
*/
X86CPU.prototype.setIP = function(off)
{
this.regLIP = this.segCS.base + (this.regEIP = off & this.addrMask);
this.regLIP = this.segCS.base + (this.regEIP = off & (I386? this.addrMask : 0xffff));
if (PREFETCH) this.flushPrefetch(this.regLIP);
};
@ -1429,7 +1442,7 @@ X86CPU.prototype.setCSIP = function(off, sel, fCall)
*/
X86CPU.prototype.advanceIP = function(inc)
{
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + inc) & this.addrMask);
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + inc) & (I386? this.addrMask : 0xffff));
if (PREFETCH) this.advancePrefetch(inc);
};
@ -2026,9 +2039,9 @@ X86CPU.prototype.getEAByte = function(seg, off)
X86CPU.prototype.getEAWord = function(seg, off)
{
this.segEA = seg;
this.regEA = seg.checkRead(this.offEA = off, this.dataSize-1);
this.regEA = seg.checkRead(this.offEA = off, (I386? this.dataSize-1 : 1));
if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var w = this.opMem.getWord(this.regEA);
var w = I386? this.opMem.getWord(this.regEA) : this.getShort(this.regEA);
if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2065,9 +2078,9 @@ X86CPU.prototype.modEAByte = function(seg, off)
X86CPU.prototype.modEAWord = function(seg, off)
{
this.segEA = seg;
this.regEAWrite = this.regEA = seg.checkRead(this.offEA = off, this.dataSize-1);
this.regEAWrite = this.regEA = seg.checkRead(this.offEA = off, (I386? this.dataSize-1 : 1));
if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var w = this.opMem.getWord(this.regEA);
var w = I386? this.opMem.getWord(this.regEA) : this.getShort(this.regEA);
if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2086,7 +2099,7 @@ X86CPU.prototype.getEAByteData = function(off)
{
// return this.getEAByte(this.segData, off & this.addrMask);
this.segEA = this.segData;
this.regEA = this.segData.checkRead(this.offEA = off & this.addrMask, 0);
this.regEA = this.segData.checkRead(this.offEA = off & (I386? this.addrMask : 0xffff), 0);
if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var b = this.getByte(this.regEA);
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiMemLo;
@ -2104,7 +2117,7 @@ X86CPU.prototype.getEAByteStack = function(off)
{
// return this.getEAByte(this.segStack, off & this.addrMask);
this.segEA = this.segStack;
this.regEA = this.segStack.checkRead(this.offEA = off & this.addrMask, 0);
this.regEA = this.segStack.checkRead(this.offEA = off & (I386? this.addrMask : 0xffff), 0);
if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var b = this.getByte(this.regEA);
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiMemLo;
@ -2122,9 +2135,9 @@ X86CPU.prototype.getEAWordData = function(off)
{
// return this.getEAWord(this.segData, off & this.addrMask);
this.segEA = this.segData;
this.regEA = this.segData.checkRead(this.offEA = off & this.addrMask, this.dataSize-1);
this.regEA = this.segData.checkRead(this.offEA = off & (I386? this.addrMask : 0xffff), (I386? this.dataSize-1 : 1));
if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var w = this.opMem.getWord(this.regEA);
var w = I386? this.opMem.getWord(this.regEA) : this.getShort(this.regEA);
if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2143,9 +2156,9 @@ X86CPU.prototype.getEAWordStack = function(off)
{
// return this.getEAWord(this.segStack, off & this.addrMask);
this.segEA = this.segStack;
this.regEA = this.segStack.checkRead(this.offEA = off & this.addrMask, this.dataSize-1);
this.regEA = this.segStack.checkRead(this.offEA = off & (I386? this.addrMask : 0xffff), (I386? this.dataSize-1 : 1));
if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var w = this.opMem.getWord(this.regEA);
var w = I386? this.opMem.getWord(this.regEA) : this.getShort(this.regEA);
if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2164,7 +2177,7 @@ X86CPU.prototype.modEAByteData = function(off)
{
// return this.modEAByte(this.segData, off & this.addrMask);
this.segEA = this.segData;
this.regEAWrite = this.regEA = this.segData.checkRead(this.offEA = off & this.addrMask, 0);
this.regEAWrite = this.regEA = this.segData.checkRead(this.offEA = off & (I386? this.addrMask : 0xffff), 0);
if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var b = this.getByte(this.regEA);
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiMemLo;
@ -2182,7 +2195,7 @@ X86CPU.prototype.modEAByteStack = function(off)
{
// return this.modEAByte(this.segStack, off & this.addrMask);
this.segEA = this.segStack;
this.regEAWrite = this.regEA = this.segStack.checkRead(this.offEA = off & this.addrMask, 0);
this.regEAWrite = this.regEA = this.segStack.checkRead(this.offEA = off & (I386? this.addrMask : 0xffff), 0);
if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var b = this.getByte(this.regEA);
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiMemLo;
@ -2200,9 +2213,9 @@ X86CPU.prototype.modEAWordData = function(off)
{
// return this.modEAWord(this.segData, off & this.addrMask);
this.segEA = this.segData;
this.regEAWrite = this.regEA = this.segData.checkRead(this.offEA = off & this.addrMask, this.dataSize-1);
this.regEAWrite = this.regEA = this.segData.checkRead(this.offEA = off & (I386? this.addrMask : 0xffff), (I386? this.dataSize-1 : 1));
if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var w = this.opMem.getWord(this.regEA);
var w = I386? this.opMem.getWord(this.regEA) : this.getShort(this.regEA);
if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2221,9 +2234,9 @@ X86CPU.prototype.modEAWordStack = function(off)
{
// return this.modEAWord(this.segStack, off & this.addrMask);
this.segEA = this.segStack;
this.regEAWrite = this.regEA = this.segStack.checkRead(this.offEA = off & this.addrMask, this.dataSize-1);
this.regEAWrite = this.regEA = this.segStack.checkRead(this.offEA = off & (I386? this.addrMask : 0xffff), (I386? this.dataSize-1 : 1));
if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var w = this.opMem.getWord(this.regEA);
var w = I386? this.opMem.getWord(this.regEA) : this.getShort(this.regEA);
if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2257,7 +2270,11 @@ X86CPU.prototype.setEAWord = function(w)
this.backTrack.btiMemLo = this.backTrack.btiEALo;
this.backTrack.btiMemHi = this.backTrack.btiEAHi;
}
this.opMem.setWord(this.segEA.checkWrite(this.offEA, this.dataSize-1), w);
if (!I386) {
this.setShort(this.segEA.checkWrite(this.offEA, 1), w);
} else {
this.opMem.setWord(this.segEA.checkWrite(this.offEA, this.dataSize-1), w);
}
};
/**
@ -2287,7 +2304,11 @@ X86CPU.prototype.getSOByte = function(seg, off)
*/
X86CPU.prototype.getSOWord = function(seg, off)
{
return this.opMem.getWord(seg.checkRead(off, this.dataSize-1));
if (!I386) {
return this.getShort(seg.checkRead(off, 1));
} else {
return this.opMem.getWord(seg.checkRead(off, this.dataSize-1));
}
};
/**
@ -2317,7 +2338,11 @@ X86CPU.prototype.setSOByte = function(seg, off, b)
*/
X86CPU.prototype.setSOWord = function(seg, off, w)
{
this.opMem.setWord(seg.checkWrite(off, this.dataSize-1), w);
if (!I386) {
this.setShort(seg.checkWrite(off, 1), w);
} else {
this.opMem.setWord(seg.checkWrite(off, this.dataSize-1), w);
}
};
/**
@ -2460,7 +2485,7 @@ X86CPU.prototype.getIPByte = function()
{
var b = (PREFETCH? this.getBytePrefetch(this.regLIP) : this.getByte(this.regLIP));
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + 1) & this.addrMask);
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + 1) & (I386? this.addrMask : 0xffff));
return b;
};
@ -2474,8 +2499,8 @@ X86CPU.prototype.getIPDisp = function()
{
var b = ((PREFETCH? this.getBytePrefetch(this.regLIP) : this.getByte(this.regLIP)) << 24) >> 24;
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + 1) & this.addrMask);
return b & this.addrMask;
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + 1) & (I386? this.addrMask : 0xffff));
return b & (I386? this.addrMask : 0xffff);
};
/**
@ -2486,12 +2511,12 @@ X86CPU.prototype.getIPDisp = function()
*/
X86CPU.prototype.getIPWord = function()
{
var w = (PREFETCH? this.getWordPrefetch(this.regLIP) : this.opMem.getWord(this.regLIP));
var w = (PREFETCH? this.getWordPrefetch(this.regLIP) : (I386? this.opMem.getWord(this.regLIP) : this.getShort(this.regLIP)));
if (BACKTRACK) {
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMemHi);
}
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + this.dataSize) & this.addrMask);
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + (I386? this.dataSize : 2)) & (I386? this.addrMask : 0xffff));
return w;
};
@ -2518,7 +2543,7 @@ X86CPU.prototype.getSIBAddr = function(mod)
X86CPU.prototype.popWord = function()
{
var regESP = this.regESP;
this.regESP = (this.regESP + this.dataSize) & this.addrMask;
this.regESP = (this.regESP + (I386? this.dataSize : 2)) & (I386? this.addrMask : 0xffff);
return this.getSOWord(this.segSS, regESP);
};
@ -2531,7 +2556,7 @@ X86CPU.prototype.popWord = function()
X86CPU.prototype.pushWord = function(w)
{
this.assert((w & this.dataMask) == w);
this.setSOWord(this.segSS, (this.regESP = (this.regESP - this.dataSize) & this.addrMask), w);
this.setSOWord(this.segSS, (this.regESP = (this.regESP - (I386? this.dataSize : 2)) & (I386? this.addrMask : 0xffff)), w);
};
/**
@ -2823,7 +2848,6 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
this.addrSize = this.segCS.addrSize;
this.addrMask = this.segCS.addrMask;
this.opMem = this.aaOpMem[this.dataSize];
this.opMod = this.aaOpMod[this.addrSize];
}
this.opPrefixes = this.opFlags & X86.OPFLAG.REPEAT;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -49,7 +49,7 @@ var X86Op0F = {
if ((bModRM & 0x38) < 0x10) { // possible reg values: 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
this.opFlags |= X86.OPFLAG.NOREAD;
}
this.opMod.aOpModGrpWord[bModRM].call(this, this.aOpGrp6, X86Grps.opGrpNoSrc);
this.aOpModGrpWord[bModRM].call(this, this.aOpGrp6, X86Grps.opGrpNoSrc);
},
/**
* @this {X86CPU}
@ -61,7 +61,7 @@ var X86Op0F = {
if (!(bModRM & 0x10)) {
this.opFlags |= X86.OPFLAG.NOREAD;
}
this.opMod.aOpModGrpWord[bModRM].call(this, X86Op0F.aOpGrp7, X86Grps.opGrpNoSrc);
this.aOpModGrpWord[bModRM].call(this, X86Op0F.aOpGrp7, X86Grps.opGrpNoSrc);
},
/**
* @this {X86CPU}
@ -69,7 +69,7 @@ var X86Op0F = {
* op=0x0F,0x02 (lar reg,rm)
*/
opLAR: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLAR);
this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLAR);
},
/**
* @this {X86CPU}
@ -77,7 +77,7 @@ var X86Op0F = {
* op=0x0F,0x03 (lsl reg,rm)
*/
opLSL: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLSL);
this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLSL);
},
/**
* opLOADALL()

View file

@ -53,8 +53,8 @@ var X86OpXX = {
* Opcode bytes 0x00 0x00 are sufficiently uncommon that it's more likely we've started executing
* in the weeds, so we'll stop the CPU if we're in DEBUG mode.
*/
if (DEBUG && !b) this.stopCPU();
this.opMod.aOpModMemByte[b].call(this, X86Grps.opGrpADDb);
if (DEBUG && DEBUGGER && !b) this.stopCPU();
this.aOpModMemByte[b].call(this, X86Grps.opGrpADDb);
},
/**
* op=0x01 (ADD word,reg)
@ -62,7 +62,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opADDmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpADDw);
this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpADDw);
},
/**
* op=0x02 (ADD reg,byte)
@ -70,7 +70,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opADDrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpADDb);
this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpADDb);
},
/**
* op=0x03 (ADD reg,word)
@ -78,7 +78,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opADDrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpADDw);
this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpADDw);
},
/**
* op=0x04 (ADD AL,imm8)
@ -139,7 +139,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opORmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpORb);
this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpORb);
},
/**
* op=0x09 (OR word,reg)
@ -147,7 +147,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opORmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpORw);
this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpORw);
},
/**
* op=0x0A (OR reg,byte)
@ -155,7 +155,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opORrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpORb);
this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpORb);
},
/**
* op=0x0B (OR reg,word)
@ -163,7 +163,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opORrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpORw);
this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpORw);
},
/**
* op=0x0C (OR AL,imm8)
@ -227,7 +227,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opADCmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpADCb);
this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpADCb);
},
/**
* op=0x11 (ADC word,reg)
@ -235,7 +235,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opADCmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpADCw);
this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpADCw);
},
/**
* op=0x12 (ADC reg,byte)
@ -243,7 +243,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opADCrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpADCb);
this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpADCb);
},
/**
* op=0x13 (ADC reg,word)
@ -251,7 +251,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opADCrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpADCw);
this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpADCw);
},
/**
* op=0x14 (ADC AL,imm8)
@ -307,7 +307,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opSBBmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpSBBb);
this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpSBBb);
},
/**
* op=0x19 (SBB word,reg)
@ -315,7 +315,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opSBBmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpSBBw);
this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpSBBw);
},
/**
* op=0x1A (SBB reg,byte)
@ -323,7 +323,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opSBBrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpSBBb);
this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpSBBb);
},
/**
* op=0x1B (SBB reg,word)
@ -331,7 +331,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opSBBrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpSBBw);
this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpSBBw);
},
/**
* op=0x1C (SBB AL,imm8)
@ -387,7 +387,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opANDmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpANDb);
this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpANDb);
},
/**
* op=0x21 (AND word,reg)
@ -395,7 +395,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opANDmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpANDw);
this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpANDw);
},
/**
* op=0x22 (AND reg,byte)
@ -403,7 +403,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opANDrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpANDb);
this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpANDb);
},
/**
* op=0x23 (AND reg,word)
@ -411,7 +411,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opANDrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpANDw);
this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpANDw);
},
/**
* op=0x24 (AND AL,imm8)
@ -486,7 +486,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opSUBmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpSUBb);
this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpSUBb);
},
/**
* op=0x29 (SUB word,reg)
@ -494,7 +494,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opSUBmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpSUBw);
this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpSUBw);
},
/**
* op=0x2A (SUB reg,byte)
@ -502,7 +502,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opSUBrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpSUBb);
this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpSUBb);
},
/**
* op=0x2B (SUB reg,word)
@ -510,7 +510,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opSUBrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpSUBw);
this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpSUBw);
},
/**
* op=0x2C (SUB AL,imm8)
@ -585,7 +585,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opXORmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpXORb);
this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpXORb);
},
/**
* op=0x31 (XOR word,reg)
@ -593,7 +593,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opXORmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpXORw);
this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpXORw);
},
/**
* op=0x32 (XOR reg,byte)
@ -601,7 +601,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opXORrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpXORb);
this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpXORb);
},
/**
* op=0x33 (XOR reg,word)
@ -609,7 +609,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opXORrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpXORw);
this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpXORw);
},
/**
* op=0x34 (XOR AL,imm8)
@ -684,7 +684,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opCMPmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpCMPb);
this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpCMPb);
},
/**
* op=0x39 (CMP word,reg)
@ -692,7 +692,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opCMPmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw);
this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw);
},
/**
* op=0x3A (CMP reg,byte)
@ -700,7 +700,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opCMPrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpCMPb);
this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpCMPb);
},
/**
* op=0x3B (CMP reg,word)
@ -708,7 +708,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opCMPrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw);
this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw);
},
/**
* op=0x3C (CMP AL,imm8)
@ -1249,7 +1249,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opBOUND: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpBOUND);
this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpBOUND);
},
/**
* op=0x63 (ARPL word,reg) (80286 and up)
@ -1257,7 +1257,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opARPL: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpARPL);
this.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpARPL);
},
/**
* op=0x66 (OS:) (80386 and up)
@ -1267,11 +1267,13 @@ var X86OpXX = {
* @this {X86CPU}
*/
opOS: function() {
this.opFlags |= X86.OPFLAG.SEG;
this.dataSize ^= 0x6; // that which is 2 shall become 4, and vice versa
this.dataMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa
this.opMem = this.aaOpMem[this.dataSize];
this.nStepCycles -= this.CYCLES.nOpCyclesPrefix;
if (I386) {
this.opFlags |= X86.OPFLAG.SEG;
this.dataSize ^= 0x6; // that which is 2 shall become 4, and vice versa
this.dataMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa
this.opMem = this.aaOpMem[this.dataSize];
this.nStepCycles -= this.CYCLES.nOpCyclesPrefix;
}
},
/**
* op=0x67 (AS:) (80386 and up)
@ -1281,11 +1283,13 @@ var X86OpXX = {
* @this {X86CPU}
*/
opAS: function() {
this.opFlags |= X86.OPFLAG.SEG;
this.addrSize ^= 0x06; // that which is 2 shall become 4, and vice versa
this.addrMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa
this.opMod = this.aaOpMod[this.addrSize];
this.nStepCycles -= this.CYCLES.nOpCyclesPrefix;
if (I386) {
this.opFlags |= X86.OPFLAG.SEG;
this.addrSize ^= 0x06; // that which is 2 shall become 4, and vice versa
this.addrMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa
this.setOpMod();
this.nStepCycles -= this.CYCLES.nOpCyclesPrefix;
}
},
/**
* op=0x68 (PUSH imm16) (80186/80188 and up)
@ -1302,7 +1306,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opIMUL16: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpIMUL16);
this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpIMUL16);
},
/**
* op=0x6A (PUSH imm8) (80186/80188 and up)
@ -1320,7 +1324,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opIMUL8: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpIMUL8);
this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpIMUL8);
},
/**
* op=0x6C (INSB) (80186/80188 and up)
@ -1743,7 +1747,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp1b: function() {
this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp1b, this.getIPByte);
this.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp1b, this.getIPByte);
this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
},
/**
@ -1752,7 +1756,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp1w: function() {
this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp1w, this.getIPWord);
this.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp1w, this.getIPWord);
this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
},
/**
@ -1761,7 +1765,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp1sw: function() {
this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp1w, this.getIPDisp);
this.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp1w, this.getIPDisp);
this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
},
/**
@ -1770,7 +1774,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opTESTrb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Help.opHelpTESTb);
this.aOpModMemByte[this.getIPByte()].call(this, X86Help.opHelpTESTb);
},
/**
* op=0x85 (TEST reg,word)
@ -1778,7 +1782,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opTESTrw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpTESTw);
this.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpTESTw);
},
/**
* op=0x86 (XCHG reg,byte)
@ -1807,7 +1811,7 @@ var X86OpXX = {
* this.regEDX = (this.regEDX & 0xff) | (b << 8);
* }
*/
this.opMod.aOpModRegByte[this.bModRM = this.getIPByte()].call(this, X86Help.opHelpXCHGrb);
this.aOpModRegByte[this.bModRM = this.getIPByte()].call(this, X86Help.opHelpXCHGrb);
},
/**
* op=0x87 (XCHG reg,word)
@ -1818,7 +1822,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opXCHGrw: function() {
this.opMod.aOpModRegWord[this.bModRM = this.getIPByte()].call(this, X86Help.opHelpXCHGrw);
this.aOpModRegWord[this.bModRM = this.getIPByte()].call(this, X86Help.opHelpXCHGrw);
},
/**
* op=0x88 (MOV byte,reg)
@ -1830,7 +1834,7 @@ var X86OpXX = {
* Like other MOV operations, the destination does not need to be read, just written.
*/
this.opFlags |= X86.OPFLAG.NOREAD;
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Help.opHelpMOV);
this.aOpModMemByte[this.getIPByte()].call(this, X86Help.opHelpMOV);
},
/**
* op=0x89 (MOV word,reg)
@ -1842,7 +1846,7 @@ var X86OpXX = {
* Like other MOV operations, the destination does not need to be read, just written.
*/
this.opFlags |= X86.OPFLAG.NOREAD;
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpMOV);
this.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpMOV);
},
/**
* op=0x8A (MOV reg,byte)
@ -1850,7 +1854,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opMOVrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Help.opHelpMOV);
this.aOpModRegByte[this.getIPByte()].call(this, X86Help.opHelpMOV);
},
/**
* op=0x8B (MOV reg,word)
@ -1858,7 +1862,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opMOVrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpMOV);
this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpMOV);
},
/**
* op=0x8C (MOV word,sr)
@ -1893,7 +1897,7 @@ var X86OpXX = {
* Like other MOV operations, the destination does not need to be read, just written.
*/
this.opFlags |= X86.OPFLAG.NOREAD;
this.opMod.aOpModMemWord[bModRM].call(this, X86Help.opHelpMOVSegSrc);
this.aOpModMemWord[bModRM].call(this, X86Help.opHelpMOVSegSrc);
},
/**
* op=0x8D (LEA reg,word)
@ -1903,7 +1907,7 @@ var X86OpXX = {
opLEA: function() {
this.opFlags |= X86.OPFLAG.NOREAD;
this.segData = this.segStack = this.segNULL; // we can't have the EA calculation, if any, "polluted" by segment arithmetic
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLEA);
this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLEA);
},
/**
* op=0x8E (MOV sr,word)
@ -1954,7 +1958,7 @@ var X86OpXX = {
}
break;
}
this.opMod.aOpModRegWord[bModRM].call(this, X86Help.opHelpMOV);
this.aOpModRegWord[bModRM].call(this, X86Help.opHelpMOV);
switch (reg) {
case 0x0:
this.setES(this.regEAX);
@ -2002,7 +2006,7 @@ var X86OpXX = {
* Like other MOV operations, the destination does not need to be read, just written.
*/
this.opFlags |= X86.OPFLAG.NOREAD;
this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrpPOPw, this.popWord);
this.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrpPOPw, this.popWord);
},
/**
* op=0x90 (NOP, aka XCHG AX,AX)
@ -2892,7 +2896,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp2bi: function() {
this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2CountImm);
this.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2CountImm);
},
/**
* op=0xC1 (GRP2 word,imm16) (80186/80188 and up)
@ -2900,7 +2904,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp2wi: function() {
this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountImm);
this.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountImm);
},
/**
* op=0xC2 (RET n)
@ -2931,7 +2935,7 @@ var X86OpXX = {
/*
* This is like a "MOV reg,rm" operation, but it also loads ES from the next word.
*/
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLES);
this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLES);
},
/**
* op=0xC5 (LDS reg,word)
@ -2942,7 +2946,7 @@ var X86OpXX = {
/*
* This is like a "MOV reg,rm" operation, but it also loads DS from the next word.
*/
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLDS);
this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLDS);
},
/**
* op=0xC6 (MOV byte,imm8)
@ -2954,7 +2958,7 @@ var X86OpXX = {
* Like other MOV operations, the destination does not need to be read, just written.
*/
this.opFlags |= X86.OPFLAG.NOREAD;
this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrpMOVImm, this.getIPByte);
this.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrpMOVImm, this.getIPByte);
},
/**
* op=0xC7 (MOV word,imm16)
@ -2966,7 +2970,7 @@ var X86OpXX = {
* Like other MOV operations, the destination does not need to be read, just written.
*/
this.opFlags |= X86.OPFLAG.NOREAD;
this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrpMOVImm, this.getIPWord);
this.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrpMOVImm, this.getIPWord);
},
/**
* op=0xC8 (ENTER imm16,imm8) (80186/80188 and up)
@ -3093,7 +3097,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp2b1: function() {
this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2Count1);
this.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2Count1);
},
/**
* op=0xD1 (GRP2 word,1)
@ -3101,7 +3105,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp2w1: function() {
this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2Count1);
this.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2Count1);
},
/**
* op=0xD2 (GRP2 byte,CL)
@ -3109,7 +3113,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp2bCL: function() {
this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2CountCL);
this.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2CountCL);
},
/**
* op=0xD3 (GRP2 word,CL)
@ -3117,7 +3121,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp2wCL: function() {
this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountCL);
this.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountCL);
},
/**
* op=0xD4 0x0A (AAM)
@ -3196,7 +3200,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opESC: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpESC);
this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpESC);
this.nStepCycles -= 8; // TODO: Fix
},
/**
@ -3497,7 +3501,7 @@ var X86OpXX = {
*/
opGrp3b: function() {
this.regMD16 = -1;
this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp3b, X86Grps.opGrpNoSrc);
this.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp3b, X86Grps.opGrpNoSrc);
if (this.regMD16 >= 0) this.regEAX = this.regMD16;
},
/**
@ -3520,7 +3524,7 @@ var X86OpXX = {
*/
opGrp3w: function() {
this.regMD16 = -1;
this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp3w, X86Grps.opGrpNoSrc);
this.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp3w, X86Grps.opGrpNoSrc);
if (this.regMD16 >= 0) {
this.regEAX = this.regMD16;
this.regEDX = this.regMD32;
@ -3587,7 +3591,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp4b: function() {
this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp4b, X86Grps.opGrpNoSrc);
this.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp4b, X86Grps.opGrpNoSrc);
},
/**
* op=0xFF (GRP4 word)
@ -3595,7 +3599,7 @@ var X86OpXX = {
* @this {X86CPU}
*/
opGrp4w: function() {
this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp4w, X86Grps.opGrpNoSrc);
this.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp4w, X86Grps.opGrpNoSrc);
}
};