Added 32-bit interfaces to the Memory component

This commit is contained in:
Jeff Parsons 2015-01-25 14:09:24 -08:00 • committed by jeffpar
commit e0959dc00c
7 changed files with 319 additions and 119 deletions

View file

@ -191,7 +191,7 @@ function Memory(addr, size, type, controller)
* are designed to ignore writes to ROM. * are designed to ignore writes to ROM.
* *
* The other purpose these types serve is to provide the Control Panel with the ability to highlight * The other purpose these types serve is to provide the Control Panel with the ability to highlight
* memory regions according to their primary purpose. * memory regions according to one of the following types.
* *
* Unallocated regions of the address space also contain memory blocks, but the blocks themselves are * Unallocated regions of the address space also contain memory blocks, but the blocks themselves are
* empty (that is, their data arrays are uninitialized) and the memory type is NONE. * empty (that is, their data arrays are uninitialized) and the memory type is NONE.
@ -264,7 +264,7 @@ Memory.readWordMemory = function readWordMemory(off)
var w; var w;
var idw = off >> 2; var idw = off >> 2;
var nShift = (off & 0x3) << 3; var nShift = (off & 0x3) << 3;
var dw = (this.adw[idw] >>> nShift); var dw = (this.adw[idw] >> nShift);
if (nShift < 24) { if (nShift < 24) {
w = dw & 0xffff; w = dw & 0xffff;
} else { } else {
@ -273,6 +273,29 @@ Memory.readWordMemory = function readWordMemory(off)
return w; return w;
}; };
/**
* readLongMemory(off)
*
* @this {Memory}
* @param {number} off
* @return {number}
*/
Memory.readLongMemory = function readLongMemory(off)
{
Component.assert(off >= 0 && off < this.cb - 3);
if (FATARRAYS) {
return this.ab[off] | (this.ab[off + 1] << 8) | (this.ab[off + 2] << 16) | (this.ab[off + 3] << 24);
}
var idw = off >> 2;
var nShift = (off & 0x3) << 3;
var dw = this.adw[idw];
if (nShift) {
dw >>>= nShift;
dw |= this.adw[idw + 1] << (32 - nShift);
}
return dw;
};
/** /**
* writeByteMemory(off, b) * writeByteMemory(off, b)
* *
@ -320,6 +343,35 @@ Memory.writeWordMemory = function writeWordMemory(off, w)
this.fDirty = true; this.fDirty = true;
}; };
/**
* writeLongMemory(off, dw)
*
* @this {Memory}
* @param {number} off
* @param {number} dw
*/
Memory.writeLongMemory = function writeLongMemory(off, dw)
{
Component.assert(off >= 0 && off < this.cb - 3);
if (FATARRAYS) {
this.ab[off] = (dw & 0xff);
this.ab[off + 1] = (dw >> 8) & 0xff;
this.ab[off + 2] = (dw >> 16) & 0xff;
this.ab[off + 3] = (dw >> 24) & 0xff;
} else {
var idw = off >> 2;
var nShift = (off & 0x3) << 3;
if (!nShift) {
this.adw[idw] = dw;
} else {
this.adw[idw] = (this.adw[idw] & ~(0xffffffff << nShift)) | (dw << nShift);
idw++;
this.adw[idw] = (this.adw[idw] & (0xffffffff << nShift)) | (dw >>> (32 - nShift));
}
}
this.fDirty = true;
};
/** /**
* readByteChecked(off) * readByteChecked(off)
* *
@ -343,11 +395,30 @@ Memory.readByteChecked = function readByteChecked(off)
Memory.readWordChecked = function readWordChecked(off) Memory.readWordChecked = function readWordChecked(off)
{ {
if (DEBUGGER) { if (DEBUGGER) {
this.dbg.checkMemoryRead(this.addr + off) || this.dbg.checkMemoryRead(this.addr + off + 1); // jshint ignore:line this.dbg.checkMemoryRead(this.addr + off) ||
this.dbg.checkMemoryRead(this.addr + off + 1);
} }
return this.readWordDirect(off); return this.readWordDirect(off);
}; };
/**
* readLongChecked(off)
*
* @this {Memory}
* @param {number} off
* @return {number}
*/
Memory.readLongChecked = function readLongChecked(off)
{
if (DEBUGGER) {
this.dbg.checkMemoryRead(this.addr + off) ||
this.dbg.checkMemoryRead(this.addr + off + 1) ||
this.dbg.checkMemoryRead(this.addr + off + 2) ||
this.dbg.checkMemoryRead(this.addr + off + 3);
}
return this.readLongDirect(off);
};
/** /**
* writeByteChecked(off, b) * writeByteChecked(off, b)
* *
@ -371,11 +442,30 @@ Memory.writeByteChecked = function writeByteChecked(off, b)
Memory.writeWordChecked = function writeWordChecked(off, w) Memory.writeWordChecked = function writeWordChecked(off, w)
{ {
if (DEBUGGER) { if (DEBUGGER) {
this.dbg.checkMemoryWrite(this.addr + off) || this.dbg.checkMemoryWrite(this.addr + off + 1); // jshint ignore:line this.dbg.checkMemoryWrite(this.addr + off) ||
this.dbg.checkMemoryWrite(this.addr + off + 1);
} }
this.writeWordDirect(off, w); this.writeWordDirect(off, w);
}; };
/**
* writeLongChecked(off, dw)
*
* @this {Memory}
* @param {number} off
* @param {number} dw
*/
Memory.writeLongChecked = function writeLongChecked(off, dw)
{
if (DEBUGGER) {
this.dbg.checkMemoryWrite(this.addr + off) ||
this.dbg.checkMemoryWrite(this.addr + off + 1) ||
this.dbg.checkMemoryWrite(this.addr + off + 2) ||
this.dbg.checkMemoryWrite(this.addr + off + 3)
}
this.writeLongDirect(off, dw);
};
/** /**
* readByteTypedArray(off) * readByteTypedArray(off)
* *
@ -402,6 +492,19 @@ Memory.readWordTypedArray = function readWordTypedArray(off)
return this.dv.getUint16(off, true); return this.dv.getUint16(off, true);
}; };
/**
* readLongTypedArray(off)
*
* @this {Memory}
* @param {number} off
* @return {number}
*/
Memory.readLongTypedArray = function readLongTypedArray(off)
{
Component.assert(off >= 0 && off < this.cb - 3);
return this.dv.getInt32(off, true);
};
/** /**
* writeByteTypedArray(off, b) * writeByteTypedArray(off, b)
* *
@ -430,6 +533,20 @@ Memory.writeWordTypedArray = function writeWordTypedArray(off, w)
this.fDirty = true; this.fDirty = true;
}; };
/**
* writeLongTypedArray(off, dw)
*
* @this {Memory}
* @param {number} off
* @param {number} dw
*/
Memory.writeLongTypedArray = function writeLongTypedArray(off, dw)
{
Component.assert(off >= 0 && off < this.cb - 3);
this.dv.setInt32(off, dw, true);
this.fDirty = true;
};
/** /**
* readBackTrackNone(off) * readBackTrackNone(off)
* *
@ -483,11 +600,11 @@ Memory.writeBackTrackIndex = function writeBackTrackIndex(off, bti)
return btiPrev; return btiPrev;
}; };
Memory.afnMemory = [Memory.readByteMemory, Memory.readWordMemory, Memory.writeByteMemory, Memory.writeWordMemory]; Memory.afnMemory = [Memory.readByteMemory, Memory.readWordMemory, Memory.readLongMemory, Memory.writeByteMemory, Memory.writeWordMemory, Memory.writeLongMemory];
Memory.afnChecked = [Memory.readByteChecked, Memory.readWordChecked, Memory.writeByteChecked, Memory.writeWordChecked]; Memory.afnChecked = [Memory.readByteChecked, Memory.readWordChecked, Memory.readLongChecked, Memory.writeByteChecked, Memory.writeWordChecked, Memory.writeLongChecked];
if (TYPEDARRAYS) { if (TYPEDARRAYS) {
Memory.afnTypedArray = [Memory.readByteTypedArray, Memory.readWordTypedArray, Memory.writeByteTypedArray, Memory.writeWordTypedArray]; Memory.afnTypedArray = [Memory.readByteTypedArray, Memory.readWordTypedArray, Memory.readLongTypedArray, Memory.writeByteTypedArray, Memory.writeWordTypedArray, Memory.writeLongTypedArray];
} }
Memory.prototype = { Memory.prototype = {
@ -608,9 +725,11 @@ Memory.prototype = {
setReadAccess: function(afn, fDirect) { setReadAccess: function(afn, fDirect) {
this.readByte = afn[0] || Memory.readNone; this.readByte = afn[0] || Memory.readNone;
this.readWord = afn[1] || Memory.readNone; this.readWord = afn[1] || Memory.readNone;
this.readLong = afn[2] || Memory.readNone;
if (fDirect) { if (fDirect) {
this.readByteDirect = afn[0] || Memory.readNone; this.readByteDirect = afn[0] || Memory.readNone;
this.readWordDirect = afn[1] || Memory.readNone; this.readWordDirect = afn[1] || Memory.readNone;
this.readLongDirect = afn[2] || Memory.readNone;
} }
}, },
/** /**
@ -621,11 +740,13 @@ Memory.prototype = {
* @param {boolean} [fDirect] * @param {boolean} [fDirect]
*/ */
setWriteAccess: function(afn, fDirect) { setWriteAccess: function(afn, fDirect) {
this.writeByte = !this.fReadOnly && afn[2] || Memory.writeNone; this.writeByte = !this.fReadOnly && afn[3] || Memory.writeNone;
this.writeWord = !this.fReadOnly && afn[3] || Memory.writeNone; this.writeWord = !this.fReadOnly && afn[4] || Memory.writeNone;
this.writeLong = !this.fReadOnly && afn[5] || Memory.writeNone;
if (fDirect) { if (fDirect) {
this.writeByteDirect = afn[2] || Memory.writeNone; this.writeByteDirect = afn[3] || Memory.writeNone;
this.writeWordDirect = afn[3] || Memory.writeNone; this.writeWordDirect = afn[4] || Memory.writeNone;
this.writeLongDirect = afn[5] || Memory.writeNone;
} }
}, },
/** /**
@ -636,6 +757,7 @@ Memory.prototype = {
resetReadAccess: function() { resetReadAccess: function() {
this.readByte = this.readByteDirect; this.readByte = this.readByteDirect;
this.readWord = this.readWordDirect; this.readWord = this.readWordDirect;
this.readLong = this.readLongDirect;
}, },
/** /**
* resetWriteAccess() * resetWriteAccess()
@ -645,6 +767,7 @@ Memory.prototype = {
resetWriteAccess: function() { resetWriteAccess: function() {
this.writeByte = this.fReadOnly? Memory.writeNone : this.writeByteDirect; this.writeByte = this.fReadOnly? Memory.writeNone : this.writeByteDirect;
this.writeWord = this.fReadOnly? Memory.writeNone : this.writeWordDirect; this.writeWord = this.fReadOnly? Memory.writeNone : this.writeWordDirect;
this.writeLong = this.fReadOnly? Memory.writeNone : this.writeLongDirect;
}, },
/** /**
* setDebugInfo(cpu, dbg, addr, size) * setDebugInfo(cpu, dbg, addr, size)

View file

@ -1247,9 +1247,21 @@ Card.ACCESS.WRITE.MASK = 0xff00;
* @param {number} off * @param {number} off
* @return {number} * @return {number}
*/ */
Card.ACCESS.readWord = function writeWord(off) Card.ACCESS.readWord = function readWord(off)
{ {
return this.readByte(off) | (this.readByte(off+1) << 8); return this.readByte(off) | (this.readByte(off + 1) << 8);
};
/**
* readLong(off)
*
* @this {Memory}
* @param {number} off
* @return {number}
*/
Card.ACCESS.readLong = function readLong(off)
{
return this.readByte(off) | (this.readByte(off + 1) << 8) | (this.readByte(off + 2) << 16) | (this.readByte(off + 3) << 24);
}; };
/** /**
@ -1260,9 +1272,25 @@ Card.ACCESS.readWord = function writeWord(off)
* @param {number} w * @param {number} w
*/ */
Card.ACCESS.writeWord = function writeWord(off, w) Card.ACCESS.writeWord = function writeWord(off, w)
{
Component.assert(!(w & ~0xffff));
this.writeByte(off, w & 0xff);
this.writeByte(off + 1, w >> 8);
};
/**
* writeLong(off, w)
*
* @this {Memory}
* @param {number} off
* @param {number} w
*/
Card.ACCESS.writeLong = function writeLong(off, w)
{ {
this.writeByte(off, w & 0xff); this.writeByte(off, w & 0xff);
this.writeByte(off + 1, (w >> 8) & 0xff); this.writeByte(off + 1, (w >> 8) & 0xff);
this.writeByte(off + 2, (w >> 16) & 0xff);
this.writeByte(off + 3, (w >>> 24));
}; };
/** /**
@ -1925,10 +1953,10 @@ Card.prototype.setMemoryAccess = function(nAccess)
} }
} }
if (!this.afnAccess) { if (!this.afnAccess) {
this.afnAccess = [null, Card.ACCESS.readWord, null, Card.ACCESS.writeWord]; this.afnAccess = [null, Card.ACCESS.readWord, Card.ACCESS.readLong, null, Card.ACCESS.writeWord, Card.ACCESS.writeLong];
} }
this.afnAccess[0] = fnReadByte; this.afnAccess[0] = fnReadByte;
this.afnAccess[2] = fnWriteByte; this.afnAccess[3] = fnWriteByte;
this.nAccess = nAccess; this.nAccess = nAccess;
} }
}; };

View file

@ -958,7 +958,7 @@ X86CPU.prototype.resetRegs = function()
this.opFlags = this.opPrefixes = 0; this.opFlags = this.opPrefixes = 0;
/* /*
* The following contain the (default) OPERAND size (2 for 16 bits, 4 for 32 bits), and the corresponding masks * The following contain the (default) OPERAND size (0 for 16 bits, 1 for 32 bits), and the corresponding masks
* for isolating the (src) bits of an OPERAND and clearing the (dst) bits of an OPERAND. These are reset to * for isolating the (src) bits of an OPERAND and clearing the (dst) bits of an OPERAND. These are reset to
* their segCS counterparts at the start of every new instruction, but are also set here for documentation purposes. * their segCS counterparts at the start of every new instruction, but are also set here for documentation purposes.
*/ */
@ -985,7 +985,20 @@ X86CPU.prototype.resetRegs = function()
*/ */
/* /*
* The ModRM dispatch tables; opMods refers to the active set, based on the current ADDRESS size (addrSize), * The memory dispatch tables; opMem refers to the active set, based on the current OPERAND size (opSize),
* which is based foremost on segCS.opSize, but can also be overridden by an OPERAND size instruction prefix.
*/
this.aaOpMem = new Array(2);
this.aaOpMem[0] = {
getByte: this.getByte,
getWord: this.getWord,
setByte: this.setByte,
setWord: this.setWord
};
this.opMem = this.aaOpMem[this.segCS.opSize];
/*
* 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. * which is based foremost on segCS.addrSize, but can also be overridden by an ADDRESS size instruction prefix.
*/ */
this.aaOpMod = new Array(2); this.aaOpMod = new Array(2);
@ -1007,7 +1020,7 @@ X86CPU.prototype.resetRegs = function()
aOpModGrpWord: X86ModW32.aOpModGrp aOpModGrpWord: X86ModW32.aOpModGrp
}; };
} }
this.opMods = this.aaOpMod[this.segCS.addrSize]; this.opMod = this.aaOpMod[this.segCS.addrSize];
}; };
/** /**
@ -1363,7 +1376,7 @@ X86CPU.prototype.setES = function(sel)
*/ */
X86CPU.prototype.setIP = function(off) X86CPU.prototype.setIP = function(off)
{ {
this.regLIP = this.segCS.base + (this.regEIP = off & 0xffff); this.regLIP = this.segCS.base + (this.regEIP = off & this.addrMask);
if (PREFETCH) this.flushPrefetch(this.regLIP); if (PREFETCH) this.flushPrefetch(this.regLIP);
}; };
@ -1390,7 +1403,7 @@ X86CPU.prototype.setIP = function(off)
*/ */
X86CPU.prototype.setCSIP = function(off, sel, fCall) X86CPU.prototype.setCSIP = function(off, sel, fCall)
{ {
this.assert((off & 0xffff) == off); this.assert(!this.addrMask || (off & this.addrMask) == off);
this.segCS.fCall = fCall; this.segCS.fCall = fCall;
/* /*
* We break this operation into the following discrete steps (eg, set IP, load CS, and then update LIP) * We break this operation into the following discrete steps (eg, set IP, load CS, and then update LIP)
@ -1414,7 +1427,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) & 0xffff); this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + inc) & this.addrMask);
if (PREFETCH) this.advancePrefetch(inc); if (PREFETCH) this.advancePrefetch(inc);
}; };
@ -1872,10 +1885,8 @@ X86CPU.prototype.getWord = function(addr)
{ {
var off = addr & this.blockLimit; var off = addr & this.blockLimit;
var iBlock = (addr & this.addrMemMask) >> this.blockShift; var iBlock = (addr & this.addrMemMask) >> this.blockShift;
/* /*
* On the 8088, it takes 4 cycles to read the additional byte REGARDLESS whether the address is odd or even. * On the 8088, it takes 4 cycles to read the additional byte REGARDLESS whether the address is odd or even.
*
* TODO: For the 8086, the penalty is actually "(addr & 0x1) << 2" (4 additional cycles only when the address is odd). * TODO: For the 8086, the penalty is actually "(addr & 0x1) << 2" (4 additional cycles only when the address is odd).
*/ */
this.nStepCycles -= this.CYCLES.nWordCyclePenalty; this.nStepCycles -= this.CYCLES.nWordCyclePenalty;
@ -1884,10 +1895,34 @@ X86CPU.prototype.getWord = function(addr)
this.backTrack.btiMemLo = this.bus.readBackTrack(addr); this.backTrack.btiMemLo = this.bus.readBackTrack(addr);
this.backTrack.btiMemHi = this.bus.readBackTrack(addr + 1); this.backTrack.btiMemHi = this.bus.readBackTrack(addr + 1);
} }
if (off != this.blockLimit) { if (off < this.blockLimit) {
return this.aMemBlocks[iBlock].readWord(off); return this.aMemBlocks[iBlock].readWord(off);
} }
return this.aMemBlocks[iBlock++].readByte(off) | (this.aMemBlocks[iBlock & this.blockMask].readByte(0) << 8); return this.aMemBlocks[iBlock].readByte(off) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readByte(0) << 8);
};
/**
* getLong(addr)
*
* @this {X86CPU}
* @param {number} addr is a physical (non-segmented) address
* @return {number} word (32-bit) value at that address
*/
X86CPU.prototype.getLong = function(addr)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.addrMemMask) >> this.blockShift;
if (BACKTRACK) {
this.backTrack.btiMemLo = this.bus.readBackTrack(addr);
this.backTrack.btiMemHi = this.bus.readBackTrack(addr + 1);
}
var nShift = (off & 0x3) << 3;
var dw = this.aMemBlocks[iBlock].readLong(off & ~0x3);
if (nShift) {
dw >>>= nShift;
dw |= (this.aMemBlocks[(iBlock + 1) & this.blockMask].readLong(0) << (32 - nShift));
}
return dw;
}; };
/** /**
@ -1914,10 +1949,8 @@ X86CPU.prototype.setWord = function(addr, w)
{ {
var off = addr & this.blockLimit; var off = addr & this.blockLimit;
var iBlock = (addr & this.addrMemMask) >> this.blockShift; var iBlock = (addr & this.addrMemMask) >> this.blockShift;
/* /*
* On the 8088, it takes 4 cycles to write the additional byte REGARDLESS whether the address is odd or even. * On the 8088, it takes 4 cycles to write the additional byte REGARDLESS whether the address is odd or even.
*
* TODO: For the 8086, the penalty is actually "(addr & 0x1) << 2" (4 additional cycles only when the address is odd). * TODO: For the 8086, the penalty is actually "(addr & 0x1) << 2" (4 additional cycles only when the address is odd).
*/ */
this.nStepCycles -= this.CYCLES.nWordCyclePenalty; this.nStepCycles -= this.CYCLES.nWordCyclePenalty;
@ -1926,7 +1959,7 @@ X86CPU.prototype.setWord = function(addr, w)
this.bus.writeBackTrack(addr, this.backTrack.btiMemLo); this.bus.writeBackTrack(addr, this.backTrack.btiMemLo);
this.bus.writeBackTrack(addr + 1, this.backTrack.btiMemHi); this.bus.writeBackTrack(addr + 1, this.backTrack.btiMemHi);
} }
if (off != this.blockLimit) { if (off < this.blockLimit) {
this.aMemBlocks[iBlock].writeWord(off, w & 0xffff); this.aMemBlocks[iBlock].writeWord(off, w & 0xffff);
return; return;
} }
@ -2337,7 +2370,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) & 0xffff); // this.advanceIP(1) this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + 1) & this.addrMask); // this.advanceIP(1)
return b; return b;
}; };
@ -2351,8 +2384,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) & 0xffff); // this.advanceIP(1) this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + 1) & this.addrMask); // this.advanceIP(1)
return b & 0xffff; return b & this.addrMask;
}; };
/** /**
@ -2368,7 +2401,7 @@ X86CPU.prototype.getIPWord = function()
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 + 2) & 0xffff); // this.advanceIP(2) this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + 2) & this.addrMask); // this.advanceIP(2)
return w; return w;
}; };
@ -2395,7 +2428,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 + 2) & 0xffff; this.regESP = (this.regESP + 2) & this.addrMask;
return this.getSOWord(this.segSS, regESP); return this.getSOWord(this.segSS, regESP);
}; };
@ -2407,8 +2440,8 @@ X86CPU.prototype.popWord = function()
*/ */
X86CPU.prototype.pushWord = function(w) X86CPU.prototype.pushWord = function(w)
{ {
this.assert((w & 0xffff) == w); this.assert((w & this.opMask) == w);
this.setSOWord(this.segSS, (this.regESP = (this.regESP - 2) & 0xffff), w); this.setSOWord(this.segSS, (this.regESP = (this.regESP - 2) & this.addrMask), w);
}; };
/** /**
@ -2699,7 +2732,8 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
this.opMask = this.segCS.opMask; this.opMask = this.segCS.opMask;
this.addrSize = this.segCS.addrSize; this.addrSize = this.segCS.addrSize;
this.addrMask = this.segCS.addrMask; this.addrMask = this.segCS.addrMask;
this.opMods = this.aaOpMod[this.addrSize]; this.opMem = this.aaOpMem[this.opSize];
this.opMod = this.aaOpMod[this.addrSize];
} }
this.opPrefixes = this.opFlags & X86.OPFLAG.REPEAT; this.opPrefixes = this.opFlags & X86.OPFLAG.REPEAT;

View file

@ -38,6 +38,20 @@ if (typeof module !== 'undefined') {
var X86ModSIB = {}; var X86ModSIB = {};
/*
* TODO: Factor out the SIB (scale=1) decoders that are functionally equivalent to one another,
* just as I've already done for all the ModRM (register-to-register) decoders. For example:
*
* opModSIB01(): this.regECX + this.regEAX
*
* is functionally equivalent to:
*
* opModSIB08(): this.regEAX + this.regECX
*
* This isn't super critical, since the SIB decoders are much smaller/simpler than the ModRM decoders,
* but still, it's wasteful.
*/
X86ModSIB.aOpModSIB = [ X86ModSIB.aOpModSIB = [
/** /**
* opModSIB00(): scale=00 (1) index=000 (EAX) base=000 (EAX) * opModSIB00(): scale=00 (1) index=000 (EAX) base=000 (EAX)

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.opMods.aOpModGrpWord[bModRM].call(this, this.aOpGrp6, X86Grps.opGrpNoSrc); this.opMod.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.opMods.aOpModGrpWord[bModRM].call(this, X86Op0F.aOpGrp7, X86Grps.opGrpNoSrc); this.opMod.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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLAR); this.opMod.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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLSL); this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLSL);
}, },
/** /**
* opLOADALL() * opLOADALL()

View file

@ -54,7 +54,7 @@ var X86OpXX = {
* 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 && !b) this.stopCPU();
this.opMods.aOpModMemByte[b].call(this, X86Grps.opGrpADDb); this.opMod.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.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpADDw); this.opMod.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.opMods.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpADDb); this.opMod.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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpADDw); this.opMod.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.opMods.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpORb); this.opMod.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.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpORw); this.opMod.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.opMods.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpORb); this.opMod.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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpORw); this.opMod.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.opMods.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpADCb); this.opMod.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.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpADCw); this.opMod.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.opMods.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpADCb); this.opMod.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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpADCw); this.opMod.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.opMods.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpSBBb); this.opMod.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.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpSBBw); this.opMod.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.opMods.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpSBBb); this.opMod.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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpSBBw); this.opMod.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.opMods.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpANDb); this.opMod.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.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpANDw); this.opMod.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.opMods.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpANDb); this.opMod.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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpANDw); this.opMod.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.opMods.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpSUBb); this.opMod.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.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpSUBw); this.opMod.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.opMods.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpSUBb); this.opMod.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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpSUBw); this.opMod.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.opMods.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpXORb); this.opMod.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.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpXORw); this.opMod.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.opMods.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpXORb); this.opMod.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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpXORw); this.opMod.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.opMods.aOpModMemByte[this.getIPByte()].call(this, X86Grps.opGrpCMPb); this.opMod.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.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw); this.opMod.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.opMods.aOpModRegByte[this.getIPByte()].call(this, X86Grps.opGrpCMPb); this.opMod.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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw); this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Grps.opGrpCMPw);
}, },
/** /**
* op=0x3C (CMP AL,imm8) * op=0x3C (CMP AL,imm8)
@ -1026,7 +1026,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opPUSHSP8086: function() { opPUSHSP8086: function() {
var w = (this.regESP - this.opSize) & this.opMask; var w = (this.regESP - (2 << this.opSize)) & this.opMask;
this.pushWord(w); this.pushWord(w);
this.nStepCycles -= this.CYCLES.nOpCyclesPushReg; this.nStepCycles -= this.CYCLES.nOpCyclesPushReg;
}, },
@ -1224,7 +1224,7 @@ var X86OpXX = {
if (BACKTRACK) { if (BACKTRACK) {
this.backTrack.btiBPLo = this.backTrack.btiMemLo; this.backTrack.btiBPHi = this.backTrack.btiMemHi; this.backTrack.btiBPLo = this.backTrack.btiMemLo; this.backTrack.btiBPHi = this.backTrack.btiMemHi;
} }
this.regESP += this.opSize; this.regESP += (2 << this.opSize);
this.regEBX = (this.regEBX & ~this.opMask) | this.popWord(); this.regEBX = (this.regEBX & ~this.opMask) | this.popWord();
if (BACKTRACK) { if (BACKTRACK) {
this.backTrack.btiBL = this.backTrack.btiMemLo; this.backTrack.btiBH = this.backTrack.btiMemHi; this.backTrack.btiBL = this.backTrack.btiMemLo; this.backTrack.btiBH = this.backTrack.btiMemHi;
@ -1249,7 +1249,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opBOUND: function() { opBOUND: function() {
this.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpBOUND); this.opMod.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.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpARPL); this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpARPL);
}, },
/** /**
* op=0x66 (OS:) (80386 and up) * op=0x66 (OS:) (80386 and up)
@ -1268,8 +1268,9 @@ var X86OpXX = {
*/ */
opOS: function() { opOS: function() {
this.opFlags |= X86.OPFLAG.SEG; this.opFlags |= X86.OPFLAG.SEG;
this.opSize ^= 6; // that which is 2 shall become 4, and vice versa this.opSize ^= 1; // that which is 0 shall become 1, and vice versa
this.opMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa this.opMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa
this.opMem = this.aaOpMem[this.opSize];
this.nStepCycles -= this.CYCLES.nOpCyclesPrefix; this.nStepCycles -= this.CYCLES.nOpCyclesPrefix;
}, },
/** /**
@ -1283,7 +1284,7 @@ var X86OpXX = {
this.opFlags |= X86.OPFLAG.SEG; this.opFlags |= X86.OPFLAG.SEG;
this.addrSize ^= 1; // that which is 0 shall become 1, and vice versa this.addrSize ^= 1; // that which is 0 shall become 1, and vice versa
this.addrMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa this.addrMask ^= 0xffff0000; // that which is 0x0000ffff shall become 0xffffffff, and vice versa
this.opMods = this.aaOpMod[this.addrSize]; this.opMod = this.aaOpMod[this.addrSize];
this.nStepCycles -= this.CYCLES.nOpCyclesPrefix; this.nStepCycles -= this.CYCLES.nOpCyclesPrefix;
}, },
/** /**
@ -1301,7 +1302,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opIMUL16: function() { opIMUL16: function() {
this.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpIMUL16); this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpIMUL16);
}, },
/** /**
* op=0x6A (PUSH imm8) (80186/80188 and up) * op=0x6A (PUSH imm8) (80186/80188 and up)
@ -1319,7 +1320,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opIMUL8: function() { opIMUL8: function() {
this.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpIMUL8); this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpIMUL8);
}, },
/** /**
* op=0x6C (INSB) (80186/80188 and up) * op=0x6C (INSB) (80186/80188 and up)
@ -1742,7 +1743,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp1b: function() { opGrp1b: function() {
this.opMods.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp1b, this.getIPByte); this.opMod.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);
}, },
/** /**
@ -1751,7 +1752,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp1w: function() { opGrp1w: function() {
this.opMods.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp1w, this.getIPWord); this.opMod.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);
}, },
/** /**
@ -1760,7 +1761,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp1sw: function() { opGrp1sw: function() {
this.opMods.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp1w, this.getIPDisp); this.opMod.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);
}, },
/** /**
@ -1769,7 +1770,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opTESTrb: function() { opTESTrb: function() {
this.opMods.aOpModMemByte[this.getIPByte()].call(this, X86Help.opHelpTESTb); this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Help.opHelpTESTb);
}, },
/** /**
* op=0x85 (TEST reg,word) * op=0x85 (TEST reg,word)
@ -1777,7 +1778,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opTESTrw: function() { opTESTrw: function() {
this.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpTESTw); this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpTESTw);
}, },
/** /**
* op=0x86 (XCHG reg,byte) * op=0x86 (XCHG reg,byte)
@ -1806,7 +1807,7 @@ var X86OpXX = {
* this.regEDX = (this.regEDX & 0xff) | (b << 8); * this.regEDX = (this.regEDX & 0xff) | (b << 8);
* } * }
*/ */
this.opMods.aOpModRegByte[this.bModRM = this.getIPByte()].call(this, X86Help.opHelpXCHGrb); this.opMod.aOpModRegByte[this.bModRM = this.getIPByte()].call(this, X86Help.opHelpXCHGrb);
}, },
/** /**
* op=0x87 (XCHG reg,word) * op=0x87 (XCHG reg,word)
@ -1817,7 +1818,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opXCHGrw: function() { opXCHGrw: function() {
this.opMods.aOpModRegWord[this.bModRM = this.getIPByte()].call(this, X86Help.opHelpXCHGrw); this.opMod.aOpModRegWord[this.bModRM = this.getIPByte()].call(this, X86Help.opHelpXCHGrw);
}, },
/** /**
* op=0x88 (MOV byte,reg) * op=0x88 (MOV byte,reg)
@ -1829,7 +1830,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.opMods.aOpModMemByte[this.getIPByte()].call(this, X86Help.opHelpMOV); this.opMod.aOpModMemByte[this.getIPByte()].call(this, X86Help.opHelpMOV);
}, },
/** /**
* op=0x89 (MOV word,reg) * op=0x89 (MOV word,reg)
@ -1841,7 +1842,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.opMods.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpMOV); this.opMod.aOpModMemWord[this.getIPByte()].call(this, X86Help.opHelpMOV);
}, },
/** /**
* op=0x8A (MOV reg,byte) * op=0x8A (MOV reg,byte)
@ -1849,7 +1850,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opMOVrb: function() { opMOVrb: function() {
this.opMods.aOpModRegByte[this.getIPByte()].call(this, X86Help.opHelpMOV); this.opMod.aOpModRegByte[this.getIPByte()].call(this, X86Help.opHelpMOV);
}, },
/** /**
* op=0x8B (MOV reg,word) * op=0x8B (MOV reg,word)
@ -1857,7 +1858,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opMOVrw: function() { opMOVrw: function() {
this.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpMOV); this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpMOV);
}, },
/** /**
* op=0x8C (MOV word,sr) * op=0x8C (MOV word,sr)
@ -1892,7 +1893,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.opMods.aOpModMemWord[bModRM].call(this, X86Help.opHelpMOVSegSrc); this.opMod.aOpModMemWord[bModRM].call(this, X86Help.opHelpMOVSegSrc);
}, },
/** /**
* op=0x8D (LEA reg,word) * op=0x8D (LEA reg,word)
@ -1902,7 +1903,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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLEA); this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLEA);
}, },
/** /**
* op=0x8E (MOV sr,word) * op=0x8E (MOV sr,word)
@ -1953,7 +1954,7 @@ var X86OpXX = {
} }
break; break;
} }
this.opMods.aOpModRegWord[bModRM].call(this, X86Help.opHelpMOV); this.opMod.aOpModRegWord[bModRM].call(this, X86Help.opHelpMOV);
switch (reg) { switch (reg) {
case 0x0: case 0x0:
this.setES(this.regEAX); this.setES(this.regEAX);
@ -2001,7 +2002,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.opMods.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrpPOPw, this.popWord); this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrpPOPw, this.popWord);
}, },
/** /**
* op=0x90 (NOP, aka XCHG AX,AX) * op=0x90 (NOP, aka XCHG AX,AX)
@ -2122,7 +2123,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opCBW: function() { opCBW: function() {
if (this.opSize == 2) { if (!this.opSize) {
/* /*
* CBW * CBW
*/ */
@ -2145,7 +2146,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opCWD: function() { opCWD: function() {
if (this.opSize == 2) { if (!this.opSize) {
/* /*
* CWD * CWD
*/ */
@ -2891,7 +2892,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2bi: function() { opGrp2bi: function() {
this.opMods.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2CountImm); this.opMod.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)
@ -2899,7 +2900,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2wi: function() { opGrp2wi: function() {
this.opMods.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountImm); this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountImm);
}, },
/** /**
* op=0xC2 (RET n) * op=0xC2 (RET n)
@ -2909,7 +2910,7 @@ var X86OpXX = {
opRETn: function() { opRETn: function() {
var n = this.getIPWord(); var n = this.getIPWord();
this.setIP(this.popWord()); this.setIP(this.popWord());
this.regESP = (this.regESP & ~this.addrMask) | ((this.regESP + (n << (this.opSize >> 2))) & this.addrMask); this.regESP = (this.regESP & ~this.addrMask) | ((this.regESP + (n << this.opSize)) & this.addrMask);
this.nStepCycles -= this.CYCLES.nOpCyclesRetn; this.nStepCycles -= this.CYCLES.nOpCyclesRetn;
}, },
/** /**
@ -2930,7 +2931,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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLES); this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLES);
}, },
/** /**
* op=0xC5 (LDS reg,word) * op=0xC5 (LDS reg,word)
@ -2941,7 +2942,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.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLDS); this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpLDS);
}, },
/** /**
* op=0xC6 (MOV byte,imm8) * op=0xC6 (MOV byte,imm8)
@ -2953,7 +2954,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.opMods.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrpMOVImm, this.getIPByte); this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrpMOVImm, this.getIPByte);
}, },
/** /**
* op=0xC7 (MOV word,imm16) * op=0xC7 (MOV word,imm16)
@ -2965,7 +2966,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.opMods.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrpMOVImm, this.getIPWord); this.opMod.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)
@ -3003,7 +3004,7 @@ var X86OpXX = {
if (bLevel > 0) { if (bLevel > 0) {
this.nStepCycles -= (bLevel << 2) + (bLevel > 1? 1 : 0); this.nStepCycles -= (bLevel << 2) + (bLevel > 1? 1 : 0);
while (--bLevel) { while (--bLevel) {
this.regEBP = (this.regEBP & ~this.segSS.addrMask) | ((this.regEBP - this.opSize) & this.segSS.addrMask); this.regEBP = (this.regEBP & ~this.segSS.addrMask) | ((this.regEBP - (2 << this.opSize)) & this.segSS.addrMask);
this.pushWord(this.getSOWord(this.segSS, this.regEBP & this.segSS.addrMask)); this.pushWord(this.getSOWord(this.segSS, this.regEBP & this.segSS.addrMask));
} }
this.pushWord(wFrame); this.pushWord(wFrame);
@ -3092,7 +3093,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2b1: function() { opGrp2b1: function() {
this.opMods.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2Count1); this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2Count1);
}, },
/** /**
* op=0xD1 (GRP2 word,1) * op=0xD1 (GRP2 word,1)
@ -3100,7 +3101,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2w1: function() { opGrp2w1: function() {
this.opMods.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2Count1); this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2Count1);
}, },
/** /**
* op=0xD2 (GRP2 byte,CL) * op=0xD2 (GRP2 byte,CL)
@ -3108,7 +3109,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2bCL: function() { opGrp2bCL: function() {
this.opMods.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2CountCL); this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2CountCL);
}, },
/** /**
* op=0xD3 (GRP2 word,CL) * op=0xD3 (GRP2 word,CL)
@ -3116,7 +3117,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp2wCL: function() { opGrp2wCL: function() {
this.opMods.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountCL); this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountCL);
}, },
/** /**
* op=0xD4 0x0A (AAM) * op=0xD4 0x0A (AAM)
@ -3195,7 +3196,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opESC: function() { opESC: function() {
this.opMods.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpESC); this.opMod.aOpModRegWord[this.getIPByte()].call(this, X86Help.opHelpESC);
this.nStepCycles -= 8; // TODO: Fix this.nStepCycles -= 8; // TODO: Fix
}, },
/** /**
@ -3496,7 +3497,7 @@ var X86OpXX = {
*/ */
opGrp3b: function() { opGrp3b: function() {
this.regMD16 = -1; this.regMD16 = -1;
this.opMods.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp3b, X86Grps.opGrpNoSrc); this.opMod.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;
}, },
/** /**
@ -3519,7 +3520,7 @@ var X86OpXX = {
*/ */
opGrp3w: function() { opGrp3w: function() {
this.regMD16 = -1; this.regMD16 = -1;
this.opMods.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp3w, X86Grps.opGrpNoSrc); this.opMod.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;
@ -3586,7 +3587,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp4b: function() { opGrp4b: function() {
this.opMods.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp4b, X86Grps.opGrpNoSrc); this.opMod.aOpModGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp4b, X86Grps.opGrpNoSrc);
}, },
/** /**
* op=0xFF (GRP4 word) * op=0xFF (GRP4 word)
@ -3594,7 +3595,7 @@ var X86OpXX = {
* @this {X86CPU} * @this {X86CPU}
*/ */
opGrp4w: function() { opGrp4w: function() {
this.opMods.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp4w, X86Grps.opGrpNoSrc); this.opMod.aOpModGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp4w, X86Grps.opGrpNoSrc);
} }
}; };

