More 80286 testing

This commit is contained in:
Jeff Parsons 2015-05-15 09:08:42 -07:00 committed by jeffpar
commit a28fa95d25
25 changed files with 107 additions and 36 deletions

View file

@ -538,7 +538,7 @@ DiskDump.getManifestAttr = function(sID, sTag)
*/
DiskDump.updateManifest = function(disk, sManifestFile, sDiskPath, sOutputFile, fOverwrite, sTitle, md5Disk, md5JSON)
{
var fUnchanged, fExists = false, sXML, err = null;
var i, fUnchanged, fExists = false, sXML, err = null;
var sMatchDisk = null, sIDDisk = null, sMD5Disk = null, sMD5JSON = null;
try {
@ -551,7 +551,10 @@ DiskDump.updateManifest = function(disk, sManifestFile, sDiskPath, sOutputFile,
if (sTitle) {
sTitle = sTitle.charAt(0).toUpperCase() + sTitle.substr(1);
}
sPrefix = ' type="prefix"';
}
if (sTitle) {
i = sTitle.indexOf(':');
if (i > 0) sPrefix = ' prefix="' + sTitle.substr(0, i) + '"';
}
sXML = '<?xml version="1.0" encoding="UTF-8"?>\n';
sXML += '<?xml-stylesheet type="text/xsl" href="/versions/pcjs/' + pkg.version + '/manifest.xsl"?>\n';
@ -560,7 +563,7 @@ DiskDump.updateManifest = function(disk, sManifestFile, sDiskPath, sOutputFile,
sXML += '</manifest>';
}
var i = sOutputFile.indexOf("/disks/");
i = sOutputFile.indexOf("/disks/");
if (i > 0) {
sOutputFile = sOutputFile.substr(i);
} else {

View file

@ -419,11 +419,12 @@ if (DEBUGGER) {
Debugger.TYPE_WORD = 0x0003; // (w) word, regardless...
Debugger.TYPE_VWORD = 0x0004; // (v) word or double-word, depending...
Debugger.TYPE_DWORD = 0x0005; // (d) double-word, regardless...
Debugger.TYPE_FARP = 0x0006; // (p) 32-bit or 48-bit pointer, depending
Debugger.TYPE_2WORD = 0x0007; // (a) two memory operands (BOUND only)
Debugger.TYPE_DESC = 0x0008; // (s) 6 byte pseudo-descriptor
Debugger.TYPE_WORDIB = 0x0009; // two source operands (eg, IMUL)
Debugger.TYPE_WORDIW = 0x000A; // two source operands (eg, IMUL)
Debugger.TYPE_SEGP = 0x0006; // (p) 32-bit or 48-bit pointer
Debugger.TYPE_FARP = 0x0007; // (p) 32-bit or 48-bit pointer for JMP/CALL
Debugger.TYPE_2WORD = 0x0008; // (a) two memory operands (BOUND only)
Debugger.TYPE_DESC = 0x0009; // (s) 6 byte pseudo-descriptor
Debugger.TYPE_WORDIB = 0x000A; // two source operands (eg, IMUL)
Debugger.TYPE_WORDIW = 0x000B; // two source operands (eg, IMUL)
Debugger.TYPE_PREFIX = 0x000F; // (treat similarly to TYPE_NONE)
/*
@ -826,8 +827,8 @@ if (DEBUGGER) {
/* 0xC1 */ [Debugger.INS.GRP2W, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_BOTH | Debugger.TYPE_80186, Debugger.TYPE_IMM | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
/* 0xC2 */ [Debugger.INS.RET, Debugger.TYPE_IMM | Debugger.TYPE_WORD | Debugger.TYPE_IN],
/* 0xC3 */ [Debugger.INS.RET],
/* 0xC4 */ [Debugger.INS.LES, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_MEM | Debugger.TYPE_FARP | Debugger.TYPE_IN],
/* 0xC5 */ [Debugger.INS.LDS, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_MEM | Debugger.TYPE_FARP | Debugger.TYPE_IN],
/* 0xC4 */ [Debugger.INS.LES, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_MEM | Debugger.TYPE_SEGP | Debugger.TYPE_IN],
/* 0xC5 */ [Debugger.INS.LDS, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_MEM | Debugger.TYPE_SEGP | Debugger.TYPE_IN],
/* 0xC6 */ [Debugger.INS.MOV, Debugger.TYPE_MODRM | Debugger.TYPE_BYTE | Debugger.TYPE_OUT, Debugger.TYPE_IMM | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
/* 0xC7 */ [Debugger.INS.MOV, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_IMM | Debugger.TYPE_VWORD | Debugger.TYPE_IN],
@ -947,10 +948,10 @@ if (DEBUGGER) {
0xAC: [Debugger.INS.SHRD, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_IN, Debugger.TYPE_IMM | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
0xAD: [Debugger.INS.SHRD, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_IN, Debugger.TYPE_IMPREG | Debugger.TYPE_CL | Debugger.TYPE_IN],
0xAF: [Debugger.INS.IMUL, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_BOTH | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_IN],
0xB2: [Debugger.INS.LSS, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_MEM | Debugger.TYPE_FARP | Debugger.TYPE_IN],
0xB2: [Debugger.INS.LSS, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_MEM | Debugger.TYPE_SEGP | Debugger.TYPE_IN],
0xB3: [Debugger.INS.BTR, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_IN],
0xB4: [Debugger.INS.LFS, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_MEM | Debugger.TYPE_FARP | Debugger.TYPE_IN],
0xB5: [Debugger.INS.LGS, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_MEM | Debugger.TYPE_FARP | Debugger.TYPE_IN],
0xB4: [Debugger.INS.LFS, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_MEM | Debugger.TYPE_SEGP | Debugger.TYPE_IN],
0xB5: [Debugger.INS.LGS, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT, Debugger.TYPE_MEM | Debugger.TYPE_SEGP | Debugger.TYPE_IN],
0xB6: [Debugger.INS.MOVZX, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_MODRM | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
0xB7: [Debugger.INS.MOVZX, Debugger.TYPE_REG | Debugger.TYPE_DWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_MODRM | Debugger.TYPE_WORD | Debugger.TYPE_IN],
0xBA: [Debugger.INS.GRP8, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_BOTH | Debugger.TYPE_80386, Debugger.TYPE_IMM | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
@ -3367,6 +3368,7 @@ if (DEBUGGER) {
}
}
sOperand = "[" + sOperand + "]";
if ((type & Debugger.TYPE_SIZE) == Debugger.TYPE_FARP) sOperand = "FAR " + sOperand;
}
else {
sOperand = this.getRegOperand(bRM, type, dbgAddr);

View file

@ -103,16 +103,15 @@ var X86 = {
MASK: 0xfff8 // table index
},
DESC: { // Descriptor Table Entry
LIMIT: { // LIMIT bits 0-15
LIMIT: { // LIMIT bits 0-15 (or OFFSET if this is an INTERRUPT or TRAP gate)
OFFSET: 0x0
},
BASE: { // BASE bits 0-15
BASE: { // BASE bits 0-15 (or SELECTOR if this is a TASK, INTERRUPT or TRAP gate)
OFFSET: 0x2
},
ACC: { // bit definitions for the access word (offset 0x4)
OFFSET: 0x4,
BASE1623: 0x00ff,
MASK: 0xff00,
BASE1623: 0x00ff, // (not used if this a TASK, INTERRUPT or TRAP gate; bits 0-5 are parm count for CALL gates)
TYPE: {
OFFSET: 0x5,
MASK: 0x1f00,

View file

@ -1311,13 +1311,16 @@ X86.fnLAR = function LAR(dst, src)
* TODO: This instruction's 80286 documentation does not discuss conforming code segments; determine
* if we need a special check for them.
*/
this.clearZF();
if (this.segVER.load(src, true) !== X86.ADDR_INVALID) {
if (this.segVER.dpl >= this.segCS.cpl && this.segVER.dpl >= (src & X86.SEL.RPL)) {
this.setZF();
return this.segVER.acc & X86.DESC.ACC.MASK;
dst = this.segVER.acc & ~X86.DESC.ACC.BASE1623;
if (this.dataSize > 2) {
dst |= ((this.segVER.ext & ~X86.DESC.EXT.BASE2431) << 16);
}
}
}
this.clearZF();
return dst;
};

View file

@ -185,16 +185,14 @@ X86Seg.prototype.loadProt = function loadProt(sel, fSuppress)
* which has no bearing on the ROM's own code, because it never loads any LDT selectors, but if at the same
* time our Debugger attempts to validate a selector in one of its breakpoints, that could cause some
* grief here. We avoid that grief by 1) relying on the Debugger setting fSuppress to true, and 2) skipping
* segment lookup if the descriptor table being referenced is zero.
*
* TODO: This could probably be simplified to a test of addrDT; however, there's nothing in the design
* of the CPU that prevents the GDT or LDT being located at linear address zero.
* segment lookup if the descriptor table being referenced is zero. Both tests are required, because
* there's nothing in the design of the CPU that prevents the GDT or LDT being at linear address zero.
*/
if (!fSuppress || addrDT) {
var addrDesc = (addrDT + (sel & X86.SEL.MASK))|0;
if ((addrDTLimit - addrDesc)|0 >= 7) {
/*
* TODO: This is only the first of many steps toward accurately counting cycles in protected mode;
* TODO: This is the first of many steps toward accurately counting cycles in protected mode;
* I simply noted that "POP segreg" takes 5 cycles in real mode and 20 in protected mode, so I'm
* starting with a 15-cycle difference. Obviously the difference will vary with the instruction,
* and will be much greater whenever the load fails.
@ -563,7 +561,7 @@ X86Seg.prototype.loadDesc6 = function(addrDesc, sel)
this.base = base;
this.limit = limit;
this.offMax = (limit >>> 0) + 1;
this.acc = acc & X86.DESC.ACC.MASK;
this.acc = acc;
this.type = (acc & X86.DESC.ACC.TYPE.MASK);
this.ext = 0;
this.addrDesc = addrDesc;
@ -641,7 +639,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
* Otherwise, we must be dealing with a CALLF or JMPF to a less privileged segment, in which
* case either DPL == CPL *or* the new segment is conforming and DPL <= CPL.
*/
if (fCall !== false && !(dpl == this.cpl || (acc & X86.DESC.ACC.TYPE.CONFORMING) && dpl <= this.cpl)) {
if (fCall !== false && !(dpl == this.cpl || (type & X86.DESC.ACC.TYPE.CONFORMING) && dpl <= this.cpl)) {
base = addrDesc = X86.ADDR_INVALID;
break;
}
@ -793,7 +791,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
/*
* For LSL, we must support any descriptor marked X86.DESC.ACC.TYPE.SEG, as well as TSS and LDT descriptors.
*/
if (!(acc & X86.DESC.ACC.TYPE.SEG) && type > X86.DESC.ACC.TYPE.TSS_BUSY) {
if (!(type & X86.DESC.ACC.TYPE.SEG) && type > X86.DESC.ACC.TYPE.TSS_BUSY) {
base = addrDesc = X86.ADDR_INVALID;
break;
}
@ -937,23 +935,23 @@ X86Seg.prototype.updateMode = function(fLoad, fProt)
this.checkWrite = this.checkWriteProtDisallowed;
}
else if (this.acc & X86.DESC.ACC.TYPE.SEG) {
else if (this.type & X86.DESC.ACC.TYPE.SEG) {
/*
* If the READABLE bit of CODE_READABLE is not set, then disallow reads.
*/
if ((this.acc & X86.DESC.ACC.TYPE.CODE_READABLE) == X86.DESC.ACC.TYPE.CODE_EXECONLY) {
if ((this.type & X86.DESC.ACC.TYPE.CODE_READABLE) == X86.DESC.ACC.TYPE.CODE_EXECONLY) {
this.checkRead = this.checkReadProtDisallowed;
}
/*
* If the CODE bit is set, or the the WRITABLE bit is not set, then disallow writes.
*/
if ((this.acc & X86.DESC.ACC.TYPE.CODE) || !(this.acc & X86.DESC.ACC.TYPE.WRITABLE)) {
if ((this.type & X86.DESC.ACC.TYPE.CODE) || !(this.type & X86.DESC.ACC.TYPE.WRITABLE)) {
this.checkWrite = this.checkWriteProtDisallowed;
}
/*
* If the CODE bit is not set *and* the EXPDOWN bit is set, then invert the limit check.
*/
if ((this.acc & (X86.DESC.ACC.TYPE.CODE | X86.DESC.ACC.TYPE.EXPDOWN)) == X86.DESC.ACC.TYPE.EXPDOWN) {
if ((this.type & (X86.DESC.ACC.TYPE.CODE | X86.DESC.ACC.TYPE.EXPDOWN)) == X86.DESC.ACC.TYPE.EXPDOWN) {
if (this.checkRead == this.checkReadProt) this.checkRead = this.checkReadProtDown;
if (this.checkWrite == this.checkWriteProt) this.checkWrite = this.checkWriteProtDown;
this.fExpDown = true;
@ -983,8 +981,8 @@ X86Seg.prototype.updateMode = function(fLoad, fProt)
* for other purposes, on the assumption that that descriptor is completely unused.
*/
if ((this.sel & ~X86.SEL.RPL) && this.addrDesc !== X86.ADDR_INVALID) {
var addrACC = this.addrDesc + X86.DESC.ACC.TYPE.OFFSET;
this.cpu.setByte(addrACC, this.cpu.getByte(addrACC) | (X86.DESC.ACC.TYPE.ACCESSED >> 8));
var addrType = this.addrDesc + X86.DESC.ACC.TYPE.OFFSET;
this.cpu.setByte(addrType, this.cpu.getByte(addrType) | (X86.DESC.ACC.TYPE.ACCESSED >> 8));
}
this.cpl = this.sel & X86.SEL.RPL;
this.dpl = (this.acc & X86.DESC.ACC.DPL.MASK) >> X86.DESC.ACC.DPL.SHIFT;

View file

@ -457,7 +457,7 @@
<xsl:param name="disk"><xsl:value-of select="@disk"/></xsl:param>
<xsl:if test="$disk != ''">
<xsl:variable name="prefix">
<xsl:if test="title[@prefix]"><xsl:value-of select="title"/><xsl:text>: </xsl:text></xsl:if>
<xsl:if test="title/@prefix"><xsl:value-of select="title/@prefix"/><xsl:text>: </xsl:text></xsl:if>
</xsl:variable>
<xsl:for-each select="disk">
<xsl:if test="$disk = @id or $disk = '*'">