32-bit operand fixes
This commit is contained in:
parent
73086a7ac8
commit
380db6ef7d
8 changed files with 53 additions and 20 deletions
|
|
@ -3,7 +3,8 @@
|
|||
"id": "pc386.computer",
|
||||
"name": "Compaq DeskPro 386",
|
||||
"resume": 0,
|
||||
"state": ""
|
||||
"state": "",
|
||||
"busWidth": 32
|
||||
},
|
||||
"ram": [
|
||||
{ "id": "pc386.ramLow",
|
||||
|
|
@ -18,6 +19,7 @@
|
|||
"name": "",
|
||||
"addr": 983296,
|
||||
"size": 65280,
|
||||
"alias": 4294902016,
|
||||
"file": "/tests/pc/80386/tests.json",
|
||||
"notify": ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ if (typeof module !== 'undefined') {
|
|||
* The Computer component has no required (parmsComputer) properties, but does
|
||||
* support the following:
|
||||
*
|
||||
* buswidth: number of memory address lines (address bits) on the computer's "bus";
|
||||
* busWidth: number of memory address lines (address bits) on the computer's "bus";
|
||||
* 20 is the minimum (and the default), which implies 8086/8088 real-mode addressing,
|
||||
* while 24 is required for 80286 protected-mode addressing. This value is passed
|
||||
* directly through to the Bus component; see that component for more details.
|
||||
|
|
@ -125,7 +125,10 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
|
|||
Component.call(this, "Computer", parmsComputer, Computer, Messages.COMPUTER);
|
||||
|
||||
this.aFlags.fPowered = false;
|
||||
this.nBusWidth = parmsComputer['buswidth'];
|
||||
/*
|
||||
* TODO: Deprecate 'buswidth' (it should have always used camelCase)
|
||||
*/
|
||||
this.nBusWidth = parmsComputer['busWidth'] || parmsComputer['buswidth'];
|
||||
this.resume = Computer.RESUME_NONE;
|
||||
this.sStateData = null;
|
||||
this.fServerState = false;
|
||||
|
|
|
|||
|
|
@ -1325,14 +1325,14 @@ X86CPU.prototype.resetRegs = function()
|
|||
};
|
||||
|
||||
/**
|
||||
* setAddrSize()
|
||||
* updateAddrSize()
|
||||
*
|
||||
* Select the appropriate ModRM dispatch tables, based on the current ADDRESS size (addrSize), which
|
||||
* is based foremost on segCS.addrSize, but can also be overridden by an ADDRESS size instruction prefix.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86CPU.prototype.setAddrSize = function()
|
||||
X86CPU.prototype.updateAddrSize = function()
|
||||
{
|
||||
if (!I386) {
|
||||
this.getAddr = this.getShort;
|
||||
|
|
@ -1364,11 +1364,30 @@ X86CPU.prototype.setAddrSize = function()
|
|||
};
|
||||
|
||||
/**
|
||||
* setDataSize()
|
||||
* setDataSize(size)
|
||||
*
|
||||
* This is used by opcodes that require a particular OPERAND size, which we enforce by
|
||||
* internally simulating an OPERAND size override, if needed.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} size (2 for 2-byte/16-bit operands, or 4 for 4-byte/32-bit operands)
|
||||
*/
|
||||
X86CPU.prototype.setDataSize = function(size)
|
||||
{
|
||||
if (this.dataSize != size) {
|
||||
this.opPrefixes |= X86.OPFLAG.DATASIZE;
|
||||
this.dataSize = size;
|
||||
this.dataMask = (size == 2? 0xffff : (0xffffffff|0));
|
||||
this.updateDataSize();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* updateDataSize()
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
X86CPU.prototype.setDataSize = function()
|
||||
X86CPU.prototype.updateDataSize = function()
|
||||
{
|
||||
if (this.dataSize == 2) {
|
||||
this.dataType = X86.RESULT.WORD;
|
||||
|
|
@ -1407,7 +1426,7 @@ X86CPU.prototype.resetSizes = function()
|
|||
* to separate X86CPU properties, as we do for the OPERAND size and ADDRESS size properties.
|
||||
*/
|
||||
|
||||
this.setAddrSize();
|
||||
this.updateAddrSize();
|
||||
|
||||
/*
|
||||
* The following contain the (default) OPERAND size (2 for 16 bits, 4 for 32 bits), and the corresponding masks
|
||||
|
|
@ -1417,7 +1436,7 @@ X86CPU.prototype.resetSizes = function()
|
|||
this.dataSize = this.segCS.dataSize;
|
||||
this.dataMask = this.segCS.dataMask;
|
||||
|
||||
this.setDataSize();
|
||||
this.updateDataSize();
|
||||
|
||||
this.opPrefixes &= ~(X86.OPFLAG.ADDRSIZE | X86.OPFLAG.DATASIZE);
|
||||
};
|
||||
|
|
@ -3775,11 +3794,6 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
|
|||
|
||||
if (I386 && (this.opPrefixes & (X86.OPFLAG.ADDRSIZE | X86.OPFLAG.DATASIZE))) {
|
||||
this.resetSizes();
|
||||
if (MAXDEBUG && DEBUGGER) {
|
||||
this.println("80386 override processed");
|
||||
this.stopCPU();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.opPrefixes = this.opFlags & X86.OPFLAG.REPEAT;
|
||||
|
|
|
|||
|
|
@ -1675,7 +1675,7 @@ X86.fnMOVn = function MOVn(dst, src)
|
|||
* @this {X86CPU}
|
||||
* @param {number} dst (current value, ignored)
|
||||
* @param {number} src (new value)
|
||||
* @return {number} dst (src is overridden, replaced with regXX, as specified by opMOVwsr())
|
||||
* @return {number} dst (src is overridden, replaced with regXX, as specified by opMOVwsr() or opMOVrc())
|
||||
*/
|
||||
X86.fnMOVxx = function MOVxx(dst, src)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -256,7 +256,11 @@ X86.opMOVrc = function MOVrc()
|
|||
* however, it's moot, because we've already restricted this opcode to registers only.
|
||||
*
|
||||
* this.opFlags |= X86.OPFLAG.NOREAD;
|
||||
*
|
||||
* Another issue, however, is that this instruction always assumes a 32-bit OPERAND size,
|
||||
* so we must call setDataSize(4) first.
|
||||
*/
|
||||
this.setDataSize(4);
|
||||
this.aOpModRegWord[bModRM].call(this, X86.fnMOVxx);
|
||||
};
|
||||
|
||||
|
|
@ -319,7 +323,13 @@ X86.opMOVcr = function MOVcr()
|
|||
X86.opInvalid.call(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This instruction always assumes a 32-bit OPERAND size, so we must call setDataSize(4) first.
|
||||
*/
|
||||
this.setDataSize(4);
|
||||
this.aOpModRegWord[bModRM].call(this, X86.fnMOV);
|
||||
|
||||
switch(reg) {
|
||||
case 0x0:
|
||||
reg = this.regEAX;
|
||||
|
|
|
|||
|
|
@ -1380,7 +1380,7 @@ X86.opOS = function OS()
|
|||
this.opFlags |= X86.OPFLAG.DATASIZE;
|
||||
this.dataSize ^= 0x6; // that which is 2 shall become 4, and vice versa
|
||||
this.dataMask ^= (0xffff0000|0); // that which is 0x0000ffff shall become 0xffffffff, and vice versa
|
||||
this.setDataSize();
|
||||
this.updateDataSize();
|
||||
this.nStepCycles -= this.cycleCounts.nOpCyclesPrefix;
|
||||
}
|
||||
};
|
||||
|
|
@ -1398,7 +1398,7 @@ X86.opAS = function AS()
|
|||
this.opFlags |= X86.OPFLAG.ADDRSIZE;
|
||||
this.addrSize ^= 0x06; // that which is 2 shall become 4, and vice versa
|
||||
this.addrMask ^= (0xffff0000|0); // that which is 0x0000ffff shall become 0xffffffff, and vice versa
|
||||
this.setAddrSize();
|
||||
this.updateAddrSize();
|
||||
this.nStepCycles -= this.cycleCounts.nOpCyclesPrefix;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -974,7 +974,7 @@
|
|||
<xsl:template match="computer[not(@ref)]">
|
||||
<xsl:param name="machine" select="''"/>
|
||||
<xsl:param name="machineState" select="''"/>
|
||||
<xsl:variable name="buswidth">
|
||||
<xsl:variable name="busWidth">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@buswidth"><xsl:value-of select="@buswidth"/></xsl:when>
|
||||
<xsl:otherwise>20</xsl:otherwise>
|
||||
|
|
@ -996,7 +996,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">computer</xsl:with-param>
|
||||
<xsl:with-param name="parms">,buswidth:<xsl:value-of select="$buswidth"/>,resume:<xsl:value-of select="$resume"/>,state:'<xsl:value-of select="$state"/>'</xsl:with-param>
|
||||
<xsl:with-param name="parms">,busWidth:<xsl:value-of select="$busWidth"/>,resume:<xsl:value-of select="$resume"/>,state:'<xsl:value-of select="$state"/>'</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
|
|||
|
|
@ -46,11 +46,15 @@ start: mov eax,0x44332211
|
|||
jnz near goProt ; apparently we have to tell NASM "near" because this is a forward reference
|
||||
times 32768 nop ; lots of NOPs to force a 16-bit conditional jump
|
||||
|
||||
addrGDT:dw romGDTEnd - romGDT - 1 ; 16-bit limit of romGDT
|
||||
dw romGDT, 0xffff ; 32-bit base address of romGDT (works as long as we're aliased at 0xffff0000)
|
||||
|
||||
romGDT: defDesc 0 ; the first descriptor in any descriptor table is always a dud (it corresponds to the null descriptor)
|
||||
defDesc 0x000f0000,0x0000ffff,ACC_TYPE_CODE_READABLE
|
||||
defDesc 0x00000000,0x000fffff,ACC_TYPE_DATA_WRITABLE
|
||||
romGDTEnd:
|
||||
|
||||
goProt: lgdt [cs:romGDT]
|
||||
goProt: o32 lgdt [cs:addrGDT]
|
||||
mov eax,cr0
|
||||
or eax,CR0_MSW_PE
|
||||
mov cr0,eax
|
||||
|
|
|
|||
Loading…
Reference in a new issue