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

View file

@ -4746,7 +4746,7 @@ if (DEBUGGER) {
if (this.cmp) this.cmp.reset(); if (this.cmp) this.cmp.reset();
return true; return true;
case "ver": 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; return true;
default: default:
ch0 = sCmd.charAt(0); ch0 = sCmd.charAt(0);

View file

@ -53,6 +53,7 @@ if (typeof module !== 'undefined') {
var Component = require("../../shared/lib/component"); var Component = require("../../shared/lib/component");
var Messages = require("./messages"); var Messages = require("./messages");
} }
/** /**
* @class DataView * @class DataView
* @property {function(number,boolean):number} getUint8 * @property {function(number,boolean):number} getUint8
@ -63,6 +64,12 @@ if (typeof module !== 'undefined') {
* @property {function(number,number,boolean)} setInt32 * @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) * Memory(addr, size, type, controller)
* *
@ -163,11 +170,14 @@ function Memory(addr, size, type, controller)
this.buffer = new ArrayBuffer(size); this.buffer = new ArrayBuffer(size);
this.dv = new DataView(this.buffer, 0, 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 * If littleEndian is true, we can use ab[], aw[] and adw[] directly; well, we can use them
* in this.buffer is more convenient and presents no "endianness" issues. * 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.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 { } else {
if (FATARRAYS) { if (FATARRAYS) {
this.ab = new Array(size); this.ab = new Array(size);
@ -473,86 +483,199 @@ Memory.writeLongChecked = function writeLongChecked(off, l)
}; };
/** /**
* readByteTypedArray(off) * readByteBigEndian(off)
* *
* @this {Memory} * @this {Memory}
* @param {number} off * @param {number} off
* @return {number} * @return {number}
*/ */
Memory.readByteTypedArray = function readByteTypedArray(off) Memory.readByteBigEndian = function readByteBigEndian(off)
{ {
Component.assert(off >= 0 && off < this.size); Component.assert(off >= 0 && off < this.size);
return this.ab[off]; return this.ab[off];
}; };
/** /**
* readShortTypedArray(off) * readByteLittleEndian(off)
* *
* @this {Memory} * @this {Memory}
* @param {number} off * @param {number} off
* @return {number} * @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); Component.assert(off >= 0 && off < this.size - 1);
return this.dv.getUint16(off, true); return this.dv.getUint16(off, true);
}; };
/** /**
* readLongTypedArray(off) * readShortLittleEndian(off)
* *
* @this {Memory} * @this {Memory}
* @param {number} off * @param {number} off
* @return {number} * @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); Component.assert(off >= 0 && off < this.size - 3);
return this.dv.getInt32(off, true); 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} * @this {Memory}
* @param {number} off * @param {number} off
* @param {number} b * @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.ab[off] = b;
this.fDirty = true; 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} * @this {Memory}
* @param {number} off * @param {number} off
* @param {number} w * @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.dv.setUint16(off, w, true);
this.fDirty = 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} * @this {Memory}
* @param {number} off * @param {number} off
* @param {number} l * @param {number} l
*/ */
Memory.writeLongTypedArray = function writeLongTypedArray(off, l) Memory.writeLongBigEndian = function writeLongBigEndian(off, l)
{ {
Component.assert(off >= 0 && off < this.size - 3); Component.assert(off >= 0 && off < this.size - 3);
this.dv.setInt32(off, l, true); this.dv.setInt32(off, l, true);
this.fDirty = 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) * 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]; Memory.afnChecked = [Memory.readByteChecked, Memory.readShortChecked, Memory.readLongChecked, Memory.writeByteChecked, Memory.writeShortChecked, Memory.writeLongChecked];
if (TYPEDARRAYS) { 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 = { Memory.prototype = {

View file

@ -52,6 +52,8 @@ if (typeof module !== 'undefined') {
if (I386) { if (I386) {
if (typeof module !== 'undefined') { if (typeof module !== 'undefined') {
var X86ModB16 = require("./x86modb16");
var X86ModW16 = require("./x86modw16");
var X86ModB32 = require("./x86modb32"); var X86ModB32 = require("./x86modb32");
var X86ModW32 = require("./x86modw32"); var X86ModW32 = require("./x86modw32");
var X86ModSIB = require("./x86modsib"); var X86ModSIB = require("./x86modsib");
@ -970,7 +972,6 @@ X86CPU.prototype.resetRegs = function()
*/ */
this.addrSize = this.segCS.addrSize; this.addrSize = this.segCS.addrSize;
this.addrMask = this.segCS.addrMask; this.addrMask = this.segCS.addrMask;
/* /*
* It's also worth noting that instructions that implicitly use the stack also rely on something called STACK size, * 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: * 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), * 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. * 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] = { this.aaOpMem[2] = {
getWord: this.getShort.bind(this), getWord: this.getShort.bind(this),
setWord: this.setShort.bind(this) setWord: this.setShort.bind(this)
@ -998,31 +999,43 @@ X86CPU.prototype.resetRegs = function()
}; };
} }
this.opMem = this.aaOpMem[this.segCS.dataSize]; 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), * setOpMod()
* which is based foremost on segCS.addrSize, but can also be overridden by an ADDRESS size instruction prefix. *
*/ * Select the appropriate ModRM dispatch tables, based on the current ADDRESS size (addrSize), which
this.aaOpMod = new Array(5); * is based foremost on segCS.addrSize, but can also be overridden by an ADDRESS size instruction prefix.
this.aaOpMod[2] = { *
aOpModRegByte: X86ModB.aOpModReg, * @this {X86CPU}
aOpModMemByte: X86ModB.aOpModMem, */
aOpModGrpByte: X86ModB.aOpModGrp, X86CPU.prototype.setOpMod = function()
aOpModRegWord: X86ModW.aOpModReg, {
aOpModMemWord: X86ModW.aOpModMem, if (!I386) {
aOpModGrpWord: X86ModW.aOpModGrp this.aOpModRegByte = X86ModB.aOpModReg;
}; this.aOpModMemByte = X86ModB.aOpModMem;
if (I386) { this.aOpModGrpByte = X86ModB.aOpModGrp;
this.aaOpMod[4] = { this.aOpModRegWord = X86ModW.aOpModReg;
aOpModRegByte: X86ModB32.aOpModReg, this.aOpModMemWord = X86ModW.aOpModMem;
aOpModMemByte: X86ModB32.aOpModMem, this.aOpModGrpWord = X86ModW.aOpModGrp;
aOpModGrpByte: X86ModB32.aOpModGrp, } else {
aOpModRegWord: X86ModW32.aOpModReg, if (this.addrSize == 2) {
aOpModMemWord: X86ModW32.aOpModMem, this.aOpModRegByte = X86ModB16.aOpModReg;
aOpModGrpWord: X86ModW32.aOpModGrp 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) 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); if (PREFETCH) this.flushPrefetch(this.regLIP);
}; };
@ -1429,7 +1442,7 @@ X86CPU.prototype.setCSIP = function(off, sel, fCall)
*/ */
X86CPU.prototype.advanceIP = function(inc) 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); if (PREFETCH) this.advancePrefetch(inc);
}; };
@ -2026,9 +2039,9 @@ X86CPU.prototype.getEAByte = function(seg, off)
X86CPU.prototype.getEAWord = function(seg, off) X86CPU.prototype.getEAWord = function(seg, off)
{ {
this.segEA = seg; 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; 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) { if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo; this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi; this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2065,9 +2078,9 @@ X86CPU.prototype.modEAByte = function(seg, off)
X86CPU.prototype.modEAWord = function(seg, off) X86CPU.prototype.modEAWord = function(seg, off)
{ {
this.segEA = seg; 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; 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) { if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo; this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi; this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2086,7 +2099,7 @@ X86CPU.prototype.getEAByteData = function(off)
{ {
// return this.getEAByte(this.segData, off & this.addrMask); // return this.getEAByte(this.segData, off & this.addrMask);
this.segEA = this.segData; 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; if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var b = this.getByte(this.regEA); var b = this.getByte(this.regEA);
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiMemLo; 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); // return this.getEAByte(this.segStack, off & this.addrMask);
this.segEA = this.segStack; 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; if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var b = this.getByte(this.regEA); var b = this.getByte(this.regEA);
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiMemLo; 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); // return this.getEAWord(this.segData, off & this.addrMask);
this.segEA = this.segData; 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; 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) { if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo; this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi; this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2143,9 +2156,9 @@ X86CPU.prototype.getEAWordStack = function(off)
{ {
// return this.getEAWord(this.segStack, off & this.addrMask); // return this.getEAWord(this.segStack, off & this.addrMask);
this.segEA = this.segStack; 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; 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) { if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo; this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi; this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2164,7 +2177,7 @@ X86CPU.prototype.modEAByteData = function(off)
{ {
// return this.modEAByte(this.segData, off & this.addrMask); // return this.modEAByte(this.segData, off & this.addrMask);
this.segEA = this.segData; 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; if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var b = this.getByte(this.regEA); var b = this.getByte(this.regEA);
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiMemLo; 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); // return this.modEAByte(this.segStack, off & this.addrMask);
this.segEA = this.segStack; 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; if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var b = this.getByte(this.regEA); var b = this.getByte(this.regEA);
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiMemLo; 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); // return this.modEAWord(this.segData, off & this.addrMask);
this.segEA = this.segData; 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; 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) { if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo; this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi; this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2221,9 +2234,9 @@ X86CPU.prototype.modEAWordStack = function(off)
{ {
// return this.modEAWord(this.segStack, off & this.addrMask); // return this.modEAWord(this.segStack, off & this.addrMask);
this.segEA = this.segStack; 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; 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) { if (BACKTRACK) {
this.backTrack.btiEALo = this.backTrack.btiMemLo; this.backTrack.btiEALo = this.backTrack.btiMemLo;
this.backTrack.btiEAHi = this.backTrack.btiMemHi; this.backTrack.btiEAHi = this.backTrack.btiMemHi;
@ -2257,7 +2270,11 @@ X86CPU.prototype.setEAWord = function(w)
this.backTrack.btiMemLo = this.backTrack.btiEALo; this.backTrack.btiMemLo = this.backTrack.btiEALo;
this.backTrack.btiMemHi = this.backTrack.btiEAHi; 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) 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) 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)); var b = (PREFETCH? this.getBytePrefetch(this.regLIP) : this.getByte(this.regLIP));
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo); 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; return b;
}; };
@ -2474,8 +2499,8 @@ X86CPU.prototype.getIPDisp = function()
{ {
var b = ((PREFETCH? this.getBytePrefetch(this.regLIP) : this.getByte(this.regLIP)) << 24) >> 24; var b = ((PREFETCH? this.getBytePrefetch(this.regLIP) : this.getByte(this.regLIP)) << 24) >> 24;
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo); 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 & this.addrMask; return b & (I386? this.addrMask : 0xffff);
}; };
/** /**
@ -2486,12 +2511,12 @@ X86CPU.prototype.getIPDisp = function()
*/ */
X86CPU.prototype.getIPWord = 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) { if (BACKTRACK) {
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo); this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMemHi); 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; return w;
}; };
@ -2518,7 +2543,7 @@ X86CPU.prototype.getSIBAddr = function(mod)
X86CPU.prototype.popWord = function() X86CPU.prototype.popWord = function()
{ {
var regESP = this.regESP; 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); return this.getSOWord(this.segSS, regESP);
}; };
@ -2531,7 +2556,7 @@ X86CPU.prototype.popWord = function()
X86CPU.prototype.pushWord = function(w) X86CPU.prototype.pushWord = function(w)
{ {
this.assert((w & this.dataMask) == 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.addrSize = this.segCS.addrSize;
this.addrMask = this.segCS.addrMask; this.addrMask = this.segCS.addrMask;
this.opMem = this.aaOpMem[this.dataSize]; this.opMem = this.aaOpMem[this.dataSize];
this.opMod = this.aaOpMod[this.addrSize];
} }
this.opPrefixes = this.opFlags & X86.OPFLAG.REPEAT; 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 if ((bModRM & 0x38) < 0x10) { // possible reg values: 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
this.opFlags |= X86.OPFLAG.NOREAD; 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} * @this {X86CPU}
@ -61,7 +61,7 @@ var X86Op0F = {
if (!(bModRM & 0x10)) { if (!(bModRM & 0x10)) {
this.opFlags |= X86.OPFLAG.NOREAD; 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} * @this {X86CPU}
@ -69,7 +69,7 @@ var X86Op0F = {
* op=0x0F,0x02 (lar reg,rm) * op=0x0F,0x02 (lar reg,rm)
*/ */
opLAR: function() { opLAR: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLAR); this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLAR);
}, },
/** /**
* @this {X86CPU} * @this {X86CPU}
@ -77,7 +77,7 @@ var X86Op0F = {
* op=0x0F,0x03 (lsl reg,rm) * op=0x0F,0x03 (lsl reg,rm)
*/ */
opLSL: function() { opLSL: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLSL); this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLSL);
}, },
/** /**
* opLOADALL() * 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 * 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. * in the weeds, so we'll stop the CPU if we're in DEBUG mode.
*/ */
if (DEBUG && !b) this.stopCPU(); if (DEBUG && DEBUGGER && !b) this.stopCPU();
this.opMod.aOpModMemByte[b].call(this, X86Grps.opGrpADDb); this.aOpModMemByte[b].call(this, X86Grps.opGrpADDb);
}, },
/** /**
* op=0x01 (ADD word,reg) * op=0x01 (ADD word,reg)
@ -62,7 +62,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opADDmw: function() { opADDmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpADDw); this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpADDw);
}, },
/** /**
* op=0x02 (ADD reg,byte) * op=0x02 (ADD reg,byte)
@ -70,7 +70,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opADDrb: function() { opADDrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpADDb); this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpADDb);
}, },
/** /**
* op=0x03 (ADD reg,word) * op=0x03 (ADD reg,word)
@ -78,7 +78,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opADDrw: function() { opADDrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpADDw); this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpADDw);
}, },
/** /**
* op=0x04 (ADD AL,imm8) * op=0x04 (ADD AL,imm8)
@ -139,7 +139,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opORmb: function() { opORmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpORb); this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpORb);
}, },
/** /**
* op=0x09 (OR word,reg) * op=0x09 (OR word,reg)
@ -147,7 +147,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opORmw: function() { opORmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpORw); this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpORw);
}, },
/** /**
* op=0x0A (OR reg,byte) * op=0x0A (OR reg,byte)
@ -155,7 +155,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opORrb: function() { opORrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpORb); this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpORb);
}, },
/** /**
* op=0x0B (OR reg,word) * op=0x0B (OR reg,word)
@ -163,7 +163,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opORrw: function() { opORrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpORw); this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpORw);
}, },
/** /**
* op=0x0C (OR AL,imm8) * op=0x0C (OR AL,imm8)
@ -227,7 +227,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opADCmb: function() { opADCmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpADCb); this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpADCb);
}, },
/** /**
* op=0x11 (ADC word,reg) * op=0x11 (ADC word,reg)
@ -235,7 +235,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opADCmw: function() { opADCmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpADCw); this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpADCw);
}, },
/** /**
* op=0x12 (ADC reg,byte) * op=0x12 (ADC reg,byte)
@ -243,7 +243,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opADCrb: function() { opADCrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpADCb); this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpADCb);
}, },
/** /**
* op=0x13 (ADC reg,word) * op=0x13 (ADC reg,word)
@ -251,7 +251,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opADCrw: function() { opADCrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpADCw); this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpADCw);
}, },
/** /**
* op=0x14 (ADC AL,imm8) * op=0x14 (ADC AL,imm8)
@ -307,7 +307,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opSBBmb: function() { opSBBmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpSBBb); this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpSBBb);
}, },
/** /**
* op=0x19 (SBB word,reg) * op=0x19 (SBB word,reg)
@ -315,7 +315,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opSBBmw: function() { opSBBmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpSBBw); this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpSBBw);
}, },
/** /**
* op=0x1A (SBB reg,byte) * op=0x1A (SBB reg,byte)
@ -323,7 +323,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opSBBrb: function() { opSBBrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpSBBb); this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpSBBb);
}, },
/** /**
* op=0x1B (SBB reg,word) * op=0x1B (SBB reg,word)
@ -331,7 +331,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opSBBrw: function() { opSBBrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpSBBw); this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpSBBw);
}, },
/** /**
* op=0x1C (SBB AL,imm8) * op=0x1C (SBB AL,imm8)
@ -387,7 +387,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opANDmb: function() { opANDmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpANDb); this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpANDb);
}, },
/** /**
* op=0x21 (AND word,reg) * op=0x21 (AND word,reg)
@ -395,7 +395,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opANDmw: function() { opANDmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpANDw); this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpANDw);
}, },
/** /**
* op=0x22 (AND reg,byte) * op=0x22 (AND reg,byte)
@ -403,7 +403,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opANDrb: function() { opANDrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpANDb); this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpANDb);
}, },
/** /**
* op=0x23 (AND reg,word) * op=0x23 (AND reg,word)
@ -411,7 +411,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opANDrw: function() { opANDrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpANDw); this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpANDw);
}, },
/** /**
* op=0x24 (AND AL,imm8) * op=0x24 (AND AL,imm8)
@ -486,7 +486,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opSUBmb: function() { opSUBmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpSUBb); this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpSUBb);
}, },
/** /**
* op=0x29 (SUB word,reg) * op=0x29 (SUB word,reg)
@ -494,7 +494,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opSUBmw: function() { opSUBmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpSUBw); this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpSUBw);
}, },
/** /**
* op=0x2A (SUB reg,byte) * op=0x2A (SUB reg,byte)
@ -502,7 +502,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opSUBrb: function() { opSUBrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpSUBb); this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpSUBb);
}, },
/** /**
* op=0x2B (SUB reg,word) * op=0x2B (SUB reg,word)
@ -510,7 +510,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opSUBrw: function() { opSUBrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpSUBw); this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpSUBw);
}, },
/** /**
* op=0x2C (SUB AL,imm8) * op=0x2C (SUB AL,imm8)
@ -585,7 +585,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opXORmb: function() { opXORmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpXORb); this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpXORb);
}, },
/** /**
* op=0x31 (XOR word,reg) * op=0x31 (XOR word,reg)
@ -593,7 +593,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opXORmw: function() { opXORmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpXORw); this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpXORw);
}, },
/** /**
* op=0x32 (XOR reg,byte) * op=0x32 (XOR reg,byte)
@ -601,7 +601,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opXORrb: function() { opXORrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpXORb); this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpXORb);
}, },
/** /**
* op=0x33 (XOR reg,word) * op=0x33 (XOR reg,word)
@ -609,7 +609,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opXORrw: function() { opXORrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpXORw); this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpXORw);
}, },
/** /**
* op=0x34 (XOR AL,imm8) * op=0x34 (XOR AL,imm8)
@ -684,7 +684,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opCMPmb: function() { opCMPmb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpCMPb); this.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpCMPb);
}, },
/** /**
* op=0x39 (CMP word,reg) * op=0x39 (CMP word,reg)
@ -692,7 +692,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opCMPmw: function() { opCMPmw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw); this.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw);
}, },
/** /**
* op=0x3A (CMP reg,byte) * op=0x3A (CMP reg,byte)
@ -700,7 +700,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opCMPrb: function() { opCMPrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpCMPb); this.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpCMPb);
}, },
/** /**
* op=0x3B (CMP reg,word) * op=0x3B (CMP reg,word)
@ -708,7 +708,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opCMPrw: function() { opCMPrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw); this.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw);
}, },
/** /**
* op=0x3C (CMP AL,imm8) * op=0x3C (CMP AL,imm8)
@ -1249,7 +1249,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opBOUND: function() { 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) * op=0x63 (ARPL word,reg) (80286 and up)
@ -1257,7 +1257,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opARPL: function() { 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) * op=0x66 (OS:) (80386 and up)
@ -1267,11 +1267,13 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opOS: function() { opOS: function() {
this.opFlags |= X86.OPFLAG.SEG; if (I386) {
this.dataSize ^= 0x6; // that which is 2 shall become 4, and vice versa this.opFlags |= X86.OPFLAG.SEG;
this.dataMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa this.dataSize ^= 0x6; // that which is 2 shall become 4, and vice versa
this.opMem = this.aaOpMem[this.dataSize]; this.dataMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa
this.nStepCycles -= this.CYCLES.nOpCyclesPrefix; this.opMem = this.aaOpMem[this.dataSize];
this.nStepCycles -= this.CYCLES.nOpCyclesPrefix;
}
}, },
/** /**
* op=0x67 (AS:) (80386 and up) * op=0x67 (AS:) (80386 and up)
@ -1281,11 +1283,13 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opAS: function() { opAS: function() {
this.opFlags |= X86.OPFLAG.SEG; if (I386) {
this.addrSize ^= 0x06; // that which is 2 shall become 4, and vice versa this.opFlags |= X86.OPFLAG.SEG;
this.addrMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa this.addrSize ^= 0x06; // that which is 2 shall become 4, and vice versa
this.opMod = this.aaOpMod[this.addrSize]; this.addrMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa
this.nStepCycles -= this.CYCLES.nOpCyclesPrefix; this.setOpMod();
this.nStepCycles -= this.CYCLES.nOpCyclesPrefix;
}
}, },
/** /**
* op=0x68 (PUSH imm16) (80186/80188 and up) * op=0x68 (PUSH imm16) (80186/80188 and up)
@ -1302,7 +1306,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opIMUL16: function() { 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) * op=0x6A (PUSH imm8) (80186/80188 and up)
@ -1320,7 +1324,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opIMUL8: function() { 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) * op=0x6C (INSB) (80186/80188 and up)
@ -1743,7 +1747,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp1b: function() { 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); this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
}, },
/** /**
@ -1752,7 +1756,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp1w: function() { 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); this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
}, },
/** /**
@ -1761,7 +1765,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp1sw: function() { 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); this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
}, },
/** /**
@ -1770,7 +1774,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opTESTrb: function() { opTESTrb: function() {
this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Help.opHelpTESTb); this.aOpModMemByte[this.getIPByte()].call(this, X86Help.opHelpTESTb);
}, },
/** /**
* op=0x85 (TEST reg,word) * op=0x85 (TEST reg,word)
@ -1778,7 +1782,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opTESTrw: function() { opTESTrw: function() {
this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpTESTw); this.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpTESTw);
}, },
/** /**
* op=0x86 (XCHG reg,byte) * op=0x86 (XCHG reg,byte)
@ -1807,7 +1811,7 @@ var X86OpXX = {
* this.regEDX = (this.regEDX & 0xff) | (b << 8); * 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) * op=0x87 (XCHG reg,word)
@ -1818,7 +1822,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opXCHGrw: function() { 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) * 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. * Like other MOV operations, the destination does not need to be read, just written.
*/ */
this.opFlags |= X86.OPFLAG.NOREAD; 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) * 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. * Like other MOV operations, the destination does not need to be read, just written.
*/ */
this.opFlags |= X86.OPFLAG.NOREAD; 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) * op=0x8A (MOV reg,byte)
@ -1850,7 +1854,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opMOVrb: function() { opMOVrb: function() {
this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Help.opHelpMOV); this.aOpModRegByte[this.getIPByte()].call(this, X86Help.opHelpMOV);
}, },
/** /**
* op=0x8B (MOV reg,word) * op=0x8B (MOV reg,word)
@ -1858,7 +1862,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opMOVrw: function() { opMOVrw: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpMOV); this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpMOV);
}, },
/** /**
* op=0x8C (MOV word,sr) * 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. * Like other MOV operations, the destination does not need to be read, just written.
*/ */
this.opFlags |= X86.OPFLAG.NOREAD; 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) * op=0x8D (LEA reg,word)
@ -1903,7 +1907,7 @@ var X86OpXX = {
opLEA: function() { opLEA: function() {
this.opFlags |= X86.OPFLAG.NOREAD; 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.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) * op=0x8E (MOV sr,word)
@ -1954,7 +1958,7 @@ var X86OpXX = {
} }
break; break;
} }
this.opMod.aOpModRegWord[bModRM].call(this, X86Help.opHelpMOV); this.aOpModRegWord[bModRM].call(this, X86Help.opHelpMOV);
switch (reg) { switch (reg) {
case 0x0: case 0x0:
this.setES(this.regEAX); this.setES(this.regEAX);
@ -2002,7 +2006,7 @@ var X86OpXX = {
* Like other MOV operations, the destination does not need to be read, just written. * Like other MOV operations, the destination does not need to be read, just written.
*/ */
this.opFlags |= X86.OPFLAG.NOREAD; 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) * op=0x90 (NOP, aka XCHG AX,AX)
@ -2892,7 +2896,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2bi: function() { 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) * op=0xC1 (GRP2 word,imm16) (80186/80188 and up)
@ -2900,7 +2904,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2wi: function() { 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) * 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 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) * 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 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) * 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. * Like other MOV operations, the destination does not need to be read, just written.
*/ */
this.opFlags |= X86.OPFLAG.NOREAD; 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) * 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. * Like other MOV operations, the destination does not need to be read, just written.
*/ */
this.opFlags |= X86.OPFLAG.NOREAD; 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) * op=0xC8 (ENTER imm16,imm8) (80186/80188 and up)
@ -3093,7 +3097,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2b1: function() { 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) * op=0xD1 (GRP2 word,1)
@ -3101,7 +3105,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2w1: function() { 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) * op=0xD2 (GRP2 byte,CL)
@ -3109,7 +3113,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2bCL: function() { 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) * op=0xD3 (GRP2 word,CL)
@ -3117,7 +3121,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2wCL: function() { 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) * op=0xD4 0x0A (AAM)
@ -3196,7 +3200,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opESC: function() { opESC: function() {
this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpESC); this.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpESC);
this.nStepCycles -= 8; // TODO: Fix this.nStepCycles -= 8; // TODO: Fix
}, },
/** /**
@ -3497,7 +3501,7 @@ var X86OpXX = {
*/ */
opGrp3b: function() { opGrp3b: function() {
this.regMD16 = -1; 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; if (this.regMD16 >= 0) this.regEAX = this.regMD16;
}, },
/** /**
@ -3520,7 +3524,7 @@ var X86OpXX = {
*/ */
opGrp3w: function() { opGrp3w: function() {
this.regMD16 = -1; 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) { if (this.regMD16 >= 0) {
this.regEAX = this.regMD16; this.regEAX = this.regMD16;
this.regEDX = this.regMD32; this.regEDX = this.regMD32;
@ -3587,7 +3591,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp4b: function() { 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) * op=0xFF (GRP4 word)
@ -3595,7 +3599,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp4w: function() { opGrp4w: function() {
this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp4w, X86Grps.opGrpNoSrc); this.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp4w, X86Grps.opGrpNoSrc);
} }
}; };

View file

@ -110,6 +110,8 @@
"./modules/pcjs/lib/x86help.js", "./modules/pcjs/lib/x86help.js",
"./modules/pcjs/lib/x86modb.js", "./modules/pcjs/lib/x86modb.js",
"./modules/pcjs/lib/x86modw.js", "./modules/pcjs/lib/x86modw.js",
"./modules/pcjs/lib/x86modb16.js",
"./modules/pcjs/lib/x86modw16.js",
"./modules/pcjs/lib/x86modb32.js", "./modules/pcjs/lib/x86modb32.js",
"./modules/pcjs/lib/x86modw32.js", "./modules/pcjs/lib/x86modw32.js",
"./modules/pcjs/lib/x86modsib.js", "./modules/pcjs/lib/x86modsib.js",