Skip to content

Commit 91bd698

Browse files
committedMar 11, 2015
Refactor float to integer conversion to share the same code.
80bit Intel/PPC long double is excluded due to lacking support for the abstraction. Consistently provide saturation logic. Extend to long double on 128bit IEEE extended platforms. Initial patch with test cases from GuanHong Liu. Reviewed by Steve Canon. Differential Revision: http://reviews.llvm.org/D2804 llvm-svn: 231965
1 parent d6c9bd5 commit 91bd698

27 files changed

+458
-376
lines changed
 

‎compiler-rt/lib/builtins/fixdfdi.c

+9-32
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,17 @@
66
* Source Licenses. See LICENSE.TXT for details.
77
*
88
* ===----------------------------------------------------------------------===
9-
*
10-
* This file implements __fixdfdi for the compiler_rt library.
11-
*
12-
* ===----------------------------------------------------------------------===
139
*/
1410

15-
#include "int_lib.h"
16-
17-
/* Returns: convert a to a signed long long, rounding toward zero. */
18-
19-
/* Assumption: double is a IEEE 64 bit floating point type
20-
* su_int is a 32 bit integral type
21-
* value in double is representable in di_int (no range checking performed)
22-
*/
23-
24-
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
25-
11+
#define DOUBLE_PRECISION
12+
#include "fp_lib.h"
2613
ARM_EABI_FNALIAS(d2lz, fixdfdi)
2714

15+
typedef di_int fixint_t;
16+
typedef du_int fixuint_t;
17+
#include "fp_fixint_impl.inc"
18+
2819
COMPILER_RT_ABI di_int
29-
__fixdfdi(double a)
30-
{
31-
double_bits fb;
32-
fb.f = a;
33-
int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
34-
if (e < 0)
35-
return 0;
36-
di_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31;
37-
dwords r;
38-
r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
39-
r.s.low = fb.u.s.low;
40-
if (e > 52)
41-
r.all <<= (e - 52);
42-
else
43-
r.all >>= (52 - e);
44-
return (r.all ^ s) - s;
45-
}
20+
__fixdfdi(fp_t a) {
21+
return __fixint(a);
22+
}

‎compiler-rt/lib/builtins/fixdfsi.c

+14-42
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,22 @@
1-
//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
2-
//
3-
// The LLVM Compiler Infrastructure
4-
//
5-
// This file is dual licensed under the MIT and the University of Illinois Open
6-
// Source Licenses. See LICENSE.TXT for details.
7-
//
8-
//===----------------------------------------------------------------------===//
9-
//
10-
// This file implements double-precision to integer conversion for the
11-
// compiler-rt library. No range checking is performed; the behavior of this
12-
// conversion is undefined for out of range values in the C standard.
13-
//
14-
//===----------------------------------------------------------------------===//
1+
/* ===-- fixdfsi.c - Implement __fixdfsi -----------------------------------===
2+
*
3+
* The LLVM Compiler Infrastructure
4+
*
5+
* This file is dual licensed under the MIT and the University of Illinois Open
6+
* Source Licenses. See LICENSE.TXT for details.
7+
*
8+
* ===----------------------------------------------------------------------===
9+
*/
1510

1611
#define DOUBLE_PRECISION
1712
#include "fp_lib.h"
18-
19-
#include "int_lib.h"
13+
typedef si_int fixint_t;
14+
typedef su_int fixuint_t;
15+
#include "fp_fixint_impl.inc"
2016

2117
ARM_EABI_FNALIAS(d2iz, fixdfsi)
2218

23-
COMPILER_RT_ABI int
19+
COMPILER_RT_ABI si_int
2420
__fixdfsi(fp_t a) {
25-
26-
// Break a into sign, exponent, significand
27-
const rep_t aRep = toRep(a);
28-
const rep_t aAbs = aRep & absMask;
29-
const int sign = aRep & signBit ? -1 : 1;
30-
const int exponent = (aAbs >> significandBits) - exponentBias;
31-
const rep_t significand = (aAbs & significandMask) | implicitBit;
32-
33-
// If 0 < exponent < significandBits, right shift to get the result.
34-
if ((unsigned int)exponent < significandBits) {
35-
return sign * (significand >> (significandBits - exponent));
36-
}
37-
38-
// If exponent is negative, the result is zero.
39-
else if (exponent < 0) {
40-
return 0;
41-
}
42-
43-
// If significandBits < exponent, left shift to get the result. This shift
44-
// may end up being larger than the type width, which incurs undefined
45-
// behavior, but the conversion itself is undefined in that case, so
46-
// whatever the compiler decides to do is fine.
47-
else {
48-
return sign * (significand << (exponent - significandBits));
49-
}
21+
return __fixint(a);
5022
}

