A little more meat on the X86FPU bones
This commit is contained in:
parent
2b1b62d565
commit
a1556df5a5
14 changed files with 801 additions and 81 deletions
|
|
@ -1129,7 +1129,7 @@ ChipSet.prototype.powerUp = function(data, fRepower)
|
||||||
*/
|
*/
|
||||||
ChipSet.prototype.powerDown = function(fSave, fShutdown)
|
ChipSet.prototype.powerDown = function(fSave, fShutdown)
|
||||||
{
|
{
|
||||||
return fSave && this.save? this.save() : true;
|
return fSave? this.save() : true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ CPU.prototype.powerDown = function(fSave, fShutdown)
|
||||||
*
|
*
|
||||||
* this.aFlags.fPowered = false;
|
* this.aFlags.fPowered = false;
|
||||||
*/
|
*/
|
||||||
return fSave && this.save ? this.save() : true;
|
return fSave? this.save() : true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -432,6 +432,8 @@ if (DEBUGGER) {
|
||||||
"FINCSTP","FDECSTP","FFREE", "FNOP", "FWAIT"
|
"FINCSTP","FDECSTP","FFREE", "FNOP", "FWAIT"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Debugger.FPU_TAGS = ["VALID", "ZERO", "SPECIAL", "EMPTY"];
|
||||||
|
|
||||||
Debugger.CPU_8086 = 0;
|
Debugger.CPU_8086 = 0;
|
||||||
Debugger.CPU_80186 = 1;
|
Debugger.CPU_80186 = 1;
|
||||||
Debugger.CPU_80286 = 2;
|
Debugger.CPU_80286 = 2;
|
||||||
|
|
@ -1404,6 +1406,7 @@ if (DEBUGGER) {
|
||||||
this.cmp = cmp;
|
this.cmp = cmp;
|
||||||
this.fdc = cmp.getMachineComponent("FDC");
|
this.fdc = cmp.getMachineComponent("FDC");
|
||||||
this.hdc = cmp.getMachineComponent("HDC");
|
this.hdc = cmp.getMachineComponent("HDC");
|
||||||
|
this.fpu = cmp.getMachineComponent("FPU");
|
||||||
this.mouse = cmp.getMachineComponent("Mouse");
|
this.mouse = cmp.getMachineComponent("Mouse");
|
||||||
if (MAXDEBUG) this.chipset = cmp.getMachineComponent("ChipSet");
|
if (MAXDEBUG) this.chipset = cmp.getMachineComponent("ChipSet");
|
||||||
|
|
||||||
|
|
@ -3962,7 +3965,7 @@ if (DEBUGGER) {
|
||||||
Debugger.prototype.powerDown = function(fSave, fShutdown)
|
Debugger.prototype.powerDown = function(fSave, fShutdown)
|
||||||
{
|
{
|
||||||
if (fShutdown) this.println(fSave? "suspending" : "shutting down");
|
if (fShutdown) this.println(fSave? "suspending" : "shutting down");
|
||||||
return fSave && this.save? this.save() : true;
|
return fSave? this.save() : true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -4904,14 +4907,15 @@ if (DEBUGGER) {
|
||||||
var r_m = (bModRM & 0x7);
|
var r_m = (bModRM & 0x7);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Similar to how fnFPU() decodes FPU instructions, we combine mod and reg into one
|
* Similar to how opFPU() decodes FPU instructions, we combine mod and reg into 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.
|
* All values >= 0x34 imply mod == 3 and reg >= 4, so now we shift reg into the high
|
||||||
|
* nibble and r_m into 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;
|
||||||
|
|
@ -7021,6 +7025,7 @@ if (DEBUGGER) {
|
||||||
if (asArgs && asArgs[1] == '?') {
|
if (asArgs && asArgs[1] == '?') {
|
||||||
this.println("register commands:");
|
this.println("register commands:");
|
||||||
this.println("\tr\tdump registers");
|
this.println("\tr\tdump registers");
|
||||||
|
if (this.fpu) this.println("\trfp\tdump floating-point registers");
|
||||||
this.println("\trp\tdump all registers");
|
this.println("\trp\tdump all registers");
|
||||||
this.println("\trx [#]\tset flag or register x to [#]");
|
this.println("\trx [#]\tset flag or register x to [#]");
|
||||||
return;
|
return;
|
||||||
|
|
@ -7031,9 +7036,14 @@ if (DEBUGGER) {
|
||||||
|
|
||||||
if (asArgs != null && asArgs.length > 1) {
|
if (asArgs != null && asArgs.length > 1) {
|
||||||
var sReg = asArgs[1];
|
var sReg = asArgs[1];
|
||||||
|
if (this.fpu && sReg == "fp") {
|
||||||
|
this.doFPURegisters(asArgs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (sReg == 'p') {
|
if (sReg == 'p') {
|
||||||
fProt = (this.cpu.model >= X86.MODEL_80286);
|
fProt = (this.cpu.model >= X86.MODEL_80286);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// fInstruction = false;
|
// fInstruction = false;
|
||||||
var sValue = null;
|
var sValue = null;
|
||||||
var i = sReg.indexOf('=');
|
var i = sReg.indexOf('=');
|
||||||
|
|
@ -7269,6 +7279,26 @@ if (DEBUGGER) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* doFPURegisters(asArgs)
|
||||||
|
*
|
||||||
|
* NOTE: If we're called, the existence of an FPU has already been verified.
|
||||||
|
*
|
||||||
|
* @this {Debugger}
|
||||||
|
* @param {Array.<string>} [asArgs]
|
||||||
|
*/
|
||||||
|
Debugger.prototype.doFPURegisters = function(asArgs)
|
||||||
|
{
|
||||||
|
this.assert(this.fpu);
|
||||||
|
for (var i = 0; i < 8; i++) {
|
||||||
|
var a = this.fpu.readFPUStack(i);
|
||||||
|
if (!a) break;
|
||||||
|
var sValue = str.pad(a[2].toFixed(15), 24, true);
|
||||||
|
this.println("ST" + i + ": " + sValue + " " + str.toHex(a[4]) + "," + str.toHex(a[3]) + " [" + Debugger.FPU_TAGS[a[1]] + "]");
|
||||||
|
// this.println(" REG" + a[0] + " " + str.toBin(a[7], 16) + str.toBin(a[6]) + str.toBin(a[5]));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* doRun(sCmd, sAddr, sOptions, fQuiet)
|
* doRun(sCmd, sAddr, sOptions, fQuiet)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -614,7 +614,7 @@ FDC.prototype.powerUp = function(data, fRepower)
|
||||||
*/
|
*/
|
||||||
FDC.prototype.powerDown = function(fSave, fShutdown)
|
FDC.prototype.powerDown = function(fSave, fShutdown)
|
||||||
{
|
{
|
||||||
return fSave && this.save? this.save() : true;
|
return fSave? this.save() : true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -572,7 +572,7 @@ HDC.prototype.powerUp = function(data, fRepower)
|
||||||
*/
|
*/
|
||||||
HDC.prototype.powerDown = function(fSave, fShutdown)
|
HDC.prototype.powerDown = function(fSave, fShutdown)
|
||||||
{
|
{
|
||||||
return fSave && this.save? this.save() : true;
|
return fSave? this.save() : true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1373,7 +1373,7 @@ Keyboard.prototype.powerUp = function(data, fRepower)
|
||||||
*/
|
*/
|
||||||
Keyboard.prototype.powerDown = function(fSave, fShutdown)
|
Keyboard.prototype.powerDown = function(fSave, fShutdown)
|
||||||
{
|
{
|
||||||
return fSave && this.save? this.save() : true;
|
return fSave? this.save() : true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -294,7 +294,7 @@ Mouse.prototype.powerUp = function(data, fRepower)
|
||||||
*/
|
*/
|
||||||
Mouse.prototype.powerDown = function(fSave, fShutdown)
|
Mouse.prototype.powerDown = function(fSave, fShutdown)
|
||||||
{
|
{
|
||||||
return fSave && this.save? this.save() : true;
|
return fSave? this.save() : true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -444,7 +444,7 @@ SerialPort.prototype.powerUp = function(data, fRepower)
|
||||||
*/
|
*/
|
||||||
SerialPort.prototype.powerDown = function(fSave, fShutdown)
|
SerialPort.prototype.powerDown = function(fSave, fShutdown)
|
||||||
{
|
{
|
||||||
return fSave && this.save ? this.save() : true;
|
return fSave? this.save() : true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -3497,7 +3497,7 @@ Video.prototype.powerUp = function(data, fRepower)
|
||||||
*/
|
*/
|
||||||
Video.prototype.powerDown = function(fSave, fShutdown)
|
Video.prototype.powerDown = function(fSave, fShutdown)
|
||||||
{
|
{
|
||||||
return fSave && this.save? this.save() : true;
|
return fSave? this.save() : true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -524,6 +524,7 @@ var X86 = {
|
||||||
FPU: {
|
FPU: {
|
||||||
MODEL_8087: 8087,
|
MODEL_8087: 8087,
|
||||||
MODEL_80287: 80287,
|
MODEL_80287: 80287,
|
||||||
|
MODEL_80287XL: 80387, // internally, the 80287XL was an 80387SX, so I'm not sure we really want/need a unique identifier
|
||||||
MODEL_80387: 80387,
|
MODEL_80387: 80387,
|
||||||
CONTROL: { // FPU Control Word
|
CONTROL: { // FPU Control Word
|
||||||
IM: 0x0001, // bit 0: Invalid Operation Mask
|
IM: 0x0001, // bit 0: Invalid Operation Mask
|
||||||
|
|
@ -532,13 +533,15 @@ 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
|
||||||
|
EXC: 0x003F, // all of the above exceptions
|
||||||
// bit 6: unused
|
// 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
|
// 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
|
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
|
||||||
|
UNUSED: 0xE040
|
||||||
},
|
},
|
||||||
STATUS: { // FPU Status Word
|
STATUS: { // FPU Status Word
|
||||||
IE: 0x0001, // bit 0: Invalid Operation
|
IE: 0x0001, // bit 0: Invalid Operation
|
||||||
|
|
@ -555,7 +558,8 @@ var X86 = {
|
||||||
C2: 0x0400, // bit 10: Condition Code 2
|
C2: 0x0400, // bit 10: Condition Code 2
|
||||||
ST: 0x3800, // bits 11-13: Stack Top
|
ST: 0x3800, // bits 11-13: Stack Top
|
||||||
C3: 0x4000, // bit 14: Condition Code 3
|
C3: 0x4000, // bit 14: Condition Code 3
|
||||||
BUSY: 0x8000 // bit 15: Busy
|
BUSY: 0x8000, // bit 15: Busy
|
||||||
|
ST_SHIFT: 11
|
||||||
},
|
},
|
||||||
TAGS: {
|
TAGS: {
|
||||||
VALID: 0x0,
|
VALID: 0x0,
|
||||||
|
|
|
||||||
|
|
@ -1186,6 +1186,8 @@ X86CPU.prototype.resetRegs = function()
|
||||||
this.opFlags = this.opPrefixes = 0;
|
this.opFlags = this.opPrefixes = 0;
|
||||||
this.regEA = this.regEAWrite = X86.ADDR_INVALID;
|
this.regEA = this.regEAWrite = X86.ADDR_INVALID;
|
||||||
|
|
||||||
|
this.segEA = this.segNULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* intFlags contains some internal states we use to indicate whether a hardware interrupt (INTFLAG.INTR) or
|
* intFlags contains some internal states we use to indicate whether a hardware interrupt (INTFLAG.INTR) or
|
||||||
* Trap software interrupt (INTR.TRAP) has been requested, as well as when we're in a "HLT" state (INTFLAG.HALT)
|
* Trap software interrupt (INTR.TRAP) has been requested, as well as when we're in a "HLT" state (INTFLAG.HALT)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -142,7 +142,8 @@ X86Seg.ID = {
|
||||||
TSS: 4, // "TSS"
|
TSS: 4, // "TSS"
|
||||||
LDT: 5, // "LDT"
|
LDT: 5, // "LDT"
|
||||||
VER: 6, // "VER"
|
VER: 6, // "VER"
|
||||||
DBG: 7 // "DBG"
|
FPU: 7, // "FPU"
|
||||||
|
DBG: 8 // "DBG"
|
||||||
};
|
};
|
||||||
|
|
||||||
X86Seg.CALLBREAK_SEL = 0x0001;
|
X86Seg.CALLBREAK_SEL = 0x0001;
|
||||||
|
|
|
||||||
|
|
@ -375,17 +375,19 @@ str.replaceArray = function(a, s)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pad(s, cch)
|
* pad(s, cch, fPadLeft)
|
||||||
*
|
*
|
||||||
* NOTE: the maximum amount of padding currently supported is 40 spaces.
|
* NOTE: the maximum amount of padding currently supported is 40 spaces.
|
||||||
*
|
*
|
||||||
* @param {string} s is a string
|
* @param {string} s is a string
|
||||||
* @param {number} cch is desired length
|
* @param {number} cch is desired length
|
||||||
|
* @param {boolean} [fPadLeft] (default is padding on the right)
|
||||||
* @returns {string} the original string (s) with spaces padding it to the specified length
|
* @returns {string} the original string (s) with spaces padding it to the specified length
|
||||||
*/
|
*/
|
||||||
str.pad = function(s, cch)
|
str.pad = function(s, cch, fPadLeft)
|
||||||
{
|
{
|
||||||
return s + " ".substr(0, cch - s.length);
|
var sPadding = " ";
|
||||||
|
return fPadLeft? (sPadding + s).slice(-cch) : (s + sPadding).slice(0, cch);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue