Fixed INT and RETF when stack switches occur

This commit is contained in:
Jeff Parsons 2014-11-26 16:34:54 -08:00 • committed by jeffpar
commit 38c2928882
7 changed files with 81 additions and 49 deletions

View file

@ -7,10 +7,14 @@ root = true
end_of_line = lf end_of_line = lf
insert_final_newline = true insert_final_newline = true
[{*.ASM,*.INC}]
indent_style = tab
indent_size = 8
trim_trailing_whitespace = false
[*.asm] [*.asm]
indent_style = tab indent_style = tab
indent_size = 8 indent_size = 8
trim_trailing_whitespace = true
[modules/**.js] [modules/**.js]
indent_style = space indent_style = space

View file

@ -722,8 +722,8 @@ X86CPU.prototype.initProcessor = function()
this.aOps[X86.OPCODE.INSW] = X86OpXX.opINSw; this.aOps[X86.OPCODE.INSW] = X86OpXX.opINSw;
this.aOps[X86.OPCODE.OUTSB] = X86OpXX.opOUTSb; this.aOps[X86.OPCODE.OUTSB] = X86OpXX.opOUTSb;
this.aOps[X86.OPCODE.OUTSW] = X86OpXX.opOUTSw; this.aOps[X86.OPCODE.OUTSW] = X86OpXX.opOUTSw;
this.aOps[0xC0] = X86OpXX.opGRP2ab; this.aOps[0xC0] = X86OpXX.opGrp2ab;
this.aOps[0xC1] = X86OpXX.opGRP2aw; this.aOps[0xC1] = X86OpXX.opGrp2aw;
this.aOps[X86.OPCODE.ENTER] = X86OpXX.opENTER; this.aOps[X86.OPCODE.ENTER] = X86OpXX.opENTER;
this.aOps[X86.OPCODE.LEAVE] = X86OpXX.opLEAVE; this.aOps[X86.OPCODE.LEAVE] = X86OpXX.opLEAVE;
this.aOps[0xF1] = X86OpXX.opINT1; this.aOps[0xF1] = X86OpXX.opINT1;

View file

@ -1254,7 +1254,7 @@ var X86Grps = {
}; };
/* /*
* A word (or two) on instruction groups (eg, GRP1, GRP2), which are groups of instructions that * A word (or two) on instruction groups (eg, Grp1, Grp2), which are groups of instructions that
* use a mod/reg/rm byte, where the reg field of that byte selects a function rather than a register. * use a mod/reg/rm byte, where the reg field of that byte selects a function rather than a register.
* *
* I start with the groupings used by Intel's "Pentium Processor User's Manual (Volume 3: Architecture * I start with the groupings used by Intel's "Pentium Processor User's Manual (Volume 3: Architecture
@ -1263,21 +1263,21 @@ var X86Grps = {
* *
* Opcodes Intel PCjs PC Mag TechRef * Opcodes Intel PCjs PC Mag TechRef
* ------- ----- ---- -------------- * ------- ----- ---- --------------
* 0x80-0x83 Grp1 GRP1b, GRP1w, GRP1b, and GRP1sw Group A * 0x80-0x83 Grp1 Grp1b, Grp1w, Grp1b, and Grp1sw Group A
* 0xC0-0xC1 Grp2a GRP2ab and GRP2aw Group B * 0xC0-0xC1 Grp2a Grp2ab and Grp2aw Group B
* 0xD0-0xD3 Grp2 GRP2b and GRP2w Group B * 0xD0-0xD3 Grp2 Grp2b and Grp2w Group B
* 0xF6-0xF7 Grp3 GRP3b and GRP3w Group C * 0xF6-0xF7 Grp3 Grp3b and Grp3w Group C
* 0xFE Grp4 GRP4b Group D * 0xFE Grp4 Grp4b Group D
* 0xFF Grp5 GRP4w Group E * 0xFF Grp5 Grp4w Group E
* 0x0F,0x00 Grp6 GRP6 (SLDT, STR, LLDT, LTR, VERR, VERW) Group F * 0x0F,0x00 Grp6 Grp6 (SLDT, STR, LLDT, LTR, VERR, VERW) Group F
* 0x0F,0x01 Grp7 GRP7 (SGDT, SIDT, LGDT, LIDT, SMSW, LMSW, INVLPG) Group G * 0x0F,0x01 Grp7 Grp7 (SGDT, SIDT, LGDT, LIDT, SMSW, LMSW, INVLPG) Group G
* 0x0F,0xBA Grp8 GRP8 (BT, BTS, BTR, BTC) Group H * 0x0F,0xBA Grp8 Grp8 (BT, BTS, BTR, BTC) Group H
* 0x0F,0xC7 Grp9 GRP9 (CMPXCH) (N/A, 80386 and up?) * 0x0F,0xC7 Grp9 Grp9 (CMPXCH) (N/A, 80386 and up)
* *
* My only serious deviation is Grp5, which I refer to as GRP4w, because it contains word forms of * My only serious deviation is Grp5, which I refer to as Grp4w, because it contains word forms of
* the INC and DEC instructions found in GRP4b. Granted, GRP4w also contains versions of the CALL, * the INC and DEC instructions found in Grp4b. Granted, Grp4w also contains versions of the CALL,
* JMP and PUSH instructions, which are not in GRP4b, but there's nothing in GRP4b that conflicts with * JMP and PUSH instructions, which are not in Grp4b, but there's nothing in Grp4b that conflicts with
* GRP4w, so I think my nomenclature makes more sense. To compensate, I don't use GRP5, so that the * Grp4w, so I think my nomenclature makes more sense. To compensate, I don't use Grp5, so that the
* remaining group numbers remain in sync with Intel's. * remaining group numbers remain in sync with Intel's.
*/ */
X86Grps.aOpGrp1b = [ X86Grps.aOpGrp1b = [

View file

@ -574,16 +574,22 @@ var X86Help = {
* Helper to push processor state, CS:IP, and optional error code onto the stack, and then jump * Helper to push processor state, CS:IP, and optional error code onto the stack, and then jump
* to whatever CS:IP was fetched into descIDT by opHelpLoadIDT(). * to whatever CS:IP was fetched into descIDT by opHelpLoadIDT().
* *
* For protected-mode, this function must attempt to load the new code segment first, because if the new segment
* requires a change in privilege level, the return address must be pushed on the NEW stack, not the current stack.
*
* @this {X86CPU} * @this {X86CPU}
* @param {number|null|undefined} nError * @param {number|null|undefined} nError
*/ */
opHelpPushPS: function(nError) { opHelpPushPS: function(nError) {
this.pushWord(this.getPS()); var regPS = this.getPS();
var regCS = this.segCS.sel;
var regIP = this.regIP;
this.regPS &= this.descIDT.maskPS; this.regPS &= this.descIDT.maskPS;
this.pushWord(this.segCS.sel); this.setCSIP(this.descIDT.off, this.descIDT.sel, true);
this.pushWord(this.regIP); this.pushWord(regPS);
this.pushWord(regCS);
this.pushWord(regIP);
if (nError != null) this.pushWord(nError); if (nError != null) this.pushWord(nError);
this.setCSIP(this.descIDT.off, this.descIDT.sel);
this.nFault = -1; this.nFault = -1;
}, },
/** /**

View file

@ -46,7 +46,7 @@ var X86Op0F = {
* *
* op=0x0F,0x00 (grp6 rm) * op=0x0F,0x00 (grp6 rm)
*/ */
opGRP6: function() { opGrp6: function() {
var bModRM = this.getIPByte(); var bModRM = this.getIPByte();
if ((bModRM & 0x38) < 0x10) { // possible reg values: 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38 if ((bModRM & 0x38) < 0x10) { // possible reg values: 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
if (EAFUNCS) this.modEAWord = this.modEAWordDisabled; else this.opFlags |= X86.OPFLAG.NOREAD; if (EAFUNCS) this.modEAWord = this.modEAWordDisabled; else this.opFlags |= X86.OPFLAG.NOREAD;
@ -59,7 +59,7 @@ var X86Op0F = {
* *
* op=0x0F,0x01 (grp7 rm) * op=0x0F,0x01 (grp7 rm)
*/ */
opGRP7: function() { opGrp7: function() {
var bModRM = this.getIPByte(); var bModRM = this.getIPByte();
if (!(bModRM & 0x10)) { if (!(bModRM & 0x10)) {
if (EAFUNCS) this.modEAWord = this.modEAWordDisabled; else this.opFlags |= X86.OPFLAG.NOREAD; if (EAFUNCS) this.modEAWord = this.modEAWordDisabled; else this.opFlags |= X86.OPFLAG.NOREAD;
@ -438,7 +438,7 @@ var X86Op0F = {
}; };
X86Op0F.aOps0F = [ X86Op0F.aOps0F = [
X86Op0F.opGRP6, X86Op0F.opGRP7, X86Op0F.opLAR, X86Op0F.opLSL, // 0x00-0x03 X86Op0F.opGrp6, X86Op0F.opGrp7, X86Op0F.opLAR, X86Op0F.opLSL, // 0x00-0x03
X86OpXX.opUndefined, X86Op0F.opLOADALL, X86Op0F.opCLTS, X86OpXX.opUndefined, // 0x04-0x07 X86OpXX.opUndefined, X86Op0F.opLOADALL, X86Op0F.opCLTS, X86OpXX.opUndefined, // 0x04-0x07
/* /*
* On all processors (except the 8086/8088, of course), 0x0F,0x0B is also referred to as "UD2": an * On all processors (except the 8086/8088, of course), 0x0F,0x0B is also referred to as "UD2": an
@ -509,8 +509,8 @@ X86Op0F.aOps0F = [
]; ];
/* /*
* These instruction groups are not as orthogonal as the original 8086/8088 groups (GRP1 through GRP4): some of * These instruction groups are not as orthogonal as the original 8086/8088 groups (Grp1 through Grp4): some of
* the instructions in GRP6 and GRP7 only read their dst operand (eg, LLDT), which means the ModRM helper function * the instructions in Grp6 and Grp7 only read their dst operand (eg, LLDT), which means the ModRM helper function
* must insure that setEAWord() is disabled, while others only write their dst operand (eg, SLDT), which means that * must insure that setEAWord() is disabled, while others only write their dst operand (eg, SLDT), which means that
* getEAWord() should be disabled *prior* to calling the ModRM helper function. This latter case requires that * getEAWord() should be disabled *prior* to calling the ModRM helper function. This latter case requires that
* we decode the reg field of the ModRM byte before dispatching. * we decode the reg field of the ModRM byte before dispatching.
@ -526,7 +526,7 @@ X86Op0F.aOpGrp6Real = [
]; ];
/* /*
* Unlike GRP6, GRP7 does not require separate real-mode and protected-mode dispatch tables, because all GRP7 * Unlike Grp6, Grp7 does not require separate real-mode and protected-mode dispatch tables, because all Grp7
* instructions are valid in both modes. * instructions are valid in both modes.
*/ */
X86Op0F.aOpGrp7 = [ X86Op0F.aOpGrp7 = [

View file

@ -1590,7 +1590,7 @@ var X86OpXX = {
* *
* op=0x80/0x82 (grp1b rm,imm8) * op=0x80/0x82 (grp1b rm,imm8)
*/ */
opGRP1b: function() { opGrp1b: function() {
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp1b, this.getIPByte); X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp1b, this.getIPByte);
if (EAFUNCS) this.setEAByte = this.setEAByteEnabled; if (EAFUNCS) this.setEAByte = this.setEAByteEnabled;
this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID); this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
@ -1600,7 +1600,7 @@ var X86OpXX = {
* *
* op=0x81 (grp1w rm,imm16) * op=0x81 (grp1w rm,imm16)
*/ */
opGRP1w: function() { opGrp1w: function() {
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp1w, this.getIPWord); X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp1w, this.getIPWord);
if (EAFUNCS) this.setEAWord = this.setEAWordEnabled; if (EAFUNCS) this.setEAWord = this.setEAWordEnabled;
this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID); this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
@ -1610,7 +1610,7 @@ var X86OpXX = {
* *
* op=0x83 (grp1sw rm,disp) * op=0x83 (grp1sw rm,disp)
*/ */
opGRP1sw: function() { opGrp1sw: function() {
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp1w, this.getIPDisp); X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp1w, this.getIPDisp);
if (EAFUNCS) this.setEAWord = this.setEAWordEnabled; if (EAFUNCS) this.setEAWord = this.setEAWordEnabled;
this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID); this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
@ -2639,7 +2639,7 @@ var X86OpXX = {
* *
* op=0xC0 (grp2ab rm) (80186/80188 and up) * op=0xC0 (grp2ab rm) (80186/80188 and up)
*/ */
opGRP2ab: function() { opGrp2ab: function() {
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2ab, X86Grps.opGrp2CountImm); X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2ab, X86Grps.opGrp2CountImm);
}, },
/** /**
@ -2647,7 +2647,7 @@ var X86OpXX = {
* *
* op=0xC1 (grp2aw rm) (80186/80188 and up) * op=0xC1 (grp2aw rm) (80186/80188 and up)
*/ */
opGRP2aw: function() { opGrp2aw: function() {
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2aw, X86Grps.opGrp2CountImm); X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2aw, X86Grps.opGrp2CountImm);
}, },
/** /**
@ -2849,7 +2849,7 @@ var X86OpXX = {
* *
* op=0xD0 (grp2b rm,1) * op=0xD0 (grp2b rm,1)
*/ */
opGRP2b1: function() { opGrp2b1: function() {
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2Count1); X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2Count1);
}, },
/** /**
@ -2857,7 +2857,7 @@ var X86OpXX = {
* *
* op=0xD1 (grp2w rm,1) * op=0xD1 (grp2w rm,1)
*/ */
opGRP2w1: function() { opGrp2w1: function() {
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2Count1); X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2Count1);
}, },
/** /**
@ -2865,7 +2865,7 @@ var X86OpXX = {
* *
* op=0xD2 (grp2b rm,CL) * op=0xD2 (grp2b rm,CL)
*/ */
opGRP2bCL: function() { opGrp2bCL: function() {
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2CountCL); X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2CountCL);
}, },
/** /**
@ -2873,7 +2873,7 @@ var X86OpXX = {
* *
* op=0xD3 (grp2w rm,CL) * op=0xD3 (grp2w rm,CL)
*/ */
opGRP2wCL: function() { opGrp2wCL: function() {
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountCL); X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountCL);
}, },
/** /**
@ -3241,7 +3241,7 @@ var X86OpXX = {
* *
* Similar issues with IMUL (and DIV and IDIV) are resolved using the same special variable(s). * Similar issues with IMUL (and DIV and IDIV) are resolved using the same special variable(s).
*/ */
opGRP3b: function() { opGrp3b: function() {
this.regMD16 = -1; this.regMD16 = -1;
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp3b, X86Grps.opGrpNoSrc); X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp3b, X86Grps.opGrpNoSrc);
if (this.regMD16 >= 0) this.regAX = this.regMD16; if (this.regMD16 >= 0) this.regAX = this.regMD16;
@ -3265,7 +3265,7 @@ var X86OpXX = {
* (eg, regMD16/regMD32), which we will then put back into regAX/regDX if it's been updated. This also relieves * (eg, regMD16/regMD32), which we will then put back into regAX/regDX if it's been updated. This also relieves
* us from having to decode any part of the ModRM byte, so maybe it's not such a bad work-around after all. * us from having to decode any part of the ModRM byte, so maybe it's not such a bad work-around after all.
*/ */
opGRP3w: function() { opGrp3w: function() {
this.regMD16 = -1; this.regMD16 = -1;
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp3w, X86Grps.opGrpNoSrc); X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp3w, X86Grps.opGrpNoSrc);
if (this.regMD16 >= 0) { if (this.regMD16 >= 0) {
@ -3334,7 +3334,7 @@ var X86OpXX = {
* *
* op=0xFE (grp4b rm) * op=0xFE (grp4b rm)
*/ */
opGRP4b: function() { opGrp4b: function() {
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp4b, X86Grps.opGrpNoSrc); X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp4b, X86Grps.opGrpNoSrc);
}, },
/** /**
@ -3342,7 +3342,7 @@ var X86OpXX = {
* *
* op=0xFF (grp4w rm) * op=0xFF (grp4w rm)
*/ */
opGRP4w: function() { opGrp4w: function() {
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp4w, X86Grps.opGrpNoSrc); X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp4w, X86Grps.opGrpNoSrc);
if (EAFUNCS) this.setEAWord = this.setEAWordEnabled; if (EAFUNCS) this.setEAWord = this.setEAWordEnabled;
}, },
@ -3416,7 +3416,7 @@ X86OpXX.aOps = [
* to opcode 0x82 as a "reserved" instruction, but also cryptically refers to it as "MOVB AL,imm". This is * to opcode 0x82 as a "reserved" instruction, but also cryptically refers to it as "MOVB AL,imm". This is
* assumed to be an error in the manual, because as far as I know, 0x82 has always mirrored 0x80. * assumed to be an error in the manual, because as far as I know, 0x82 has always mirrored 0x80.
*/ */
X86OpXX.opGRP1b, X86OpXX.opGRP1w, X86OpXX.opGRP1b, X86OpXX.opGRP1sw, // 0x80-0x83 X86OpXX.opGrp1b, X86OpXX.opGrp1w, X86OpXX.opGrp1b, X86OpXX.opGrp1sw, // 0x80-0x83
X86OpXX.opTESTrb, X86OpXX.opTESTrw, X86OpXX.opXCHGrb, X86OpXX.opXCHGrw, // 0x84-0x87 X86OpXX.opTESTrb, X86OpXX.opTESTrw, X86OpXX.opXCHGrb, X86OpXX.opXCHGrw, // 0x84-0x87
X86OpXX.opMOVmb, X86OpXX.opMOVmw, X86OpXX.opMOVrb, X86OpXX.opMOVrw, // 0x88-0x8B X86OpXX.opMOVmb, X86OpXX.opMOVmw, X86OpXX.opMOVrb, X86OpXX.opMOVrw, // 0x88-0x8B
X86OpXX.opMOVSegSrc, X86OpXX.opLEA, X86OpXX.opMOVSegDst, X86OpXX.opPOPmw, // 0x8C-0x8F X86OpXX.opMOVSegSrc, X86OpXX.opLEA, X86OpXX.opMOVSegDst, X86OpXX.opPOPmw, // 0x8C-0x8F
@ -3439,7 +3439,7 @@ X86OpXX.aOps = [
X86OpXX.opLES, X86OpXX.opLDS, X86OpXX.opMOVb, X86OpXX.opMOVw, // 0xC4-0xC7 X86OpXX.opLES, X86OpXX.opLDS, X86OpXX.opMOVb, X86OpXX.opMOVw, // 0xC4-0xC7
X86OpXX.opRETFn, X86OpXX.opRETF, X86OpXX.opRETFn, X86OpXX.opRETF, // 0xC8-0xCB X86OpXX.opRETFn, X86OpXX.opRETF, X86OpXX.opRETFn, X86OpXX.opRETF, // 0xC8-0xCB
X86OpXX.opINT3, X86OpXX.opINTn, X86OpXX.opINTO, X86OpXX.opIRET, // 0xCC-0xCF X86OpXX.opINT3, X86OpXX.opINTn, X86OpXX.opINTO, X86OpXX.opIRET, // 0xCC-0xCF
X86OpXX.opGRP2b1, X86OpXX.opGRP2w1, X86OpXX.opGRP2bCL, X86OpXX.opGRP2wCL, // 0xD0-0xD3 X86OpXX.opGrp2b1, X86OpXX.opGrp2w1, X86OpXX.opGrp2bCL, X86OpXX.opGrp2wCL, // 0xD0-0xD3
/* /*
* Even as of the Pentium, opcode 0xD6 is still marked as "reserved", but it's always been SETALC/SALC. * Even as of the Pentium, opcode 0xD6 is still marked as "reserved", but it's always been SETALC/SALC.
*/ */
@ -3455,9 +3455,9 @@ X86OpXX.aOps = [
* a prefix on those processors, so we treat it as such. As of the Pentium, it is still marked as "reserved". * a prefix on those processors, so we treat it as such. As of the Pentium, it is still marked as "reserved".
*/ */
X86OpXX.opLOCK, X86OpXX.opLOCK, X86OpXX.opREPNZ, X86OpXX.opREPZ, // 0xF0-0xF3 X86OpXX.opLOCK, X86OpXX.opLOCK, X86OpXX.opREPNZ, X86OpXX.opREPZ, // 0xF0-0xF3
X86OpXX.opHLT, X86OpXX.opCMC, X86OpXX.opGRP3b, X86OpXX.opGRP3w, // 0xF4-0xF7 X86OpXX.opHLT, X86OpXX.opCMC, X86OpXX.opGrp3b, X86OpXX.opGrp3w, // 0xF4-0xF7
X86OpXX.opCLC, X86OpXX.opSTC, X86OpXX.opCLI, X86OpXX.opSTI, // 0xF8-0xFB X86OpXX.opCLC, X86OpXX.opSTC, X86OpXX.opCLI, X86OpXX.opSTI, // 0xF8-0xFB
X86OpXX.opCLD, X86OpXX.opSTD, X86OpXX.opGRP4b, X86OpXX.opGRP4w // 0xFC-0xFF X86OpXX.opCLD, X86OpXX.opSTD, X86OpXX.opGrp4b, X86OpXX.opGrp4w // 0xFC-0xFF
]; ];
if (typeof module !== 'undefined') module.exports = X86OpXX; if (typeof module !== 'undefined') module.exports = X86OpXX;

View file

@ -59,7 +59,31 @@ function X86Seg(cpu, id, sName, fProt)
this.addrDesc = null; this.addrDesc = null;
this.cpl = 0; this.cpl = 0;
this.dpl = 0; this.dpl = 0;
/*
* The following properties are used for CODE segments only (ie, segCS); if the process of loading
* CS also requires a stack switch, then fStackSwitch will be set to true; additionally, if the stack
* switch was the result of a CALL (ie, fCall is true) and one or more (up to 32) parameters are on
* the old stack, they will be copied to awScratch, and then once the stack is switched, the parameters
* will be pushed from awScratch onto the new stack.
*
* The typical ways of loading a new segment into CS are JMPF, CALLF (or INT), and RETF (or IRET);
* prior to calling segCS.load(), each of those operations must first set segCS.fCall to one of null,
* true, or false, respectively.
*
* It's critical that fCall be properly set prior to calling segCS.load(); fCall == null means NO
* privilege level transition may occur, fCall == true allows a stack switch and a privilege transition
* to a numerically lower privilege, and fCall == false allows a stack switch (restore) and a privilege
* transition to a numerically greater privilege.
*
* As long as setCSIP() is used for all CS changes, the foregoing is automatically taken care of.
*
* TODO: Consider making fCall a parameter to load(), instead of a property that must be set prior to
* calling load(); the downside (and why I didn't do that in the first place) is that such a parameter
* to load() would be meaningless for segments other than segCS.
*/
this.awScratch = (this.id == X86Seg.ID.CODE? new Array(32) : []); this.awScratch = (this.id == X86Seg.ID.CODE? new Array(32) : []);
this.fCall = null;
this.fStackSwitch = false;
this.updateAccess(fProt); this.updateAccess(fProt);
} }
@ -470,7 +494,7 @@ X86Seg.prototype.setBase = function(addr)
* save() * save()
* *
* Early versions of PCjs saved only segment selectors, since that's all that mattered in real-mode; * Early versions of PCjs saved only segment selectors, since that's all that mattered in real-mode;
* newer versions need to save/restore the entire segment object. * newer versions need to save/restore all the "defining" properties of the X86Seg object.
* *
* @this {X86Seg} * @this {X86Seg}
* @return {Array} * @return {Array}
@ -484,7 +508,7 @@ X86Seg.prototype.save = function()
* restore(a) * restore(a)
* *
* Early versions of PCjs saved only segment selectors, since that's all that mattered in real-mode; * Early versions of PCjs saved only segment selectors, since that's all that mattered in real-mode;
* newer versions need to save/restore the entire segment object. * newer versions need to save/restore all the "defining" properties of the X86Seg object.
* *
* @this {X86Seg} * @this {X86Seg}
* @param {Array|number} a * @param {Array|number} a
@ -555,8 +579,6 @@ X86Seg.prototype.updateAccess = function(fProt)
this.cpl = this.dpl = 0; this.cpl = this.dpl = 0;
this.addrDesc = null; this.addrDesc = null;
} }
this.fCall = null; // true if CALLF in progress, false if RETF in progress, null/undefined otherwise (X86Seg.ID.CODE only)
this.fStackSwitch = false; // true if a stack switch occurred on the last loadDesc8(), false otherwise (X86Seg.ID.CODE only)
return fProt; return fProt;
}; };