diff --git a/blog/2015/02/23/README.md b/blog/2015/02/23/README.md index 9e6e51644..f0d541be2 100644 --- a/blog/2015/02/23/README.md +++ b/blog/2015/02/23/README.md @@ -856,7 +856,7 @@ Never allocate valid memory at 0x80000xxx. ### Instructions -Here's more information on the opcodes (IBTS and XBTS) that were removed from the B1 stepping. +Here's more information on the 80386 opcodes (IBTS and XBTS) that were removed from the 80386, as of the B1 stepping. [IBTS (0x0F 0xA7)](http://asm.inightmare.org/opcodelst/index.php?op=IBTS) @@ -898,6 +898,28 @@ Here's more information on the opcodes (IBTS and XBTS) that were removed from th Clocks: XBTS 80386: 6/13 +FYI, PCjs now has limited support for the XBTS (0x0F 0xA6) and IBTS (0x0F 0xA7) instructions in any 80386 machine +configuration file that contains a CPU *stepping* attribute of "A0" through "B0". + +By limited, I mean that: + +1. The Debugger component can disassemble them +2. The X86CPU component can emulate them (but only for bit indexes 0-31) + +I'm content with limited emulation, because it seems unlikely there is much (if any) real-world software that actually +used those short-lived instructions except as a way of discriminating between 80386 steppings. I also couldn't find any +decent specs for exactly how these instructions operated, so the emulation will have to stay limited. + +The 0xA6 and 0xA7 opcodes were briefly reused on early 80486 CPUs for the byte and word forms, respectively, of CMPXCHG, +but then those CMPXCHG instructions were moved to opcodes 0xB0 and 0xB1 on later 80486 CPUs. + +NOTE: The "PC Magazine Programmer's Technical Reference" claims that CMPXCHG used 0x0F opcodes 0xA6 and 0xA7 only on the +80486 B0 stepping, and that they were moved to 0x0F opcodes 0xB0 and 0xB1 on the "B1" stepping. However, I can't find +any independent confirmation of that. + +Most other sources suggest that CMPXCHG used the old XBTS/IBTS opcodes only on 80486 "A" steppings, not any "B" steppings. +The PC Magazine author may have simply confused the 0xB0 and 0xB1 opcodes with the B0 and B1 steppings. + *[@jeffpar](http://twitter.com/jeffpar)* *February 23, 2015* *(Updated March 9, 2015 with information from "Advanced 80386 Programming Techniques")* diff --git a/modules/pcjs/lib/x86.js b/modules/pcjs/lib/x86.js index ec89f98ab..6442fa7cc 100644 --- a/modules/pcjs/lib/x86.js +++ b/modules/pcjs/lib/x86.js @@ -46,10 +46,15 @@ var X86 = { /* * 80386 CPU stepping identifiers (supported) */ - STEPPING_80386_A0: (80386+0xA0), - STEPPING_80386_B0: (80386+0xB0), // for now, the only B0 difference is support for XBTS - STEPPING_80386_B1: (80386+0xB1), // our version of the B1 stepping also includes the infamous 32-bit multiplication bug + STEPPING_80386_A0: (80386+0xA0), // we have very little information about this stepping... + STEPPING_80386_A1: (80386+0xA1), // we know much more about the A1 stepping (see /blog/2015/02/23/README.md) + STEPPING_80386_B0: (80386+0xB0), // for now, the only B0 difference in PCjs is support for XBTS and IBTS + STEPPING_80386_B1: (80386+0xB1), // our implementation of the B1 stepping also includes the infamous 32-bit multiplication bug STEPPING_80386_B2: (80386+0xB2), // this is an imaginary stepping that simply means "B1 without the 32-bit multiplication bug" (ie, a B1 with the "double sigma" stamp) + STEPPING_80386_C0: (80386+0xC0), // this presumably fixed lots of B1 issues, but it seems to have been quickly superseded by the D0 + STEPPING_80386_D0: (80386+0xD0), // we don't have any detailed information (eg, errata) for these later steppings + STEPPING_80386_D1: (80386+0xD1), + STEPPING_80386_D2: (80386+0xD2), /* * This constant is used to mark points in the code where the physical address being returned diff --git a/modules/pcjs/lib/x86cpu.js b/modules/pcjs/lib/x86cpu.js index a76e62b13..cca927a7e 100644 --- a/modules/pcjs/lib/x86cpu.js +++ b/modules/pcjs/lib/x86cpu.js @@ -1064,7 +1064,26 @@ X86CPU.prototype.resetRegs = function() this.setSS(0); if (I386 && this.model >= X86.MODEL_80386) { - this.regEDX = 0x0304; // Intel errata sheets indicate this is what an 80386-C0 reported + /* + * Here lies everything I currently know about 80386 stepping revision numbers... + */ + switch(this.stepping) { + case X86.STEPPING_80386_B0: + case X86.STEPPING_80386_B1: + this.regEDX = 0x0303; + break; + case X86.STEPPING_80386_C0: + this.regEDX = 0x0304; + break; + case X86.STEPPING_80386_D0: + this.regEDX = 0x0305; + break; + case X86.STEPPING_80386_D1: + case X86.STEPPING_80386_D2: + default: + this.regEDX = 0x0308; // in the absence of a specific stepping, default to the highest known revision + break; + } this.regCR0 = X86.CR0.ET; // formerly MSW this.regCR1 = 0; // reserved this.regCR2 = 0; // page fault linear address (PFLA)