Fixed new modRM decoders

This commit is contained in:
Jeff Parsons 2016-03-08 16:39:10 -08:00
commit 7953383fa9
37 changed files with 7973 additions and 1603 deletions

View file

@ -3549,7 +3549,7 @@ ChipSet.prototype.setFPUInterrupt = function()
* later, and the FPU coprocessor is still indicating an error condition, should we then generate an NMI?
*/
if (!(this.bNMI & ChipSet.NMI.DISABLE)) {
X86.fnInterrupt.call(this.cpu, X86.EXCEPTION.NMI);
X86.helpInterrupt.call(this.cpu, X86.EXCEPTION.NMI);
}
}
};

View file

@ -1090,9 +1090,28 @@ Computer.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
};
return true;
/*
* Technically, this binding should now be called "saveState", to clearly distinguish it from
* the "Save Machine" control that's normally bound to the savePC() function in save.js. Saving
* an entire machine includes everything needed to start/restore the machine; eg, the machine
* XML configuration file(s) *and* the JSON-encoded machine state.
*/
case "save":
/*
* Since this feature depends on the server supporting the PCjs User API (see userapi.js),
* and since pcjs.org is no longer running a Node web server, we disable the feature for that
* particular host.
*/
if (str.endsWith(web.getHost(), "pcjs.org")) {
control.style.display = "none";
if (DEBUG) this.log("Remote user API not available");
/*
* We could also simply hide the control; eg:
*
* control.style.display = "none";
*
* but removing the control altogether seems better.
*/
control.parentNode.removeChild(/** @type {Node} */ (control));
return false;
}
this.bindings[sBinding] = control;

View file

