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 @@
- +