From 19ce34787d30cc35848063c5d225de980106c8bd Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Apr 2023 18:05:20 +0200 Subject: [PATCH] Implemented the x87 instruction FXTRACT. --- src/cpu/x87_ops.h | 21 ++++++++++++++++----- src/cpu/x87_ops_misc.h | 14 ++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index c00cdff16..faac0ea60 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -46,6 +46,17 @@ static int rounding_modes[4] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARD #define STATUS_ZERODIVIDE 4 +typedef union +{ + double d; + + struct { + unsigned int mantissa:52; + unsigned int exponent:11; + unsigned int negative:1; + }; +} double_decompose; + #if defined(_MSC_VER) && !defined(__clang__) # if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 # define X87_INLINE_ASM @@ -570,7 +581,7 @@ const OpFn OP_TABLE(fpu_8087_d9)[256] = { ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a16, ILLEGAL_a16, opFTST, opFXAM, ILLEGAL_a16, ILLEGAL_a16, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a16, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a16, ILLEGAL_a16, opFDECSTP, opFINCSTP, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, opFPREM, opFYL2XP1, opFSQRT, ILLEGAL_a16, opFRNDINT, opFSCALE, ILLEGAL_a16, ILLEGAL_a16 // clang-format on }; @@ -839,7 +850,7 @@ const OpFn OP_TABLE(fpu_287_d9_a16)[256] = { ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a16, ILLEGAL_a16, opFTST, opFXAM, ILLEGAL_a16, ILLEGAL_a16, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a16, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a16, opFPREM1, opFDECSTP, opFINCSTP, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS // clang-format on }; @@ -879,7 +890,7 @@ const OpFn OP_TABLE(fpu_287_d9_a32)[256] = { ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a32, ILLEGAL_a32, opFTST, opFXAM, ILLEGAL_a32, ILLEGAL_a32, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a32, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a32, opFPREM1, opFDECSTP, opFINCSTP, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS // clang-format on }; @@ -919,7 +930,7 @@ const OpFn OP_TABLE(fpu_d9_a16)[256] = { opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a16, ILLEGAL_a16, opFTST, opFXAM, ILLEGAL_a16, ILLEGAL_a16, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a16, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a16, opFPREM1, opFDECSTP, opFINCSTP, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS // clang-format on }; @@ -959,7 +970,7 @@ const OpFn OP_TABLE(fpu_d9_a32)[256] = { opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a32, ILLEGAL_a32, opFTST, opFXAM, ILLEGAL_a32, ILLEGAL_a32, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a32, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a32, opFPREM1, opFDECSTP, opFINCSTP, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS // clang-format on }; diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index 091d7cc31..a7295b0a3 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -33,6 +33,20 @@ opFNOP(uint32_t fetchdat) return 0; } +static int +opFXTRACT(uint32_t fetchdat) +{ + double_decompose_t temp = (double_decompose_t) ST(0); + + FP_ENTER(); + cpu_state.pc++; + ST(0) = (double) temp.exponent; + x87_push((double) temp.mantissa); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxtract) : (x87_timings.fxtract * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxtract) : (x87_concurrency.fxtract * cpu_multi)); + return 0; +} + static int opFCLEX(uint32_t fetchdat) {