Added placeholders for IBTS and XBTS (80386 opcodes on A0-B0 steppings only)

This commit is contained in:
Jeff Parsons 2015-10-29 22:44:33 -07:00
commit 8bd1794928
7 changed files with 139 additions and 75 deletions

View file

@ -6,8 +6,7 @@ problems were fixed by a later stepping, seems virtually impossible at this late
I won't make the attempt here, either. Using information from various sources, I'll start with an overview
of the steppings, including how each stepping was externally marked and internally identified, along with lists
of associated errata, then move on to more detailed errata information (from Intel's own documents), and end
with a summary of undocumented 80386 instructions.
of associated errata, then move on to more detailed errata information, based on Intel's own documents.
### Steppings
@ -866,23 +865,15 @@ Here's more information on the opcodes (IBTS and XBTS) that were removed from th
CPU: 80386 step A0-B0 only
Type of Instruction: User
Instruction: IBTS base,bitoffset,len,sorc
Description:
Write bit string length <len> bits from
<sorc> [bits <len> .. 0 ] (lowest bits) to bitfield,
defined by <base> and bitsoffset <bitoffset> from this base
to start of the field to write. String write from this start
field bit to higher memory addresses or register bits.
Instruction: IBTS base,bitoffset,len,src
Flags Affected: None
CPU mode: RM,PM,VM
+++++++++++++++++++++++
Physical Form: IBTS r/m16,AX,CL,r16
IBTS r/m32,EAX,CL,r32
COP (Code of Operation) : 0FH A7H
IBTS r/m16,AX,CL,r16
IBTS r/m32,EAX,CL,r32
COP (Code of Operation): 0FH A7H
Clocks: IBTS
80386: 12/19
@ -894,29 +885,15 @@ Here's more information on the opcodes (IBTS and XBTS) that were removed from th
CPU: 80386 step A0-B0 only
Type of Instruction: User
Instruction: XBTS dest,base,bitoffset,len
Description:
Write bit string length <len> bits from bitfield, defined by
<base> and bitsoffset <bitoffset> from this base to start of
the field to read. String read from this start field bit to
higher memory addresses or register bits.
And after it string placed to <dest> operand, lowest bit of
register or memory to bit 0 of <dest>.
Note: Use SHLD/SHRD instructions for extract bits strings.
On 80386 steps B1+ this opcode generation INT 6,
and on some of 486 other instruction replace this
instruction opcode.
Instruction: XBTS dst,base,bitoffset,len
Flags Affected: None
CPU mode: RM,PM,VM
+++++++++++++++++++++++
Physical Form: XBTS r16,r/m16,AX,CL
XBTS r16,r/m16,AX,CL
XBTS r32,r/m32,EAX,CL
COP (Code of Operation) : 0FH A6H
COP (Code of Operation): 0FH A6H
Clocks: XBTS
80386: 6/13

View file

@ -327,25 +327,25 @@ if (DEBUGGER) {
FCOM: 40, FCOMP: 41, FDIV: 42, FDIVR: 43, FIADD: 44, FICOM: 45, FICOMP: 46, FIDIV: 47,
FIDIVR: 48, FILD: 49, FIMUL: 50, FIST: 51, FISTP: 52, FISUB: 53, FISUBR: 54, FLD: 55,
FLDCW: 56, FLDENV: 57, FMUL: 58, FNSAVE: 59, FNSTCW: 60, FNSTENV:61, FNSTSW: 62, FRSTOR: 63,
FS: 64, FST: 65, FSTP: 66, FSUB: 67, FSUBR: 68, GS: 69, HLT: 70, IDIV: 71,
IMUL: 72, IN: 73, INC: 74, INS: 75, INT: 76, INT3: 77, INTO: 78, IRET: 79,
JBE: 80, JC: 81, JCXZ: 82, JG: 83, JGE: 84, JL: 85, JLE: 86, JMP: 87,
JA: 88, JNC: 89, JNO: 90, JNP: 91, JNS: 92, JNZ: 93, JO: 94, JP: 95,
JS: 96, JZ: 97, LAHF: 98, LAR: 99, LDS: 100, LEA: 101, LEAVE: 102, LES: 103,
LFS: 104, LGDT: 105, LGS: 106, LIDT: 107, LLDT: 108, LMSW: 109, LOADALL:110, LOCK: 111,
LODSB: 112, LODSW: 113, LOOP: 114, LOOPNZ: 115, LOOPZ: 116, LSL: 117, LSS: 118, LTR: 119,
MOV: 120, MOVSB: 121, MOVSW: 122, MOVSX: 123, MOVZX: 124, MUL: 125, NEG: 126, NOP: 127,
NOT: 128, OR: 129, OS: 130, OUT: 131, OUTS: 132, POP: 133, POPA: 134, POPF: 135,
PUSHF: 136, PUSHA: 137, PUSH: 138, RCL: 139, RCR: 140, REPNZ: 141, REPZ: 142, RET: 143,
RETF: 144, ROL: 145, ROR: 146, SAHF: 147, SALC: 148, SAR: 149, SBB: 150, SCASB: 151,
SCASW: 152, SETBE: 153, SETC: 154, SETG: 155, SETGE: 156, SETL: 157, SETLE: 158, SETNBE: 159,
SETNC: 160, SETNO: 161, SETNP: 162, SETNS: 163, SETNZ: 164, SETO: 165, SETP: 166, SETS: 167,
SETZ: 168, SGDT: 169, SHL: 170, SHLD: 171, SHR: 172, SHRD: 173, SIDT: 174, SLDT: 175,
SMSW: 176, SS: 177, STC: 178, STD: 179, STI: 180, STOSB: 181, STOSW: 182, STR: 183,
SUB: 184, TEST: 185, VERR: 186, VERW: 187, WAIT: 188, XCHG: 189, XLAT: 190, XOR: 191,
GRP1B: 192, GRP1W: 193, GRP1SW: 194, GRP2B: 195, GRP2W: 196, GRP2B1: 197, GRP2W1: 198, GRP2BC: 199,
GRP2WC: 200, GRP3B: 201, GRP3W: 202, GRP4B: 203, GRP4W: 204, OP0F: 205, GRP6: 206, GRP7: 207,
GRP8: 208
FS: 64, FST: 65, FSTP: 66, FSUB: 67, FSUBR: 68, GS: 69, HLT: 70, IBTS: 71,
IDIV: 72, IMUL: 73, IN: 74, INC: 75, INS: 76, INT: 77, INT3: 78, INTO: 79,
IRET: 80, JBE: 81, JC: 82, JCXZ: 83, JG: 84, JGE: 85, JL: 86, JLE: 87,
JMP: 88, JA: 89, JNC: 90, JNO: 91, JNP: 92, JNS: 93, JNZ: 94, JO: 95,
JP: 96, JS: 97, JZ: 98, LAHF: 99, LAR: 100, LDS: 101, LEA: 102, LEAVE: 103,
LES: 104, LFS: 105, LGDT: 106, LGS: 107, LIDT: 108, LLDT: 109, LMSW: 110, LOADALL:111,
LOCK: 112, LODSB: 113, LODSW: 114, LOOP: 115, LOOPNZ: 116, LOOPZ: 117, LSL: 118, LSS: 119,
LTR: 120, MOV: 121, MOVSB: 122, MOVSW: 123, MOVSX: 124, MOVZX: 125, MUL: 126, NEG: 127,
NOP: 128, NOT: 129, OR: 130, OS: 131, OUT: 132, OUTS: 133, POP: 134, POPA: 135,
POPF: 136, PUSHF: 137, PUSHA: 138, PUSH: 139, RCL: 140, RCR: 141, REPNZ: 142, REPZ: 143,
RET: 144, RETF: 145, ROL: 146, ROR: 147, SAHF: 148, SALC: 149, SAR: 150, SBB: 151,
SCASB: 152, SCASW: 153, SETBE: 154, SETC: 155, SETG: 156, SETGE: 157, SETL: 158, SETLE: 159,
SETNBE: 160, SETNC: 161, SETNO: 162, SETNP: 163, SETNS: 164, SETNZ: 165, SETO: 166, SETP: 167,
SETS: 168, SETZ: 169, SGDT: 170, SHL: 171, SHLD: 172, SHR: 173, SHRD: 174, SIDT: 175,
SLDT: 176, SMSW: 177, SS: 178, STC: 179, STD: 180, STI: 181, STOSB: 182, STOSW: 183,
STR: 184, SUB: 185, TEST: 186, VERR: 187, VERW: 188, WAIT: 189, XBTS: 190, XCHG: 191,
XLAT: 192, XOR: 193, GRP1B: 194, GRP1W: 195, GRP1SW: 196, GRP2B: 197, GRP2W: 198, GRP2B1: 199,
GRP2W1: 200, GRP2BC: 201, GRP2WC: 202, GRP3B: 203, GRP3W: 204, GRP4B: 205, GRP4W: 206, OP0F: 207,
GRP6: 208, GRP7: 209, GRP8: 210
};
/*
@ -360,22 +360,23 @@ if (DEBUGGER) {
"FCOM", "FCOMP", "FDIV", "FDIVR", "FIADD", "FICOM", "FICOMP", "FIDIV",
"FIDIVR", "FILD", "FIMUL", "FIST", "FISTP", "FISUB", "FISUBR", "FLD",
"FLDCW", "FLDENV", "FMUL", "FNSAVE", "FNSTCW", "FNSTENV","FNSTSW", "FRSTOR",
"FS:", "FST", "FSTP", "FSUB", "FSUBR", "GS:", "HLT", "IDIV",
"IMUL", "IN", "INC", "INS", "INT", "INT3", "INTO", "IRET",
"JBE", "JC", "JCXZ", "JG", "JGE", "JL", "JLE", "JMP",
"JA", "JNC", "JNO", "JNP", "JNS", "JNZ", "JO", "JP",
"JS", "JZ", "LAHF", "LAR", "LDS", "LEA", "LEAVE", "LES",
"LFS", "LGDT", "LGS", "LIDT", "LLDT", "LMSW", "LOADALL","LOCK",
"LODSB", "LODSW", "LOOP", "LOOPNZ", "LOOPZ", "LSL", "LSS", "LTR",
"MOV", "MOVSB", "MOVSW", "MOVSX", "MOVZX", "MUL", "NEG", "NOP",
"NOT", "OR", "OS:", "OUT", "OUTS", "POP", "POPA", "POPF",
"PUSHF", "PUSHA", "PUSH", "RCL", "RCR", "REPNZ", "REPZ", "RET",
"RETF", "ROL", "ROR", "SAHF", "SALC", "SAR", "SBB", "SCASB",
"SCASW", "SETBE", "SETC", "SETG", "SETGE", "SETL", "SETLE", "SETNBE",
"SETNC", "SETNO", "SETNP", "SETNS", "SETNZ", "SETO", "SETP", "SETS",
"SETZ", "SGDT", "SHL", "SHLD", "SHR", "SHRD", "SIDT", "SLDT",
"SMSW", "SS:", "STC", "STD", "STI", "STOSB", "STOSW", "STR",
"SUB", "TEST", "VERR", "VERW", "WAIT", "XCHG", "XLAT", "XOR"
"FS:", "FST", "FSTP", "FSUB", "FSUBR", "GS:", "HLT", "IBTS",
"IDIV", "IMUL", "IN", "INC", "INS", "INT", "INT3", "INTO",
"IRET", "JBE", "JC", "JCXZ", "JG", "JGE", "JL", "JLE",
"JMP", "JA", "JNC", "JNO", "JNP", "JNS", "JNZ", "JO",
"JP", "JS", "JZ", "LAHF", "LAR", "LDS", "LEA", "LEAVE",
"LES", "LFS", "LGDT", "LGS", "LIDT", "LLDT", "LMSW", "LOADALL",
"LOCK", "LODSB", "LODSW", "LOOP", "LOOPNZ", "LOOPZ", "LSL", "LSS",
"LTR", "MOV", "MOVSB", "MOVSW", "MOVSX", "MOVZX", "MUL", "NEG",
"NOP", "NOT", "OR", "OS:", "OUT", "OUTS", "POP", "POPA",
"POPF", "PUSHF", "PUSHA", "PUSH", "RCL", "RCR", "REPNZ", "REPZ",
"RET", "RETF", "ROL", "ROR", "SAHF", "SALC", "SAR", "SBB",
"SCASB", "SCASW", "SETBE", "SETC", "SETG", "SETGE", "SETL", "SETLE",
"SETNBE", "SETNC", "SETNO", "SETNP", "SETNS", "SETNZ", "SETO", "SETP",
"SETS", "SETZ", "SGDT", "SHL", "SHLD", "SHR", "SHRD", "SIDT",
"SLDT", "SMSW", "SS:", "STC", "STD", "STI", "STOSB", "STOSW",
"STR", "SUB", "TEST", "VERR", "VERW", "WAIT", "XBTS", "XCHG",
"XLAT", "XOR"
];
Debugger.CPU_8086 = 0;
@ -981,6 +982,8 @@ if (DEBUGGER) {
0xA3: [Debugger.INS.BT, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_IN | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_IN],
0xA4: [Debugger.INS.SHLD, 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],
0xA5: [Debugger.INS.SHLD, 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],
0xA6: [Debugger.INS.XBTS, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_IN, Debugger.TYPE_IMPREG | Debugger.TYPE_AX | Debugger.TYPE_IN, Debugger.TYPE_IMPREG | Debugger.TYPE_CL | Debugger.TYPE_IN],
0xA7: [Debugger.INS.IBTS, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_IMPREG | Debugger.TYPE_AX | Debugger.TYPE_IN, Debugger.TYPE_IMPREG | Debugger.TYPE_CL | Debugger.TYPE_IN, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_IN],
0xA8: [Debugger.INS.PUSH, Debugger.TYPE_GS | Debugger.TYPE_IN | Debugger.TYPE_80386],
0xA9: [Debugger.INS.POP, Debugger.TYPE_GS | Debugger.TYPE_OUT | Debugger.TYPE_80386],
0xAB: [Debugger.INS.BTS, Debugger.TYPE_MODRM | Debugger.TYPE_VWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_VWORD | Debugger.TYPE_IN],

View file

@ -44,10 +44,12 @@ var X86 = {
MODEL_80386: 80386,
/*
* CPU stepping identifiers (supported)
* 80386 CPU stepping identifiers (supported)
*/
STEPPING_B1: 0xB1, // our version of the B1 stepping also includes the infamous 32-bit multiplication bug
STEPPING_B2: 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_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_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)
/*
* This constant is used to mark points in the code where the physical address being returned

View file

@ -110,8 +110,13 @@ function X86CPU(parmsCPU)
{
this.model = parmsCPU['model'] || X86.MODEL_8088;
/*
* We take the 'stepping' value, convert it to a hex value, and then add that to the model to provide
* a single value that's unique for any given CPU stepping. If no stepping is provided, then stepping
* is equal to model.
*/
var stepping = parmsCPU['stepping'];
this.stepping = (stepping? str.parseInt(stepping, 16) : 0);
this.stepping = this.model + (stepping? str.parseInt(stepping, 16) : 0);
var nCyclesDefault = 0;
switch(this.model) {
@ -812,6 +817,10 @@ X86CPU.prototype.initProcessor = function()
for (bOpcode in X86.aOps0F386) {
this.aOps0F[+bOpcode] = X86.aOps0F386[bOpcode];
}
if (this.stepping >= X86.STEPPING_80386_A0 && this.stepping <= X86.STEPPING_80386_B0) {
this.aOps0F[0xA6] = X86.opXBTS;
this.aOps0F[0xA7] = X86.opIBTS;
}
}
}
}

