1
0
Fork 0

Refine stack overflow and underflow for the fpu a bit.

Overflow is still treated as Exit.
Underflow is ignored in release mode as it happens every now and then and doesn't seem to cause issues if ignored, thus restoring 0.74 behaviour.



Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@4199
This commit is contained in:
Peter Veenstra 2019-04-01 14:32:18 +00:00
parent c9c97f13af
commit 4a1ef4d3d7
3 changed files with 96 additions and 5 deletions

View file

@ -19,6 +19,11 @@
#ifndef DOSBOX_FPU_H
#define DOSBOX_FPU_H
#ifndef DOSBOX_DOSBOX_H
//So the right config.h gets included for C_DEBUG
#include "dosbox.h"
#endif
#ifndef DOSBOX_MEM_H
#include "mem.h"
#endif
@ -150,5 +155,22 @@ static INLINE void FPU_SET_C3(Bitu C){
if(C) fpu.sw |= 0x4000;
}
#define DB_FPU_STACK_CHECK_NONE 0
#define DB_FPU_STACK_CHECK_LOG 1
#define DB_FPU_STACK_CHECK_EXIT 2
//NONE is 0.74 behavior: not care about stack overflow/underflow
//Overflow is always logged/exited on.
//Underflow can be controlled with by this.
//LOG is giving a message when encountered
//EXIT is to hard exit.
//Currently pop is ignored in release mode and overflow is exit.
//in debug mode: pop will log and overflow is exit.
#if C_DEBUG
#define DB_FPU_STACK_CHECK_POP DB_FPU_STACK_CHECK_LOG
#define DB_FPU_STACK_CHECK_PUSH DB_FPU_STACK_CHECK_EXIT
#else
#define DB_FPU_STACK_CHECK_POP DB_FPU_STACK_CHECK_NONE
#define DB_FPU_STACK_CHECK_PUSH DB_FPU_STACK_CHECK_EXIT
#endif
#endif

View file

@ -16,6 +16,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_FPU_H
#include "fpu.h"
#endif
static void FPU_FINIT(void) {
@ -43,7 +46,23 @@ static void FPU_FNOP(void){
static void FPU_PREP_PUSH(void){
TOP = (TOP - 1) &7;
if (GCC_UNLIKELY(fpu.tags[TOP] != TAG_Empty)) E_Exit("FPU stack overflow");
#if DB_FPU_STACK_CHECK_PUSH > DB_FPU_STACK_CHECK_NONE
if (GCC_UNLIKELY(fpu.tags[TOP] != TAG_Empty)) {
#if DB_FPU_STACK_CHECK_PUSH == DB_FPU_STACK_CHECK_EXIT
E_Exit("FPU stack overflow");
#else
if (fpu.cw&1) { // Masked ?
fpu.sw &= 0x1; //Invalid Operation
fpu.sw &= 0x40; //Stack Fault
FPU_SET_C1(1); //Register is used.
//No need to set 0x80 as the exception is masked.
LOG(LOG_FPU,LOG_ERROR)("Masked stack overflow encountered!");
} else {
E_Exit("FPU stack overflow"); //Exit as this is bad
}
#endif
}
#endif
fpu.tags[TOP] = TAG_Valid;
}
@ -56,7 +75,23 @@ static void FPU_PUSH(double in){
static void FPU_FPOP(void){
if (GCC_UNLIKELY(fpu.tags[TOP] == TAG_Empty)) E_Exit("FPU stack underflow");
#if DB_FPU_STACK_CHECK_POP > DB_FPU_STACK_CHECK_NONE
if (GCC_UNLIKELY(fpu.tags[TOP] != TAG_Empty)) {
#if DB_FPU_STACK_CHECK_POP == DB_FPU_STACK_CHECK_EXIT
E_Exit("FPU stack underflow");
#else
if (fpu.cw&1) { // Masked ?
fpu.sw &= 0x1; //Invalid Operation
fpu.sw &= 0x40; //Stack Fault
FPU_SET_C1(0); //Register is free.
//No need to set 0x80 as the exception is masked.
LOG(LOG_FPU,LOG_ERROR)("Masked stack underflow encountered!");
} else {
LOG_MSG("Unmasked Stack underflow!"); //Also log in release mode
}
#endif
}
#endif
fpu.tags[TOP]=TAG_Empty;
//maybe set zero in it as well
TOP = ((TOP+1)&7);

View file

@ -16,7 +16,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_FPU_H
#include "fpu.h"
#endif
// #define WEAK_EXCEPTIONS
@ -957,12 +959,44 @@ static void FPU_FNOP(void){
static void FPU_PREP_PUSH(void){
TOP = (TOP - 1) &7;
if (GCC_UNLIKELY(fpu.tags[TOP] != TAG_Empty)) E_Exit("FPU stack overflow");
#if DB_FPU_STACK_CHECK_PUSH > DB_FPU_STACK_CHECK_NONE
if (GCC_UNLIKELY(fpu.tags[TOP] != TAG_Empty)) {
#if DB_FPU_STACK_CHECK_PUSH == DB_FPU_STACK_CHECK_EXIT
E_Exit("FPU stack overflow");
#else
if (fpu.cw&1) { // Masked ?
fpu.sw &= 0x1; //Invalid Operation
fpu.sw &= 0x40; //Stack Fault
FPU_SET_C1(1); //Register is used.
//No need to set 0x80 as the exception is masked.
LOG(LOG_FPU,LOG_ERROR)("Masked stack overflow encountered!");
} else {
E_Exit("FPU stack overflow"); //Exit as this is bad
}
#endif
}
#endif
fpu.tags[TOP] = TAG_Valid;
}
static void FPU_FPOP(void){
if (GCC_UNLIKELY(fpu.tags[TOP] == TAG_Empty)) E_Exit("FPU stack underflow");
#if DB_FPU_STACK_CHECK_POP > DB_FPU_STACK_CHECK_NONE
if (GCC_UNLIKELY(fpu.tags[TOP] == TAG_Empty)) {
#if DB_FPU_STACK_CHECK_POP == DB_FPU_STACK_CHECK_EXIT
E_Exit("FPU stack underflow");
#else
if (fpu.cw&1) { // Masked ?
fpu.sw &= 0x1; //Invalid Operation
fpu.sw &= 0x40; //Stack Fault
FPU_SET_C1(0); //Register is free.
//No need to set 0x80 as the exception is masked.
LOG(LOG_FPU,LOG_ERROR)("Masked stack underflow encountered!");
} else {
LOG_MSG("Unmasked Stack underflow!");
}
#endif
}
#endif
fpu.tags[TOP] = TAG_Empty;
TOP = ((TOP+1)&7);
}