mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
7e0a09feec
This change ports APE Loader to Linux AARCH64, so that Raspberry Pi users can run programs like redbean, without the executable needing to modify itself. Progress has also slipped into this change on the issue of making progress better conforming to user expectations and industry standards regarding which symbols we're allowed to declare
157 lines
4.4 KiB
C
157 lines
4.4 KiB
C
/* clang-format off */
|
|
//===-- lib/comparedf2.c - Double-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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// // This file implements the following soft-float comparison routines:
|
|
//
|
|
// __eqdf2 __gedf2 __unorddf2
|
|
// __ledf2 __gtdf2
|
|
// __ltdf2
|
|
// __nedf2
|
|
//
|
|
// 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:
|
|
//
|
|
// __ledf2(a,b) returns -1 if a < b
|
|
// 0 if a == b
|
|
// 1 if a > b
|
|
// 1 if either a or b is NaN
|
|
//
|
|
// __gedf2(a,b) returns -1 if a < b
|
|
// 0 if a == b
|
|
// 1 if a > b
|
|
// -1 if either a or b is NaN
|
|
//
|
|
// __unorddf2(a,b) returns 0 if both a and b are numbers
|
|
// 1 if either a or b is NaN
|
|
//
|
|
// Note that __ledf2( ) and __gedf2( ) are identical except in their handling of
|
|
// NaN values.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
__static_yoink("huge_compiler_rt_license");
|
|
|
|
#define DOUBLE_PRECISION
|
|
#include "third_party/compiler_rt/fp_lib.inc"
|
|
|
|
enum LE_RESULT {
|
|
LE_LESS = -1,
|
|
LE_EQUAL = 0,
|
|
LE_GREATER = 1,
|
|
LE_UNORDERED = 1
|
|
};
|
|
|
|
COMPILER_RT_ABI enum LE_RESULT
|
|
__ledf2(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 floating-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;
|
|
}
|
|
}
|
|
|
|
// Alias for libgcc compatibility
|
|
COMPILER_RT_ABI enum LE_RESULT
|
|
__cmpdf2(fp_t a, fp_t b) {
|
|
return __ledf2(a, b);
|
|
}
|
|
|
|
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
|
|
__gedf2(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_ABI int
|
|
__unorddf2(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 preceding routines.
|
|
|
|
COMPILER_RT_ABI enum LE_RESULT
|
|
__eqdf2(fp_t a, fp_t b) {
|
|
return __ledf2(a, b);
|
|
}
|
|
|
|
COMPILER_RT_ABI enum LE_RESULT
|
|
__ltdf2(fp_t a, fp_t b) {
|
|
return __ledf2(a, b);
|
|
}
|
|
|
|
COMPILER_RT_ABI enum LE_RESULT
|
|
__nedf2(fp_t a, fp_t b) {
|
|
return __ledf2(a, b);
|
|
}
|
|
|
|
COMPILER_RT_ABI enum GE_RESULT
|
|
__gtdf2(fp_t a, fp_t b) {
|
|
return __gedf2(a, b);
|
|
}
|
|
|
|
#if defined(__ARM_EABI__)
|
|
#if defined(COMPILER_RT_ARMHF_TARGET)
|
|
AEABI_RTABI int __aeabi_dcmpun(fp_t a, fp_t b) {
|
|
return __unorddf2(a, b);
|
|
}
|
|
#else
|
|
AEABI_RTABI int __aeabi_dcmpun(fp_t a, fp_t b) COMPILER_RT_ALIAS(__unorddf2);
|
|
#endif
|
|
#endif
|