Re-enable PREFTECH, fix IP limit checking, and restore support for autoMount overrides

This commit is contained in:
Jeff Parsons 2016-03-09 09:47:17 -08:00
commit 81c4b61522
10 changed files with 2648 additions and 2644 deletions

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/versions/pcjs/1.21.0/machine.xsl"?> <?xml-stylesheet type="text/xsl" href="/versions/pcjs/1.21.0/machine.xsl"?>
<machine id="deskpro386" class="pc" border="1" pos="center" background="#FAEBD7"> <machine id="deskpro386" class="pc" border="1" pos="center" background="#FAEBD7">
<name pos="center">COMPAQ DeskPro 386, 2Mb RAM, COMPAQ EGA</name> <name pos="center">COMPAQ DeskPro 386, 2Mb RAM, 128Kb EGA</name>
<computer id="deskpro386-ega-2048k" name="COMPAQ DeskPro 386" buswidth="32"/> <computer id="deskpro386-ega-2048k" name="COMPAQ DeskPro 386" buswidth="32"/>
<cpu id="cpu386" model="80386" autostart="false"/> <cpu id="cpu386" model="80386" autostart="false"/>
<ram id="ramLow" addr="0x00000" test="false" size="0xa0000" comment="ROM BIOS memory test has been disabled"/> <ram id="ramLow" addr="0x00000" test="false" size="0xa0000" comment="ROM BIOS memory test has been disabled"/>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/versions/pcjs/1.21.0/machine.xsl"?> <?xml-stylesheet type="text/xsl" href="/versions/pcjs/1.21.0/machine.xsl"?>
<machine id="deskpro386" class="pc" border="1" pos="center" background="#FAEBD7"> <machine id="deskpro386" class="pc" border="1" pos="center" background="#FAEBD7">
<name pos="center">COMPAQ DeskPro 386, 4Mb RAM, COMPAQ EGA</name> <name pos="center">COMPAQ DeskPro 386, 4Mb RAM, 128Kb EGA</name>
<computer id="deskpro386-ega-2048k" name="COMPAQ DeskPro 386" buswidth="32"/> <computer id="deskpro386-ega-2048k" name="COMPAQ DeskPro 386" buswidth="32"/>
<cpu id="cpu386" model="80386" autostart="false"/> <cpu id="cpu386" model="80386" autostart="false"/>
<ram id="ramLow" addr="0x00000" test="false" size="0xa0000" comment="ROM BIOS memory test has been disabled"/> <ram id="ramLow" addr="0x00000" test="false" size="0xa0000" comment="ROM BIOS memory test has been disabled"/>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -332,7 +332,7 @@ MarkOut.aHTMLEntities = {
* 'config' (eg, "machine.xml") * 'config' (eg, "machine.xml")
* 'template' (eg, "machine.xsl") * 'template' (eg, "machine.xsl")
* 'uncompiled' (eg, true) * 'uncompiled' (eg, true)
* 'automount' (eg, {"A":{"name":"OS/2 FOOTBALL Boot Disk (v7.68.17)","path":"/disks/pc/os2/misc/football/debugger/FOOTBALL-7.68.17.json"}}) * 'autoMount' (eg, {"A":{"name":"OS/2 FOOTBALL Boot Disk (v7.68.17)","path":"/disks/pc/os2/misc/football/debugger/FOOTBALL-7.68.17.json"}})
* 'parms' * 'parms'
* *
* Non-reserved properties include: * Non-reserved properties include:
@ -356,7 +356,7 @@ MarkOut.aHTMLEntities = {
MarkOut.aFMBooleanMachineProps = { MarkOut.aFMBooleanMachineProps = {
'autopower': "autoPower" 'autopower': "autoPower"
}; };
MarkOut.aFMReservedMachineProps = ['id', 'name', 'type', 'debugger', 'config', 'template', 'uncompiled', 'automount', 'parms']; MarkOut.aFMReservedMachineProps = ['id', 'name', 'type', 'debugger', 'config', 'template', 'uncompiled', 'autoMount', 'parms'];
/** /**
* convertMD() * convertMD()
@ -436,17 +436,18 @@ MarkOut.prototype.convertMD = function(sIndent)
} }
for (var iOption = 0; iOption < aaOptions.length; iOption++) { for (var iOption = 0; iOption < aaOptions.length; iOption++) {
aOptions = aaOptions[iOption]; aOptions = aaOptions[iOption];
var sSpace = aOptions[1], sName = aOptions[2], sValue = aOptions[3]; var sSpace = aOptions[1], sName = aOptions[2].toLowerCase(), sValue = aOptions[3];
if (sName == 'automount') sName = 'autoMount'; // for backward compatibility
if (!id && sName == 'id') { if (!id && sName == 'id') {
id = sValue; id = sValue;
} else if (sName == 'automount') { } else if (sName == 'autoMount') {
/* /*
* I take a simplistic approach to parsing the object definition associated with "automount", * I take a simplistic approach to parsing the object definition associated with "autoMount",
* because I know it only consists of 1 or more drive letters, each of which may be followed * because I know it only consists of 1 or more drive letters, each of which may be followed
* by 1 or 2 additional properties (eg, "name" and "path"). If we need to support other JSON * by 1 or 2 additional properties (eg, "name" and "path"). If we need to support other JSON
* object definitions in the future, this will have to be generalized. * object definitions in the future, this will have to be generalized.
* *
* Here's an example of "automount" output: * Here's an example of "autoMount" output:
* *
* {"A":{"name":"OS/2 FOOTBALL Boot Disk (v7.68.17)","path":"/disks/pc/os2/misc/football/debugger/FOOTBALL-7.68.17.json"}} * {"A":{"name":"OS/2 FOOTBALL Boot Disk (v7.68.17)","path":"/disks/pc/os2/misc/football/debugger/FOOTBALL-7.68.17.json"}}
* *
@ -477,7 +478,7 @@ MarkOut.prototype.convertMD = function(sIndent)
machine[sName] = sValue; machine[sName] = sValue;
} }
/* /*
* Any "non-reserved" properties are now merged into the 'parms' property; 'automount' * Any "non-reserved" properties are now merged into the 'parms' property; 'autoMount'
* is treated as reserved only because it must be encoded as an object rather than a string. * is treated as reserved only because it must be encoded as an object rather than a string.
*/ */
machine['parms'] = '{'; machine['parms'] = '{';
@ -490,7 +491,7 @@ MarkOut.prototype.convertMD = function(sIndent)
machine['parms'] += sProp + ':"' + machine[sProp] + '",'; machine['parms'] += sProp + ':"' + machine[sProp] + '",';
} }
} }
machine['parms'] += 'autoMount:' + machine['automount'] + '}'; machine['parms'] += 'autoMount:' + machine['autoMount'] + '}';
if (id) this.aMachineDefs[id] = machine; if (id) this.aMachineDefs[id] = machine;
} }
} }