@ -1048,7 +1048,7 @@ CPU.prototype.runCPU = function(fSetFocus)
if (MAXDEBUG) this.println("CPU exception " + str.toHexByte(exception));
/*
* TODO: If we ever get into a situation where every single instruction is generating a fault
* (eg, if an 8088 executes opcode 0xFF 0xFF, which is incorrectly routed to fnFault() instead
* (eg, if an 8088 executes opcode 0xFF 0xFF, which is incorrectly routed to helpFault() instead
* of fnGRPUndefined()), the browser may hang because we're failing to yield often enough.
* This is likely because the thrown exceptions are taking MUCH longer than normal instructions,
* throwing off our burst calculations. We need to either adjust the burst or break out of the

View file

@ -3173,9 +3173,17 @@ if (DEBUGGER) {
* We must create a new dbgAddr from the address in aHistory, because dbgAddr was
* a reference, not a copy, and we don't want getInstruction() modifying the original.
*/
dbgAddr = this.newAddr(dbgAddr.off, dbgAddr.sel, dbgAddr.addr, dbgAddr.type, dbgAddr.fData32, dbgAddr.fAddr32);
var dbgAddrNew = this.newAddr(dbgAddr.off, dbgAddr.sel, dbgAddr.addr, dbgAddr.type, dbgAddr.fData32, dbgAddr.fAddr32);
var sComment = "history";
var nSequence = nPrev--;
if (DEBUG && dbgAddr.cycleCount != null) {
sComment = "cycles";
nSequence = dbgAddr.cycleCount;
}
var sInstruction = this.getInstruction(dbgAddrNew, sComment, nSequence);
var sInstruction = this.getInstruction(dbgAddr, "history", nPrev--);
if (!aFilters.length || sInstruction.indexOf(aFilters[0]) >= 0) {
this.println(sInstruction);
}
@ -3184,8 +3192,8 @@ if (DEBUGGER) {
* If there were OPERAND or ADDRESS overrides on the previous instruction, getInstruction()
* will have automatically disassembled additional bytes, so skip additional history entries.
*/
if (dbgAddr.cOverrides) {
iHistory += dbgAddr.cOverrides; nLines -= dbgAddr.cOverrides; nPrev -= dbgAddr.cOverrides;
if (dbgAddrNew.cOverrides) {
iHistory += dbgAddrNew.cOverrides; nLines -= dbgAddrNew.cOverrides; nPrev -= dbgAddrNew.cOverrides;
}
if (iHistory >= aHistory.length) iHistory = 0;
@ -4240,6 +4248,8 @@ if (DEBUGGER) {
*/
Debugger.prototype.checkInstruction = function(addr, nState)
{
var cpu = this.cpu;
if (nState > 0) {
if (this.nBreakIns && !--this.nBreakIns) {
return true;
@ -4250,8 +4260,8 @@ if (DEBUGGER) {
/*
* Halt if running with interrupts disabled and IOPL < CPL, because that's likely an error
*/
if (MAXDEBUG && !(this.cpu.regPS & X86.PS.IF) && this.cpu.nIOPL < this.cpu.nCPL) {
this.printMessage("interrupts disabled at IOPL " + this.cpu.nIOPL + " and CPL " + this.cpu.nCPL, true);
if (MAXDEBUG && !(cpu.regPS & X86.PS.IF) && cpu.nIOPL < cpu.nCPL) {
this.printMessage("interrupts disabled at IOPL " + cpu.nIOPL + " and CPL " + cpu.nCPL, true);
return true;
}
}
@ -4264,11 +4274,12 @@ if (DEBUGGER) {
*/
if (nState >= 0 && this.aaOpcodeCounts.length) {
this.cOpcodes++;
var bOpcode = this.cpu.probeAddr(addr);
var bOpcode = cpu.probeAddr(addr);
if (bOpcode != null) {
this.aaOpcodeCounts[bOpcode][1]++;
var dbgAddr = this.aOpcodeHistory[this.iOpcodeHistory];
this.setAddr(dbgAddr, this.cpu.getIP(), this.cpu.getCS());
this.setAddr(dbgAddr, cpu.getIP(), cpu.getCS());
if (DEBUG) dbgAddr.cycleCount = cpu.getCycles();
if (++this.iOpcodeHistory == this.aOpcodeHistory.length) this.iOpcodeHistory = 0;
}
}
@ -7341,14 +7352,14 @@ if (DEBUGGER) {
break;
case "CR0":
this.cpu.regCR0 = w;
X86.fnLCR0.call(this.cpu, w);
X86.helpLoadCR0.call(this.cpu, w);
break;
case "CR2":
this.cpu.regCR2 = w;
break;
case "CR3":
this.cpu.regCR3 = w;
X86.fnLCR3.call(this.cpu, w);
X86.helpLoadCR3.call(this.cpu, w);
break;
/*
* TODO: Add support for DR0-DR7 and TR6-TR7.
@ -7682,18 +7693,35 @@ if (DEBUGGER) {
/**
* doTrace(sCmd, sCount)
*
* The "t" and "tr" commands interpret the count as a number of instructions, and since
* we call the Debugger's stepCPU() for each iteration, a single instruction includes
* any/all prefixes; the CPU's stepCPU() treats prefixes as discrete operations. The only
* difference between "t" and "tr": the former displays only the next instruction, while
* the latter also displays the (updated) registers.
*
* The "tc" command interprets the count as a number of cycles rather than instructions,
* allowing you to quickly execute large chunks of instructions with a single command; it
* doesn't display anything until the the chunk has finished.
*
* However, generally a more useful command is "bn", which allows you to break after some
* number of instructions have been executed (as opposed to some number of cycles).
*
* @this {Debugger}
* @param {string} [sCmd] "t" or "tr"
* @param {string} [sCmd] ("t", "tc", or "tr")
* @param {string} [sCount] # of instructions to step
*/
Debugger.prototype.doTrace = function(sCmd, sCount)
{
var dbg = this;
var fRegs = (sCmd == "tr");
var count = this.parseValue(sCount, null, true) || 1;
var nCycles = (count == 1? 0 : 1);
var fRegs = (sCmd != "t");
var nCount = this.parseValue(sCount, null, true) || 1;
var nCycles = (nCount == 1? 0 : 1);
if (sCmd == "tc") {
nCycles = nCount;
nCount = 1;
}
web.onCountRepeat(
count,
nCount,
function onCountStep() {
return dbg.setBusy(true) && dbg.stepCPU(nCycles, fRegs, false);
},

View file

@ -457,6 +457,7 @@ FDC.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
case "loadDrive":
this.bindings[sBinding] = control;
control.onclick = function onClickLoadDrive(event) {
var controlDisks = fdc.bindings["listDisks"];
if (controlDisks) {
@ -468,7 +469,21 @@ FDC.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
return true;
case "saveDrive":
if (!this.fLocalDisks) {
if (DEBUG) this.log("Local disk support not available");
/*
* We could also simply hide the control; eg:
*
* control.style.display = "none";
*
* but removing the control altogether seems better.
*/
control.parentNode.removeChild(/** @type {Node} */ (control));
return false;
}
this.bindings[sBinding] = control;
control.onclick = function onClickLoadDrive(event) {
var controlDrives = fdc.bindings["listDrives"];
if (controlDrives && controlDrives.options && fdc.aDrives) {
@ -490,35 +505,43 @@ FDC.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
return true;
case "mountDrive":
if (this.fLocalDisks) {
this.bindings[sBinding] = control;
if (!this.fLocalDisks) {
if (DEBUG) this.log("Local disk support not available");
/*
* Enable "Mount" button only if a file is actually selected
* We could also simply hide the control; eg:
*
* control.style.display = "none";
*
* but removing the control altogether seems better.
*/
control.addEventListener('change', function() {
var fieldset = control.children[0];
var files = fieldset.children[0].files;
var submit = fieldset.children[1];
submit.disabled = !files.length;
});
control.onsubmit = function(event) {
var file = event.currentTarget[1].files[0];
if (file) {
var sDiskettePath = file.name;
var sDisketteName = str.getBaseName(sDiskettePath, true);
fdc.loadSelectedDrive(sDisketteName, sDiskettePath, file);
}
/*
* Prevent reloading of web page after form submission
*/
return false;
};
}
else {
if (DEBUG) this.log("Local file support not available");
control.parentNode.removeChild(/** @type {Node} */ (control));
return false;
}
this.bindings[sBinding] = control;
/*
* Enable "Mount" button only if a file is actually selected
*/
control.addEventListener('change', function() {
var fieldset = control.children[0];
var files = fieldset.children[0].files;
var submit = fieldset.children[1];
submit.disabled = !files.length;
});
control.onsubmit = function(event) {
var file = event.currentTarget[1].files[0];
if (file) {
var sDiskettePath = file.name;
var sDisketteName = str.getBaseName(sDiskettePath, true);
fdc.loadSelectedDrive(sDisketteName, sDiskettePath, file);
}
/*
* Prevent reloading of web page after form submission
*/
return false;
};
return true;
default:

View file

@ -1117,6 +1117,16 @@ Memory.prototype = {
readBytePLE: function readBytePLE(off, addr) {
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED;
/*
* TODO: Review this performance hack. Basically, after the first read of a page,
* we redirect the default read handler to a faster handler. However, if operating
* systems clear the PDE/PTE bits without reloading CR3, they won't get set again.
*
* We should look into creating special write handlers for pages containing PDE/PTE
* entries, and whenever those entries are written, reset the read/write handlers
* for the corresponding pages.
*/
this.readByte = this.readByteLE;
return this.ab[off];
},
/**
@ -1160,6 +1170,16 @@ Memory.prototype = {
*/
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED;
/*
* TODO: Review this performance hack. Basically, after the first read of a page,
* we redirect the default read handler to a faster handler. However, if operating
* systems clear the PDE/PTE bits without reloading CR3, they won't get set again.
*
* We should look into creating special write handlers for pages containing PDE/PTE
* entries, and whenever those entries are written, reset the read/write handlers
* for the corresponding pages.
*/
this.readShort = this.readShortLE;
return (off & 0x1)? (this.ab[off] | (this.ab[off+1] << 8)) : this.aw[off >> 1];
},
/**
@ -1203,6 +1223,16 @@ Memory.prototype = {
*/
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED;
/*
* TODO: Review this performance hack. Basically, after the first read of a page,
* we redirect the default read handler to a faster handler. However, if operating
* systems clear the PDE/PTE bits without reloading CR3, they won't get set again.
*
* We should look into creating special write handlers for pages containing PDE/PTE
* entries, and whenever those entries are written, reset the read/write handlers
* for the corresponding pages.
*/
this.readLong = this.readLongLE;
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];
},
/**
@ -1241,6 +1271,16 @@ Memory.prototype = {
this.ab[off] = b;
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED | X86.PTE.DIRTY;
/*
* TODO: Review this performance hack. Basically, after the first write of a page,
* we redirect the default write handler to a faster handler. However, if operating
* systems clear the PDE/PTE bits without reloading CR3, they won't get set again.
*
* We should look into creating special write handlers for pages containing PDE/PTE
* entries, and whenever those entries are written, reset the read/write handlers
* for the corresponding pages.
*/
this.writeByte = this.writeByteLE;
/*
* NOTE: Technically, we should be setting the fDirty flag on blockPDE and blockPTE as well, but let's
* consider the two sole uses of fDirty. First, we have cleanMemory(), which is currently used only by
@ -1304,6 +1344,16 @@ Memory.prototype = {
}
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED | X86.PTE.DIRTY;
/*
* TODO: Review this performance hack. Basically, after the first write of a page,
* we redirect the default write handler to a faster handler. However, if operating
* systems clear the PDE/PTE bits without reloading CR3, they won't get set again.
*
* We should look into creating special write handlers for pages containing PDE/PTE
* entries, and whenever those entries are written, reset the read/write handlers
* for the corresponding pages.
*/
this.writeShort = this.writeShortLE;
/*
* NOTE: Technically, we should be setting the fDirty flag on blockPDE and blockPTE as well, but let's
* consider the two sole uses of fDirty. First, we have cleanMemory(), which is currently used only by
@ -1371,6 +1421,16 @@ Memory.prototype = {
}
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED | X86.PTE.DIRTY;
/*
* TODO: Review this performance hack. Basically, after the first write of a page,
* we redirect the default write handler to a faster handler. However, if operating
* systems clear the PDE/PTE bits without reloading CR3, they won't get set again.
*
* We should look into creating special write handlers for pages containing PDE/PTE
* entries, and whenever those entries are written, reset the read/write handlers
* for the corresponding pages.
*/
this.writeLong = this.writeLongLE;
/*
* NOTE: Technically, we should be setting the fDirty flag on blockPDE and blockPTE as well, but let's
* consider the two sole uses of fDirty. First, we have cleanMemory(), which is currently used only by

View file

@ -545,12 +545,12 @@ X86CPU.prototype.mapPageBlock = function(addr, fWrite, fSuppress)
var pde = blockPDE.readLong(offPDE);
if (!(pde & X86.PTE.PRESENT)) {
if (!fSuppress) X86.fnPageFault.call(this, addr, false, fWrite);
if (!fSuppress) X86.helpPageFault.call(this, addr, false, fWrite);
return this.memEmpty;
}
if (!(pde & X86.PTE.USER) && this.nCPL == 3) {
if (!fSuppress) X86.fnPageFault.call(this, addr, true, fWrite);
if (!fSuppress) X86.helpPageFault.call(this, addr, true, fWrite);
return this.memEmpty;
}
@ -565,12 +565,12 @@ X86CPU.prototype.mapPageBlock = function(addr, fWrite, fSuppress)
var pte = blockPTE.readLong(offPTE);
if (!(pte & X86.PTE.PRESENT)) {
if (!fSuppress) X86.fnPageFault.call(this, addr, false, fWrite);
if (!fSuppress) X86.helpPageFault.call(this, addr, false, fWrite);
return this.memEmpty;
}
if (!(pte & X86.PTE.USER) && this.nCPL == 3) {
if (!fSuppress) X86.fnPageFault.call(this, addr, true, fWrite);
if (!fSuppress) X86.helpPageFault.call(this, addr, true, fWrite);
return this.memEmpty;
}
@ -1080,7 +1080,7 @@ X86CPU.prototype.resetRegs = function()
/*
* NOTE: Even though the 8086 doesn't have CR0 (aka MSW) and IDTR, we initialize them for ALL CPUs, so
* that functions like X86.fnINT() can use the same code for both. The 8086/8088 have no direct way
* that functions like X86.helpINT() can use the same code for both. The 8086/8088 have no direct way
* of accessing or changing them, so this is an implementation detail those processors are unaware of.
*/
this.regCR0 = X86.CR0.MSW.ON;
@ -1096,8 +1096,8 @@ X86CPU.prototype.resetRegs = function()
this.resultDst = this.resultSrc = this.resultArith = this.resultLogic = 0;
/*
* nFault is set by fnFault() and reset (to -1) by resetRegs() and opIRET(). Its initial purpose was to
* help fnFault() determine when a nested fault should be converted into either a double-fault (DF_FAULT)
* nFault is set by helpFault() and reset (to -1) by resetRegs() and opIRET(). Its initial purpose was to
* help helpFault() determine when a nested fault should be converted into either a double-fault (DF_FAULT)
* or a triple-fault (ie, a processor reset).
*
* It has since evolved into another important role: helping segCS.loadIDT() know when an exception
@ -1105,8 +1105,8 @@ X86CPU.prototype.resetRegs = function()
* to the corresponding fault #, whereas the latter must set it to -1, so that if the IDT contains a gate
* whose DPL < CPL, a GP fault will be generated instead.
*
* The former always call fnFault(), and the latter call fnTrap(), so nFault is updated automatically.
* However, there are also intermediate cases, like hardware interrupts, which call fnINT() after manually
* The former always call helpFault(), and the latter call helpTrap(), so nFault is updated automatically.
* However, there are also intermediate cases, like hardware interrupts, which call helpINT() after manually
* setting nFault to the IDT #. TODO: Review all those "intermediate" cases.
*/
this.nFault = -1;
@ -1326,16 +1326,16 @@ X86CPU.prototype.setAddrSize = function(size)
* aOpModGrpWord
*
* However, when support for the 80386 was added, the number of dispatch tables doubled, and since each entry
* in the table was a discrete function, decoding was fast, but it also produced a lot of code.
* in the table was a discrete function, decoding was fast, but it also required a LOT of code.
*
* So we have now replaced the above table pointers with function pointers:
*
* decodeModRegByte (set to one of: decodeModRegByte16, decodeModRegByte32)
* decodeModMemByte (set to one of: decodeModMemByte16, decodeModMemByte32)
* decodeModGrpByte (set to one of: decodeModGrpByte16, decodeModGrpByte32)
* decodeModRegWord (set to one of: decodeModRegShort16, decodeModRegLong16, decodeModRegShort32, decodeModRegLong32)
* decodeModMemWord (set to one of: decodeModMemShort16, decodeModMemLong16, decodeModMemShort32, decodeModMemLong32)
* decodeModGrpWord (set to one of: decodeModGrpShort16, decodeModGrpLong16, decodeModGrpShort32, decodeModGrpLong32)
* decodeModRegByte (set to one of: modRegByte16, modRegByte32)
* decodeModMemByte (set to one of: modMemByte16, modMemByte32)
* decodeModGrpByte (set to one of: modGrpByte16, modGrpByte32)
* decodeModRegWord (set to one of: modRegShort16, modRegLong16, modRegShort32, modRegLong32)
* decodeModMemWord (set to one of: modMemShort16, modMemLong16, modMemShort32, modMemLong32)
* decodeModGrpWord (set to one of: modGrpShort16, modGrpLong16, modGrpShort32, modGrpLong32)
*
* So opcode handlers that used to do this:
*
@ -1345,46 +1345,50 @@ X86CPU.prototype.setAddrSize = function(size)
*
* this.decodeModMemByte.call(this, X86.fnADDb);
*
* Decoding of ModRM bytes is now slightly slower, but the previous code is still in the repository
* (look for x86modb.js and x86modw.js for the pre-80386 dispatch tables, and x86modb16.js, x86modb32.js,
* x86modw16.js, x86modw32.js, and x86modsib.js for the post-80386 dispatch tables).
*
* @this {X86CPU}
*/
X86CPU.prototype.updateAddrSize = function()
{
if (!I386) {
this.getAddr = (PREFETCH? this.getShortPrefetch : this.getShort);
this.decodeModRegByte = X86.decodeModRegByte16;
this.decodeModMemByte = X86.decodeModMemByte16;
this.decodeModGrpByte = X86.decodeModGrpByte16;
this.decodeModRegWord = X86.decodeModRegShort16;
this.decodeModMemWord = X86.decodeModMemShort16;
this.decodeModGrpWord = X86.decodeModGrpShort16;
this.decodeModRegByte = X86.modRegByte16;
this.decodeModMemByte = X86.modMemByte16;
this.decodeModGrpByte = X86.modGrpByte16;
this.decodeModRegWord = X86.modRegShort16;
this.decodeModMemWord = X86.modMemShort16;
this.decodeModGrpWord = X86.modGrpShort16;
} else {
if (this.sizeAddr == 2) {
this.getAddr = (PREFETCH? this.getShortPrefetch : this.getShort);
this.decodeModRegByte = X86.decodeModRegByte16;
this.decodeModMemByte = X86.decodeModMemByte16;
this.decodeModGrpByte = X86.decodeModGrpByte16;
this.decodeModRegByte = X86.modRegByte16;
this.decodeModMemByte = X86.modMemByte16;
this.decodeModGrpByte = X86.modGrpByte16;
if (this.sizeData == 2) {
this.decodeModRegWord = X86.decodeModRegShort16;
this.decodeModMemWord = X86.decodeModMemShort16;
this.decodeModGrpWord = X86.decodeModGrpShort16;
this.decodeModRegWord = X86.modRegShort16;
this.decodeModMemWord = X86.modMemShort16;
this.decodeModGrpWord = X86.modGrpShort16;
} else {
this.decodeModRegWord = X86.decodeModRegLong16;
this.decodeModMemWord = X86.decodeModMemLong16;
this.decodeModGrpWord = X86.decodeModGrpLong16;
this.decodeModRegWord = X86.modRegLong16;
this.decodeModMemWord = X86.modMemLong16;
this.decodeModGrpWord = X86.modGrpLong16;
}
} else {
this.getAddr = (PREFETCH? this.getLongPrefetch : this.getLong);
this.decodeModRegByte = X86.decodeModRegByte32;
this.decodeModMemByte = X86.decodeModMemByte32;
this.decodeModGrpByte = X86.decodeModGrpByte32;
this.decodeModRegByte = X86.modRegByte32;
this.decodeModMemByte = X86.modMemByte32;
this.decodeModGrpByte = X86.modGrpByte32;
if (this.sizeData == 2) {
this.decodeModRegWord = X86.decodeModRegShort32;
this.decodeModMemWord = X86.decodeModMemShort32;
this.decodeModGrpWord = X86.decodeModGrpShort32;
this.decodeModRegWord = X86.modRegShort32;
this.decodeModMemWord = X86.modMemShort32;
this.decodeModGrpWord = X86.modGrpShort32;
} else {
this.decodeModRegWord = X86.decodeModRegLong32;
this.decodeModMemWord = X86.decodeModMemLong32;
this.decodeModGrpWord = X86.decodeModGrpLong32;
this.decodeModRegWord = X86.modRegLong32;
this.decodeModMemWord = X86.modMemLong32;
this.decodeModGrpWord = X86.modGrpLong32;
}
}
}
@ -1421,26 +1425,26 @@ X86CPU.prototype.updateDataSize = function()
this.getWord = this.getShort;
this.setWord = this.setShort;
if (this.sizeAddr == 2) {
this.decodeModRegWord = X86.decodeModRegShort16;
this.decodeModMemWord = X86.decodeModMemShort16;
this.decodeModGrpWord = X86.decodeModGrpShort16;
this.decodeModRegWord = X86.modRegShort16;
this.decodeModMemWord = X86.modMemShort16;
this.decodeModGrpWord = X86.modGrpShort16;
} else {
this.decodeModRegWord = X86.decodeModRegShort32;
this.decodeModMemWord = X86.decodeModMemShort32;
this.decodeModGrpWord = X86.decodeModGrpShort32;
this.decodeModRegWord = X86.modRegShort32;
this.decodeModMemWord = X86.modMemShort32;
this.decodeModGrpWord = X86.modGrpShort32;
}
} else {
this.typeData = X86.RESULT.DWORD;
this.getWord = this.getLong;
this.setWord = this.setLong;
if (this.sizeAddr == 2) {
this.decodeModRegWord = X86.decodeModRegLong16;
this.decodeModMemWord = X86.decodeModMemLong16;
this.decodeModGrpWord = X86.decodeModGrpLong16;
this.decodeModRegWord = X86.modRegLong16;
this.decodeModMemWord = X86.modMemLong16;
this.decodeModGrpWord = X86.modGrpLong16;
} else {
this.decodeModRegWord = X86.decodeModRegLong32;
this.decodeModMemWord = X86.decodeModMemLong32;
this.decodeModGrpWord = X86.decodeModGrpLong32;
this.decodeModRegWord = X86.modRegLong32;
this.decodeModMemWord = X86.modMemLong32;
this.decodeModGrpWord = X86.modGrpLong32;
}
}
};
@ -1591,8 +1595,8 @@ X86CPU.prototype.addIntReturn = function(addr, fn)
/**
* checkIntReturn(addr)
*
* We check for possible "INT n" software interrupt returns in the cases of "IRET" (fnIRET), "RETF 2"
* (fnRETF) and "JMPF [DWORD]" (fnJMPFdw).
* We check for possible "INT n" software interrupt returns in the cases of "IRET" (helpIRET), "RETF 2"
* (helpRETF) and "JMPF [DWORD]" (fnJMPFdw).
*
* "JMPF [DWORD]" is an unfortunate choice that newer versions of DOS (as of at least 3.20, and probably
* earlier) employed in their INT 0x13 hooks; I would have preferred not making this call for that opcode.
@ -1718,7 +1722,7 @@ X86CPU.prototype.checkMemoryException = function(addr, nb, fWrite)
* Data access breakpoints are not faults; they must generate a trap at the end of the
* instruction, so we use the X86.INTFLAG.TRAP flag to generate the X86.EXCEPTION.DB_EXC trap.
*
* X86.fnFault.call(this, X86.EXCEPTION.DB_EXC);
* X86.helpFault.call(this, X86.EXCEPTION.DB_EXC);
*/
this.intFlags |= X86.INTFLAG.TRAP;
return;
@ -2285,16 +2289,24 @@ X86CPU.prototype.advanceIP = function(inc)
* fetch a byte from 06FC, which won't happen. I'm working around this for now by applying a -1
* fudge factor to the fault check below.
*/
var off = (this.regLIPLimit - this.regLIP)|0;
if (off < 0 && (this.regLIPLimit ^ this.regLIP) >= 0) {
if (DEBUG) {
/*
* There's no such thing as a GP fault on the 8086/8088, and I'm assuming that, on newer
* processors, when the segment limit is set to the maximum, it's OK for IP to wrap.
* TODO: This isn't DEBUG code, but it also isn't strictly necessary for properly written code,
* and it hurts performance. Since this effectively turns advanceIP() into a one-line function for
* non-DEBUG builds, it should automatically get inlined (either at compile-time by the Closure Compiler
* or at run-time by whatever JavaScript engine you're using).
*/
if (this.model <= X86.MODEL_8088 || this.segCS.limit == this.segCS.maskAddr) {
this.setIP(this.regLIP - this.segCS.base);
} else if (off < -1) { // fudge factor
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
var off = (this.regLIPLimit - this.regLIP)|0;
if (off < 0 && (this.regLIPLimit ^ this.regLIP) >= 0) {
/*
* There's no such thing as a GP fault on the 8086/8088, and I'm assuming that, on newer
* processors, when the segment limit is set to the maximum, it's OK for IP to wrap.
*/
if (this.model <= X86.MODEL_8088 || this.segCS.limit == this.segCS.maskAddr) {
this.setIP(this.regLIP - this.segCS.base);
} else if (off < -1) { // fudge factor
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
}
}
}
};
@ -2974,7 +2986,7 @@ X86CPU.prototype.checkIOPM = function(port, nPorts, fInput)
}
if (bitsPorts) {
if (this.messageEnabled(Messages.PORT)) this.printMessage("checkIOPM(" + str.toHexWord(port) + "," + nPorts + "," + (fInput? "input" : "output") + "): trapped", true, true);
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return false;
}
return true;
@ -3047,7 +3059,7 @@ X86CPU.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
* probeAddr(addr, size, fPhysical)
*
* Used by the Debugger to probe addresses without risk of triggering a page fault, and by internal
* functions, like fnCheckFault(), that must also avoid triggering faults, since they're not part of
* functions, like helpCheckFault(), that must also avoid triggering faults, since they're not part of
* standard CPU operation.
*
* Since originally written, I've also relaxed the requirement that the request be contained entirely
@ -3110,7 +3122,7 @@ X86CPU.prototype.probeAddr = function(addr, size, fPhysical)
* @param {number} addr is a linear address
* @return {number} byte (8-bit) value at that address
*/
X86CPU.prototype.getByte = function getByte(addr)
X86CPU.prototype.getByte = function(addr)
{
if (BACKTRACK) this.backTrack.btiMem0 = this.bus.readBackTrack(addr);
return this.aMemBlocks[(addr & this.nMemMask) >>> this.nBlockShift].readByte(addr & this.nBlockLimit, addr);
@ -3126,7 +3138,7 @@ X86CPU.prototype.getByte = function getByte(addr)
* @param {number} addr is a linear address
* @return {number} word (16-bit) value at that address
*/
X86CPU.prototype.getShort = function getShort(addr)
X86CPU.prototype.getShort = function(addr)
{
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nMemMask) >>> this.nBlockShift;
@ -3160,7 +3172,7 @@ X86CPU.prototype.getShort = function getShort(addr)
* @param {number} addr is a linear address
* @return {number} long (32-bit) value at that address
*/
X86CPU.prototype.getLong = function getLong(addr)
X86CPU.prototype.getLong = function(addr)
{
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nMemMask) >>> this.nBlockShift;
@ -3204,7 +3216,7 @@ X86CPU.prototype.getLong = function getLong(addr)
* @param {number} addr is a linear address
* @param {number} b is the byte (8-bit) value to write (which we truncate to 8 bits; required by opSTOSb)
*/
X86CPU.prototype.setByte = function setByte(addr, b)
X86CPU.prototype.setByte = function(addr, b)
{
if (BACKTRACK) this.bus.writeBackTrack(addr, this.backTrack.btiMem0);
this.aMemBlocks[(addr & this.nMemMask) >>> this.nBlockShift].writeByte(addr & this.nBlockLimit, b & 0xff, addr);
@ -3220,7 +3232,7 @@ X86CPU.prototype.setByte = function setByte(addr, b)
* @param {number} addr is a linear address
* @param {number} w is the word (16-bit) value to write (which we truncate to 16 bits to be safe)
*/
X86CPU.prototype.setShort = function setShort(addr, w)
X86CPU.prototype.setShort = function(addr, w)
{
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nMemMask) >>> this.nBlockShift;
@ -3253,7 +3265,7 @@ X86CPU.prototype.setShort = function setShort(addr, w)
* @param {number} addr is a linear address
* @param {number} l is the long (32-bit) value to write
*/
X86CPU.prototype.setLong = function setLong(addr, l)
X86CPU.prototype.setLong = function(addr, l)
{
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nMemMask) >>> this.nBlockShift;
@ -3825,7 +3837,7 @@ X86CPU.prototype.popWord = function()
if (this.model <= X86.MODEL_8088 || !this.segSS.fExpDown && this.segSS.limit == this.segSS.maskAddr || this.segSS.fExpDown && !this.segSS.limit) {
this.setSP((this.regLSP - this.segSS.base) & this.segSS.maskAddr);
} else if (off < -1) { // fudge factor
X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
}
}
return w;
@ -3871,7 +3883,7 @@ X86CPU.prototype.pushData = function(d, width, size)
this.setSP((regLSP - this.segSS.base) & this.segSS.maskAddr);
regLSP = this.regLSP;
} else {
X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
}
}
@ -3932,7 +3944,7 @@ X86CPU.prototype.pushWord = function(w)
this.setSP((regLSP - this.segSS.base) & this.segSS.maskAddr);
regLSP = this.regLSP;
} else {
X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
}
}
@ -4034,7 +4046,7 @@ X86CPU.prototype.checkINTR = function()
this.intFlags &= ~X86.INTFLAG.INTR;
if (nIDT >= 0) {
this.intFlags &= ~X86.INTFLAG.HALT;
X86.fnInterrupt.call(this, nIDT);
X86.helpInterrupt.call(this, nIDT);
return true;
}
}
@ -4044,7 +4056,7 @@ X86CPU.prototype.checkINTR = function()
if ((this.intFlags & X86.INTFLAG.TRAP)) {
this.intFlags &= ~X86.INTFLAG.TRAP;
if (I386 && this.model >= X86.MODEL_80386) this.regDR[6] |= X86.DR6.BS;
X86.fnInterrupt.call(this, X86.EXCEPTION.DB_EXC);
X86.helpInterrupt.call(this, X86.EXCEPTION.DB_EXC);
return true;
}
break;

View file

@ -186,9 +186,9 @@ X86.fnBOUND = function(dst, src)
* The INT 0x05 handler must be called with CS:IP pointing to the BOUND instruction.
*
* TODO: Determine the cycle cost when a BOUND exception is triggered, over and above nCyclesBound,
* and then call X86.fnFault(X86.EXCEPTION.BR_FAULT, null, nCycles).
* and then call X86.helpFault(X86.EXCEPTION.BR_FAULT, null, nCycles).
*/
X86.fnFault.call(this, X86.EXCEPTION.BR_FAULT);
X86.helpFault.call(this, X86.EXCEPTION.BR_FAULT);
}
this.opFlags |= X86.OPFLAG.NOWRITE;
return dst;
@ -546,13 +546,13 @@ X86.fnCALLFdw = function(dst, src)
return X86.fnGRPUndefined.call(this, dst, src);
}
/*
* Originally, we would snapshot regLSP into opLSP because fnCALLF() could trigger a segment fault,
* Originally, we would snapshot regLSP into opLSP because helpCALLF() could trigger a segment fault,
* but additionally, the stack segment could trigger either a segment fault or a page fault; indeed,
* any operation that performs multiple stack modifications must take this precaution and snapshot regLSP.
*/
this.opLSP = this.regLSP;
X86.fnCALLF.call(this, dst, this.getShort(this.regEA + this.sizeData));
X86.helpCALLF.call(this, dst, this.getShort(this.regEA + this.sizeData));
this.nStepCycles -= this.cycleCounts.nOpCyclesCallDM;
this.opFlags |= X86.OPFLAG.NOWRITE;
@ -640,7 +640,7 @@ X86.fnDIVb = function(dst, src)
* Detect zero divisor
*/
if (!dst) {
X86.fnDivOverflow.call(this);
X86.helpDIVOverflow.call(this);
return dst;
}
@ -649,7 +649,7 @@ X86.fnDIVb = function(dst, src)
*/
var result = ((src = this.regEAX & 0xffff) / dst);
if (result > 0xff) {
X86.fnDivOverflow.call(this);
X86.helpDIVOverflow.call(this);
return dst;
}
@ -676,7 +676,7 @@ X86.fnDIVw = function(dst, src)
* Detect zero divisor
*/
if (!dst) {
X86.fnDivOverflow.call(this);
X86.helpDIVOverflow.call(this);
return dst;
}
/*
@ -689,15 +689,15 @@ X86.fnDIVw = function(dst, src)
src = (this.regEDX & 0xffff) * 0x10000 + (this.regEAX & 0xffff);
var result = (src / dst);
if (result >= 0x10000) {
X86.fnDivOverflow.call(this);
X86.helpDIVOverflow.call(this);
return dst;
}
this.regMDLo = (result & 0xffff);
this.regMDHi = (src % dst) & 0xffff;
}
else {
if (!X86.fnDIV32.call(this, this.regEAX, this.regEDX, dst)) {
X86.fnDivOverflow.call(this);
if (!X86.helpDIV32.call(this, this.regEAX, this.regEDX, dst)) {
X86.helpDIVOverflow.call(this);
return dst;
}
this.regMDLo |= 0;
@ -750,7 +750,7 @@ X86.fnGRPFault = function(dst, src)
if (this.model < X86.MODEL_80186) {
return X86.fnGRPUndefined.call(this, dst, src);
}
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return dst;
};
@ -796,7 +796,7 @@ X86.fnIDIVb = function(dst, src)
* Detect zero divisor
*/
if (!dst) {
X86.fnDivOverflow.call(this);
X86.helpDIVOverflow.call(this);
return dst;
}
@ -816,7 +816,7 @@ X86.fnIDIVb = function(dst, src)
* -32768 and -128 in decimal, respectively)."
*/
if (result != ((result << 24) >> 24) || this.model == X86.MODEL_8086 && result == -128) {
X86.fnDivOverflow.call(this);
X86.helpDIVOverflow.call(this);
return dst;
}
@ -843,7 +843,7 @@ X86.fnIDIVw = function(dst, src)
* Detect zero divisor
*/
if (!dst) {
X86.fnDivOverflow.call(this);
X86.helpDIVOverflow.call(this);
return dst;
}
@ -863,7 +863,7 @@ X86.fnIDIVw = function(dst, src)
* -32768 and -128 in decimal, respectively)."
*/
if (result != ((result << 16) >> 16) || this.model == X86.MODEL_8086 && result == -32768) {
X86.fnDivOverflow.call(this);
X86.helpDIVOverflow.call(this);
return dst;
}
@ -871,8 +871,8 @@ X86.fnIDIVw = function(dst, src)
this.regMDHi = (src % div) & 0xffff;
}
else {
if (!X86.fnIDIV32.call(this, this.regEAX, this.regEDX, dst)) {
X86.fnDivOverflow.call(this);
if (!X86.helpIDIV32.call(this, this.regEAX, this.regEDX, dst)) {
X86.helpDIVOverflow.call(this);
return dst;
}
this.regMDLo |= 0;
@ -1558,23 +1558,10 @@ X86.fnMOV = function(dst, src)
return src;
};
/**
* fnMOVX(dst, src)
*
* @this {X86CPU}
* @param {number} dst (current value, ignored)
* @param {number} src (new value)
* @return {number} dst (updated value, from src)
*/
X86.fnMOVX = function(dst, src)
{
return src;
};
/**
* fnMOVXb(dst, src)
*
* Helper for opMOVSXb() and opMOVZXb()
* Helper for opMOVSXb() and opMOVZXb() (which also take care of updating nStepCycles, so we don't have to)
*
* @this {X86CPU}
* @param {number} dst (current value, ignored)
@ -1595,7 +1582,8 @@ X86.fnMOVXb = function(dst, src)
* 110: DH -> 110: SI
* 111: BH -> 111: DI
*/
var reg = (this.bModRM & 0x38) >> 3;
var reg = (this.bModRM >> 3) & 0x7;
switch(reg) {
case 0x4:
this.regXX = this.regEAX;
@ -1613,6 +1601,21 @@ X86.fnMOVXb = function(dst, src)
return src;
};
/**
* fnMOVXw(dst, src)
*
* Helper for opMOVSXw() and opMOVZXw() (which also take care of updating nStepCycles, so we don't have to)
*
* @this {X86CPU}
* @param {number} dst (current value, ignored)
* @param {number} src (new value)
* @return {number} dst (updated value, from src)
*/
X86.fnMOVXw = function(dst, src)
{
return src;
};
/**
* fnMOVn(dst, src)
*
@ -1627,64 +1630,6 @@ X86.fnMOVn = function(dst, src)
return src;
};
/**
* fnMOVwsr(dst, src)
*
* @this {X86CPU}
* @param {number} dst (current value, ignored)
* @param {number} src (new value)
* @return {number} dst
*/
X86.fnMOVwsr = function(dst, src)
{
var reg = (this.bModRM & 0x38) >> 3;
switch (reg) {
case 0x0:
src = this.segES.sel;
break;
case 0x1:
src = this.segCS.sel;
break;
case 0x2:
src = this.segSS.sel;
break;
case 0x3:
src = this.segDS.sel;
break;
case 0x4:
if (I386 && this.model >= X86.MODEL_80386) {
src = this.segFS.sel;
break;
}
X86.opInvalid.call(this);
src = dst;
break;
case 0x5:
if (I386 && this.model >= X86.MODEL_80386) {
src = this.segGS.sel;
break;
}
/* falls through */
default:
X86.opInvalid.call(this);
src = dst;
break;
}
/*
* When a 32-bit OPERAND size is in effect, segment register writes via opMOVwsr() must write 32 bits
* (zero-extended) if the destination is a register, but only 16 bits if the destination is memory,
* hence the setDataSize(2) below.
*
* The only other caller, opMOVrc(), is not affected, because it writes only to register destinations.
*/
if (this.regEAWrite !== X86.ADDR_INVALID) {
this.setDataSize(2);
}
return X86.fnMOV.call(this, dst, src);
};
/**
* fnMOVsrw(dst, src)
*
@ -1736,7 +1681,71 @@ X86.fnMOVsrw = function(dst, src)
}
break;
}
return src;
/*
* We could just return src, but nStepCycles needs to be updated, too.
*/
return X86.fnMOV.call(this, dst, src);
};
/**
* fnMOVwsr(dst, src)
*
* @this {X86CPU}
* @param {number} dst (current value, ignored)
* @param {number} src (new value)
* @return {number} dst
*/
X86.fnMOVwsr = function(dst, src)
{
var reg = (this.bModRM >> 3) & 0x7;
switch (reg) {
case 0x0:
src = this.segES.sel;
break;
case 0x1:
src = this.segCS.sel;
break;
case 0x2:
src = this.segSS.sel;
break;
case 0x3:
src = this.segDS.sel;
break;
case 0x4:
if (I386 && this.model >= X86.MODEL_80386) {
src = this.segFS.sel;
break;
}
X86.opInvalid.call(this);
src = dst;
break;
case 0x5:
if (I386 && this.model >= X86.MODEL_80386) {
src = this.segGS.sel;
break;
}
/* falls through */
default:
X86.opInvalid.call(this);
src = dst;
break;
}
/*
* When a 32-bit OPERAND size is in effect, segment register writes via opMOVwsr() must write 32 bits
* (zero-extended) if the destination is a register, but only 16 bits if the destination is memory,
* hence the setDataSize(2) below.
*
* The only other caller, opMOVrc(), is not affected, because it writes only to register destinations.
*/
if (this.regEAWrite !== X86.ADDR_INVALID) {
this.setDataSize(2);
}
/*
* We could just return src, but nStepCycles needs to be updated, too.
*/
return X86.fnMOV.call(this, dst, src);
};
/**
@ -2751,7 +2760,7 @@ X86.fnSHLd = function(dst, src)
*/
X86.fnSHLDwi = function(dst, src)
{
return X86.fnSHLDw.call(this, dst, src, this.getIPByte());
return X86.helpSHLDw.call(this, dst, src, this.getIPByte());
};
/**
@ -2764,7 +2773,7 @@ X86.fnSHLDwi = function(dst, src)
*/
X86.fnSHLDdi = function(dst, src)
{
return X86.fnSHLDd.call(this, dst, src, this.getIPByte());
return X86.helpSHLDd.call(this, dst, src, this.getIPByte());
};
/**
@ -2777,7 +2786,7 @@ X86.fnSHLDdi = function(dst, src)
*/
X86.fnSHLDwCL = function(dst, src)
{
return X86.fnSHLDw.call(this, dst, src, this.regECX & 0x1f);
return X86.helpSHLDw.call(this, dst, src, this.regECX & 0x1f);
};
/**
@ -2790,7 +2799,7 @@ X86.fnSHLDwCL = function(dst, src)
*/
X86.fnSHLDdCL = function(dst, src)
{
return X86.fnSHLDd.call(this, dst, src, this.regECX & 0x1f);
return X86.helpSHLDd.call(this, dst, src, this.regECX & 0x1f);
};
/**
@ -2860,7 +2869,7 @@ X86.fnSHRd = function(dst, src)
*/
X86.fnSHRDwi = function(dst, src)
{
return X86.fnSHRDw.call(this, dst, src, this.getIPByte());
return X86.helpSHRDw.call(this, dst, src, this.getIPByte());
};
/**
@ -2873,7 +2882,7 @@ X86.fnSHRDwi = function(dst, src)
*/
X86.fnSHRDdi = function(dst, src)
{
return X86.fnSHRDd.call(this, dst, src, this.getIPByte());
return X86.helpSHRDd.call(this, dst, src, this.getIPByte());
};
/**
@ -2886,7 +2895,7 @@ X86.fnSHRDdi = function(dst, src)
*/
X86.fnSHRDwCL = function(dst, src)
{
return X86.fnSHRDw.call(this, dst, src, this.regECX & 0x1f);
return X86.helpSHRDw.call(this, dst, src, this.regECX & 0x1f);
};
/**
@ -2899,7 +2908,7 @@ X86.fnSHRDwCL = function(dst, src)
*/
X86.fnSHRDdCL = function(dst, src)
{
return X86.fnSHRDd.call(this, dst, src, this.regECX & 0x1f);
return X86.helpSHRDd.call(this, dst, src, this.regECX & 0x1f);
};
/**

View file

@ -39,14 +39,14 @@ if (NODE) {
}
/**
* fnAdd64(dst, src)
* helpAdd64(dst, src)
*
* Adds src to dst.
*
* @param {Array} dst is a 64-bit value
* @param {Array} src is a 64-bit value
*/
X86.fnAdd64 = function(dst, src)
X86.helpAdd64 = function(dst, src)
{
dst[0] += src[0];
dst[1] += src[1];
@ -57,7 +57,7 @@ X86.fnAdd64 = function(dst, src)
};
/**
* fnCmp64(dst, src)
* helpCmp64(dst, src)
*
* Compares dst to src, by computing dst - src.
*
@ -65,7 +65,7 @@ X86.fnAdd64 = function(dst, src)
* @param {Array} src is a 64-bit value
* @return {number} > 0 if dst > src, == 0 if dst == src, < 0 if dst < src
*/
X86.fnCmp64 = function(dst, src)
X86.helpCmp64 = function(dst, src)
{
var result = dst[1] - src[1];
if (!result) result = dst[0] - src[0];
@ -73,24 +73,24 @@ X86.fnCmp64 = function(dst, src)
};
/**
* fnSet64(lo, hi)
* helpSet64(lo, hi)
*
* @param {number} lo
* @param {number} hi
*/
X86.fnSet64 = function(lo, hi)
X86.helpSet64 = function(lo, hi)
{
return [lo >>> 0, hi >>> 0];
};
/**
* fnShr64(dst)
* helpShr64(dst)
*
* Shifts dst right one bit.
*
* @param {Array} dst is a 64-bit value
*/
X86.fnShr64 = function(dst)
X86.helpShr64 = function(dst)
{
dst[0] >>>= 1;
if (dst[1] & 0x1) {
@ -100,14 +100,14 @@ X86.fnShr64 = function(dst)
};
/**
* fnSub64(dst, src)
* helpSub64(dst, src)
*
* Subtracts src from dst.
*
* @param {Array} dst is a 64-bit value
* @param {Array} src is a 64-bit value
*/
X86.fnSub64 = function(dst, src)
X86.helpSub64 = function(dst, src)
{
dst[0] -= src[0];
dst[1] -= src[1];
@ -118,13 +118,13 @@ X86.fnSub64 = function(dst, src)
};
/**
* fnDECr(w)
* helpDECreg(w)
*
* @this {X86CPU}
* @param {number} w
* @return {number}
*/
X86.fnDECr = function(w)
X86.helpDECreg = function(w)
{
var result = (w - 1)|0;
this.setArithResult(w, 1, result, this.typeData | X86.RESULT.NOTCF, true);
@ -133,7 +133,7 @@ X86.fnDECr = function(w)
};
/**
* fnDIV32(dstLo, dstHi, src)
* helpDIV32(dstLo, dstHi, src)
*
* This sets regMDLo to dstHi:dstLo / src, and regMDHi to dstHi:dstLo % src; all inputs are treated as unsigned.
*
@ -145,7 +145,7 @@ X86.fnDECr = function(w)
* @param {number} src (32-bit divisor)
* @return {boolean} true if successful, false if overflow (ie, the divisor was either zero or too small)
*/
X86.fnDIV32 = function(dstLo, dstHi, src)
X86.helpDIV32 = function(dstLo, dstHi, src)
{
src >>>= 0;
if (!src || src <= (dstHi >>> 0)) {
@ -154,19 +154,19 @@ X86.fnDIV32 = function(dstLo, dstHi, src)
var result = 0, bit = 1;
var div = X86.fnSet64(src, 0);
var rem = X86.fnSet64(dstLo, dstHi);
var div = X86.helpSet64(src, 0);
var rem = X86.helpSet64(dstLo, dstHi);
while (X86.fnCmp64(rem, div) > 0) {
X86.fnAdd64(div, div);
while (X86.helpCmp64(rem, div) > 0) {
X86.helpAdd64(div, div);
bit += bit;
}
do {
if (X86.fnCmp64(rem, div) >= 0) {
X86.fnSub64(rem, div);
if (X86.helpCmp64(rem, div) >= 0) {
X86.helpSub64(rem, div);
result += bit;
}
X86.fnShr64(div);
X86.helpShr64(div);
bit /= 2;
} while (bit >= 1);
@ -178,7 +178,7 @@ X86.fnDIV32 = function(dstLo, dstHi, src)
};
/**
* fnIDIV32(dstLo, dstHi, src)
* helpIDIV32(dstLo, dstHi, src)
*
* This sets regMDLo to dstHi:dstLo / src, and regMDHi to dstHi:dstLo % src; all inputs are treated as signed.
*
@ -190,7 +190,7 @@ X86.fnDIV32 = function(dstLo, dstHi, src)
* @param {number} src (32-bit divisor)
* @return {boolean} true if successful, false if overflow (ie, the divisor was either zero or too small)
*/
X86.fnIDIV32 = function(dstLo, dstHi, src)
X86.helpIDIV32 = function(dstLo, dstHi, src)
{
var bNegLo = 0, bNegHi = 0;
/*
@ -212,7 +212,7 @@ X86.fnIDIV32 = function(dstLo, dstHi, src)
bNegHi = 1;
bNegLo = 1 - bNegLo;
}
if (!X86.fnDIV32.call(this, dstLo, dstHi, src) || this.regMDLo > 0x7fffffff+bNegLo || this.regMDHi > 0x7fffffff+bNegHi) {
if (!X86.helpDIV32.call(this, dstLo, dstHi, src) || this.regMDLo > 0x7fffffff+bNegLo || this.regMDHi > 0x7fffffff+bNegHi) {
return false;
}
if (bNegLo) this.regMDLo = -this.regMDLo;
@ -221,13 +221,13 @@ X86.fnIDIV32 = function(dstLo, dstHi, src)
};
/**
* fnINCr(w)
* helpINCreg(w)
*
* @this {X86CPU}
* @param {number} w
* @return {number}
*/
X86.fnINCr = function(w)
X86.helpINCreg = function(w)
{
var result = (w + 1)|0;
this.setArithResult(w, 1, result, this.typeData | X86.RESULT.NOTCF);
@ -236,7 +236,7 @@ X86.fnINCr = function(w)
};
/**
* fnLCR0(l)
* helpLoadCR0(l)
*
* This is called by an 80386 control instruction (ie, MOV CR0,reg).
*
@ -245,7 +245,7 @@ X86.fnINCr = function(w)
* @this {X86CPU}
* @param {number} l
*/
X86.fnLCR0 = function(l)
X86.helpLoadCR0 = function(l)
{
this.regCR0 = l;
this.setProtMode();
@ -261,14 +261,14 @@ X86.fnLCR0 = function(l)
};
/**
* fnLCR3(l)
* helpLoadCR3(l)
*
* This is called by an 80386 control instruction (ie, MOV CR3,reg) or an 80386 task switch.
*
* @this {X86CPU}
* @param {number} l
*/
X86.fnLCR3 = function(l)
X86.helpLoadCR3 = function(l)
{
this.regCR3 = l;
/*
@ -280,12 +280,12 @@ X86.fnLCR3 = function(l)
};
/**
* fnSETcc()
* helpSETcc()
*
* @this {X86CPU}
* @param {function(number,number)} fnSet
*/
X86.fnSETcc = function(fnSet)
X86.helpSETcc = function(fnSet)
{
this.opFlags |= X86.OPFLAG.NOREAD;
this.decodeModMemByte.call(this, fnSet);
@ -293,7 +293,7 @@ X86.fnSETcc = function(fnSet)
};
/**
* fnSHLDw(dst, src, count)
* helpSHLDw(dst, src, count)
*
* @this {X86CPU}
* @param {number} dst
@ -301,7 +301,7 @@ X86.fnSETcc = function(fnSet)
* @param {number} count (0-31)
* @return {number}
*/
X86.fnSHLDw = function(dst, src, count)
X86.helpSHLDw = function(dst, src, count)
{
if (count) {
if (count > 16) {
@ -316,7 +316,7 @@ X86.fnSHLDw = function(dst, src, count)
};
/**
* fnSHLDd(dst, src, count)
* helpSHLDd(dst, src, count)
*
* @this {X86CPU}
* @param {number} dst
@ -324,7 +324,7 @@ X86.fnSHLDw = function(dst, src, count)
* @param {number} count
* @return {number}
*/
X86.fnSHLDd = function(dst, src, count)
X86.helpSHLDd = function(dst, src, count)
{
if (count) {
var carry = dst << (count - 1);
@ -335,7 +335,7 @@ X86.fnSHLDd = function(dst, src, count)
};
/**
* fnSHRDw(dst, src, count)
* helpSHRDw(dst, src, count)
*
* @this {X86CPU}
* @param {number} dst
@ -343,7 +343,7 @@ X86.fnSHLDd = function(dst, src, count)
* @param {number} count (0-31)
* @return {number}
*/
X86.fnSHRDw = function(dst, src, count)
X86.helpSHRDw = function(dst, src, count)
{
if (count) {
if (count > 16) {
@ -358,7 +358,7 @@ X86.fnSHRDw = function(dst, src, count)
};
/**
* fnSHRDd(dst, src, count)
* helpSHRDd(dst, src, count)
*
* @this {X86CPU}
* @param {number} dst
@ -366,7 +366,7 @@ X86.fnSHRDw = function(dst, src, count)
* @param {number} count
* @return {number}
*/
X86.fnSHRDd = function(dst, src, count)
X86.helpSHRDd = function(dst, src, count)
{
if (count) {
var carry = dst >>> (count - 1);
@ -377,24 +377,24 @@ X86.fnSHRDd = function(dst, src, count)
};
/**
* fnSRC1()
* helpSRC1()
*
* @this {X86CPU}
* @return {number}
*/
X86.fnSRC1 = function()
X86.helpSRC1 = function()
{
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 2 : this.cycleCounts.nOpCyclesShift1M);
return 1;
};
/**
* fnSRCCL()
* helpSRCCL()
*
* @this {X86CPU}
* @return {number}
*/
X86.fnSRCCL = function()
X86.helpSRCCL = function()
{
var count = this.regECX & 0xff;
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesShiftCR : this.cycleCounts.nOpCyclesShiftCM) + (count << this.cycleCounts.nOpCyclesShiftCS);
@ -402,12 +402,12 @@ X86.fnSRCCL = function()
};
/**
* fnSRCByte()
* helpSRCByte()
*
* @this {X86CPU}
* @return {number}
*/
X86.fnSRCByte = function()
X86.helpSRCByte = function()
{
var count = this.getIPByte();
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesShiftCR : this.cycleCounts.nOpCyclesShiftCM) + (count << this.cycleCounts.nOpCyclesShiftCS);
@ -415,18 +415,18 @@ X86.fnSRCByte = function()
};
/**
* fnSRCNone()
* helpSRCNone()
*
* @this {X86CPU}
* @return {number|null}
*/
X86.fnSRCNone = function()
X86.helpSRCNone = function()
{
return null;
};
/**
* fnSRCxx()
* helpSRCxx()
*
* This is used by opPOPmw(), because the actual pop must occur BEFORE the effective address (EA)
* calculation. So opPOPmw() does the pop, saves the popped value in regXX, and this passes src function
@ -435,13 +435,13 @@ X86.fnSRCNone = function()
* @this {X86CPU}
* @return {number} regXX
*/
X86.fnSRCxx = function()
X86.helpSRCxx = function()
{
return this.regXX;
};
/**
* fnCALLF(off, sel)
* helpCALLF(off, sel)
*
* For protected-mode, this function must attempt to load the new code segment first, because if the new segment
* requires a change in privilege level, the return address must be pushed on the NEW stack, not the current stack.
@ -459,12 +459,12 @@ X86.fnSRCxx = function()
* @param {number} off
* @param {number} sel
*/
X86.fnCALLF = function(off, sel)
X86.helpCALLF = function(off, sel)
{
/*
* Since we always push the return address AFTER calling setCSIP(), and since either push could trigger a
* fault (eg, segment fault, page fault, etc), we must not only snapshot regLSP into opLSP, but also the
* current CS into opCS, so that fnFault() can always make CALLF restartable. Ditto for opSS and the SS register.
* current CS into opCS, so that helpFault() can always make CALLF restartable. Ditto for opSS and the SS register.
*/
this.opCS = this.getCS();
this.opSS = this.getSS();
@ -485,7 +485,7 @@ X86.fnCALLF = function(off, sel)
};
/**
* fnINT(nIDT, nError, nCycles)
* helpINT(nIDT, nError, nCycles)
*
* NOTE: We no longer use setCSIP(), because it always loads the new CS using segCS.load(), which only knows
* how to load GDT and LDT descriptors, whereas interrupts must use setCS.loadIDT(), which deals exclusively
@ -496,7 +496,7 @@ X86.fnCALLF = function(off, sel)
* @param {number|null} [nError]
* @param {number} [nCycles] (in addition to the default of nOpCyclesInt)
*/
X86.fnINT = function(nIDT, nError, nCycles)
X86.helpINT = function(nIDT, nError, nCycles)
{
/*
* TODO: We assess the cycle cost up front, because otherwise, if loadIDT() fails, no cost may be assessed.
@ -509,10 +509,10 @@ X86.fnINT = function(nIDT, nError, nCycles)
if (addr !== X86.ADDR_INVALID) {
/*
* TODO: Determine if we should use pushData() instead of pushWord() for oldCS and nError, to deal with
* the same 32-bit 80386 compatibility issue that fnCALLF(), opPUSHCS(), et al must deal with; namely, that
* the same 32-bit 80386 compatibility issue that helpCALLF(), opPUSHCS(), et al must deal with; namely, that
* 32-bit segment register writes (and, reportedly, 32-bit error codes) don't modify the upper 16 bits.
*
* Also, note that fnCALLF() is using the OPERAND size in effect *before* CS is loaded, whereas here we're
* Also, note that helpCALLF() is using the OPERAND size in effect *before* CS is loaded, whereas here we're
* using the OPERAND size in effect *after* CS is loaded. Is that correct? And does an explicit OPERAND
* size override on an "INT" instruction have any effect on that behavior? Is that even allowed?
*/
@ -526,11 +526,11 @@ X86.fnINT = function(nIDT, nError, nCycles)
};
/**
* fnIRET()
* helpIRET()
*
* @this {X86CPU}
*/
X86.fnIRET = function()
X86.helpIRET = function()
{
/*
* Originally, we would snapshot regLSP into opLSP because newCS could trigger a segment fault,
@ -615,7 +615,7 @@ X86.fnIRET = function()
};
/**
* fnRETF(n)
* helpRETF(n)
*
* For protected-mode, this function must pop any arguments off the current stack AND whatever stack
* we may have switched to; setCSIP() returns true if a stack switch occurred, false if not, and null
@ -624,7 +624,7 @@ X86.fnIRET = function()
* @this {X86CPU}
* @param {number} n
*/
X86.fnRETF = function(n)
X86.helpRETF = function(n)
{
/*
* Originally, we would snapshot regLSP into opLSP because newCS could trigger a segment fault,
@ -669,11 +669,11 @@ X86.fnRETF = function(n)
};
/**
* fnDivOverflow()
* helpDIVOverflow()
*
* @this {X86CPU}
*/
X86.fnDivOverflow = function()
X86.helpDIVOverflow = function()
{
/*
* Divide error exceptions are traps on the 8086 and faults on later processors. I question the value of that
@ -685,14 +685,14 @@ X86.fnDivOverflow = function()
* TODO: Determine the proper cycle cost.
*/
if (this.model == X86.MODEL_8086) {
X86.fnTrap.call(this, X86.EXCEPTION.DE_EXC, 2);
X86.helpTrap.call(this, X86.EXCEPTION.DE_EXC, 2);
} else {
X86.fnFault.call(this, X86.EXCEPTION.DE_EXC, null, 2);
X86.helpFault.call(this, X86.EXCEPTION.DE_EXC, null, 2);
}
};
/**
* fnInterrupt(nIDT, nCycles)
* helpInterrupt(nIDT, nCycles)
*
* Helper to dispatch external interrupts. nCycles defaults to 11 for the 8086/8088
* if no alternate value is specified.
@ -701,15 +701,15 @@ X86.fnDivOverflow = function()
* @param {number} nIDT
* @param {number} [nCycles] (number of cycles in addition to the default of nOpCyclesInt)
*/
X86.fnInterrupt = function(nIDT, nCycles)
X86.helpInterrupt = function(nIDT, nCycles)
{
this.nFault = nIDT;
if (nCycles === undefined) nCycles = 11;
X86.fnINT.call(this, nIDT, null, nCycles);
X86.helpINT.call(this, nIDT, null, nCycles);
};
/**
* fnTrap(nIDT, nCycles)
* helpTrap(nIDT, nCycles)
*
* Helper to dispatch traps (ie, exceptions that occur AFTER the instruction, with NO error code)
*
@ -717,24 +717,24 @@ X86.fnInterrupt = function(nIDT, nCycles)
* @param {number} nIDT
* @param {number} [nCycles] (number of cycles in addition to the default of nOpCyclesInt)
*/
X86.fnTrap = function(nIDT, nCycles)
X86.helpTrap = function(nIDT, nCycles)
{
this.nFault = -1;
X86.fnINT.call(this, nIDT, null, nCycles);
X86.helpINT.call(this, nIDT, null, nCycles);
};
/**
* fnFault(nFault, nError, nCycles, fHalt)
* helpFault(nFault, nError, nCycles, fHalt)
*
* Helper to dispatch faults (ie, exceptions that occur DURING an instruction and MAY generate an error code)
*
* @this {X86CPU}
* @param {number} nFault
* @param {number|null} [nError] (if omitted, no error code will be pushed)
* @param {number} [nCycles] cycle count to pass through to fnINT(), if any
* @param {number} [nCycles] cycle count to pass through to helpINT(), if any
* @param {boolean} [fHalt] (true to halt the CPU, false to not, undefined if "it depends")
*/
X86.fnFault = function(nFault, nError, nCycles, fHalt)
X86.helpFault = function(nFault, nError, nCycles, fHalt)
{
var fDispatch = false;
@ -793,9 +793,9 @@ X86.fnFault = function(nFault, nError, nCycles, fHalt)
}
}
if (X86.fnCheckFault.call(this, nFault, nError, fHalt)) {
if (X86.helpCheckFault.call(this, nFault, nError, fHalt)) {
/*
* If this is a fault that would normally be dispatched BUT fnCheckFault() wants us to halt,
* If this is a fault that would normally be dispatched BUT helpCheckFault() wants us to halt,
* then we throw a bogus fault number (-1), simply to interrupt the current instruction in exactly
* the same way that a dispatched fault would interrupt it.
*/
@ -805,7 +805,7 @@ X86.fnFault = function(nFault, nError, nCycles, fHalt)
if (fDispatch) {
this.nFault = nFault;
X86.fnINT.call(this, nFault, nError, nCycles);
X86.helpINT.call(this, nFault, nError, nCycles);
/*
* REP'eated instructions that rewind regLIP to opLIP used to screw up this dispatch,
@ -850,7 +850,7 @@ X86.fnFault = function(nFault, nError, nCycles, fHalt)
};
/**
* fnPageFault(addr, fPresent, fWrite)
* helpPageFault(addr, fPresent, fWrite)
*
* Helper to dispatch page faults.
*
@ -859,18 +859,18 @@ X86.fnFault = function(nFault, nError, nCycles, fHalt)
* @param {boolean} fPresent
* @param {boolean} fWrite
*/
X86.fnPageFault = function(addr, fPresent, fWrite)
X86.helpPageFault = function(addr, fPresent, fWrite)
{
this.regCR2 = addr;
var nError = 0;
if (fPresent) nError |= X86.PTE.PRESENT;
if (fWrite) nError |= X86.PTE.READWRITE;
if (this.nCPL == 3) nError |= X86.PTE.USER;
X86.fnFault.call(this, X86.EXCEPTION.PF_FAULT, nError);
X86.helpFault.call(this, X86.EXCEPTION.PF_FAULT, nError);
};
/**
* fnCheckFault(nFault, nError, fHalt)
* helpCheckFault(nFault, nError, fHalt)
*
* Aside from giving the Debugger an opportunity to report every fault, this also gives us the ability to
* halt exception processing in tracks: return true to prevent the fault handler from being dispatched.
@ -886,7 +886,7 @@ X86.fnPageFault = function(addr, fPresent, fWrite)
* @param {boolean} [fHalt] (true to halt the CPU, false to not, undefined if "it depends")
* @return {boolean|undefined} true to block the fault (often desirable when fHalt is true), otherwise dispatch it
*/
X86.fnCheckFault = function(nFault, nError, fHalt)
X86.helpCheckFault = function(nFault, nError, fHalt)
{
var bitsMessage = Messages.FAULT;

View file

@ -37,12 +37,12 @@ if (NODE) {
}
/**
* decodeModRegByte16(fn)
* modRegByte16(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModRegByte16 = function(fn)
X86.modRegByte16 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -178,7 +178,7 @@ X86.decodeModRegByte16 = function(fn)
break;
default:
src = 0;
this.assert(false, "decodeModRegByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modRegByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -253,12 +253,12 @@ X86.decodeModRegByte16 = function(fn)
};
/**
* decodeModMemByte16(fn)
* modMemByte16(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModMemByte16 = function(fn)
X86.modMemByte16 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -386,7 +386,7 @@ X86.decodeModMemByte16 = function(fn)
break;
default:
dst = 0;
this.assert(false, "decodeModMemByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modMemByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -511,19 +511,19 @@ X86.decodeModMemByte16 = function(fn)
if (BACKTRACK) this.backTrack.btiBH = this.backTrack.btiEALo;
break;
default:
this.assert(false, "decodeModMemByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modMemByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
};
/**
* decodeModGrpByte16(afnGrp, fnSrc)
* modGrpByte16(afnGrp, fnSrc)
*
* @this {X86CPU}
* @param {Array.<function(number,number)>} afnGrp
* @param {function()} fnSrc
*/
X86.decodeModGrpByte16 = function(afnGrp, fnSrc) {
X86.modGrpByte16 = function(afnGrp, fnSrc) {
var dst;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -650,7 +650,7 @@ X86.decodeModGrpByte16 = function(afnGrp, fnSrc) {
break;
default:
dst = 0;
this.assert(false, "decodeModGrpByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modGrpByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -732,12 +732,12 @@ X86.decodeModGrpByte16 = function(afnGrp, fnSrc) {
};
/**
* decodeModRegShort16(fn)
* modRegShort16(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModRegShort16 = function(fn)
X86.modRegShort16 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -889,7 +889,7 @@ X86.decodeModRegShort16 = function(fn)
break;
default:
src = 0;
this.assert(false, "decodeModRegShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modRegShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -977,12 +977,12 @@ X86.decodeModRegShort16 = function(fn)
};
/**
* decodeModMemShort16(fn)
* modMemShort16(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModMemShort16 = function(fn)
X86.modMemShort16 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -1110,7 +1110,7 @@ X86.decodeModMemShort16 = function(fn)
break;
default:
dst = 0;
this.assert(false, "decodeModMemShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modMemShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -1219,64 +1219,64 @@ X86.decodeModMemShort16 = function(fn)
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
break;
case 0xC0:
this.regEAX = w;
this.regEAX = (this.regEAX & ~0xffff) | w;
if (BACKTRACK) {
this.backTrack.btiAL = this.backTrack.btiEALo; this.backTrack.btiAH = this.backTrack.btiEAHi;
}
break;
case 0xC1:
this.regECX = w;
this.regECX = (this.regECX & ~0xffff) | w;
if (BACKTRACK) {
this.backTrack.btiCL = this.backTrack.btiEALo; this.backTrack.btiCH = this.backTrack.btiEAHi;
}
break;
case 0xC2:
this.regEDX = w;
this.regEDX = (this.regEDX & ~0xffff) | w;
if (BACKTRACK) {
this.backTrack.btiDL = this.backTrack.btiEALo; this.backTrack.btiDH = this.backTrack.btiEAHi;
}
break;
case 0xC3:
this.regEBX = w;
this.regEBX = (this.regEBX & ~0xffff) | w;
if (BACKTRACK) {
this.backTrack.btiBL = this.backTrack.btiEALo; this.backTrack.btiBH = this.backTrack.btiEAHi;
}
break;
case 0xC4:
this.setSP(w);
this.setSP((this.getSP() & ~0xffff) | w);
break;
case 0xC5:
this.regEBP = w;
this.regEBP = (this.regEBP & ~0xffff) | w;
if (BACKTRACK) {
this.backTrack.btiBPLo = this.backTrack.btiEALo; this.backTrack.btiBPHi = this.backTrack.btiEAHi;
}
break;
case 0xC6:
this.regESI = w;
this.regESI = (this.regESI & ~0xffff) | w;
if (BACKTRACK) {
this.backTrack.btiSILo = this.backTrack.btiEALo; this.backTrack.btiSIHi = this.backTrack.btiEAHi;
}
break;
case 0xC7:
this.regEDI = w;
this.regEDI = (this.regEDI & ~0xffff) | w;
if (BACKTRACK) {
this.backTrack.btiDILo = this.backTrack.btiEALo; this.backTrack.btiDIHi = this.backTrack.btiEAHi;
}
break;
default:
this.assert(false, "decodeModMemShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modMemShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
};
/**
* decodeModGrpShort16(afnGrp, fnSrc)
* modGrpShort16(afnGrp, fnSrc)
*
* @this {X86CPU}
* @param {Array.<function(number,number)>} afnGrp
* @param {function()} fnSrc
*/
X86.decodeModGrpShort16 = function(afnGrp, fnSrc) {
X86.modGrpShort16 = function(afnGrp, fnSrc) {
var dst;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -1403,7 +1403,7 @@ X86.decodeModGrpShort16 = function(afnGrp, fnSrc) {
break;
default:
dst = 0;
this.assert(false, "decodeModGrpShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modGrpShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -1485,12 +1485,12 @@ X86.decodeModGrpShort16 = function(afnGrp, fnSrc) {
};
/**
* decodeModRegLong16(fn)
* modRegLong16(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModRegLong16 = function(fn)
X86.modRegLong16 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -1642,7 +1642,7 @@ X86.decodeModRegLong16 = function(fn)
break;
default:
src = 0;
this.assert(false, "decodeModRegLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modRegLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -1730,12 +1730,12 @@ X86.decodeModRegLong16 = function(fn)
};
/**
* decodeModMemLong16(fn)
* modMemLong16(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModMemLong16 = function(fn)
X86.modMemLong16 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -1863,7 +1863,7 @@ X86.decodeModMemLong16 = function(fn)
break;
default:
dst = 0;
this.assert(false, "decodeModMemLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modMemLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -2017,19 +2017,19 @@ X86.decodeModMemLong16 = function(fn)
}
break;
default:
this.assert(false, "decodeModMemLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modMemLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
};
/**
* decodeModGrpLong16(afnGrp, fnSrc)
* modGrpLong16(afnGrp, fnSrc)
*
* @this {X86CPU}
* @param {Array.<function(number,number)>} afnGrp
* @param {function()} fnSrc
*/
X86.decodeModGrpLong16 = function(afnGrp, fnSrc) {
X86.modGrpLong16 = function(afnGrp, fnSrc) {
var dst;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -2155,7 +2155,7 @@ X86.decodeModGrpLong16 = function(afnGrp, fnSrc) {
dst = this.regEDI;
break;
default:
this.assert(false, "decodeModGrpLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modGrpLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -2237,12 +2237,12 @@ X86.decodeModGrpLong16 = function(afnGrp, fnSrc) {
};
/**
* decodeModRegByte32(fn)
* modRegByte32(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModRegByte32 = function(fn)
X86.modRegByte32 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -2261,7 +2261,7 @@ X86.decodeModRegByte32 = function(fn)
src = this.getEAByteData(this.regEBX);
break;
case 0x04:
src = this.getEAByteData(X86.decodeSIB.call(this, 0));
src = this.getEAByteData(X86.modSIB.call(this, 0));
break;
case 0x05:
src = this.getEAByteData(this.getIPAddr());
@ -2285,7 +2285,7 @@ X86.decodeModRegByte32 = function(fn)
src = this.getEAByteData(this.regEBX + this.getIPDisp());
break;
case 0x44:
src = this.getEAByteData(X86.decodeSIB.call(this, 1) + this.getIPDisp());
src = this.getEAByteData(X86.modSIB.call(this, 1) + this.getIPDisp());
break;
case 0x45:
src = this.getEAByteStack(this.regEBP + this.getIPDisp());
@ -2309,7 +2309,7 @@ X86.decodeModRegByte32 = function(fn)
src = this.getEAByteData(this.regEBX + this.getIPAddr());
break;
case 0x84:
src = this.getEAByteData(X86.decodeSIB.call(this, 2) + this.getIPAddr());
src = this.getEAByteData(X86.modSIB.call(this, 2) + this.getIPAddr());
break;
case 0x85:
src = this.getEAByteStack(this.regEBP + this.getIPAddr());
@ -2354,7 +2354,7 @@ X86.decodeModRegByte32 = function(fn)
break;
default:
src = 0;
this.assert(false, "decodeModRegByte32(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modRegByte32(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -2429,12 +2429,12 @@ X86.decodeModRegByte32 = function(fn)
};
/**
* decodeModMemByte32(fn)
* modMemByte32(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModMemByte32 = function(fn)
X86.modMemByte32 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -2457,7 +2457,7 @@ X86.decodeModMemByte32 = function(fn)
this.regEAWrite = this.regEA;
break;
case 0x04:
dst = this.getEAByteData(X86.decodeSIB.call(this, 0));
dst = this.getEAByteData(X86.modSIB.call(this, 0));
this.regEAWrite = this.regEA;
break;
case 0x05:
@ -2489,7 +2489,7 @@ X86.decodeModMemByte32 = function(fn)
this.regEAWrite = this.regEA;
break;
case 0x44:
dst = this.getEAByteData(X86.decodeSIB.call(this, 1) + this.getIPDisp());
dst = this.getEAByteData(X86.modSIB.call(this, 1) + this.getIPDisp());
this.regEAWrite = this.regEA;
break;
case 0x45:
@ -2521,7 +2521,7 @@ X86.decodeModMemByte32 = function(fn)
this.regEAWrite = this.regEA;
break;
case 0x84:
dst = this.getEAByteData(X86.decodeSIB.call(this, 2) + this.getIPAddr());
dst = this.getEAByteData(X86.modSIB.call(this, 2) + this.getIPAddr());
this.regEAWrite = this.regEA;
break;
case 0x85:
@ -2562,7 +2562,7 @@ X86.decodeModMemByte32 = function(fn)
break;
default:
dst = 0;
this.assert(false, "decodeModMemByte32(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modMemByte32(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -2648,13 +2648,13 @@ X86.decodeModMemByte32 = function(fn)
};
/**
* decodeModGrpByte32(afnGrp, fnSrc)
* modGrpByte32(afnGrp, fnSrc)
*
* @this {X86CPU}
* @param {Array.<function(number,number)>} afnGrp
* @param {function()} fnSrc
*/
X86.decodeModGrpByte32 = function(afnGrp, fnSrc) {
X86.modGrpByte32 = function(afnGrp, fnSrc) {
var dst;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -2676,7 +2676,7 @@ X86.decodeModGrpByte32 = function(afnGrp, fnSrc) {
this.regEAWrite = this.regEA;
break;
case 0x04:
dst = this.getEAByteData(X86.decodeSIB.call(this, 0));
dst = this.getEAByteData(X86.modSIB.call(this, 0));
this.regEAWrite = this.regEA;
break;
case 0x05:
@ -2708,7 +2708,7 @@ X86.decodeModGrpByte32 = function(afnGrp, fnSrc) {
this.regEAWrite = this.regEA;
break;
case 0x44:
dst = this.getEAByteData(X86.decodeSIB.call(this, 1) + this.getIPDisp());
dst = this.getEAByteData(X86.modSIB.call(this, 1) + this.getIPDisp());
this.regEAWrite = this.regEA;
break;
case 0x45:
@ -2740,7 +2740,7 @@ X86.decodeModGrpByte32 = function(afnGrp, fnSrc) {
this.regEAWrite = this.regEA;
break;
case 0x84:
dst = this.getEAByteData(X86.decodeSIB.call(this, 2) + this.getIPAddr());
dst = this.getEAByteData(X86.modSIB.call(this, 2) + this.getIPAddr());
this.regEAWrite = this.regEA;
break;
case 0x85:
@ -2781,7 +2781,7 @@ X86.decodeModGrpByte32 = function(afnGrp, fnSrc) {
break;
default:
dst = 0;
this.assert(false, "decodeModGrpByte32(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modGrpByte32(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -2821,12 +2821,12 @@ X86.decodeModGrpByte32 = function(afnGrp, fnSrc) {
};
/**
* decodeModRegShort32(fn)
* modRegShort32(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModRegShort32 = function(fn)
X86.modRegShort32 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -2845,7 +2845,7 @@ X86.decodeModRegShort32 = function(fn)
src = this.getEAShortData(this.regEBX);
break;
case 0x04:
src = this.getEAShortData(X86.decodeSIB.call(this, 0));
src = this.getEAShortData(X86.modSIB.call(this, 0));
break;
case 0x05:
src = this.getEAShortData(this.getIPAddr());
@ -2869,7 +2869,7 @@ X86.decodeModRegShort32 = function(fn)
src = this.getEAShortData(this.regEBX + this.getIPDisp());
break;
case 0x44:
src = this.getEAShortData(X86.decodeSIB.call(this, 1) + this.getIPDisp());
src = this.getEAShortData(X86.modSIB.call(this, 1) + this.getIPDisp());
break;
case 0x45:
src = this.getEAShortStack(this.regEBP + this.getIPDisp());
@ -2893,7 +2893,7 @@ X86.decodeModRegShort32 = function(fn)
src = this.getEAShortData(this.regEBX + this.getIPAddr());
break;
case 0x84:
src = this.getEAShortData(X86.decodeSIB.call(this, 2) + this.getIPAddr());
src = this.getEAShortData(X86.modSIB.call(this, 2) + this.getIPAddr());
break;
case 0x85:
src = this.getEAShortStack(this.regEBP + this.getIPAddr());
@ -2954,7 +2954,7 @@ X86.decodeModRegShort32 = function(fn)
break;
default:
src = 0;
this.assert(false, "decodeModRegShort32(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modRegShort32(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -3042,12 +3042,12 @@ X86.decodeModRegShort32 = function(fn)
};
/**
* decodeModMemShort32(fn)
* modMemShort32(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModMemShort32 = function(fn)
X86.modMemShort32 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -3070,7 +3070,7 @@ X86.decodeModMemShort32 = function(fn)
this.regEAWrite = this.regEA;
break;
case 0x04:
dst = this.getEAShortData(X86.decodeSIB.call(this, 0));
dst = this.getEAShortData(X86.modSIB.call(this, 0));
this.regEAWrite = this.regEA;
break;
case 0x05:
@ -3102,7 +3102,7 @@ X86.decodeModMemShort32 = function(fn)
this.regEAWrite = this.regEA;
break;
case 0x44:
dst = this.getEAShortData(X86.decodeSIB.call(this, 1) + this.getIPDisp());
dst = this.getEAShortData(X86.modSIB.call(this, 1) + this.getIPDisp());
this.regEAWrite = this.regEA;
break;
case 0x45:
@ -3134,7 +3134,7 @@ X86.decodeModMemShort32 = function(fn)
this.regEAWrite = this.regEA;
break;
case 0x84:
dst = this.getEAShortData(X86.decodeSIB.call(this, 2) + this.getIPAddr());
dst = this.getEAShortData(X86.modSIB.call(this, 2) + this.getIPAddr());
this.regEAWrite = this.regEA;
break;
case 0x85:
@ -3175,7 +3175,7 @@ X86.decodeModMemShort32 = function(fn)
break;
default:
dst = 0;
this.assert(false, "decodeModMemShort32(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modMemShort32(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -3290,13 +3290,13 @@ X86.decodeModMemShort32 = function(fn)
};
/**
* decodeModGrpShort32(afnGrp, fnSrc)
* modGrpShort32(afnGrp, fnSrc)
*
* @this {X86CPU}
* @param {Array.<function(number,number)>} afnGrp
* @param {function()} fnSrc
*/
X86.decodeModGrpShort32 = function(afnGrp, fnSrc) {
X86.modGrpShort32 = function(afnGrp, fnSrc) {
var dst;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -3318,7 +3318,7 @@ X86.decodeModGrpShort32 = function(afnGrp, fnSrc) {
this.regEAWrite = this.regEA;
break;
case 0x04:
dst = this.getEAShortData(X86.decodeSIB.call(this, 0));
dst = this.getEAShortData(X86.modSIB.call(this, 0));
this.regEAWrite = this.regEA;
break;
case 0x05:
@ -3350,7 +3350,7 @@ X86.decodeModGrpShort32 = function(afnGrp, fnSrc) {
this.regEAWrite = this.regEA;
break;
case 0x44:
dst = this.getEAShortData(X86.decodeSIB.call(this, 1) + this.getIPDisp());
dst = this.getEAShortData(X86.modSIB.call(this, 1) + this.getIPDisp());
this.regEAWrite = this.regEA;
break;
case 0x45:
@ -3382,7 +3382,7 @@ X86.decodeModGrpShort32 = function(afnGrp, fnSrc) {
this.regEAWrite = this.regEA;
break;
case 0x84:
dst = this.getEAShortData(X86.decodeSIB.call(this, 2) + this.getIPAddr());
dst = this.getEAShortData(X86.modSIB.call(this, 2) + this.getIPAddr());
this.regEAWrite = this.regEA;
break;
case 0x85:
@ -3423,7 +3423,7 @@ X86.decodeModGrpShort32 = function(afnGrp, fnSrc) {
break;
default:
dst = 0;
this.assert(false, "decodeModGrpShort32(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modGrpShort32(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -3463,12 +3463,12 @@ X86.decodeModGrpShort32 = function(afnGrp, fnSrc) {
};
/**
* decodeModRegLong32(fn)
* modRegLong32(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModRegLong32 = function(fn)
X86.modRegLong32 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -3487,7 +3487,7 @@ X86.decodeModRegLong32 = function(fn)
src = this.getEALongData(this.regEBX);
break;
case 0x04:
src = this.getEALongData(X86.decodeSIB.call(this, 0));
src = this.getEALongData(X86.modSIB.call(this, 0));
break;
case 0x05:
src = this.getEALongData(this.getIPAddr());
@ -3511,7 +3511,7 @@ X86.decodeModRegLong32 = function(fn)
src = this.getEALongData(this.regEBX + this.getIPDisp());
break;
case 0x44:
src = this.getEALongData(X86.decodeSIB.call(this, 1) + this.getIPDisp());
src = this.getEALongData(X86.modSIB.call(this, 1) + this.getIPDisp());
break;
case 0x45:
src = this.getEALongStack(this.regEBP + this.getIPDisp());
@ -3535,7 +3535,7 @@ X86.decodeModRegLong32 = function(fn)
src = this.getEALongData(this.regEBX + this.getIPAddr());
break;
case 0x84:
src = this.getEALongData(X86.decodeSIB.call(this, 2) + this.getIPAddr());
src = this.getEALongData(X86.modSIB.call(this, 2) + this.getIPAddr());
break;
case 0x85:
src = this.getEALongStack(this.regEBP + this.getIPAddr());
@ -3596,7 +3596,7 @@ X86.decodeModRegLong32 = function(fn)
break;
default:
src = 0;
this.assert(false, "decodeModRegLong32(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modRegLong32(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -3684,12 +3684,12 @@ X86.decodeModRegLong32 = function(fn)
};
/**
* decodeModMemLong32(fn)
* modMemLong32(fn)
*
* @this {X86CPU}
* @param {function(number,number)} fn (dst,src)
*/
X86.decodeModMemLong32 = function(fn)
X86.modMemLong32 = function(fn)
{
var dst, src;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -3712,7 +3712,7 @@ X86.decodeModMemLong32 = function(fn)
this.regEAWrite = this.regEA;
break;
case 0x04:
dst = this.getEALongData(X86.decodeSIB.call(this, 0));
dst = this.getEALongData(X86.modSIB.call(this, 0));
this.regEAWrite = this.regEA;
break;
case 0x05:
@ -3744,7 +3744,7 @@ X86.decodeModMemLong32 = function(fn)
this.regEAWrite = this.regEA;
break;
case 0x44:
dst = this.getEALongData(X86.decodeSIB.call(this, 1) + this.getIPDisp());
dst = this.getEALongData(X86.modSIB.call(this, 1) + this.getIPDisp());
this.regEAWrite = this.regEA;
break;
case 0x45:
@ -3776,7 +3776,7 @@ X86.decodeModMemLong32 = function(fn)
this.regEAWrite = this.regEA;
break;
case 0x84:
dst = this.getEALongData(X86.decodeSIB.call(this, 2) + this.getIPAddr());
dst = this.getEALongData(X86.modSIB.call(this, 2) + this.getIPAddr());
this.regEAWrite = this.regEA;
break;
case 0x85:
@ -3817,7 +3817,7 @@ X86.decodeModMemLong32 = function(fn)
break;
default:
dst = 0;
this.assert(false, "decodeModMemLong32(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modMemLong32(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -3932,13 +3932,13 @@ X86.decodeModMemLong32 = function(fn)
};
/**
* decodeModGrpLong32(afnGrp, fnSrc)
* modGrpLong32(afnGrp, fnSrc)
*
* @this {X86CPU}
* @param {Array.<function(number,number)>} afnGrp
* @param {function()} fnSrc
*/
X86.decodeModGrpLong32 = function(afnGrp, fnSrc) {
X86.modGrpLong32 = function(afnGrp, fnSrc) {
var dst;
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
@ -3960,7 +3960,7 @@ X86.decodeModGrpLong32 = function(afnGrp, fnSrc) {
this.regEAWrite = this.regEA;
break;
case 0x04:
dst = this.getEALongData(X86.decodeSIB.call(this, 0));
dst = this.getEALongData(X86.modSIB.call(this, 0));
this.regEAWrite = this.regEA;
break;
case 0x05:
@ -3992,7 +3992,7 @@ X86.decodeModGrpLong32 = function(afnGrp, fnSrc) {
this.regEAWrite = this.regEA;
break;
case 0x44:
dst = this.getEALongData(X86.decodeSIB.call(this, 1) + this.getIPDisp());
dst = this.getEALongData(X86.modSIB.call(this, 1) + this.getIPDisp());
this.regEAWrite = this.regEA;
break;
case 0x45:
@ -4024,7 +4024,7 @@ X86.decodeModGrpLong32 = function(afnGrp, fnSrc) {
this.regEAWrite = this.regEA;
break;
case 0x84:
dst = this.getEALongData(X86.decodeSIB.call(this, 2) + this.getIPAddr());
dst = this.getEALongData(X86.modSIB.call(this, 2) + this.getIPAddr());
this.regEAWrite = this.regEA;
break;
case 0x85:
@ -4065,7 +4065,7 @@ X86.decodeModGrpLong32 = function(afnGrp, fnSrc) {
break;
default:
dst = 0;
this.assert(false, "decodeModGrpLong32(): unrecognized modrm byte " + str.toHexByte(bModRM));
this.assert(false, "modGrpLong32(): unrecognized modrm byte " + str.toHexByte(bModRM));
break;
}
@ -4105,13 +4105,13 @@ X86.decodeModGrpLong32 = function(afnGrp, fnSrc) {
};
/**
* decodeSIB(mod)
* modSIB(mod)
*
* @this {X86CPU}
* @param {number} mod
* @return {number}
*/
X86.decodeSIB = function(mod)
X86.modSIB = function(mod)
{
var bSIB = this.getIPByte();
var scale = bSIB >> 6, index, base;

View file

@ -47,7 +47,7 @@ X86.opGRP6 = function()
if ((bModRM & 0x38) < 0x10) { // possible reg values: 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
this.opFlags |= X86.OPFLAG.NOREAD;
}
this.decodeModGrpWord.call(this, this.aOpGrp6, X86.fnSRCNone);
this.decodeModGrpWord.call(this, this.aOpGrp6, X86.helpSRCNone);
};
/**
@ -61,7 +61,7 @@ X86.opGRP7 = function()
if (!(bModRM & 0x10)) {
this.opFlags |= X86.OPFLAG.NOREAD;
}
this.decodeModGrpWord.call(this, X86.aOpGrp7, X86.fnSRCNone);
this.decodeModGrpWord.call(this, X86.aOpGrp7, X86.helpSRCNone);
};
/**
@ -146,7 +146,7 @@ X86.opLOADALL286 = function()
/*
* To use LOADALL, CPL must be zero.
*/
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0, 0, true);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0, 0, true);
return;
}
this.setMSW(this.getShort(0x806));
@ -214,7 +214,7 @@ X86.opCLTS = function()
* NOTE: The following code shouldn't need to also test X86.PS.VM, because V86-mode is CPL 3.
*/
if (this.nCPL) {
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
this.regCR0 &= ~X86.CR0.MSW.TS;
@ -313,12 +313,12 @@ X86.opLOADALL386 = function()
/*
* To use LOADALL, CPL must be zero.
*/
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0, 0, true);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0, 0, true);
return;
}
var addr = this.segES.checkRead(this.regEDI & this.maskAddr, 0xCC);
if (addr !== X86.ADDR_INVALID) {
X86.fnLCR0.call(this, this.getLong(addr));
X86.helpLoadCR0.call(this, this.getLong(addr));
/*
* We need to call setPS() before loading any segment registers, because if the Virtual 8086 Mode (VM)
* bit is set in EFLAGS, the segment registers need to know that.
@ -399,7 +399,7 @@ X86.opMOVrc = function()
/*
* You're not allowed to read control registers if the current privilege level is not zero.
*/
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
@ -448,7 +448,7 @@ X86.opMOVrd = function()
/*
* You're not allowed to read control registers if the current privilege level is not zero.
*/
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
@ -497,7 +497,7 @@ X86.opMOVcr = function()
/*
* You're not allowed to write control registers if the current privilege level is not zero.
*/
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
@ -506,7 +506,7 @@ X86.opMOVcr = function()
switch((bModRM & 0x38) >> 3) {
case 0x0:
X86.fnLCR0.call(this, reg);
X86.helpLoadCR0.call(this, reg);
this.nStepCycles -= 10;
break;
case 0x2:
@ -514,7 +514,7 @@ X86.opMOVcr = function()
this.nStepCycles -= 4;
break;
case 0x3:
X86.fnLCR3.call(this, reg);
X86.helpLoadCR3.call(this, reg);
this.nStepCycles -= 5;
break;
default:
@ -546,7 +546,7 @@ X86.opMOVdr = function()
/*
* You're not allowed to write control registers if the current privilege level is not zero.
*/
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
@ -592,7 +592,7 @@ X86.opMOVrt = function()
/*
* You're not allowed to read control registers if the current privilege level is not zero.
*/
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
@ -638,7 +638,7 @@ X86.opMOVtr = function()
/*
* You're not allowed to write control registers if the current privilege level is not zero.
*/
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
@ -983,7 +983,7 @@ X86.opJNLEw = function()
*/
X86.opSETO = function()
{
X86.fnSETcc.call(this, X86.fnSETO);
X86.helpSETcc.call(this, X86.fnSETO);
};
/**
@ -995,7 +995,7 @@ X86.opSETO = function()
*/
X86.opSETNO = function()
{
X86.fnSETcc.call(this, X86.fnSETO);
X86.helpSETcc.call(this, X86.fnSETO);
};
/**
@ -1007,7 +1007,7 @@ X86.opSETNO = function()
*/
X86.opSETC = function()
{
X86.fnSETcc.call(this, X86.fnSETC);
X86.helpSETcc.call(this, X86.fnSETC);
};
/**
@ -1019,7 +1019,7 @@ X86.opSETC = function()
*/
X86.opSETNC = function()
{
X86.fnSETcc.call(this, X86.fnSETNC);
X86.helpSETcc.call(this, X86.fnSETNC);
};
/**
@ -1031,7 +1031,7 @@ X86.opSETNC = function()
*/
X86.opSETZ = function()
{
X86.fnSETcc.call(this, X86.fnSETZ);
X86.helpSETcc.call(this, X86.fnSETZ);
};
/**
@ -1043,7 +1043,7 @@ X86.opSETZ = function()
*/
X86.opSETNZ = function()
{
X86.fnSETcc.call(this, X86.fnSETNZ);
X86.helpSETcc.call(this, X86.fnSETNZ);
};
/**
@ -1055,7 +1055,7 @@ X86.opSETNZ = function()
*/
X86.opSETBE = function()
{
X86.fnSETcc.call(this, X86.fnSETBE);
X86.helpSETcc.call(this, X86.fnSETBE);
};
/**
@ -1067,7 +1067,7 @@ X86.opSETBE = function()
*/
X86.opSETNBE = function()
{
X86.fnSETcc.call(this, X86.fnSETNBE);
X86.helpSETcc.call(this, X86.fnSETNBE);
};
/**
@ -1079,7 +1079,7 @@ X86.opSETNBE = function()
*/
X86.opSETS = function()
{
X86.fnSETcc.call(this, X86.fnSETS);
X86.helpSETcc.call(this, X86.fnSETS);
};
/**
@ -1091,7 +1091,7 @@ X86.opSETS = function()
*/
X86.opSETNS = function()
{
X86.fnSETcc.call(this, X86.fnSETNS);
X86.helpSETcc.call(this, X86.fnSETNS);
};
/**
@ -1103,7 +1103,7 @@ X86.opSETNS = function()
*/
X86.opSETP = function()
{
X86.fnSETcc.call(this, X86.fnSETP);
X86.helpSETcc.call(this, X86.fnSETP);
};
/**
@ -1115,7 +1115,7 @@ X86.opSETP = function()
*/
X86.opSETNP = function()
{
X86.fnSETcc.call(this, X86.fnSETNP);
X86.helpSETcc.call(this, X86.fnSETNP);
};
/**
@ -1127,7 +1127,7 @@ X86.opSETNP = function()
*/
X86.opSETL = function()
{
X86.fnSETcc.call(this, X86.fnSETL);
X86.helpSETcc.call(this, X86.fnSETL);
};
/**
@ -1139,7 +1139,7 @@ X86.opSETL = function()
*/
X86.opSETNL = function()
{
X86.fnSETcc.call(this, X86.fnSETNL);
X86.helpSETcc.call(this, X86.fnSETNL);
};
/**
@ -1151,7 +1151,7 @@ X86.opSETNL = function()
*/
X86.opSETLE = function()
{
X86.fnSETcc.call(this, X86.fnSETLE);
X86.helpSETcc.call(this, X86.fnSETLE);
};
/**
@ -1163,7 +1163,7 @@ X86.opSETLE = function()
*/
X86.opSETNLE = function()
{
X86.fnSETcc.call(this, X86.fnSETNLE);
X86.helpSETcc.call(this, X86.fnSETNLE);
};
/**
@ -1427,7 +1427,7 @@ X86.opLGS = function()
X86.opMOVZXb = function()
{
this.decodeModRegByte.call(this, X86.fnMOVXb);
var reg = (this.bModRM & 0x38) >> 3;
var reg = (this.bModRM >> 3) & 0x7;
switch(reg) {
case 0x0:
this.regEAX = (this.regEAX & ~this.maskData) | (this.regEAX & 0xff);
@ -1471,8 +1471,8 @@ X86.opMOVZXb = function()
X86.opMOVZXw = function()
{
this.setDataSize(2);
this.decodeModRegWord.call(this, X86.fnMOVX);
switch((this.bModRM & 0x38) >> 3) {
this.decodeModRegWord.call(this, X86.fnMOVXw);
switch((this.bModRM >> 3) & 0x7) {
case 0x0:
this.regEAX = (this.regEAX & 0xffff);
break;
@ -1558,7 +1558,7 @@ X86.opBSR = function()
X86.opMOVSXb = function()
{
this.decodeModRegByte.call(this, X86.fnMOVXb);
var reg = (this.bModRM & 0x38) >> 3;
var reg = (this.bModRM >> 3) & 0x7;
switch(reg) {
case 0x0:
this.regEAX = (this.regEAX & ~this.maskData) | ((((this.regEAX & 0xff) << 24) >> 24) & this.maskData);
@ -1602,8 +1602,8 @@ X86.opMOVSXb = function()
X86.opMOVSXw = function()
{
this.setDataSize(2);
this.decodeModRegWord.call(this, X86.fnMOVX);
switch((this.bModRM & 0x38) >> 3) {
this.decodeModRegWord.call(this, X86.fnMOVXw);
switch((this.bModRM >> 3) & 0x7) {
case 0x0:
this.regEAX = ((this.regEAX << 16) >> 16);
break;

View file

@ -903,7 +903,7 @@ X86.opAAS = function()
*/
X86.opINCAX = function()
{
this.regEAX = X86.fnINCr.call(this, this.regEAX);
this.regEAX = X86.helpINCreg.call(this, this.regEAX);
};
/**
@ -913,7 +913,7 @@ X86.opINCAX = function()
*/
X86.opINCCX = function()
{
this.regECX = X86.fnINCr.call(this, this.regECX);
this.regECX = X86.helpINCreg.call(this, this.regECX);
};
/**
@ -923,7 +923,7 @@ X86.opINCCX = function()
*/
X86.opINCDX = function()
{
this.regEDX = X86.fnINCr.call(this, this.regEDX);
this.regEDX = X86.helpINCreg.call(this, this.regEDX);
};
/**
@ -933,7 +933,7 @@ X86.opINCDX = function()
*/
X86.opINCBX = function()
{
this.regEBX = X86.fnINCr.call(this, this.regEBX);
this.regEBX = X86.helpINCreg.call(this, this.regEBX);
};
/**
@ -943,7 +943,7 @@ X86.opINCBX = function()
*/
X86.opINCSP = function()
{
this.setSP(X86.fnINCr.call(this, this.getSP()));
this.setSP(X86.helpINCreg.call(this, this.getSP()));
};
/**
@ -953,7 +953,7 @@ X86.opINCSP = function()
*/
X86.opINCBP = function()
{
this.regEBP = X86.fnINCr.call(this, this.regEBP);
this.regEBP = X86.helpINCreg.call(this, this.regEBP);
};
/**
@ -963,7 +963,7 @@ X86.opINCBP = function()
*/
X86.opINCSI = function()
{
this.regESI = X86.fnINCr.call(this, this.regESI);
this.regESI = X86.helpINCreg.call(this, this.regESI);
};
/**
@ -973,7 +973,7 @@ X86.opINCSI = function()
*/
X86.opINCDI = function()
{
this.regEDI = X86.fnINCr.call(this, this.regEDI);
this.regEDI = X86.helpINCreg.call(this, this.regEDI);
};
/**
@ -983,7 +983,7 @@ X86.opINCDI = function()
*/
X86.opDECAX = function()
{
this.regEAX = X86.fnDECr.call(this, this.regEAX);
this.regEAX = X86.helpDECreg.call(this, this.regEAX);
};
/**
@ -993,7 +993,7 @@ X86.opDECAX = function()
*/
X86.opDECCX = function()
{
this.regECX = X86.fnDECr.call(this, this.regECX);
this.regECX = X86.helpDECreg.call(this, this.regECX);
};
/**
@ -1003,7 +1003,7 @@ X86.opDECCX = function()
*/
X86.opDECDX = function()
{
this.regEDX = X86.fnDECr.call(this, this.regEDX);
this.regEDX = X86.helpDECreg.call(this, this.regEDX);
};
/**
@ -1013,7 +1013,7 @@ X86.opDECDX = function()
*/
X86.opDECBX = function()
{
this.regEBX = X86.fnDECr.call(this, this.regEBX);
this.regEBX = X86.helpDECreg.call(this, this.regEBX);
};
/**
@ -1023,7 +1023,7 @@ X86.opDECBX = function()
*/
X86.opDECSP = function()
{
this.setSP(X86.fnDECr.call(this, this.getSP()));
this.setSP(X86.helpDECreg.call(this, this.getSP()));
};
/**
@ -1033,7 +1033,7 @@ X86.opDECSP = function()
*/
X86.opDECBP = function()
{
this.regEBP = X86.fnDECr.call(this, this.regEBP);
this.regEBP = X86.helpDECreg.call(this, this.regEBP);
};
/**
@ -1043,7 +1043,7 @@ X86.opDECBP = function()
*/
X86.opDECSI = function()
{
this.regESI = X86.fnDECr.call(this, this.regESI);
this.regESI = X86.helpDECreg.call(this, this.regESI);
};
/**`
@ -1053,7 +1053,7 @@ X86.opDECSI = function()
*/
X86.opDECDI = function()
{
this.regEDI = X86.fnDECr.call(this, this.regEDI);
this.regEDI = X86.helpDECreg.call(this, this.regEDI);
};
/**
@ -1652,7 +1652,7 @@ X86.opINSb = function()
var b = this.bus.checkPortInputNotify(port, 1, this.regLIP - nDelta - 1);
this.setSOByte(this.segES, this.regEDI & maskAddr, b);
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -1705,7 +1705,7 @@ X86.opINSw = function()
}
this.setSOWord(this.segES, this.regEDI & maskAddr, w);
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -1751,7 +1751,7 @@ X86.opOUTSb = function()
if (!this.checkIOPM(port, 1, false)) return;
var b = this.getSOByte(this.segDS, this.regESI & maskAddr);
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -1797,7 +1797,7 @@ X86.opOUTSw = function()
if (nReps--) {
var w = this.getSOWord(this.segDS, this.regESI & maskAddr);
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -2344,7 +2344,7 @@ X86.opPOPmw = function()
*
* pops the DWORD from the top of the stack and places it at ESP+08, where ESP is the value
* AFTER the pop, not before. We used to (incorrectly) pass "popWord" as the fnSrc parameter
* below; we now pop the word first, saving it in regXX, and then pass "fnSRCxx" as fnSrc,
* below; we now pop the word first, saving it in regXX, and then pass "helpSRCxx" as fnSrc,
* which simply returns the contents of regXX.
*
* Also, in case you're wondering, fnPUSHw() (in aOpGrp4w) is the complement to this instruction,
@ -2353,7 +2353,7 @@ X86.opPOPmw = function()
*/
this.regXX = this.popWord();
this.decodeModGrpWord.call(this, X86.aOpGrpPOPw, X86.fnSRCxx);
this.decodeModGrpWord.call(this, X86.aOpGrpPOPw, X86.helpSRCxx);
this.opLSP = X86.ADDR_INVALID;
};
@ -2532,7 +2532,7 @@ X86.opCWD = function()
*/
X86.opCALLF = function()
{
X86.fnCALLF.call(this, this.getIPWord(), this.getIPShort());
X86.helpCALLF.call(this, this.getIPWord(), this.getIPShort());
this.nStepCycles -= this.cycleCounts.nOpCyclesCallF;
};
@ -2562,7 +2562,7 @@ X86.opPUSHF = function()
if (I386) {
if ((regPS & X86.PS.VM) && this.nIOPL < 3) {
if (DEBUG) this.printMessage("PUSHF in v86-mode (IOPL < 3)", this.bitsMessage, true);
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
/*
@ -2597,7 +2597,7 @@ X86.opPOPF = function()
*/
if (I386 && (this.regPS & X86.PS.VM) && this.nIOPL < 3) {
if (DEBUG) this.printMessage("POPF in v86-mode (IOPL < 3)", this.bitsMessage, true);
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
/*
@ -2728,7 +2728,7 @@ X86.opMOVSb = function()
if (nReps--) {
this.setSOByte(this.segES, this.regEDI & maskAddr, this.getSOByte(this.segData, this.regESI & maskAddr));
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -2765,7 +2765,7 @@ X86.opMOVSw = function()
if (nReps--) {
this.setSOWord(this.segES, this.regEDI & maskAddr, this.getSOWord(this.segData, this.regESI & maskAddr));
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -2804,7 +2804,7 @@ X86.opCMPSb = function()
var bSrc = this.getEAByte(this.segES, this.regEDI);
this.regEAWrite = this.regEA; // TODO: Is this necessary?
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -2852,7 +2852,7 @@ X86.opCMPSw = function()
var wSrc = this.getEAWord(this.segES, this.regEDI & maskAddr);
this.regEAWrite = this.regEA; // TODO: Is this necessary?
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -2922,7 +2922,7 @@ X86.opSTOSb = function()
if (nReps--) {
this.setSOByte(this.segES, this.regEDI & maskAddr, this.regEAX);
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -2980,7 +2980,7 @@ X86.opSTOSw = function()
if (nReps--) {
this.setSOWord(this.segES, this.regEDI & maskAddr, this.regEAX);
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -3018,7 +3018,7 @@ X86.opLODSb = function()
if (nReps--) {
var b = this.getSOByte(this.segData, this.regESI & maskAddr);
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -3055,7 +3055,7 @@ X86.opLODSw = function()
if (nReps--) {
var w = this.getSOWord(this.segData, this.regESI & maskAddr);
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -3097,7 +3097,7 @@ X86.opSCASb = function()
this.regEAWrite = this.regEA; // TODO: Is this necessary?
X86.fnCMPb.call(this, bDst, bSrc);
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -3143,7 +3143,7 @@ X86.opSCASw = function()
this.regEAWrite = this.regEA; // TODO: Is this necessary?
X86.fnCMPw.call(this, wDst, wSrc);
/*
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
* helpFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
@ -3377,7 +3377,7 @@ X86.opMOVDI = function()
*/
X86.opGRP2bn = function()
{
this.decodeModGrpByte.call(this, X86.aOpGrp2b, X86.fnSRCByte);
this.decodeModGrpByte.call(this, X86.aOpGrp2b, X86.helpSRCByte);
};
/**
@ -3387,7 +3387,7 @@ X86.opGRP2bn = function()
*/
X86.opGRP2wn = function()
{
this.decodeModGrpWord.call(this, this.sizeData == 2? X86.aOpGrp2w : X86.aOpGrp2d, X86.fnSRCByte);
this.decodeModGrpWord.call(this, this.sizeData == 2? X86.aOpGrp2w : X86.aOpGrp2d, X86.helpSRCByte);
};
/**
@ -3533,7 +3533,7 @@ X86.opLEAVE = function()
*/
X86.opRETFn = function()
{
X86.fnRETF.call(this, this.getIPShort());
X86.helpRETF.call(this, this.getIPShort());
this.nStepCycles -= this.cycleCounts.nOpCyclesRetFn;
};
@ -3544,7 +3544,7 @@ X86.opRETFn = function()
*/
X86.opRETF = function()
{
X86.fnRETF.call(this, 0);
X86.helpRETF.call(this, 0);
this.nStepCycles -= this.cycleCounts.nOpCyclesRetF;
};
@ -3560,16 +3560,16 @@ X86.opINT3 = function()
*/
if (I386 && (this.regPS & X86.PS.VM) && this.nIOPL < 3) {
if (DEBUG) this.printMessage("INT 0x03 in v86-mode (IOPL < 3)", this.bitsMessage, true);
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
/*
* Because INT3 is a trap, not a fault, we must use fnTrap() rather than fnFault(). Unfortunately, that
* means you can't rely on the Debugger logic instead fnFault() to conditionally stop execution on an INT3,
* Because INT3 is a trap, not a fault, we must use helpTrap() rather than helpFault(). Unfortunately, that
* means you can't rely on the Debugger logic instead helpFault() to conditionally stop execution on an INT3,
* so I've changed the Debugger's checkBreakpoint() function to stop execution on INT3 whenever both the
* INT and HALT message bits are set; a simple "g" command allows you to continue.
*/
X86.fnTrap.call(this, X86.EXCEPTION.BP_TRAP, this.cycleCounts.nOpCyclesInt3D);
X86.helpTrap.call(this, X86.EXCEPTION.BP_TRAP, this.cycleCounts.nOpCyclesInt3D);
};
/**
@ -3585,7 +3585,7 @@ X86.opINTn = function()
*/
if (I386 && (this.regPS & X86.PS.VM) && this.nIOPL < 3) {
if (DEBUG && this.messageEnabled()) this.printMessage("INT " + str.toHexByte(nInt) + " in v86-mode (IOPL < 3)", true, true);
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
/*
@ -3593,7 +3593,7 @@ X86.opINTn = function()
* and returns false ONLY if a notification handler returned false (ie, requesting the interrupt be skipped).
*/
if (this.checkIntNotify(nInt)) {
X86.fnTrap.call(this, nInt, 0);
X86.helpTrap.call(this, nInt, 0);
return;
}
this.nStepCycles--; // we don't need to assess the full cost of nOpCyclesInt, but we need to assess something...
@ -3612,10 +3612,10 @@ X86.opINTO = function()
*/
if (I386 && (this.regPS & X86.PS.VM) && this.nIOPL < 3) {
if (DEBUG) this.printMessage("INTO in v86-mode (IOPL < 3)", this.bitsMessage, true);
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
X86.fnTrap.call(this, X86.EXCEPTION.OF_TRAP, this.cycleCounts.nOpCyclesIntOD);
X86.helpTrap.call(this, X86.EXCEPTION.OF_TRAP, this.cycleCounts.nOpCyclesIntOD);
return;
}
this.nStepCycles -= this.cycleCounts.nOpCyclesIntOFall;
@ -3633,10 +3633,10 @@ X86.opIRET = function()
*/
if (I386 && (this.regPS & X86.PS.VM) && this.nIOPL < 3) {
if (DEBUG) this.printMessage("IRET in v86-mode (IOPL < 3)", this.bitsMessage, true);
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
X86.fnIRET.call(this);
X86.helpIRET.call(this);
};
/**
@ -3646,7 +3646,7 @@ X86.opIRET = function()
*/
X86.opGRP2b1 = function()
{
this.decodeModGrpByte.call(this, X86.aOpGrp2b, X86.fnSRC1);
this.decodeModGrpByte.call(this, X86.aOpGrp2b, X86.helpSRC1);
};
/**
@ -3656,7 +3656,7 @@ X86.opGRP2b1 = function()
*/
X86.opGRP2w1 = function()
{
this.decodeModGrpWord.call(this, this.sizeData == 2? X86.aOpGrp2w : X86.aOpGrp2d, X86.fnSRC1);
this.decodeModGrpWord.call(this, this.sizeData == 2? X86.aOpGrp2w : X86.aOpGrp2d, X86.helpSRC1);
};
/**
@ -3666,7 +3666,7 @@ X86.opGRP2w1 = function()
*/
X86.opGRP2bCL = function()
{
this.decodeModGrpByte.call(this, X86.aOpGrp2b, X86.fnSRCCL);
this.decodeModGrpByte.call(this, X86.aOpGrp2b, X86.helpSRCCL);
};
/**
@ -3676,7 +3676,7 @@ X86.opGRP2bCL = function()
*/
X86.opGRP2wCL = function()
{
this.decodeModGrpWord.call(this, this.sizeData == 2? X86.aOpGrp2w : X86.aOpGrp2d, X86.fnSRCCL);
this.decodeModGrpWord.call(this, this.sizeData == 2? X86.aOpGrp2w : X86.aOpGrp2d, X86.helpSRCCL);
};
/**
@ -3724,7 +3724,7 @@ X86.opAAM = function()
{
var b = this.getIPByte();
if (!b) {
X86.fnDivOverflow.call(this);
X86.helpDIVOverflow.call(this);
return;
}
var AL = this.regEAX & 0xff;
@ -4227,7 +4227,7 @@ X86.opHLT = function()
* TODO: Consider swapping out this function whenever setProtMode() changes the mode to V86-mode.
*/
if (I386 && (this.regPS & X86.PS.VM)) {
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
/*
@ -4291,7 +4291,7 @@ X86.opCMC = function()
X86.opGRP3b = function()
{
this.fMDSet = false;
this.decodeModGrpByte.call(this, X86.aOpGrp3b, X86.fnSRCNone);
this.decodeModGrpByte.call(this, X86.aOpGrp3b, X86.helpSRCNone);
if (this.fMDSet) this.regEAX = (this.regEAX & ~this.maskData) | (this.regMDLo & this.maskData);
};
@ -4317,7 +4317,7 @@ X86.opGRP3b = function()
X86.opGRP3w = function()
{
this.fMDSet = false;
this.decodeModGrpWord.call(this, X86.aOpGrp3w, X86.fnSRCNone);
this.decodeModGrpWord.call(this, X86.aOpGrp3w, X86.helpSRCNone);
if (this.fMDSet) {
this.regEAX = (this.regEAX & ~this.maskData) | (this.regMDLo & this.maskData);
this.regEDX = (this.regEDX & ~this.maskData) | (this.regMDHi & this.maskData);
@ -4359,7 +4359,7 @@ X86.opCLI = function()
*/
if (this.nCPL > this.nIOPL) {
if (DEBUG && (this.regPS & X86.PS.VM)) this.printMessage("CLI in v86-mode (IOPL < 3)", this.bitsMessage, true);
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
this.clearIF();
@ -4379,7 +4379,7 @@ X86.opSTI = function()
*/
if (this.nCPL > this.nIOPL) {
if (DEBUG && (this.regPS & X86.PS.VM)) this.printMessage("STI in v86-mode (IOPL < 3)", this.bitsMessage, true);
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
return;
}
this.setIF();
@ -4416,7 +4416,7 @@ X86.opSTD = function()
*/
X86.opGRP4b = function()
{
this.decodeModGrpByte.call(this, X86.aOpGrp4b, X86.fnSRCNone);
this.decodeModGrpByte.call(this, X86.aOpGrp4b, X86.helpSRCNone);
};
/**
@ -4426,7 +4426,7 @@ X86.opGRP4b = function()
*/
X86.opGRP4w = function()
{
this.decodeModGrpWord.call(this, X86.aOpGrp4w, X86.fnSRCNone);
this.decodeModGrpWord.call(this, X86.aOpGrp4w, X86.helpSRCNone);
};
/**
@ -4436,7 +4436,7 @@ X86.opGRP4w = function()
*/
X86.opInvalid = function()
{
X86.fnFault.call(this, X86.EXCEPTION.UD_FAULT);
X86.helpFault.call(this, X86.EXCEPTION.UD_FAULT);
};
/**

View file

@ -115,7 +115,7 @@ function X86Seg(cpu, id, sName, fProt)
* will be pushed from awParms onto the new stack.
*
* The typical ways of loading a new segment into CS are JMPF, CALLF (or INT), and RETF (or IRET),
* via CPU functions setCSIP() and fnINT(), which use segCS.loadCode() and segCS.loadIDT(), respectively.
* via CPU functions setCSIP() and helpINT(), which use segCS.loadCode() and segCS.loadIDT(), respectively.
*
* loadCode() requires an fCall value: null means NO privilege level transition may occur, true
* allows a stack switch and a privilege transition to a numerically lower privilege, and false allows
@ -268,7 +268,7 @@ X86Seg.prototype.loadProt = function loadProt(sel, fProbe)
return this.loadDesc8(addrDesc, sel, fProbe);
}
if (this.id < X86Seg.ID.VER) {
X86.fnFault.call(cpu, fProbe && this.id == X86Seg.ID.STACK? X86.EXCEPTION.TS_FAULT : X86.EXCEPTION.GP_FAULT, sel & X86.ERRCODE.SELMASK);
X86.helpFault.call(cpu, fProbe && this.id == X86Seg.ID.STACK? X86.EXCEPTION.TS_FAULT : X86.EXCEPTION.GP_FAULT, sel & X86.ERRCODE.SELMASK);
}
}
return X86.ADDR_INVALID;
@ -323,15 +323,15 @@ X86Seg.prototype.loadIDTProt = function loadIDTProt(nIDT)
if (addr !== X86.ADDR_INVALID) addr += this.offIP;
return addr;
}
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, nIDT | X86.ERRCODE.IDT);
X86.helpFault.call(cpu, X86.EXCEPTION.GP_FAULT, nIDT | X86.ERRCODE.IDT);
return X86.ADDR_INVALID;
};
/**
* checkReadReal(off, cb)
*
* TODO: Invoke X86.fnFault.call(this.cpu, X86.EXCEPTION.GP_FAULT) if off+cb is beyond offMax on 80186 and up;
* also, determine whether fnFault() call should include an error code, since this is happening in real-mode.
* TODO: Invoke X86.helpFault.call(this.cpu, X86.EXCEPTION.GP_FAULT) if off+cb is beyond offMax on 80186 and up;
* also, determine whether helpFault() call should include an error code, since this is happening in real-mode.
*
* @this {X86Seg}
* @param {number} off is a segment-relative offset
@ -346,8 +346,8 @@ X86Seg.prototype.checkReadReal = function checkReadReal(off, cb)
/**
* checkWriteReal(off, cb)
*
* TODO: Invoke X86.fnFault.call(this.cpu, X86.EXCEPTION.GP_FAULT) if off+cb is beyond offMax on 80186 and up;
* also, determine whether fnFault() call should include an error code, since this is happening in real-mode.
* TODO: Invoke X86.helpFault.call(this.cpu, X86.EXCEPTION.GP_FAULT) if off+cb is beyond offMax on 80186 and up;
* also, determine whether helpFault() call should include an error code, since this is happening in real-mode.
*
* @this {X86Seg}
* @param {number} off is a segment-relative offset
@ -409,7 +409,7 @@ X86Seg.prototype.checkReadProtDown = function checkReadProtDown(off, cb)
*/
X86Seg.prototype.checkReadProtDisallowed = function checkReadProtDisallowed(off, cb)
{
X86.fnFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, 0);
return X86.ADDR_INVALID;
};
@ -463,7 +463,7 @@ X86Seg.prototype.checkWriteProtDown = function checkWriteProtDown(off, cb)
*/
X86Seg.prototype.checkWriteProtDisallowed = function checkWriteProtDisallowed(off, cb)
{
X86.fnFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, 0);
X86.helpFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, 0);
return X86.ADDR_INVALID;
};
@ -546,7 +546,7 @@ X86Seg.prototype.loadAcc = function(sel, fGDT)
return cpu.getShort(addrDesc + X86.DESC.ACC.OFFSET);
}
}
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel & X86.ERRCODE.SELMASK);
X86.helpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel & X86.ERRCODE.SELMASK);
return X86.DESC.ACC.INVALID;
};
*/
@ -898,7 +898,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fProbe)
* 5) Descriptor must indicate writable data segment else #TS (SS selector)
*/
if (!selStack) {
X86.fnFault.call(cpu, X86.EXCEPTION.TS_FAULT, selStack);
X86.helpFault.call(cpu, X86.EXCEPTION.TS_FAULT, selStack);
return X86.ADDR_INVALID;
}
@ -969,7 +969,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fProbe)
* FS (upper 16 bits undefined)
* high: GS (upper 16 bits undefined)
*
* Our caller (eg, fnINT()) will take care of pushing the final bits (EFLAGS, CS, and EIP).
* Our caller (eg, helpINT()) will take care of pushing the final bits (EFLAGS, CS, and EIP).
*/
cpu.setDataSize(4);
cpu.assert(I386 && cpu.model >= X86.MODEL_80386);
@ -992,12 +992,12 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fProbe)
}
if (sizeGate != 0) {
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, (sel & X86.ERRCODE.SELMASK) | (fIDT? X86.ERRCODE.IDT : 0));
X86.helpFault.call(cpu, X86.EXCEPTION.GP_FAULT, (sel & X86.ERRCODE.SELMASK) | (fIDT? X86.ERRCODE.IDT : 0));
return X86.ADDR_INVALID;
}
if (!(acc & X86.DESC.ACC.PRESENT)) {
X86.fnFault.call(cpu, X86.EXCEPTION.NP_FAULT, (sel & X86.ERRCODE.SELMASK) | (fIDT? X86.ERRCODE.IDT : 0));
X86.helpFault.call(cpu, X86.EXCEPTION.NP_FAULT, (sel & X86.ERRCODE.SELMASK) | (fIDT? X86.ERRCODE.IDT : 0));
return X86.ADDR_INVALID;
}
break;
@ -1040,14 +1040,14 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fProbe)
* implies that, yes, GP_FAULT checks are supposed to be performed *before* NP_FAULT checks.
*/
if (type < X86.DESC.ACC.TYPE.SEG || (type & (X86.DESC.ACC.TYPE.CODE | X86.DESC.ACC.TYPE.READABLE)) == X86.DESC.ACC.TYPE.CODE) {
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel & X86.ERRCODE.SELMASK);
X86.helpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel & X86.ERRCODE.SELMASK);
return X86.ADDR_INVALID;
}
/*
* TODO: This would be a good place to perform some additional access rights checks, too.
*/
if (!(acc & X86.DESC.ACC.PRESENT)) {
X86.fnFault.call(cpu, X86.EXCEPTION.NP_FAULT, sel & X86.ERRCODE.SELMASK);
X86.helpFault.call(cpu, X86.EXCEPTION.NP_FAULT, sel & X86.ERRCODE.SELMASK);
return X86.ADDR_INVALID;
}
}
@ -1055,11 +1055,11 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fProbe)
case X86Seg.ID.STACK:
if (!selMasked || type < X86.DESC.ACC.TYPE.SEG || (type & (X86.DESC.ACC.TYPE.CODE | X86.DESC.ACC.TYPE.WRITABLE)) != X86.DESC.ACC.TYPE.WRITABLE) {
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel & X86.ERRCODE.SELMASK);
X86.helpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel & X86.ERRCODE.SELMASK);
return X86.ADDR_INVALID;
}
if (!(acc & X86.DESC.ACC.PRESENT)) {
X86.fnFault.call(cpu, X86.EXCEPTION.SS_FAULT, sel & X86.ERRCODE.SELMASK);
X86.helpFault.call(cpu, X86.EXCEPTION.SS_FAULT, sel & X86.ERRCODE.SELMASK);
return X86.ADDR_INVALID;
}
break;
@ -1067,7 +1067,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fProbe)
case X86Seg.ID.TSS:
var typeTSS = type & ~X86.DESC.ACC.TSS_BUSY;
if (!selMasked || typeTSS != X86.DESC.ACC.TYPE.TSS286 && typeTSS != X86.DESC.ACC.TYPE.TSS386) {
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel & X86.ERRCODE.SELMASK);
X86.helpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel & X86.ERRCODE.SELMASK);
return X86.ADDR_INVALID;
}
/*
@ -1181,7 +1181,7 @@ X86Seg.prototype.switchTSS = function switchTSS(selNew, fNest)
* TODO: Verify that it is (always) correct to require that the BUSY bit be currently set.
*/
if (!(cpu.segTSS.type & X86.DESC.ACC.TSS_BUSY)) {
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, selNew & X86.ERRCODE.SELMASK);
X86.helpFault.call(cpu, X86.EXCEPTION.GP_FAULT, selNew & X86.ERRCODE.SELMASK);
return false;
}
/*
@ -1201,7 +1201,7 @@ X86Seg.prototype.switchTSS = function switchTSS(selNew, fNest)
if (fNest !== false) {
if (cpu.segTSS.type & X86.DESC.ACC.TSS_BUSY) {
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, selNew & X86.ERRCODE.SELMASK);
X86.helpFault.call(cpu, X86.EXCEPTION.GP_FAULT, selNew & X86.ERRCODE.SELMASK);
return false;
}
cpu.setShort(cpu.segTSS.addrDesc + X86.DESC.ACC.OFFSET, cpu.segTSS.acc |= X86.DESC.ACC.TSS_BUSY);
@ -1288,7 +1288,7 @@ X86Seg.prototype.switchTSS = function switchTSS(selNew, fNest)
* rather than later, so that as segment registers are reloaded, any LDT selectors will
* will be located in the correct table.
*/
X86.fnLCR3.call(cpu, cpu.getLong(addrNew + X86.TSS386.TASK_CR3));
X86.helpLoadCR3.call(cpu, cpu.getLong(addrNew + X86.TSS386.TASK_CR3));
cpu.segLDT.load(cpu.getShort(addrNew + X86.TSS386.TASK_LDT));
cpu.setPS(cpu.getLong(addrNew + X86.TSS386.TASK_PS) | (fNest? X86.PS.NT : 0));
cpu.assert(!fNest || !!(cpu.regPS & X86.PS.NT));