More 80286 testing
This commit is contained in:
parent
c431e5dde8
commit
a28fa95d25
25 changed files with 107 additions and 36 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 = '*'">
|
||||
|
|
|
|||
Loading…
Reference in a new issue