Added CLTS support, TSS dumping, proper setting of the NT and IOPL flag bits, and more
This commit is contained in:
parent
6660b9479f
commit
2a7bc0f454
9 changed files with 312 additions and 208 deletions
|
|
@ -305,6 +305,17 @@ Bus.prototype.setA20 = function(fEnable)
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* getWidth()
|
||||
*
|
||||
* @this {Bus}
|
||||
* @return {number}
|
||||
*/
|
||||
Bus.prototype.getWidth = function()
|
||||
{
|
||||
return this.nBusWidth;
|
||||
};
|
||||
|
||||
/**
|
||||
* setMemoryAccess(addr, size)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -80,6 +80,11 @@ function Debugger(parmsDbg)
|
|||
this.nCycles = -1;
|
||||
this.cInstructions = -1;
|
||||
|
||||
/*
|
||||
* The default numder of hex characters in a physical address; updated by initBus().
|
||||
*/
|
||||
this.cchAddr = 5;
|
||||
|
||||
/*
|
||||
* Most commands that require an address call parseAddr(), which defaults to aAddrNextCode
|
||||
* or aAddrNextData when no address has been given. doDump() and doUnassemble(), in turn,
|
||||
|
|
@ -183,31 +188,33 @@ function Debugger(parmsDbg)
|
|||
*/
|
||||
Debugger.MESSAGE = {
|
||||
CPU: 0x00000001,
|
||||
INT: 0x00000002,
|
||||
SEG: 0x00000004,
|
||||
FAULT: 0x00000008,
|
||||
MEM: 0x00000010,
|
||||
PORT: 0x00000020,
|
||||
DMA: 0x00000040,
|
||||
PIC: 0x00000080,
|
||||
TIMER: 0x00000100,
|
||||
CMOS: 0x00000200,
|
||||
RTC: 0x00000400,
|
||||
C8042: 0x00000800,
|
||||
CHIPSET: 0x00001000,
|
||||
KBD: 0x00002000,
|
||||
KEYS: 0x00004000,
|
||||
VIDEO: 0x00008000,
|
||||
FDC: 0x00010000,
|
||||
HDC: 0x00020000,
|
||||
DISK: 0x00040000,
|
||||
SERIAL: 0x00080000,
|
||||
SPEAKER: 0x00100000,
|
||||
STATE: 0x00200000,
|
||||
MOUSE: 0x00400000,
|
||||
COMPUTER: 0x00800000,
|
||||
LOG: 0x01000000,
|
||||
DOS: 0x02000000,
|
||||
SEG: 0x00000002,
|
||||
DESC: 0x00000004,
|
||||
TSS: 0x00000008,
|
||||
INT: 0x00000010,
|
||||
FAULT: 0x00000020,
|
||||
MEM: 0x00000040,
|
||||
PORT: 0x00000080,
|
||||
DMA: 0x00000100,
|
||||
PIC: 0x00000200,
|
||||
TIMER: 0x00000400,
|
||||
CMOS: 0x00000800,
|
||||
RTC: 0x00001000,
|
||||
C8042: 0x00002000,
|
||||
CHIPSET: 0x00004000,
|
||||
KBD: 0x00008000,
|
||||
KEYS: 0x00010000,
|
||||
VIDEO: 0x00020000,
|
||||
FDC: 0x00040000,
|
||||
HDC: 0x00080000,
|
||||
DISK: 0x00100000,
|
||||
SERIAL: 0x00200000,
|
||||
SPEAKER: 0x00400000,
|
||||
STATE: 0x00800000,
|
||||
MOUSE: 0x01000000,
|
||||
COMPUTER: 0x02000000,
|
||||
LOG: 0x04000000,
|
||||
DOS: 0x08000000,
|
||||
HALT: 0x80000000
|
||||
};
|
||||
|
||||
|
|
@ -495,8 +502,10 @@ if (DEBUGGER) {
|
|||
*/
|
||||
Debugger.MESSAGES = {
|
||||
"cpu": Debugger.MESSAGE.CPU,
|
||||
"int": Debugger.MESSAGE.INT,
|
||||
"seg": Debugger.MESSAGE.SEG,
|
||||
"desc": Debugger.MESSAGE.DESC,
|
||||
"tss": Debugger.MESSAGE.TSS,
|
||||
"int": Debugger.MESSAGE.INT,
|
||||
"fault": Debugger.MESSAGE.FAULT,
|
||||
"mem": Debugger.MESSAGE.MEM,
|
||||
"port": Debugger.MESSAGE.PORT,
|
||||
|
|
@ -886,7 +895,8 @@ if (DEBUGGER) {
|
|||
0x01: [Debugger.INS.GRP7, Debugger.TYPE_MODRM | Debugger.TYPE_WORD | Debugger.TYPE_BOTH],
|
||||
0x02: [Debugger.INS.LAR, Debugger.TYPE_REG | Debugger.TYPE_WORD | Debugger.TYPE_IN | Debugger.TYPE_286, Debugger.TYPE_MEM | Debugger.TYPE_WORD | Debugger.TYPE_IN],
|
||||
0x03: [Debugger.INS.LSL, Debugger.TYPE_REG | Debugger.TYPE_WORD | Debugger.TYPE_IN | Debugger.TYPE_286, Debugger.TYPE_MEM | Debugger.TYPE_WORD | Debugger.TYPE_IN],
|
||||
0x05: [Debugger.INS.LOADALL,Debugger.TYPE_286]
|
||||
0x05: [Debugger.INS.LOADALL,Debugger.TYPE_286],
|
||||
0x06: [Debugger.INS.CLTS, Debugger.TYPE_286]
|
||||
};
|
||||
|
||||
Debugger.aaGrpDescs = [
|
||||
|
|
@ -1197,6 +1207,8 @@ if (DEBUGGER) {
|
|||
this.hdc = cmp.getComponentByType("HDC");
|
||||
if (MAXDEBUG) this.chipset = cmp.getComponentByType("ChipSet");
|
||||
|
||||
this.cchAddr = bus.getWidth() >> 2;
|
||||
|
||||
this.aaOpDescs = Debugger.aaOpDescs;
|
||||
if (this.cpu.model >= X86.MODEL_80186) {
|
||||
this.aaOpDescs = Debugger.aaOpDescs.slice();
|
||||
|
|
@ -1206,9 +1218,8 @@ if (DEBUGGER) {
|
|||
}
|
||||
}
|
||||
|
||||
this.messageDump(Debugger.MESSAGE.DOS, function onDumpDOS(s) {
|
||||
dbg.dumpDOS(s);
|
||||
});
|
||||
this.messageDump(Debugger.MESSAGE.TSS, function onDumpTSS(s) { dbg.dumpTSS(s); });
|
||||
this.messageDump(Debugger.MESSAGE.DOS, function onDumpDOS(s) { dbg.dumpDOS(s); });
|
||||
|
||||
this.setReady();
|
||||
|
||||
|
|
@ -1320,6 +1331,8 @@ if (DEBUGGER) {
|
|||
/**
|
||||
* dumpDOS(s)
|
||||
*
|
||||
* This dumps DOS MCBs (Memory Control Blocks).
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {string} [s]
|
||||
*/
|
||||
|
|
@ -1345,6 +1358,67 @@ if (DEBUGGER) {
|
|||
}
|
||||
};
|
||||
|
||||
Debugger.aTSSFields = {
|
||||
"PREV_TSS": 0x00,
|
||||
"CPL0_SP": 0x02,
|
||||
"CPL0_SS": 0x04,
|
||||
"CPL1_SP": 0x06,
|
||||
"CPL1_SS": 0x08,
|
||||
"CPL2_SP": 0x0a,
|
||||
"CPL2_SS": 0x0c,
|
||||
"TASK_IP": 0x0e,
|
||||
"TASK_PS": 0x10,
|
||||
"TASK_AX": 0x12,
|
||||
"TASK_CX": 0x14,
|
||||
"TASK_DX": 0x16,
|
||||
"TASK_BX": 0x18,
|
||||
"TASK_SP": 0x1a,
|
||||
"TASK_BP": 0x1c,
|
||||
"TASK_SI": 0x1e,
|
||||
"TASK_DI": 0x20,
|
||||
"TASK_ES": 0x22,
|
||||
"TASK_CS": 0x24,
|
||||
"TASK_SS": 0x26,
|
||||
"TASK_DS": 0x28,
|
||||
"TASK_LDT": 0x2a
|
||||
};
|
||||
|
||||
/**
|
||||
* dumpTSS(s)
|
||||
*
|
||||
* This dumps a TSS using the given selector. If none is specified, the current TR is used.
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {string} [s]
|
||||
*/
|
||||
Debugger.prototype.dumpTSS = function(s)
|
||||
{
|
||||
var seg;
|
||||
if (!s) {
|
||||
seg = this.cpu.segTSS;
|
||||
} else {
|
||||
var sel = str.parseInt(s);
|
||||
if (sel === undefined) {
|
||||
this.println("invalid task selector: " + s);
|
||||
return;
|
||||
}
|
||||
seg = this.getSegment(sel);
|
||||
}
|
||||
|
||||
this.println("dumpTSS(" + str.toHexWord(seg.sel) + "): %" + str.toHex(seg.base, this.cchAddr));
|
||||
|
||||
var sDump = "";
|
||||
for (var sField in Debugger.aTSSFields) {
|
||||
var off = Debugger.aTSSFields[sField];
|
||||
var ch = (sField.length < 8? ' ' : '');
|
||||
var w = this.bus.getWordDirect(seg.base + off);
|
||||
if (sDump) sDump += '\n';
|
||||
sDump += str.toHexWord(off) + " " + sField + ": " + ch + str.toHexWord(w);
|
||||
}
|
||||
|
||||
this.println(sDump);
|
||||
};
|
||||
|
||||
/**
|
||||
* dumpSZ(aAddr, cchMax)
|
||||
*
|
||||
|
|
@ -2869,7 +2943,7 @@ if (DEBUGGER) {
|
|||
*/
|
||||
Debugger.prototype.getSegStr = function(seg, fProt)
|
||||
{
|
||||
return seg.sName + '=' + str.toHexWord(seg.sel) + (fProt? '[' + str.toHex(seg.base, 6) + ',' + str.toHexWord(seg.limit) + ']' : "");
|
||||
return seg.sName + '=' + str.toHexWord(seg.sel) + (fProt? '[' + str.toHex(seg.base, this.cchAddr) + ',' + str.toHexWord(seg.limit) + ']' : "");
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2884,7 +2958,7 @@ if (DEBUGGER) {
|
|||
*/
|
||||
Debugger.prototype.getDTRStr = function(sName, sel, addr, addrLimit)
|
||||
{
|
||||
return sName + '=' + (sel != null? str.toHexWord(sel) : "") + '[' + str.toHex(addr, 6) + ',' + str.toHexWord(addrLimit - addr) + ']';
|
||||
return sName + '=' + (sel != null? str.toHexWord(sel) : "") + '[' + str.toHex(addr, this.cchAddr) + ',' + str.toHexWord(addrLimit - addr) + ']';
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -3843,6 +3917,41 @@ if (DEBUGGER) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* doList(sSymbol)
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {string} sSymbol
|
||||
*/
|
||||
Debugger.prototype.doList = function(sSymbol)
|
||||
{
|
||||
var aAddr = this.parseAddr(sSymbol, Debugger.ADDR_CODE);
|
||||
if (aAddr[0] == null && aAddr[2] == null) return;
|
||||
|
||||
var addr = this.getAddr(aAddr);
|
||||
|
||||
this.println(sSymbol + ": " + this.hexAddr(aAddr) + " (%" + str.toHex(addr, this.cchAddr) + ")");
|
||||
|
||||
var aSymbol = this.findSymbolAtAddr(aAddr, true);
|
||||
if (aSymbol.length) {
|
||||
var nDelta, sDelta;
|
||||
if (aSymbol[0]) {
|
||||
sDelta = "";
|
||||
nDelta = aAddr[0] - aSymbol[1];
|
||||
if (nDelta) sDelta = " + " + str.toHexWord(nDelta);
|
||||
this.println(aSymbol[0] + " (" + str.toHexAddr(aSymbol[1], aAddr[1]) + ")" + sDelta);
|
||||
}
|
||||
if (aSymbol.length > 4 && aSymbol[4]) {
|
||||
sDelta = "";
|
||||
nDelta = aSymbol[5] - aAddr[0];
|
||||
if (nDelta) sDelta = " - " + str.toHexWord(nDelta);
|
||||
this.println(aSymbol[4] + " (" + str.toHexAddr(aSymbol[5], aAddr[1]) + ")" + sDelta);
|
||||
}
|
||||
} else {
|
||||
this.println("no symbols");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* doLoad(asArgs)
|
||||
*
|
||||
|
|
@ -3869,37 +3978,15 @@ if (DEBUGGER) {
|
|||
return;
|
||||
}
|
||||
|
||||
var aAddr = [], iDrive, iSector = 0, nSectors = 0;
|
||||
|
||||
var fJSON = false;
|
||||
if (asArgs[1] == "json") {
|
||||
fJSON = true;
|
||||
} else {
|
||||
var fListSymbols = (asArgs[0] == "ln");
|
||||
aAddr = this.parseAddr(asArgs[1], fListSymbols? Debugger.ADDR_CODE : Debugger.ADDR_DATA);
|
||||
if (fListSymbols) {
|
||||
var aSymbol = this.findSymbolAtAddr(aAddr, true);
|
||||
if (aSymbol.length) {
|
||||
var nDelta, sDelta;
|
||||
if (aSymbol[0]) {
|
||||
sDelta = "";
|
||||
nDelta = aAddr[0] - aSymbol[1];
|
||||
if (nDelta) sDelta = " + " + str.toHexWord(nDelta);
|
||||
this.println(aSymbol[0] + " (" + str.toHexAddr(aSymbol[1], aAddr[1]) + ")" + sDelta);
|
||||
}
|
||||
if (aSymbol.length > 4 && aSymbol[4]) {
|
||||
sDelta = "";
|
||||
nDelta = aSymbol[5] - aAddr[0];
|
||||
if (nDelta) sDelta = " - " + str.toHexWord(nDelta);
|
||||
this.println(aSymbol[4] + " (" + str.toHexAddr(aSymbol[5], aAddr[1]) + ")" + sDelta);
|
||||
}
|
||||
} else {
|
||||
this.println("no symbols");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (asArgs[0] == "ln") {
|
||||
this.doList(asArgs[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
var fJSON = (asArgs[1] == "json");
|
||||
var iDrive, iSector = 0, nSectors = 0;
|
||||
var aAddr = (fJSON? [] : this.parseAddr(asArgs[1], Debugger.ADDR_DATA));
|
||||
|
||||
iDrive = this.parseValue(asArgs[2], "drive #");
|
||||
if (iDrive === undefined) return;
|
||||
if (!fJSON) {
|
||||
|
|
@ -4147,14 +4234,11 @@ if (DEBUGGER) {
|
|||
var sReg = asArgs[1];
|
||||
if (sReg == 'p') {
|
||||
/*
|
||||
* If the CPU has not defined addrGDT, then there are no protected-mode registers
|
||||
*
|
||||
* TODO: Come up with a more formal way of determining the CPU's support for protected-mode,
|
||||
* and/or report an error.
|
||||
* If the CPU has not defined addrGDT, then there are no protected-mode registers.
|
||||
*/
|
||||
fProt = (this.cpu.addrGDT !== undefined);
|
||||
} else {
|
||||
fIns = false;
|
||||
// fIns = false;
|
||||
var sValue = null;
|
||||
var i = sReg.indexOf("=");
|
||||
if (i > 0) {
|
||||
|
|
@ -4230,20 +4314,21 @@ if (DEBUGGER) {
|
|||
this.cpu.setSS(w);
|
||||
break;
|
||||
case "CS":
|
||||
fIns = true;
|
||||
// fIns = true;
|
||||
this.cpu.setCS(w);
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regIP, this.cpu.segCS.sel);
|
||||
break;
|
||||
case "IP":
|
||||
fIns = true;
|
||||
// fIns = true;
|
||||
this.cpu.setIP(w);
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regIP, this.cpu.segCS.sel);
|
||||
break;
|
||||
/*
|
||||
* I used to alias "PC" to "IP", until I discovered that early (perhaps ALL) versions of
|
||||
* DEBUG.COM treat "PC" as an alias for the 16-bit flags register.
|
||||
* DEBUG.COM treat "PC" as an alias for the 16-bit flags register. I, of course, prefer "PS".
|
||||
*/
|
||||
case "PC":
|
||||
case "PS":
|
||||
this.cpu.setPS(w);
|
||||
break;
|
||||
case "C":
|
||||
|
|
|
|||
|
|
@ -146,21 +146,21 @@ var X86 = {
|
|||
CPL1_SS: 0x08,
|
||||
CPL2_SP: 0x0a,
|
||||
CPL2_SS: 0x0c,
|
||||
CURR_IP: 0x0e,
|
||||
CURR_PS: 0x10,
|
||||
CURR_AX: 0x12,
|
||||
CURR_CX: 0x14,
|
||||
CURR_DX: 0x16,
|
||||
CURR_BX: 0x18,
|
||||
CURR_SP: 0x1a,
|
||||
CURR_BP: 0x1c,
|
||||
CURR_SI: 0x1e,
|
||||
CURR_DI: 0x20,
|
||||
CURR_ES: 0x22,
|
||||
CURR_CS: 0x24,
|
||||
CURR_SS: 0x26,
|
||||
CURR_DS: 0x28, // end of values altered by task switches
|
||||
CURR_LDT: 0x2a
|
||||
TASK_IP: 0x0e,
|
||||
TASK_PS: 0x10,
|
||||
TASK_AX: 0x12,
|
||||
TASK_CX: 0x14,
|
||||
TASK_DX: 0x16,
|
||||
TASK_BX: 0x18,
|
||||
TASK_SP: 0x1a,
|
||||
TASK_BP: 0x1c,
|
||||
TASK_SI: 0x1e,
|
||||
TASK_DI: 0x20,
|
||||
TASK_ES: 0x22,
|
||||
TASK_CS: 0x24,
|
||||
TASK_SS: 0x26,
|
||||
TASK_DS: 0x28, // end of values altered by task switches
|
||||
TASK_LDT: 0x2a
|
||||
},
|
||||
/*
|
||||
* Processor Exception Interrupts
|
||||
|
|
@ -320,7 +320,7 @@ X86.PS.DIRECT = (X86.PS.TF | X86.PS.IF | X86.PS.DF);
|
|||
X86.PS.INDIRECT = (X86.PS.CF | X86.PS.PF | X86.PS.AF | X86.PS.ZF | X86.PS.SF | X86.PS.OF);
|
||||
|
||||
/*
|
||||
* NOTE: These are the default "always set" PS bits for the 8086/8088; other processors must
|
||||
* These are the default "always set" PS bits for the 8086/8088; other processors must
|
||||
* adjust these bits accordingly. The final adjusted value is then stored in the X86CPU object
|
||||
* as "this.PS_SET"; setPS() must use that value, NOT this one.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -671,12 +671,17 @@ X86CPU.prototype.setAddressMask = function(addrMask)
|
|||
X86CPU.prototype.initProcessor = function()
|
||||
{
|
||||
this.PS_SET = X86.PS.SET;
|
||||
this.PS_DIRECT = X86.PS.DIRECT;
|
||||
|
||||
this.OPFLAG_NOINTR8086 = X86.OPFLAG.NOINTR;
|
||||
this.nShiftCountMask = 0xff; // on an 8086/8088, all shift counts are used as-is
|
||||
|
||||
this.CYCLES = (this.model >= X86.MODEL_80286? X86CPU.CYCLES_80286 : X86CPU.CYCLES_8088);
|
||||
|
||||
this.aOps = X86OpXX.aOps.slice(); // make a copy of aOps before modifying it
|
||||
this.aOps = X86OpXX.aOps.slice(); // make a copy of aOps and others before modifying them
|
||||
this.aOpGrp4b = X86Grps.aOpGrp4b.slice();
|
||||
this.aOpGrp4w = X86Grps.aOpGrp4w.slice();
|
||||
this.aOpGrp6 = X86Op0F.aOpGrp6Real; // setProtMode() will ensure that aOpGrp6 is switched
|
||||
|
||||
if (this.model >= X86.MODEL_80186) {
|
||||
/*
|
||||
|
|
@ -686,35 +691,39 @@ X86CPU.prototype.initProcessor = function()
|
|||
* opOUTSw, opENTER, and opLEAVE.
|
||||
*/
|
||||
this.nShiftCountMask = 0x1f; // on newer processors, all shift counts are MOD 32
|
||||
this.aOps[0x0F] = X86OpXX.opInvalid;
|
||||
this.aOps[X86.OPCODE.PUSHA] = X86OpXX.opPUSHA;
|
||||
this.aOps[X86.OPCODE.POPA] = X86OpXX.opPOPA;
|
||||
this.aOps[X86.OPCODE.BOUND] = X86OpXX.opBOUND;
|
||||
this.aOps[0x63] = X86OpXX.opInvalid;
|
||||
this.aOps[0x64] = X86OpXX.opInvalid;
|
||||
this.aOps[0x65] = X86OpXX.opInvalid;
|
||||
this.aOps[0x66] = X86OpXX.opInvalid;
|
||||
this.aOps[0x67] = X86OpXX.opInvalid;
|
||||
this.aOps[X86.OPCODE.PUSH16]= X86OpXX.opPUSH16;
|
||||
this.aOps[X86.OPCODE.IMUL16]= X86OpXX.opIMUL16;
|
||||
this.aOps[X86.OPCODE.PUSH8] = X86OpXX.opPUSH8;
|
||||
this.aOps[X86.OPCODE.IMUL8] = X86OpXX.opIMUL8;
|
||||
this.aOps[X86.OPCODE.INSB] = X86OpXX.opINSb;
|
||||
this.aOps[X86.OPCODE.INSW] = X86OpXX.opINSw;
|
||||
this.aOps[X86.OPCODE.OUTSB] = X86OpXX.opOUTSb;
|
||||
this.aOps[X86.OPCODE.OUTSW] = X86OpXX.opOUTSw;
|
||||
this.aOps[0xC0] = X86OpXX.opGRP2ab;
|
||||
this.aOps[0xC1] = X86OpXX.opGRP2aw;
|
||||
this.aOps[X86.OPCODE.ENTER] = X86OpXX.opENTER;
|
||||
this.aOps[X86.OPCODE.LEAVE] = X86OpXX.opLEAVE;
|
||||
this.aOps[0xF1] = X86OpXX.opINT1;
|
||||
X86Grps.aOpGRP4b[0x07] = X86Grps.opGrpInvalid;
|
||||
X86Grps.aOpGRP4w[0x07] = X86Grps.opGrpInvalid;
|
||||
this.aOps[0x0F] = X86OpXX.opInvalid;
|
||||
this.aOps[X86.OPCODE.PUSHA] = X86OpXX.opPUSHA;
|
||||
this.aOps[X86.OPCODE.POPA] = X86OpXX.opPOPA;
|
||||
this.aOps[X86.OPCODE.BOUND] = X86OpXX.opBOUND;
|
||||
this.aOps[0x63] = X86OpXX.opInvalid;
|
||||
this.aOps[0x64] = X86OpXX.opInvalid;
|
||||
this.aOps[0x65] = X86OpXX.opInvalid;
|
||||
this.aOps[0x66] = X86OpXX.opInvalid;
|
||||
this.aOps[0x67] = X86OpXX.opInvalid;
|
||||
this.aOps[X86.OPCODE.PUSH16] = X86OpXX.opPUSH16;
|
||||
this.aOps[X86.OPCODE.IMUL16] = X86OpXX.opIMUL16;
|
||||
this.aOps[X86.OPCODE.PUSH8] = X86OpXX.opPUSH8;
|
||||
this.aOps[X86.OPCODE.IMUL8] = X86OpXX.opIMUL8;
|
||||
this.aOps[X86.OPCODE.INSB] = X86OpXX.opINSb;
|
||||
this.aOps[X86.OPCODE.INSW] = X86OpXX.opINSw;
|
||||
this.aOps[X86.OPCODE.OUTSB] = X86OpXX.opOUTSb;
|
||||
this.aOps[X86.OPCODE.OUTSW] = X86OpXX.opOUTSw;
|
||||
this.aOps[0xC0] = X86OpXX.opGRP2ab;
|
||||
this.aOps[0xC1] = X86OpXX.opGRP2aw;
|
||||
this.aOps[X86.OPCODE.ENTER] = X86OpXX.opENTER;
|
||||
this.aOps[X86.OPCODE.LEAVE] = X86OpXX.opLEAVE;
|
||||
this.aOps[0xF1] = X86OpXX.opINT1;
|
||||
this.aOpGrp4b[0x07] = X86Grps.opGrpInvalid;
|
||||
this.aOpGrp4w[0x07] = X86Grps.opGrpInvalid;
|
||||
|
||||
if (this.model >= X86.MODEL_80286) {
|
||||
|
||||
this.PS_SET = X86.PS.BIT1; // on the 80286, only BIT1 of Processor Status (flags) is always set
|
||||
this.PS_DIRECT |= X86.PS.IOPL.MASK | X86.PS.NT;
|
||||
|
||||
this.OPFLAG_NOINTR8086 = 0; // used with instructions that should *not* set NOINTR on an 80286 (eg, non-SS segment loads)
|
||||
this.aOps[0x0F] = X86OpXX.op0F;
|
||||
|
||||
this.aOps[0x0F] = X86OpXX.op0F;
|
||||
this.aOps[X86.OPCODE.ARPL] = X86OpXX.opARPL;
|
||||
this.aOps[X86.OPCODE.PUSHSP]= X86OpXX.opPUSHSP;
|
||||
}
|
||||
|
|
@ -1010,11 +1019,7 @@ X86CPU.prototype.setProtMode = function(fProt)
|
|||
if (fProt === undefined) {
|
||||
fProt = !!(this.regMSW & X86.MSW.PE);
|
||||
}
|
||||
if (fProt) {
|
||||
X86Op0F.aOpGRP6 = X86Op0F.aOpGRP6Prot;
|
||||
} else {
|
||||
X86Op0F.aOpGRP6 = X86Op0F.aOpGRP6Real;
|
||||
}
|
||||
this.aOpGrp6 = (fProt? X86Op0F.aOpGrp6Prot : X86Op0F.aOpGrp6Real);
|
||||
this.segCS.updateAccess(fProt);
|
||||
this.segDS.updateAccess(fProt);
|
||||
this.segSS.updateAccess(fProt);
|
||||
|
|
@ -1600,8 +1605,9 @@ X86CPU.prototype.setPS = function(regPS)
|
|||
if (regPS & X86.PS.OF) this.setOF();
|
||||
|
||||
/*
|
||||
* Since PS.IOPL and PS.IF are part of PS.DIRECT, we need to take care of any 80286-specific checks before
|
||||
* setting the PS.DIRECT bits. Specifically, PS.IOPL is unchanged if CPL > 0, and PS.IF is unchanged if CPL > IOPL.
|
||||
* Since PS.IOPL and PS.IF are part of PS_DIRECT, we need to take care of any 80286-specific checks before
|
||||
* setting the PS_DIRECT bits from the incoming regPS bits. Specifically, PS.IOPL is unchanged if CPL > 0,
|
||||
* and PS.IF is unchanged if CPL > IOPL.
|
||||
*/
|
||||
if (!this.segCS.cpl) {
|
||||
this.nIOPL = (regPS & X86.PS.IOPL.MASK) >> X86.PS.IOPL.SHIFT; // IOPL allowed to change
|
||||
|
|
@ -1609,11 +1615,12 @@ X86CPU.prototype.setPS = function(regPS)
|
|||
} else {
|
||||
regPS = (regPS & ~X86.PS.IOPL.MASK) | (this.regPS & X86.PS.IOPL.MASK); // IOPL not allowed to change
|
||||
}
|
||||
|
||||
if (this.segCS.cpl > this.nIOPL) {
|
||||
regPS = (regPS & ~X86.PS.IF) | (this.regPS & X86.PS.IF); // IF not allowed to change
|
||||
}
|
||||
|
||||
this.regPS = (this.regPS & ~X86.PS.DIRECT) | (regPS & X86.PS.DIRECT) | this.PS_SET;
|
||||
this.regPS = (this.regPS & ~this.PS_DIRECT) | (regPS & this.PS_DIRECT) | this.PS_SET;
|
||||
|
||||
/*
|
||||
* Assert that all requested flag bits now agree with our simulated (PS_INDIRECT) bits
|
||||
|
|
|
|||
|
|
@ -1282,12 +1282,12 @@ var X86Grps = {
|
|||
* 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.
|
||||
*/
|
||||
X86Grps.aOpGRP1b = [
|
||||
X86Grps.aOpGrp1b = [
|
||||
X86Grps.opGrpADDb, X86Grps.opGrpORb, X86Grps.opGrpADCb, X86Grps.opGrpSBBb, // 0x80/0x82(reg=0x0-0x3)
|
||||
X86Grps.opGrpANDb, X86Grps.opGrpSUBb, X86Grps.opGrpXORb, X86Grps.opGrpCMPb // 0x80/0x82(reg=0x4-0x7)
|
||||
];
|
||||
|
||||
X86Grps.aOpGRP1w = [
|
||||
X86Grps.aOpGrp1w = [
|
||||
X86Grps.opGrpADDw, X86Grps.opGrpORw, X86Grps.opGrpADCw, X86Grps.opGrpSBBw, // 0x81/0x83(reg=0x0-0x3)
|
||||
X86Grps.opGrpANDw, X86Grps.opGrpSUBw, X86Grps.opGrpXORw, X86Grps.opGrpCMPw // 0x81/0x83(reg=0x4-0x7)
|
||||
];
|
||||
|
|
@ -1302,32 +1302,32 @@ X86Grps.aOpGrpMOVImm = [
|
|||
X86Grps.opGrpUndefined, X86Grps.opGrpUndefined, X86Grps.opGrpUndefined, X86Grps.opGrpUndefined // 0xC6/0xC7(reg=0x4-0x7)
|
||||
];
|
||||
|
||||
X86Grps.aOpGRP2b = [
|
||||
X86Grps.aOpGrp2b = [
|
||||
X86Grps.opGrpROLb, X86Grps.opGrpRORb, X86Grps.opGrpRCLb, X86Grps.opGrpRCRb, // 0xD0/0xD2(reg=0x0-0x3)
|
||||
X86Grps.opGrpSHLb, X86Grps.opGrpSHRb, X86Grps.opGrpUndefined, X86Grps.opGrpSARb // 0xD0/0xD2(reg=0x4-0x7)
|
||||
];
|
||||
|
||||
X86Grps.aOpGRP2w = [
|
||||
X86Grps.aOpGrp2w = [
|
||||
X86Grps.opGrpROLw, X86Grps.opGrpRORw, X86Grps.opGrpRCLw, X86Grps.opGrpRCRw, // 0xD1/0xD3(reg=0x0-0x3)
|
||||
X86Grps.opGrpSHLw, X86Grps.opGrpSHRw, X86Grps.opGrpUndefined, X86Grps.opGrpSARw // 0xD1/0xD3(reg=0x4-0x7)
|
||||
];
|
||||
|
||||
X86Grps.aOpGRP3b = [
|
||||
X86Grps.aOpGrp3b = [
|
||||
X86Grps.opGrpTEST8, X86Grps.opGrpUndefined, X86Grps.opGrpNOTb, X86Grps.opGrpNEGb, // 0xF6(reg=0x0-0x3)
|
||||
X86Grps.opGrpMULb, X86Grps.opGrpIMULb, X86Grps.opGrpDIVb, X86Grps.opGrpIDIVb // 0xF6(reg=0x4-0x7)
|
||||
];
|
||||
|
||||
X86Grps.aOpGRP3w = [
|
||||
X86Grps.aOpGrp3w = [
|
||||
X86Grps.opGrpTEST16, X86Grps.opGrpUndefined, X86Grps.opGrpNOTw, X86Grps.opGrpNEGw, // 0xF7(reg=0x0-0x3)
|
||||
X86Grps.opGrpMULw, X86Grps.opGrpIMULw, X86Grps.opGrpDIVw, X86Grps.opGrpIDIVw // 0xF7(reg=0x4-0x7)
|
||||
];
|
||||
|
||||
X86Grps.aOpGRP4b = [
|
||||
X86Grps.aOpGrp4b = [
|
||||
X86Grps.opGrpINCb, X86Grps.opGrpDECb, X86Grps.opGrpUndefined, X86Grps.opGrpUndefined, // 0xFE(reg=0x0-0x3)
|
||||
X86Grps.opGrpUndefined, X86Grps.opGrpUndefined, X86Grps.opGrpUndefined, X86Grps.opGrpUndefined // 0xFE(reg=0x4-0x7)
|
||||
];
|
||||
|
||||
X86Grps.aOpGRP4w = [
|
||||
X86Grps.aOpGrp4w = [
|
||||
X86Grps.opGrpINCw, X86Grps.opGrpDECw, X86Grps.opGrpCALLw, X86Grps.opGrpCALLdw, // 0xFF(reg=0x0-0x3)
|
||||
X86Grps.opGrpJMPw, X86Grps.opGrpJMPf, X86Grps.opGrpPUSHw, X86Grps.opGrpFault // 0xFF(reg=0x4-0x7)
|
||||
];
|
||||
|
|
@ -1335,12 +1335,12 @@ X86Grps.aOpGRP4w = [
|
|||
/*
|
||||
* The following are for 80186/80188 and up...
|
||||
*/
|
||||
X86Grps.aOpGRP2ab = [
|
||||
X86Grps.aOpGrp2ab = [
|
||||
X86Grps.opGrpROLb, X86Grps.opGrpRORb, X86Grps.opGrpRCLb, X86Grps.opGrpRCRb, // 0xC0(reg=0x0-0x3)
|
||||
X86Grps.opGrpSHLb, X86Grps.opGrpSHRb, X86Grps.opGrpUndefined, X86Grps.opGrpSARb // 0xC0(reg=0x4-0x7)
|
||||
];
|
||||
|
||||
X86Grps.aOpGRP2aw = [
|
||||
X86Grps.aOpGrp2aw = [
|
||||
X86Grps.opGrpROLw, X86Grps.opGrpRORw, X86Grps.opGrpRCLw, X86Grps.opGrpRCRw, // 0xC1(reg=0x0-0x3)
|
||||
X86Grps.opGrpSHLw, X86Grps.opGrpSHRw, X86Grps.opGrpUndefined, X86Grps.opGrpSARw // 0xC1(reg=0x4-0x7)
|
||||
];
|
||||
|
|
|
|||
|
|
@ -485,7 +485,7 @@ var X86Help = {
|
|||
if (this.regPS & X86.PS.NT) {
|
||||
var addrNew = this.segTSS.base;
|
||||
var sel = this.getWord(addrNew + X86.TSS.PREV_TSS);
|
||||
X86Help.opHelpSwitchTSS.call(this, sel);
|
||||
X86Help.opHelpSwitchTSS.call(this, sel, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -569,7 +569,7 @@ var X86Help = {
|
|||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} selNew
|
||||
* @param {boolean} [fNest]
|
||||
* @param {boolean} fNest is true if nesting, false if un-nesting
|
||||
* @return {boolean} true if successful, false if error
|
||||
*/
|
||||
opHelpSwitchTSS: function(selNew, fNest) {
|
||||
|
|
@ -581,65 +581,59 @@ var X86Help = {
|
|||
X86Help.opHelpFault.call(this, X86.EXCEPTION.TS_FAULT, selNew, true);
|
||||
return false;
|
||||
}
|
||||
this.setWord(this.segTSS.addrDesc + X86.DESC.ACC.OFFSET, this.segTSS.acc &= ~X86.DESC.ACC.TYPE.LDT);
|
||||
this.segTSS.type = X86.DESC.ACC.TYPE.TSS;
|
||||
this.setWord(this.segTSS.addrDesc + X86.DESC.ACC.OFFSET, (this.segTSS.acc & ~X86.DESC.ACC.TYPE.TSS_BUSY) | X86.DESC.ACC.TYPE.TSS);
|
||||
}
|
||||
if (this.segTSS.load(selNew) == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.segTSS.load(selNew) == null) return false;
|
||||
var addrNew = this.segTSS.base;
|
||||
if (DEBUG) {
|
||||
this.messageDebugger((fNest? "switchTSS" : "returnTSS") + ": old TR=" + str.toHexWord(selOld) + " TSS=" + str.toHex(addrOld, 6) + ", new TR=" + str.toHexWord(selNew) + " TSS=" + str.toHex(addrNew, 6));
|
||||
this.messageDebugger((fNest? "Task switch" : "Task return") + ": TR " + str.toHexWord(selOld) + " (%" + str.toHex(addrOld, 6) + "), new TR " + str.toHexWord(selNew) + " (%" + str.toHex(addrNew, 6) + ")", Debugger.MESSAGE.TSS);
|
||||
}
|
||||
if (fNest) {
|
||||
if (this.segTSS.type == X86.DESC.ACC.TYPE.TSS_BUSY) {
|
||||
X86Help.opHelpFault.call(this, X86.EXCEPTION.GP_FAULT, selNew, true);
|
||||
return false;
|
||||
}
|
||||
this.setWord(this.segTSS.addrDesc + X86.DESC.ACC.OFFSET, this.segTSS.acc |= X86.DESC.ACC.TYPE.LDT);
|
||||
this.setWord(this.segTSS.addrDesc + X86.DESC.ACC.OFFSET, this.segTSS.acc |= X86.DESC.ACC.TYPE.TSS_BUSY);
|
||||
this.segTSS.type = X86.DESC.ACC.TYPE.TSS_BUSY;
|
||||
}
|
||||
this.setWord(addrOld + X86.TSS.CURR_IP, this.regIP);
|
||||
this.setWord(addrOld + X86.TSS.CURR_PS, this.getPS());
|
||||
this.setWord(addrOld + X86.TSS.CURR_AX, this.regAX);
|
||||
this.setWord(addrOld + X86.TSS.CURR_CX, this.regCX);
|
||||
this.setWord(addrOld + X86.TSS.CURR_DX, this.regDX);
|
||||
this.setWord(addrOld + X86.TSS.CURR_BX, this.regBX);
|
||||
this.setWord(addrOld + X86.TSS.CURR_SP, this.regSP);
|
||||
this.setWord(addrOld + X86.TSS.CURR_BP, this.regBP);
|
||||
this.setWord(addrOld + X86.TSS.CURR_SI, this.regSI);
|
||||
this.setWord(addrOld + X86.TSS.CURR_DI, this.regDI);
|
||||
this.setWord(addrOld + X86.TSS.CURR_ES, this.segES.sel);
|
||||
this.setWord(addrOld + X86.TSS.CURR_CS, this.segCS.sel);
|
||||
this.setWord(addrOld + X86.TSS.CURR_SS, this.segSS.sel);
|
||||
this.setWord(addrOld + X86.TSS.CURR_DS, this.segDS.sel);
|
||||
var offSS = X86.TSS.CURR_SS;
|
||||
var offSP = X86.TSS.CURR_SP;
|
||||
var regPS = this.getWord(addrNew + X86.TSS.CURR_PS);
|
||||
this.setPS(regPS);
|
||||
/*
|
||||
* We have to set the NT (Nested Task) flag manually, because setPS() doesn't allow it.
|
||||
*/
|
||||
this.regPS = (this.regPS & ~X86.PS.NT) | (regPS | X86.PS.NT);
|
||||
this.regAX = this.getWord(addrNew + X86.TSS.CURR_AX);
|
||||
this.regCX = this.getWord(addrNew + X86.TSS.CURR_CX);
|
||||
this.regDX = this.getWord(addrNew + X86.TSS.CURR_DX);
|
||||
this.regBX = this.getWord(addrNew + X86.TSS.CURR_BX);
|
||||
this.regBP = this.getWord(addrNew + X86.TSS.CURR_BP);
|
||||
this.regSI = this.getWord(addrNew + X86.TSS.CURR_SI);
|
||||
this.regDI = this.getWord(addrNew + X86.TSS.CURR_DI);
|
||||
this.segES.load(this.getWord(addrNew + X86.TSS.CURR_ES));
|
||||
this.segDS.load(this.getWord(addrNew + X86.TSS.CURR_DS));
|
||||
this.setCSIP(this.getWord(addrNew + X86.TSS.CURR_IP), this.getWord(addrNew + X86.TSS.CURR_CS));
|
||||
this.setWord(addrOld + X86.TSS.TASK_IP, this.regIP);
|
||||
this.setWord(addrOld + X86.TSS.TASK_PS, this.getPS());
|
||||
this.setWord(addrOld + X86.TSS.TASK_AX, this.regAX);
|
||||
this.setWord(addrOld + X86.TSS.TASK_CX, this.regCX);
|
||||
this.setWord(addrOld + X86.TSS.TASK_DX, this.regDX);
|
||||
this.setWord(addrOld + X86.TSS.TASK_BX, this.regBX);
|
||||
this.setWord(addrOld + X86.TSS.TASK_SP, this.regSP);
|
||||
this.setWord(addrOld + X86.TSS.TASK_BP, this.regBP);
|
||||
this.setWord(addrOld + X86.TSS.TASK_SI, this.regSI);
|
||||
this.setWord(addrOld + X86.TSS.TASK_DI, this.regDI);
|
||||
this.setWord(addrOld + X86.TSS.TASK_ES, this.segES.sel);
|
||||
this.setWord(addrOld + X86.TSS.TASK_CS, this.segCS.sel);
|
||||
this.setWord(addrOld + X86.TSS.TASK_SS, this.segSS.sel);
|
||||
this.setWord(addrOld + X86.TSS.TASK_DS, this.segDS.sel);
|
||||
var offSS = X86.TSS.TASK_SS;
|
||||
var offSP = X86.TSS.TASK_SP;
|
||||
this.setPS(this.getWord(addrNew + X86.TSS.TASK_PS) | (fNest? X86.PS.NT : 0));
|
||||
if (DEBUG) this.assert(!fNest || !!(this.regPS & X86.PS.NT));
|
||||
this.regAX = this.getWord(addrNew + X86.TSS.TASK_AX);
|
||||
this.regCX = this.getWord(addrNew + X86.TSS.TASK_CX);
|
||||
this.regDX = this.getWord(addrNew + X86.TSS.TASK_DX);
|
||||
this.regBX = this.getWord(addrNew + X86.TSS.TASK_BX);
|
||||
this.regBP = this.getWord(addrNew + X86.TSS.TASK_BP);
|
||||
this.regSI = this.getWord(addrNew + X86.TSS.TASK_SI);
|
||||
this.regDI = this.getWord(addrNew + X86.TSS.TASK_DI);
|
||||
this.segES.load(this.getWord(addrNew + X86.TSS.TASK_ES));
|
||||
this.segDS.load(this.getWord(addrNew + X86.TSS.TASK_DS));
|
||||
this.setCSIP(this.getWord(addrNew + X86.TSS.TASK_IP), this.getWord(addrNew + X86.TSS.TASK_CS));
|
||||
if (this.segCS.cpl < cplOld) {
|
||||
offSP = (this.segCS.cpl << 2) + X86.TSS.CPL0_SP;
|
||||
offSS = offSP + 2;
|
||||
}
|
||||
this.regSP = this.getWord(addrNew + offSP);
|
||||
this.segSS.load(this.getWord(addrNew + offSS));
|
||||
this.segLDT.load(this.getWord(addrNew + X86.TSS.CURR_LDT));
|
||||
if (fNest) {
|
||||
this.setWord(addrNew + X86.TSS.PREV_TSS, selOld);
|
||||
this.regPS |= X86.PS.NT;
|
||||
}
|
||||
this.segLDT.load(this.getWord(addrNew + X86.TSS.TASK_LDT));
|
||||
if (fNest) this.setWord(addrNew + X86.TSS.PREV_TSS, selOld);
|
||||
this.regMSW |= X86.MSW.TS;
|
||||
return true;
|
||||
},
|
||||
|
|
@ -690,20 +684,22 @@ var X86Help = {
|
|||
var bOpcode = this.bus.getByteDirect(this.regEIP);
|
||||
/*
|
||||
* OS/2 1.0 uses an INT3 (0xCC) opcode in conjunction with an invalid IDT to trigger a triple-fault
|
||||
* reset and return to real-mode, and these resets happen quite frequently during boot; for example, OS/2
|
||||
* startup messages are displayed using a series of INT 0x10 BIOS calls for each character, and each
|
||||
* series of BIOS calls requires a round-trip mode switch.
|
||||
* reset and return to real-mode, and these resets happen quite frequently during boot; for example,
|
||||
* OS/2 startup messages are displayed using a series of INT 0x10 BIOS calls for each character, and
|
||||
* each series of BIOS calls requires a round-trip mode switch.
|
||||
*
|
||||
* Since we really only want to halt on "bad" faults, not "good" (ie, intentional) faults, we take
|
||||
* advantage of the fact that all 3 faults comprising the triple-fault point to the INT3 (0xCC) opcode,
|
||||
* advantage of the fact that all 3 faults comprising the triple-fault point to an INT3 (0xCC) opcode,
|
||||
* and so whenever we see that opcode, we ignore the caller's fHalt flag, and suppress FAULT messages
|
||||
* unless CPU messages are also enabled.
|
||||
*
|
||||
* When a triple fault shows up, nFault is -1; it displays as "ff" only because we truncate it to a byte.
|
||||
*/
|
||||
if (bOpcode == X86.OPCODE.INT3) {
|
||||
fHalt = false;
|
||||
bitsMessage |= Debugger.MESSAGE.CPU;
|
||||
}
|
||||
this.messageDebugger("Fault 0x" + str.toHexByte(nFault) + (nError != null? " (0x" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + str.toHexAddr(this.regIP, this.segCS.sel) + " (" + str.toHex(this.regEIP, 6) + ")", bitsMessage);
|
||||
this.messageDebugger("Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + str.toHexAddr(this.regIP, this.segCS.sel) + " (%" + str.toHex(this.regEIP, 6) + ")", bitsMessage);
|
||||
if (fHalt) this.dbg.stopCPU();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ var X86Op0F = {
|
|||
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;
|
||||
}
|
||||
X86Mods.aOpModsGrpWord[bModRM].call(this, X86Op0F.aOpGRP6, X86Grps.opGrpNoSrc);
|
||||
X86Mods.aOpModsGrpWord[bModRM].call(this, this.aOpGrp6, X86Grps.opGrpNoSrc);
|
||||
if (EAFUNCS) { this.modEAWord = this.modEAWordEnabled; this.setEAWord = this.setEAWordEnabled; }
|
||||
},
|
||||
/**
|
||||
|
|
@ -64,7 +64,7 @@ var X86Op0F = {
|
|||
if (!(bModRM & 0x10)) {
|
||||
if (EAFUNCS) this.modEAWord = this.modEAWordDisabled; else this.opFlags |= X86.OPFLAG.NOREAD;
|
||||
}
|
||||
X86Mods.aOpModsGrpWord[bModRM].call(this, X86Op0F.aOpGRP7, X86Grps.opGrpNoSrc);
|
||||
X86Mods.aOpModsGrpWord[bModRM].call(this, X86Op0F.aOpGrp7, X86Grps.opGrpNoSrc);
|
||||
if (EAFUNCS) { this.modEAWord = this.modEAWordEnabled; this.setEAWord = this.setEAWordEnabled; }
|
||||
},
|
||||
/**
|
||||
|
|
@ -159,6 +159,19 @@ var X86Op0F = {
|
|||
*/
|
||||
if (DEBUG && DEBUGGER && (this.regMSW & X86.MSW.PE)) this.stopCPU();
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
*
|
||||
* op=0x0F,0x06 (clts)
|
||||
*/
|
||||
opCLTS: function() {
|
||||
if (this.segCS.cpl) {
|
||||
X86Help.opHelpFault.call(this, X86.EXCEPTION.GP_FAULT, 0, true);
|
||||
return;
|
||||
}
|
||||
this.regMSW &= ~X86.MSW.TS;
|
||||
this.nStepCycles -= 2;
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
* @param {number} dst
|
||||
|
|
@ -426,7 +439,7 @@ var X86Op0F = {
|
|||
|
||||
X86Op0F.aOps0F = [
|
||||
X86Op0F.opGRP6, X86Op0F.opGRP7, X86Op0F.opLAR, X86Op0F.opLSL, // 0x00-0x03
|
||||
X86OpXX.opUndefined, X86Op0F.opLOADALL, X86OpXX.opUndefined, 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
|
||||
* instruction guaranteed to raise a #UD (Invalid Opcode) exception (INT 0x06) on all future x86 processors.
|
||||
|
|
@ -502,27 +515,21 @@ X86Op0F.aOps0F = [
|
|||
* 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.
|
||||
*/
|
||||
X86Op0F.aOpGRP6Prot = [
|
||||
X86Op0F.aOpGrp6Prot = [
|
||||
X86Op0F.opSLDT, X86Op0F.opSTR, X86Op0F.opLLDT, X86Op0F.opLTR, // 0x0F,0x00(reg=0x0-0x3)
|
||||
X86Op0F.opVERR, X86Op0F.opVERW, X86Grps.opGrpUndefined, X86Grps.opGrpUndefined // 0x0F,0x00(reg=0x4-0x7)
|
||||
];
|
||||
|
||||
X86Op0F.aOpGRP6Real = [
|
||||
X86Op0F.aOpGrp6Real = [
|
||||
X86Grps.opGrpInvalid, X86Grps.opGrpInvalid, X86Grps.opGrpInvalid, X86Grps.opGrpInvalid, // 0x0F,0x00(reg=0x0-0x3)
|
||||
X86Grps.opGrpInvalid, X86Grps.opGrpInvalid, X86Grps.opGrpUndefined, X86Grps.opGrpUndefined // 0x0F,0x00(reg=0x4-0x7)
|
||||
];
|
||||
|
||||
/*
|
||||
* setProtMode() will ensure that aOpGRP6 is set to the appropriate group, but it doesn't hurt to statically
|
||||
* initialize to its real-mode default, either.
|
||||
*/
|
||||
X86Op0F.aOpGRP6 = X86Op0F.aOpGRP6Real;
|
||||
|
||||
/*
|
||||
* Unlike GRP6, GRP7 does not require separate real-mode and protected-mode dispatch tables, because all GRP7
|
||||
* instructions are valid in both modes.
|
||||
*/
|
||||
X86Op0F.aOpGRP7 = [
|
||||
X86Op0F.aOpGrp7 = [
|
||||
X86Op0F.opSGDT, X86Op0F.opSIDT, X86Op0F.opLGDT, X86Op0F.opLIDT, // 0x0F,0x01(reg=0x0-0x3)
|
||||
X86Op0F.opSMSW, X86Grps.opGrpUndefined, X86Op0F.opLMSW, X86Grps.opGrpUndefined // 0x0F,0x01(reg=0x4-0x7)
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1591,7 +1591,7 @@ var X86OpXX = {
|
|||
* op=0x80/0x82 (grp1b rm,imm8)
|
||||
*/
|
||||
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;
|
||||
this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
|
||||
},
|
||||
|
|
@ -1601,7 +1601,7 @@ var X86OpXX = {
|
|||
* op=0x81 (grp1w rm,imm16)
|
||||
*/
|
||||
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;
|
||||
this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
|
||||
},
|
||||
|
|
@ -1611,7 +1611,7 @@ var X86OpXX = {
|
|||
* op=0x83 (grp1sw rm,disp)
|
||||
*/
|
||||
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;
|
||||
this.nStepCycles -= (this.regEAWrite < 0? 1 : this.CYCLES.nOpCyclesArithMID);
|
||||
},
|
||||
|
|
@ -1984,10 +1984,8 @@ var X86OpXX = {
|
|||
* op=0x9B (wait)
|
||||
*/
|
||||
opWAIT: function() {
|
||||
/*
|
||||
* TODO: Implement
|
||||
*/
|
||||
X86OpXX.opUndefined.call(this);
|
||||
this.messageDebugger("WAIT not implemented");
|
||||
this.nStepCycles--;
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -2646,7 +2644,7 @@ var X86OpXX = {
|
|||
* op=0xC0 (grp2ab rm) (80186/80188 and up)
|
||||
*/
|
||||
opGRP2ab: function() {
|
||||
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGRP2ab, X86Grps.opGrp2CountImm);
|
||||
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2ab, X86Grps.opGrp2CountImm);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -2654,7 +2652,7 @@ var X86OpXX = {
|
|||
* op=0xC1 (grp2aw rm) (80186/80188 and up)
|
||||
*/
|
||||
opGRP2aw: function() {
|
||||
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGRP2aw, X86Grps.opGrp2CountImm);
|
||||
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2aw, X86Grps.opGrp2CountImm);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -2852,7 +2850,7 @@ var X86OpXX = {
|
|||
* op=0xD0 (grp2b rm,1)
|
||||
*/
|
||||
opGRP2b1: function() {
|
||||
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGRP2b, X86Grps.opGrp2Count1);
|
||||
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2Count1);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -2860,7 +2858,7 @@ var X86OpXX = {
|
|||
* op=0xD1 (grp2w rm,1)
|
||||
*/
|
||||
opGRP2w1: function() {
|
||||
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGRP2w, X86Grps.opGrp2Count1);
|
||||
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2Count1);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -2868,7 +2866,7 @@ var X86OpXX = {
|
|||
* op=0xD2 (grp2b rm,CL)
|
||||
*/
|
||||
opGRP2bCL: function() {
|
||||
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGRP2b, X86Grps.opGrp2CountCL);
|
||||
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp2b, X86Grps.opGrp2CountCL);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -2876,7 +2874,7 @@ var X86OpXX = {
|
|||
* op=0xD3 (grp2w rm,CL)
|
||||
*/
|
||||
opGRP2wCL: function() {
|
||||
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGRP2w, X86Grps.opGrp2CountCL);
|
||||
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGrp2w, X86Grps.opGrp2CountCL);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -3245,7 +3243,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opGRP3b: function() {
|
||||
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 (EAFUNCS) this.setEAByte = this.setEAByteEnabled;
|
||||
},
|
||||
|
|
@ -3269,7 +3267,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opGRP3w: function() {
|
||||
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) {
|
||||
this.regAX = this.regMD16;
|
||||
this.regDX = this.regMD32;
|
||||
|
|
@ -3337,7 +3335,7 @@ var X86OpXX = {
|
|||
* op=0xFE (grp4b rm)
|
||||
*/
|
||||
opGRP4b: function() {
|
||||
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGRP4b, X86Grps.opGrpNoSrc);
|
||||
X86Mods.aOpModsGrpByte[this.getIPByte()].call(this, X86Grps.aOpGrp4b, X86Grps.opGrpNoSrc);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -3345,7 +3343,7 @@ var X86OpXX = {
|
|||
* op=0xFF (grp4w rm)
|
||||
*/
|
||||
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;
|
||||
},
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -446,7 +446,7 @@ X86Seg.prototype.messageDebugger = function(base, limit, acc, ext)
|
|||
var ch = (this.sName.length < 3? " " : "");
|
||||
var sDPL = " dpl=" + this.dpl;
|
||||
if (this.id == X86Seg.ID.CODE) sDPL += " cpl=" + this.cpl;
|
||||
this.cpu.messageDebugger("loadDesc(" + this.sName + "):" + ch + " base=" + str.toHex(base) + " limit=" + str.toHexWord(limit) + " acc=" + str.toHexWord(acc) + sDPL, Debugger.MESSAGE.SEG);
|
||||
this.cpu.messageDebugger("loadSeg(" + this.sName + "):" + ch + " base=" + str.toHex(base) + " limit=" + str.toHexWord(limit) + " acc=" + str.toHexWord(acc) + sDPL, Debugger.MESSAGE.SEG);
|
||||
}
|
||||
this.cpu.assert(!ext || ext == X86.DESC.EXT.AVAIL);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue