diff --git a/devices/pc/machine/compaq/deskpro386/ega/2048kb/machine.xml b/devices/pc/machine/compaq/deskpro386/ega/2048kb/machine.xml
index d5bfd2af9..e301aa782 100644
--- a/devices/pc/machine/compaq/deskpro386/ega/2048kb/machine.xml
+++ b/devices/pc/machine/compaq/deskpro386/ega/2048kb/machine.xml
@@ -13,7 +13,7 @@
-
+
diff --git a/disks/pc/cpm/machine.xml b/disks/pc/cpm/machine.xml
index 0d17eb81c..41a819be6 100644
--- a/disks/pc/cpm/machine.xml
+++ b/disks/pc/cpm/machine.xml
@@ -18,7 +18,7 @@
None
- Load Drive
+ Load
diff --git a/disks/pc/diags/ibm/2.20/machine.xml b/disks/pc/diags/ibm/2.20/machine.xml
index 469c752ca..c35d5fdd4 100644
--- a/disks/pc/diags/ibm/2.20/machine.xml
+++ b/disks/pc/diags/ibm/2.20/machine.xml
@@ -21,7 +21,7 @@
- Load Drive
+ Load
diff --git a/disks/pc/library.xml b/disks/pc/library.xml
index 129b487ba..4700aad39 100644
--- a/disks/pc/library.xml
+++ b/disks/pc/library.xml
@@ -50,7 +50,7 @@
- Download
+ Load
diff --git a/disks/pc/samples.xml b/disks/pc/samples.xml
index fce094079..098d2356f 100644
--- a/disks/pc/samples.xml
+++ b/disks/pc/samples.xml
@@ -9,7 +9,7 @@
- Download
+ Load
diff --git a/disks/pc/windows/win10x.xml b/disks/pc/windows/win10x.xml
index 0c9f826b3..43db46da5 100644
--- a/disks/pc/windows/win10x.xml
+++ b/disks/pc/windows/win10x.xml
@@ -16,6 +16,6 @@
Windows 1.03 (APPS)
Windows 1.03 (WRITE)
- Load Drive
+ Load
diff --git a/docs/pcjs/demos/sample2.xml b/docs/pcjs/demos/sample2.xml
index de4857a49..654827688 100644
--- a/docs/pcjs/demos/sample2.xml
+++ b/docs/pcjs/demos/sample2.xml
@@ -20,7 +20,7 @@
None
PC-DOS 1.00
- Load Drive
+ Load
diff --git a/docs/pcjs/demos/sample3a.xml b/docs/pcjs/demos/sample3a.xml
index 52a75585f..78acf4e55 100644
--- a/docs/pcjs/demos/sample3a.xml
+++ b/docs/pcjs/demos/sample3a.xml
@@ -60,7 +60,7 @@
PC-DOS 1.00
VisiCalc
- Load Drive
+ Load
diff --git a/modules/c1pjs/templates/components.xsl b/modules/c1pjs/templates/components.xsl
index 37f795e89..3758964ad 100644
--- a/modules/c1pjs/templates/components.xsl
+++ b/modules/c1pjs/templates/components.xsl
@@ -289,7 +289,7 @@
diff --git a/modules/pcjs/lib/debugger.js b/modules/pcjs/lib/debugger.js
index 0bfb4a68f..11794e2c4 100644
--- a/modules/pcjs/lib/debugger.js
+++ b/modules/pcjs/lib/debugger.js
@@ -879,20 +879,38 @@ if (DEBUGGER) {
Debugger.aaOp0FDescs = {
0x00: [Debugger.INS.GRP6, Debugger.TYPE_MODRM | Debugger.TYPE_WORD | Debugger.TYPE_BOTH],
0x01: [Debugger.INS.GRP7, Debugger.TYPE_MODRM | Debugger.TYPE_WORD | Debugger.TYPE_BOTH],
- 0x02: [Debugger.INS.LAR, Debugger.TYPE_REG | Debugger.TYPE_WORD | Debugger.TYPE_OUT | Debugger.TYPE_80286, Debugger.TYPE_MEM | Debugger.TYPE_WORD | Debugger.TYPE_IN],
- 0x03: [Debugger.INS.LSL, Debugger.TYPE_REG | Debugger.TYPE_WORD | Debugger.TYPE_OUT | Debugger.TYPE_80286, Debugger.TYPE_MEM | Debugger.TYPE_WORD | Debugger.TYPE_IN],
+ 0x02: [Debugger.INS.LAR, Debugger.TYPE_REG | Debugger.TYPE_WORD | Debugger.TYPE_OUT | Debugger.TYPE_80286, Debugger.TYPE_MEM | Debugger.TYPE_WORD | Debugger.TYPE_IN],
+ 0x03: [Debugger.INS.LSL, Debugger.TYPE_REG | Debugger.TYPE_WORD | Debugger.TYPE_OUT | Debugger.TYPE_80286, Debugger.TYPE_MEM | Debugger.TYPE_WORD | Debugger.TYPE_IN],
0x05: [Debugger.INS.LOADALL,Debugger.TYPE_80286],
0x06: [Debugger.INS.CLTS, Debugger.TYPE_80286],
- 0x20: [Debugger.INS.MOV, Debugger.TYPE_REG | Debugger.TYPE_DWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_CTLREG | Debugger.TYPE_DWORD | Debugger.TYPE_IN],
- 0x22: [Debugger.INS.MOV, Debugger.TYPE_CTLREG | Debugger.TYPE_DWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_DWORD | Debugger.TYPE_IN],
+ 0x20: [Debugger.INS.MOV, Debugger.TYPE_REG | Debugger.TYPE_DWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_CTLREG | Debugger.TYPE_DWORD | Debugger.TYPE_IN],
+ 0x22: [Debugger.INS.MOV, Debugger.TYPE_CTLREG | Debugger.TYPE_DWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_DWORD | Debugger.TYPE_IN],
+ 0x80: [Debugger.INS.JO, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x81: [Debugger.INS.JNO, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x82: [Debugger.INS.JC, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x83: [Debugger.INS.JNC, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x84: [Debugger.INS.JZ, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x85: [Debugger.INS.JNZ, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x86: [Debugger.INS.JBE, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x87: [Debugger.INS.JNBE, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x88: [Debugger.INS.JS, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x89: [Debugger.INS.JNS, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x8A: [Debugger.INS.JP, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x8B: [Debugger.INS.JNP, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x8C: [Debugger.INS.JL, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x8D: [Debugger.INS.JGE, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x8E: [Debugger.INS.JLE, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
+ 0x8F: [Debugger.INS.JG, Debugger.TYPE_IMMREL | Debugger.TYPE_WORDV | Debugger.TYPE_IN | Debugger.TYPE_80386],
0xA0: [Debugger.INS.PUSH, Debugger.TYPE_FS | Debugger.TYPE_IN | Debugger.TYPE_80386],
0xA1: [Debugger.INS.POP, Debugger.TYPE_FS | Debugger.TYPE_OUT | Debugger.TYPE_80386],
- 0xA4: [Debugger.INS.SHLD, Debugger.TYPE_MODRM | Debugger.TYPE_WORDV | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_WORDV | Debugger.TYPE_IN, Debugger.TYPE_IMM | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
- 0xA5: [Debugger.INS.SHLD, Debugger.TYPE_MODRM | Debugger.TYPE_WORDV | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_WORDV | Debugger.TYPE_IN, Debugger.TYPE_IMPREG | Debugger.TYPE_CL | Debugger.TYPE_IN],
+ 0xA4: [Debugger.INS.SHLD, Debugger.TYPE_MODRM | Debugger.TYPE_WORDV | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_WORDV | Debugger.TYPE_IN, Debugger.TYPE_IMM | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
+ 0xA5: [Debugger.INS.SHLD, Debugger.TYPE_MODRM | Debugger.TYPE_WORDV | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_WORDV | Debugger.TYPE_IN, Debugger.TYPE_IMPREG | Debugger.TYPE_CL | Debugger.TYPE_IN],
0xA8: [Debugger.INS.PUSH, Debugger.TYPE_GS | Debugger.TYPE_IN | Debugger.TYPE_80386],
0xA9: [Debugger.INS.POP, Debugger.TYPE_GS | Debugger.TYPE_OUT | Debugger.TYPE_80386],
- 0xAC: [Debugger.INS.SHRD, Debugger.TYPE_MODRM | Debugger.TYPE_WORDV | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_WORDV | Debugger.TYPE_IN, Debugger.TYPE_IMM | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
- 0xAD: [Debugger.INS.SHRD, Debugger.TYPE_MODRM | Debugger.TYPE_WORDV | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_WORDV | Debugger.TYPE_IN, Debugger.TYPE_IMPREG | Debugger.TYPE_CL | Debugger.TYPE_IN]
+ 0xAC: [Debugger.INS.SHRD, Debugger.TYPE_MODRM | Debugger.TYPE_WORDV | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_WORDV | Debugger.TYPE_IN, Debugger.TYPE_IMM | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
+ 0xAD: [Debugger.INS.SHRD, Debugger.TYPE_MODRM | Debugger.TYPE_WORDV | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_WORDV | Debugger.TYPE_IN, Debugger.TYPE_IMPREG | Debugger.TYPE_CL | Debugger.TYPE_IN],
+ 0xB6: [Debugger.INS.MOVZX, Debugger.TYPE_REG | Debugger.TYPE_WORDV | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_MODRM | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
+ 0xB7: [Debugger.INS.MOVZX, Debugger.TYPE_REG | Debugger.TYPE_DWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_MODRM | Debugger.TYPE_WORD | Debugger.TYPE_IN]
};
Debugger.aaGrpDescs = [
@@ -2421,15 +2439,6 @@ if (DEBUGGER) {
this.cInstructions++;
var bOpcode = this.bus.getByteDirect(addr);
this.aaOpcodeCounts[bOpcode][1]++;
-
- /*
- * This is a good example of what NOT to do in a high-frequency function, and defeats
- * the purpose of pre-allocating and pre-initializing the history array in historyInit():
- *
- * this.aOpcodeHistory[this.iOpcodeHistory] = this.newAddr(this.cpu.getIP(), this.cpu.getCS(), addr);
- *
- * As the name implies, newAddr() returns a new "Addr" (Array) object every time it's called.
- */
var a = this.aOpcodeHistory[this.iOpcodeHistory];
a[0] = this.cpu.getIP();
a[1] = this.cpu.getCS();
@@ -4225,18 +4234,23 @@ if (DEBUGGER) {
this.println(n + " instructions earlier:");
}
while (cLines && iHistory != this.iOpcodeHistory) {
- var aAddr = aHistory[iHistory];
+ var aAddr = aHistory[iHistory++];
if (aAddr[1] == null) break;
/*
* We must create a new aAddr from the address we obtained from aHistory, because aAddr
* was a reference, not a copy, and we don't want getInstruction() modifying the original.
- *
- * TODO: By using a new address each time, history dumps will not disassemble 32-bit overrides properly.
*/
aAddr = this.newAddr(aAddr[0], aAddr[1], aAddr[2]);
- this.println(this.getInstruction(aAddr, "history", n));
- if (++iHistory == aHistory.length) iHistory = 0;
- this.nextHistory = --n;
+ this.println(this.getInstruction(aAddr, "history", n--));
+ /*
+ * If there was an OPERAND or ADDRESS override on the previous instruction, getInstruction()
+ * will have automatically disassembled the next instruction, so skip one more history entry.
+ */
+ if (aAddr[6]) {
+ iHistory++; n--;
+ }
+ if (iHistory >= aHistory.length) iHistory = 0;
+ this.nextHistory = n;
cLines--;
}
}
@@ -5039,6 +5053,10 @@ if (DEBUGGER) {
*/
Debugger.prototype.initAddrSize = function(aAddr, fNonPrefix)
{
+ /*
+ * Use aAddr[6] to record whether we previously processed any OPERAND or ADDRESS overrides.
+ */
+ aAddr[6] = (aAddr[4] || aAddr[5]);
/*
* For proper disassembly of instructions preceded by an OPERAND (0x66) size prefix, we set aAddr[4]
* to true whenever the operand size is 32-bit; similarly, for an ADDRESS (0x67) size prefix, we set
@@ -5050,10 +5068,10 @@ if (DEBUGGER) {
aAddr[5] = (this.cpu.segCS.addrSize == 4);
}
/*
- * We also use aAddr[6] to record whether the caller (ie, getInstruction()) is reporting that it
+ * We also use aAddr[7] to record whether the caller (ie, getInstruction()) is reporting that it
* processed a complete instruction (ie, a non-prefix) or not.
*/
- aAddr[6] = fNonPrefix;
+ aAddr[7] = fNonPrefix;
};
/**
@@ -5128,11 +5146,11 @@ if (DEBUGGER) {
var sIns = this.getInstruction(aAddr, sComment, nSequence);
/*
- * If getInstruction() reported that it did not yet process a complete instruction (via aAddr[6]),
+ * If getInstruction() reported that it did not yet process a complete instruction (via aAddr[7]),
* then bump the instruction count by one, so that we display one more line (and hopefully the complete
* instruction).
*/
- if (!aAddr[6] && !n) n++;
+ if (!aAddr[7] && !n) n++;
this.println(sIns);
this.aAddrNextCode = aAddr;
diff --git a/modules/pcjs/lib/fdc.js b/modules/pcjs/lib/fdc.js
index 43a9d64dd..e77a3dab1 100644
--- a/modules/pcjs/lib/fdc.js
+++ b/modules/pcjs/lib/fdc.js
@@ -1203,7 +1203,7 @@ FDC.prototype.loadSelectedDrive = function(sDisketteName, sDiskettePath, file)
}
if (sDiskettePath == "?") {
- this.notice('Use "Choose File" and "Load" to select and load a local disk.');
+ this.notice('Use "Choose File" and "Mount" to select and load a local disk.');
return;
}
@@ -1337,14 +1337,14 @@ FDC.prototype.doneLoadDiskette = function onFDCLoadNotify(drive, disk, sDiskette
/*
* Adding local disk image names to the disk list seems like a nice idea, but it's too confusing,
- * because then it looks like the "Load" button should be able to (re)load them, and that can NEVER
+ * because then it looks like the "Mount" button should be able to (re)load them, and that can NEVER
* happen, for security reasons; local disk images can ONLY be loaded via the "Mount" button after
* the user has selected them via the "Choose File" button.
*
* this.addDiskette(sDisketteName, sDiskettePath);
*
* So we're going to take a different approach: when displayDiskette() is asked to display the name
- * of a local disk image, it will map all such disks to "Local Disk", and any attempt to "Load" such
+ * of a local disk image, it will map all such disks to "Local Disk", and any attempt to "Mount" such
* a disk, will essentially result in a "Disk not found" error.
*/
diff --git a/modules/pcjs/lib/x86func.js b/modules/pcjs/lib/x86func.js
index 4e148e6bf..ba9f53608 100644
--- a/modules/pcjs/lib/x86func.js
+++ b/modules/pcjs/lib/x86func.js
@@ -659,7 +659,7 @@ X86.fnDIVb = function DIVb(dst, src)
* However, src is technically an output, and dst is merely an input (which is why we must return
* dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src.
*/
- if (DEBUG && DEBUGGER) this.traceLog('DIVB', src, dst, null, this.getPS(), this.regMDLo);
+ if (DEBUG && DEBUGGER) this.traceLog('DIVb', src, dst, null, this.getPS(), this.regMDLo);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesDivBR : this.cycleCounts.nOpCyclesDivBM);
this.opFlags |= X86.OPFLAG.NOWRITE;
return dst;
@@ -718,9 +718,9 @@ X86.fnDIVw = function DIVw(dst, src)
*/
if (DEBUG && DEBUGGER) {
if (this.dataSize == 2) {
- this.traceLog('DIVW', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
+ this.traceLog('DIVw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
} else {
- this.traceLog('DIVD', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
+ this.traceLog('DIVd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
}
}
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesDivWR : this.cycleCounts.nOpCyclesDivWM);
@@ -788,7 +788,7 @@ X86.fnIDIVb = function IDIVb(dst, src)
* However, src is technically an output, and dst is merely an input (which is why we must return
* dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src.
*/
- if (DEBUG && DEBUGGER) this.traceLog('IDIVB', src, dst, null, this.getPS(), this.regMDLo);
+ if (DEBUG && DEBUGGER) this.traceLog('IDIVb', src, dst, null, this.getPS(), this.regMDLo);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesIDivBR : this.cycleCounts.nOpCyclesIDivBM);
this.opFlags |= X86.OPFLAG.NOWRITE;
return dst;
@@ -855,9 +855,9 @@ X86.fnIDIVw = function IDIVw(dst, src)
*/
if (DEBUG && DEBUGGER) {
if (this.dataSize == 2) {
- this.traceLog('IDIVW', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
+ this.traceLog('IDIVw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
} else {
- this.traceLog('IDIVD', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
+ this.traceLog('IDIVd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
}
}
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesIDivWR : this.cycleCounts.nOpCyclesIDivWM);
@@ -945,7 +945,7 @@ X86.fnIMULb = function IMULb(dst, src)
* However, src is technically an output, and dst is merely an input (which is why we must return
* dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src.
*/
- if (DEBUG && DEBUGGER) this.traceLog('IMULB', src, dst, null, this.getPS(), this.regMDLo);
+ if (DEBUG && DEBUGGER) this.traceLog('IMULb', src, dst, null, this.getPS(), this.regMDLo);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesIMulBR : this.cycleCounts.nOpCyclesIMulBM);
this.opFlags |= X86.OPFLAG.NOWRITE;
@@ -989,7 +989,7 @@ X86.fnIMULn = function IMULn(dst, src)
}
result &= this.dataMask;
- if (DEBUG && DEBUGGER) this.traceLog('IMULN', dst, src, null, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('IMULn', dst, src, null, this.getPS(), result);
/*
* NOTE: These are the cycle counts for the 80286; the 80186/80188 have slightly different values (ranges):
@@ -1086,9 +1086,9 @@ X86.fnIMULw = function IMULw(dst, src)
*/
if (DEBUG && DEBUGGER) {
if (this.dataSize == 2) {
- this.traceLog('IMULW', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
+ this.traceLog('IMULw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
} else {
- this.traceLog('IMULD', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
+ this.traceLog('IMULd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
}
}
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesIMulWR : this.cycleCounts.nOpCyclesIMulWM);
@@ -1683,7 +1683,7 @@ X86.fnMULb = function MULb(dst, src)
* However, src is technically an output, and dst is merely an input (which is why we must return
* dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src.
*/
- if (DEBUG && DEBUGGER) this.traceLog('MULB', src, dst, null, this.getPS(), this.regMDLo);
+ if (DEBUG && DEBUGGER) this.traceLog('MULb', src, dst, null, this.getPS(), this.regMDLo);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesMulBR : this.cycleCounts.nOpCyclesMulBM);
this.opFlags |= X86.OPFLAG.NOWRITE;
@@ -1760,9 +1760,9 @@ X86.fnMULw = function MULw(dst, src)
*/
if (DEBUG && DEBUGGER) {
if (this.dataSize == 2) {
- this.traceLog('MULW', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
+ this.traceLog('MULw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
} else {
- this.traceLog('MULD', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
+ this.traceLog('MULd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
}
}
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesMulWR : this.cycleCounts.nOpCyclesMulWM);
@@ -1928,7 +1928,7 @@ X86.fnRCLb = function RCLb(dst, src)
}
this.setRotateResult(result, carry, X86.RESULT.BYTE);
}
- if (DEBUG && DEBUGGER) this.traceLog('RCLB', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('RCLb', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -1956,7 +1956,7 @@ X86.fnRCLw = function RCLw(dst, src)
}
this.setRotateResult(result, carry, X86.RESULT.WORD);
}
- if (DEBUG && DEBUGGER) this.traceLog('RCLW', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('RCLw', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -1972,7 +1972,7 @@ X86.fnRCLd = function RCLd(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
- var count = src & this.nShiftCountMask; // Yes, this 32-bit-only function could mask with 0x1f directly
+ var count = src & this.nShiftCountMask; // this 32-bit-only function could mask with 0x1f directly
if (count) {
var carry = this.getCarry();
/*
@@ -1984,7 +1984,7 @@ X86.fnRCLd = function RCLd(dst, src)
carry = dst << (count - 1);
this.setRotateResult(result, carry, X86.RESULT.DWORD);
}
- if (DEBUG && DEBUGGER) this.traceLog('RCLD', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('RCLd', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -2012,7 +2012,7 @@ X86.fnRCRb = function RCRb(dst, src)
}
this.setRotateResult(result, carry, X86.RESULT.BYTE);
}
- if (DEBUG && DEBUGGER) this.traceLog('RCRB', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('RCRb', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -2040,7 +2040,7 @@ X86.fnRCRw = function RCRw(dst, src)
}
this.setRotateResult(result, carry, X86.RESULT.WORD);
}
- if (DEBUG && DEBUGGER) this.traceLog('RCRW', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('RCRw', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -2056,7 +2056,7 @@ X86.fnRCRd = function RCRd(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
- var count = src & this.nShiftCountMask; // Yes, this 32-bit-only function could mask with 0x1f directly
+ var count = src & this.nShiftCountMask; // this 32-bit-only function could mask with 0x1f directly
if (count) {
var carry = this.getCarry();
/*
@@ -2068,7 +2068,7 @@ X86.fnRCRd = function RCRd(dst, src)
carry = dst << (32 - count);
this.setRotateResult(result, carry, X86.RESULT.DWORD);
}
- if (DEBUG && DEBUGGER) this.traceLog('RCRD', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('RCRd', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -2130,12 +2130,12 @@ X86.fnROLb = function ROLb(dst, src)
if (!count) {
carry = dst << 7;
} else {
- result = ((dst << count) | (dst >> (8 - count))) & 0xff;
carry = dst << (count - 1);
+ result = ((dst << count) | (dst >> (8 - count))) & 0xff;
}
this.setRotateResult(result, carry, X86.RESULT.BYTE);
}
- if (DEBUG && DEBUGGER) this.traceLog('ROLB', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('ROLb', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -2158,12 +2158,34 @@ X86.fnROLw = function ROLw(dst, src)
if (!count) {
carry = dst << 15;
} else {
- result = ((dst << count) | (dst >> (16 - count))) & 0xffff;
carry = dst << (count - 1);
+ result = ((dst << count) | (dst >> (16 - count))) & 0xffff;
}
this.setRotateResult(result, carry, X86.RESULT.WORD);
}
- if (DEBUG && DEBUGGER) this.traceLog('ROLW', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('ROLw', dst, src, flagsIn, this.getPS(), result);
+ return result;
+};
+
+/**
+ * fnROLd(dst, src)
+ *
+ * @this {X86CPU}
+ * @param {number} dst
+ * @param {number} src (1 or CL)
+ * @return {number}
+ */
+X86.fnROLd = function ROLd(dst, src)
+{
+ var result = dst;
+ var flagsIn = (DEBUG? this.getPS() : 0);
+ var count = src & this.nShiftCountMask;
+ if (count) {
+ var carry = dst << (count - 1);
+ result = (dst << count) | (dst >>> (32 - count));
+ this.setRotateResult(result, carry, X86.RESULT.DWORD);
+ }
+ if (DEBUG && DEBUGGER) this.traceLog('ROLd', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -2186,12 +2208,12 @@ X86.fnRORb = function RORb(dst, src)
if (!count) {
carry = dst;
} else {
- result = ((dst >> count) | (dst << (8 - count))) & 0xff;
carry = dst << (8 - count);
+ result = ((dst >>> count) | carry) & 0xff;
}
this.setRotateResult(result, carry, X86.RESULT.BYTE);
}
- if (DEBUG && DEBUGGER) this.traceLog('RORB', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('RORb', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -2214,12 +2236,34 @@ X86.fnRORw = function RORw(dst, src)
if (!count) {
carry = dst;
} else {
- result = ((dst >> count) | (dst << (16 - count))) & 0xffff;
carry = dst << (16 - count);
+ result = ((dst >>> count) | carry) & 0xffff;
}
this.setRotateResult(result, carry, X86.RESULT.WORD);
}
- if (DEBUG && DEBUGGER) this.traceLog('RORW', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('RORw', dst, src, flagsIn, this.getPS(), result);
+ return result;
+};
+
+/**
+ * fnRORd(dst, src)
+ *
+ * @this {X86CPU}
+ * @param {number} dst
+ * @param {number} src (1 or CL)
+ * @return {number}
+ */
+X86.fnRORd = function RORd(dst, src)
+{
+ var result = dst;
+ var flagsIn = (DEBUG? this.getPS() : 0);
+ var count = src & this.nShiftCountMask;
+ if (count) {
+ var carry = dst << (32 - count);
+ result = (dst >>> count) | carry;
+ this.setRotateResult(result, carry, X86.RESULT.DWORD);
+ }
+ if (DEBUG && DEBUGGER) this.traceLog('RORd', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -2235,7 +2279,7 @@ X86.fnSARb = function SARb(dst, src)
{
var count = src & this.nShiftCountMask;
if (count) {
- if (count > 8) count = 9;
+ if (count > 9) count = 9;
var carry = ((dst << 24) >> 24) >> (count - 1);
dst = (carry >> 1) & 0xff;
this.setLogicResult(dst, X86.RESULT.BYTE, carry & 0x1);
@@ -2255,7 +2299,7 @@ X86.fnSARw = function SARw(dst, src)
{
var count = src & this.nShiftCountMask;
if (count) {
- if (count > 16) count = 17;
+ if (count > 17) count = 17;
var carry = ((dst << 16) >> 16) >> (count - 1);
dst = (carry >> 1) & 0xffff;
this.setLogicResult(dst, X86.RESULT.WORD, carry & 0x1);
@@ -2263,6 +2307,25 @@ X86.fnSARw = function SARw(dst, src)
return dst;
};
+/**
+ * fnSARd(dst, src)
+ *
+ * @this {X86CPU}
+ * @param {number} dst
+ * @param {number} src (1 or CL, or an immediate byte for 80186/80188 and up)
+ * @return {number}
+ */
+X86.fnSARd = function SARd(dst, src)
+{
+ var count = src & this.nShiftCountMask;
+ if (count) {
+ var carry = dst >> (count - 1);
+ dst = (carry >> 1);
+ this.setLogicResult(dst, X86.RESULT.DWORD, carry & 0x1);
+ }
+ return dst;
+};
+
/**
* fnSBBb(dst, src)
*
@@ -2596,7 +2659,7 @@ X86.fnSHLb = function SHLb(dst, src)
}
this.setLogicResult(result, X86.RESULT.BYTE, carry & X86.RESULT.BYTE, (result ^ carry) & X86.RESULT.BYTE);
}
- if (DEBUG && DEBUGGER) this.traceLog('SHLB', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('SHLb', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -2623,7 +2686,29 @@ X86.fnSHLw = function SHLw(dst, src)
}
this.setLogicResult(result, X86.RESULT.WORD, carry & X86.RESULT.WORD, (result ^ carry) & X86.RESULT.WORD);
}
- if (DEBUG && DEBUGGER) this.traceLog('SHLW', dst, src, flagsIn, this.getPS(), result);
+ if (DEBUG && DEBUGGER) this.traceLog('SHLw', dst, src, flagsIn, this.getPS(), result);
+ return result;
+};
+
+/**
+ * fnSHLd(dst, src)
+ *
+ * @this {X86CPU}
+ * @param {number} dst
+ * @param {number} src (1 or CL, or an immediate byte for 80186/80188 and up)
+ * @return {number}
+ */
+X86.fnSHLd = function SHLd(dst, src)
+{
+ var result = dst;
+ var flagsIn = (DEBUG? this.getPS() : 0);
+ var count = src & this.nShiftCountMask; // this 32-bit-only function could mask with 0x1f directly
+ if (count) {
+ var carry = dst << (count - 1);
+ result = (carry << 1);
+ this.setLogicResult(result, X86.RESULT.DWORD, carry & X86.RESULT.DWORD, (result ^ carry) & X86.RESULT.DWORD);
+ }
+ if (DEBUG && DEBUGGER) this.traceLog('SHLd', dst, src, flagsIn, this.getPS(), result);
return result;
};
@@ -2733,8 +2818,8 @@ X86.fnSHRb = function SHRb(dst, src)
{
var count = src & this.nShiftCountMask;
if (count) {
- var carry = (count > 8? 0 : (dst >> (count - 1)));
- dst = (carry >> 1) & 0xff;
+ var carry = (count > 8? 0 : (dst >>> (count - 1)));
+ dst = (carry >>> 1) & 0xff;
this.setLogicResult(dst, X86.RESULT.BYTE, carry & 0x1, dst & X86.RESULT.BYTE);
}
return dst;
@@ -2752,13 +2837,32 @@ X86.fnSHRw = function SHRw(dst, src)
{
var count = src & this.nShiftCountMask;
if (count) {
- var carry = (count > 16? 0 : (dst >> (count - 1)));
- dst = (carry >> 1) & 0xffff;
+ var carry = (count > 16? 0 : (dst >>> (count - 1)));
+ dst = (carry >>> 1) & 0xffff;
this.setLogicResult(dst, X86.RESULT.WORD, carry & 0x1, dst & X86.RESULT.WORD);
}
return dst;
};
+/**
+ * fnSHRd(dst, src)
+ *
+ * @this {X86CPU}
+ * @param {number} dst
+ * @param {number} src (1 or CL, or an immediate byte for 80186/80188 and up)
+ * @return {number}
+ */
+X86.fnSHRd = function SHRd(dst, src)
+{
+ var count = src & this.nShiftCountMask;
+ if (count) {
+ var carry = (dst >>> (count - 1));
+ dst = (carry >>> 1);
+ this.setLogicResult(dst, X86.RESULT.DWORD, carry & 0x1, dst & X86.RESULT.DWORD);
+ }
+ return dst;
+};
+
/**
* fnSHRDw(dst, src, count)
*
diff --git a/modules/pcjs/lib/x86ops.js b/modules/pcjs/lib/x86ops.js
index 811d94749..935f941f8 100644
--- a/modules/pcjs/lib/x86ops.js
+++ b/modules/pcjs/lib/x86ops.js
@@ -4146,18 +4146,18 @@ X86.aOpGrpMOVn = [
];
X86.aOpGrp2b = [
- X86.fnROLb, X86.fnRORb, X86.fnRCLb, X86.fnRCRb, // 0xD0/0xD2(reg=0x0-0x3)
- X86.fnSHLb, X86.fnSHRb, X86.fnGRPUndefined, X86.fnSARb // 0xD0/0xD2(reg=0x4-0x7)
+ X86.fnROLb, X86.fnRORb, X86.fnRCLb, X86.fnRCRb, // 0xC0/0xD0/0xD2(reg=0x0-0x3)
+ X86.fnSHLb, X86.fnSHRb, X86.fnGRPUndefined, X86.fnSARb // 0xC0/0xD0/0xD2(reg=0x4-0x7)
];
X86.aOpGrp2w = [
- X86.fnROLw, X86.fnRORw, X86.fnRCLw, X86.fnRCRw, // 0xD1/0xD3(reg=0x0-0x3)
- X86.fnSHLw, X86.fnSHRw, X86.fnGRPUndefined, X86.fnSARw // 0xD1/0xD3(reg=0x4-0x7)
+ X86.fnROLw, X86.fnRORw, X86.fnRCLw, X86.fnRCRw, // 0xC1/0xD1/0xD3(reg=0x0-0x3)
+ X86.fnSHLw, X86.fnSHRw, X86.fnGRPUndefined, X86.fnSARw // 0xC1/0xD1/0xD3(reg=0x4-0x7)
];
X86.aOpGrp2d = [
- X86.fnTBD, X86.fnTBD, X86.fnRCLd, X86.fnRCRd, // 0xD1/0xD3(reg=0x0-0x3)
- X86.fnTBD, X86.fnTBD, X86.fnGRPUndefined, X86.fnTBD // 0xD1/0xD3(reg=0x4-0x7)
+ X86.fnROLd, X86.fnRORd, X86.fnRCLd, X86.fnRCRd, // 0xC1/0xD1/0xD3(reg=0x0-0x3)
+ X86.fnSHLd, X86.fnSHRd, X86.fnGRPUndefined, X86.fnSARd // 0xC1/0xD1/0xD3(reg=0x4-0x7)
];
X86.aOpGrp3b = [
diff --git a/modules/pcjs/lib/x86seg.js b/modules/pcjs/lib/x86seg.js
index 131edb16d..4f6ad17e6 100644
--- a/modules/pcjs/lib/x86seg.js
+++ b/modules/pcjs/lib/x86seg.js
@@ -54,13 +54,12 @@ function X86Seg(cpu, id, sName, fProt)
this.id = id;
this.sName = sName || "";
this.sel = 0;
- this.base = 0;
- this.limit = 0xffff;
- this.acc = 0;
- this.ext = 0;
+ this.limit = 0xffff; // in protected-mode, this is descriptor word 0x0 (word 0x6 on the 80386 supplements limit bits 16-19)
+ this.base = 0; // in protected-mode, this is descriptor word 0x2 (word 0x6 on the 80386 supplements base bits 24-31)
+ this.acc = 0; // in protected-mode, this is descriptor word 0x4, masked with 0xff00 (bits 0-7 supplement base bits 16-23)
+ this.ext = 0; // in protected-mode, this is descriptor word 0x6 (used only on the 80386)
+ this.cpl = this.dpl = 0;
this.addrDesc = X86.ADDR_INVALID;
- this.cpl = 0;
- this.dpl = 0;
/*
* The following properties are used for CODE segments only (ie, segCS); if the process of loading
* CS also requires a stack switch, then fStackSwitch will be set to true; additionally, if the stack
@@ -839,6 +838,15 @@ X86Seg.prototype.updateMode = function(fProt)
}
this.fExpDown = false;
if (fProt) {
+ /*
+ * If we've just transitioned from real-mode, then CPL (which is meaningful for segCS only)
+ * should be left alone (ie, should remain at zero). On the first protected-mode CS selector
+ * load (normally an intersegment JMP immediately following the protected-mode switch), CPL
+ * (along with the rest of the segment settings) will be properly set.
+ */
+ if (this.load !== this.loadReal) {
+ this.cpl = this.sel & X86.SEL.RPL;
+ }
this.load = this.loadProt;
this.loadIDT = this.loadIDTProt;
this.checkRead = this.checkReadProt;
@@ -865,7 +873,6 @@ X86Seg.prototype.updateMode = function(fProt)
this.fExpDown = true;
}
}
- this.cpl = this.sel & X86.SEL.RPL;
this.dpl = (this.acc & X86.DESC.ACC.DPL.MASK) >> X86.DESC.ACC.DPL.SHIFT;
if (this.cpu.model < X86.MODEL_80386 || !(this.ext & X86.DESC.EXT.BIG)) {
this.addrSize = 2;
@@ -880,6 +887,7 @@ X86Seg.prototype.updateMode = function(fProt)
this.checkRead = this.checkReadReal;
this.checkWrite = this.checkWriteReal;
this.limit = 0xffff;
+ this.acc = this.ext = 0;
this.cpl = this.dpl = 0;
this.addrDesc = X86.ADDR_INVALID;
this.addrSize = 2;
diff --git a/modules/pcjs/templates/components.xsl b/modules/pcjs/templates/components.xsl
index 53ee610ca..9f6e7682a 100644
--- a/modules/pcjs/templates/components.xsl
+++ b/modules/pcjs/templates/components.xsl
@@ -377,7 +377,7 @@