‎compiler-rt/lib/builtins/fixdfti.c

+7-26
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,21 @@
66
* Source Licenses. See LICENSE.TXT for details.
77
*
88
* ===----------------------------------------------------------------------===
9-
*
10-
* This file implements __fixdfti for the compiler_rt library.
11-
*
12-
* ===----------------------------------------------------------------------===
139
*/
1410

1511
#include "int_lib.h"
1612

1713
#ifdef CRT_HAS_128BIT
14+
#define DOUBLE_PRECISION
15+
#include "fp_lib.h"
1816

19-
/* Returns: convert a to a signed long long, rounding toward zero. */
20-
21-
/* Assumption: double is a IEEE 64 bit floating point type
22-
* su_int is a 32 bit integral type
23-
* value in double is representable in ti_int (no range checking performed)
24-
*/
25-
26-
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
17+
typedef ti_int fixint_t;
18+
typedef tu_int fixuint_t;
19+
#include "fp_fixint_impl.inc"
2720

2821
COMPILER_RT_ABI ti_int
29-
__fixdfti(double a)
30-
{
31-
double_bits fb;
32-
fb.f = a;
33-
int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
34-
if (e < 0)
35-
return 0;
36-
ti_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31;
37-
ti_int r = 0x0010000000000000uLL | (0x000FFFFFFFFFFFFFuLL & fb.u.all);
38-
if (e > 52)
39-
r <<= (e - 52);
40-
else
41-
r >>= (52 - e);
42-
return (r ^ s) - s;
22+
__fixdfti(fp_t a) {
23+
return __fixint(a);
4324
}
4425

4526
#endif /* CRT_HAS_128BIT */

‎compiler-rt/lib/builtins/fixsfdi.c

+9-29
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,23 @@
11
/* ===-- fixsfdi.c - Implement __fixsfdi -----------------------------------===
22
*
3-
* The LLVM Compiler Infrastructure
3+
* The LLVM Compiler Infrastructure
44
*
55
* This file is dual licensed under the MIT and the University of Illinois Open
66
* Source Licenses. See LICENSE.TXT for details.
77
*
88
* ===----------------------------------------------------------------------===
9-
*
10-
* This file implements __fixsfdi for the compiler_rt library.
11-
*
12-
* ===----------------------------------------------------------------------===
13-
*/
14-
15-
#include "int_lib.h"
16-
17-
/* Returns: convert a to a signed long long, rounding toward zero. */
18-
19-
/* Assumption: float is a IEEE 32 bit floating point type
20-
* su_int is a 32 bit integral type
21-
* value in float is representable in di_int (no range checking performed)
229
*/
2310

24-
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
11+
#define SINGLE_PRECISION
12+
#include "fp_lib.h"
2513

2614
ARM_EABI_FNALIAS(f2lz, fixsfdi)
2715

16+
typedef di_int fixint_t;
17+
typedef du_int fixuint_t;
18+
#include "fp_fixint_impl.inc"
19+
2820
COMPILER_RT_ABI di_int
29-
__fixsfdi(float a)
30-
{
31-
float_bits fb;
32-
fb.f = a;
33-
int e = ((fb.u & 0x7F800000) >> 23) - 127;
34-
if (e < 0)
35-
return 0;
36-
di_int s = (si_int)(fb.u & 0x80000000) >> 31;
37-
di_int r = (fb.u & 0x007FFFFF) | 0x00800000;
38-
if (e > 23)
39-
r <<= (e - 23);
40-
else
41-
r >>= (23 - e);
42-
return (r ^ s) - s;
21+
__fixsfdi(fp_t a) {
22+
return __fixint(a);
4323
}

‎compiler-rt/lib/builtins/fixsfsi.c

+14-39
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,22 @@
1-
//===-- lib/fixsfsi.c - Single-precision -> integer conversion ----*- C -*-===//
2-
//
3-
// The LLVM Compiler Infrastructure
4-
//
5-
// This file is dual licensed under the MIT and the University of Illinois Open
6-
// Source Licenses. See LICENSE.TXT for details.
7-
//
8-
//===----------------------------------------------------------------------===//
9-
//
10-
// This file implements single-precision to integer conversion for the
11-
// compiler-rt library. No range checking is performed; the behavior of this
12-
// conversion is undefined for out of range values in the C standard.
13-
//
14-
//===----------------------------------------------------------------------===//
1+
/* ===-- fixsfsi.c - Implement __fixsfsi -----------------------------------===
2+
*
3+
* The LLVM Compiler Infrastructure
4+
*
5+
* This file is dual licensed under the MIT and the University of Illinois Open
6+
* Source Licenses. See LICENSE.TXT for details.
7+
*
8+
* ===----------------------------------------------------------------------===
9+
*/
1510

1611
#define SINGLE_PRECISION
1712
#include "fp_lib.h"
13+
typedef si_int fixint_t;
14+
typedef su_int fixuint_t;
15+
#include "fp_fixint_impl.inc"
1816

1917
ARM_EABI_FNALIAS(f2iz, fixsfsi)
2018

21-
COMPILER_RT_ABI int
19+
COMPILER_RT_ABI si_int
2220
__fixsfsi(fp_t a) {
23-
// Break a into sign, exponent, significand
24-
const rep_t aRep = toRep(a);
25-
const rep_t aAbs = aRep & absMask;
26-
const int sign = aRep & signBit ? -1 : 1;
27-
const int exponent = (aAbs >> significandBits) - exponentBias;
28-
const rep_t significand = (aAbs & significandMask) | implicitBit;
29-
30-
// If 0 < exponent < significandBits, right shift to get the result.
31-
if ((unsigned int)exponent < significandBits) {
32-
return sign * (significand >> (significandBits - exponent));
33-
}
34-
35-
// If exponent is negative, the result is zero.
36-
else if (exponent < 0) {
37-
return 0;
38-
}
39-
40-
// If significandBits < exponent, left shift to get the result. This shift
41-
// may end up being larger than the type width, which incurs undefined
42-
// behavior, but the conversion itself is undefined in that case, so
43-
// whatever the compiler decides to do is fine.
44-
else {
45-
return sign * (significand << (exponent - significandBits));
46-
}
21+
return __fixint(a);
4722
}

‎compiler-rt/lib/builtins/fixsfti.c

+7-26
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,21 @@
66
* Source Licenses. See LICENSE.TXT for details.
77
*
88
* ===----------------------------------------------------------------------===
9-
*
10-
* This file implements __fixsfti for the compiler_rt library.
11-
*
12-
* ===----------------------------------------------------------------------===
139
*/
1410

1511
#include "int_lib.h"
1612

1713
#ifdef CRT_HAS_128BIT
14+
#define SINGLE_PRECISION
15+
#include "fp_lib.h"
1816

19-
/* Returns: convert a to a signed long long, rounding toward zero. */
20-
21-
/* Assumption: float is a IEEE 32 bit floating point type
22-
* su_int is a 32 bit integral type
23-
* value in float is representable in ti_int (no range checking performed)
24-
*/
25-
26-
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
17+
typedef ti_int fixint_t;
18+
typedef tu_int fixuint_t;
19+
#include "fp_fixint_impl.inc"
2720

2821
COMPILER_RT_ABI ti_int
29-
__fixsfti(float a)
30-
{
31-
float_bits fb;
32-
fb.f = a;
33-
int e = ((fb.u & 0x7F800000) >> 23) - 127;
34-
if (e < 0)
35-
return 0;
36-
ti_int s = (si_int)(fb.u & 0x80000000) >> 31;
37-
ti_int r = (fb.u & 0x007FFFFF) | 0x00800000;
38-
if (e > 23)
39-
r <<= (e - 23);
40-
else
41-
r >>= (23 - e);
42-
return (r ^ s) - s;
22+
__fixsfti(fp_t a) {
23+
return __fixint(a);
4324
}
4425

4526
#endif /* CRT_HAS_128BIT */

‎compiler-rt/lib/builtins/fixtfdi.c

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* ===-- fixtfdi.c - Implement __fixtfdi -----------------------------------===
2+
*
3+
* The LLVM Compiler Infrastructure
4+
*
5+
* This file is dual licensed under the MIT and the University of Illinois Open
6+
* Source Licenses. See LICENSE.TXT for details.
7+
*
8+
* ===----------------------------------------------------------------------===
9+
*/
10+
11+
#define QUAD_PRECISION
12+
#include "fp_lib.h"
13+
14+
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
15+
typedef di_int fixint_t;
16+
typedef du_int fixuint_t;
17+
#include "fp_fixuint_impl.inc"
18+
19+
COMPILER_RT_ABI di_int
20+
__fixtfdi(fp_t a) {
21+
return __fixint(a);
22+
}
23+
#endif

‎compiler-rt/lib/builtins/fixtfsi.c

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* ===-- fixtfsi.c - Implement __fixtfsi -----------------------------------===
2+
*
3+
* The LLVM Compiler Infrastructure
4+
*
5+
* This file is dual licensed under the MIT and the University of Illinois Open
6+
* Source Licenses. See LICENSE.TXT for details.
7+
*
8+
* ===----------------------------------------------------------------------===
9+
*/
10+
11+
#define QUAD_PRECISION
12+
#include "fp_lib.h"
13+
14+
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
15+
typedef si_int fixint_t;
16+
typedef su_int fixuint_t;
17+
#include "fp_fixuint_impl.inc"
18+
19+
COMPILER_RT_ABI si_int
20+
__fixtfsi(fp_t a) {
21+
return __fixint(a);
22+
}
23+
#endif

‎compiler-rt/lib/builtins/fixtfti.c

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* ===-- fixtfti.c - Implement __fixtfti -----------------------------------===
2+
*
3+
* The LLVM Compiler Infrastructure
4+
*
5+
* This file is dual licensed under the MIT and the University of Illinois Open
6+
* Source Licenses. See LICENSE.TXT for details.
7+
*
8+
* ===----------------------------------------------------------------------===
9+
*/
10+
11+
#define QUAD_PRECISION
12+
#include "fp_lib.h"
13+
14+
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
15+
typedef ti_int fixint_t;
16+
typedef tu_int fixuint_t;
17+
#include "fp_fixuint_impl.inc"
18+
19+
COMPILER_RT_ABI ti_int
20+
__fixtfti(fp_t a) {
21+
return __fixint(a);
22+
}
23+
#endif

‎compiler-rt/lib/builtins/fixunsdfdi.c

+6-32
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,16 @@
66
* Source Licenses. See LICENSE.TXT for details.
77
*
88
* ===----------------------------------------------------------------------===
9-
*
10-
* This file implements __fixunsdfdi for the compiler_rt library.
11-
*
12-
* ===----------------------------------------------------------------------===
13-
*/
14-
15-
#include "int_lib.h"
16-
17-
/* Returns: convert a to a unsigned long long, rounding toward zero.
18-
* Negative values all become zero.
19-
*/
20-
21-
/* Assumption: double is a IEEE 64 bit floating point type
22-
* du_int is a 64 bit integral type
23-
* value in double is representable in du_int or is negative
24-
* (no range checking performed)
259
*/
2610

27-
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
11+
#define DOUBLE_PRECISION
12+
#include "fp_lib.h"
13+
typedef du_int fixuint_t;
14+
#include "fp_fixuint_impl.inc"
2815

2916
ARM_EABI_FNALIAS(d2ulz, fixunsdfdi)
3017

3118
COMPILER_RT_ABI du_int
32-
__fixunsdfdi(double a)
33-
{
34-
double_bits fb;
35-
fb.f = a;
36-
int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
37-
if (e < 0 || (fb.u.s.high & 0x80000000))
38-
return 0;
39-
udwords r;
40-
r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
41-
r.s.low = fb.u.s.low;
42-
if (e > 52)
43-
r.all <<= (e - 52);
44-
else
45-
r.all >>= (52 - e);
46-
return r.all;
19+
__fixunsdfdi(fp_t a) {
20+
return __fixuint(a);
4721
}

‎compiler-rt/lib/builtins/fixunsdfsi.c

+6-29
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,16 @@
66
* Source Licenses. See LICENSE.TXT for details.
77
*
88
* ===----------------------------------------------------------------------===
9-
*
10-
* This file implements __fixunsdfsi for the compiler_rt library.
11-
*
12-
* ===----------------------------------------------------------------------===
13-
*/
14-
15-
#include "int_lib.h"
16-
17-
/* Returns: convert a to a unsigned int, rounding toward zero.
18-
* Negative values all become zero.
19-
*/
20-
21-
/* Assumption: double is a IEEE 64 bit floating point type
22-
* su_int is a 32 bit integral type
23-
* value in double is representable in su_int or is negative
24-
* (no range checking performed)
259
*/
2610

27-
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
11+
#define DOUBLE_PRECISION
12+
#include "fp_lib.h"
13+
typedef su_int fixuint_t;
14+
#include "fp_fixuint_impl.inc"
2815

2916
ARM_EABI_FNALIAS(d2uiz, fixunsdfsi)
3017

3118
COMPILER_RT_ABI su_int
32-
__fixunsdfsi(double a)
33-
{
34-
double_bits fb;
35-
fb.f = a;
36-
int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
37-
if (e < 0 || (fb.u.s.high & 0x80000000))
38-
return 0;
39-
return (
40-
0x80000000u |
41-
((fb.u.s.high & 0x000FFFFF) << 11) |
42-
(fb.u.s.low >> 21)
43-
) >> (31 - e);
19+
__fixunsdfsi(fp_t a) {
20+
return __fixuint(a);
4421
}

‎compiler-rt/lib/builtins/fixunsdfti.c

+6-30
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,18 @@
66
* Source Licenses. See LICENSE.TXT for details.
77
*
88
* ===----------------------------------------------------------------------===
9-
*
10-
* This file implements __fixunsdfti for the compiler_rt library.
11-
*
12-
* ===----------------------------------------------------------------------===
139
*/
1410

1511
#include "int_lib.h"
1612

1713
#ifdef CRT_HAS_128BIT
18-
19-
/* Returns: convert a to a unsigned long long, rounding toward zero.
20-
* Negative values all become zero.
21-
*/
22-
23-
/* Assumption: double is a IEEE 64 bit floating point type
24-
* tu_int is a 64 bit integral type
25-
* value in double is representable in tu_int or is negative
26-
* (no range checking performed)
27-
*/
28-
29-
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
14+
#define DOUBLE_PRECISION
15+
#include "fp_lib.h"
16+
typedef tu_int fixuint_t;
17+
#include "fp_fixuint_impl.inc"
3018

3119
COMPILER_RT_ABI tu_int
32-
__fixunsdfti(double a)
33-
{
34-
double_bits fb;
35-
fb.f = a;
36-
int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
37-
if (e < 0 || (fb.u.s.high & 0x80000000))
38-
return 0;
39-
tu_int r = 0x0010000000000000uLL | (fb.u.all & 0x000FFFFFFFFFFFFFuLL);
40-
if (e > 52)
41-
r <<= (e - 52);
42-
else
43-
r >>= (52 - e);
44-
return r;
20+
__fixunsdftti(fp_t a) {
21+
return __fixuint(a);
4522
}
46-
4723
#endif /* CRT_HAS_128BIT */

‎compiler-rt/lib/builtins/fixunssfdi.c

+6-29
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,16 @@
66
* Source Licenses. See LICENSE.TXT for details.
77
*
88
* ===----------------------------------------------------------------------===
9-
*
10-
* This file implements __fixunssfdi for the compiler_rt library.
11-
*
12-
* ===----------------------------------------------------------------------===
13-
*/
14-
15-
#include "int_lib.h"
16-
/* Returns: convert a to a unsigned long long, rounding toward zero.
17-
* Negative values all become zero.
18-
*/
19-
20-
/* Assumption: float is a IEEE 32 bit floating point type
21-
* du_int is a 64 bit integral type
22-
* value in float is representable in du_int or is negative
23-
* (no range checking performed)
249
*/
2510

26-
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
11+
#define SINGLE_PRECISION
12+
#include "fp_lib.h"
13+
typedef du_int fixuint_t;
14+
#include "fp_fixuint_impl.inc"
2715

2816
ARM_EABI_FNALIAS(f2ulz, fixunssfdi)
2917

3018
COMPILER_RT_ABI du_int
31-
__fixunssfdi(float a)
32-
{
33-
float_bits fb;
34-
fb.f = a;
35-
int e = ((fb.u & 0x7F800000) >> 23) - 127;
36-
if (e < 0 || (fb.u & 0x80000000))
37-
return 0;
38-
du_int r = (fb.u & 0x007FFFFF) | 0x00800000;
39-
if (e > 23)
40-
r <<= (e - 23);
41-
else
42-
r >>= (23 - e);
43-
return r;
19+
__fixunssfdi(fp_t a) {
20+
return __fixuint(a);
4421
}

‎compiler-rt/lib/builtins/fixunssfsi.c

+6-26
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,14 @@
1212
* ===----------------------------------------------------------------------===
1313
*/
1414

15-
#include "int_lib.h"
16-
17-
/* Returns: convert a to a unsigned int, rounding toward zero.
18-
* Negative values all become zero.
19-
*/
20-
21-
/* Assumption: float is a IEEE 32 bit floating point type
22-
* su_int is a 32 bit integral type
23-
* value in float is representable in su_int or is negative
24-
* (no range checking performed)
25-
*/
26-
27-
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
15+
#define SINGLE_PRECISION
16+
#include "fp_lib.h"
17+
typedef su_int fixuint_t;
18+
#include "fp_fixuint_impl.inc"
2819

2920
ARM_EABI_FNALIAS(f2uiz, fixunssfsi)
3021

3122
COMPILER_RT_ABI su_int
32-
__fixunssfsi(float a)
33-
{
34-
float_bits fb;
35-
fb.f = a;
36-
int e = ((fb.u & 0x7F800000) >> 23) - 127;
37-
if (e < 0 || (fb.u & 0x80000000))
38-
return 0;
39-
su_int r = (fb.u & 0x007FFFFF) | 0x00800000;
40-
if (e > 23)
41-
r <<= (e - 23);
42-
else
43-
r >>= (23 - e);
44-
return r;
23+
__fixunssfsi(fp_t a) {
24+
return __fixuint(a);
4525
}

‎compiler-rt/lib/builtins/fixunssfti.c

+6-30
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,12 @@
1212
* ===----------------------------------------------------------------------===
1313
*/
1414

15-
#include "int_lib.h"
16-
17-
#ifdef CRT_HAS_128BIT
18-
19-
/* Returns: convert a to a unsigned long long, rounding toward zero.
20-
* Negative values all become zero.
21-
*/
22-
23-
/* Assumption: float is a IEEE 32 bit floating point type
24-
* tu_int is a 64 bit integral type
25-
* value in float is representable in tu_int or is negative
26-
* (no range checking performed)
27-
*/
28-
29-
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
15+
#if defined(CRT_HAS_128BIT)
16+
typedef tu_int fixuint_t;
17+
#include "fp_fixuint_impl.inc"
3018

3119
COMPILER_RT_ABI tu_int
32-
__fixunssfti(float a)
33-
{
34-
float_bits fb;
35-
fb.f = a;
36-
int e = ((fb.u & 0x7F800000) >> 23) - 127;
37-
if (e < 0 || (fb.u & 0x80000000))
38-
return 0;
39-
tu_int r = (fb.u & 0x007FFFFF) | 0x00800000;
40-
if (e > 23)
41-
r <<= (e - 23);
42-
else
43-
r >>= (23 - e);
44-
return r;
20+
__fixunssfti(fp_t a) {
21+
return __fixuint(a);
4522
}
46-
47-
#endif /* CRT_HAS_128BIT */
23+
#endif

‎compiler-rt/lib/builtins/fixunstfdi.c

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* ===-- fixunstfdi.c - Implement __fixunstfdi -----------------------------===
2+
*
3+
* The LLVM Compiler Infrastructure
4+
*
5+
* This file is dual licensed under the MIT and the University of Illinois Open
6+
* Source Licenses. See LICENSE.TXT for details.
7+
*
8+
* ===----------------------------------------------------------------------===
9+
*/
10+
11+
#define QUAD_PRECISION
12+
#include "fp_lib.h"
13+
14+
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
15+
typedef du_int fixuint_t;
16+
#include "fp_fixuint_impl.inc"
17+
18+
COMPILER_RT_ABI du_int
19+
__fixunstfdi(fp_t a) {
20+
return __fixuint(a);
21+
}
22+
#endif

‎compiler-rt/lib/builtins/fixunstfsi.c

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* ===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------===
2+
*
3+
* The LLVM Compiler Infrastructure
4+
*
5+
* This file is dual licensed under the MIT and the University of Illinois Open
6+
* Source Licenses. See LICENSE.TXT for details.
7+
*
8+
* ===----------------------------------------------------------------------===
9+
*/
10+
11+
#define QUAD_PRECISION
12+
#include "fp_lib.h"
13+
14+
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
15+
typedef su_int fixuint_t;
16+
#include "fp_fixuint_impl.inc"
17+
18+
COMPILER_RT_ABI su_int
19+
__fixunstfsi(fp_t a) {
20+
return __fixuint(a);
21+
}
22+
#endif

‎compiler-rt/lib/builtins/fixunstfti.c

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* ===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------===
2+
*
3+
* The LLVM Compiler Infrastructure
4+
*
5+
* This file is dual licensed under the MIT and the University of Illinois Open
6+
* Source Licenses. See LICENSE.TXT for details.
7+
*
8+
* ===----------------------------------------------------------------------===
9+
*/
10+
11+
#define QUAD_PRECISION
12+
#include "fp_lib.h"
13+
14+
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
15+
typedef tu_int fixuint_t;
16+
#include "fp_fixuint_impl.inc"
17+
18+
COMPILER_RT_ABI tu_int
19+
__fixunstfti(fp_t a) {
20+
return __fixuint(a);
21+
}
22+
#endif

‎compiler-rt/lib/builtins/fixunsxfdi.c

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ __fixunsxfdi(long double a)
3838
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
3939
if (e < 0 || (fb.u.high.s.low & 0x00008000))
4040
return 0;
41+
if ((unsigned)e > sizeof(du_int) * CHAR_BIT)
42+
return ~(du_int)0;
4143
return fb.u.low.all >> (63 - e);
4244
}
4345

‎compiler-rt/lib/builtins/fixunsxfsi.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
2424
* su_int is a 32 bit integral type
2525
* value in long double is representable in su_int or is negative
26-
* (no range checking performed)
2726
*/
2827

2928
/* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
@@ -38,6 +37,8 @@ __fixunsxfsi(long double a)
3837
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
3938
if (e < 0 || (fb.u.high.s.low & 0x00008000))
4039
return 0;
40+
if ((unsigned)e > sizeof(su_int) * CHAR_BIT)
41+
return ~(su_int)0;
4142
return fb.u.low.s.high >> (31 - e);
4243
}
4344

‎compiler-rt/lib/builtins/fixunsxfti.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@
2121
*/
2222

2323
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
24-
* tu_int is a 64 bit integral type
24+
* tu_int is a 128 bit integral type
2525
* value in long double is representable in tu_int or is negative
26-
* (no range checking performed)
2726
*/
2827

2928
/* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
@@ -38,6 +37,8 @@ __fixunsxfti(long double a)
3837
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
3938
if (e < 0 || (fb.u.high.s.low & 0x00008000))
4039
return 0;
40+
if ((unsigned)e > sizeof(tu_int) * CHAR_BIT)
41+
return ~(tu_int)0;
4142
tu_int r = fb.u.low.all;
4243
if (e > 63)
4344
r <<= (e - 63);

‎compiler-rt/lib/builtins/fixxfdi.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
/* Returns: convert a to a signed long long, rounding toward zero. */
2020

2121
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
22-
* su_int is a 32 bit integral type
22+
* di_int is a 64 bit integral type
2323
* value in long double is representable in di_int (no range checking performed)
2424
*/
2525

@@ -30,11 +30,15 @@
3030
COMPILER_RT_ABI di_int
3131
__fixxfdi(long double a)
3232
{
33+
const di_int di_max = (di_int)((~(du_int)0) / 2);
34+
const di_int di_min = -di_max - 1;
3335
long_double_bits fb;
3436
fb.f = a;
3537
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
3638
if (e < 0)
3739
return 0;
40+
if ((unsigned)e >= sizeof(di_int) * CHAR_BIT)
41+
return a > 0 ? di_max : di_min;
3842
di_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15);
3943
di_int r = fb.u.low.all;
4044
r = (du_int)r >> (63 - e);

‎compiler-rt/lib/builtins/fixxfti.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
/* Returns: convert a to a signed long long, rounding toward zero. */
2020

2121
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
22-
* su_int is a 32 bit integral type
23-
* value in long double is representable in ti_int (no range checking performed)
22+
* ti_int is a 128 bit integral type
23+
* value in long double is representable in ti_int
2424
*/
2525

2626
/* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
@@ -30,13 +30,17 @@
3030
COMPILER_RT_ABI ti_int
3131
__fixxfti(long double a)
3232
{
33+
const ti_int ti_max = (ti_int)((~(tu_int)0) / 2);
34+
const ti_int ti_min = -ti_max - 1;
3335
long_double_bits fb;
3436
fb.f = a;
3537
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
3638
if (e < 0)
3739
return 0;
3840
ti_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15);
3941
ti_int r = fb.u.low.all;
42+
if ((unsigned)e >= sizeof(ti_int) * CHAR_BIT)
43+
return a > 0 ? ti_max : ti_min;
4044
if (e > 63)
4145
r <<= (e - 63);
4246
else
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file implements float to integer conversion for the
11+
// compiler-rt library.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "fp_lib.h"
16+
17+
static inline fixint_t __fixint(fp_t a) {
18+
const fixint_t fixint_max = (fixint_t)((~(fixuint_t)0) / 2);
19+
const fixint_t fixint_min = -fixint_max - 1;
20+
// Break a into sign, exponent, significand
21+
const rep_t aRep = toRep(a);
22+
const rep_t aAbs = aRep & absMask;
23+
const fixint_t sign = aRep & signBit ? -1 : 1;
24+
const int exponent = (aAbs >> significandBits) - exponentBias;
25+
const rep_t significand = (aAbs & significandMask) | implicitBit;
26+
27+
// If exponent is negative, the result is zero.
28+
if (exponent < 0)
29+
return 0;
30+
31+
// If the value is too large for the integer type, saturate.
32+
if ((unsigned)exponent >= sizeof(fixint_t) * CHAR_BIT)
33+
return sign == 1 ? fixint_max : fixint_min;
34+
35+
// If 0 <= exponent < significandBits, right shift to get the result.
36+
// Otherwise, shift left.
37+
if (exponent < significandBits)
38+
return sign * (significand >> (significandBits - exponent));
39+
else
40+
return sign * ((fixint_t)significand << (exponent - significandBits));
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file implements float to unsigned integer conversion for the
11+
// compiler-rt library.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "fp_lib.h"
16+
17+
static inline fixuint_t __fixuint(fp_t a) {
18+
// Break a into sign, exponent, significand
19+
const rep_t aRep = toRep(a);
20+
const rep_t aAbs = aRep & absMask;
21+
const int sign = aRep & signBit ? -1 : 1;
22+
const int exponent = (aAbs >> significandBits) - exponentBias;
23+
const rep_t significand = (aAbs & significandMask) | implicitBit;
24+
25+
// If either the value or the exponent is negative, the result is zero.
26+
if (sign == -1 || exponent < 0)
27+
return 0;
28+
29+
// If the value is too large for the integer type, saturate.
30+
if ((unsigned)exponent > sizeof(fixuint_t) * CHAR_BIT)
31+
return ~(fixuint_t)0;
32+
33+
// If 0 <= exponent < significandBits, right shift to get the result.
34+
// Otherwise, shift left.
35+
if (exponent < significandBits)
36+
return significand >> (significandBits - exponent);
37+
else
38+
return (fixuint_t)significand << (exponent - significandBits);
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//===--------------- fixtfsi_test.c - Test __fixtfsi ----------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file tests __fixtfsi for the compiler_rt library.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include <stdio.h>
15+
16+
#if __LDBL_MANT_DIG__ == 113
17+
18+
#include "fp_test.h"
19+
20+
int __fixtfsi(long double a);
21+
22+
int test__fixtfsi(long double a, int expected)
23+
{
24+
int x = __fixtfsi(a);
25+
int ret = (x != expected);
26+
27+
if (ret){
28+
printf("error in test__fixtfsi(%.20Lf) = %d, "
29+
"expected %d\n", a, x, expected);
30+
}
31+
return ret;
32+
}
33+
34+
char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
35+
36+
#endif
37+
38+
int main()
39+
{
40+
#if __LDBL_MANT_DIG__ == 113
41+
if (test__fixtfsi(makeInf128(), 0x7fffffff))
42+
return 1;
43+
if (test__fixtfsi(0, 0x0))
44+
return 1;
45+
if (test__fixtfsi(0x1.23456789abcdefp+5, 0x24))
46+
return 1;
47+
if (test__fixtfsi(0x1.23456789abcdefp-3, 0x0))
48+
return 1;
49+
if (test__fixtfsi(0x1.23456789abcdefp+20, 0x123456))
50+
return 1;
51+
if (test__fixtfsi(0x1.23456789abcdefp+40, 0x7fffffff))
52+
return 1;
53+
if (test__fixtfsi(0x1.23456789abcdefp+256, 0x7fffffff))
54+
return 1;
55+
if (test__fixtfsi(-0x1.23456789abcdefp+20, 0xffedcbaa))
56+
return 1;
57+
if (test__fixtfsi(-0x1.23456789abcdefp+40, 0x80000001))
58+
return 1;
59+
60+
#else
61+
printf("skipped\n");
62+
63+
#endif
64+
return 0;
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===--------------- fixunstfsi_test.c - Test __fixunstfsi ----------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file tests __fixunstfsi for the compiler_rt library.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include <stdio.h>
15+
16+
#if __LDBL_MANT_DIG__ == 113
17+
18+
#include "fp_test.h"
19+
20+
unsigned int __fixunstfsi(long double a);
21+
22+
int test__fixunstfsi(long double a, unsigned int expected)
23+
{
24+
unsigned int x = __fixunstfsi(a);
25+
int ret = (x != expected);
26+
27+
if (ret)
28+
{
29+
printf("error in test__fixunstfsi(%.20Lf) = %u, "
30+
"expected %u\n", a, x, expected);
31+
}
32+
return ret;
33+
}
34+
35+
char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
36+
37+
#endif
38+
39+
int main()
40+
{
41+
#if __LDBL_MANT_DIG__ == 113
42+
if (test__fixunstfsi(makeInf128(), UINT32_C(0xffffffff)))
43+
return 1;
44+
if (test__fixunstfsi(0, UINT32_C(0x0)))
45+
return 1;
46+
if (test__fixunstfsi(0x1.23456789abcdefp+5, UINT32_C(0x24)))
47+
return 1;
48+
if (test__fixunstfsi(0x1.23456789abcdefp-3, UINT32_C(0x0)))
49+
return 1;
50+
if (test__fixunstfsi(0x1.23456789abcdefp+20, UINT32_C(0x123456)))
51+
return 1;
52+
if (test__fixunstfsi(0x1.23456789abcdefp+40, UINT32_C(0xffffffff)))
53+
return 1;
54+
if (test__fixunstfsi(0x1.23456789abcdefp+256, UINT32_C(0xffffffff)))
55+
return 1;
56+
if (test__fixunstfsi(-0x1.23456789abcdefp+3, UINT32_C(0x0)))
57+
return 1;
58+
59+
#else
60+
printf("skipped\n");
61+
62+
#endif
63+
return 0;
64+
}

0 commit comments

Comments
 (0)
Please sign in to comment.