diff --git a/include/fpu.h b/include/fpu.h index da29096f..44acd31b 100644 --- a/include/fpu.h +++ b/include/fpu.h @@ -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 diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h index c0c3d090..9dc97c76 100644 --- a/src/fpu/fpu_instructions.h +++ b/src/fpu/fpu_instructions.h @@ -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); diff --git a/src/fpu/fpu_instructions_x86.h b/src/fpu/fpu_instructions_x86.h index 5b62177d..31e51fc4 100644 --- a/src/fpu/fpu_instructions_x86.h +++ b/src/fpu/fpu_instructions_x86.h @@ -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); }