Re-enable PREFTECH, fix IP limit checking, and restore support for autoMount overrides
This commit is contained in:
parent
7663b061f7
commit
81c4b61522
10 changed files with 2648 additions and 2644 deletions
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in a new issue