Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions compiler-rt/test/builtins/Unit/extendhfxf2_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,58 @@

#include "fp_test.h"

#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) && \
defined(COMPILER_RT_HAS_FLOAT16)
#if HAS_80_BIT_LONG_DOUBLE

xf_float __extendhfxf2(TYPE_FP16 f);

int test_extendhfxf2(TYPE_FP16 a, uint64_t expectedHi, uint64_t expectedLo) {
int test_extendhfxf2(TYPE_FP16 a, uint16_t expectedHi, uint64_t expectedLo) {
xf_float x = __extendhfxf2(a);
int ret = compareResultF80(x, expectedHi, expectedLo);
if (ret) {
printf("error in test__extendhfxf2(%#.4x) = %.20Lf, "
"expected %.20Lf\n",
toRep16(a), x, F80FromRep128(expectedHi, expectedLo));
toRep16(a), x, F80FromRep80(expectedHi, expectedLo));
}
return ret;
}

int main() {
// Small positive value
if (test_extendhfxf2(fromRep16(0x2e66), UINT64_C(0x3ffb),
if (test_extendhfxf2(fromRep16(0x2e66), UINT16_C(0x3ffb),
UINT64_C(0xccc0000000000000)))
return 1;

// Small negative value
if (test_extendhfxf2(fromRep16(0xae66), UINT64_C(0xbffb),
if (test_extendhfxf2(fromRep16(0xae66), UINT16_C(0xbffb),
UINT64_C(0xccc0000000000000)))
return 1;

// Zero
if (test_extendhfxf2(fromRep16(0), UINT64_C(0x0), UINT64_C(0x0)))
if (test_extendhfxf2(fromRep16(0), UINT16_C(0x0), UINT64_C(0x0)))
return 1;

// Smallest positive non-zero value
if (test_extendhfxf2(fromRep16(0x0100), UINT64_C(0x3fef),
if (test_extendhfxf2(fromRep16(0x0100), UINT16_C(0x3fef),
UINT64_C(0x8000000000000000)))
return 1;

// Smallest negative non-zero value
if (test_extendhfxf2(fromRep16(0x8100), UINT64_C(0xbfef),
if (test_extendhfxf2(fromRep16(0x8100), UINT16_C(0xbfef),
UINT64_C(0x8000000000000000)))
return 1;

// Positive infinity
if (test_extendhfxf2(makeInf16(), UINT64_C(0x7fff),
if (test_extendhfxf2(makeInf16(), UINT16_C(0x7fff),
UINT64_C(0x8000000000000000)))
return 1;

// Negative infinity
if (test_extendhfxf2(makeNegativeInf16(), UINT64_C(0xffff),
if (test_extendhfxf2(makeNegativeInf16(), UINT16_C(0xffff),
UINT64_C(0x8000000000000000)))
return 1;

// NaN
if (test_extendhfxf2(makeQNaN16(), UINT64_C(0x7fff),
if (test_extendhfxf2(makeQNaN16(), UINT16_C(0x7fff),
UINT64_C(0xc000000000000000)))
return 1;

Expand Down
60 changes: 33 additions & 27 deletions compiler-rt/test/builtins/Unit/fp_test.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "int_types.h"

Expand Down Expand Up @@ -230,44 +231,49 @@ static inline double makeQNaN64(void)
return fromRep64(0x7ff8000000000000UL);
}

#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__)
static inline long double F80FromRep128(uint64_t hi, uint64_t lo) {
__uint128_t x = ((__uint128_t)hi << 64) + lo;
long double ret;
memcpy(&ret, &x, 16);
return ret;
#if HAS_80_BIT_LONG_DOUBLE
static inline xf_float F80FromRep80(uint16_t hi, uint64_t lo) {
uqwords bits;
bits.high.all = hi;
bits.low.all = lo;
xf_float ret;
static_assert(sizeof(xf_float) <= sizeof(uqwords), "wrong representation");
memcpy(&ret, &bits, sizeof(ret));
return ret;
}

static inline __uint128_t F80ToRep128(long double x) {
__uint128_t ret;
memcpy(&ret, &x, 16);
return ret;
static inline uqwords F80ToRep80(xf_float x) {
uqwords ret;
memset(&ret, 0, sizeof(ret));
memcpy(&ret, &x, sizeof(x));
// Any bits beyond the first 16 in high are undefined.
ret.high.all = (uint16_t)ret.high.all;
return ret;
}

static inline int compareResultF80(long double result, uint64_t expectedHi,
static inline int compareResultF80(xf_float result, uint16_t expectedHi,
uint64_t expectedLo) {
__uint128_t rep = F80ToRep128(result);
// F80 occupies the lower 80 bits of __uint128_t.
uint64_t hi = (rep >> 64) & ((1UL << (80 - 64)) - 1);
uint64_t lo = rep;
return !(hi == expectedHi && lo == expectedLo);
uqwords rep = F80ToRep80(result);
// F80 high occupies the lower 16 bits of high.
assert((uint64_t)(uint16_t)rep.high.all == rep.high.all);
return !(rep.high.all == expectedHi && rep.low.all == expectedLo);
}

static inline long double makeQNaN80(void) {
return F80FromRep128(0x7fffUL, 0xc000000000000000UL);
static inline xf_float makeQNaN80(void) {
return F80FromRep80(0x7fffu, 0xc000000000000000UL);
}

static inline long double makeNaN80(uint64_t rand) {
return F80FromRep128(0x7fffUL,
0x8000000000000000 | (rand & 0x3fffffffffffffff));
static inline xf_float makeNaN80(uint64_t rand) {
return F80FromRep80(0x7fffu,
0x8000000000000000 | (rand & 0x3fffffffffffffff));
}

static inline long double makeInf80(void) {
return F80FromRep128(0x7fffUL, 0x8000000000000000UL);
static inline xf_float makeInf80(void) {
return F80FromRep80(0x7fffu, 0x8000000000000000UL);
}

static inline long double makeNegativeInf80(void) {
return F80FromRep128(0xffffUL, 0x8000000000000000UL);
static inline xf_float makeNegativeInf80(void) {
return F80FromRep80(0xffffu, 0x8000000000000000UL);
}
#endif

Expand Down
Loading