Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'remotes/rth/tags/pull-fpu-20200515' int…
…o staging floatx80 x87 pseudo-denormal fixes # gpg: Signature made Fri 15 May 2020 19:10:27 BST # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth/tags/pull-fpu-20200515: softfloat: fix floatx80 pseudo-denormal round to integer softfloat: fix floatx80 pseudo-denormal comparisons softfloat: fix floatx80 pseudo-denormal addition / subtraction softfloat: silence sNaN for conversions to/from floatx80 Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
- Loading branch information
Showing
3 changed files
with
133 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* Test pseudo-denormal operations. */ | ||
|
||
#include <stdint.h> | ||
#include <stdio.h> | ||
|
||
union u { | ||
struct { uint64_t sig; uint16_t sign_exp; } s; | ||
long double ld; | ||
}; | ||
|
||
volatile union u ld_pseudo_m16382 = { .s = { UINT64_C(1) << 63, 0 } }; | ||
|
||
volatile long double ld_res; | ||
|
||
int main(void) | ||
{ | ||
short cw; | ||
int ret = 0; | ||
ld_res = ld_pseudo_m16382.ld + ld_pseudo_m16382.ld; | ||
if (ld_res != 0x1p-16381L) { | ||
printf("FAIL: pseudo-denormal add\n"); | ||
ret = 1; | ||
} | ||
if (ld_pseudo_m16382.ld != 0x1p-16382L) { | ||
printf("FAIL: pseudo-denormal compare\n"); | ||
ret = 1; | ||
} | ||
/* Set round-upward. */ | ||
__asm__ volatile ("fnstcw %0" : "=m" (cw)); | ||
cw = (cw & ~0xc00) | 0x800; | ||
__asm__ volatile ("fldcw %0" : : "m" (cw)); | ||
__asm__ ("frndint" : "=t" (ld_res) : "0" (ld_pseudo_m16382.ld)); | ||
if (ld_res != 1.0L) { | ||
printf("FAIL: pseudo-denormal round-to-integer\n"); | ||
ret = 1; | ||
} | ||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* Test conversions of signaling NaNs to and from long double. */ | ||
|
||
#include <stdint.h> | ||
#include <stdio.h> | ||
|
||
volatile float f_res; | ||
volatile double d_res; | ||
volatile long double ld_res; | ||
|
||
volatile float f_snan = __builtin_nansf(""); | ||
volatile double d_snan = __builtin_nans(""); | ||
volatile long double ld_snan = __builtin_nansl(""); | ||
|
||
int issignaling_f(float x) | ||
{ | ||
union { float f; uint32_t u; } u = { .f = x }; | ||
return (u.u & 0x7fffffff) > 0x7f800000 && (u.u & 0x400000) == 0; | ||
} | ||
|
||
int issignaling_d(double x) | ||
{ | ||
union { double d; uint64_t u; } u = { .d = x }; | ||
return (((u.u & UINT64_C(0x7fffffffffffffff)) > | ||
UINT64_C(0x7ff0000000000000)) && | ||
(u.u & UINT64_C(0x8000000000000)) == 0); | ||
} | ||
|
||
int issignaling_ld(long double x) | ||
{ | ||
union { | ||
long double ld; | ||
struct { uint64_t sig; uint16_t sign_exp; } s; | ||
} u = { .ld = x }; | ||
return ((u.s.sign_exp & 0x7fff) == 0x7fff && | ||
(u.s.sig >> 63) != 0 && | ||
(u.s.sig & UINT64_C(0x4000000000000000)) == 0); | ||
} | ||
|
||
int main(void) | ||
{ | ||
int ret = 0; | ||
ld_res = f_snan; | ||
if (issignaling_ld(ld_res)) { | ||
printf("FAIL: float -> long double\n"); | ||
ret = 1; | ||
} | ||
ld_res = d_snan; | ||
if (issignaling_ld(ld_res)) { | ||
printf("FAIL: double -> long double\n"); | ||
ret = 1; | ||
} | ||
f_res = ld_snan; | ||
if (issignaling_d(f_res)) { | ||
printf("FAIL: long double -> float\n"); | ||
ret = 1; | ||
} | ||
d_res = ld_snan; | ||
if (issignaling_d(d_res)) { | ||
printf("FAIL: long double -> double\n"); | ||
ret = 1; | ||
} | ||
return ret; | ||
} |