32-bit operand fixes

This commit is contained in:
Jeff Parsons 2015-05-05 11:45:24 -07:00 committed by jeffpar
commit 380db6ef7d
8 changed files with 53 additions and 20 deletions

View file

@ -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": ""
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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