More 80386 instructions and more 80386 Debugger support

This commit is contained in:
Jeff Parsons 2015-04-30 13:27:43 -07:00 committed by jeffpar
commit 051e12c87e
15 changed files with 220 additions and 90 deletions

View file

@ -13,7 +13,7 @@
<debugger id="debugger" messages="fault|port" commands=""/>
<panel ref="/devices/pc/panel/btpanel.xml"/>
<fdc ref="/disks/pc/library.xml" width="340px" automount='{A: {name: "PC-DOS 3.00 (Disk 1)", path: "/disks/pc/dos/ibm/3.00/PCDOS300-DISK1.json"}, B: {name: "PC-DOS 3.00 (Disk 2)", path: "/disks/pc/dos/ibm/3.00/PCDOS300-DISK2.json"}}'/>
<hdc id="hdcAT" type="at" drives='[{name:"20Mb Hard Disk",type:2}]'/>
<hdcFoo id="hdcAT" type="at" drives='[{name:"20Mb Hard Disk",type:2}]'/>
<chipset id="chipset" model="deskpro386" floppies="[1200,1200]"/>
<serial id="com1" adapter="1"/>
<serial id="com2" adapter="2" binding="print"/>

View file

@ -18,7 +18,7 @@
<disk path="">None</disk>
<manifest ref="/disks/pc/cpm/manifest.xml" disk="*"/>
</control>
<control type="button" binding="loadDrive">Load Drive</control>
<control type="button" binding="loadDrive">Load</control>
<control type="description" binding="descDisk" padleft="8px"/>
</fdc>
<chipset id="chipset" model="5150" sw1="01000001" sw2="11110000"/>

View file

@ -21,7 +21,7 @@
<manifest ref="/disks/pc/dos/ibm/2.00/manifest.xml" disk="*"/>
<manifest ref="/disks/pc/diags/ibm/2.20/manifest.xml" disk="*"/>
</control>
<control type="button" binding="loadDrive">Load Drive</control>
<control type="button" binding="loadDrive">Load</control>
<control type="description" binding="descDisk" padleft="8px"/>
</fdc>
<chipset id="chipset" model="5150" sw1="01000001" sw2="11110000"/>

View file

@ -50,7 +50,7 @@
<manifest ref="/apps/pc/1987/thinktank/manifest.xml" disk="disk01"/>
<manifest ref="/apps/pc/1992/moria/manifest.xml" disk="disk01"/>
</control>
<control type="button" binding="loadDrive" padright="8px">Download</control>
<control type="button" binding="loadDrive" padright="8px">Load</control>
<control type="description" binding="descDisk" padright="8px"/>
<control type="file" binding="mountDrive"/>
</fdc>

View file

@ -9,7 +9,7 @@
<manifest ref="/disks/pc/games/microsoft/adventure/manifest.xml" disk="*"/>
<manifest ref="/apps/pc/1981/visicalc/manifest.xml" disk="*"/>
</control>
<control type="button" binding="loadDrive" padright="8px">Download</control>
<control type="button" binding="loadDrive" padright="8px">Load</control>
<control type="description" binding="descDisk" padright="8px"/>
<control type="file" binding="mountDrive"/>
</fdc>

View file

@ -16,6 +16,6 @@
<disk path="/disks/pc/windows/1.03/05-APPS/">Windows 1.03 (APPS)</disk>
<disk path="/disks/pc/windows/1.03/06-WRITE/">Windows 1.03 (WRITE)</disk>
</control>
<control type="button" binding="loadDrive">Load Drive</control>
<control type="button" binding="loadDrive">Load</control>
<control type="description" binding="descDisk" padleft="8px"/>
</fdc>

View file

@ -20,7 +20,7 @@
<disk path="">None</disk>
<disk path="PCDOS100.json">PC-DOS 1.00</disk>
</control>
<control type="button" binding="loadDrive">Load Drive</control>
<control type="button" binding="loadDrive">Load</control>
</control>
</fdc>
<chipset id="chipset" model="5150" sw1="01000001" sw2="11110000"/>

View file

@ -60,7 +60,7 @@
<disk path="PCDOS100.json">PC-DOS 1.00</disk>
<disk path="visicalc.json" href="http://www.bricklin.com/history/vclicense.htm" desc="VisiCalc License">VisiCalc</disk>
</control>
<control type="button" binding="loadDrive">Load Drive</control>
<control type="button" binding="loadDrive">Load</control>
<control type="description" binding="descDisk" padleft="8px"/>
</control>
</fdc>

View file

@ -289,7 +289,7 @@
<form class="{$APPCLASS}-binding" style="{$border}{$width}{$height}{$style}" data-value="{$type},{$binding}">
<fieldset class="{$APPCLASS}-fieldset">
<input type="file"/>
<input type="submit" value="Load" disabled="true"/>
<input type="submit" value="Mount" disabled="true"/>
</fieldset>
</form>
</xsl:when>

View file

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

View file

@ -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.
*/

View file

@ -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)
*

View file

@ -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 = [

View file

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

View file

@ -377,7 +377,7 @@
<form class="{$APPCLASS}-binding" data-value="{$type},{$binding}">
<fieldset class="{$APPCLASS}-fieldset">
<input type="file"/>
<input type="submit" value="Load" disabled="true"/>
<input type="submit" value="Mount" disabled="true"/>
</fieldset>
</form>
</xsl:when>