diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-10-25 20:14:11 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-25 14:14:11 +0200 |
| commit | 87bf751b115267d7c388c849c43fca6d3f0d0881 (patch) | |
| tree | edc6f3976538daf8dd1d9a49694d4bda19ef591d /src/emu | |
| parent | 12c40a5b804143cee0d538c4de4b526522bcfcd2 (diff) | |
| download | box64-87bf751b115267d7c388c849c43fca6d3f0d0881.tar.gz box64-87bf751b115267d7c388c849c43fca6d3f0d0881.zip | |
[INTERP] Fix fpu_round (#1030)
* [INTERP] Fix fpu_round * Should be working this time * Handling wrappedlibm * Format * Fix loongarch * Make it optional * Fix android build
Diffstat (limited to 'src/emu')
| -rw-r--r-- | src/emu/x64run0f.c | 7 | ||||
| -rw-r--r-- | src/emu/x64run660f.c | 37 | ||||
| -rw-r--r-- | src/emu/x64runf20f.c | 19 | ||||
| -rw-r--r-- | src/emu/x64runf30f.c | 13 | ||||
| -rw-r--r-- | src/emu/x87emu_private.h | 10 |
5 files changed, 72 insertions, 14 deletions
diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c index a05b3596..e8a047f2 100644 --- a/src/emu/x64run0f.c +++ b/src/emu/x64run0f.c @@ -3,6 +3,7 @@ #include <stdio.h> #include <stdlib.h> #include <math.h> +#include <fenv.h> #include <string.h> #include <signal.h> #include <sys/types.h> @@ -232,9 +233,13 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); tmp64s = nearbyintf(EX->f[i]); + fesetround(round); break; + } case ROUND_Down: tmp64s = floorf(EX->f[i]); break; diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index 84f5a38e..9b969c83 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -3,6 +3,7 @@ #include <stdio.h> #include <stdlib.h> #include <math.h> +#include <fenv.h> #include <string.h> #include <signal.h> #include <sys/types.h> @@ -221,10 +222,14 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GETEX(0); GETGM; switch(emu->mxcsr.f.MXCSR_RC) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); i64[0] = nearbyint(EX->d[0]); i64[1] = nearbyint(EX->d[1]); + fesetround(round); break; + } case ROUND_Down: i64[0] = floor(EX->d[0]); i64[1] = floor(EX->d[1]); @@ -818,10 +823,14 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) else tmp8u &= 3; switch(tmp8u) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); for(int i=0; i<4; ++i) GX->f[i] = nearbyintf(EX->f[i]); + fesetround(round); break; + } case ROUND_Down: for(int i=0; i<4; ++i) GX->f[i] = floorf(EX->f[i]); @@ -846,10 +855,14 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) else tmp8u &= 3; switch(tmp8u) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); GX->d[0] = nearbyint(EX->d[0]); GX->d[1] = nearbyint(EX->d[1]); + fesetround(round); break; + } case ROUND_Down: GX->d[0] = floor(EX->d[0]); GX->d[1] = floor(EX->d[1]); @@ -874,9 +887,13 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) else tmp8u &= 3; switch(tmp8u) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); GX->f[0] = nearbyintf(EX->f[0]); + fesetround(round); break; + } case ROUND_Down: GX->f[0] = floorf(EX->f[0]); break; @@ -898,9 +915,13 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) else tmp8u &= 3; switch(tmp8u) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); GX->d[0] = nearbyint(EX->d[0]); + fesetround(round); break; + } case ROUND_Down: GX->d[0] = floor(EX->d[0]); break; @@ -1227,9 +1248,13 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); tmp64s = nearbyintf(EX->f[i]); + fesetround(round); break; + } case ROUND_Down: tmp64s = floorf(EX->f[i]); break; diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c index 33750318..d5ce598f 100644 --- a/src/emu/x64runf20f.c +++ b/src/emu/x64runf20f.c @@ -3,6 +3,7 @@ #include <stdio.h> #include <stdlib.h> #include <math.h> +#include <fenv.h> #include <string.h> #include <signal.h> #include <sys/types.h> @@ -113,9 +114,13 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GD->q[0] = 0x8000000000000000LL; else switch(emu->mxcsr.f.MXCSR_RC) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); GD->sq[0] = nearbyint(EX->d[0]); + fesetround(round); break; + } case ROUND_Down: GD->sq[0] = floor(EX->d[0]); break; @@ -131,9 +136,13 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GD->dword[0] = 0x80000000; else switch(emu->mxcsr.f.MXCSR_RC) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); GD->sdword[0] = nearbyint(EX->d[0]); + fesetround(round); break; + } case ROUND_Down: GD->sdword[0] = floor(EX->d[0]); break; @@ -325,10 +334,14 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETEX(0); GETGX; switch(emu->mxcsr.f.MXCSR_RC) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); tmp64s0 = nearbyint(EX->d[0]); tmp64s1 = nearbyint(EX->d[1]); + fesetround(round); break; + } case ROUND_Down: tmp64s0 = floor(EX->d[0]); tmp64s1 = floor(EX->d[1]); diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c index d5b70b20..bd7c97e9 100644 --- a/src/emu/x64runf30f.c +++ b/src/emu/x64runf30f.c @@ -3,6 +3,7 @@ #include <stdio.h> #include <stdlib.h> #include <math.h> +#include <fenv.h> #include <string.h> #include <signal.h> #include <sys/types.h> @@ -119,9 +120,13 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr) GD->q[0] = 0x8000000000000000LL; else switch(emu->mxcsr.f.MXCSR_RC) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); GD->sq[0] = nearbyintf(EX->f[0]); + fesetround(round); break; + } case ROUND_Down: GD->sq[0] = floorf(EX->f[0]); break; @@ -137,9 +142,13 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { - case ROUND_Nearest: + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); tmp64s = nearbyintf(EX->f[0]); + fesetround(round); break; + } case ROUND_Down: tmp64s = floorf(EX->f[0]); break; diff --git a/src/emu/x87emu_private.h b/src/emu/x87emu_private.h index 5721088f..a8e2d39c 100644 --- a/src/emu/x87emu_private.h +++ b/src/emu/x87emu_private.h @@ -3,6 +3,7 @@ #include <stdint.h> #include <math.h> +#include <fenv.h> #include "regs.h" #include "x64run_private.h" #include "debug.h" @@ -108,8 +109,13 @@ static inline double fpu_round(x64emu_t* emu, double d) { if (!isfinite(d)) return d; switch(emu->cw.f.C87_RD) { - case ROUND_Nearest: - return nearbyint(d); + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); + double res = nearbyint(d); + fesetround(round); + return res; + } case ROUND_Down: return floor(d); case ROUND_Up: |