Move libclang into libc.
Catch all warnings.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -26,3 +26,4 @@
|
|||||||
*.img
|
*.img
|
||||||
|
|
||||||
Makefile.user
|
Makefile.user
|
||||||
|
TODO
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ include $(TOPSRC)/target.mk
|
|||||||
# Programs that live in subdirectories, and have makefiles of their own.
|
# Programs that live in subdirectories, and have makefiles of their own.
|
||||||
#
|
#
|
||||||
SUBDIR = startup-$(MACHINE) libc libm libutil libtermlib libcurses \
|
SUBDIR = startup-$(MACHINE) libc libm libutil libtermlib libcurses \
|
||||||
libvmf libwiznet libreadline libgpanel share cmd games man \
|
libvmf libwiznet libreadline libgpanel share cmd games man
|
||||||
libclang
|
|
||||||
|
|
||||||
all: $(SUBDIR)
|
all: $(SUBDIR)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ CFLAGS += -Werror -Os
|
|||||||
|
|
||||||
YACC = bison -y
|
YACC = bison -y
|
||||||
YFLAGS = -d
|
YFLAGS = -d
|
||||||
LIBS = -lm -lc -lclang
|
LIBS = -lm -lc
|
||||||
FILES = awk.lx.o b.o main.o tran.o lib.o run.o parse.o proctab.o freeze.o
|
FILES = awk.lx.o b.o main.o tran.o lib.o run.o parse.o proctab.o freeze.o
|
||||||
SOURCE = awk.def.h awk.g.y awk.lx.l b.c lib.c main.c parse.c \
|
SOURCE = awk.def.h awk.g.y awk.lx.l b.c lib.c main.c parse.c \
|
||||||
proc.c freeze.c run.c tran.c
|
proc.c freeze.c run.c tran.c
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ struct xx
|
|||||||
{ INDIRECT, "indirect", "$("},
|
{ INDIRECT, "indirect", "$("},
|
||||||
{ SUBSTR, "substr", "substr"},
|
{ SUBSTR, "substr", "substr"},
|
||||||
{ INDEX, "sindex", "sindex"},
|
{ INDEX, "sindex", "sindex"},
|
||||||
{ SPRINTF, "asprintf", "sprintf "},
|
{ SPRINTF, "awksprintf", "sprintf "},
|
||||||
{ ADD, "arith", " + "},
|
{ ADD, "arith", " + "},
|
||||||
{ MINUS, "arith", " - "},
|
{ MINUS, "arith", " - "},
|
||||||
{ MULT, "arith", " * "},
|
{ MULT, "arith", " * "},
|
||||||
|
|||||||
@@ -402,7 +402,7 @@ char *format(s,a) char *s; node *a;
|
|||||||
return(buf);
|
return(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
obj asprintf1(a,n) node **a;
|
obj awksprintf(a,n) node **a;
|
||||||
{
|
{
|
||||||
obj x;
|
obj x;
|
||||||
node *y;
|
node *y;
|
||||||
@@ -597,7 +597,7 @@ obj aprintf(a,n) node **a;
|
|||||||
{
|
{
|
||||||
obj x;
|
obj x;
|
||||||
|
|
||||||
x = asprintf1(a,n);
|
x = awksprintf(a,n);
|
||||||
if (a[1]==NULL) {
|
if (a[1]==NULL) {
|
||||||
printf("%s", x.optr->sval);
|
printf("%s", x.optr->sval);
|
||||||
tempfree(x);
|
tempfree(x);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ TOPSRC = $(shell cd ../..; pwd)
|
|||||||
include $(TOPSRC)/target.mk
|
include $(TOPSRC)/target.mk
|
||||||
|
|
||||||
DEFS = -Wall -Werror
|
DEFS = -Wall -Werror
|
||||||
ALL = gen stdio stdlib string inet compat ${MACHINE}
|
ALL = gen stdio stdlib string inet compat runtime ${MACHINE}
|
||||||
|
|
||||||
all: ../libc.a
|
all: ../libc.a
|
||||||
|
|
||||||
|
|||||||
@@ -19,20 +19,30 @@ include $(TOPSRC)/target.mk
|
|||||||
|
|
||||||
CFLAGS += ${DEFS}
|
CFLAGS += ${DEFS}
|
||||||
|
|
||||||
OBJS = addsf3.o comparesf2.o divsf3.o fixsfsi.o floatsisf.o \
|
OBJS = adddf3.o \
|
||||||
mulsf3.o negsf2.o subsf3.o sc_case.o fixunssfsi.o \
|
addsf3.o \
|
||||||
floatunsisf.o
|
divdf3.o \
|
||||||
|
divsf3.o \
|
||||||
all: ${OBJS}
|
comparedf2.o \
|
||||||
|
comparesf2.o \
|
||||||
|
extendsfdf2.o \
|
||||||
|
fixdfsi.o \
|
||||||
|
fixsfsi.o \
|
||||||
|
floatsidf.o \
|
||||||
|
floatsisf.o \
|
||||||
|
floatunsisf.o \
|
||||||
|
fp_mode.o \
|
||||||
|
muldf3.o \
|
||||||
|
mulsf3.o \
|
||||||
|
subdf3.o \
|
||||||
|
subsf3.o \
|
||||||
|
truncdfsf2.o
|
||||||
|
|
||||||
|
runtime.a: ${OBJS}
|
||||||
|
@echo "buiding runtime.a"
|
||||||
|
@$(AR) cru runtime.a ${OBJS}
|
||||||
clean:
|
clean:
|
||||||
rm -f *.a *.o *~ profiled/*.o tags
|
rm -f *.a *.o *~ profiled/*.o tags
|
||||||
|
|
||||||
cleandir: clean
|
cleandir: clean
|
||||||
rm -f .depend
|
rm -f .depend
|
||||||
|
|
||||||
install: all
|
|
||||||
# cp ../libgcc.a ${DESTDIR}/lib/
|
|
||||||
# $(RANLIB) -t ${DESTDIR}/lib/libgcc.a
|
|
||||||
# cp libgcc_p.a ${DESTDIR}/lib/
|
|
||||||
# $(RANLIB) -t ${DESTDIR}/lib/libgcc_p.a
|
|
||||||
|
|||||||
@@ -20,13 +20,18 @@ Here is the specification for this library:
|
|||||||
|
|
||||||
http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc
|
http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc
|
||||||
|
|
||||||
|
Please note that the libgcc specification explicitly mentions actual types of
|
||||||
|
arguments and returned values being expressed with machine modes.
|
||||||
|
In some cases particular types such as "int", "unsigned", "long long", etc.
|
||||||
|
may be specified just as examples there.
|
||||||
|
|
||||||
Here is a synopsis of the contents of this library:
|
Here is a synopsis of the contents of this library:
|
||||||
|
|
||||||
typedef int si_int;
|
typedef int32_t si_int;
|
||||||
typedef unsigned su_int;
|
typedef uint32_t su_int;
|
||||||
|
|
||||||
typedef long long di_int;
|
typedef int64_t di_int;
|
||||||
typedef unsigned long long du_int;
|
typedef uint64_t du_int;
|
||||||
|
|
||||||
// Integral bit manipulation
|
// Integral bit manipulation
|
||||||
|
|
||||||
@@ -38,26 +43,27 @@ ti_int __ashrti3(ti_int a, si_int b); // a >> b arithmetic (sign fill)
|
|||||||
di_int __lshrdi3(di_int a, si_int b); // a >> b logical (zero fill)
|
di_int __lshrdi3(di_int a, si_int b); // a >> b logical (zero fill)
|
||||||
ti_int __lshrti3(ti_int a, si_int b); // a >> b logical (zero fill)
|
ti_int __lshrti3(ti_int a, si_int b); // a >> b logical (zero fill)
|
||||||
|
|
||||||
si_int __clzsi2(si_int a); // count leading zeros
|
int __clzsi2(si_int a); // count leading zeros
|
||||||
si_int __clzdi2(di_int a); // count leading zeros
|
int __clzdi2(di_int a); // count leading zeros
|
||||||
si_int __clzti2(ti_int a); // count leading zeros
|
int __clzti2(ti_int a); // count leading zeros
|
||||||
si_int __ctzsi2(si_int a); // count trailing zeros
|
int __ctzsi2(si_int a); // count trailing zeros
|
||||||
si_int __ctzdi2(di_int a); // count trailing zeros
|
int __ctzdi2(di_int a); // count trailing zeros
|
||||||
si_int __ctzti2(ti_int a); // count trailing zeros
|
int __ctzti2(ti_int a); // count trailing zeros
|
||||||
|
|
||||||
si_int __ffsdi2(di_int a); // find least significant 1 bit
|
int __ffssi2(si_int a); // find least significant 1 bit
|
||||||
si_int __ffsti2(ti_int a); // find least significant 1 bit
|
int __ffsdi2(di_int a); // find least significant 1 bit
|
||||||
|
int __ffsti2(ti_int a); // find least significant 1 bit
|
||||||
|
|
||||||
si_int __paritysi2(si_int a); // bit parity
|
int __paritysi2(si_int a); // bit parity
|
||||||
si_int __paritydi2(di_int a); // bit parity
|
int __paritydi2(di_int a); // bit parity
|
||||||
si_int __parityti2(ti_int a); // bit parity
|
int __parityti2(ti_int a); // bit parity
|
||||||
|
|
||||||
si_int __popcountsi2(si_int a); // bit population
|
int __popcountsi2(si_int a); // bit population
|
||||||
si_int __popcountdi2(di_int a); // bit population
|
int __popcountdi2(di_int a); // bit population
|
||||||
si_int __popcountti2(ti_int a); // bit population
|
int __popcountti2(ti_int a); // bit population
|
||||||
|
|
||||||
uint32_t __bswapsi2(uint32_t a); // a byteswapped, arm only
|
uint32_t __bswapsi2(uint32_t a); // a byteswapped
|
||||||
uint64_t __bswapdi2(uint64_t a); // a byteswapped, arm only
|
uint64_t __bswapdi2(uint64_t a); // a byteswapped
|
||||||
|
|
||||||
// Integral arithmetic
|
// Integral arithmetic
|
||||||
|
|
||||||
@@ -81,6 +87,8 @@ du_int __udivmoddi4(du_int a, du_int b, du_int* rem); // a / b, *rem = a % b u
|
|||||||
tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); // a / b, *rem = a % b unsigned
|
tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); // a / b, *rem = a % b unsigned
|
||||||
su_int __udivmodsi4(su_int a, su_int b, su_int* rem); // a / b, *rem = a % b unsigned
|
su_int __udivmodsi4(su_int a, su_int b, su_int* rem); // a / b, *rem = a % b unsigned
|
||||||
si_int __divmodsi4(si_int a, si_int b, si_int* rem); // a / b, *rem = a % b signed
|
si_int __divmodsi4(si_int a, si_int b, si_int* rem); // a / b, *rem = a % b signed
|
||||||
|
di_int __divmoddi4(di_int a, di_int b, di_int* rem); // a / b, *rem = a % b signed
|
||||||
|
ti_int __divmodti4(ti_int a, ti_int b, ti_int* rem); // a / b, *rem = a % b signed
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -168,10 +176,10 @@ long double __floatuntixf(tu_int a);
|
|||||||
|
|
||||||
// Floating point raised to integer power
|
// Floating point raised to integer power
|
||||||
|
|
||||||
float __powisf2( float a, si_int b); // a ^ b
|
float __powisf2( float a, int b); // a ^ b
|
||||||
double __powidf2( double a, si_int b); // a ^ b
|
double __powidf2( double a, int b); // a ^ b
|
||||||
long double __powixf2(long double a, si_int b); // a ^ b
|
long double __powixf2(long double a, int b); // a ^ b
|
||||||
long double __powitf2(long double a, si_int b); // ppc only, a ^ b
|
long double __powitf2(long double a, int b); // ppc only, a ^ b
|
||||||
|
|
||||||
// Complex arithmetic
|
// Complex arithmetic
|
||||||
|
|
||||||
@@ -198,7 +206,7 @@ long double _Complex __divtc3(long double a, long double b,
|
|||||||
|
|
||||||
// __clear_cache() is used to tell process that new instructions have been
|
// __clear_cache() is used to tell process that new instructions have been
|
||||||
// written to an address range. Necessary on processors that do not have
|
// written to an address range. Necessary on processors that do not have
|
||||||
// a unified instuction and data cache.
|
// a unified instruction and data cache.
|
||||||
void __clear_cache(void* start, void* end);
|
void __clear_cache(void* start, void* end);
|
||||||
|
|
||||||
// __enable_execute_stack() is used with nested functions when a trampoline
|
// __enable_execute_stack() is used with nested functions when a trampoline
|
||||||
@@ -220,7 +228,9 @@ _Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions,
|
|||||||
// for use with some implementations of assert() in <assert.h>
|
// for use with some implementations of assert() in <assert.h>
|
||||||
void __eprintf(const char* format, const char* assertion_expression,
|
void __eprintf(const char* format, const char* assertion_expression,
|
||||||
const char* line, const char* file);
|
const char* line, const char* file);
|
||||||
|
|
||||||
|
// for systems with emulated thread local storage
|
||||||
|
void* __emutls_get_address(struct __emutls_control*);
|
||||||
|
|
||||||
|
|
||||||
// Power PC specific functions
|
// Power PC specific functions
|
||||||
|
|||||||
@@ -1,150 +1,24 @@
|
|||||||
//===-- lib/addsf3.c - Single-precision addition ------------------*- C -*-===//
|
//===-- lib/addsf3.c - Single-precision addition ------------------*- C -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
//
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// This file implements single-precision soft-float addition with the IEEE-754
|
// This file implements single-precision soft-float addition.
|
||||||
// default rounding (to nearest, ties to even).
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
#define SINGLE_PRECISION
|
||||||
#include "fp_lib.h"
|
#include "fp_add_impl.inc"
|
||||||
|
|
||||||
fp_t
|
COMPILER_RT_ABI float __addsf3(float a, float b) { return __addXf3__(a, b); }
|
||||||
__addsf3(fp_t a, fp_t b)
|
|
||||||
{
|
|
||||||
rep_t aRep = toRep(a);
|
|
||||||
rep_t bRep = toRep(b);
|
|
||||||
const rep_t aAbs = aRep & absMask;
|
|
||||||
const rep_t bAbs = bRep & absMask;
|
|
||||||
|
|
||||||
// Detect if a or b is zero, infinity, or NaN.
|
#if defined(__ARM_EABI__)
|
||||||
if (aAbs - 1U >= infRep - 1U || bAbs - 1U >= infRep - 1U) {
|
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||||
|
AEABI_RTABI float __aeabi_fadd(float a, float b) { return __addsf3(a, b); }
|
||||||
// NaN + anything = qNaN
|
#else
|
||||||
if (aAbs > infRep) return fromRep(toRep(a) | quietBit);
|
COMPILER_RT_ALIAS(__addsf3, __aeabi_fadd)
|
||||||
// anything + NaN = qNaN
|
#endif
|
||||||
if (bAbs > infRep) return fromRep(toRep(b) | quietBit);
|
#endif
|
||||||
|
|
||||||
if (aAbs == infRep) {
|
|
||||||
// +/-infinity + -/+infinity = qNaN
|
|
||||||
if ((toRep(a) ^ toRep(b)) == signBit) return fromRep(qnanRep);
|
|
||||||
// +/-infinity + anything remaining = +/- infinity
|
|
||||||
else return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// anything remaining + +/-infinity = +/-infinity
|
|
||||||
if (bAbs == infRep) return b;
|
|
||||||
|
|
||||||
// zero + anything = anything
|
|
||||||
if (!aAbs) {
|
|
||||||
// but we need to get the sign right for zero + zero
|
|
||||||
if (!bAbs) return fromRep(toRep(a) & toRep(b));
|
|
||||||
else return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// anything + zero = anything
|
|
||||||
if (!bAbs) return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap a and b if necessary so that a has the larger absolute value.
|
|
||||||
if (bAbs > aAbs) {
|
|
||||||
const rep_t temp = aRep;
|
|
||||||
aRep = bRep;
|
|
||||||
bRep = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the exponent and significand from the (possibly swapped) a and b.
|
|
||||||
int aExponent = aRep >> significandBits & maxExponent;
|
|
||||||
int bExponent = bRep >> significandBits & maxExponent;
|
|
||||||
rep_t aSignificand = aRep & significandMask;
|
|
||||||
rep_t bSignificand = bRep & significandMask;
|
|
||||||
|
|
||||||
// Normalize any denormals, and adjust the exponent accordingly.
|
|
||||||
if (aExponent == 0) aExponent = normalize(&aSignificand);
|
|
||||||
if (bExponent == 0) bExponent = normalize(&bSignificand);
|
|
||||||
|
|
||||||
// The sign of the result is the sign of the larger operand, a. If they
|
|
||||||
// have opposite signs, we are performing a subtraction; otherwise addition.
|
|
||||||
const rep_t resultSign = aRep & signBit;
|
|
||||||
const int subtraction = ((aRep ^ bRep) & signBit) != 0;
|
|
||||||
|
|
||||||
// Shift the significands to give us round, guard and sticky, and or in the
|
|
||||||
// implicit significand bit. (If we fell through from the denormal path it
|
|
||||||
// was already set by normalize( ), but setting it twice won't hurt
|
|
||||||
// anything.)
|
|
||||||
aSignificand = (aSignificand | implicitBit) << 3;
|
|
||||||
bSignificand = (bSignificand | implicitBit) << 3;
|
|
||||||
|
|
||||||
// Shift the significand of b by the difference in exponents, with a sticky
|
|
||||||
// bottom bit to get rounding correct.
|
|
||||||
const unsigned int align = aExponent - bExponent;
|
|
||||||
if (align) {
|
|
||||||
if (align < typeWidth) {
|
|
||||||
const int sticky = (bSignificand << (typeWidth - align)) != 0;
|
|
||||||
bSignificand = bSignificand >> align | sticky;
|
|
||||||
} else {
|
|
||||||
bSignificand = 1; // sticky; b is known to be non-zero.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subtraction) {
|
|
||||||
aSignificand -= bSignificand;
|
|
||||||
|
|
||||||
// If a == -b, return +zero.
|
|
||||||
if (aSignificand == 0) return fromRep(0);
|
|
||||||
|
|
||||||
// If partial cancellation occured, we need to left-shift the result
|
|
||||||
// and adjust the exponent:
|
|
||||||
if (aSignificand < implicitBit << 3) {
|
|
||||||
const int shift = rep_clz(aSignificand) - rep_clz(implicitBit << 3);
|
|
||||||
aSignificand <<= shift;
|
|
||||||
aExponent -= shift;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else /* addition */ {
|
|
||||||
aSignificand += bSignificand;
|
|
||||||
|
|
||||||
// If the addition carried up, we need to right-shift the result and
|
|
||||||
// adjust the exponent:
|
|
||||||
if (aSignificand & implicitBit << 4) {
|
|
||||||
const int sticky = aSignificand & 1;
|
|
||||||
aSignificand = aSignificand >> 1 | sticky;
|
|
||||||
aExponent += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have overflowed the type, return +/- infinity:
|
|
||||||
if (aExponent >= maxExponent) return fromRep(infRep | resultSign);
|
|
||||||
|
|
||||||
if (aExponent <= 0) {
|
|
||||||
// Result is denormal before rounding; the exponent is zero and we
|
|
||||||
// need to shift the significand.
|
|
||||||
const int shift = 1 - aExponent;
|
|
||||||
const int sticky = (aSignificand << (typeWidth - shift)) != 0;
|
|
||||||
aSignificand = aSignificand >> shift | sticky;
|
|
||||||
aExponent = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Low three bits are round, guard, and sticky.
|
|
||||||
const int roundGuardSticky = aSignificand & 0x7;
|
|
||||||
|
|
||||||
// Shift the significand into place, and mask off the implicit bit.
|
|
||||||
rep_t result = aSignificand >> 3 & significandMask;
|
|
||||||
|
|
||||||
// Insert the exponent and sign.
|
|
||||||
result |= (rep_t)aExponent << significandBits;
|
|
||||||
result |= resultSign;
|
|
||||||
|
|
||||||
// Final rounding. The result may overflow to infinity, but that is the
|
|
||||||
// correct result in that case.
|
|
||||||
if (roundGuardSticky > 0x4) result++;
|
|
||||||
if (roundGuardSticky == 0x4) result += result & 1;
|
|
||||||
return fromRep(result);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
//===-- lib/comparesf2.c - Single-precision comparisons -----------*- C -*-===//
|
//===-- lib/comparesf2.c - Single-precision comparisons -----------*- C -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
//
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
@@ -40,104 +39,113 @@
|
|||||||
#define SINGLE_PRECISION
|
#define SINGLE_PRECISION
|
||||||
#include "fp_lib.h"
|
#include "fp_lib.h"
|
||||||
|
|
||||||
enum LE_RESULT {
|
enum LE_RESULT { LE_LESS = -1, LE_EQUAL = 0, LE_GREATER = 1, LE_UNORDERED = 1 };
|
||||||
LE_LESS = -1,
|
|
||||||
LE_EQUAL = 0,
|
|
||||||
LE_GREATER = 1,
|
|
||||||
LE_UNORDERED = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum LE_RESULT
|
COMPILER_RT_ABI enum LE_RESULT __lesf2(fp_t a, fp_t b) {
|
||||||
__lesf2(fp_t a, fp_t b)
|
|
||||||
{
|
|
||||||
const srep_t aInt = toRep(a);
|
|
||||||
const srep_t bInt = toRep(b);
|
|
||||||
const rep_t aAbs = aInt & absMask;
|
|
||||||
const rep_t bAbs = bInt & absMask;
|
|
||||||
|
|
||||||
// If either a or b is NaN, they are unordered.
|
const srep_t aInt = toRep(a);
|
||||||
if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
|
const srep_t bInt = toRep(b);
|
||||||
|
const rep_t aAbs = aInt & absMask;
|
||||||
|
const rep_t bAbs = bInt & absMask;
|
||||||
|
|
||||||
// If a and b are both zeros, they are equal.
|
// If either a or b is NaN, they are unordered.
|
||||||
if ((aAbs | bAbs) == 0) return LE_EQUAL;
|
if (aAbs > infRep || bAbs > infRep)
|
||||||
|
return LE_UNORDERED;
|
||||||
|
|
||||||
// If at least one of a and b is positive, we get the same result comparing
|
// If a and b are both zeros, they are equal.
|
||||||
// a and b as signed integers as we would with a fp_ting-point compare.
|
if ((aAbs | bAbs) == 0)
|
||||||
if ((aInt & bInt) >= 0) {
|
return LE_EQUAL;
|
||||||
if (aInt < bInt) return LE_LESS;
|
|
||||||
else if (aInt == bInt) return LE_EQUAL;
|
|
||||||
else return LE_GREATER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, both are negative, so we need to flip the sense of the
|
// If at least one of a and b is positive, we get the same result comparing
|
||||||
// comparison to get the correct result. (This assumes a twos- or ones-
|
// a and b as signed integers as we would with a fp_ting-point compare.
|
||||||
// complement integer representation; if integers are represented in a
|
if ((aInt & bInt) >= 0) {
|
||||||
// sign-magnitude representation, then this flip is incorrect).
|
if (aInt < bInt)
|
||||||
else {
|
return LE_LESS;
|
||||||
if (aInt > bInt) return LE_LESS;
|
else if (aInt == bInt)
|
||||||
else if (aInt == bInt) return LE_EQUAL;
|
return LE_EQUAL;
|
||||||
else return LE_GREATER;
|
else
|
||||||
}
|
return LE_GREATER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, both are negative, so we need to flip the sense of the
|
||||||
|
// comparison to get the correct result. (This assumes a twos- or ones-
|
||||||
|
// complement integer representation; if integers are represented in a
|
||||||
|
// sign-magnitude representation, then this flip is incorrect).
|
||||||
|
else {
|
||||||
|
if (aInt > bInt)
|
||||||
|
return LE_LESS;
|
||||||
|
else if (aInt == bInt)
|
||||||
|
return LE_EQUAL;
|
||||||
|
else
|
||||||
|
return LE_GREATER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__ELF__)
|
||||||
|
// Alias for libgcc compatibility
|
||||||
|
COMPILER_RT_ALIAS(__lesf2, __cmpsf2)
|
||||||
|
#endif
|
||||||
|
COMPILER_RT_ALIAS(__lesf2, __eqsf2)
|
||||||
|
COMPILER_RT_ALIAS(__lesf2, __ltsf2)
|
||||||
|
COMPILER_RT_ALIAS(__lesf2, __nesf2)
|
||||||
|
|
||||||
enum GE_RESULT {
|
enum GE_RESULT {
|
||||||
GE_LESS = -1,
|
GE_LESS = -1,
|
||||||
GE_EQUAL = 0,
|
GE_EQUAL = 0,
|
||||||
GE_GREATER = 1,
|
GE_GREATER = 1,
|
||||||
GE_UNORDERED = -1 // Note: different from LE_UNORDERED
|
GE_UNORDERED = -1 // Note: different from LE_UNORDERED
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GE_RESULT
|
COMPILER_RT_ABI enum GE_RESULT __gesf2(fp_t a, fp_t b) {
|
||||||
__gesf2(fp_t a, fp_t b)
|
|
||||||
{
|
|
||||||
const srep_t aInt = toRep(a);
|
|
||||||
const srep_t bInt = toRep(b);
|
|
||||||
const rep_t aAbs = aInt & absMask;
|
|
||||||
const rep_t bAbs = bInt & absMask;
|
|
||||||
|
|
||||||
if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
|
const srep_t aInt = toRep(a);
|
||||||
if ((aAbs | bAbs) == 0) return GE_EQUAL;
|
const srep_t bInt = toRep(b);
|
||||||
if ((aInt & bInt) >= 0) {
|
const rep_t aAbs = aInt & absMask;
|
||||||
if (aInt < bInt) return GE_LESS;
|
const rep_t bAbs = bInt & absMask;
|
||||||
else if (aInt == bInt) return GE_EQUAL;
|
|
||||||
else return GE_GREATER;
|
if (aAbs > infRep || bAbs > infRep)
|
||||||
} else {
|
return GE_UNORDERED;
|
||||||
if (aInt > bInt) return GE_LESS;
|
if ((aAbs | bAbs) == 0)
|
||||||
else if (aInt == bInt) return GE_EQUAL;
|
return GE_EQUAL;
|
||||||
else return GE_GREATER;
|
if ((aInt & bInt) >= 0) {
|
||||||
}
|
if (aInt < bInt)
|
||||||
|
return GE_LESS;
|
||||||
|
else if (aInt == bInt)
|
||||||
|
return GE_EQUAL;
|
||||||
|
else
|
||||||
|
return GE_GREATER;
|
||||||
|
} else {
|
||||||
|
if (aInt > bInt)
|
||||||
|
return GE_LESS;
|
||||||
|
else if (aInt == bInt)
|
||||||
|
return GE_EQUAL;
|
||||||
|
else
|
||||||
|
return GE_GREATER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
COMPILER_RT_ALIAS(__gesf2, __gtsf2)
|
||||||
__unordsf2(fp_t a, fp_t b)
|
|
||||||
{
|
COMPILER_RT_ABI int
|
||||||
|
__unordsf2(fp_t a, fp_t b) {
|
||||||
const rep_t aAbs = toRep(a) & absMask;
|
const rep_t aAbs = toRep(a) & absMask;
|
||||||
const rep_t bAbs = toRep(b) & absMask;
|
const rep_t bAbs = toRep(b) & absMask;
|
||||||
return aAbs > infRep || bAbs > infRep;
|
return aAbs > infRep || bAbs > infRep;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following are alternative names for the preceeding routines.
|
#if defined(__ARM_EABI__)
|
||||||
|
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||||
|
AEABI_RTABI int __aeabi_fcmpun(fp_t a, fp_t b) { return __unordsf2(a, b); }
|
||||||
|
#else
|
||||||
|
COMPILER_RT_ALIAS(__unordsf2, __aeabi_fcmpun)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
enum LE_RESULT
|
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||||
__eqsf2(fp_t a, fp_t b)
|
// The alias mechanism doesn't work on Windows except for MinGW, so emit
|
||||||
{
|
// wrapper functions.
|
||||||
return __lesf2(a, b);
|
int __eqsf2(fp_t a, fp_t b) { return __lesf2(a, b); }
|
||||||
}
|
int __ltsf2(fp_t a, fp_t b) { return __lesf2(a, b); }
|
||||||
|
int __nesf2(fp_t a, fp_t b) { return __lesf2(a, b); }
|
||||||
enum LE_RESULT
|
int __gtsf2(fp_t a, fp_t b) { return __gesf2(a, b); }
|
||||||
__ltsf2(fp_t a, fp_t b)
|
#endif
|
||||||
{
|
|
||||||
return __lesf2(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum LE_RESULT
|
|
||||||
__nesf2(fp_t a, fp_t b)
|
|
||||||
{
|
|
||||||
return __lesf2(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GE_RESULT
|
|
||||||
__gtsf2(fp_t a, fp_t b)
|
|
||||||
{
|
|
||||||
return __gesf2(a, b);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,165 +1,30 @@
|
|||||||
//===-- lib/divsf3.c - Single-precision division ------------------*- C -*-===//
|
//===-- lib/divsf3.c - Single-precision division ------------------*- C -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
//
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// This file implements single-precision soft-float division
|
// This file implements single-precision soft-float division
|
||||||
// with the IEEE-754 default rounding (to nearest, ties to even).
|
// with the IEEE-754 default rounding (to nearest, ties to even).
|
||||||
//
|
//
|
||||||
// For simplicity, this implementation currently flushes denormals to zero.
|
|
||||||
// It should be a fairly straightforward exercise to implement gradual
|
|
||||||
// underflow with correct rounding.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
#define SINGLE_PRECISION
|
||||||
#include "fp_lib.h"
|
|
||||||
|
|
||||||
fp_t
|
#define NUMBER_OF_HALF_ITERATIONS 0
|
||||||
__divsf3(fp_t a, fp_t b)
|
#define NUMBER_OF_FULL_ITERATIONS 3
|
||||||
{
|
#define USE_NATIVE_FULL_ITERATIONS
|
||||||
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
|
|
||||||
const unsigned int bExponent = toRep(b) >> significandBits & maxExponent;
|
|
||||||
const rep_t quotientSign = (toRep(a) ^ toRep(b)) & signBit;
|
|
||||||
|
|
||||||
rep_t aSignificand = toRep(a) & significandMask;
|
#include "fp_div_impl.inc"
|
||||||
rep_t bSignificand = toRep(b) & significandMask;
|
|
||||||
int scale = 0;
|
|
||||||
|
|
||||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
COMPILER_RT_ABI fp_t __divsf3(fp_t a, fp_t b) { return __divXf3__(a, b); }
|
||||||
if (aExponent-1U >= maxExponent-1U || bExponent-1U >= maxExponent-1U) {
|
|
||||||
|
|
||||||
const rep_t aAbs = toRep(a) & absMask;
|
#if defined(__ARM_EABI__)
|
||||||
const rep_t bAbs = toRep(b) & absMask;
|
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||||
|
AEABI_RTABI fp_t __aeabi_fdiv(fp_t a, fp_t b) { return __divsf3(a, b); }
|
||||||
// NaN / anything = qNaN
|
#else
|
||||||
if (aAbs > infRep) return fromRep(toRep(a) | quietBit);
|
COMPILER_RT_ALIAS(__divsf3, __aeabi_fdiv)
|
||||||
// anything / NaN = qNaN
|
#endif
|
||||||
if (bAbs > infRep) return fromRep(toRep(b) | quietBit);
|
#endif
|
||||||
|
|
||||||
if (aAbs == infRep) {
|
|
||||||
// infinity / infinity = NaN
|
|
||||||
if (bAbs == infRep) return fromRep(qnanRep);
|
|
||||||
// infinity / anything else = +/- infinity
|
|
||||||
else return fromRep(aAbs | quotientSign);
|
|
||||||
}
|
|
||||||
|
|
||||||
// anything else / infinity = +/- 0
|
|
||||||
if (bAbs == infRep) return fromRep(quotientSign);
|
|
||||||
|
|
||||||
if (!aAbs) {
|
|
||||||
// zero / zero = NaN
|
|
||||||
if (!bAbs) return fromRep(qnanRep);
|
|
||||||
// zero / anything else = +/- zero
|
|
||||||
else return fromRep(quotientSign);
|
|
||||||
}
|
|
||||||
// anything else / zero = +/- infinity
|
|
||||||
if (!bAbs) return fromRep(infRep | quotientSign);
|
|
||||||
|
|
||||||
// one or both of a or b is denormal, the other (if applicable) is a
|
|
||||||
// normal number. Renormalize one or both of a and b, and set scale to
|
|
||||||
// include the necessary exponent adjustment.
|
|
||||||
if (aAbs < implicitBit) scale += normalize(&aSignificand);
|
|
||||||
if (bAbs < implicitBit) scale -= normalize(&bSignificand);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Or in the implicit significand bit. (If we fell through from the
|
|
||||||
// denormal path it was already set by normalize( ), but setting it twice
|
|
||||||
// won't hurt anything.)
|
|
||||||
aSignificand |= implicitBit;
|
|
||||||
bSignificand |= implicitBit;
|
|
||||||
int quotientExponent = aExponent - bExponent + scale;
|
|
||||||
|
|
||||||
// Align the significand of b as a Q31 fixed-point number in the range
|
|
||||||
// [1, 2.0) and get a Q32 approximate reciprocal using a small minimax
|
|
||||||
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
|
||||||
// is accurate to about 3.5 binary digits.
|
|
||||||
uint32_t q31b = bSignificand << 8;
|
|
||||||
uint32_t reciprocal = UINT32_C(0x7504f333) - q31b;
|
|
||||||
|
|
||||||
// Now refine the reciprocal estimate using a Newton-Raphson iteration:
|
|
||||||
//
|
|
||||||
// x1 = x0 * (2 - x0 * b)
|
|
||||||
//
|
|
||||||
// This doubles the number of correct binary digits in the approximation
|
|
||||||
// with each iteration, so after three iterations, we have about 28 binary
|
|
||||||
// digits of accuracy.
|
|
||||||
uint32_t correction;
|
|
||||||
correction = -((uint64_t)reciprocal * q31b >> 32);
|
|
||||||
reciprocal = (uint64_t)reciprocal * correction >> 31;
|
|
||||||
correction = -((uint64_t)reciprocal * q31b >> 32);
|
|
||||||
reciprocal = (uint64_t)reciprocal * correction >> 31;
|
|
||||||
correction = -((uint64_t)reciprocal * q31b >> 32);
|
|
||||||
reciprocal = (uint64_t)reciprocal * correction >> 31;
|
|
||||||
|
|
||||||
// Exhaustive testing shows that the error in reciprocal after three steps
|
|
||||||
// is in the interval [-0x1.f58108p-31, 0x1.d0e48cp-29], in line with our
|
|
||||||
// expectations. We bump the reciprocal by a tiny value to force the error
|
|
||||||
// to be strictly positive (in the range [0x1.4fdfp-37,0x1.287246p-29], to
|
|
||||||
// be specific). This also causes 1/1 to give a sensible approximation
|
|
||||||
// instead of zero (due to overflow).
|
|
||||||
reciprocal -= 2;
|
|
||||||
|
|
||||||
// The numerical reciprocal is accurate to within 2^-28, lies in the
|
|
||||||
// interval [0x1.000000eep-1, 0x1.fffffffcp-1], and is strictly smaller
|
|
||||||
// than the true reciprocal of b. Multiplying a by this reciprocal thus
|
|
||||||
// gives a numerical q = a/b in Q24 with the following properties:
|
|
||||||
//
|
|
||||||
// 1. q < a/b
|
|
||||||
// 2. q is in the interval [0x1.000000eep-1, 0x1.fffffffcp0)
|
|
||||||
// 3. the error in q is at most 2^-24 + 2^-27 -- the 2^24 term comes
|
|
||||||
// from the fact that we truncate the product, and the 2^27 term
|
|
||||||
// is the error in the reciprocal of b scaled by the maximum
|
|
||||||
// possible value of a. As a consequence of this error bound,
|
|
||||||
// either q or nextafter(q) is the correctly rounded
|
|
||||||
rep_t quotient = (uint64_t)reciprocal*(aSignificand << 1) >> 32;
|
|
||||||
|
|
||||||
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
|
|
||||||
// In either case, we are going to compute a residual of the form
|
|
||||||
//
|
|
||||||
// r = a - q*b
|
|
||||||
//
|
|
||||||
// We know from the construction of q that r satisfies:
|
|
||||||
//
|
|
||||||
// 0 <= r < ulp(q)*b
|
|
||||||
//
|
|
||||||
// if r is greater than 1/2 ulp(q)*b, then q rounds up. Otherwise, we
|
|
||||||
// already have the correct result. The exact halfway case cannot occur.
|
|
||||||
// We also take this time to right shift quotient if it falls in the [1,2)
|
|
||||||
// range and adjust the exponent accordingly.
|
|
||||||
rep_t residual;
|
|
||||||
if (quotient < (implicitBit << 1)) {
|
|
||||||
residual = (aSignificand << 24) - quotient * bSignificand;
|
|
||||||
quotientExponent--;
|
|
||||||
} else {
|
|
||||||
quotient >>= 1;
|
|
||||||
residual = (aSignificand << 23) - quotient * bSignificand;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int writtenExponent = quotientExponent + exponentBias;
|
|
||||||
|
|
||||||
if (writtenExponent >= maxExponent) {
|
|
||||||
// If we have overflowed the exponent, return infinity.
|
|
||||||
return fromRep(infRep | quotientSign);
|
|
||||||
}
|
|
||||||
else if (writtenExponent < 1) {
|
|
||||||
// Flush denormals to zero. In the future, it would be nice to add
|
|
||||||
// code to round them correctly.
|
|
||||||
return fromRep(quotientSign);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int round = (residual << 1) > bSignificand;
|
|
||||||
// Clear the implicit bit
|
|
||||||
rep_t absResult = quotient & significandMask;
|
|
||||||
// Insert the exponent
|
|
||||||
absResult |= (rep_t)writtenExponent << significandBits;
|
|
||||||
// Round
|
|
||||||
absResult += round;
|
|
||||||
// Insert the sign and return
|
|
||||||
return fromRep(absResult | quotientSign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,46 +1,23 @@
|
|||||||
//===-- lib/fixsfsi.c - Single-precision -> integer conversion ----*- C -*-===//
|
//===-- fixsfsi.c - Implement __fixsfsi -----------------------------------===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
//
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements single-precision to integer conversion for the
|
|
||||||
// compiler-rt library. No range checking is performed; the behavior of this
|
|
||||||
// conversion is undefined for out of range values in the C standard.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
#define SINGLE_PRECISION
|
||||||
#include "fp_lib.h"
|
#include "fp_lib.h"
|
||||||
|
typedef si_int fixint_t;
|
||||||
|
typedef su_int fixuint_t;
|
||||||
|
#include "fp_fixint_impl.inc"
|
||||||
|
|
||||||
int
|
COMPILER_RT_ABI si_int __fixsfsi(fp_t a) { return __fixint(a); }
|
||||||
__fixsfsi(fp_t a)
|
|
||||||
{
|
|
||||||
// Break a into sign, exponent, significand
|
|
||||||
const rep_t aRep = toRep(a);
|
|
||||||
const rep_t aAbs = aRep & absMask;
|
|
||||||
const int sign = aRep & signBit ? -1 : 1;
|
|
||||||
const int exponent = (aAbs >> significandBits) - exponentBias;
|
|
||||||
const rep_t significand = (aAbs & significandMask) | implicitBit;
|
|
||||||
|
|
||||||
// If 0 < exponent < significandBits, right shift to get the result.
|
#if defined(__ARM_EABI__)
|
||||||
if ((unsigned int)exponent < significandBits) {
|
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||||
return sign * (significand >> (significandBits - exponent));
|
AEABI_RTABI si_int __aeabi_f2iz(fp_t a) { return __fixsfsi(a); }
|
||||||
}
|
#else
|
||||||
|
COMPILER_RT_ALIAS(__fixsfsi, __aeabi_f2iz)
|
||||||
// If exponent is negative, the result is zero.
|
#endif
|
||||||
else if (exponent < 0) {
|
#endif
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If significandBits < exponent, left shift to get the result. This shift
|
|
||||||
// may end up being larger than the type width, which incurs undefined
|
|
||||||
// behavior, but the conversion itself is undefined in that case, so
|
|
||||||
// whatever the compiler decides to do is fine.
|
|
||||||
else {
|
|
||||||
return sign * (significand << (exponent - significandBits));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
/* ===-- fixunssfsi.c - Implement __fixunssfsi -----------------------------===
|
|
||||||
*
|
|
||||||
* The LLVM Compiler Infrastructure
|
|
||||||
*
|
|
||||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
|
||||||
* Source Licenses. See LICENSE.TXT for details.
|
|
||||||
*
|
|
||||||
* ===----------------------------------------------------------------------===
|
|
||||||
*
|
|
||||||
* This file implements __fixunssfsi for the compiler_rt library.
|
|
||||||
*
|
|
||||||
* ===----------------------------------------------------------------------===
|
|
||||||
*/
|
|
||||||
#define SINGLE_PRECISION
|
|
||||||
#include "fp_lib.h"
|
|
||||||
|
|
||||||
/* Returns: convert a to a unsigned int, rounding toward zero.
|
|
||||||
* Negative values all become zero.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Assumption: float is a IEEE 32 bit floating point type
|
|
||||||
* su_int is a 32 bit integral type
|
|
||||||
* value in float is representable in su_int or is negative
|
|
||||||
* (no range checking performed)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
|
|
||||||
|
|
||||||
uint32_t
|
|
||||||
__fixunssfsi(fp_t a)
|
|
||||||
{
|
|
||||||
union { fp_t f; rep_t u; } fb;
|
|
||||||
fb.f = a;
|
|
||||||
|
|
||||||
int e = ((fb.u & 0x7F800000) >> 23) - 127;
|
|
||||||
if (e < 0 || (fb.u & 0x80000000))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rep_t r = (fb.u & 0x007FFFFF) | 0x00800000;
|
|
||||||
if (e > 23)
|
|
||||||
r <<= (e - 23);
|
|
||||||
else
|
|
||||||
r >>= (23 - e);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
//===-- lib/floatsisf.c - integer -> single-precision conversion --*- C -*-===//
|
//===-- lib/floatsisf.c - integer -> single-precision conversion --*- C -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
//
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
@@ -16,40 +15,51 @@
|
|||||||
#define SINGLE_PRECISION
|
#define SINGLE_PRECISION
|
||||||
#include "fp_lib.h"
|
#include "fp_lib.h"
|
||||||
|
|
||||||
fp_t
|
#include "int_lib.h"
|
||||||
__floatsisf(int a)
|
|
||||||
{
|
|
||||||
const int aWidth = sizeof a * CHAR_BIT;
|
|
||||||
|
|
||||||
// Handle zero as a special case to protect clz
|
COMPILER_RT_ABI fp_t __floatsisf(int a) {
|
||||||
if (a == 0)
|
|
||||||
return fromRep(0);
|
|
||||||
|
|
||||||
// All other cases begin by extracting the sign and absolute value of a
|
const int aWidth = sizeof a * CHAR_BIT;
|
||||||
rep_t sign = 0;
|
|
||||||
if (a < 0) {
|
|
||||||
sign = signBit;
|
|
||||||
a = -a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exponent of (fp_t)a is the width of abs(a).
|
// Handle zero as a special case to protect clz
|
||||||
const int exponent = (aWidth - 1) - __builtin_clz(a);
|
if (a == 0)
|
||||||
rep_t result;
|
return fromRep(0);
|
||||||
|
|
||||||
// Shift a into the significand field, rounding if it is a right-shift
|
// All other cases begin by extracting the sign and absolute value of a
|
||||||
if (exponent <= significandBits) {
|
rep_t sign = 0;
|
||||||
const int shift = significandBits - exponent;
|
if (a < 0) {
|
||||||
result = (rep_t)a << shift ^ implicitBit;
|
sign = signBit;
|
||||||
} else {
|
a = -a;
|
||||||
const int shift = exponent - significandBits;
|
}
|
||||||
result = (rep_t)a >> shift ^ implicitBit;
|
|
||||||
rep_t round = (rep_t)a << (typeWidth - shift);
|
|
||||||
if (round > signBit) result++;
|
|
||||||
if (round == signBit) result += result & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the exponent
|
// Exponent of (fp_t)a is the width of abs(a).
|
||||||
result += (rep_t)(exponent + exponentBias) << significandBits;
|
const int exponent = (aWidth - 1) - __builtin_clz(a);
|
||||||
// Insert the sign bit and return
|
rep_t result;
|
||||||
return fromRep(result | sign);
|
|
||||||
|
// Shift a into the significand field, rounding if it is a right-shift
|
||||||
|
if (exponent <= significandBits) {
|
||||||
|
const int shift = significandBits - exponent;
|
||||||
|
result = (rep_t)a << shift ^ implicitBit;
|
||||||
|
} else {
|
||||||
|
const int shift = exponent - significandBits;
|
||||||
|
result = (rep_t)a >> shift ^ implicitBit;
|
||||||
|
rep_t round = (rep_t)a << (typeWidth - shift);
|
||||||
|
if (round > signBit)
|
||||||
|
result++;
|
||||||
|
if (round == signBit)
|
||||||
|
result += result & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the exponent
|
||||||
|
result += (rep_t)(exponent + exponentBias) << significandBits;
|
||||||
|
// Insert the sign bit and return
|
||||||
|
return fromRep(result | sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__ARM_EABI__)
|
||||||
|
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||||
|
AEABI_RTABI fp_t __aeabi_i2f(int a) { return __floatsisf(a); }
|
||||||
|
#else
|
||||||
|
COMPILER_RT_ALIAS(__floatsisf, __aeabi_i2f)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
//===-- lib/floatunsisf.c - uint -> single-precision conversion ---*- C -*-===//
|
//===-- lib/floatunsisf.c - uint -> single-precision conversion ---*- C -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
//
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
@@ -16,32 +15,43 @@
|
|||||||
#define SINGLE_PRECISION
|
#define SINGLE_PRECISION
|
||||||
#include "fp_lib.h"
|
#include "fp_lib.h"
|
||||||
|
|
||||||
fp_t
|
#include "int_lib.h"
|
||||||
__floatunsisf(unsigned int a)
|
|
||||||
{
|
|
||||||
const int aWidth = sizeof a * CHAR_BIT;
|
|
||||||
|
|
||||||
// Handle zero as a special case to protect clz
|
COMPILER_RT_ABI fp_t __floatunsisf(unsigned int a) {
|
||||||
if (a == 0)
|
|
||||||
return fromRep(0);
|
|
||||||
|
|
||||||
// Exponent of (fp_t)a is the width of abs(a).
|
const int aWidth = sizeof a * CHAR_BIT;
|
||||||
const int exponent = (aWidth - 1) - __builtin_clz(a);
|
|
||||||
rep_t result;
|
|
||||||
|
|
||||||
// Shift a into the significand field, rounding if it is a right-shift
|
// Handle zero as a special case to protect clz
|
||||||
if (exponent <= significandBits) {
|
if (a == 0)
|
||||||
const int shift = significandBits - exponent;
|
return fromRep(0);
|
||||||
result = (rep_t)a << shift ^ implicitBit;
|
|
||||||
} else {
|
|
||||||
const int shift = exponent - significandBits;
|
|
||||||
result = (rep_t)a >> shift ^ implicitBit;
|
|
||||||
rep_t round = (rep_t)a << (typeWidth - shift);
|
|
||||||
if (round > signBit) result++;
|
|
||||||
if (round == signBit) result += result & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the exponent
|
// Exponent of (fp_t)a is the width of abs(a).
|
||||||
result += (rep_t)(exponent + exponentBias) << significandBits;
|
const int exponent = (aWidth - 1) - __builtin_clz(a);
|
||||||
return fromRep(result);
|
rep_t result;
|
||||||
|
|
||||||
|
// Shift a into the significand field, rounding if it is a right-shift
|
||||||
|
if (exponent <= significandBits) {
|
||||||
|
const int shift = significandBits - exponent;
|
||||||
|
result = (rep_t)a << shift ^ implicitBit;
|
||||||
|
} else {
|
||||||
|
const int shift = exponent - significandBits;
|
||||||
|
result = (rep_t)a >> shift ^ implicitBit;
|
||||||
|
rep_t round = (rep_t)a << (typeWidth - shift);
|
||||||
|
if (round > signBit)
|
||||||
|
result++;
|
||||||
|
if (round == signBit)
|
||||||
|
result += result & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the exponent
|
||||||
|
result += (rep_t)(exponent + exponentBias) << significandBits;
|
||||||
|
return fromRep(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__ARM_EABI__)
|
||||||
|
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||||
|
AEABI_RTABI fp_t __aeabi_ui2f(unsigned int a) { return __floatunsisf(a); }
|
||||||
|
#else
|
||||||
|
COMPILER_RT_ALIAS(__floatunsisf, __aeabi_ui2f)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
//===-- lib/fp_lib.h - Floating-point utilities -------------------*- C -*-===//
|
//===-- lib/fp_lib.h - Floating-point utilities -------------------*- C -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
//
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
@@ -12,60 +11,72 @@
|
|||||||
// many useful constants and utility routines that are used in the
|
// many useful constants and utility routines that are used in the
|
||||||
// implementation of the soft-float routines in compiler-rt.
|
// implementation of the soft-float routines in compiler-rt.
|
||||||
//
|
//
|
||||||
// Assumes that float and double correspond to the IEEE-754 binary32 and
|
// Assumes that float, double and long double correspond to the IEEE-754
|
||||||
// binary64 types, respectively, and that integer endianness matches floating
|
// binary32, binary64 and binary 128 types, respectively, and that integer
|
||||||
// point endianness on the target platform.
|
// endianness matches floating point endianness on the target platform.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef FP_LIB_HEADER
|
#ifndef FP_LIB_HEADER
|
||||||
#define FP_LIB_HEADER
|
#define FP_LIB_HEADER
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "int_lib.h"
|
||||||
|
#include "int_math.h"
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef unsigned long long uint64_t;
|
// x86_64 FreeBSD prior v9.3 define fixed-width types incorrectly in
|
||||||
|
// 32-bit mode.
|
||||||
#define UINT32_C(x) (x##U)
|
#if defined(__FreeBSD__) && defined(__i386__)
|
||||||
|
#include <sys/param.h>
|
||||||
|
#if __FreeBSD_version < 903000 // v9.3
|
||||||
|
#define uint64_t unsigned long long
|
||||||
|
#define int64_t long long
|
||||||
|
#undef UINT64_C
|
||||||
|
#define UINT64_C(c) (c##ULL)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined SINGLE_PRECISION
|
#if defined SINGLE_PRECISION
|
||||||
|
|
||||||
|
typedef uint16_t half_rep_t;
|
||||||
typedef uint32_t rep_t;
|
typedef uint32_t rep_t;
|
||||||
|
typedef uint64_t twice_rep_t;
|
||||||
typedef int32_t srep_t;
|
typedef int32_t srep_t;
|
||||||
typedef float fp_t;
|
typedef float fp_t;
|
||||||
|
#define HALF_REP_C UINT16_C
|
||||||
#define REP_C UINT32_C
|
#define REP_C UINT32_C
|
||||||
#define significandBits 23
|
#define significandBits 23
|
||||||
|
|
||||||
static inline int rep_clz(rep_t a)
|
static __inline int rep_clz(rep_t a) { return clzsi(a); }
|
||||||
{
|
|
||||||
return __builtin_clz(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 32x32 --> 64 bit multiply
|
// 32x32 --> 64 bit multiply
|
||||||
static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo)
|
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
|
||||||
{
|
const uint64_t product = (uint64_t)a * b;
|
||||||
const uint64_t product = (uint64_t)a*b;
|
*hi = product >> 32;
|
||||||
*hi = product >> 32;
|
*lo = product;
|
||||||
*lo = product;
|
|
||||||
}
|
}
|
||||||
|
COMPILER_RT_ABI fp_t __addsf3(fp_t a, fp_t b);
|
||||||
|
|
||||||
#elif defined DOUBLE_PRECISION
|
#elif defined DOUBLE_PRECISION
|
||||||
|
|
||||||
|
typedef uint32_t half_rep_t;
|
||||||
typedef uint64_t rep_t;
|
typedef uint64_t rep_t;
|
||||||
typedef int64_t srep_t;
|
typedef int64_t srep_t;
|
||||||
typedef double fp_t;
|
typedef double fp_t;
|
||||||
|
#define HALF_REP_C UINT32_C
|
||||||
#define REP_C UINT64_C
|
#define REP_C UINT64_C
|
||||||
#define significandBits 52
|
#define significandBits 52
|
||||||
|
|
||||||
static inline int rep_clz(rep_t a)
|
static __inline int rep_clz(rep_t a) {
|
||||||
{
|
|
||||||
#if defined __LP64__
|
#if defined __LP64__
|
||||||
return __builtin_clzl(a);
|
return __builtin_clzl(a);
|
||||||
#else
|
#else
|
||||||
if (a & REP_C(0xffffffff00000000))
|
if (a & REP_C(0xffffffff00000000))
|
||||||
return __builtin_clz(a >> 32);
|
return clzsi(a >> 32);
|
||||||
else
|
else
|
||||||
return 32 + __builtin_clz(a & REP_C(0xffffffff));
|
return 32 + clzsi(a & REP_C(0xffffffff));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,81 +86,241 @@ static inline int rep_clz(rep_t a)
|
|||||||
// 64x64 -> 128 wide multiply for platforms that don't have such an operation;
|
// 64x64 -> 128 wide multiply for platforms that don't have such an operation;
|
||||||
// many 64-bit platforms have this operation, but they tend to have hardware
|
// many 64-bit platforms have this operation, but they tend to have hardware
|
||||||
// floating-point, so we don't bother with a special case for them here.
|
// floating-point, so we don't bother with a special case for them here.
|
||||||
static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo)
|
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
|
||||||
{
|
// Each of the component 32x32 -> 64 products
|
||||||
// Each of the component 32x32 -> 64 products
|
const uint64_t plolo = loWord(a) * loWord(b);
|
||||||
const uint64_t plolo = loWord(a) * loWord(b);
|
const uint64_t plohi = loWord(a) * hiWord(b);
|
||||||
const uint64_t plohi = loWord(a) * hiWord(b);
|
const uint64_t philo = hiWord(a) * loWord(b);
|
||||||
const uint64_t philo = hiWord(a) * loWord(b);
|
const uint64_t phihi = hiWord(a) * hiWord(b);
|
||||||
const uint64_t phihi = hiWord(a) * hiWord(b);
|
// Sum terms that contribute to lo in a way that allows us to get the carry
|
||||||
// Sum terms that contribute to lo in a way that allows us to get the carry
|
const uint64_t r0 = loWord(plolo);
|
||||||
const uint64_t r0 = loWord(plolo);
|
const uint64_t r1 = hiWord(plolo) + loWord(plohi) + loWord(philo);
|
||||||
const uint64_t r1 = hiWord(plolo) + loWord(plohi) + loWord(philo);
|
*lo = r0 + (r1 << 32);
|
||||||
*lo = r0 + (r1 << 32);
|
// Sum terms contributing to hi with the carry from lo
|
||||||
// Sum terms contributing to hi with the carry from lo
|
*hi = hiWord(plohi) + hiWord(philo) + hiWord(r1) + phihi;
|
||||||
*hi = hiWord(plohi) + hiWord(philo) + hiWord(r1) + phihi;
|
}
|
||||||
|
#undef loWord
|
||||||
|
#undef hiWord
|
||||||
|
|
||||||
|
COMPILER_RT_ABI fp_t __adddf3(fp_t a, fp_t b);
|
||||||
|
|
||||||
|
#elif defined QUAD_PRECISION
|
||||||
|
#if __LDBL_MANT_DIG__ == 113 && defined(__SIZEOF_INT128__)
|
||||||
|
#define CRT_LDBL_128BIT
|
||||||
|
typedef uint64_t half_rep_t;
|
||||||
|
typedef __uint128_t rep_t;
|
||||||
|
typedef __int128_t srep_t;
|
||||||
|
typedef long double fp_t;
|
||||||
|
#define HALF_REP_C UINT64_C
|
||||||
|
#define REP_C (__uint128_t)
|
||||||
|
// Note: Since there is no explicit way to tell compiler the constant is a
|
||||||
|
// 128-bit integer, we let the constant be casted to 128-bit integer
|
||||||
|
#define significandBits 112
|
||||||
|
|
||||||
|
static __inline int rep_clz(rep_t a) {
|
||||||
|
const union {
|
||||||
|
__uint128_t ll;
|
||||||
|
#if _YUGA_BIG_ENDIAN
|
||||||
|
struct {
|
||||||
|
uint64_t high, low;
|
||||||
|
} s;
|
||||||
|
#else
|
||||||
|
struct {
|
||||||
|
uint64_t low, high;
|
||||||
|
} s;
|
||||||
|
#endif
|
||||||
|
} uu = {.ll = a};
|
||||||
|
|
||||||
|
uint64_t word;
|
||||||
|
uint64_t add;
|
||||||
|
|
||||||
|
if (uu.s.high) {
|
||||||
|
word = uu.s.high;
|
||||||
|
add = 0;
|
||||||
|
} else {
|
||||||
|
word = uu.s.low;
|
||||||
|
add = 64;
|
||||||
|
}
|
||||||
|
return __builtin_clzll(word) + add;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define Word_LoMask UINT64_C(0x00000000ffffffff)
|
||||||
|
#define Word_HiMask UINT64_C(0xffffffff00000000)
|
||||||
|
#define Word_FullMask UINT64_C(0xffffffffffffffff)
|
||||||
|
#define Word_1(a) (uint64_t)((a >> 96) & Word_LoMask)
|
||||||
|
#define Word_2(a) (uint64_t)((a >> 64) & Word_LoMask)
|
||||||
|
#define Word_3(a) (uint64_t)((a >> 32) & Word_LoMask)
|
||||||
|
#define Word_4(a) (uint64_t)(a & Word_LoMask)
|
||||||
|
|
||||||
|
// 128x128 -> 256 wide multiply for platforms that don't have such an operation;
|
||||||
|
// many 64-bit platforms have this operation, but they tend to have hardware
|
||||||
|
// floating-point, so we don't bother with a special case for them here.
|
||||||
|
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
|
||||||
|
|
||||||
|
const uint64_t product11 = Word_1(a) * Word_1(b);
|
||||||
|
const uint64_t product12 = Word_1(a) * Word_2(b);
|
||||||
|
const uint64_t product13 = Word_1(a) * Word_3(b);
|
||||||
|
const uint64_t product14 = Word_1(a) * Word_4(b);
|
||||||
|
const uint64_t product21 = Word_2(a) * Word_1(b);
|
||||||
|
const uint64_t product22 = Word_2(a) * Word_2(b);
|
||||||
|
const uint64_t product23 = Word_2(a) * Word_3(b);
|
||||||
|
const uint64_t product24 = Word_2(a) * Word_4(b);
|
||||||
|
const uint64_t product31 = Word_3(a) * Word_1(b);
|
||||||
|
const uint64_t product32 = Word_3(a) * Word_2(b);
|
||||||
|
const uint64_t product33 = Word_3(a) * Word_3(b);
|
||||||
|
const uint64_t product34 = Word_3(a) * Word_4(b);
|
||||||
|
const uint64_t product41 = Word_4(a) * Word_1(b);
|
||||||
|
const uint64_t product42 = Word_4(a) * Word_2(b);
|
||||||
|
const uint64_t product43 = Word_4(a) * Word_3(b);
|
||||||
|
const uint64_t product44 = Word_4(a) * Word_4(b);
|
||||||
|
|
||||||
|
const __uint128_t sum0 = (__uint128_t)product44;
|
||||||
|
const __uint128_t sum1 = (__uint128_t)product34 + (__uint128_t)product43;
|
||||||
|
const __uint128_t sum2 =
|
||||||
|
(__uint128_t)product24 + (__uint128_t)product33 + (__uint128_t)product42;
|
||||||
|
const __uint128_t sum3 = (__uint128_t)product14 + (__uint128_t)product23 +
|
||||||
|
(__uint128_t)product32 + (__uint128_t)product41;
|
||||||
|
const __uint128_t sum4 =
|
||||||
|
(__uint128_t)product13 + (__uint128_t)product22 + (__uint128_t)product31;
|
||||||
|
const __uint128_t sum5 = (__uint128_t)product12 + (__uint128_t)product21;
|
||||||
|
const __uint128_t sum6 = (__uint128_t)product11;
|
||||||
|
|
||||||
|
const __uint128_t r0 = (sum0 & Word_FullMask) + ((sum1 & Word_LoMask) << 32);
|
||||||
|
const __uint128_t r1 = (sum0 >> 64) + ((sum1 >> 32) & Word_FullMask) +
|
||||||
|
(sum2 & Word_FullMask) + ((sum3 << 32) & Word_HiMask);
|
||||||
|
|
||||||
|
*lo = r0 + (r1 << 64);
|
||||||
|
*hi = (r1 >> 64) + (sum1 >> 96) + (sum2 >> 64) + (sum3 >> 32) + sum4 +
|
||||||
|
(sum5 << 32) + (sum6 << 64);
|
||||||
|
}
|
||||||
|
#undef Word_1
|
||||||
|
#undef Word_2
|
||||||
|
#undef Word_3
|
||||||
|
#undef Word_4
|
||||||
|
#undef Word_HiMask
|
||||||
|
#undef Word_LoMask
|
||||||
|
#undef Word_FullMask
|
||||||
|
#endif // __LDBL_MANT_DIG__ == 113 && __SIZEOF_INT128__
|
||||||
#else
|
#else
|
||||||
#error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined.
|
#error SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define typeWidth (sizeof(rep_t)*CHAR_BIT)
|
#if defined(SINGLE_PRECISION) || defined(DOUBLE_PRECISION) || \
|
||||||
#define exponentBits (typeWidth - significandBits - 1)
|
defined(CRT_LDBL_128BIT)
|
||||||
#define maxExponent ((1 << exponentBits) - 1)
|
#define typeWidth (sizeof(rep_t) * CHAR_BIT)
|
||||||
#define exponentBias (maxExponent >> 1)
|
#define exponentBits (typeWidth - significandBits - 1)
|
||||||
|
#define maxExponent ((1 << exponentBits) - 1)
|
||||||
|
#define exponentBias (maxExponent >> 1)
|
||||||
|
|
||||||
#define implicitBit (REP_C(1) << significandBits)
|
#define implicitBit (REP_C(1) << significandBits)
|
||||||
#define significandMask (implicitBit - 1U)
|
#define significandMask (implicitBit - 1U)
|
||||||
#define signBit (REP_C(1) << (significandBits + exponentBits))
|
#define signBit (REP_C(1) << (significandBits + exponentBits))
|
||||||
#define absMask (signBit - 1U)
|
#define absMask (signBit - 1U)
|
||||||
#define exponentMask (absMask ^ significandMask)
|
#define exponentMask (absMask ^ significandMask)
|
||||||
#define oneRep ((rep_t)exponentBias << significandBits)
|
#define oneRep ((rep_t)exponentBias << significandBits)
|
||||||
#define infRep exponentMask
|
#define infRep exponentMask
|
||||||
#define quietBit (implicitBit >> 1)
|
#define quietBit (implicitBit >> 1)
|
||||||
#define qnanRep (exponentMask | quietBit)
|
#define qnanRep (exponentMask | quietBit)
|
||||||
|
|
||||||
static inline rep_t toRep(fp_t x)
|
static __inline rep_t toRep(fp_t x) {
|
||||||
{
|
const union {
|
||||||
const union { fp_t f; rep_t i; } rep = {.f = x};
|
fp_t f;
|
||||||
return rep.i;
|
rep_t i;
|
||||||
|
} rep = {.f = x};
|
||||||
|
return rep.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline fp_t fromRep(rep_t x)
|
static __inline fp_t fromRep(rep_t x) {
|
||||||
{
|
const union {
|
||||||
const union { fp_t f; rep_t i; } rep = {.i = x};
|
fp_t f;
|
||||||
return rep.f;
|
rep_t i;
|
||||||
|
} rep = {.i = x};
|
||||||
|
return rep.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int normalize(rep_t *significand)
|
static __inline int normalize(rep_t *significand) {
|
||||||
{
|
const int shift = rep_clz(*significand) - rep_clz(implicitBit);
|
||||||
const int shift = rep_clz(*significand) - rep_clz(implicitBit);
|
*significand <<= shift;
|
||||||
*significand <<= shift;
|
return 1 - shift;
|
||||||
return 1 - shift;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void wideLeftShift(rep_t *hi, rep_t *lo, int count)
|
static __inline void wideLeftShift(rep_t *hi, rep_t *lo, int count) {
|
||||||
{
|
*hi = *hi << count | *lo >> (typeWidth - count);
|
||||||
*hi = *hi << count | *lo >> (typeWidth - count);
|
*lo = *lo << count;
|
||||||
*lo = *lo << count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo, unsigned int count)
|
static __inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo,
|
||||||
{
|
unsigned int count) {
|
||||||
if (count < typeWidth) {
|
if (count < typeWidth) {
|
||||||
int sticky = (*lo << (typeWidth - count)) != 0;
|
const bool sticky = (*lo << (typeWidth - count)) != 0;
|
||||||
*lo = *hi << (typeWidth - count) | *lo >> count | sticky;
|
*lo = *hi << (typeWidth - count) | *lo >> count | sticky;
|
||||||
*hi = *hi >> count;
|
*hi = *hi >> count;
|
||||||
}
|
} else if (count < 2 * typeWidth) {
|
||||||
else if (count < 2*typeWidth) {
|
const bool sticky = *hi << (2 * typeWidth - count) | *lo;
|
||||||
int sticky = (*hi << (2*typeWidth - count) | *lo) != 0;
|
*lo = *hi >> (count - typeWidth) | sticky;
|
||||||
*lo = *hi >> (count - typeWidth) | sticky;
|
*hi = 0;
|
||||||
*hi = 0;
|
} else {
|
||||||
|
const bool sticky = *hi | *lo;
|
||||||
|
*lo = sticky;
|
||||||
|
*hi = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements logb methods (logb, logbf, logbl) for IEEE-754. This avoids
|
||||||
|
// pulling in a libm dependency from compiler-rt, but is not meant to replace
|
||||||
|
// it (i.e. code calling logb() should get the one from libm, not this), hence
|
||||||
|
// the __compiler_rt prefix.
|
||||||
|
static __inline fp_t __compiler_rt_logbX(fp_t x) {
|
||||||
|
rep_t rep = toRep(x);
|
||||||
|
int exp = (rep & exponentMask) >> significandBits;
|
||||||
|
|
||||||
|
// Abnormal cases:
|
||||||
|
// 1) +/- inf returns +inf; NaN returns NaN
|
||||||
|
// 2) 0.0 returns -inf
|
||||||
|
if (exp == maxExponent) {
|
||||||
|
if (((rep & signBit) == 0) || (x != x)) {
|
||||||
|
return x; // NaN or +inf: return x
|
||||||
} else {
|
} else {
|
||||||
int sticky = (*hi | *lo) != 0;
|
return -x; // -inf: return -x
|
||||||
*lo = sticky;
|
|
||||||
*hi = 0;
|
|
||||||
}
|
}
|
||||||
|
} else if (x == 0.0) {
|
||||||
|
// 0.0: return -inf
|
||||||
|
return fromRep(infRep | signBit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp != 0) {
|
||||||
|
// Normal number
|
||||||
|
return exp - exponentBias; // Unbias exponent
|
||||||
|
} else {
|
||||||
|
// Subnormal number; normalize and repeat
|
||||||
|
rep &= absMask;
|
||||||
|
const int shift = 1 - normalize(&rep);
|
||||||
|
exp = (rep & exponentMask) >> significandBits;
|
||||||
|
return exp - exponentBias - shift; // Unbias exponent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SINGLE_PRECISION)
|
||||||
|
static __inline fp_t __compiler_rt_logbf(fp_t x) {
|
||||||
|
return __compiler_rt_logbX(x);
|
||||||
|
}
|
||||||
|
#elif defined(DOUBLE_PRECISION)
|
||||||
|
static __inline fp_t __compiler_rt_logb(fp_t x) {
|
||||||
|
return __compiler_rt_logbX(x);
|
||||||
|
}
|
||||||
|
#elif defined(QUAD_PRECISION)
|
||||||
|
#if defined(CRT_LDBL_128BIT)
|
||||||
|
static __inline fp_t __compiler_rt_logbl(fp_t x) {
|
||||||
|
return __compiler_rt_logbX(x);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// The generic implementation only works for ieee754 floating point. For other
|
||||||
|
// floating point types, continue to rely on the libm implementation for now.
|
||||||
|
static __inline long double __compiler_rt_logbl(long double x) {
|
||||||
|
return crt_logbl(x);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // FP_LIB_HEADER
|
#endif // FP_LIB_HEADER
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
//===-- lib/mulsf3.c - Single-precision multiplication ------------*- C -*-===//
|
//===-- lib/mulsf3.c - Single-precision multiplication ------------*- C -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
//
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
@@ -13,98 +12,14 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
#define SINGLE_PRECISION
|
||||||
#include "fp_lib.h"
|
#include "fp_mul_impl.inc"
|
||||||
|
|
||||||
fp_t
|
COMPILER_RT_ABI fp_t __mulsf3(fp_t a, fp_t b) { return __mulXf3__(a, b); }
|
||||||
__mulsf3(fp_t a, fp_t b)
|
|
||||||
{
|
|
||||||
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
|
|
||||||
const unsigned int bExponent = toRep(b) >> significandBits & maxExponent;
|
|
||||||
const rep_t productSign = (toRep(a) ^ toRep(b)) & signBit;
|
|
||||||
|
|
||||||
rep_t aSignificand = toRep(a) & significandMask;
|
#if defined(__ARM_EABI__)
|
||||||
rep_t bSignificand = toRep(b) & significandMask;
|
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||||
int scale = 0;
|
AEABI_RTABI fp_t __aeabi_fmul(fp_t a, fp_t b) { return __mulsf3(a, b); }
|
||||||
|
#else
|
||||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
COMPILER_RT_ALIAS(__mulsf3, __aeabi_fmul)
|
||||||
if (aExponent-1U >= maxExponent-1U || bExponent-1U >= maxExponent-1U) {
|
#endif
|
||||||
|
#endif
|
||||||
const rep_t aAbs = toRep(a) & absMask;
|
|
||||||
const rep_t bAbs = toRep(b) & absMask;
|
|
||||||
|
|
||||||
// NaN * anything = qNaN
|
|
||||||
if (aAbs > infRep) return fromRep(toRep(a) | quietBit);
|
|
||||||
// anything * NaN = qNaN
|
|
||||||
if (bAbs > infRep) return fromRep(toRep(b) | quietBit);
|
|
||||||
|
|
||||||
if (aAbs == infRep) {
|
|
||||||
// infinity * non-zero = +/- infinity
|
|
||||||
if (bAbs) return fromRep(aAbs | productSign);
|
|
||||||
// infinity * zero = NaN
|
|
||||||
else return fromRep(qnanRep);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bAbs == infRep) {
|
|
||||||
// non-zero * infinity = +/- infinity
|
|
||||||
if (aAbs) return fromRep(bAbs | productSign);
|
|
||||||
// zero * infinity = NaN
|
|
||||||
else return fromRep(qnanRep);
|
|
||||||
}
|
|
||||||
|
|
||||||
// zero * anything = +/- zero
|
|
||||||
if (!aAbs) return fromRep(productSign);
|
|
||||||
// anything * zero = +/- zero
|
|
||||||
if (!bAbs) return fromRep(productSign);
|
|
||||||
|
|
||||||
// one or both of a or b is denormal, the other (if applicable) is a
|
|
||||||
// normal number. Renormalize one or both of a and b, and set scale to
|
|
||||||
// include the necessary exponent adjustment.
|
|
||||||
if (aAbs < implicitBit) scale += normalize(&aSignificand);
|
|
||||||
if (bAbs < implicitBit) scale += normalize(&bSignificand);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Or in the implicit significand bit. (If we fell through from the
|
|
||||||
// denormal path it was already set by normalize( ), but setting it twice
|
|
||||||
// won't hurt anything.)
|
|
||||||
aSignificand |= implicitBit;
|
|
||||||
bSignificand |= implicitBit;
|
|
||||||
|
|
||||||
// Get the significand of a*b. Before multiplying the significands, shift
|
|
||||||
// one of them left to left-align it in the field. Thus, the product will
|
|
||||||
// have (exponentBits + 2) integral digits, all but two of which must be
|
|
||||||
// zero. Normalizing this result is just a conditional left-shift by one
|
|
||||||
// and bumping the exponent accordingly.
|
|
||||||
rep_t productHi, productLo;
|
|
||||||
wideMultiply(aSignificand, bSignificand << exponentBits,
|
|
||||||
&productHi, &productLo);
|
|
||||||
|
|
||||||
int productExponent = aExponent + bExponent - exponentBias + scale;
|
|
||||||
|
|
||||||
// Normalize the significand, adjust exponent if needed.
|
|
||||||
if (productHi & implicitBit) productExponent++;
|
|
||||||
else wideLeftShift(&productHi, &productLo, 1);
|
|
||||||
|
|
||||||
// If we have overflowed the type, return +/- infinity.
|
|
||||||
if (productExponent >= maxExponent) return fromRep(infRep | productSign);
|
|
||||||
|
|
||||||
if (productExponent <= 0) {
|
|
||||||
// Result is denormal before rounding, the exponent is zero and we
|
|
||||||
// need to shift the significand.
|
|
||||||
wideRightShiftWithSticky(&productHi, &productLo, 1U - (unsigned)productExponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
// Result is normal before rounding; insert the exponent.
|
|
||||||
productHi &= significandMask;
|
|
||||||
productHi |= (rep_t)productExponent << significandBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the sign of the result:
|
|
||||||
productHi |= productSign;
|
|
||||||
|
|
||||||
// Final rounding. The final result may overflow to infinity, or underflow
|
|
||||||
// to zero, but those are the correct results in those cases.
|
|
||||||
if (productLo > signBit) productHi++;
|
|
||||||
if (productLo == signBit) productHi += productHi & 1;
|
|
||||||
return fromRep(productHi);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
//===-- lib/negsf2.c - single-precision negation ------------------*- C -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements single-precision soft-float negation.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
|
||||||
#include "fp_lib.h"
|
|
||||||
|
|
||||||
fp_t
|
|
||||||
__negsf2(fp_t a)
|
|
||||||
{
|
|
||||||
return fromRep(toRep(a) ^ signBit);
|
|
||||||
}
|
|
||||||
@@ -1,25 +1,27 @@
|
|||||||
//===-- lib/subsf3.c - Single-precision subtraction ---------------*- C -*-===//
|
//===-- lib/subsf3.c - Single-precision subtraction ---------------*- C -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
//
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// This file implements single-precision soft-float subtraction with the
|
// This file implements single-precision soft-float subtraction.
|
||||||
// IEEE-754 default rounding (to nearest, ties to even).
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
#define SINGLE_PRECISION
|
||||||
#include "fp_lib.h"
|
#include "fp_lib.h"
|
||||||
|
|
||||||
fp_t __addsf3(fp_t a, fp_t b);
|
|
||||||
|
|
||||||
// Subtraction; flip the sign bit of b and add.
|
// Subtraction; flip the sign bit of b and add.
|
||||||
fp_t
|
COMPILER_RT_ABI fp_t __subsf3(fp_t a, fp_t b) {
|
||||||
__subsf3(fp_t a, fp_t b)
|
return __addsf3(a, fromRep(toRep(b) ^ signBit));
|
||||||
{
|
|
||||||
return __addsf3(a, fromRep(toRep(b) ^ signBit));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__ARM_EABI__)
|
||||||
|
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||||
|
AEABI_RTABI fp_t __aeabi_fsub(fp_t a, fp_t b) { return __subsf3(a, b); }
|
||||||
|
#else
|
||||||
|
COMPILER_RT_ALIAS(__subsf3, __aeabi_fsub)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
TOPSRC = $(shell cd ../..; pwd)
|
|
||||||
include $(TOPSRC)/target.mk
|
|
||||||
|
|
||||||
CFLAGS += ${DEFS} -Werror -Wall
|
|
||||||
|
|
||||||
OBJS = adddf3.o \
|
|
||||||
addsf3.o \
|
|
||||||
divdf3.o \
|
|
||||||
divsf3.o \
|
|
||||||
comparedf2.o \
|
|
||||||
comparesf2.o \
|
|
||||||
extendsfdf2.o \
|
|
||||||
fixdfsi.o \
|
|
||||||
fixsfsi.o \
|
|
||||||
floatsidf.o \
|
|
||||||
floatsisf.o \
|
|
||||||
floatunsisf.o \
|
|
||||||
fp_mode.o \
|
|
||||||
muldf3.o \
|
|
||||||
mulsf3.o \
|
|
||||||
subdf3.o \
|
|
||||||
subsf3.o \
|
|
||||||
truncdfsf2.o
|
|
||||||
|
|
||||||
all: ../libclang.a
|
|
||||||
|
|
||||||
../libclang.a: ${OBJS}
|
|
||||||
$(AR) cru $@ ${OBJS}
|
|
||||||
$(RANLIB) $@
|
|
||||||
|
|
||||||
install: all
|
|
||||||
# ${INSTALLDIR} ${DESTDIR}/lib
|
|
||||||
# ${INSTALL} ../libclang.a ${DESTDIR}/lib/libclang.a
|
|
||||||
# $(RANLIB) ${DESTDIR}/lib/libclang.a
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f ../libclang.a *.o *~ tags
|
|
||||||
@@ -1,353 +0,0 @@
|
|||||||
Compiler-RT
|
|
||||||
================================
|
|
||||||
|
|
||||||
This directory and its subdirectories contain source code for the compiler
|
|
||||||
support routines.
|
|
||||||
|
|
||||||
Compiler-RT is open source software. You may freely distribute it under the
|
|
||||||
terms of the license agreement found in LICENSE.txt.
|
|
||||||
|
|
||||||
================================
|
|
||||||
|
|
||||||
This is a replacement library for libgcc. Each function is contained
|
|
||||||
in its own file. Each function has a corresponding unit test under
|
|
||||||
test/Unit.
|
|
||||||
|
|
||||||
A rudimentary script to test each file is in the file called
|
|
||||||
test/Unit/test.
|
|
||||||
|
|
||||||
Here is the specification for this library:
|
|
||||||
|
|
||||||
http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc
|
|
||||||
|
|
||||||
Please note that the libgcc specification explicitly mentions actual types of
|
|
||||||
arguments and returned values being expressed with machine modes.
|
|
||||||
In some cases particular types such as "int", "unsigned", "long long", etc.
|
|
||||||
may be specified just as examples there.
|
|
||||||
|
|
||||||
Here is a synopsis of the contents of this library:
|
|
||||||
|
|
||||||
typedef int32_t si_int;
|
|
||||||
typedef uint32_t su_int;
|
|
||||||
|
|
||||||
typedef int64_t di_int;
|
|
||||||
typedef uint64_t du_int;
|
|
||||||
|
|
||||||
// Integral bit manipulation
|
|
||||||
|
|
||||||
di_int __ashldi3(di_int a, si_int b); // a << b
|
|
||||||
ti_int __ashlti3(ti_int a, si_int b); // a << b
|
|
||||||
|
|
||||||
di_int __ashrdi3(di_int a, si_int b); // a >> b arithmetic (sign fill)
|
|
||||||
ti_int __ashrti3(ti_int a, si_int b); // a >> b arithmetic (sign fill)
|
|
||||||
di_int __lshrdi3(di_int a, si_int b); // a >> b logical (zero fill)
|
|
||||||
ti_int __lshrti3(ti_int a, si_int b); // a >> b logical (zero fill)
|
|
||||||
|
|
||||||
int __clzsi2(si_int a); // count leading zeros
|
|
||||||
int __clzdi2(di_int a); // count leading zeros
|
|
||||||
int __clzti2(ti_int a); // count leading zeros
|
|
||||||
int __ctzsi2(si_int a); // count trailing zeros
|
|
||||||
int __ctzdi2(di_int a); // count trailing zeros
|
|
||||||
int __ctzti2(ti_int a); // count trailing zeros
|
|
||||||
|
|
||||||
int __ffssi2(si_int a); // find least significant 1 bit
|
|
||||||
int __ffsdi2(di_int a); // find least significant 1 bit
|
|
||||||
int __ffsti2(ti_int a); // find least significant 1 bit
|
|
||||||
|
|
||||||
int __paritysi2(si_int a); // bit parity
|
|
||||||
int __paritydi2(di_int a); // bit parity
|
|
||||||
int __parityti2(ti_int a); // bit parity
|
|
||||||
|
|
||||||
int __popcountsi2(si_int a); // bit population
|
|
||||||
int __popcountdi2(di_int a); // bit population
|
|
||||||
int __popcountti2(ti_int a); // bit population
|
|
||||||
|
|
||||||
uint32_t __bswapsi2(uint32_t a); // a byteswapped
|
|
||||||
uint64_t __bswapdi2(uint64_t a); // a byteswapped
|
|
||||||
|
|
||||||
// Integral arithmetic
|
|
||||||
|
|
||||||
di_int __negdi2 (di_int a); // -a
|
|
||||||
ti_int __negti2 (ti_int a); // -a
|
|
||||||
di_int __muldi3 (di_int a, di_int b); // a * b
|
|
||||||
ti_int __multi3 (ti_int a, ti_int b); // a * b
|
|
||||||
si_int __divsi3 (si_int a, si_int b); // a / b signed
|
|
||||||
di_int __divdi3 (di_int a, di_int b); // a / b signed
|
|
||||||
ti_int __divti3 (ti_int a, ti_int b); // a / b signed
|
|
||||||
su_int __udivsi3 (su_int n, su_int d); // a / b unsigned
|
|
||||||
du_int __udivdi3 (du_int a, du_int b); // a / b unsigned
|
|
||||||
tu_int __udivti3 (tu_int a, tu_int b); // a / b unsigned
|
|
||||||
si_int __modsi3 (si_int a, si_int b); // a % b signed
|
|
||||||
di_int __moddi3 (di_int a, di_int b); // a % b signed
|
|
||||||
ti_int __modti3 (ti_int a, ti_int b); // a % b signed
|
|
||||||
su_int __umodsi3 (su_int a, su_int b); // a % b unsigned
|
|
||||||
du_int __umoddi3 (du_int a, du_int b); // a % b unsigned
|
|
||||||
tu_int __umodti3 (tu_int a, tu_int b); // a % b unsigned
|
|
||||||
du_int __udivmoddi4(du_int a, du_int b, du_int* rem); // a / b, *rem = a % b unsigned
|
|
||||||
tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); // a / b, *rem = a % b unsigned
|
|
||||||
su_int __udivmodsi4(su_int a, su_int b, su_int* rem); // a / b, *rem = a % b unsigned
|
|
||||||
si_int __divmodsi4(si_int a, si_int b, si_int* rem); // a / b, *rem = a % b signed
|
|
||||||
di_int __divmoddi4(di_int a, di_int b, di_int* rem); // a / b, *rem = a % b signed
|
|
||||||
ti_int __divmodti4(ti_int a, ti_int b, ti_int* rem); // a / b, *rem = a % b signed
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Integral arithmetic with trapping overflow
|
|
||||||
|
|
||||||
si_int __absvsi2(si_int a); // abs(a)
|
|
||||||
di_int __absvdi2(di_int a); // abs(a)
|
|
||||||
ti_int __absvti2(ti_int a); // abs(a)
|
|
||||||
|
|
||||||
si_int __negvsi2(si_int a); // -a
|
|
||||||
di_int __negvdi2(di_int a); // -a
|
|
||||||
ti_int __negvti2(ti_int a); // -a
|
|
||||||
|
|
||||||
si_int __addvsi3(si_int a, si_int b); // a + b
|
|
||||||
di_int __addvdi3(di_int a, di_int b); // a + b
|
|
||||||
ti_int __addvti3(ti_int a, ti_int b); // a + b
|
|
||||||
|
|
||||||
si_int __subvsi3(si_int a, si_int b); // a - b
|
|
||||||
di_int __subvdi3(di_int a, di_int b); // a - b
|
|
||||||
ti_int __subvti3(ti_int a, ti_int b); // a - b
|
|
||||||
|
|
||||||
si_int __mulvsi3(si_int a, si_int b); // a * b
|
|
||||||
di_int __mulvdi3(di_int a, di_int b); // a * b
|
|
||||||
ti_int __mulvti3(ti_int a, ti_int b); // a * b
|
|
||||||
|
|
||||||
|
|
||||||
// Integral arithmetic which returns if overflow
|
|
||||||
|
|
||||||
si_int __mulosi4(si_int a, si_int b, int* overflow); // a * b, overflow set to one if result not in signed range
|
|
||||||
di_int __mulodi4(di_int a, di_int b, int* overflow); // a * b, overflow set to one if result not in signed range
|
|
||||||
ti_int __muloti4(ti_int a, ti_int b, int* overflow); // a * b, overflow set to
|
|
||||||
one if result not in signed range
|
|
||||||
|
|
||||||
|
|
||||||
// Integral comparison: a < b -> 0
|
|
||||||
// a == b -> 1
|
|
||||||
// a > b -> 2
|
|
||||||
|
|
||||||
si_int __cmpdi2 (di_int a, di_int b);
|
|
||||||
si_int __cmpti2 (ti_int a, ti_int b);
|
|
||||||
si_int __ucmpdi2(du_int a, du_int b);
|
|
||||||
si_int __ucmpti2(tu_int a, tu_int b);
|
|
||||||
|
|
||||||
// Integral / floating point conversion
|
|
||||||
|
|
||||||
di_int __fixsfdi( float a);
|
|
||||||
di_int __fixdfdi( double a);
|
|
||||||
di_int __fixxfdi(long double a);
|
|
||||||
|
|
||||||
ti_int __fixsfti( float a);
|
|
||||||
ti_int __fixdfti( double a);
|
|
||||||
ti_int __fixxfti(long double a);
|
|
||||||
uint64_t __fixtfdi(long double input); // ppc only, doesn't match documentation
|
|
||||||
|
|
||||||
su_int __fixunssfsi( float a);
|
|
||||||
su_int __fixunsdfsi( double a);
|
|
||||||
su_int __fixunsxfsi(long double a);
|
|
||||||
|
|
||||||
du_int __fixunssfdi( float a);
|
|
||||||
du_int __fixunsdfdi( double a);
|
|
||||||
du_int __fixunsxfdi(long double a);
|
|
||||||
|
|
||||||
tu_int __fixunssfti( float a);
|
|
||||||
tu_int __fixunsdfti( double a);
|
|
||||||
tu_int __fixunsxfti(long double a);
|
|
||||||
uint64_t __fixunstfdi(long double input); // ppc only
|
|
||||||
|
|
||||||
float __floatdisf(di_int a);
|
|
||||||
double __floatdidf(di_int a);
|
|
||||||
long double __floatdixf(di_int a);
|
|
||||||
long double __floatditf(int64_t a); // ppc only
|
|
||||||
|
|
||||||
float __floattisf(ti_int a);
|
|
||||||
double __floattidf(ti_int a);
|
|
||||||
long double __floattixf(ti_int a);
|
|
||||||
|
|
||||||
float __floatundisf(du_int a);
|
|
||||||
double __floatundidf(du_int a);
|
|
||||||
long double __floatundixf(du_int a);
|
|
||||||
long double __floatunditf(uint64_t a); // ppc only
|
|
||||||
|
|
||||||
float __floatuntisf(tu_int a);
|
|
||||||
double __floatuntidf(tu_int a);
|
|
||||||
long double __floatuntixf(tu_int a);
|
|
||||||
|
|
||||||
// Floating point raised to integer power
|
|
||||||
|
|
||||||
float __powisf2( float a, int b); // a ^ b
|
|
||||||
double __powidf2( double a, int b); // a ^ b
|
|
||||||
long double __powixf2(long double a, int b); // a ^ b
|
|
||||||
long double __powitf2(long double a, int b); // ppc only, a ^ b
|
|
||||||
|
|
||||||
// Complex arithmetic
|
|
||||||
|
|
||||||
// (a + ib) * (c + id)
|
|
||||||
|
|
||||||
float _Complex __mulsc3( float a, float b, float c, float d);
|
|
||||||
double _Complex __muldc3(double a, double b, double c, double d);
|
|
||||||
long double _Complex __mulxc3(long double a, long double b,
|
|
||||||
long double c, long double d);
|
|
||||||
long double _Complex __multc3(long double a, long double b,
|
|
||||||
long double c, long double d); // ppc only
|
|
||||||
|
|
||||||
// (a + ib) / (c + id)
|
|
||||||
|
|
||||||
float _Complex __divsc3( float a, float b, float c, float d);
|
|
||||||
double _Complex __divdc3(double a, double b, double c, double d);
|
|
||||||
long double _Complex __divxc3(long double a, long double b,
|
|
||||||
long double c, long double d);
|
|
||||||
long double _Complex __divtc3(long double a, long double b,
|
|
||||||
long double c, long double d); // ppc only
|
|
||||||
|
|
||||||
|
|
||||||
// Runtime support
|
|
||||||
|
|
||||||
// __clear_cache() is used to tell process that new instructions have been
|
|
||||||
// written to an address range. Necessary on processors that do not have
|
|
||||||
// a unified instruction and data cache.
|
|
||||||
void __clear_cache(void* start, void* end);
|
|
||||||
|
|
||||||
// __enable_execute_stack() is used with nested functions when a trampoline
|
|
||||||
// function is written onto the stack and that page range needs to be made
|
|
||||||
// executable.
|
|
||||||
void __enable_execute_stack(void* addr);
|
|
||||||
|
|
||||||
// __gcc_personality_v0() is normally only called by the system unwinder.
|
|
||||||
// C code (as opposed to C++) normally does not need a personality function
|
|
||||||
// because there are no catch clauses or destructors to be run. But there
|
|
||||||
// is a C language extension __attribute__((cleanup(func))) which marks local
|
|
||||||
// variables as needing the cleanup function "func" to be run when the
|
|
||||||
// variable goes out of scope. That includes when an exception is thrown,
|
|
||||||
// so a personality handler is needed.
|
|
||||||
_Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions,
|
|
||||||
uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject,
|
|
||||||
_Unwind_Context_t context);
|
|
||||||
|
|
||||||
// for use with some implementations of assert() in <assert.h>
|
|
||||||
void __eprintf(const char* format, const char* assertion_expression,
|
|
||||||
const char* line, const char* file);
|
|
||||||
|
|
||||||
// for systems with emulated thread local storage
|
|
||||||
void* __emutls_get_address(struct __emutls_control*);
|
|
||||||
|
|
||||||
|
|
||||||
// Power PC specific functions
|
|
||||||
|
|
||||||
// There is no C interface to the saveFP/restFP functions. They are helper
|
|
||||||
// functions called by the prolog and epilog of functions that need to save
|
|
||||||
// a number of non-volatile float point registers.
|
|
||||||
saveFP
|
|
||||||
restFP
|
|
||||||
|
|
||||||
// PowerPC has a standard template for trampoline functions. This function
|
|
||||||
// generates a custom trampoline function with the specific realFunc
|
|
||||||
// and localsPtr values.
|
|
||||||
void __trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,
|
|
||||||
const void* realFunc, void* localsPtr);
|
|
||||||
|
|
||||||
// adds two 128-bit double-double precision values ( x + y )
|
|
||||||
long double __gcc_qadd(long double x, long double y);
|
|
||||||
|
|
||||||
// subtracts two 128-bit double-double precision values ( x - y )
|
|
||||||
long double __gcc_qsub(long double x, long double y);
|
|
||||||
|
|
||||||
// multiples two 128-bit double-double precision values ( x * y )
|
|
||||||
long double __gcc_qmul(long double x, long double y);
|
|
||||||
|
|
||||||
// divides two 128-bit double-double precision values ( x / y )
|
|
||||||
long double __gcc_qdiv(long double a, long double b);
|
|
||||||
|
|
||||||
|
|
||||||
// ARM specific functions
|
|
||||||
|
|
||||||
// There is no C interface to the switch* functions. These helper functions
|
|
||||||
// are only needed by Thumb1 code for efficient switch table generation.
|
|
||||||
switch16
|
|
||||||
switch32
|
|
||||||
switch8
|
|
||||||
switchu8
|
|
||||||
|
|
||||||
// There is no C interface to the *_vfp_d8_d15_regs functions. There are
|
|
||||||
// called in the prolog and epilog of Thumb1 functions. When the C++ ABI use
|
|
||||||
// SJLJ for exceptions, each function with a catch clause or destuctors needs
|
|
||||||
// to save and restore all registers in it prolog and epliog. But there is
|
|
||||||
// no way to access vector and high float registers from thumb1 code, so the
|
|
||||||
// compiler must add call outs to these helper functions in the prolog and
|
|
||||||
// epilog.
|
|
||||||
restore_vfp_d8_d15_regs
|
|
||||||
save_vfp_d8_d15_regs
|
|
||||||
|
|
||||||
|
|
||||||
// Note: long ago ARM processors did not have floating point hardware support.
|
|
||||||
// Floating point was done in software and floating point parameters were
|
|
||||||
// passed in integer registers. When hardware support was added for floating
|
|
||||||
// point, new *vfp functions were added to do the same operations but with
|
|
||||||
// floating point parameters in floating point registers.
|
|
||||||
|
|
||||||
// Undocumented functions
|
|
||||||
|
|
||||||
float __addsf3vfp(float a, float b); // Appears to return a + b
|
|
||||||
double __adddf3vfp(double a, double b); // Appears to return a + b
|
|
||||||
float __divsf3vfp(float a, float b); // Appears to return a / b
|
|
||||||
double __divdf3vfp(double a, double b); // Appears to return a / b
|
|
||||||
int __eqsf2vfp(float a, float b); // Appears to return one
|
|
||||||
// iff a == b and neither is NaN.
|
|
||||||
int __eqdf2vfp(double a, double b); // Appears to return one
|
|
||||||
// iff a == b and neither is NaN.
|
|
||||||
double __extendsfdf2vfp(float a); // Appears to convert from
|
|
||||||
// float to double.
|
|
||||||
int __fixdfsivfp(double a); // Appears to convert from
|
|
||||||
// double to int.
|
|
||||||
int __fixsfsivfp(float a); // Appears to convert from
|
|
||||||
// float to int.
|
|
||||||
unsigned int __fixunssfsivfp(float a); // Appears to convert from
|
|
||||||
// float to unsigned int.
|
|
||||||
unsigned int __fixunsdfsivfp(double a); // Appears to convert from
|
|
||||||
// double to unsigned int.
|
|
||||||
double __floatsidfvfp(int a); // Appears to convert from
|
|
||||||
// int to double.
|
|
||||||
float __floatsisfvfp(int a); // Appears to convert from
|
|
||||||
// int to float.
|
|
||||||
double __floatunssidfvfp(unsigned int a); // Appears to convert from
|
|
||||||
// unisgned int to double.
|
|
||||||
float __floatunssisfvfp(unsigned int a); // Appears to convert from
|
|
||||||
// unisgned int to float.
|
|
||||||
int __gedf2vfp(double a, double b); // Appears to return __gedf2
|
|
||||||
// (a >= b)
|
|
||||||
int __gesf2vfp(float a, float b); // Appears to return __gesf2
|
|
||||||
// (a >= b)
|
|
||||||
int __gtdf2vfp(double a, double b); // Appears to return __gtdf2
|
|
||||||
// (a > b)
|
|
||||||
int __gtsf2vfp(float a, float b); // Appears to return __gtsf2
|
|
||||||
// (a > b)
|
|
||||||
int __ledf2vfp(double a, double b); // Appears to return __ledf2
|
|
||||||
// (a <= b)
|
|
||||||
int __lesf2vfp(float a, float b); // Appears to return __lesf2
|
|
||||||
// (a <= b)
|
|
||||||
int __ltdf2vfp(double a, double b); // Appears to return __ltdf2
|
|
||||||
// (a < b)
|
|
||||||
int __ltsf2vfp(float a, float b); // Appears to return __ltsf2
|
|
||||||
// (a < b)
|
|
||||||
double __muldf3vfp(double a, double b); // Appears to return a * b
|
|
||||||
float __mulsf3vfp(float a, float b); // Appears to return a * b
|
|
||||||
int __nedf2vfp(double a, double b); // Appears to return __nedf2
|
|
||||||
// (a != b)
|
|
||||||
double __negdf2vfp(double a); // Appears to return -a
|
|
||||||
float __negsf2vfp(float a); // Appears to return -a
|
|
||||||
float __negsf2vfp(float a); // Appears to return -a
|
|
||||||
double __subdf3vfp(double a, double b); // Appears to return a - b
|
|
||||||
float __subsf3vfp(float a, float b); // Appears to return a - b
|
|
||||||
float __truncdfsf2vfp(double a); // Appears to convert from
|
|
||||||
// double to float.
|
|
||||||
int __unorddf2vfp(double a, double b); // Appears to return __unorddf2
|
|
||||||
int __unordsf2vfp(float a, float b); // Appears to return __unordsf2
|
|
||||||
|
|
||||||
|
|
||||||
Preconditions are listed for each function at the definition when there are any.
|
|
||||||
Any preconditions reflect the specification at
|
|
||||||
http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc.
|
|
||||||
|
|
||||||
Assumptions are listed in "int_lib.h", and in individual files. Where possible
|
|
||||||
assumptions are checked at compile time.
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
//===-- lib/addsf3.c - Single-precision addition ------------------*- C -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements single-precision soft-float addition.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
|
||||||
#include "fp_add_impl.inc"
|
|
||||||
|
|
||||||
COMPILER_RT_ABI float __addsf3(float a, float b) { return __addXf3__(a, b); }
|
|
||||||
|
|
||||||
#if defined(__ARM_EABI__)
|
|
||||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
|
||||||
AEABI_RTABI float __aeabi_fadd(float a, float b) { return __addsf3(a, b); }
|
|
||||||
#else
|
|
||||||
COMPILER_RT_ALIAS(__addsf3, __aeabi_fadd)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
//===-- lib/comparesf2.c - Single-precision comparisons -----------*- C -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements the following soft-fp_t comparison routines:
|
|
||||||
//
|
|
||||||
// __eqsf2 __gesf2 __unordsf2
|
|
||||||
// __lesf2 __gtsf2
|
|
||||||
// __ltsf2
|
|
||||||
// __nesf2
|
|
||||||
//
|
|
||||||
// The semantics of the routines grouped in each column are identical, so there
|
|
||||||
// is a single implementation for each, and wrappers to provide the other names.
|
|
||||||
//
|
|
||||||
// The main routines behave as follows:
|
|
||||||
//
|
|
||||||
// __lesf2(a,b) returns -1 if a < b
|
|
||||||
// 0 if a == b
|
|
||||||
// 1 if a > b
|
|
||||||
// 1 if either a or b is NaN
|
|
||||||
//
|
|
||||||
// __gesf2(a,b) returns -1 if a < b
|
|
||||||
// 0 if a == b
|
|
||||||
// 1 if a > b
|
|
||||||
// -1 if either a or b is NaN
|
|
||||||
//
|
|
||||||
// __unordsf2(a,b) returns 0 if both a and b are numbers
|
|
||||||
// 1 if either a or b is NaN
|
|
||||||
//
|
|
||||||
// Note that __lesf2( ) and __gesf2( ) are identical except in their handling of
|
|
||||||
// NaN values.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
|
||||||
#include "fp_lib.h"
|
|
||||||
|
|
||||||
enum LE_RESULT { LE_LESS = -1, LE_EQUAL = 0, LE_GREATER = 1, LE_UNORDERED = 1 };
|
|
||||||
|
|
||||||
COMPILER_RT_ABI enum LE_RESULT __lesf2(fp_t a, fp_t b) {
|
|
||||||
|
|
||||||
const srep_t aInt = toRep(a);
|
|
||||||
const srep_t bInt = toRep(b);
|
|
||||||
const rep_t aAbs = aInt & absMask;
|
|
||||||
const rep_t bAbs = bInt & absMask;
|
|
||||||
|
|
||||||
// If either a or b is NaN, they are unordered.
|
|
||||||
if (aAbs > infRep || bAbs > infRep)
|
|
||||||
return LE_UNORDERED;
|
|
||||||
|
|
||||||
// If a and b are both zeros, they are equal.
|
|
||||||
if ((aAbs | bAbs) == 0)
|
|
||||||
return LE_EQUAL;
|
|
||||||
|
|
||||||
// If at least one of a and b is positive, we get the same result comparing
|
|
||||||
// a and b as signed integers as we would with a fp_ting-point compare.
|
|
||||||
if ((aInt & bInt) >= 0) {
|
|
||||||
if (aInt < bInt)
|
|
||||||
return LE_LESS;
|
|
||||||
else if (aInt == bInt)
|
|
||||||
return LE_EQUAL;
|
|
||||||
else
|
|
||||||
return LE_GREATER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, both are negative, so we need to flip the sense of the
|
|
||||||
// comparison to get the correct result. (This assumes a twos- or ones-
|
|
||||||
// complement integer representation; if integers are represented in a
|
|
||||||
// sign-magnitude representation, then this flip is incorrect).
|
|
||||||
else {
|
|
||||||
if (aInt > bInt)
|
|
||||||
return LE_LESS;
|
|
||||||
else if (aInt == bInt)
|
|
||||||
return LE_EQUAL;
|
|
||||||
else
|
|
||||||
return LE_GREATER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__ELF__)
|
|
||||||
// Alias for libgcc compatibility
|
|
||||||
COMPILER_RT_ALIAS(__lesf2, __cmpsf2)
|
|
||||||
#endif
|
|
||||||
COMPILER_RT_ALIAS(__lesf2, __eqsf2)
|
|
||||||
COMPILER_RT_ALIAS(__lesf2, __ltsf2)
|
|
||||||
COMPILER_RT_ALIAS(__lesf2, __nesf2)
|
|
||||||
|
|
||||||
enum GE_RESULT {
|
|
||||||
GE_LESS = -1,
|
|
||||||
GE_EQUAL = 0,
|
|
||||||
GE_GREATER = 1,
|
|
||||||
GE_UNORDERED = -1 // Note: different from LE_UNORDERED
|
|
||||||
};
|
|
||||||
|
|
||||||
COMPILER_RT_ABI enum GE_RESULT __gesf2(fp_t a, fp_t b) {
|
|
||||||
|
|
||||||
const srep_t aInt = toRep(a);
|
|
||||||
const srep_t bInt = toRep(b);
|
|
||||||
const rep_t aAbs = aInt & absMask;
|
|
||||||
const rep_t bAbs = bInt & absMask;
|
|
||||||
|
|
||||||
if (aAbs > infRep || bAbs > infRep)
|
|
||||||
return GE_UNORDERED;
|
|
||||||
if ((aAbs | bAbs) == 0)
|
|
||||||
return GE_EQUAL;
|
|
||||||
if ((aInt & bInt) >= 0) {
|
|
||||||
if (aInt < bInt)
|
|
||||||
return GE_LESS;
|
|
||||||
else if (aInt == bInt)
|
|
||||||
return GE_EQUAL;
|
|
||||||
else
|
|
||||||
return GE_GREATER;
|
|
||||||
} else {
|
|
||||||
if (aInt > bInt)
|
|
||||||
return GE_LESS;
|
|
||||||
else if (aInt == bInt)
|
|
||||||
return GE_EQUAL;
|
|
||||||
else
|
|
||||||
return GE_GREATER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
COMPILER_RT_ALIAS(__gesf2, __gtsf2)
|
|
||||||
|
|
||||||
COMPILER_RT_ABI int
|
|
||||||
__unordsf2(fp_t a, fp_t b) {
|
|
||||||
const rep_t aAbs = toRep(a) & absMask;
|
|
||||||
const rep_t bAbs = toRep(b) & absMask;
|
|
||||||
return aAbs > infRep || bAbs > infRep;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__ARM_EABI__)
|
|
||||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
|
||||||
AEABI_RTABI int __aeabi_fcmpun(fp_t a, fp_t b) { return __unordsf2(a, b); }
|
|
||||||
#else
|
|
||||||
COMPILER_RT_ALIAS(__unordsf2, __aeabi_fcmpun)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
|
||||||
// The alias mechanism doesn't work on Windows except for MinGW, so emit
|
|
||||||
// wrapper functions.
|
|
||||||
int __eqsf2(fp_t a, fp_t b) { return __lesf2(a, b); }
|
|
||||||
int __ltsf2(fp_t a, fp_t b) { return __lesf2(a, b); }
|
|
||||||
int __nesf2(fp_t a, fp_t b) { return __lesf2(a, b); }
|
|
||||||
int __gtsf2(fp_t a, fp_t b) { return __gesf2(a, b); }
|
|
||||||
#endif
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
//===-- lib/divsf3.c - Single-precision division ------------------*- C -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements single-precision soft-float division
|
|
||||||
// with the IEEE-754 default rounding (to nearest, ties to even).
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
|
||||||
|
|
||||||
#define NUMBER_OF_HALF_ITERATIONS 0
|
|
||||||
#define NUMBER_OF_FULL_ITERATIONS 3
|
|
||||||
#define USE_NATIVE_FULL_ITERATIONS
|
|
||||||
|
|
||||||
#include "fp_div_impl.inc"
|
|
||||||
|
|
||||||
COMPILER_RT_ABI fp_t __divsf3(fp_t a, fp_t b) { return __divXf3__(a, b); }
|
|
||||||
|
|
||||||
#if defined(__ARM_EABI__)
|
|
||||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
|
||||||
AEABI_RTABI fp_t __aeabi_fdiv(fp_t a, fp_t b) { return __divsf3(a, b); }
|
|
||||||
#else
|
|
||||||
COMPILER_RT_ALIAS(__divsf3, __aeabi_fdiv)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
//===-- fixsfsi.c - Implement __fixsfsi -----------------------------------===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
|
||||||
#include "fp_lib.h"
|
|
||||||
typedef si_int fixint_t;
|
|
||||||
typedef su_int fixuint_t;
|
|
||||||
#include "fp_fixint_impl.inc"
|
|
||||||
|
|
||||||
COMPILER_RT_ABI si_int __fixsfsi(fp_t a) { return __fixint(a); }
|
|
||||||
|
|
||||||
#if defined(__ARM_EABI__)
|
|
||||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
|
||||||
AEABI_RTABI si_int __aeabi_f2iz(fp_t a) { return __fixsfsi(a); }
|
|
||||||
#else
|
|
||||||
COMPILER_RT_ALIAS(__fixsfsi, __aeabi_f2iz)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
//===-- lib/floatsisf.c - integer -> single-precision conversion --*- C -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements integer to single-precision conversion for the
|
|
||||||
// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even
|
|
||||||
// mode.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
|
||||||
#include "fp_lib.h"
|
|
||||||
|
|
||||||
#include "int_lib.h"
|
|
||||||
|
|
||||||
COMPILER_RT_ABI fp_t __floatsisf(int a) {
|
|
||||||
|
|
||||||
const int aWidth = sizeof a * CHAR_BIT;
|
|
||||||
|
|
||||||
// Handle zero as a special case to protect clz
|
|
||||||
if (a == 0)
|
|
||||||
return fromRep(0);
|
|
||||||
|
|
||||||
// All other cases begin by extracting the sign and absolute value of a
|
|
||||||
rep_t sign = 0;
|
|
||||||
if (a < 0) {
|
|
||||||
sign = signBit;
|
|
||||||
a = -a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exponent of (fp_t)a is the width of abs(a).
|
|
||||||
const int exponent = (aWidth - 1) - __builtin_clz(a);
|
|
||||||
rep_t result;
|
|
||||||
|
|
||||||
// Shift a into the significand field, rounding if it is a right-shift
|
|
||||||
if (exponent <= significandBits) {
|
|
||||||
const int shift = significandBits - exponent;
|
|
||||||
result = (rep_t)a << shift ^ implicitBit;
|
|
||||||
} else {
|
|
||||||
const int shift = exponent - significandBits;
|
|
||||||
result = (rep_t)a >> shift ^ implicitBit;
|
|
||||||
rep_t round = (rep_t)a << (typeWidth - shift);
|
|
||||||
if (round > signBit)
|
|
||||||
result++;
|
|
||||||
if (round == signBit)
|
|
||||||
result += result & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the exponent
|
|
||||||
result += (rep_t)(exponent + exponentBias) << significandBits;
|
|
||||||
// Insert the sign bit and return
|
|
||||||
return fromRep(result | sign);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__ARM_EABI__)
|
|
||||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
|
||||||
AEABI_RTABI fp_t __aeabi_i2f(int a) { return __floatsisf(a); }
|
|
||||||
#else
|
|
||||||
COMPILER_RT_ALIAS(__floatsisf, __aeabi_i2f)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
//===-- lib/floatunsisf.c - uint -> single-precision conversion ---*- C -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements unsigned integer to single-precision conversion for the
|
|
||||||
// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even
|
|
||||||
// mode.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
|
||||||
#include "fp_lib.h"
|
|
||||||
|
|
||||||
#include "int_lib.h"
|
|
||||||
|
|
||||||
COMPILER_RT_ABI fp_t __floatunsisf(unsigned int a) {
|
|
||||||
|
|
||||||
const int aWidth = sizeof a * CHAR_BIT;
|
|
||||||
|
|
||||||
// Handle zero as a special case to protect clz
|
|
||||||
if (a == 0)
|
|
||||||
return fromRep(0);
|
|
||||||
|
|
||||||
// Exponent of (fp_t)a is the width of abs(a).
|
|
||||||
const int exponent = (aWidth - 1) - __builtin_clz(a);
|
|
||||||
rep_t result;
|
|
||||||
|
|
||||||
// Shift a into the significand field, rounding if it is a right-shift
|
|
||||||
if (exponent <= significandBits) {
|
|
||||||
const int shift = significandBits - exponent;
|
|
||||||
result = (rep_t)a << shift ^ implicitBit;
|
|
||||||
} else {
|
|
||||||
const int shift = exponent - significandBits;
|
|
||||||
result = (rep_t)a >> shift ^ implicitBit;
|
|
||||||
rep_t round = (rep_t)a << (typeWidth - shift);
|
|
||||||
if (round > signBit)
|
|
||||||
result++;
|
|
||||||
if (round == signBit)
|
|
||||||
result += result & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the exponent
|
|
||||||
result += (rep_t)(exponent + exponentBias) << significandBits;
|
|
||||||
return fromRep(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__ARM_EABI__)
|
|
||||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
|
||||||
AEABI_RTABI fp_t __aeabi_ui2f(unsigned int a) { return __floatunsisf(a); }
|
|
||||||
#else
|
|
||||||
COMPILER_RT_ALIAS(__floatunsisf, __aeabi_ui2f)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -1,326 +0,0 @@
|
|||||||
//===-- lib/fp_lib.h - Floating-point utilities -------------------*- C -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file is a configuration header for soft-float routines in compiler-rt.
|
|
||||||
// This file does not provide any part of the compiler-rt interface, but defines
|
|
||||||
// many useful constants and utility routines that are used in the
|
|
||||||
// implementation of the soft-float routines in compiler-rt.
|
|
||||||
//
|
|
||||||
// Assumes that float, double and long double correspond to the IEEE-754
|
|
||||||
// binary32, binary64 and binary 128 types, respectively, and that integer
|
|
||||||
// endianness matches floating point endianness on the target platform.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef FP_LIB_HEADER
|
|
||||||
#define FP_LIB_HEADER
|
|
||||||
|
|
||||||
#include "int_lib.h"
|
|
||||||
#include "int_math.h"
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// x86_64 FreeBSD prior v9.3 define fixed-width types incorrectly in
|
|
||||||
// 32-bit mode.
|
|
||||||
#if defined(__FreeBSD__) && defined(__i386__)
|
|
||||||
#include <sys/param.h>
|
|
||||||
#if __FreeBSD_version < 903000 // v9.3
|
|
||||||
#define uint64_t unsigned long long
|
|
||||||
#define int64_t long long
|
|
||||||
#undef UINT64_C
|
|
||||||
#define UINT64_C(c) (c##ULL)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SINGLE_PRECISION
|
|
||||||
|
|
||||||
typedef uint16_t half_rep_t;
|
|
||||||
typedef uint32_t rep_t;
|
|
||||||
typedef uint64_t twice_rep_t;
|
|
||||||
typedef int32_t srep_t;
|
|
||||||
typedef float fp_t;
|
|
||||||
#define HALF_REP_C UINT16_C
|
|
||||||
#define REP_C UINT32_C
|
|
||||||
#define significandBits 23
|
|
||||||
|
|
||||||
static __inline int rep_clz(rep_t a) { return clzsi(a); }
|
|
||||||
|
|
||||||
// 32x32 --> 64 bit multiply
|
|
||||||
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
|
|
||||||
const uint64_t product = (uint64_t)a * b;
|
|
||||||
*hi = product >> 32;
|
|
||||||
*lo = product;
|
|
||||||
}
|
|
||||||
COMPILER_RT_ABI fp_t __addsf3(fp_t a, fp_t b);
|
|
||||||
|
|
||||||
#elif defined DOUBLE_PRECISION
|
|
||||||
|
|
||||||
typedef uint32_t half_rep_t;
|
|
||||||
typedef uint64_t rep_t;
|
|
||||||
typedef int64_t srep_t;
|
|
||||||
typedef double fp_t;
|
|
||||||
#define HALF_REP_C UINT32_C
|
|
||||||
#define REP_C UINT64_C
|
|
||||||
#define significandBits 52
|
|
||||||
|
|
||||||
static __inline int rep_clz(rep_t a) {
|
|
||||||
#if defined __LP64__
|
|
||||||
return __builtin_clzl(a);
|
|
||||||
#else
|
|
||||||
if (a & REP_C(0xffffffff00000000))
|
|
||||||
return clzsi(a >> 32);
|
|
||||||
else
|
|
||||||
return 32 + clzsi(a & REP_C(0xffffffff));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#define loWord(a) (a & 0xffffffffU)
|
|
||||||
#define hiWord(a) (a >> 32)
|
|
||||||
|
|
||||||
// 64x64 -> 128 wide multiply for platforms that don't have such an operation;
|
|
||||||
// many 64-bit platforms have this operation, but they tend to have hardware
|
|
||||||
// floating-point, so we don't bother with a special case for them here.
|
|
||||||
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
|
|
||||||
// Each of the component 32x32 -> 64 products
|
|
||||||
const uint64_t plolo = loWord(a) * loWord(b);
|
|
||||||
const uint64_t plohi = loWord(a) * hiWord(b);
|
|
||||||
const uint64_t philo = hiWord(a) * loWord(b);
|
|
||||||
const uint64_t phihi = hiWord(a) * hiWord(b);
|
|
||||||
// Sum terms that contribute to lo in a way that allows us to get the carry
|
|
||||||
const uint64_t r0 = loWord(plolo);
|
|
||||||
const uint64_t r1 = hiWord(plolo) + loWord(plohi) + loWord(philo);
|
|
||||||
*lo = r0 + (r1 << 32);
|
|
||||||
// Sum terms contributing to hi with the carry from lo
|
|
||||||
*hi = hiWord(plohi) + hiWord(philo) + hiWord(r1) + phihi;
|
|
||||||
}
|
|
||||||
#undef loWord
|
|
||||||
#undef hiWord
|
|
||||||
|
|
||||||
COMPILER_RT_ABI fp_t __adddf3(fp_t a, fp_t b);
|
|
||||||
|
|
||||||
#elif defined QUAD_PRECISION
|
|
||||||
#if __LDBL_MANT_DIG__ == 113 && defined(__SIZEOF_INT128__)
|
|
||||||
#define CRT_LDBL_128BIT
|
|
||||||
typedef uint64_t half_rep_t;
|
|
||||||
typedef __uint128_t rep_t;
|
|
||||||
typedef __int128_t srep_t;
|
|
||||||
typedef long double fp_t;
|
|
||||||
#define HALF_REP_C UINT64_C
|
|
||||||
#define REP_C (__uint128_t)
|
|
||||||
// Note: Since there is no explicit way to tell compiler the constant is a
|
|
||||||
// 128-bit integer, we let the constant be casted to 128-bit integer
|
|
||||||
#define significandBits 112
|
|
||||||
|
|
||||||
static __inline int rep_clz(rep_t a) {
|
|
||||||
const union {
|
|
||||||
__uint128_t ll;
|
|
||||||
#if _YUGA_BIG_ENDIAN
|
|
||||||
struct {
|
|
||||||
uint64_t high, low;
|
|
||||||
} s;
|
|
||||||
#else
|
|
||||||
struct {
|
|
||||||
uint64_t low, high;
|
|
||||||
} s;
|
|
||||||
#endif
|
|
||||||
} uu = {.ll = a};
|
|
||||||
|
|
||||||
uint64_t word;
|
|
||||||
uint64_t add;
|
|
||||||
|
|
||||||
if (uu.s.high) {
|
|
||||||
word = uu.s.high;
|
|
||||||
add = 0;
|
|
||||||
} else {
|
|
||||||
word = uu.s.low;
|
|
||||||
add = 64;
|
|
||||||
}
|
|
||||||
return __builtin_clzll(word) + add;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define Word_LoMask UINT64_C(0x00000000ffffffff)
|
|
||||||
#define Word_HiMask UINT64_C(0xffffffff00000000)
|
|
||||||
#define Word_FullMask UINT64_C(0xffffffffffffffff)
|
|
||||||
#define Word_1(a) (uint64_t)((a >> 96) & Word_LoMask)
|
|
||||||
#define Word_2(a) (uint64_t)((a >> 64) & Word_LoMask)
|
|
||||||
#define Word_3(a) (uint64_t)((a >> 32) & Word_LoMask)
|
|
||||||
#define Word_4(a) (uint64_t)(a & Word_LoMask)
|
|
||||||
|
|
||||||
// 128x128 -> 256 wide multiply for platforms that don't have such an operation;
|
|
||||||
// many 64-bit platforms have this operation, but they tend to have hardware
|
|
||||||
// floating-point, so we don't bother with a special case for them here.
|
|
||||||
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
|
|
||||||
|
|
||||||
const uint64_t product11 = Word_1(a) * Word_1(b);
|
|
||||||
const uint64_t product12 = Word_1(a) * Word_2(b);
|
|
||||||
const uint64_t product13 = Word_1(a) * Word_3(b);
|
|
||||||
const uint64_t product14 = Word_1(a) * Word_4(b);
|
|
||||||
const uint64_t product21 = Word_2(a) * Word_1(b);
|
|
||||||
const uint64_t product22 = Word_2(a) * Word_2(b);
|
|
||||||
const uint64_t product23 = Word_2(a) * Word_3(b);
|
|
||||||
const uint64_t product24 = Word_2(a) * Word_4(b);
|
|
||||||
const uint64_t product31 = Word_3(a) * Word_1(b);
|
|
||||||
const uint64_t product32 = Word_3(a) * Word_2(b);
|
|
||||||
const uint64_t product33 = Word_3(a) * Word_3(b);
|
|
||||||
const uint64_t product34 = Word_3(a) * Word_4(b);
|
|
||||||
const uint64_t product41 = Word_4(a) * Word_1(b);
|
|
||||||
const uint64_t product42 = Word_4(a) * Word_2(b);
|
|
||||||
const uint64_t product43 = Word_4(a) * Word_3(b);
|
|
||||||
const uint64_t product44 = Word_4(a) * Word_4(b);
|
|
||||||
|
|
||||||
const __uint128_t sum0 = (__uint128_t)product44;
|
|
||||||
const __uint128_t sum1 = (__uint128_t)product34 + (__uint128_t)product43;
|
|
||||||
const __uint128_t sum2 =
|
|
||||||
(__uint128_t)product24 + (__uint128_t)product33 + (__uint128_t)product42;
|
|
||||||
const __uint128_t sum3 = (__uint128_t)product14 + (__uint128_t)product23 +
|
|
||||||
(__uint128_t)product32 + (__uint128_t)product41;
|
|
||||||
const __uint128_t sum4 =
|
|
||||||
(__uint128_t)product13 + (__uint128_t)product22 + (__uint128_t)product31;
|
|
||||||
const __uint128_t sum5 = (__uint128_t)product12 + (__uint128_t)product21;
|
|
||||||
const __uint128_t sum6 = (__uint128_t)product11;
|
|
||||||
|
|
||||||
const __uint128_t r0 = (sum0 & Word_FullMask) + ((sum1 & Word_LoMask) << 32);
|
|
||||||
const __uint128_t r1 = (sum0 >> 64) + ((sum1 >> 32) & Word_FullMask) +
|
|
||||||
(sum2 & Word_FullMask) + ((sum3 << 32) & Word_HiMask);
|
|
||||||
|
|
||||||
*lo = r0 + (r1 << 64);
|
|
||||||
*hi = (r1 >> 64) + (sum1 >> 96) + (sum2 >> 64) + (sum3 >> 32) + sum4 +
|
|
||||||
(sum5 << 32) + (sum6 << 64);
|
|
||||||
}
|
|
||||||
#undef Word_1
|
|
||||||
#undef Word_2
|
|
||||||
#undef Word_3
|
|
||||||
#undef Word_4
|
|
||||||
#undef Word_HiMask
|
|
||||||
#undef Word_LoMask
|
|
||||||
#undef Word_FullMask
|
|
||||||
#endif // __LDBL_MANT_DIG__ == 113 && __SIZEOF_INT128__
|
|
||||||
#else
|
|
||||||
#error SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SINGLE_PRECISION) || defined(DOUBLE_PRECISION) || \
|
|
||||||
defined(CRT_LDBL_128BIT)
|
|
||||||
#define typeWidth (sizeof(rep_t) * CHAR_BIT)
|
|
||||||
#define exponentBits (typeWidth - significandBits - 1)
|
|
||||||
#define maxExponent ((1 << exponentBits) - 1)
|
|
||||||
#define exponentBias (maxExponent >> 1)
|
|
||||||
|
|
||||||
#define implicitBit (REP_C(1) << significandBits)
|
|
||||||
#define significandMask (implicitBit - 1U)
|
|
||||||
#define signBit (REP_C(1) << (significandBits + exponentBits))
|
|
||||||
#define absMask (signBit - 1U)
|
|
||||||
#define exponentMask (absMask ^ significandMask)
|
|
||||||
#define oneRep ((rep_t)exponentBias << significandBits)
|
|
||||||
#define infRep exponentMask
|
|
||||||
#define quietBit (implicitBit >> 1)
|
|
||||||
#define qnanRep (exponentMask | quietBit)
|
|
||||||
|
|
||||||
static __inline rep_t toRep(fp_t x) {
|
|
||||||
const union {
|
|
||||||
fp_t f;
|
|
||||||
rep_t i;
|
|
||||||
} rep = {.f = x};
|
|
||||||
return rep.i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline fp_t fromRep(rep_t x) {
|
|
||||||
const union {
|
|
||||||
fp_t f;
|
|
||||||
rep_t i;
|
|
||||||
} rep = {.i = x};
|
|
||||||
return rep.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline int normalize(rep_t *significand) {
|
|
||||||
const int shift = rep_clz(*significand) - rep_clz(implicitBit);
|
|
||||||
*significand <<= shift;
|
|
||||||
return 1 - shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline void wideLeftShift(rep_t *hi, rep_t *lo, int count) {
|
|
||||||
*hi = *hi << count | *lo >> (typeWidth - count);
|
|
||||||
*lo = *lo << count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo,
|
|
||||||
unsigned int count) {
|
|
||||||
if (count < typeWidth) {
|
|
||||||
const bool sticky = (*lo << (typeWidth - count)) != 0;
|
|
||||||
*lo = *hi << (typeWidth - count) | *lo >> count | sticky;
|
|
||||||
*hi = *hi >> count;
|
|
||||||
} else if (count < 2 * typeWidth) {
|
|
||||||
const bool sticky = *hi << (2 * typeWidth - count) | *lo;
|
|
||||||
*lo = *hi >> (count - typeWidth) | sticky;
|
|
||||||
*hi = 0;
|
|
||||||
} else {
|
|
||||||
const bool sticky = *hi | *lo;
|
|
||||||
*lo = sticky;
|
|
||||||
*hi = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements logb methods (logb, logbf, logbl) for IEEE-754. This avoids
|
|
||||||
// pulling in a libm dependency from compiler-rt, but is not meant to replace
|
|
||||||
// it (i.e. code calling logb() should get the one from libm, not this), hence
|
|
||||||
// the __compiler_rt prefix.
|
|
||||||
static __inline fp_t __compiler_rt_logbX(fp_t x) {
|
|
||||||
rep_t rep = toRep(x);
|
|
||||||
int exp = (rep & exponentMask) >> significandBits;
|
|
||||||
|
|
||||||
// Abnormal cases:
|
|
||||||
// 1) +/- inf returns +inf; NaN returns NaN
|
|
||||||
// 2) 0.0 returns -inf
|
|
||||||
if (exp == maxExponent) {
|
|
||||||
if (((rep & signBit) == 0) || (x != x)) {
|
|
||||||
return x; // NaN or +inf: return x
|
|
||||||
} else {
|
|
||||||
return -x; // -inf: return -x
|
|
||||||
}
|
|
||||||
} else if (x == 0.0) {
|
|
||||||
// 0.0: return -inf
|
|
||||||
return fromRep(infRep | signBit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp != 0) {
|
|
||||||
// Normal number
|
|
||||||
return exp - exponentBias; // Unbias exponent
|
|
||||||
} else {
|
|
||||||
// Subnormal number; normalize and repeat
|
|
||||||
rep &= absMask;
|
|
||||||
const int shift = 1 - normalize(&rep);
|
|
||||||
exp = (rep & exponentMask) >> significandBits;
|
|
||||||
return exp - exponentBias - shift; // Unbias exponent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SINGLE_PRECISION)
|
|
||||||
static __inline fp_t __compiler_rt_logbf(fp_t x) {
|
|
||||||
return __compiler_rt_logbX(x);
|
|
||||||
}
|
|
||||||
#elif defined(DOUBLE_PRECISION)
|
|
||||||
static __inline fp_t __compiler_rt_logb(fp_t x) {
|
|
||||||
return __compiler_rt_logbX(x);
|
|
||||||
}
|
|
||||||
#elif defined(QUAD_PRECISION)
|
|
||||||
#if defined(CRT_LDBL_128BIT)
|
|
||||||
static __inline fp_t __compiler_rt_logbl(fp_t x) {
|
|
||||||
return __compiler_rt_logbX(x);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// The generic implementation only works for ieee754 floating point. For other
|
|
||||||
// floating point types, continue to rely on the libm implementation for now.
|
|
||||||
static __inline long double __compiler_rt_logbl(long double x) {
|
|
||||||
return crt_logbl(x);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // FP_LIB_HEADER
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
//===-- lib/mulsf3.c - Single-precision multiplication ------------*- C -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements single-precision soft-float multiplication
|
|
||||||
// with the IEEE-754 default rounding (to nearest, ties to even).
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
|
||||||
#include "fp_mul_impl.inc"
|
|
||||||
|
|
||||||
COMPILER_RT_ABI fp_t __mulsf3(fp_t a, fp_t b) { return __mulXf3__(a, b); }
|
|
||||||
|
|
||||||
#if defined(__ARM_EABI__)
|
|
||||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
|
||||||
AEABI_RTABI fp_t __aeabi_fmul(fp_t a, fp_t b) { return __mulsf3(a, b); }
|
|
||||||
#else
|
|
||||||
COMPILER_RT_ALIAS(__mulsf3, __aeabi_fmul)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
//===-- lib/subsf3.c - Single-precision subtraction ---------------*- C -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements single-precision soft-float subtraction.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define SINGLE_PRECISION
|
|
||||||
#include "fp_lib.h"
|
|
||||||
|
|
||||||
// Subtraction; flip the sign bit of b and add.
|
|
||||||
COMPILER_RT_ABI fp_t __subsf3(fp_t a, fp_t b) {
|
|
||||||
return __addsf3(a, fromRep(toRep(b) ^ signBit));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__ARM_EABI__)
|
|
||||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
|
||||||
AEABI_RTABI fp_t __aeabi_fsub(fp_t a, fp_t b) { return __subsf3(a, b); }
|
|
||||||
#else
|
|
||||||
COMPILER_RT_ALIAS(__subsf3, __aeabi_fsub)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
static int outcol, outline, destcol, destline;
|
static int outcol, outline, destcol, destline;
|
||||||
|
|
||||||
WINDOW *_win;
|
extern WINDOW *_win;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move (slowly) to destination.
|
* Move (slowly) to destination.
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
#define MAXRETURNSIZE 64
|
#define MAXRETURNSIZE 64
|
||||||
|
|
||||||
char *UP;
|
extern char *UP;
|
||||||
char *BC;
|
extern char *BC;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routine to perform cursor addressing.
|
* Routine to perform cursor addressing.
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ static short tmspc10[] = {
|
|||||||
0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
|
0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
|
||||||
};
|
};
|
||||||
|
|
||||||
short ospeed;
|
extern short ospeed;
|
||||||
char PC;
|
extern char PC;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put the character string cp out, with padding.
|
* Put the character string cp out, with padding.
|
||||||
|
|||||||
@@ -60,7 +60,10 @@ ELF2AOUT = $(TOPSRC)/tools/elf2aout/elf2aout
|
|||||||
CFLAGS = -Os -nostdinc
|
CFLAGS = -Os -nostdinc
|
||||||
|
|
||||||
LDFLAGS = --nmagic -T$(TOPSRC)/src/elf32-mips.ld $(TOPSRC)/src/crt0.o -L$(TOPSRC)/src
|
LDFLAGS = --nmagic -T$(TOPSRC)/src/elf32-mips.ld $(TOPSRC)/src/crt0.o -L$(TOPSRC)/src
|
||||||
LIBS = -lc -lclang
|
LIBS = -lc
|
||||||
|
|
||||||
# Enable mips16e instruction set by default
|
# Enable mips16e instruction set by default
|
||||||
#CFLAGS += -mips16
|
#CFLAGS += -mips16
|
||||||
|
|
||||||
|
# Catch all warnings
|
||||||
|
CC += -Werror
|
||||||
|
|||||||
Reference in New Issue
Block a user