View file

@ -529,9 +529,15 @@ CPU.prototype.setFocus = function()
* into view. The CPU is not a visual component, so when the CPU wants to set focus, the primary intent * into view. The CPU is not a visual component, so when the CPU wants to set focus, the primary intent
* is to ensure that keyboard input is fielded properly. * is to ensure that keyboard input is fielded properly.
*/ */
var x = window.scrollX, y = window.scrollY; var x = 0, y = 0;
if (window) {
x = window.scrollX;
y = window.scrollY;
}
this.aVideo[0].setFocus(); this.aVideo[0].setFocus();
window.scrollTo(x, y); if (window) {
window.scrollTo(x, y);
}
} }
}; };

View file

@ -59,7 +59,7 @@ var DEBUGGER = true; // this @define is overridden by the Closure Com
* but as currently implemented, it does not yield as much improvement as I'd hoped when paging is enabled, so PREFETCH * but as currently implemented, it does not yield as much improvement as I'd hoped when paging is enabled, so PREFETCH
* is still off by default. * is still off by default.
*/ */
var PREFETCH = false; var PREFETCH = true;
/** /**
* @define {boolean} * @define {boolean}

View file

@ -2190,8 +2190,8 @@ X86CPU.prototype.setIP = function(off)
*/ */
X86CPU.prototype.setLIP = function(addr) X86CPU.prototype.setLIP = function(addr)
{ {
this.regLIP = addr|0; this.regLIP = addr;
this.regLIPLimit = (this.segCS.base + this.segCS.limit)|0; this.regLIPMax = (this.segCS.base >>> 0) + (this.segCS.limit >>> 0) + 1;
/* /*
* TODO: Verify the proper source for CPL. Should it come from segCS.cpl or segCS.dpl? * TODO: Verify the proper source for CPL. Should it come from segCS.cpl or segCS.dpl?
@ -2230,8 +2230,7 @@ X86CPU.prototype.setLIP = function(addr)
X86CPU.prototype.setCSIP = function(off, sel, fCall) X86CPU.prototype.setCSIP = function(off, sel, fCall)
{ {
/* /*
* We break this operation into the following discrete steps (eg, set IP, load CS, and then update IP) so * Setting IP needs to occur AFTER loadCode(), because it may differ from the given IP if sel refers to a gate.
* that segCS.load(sel) has the ability to modify IP when sel refers to a gate (call, interrupt, trap, etc).
*/ */
var base = this.segCS.loadCode(off, sel, fCall); var base = this.segCS.loadCode(off, sel, fCall);
if (base !== X86.ADDR_INVALID) { if (base !== X86.ADDR_INVALID) {
@ -2254,61 +2253,41 @@ X86CPU.prototype.setCSBase = function(addr)
var regIP = this.getIP(); var regIP = this.getIP();
addr = this.segCS.setBase(addr); addr = this.segCS.setBase(addr);
this.regLIP = (addr + regIP)|0; this.regLIP = (addr + regIP)|0;
this.regLIPLimit = (addr + this.segCS.limit)|0; this.regLIPMax = (addr >>> 0) + (this.segCS.limit >>> 0) + 1;
}; };
/** /**
* advanceIP(inc) * checkIP(inc)
*
* TODO: If we didn't care about compatibility, we could just return:
*
* (this.regLIP + inc)|0
*
* and be done with it, because there probably isn't any "good" code that triggers the
* "newLIP > this.regLIPMax" condition. This check costs us about 2Mhz performance on an 80386.
*
* Turning PREFETCH on tends to offset this performance hit, but PREFETCH *without* this hit would
* probably perform even better.
* *
* @this {X86CPU} * @this {X86CPU}
* @param {number} inc (positive) * @param {number} inc (positive)
* @return {number} new LIP
*/ */
X86CPU.prototype.advanceIP = function(inc) X86CPU.prototype.checkIP = function(inc)
{ {
// DEBUG: this.assert(inc > 0); var newLIP = (this.regLIP >>> 0) + inc;
if (newLIP > this.regLIPMax) {
this.regLIP = (this.regLIP + inc)|0;
/*
* Properly comparing regLIP to regLIPLimit would normally require coercing both to unsigned
* (ie, floating-point) values. But instead, we do a subtraction, (regLIPLimit - regLIP), and
* if the result is negative, we need only be concerned if the signs of both numbers are the same
* (ie, the sign of their XOR'ed union is positive).
*
* TODO: I'm combining the old 8088 address-wrap check with the new segment-limit check,
* even though the correct time to do the latter is immediately BEFORE a fetch, not AFTER; eg,
* consider the following code:
*
* AX=0100 BX=0015 CX=0080 DX=F859 SP=0A62 BP=0A98 SI=0000 DI=0000
* SS=0038[1759E0,0B5F] DS=02E8[0107A0,017F] ES=0970[009700,6949] A20=ON
* CS=02E0[010080,06FB] LD=0028[000000,0000] GD=[11AEE0,4977] ID=[120082,03FF]
* TR=0010 MS=FFF3 PS=3202 V0 D0 I1 T0 S0 Z0 A0 P0 C0
* 02E0:06F9 C20400 RET 0004
*
* After fetching the 3rd byte of the "RET 0004" instruction at CS:06FB, the CPU wants to automatically
* advance IP to 06FC, which of course, exceeds the limit, but that doesn't matter unless we actually
* fetch a byte from 06FC, which won't happen. I'm working around this for now by applying a -1
* fudge factor to the fault check below.
*/
if (DEBUG) {
/* /*
* TODO: This isn't DEBUG code, but it also isn't strictly necessary for properly written code, * There's no such thing as a GP fault on the 8086/8088, and I'm assuming that,
* and it hurts performance. Since this effectively turns advanceIP() into a one-line function for * on newer processors, when the segment limit is the maximum, it's OK for IP to wrap.
* non-DEBUG builds, it should automatically get inlined (either at compile-time by the Closure Compiler
* or at run-time by whatever JavaScript engine you're using).
*/ */
var off = (this.regLIPLimit - this.regLIP)|0; if (this.model <= X86.MODEL_8088 || this.segCS.limit == this.segCS.maskAddr) {
if (off < 0 && (this.regLIPLimit ^ this.regLIP) >= 0) { newLIP = this.segCS.base + ((newLIP - this.regLIPMax) & (I386? this.maskData : 0xffff));
/* } else {
* There's no such thing as a GP fault on the 8086/8088, and I'm assuming that, on newer X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
* processors, when the segment limit is set to the maximum, it's OK for IP to wrap.
*/
if (this.model <= X86.MODEL_8088 || this.segCS.limit == this.segCS.maskAddr) {
this.setIP(this.regLIP - this.segCS.base);
} else if (off < -1) { // fudge factor
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
}
} }
} }
return newLIP|0;
}; };
/** /**
@ -3704,9 +3683,10 @@ X86CPU.prototype.refillPrefetch = function()
*/ */
X86CPU.prototype.getIPByte = function() X86CPU.prototype.getIPByte = function()
{ {
var newLIP = this.checkIP(1);
var b = (PREFETCH? this.getBytePrefetch() : this.getByte(this.regLIP)); var b = (PREFETCH? this.getBytePrefetch() : this.getByte(this.regLIP));
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0); if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.advanceIP(1); this.regLIP = newLIP;
return b; return b;
}; };
@ -3718,12 +3698,13 @@ X86CPU.prototype.getIPByte = function()
*/ */
X86CPU.prototype.getIPShort = function() X86CPU.prototype.getIPShort = function()
{ {
var newLIP = this.checkIP(2);
var w = (PREFETCH? this.getShortPrefetch() : this.getShort(this.regLIP)); var w = (PREFETCH? this.getShortPrefetch() : this.getShort(this.regLIP));
if (BACKTRACK) { if (BACKTRACK) {
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0); this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1); this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1);
} }
this.advanceIP(2); this.regLIP = newLIP;
return w; return w;
}; };
@ -3735,6 +3716,7 @@ X86CPU.prototype.getIPShort = function()
* *
X86CPU.prototype.getIPLong = function() X86CPU.prototype.getIPLong = function()
{ {
var newLIP = this.checkIP(4);
var l = (PREFETCH? this.getLongPrefetch() : this.getLong(this.regLIP)); var l = (PREFETCH? this.getLongPrefetch() : this.getLong(this.regLIP));
if (BACKTRACK) { if (BACKTRACK) {
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0); this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
@ -3742,7 +3724,7 @@ X86CPU.prototype.getIPLong = function()
this.bus.updateBackTrackCode(this.regLIP + 2, this.backTrack.btiMem2); this.bus.updateBackTrackCode(this.regLIP + 2, this.backTrack.btiMem2);
this.bus.updateBackTrackCode(this.regLIP + 3, this.backTrack.btiMem3); this.bus.updateBackTrackCode(this.regLIP + 3, this.backTrack.btiMem3);
} }
this.advanceIP(4); this.regLIP = newLIP;
return l; return l;
}; };
*/ */
@ -3755,12 +3737,13 @@ X86CPU.prototype.getIPLong = function()
*/ */
X86CPU.prototype.getIPAddr = function() X86CPU.prototype.getIPAddr = function()
{ {
var newLIP = this.checkIP(this.sizeAddr);
var w = (PREFETCH? this.getAddr() : this.getAddr(this.regLIP)); var w = (PREFETCH? this.getAddr() : this.getAddr(this.regLIP));
if (BACKTRACK) { if (BACKTRACK) {
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0); this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1); this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1);
} }
this.advanceIP(this.sizeAddr); this.regLIP = newLIP;
return w; return w;
}; };
@ -3772,12 +3755,13 @@ X86CPU.prototype.getIPAddr = function()
*/ */
X86CPU.prototype.getIPWord = function() X86CPU.prototype.getIPWord = function()
{ {
var newLIP = this.checkIP(this.sizeData);
var w = (PREFETCH? this.getWordPrefetch() : this.getWord(this.regLIP)); var w = (PREFETCH? this.getWordPrefetch() : this.getWord(this.regLIP));
if (BACKTRACK) { if (BACKTRACK) {
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0); this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1); this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1);
} }
this.advanceIP(this.sizeData); this.regLIP = newLIP;
return w; return w;
}; };
@ -3789,9 +3773,10 @@ X86CPU.prototype.getIPWord = function()
*/ */
X86CPU.prototype.getIPDisp = function() X86CPU.prototype.getIPDisp = function()
{ {
var newLIP = this.checkIP(1);
var w = ((PREFETCH? this.getBytePrefetch() : this.getByte(this.regLIP)) << 24) >> 24; var w = ((PREFETCH? this.getBytePrefetch() : this.getByte(this.regLIP)) << 24) >> 24;
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0); if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.advanceIP(1); this.regLIP = newLIP;
return w; return w;
}; };

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff