From 33685c33185f0c7335ed22f71f88dc038cf12061 Mon Sep 17 00:00:00 2001 From: TomW Date: Mon, 28 Sep 2015 20:33:36 +0100 Subject: [PATCH] More changes to FPU nearest rounding, Unreal works again. --- src/codegen_ops_x86-64.h | 11 ++++++++++- src/codegen_ops_x86.h | 28 ++++++++++++++++++++-------- src/x87_ops.h | 14 ++++++++++---- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/codegen_ops_x86-64.h b/src/codegen_ops_x86-64.h index 7b52213..fb025aa 100644 --- a/src/codegen_ops_x86-64.h +++ b/src/codegen_ops_x86-64.h @@ -3737,10 +3737,19 @@ static void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) } static int64_t x87_fround(double b) { + int64_t a, c; + switch ((npxc>>10)&3) { case 0: /*Nearest*/ - return (int64_t)(b+0.5); + a = (int64_t)floor(b); + c = (int64_t)floor(b + 1.0); + if ((b - a) < (b - c)) + return a; + else if ((b - a) > (b - c)) + return b; + else + return (a & 1) ? c : a; case 1: /*Down*/ return (int64_t)floor(b); case 2: /*Up*/ diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index 9f27634..79a50f3 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -2254,13 +2254,19 @@ static void FP_RESTORE_ROUNDING() static int32_t x87_fround32(double b) { + int64_t a, c; + switch ((npxc>>10)&3) { case 0: /*Nearest*/ - if (b < 0.0) - return (int32_t)(b-0.5); - else - return (int32_t)(b+0.5); + a = (int64_t)floor(b); + c = (int64_t)floor(b + 1.0); + if ((b - a) < (b - c)) + return a; + else if ((b - a) > (b - c)) + return b; + else + return (a & 1) ? c : a; case 1: /*Down*/ return (int32_t)floor(b); case 2: /*Up*/ @@ -2271,13 +2277,19 @@ static int32_t x87_fround32(double b) } static int64_t x87_fround64(double b) { + int64_t a, c; + switch ((npxc>>10)&3) { case 0: /*Nearest*/ - if (b < 0.0) - return (int64_t)(b-0.5); - else - return (int64_t)(b+0.5); + a = (int64_t)floor(b); + c = (int64_t)floor(b + 1.0); + if ((b - a) < (b - c)) + return a; + else if ((b - a) > (b - c)) + return b; + else + return (a & 1) ? c : a; case 1: /*Down*/ return (int64_t)floor(b); case 2: /*Up*/ diff --git a/src/x87_ops.h b/src/x87_ops.h index e301dde..1cd4e8c 100644 --- a/src/x87_ops.h +++ b/src/x87_ops.h @@ -66,13 +66,19 @@ static inline double x87_pop() static inline int64_t x87_fround(double b) { + int64_t a, c; + switch ((npxc>>10)&3) { case 0: /*Nearest*/ - if (b < 0.0) - return (int64_t)(b-0.5); - else - return (int64_t)(b+0.5); + a = (int64_t)floor(b); + c = (int64_t)floor(b + 1.0); + if ((b - a) < (b - c)) + return a; + else if ((b - a) > (b - c)) + return b; + else + return (a & 1) ? c : a; case 1: /*Down*/ return (int64_t)floor(b); case 2: /*Up*/