A little more meat on the X86FPU bones

This commit is contained in:
Jeff Parsons 2015-11-15 11:13:59 -08:00
commit a1556df5a5
14 changed files with 801 additions and 81 deletions

View file

@ -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;
}; };
/** /**

View file

@ -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;
}; };
/** /**

View file

@ -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)
* *

View file

@ -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;
}; };
/** /**

View file

@ -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;
}; };
/** /**

View file

@ -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;
}; };
/** /**

View file

@ -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;
}; };
/** /**

View file

@ -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;
}; };
/** /**

View file

@ -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;
}; };
/** /**

View file

@ -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,

View file

@ -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

View file

@ -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;

View file

@ -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);
}; };
/** /**