Move libclang into libc.
Catch all warnings.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -26,3 +26,4 @@
|
||||
*.img
|
||||
|
||||
Makefile.user
|
||||
TODO
|
||||
|
||||
@@ -9,8 +9,7 @@ include $(TOPSRC)/target.mk
|
||||
# Programs that live in subdirectories, and have makefiles of their own.
|
||||
#
|
||||
SUBDIR = startup-$(MACHINE) libc libm libutil libtermlib libcurses \
|
||||
libvmf libwiznet libreadline libgpanel share cmd games man \
|
||||
libclang
|
||||
libvmf libwiznet libreadline libgpanel share cmd games man
|
||||
|
||||
all: $(SUBDIR)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ CFLAGS += -Werror -Os
|
||||
|
||||
YACC = bison -y
|
||||
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
|
||||
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
|
||||
|
||||
@@ -30,7 +30,7 @@ struct xx
|
||||
{ INDIRECT, "indirect", "$("},
|
||||
{ SUBSTR, "substr", "substr"},
|
||||
{ INDEX, "sindex", "sindex"},
|
||||
{ SPRINTF, "asprintf", "sprintf "},
|
||||
{ SPRINTF, "awksprintf", "sprintf "},
|
||||
{ ADD, "arith", " + "},
|
||||
{ MINUS, "arith", " - "},
|
||||
{ MULT, "arith", " * "},
|
||||
|
||||
@@ -402,7 +402,7 @@ char *format(s,a) char *s; node *a;
|
||||
return(buf);
|
||||
}
|
||||
|
||||
obj asprintf1(a,n) node **a;
|
||||
obj awksprintf(a,n) node **a;
|
||||
{
|
||||
obj x;
|
||||
node *y;
|
||||
@@ -597,7 +597,7 @@ obj aprintf(a,n) node **a;
|
||||
{
|
||||
obj x;
|
||||
|
||||
x = asprintf1(a,n);
|
||||
x = awksprintf(a,n);
|
||||
if (a[1]==NULL) {
|
||||
printf("%s", x.optr->sval);
|
||||
tempfree(x);
|
||||
|
||||
@@ -27,7 +27,7 @@ TOPSRC = $(shell cd ../..; pwd)
|
||||
include $(TOPSRC)/target.mk
|
||||
|
||||
DEFS = -Wall -Werror
|
||||
ALL = gen stdio stdlib string inet compat ${MACHINE}
|
||||
ALL = gen stdio stdlib string inet compat runtime ${MACHINE}
|
||||
|
||||
all: ../libc.a
|
||||
|
||||
|
||||
@@ -19,20 +19,30 @@ include $(TOPSRC)/target.mk
|
||||
|
||||
CFLAGS += ${DEFS}
|
||||
|
||||
OBJS = addsf3.o comparesf2.o divsf3.o fixsfsi.o floatsisf.o \
|
||||
mulsf3.o negsf2.o subsf3.o sc_case.o fixunssfsi.o \
|
||||
floatunsisf.o
|
||||
|
||||
all: ${OBJS}
|
||||
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
|
||||
|
||||
runtime.a: ${OBJS}
|
||||
@echo "buiding runtime.a"
|
||||
@$(AR) cru runtime.a ${OBJS}
|
||||
clean:
|
||||
rm -f *.a *.o *~ profiled/*.o tags
|
||||
|
||||
cleandir: clean
|
||||
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
|
||||
|
||||
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 int si_int;
|
||||
typedef unsigned su_int;
|
||||
typedef int32_t si_int;
|
||||
typedef uint32_t su_int;
|
||||
|
||||
typedef long long di_int;
|
||||
typedef unsigned long long du_int;
|
||||
typedef int64_t di_int;
|
||||
typedef uint64_t du_int;
|
||||
|
||||
// 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)
|
||||
ti_int __lshrti3(ti_int a, si_int b); // a >> b logical (zero fill)
|
||||
|
||||
si_int __clzsi2(si_int a); // count leading zeros
|
||||
si_int __clzdi2(di_int a); // count leading zeros
|
||||
si_int __clzti2(ti_int a); // count leading zeros
|
||||
si_int __ctzsi2(si_int a); // count trailing zeros
|
||||
si_int __ctzdi2(di_int a); // count trailing zeros
|
||||
si_int __ctzti2(ti_int a); // count trailing zeros
|
||||
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
|
||||
|
||||
si_int __ffsdi2(di_int a); // find least significant 1 bit
|
||||
si_int __ffsti2(ti_int a); // find least significant 1 bit
|
||||
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
|
||||
|
||||
si_int __paritysi2(si_int a); // bit parity
|
||||
si_int __paritydi2(di_int a); // bit parity
|
||||
si_int __parityti2(ti_int a); // bit parity
|
||||
int __paritysi2(si_int a); // bit parity
|
||||
int __paritydi2(di_int a); // bit parity
|
||||
int __parityti2(ti_int a); // bit parity
|
||||
|
||||
si_int __popcountsi2(si_int a); // bit population
|
||||
si_int __popcountdi2(di_int a); // bit population
|
||||
si_int __popcountti2(ti_int a); // bit population
|
||||
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, arm only
|
||||
uint64_t __bswapdi2(uint64_t a); // a byteswapped, arm only
|
||||
uint32_t __bswapsi2(uint32_t a); // a byteswapped
|
||||
uint64_t __bswapdi2(uint64_t a); // a byteswapped
|
||||
|
||||
// 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
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -168,10 +176,10 @@ long double __floatuntixf(tu_int a);
|
||||
|
||||
// Floating point raised to integer power
|
||||
|
||||
float __powisf2( float a, si_int b); // a ^ b
|
||||
double __powidf2( double a, si_int b); // a ^ b
|
||||
long double __powixf2(long double a, si_int b); // a ^ b
|
||||
long double __powitf2(long double a, si_int b); // ppc only, a ^ b
|
||||
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
|
||||
|
||||
@@ -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
|
||||
// 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);
|
||||
|
||||
// __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>
|
||||
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
|
||||
|
||||
@@ -1,150 +1,24 @@
|
||||
//===-- lib/addsf3.c - Single-precision addition ------------------*- 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.
|
||||
// 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 with the IEEE-754
|
||||
// default rounding (to nearest, ties to even).
|
||||
// This file implements single-precision soft-float addition.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
#include "fp_add_impl.inc"
|
||||
|
||||
fp_t
|
||||
__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;
|
||||
COMPILER_RT_ABI float __addsf3(float a, float b) { return __addXf3__(a, b); }
|
||||
|
||||
// Detect if a or b is zero, infinity, or NaN.
|
||||
if (aAbs - 1U >= infRep - 1U || bAbs - 1U >= infRep - 1U) {
|
||||
|
||||
// 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 + -/+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);
|
||||
}
|
||||
#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,9 +1,8 @@
|
||||
//===-- lib/comparesf2.c - Single-precision comparisons -----------*- 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.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
@@ -40,104 +39,113 @@
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
enum LE_RESULT {
|
||||
LE_LESS = -1,
|
||||
LE_EQUAL = 0,
|
||||
LE_GREATER = 1,
|
||||
LE_UNORDERED = 1
|
||||
};
|
||||
enum LE_RESULT { LE_LESS = -1, LE_EQUAL = 0, LE_GREATER = 1, LE_UNORDERED = 1 };
|
||||
|
||||
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;
|
||||
COMPILER_RT_ABI enum LE_RESULT __lesf2(fp_t a, fp_t b) {
|
||||
|
||||
// If either a or b is NaN, they are unordered.
|
||||
if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
|
||||
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 a and b are both zeros, they are equal.
|
||||
if ((aAbs | bAbs) == 0) return LE_EQUAL;
|
||||
// If either a or b is NaN, they are unordered.
|
||||
if (aAbs > infRep || bAbs > infRep)
|
||||
return LE_UNORDERED;
|
||||
|
||||
// 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;
|
||||
}
|
||||
// If a and b are both zeros, they are equal.
|
||||
if ((aAbs | bAbs) == 0)
|
||||
return LE_EQUAL;
|
||||
|
||||
// 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 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
|
||||
GE_LESS = -1,
|
||||
GE_EQUAL = 0,
|
||||
GE_GREATER = 1,
|
||||
GE_UNORDERED = -1 // Note: different from LE_UNORDERED
|
||||
};
|
||||
|
||||
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;
|
||||
COMPILER_RT_ABI enum GE_RESULT __gesf2(fp_t a, fp_t b) {
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
__unordsf2(fp_t a, fp_t b)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// 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
|
||||
__eqsf2(fp_t a, fp_t b)
|
||||
{
|
||||
return __lesf2(a, b);
|
||||
}
|
||||
|
||||
enum LE_RESULT
|
||||
__ltsf2(fp_t a, fp_t b)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#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,165 +1,30 @@
|
||||
//===-- lib/divsf3.c - Single-precision division ------------------*- 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.
|
||||
// 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).
|
||||
//
|
||||
// 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
|
||||
#include "fp_lib.h"
|
||||
|
||||
fp_t
|
||||
__divsf3(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 quotientSign = (toRep(a) ^ toRep(b)) & signBit;
|
||||
#define NUMBER_OF_HALF_ITERATIONS 0
|
||||
#define NUMBER_OF_FULL_ITERATIONS 3
|
||||
#define USE_NATIVE_FULL_ITERATIONS
|
||||
|
||||
rep_t aSignificand = toRep(a) & significandMask;
|
||||
rep_t bSignificand = toRep(b) & significandMask;
|
||||
int scale = 0;
|
||||
#include "fp_div_impl.inc"
|
||||
|
||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
||||
if (aExponent-1U >= maxExponent-1U || bExponent-1U >= maxExponent-1U) {
|
||||
COMPILER_RT_ABI fp_t __divsf3(fp_t a, fp_t b) { return __divXf3__(a, b); }
|
||||
|
||||
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 / 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);
|
||||
}
|
||||
}
|
||||
#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,46 +1,23 @@
|
||||
//===-- lib/fixsfsi.c - Single-precision -> integer conversion ----*- C -*-===//
|
||||
//===-- fixsfsi.c - Implement __fixsfsi -----------------------------------===//
|
||||
//
|
||||
// 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 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.
|
||||
// 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"
|
||||
|
||||
int
|
||||
__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;
|
||||
COMPILER_RT_ABI si_int __fixsfsi(fp_t a) { return __fixint(a); }
|
||||
|
||||
// If 0 < exponent < significandBits, right shift to get the result.
|
||||
if ((unsigned int)exponent < significandBits) {
|
||||
return sign * (significand >> (significandBits - exponent));
|
||||
}
|
||||
|
||||
// If exponent is negative, the result is zero.
|
||||
else if (exponent < 0) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
#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,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 -*-===//
|
||||
//
|
||||
// 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.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
@@ -16,40 +15,51 @@
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
fp_t
|
||||
__floatsisf(int a)
|
||||
{
|
||||
const int aWidth = sizeof a * CHAR_BIT;
|
||||
#include "int_lib.h"
|
||||
|
||||
// Handle zero as a special case to protect clz
|
||||
if (a == 0)
|
||||
return fromRep(0);
|
||||
COMPILER_RT_ABI fp_t __floatsisf(int a) {
|
||||
|
||||
// All other cases begin by extracting the sign and absolute value of a
|
||||
rep_t sign = 0;
|
||||
if (a < 0) {
|
||||
sign = signBit;
|
||||
a = -a;
|
||||
}
|
||||
const int aWidth = sizeof a * CHAR_BIT;
|
||||
|
||||
// Exponent of (fp_t)a is the width of abs(a).
|
||||
const int exponent = (aWidth - 1) - __builtin_clz(a);
|
||||
rep_t result;
|
||||
// Handle zero as a special case to protect clz
|
||||
if (a == 0)
|
||||
return fromRep(0);
|
||||
|
||||
// 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;
|
||||
}
|
||||
// All other cases begin by extracting the sign and absolute value of a
|
||||
rep_t sign = 0;
|
||||
if (a < 0) {
|
||||
sign = signBit;
|
||||
a = -a;
|
||||
}
|
||||
|
||||
// Insert the exponent
|
||||
result += (rep_t)(exponent + exponentBias) << significandBits;
|
||||
// Insert the sign bit and return
|
||||
return fromRep(result | sign);
|
||||
// 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,9 +1,8 @@
|
||||
//===-- lib/floatunsisf.c - uint -> single-precision conversion ---*- 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.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
@@ -16,32 +15,43 @@
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
fp_t
|
||||
__floatunsisf(unsigned int a)
|
||||
{
|
||||
const int aWidth = sizeof a * CHAR_BIT;
|
||||
#include "int_lib.h"
|
||||
|
||||
// Handle zero as a special case to protect clz
|
||||
if (a == 0)
|
||||
return fromRep(0);
|
||||
COMPILER_RT_ABI fp_t __floatunsisf(unsigned int a) {
|
||||
|
||||
// Exponent of (fp_t)a is the width of abs(a).
|
||||
const int exponent = (aWidth - 1) - __builtin_clz(a);
|
||||
rep_t result;
|
||||
const int aWidth = sizeof a * CHAR_BIT;
|
||||
|
||||
// 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;
|
||||
}
|
||||
// Handle zero as a special case to protect clz
|
||||
if (a == 0)
|
||||
return fromRep(0);
|
||||
|
||||
// Insert the exponent
|
||||
result += (rep_t)(exponent + exponentBias) << significandBits;
|
||||
return fromRep(result);
|
||||
// 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,9 +1,8 @@
|
||||
//===-- lib/fp_lib.h - Floating-point utilities -------------------*- 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.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
@@ -12,60 +11,72 @@
|
||||
// many useful constants and utility routines that are used in the
|
||||
// implementation of the soft-float routines in compiler-rt.
|
||||
//
|
||||
// Assumes that float and double correspond to the IEEE-754 binary32 and
|
||||
// binary64 types, respectively, and that integer endianness matches floating
|
||||
// point endianness on the target platform.
|
||||
// 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 <stdint.h>
|
||||
#include "int_lib.h"
|
||||
#include "int_math.h"
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
#define UINT32_C(x) (x##U)
|
||||
// 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 __builtin_clz(a);
|
||||
}
|
||||
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;
|
||||
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)
|
||||
{
|
||||
static __inline int rep_clz(rep_t a) {
|
||||
#if defined __LP64__
|
||||
return __builtin_clzl(a);
|
||||
return __builtin_clzl(a);
|
||||
#else
|
||||
if (a & REP_C(0xffffffff00000000))
|
||||
return __builtin_clz(a >> 32);
|
||||
else
|
||||
return 32 + __builtin_clz(a & REP_C(0xffffffff));
|
||||
if (a & REP_C(0xffffffff00000000))
|
||||
return clzsi(a >> 32);
|
||||
else
|
||||
return 32 + clzsi(a & REP_C(0xffffffff));
|
||||
#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;
|
||||
// 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;
|
||||
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 Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined.
|
||||
#error SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined.
|
||||
#endif
|
||||
|
||||
#define typeWidth (sizeof(rep_t)*CHAR_BIT)
|
||||
#define exponentBits (typeWidth - significandBits - 1)
|
||||
#define maxExponent ((1 << exponentBits) - 1)
|
||||
#define exponentBias (maxExponent >> 1)
|
||||
#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 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)
|
||||
#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 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 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 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 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) {
|
||||
int sticky = (*lo << (typeWidth - count)) != 0;
|
||||
*lo = *hi << (typeWidth - count) | *lo >> count | sticky;
|
||||
*hi = *hi >> count;
|
||||
}
|
||||
else if (count < 2*typeWidth) {
|
||||
int sticky = (*hi << (2*typeWidth - count) | *lo) != 0;
|
||||
*lo = *hi >> (count - typeWidth) | sticky;
|
||||
*hi = 0;
|
||||
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 {
|
||||
int sticky = (*hi | *lo) != 0;
|
||||
*lo = sticky;
|
||||
*hi = 0;
|
||||
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,9 +1,8 @@
|
||||
//===-- lib/mulsf3.c - Single-precision multiplication ------------*- 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.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
@@ -13,98 +12,14 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
#include "fp_mul_impl.inc"
|
||||
|
||||
fp_t
|
||||
__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;
|
||||
COMPILER_RT_ABI fp_t __mulsf3(fp_t a, fp_t b) { return __mulXf3__(a, b); }
|
||||
|
||||
rep_t aSignificand = toRep(a) & significandMask;
|
||||
rep_t bSignificand = toRep(b) & significandMask;
|
||||
int scale = 0;
|
||||
|
||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
||||
if (aExponent-1U >= maxExponent-1U || bExponent-1U >= maxExponent-1U) {
|
||||
|
||||
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);
|
||||
}
|
||||
#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,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 -*-===//
|
||||
//
|
||||
// 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.
|
||||
// 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 with the
|
||||
// IEEE-754 default rounding (to nearest, ties to even).
|
||||
// This file implements single-precision soft-float subtraction.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
fp_t __addsf3(fp_t a, fp_t b);
|
||||
|
||||
// Subtraction; flip the sign bit of b and add.
|
||||
fp_t
|
||||
__subsf3(fp_t a, fp_t b)
|
||||
{
|
||||
return __addsf3(a, fromRep(toRep(b) ^ signBit));
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
WINDOW *_win;
|
||||
extern WINDOW *_win;
|
||||
|
||||
/*
|
||||
* Move (slowly) to destination.
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
#define MAXRETURNSIZE 64
|
||||
|
||||
char *UP;
|
||||
char *BC;
|
||||
extern char *UP;
|
||||
extern char *BC;
|
||||
|
||||
/*
|
||||
* 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
|
||||
};
|
||||
|
||||
short ospeed;
|
||||
char PC;
|
||||
extern short ospeed;
|
||||
extern char PC;
|
||||
|
||||
/*
|
||||
* Put the character string cp out, with padding.
|
||||
|
||||
@@ -60,7 +60,10 @@ ELF2AOUT = $(TOPSRC)/tools/elf2aout/elf2aout
|
||||
CFLAGS = -Os -nostdinc
|
||||
|
||||
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
|
||||
#CFLAGS += -mips16
|
||||
|
||||
# Catch all warnings
|
||||
CC += -Werror
|
||||
|
||||
Reference in New Issue
Block a user