Fixed new modRM decoders
This commit is contained in:
parent
22b9695f25
commit
7953383fa9
37 changed files with 7973 additions and 1603 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Reference in a new issue