View file

@ -118,7 +118,7 @@ X86Seg.ID = {
X86Seg.loadReal = function loadReal(sel, fSuppress) X86Seg.loadReal = function loadReal(sel, fSuppress)
{ {
this.sel = sel; this.sel = sel;
this.opSize = 2; this.addrSize = 0; this.opSize = this.addrSize = 0;
this.opMask = this.addrMask = 0xffff; this.opMask = this.addrMask = 0xffff;
return this.base = sel << 4; return this.base = sel << 4;
}; };
@ -848,10 +848,10 @@ X86Seg.prototype.updateMode = function(fProt)
this.cpl = this.sel & X86.SEL.RPL; this.cpl = this.sel & X86.SEL.RPL;
this.dpl = (this.acc & X86.DESC.ACC.DPL.MASK) >> X86.DESC.ACC.DPL.SHIFT; this.dpl = (this.acc & X86.DESC.ACC.DPL.MASK) >> X86.DESC.ACC.DPL.SHIFT;
if (this.cpu.model < X86.MODEL_80386 || !(this.ext & X86.DESC.EXT.BIG)) { if (this.cpu.model < X86.MODEL_80386 || !(this.ext & X86.DESC.EXT.BIG)) {
this.opSize = 2; this.opSize = 0;
this.opMask = 0xffff; this.opMask = 0xffff;
} else { } else {
this.opSize = 4; this.opSize = 1;
this.opMask = 0xffffffff; this.opMask = 0xffffffff;
} }
} else { } else {
@ -862,10 +862,10 @@ X86Seg.prototype.updateMode = function(fProt)
this.limit = 0xffff; this.limit = 0xffff;
this.cpl = this.dpl = 0; this.cpl = this.dpl = 0;
this.addrDesc = X86.ADDR_INVALID; this.addrDesc = X86.ADDR_INVALID;
this.opSize = 2; this.opSize = 0;
this.opMask = 0xffff; this.opMask = 0xffff;
} }
this.addrSize = this.opSize >> 2; this.addrSize = this.opSize;
this.addrMask = this.opMask; this.addrMask = this.opMask;
return fProt; return fProt;
}; };