Index: lib/builtins/adddf3.c =================================================================== --- lib/builtins/adddf3.c +++ lib/builtins/adddf3.c @@ -13,140 +13,10 @@ //===----------------------------------------------------------------------===// #define DOUBLE_PRECISION -#include "fp_lib.h" +#include "fp_add.h" ARM_EABI_FNALIAS(dadd, adddf3) -COMPILER_RT_ABI fp_t -__adddf3(fp_t a, fp_t b) { - - rep_t aRep = toRep(a); - rep_t bRep = toRep(b); - const rep_t aAbs = aRep & absMask; - const rep_t bAbs = bRep & absMask; - - // Detect if a or b is zero, infinity, or NaN. - if (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 bool subtraction = (aRep ^ bRep) & signBit; - - // 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 bool sticky = bSignificand << (typeWidth - align); - 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 bool 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 bool sticky = aSignificand << (typeWidth - shift); - 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); +double __adddf3(double a, double b){ + return __adddf3__(a, b); } Index: lib/builtins/addsf3.c =================================================================== --- lib/builtins/addsf3.c +++ lib/builtins/addsf3.c @@ -13,139 +13,10 @@ //===----------------------------------------------------------------------===// #define SINGLE_PRECISION -#include "fp_lib.h" +#include "fp_add.h" ARM_EABI_FNALIAS(fadd, addsf3) -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; - - // 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 bool subtraction = (aRep ^ bRep) & signBit; - - // 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 bool sticky = bSignificand << (typeWidth - align); - 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 bool 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 bool sticky = aSignificand << (typeWidth - shift); - 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); +float __addsf3(float a, float b) { + return __addsf3__(a, b); } Index: lib/builtins/addtf3.c =================================================================== --- /dev/null +++ lib/builtins/addtf3.c @@ -0,0 +1,25 @@ +//===-- lib/addtf3.c - Quad-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. +// +//===----------------------------------------------------------------------===// +// +// This file implements quad-precision soft-float addition with the IEEE-754 +// default rounding (to nearest, ties to even). +// +//===----------------------------------------------------------------------===// + +// __uint128_t is undefined in 32-bit machine toolchain +#if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 + +#define QUAD_PRECISION +#include "fp_add.h" + +long double __addtf3(long double a, long double b){ + return __addtf3__(a, b); +} + +#endif Index: lib/builtins/fp_add.h =================================================================== --- /dev/null +++ lib/builtins/fp_add.h @@ -0,0 +1,160 @@ +//===----- lib/fp_add.h - floaing point 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. +// +//===----------------------------------------------------------------------===// +// +// This file implements soft-float addition with the IEEE-754 default rounding +// (to nearest, ties to even). +// +//===----------------------------------------------------------------------===// + +#ifndef FP_ADD_HEADER +#define FP_ADD_HEADER + +#include "fp_lib.h" + +#define __ADDFP(name) \ +static inline fp_t __add##name##f3__(fp_t a, fp_t b) { \ + rep_t aRep = toRep(a); \ + rep_t bRep = toRep(b); \ + const rep_t aAbs = aRep & absMask; \ + const rep_t bAbs = bRep & absMask; \ + \ + /* Detect if a or b is zero, infinity, or NaN.*/ \ + if (aAbs - REP_C(1) >= infRep - REP_C(1) || \ + bAbs - REP_C(1) >= infRep - REP_C(1)) { \ + /* 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 bool subtraction = (aRep ^ bRep) & signBit; \ + \ + /* 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 bool sticky = bSignificand << (typeWidth - align); \ + 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 bool 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 bool sticky = aSignificand << (typeWidth - shift); \ + 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 SINGLE_PRECISION + COMPILER_RT_ABI __ADDFP(s); +#elif defined DOUBLE_PRECISION + COMPILER_RT_ABI __ADDFP(d); +#elif defined QUAD_PRECISION + COMPILER_RT_ABI __ADDFP(t); +#else +#error SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined. +#endif + +#endif // FP_ADD_HEADER Index: lib/builtins/subtf3.c =================================================================== --- /dev/null +++ lib/builtins/subtf3.c @@ -0,0 +1,29 @@ +//===-- lib/subtf3.c - Quad-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. +// +//===----------------------------------------------------------------------===// +// +// This file implements quad-precision soft-float subtraction with the +// IEEE-754 default rounding (to nearest, ties to even). +// +//===----------------------------------------------------------------------===// + +// __uint128_t is undefined in 32-bit machine toolchain +#if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 + +#define QUAD_PRECISION +#include "fp_lib.h" + +COMPILER_RT_ABI fp_t __addtf3(fp_t a, fp_t b); + +// Subtraction; flip the sign bit of b and add. +COMPILER_RT_ABI fp_t +__subtf3(fp_t a, fp_t b) { + return __addtf3(a, fromRep(toRep(b) ^ signBit)); +} + +#endif Index: test/builtins/Unit/addtf3_test.c =================================================================== --- /dev/null +++ test/builtins/Unit/addtf3_test.c @@ -0,0 +1,58 @@ +//===--------------- addtf3_test.c - Test __addtf3 ------------------------===// +// +// 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 tests __addtf3 for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +// __uint128_t is undefined in 32-bit machine toolchain +#if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 + +#include +#include +#include + +// Returns: a + b +long double __addtf3(long double a, long double b); + +int test__addtf3(long double a, long double b) +{ + long double x = __addtf3(a, b); + long double expected = a + b; + if (x != expected) + { + printf("error in test__addtf3(%.20Lf, %.20Lf) = %.20Lf, " + "expected %.20Lf\n", a, b, x, expected); + } + return x != expected; +} + +char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 + // Since NaN can't be compared with NaN, we don't test the + // cases that produce NaN result + + // inf + any = inf + if (test__addtf3(0x1.0p+16384L, 0x1.23456789abcdefp+5L)) + return 1; + // any + any + if (test__addtf3(0x1.23456789abcdefp+5L, 0x1.edcba987654321fp-1L)) + return 1; + +#else + printf("skipped\n"); + +#endif + return 0; +} Index: test/builtins/Unit/subtf3_test.c =================================================================== --- /dev/null +++ test/builtins/Unit/subtf3_test.c @@ -0,0 +1,57 @@ +//===--------------- subtf3_test.c - Test __subtf3 ------------------------===// +// +// 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 tests __subtf3 for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 + +#include +#include +#include + +// Returns: a - b +long double __subtf3(long double a, long double b); + +int test__subtf3(long double a, long double b) +{ + long double x = __subtf3(a, b); + long double expected = a - b; + if (x != expected) + { + printf("error in test__subtf3(%.20Lf, %.20Lf) = %.20Lf, " + "expected %.20Lf\n", a, b, x, expected); + } + return x != expected; +} + +char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 + // Since NaN can't be compared with NaN, we don't test the + // cases that produce NaN result + + // inf - any = inf + if (test__subtf3(0x1.0p+16384L, 0x1.23456789abcdefp+5L)) + return 1; + // any - any + if (test__subtf3(0x1.23456789abcdefp+5L, 0x1.edcba987654321fp-1L)) + return 1; + +#else + printf("skipped\n"); + +#endif + return 0; +}