New skeleton for x86fpu.js
This commit is contained in:
parent
1b3734440e
commit
2b1b62d565
7 changed files with 1440 additions and 167 deletions
|
|
@ -40,6 +40,7 @@ if (NODE) {
|
||||||
var Interrupts = require("./interrupts");
|
var Interrupts = require("./interrupts");
|
||||||
var Messages = require("./messages");
|
var Messages = require("./messages");
|
||||||
var State = require("./state");
|
var State = require("./state");
|
||||||
|
var X86 = require("./x86");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -985,7 +986,7 @@ ChipSet.NMI = { // this.bNMI
|
||||||
/*
|
/*
|
||||||
* Coprocessor Control Registers (MODEL_5170)
|
* Coprocessor Control Registers (MODEL_5170)
|
||||||
*/
|
*/
|
||||||
ChipSet.COPROC = { // TODO: Define a variable for this
|
ChipSet.COPROC = { // TODO: Define a variable for this?
|
||||||
PORT_CLEAR: 0xF0, // clear the coprocessor's "busy" state
|
PORT_CLEAR: 0xF0, // clear the coprocessor's "busy" state
|
||||||
PORT_RESET: 0xF1 // reset the coprocessor
|
PORT_RESET: 0xF1 // reset the coprocessor
|
||||||
};
|
};
|
||||||
|
|
@ -1058,7 +1059,12 @@ ChipSet.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||||
this.cpu = cpu;
|
this.cpu = cpu;
|
||||||
this.dbg = dbg;
|
this.dbg = dbg;
|
||||||
this.cmp = cmp;
|
this.cmp = cmp;
|
||||||
|
|
||||||
|
this.fpu = cmp.getMachineComponent("FPU");
|
||||||
|
if (this.fpu) this.sw1Init |= ChipSet.PPI_SW.COPROC;
|
||||||
|
|
||||||
this.kbd = cmp.getMachineComponent("Keyboard");
|
this.kbd = cmp.getMachineComponent("Keyboard");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This divisor is invariant, so we calculate it as soon as we're able to query the CPU's base speed.
|
* This divisor is invariant, so we calculate it as soon as we're able to query the CPU's base speed.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1091,9 +1097,6 @@ ChipSet.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||||
}
|
}
|
||||||
cpu.addIntNotify(Interrupts.RTC, this.intBIOSRTC.bind(this));
|
cpu.addIntNotify(Interrupts.RTC, this.intBIOSRTC.bind(this));
|
||||||
}
|
}
|
||||||
if (cpu.fpu) {
|
|
||||||
this.sw1Init |= ChipSet.PPI_SW.COPROC;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -3513,6 +3516,43 @@ ChipSet.prototype.getIRRVector = function(iPIC)
|
||||||
return nIDT;
|
return nIDT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setFPUInterrupt()
|
||||||
|
*
|
||||||
|
* @this {ChipSet}
|
||||||
|
*/
|
||||||
|
ChipSet.prototype.setFPUInterrupt = function()
|
||||||
|
{
|
||||||
|
if (this.model >= ChipSet.MODEL_5170) {
|
||||||
|
this.setIRR(ChipSet.IRQ.COPROC);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* TODO: Determine whether we need to maintain an "Active NMI" state; ie, if NMI.DISABLE is cleared
|
||||||
|
* later, and the coprocessor is still indicating an error condition, should we then generate an NMI?
|
||||||
|
*/
|
||||||
|
if (!(this.bNMI & ChipSet.NMI.DISABLE)) {
|
||||||
|
X86.fnInterrupt.call(this.cpu, X86.EXCEPTION.NMI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clearFPUInterrupt(fSet)
|
||||||
|
*
|
||||||
|
* @this {ChipSet}
|
||||||
|
*/
|
||||||
|
ChipSet.prototype.clearFPUInterrupt = function()
|
||||||
|
{
|
||||||
|
if (this.model >= ChipSet.MODEL_5170) {
|
||||||
|
this.clearIRR(ChipSet.IRQ.COPROC);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* TODO: If we maintain an "Active NMI" state, then we will need code here to clear that state, as well
|
||||||
|
* as code in outNMI() to clear that state and generate an NMI as needed.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* inTimer(iTimer, addrFrom)
|
* inTimer(iTimer, addrFrom)
|
||||||
*
|
*
|
||||||
|
|
@ -4959,11 +4999,9 @@ ChipSet.prototype.outNMI = function(port, bOut, addrFrom)
|
||||||
*/
|
*/
|
||||||
ChipSet.prototype.outCoprocClear = function(port, bOut, addrFrom)
|
ChipSet.prototype.outCoprocClear = function(port, bOut, addrFrom)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* TODO: Implement
|
|
||||||
*/
|
|
||||||
this.printMessageIO(port, bOut, addrFrom, "COPROC.CLEAR");
|
this.printMessageIO(port, bOut, addrFrom, "COPROC.CLEAR");
|
||||||
this.assert(!bOut);
|
this.assert(!bOut);
|
||||||
|
if (this.fpu) this.fpu.clearBusy();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -4978,11 +5016,9 @@ ChipSet.prototype.outCoprocClear = function(port, bOut, addrFrom)
|
||||||
*/
|
*/
|
||||||
ChipSet.prototype.outCoprocReset = function(port, bOut, addrFrom)
|
ChipSet.prototype.outCoprocReset = function(port, bOut, addrFrom)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* TODO: Implement
|
|
||||||
*/
|
|
||||||
this.printMessageIO(port, bOut, addrFrom, "COPROC.RESET");
|
this.printMessageIO(port, bOut, addrFrom, "COPROC.RESET");
|
||||||
this.assert(!bOut);
|
this.assert(!bOut);
|
||||||
|
if (this.fpu) this.fpu.resetFPU();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,7 @@ CPU.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||||
this.cmp = cmp;
|
this.cmp = cmp;
|
||||||
this.bus = bus;
|
this.bus = bus;
|
||||||
this.dbg = dbg;
|
this.dbg = dbg;
|
||||||
|
this.fpu = cmp.getMachineComponent("FPU");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attach the Video component to the CPU, so that the CPU can periodically update
|
* Attach the Video component to the CPU, so that the CPU can periodically update
|
||||||
|
|
@ -197,9 +198,6 @@ CPU.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||||
* We must also call chipset.updateAllTimers() periodically; stepCPU() takes care of that.
|
* We must also call chipset.updateAllTimers() periodically; stepCPU() takes care of that.
|
||||||
*/
|
*/
|
||||||
this.chipset = cmp.getMachineComponent("ChipSet");
|
this.chipset = cmp.getMachineComponent("ChipSet");
|
||||||
|
|
||||||
this.fpu = cmp.getMachineComponent("FPU");
|
|
||||||
|
|
||||||
this.setReady();
|
this.setReady();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -534,7 +534,8 @@ if (DEBUGGER) {
|
||||||
Debugger.TYPE_OTHER = 0xF000; // "other" field
|
Debugger.TYPE_OTHER = 0xF000; // "other" field
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TYPE_SIZE values.
|
* TYPE_SIZE values. Some definitions use duplicate values when the operands are the
|
||||||
|
* same size and the Debugger doesn't need to make a distinction.
|
||||||
*/
|
*/
|
||||||
Debugger.TYPE_NONE = 0x0000; // (all other TYPE fields ignored)
|
Debugger.TYPE_NONE = 0x0000; // (all other TYPE fields ignored)
|
||||||
Debugger.TYPE_BYTE = 0x0001; // (b) byte, regardless of operand size
|
Debugger.TYPE_BYTE = 0x0001; // (b) byte, regardless of operand size
|
||||||
|
|
@ -544,18 +545,16 @@ if (DEBUGGER) {
|
||||||
Debugger.TYPE_LONG = 0x0005; // (d) 32-bit value
|
Debugger.TYPE_LONG = 0x0005; // (d) 32-bit value
|
||||||
Debugger.TYPE_SEGP = 0x0006; // (p) 32-bit or 48-bit pointer
|
Debugger.TYPE_SEGP = 0x0006; // (p) 32-bit or 48-bit pointer
|
||||||
Debugger.TYPE_FARP = 0x0007; // (p) 32-bit or 48-bit pointer for JMP/CALL
|
Debugger.TYPE_FARP = 0x0007; // (p) 32-bit or 48-bit pointer for JMP/CALL
|
||||||
Debugger.TYPE_2WORD = 0x0008; // (a) two memory operands (BOUND only)
|
Debugger.TYPE_PREFIX = 0x0008; // (treat similarly to TYPE_NONE)
|
||||||
Debugger.TYPE_DESC = 0x0009; // (s) 6 byte pseudo-descriptor
|
Debugger.TYPE_ST = 0x0009; // FPU ST (implicit top)
|
||||||
Debugger.TYPE_PREFIX = 0x000A; // (treat similarly to TYPE_NONE)
|
Debugger.TYPE_STREG = 0x000A; // FPU ST (explicit register)
|
||||||
Debugger.TYPE_ST = 0x000B; // FPU ST
|
Debugger.TYPE_SI = 0x000B; // FPU SI (short-integer; 32-bit)
|
||||||
Debugger.TYPE_STREG = 0x000C; // FPU ST register
|
Debugger.TYPE_SR = 0x000B; // FPU SR (short-real; 32-bit)
|
||||||
Debugger.TYPE_SI = 0x000D; // FPU SI (short-integer; 32-bit)
|
Debugger.TYPE_LI = 0x000C; // FPU LI (long-integer; 64-bit)
|
||||||
Debugger.TYPE_SR = 0x000D; // FPU SR (short-real; 32-bit)
|
Debugger.TYPE_LR = 0x000C; // FPU LR (long-real; 64-bit)
|
||||||
Debugger.TYPE_LI = 0x000E; // FPU LI (long-integer; 64-bit)
|
Debugger.TYPE_TR = 0x000D; // FPU TR (temp-real; 80-zbit)
|
||||||
Debugger.TYPE_LR = 0x000E; // FPU LR (long-real; 64-bit)
|
Debugger.TYPE_PD = 0x000D; // FPU PD (packed-decimal, 18 digits; 80-bit)
|
||||||
Debugger.TYPE_TR = 0x000F; // FPU TR (temp-real; 80-bit)
|
Debugger.TYPE_ENV = 0x000E; // FPU ENV (environment; 14 bytes)
|
||||||
Debugger.TYPE_PD = 0x000F; // FPU PD (packed-decimal, 18 digits; 80-bit)
|
|
||||||
Debugger.TYPE_ENV = 0x000F; // FPU ENV (environment; 14 bytes)
|
|
||||||
Debugger.TYPE_FPU = 0x000F; // FPU SAVE (save/restore; 94 bytes)
|
Debugger.TYPE_FPU = 0x000F; // FPU SAVE (save/restore; 94 bytes)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -816,7 +815,7 @@ if (DEBUGGER) {
|
||||||
|
|
||||||
/* 0x60 */ [Debugger.INS.PUSHA, Debugger.TYPE_NONE | Debugger.TYPE_80286],
|
/* 0x60 */ [Debugger.INS.PUSHA, Debugger.TYPE_NONE | Debugger.TYPE_80286],
|
||||||
/* 0x61 */ [Debugger.INS.POPA, Debugger.TYPE_NONE | Debugger.TYPE_80286],
|
/* 0x61 */ [Debugger.INS.POPA, Debugger.TYPE_NONE | Debugger.TYPE_80286],
|
||||||
/* 0x62 */ [Debugger.INS.BOUND, Debugger.TYPE_REG | Debugger.TYPE_WORD | Debugger.TYPE_IN | Debugger.TYPE_80286, Debugger.TYPE_MODRM | Debugger.TYPE_2WORD | Debugger.TYPE_IN],
|
/* 0x62 */ [Debugger.INS.BOUND, Debugger.TYPE_REG | Debugger.TYPE_WORD | Debugger.TYPE_IN | Debugger.TYPE_80286, Debugger.TYPE_MODRM | Debugger.TYPE_WORD | Debugger.TYPE_IN],
|
||||||
/* 0x63 */ [Debugger.INS.ARPL, Debugger.TYPE_MODRM | Debugger.TYPE_SHORT | Debugger.TYPE_OUT, Debugger.TYPE_REG | Debugger.TYPE_SHORT | Debugger.TYPE_IN],
|
/* 0x63 */ [Debugger.INS.ARPL, Debugger.TYPE_MODRM | Debugger.TYPE_SHORT | Debugger.TYPE_OUT, Debugger.TYPE_REG | Debugger.TYPE_SHORT | Debugger.TYPE_IN],
|
||||||
/* 0x64 */ [Debugger.INS.FS, Debugger.TYPE_PREFIX | Debugger.TYPE_80386],
|
/* 0x64 */ [Debugger.INS.FS, Debugger.TYPE_PREFIX | Debugger.TYPE_80386],
|
||||||
/* 0x65 */ [Debugger.INS.GS, Debugger.TYPE_PREFIX | Debugger.TYPE_80386],
|
/* 0x65 */ [Debugger.INS.GS, Debugger.TYPE_PREFIX | Debugger.TYPE_80386],
|
||||||
|
|
@ -1067,6 +1066,9 @@ if (DEBUGGER) {
|
||||||
0xBF: [Debugger.INS.MOVSX, Debugger.TYPE_REG | Debugger.TYPE_LONG | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_MODRM | Debugger.TYPE_SHORT | Debugger.TYPE_IN]
|
0xBF: [Debugger.INS.MOVSX, Debugger.TYPE_REG | Debugger.TYPE_LONG | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_MODRM | Debugger.TYPE_SHORT | Debugger.TYPE_IN]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Be sure to keep the following table in sync with X86FPU.aaOps
|
||||||
|
*/
|
||||||
Debugger.aaaOpFPUDescs = {
|
Debugger.aaaOpFPUDescs = {
|
||||||
0xD8: {
|
0xD8: {
|
||||||
0x00: [Debugger.FINS.FADD, Debugger.TYPE_MODRM | Debugger.TYPE_SR | Debugger.TYPE_IN],
|
0x00: [Debugger.FINS.FADD, Debugger.TYPE_MODRM | Debugger.TYPE_SR | Debugger.TYPE_IN],
|
||||||
|
|
@ -1097,7 +1099,7 @@ if (DEBUGGER) {
|
||||||
0x30: [Debugger.FINS.FLD, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_OUT],
|
0x30: [Debugger.FINS.FLD, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_OUT],
|
||||||
0x31: [Debugger.FINS.FXCH, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_OUT],
|
0x31: [Debugger.FINS.FXCH, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_OUT],
|
||||||
0x32: [Debugger.FINS.FNOP],
|
0x32: [Debugger.FINS.FNOP],
|
||||||
0x33: [Debugger.FINS.FSTP, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_OUT],
|
0x33: [Debugger.FINS.FSTP, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_OUT],
|
||||||
0x40: [Debugger.FINS.FCHS],
|
0x40: [Debugger.FINS.FCHS],
|
||||||
0x41: [Debugger.FINS.FABS],
|
0x41: [Debugger.FINS.FABS],
|
||||||
0x44: [Debugger.FINS.FTST],
|
0x44: [Debugger.FINS.FTST],
|
||||||
|
|
@ -1144,14 +1146,14 @@ if (DEBUGGER) {
|
||||||
0x43: [Debugger.FINS.FINIT]
|
0x43: [Debugger.FINS.FINIT]
|
||||||
},
|
},
|
||||||
0xDC: {
|
0xDC: {
|
||||||
0x00: [Debugger.FINS.FADD, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
0x00: [Debugger.FINS.FADD, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
||||||
0x01: [Debugger.FINS.FMUL, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
0x01: [Debugger.FINS.FMUL, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
||||||
0x02: [Debugger.FINS.FCOM, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
0x02: [Debugger.FINS.FCOM, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
||||||
0x03: [Debugger.FINS.FCOMP, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
0x03: [Debugger.FINS.FCOMP, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
||||||
0x04: [Debugger.FINS.FSUB, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
0x04: [Debugger.FINS.FSUB, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
||||||
0x05: [Debugger.FINS.FSUBR, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
0x05: [Debugger.FINS.FSUBR, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
||||||
0x06: [Debugger.FINS.FDIV, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
0x06: [Debugger.FINS.FDIV, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
||||||
0x07: [Debugger.FINS.FDIVR, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
0x07: [Debugger.FINS.FDIVR, Debugger.TYPE_MODRM | Debugger.TYPE_LR | Debugger.TYPE_IN],
|
||||||
0x30: [Debugger.FINS.FADD, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_OUT, Debugger.TYPE_IMPREG | Debugger.TYPE_ST | Debugger.TYPE_IN],
|
0x30: [Debugger.FINS.FADD, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_OUT, Debugger.TYPE_IMPREG | Debugger.TYPE_ST | Debugger.TYPE_IN],
|
||||||
0x31: [Debugger.FINS.FMUL, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_OUT, Debugger.TYPE_IMPREG | Debugger.TYPE_ST | Debugger.TYPE_IN],
|
0x31: [Debugger.FINS.FMUL, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_OUT, Debugger.TYPE_IMPREG | Debugger.TYPE_ST | Debugger.TYPE_IN],
|
||||||
0x32: [Debugger.FINS.FCOM, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_IN],
|
0x32: [Debugger.FINS.FCOM, Debugger.TYPE_IMPREG | Debugger.TYPE_STREG | Debugger.TYPE_IN],
|
||||||
|
|
@ -4902,14 +4904,14 @@ if (DEBUGGER) {
|
||||||
var r_m = (bModRM & 0x7);
|
var r_m = (bModRM & 0x7);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Similar to how fnFPU() decodes FPU instructions, we now combine mod and reg into
|
* Similar to how fnFPU() decodes FPU instructions, we combine mod and reg into one
|
||||||
* one decodable value: put mod in the high nibble and reg in the low nibble, after first
|
* decodable value: put mod in the high nibble and reg in the low nibble, after first
|
||||||
* collapsing all mod values < 3 to zero.
|
* collapsing all mod values < 3 to zero.
|
||||||
*/
|
*/
|
||||||
var modReg = (mod < 3? 0 : 0x30) + reg;
|
var modReg = (mod < 3? 0 : 0x30) + reg;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use values >= 0x40 to indicate mod == 0x3, with reg in the high nibble, and r_m in the low.
|
* Use values >= 0x40 to indicate mod == 0x3, with reg in the high nibble and r_m in the low.
|
||||||
*/
|
*/
|
||||||
if ((bOpcode == X86.OPCODE.ESC1 || bOpcode == X86.OPCODE.ESC3) && modReg >= 0x34) {
|
if ((bOpcode == X86.OPCODE.ESC1 || bOpcode == X86.OPCODE.ESC3) && modReg >= 0x34) {
|
||||||
modReg = (reg << 4) | r_m;
|
modReg = (reg << 4) | r_m;
|
||||||
|
|
@ -4949,7 +4951,6 @@ if (DEBUGGER) {
|
||||||
sOperand = str.toHex((this.getByte(dbgAddr, 1) << 24) >> 24, dbgAddr.fData32? 8: 4);
|
sOperand = str.toHex((this.getByte(dbgAddr, 1) << 24) >> 24, dbgAddr.fData32? 8: 4);
|
||||||
break;
|
break;
|
||||||
case Debugger.TYPE_WORD:
|
case Debugger.TYPE_WORD:
|
||||||
case Debugger.TYPE_2WORD:
|
|
||||||
if (dbgAddr.fData32) {
|
if (dbgAddr.fData32) {
|
||||||
sOperand = str.toHex(this.getLong(dbgAddr, 4));
|
sOperand = str.toHex(this.getLong(dbgAddr, 4));
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -532,10 +532,13 @@ var X86 = {
|
||||||
OM: 0x0008, // bit 3: Overflow Mask
|
OM: 0x0008, // bit 3: Overflow Mask
|
||||||
UM: 0x0010, // bit 4: Underflow Mask
|
UM: 0x0010, // bit 4: Underflow Mask
|
||||||
PM: 0x0020, // bit 5: Precision Mask
|
PM: 0x0020, // bit 5: Precision Mask
|
||||||
|
// bit 6: unused
|
||||||
IEM: 0x0080, // bit 7: Interrupt Enable Mask (0 enables interrupts, 1 masks them; 8087 only)
|
IEM: 0x0080, // bit 7: Interrupt Enable Mask (0 enables interrupts, 1 masks them; 8087 only)
|
||||||
PC: 0x0300, // bits 8-9: Precision Control
|
PC: 0x0300, // bits 8-9: Precision Control
|
||||||
RC: 0x0C00, // bits 10-11: Rounding Control
|
RC: 0x0C00, // bits 10-11: Rounding Control
|
||||||
IC: 0x1000 // bit 12: Infinity Control (0 for Projective, 1 for Affine)
|
IC: 0x1000, // bit 12: Infinity Control (0 for Projective, 1 for Affine)
|
||||||
|
// bits 13-15: unused
|
||||||
|
INIT: 0x03BF // X86.FPU.CONTROL.IM | X86.FPU.CONTROL.DM | X86.FPU.CONTROL.ZM | X86.FPU.CONTROL.OM | X86.FPU.CONTROL.UM | X86.FPU.CONTROL.PM | X86.FPU.CONTROL.IEM | X86.FPU.CONTROL.PC
|
||||||
},
|
},
|
||||||
STATUS: { // FPU Status Word
|
STATUS: { // FPU Status Word
|
||||||
IE: 0x0001, // bit 0: Invalid Operation
|
IE: 0x0001, // bit 0: Invalid Operation
|
||||||
|
|
@ -545,6 +548,7 @@ var X86 = {
|
||||||
UE: 0x0010, // bit 4: Underflow
|
UE: 0x0010, // bit 4: Underflow
|
||||||
PE: 0x0020, // bit 5: Precision
|
PE: 0x0020, // bit 5: Precision
|
||||||
SF: 0x0040, // bit 6: Stack Fault (80387 and later)
|
SF: 0x0040, // bit 6: Stack Fault (80387 and later)
|
||||||
|
EXC: 0x007F, // all of the above exceptions
|
||||||
ES: 0x0080, // bit 7: Exception Summary (Interrupt Request on 8087)
|
ES: 0x0080, // bit 7: Exception Summary (Interrupt Request on 8087)
|
||||||
C0: 0x0100, // bit 8: Condition Code 0
|
C0: 0x0100, // bit 8: Condition Code 0
|
||||||
C1: 0x0200, // bit 9: Condition Code 1
|
C1: 0x0200, // bit 9: Condition Code 1
|
||||||
|
|
@ -553,11 +557,12 @@ var X86 = {
|
||||||
C3: 0x4000, // bit 14: Condition Code 3
|
C3: 0x4000, // bit 14: Condition Code 3
|
||||||
BUSY: 0x8000 // bit 15: Busy
|
BUSY: 0x8000 // bit 15: Busy
|
||||||
},
|
},
|
||||||
TAG: {
|
TAGS: {
|
||||||
VALID: 0x0,
|
VALID: 0x0,
|
||||||
ZERO: 0x1,
|
ZERO: 0x1,
|
||||||
SPECIAL: 0x2,
|
SPECIAL:0x2,
|
||||||
EMPTY: 0x3
|
EMPTY: 0x3,
|
||||||
|
MASK: 0x3
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
C3 C2 C1 C0 Condition Code (CC) values following an Examine
|
C3 C2 C1 C0 Condition Code (CC) values following an Examine
|
||||||
|
|
|
||||||
|
|
@ -3937,7 +3937,7 @@ X86CPU.prototype.checkINTR = function()
|
||||||
this.intFlags &= ~X86.INTFLAG.INTR;
|
this.intFlags &= ~X86.INTFLAG.INTR;
|
||||||
if (nIDT >= 0) {
|
if (nIDT >= 0) {
|
||||||
this.intFlags &= ~X86.INTFLAG.HALT;
|
this.intFlags &= ~X86.INTFLAG.HALT;
|
||||||
X86.fnINT.call(this, this.nFault = nIDT, null, 11);
|
X86.fnInterrupt.call(this, nIDT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3947,7 +3947,7 @@ X86CPU.prototype.checkINTR = function()
|
||||||
if ((this.intFlags & X86.INTFLAG.TRAP)) {
|
if ((this.intFlags & X86.INTFLAG.TRAP)) {
|
||||||
this.intFlags &= ~X86.INTFLAG.TRAP;
|
this.intFlags &= ~X86.INTFLAG.TRAP;
|
||||||
if (I386 && this.model >= X86.MODEL_80386) this.regDR[6] |= X86.DR6.BS;
|
if (I386 && this.model >= X86.MODEL_80386) this.regDR[6] |= X86.DR6.BS;
|
||||||
X86.fnINT.call(this, this.nFault = X86.EXCEPTION.DB_EXC, null, 11);
|
X86.fnInterrupt.call(this, X86.EXCEPTION.DB_EXC);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -946,8 +946,7 @@ X86.fnDIVw = function(dst, src)
|
||||||
X86.fnESC = function(dst, src)
|
X86.fnESC = function(dst, src)
|
||||||
{
|
{
|
||||||
if (this.fpu) {
|
if (this.fpu) {
|
||||||
this.fpu.fnFPU(this.bOpcode, this.bModRM, dst, src);
|
this.fpu.opFPU(this.bOpcode, this.bModRM, dst, src);
|
||||||
this.stopCPU();
|
|
||||||
}
|
}
|
||||||
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 2 : 8);
|
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 2 : 8);
|
||||||
return dst;
|
return dst;
|
||||||
|
|
@ -3879,6 +3878,23 @@ X86.fnSRCxx = function()
|
||||||
return this.regXX;
|
return this.regXX;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fnInterrupt(nIDT, nCycles)
|
||||||
|
*
|
||||||
|
* Helper to dispatch external interrupts. nCycles defaults to 11 for the 8086/8088
|
||||||
|
* if no alternate value is specified.
|
||||||
|
*
|
||||||
|
* @this {X86CPU}
|
||||||
|
* @param {number} nIDT
|
||||||
|
* @param {number} [nCycles] (number of cycles in addition to the default of nOpCyclesInt)
|
||||||
|
*/
|
||||||
|
X86.fnInterrupt = function(nIDT, nCycles)
|
||||||
|
{
|
||||||
|
this.nFault = nIDT;
|
||||||
|
if (nCycles === undefined) nCycles = 11;
|
||||||
|
X86.fnINT.call(this, nIDT, null, nCycles);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fnTrap(nIDT, nCycles)
|
* fnTrap(nIDT, nCycles)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue