Notes on FPU stack faults (which only affects the 80387 and up, which isn't fully supported yet)

This commit is contained in:
Jeff Parsons 2015-12-01 11:44:57 -08:00
commit 3bad5547c2
2 changed files with 14 additions and 2 deletions

View file

@ -554,7 +554,7 @@ var X86 = {
OE: 0x0008, // bit 3: Overflow
UE: 0x0010, // bit 4: Underflow
PE: 0x0020, // bit 5: Precision
SF: 0x0040, // bit 6: Stack Fault (80387 and later)
SF: 0x0040, // bit 6: Stack Fault (80387 and later; triggers an Invalid Operation exception)
EXC: 0x007F, // all of the above exceptions
ES: 0x0080, // bit 7: Error/Exception Status/Summary (Interrupt Request on 8087)
C0: 0x0100, // bit 8: Condition Code 0

View file

@ -427,7 +427,16 @@ X86FPU.prototype.opUnimplemented = function()
X86FPU.prototype.checkException = function()
{
this.regStatus &= ~X86.FPU.STATUS.ES;
if (this.regStatus & (~this.regControl & X86.FPU.STATUS.EXC)) {
/*
* NOTE: The "Stack Fault" (SF) status bit wasn't introduced until the 80387, so it triggers the pre-existing
* "Invalid Operation" (IE) exception; there is no corresponding "Stack Fault" (SE) exception, and the matching
* control bit is still reserved. Consequently, X86.FPU.CONTROL.EXC is a *subset* of X86.FPU.STATUS.EXC (0x3F
* instead of 0x7F).
*
* However, we shouldn't have to do anything special when SF is set, because any setException() call that sets
* SF should ALSO set IE.
*/
if (this.regStatus & (~this.regControl & X86.FPU.CONTROL.EXC)) {
this.regStatus |= X86.FPU.STATUS.ES; // set ES whenever one or more unmasked EXC bits are set
}
if ((this.regStatus & X86.FPU.STATUS.ES) && !(this.regControl & X86.FPU.CONTROL.IEM)) {
@ -451,6 +460,9 @@ X86FPU.prototype.checkException = function()
* PE (0x0020 bit 5: Precision)
* SF (0x0040 bit 6: Stack Fault; 80387 and later)
*
* Also, as noted in checkException(), any time you set the SF bit, you should also set the IE bit, because
* Stack Fault is a subset of Invalid Operation. TODO: We should include a test for that in the assertion below.
*
* @this {X86FPU}
* @param {number} n (one or more of the above error status bits)
* @return {boolean} (true if unmasked exception exists, false if not)