View file

@ -683,6 +683,28 @@ X86.fnDECw = function(dst, src)
return w & this.maskData;
};
/**
* fnIBTS(dst, src)
*
* As best I can determine, this function copies the specified bits from src (starting at bit 0 for CL
* bits) to dst (starting at bit offset in AX). For register operands, that's simple enough.
*
* TODO: If dst refers to a memory location, then the bit index may refer to higher memory locations, just
* like the BT/BTC/BTR/BTS instructions. For an instruction that no one was really able to use, except
* as a CPU stepping discriminator, that doesn't seem worth the effort.
*
* @this {X86CPU}
* @param {number} dst
* @param {number} src
* @return {number}
*/
X86.fnIBTS = function(dst, src)
{
var shift = (this.regEAX & this.maskData);
var mask = ((1 << (this.regECX & 0x1f)) - 1);
return (dst & ~(mask << shift)) | ((src & mask) << shift);
};
/**
* fnSet64(lo, hi)
*
@ -2033,11 +2055,11 @@ X86.fnMULw = function(dst, src)
this.regMDHi = (result >> 16) & 0xffff;
} else {
X86.fnMUL32.call(this, dst, this.regEAX);
if (this.model == X86.MODEL_80386 && this.stepping == X86.STEPPING_B1) {
if (this.stepping == X86.STEPPING_80386_B1) {
if (this.regEAX == 0x0417A000 && dst == 0x00000081) {
/*
* In this case, the result should be 0x20FE7A000 (ie, regMDHi should be 0x2), and I'm not
* sure what the typical failure would look like, so I'll just set regMDHi to 0.
* Normally, the result should be 0x20FE7A000 (ie, regMDHi should be 0x2).
* I'm not sure what a typical failure looked like, so I'll just set regMDHi to 0.
*
* If you want a B1 stepping without this 32-bit multiplication flaw, select the B2 stepping.
*/
@ -3538,6 +3560,30 @@ X86.fnVERW = function(dst, src)
return dst;
};
/**
* fnXBTS(dst, src)
*
* As best I can determine, this function copies the specified bits from src (starting at the bit offset
* in AX, for the bit length in CL) to dst (starting at bit 0). For register operands, that's simple enough.
*
* TODO: If src refers to a memory location, then the bit index may refer to higher memory locations, just
* like the BT/BTC/BTR/BTS instructions. For an instruction that no one was really able to use, except
* as a CPU stepping discriminator, that doesn't seem worth the effort.
*
* @this {X86CPU}
* @param {number} dst
* @param {number} src
* @return {number}
*/
X86.fnXBTS = function(dst, src)
{
/*
* Shift src right by the bit offset in [E]AX, then apply a mask equal to the number of bits in CL,
* then mask the resulting bit string with the current OPERAND size.
*/
return ((src >> (this.regEAX & this.maskData)) & ((1 << (this.regECX & 0x1f)) - 1)) & this.maskData;
};
/**
* fnXCHGrb(dst, src)
*

View file

@ -1166,6 +1166,32 @@ X86.opSHLDcl = function SHLDcl()
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 3 : 7);
};
/**
* opXBTS()
*
* op=0x0F,0xA6 (XBTS reg,mem/reg,[E]AX,CL)
*
* @this {X86CPU}
*/
X86.opXBTS = function XBTS()
{
this.aOpModRegWord[this.getIPByte()].call(this, X86.fnXBTS);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 6 : 13);
};
/**
* opIBTS()
*
* op=0x0F,0xA7 (IBTS mem/reg,[E]AX,CL,reg)
*
* @this {X86CPU}
*/
X86.opIBTS = function IBTS()
{
this.aOpModMemWord[this.getIPByte()].call(this, X86.fnIBTS);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 12 : 19);
};
/**
* opPUSHGS()
*

View file

@ -2952,9 +2952,10 @@ X86.opSTOSb = function STOSb()
* only EDI in the case of STOS. The other instructions mentioned below monkey with different
* registers, so read the errata carefully.
*
* TODO: Extend this errata to STOSW, as well as MOVSB, MOVSW, INSB, and INSW.
* TODO: Extend this errata to STOSW, as well as MOVSB, MOVSW, INSB, and INSW. Also, scope out the
* extent to which this errara also existed on earlier steppings.
*/
if (this.model == X86.MODEL_80386 && this.stepping == X86.STEPPING_B1) {
if (this.stepping == X86.STEPPING_80386_B1) {
if (!(this.opPrefixes & X86.OPFLAG.ADDRSIZE) != (this.getByte(this.regLIP) != X86.OPCODE.AS)) {
maskAddr ^= (0xffff0000|0);
}