Added placeholders for IBTS and XBTS (80386 opcodes on A0-B0 steppings only)
This commit is contained in:
parent
6dcb644a05
commit
8bd1794928
7 changed files with 139 additions and 75 deletions
|
|
@ -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
|
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 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
|
of associated errata, then move on to more detailed errata information, based on Intel's own documents.
|
||||||
with a summary of undocumented 80386 instructions.
|
|
||||||
|
|
||||||
### Steppings
|
### 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
|
CPU: 80386 step A0-B0 only
|
||||||
Type of Instruction: User
|
Type of Instruction: User
|
||||||
|
|
||||||
Instruction: IBTS base,bitoffset,len,sorc
|
Instruction: IBTS base,bitoffset,len,src
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Flags Affected: None
|
Flags Affected: None
|
||||||
|
|
||||||
CPU mode: RM,PM,VM
|
CPU mode: RM,PM,VM
|
||||||
|
|
||||||
+++++++++++++++++++++++
|
IBTS r/m16,AX,CL,r16
|
||||||
Physical Form: IBTS r/m16,AX,CL,r16
|
IBTS r/m32,EAX,CL,r32
|
||||||
IBTS r/m32,EAX,CL,r32
|
COP (Code of Operation): 0FH A7H
|
||||||
COP (Code of Operation) : 0FH A7H
|
|
||||||
|
|
||||||
Clocks: IBTS
|
Clocks: IBTS
|
||||||
80386: 12/19
|
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
|
CPU: 80386 step A0-B0 only
|
||||||
Type of Instruction: User
|
Type of Instruction: User
|
||||||
|
|
||||||
Instruction: XBTS dest,base,bitoffset,len
|
Instruction: XBTS dst,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.
|
|
||||||
|
|
||||||
Flags Affected: None
|
Flags Affected: None
|
||||||
|
|
||||||
CPU mode: RM,PM,VM
|
CPU mode: RM,PM,VM
|
||||||
|
|
||||||
+++++++++++++++++++++++
|
XBTS r16,r/m16,AX,CL
|
||||||
Physical Form: XBTS r16,r/m16,AX,CL
|
|
||||||
XBTS r32,r/m32,EAX,CL
|
XBTS r32,r/m32,EAX,CL
|
||||||
COP (Code of Operation) : 0FH A6H
|
COP (Code of Operation): 0FH A6H
|
||||||
|
|
||||||
Clocks: XBTS
|
Clocks: XBTS
|
||||||
80386: 6/13
|
80386: 6/13
|
||||||
|
|
|
||||||
|
|
@ -327,25 +327,25 @@ if (DEBUGGER) {
|
||||||
FCOM: 40, FCOMP: 41, FDIV: 42, FDIVR: 43, FIADD: 44, FICOM: 45, FICOMP: 46, FIDIV: 47,
|
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,
|
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,
|
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,
|
FS: 64, FST: 65, FSTP: 66, FSUB: 67, FSUBR: 68, GS: 69, HLT: 70, IBTS: 71,
|
||||||
IMUL: 72, IN: 73, INC: 74, INS: 75, INT: 76, INT3: 77, INTO: 78, IRET: 79,
|
IDIV: 72, IMUL: 73, IN: 74, INC: 75, INS: 76, INT: 77, INT3: 78, INTO: 79,
|
||||||
JBE: 80, JC: 81, JCXZ: 82, JG: 83, JGE: 84, JL: 85, JLE: 86, JMP: 87,
|
IRET: 80, JBE: 81, JC: 82, JCXZ: 83, JG: 84, JGE: 85, JL: 86, JLE: 87,
|
||||||
JA: 88, JNC: 89, JNO: 90, JNP: 91, JNS: 92, JNZ: 93, JO: 94, JP: 95,
|
JMP: 88, JA: 89, JNC: 90, JNO: 91, JNP: 92, JNS: 93, JNZ: 94, JO: 95,
|
||||||
JS: 96, JZ: 97, LAHF: 98, LAR: 99, LDS: 100, LEA: 101, LEAVE: 102, LES: 103,
|
JP: 96, JS: 97, JZ: 98, LAHF: 99, LAR: 100, LDS: 101, LEA: 102, LEAVE: 103,
|
||||||
LFS: 104, LGDT: 105, LGS: 106, LIDT: 107, LLDT: 108, LMSW: 109, LOADALL:110, LOCK: 111,
|
LES: 104, LFS: 105, LGDT: 106, LGS: 107, LIDT: 108, LLDT: 109, LMSW: 110, LOADALL:111,
|
||||||
LODSB: 112, LODSW: 113, LOOP: 114, LOOPNZ: 115, LOOPZ: 116, LSL: 117, LSS: 118, LTR: 119,
|
LOCK: 112, LODSB: 113, LODSW: 114, LOOP: 115, LOOPNZ: 116, LOOPZ: 117, LSL: 118, LSS: 119,
|
||||||
MOV: 120, MOVSB: 121, MOVSW: 122, MOVSX: 123, MOVZX: 124, MUL: 125, NEG: 126, NOP: 127,
|
LTR: 120, MOV: 121, MOVSB: 122, MOVSW: 123, MOVSX: 124, MOVZX: 125, MUL: 126, NEG: 127,
|
||||||
NOT: 128, OR: 129, OS: 130, OUT: 131, OUTS: 132, POP: 133, POPA: 134, POPF: 135,
|
NOP: 128, NOT: 129, OR: 130, OS: 131, OUT: 132, OUTS: 133, POP: 134, POPA: 135,
|
||||||
PUSHF: 136, PUSHA: 137, PUSH: 138, RCL: 139, RCR: 140, REPNZ: 141, REPZ: 142, RET: 143,
|
POPF: 136, PUSHF: 137, PUSHA: 138, PUSH: 139, RCL: 140, RCR: 141, REPNZ: 142, REPZ: 143,
|
||||||
RETF: 144, ROL: 145, ROR: 146, SAHF: 147, SALC: 148, SAR: 149, SBB: 150, SCASB: 151,
|
RET: 144, RETF: 145, ROL: 146, ROR: 147, SAHF: 148, SALC: 149, SAR: 150, SBB: 151,
|
||||||
SCASW: 152, SETBE: 153, SETC: 154, SETG: 155, SETGE: 156, SETL: 157, SETLE: 158, SETNBE: 159,
|
SCASB: 152, SCASW: 153, SETBE: 154, SETC: 155, SETG: 156, SETGE: 157, SETL: 158, SETLE: 159,
|
||||||
SETNC: 160, SETNO: 161, SETNP: 162, SETNS: 163, SETNZ: 164, SETO: 165, SETP: 166, SETS: 167,
|
SETNBE: 160, SETNC: 161, SETNO: 162, SETNP: 163, SETNS: 164, SETNZ: 165, SETO: 166, SETP: 167,
|
||||||
SETZ: 168, SGDT: 169, SHL: 170, SHLD: 171, SHR: 172, SHRD: 173, SIDT: 174, SLDT: 175,
|
SETS: 168, SETZ: 169, SGDT: 170, SHL: 171, SHLD: 172, SHR: 173, SHRD: 174, SIDT: 175,
|
||||||
SMSW: 176, SS: 177, STC: 178, STD: 179, STI: 180, STOSB: 181, STOSW: 182, STR: 183,
|
SLDT: 176, SMSW: 177, SS: 178, STC: 179, STD: 180, STI: 181, STOSB: 182, STOSW: 183,
|
||||||
SUB: 184, TEST: 185, VERR: 186, VERW: 187, WAIT: 188, XCHG: 189, XLAT: 190, XOR: 191,
|
STR: 184, SUB: 185, TEST: 186, VERR: 187, VERW: 188, WAIT: 189, XBTS: 190, XCHG: 191,
|
||||||
GRP1B: 192, GRP1W: 193, GRP1SW: 194, GRP2B: 195, GRP2W: 196, GRP2B1: 197, GRP2W1: 198, GRP2BC: 199,
|
XLAT: 192, XOR: 193, GRP1B: 194, GRP1W: 195, GRP1SW: 196, GRP2B: 197, GRP2W: 198, GRP2B1: 199,
|
||||||
GRP2WC: 200, GRP3B: 201, GRP3W: 202, GRP4B: 203, GRP4W: 204, OP0F: 205, GRP6: 206, GRP7: 207,
|
GRP2W1: 200, GRP2BC: 201, GRP2WC: 202, GRP3B: 203, GRP3W: 204, GRP4B: 205, GRP4W: 206, OP0F: 207,
|
||||||
GRP8: 208
|
GRP6: 208, GRP7: 209, GRP8: 210
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -360,22 +360,23 @@ if (DEBUGGER) {
|
||||||
"FCOM", "FCOMP", "FDIV", "FDIVR", "FIADD", "FICOM", "FICOMP", "FIDIV",
|
"FCOM", "FCOMP", "FDIV", "FDIVR", "FIADD", "FICOM", "FICOMP", "FIDIV",
|
||||||
"FIDIVR", "FILD", "FIMUL", "FIST", "FISTP", "FISUB", "FISUBR", "FLD",
|
"FIDIVR", "FILD", "FIMUL", "FIST", "FISTP", "FISUB", "FISUBR", "FLD",
|
||||||
"FLDCW", "FLDENV", "FMUL", "FNSAVE", "FNSTCW", "FNSTENV","FNSTSW", "FRSTOR",
|
"FLDCW", "FLDENV", "FMUL", "FNSAVE", "FNSTCW", "FNSTENV","FNSTSW", "FRSTOR",
|
||||||
"FS:", "FST", "FSTP", "FSUB", "FSUBR", "GS:", "HLT", "IDIV",
|
"FS:", "FST", "FSTP", "FSUB", "FSUBR", "GS:", "HLT", "IBTS",
|
||||||
"IMUL", "IN", "INC", "INS", "INT", "INT3", "INTO", "IRET",
|
"IDIV", "IMUL", "IN", "INC", "INS", "INT", "INT3", "INTO",
|
||||||
"JBE", "JC", "JCXZ", "JG", "JGE", "JL", "JLE", "JMP",
|
"IRET", "JBE", "JC", "JCXZ", "JG", "JGE", "JL", "JLE",
|
||||||
"JA", "JNC", "JNO", "JNP", "JNS", "JNZ", "JO", "JP",
|
"JMP", "JA", "JNC", "JNO", "JNP", "JNS", "JNZ", "JO",
|
||||||
"JS", "JZ", "LAHF", "LAR", "LDS", "LEA", "LEAVE", "LES",
|
"JP", "JS", "JZ", "LAHF", "LAR", "LDS", "LEA", "LEAVE",
|
||||||
"LFS", "LGDT", "LGS", "LIDT", "LLDT", "LMSW", "LOADALL","LOCK",
|
"LES", "LFS", "LGDT", "LGS", "LIDT", "LLDT", "LMSW", "LOADALL",
|
||||||
"LODSB", "LODSW", "LOOP", "LOOPNZ", "LOOPZ", "LSL", "LSS", "LTR",
|
"LOCK", "LODSB", "LODSW", "LOOP", "LOOPNZ", "LOOPZ", "LSL", "LSS",
|
||||||
"MOV", "MOVSB", "MOVSW", "MOVSX", "MOVZX", "MUL", "NEG", "NOP",
|
"LTR", "MOV", "MOVSB", "MOVSW", "MOVSX", "MOVZX", "MUL", "NEG",
|
||||||
"NOT", "OR", "OS:", "OUT", "OUTS", "POP", "POPA", "POPF",
|
"NOP", "NOT", "OR", "OS:", "OUT", "OUTS", "POP", "POPA",
|
||||||
"PUSHF", "PUSHA", "PUSH", "RCL", "RCR", "REPNZ", "REPZ", "RET",
|
"POPF", "PUSHF", "PUSHA", "PUSH", "RCL", "RCR", "REPNZ", "REPZ",
|
||||||
"RETF", "ROL", "ROR", "SAHF", "SALC", "SAR", "SBB", "SCASB",
|
"RET", "RETF", "ROL", "ROR", "SAHF", "SALC", "SAR", "SBB",
|
||||||
"SCASW", "SETBE", "SETC", "SETG", "SETGE", "SETL", "SETLE", "SETNBE",
|
"SCASB", "SCASW", "SETBE", "SETC", "SETG", "SETGE", "SETL", "SETLE",
|
||||||
"SETNC", "SETNO", "SETNP", "SETNS", "SETNZ", "SETO", "SETP", "SETS",
|
"SETNBE", "SETNC", "SETNO", "SETNP", "SETNS", "SETNZ", "SETO", "SETP",
|
||||||
"SETZ", "SGDT", "SHL", "SHLD", "SHR", "SHRD", "SIDT", "SLDT",
|
"SETS", "SETZ", "SGDT", "SHL", "SHLD", "SHR", "SHRD", "SIDT",
|
||||||
"SMSW", "SS:", "STC", "STD", "STI", "STOSB", "STOSW", "STR",
|
"SLDT", "SMSW", "SS:", "STC", "STD", "STI", "STOSB", "STOSW",
|
||||||
"SUB", "TEST", "VERR", "VERW", "WAIT", "XCHG", "XLAT", "XOR"
|
"STR", "SUB", "TEST", "VERR", "VERW", "WAIT", "XBTS", "XCHG",
|
||||||
|
"XLAT", "XOR"
|
||||||
];
|
];
|
||||||
|
|
||||||
Debugger.CPU_8086 = 0;
|
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],
|
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],
|
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],
|
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],
|
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],
|
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],
|
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],
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,12 @@ var X86 = {
|
||||||
MODEL_80386: 80386,
|
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_80386_A0: (80386+0xA0),
|
||||||
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_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
|
* This constant is used to mark points in the code where the physical address being returned
|
||||||
|
|
|
||||||
|
|
@ -110,8 +110,13 @@ function X86CPU(parmsCPU)
|
||||||
{
|
{
|
||||||
this.model = parmsCPU['model'] || X86.MODEL_8088;
|
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'];
|
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;
|
var nCyclesDefault = 0;
|
||||||
switch(this.model) {
|
switch(this.model) {
|
||||||
|
|
@ -812,6 +817,10 @@ X86CPU.prototype.initProcessor = function()
|
||||||
for (bOpcode in X86.aOps0F386) {
|
for (bOpcode in X86.aOps0F386) {
|
||||||
this.aOps0F[+bOpcode] = X86.aOps0F386[bOpcode];
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -683,6 +683,28 @@ X86.fnDECw = function(dst, src)
|
||||||
return w & this.maskData;
|
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)
|
* fnSet64(lo, hi)
|
||||||
*
|
*
|
||||||
|
|
@ -2033,11 +2055,11 @@ X86.fnMULw = function(dst, src)
|
||||||
this.regMDHi = (result >> 16) & 0xffff;
|
this.regMDHi = (result >> 16) & 0xffff;
|
||||||
} else {
|
} else {
|
||||||
X86.fnMUL32.call(this, dst, this.regEAX);
|
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) {
|
if (this.regEAX == 0x0417A000 && dst == 0x00000081) {
|
||||||
/*
|
/*
|
||||||
* In this case, the result should be 0x20FE7A000 (ie, regMDHi should be 0x2), and I'm not
|
* Normally, the result should be 0x20FE7A000 (ie, regMDHi should be 0x2).
|
||||||
* sure what the typical failure would look like, so I'll just set regMDHi to 0.
|
* 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.
|
* 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;
|
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)
|
* fnXCHGrb(dst, src)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1166,6 +1166,32 @@ X86.opSHLDcl = function SHLDcl()
|
||||||
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 3 : 7);
|
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()
|
* opPUSHGS()
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -2952,9 +2952,10 @@ X86.opSTOSb = function STOSb()
|
||||||
* only EDI in the case of STOS. The other instructions mentioned below monkey with different
|
* only EDI in the case of STOS. The other instructions mentioned below monkey with different
|
||||||
* registers, so read the errata carefully.
|
* 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)) {
|
if (!(this.opPrefixes & X86.OPFLAG.ADDRSIZE) != (this.getByte(this.regLIP) != X86.OPCODE.AS)) {
|
||||||
maskAddr ^= (0xffff0000|0);
|
maskAddr ^= (0xffff0000|0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue