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",
|
"id": "pc386.computer",
|
||||||
"name": "Compaq DeskPro 386",
|
"name": "Compaq DeskPro 386",
|
||||||
"resume": 0,
|
"resume": 0,
|
||||||
"state": ""
|
"state": "",
|
||||||
|
"busWidth": 32
|
||||||
},
|
},
|
||||||
"ram": [
|
"ram": [
|
||||||
{ "id": "pc386.ramLow",
|
{ "id": "pc386.ramLow",
|
||||||
|
|
@ -18,6 +19,7 @@
|
||||||
"name": "",
|
"name": "",
|
||||||
"addr": 983296,
|
"addr": 983296,
|
||||||
"size": 65280,
|
"size": 65280,
|
||||||
|
"alias": 4294902016,
|
||||||
"file": "/tests/pc/80386/tests.json",
|
"file": "/tests/pc/80386/tests.json",
|
||||||
"notify": ""
|
"notify": ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ if (typeof module !== 'undefined') {
|
||||||
* The Computer component has no required (parmsComputer) properties, but does
|
* The Computer component has no required (parmsComputer) properties, but does
|
||||||
* support the following:
|
* 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,
|
* 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
|
* 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.
|
* 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);
|
Component.call(this, "Computer", parmsComputer, Computer, Messages.COMPUTER);
|
||||||
|
|
||||||
this.aFlags.fPowered = false;
|
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.resume = Computer.RESUME_NONE;
|
||||||
this.sStateData = null;
|
this.sStateData = null;
|
||||||
this.fServerState = false;
|
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
|
* 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.
|
* is based foremost on segCS.addrSize, but can also be overridden by an ADDRESS size instruction prefix.
|
||||||
*
|
*
|
||||||
* @this {X86CPU}
|
* @this {X86CPU}
|
||||||
*/
|
*/
|
||||||
X86CPU.prototype.setAddrSize = function()
|
X86CPU.prototype.updateAddrSize = function()
|
||||||
{
|
{
|
||||||
if (!I386) {
|
if (!I386) {
|
||||||
this.getAddr = this.getShort;
|
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}
|
* @this {X86CPU}
|
||||||
*/
|
*/
|
||||||
X86CPU.prototype.setDataSize = function()
|
X86CPU.prototype.updateDataSize = function()
|
||||||
{
|
{
|
||||||
if (this.dataSize == 2) {
|
if (this.dataSize == 2) {
|
||||||
this.dataType = X86.RESULT.WORD;
|
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.
|
* 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
|
* 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.dataSize = this.segCS.dataSize;
|
||||||
this.dataMask = this.segCS.dataMask;
|
this.dataMask = this.segCS.dataMask;
|
||||||
|
|
||||||
this.setDataSize();
|
this.updateDataSize();
|
||||||
|
|
||||||
this.opPrefixes &= ~(X86.OPFLAG.ADDRSIZE | X86.OPFLAG.DATASIZE);
|
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))) {
|
if (I386 && (this.opPrefixes & (X86.OPFLAG.ADDRSIZE | X86.OPFLAG.DATASIZE))) {
|
||||||
this.resetSizes();
|
this.resetSizes();
|
||||||
if (MAXDEBUG && DEBUGGER) {
|
|
||||||
this.println("80386 override processed");
|
|
||||||
this.stopCPU();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.opPrefixes = this.opFlags & X86.OPFLAG.REPEAT;
|
this.opPrefixes = this.opFlags & X86.OPFLAG.REPEAT;
|
||||||
|
|
|
||||||
|
|
@ -1675,7 +1675,7 @@ X86.fnMOVn = function MOVn(dst, src)
|
||||||
* @this {X86CPU}
|
* @this {X86CPU}
|
||||||
* @param {number} dst (current value, ignored)
|
* @param {number} dst (current value, ignored)
|
||||||
* @param {number} src (new value)
|
* @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)
|
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.
|
* however, it's moot, because we've already restricted this opcode to registers only.
|
||||||
*
|
*
|
||||||
* this.opFlags |= X86.OPFLAG.NOREAD;
|
* 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);
|
this.aOpModRegWord[bModRM].call(this, X86.fnMOVxx);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -319,7 +323,13 @@ X86.opMOVcr = function MOVcr()
|
||||||
X86.opInvalid.call(this);
|
X86.opInvalid.call(this);
|
||||||
return;
|
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);
|
this.aOpModRegWord[bModRM].call(this, X86.fnMOV);
|
||||||
|
|
||||||
switch(reg) {
|
switch(reg) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
reg = this.regEAX;
|
reg = this.regEAX;
|
||||||
|
|
|
||||||
|
|
@ -1380,7 +1380,7 @@ X86.opOS = function OS()
|
||||||
this.opFlags |= X86.OPFLAG.DATASIZE;
|
this.opFlags |= X86.OPFLAG.DATASIZE;
|
||||||
this.dataSize ^= 0x6; // that which is 2 shall become 4, and vice versa
|
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.dataMask ^= (0xffff0000|0); // that which is 0x0000ffff shall become 0xffffffff, and vice versa
|
||||||
this.setDataSize();
|
this.updateDataSize();
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesPrefix;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesPrefix;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1398,7 +1398,7 @@ X86.opAS = function AS()
|
||||||
this.opFlags |= X86.OPFLAG.ADDRSIZE;
|
this.opFlags |= X86.OPFLAG.ADDRSIZE;
|
||||||
this.addrSize ^= 0x06; // that which is 2 shall become 4, and vice versa
|
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.addrMask ^= (0xffff0000|0); // that which is 0x0000ffff shall become 0xffffffff, and vice versa
|
||||||
this.setAddrSize();
|
this.updateAddrSize();
|
||||||
this.nStepCycles -= this.cycleCounts.nOpCyclesPrefix;
|
this.nStepCycles -= this.cycleCounts.nOpCyclesPrefix;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -974,7 +974,7 @@
|
||||||
<xsl:template match="computer[not(@ref)]">
|
<xsl:template match="computer[not(@ref)]">
|
||||||
<xsl:param name="machine" select="''"/>
|
<xsl:param name="machine" select="''"/>
|
||||||
<xsl:param name="machineState" select="''"/>
|
<xsl:param name="machineState" select="''"/>
|
||||||
<xsl:variable name="buswidth">
|
<xsl:variable name="busWidth">
|
||||||
<xsl:choose>
|
<xsl:choose>
|
||||||
<xsl:when test="@buswidth"><xsl:value-of select="@buswidth"/></xsl:when>
|
<xsl:when test="@buswidth"><xsl:value-of select="@buswidth"/></xsl:when>
|
||||||
<xsl:otherwise>20</xsl:otherwise>
|
<xsl:otherwise>20</xsl:otherwise>
|
||||||
|
|
@ -996,7 +996,7 @@
|
||||||
<xsl:call-template name="component">
|
<xsl:call-template name="component">
|
||||||
<xsl:with-param name="machine" select="$machine"/>
|
<xsl:with-param name="machine" select="$machine"/>
|
||||||
<xsl:with-param name="class">computer</xsl:with-param>
|
<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:call-template>
|
||||||
</xsl: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
|
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
|
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)
|
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 0x000f0000,0x0000ffff,ACC_TYPE_CODE_READABLE
|
||||||
defDesc 0x00000000,0x000fffff,ACC_TYPE_DATA_WRITABLE
|
defDesc 0x00000000,0x000fffff,ACC_TYPE_DATA_WRITABLE
|
||||||
|
romGDTEnd:
|
||||||
|
|
||||||
goProt: lgdt [cs:romGDT]
|
goProt: o32 lgdt [cs:addrGDT]
|
||||||
mov eax,cr0
|
mov eax,cr0
|
||||||
or eax,CR0_MSW_PE
|
or eax,CR0_MSW_PE
|
||||||
mov cr0,eax
|
mov cr0,eax
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue