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-stylesheet type="text/xsl" href="/versions/pcjs/1.21.0/machine.xsl"?>
<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"/>
<cpu id="cpu386" model="80386" autostart="false"/>
<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-stylesheet type="text/xsl" href="/versions/pcjs/1.21.0/machine.xsl"?>
<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"/>
<cpu id="cpu386" model="80386" autostart="false"/>
<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")
* 'template' (eg, "machine.xsl")
* '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'
*
* Non-reserved properties include:
@ -356,7 +356,7 @@ MarkOut.aHTMLEntities = {
MarkOut.aFMBooleanMachineProps = {
'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()
@ -436,17 +436,18 @@ MarkOut.prototype.convertMD = function(sIndent)
}
for (var iOption = 0; iOption < aaOptions.length; 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') {
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
* 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.
*
* 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"}}
*
@ -477,7 +478,7 @@ MarkOut.prototype.convertMD = function(sIndent)
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.
*/
machine['parms'] = '{';
@ -490,7 +491,7 @@ MarkOut.prototype.convertMD = function(sIndent)
machine['parms'] += sProp + ':"' + machine[sProp] + '",';
}
}
machine['parms'] += 'autoMount:' + machine['automount'] + '}';
machine['parms'] += 'autoMount:' + machine['autoMount'] + '}';
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
* 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();
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
* is still off by default.
*/
var PREFETCH = false;
var PREFETCH = true;
/**
* @define {boolean}

View file

@ -2190,8 +2190,8 @@ X86CPU.prototype.setIP = function(off)
*/
X86CPU.prototype.setLIP = function(addr)
{
this.regLIP = addr|0;
this.regLIPLimit = (this.segCS.base + this.segCS.limit)|0;
this.regLIP = addr;
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?
@ -2230,8 +2230,7 @@ X86CPU.prototype.setLIP = function(addr)
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
* that segCS.load(sel) has the ability to modify IP when sel refers to a gate (call, interrupt, trap, etc).
* Setting IP needs to occur AFTER loadCode(), because it may differ from the given IP if sel refers to a gate.
*/
var base = this.segCS.loadCode(off, sel, fCall);
if (base !== X86.ADDR_INVALID) {
@ -2254,61 +2253,41 @@ X86CPU.prototype.setCSBase = function(addr)
var regIP = this.getIP();
addr = this.segCS.setBase(addr);
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}
* @param {number} inc (positive)
* @return {number} new LIP
*/
X86CPU.prototype.advanceIP = function(inc)
X86CPU.prototype.checkIP = function(inc)
{
// DEBUG: this.assert(inc > 0);
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) {
var newLIP = (this.regLIP >>> 0) + inc;
if (newLIP > this.regLIPMax) {
/*
* TODO: This isn't DEBUG code, but it also isn't strictly necessary for properly written code,
* and it hurts performance. Since this effectively turns advanceIP() into a one-line function for
* non-DEBUG builds, it should automatically get inlined (either at compile-time by the Closure Compiler
* or at run-time by whatever JavaScript engine you're using).
* There's no such thing as a GP fault on the 8086/8088, and I'm assuming that,
* on newer processors, when the segment limit is the maximum, it's OK for IP to wrap.
*/
var off = (this.regLIPLimit - this.regLIP)|0;
if (off < 0 && (this.regLIPLimit ^ this.regLIP) >= 0) {
/*
* There's no such thing as a GP fault on the 8086/8088, and I'm assuming that, on newer
* processors, when the segment limit is set to the maximum, it's OK for IP to wrap.
*/
if (this.model <= X86.MODEL_8088 || this.segCS.limit == this.segCS.maskAddr) {
this.setIP(this.regLIP - this.segCS.base);
} else if (off < -1) { // fudge factor
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
}
if (this.model <= X86.MODEL_8088 || this.segCS.limit == this.segCS.maskAddr) {
newLIP = this.segCS.base + ((newLIP - this.regLIPMax) & (I386? this.maskData : 0xffff));
} else {
X86.helpFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
}
}
return newLIP|0;
};
/**
@ -3704,9 +3683,10 @@ X86CPU.prototype.refillPrefetch = function()
*/
X86CPU.prototype.getIPByte = function()
{
var newLIP = this.checkIP(1);
var b = (PREFETCH? this.getBytePrefetch() : this.getByte(this.regLIP));
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.advanceIP(1);
this.regLIP = newLIP;
return b;
};
@ -3718,12 +3698,13 @@ X86CPU.prototype.getIPByte = function()
*/
X86CPU.prototype.getIPShort = function()
{
var newLIP = this.checkIP(2);
var w = (PREFETCH? this.getShortPrefetch() : this.getShort(this.regLIP));
if (BACKTRACK) {
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1);
}
this.advanceIP(2);
this.regLIP = newLIP;
return w;
};
@ -3735,6 +3716,7 @@ X86CPU.prototype.getIPShort = function()
*
X86CPU.prototype.getIPLong = function()
{
var newLIP = this.checkIP(4);
var l = (PREFETCH? this.getLongPrefetch() : this.getLong(this.regLIP));
if (BACKTRACK) {
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 + 3, this.backTrack.btiMem3);
}
this.advanceIP(4);
this.regLIP = newLIP;
return l;
};
*/
@ -3755,12 +3737,13 @@ X86CPU.prototype.getIPLong = function()
*/
X86CPU.prototype.getIPAddr = function()
{
var newLIP = this.checkIP(this.sizeAddr);
var w = (PREFETCH? this.getAddr() : this.getAddr(this.regLIP));
if (BACKTRACK) {
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1);
}
this.advanceIP(this.sizeAddr);
this.regLIP = newLIP;
return w;
};
@ -3772,12 +3755,13 @@ X86CPU.prototype.getIPAddr = function()
*/
X86CPU.prototype.getIPWord = function()
{
var newLIP = this.checkIP(this.sizeData);
var w = (PREFETCH? this.getWordPrefetch() : this.getWord(this.regLIP));
if (BACKTRACK) {
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1);
}
this.advanceIP(this.sizeData);
this.regLIP = newLIP;
return w;
};
@ -3789,9 +3773,10 @@ X86CPU.prototype.getIPWord = function()
*/
X86CPU.prototype.getIPDisp = function()
{
var newLIP = this.checkIP(1);
var w = ((PREFETCH? this.getBytePrefetch() : this.getByte(this.regLIP)) << 24) >> 24;
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.advanceIP(1);
this.regLIP = newLIP;
return w;
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff