diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index a68dee7ae..906b07dc6 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -4363,7 +4363,7 @@ static inline int FP_LOAD_REG_INT_W(int reg) addbyte(0xc5); addbyte((uint8_t)cpu_state_offset(ST)); - CALL_FUNC((uintptr_t)x87_fround); + CALL_FUNC((uintptr_t)x87_fround16_64); addbyte(0x93); /*XCHG EBX, EAX*/ @@ -4393,7 +4393,7 @@ static inline int FP_LOAD_REG_INT(int reg) addbyte(0xc5); addbyte((uint8_t)cpu_state_offset(ST)); - CALL_FUNC((uintptr_t)x87_fround); + CALL_FUNC((uintptr_t)x87_fround32_64); addbyte(0x93); /*XCHG EBX, EAX*/ diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 17861fa57..9e06a343e 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -152,10 +152,72 @@ static __inline double x87_pop() return t; } +static __inline int16_t x87_fround16(double b) +{ + int16_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int16_t)floor(b); + c = (int16_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int16_t)floor(b); + case 2: /*Up*/ + return (int16_t)ceil(b); + case 3: /*Chop*/ + return (int16_t)b; + } + + return 0; +} + +static __inline int64_t x87_fround16_64(double b) +{ + return (int64_t) x87_fround16(b); +} + +static __inline int32_t x87_fround32(double b) +{ + int32_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int32_t)floor(b); + c = (int32_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int32_t)floor(b); + case 2: /*Up*/ + return (int32_t)ceil(b); + case 3: /*Chop*/ + return (int32_t)b; + } + + return 0; +} + +static __inline int64_t x87_fround32_64(double b) +{ + return (int64_t) x87_fround32(b); +} + static __inline int64_t x87_fround(double b) { int64_t a, c; - + switch ((cpu_state.npxc >> 10) & 3) { case 0: /*Nearest*/ diff --git a/src/cpu/x87_ops_loadstore.h b/src/cpu/x87_ops_loadstore.h index f742196ea..5e754fc90 100644 --- a/src/cpu/x87_ops_loadstore.h +++ b/src/cpu/x87_ops_loadstore.h @@ -42,24 +42,20 @@ static int opFILDiw_a32(uint32_t fetchdat) static int opFISTiw_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); + seteaw(x87_fround16(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return cpu_state.abrt; } #ifndef FPU_8087 static int opFISTiw_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); + seteaw(x87_fround16(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return cpu_state.abrt; } @@ -67,12 +63,10 @@ static int opFISTiw_a32(uint32_t fetchdat) static int opFISTPiw_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; + seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return 0; @@ -80,12 +74,10 @@ static int opFISTPiw_a16(uint32_t fetchdat) #ifndef FPU_8087 static int opFISTPiw_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; + seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return 0; @@ -240,24 +232,20 @@ static int opFILDil_a32(uint32_t fetchdat) static int opFISTil_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); + seteal(x87_fround32(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return cpu_state.abrt; } #ifndef FPU_8087 static int opFISTil_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); + seteal(x87_fround32(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return cpu_state.abrt; } @@ -265,12 +253,10 @@ static int opFISTil_a32(uint32_t fetchdat) static int opFISTPil_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); if (cpu_state.abrt) return 1; + seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return 0; @@ -278,12 +264,10 @@ static int opFISTPil_a16(uint32_t fetchdat) #ifndef FPU_8087 static int opFISTPil_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); if (cpu_state.abrt) return 1; + seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return 0;