From 3bad5547c2389c9752f89278e096f45a3c6c6c24 Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Tue, 1 Dec 2015 11:44:57 -0800 Subject: [PATCH] Notes on FPU stack faults (which only affects the 80387 and up, which isn't fully supported yet) --- modules/pcjs/lib/x86.js | 2 +- modules/pcjs/lib/x86fpu.js | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/pcjs/lib/x86.js b/modules/pcjs/lib/x86.js index ce5b128c7..00acca715 100644 --- a/modules/pcjs/lib/x86.js +++ b/modules/pcjs/lib/x86.js @@ -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 diff --git a/modules/pcjs/lib/x86fpu.js b/modules/pcjs/lib/x86fpu.js index d434acc23..befb6237c 100644 --- a/modules/pcjs/lib/x86fpu.js +++ b/modules/pcjs/lib/x86fpu.js @@ -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)