diff options
Diffstat (limited to 'contrib/compiler-rt/lib/arm')
51 files changed, 1704 insertions, 0 deletions
diff --git a/contrib/compiler-rt/lib/arm/adddf3vfp.S b/contrib/compiler-rt/lib/arm/adddf3vfp.S new file mode 100644 index 0000000..cced1e0 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/adddf3vfp.S @@ -0,0 +1,24 @@ +//===-- adddf3vfp.S - Implement adddf3vfp ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// double __adddf3vfp(double a, double b) { return a + b; } +// +// Adds two double precision floating point numbers using the Darwin +// calling convention where double arguments are passsed in GPR pairs +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__adddf3vfp) + fmdrr d6, r0, r1 // move first param from r0/r1 pair into d6 + fmdrr d7, r2, r3 // move second param from r2/r3 pair into d7 + faddd d6, d6, d7 + fmrrd r0, r1, d6 // move result back to r0/r1 pair + bx lr diff --git a/contrib/compiler-rt/lib/arm/addsf3vfp.S b/contrib/compiler-rt/lib/arm/addsf3vfp.S new file mode 100644 index 0000000..b747528 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/addsf3vfp.S @@ -0,0 +1,24 @@ +//===-- addsf3vfp.S - Implement addsf3vfp ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern float __addsf3vfp(float a, float b); +// +// Adds two single precision floating point numbers using the Darwin +// calling convention where single arguments are passsed in GPRs +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__addsf3vfp) + fmsr s14, r0 // move first param from r0 into float register + fmsr s15, r1 // move second param from r1 into float register + fadds s14, s14, s15 + fmrs r0, s14 // move result back to r0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/bswapdi2.S b/contrib/compiler-rt/lib/arm/bswapdi2.S new file mode 100644 index 0000000..a0283e1 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/bswapdi2.S @@ -0,0 +1,36 @@ +//===------- bswapdi2 - Implement bswapdi2 --------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern uint64_t __bswapdi2(uint64_t); +// +// Reverse all the bytes in a 64-bit integer. +// +.align 2 +DEFINE_COMPILERRT_FUNCTION(__bswapdi2) +#if __ARM_ARCH_5TEJ__ || __ARM_ARCH_4T__ + // before armv6 does not have "rev" instruction + // r2 = rev(r0) + eor r2, r0, r0, ror #16 + bic r2, r2, #0xff0000 + mov r2, r2, lsr #8 + eor r2, r2, r0, ror #8 + // r0 = rev(r1) + eor r0, r1, r1, ror #16 + bic r0, r0, #0xff0000 + mov r0, r0, lsr #8 + eor r0, r0, r1, ror #8 +#else + rev r2, r0 // r2 = rev(r0) + rev r0, r1 // r0 = rev(r1) +#endif + mov r1, r2 // r1 = r2 = rev(r0) + bx lr diff --git a/contrib/compiler-rt/lib/arm/bswapsi2.S b/contrib/compiler-rt/lib/arm/bswapsi2.S new file mode 100644 index 0000000..4c3af1f --- /dev/null +++ b/contrib/compiler-rt/lib/arm/bswapsi2.S @@ -0,0 +1,28 @@ +//===------- bswapsi2 - Implement bswapsi2 --------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern uint32_t __bswapsi2(uint32_t); +// +// Reverse all the bytes in a 32-bit integer. +// +.align 2 +DEFINE_COMPILERRT_FUNCTION(__bswapsi2) +#if __ARM_ARCH_5TEJ__ || __ARM_ARCH_4T__ + // before armv6 does not have "rev" instruction + eor r1, r0, r0, ror #16 + bic r1, r1, #0xff0000 + mov r1, r1, lsr #8 + eor r0, r1, r0, ror #8 +#else + rev r0, r0 +#endif + bx lr diff --git a/contrib/compiler-rt/lib/arm/comparesf2.S b/contrib/compiler-rt/lib/arm/comparesf2.S new file mode 100644 index 0000000..ee18203 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/comparesf2.S @@ -0,0 +1,130 @@ +//===-- comparesf2.S - Implement single-precision soft-float comparisons --===// +// +// 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-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, with multiple names. +// +// The 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" +.syntax unified + +.align 2 +DEFINE_COMPILERRT_FUNCTION(__eqsf2) +DEFINE_COMPILERRT_FUNCTION(__lesf2) +DEFINE_COMPILERRT_FUNCTION(__ltsf2) +DEFINE_COMPILERRT_FUNCTION(__nesf2) + // Make copies of a and b with the sign bit shifted off the top. These will + // be used to detect zeros and NaNs. + mov r2, r0, lsl #1 + mov r3, r1, lsl #1 + + // We do the comparison in three stages (ignoring NaN values for the time + // being). First, we orr the absolute values of a and b; this sets the Z + // flag if both a and b are zero (of either sign). The shift of r3 doesn't + // effect this at all, but it *does* make sure that the C flag is clear for + // the subsequent operations. + orrs r12, r2, r3, lsr #1 + + // Next, we check if a and b have the same or different signs. If they have + // opposite signs, this eor will set the N flag. + eorsne r12, r0, r1 + + // If a and b are equal (either both zeros or bit identical; again, we're + // ignoring NaNs for now), this subtract will zero out r0. If they have the + // same sign, the flags are updated as they would be for a comparison of the + // absolute values of a and b. + subspl r0, r2, r3 + + // If a is smaller in magnitude than b and both have the same sign, place + // the negation of the sign of b in r0. Thus, if both are negative and + // a > b, this sets r0 to 0; if both are positive and a < b, this sets + // r0 to -1. + // + // This is also done if a and b have opposite signs and are not both zero, + // because in that case the subtract was not performed and the C flag is + // still clear from the shift argument in orrs; if a is positive and b + // negative, this places 0 in r0; if a is negative and b positive, -1 is + // placed in r0. + mvnlo r0, r1, asr #31 + + // If a is greater in magnitude than b and both have the same sign, place + // the sign of b in r0. Thus, if both are negative and a < b, -1 is placed + // in r0, which is the desired result. Conversely, if both are positive + // and a > b, zero is placed in r0. + movhi r0, r1, asr #31 + + // If you've been keeping track, at this point r0 contains -1 if a < b and + // 0 if a >= b. All that remains to be done is to set it to 1 if a > b. + // If a == b, then the Z flag is set, so we can get the correct final value + // into r0 by simply or'ing with 1 if Z is clear. + orrne r0, r0, #1 + + // Finally, we need to deal with NaNs. If either argument is NaN, replace + // the value in r0 with 1. + cmp r2, #0xff000000 + cmpls r3, #0xff000000 + movhi r0, #1 + bx lr + +.align 2 +DEFINE_COMPILERRT_FUNCTION(__gesf2) +DEFINE_COMPILERRT_FUNCTION(__gtsf2) + // Identical to the preceeding except in that we return -1 for NaN values. + // Given that the two paths share so much code, one might be tempted to + // unify them; however, the extra code needed to do so makes the code size + // to performance tradeoff very hard to justify for such small functions. + mov r2, r0, lsl #1 + mov r3, r1, lsl #1 + orrs r12, r2, r3, lsr #1 + eorsne r12, r0, r1 + subspl r0, r2, r3 + mvnlo r0, r1, asr #31 + movhi r0, r1, asr #31 + orrne r0, r0, #1 + cmp r2, #0xff000000 + cmpls r3, #0xff000000 + movhi r0, #-1 + bx lr + +.align 2 +DEFINE_COMPILERRT_FUNCTION(__unordsf2) + // Return 1 for NaN values, 0 otherwise. + mov r2, r0, lsl #1 + mov r3, r1, lsl #1 + mov r0, #0 + cmp r2, #0xff000000 + cmpls r3, #0xff000000 + movhi r0, #1 + bx lr diff --git a/contrib/compiler-rt/lib/arm/divdf3vfp.S b/contrib/compiler-rt/lib/arm/divdf3vfp.S new file mode 100644 index 0000000..74ef0ea --- /dev/null +++ b/contrib/compiler-rt/lib/arm/divdf3vfp.S @@ -0,0 +1,24 @@ +//===-- divdf3vfp.S - Implement divdf3vfp ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __divdf3vfp(double a, double b); +// +// Divides two double precision floating point numbers using the Darwin +// calling convention where double arguments are passsed in GPR pairs +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__divdf3vfp) + fmdrr d6, r0, r1 // move first param from r0/r1 pair into d6 + fmdrr d7, r2, r3 // move second param from r2/r3 pair into d7 + fdivd d5, d6, d7 + fmrrd r0, r1, d5 // move result back to r0/r1 pair + bx lr diff --git a/contrib/compiler-rt/lib/arm/divmodsi4.S b/contrib/compiler-rt/lib/arm/divmodsi4.S new file mode 100644 index 0000000..cec39a7 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/divmodsi4.S @@ -0,0 +1,47 @@ +/*===-- divmodsi4.S - 32-bit signed integer divide and modulus ------------===// + * + * 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 __divmodsi4 (32-bit signed integer divide and + * modulus) function for the ARM architecture. A naive digit-by-digit + * computation is employed for simplicity. + * + *===----------------------------------------------------------------------===*/ + +#include "../assembly.h" + +#define ESTABLISH_FRAME \ + push {r4-r7, lr} ;\ + add r7, sp, #12 +#define CLEAR_FRAME_AND_RETURN \ + pop {r4-r7, pc} + +.syntax unified +.align 3 +DEFINE_COMPILERRT_FUNCTION(__divmodsi4) + ESTABLISH_FRAME +// Set aside the sign of the quotient and modulus, and the address for the +// modulus. + eor r4, r0, r1 + mov r5, r0 + mov r6, r2 +// Take the absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). + eor ip, r0, r0, asr #31 + eor lr, r1, r1, asr #31 + sub r0, ip, r0, asr #31 + sub r1, lr, r1, asr #31 +// Unsigned divmod: + bl SYMBOL_NAME(__udivmodsi4) +// Apply the sign of quotient and modulus + ldr r1, [r6] + eor r0, r0, r4, asr #31 + eor r1, r1, r5, asr #31 + sub r0, r0, r4, asr #31 + sub r1, r1, r5, asr #31 + str r1, [r6] + CLEAR_FRAME_AND_RETURN diff --git a/contrib/compiler-rt/lib/arm/divsf3vfp.S b/contrib/compiler-rt/lib/arm/divsf3vfp.S new file mode 100644 index 0000000..9eefcf31e --- /dev/null +++ b/contrib/compiler-rt/lib/arm/divsf3vfp.S @@ -0,0 +1,24 @@ +//===-- divsf3vfp.S - Implement divsf3vfp ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern float __divsf3vfp(float a, float b); +// +// Divides two single precision floating point numbers using the Darwin +// calling convention where single arguments are passsed like 32-bit ints. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__divsf3vfp) + fmsr s14, r0 // move first param from r0 into float register + fmsr s15, r1 // move second param from r1 into float register + fdivs s13, s14, s15 + fmrs r0, s13 // move result back to r0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/divsi3.S b/contrib/compiler-rt/lib/arm/divsi3.S new file mode 100644 index 0000000..00e6181 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/divsi3.S @@ -0,0 +1,41 @@ +/*===-- divsi3.S - 32-bit signed integer divide ---------------------------===// + * + * 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 __divsi3 (32-bit signed integer divide) function + * for the ARM architecture as a wrapper around the unsigned routine. + * + *===----------------------------------------------------------------------===*/ + +#include "../assembly.h" + +#define ESTABLISH_FRAME \ + push {r4, r7, lr} ;\ + add r7, sp, #4 +#define CLEAR_FRAME_AND_RETURN \ + pop {r4, r7, pc} + +.syntax unified +.align 3 +// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine. +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_idiv, __divsi3) +DEFINE_COMPILERRT_FUNCTION(__divsi3) + ESTABLISH_FRAME +// Set aside the sign of the quotient. + eor r4, r0, r1 +// Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). + eor r2, r0, r0, asr #31 + eor r3, r1, r1, asr #31 + sub r0, r2, r0, asr #31 + sub r1, r3, r1, asr #31 +// abs(a) / abs(b) + bl SYMBOL_NAME(__udivsi3) +// Apply sign of quotient to result and return. + eor r0, r0, r4, asr #31 + sub r0, r0, r4, asr #31 + CLEAR_FRAME_AND_RETURN diff --git a/contrib/compiler-rt/lib/arm/eqdf2vfp.S b/contrib/compiler-rt/lib/arm/eqdf2vfp.S new file mode 100644 index 0000000..2998a76 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/eqdf2vfp.S @@ -0,0 +1,27 @@ +//===-- eqdf2vfp.S - Implement eqdf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __eqdf2vfp(double a, double b); +// +// Returns one iff a == b and neither is NaN. +// Uses Darwin calling convention where double precision arguments are passsed +// like in GPR pairs. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__eqdf2vfp) + fmdrr d6, r0, r1 // load r0/r1 pair in double register + fmdrr d7, r2, r3 // load r2/r3 pair in double register + fcmpd d6, d7 + fmstat + moveq r0, #1 // set result register to 1 if equal + movne r0, #0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/eqsf2vfp.S b/contrib/compiler-rt/lib/arm/eqsf2vfp.S new file mode 100644 index 0000000..927566e --- /dev/null +++ b/contrib/compiler-rt/lib/arm/eqsf2vfp.S @@ -0,0 +1,28 @@ +//===-- eqsf2vfp.S - Implement eqsf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __eqsf2vfp(float a, float b); +// +// Returns one iff a == b and neither is NaN. +// Uses Darwin calling convention where single precision arguments are passsed +// like 32-bit ints +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__eqsf2vfp) + fmsr s14, r0 // move from GPR 0 to float register + fmsr s15, r1 // move from GPR 1 to float register + fcmps s14, s15 + fmstat + moveq r0, #1 // set result register to 1 if equal + movne r0, #0 + bx lr + diff --git a/contrib/compiler-rt/lib/arm/extendsfdf2vfp.S b/contrib/compiler-rt/lib/arm/extendsfdf2vfp.S new file mode 100644 index 0000000..b1aa88e --- /dev/null +++ b/contrib/compiler-rt/lib/arm/extendsfdf2vfp.S @@ -0,0 +1,24 @@ +//===-- extendsfdf2vfp.S - Implement extendsfdf2vfp -----------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __extendsfdf2vfp(float a); +// +// Converts single precision float to double precision result. +// Uses Darwin calling convention where a single precision parameter is +// passed in a GPR and a double precision result is returned in R0/R1 pair. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__extendsfdf2vfp) + fmsr s15, r0 // load float register from R0 + fcvtds d7, s15 // convert single to double + fmrrd r0, r1, d7 // return result in r0/r1 pair + bx lr diff --git a/contrib/compiler-rt/lib/arm/fixdfsivfp.S b/contrib/compiler-rt/lib/arm/fixdfsivfp.S new file mode 100644 index 0000000..0285a17 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/fixdfsivfp.S @@ -0,0 +1,24 @@ +//===-- fixdfsivfp.S - Implement fixdfsivfp -----------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __fixdfsivfp(double a); +// +// Converts double precision float to a 32-bit int rounding towards zero. +// Uses Darwin calling convention where a double precision parameter is +// passed in GPR register pair. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__fixdfsivfp) + fmdrr d7, r0, r1 // load double register from R0/R1 + ftosizd s15, d7 // convert double to 32-bit int into s15 + fmrs r0, s15 // move s15 to result register + bx lr diff --git a/contrib/compiler-rt/lib/arm/fixsfsivfp.S b/contrib/compiler-rt/lib/arm/fixsfsivfp.S new file mode 100644 index 0000000..d05ba74 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/fixsfsivfp.S @@ -0,0 +1,24 @@ +//===-- fixsfsivfp.S - Implement fixsfsivfp -----------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __fixsfsivfp(float a); +// +// Converts single precision float to a 32-bit int rounding towards zero. +// Uses Darwin calling convention where a single precision parameter is +// passed in a GPR.. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__fixsfsivfp) + fmsr s15, r0 // load float register from R0 + ftosizs s15, s15 // convert single to 32-bit int into s15 + fmrs r0, s15 // move s15 to result register + bx lr diff --git a/contrib/compiler-rt/lib/arm/fixunsdfsivfp.S b/contrib/compiler-rt/lib/arm/fixunsdfsivfp.S new file mode 100644 index 0000000..ddb703c --- /dev/null +++ b/contrib/compiler-rt/lib/arm/fixunsdfsivfp.S @@ -0,0 +1,25 @@ +//===-- fixunsdfsivfp.S - Implement fixunsdfsivfp -------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern unsigned int __fixunsdfsivfp(double a); +// +// Converts double precision float to a 32-bit unsigned int rounding towards +// zero. All negative values become zero. +// Uses Darwin calling convention where a double precision parameter is +// passed in GPR register pair. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__fixunsdfsivfp) + fmdrr d7, r0, r1 // load double register from R0/R1 + ftouizd s15, d7 // convert double to 32-bit int into s15 + fmrs r0, s15 // move s15 to result register + bx lr diff --git a/contrib/compiler-rt/lib/arm/fixunssfsivfp.S b/contrib/compiler-rt/lib/arm/fixunssfsivfp.S new file mode 100644 index 0000000..afbb64f --- /dev/null +++ b/contrib/compiler-rt/lib/arm/fixunssfsivfp.S @@ -0,0 +1,25 @@ +//===-- fixunssfsivfp.S - Implement fixunssfsivfp -------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern unsigned int __fixunssfsivfp(float a); +// +// Converts single precision float to a 32-bit unsigned int rounding towards +// zero. All negative values become zero. +// Uses Darwin calling convention where a single precision parameter is +// passed in a GPR.. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__fixunssfsivfp) + fmsr s15, r0 // load float register from R0 + ftouizs s15, s15 // convert single to 32-bit unsigned into s15 + fmrs r0, s15 // move s15 to result register + bx lr diff --git a/contrib/compiler-rt/lib/arm/floatsidfvfp.S b/contrib/compiler-rt/lib/arm/floatsidfvfp.S new file mode 100644 index 0000000..fe3366a --- /dev/null +++ b/contrib/compiler-rt/lib/arm/floatsidfvfp.S @@ -0,0 +1,24 @@ +//===-- floatsidfvfp.S - Implement floatsidfvfp ---------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __floatsidfvfp(int a); +// +// Converts a 32-bit int to a double precision float. +// Uses Darwin calling convention where a double precision result is +// return in GPR register pair. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__floatsidfvfp) + fmsr s15, r0 // move int to float register s15 + fsitod d7, s15 // convert 32-bit int in s15 to double in d7 + fmrrd r0, r1, d7 // move d7 to result register pair r0/r1 + bx lr diff --git a/contrib/compiler-rt/lib/arm/floatsisfvfp.S b/contrib/compiler-rt/lib/arm/floatsisfvfp.S new file mode 100644 index 0000000..5b41610 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/floatsisfvfp.S @@ -0,0 +1,24 @@ +//===-- floatsisfvfp.S - Implement floatsisfvfp ---------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern float __floatsisfvfp(int a); +// +// Converts single precision float to a 32-bit int rounding towards zero. +// Uses Darwin calling convention where a single precision result is +// return in a GPR.. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__floatsisfvfp) + fmsr s15, r0 // move int to float register s15 + fsitos s15, s15 // convert 32-bit int in s15 to float in s15 + fmrs r0, s15 // move s15 to result register + bx lr diff --git a/contrib/compiler-rt/lib/arm/floatunssidfvfp.S b/contrib/compiler-rt/lib/arm/floatunssidfvfp.S new file mode 100644 index 0000000..9b22a6f --- /dev/null +++ b/contrib/compiler-rt/lib/arm/floatunssidfvfp.S @@ -0,0 +1,24 @@ +//===-- floatunssidfvfp.S - Implement floatunssidfvfp ---------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __floatunssidfvfp(unsigned int a); +// +// Converts a 32-bit int to a double precision float. +// Uses Darwin calling convention where a double precision result is +// return in GPR register pair. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__floatunssidfvfp) + fmsr s15, r0 // move int to float register s15 + fuitod d7, s15 // convert 32-bit int in s15 to double in d7 + fmrrd r0, r1, d7 // move d7 to result register pair r0/r1 + bx lr diff --git a/contrib/compiler-rt/lib/arm/floatunssisfvfp.S b/contrib/compiler-rt/lib/arm/floatunssisfvfp.S new file mode 100644 index 0000000..44d5e93 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/floatunssisfvfp.S @@ -0,0 +1,24 @@ +//===-- floatunssisfvfp.S - Implement floatunssisfvfp ---------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern float __floatunssisfvfp(unsigned int a); +// +// Converts single precision float to a 32-bit int rounding towards zero. +// Uses Darwin calling convention where a single precision result is +// return in a GPR.. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__floatunssisfvfp) + fmsr s15, r0 // move int to float register s15 + fuitos s15, s15 // convert 32-bit int in s15 to float in s15 + fmrs r0, s15 // move s15 to result register + bx lr diff --git a/contrib/compiler-rt/lib/arm/gedf2vfp.S b/contrib/compiler-rt/lib/arm/gedf2vfp.S new file mode 100644 index 0000000..9993f52 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/gedf2vfp.S @@ -0,0 +1,27 @@ +//===-- gedf2vfp.S - Implement gedf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __gedf2vfp(double a, double b); +// +// Returns one iff a >= b and neither is NaN. +// Uses Darwin calling convention where double precision arguments are passsed +// like in GPR pairs. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__gedf2vfp) + fmdrr d6, r0, r1 // load r0/r1 pair in double register + fmdrr d7, r2, r3 // load r2/r3 pair in double register + fcmpd d6, d7 + fmstat + movge r0, #1 // set result register to 1 if greater than or equal + movlt r0, #0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/gesf2vfp.S b/contrib/compiler-rt/lib/arm/gesf2vfp.S new file mode 100644 index 0000000..9ce1682 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/gesf2vfp.S @@ -0,0 +1,28 @@ +//===-- gesf2vfp.S - Implement gesf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __gesf2vfp(float a, float b); +// +// Returns one iff a >= b and neither is NaN. +// Uses Darwin calling convention where single precision arguments are passsed +// like 32-bit ints +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__gesf2vfp) + fmsr s14, r0 // move from GPR 0 to float register + fmsr s15, r1 // move from GPR 1 to float register + fcmps s14, s15 + fmstat + movge r0, #1 // set result register to 1 if greater than or equal + movlt r0, #0 + bx lr + diff --git a/contrib/compiler-rt/lib/arm/gtdf2vfp.S b/contrib/compiler-rt/lib/arm/gtdf2vfp.S new file mode 100644 index 0000000..8a049c8 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/gtdf2vfp.S @@ -0,0 +1,27 @@ +//===-- gtdf2vfp.S - Implement gtdf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __gtdf2vfp(double a, double b); +// +// Returns one iff a > b and neither is NaN. +// Uses Darwin calling convention where double precision arguments are passsed +// like in GPR pairs. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__gtdf2vfp) + fmdrr d6, r0, r1 // load r0/r1 pair in double register + fmdrr d7, r2, r3 // load r2/r3 pair in double register + fcmpd d6, d7 + fmstat + movgt r0, #1 // set result register to 1 if equal + movle r0, #0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/gtsf2vfp.S b/contrib/compiler-rt/lib/arm/gtsf2vfp.S new file mode 100644 index 0000000..1ffe1ec --- /dev/null +++ b/contrib/compiler-rt/lib/arm/gtsf2vfp.S @@ -0,0 +1,28 @@ +//===-- gtsf2vfp.S - Implement gtsf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __gtsf2vfp(float a, float b); +// +// Returns one iff a > b and neither is NaN. +// Uses Darwin calling convention where single precision arguments are passsed +// like 32-bit ints +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__gtsf2vfp) + fmsr s14, r0 // move from GPR 0 to float register + fmsr s15, r1 // move from GPR 1 to float register + fcmps s14, s15 + fmstat + movgt r0, #1 // set result register to 1 if equal + movle r0, #0 + bx lr + diff --git a/contrib/compiler-rt/lib/arm/ledf2vfp.S b/contrib/compiler-rt/lib/arm/ledf2vfp.S new file mode 100644 index 0000000..a04d0f2 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/ledf2vfp.S @@ -0,0 +1,27 @@ +//===-- ledf2vfp.S - Implement ledf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __ledf2vfp(double a, double b); +// +// Returns one iff a <= b and neither is NaN. +// Uses Darwin calling convention where double precision arguments are passsed +// like in GPR pairs. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__ledf2vfp) + fmdrr d6, r0, r1 // load r0/r1 pair in double register + fmdrr d7, r2, r3 // load r2/r3 pair in double register + fcmpd d6, d7 + fmstat + movls r0, #1 // set result register to 1 if equal + movhi r0, #0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/lesf2vfp.S b/contrib/compiler-rt/lib/arm/lesf2vfp.S new file mode 100644 index 0000000..3011200 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/lesf2vfp.S @@ -0,0 +1,28 @@ +//===-- lesf2vfp.S - Implement lesf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __lesf2vfp(float a, float b); +// +// Returns one iff a <= b and neither is NaN. +// Uses Darwin calling convention where single precision arguments are passsed +// like 32-bit ints +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__lesf2vfp) + fmsr s14, r0 // move from GPR 0 to float register + fmsr s15, r1 // move from GPR 1 to float register + fcmps s14, s15 + fmstat + movls r0, #1 // set result register to 1 if equal + movhi r0, #0 + bx lr + diff --git a/contrib/compiler-rt/lib/arm/ltdf2vfp.S b/contrib/compiler-rt/lib/arm/ltdf2vfp.S new file mode 100644 index 0000000..87144a8 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/ltdf2vfp.S @@ -0,0 +1,27 @@ +//===-- ltdf2vfp.S - Implement ltdf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __ltdf2vfp(double a, double b); +// +// Returns one iff a < b and neither is NaN. +// Uses Darwin calling convention where double precision arguments are passsed +// like in GPR pairs. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__ltdf2vfp) + fmdrr d6, r0, r1 // load r0/r1 pair in double register + fmdrr d7, r2, r3 // load r2/r3 pair in double register + fcmpd d6, d7 + fmstat + movmi r0, #1 // set result register to 1 if equal + movpl r0, #0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/ltsf2vfp.S b/contrib/compiler-rt/lib/arm/ltsf2vfp.S new file mode 100644 index 0000000..ca06ae2 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/ltsf2vfp.S @@ -0,0 +1,28 @@ +//===-- ltsf2vfp.S - Implement ltsf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __ltsf2vfp(float a, float b); +// +// Returns one iff a < b and neither is NaN. +// Uses Darwin calling convention where single precision arguments are passsed +// like 32-bit ints +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__ltsf2vfp) + fmsr s14, r0 // move from GPR 0 to float register + fmsr s15, r1 // move from GPR 1 to float register + fcmps s14, s15 + fmstat + movmi r0, #1 // set result register to 1 if equal + movpl r0, #0 + bx lr + diff --git a/contrib/compiler-rt/lib/arm/modsi3.S b/contrib/compiler-rt/lib/arm/modsi3.S new file mode 100644 index 0000000..a4cd2ee --- /dev/null +++ b/contrib/compiler-rt/lib/arm/modsi3.S @@ -0,0 +1,39 @@ +/*===-- modsi3.S - 32-bit signed integer modulus --------------------------===// + * + * 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 __modsi3 (32-bit signed integer modulus) function + * for the ARM architecture as a wrapper around the unsigned routine. + * + *===----------------------------------------------------------------------===*/ + +#include "../assembly.h" + +#define ESTABLISH_FRAME \ + push {r4, r7, lr} ;\ + add r7, sp, #4 +#define CLEAR_FRAME_AND_RETURN \ + pop {r4, r7, pc} + +.syntax unified +.align 3 +DEFINE_COMPILERRT_FUNCTION(__modsi3) + ESTABLISH_FRAME + // Set aside the sign of the dividend. + mov r4, r0 + // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). + eor r2, r0, r0, asr #31 + eor r3, r1, r1, asr #31 + sub r0, r2, r0, asr #31 + sub r1, r3, r1, asr #31 + // abs(a) % abs(b) + bl SYMBOL_NAME(__umodsi3) + // Apply sign of dividend to result and return. + eor r0, r0, r4, asr #31 + sub r0, r0, r4, asr #31 + CLEAR_FRAME_AND_RETURN diff --git a/contrib/compiler-rt/lib/arm/muldf3vfp.S b/contrib/compiler-rt/lib/arm/muldf3vfp.S new file mode 100644 index 0000000..96bba06 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/muldf3vfp.S @@ -0,0 +1,24 @@ +//===-- muldf3vfp.S - Implement muldf3vfp ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __muldf3vfp(double a, double b); +// +// Multiplies two double precision floating point numbers using the Darwin +// calling convention where double arguments are passsed in GPR pairs +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__muldf3vfp) + fmdrr d6, r0, r1 // move first param from r0/r1 pair into d6 + fmdrr d7, r2, r3 // move second param from r2/r3 pair into d7 + fmuld d6, d6, d7 + fmrrd r0, r1, d6 // move result back to r0/r1 pair + bx lr diff --git a/contrib/compiler-rt/lib/arm/mulsf3vfp.S b/contrib/compiler-rt/lib/arm/mulsf3vfp.S new file mode 100644 index 0000000..c56991d --- /dev/null +++ b/contrib/compiler-rt/lib/arm/mulsf3vfp.S @@ -0,0 +1,24 @@ +//===-- mulsf3vfp.S - Implement mulsf3vfp ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern float __mulsf3vfp(float a, float b); +// +// Multiplies two single precision floating point numbers using the Darwin +// calling convention where single arguments are passsed like 32-bit ints. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__mulsf3vfp) + fmsr s14, r0 // move first param from r0 into float register + fmsr s15, r1 // move second param from r1 into float register + fmuls s13, s14, s15 + fmrs r0, s13 // move result back to r0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/nedf2vfp.S b/contrib/compiler-rt/lib/arm/nedf2vfp.S new file mode 100644 index 0000000..a02b09c --- /dev/null +++ b/contrib/compiler-rt/lib/arm/nedf2vfp.S @@ -0,0 +1,27 @@ +//===-- nedf2vfp.S - Implement nedf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __nedf2vfp(double a, double b); +// +// Returns zero if a and b are unequal and neither is NaN. +// Uses Darwin calling convention where double precision arguments are passsed +// like in GPR pairs. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__nedf2vfp) + fmdrr d6, r0, r1 // load r0/r1 pair in double register + fmdrr d7, r2, r3 // load r2/r3 pair in double register + fcmpd d6, d7 + fmstat + movne r0, #1 // set result register to 0 if unequal + moveq r0, #0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/negdf2vfp.S b/contrib/compiler-rt/lib/arm/negdf2vfp.S new file mode 100644 index 0000000..100f4fd --- /dev/null +++ b/contrib/compiler-rt/lib/arm/negdf2vfp.S @@ -0,0 +1,21 @@ +//===-- negdf2vfp.S - Implement negdf2vfp ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __negdf2vfp(double a, double b); +// +// Returns the negation a double precision floating point numbers using the +// Darwin calling convention where double arguments are passsed in GPR pairs. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__negdf2vfp) + eor r1, r1, #-2147483648 // flip sign bit on double in r0/r1 pair + bx lr diff --git a/contrib/compiler-rt/lib/arm/negsf2vfp.S b/contrib/compiler-rt/lib/arm/negsf2vfp.S new file mode 100644 index 0000000..f96c8ad --- /dev/null +++ b/contrib/compiler-rt/lib/arm/negsf2vfp.S @@ -0,0 +1,21 @@ +//===-- negsf2vfp.S - Implement negsf2vfp ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern float __negsf2vfp(float a); +// +// Returns the negation of a single precision floating point numbers using the +// Darwin calling convention where single arguments are passsed like 32-bit ints +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__negsf2vfp) + eor r0, r0, #-2147483648 // flip sign bit on float in r0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/nesf2vfp.S b/contrib/compiler-rt/lib/arm/nesf2vfp.S new file mode 100644 index 0000000..d620549 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/nesf2vfp.S @@ -0,0 +1,28 @@ +//===-- nesf2vfp.S - Implement nesf2vfp -----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __nesf2vfp(float a, float b); +// +// Returns one iff a != b and neither is NaN. +// Uses Darwin calling convention where single precision arguments are passsed +// like 32-bit ints +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__nesf2vfp) + fmsr s14, r0 // move from GPR 0 to float register + fmsr s15, r1 // move from GPR 1 to float register + fcmps s14, s15 + fmstat + movne r0, #1 // set result register to 1 if unequal + moveq r0, #0 + bx lr + diff --git a/contrib/compiler-rt/lib/arm/restore_vfp_d8_d15_regs.S b/contrib/compiler-rt/lib/arm/restore_vfp_d8_d15_regs.S new file mode 100644 index 0000000..7f441db --- /dev/null +++ b/contrib/compiler-rt/lib/arm/restore_vfp_d8_d15_regs.S @@ -0,0 +1,37 @@ +//===-- save_restore_regs.S - Implement save/restore* ---------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// When compiling C++ functions that need to handle thrown exceptions the +// compiler is required to save all registers and call __Unwind_SjLj_Register +// in the function prolog. But when compiling for thumb1, there are +// no instructions to access the floating point registers, so the +// compiler needs to add a call to the helper function _save_vfp_d8_d15_regs +// written in ARM to save the float registers. In the epilog, the compiler +// must also add a call to __restore_vfp_d8_d15_regs to restore those registers. +// + + .text + .syntax unified + +// +// Restore registers d8-d15 from stack +// + .align 2 +DEFINE_COMPILERRT_PRIVATE_FUNCTION(__restore_vfp_d8_d15_regs) + vldmia sp!, {d8-d15} // pop registers d8-d15 off stack + bx lr // return to prolog + + + + // tell linker it can break up file at label boundaries + .subsections_via_symbols + diff --git a/contrib/compiler-rt/lib/arm/save_vfp_d8_d15_regs.S b/contrib/compiler-rt/lib/arm/save_vfp_d8_d15_regs.S new file mode 100644 index 0000000..fbd21ba --- /dev/null +++ b/contrib/compiler-rt/lib/arm/save_vfp_d8_d15_regs.S @@ -0,0 +1,35 @@ +//===-- save_restore_regs.S - Implement save/restore* ---------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// When compiling C++ functions that need to handle thrown exceptions the +// compiler is required to save all registers and call __Unwind_SjLj_Register +// in the function prolog. But when compiling for thumb1, there are +// no instructions to access the floating point registers, so the +// compiler needs to add a call to the helper function _save_vfp_d8_d15_regs +// written in ARM to save the float registers. In the epilog, the compiler +// must also add a call to __restore_vfp_d8_d15_regs to restore those registers. +// + + .text + .syntax unified + +// +// Save registers d8-d15 onto stack +// + .align 2 +DEFINE_COMPILERRT_PRIVATE_FUNCTION(__save_vfp_d8_d15_regs) + vstmdb sp!, {d8-d15} // push registers d8-d15 onto stack + bx lr // return to prolog + + // tell linker it can break up file at label boundaries + .subsections_via_symbols + diff --git a/contrib/compiler-rt/lib/arm/softfloat-alias.list b/contrib/compiler-rt/lib/arm/softfloat-alias.list new file mode 100644 index 0000000..cc6a4b3c --- /dev/null +++ b/contrib/compiler-rt/lib/arm/softfloat-alias.list @@ -0,0 +1,21 @@ +# +# These are soft float functions which can be +# aliased to the *vfp functions on arm processors +# that support floating point instructions. +# +___adddf3vfp ___adddf3 +___addsf3vfp ___addsf3 +___divdf3vfp ___divdf3 +___divsf3vfp ___divsf3 +___extendsfdf2vfp ___extendsfdf2 +___fixdfsivfp ___fixdfsi +___fixsfsivfp ___fixsfsi +___floatsidfvfp ___floatsidf +___floatsisfvfp ___floatsisf +___muldf3vfp ___muldf3 +___mulsf3vfp ___mulsf3 +___subdf3vfp ___subdf3 +___subsf3vfp ___subsf3 +___truncdfsf2vfp ___truncdfsf2 +___floatunssidfvfp ___floatunsidf +___floatunssisfvfp ___floatunsisf diff --git a/contrib/compiler-rt/lib/arm/subdf3vfp.S b/contrib/compiler-rt/lib/arm/subdf3vfp.S new file mode 100644 index 0000000..ff53b30 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/subdf3vfp.S @@ -0,0 +1,24 @@ +//===-- subdf3vfp.S - Implement subdf3vfp ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern double __subdf3vfp(double a, double b); +// +// Returns difference between two double precision floating point numbers using +// the Darwin calling convention where double arguments are passsed in GPR pairs +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__subdf3vfp) + fmdrr d6, r0, r1 // move first param from r0/r1 pair into d6 + fmdrr d7, r2, r3 // move second param from r2/r3 pair into d7 + fsubd d6, d6, d7 + fmrrd r0, r1, d6 // move result back to r0/r1 pair + bx lr diff --git a/contrib/compiler-rt/lib/arm/subsf3vfp.S b/contrib/compiler-rt/lib/arm/subsf3vfp.S new file mode 100644 index 0000000..238f3f0 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/subsf3vfp.S @@ -0,0 +1,25 @@ +//===-- subsf3vfp.S - Implement subsf3vfp ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern float __subsf3vfp(float a, float b); +// +// Returns the difference between two single precision floating point numbers +// using the Darwin calling convention where single arguments are passsed +// like 32-bit ints. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__subsf3vfp) + fmsr s14, r0 // move first param from r0 into float register + fmsr s15, r1 // move second param from r1 into float register + fsubs s14, s14, s15 + fmrs r0, s14 // move result back to r0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/switch16.S b/contrib/compiler-rt/lib/arm/switch16.S new file mode 100644 index 0000000..e8f08c4 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/switch16.S @@ -0,0 +1,44 @@ +//===-- switch.S - Implement switch* --------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// When compiling switch statements in thumb mode, the compiler +// can use these __switch* helper functions The compiler emits a blx to +// the __switch* function followed by a table of displacements for each +// case statement. On entry, R0 is the index into the table. The __switch* +// function uses the return address in lr to find the start of the table. +// The first entry in the table is the count of the entries in the table. +// It then uses R0 to index into the table and get the displacement of the +// address to jump to. If R0 is greater than the size of the table, it jumps +// to the last entry in the table. Each displacement in the table is actually +// the distance from lr to the label, thus making the tables PIC. + + + .text + .syntax unified + +// +// The table contains signed 2-byte sized elements which are 1/2 the distance +// from lr to the target label. +// + .align 2 +DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch16) + ldrh ip, [lr, #-1] // get first 16-bit word in table + cmp r0, ip // compare with index + add r0, lr, r0, lsl #1 // compute address of element in table + ldrshcc r0, [r0, #1] // load 16-bit element if r0 is in range + add ip, lr, ip, lsl #1 // compute address of last element in table + ldrshhs r0, [ip, #1] // load 16-bit element if r0 out of range + add ip, lr, r0, lsl #1 // compute label = lr + element*2 + bx ip // jump to computed label + + // tell linker it can break up file at label boundaries + .subsections_via_symbols diff --git a/contrib/compiler-rt/lib/arm/switch32.S b/contrib/compiler-rt/lib/arm/switch32.S new file mode 100644 index 0000000..7008fcc --- /dev/null +++ b/contrib/compiler-rt/lib/arm/switch32.S @@ -0,0 +1,46 @@ +//===-- switch.S - Implement switch* --------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// When compiling switch statements in thumb mode, the compiler +// can use these __switch* helper functions The compiler emits a blx to +// the __switch* function followed by a table of displacements for each +// case statement. On entry, R0 is the index into the table. The __switch* +// function uses the return address in lr to find the start of the table. +// The first entry in the table is the count of the entries in the table. +// It then uses R0 to index into the table and get the displacement of the +// address to jump to. If R0 is greater than the size of the table, it jumps +// to the last entry in the table. Each displacement in the table is actually +// the distance from lr to the label, thus making the tables PIC. + + + .text + .syntax unified + +// +// The table contains signed 4-byte sized elements which are the distance +// from lr to the target label. +// + .align 2 +DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch32) + ldr ip, [lr, #-1] // get first 32-bit word in table + cmp r0, ip // compare with index + add r0, lr, r0, lsl #2 // compute address of element in table + ldrcc r0, [r0, #3] // load 32-bit element if r0 is in range + add ip, lr, ip, lsl #2 // compute address of last element in table + ldrcs r0, [ip, #3] // load 32-bit element if r0 out of range + add ip, lr, r0 // compute label = lr + element + bx ip // jump to computed label + + + // tell linker it can break up file at label boundaries + .subsections_via_symbols + diff --git a/contrib/compiler-rt/lib/arm/switch8.S b/contrib/compiler-rt/lib/arm/switch8.S new file mode 100644 index 0000000..e784b40 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/switch8.S @@ -0,0 +1,43 @@ +//===-- switch.S - Implement switch* --------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// When compiling switch statements in thumb mode, the compiler +// can use these __switch* helper functions The compiler emits a blx to +// the __switch* function followed by a table of displacements for each +// case statement. On entry, R0 is the index into the table. The __switch* +// function uses the return address in lr to find the start of the table. +// The first entry in the table is the count of the entries in the table. +// It then uses R0 to index into the table and get the displacement of the +// address to jump to. If R0 is greater than the size of the table, it jumps +// to the last entry in the table. Each displacement in the table is actually +// the distance from lr to the label, thus making the tables PIC. + + + .text + .syntax unified + +// +// The table contains signed byte sized elements which are 1/2 the distance +// from lr to the target label. +// + .align 2 +DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch8) + ldrb ip, [lr, #-1] // get first byte in table + cmp r0, ip // signed compare with index + ldrsbcc r0, [lr, r0] // get indexed byte out of table + ldrsbhs r0, [lr, ip] // if out of range, use last entry in table + add ip, lr, r0, lsl #1 // compute label = lr + element*2 + bx ip // jump to computed label + + // tell linker it can break up file at label boundaries + .subsections_via_symbols + diff --git a/contrib/compiler-rt/lib/arm/switchu8.S b/contrib/compiler-rt/lib/arm/switchu8.S new file mode 100644 index 0000000..19bed2f --- /dev/null +++ b/contrib/compiler-rt/lib/arm/switchu8.S @@ -0,0 +1,43 @@ +//===-- switch.S - Implement switch* --------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// When compiling switch statements in thumb mode, the compiler +// can use these __switch* helper functions The compiler emits a blx to +// the __switch* function followed by a table of displacements for each +// case statement. On entry, R0 is the index into the table. The __switch* +// function uses the return address in lr to find the start of the table. +// The first entry in the table is the count of the entries in the table. +// It then uses R0 to index into the table and get the displacement of the +// address to jump to. If R0 is greater than the size of the table, it jumps +// to the last entry in the table. Each displacement in the table is actually +// the distance from lr to the label, thus making the tables PIC. + + + .text + .syntax unified + +// +// The table contains unsigned byte sized elements which are 1/2 the distance +// from lr to the target label. +// + .align 2 +DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switchu8) + ldrb ip, [lr, #-1] // get first byte in table + cmp r0, ip // compare with index + ldrbcc r0, [lr, r0] // get indexed byte out of table + ldrbhs r0, [lr, ip] // if out of range, use last entry in table + add ip, lr, r0, lsl #1 // compute label = lr + element*2 + bx ip // jump to computed label + + // tell linker it can break up file at label boundaries + .subsections_via_symbols + diff --git a/contrib/compiler-rt/lib/arm/sync_synchronize.S b/contrib/compiler-rt/lib/arm/sync_synchronize.S new file mode 100644 index 0000000..06dade9 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/sync_synchronize.S @@ -0,0 +1,34 @@ +//===-- sync_synchronize - Implement memory barrier * ----------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// When compiling a use of the gcc built-in __sync_synchronize() in thumb1 mode +// the compiler may emit a call to __sync_synchronize. +// On Darwin the implementation jumps to an OS supplied function named +// OSMemoryBarrier +// + + .text + .syntax unified + +#if __APPLE__ + + .align 2 +DEFINE_COMPILERRT_PRIVATE_FUNCTION(__sync_synchronize) + stmfd sp!, {r7, lr} + add r7, sp, #0 + bl _OSMemoryBarrier + ldmfd sp!, {r7, pc} + + // tell linker it can break up file at label boundaries + .subsections_via_symbols + +#endif diff --git a/contrib/compiler-rt/lib/arm/truncdfsf2vfp.S b/contrib/compiler-rt/lib/arm/truncdfsf2vfp.S new file mode 100644 index 0000000..6e55c7f --- /dev/null +++ b/contrib/compiler-rt/lib/arm/truncdfsf2vfp.S @@ -0,0 +1,24 @@ +//===-- truncdfsf2vfp.S - Implement truncdfsf2vfp -------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern float __truncdfsf2vfp(double a); +// +// Converts double precision float to signle precision result. +// Uses Darwin calling convention where a double precision parameter is +// passed in a R0/R1 pair and a signle precision result is returned in R0. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__truncdfsf2vfp) + fmdrr d7, r0, r1 // load double from r0/r1 pair + fcvtsd s15, d7 // convert double to single (trucate precision) + fmrs r0, s15 // return result in r0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/udivmodsi4.S b/contrib/compiler-rt/lib/arm/udivmodsi4.S new file mode 100644 index 0000000..d164a75 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/udivmodsi4.S @@ -0,0 +1,80 @@ +/*===-- udivmodsi4.S - 32-bit unsigned integer divide and modulus ---------===// + * + * 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 __udivmodsi4 (32-bit unsigned integer divide and + * modulus) function for the ARM architecture. A naive digit-by-digit + * computation is employed for simplicity. + * + *===----------------------------------------------------------------------===*/ + +#include "../assembly.h" + +#define ESTABLISH_FRAME \ + push {r4, r7, lr} ;\ + add r7, sp, #4 +#define CLEAR_FRAME_AND_RETURN \ + pop {r4, r7, pc} + +#define a r0 +#define b r1 +#define i r3 +#define r r4 +#define q ip +#define one lr + +.syntax unified +.align 3 +DEFINE_COMPILERRT_FUNCTION(__udivmodsi4) +// We use a simple digit by digit algorithm; before we get into the actual +// divide loop, we must calculate the left-shift amount necessary to align +// the MSB of the divisor with that of the dividend (If this shift is +// negative, then the result is zero, and we early out). We also conjure a +// bit mask of 1 to use in constructing the quotient, and initialize the +// quotient to zero. + ESTABLISH_FRAME + clz r4, a + tst b, b // detect divide-by-zero + clz r3, b + mov q, #0 + beq LOCAL_LABEL(return) // return 0 if b is zero. + mov one, #1 + subs i, r3, r4 + blt LOCAL_LABEL(return) // return 0 if MSB(a) < MSB(b) + +LOCAL_LABEL(mainLoop): +// This loop basically implements the following: +// +// do { +// if (a >= b << i) { +// a -= b << i; +// q |= 1 << i; +// if (a == 0) break; +// } +// } while (--i) +// +// Note that this does not perform the final iteration (i == 0); by doing it +// this way, we can merge the two branches which is a substantial win for +// such a tight loop on current ARM architectures. + subs r, a, b, lsl i + orrhs q, q,one, lsl i + movhs a, r + subsne i, i, #1 + bhi LOCAL_LABEL(mainLoop) + +// Do the final test subtraction and update of quotient (i == 0), as it is +// not performed in the main loop. + subs r, a, b + orrhs q, #1 + movhs a, r + +LOCAL_LABEL(return): +// Store the remainder, and move the quotient to r0, then return. + str a, [r2] + mov r0, q + CLEAR_FRAME_AND_RETURN diff --git a/contrib/compiler-rt/lib/arm/udivsi3.S b/contrib/compiler-rt/lib/arm/udivsi3.S new file mode 100644 index 0000000..6d89665 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/udivsi3.S @@ -0,0 +1,80 @@ +/*===-- udivsi3.S - 32-bit unsigned integer divide ------------------------===// + * + * 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 __udivsi3 (32-bit unsigned integer divide) + * function for the ARM architecture. A naive digit-by-digit computation is + * employed for simplicity. + * + *===----------------------------------------------------------------------===*/ + +#include "../assembly.h" + +#define ESTABLISH_FRAME \ + push {r7, lr} ;\ + mov r7, sp +#define CLEAR_FRAME_AND_RETURN \ + pop {r7, pc} + +#define a r0 +#define b r1 +#define r r2 +#define i r3 +#define q ip +#define one lr + +.syntax unified +.align 3 +// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine. +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_uidiv, __udivsi3) +DEFINE_COMPILERRT_FUNCTION(__udivsi3) +// We use a simple digit by digit algorithm; before we get into the actual +// divide loop, we must calculate the left-shift amount necessary to align +// the MSB of the divisor with that of the dividend (If this shift is +// negative, then the result is zero, and we early out). We also conjure a +// bit mask of 1 to use in constructing the quotient, and initialize the +// quotient to zero. + ESTABLISH_FRAME + clz r2, a + tst b, b // detect divide-by-zero + clz r3, b + mov q, #0 + beq LOCAL_LABEL(return) // return 0 if b is zero. + mov one, #1 + subs i, r3, r2 + blt LOCAL_LABEL(return) // return 0 if MSB(a) < MSB(b) + +LOCAL_LABEL(mainLoop): +// This loop basically implements the following: +// +// do { +// if (a >= b << i) { +// a -= b << i; +// q |= 1 << i; +// if (a == 0) break; +// } +// } while (--i) +// +// Note that this does not perform the final iteration (i == 0); by doing it +// this way, we can merge the two branches which is a substantial win for +// such a tight loop on current ARM architectures. + subs r, a, b, lsl i + orrhs q, q,one, lsl i + movhs a, r + subsne i, i, #1 + bhi LOCAL_LABEL(mainLoop) + +// Do the final test subtraction and update of quotient (i == 0), as it is +// not performed in the main loop. + subs r, a, b + orrhs q, #1 + +LOCAL_LABEL(return): +// Move the quotient to r0 and return. + mov r0, q + CLEAR_FRAME_AND_RETURN diff --git a/contrib/compiler-rt/lib/arm/umodsi3.S b/contrib/compiler-rt/lib/arm/umodsi3.S new file mode 100644 index 0000000..3a2ab2b --- /dev/null +++ b/contrib/compiler-rt/lib/arm/umodsi3.S @@ -0,0 +1,58 @@ +/*===-- umodsi3.S - 32-bit unsigned integer modulus -----------------------===// + * + * 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 __umodsi3 (32-bit unsigned integer modulus) + * function for the ARM architecture. A naive digit-by-digit computation is + * employed for simplicity. + * + *===----------------------------------------------------------------------===*/ + +#include "../assembly.h" + +#define a r0 +#define b r1 +#define r r2 +#define i r3 + +.syntax unified +.align 3 +DEFINE_COMPILERRT_FUNCTION(__umodsi3) +// We use a simple digit by digit algorithm; before we get into the actual +// divide loop, we must calculate the left-shift amount necessary to align +// the MSB of the divisor with that of the dividend. + clz r2, a + tst b, b // detect b == 0 + clz r3, b + bxeq lr // return a if b == 0 + subs i, r3, r2 + bxlt lr // return a if MSB(a) < MSB(b) + +LOCAL_LABEL(mainLoop): +// This loop basically implements the following: +// +// do { +// if (a >= b << i) { +// a -= b << i; +// if (a == 0) break; +// } +// } while (--i) +// +// Note that this does not perform the final iteration (i == 0); by doing it +// this way, we can merge the two branches which is a substantial win for +// such a tight loop on current ARM architectures. + subs r, a, b, lsl i + movhs a, r + subsne i, i, #1 + bhi LOCAL_LABEL(mainLoop) + +// Do the final test subtraction and update of remainder (i == 0), as it is +// not performed in the main loop. + subs r, a, b + movhs a, r + bx lr diff --git a/contrib/compiler-rt/lib/arm/unorddf2vfp.S b/contrib/compiler-rt/lib/arm/unorddf2vfp.S new file mode 100644 index 0000000..9b52131 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/unorddf2vfp.S @@ -0,0 +1,27 @@ +//===-- unorddf2vfp.S - Implement unorddf2vfp ------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __unorddf2vfp(double a, double b); +// +// Returns one iff a or b is NaN +// Uses Darwin calling convention where double precision arguments are passsed +// like in GPR pairs. +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__unorddf2vfp) + fmdrr d6, r0, r1 // load r0/r1 pair in double register + fmdrr d7, r2, r3 // load r2/r3 pair in double register + fcmpd d6, d7 + fmstat + movvs r0, #1 // set result register to 1 if "overflow" (any NaNs) + movvc r0, #0 + bx lr diff --git a/contrib/compiler-rt/lib/arm/unordsf2vfp.S b/contrib/compiler-rt/lib/arm/unordsf2vfp.S new file mode 100644 index 0000000..e486533 --- /dev/null +++ b/contrib/compiler-rt/lib/arm/unordsf2vfp.S @@ -0,0 +1,28 @@ +//===-- unordsf2vfp.S - Implement unordsf2vfp -----------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int __unordsf2vfp(float a, float b); +// +// Returns one iff a or b is NaN +// Uses Darwin calling convention where single precision arguments are passsed +// like 32-bit ints +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__unordsf2vfp) + fmsr s14, r0 // move from GPR 0 to float register + fmsr s15, r1 // move from GPR 1 to float register + fcmps s14, s15 + fmstat + movvs r0, #1 // set result register to 1 if "overflow" (any NaNs) + movvc r0, #0 + bx lr + |