diff options
Diffstat (limited to 'lib/arm')
47 files changed, 1393 insertions, 0 deletions
diff --git a/lib/arm/CMakeLists.txt b/lib/arm/CMakeLists.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/lib/arm/CMakeLists.txt diff --git a/lib/arm/Makefile.mk b/lib/arm/Makefile.mk new file mode 100644 index 000000000000..cde97c3f99ae --- /dev/null +++ b/lib/arm/Makefile.mk @@ -0,0 +1,19 @@ +#===- lib/arm/Makefile.mk ----------------------------------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +SubDirs := +OnlyArchs := armv5 armv6 armv7 + +AsmSources := $(foreach file,$(wildcard $(Dir)/*.S),$(notdir $(file))) +Sources := $(foreach file,$(wildcard $(Dir)/*.c),$(notdir $(file))) +ObjNames := $(Sources:%.c=%.o) $(AsmSources:%.S=%.o) +Implementation := Optimized + +# FIXME: use automatic dependencies? +Dependencies := $(wildcard lib/*.h $(Dir)/*.h) diff --git a/lib/arm/adddf3vfp.S b/lib/arm/adddf3vfp.S new file mode 100644 index 000000000000..5e705e3c5796 --- /dev/null +++ b/lib/arm/adddf3vfp.S @@ -0,0 +1,24 @@ +//===-- adddf3vfp.S - Implement adddf3vfp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/addsf3vfp.S b/lib/arm/addsf3vfp.S new file mode 100644 index 000000000000..36d509c1f52b --- /dev/null +++ b/lib/arm/addsf3vfp.S @@ -0,0 +1,24 @@ +//===-- addsf3vfp.S - Implement addsf3vfp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/bswapdi2.S b/lib/arm/bswapdi2.S new file mode 100644 index 000000000000..d3ca33a341c7 --- /dev/null +++ b/lib/arm/bswapdi2.S @@ -0,0 +1,36 @@ +//===------- bswapdi2 - Implement bswapdi2 --------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/bswapsi2.S b/lib/arm/bswapsi2.S new file mode 100644 index 000000000000..0a0c073706ce --- /dev/null +++ b/lib/arm/bswapsi2.S @@ -0,0 +1,28 @@ +//===------- bswapsi2 - Implement bswapsi2 --------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/comparesf2.S b/lib/arm/comparesf2.S new file mode 100644 index 000000000000..f21e0bcd13f6 --- /dev/null +++ b/lib/arm/comparesf2.S @@ -0,0 +1,130 @@ +//===-- comparesf2.S - Implement single-precision soft-float comparisons --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/divdf3vfp.S b/lib/arm/divdf3vfp.S new file mode 100644 index 000000000000..e43baa373274 --- /dev/null +++ b/lib/arm/divdf3vfp.S @@ -0,0 +1,24 @@ +//===-- divdf3vfp.S - Implement divdf3vfp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/divsf3vfp.S b/lib/arm/divsf3vfp.S new file mode 100644 index 000000000000..d96c930f8352 --- /dev/null +++ b/lib/arm/divsf3vfp.S @@ -0,0 +1,24 @@ +//===-- divsf3vfp.S - Implement divsf3vfp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/eqdf2vfp.S b/lib/arm/eqdf2vfp.S new file mode 100644 index 000000000000..d4384ec0e5ea --- /dev/null +++ b/lib/arm/eqdf2vfp.S @@ -0,0 +1,27 @@ +//===-- eqdf2vfp.S - Implement eqdf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/eqsf2vfp.S b/lib/arm/eqsf2vfp.S new file mode 100644 index 000000000000..07355a3c2239 --- /dev/null +++ b/lib/arm/eqsf2vfp.S @@ -0,0 +1,28 @@ +//===-- eqsf2vfp.S - Implement eqsf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/extendsfdf2vfp.S b/lib/arm/extendsfdf2vfp.S new file mode 100644 index 000000000000..4343a7ef1ed4 --- /dev/null +++ b/lib/arm/extendsfdf2vfp.S @@ -0,0 +1,24 @@ +//===-- extendsfdf2vfp.S - Implement extendsfdf2vfp -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/fixdfsivfp.S b/lib/arm/fixdfsivfp.S new file mode 100644 index 000000000000..30458ccd59b3 --- /dev/null +++ b/lib/arm/fixdfsivfp.S @@ -0,0 +1,24 @@ +//===-- fixdfsivfp.S - Implement fixdfsivfp -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/fixsfsivfp.S b/lib/arm/fixsfsivfp.S new file mode 100644 index 000000000000..ce6f18e1b90c --- /dev/null +++ b/lib/arm/fixsfsivfp.S @@ -0,0 +1,24 @@ +//===-- fixsfsivfp.S - Implement fixsfsivfp -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/fixunsdfsivfp.S b/lib/arm/fixunsdfsivfp.S new file mode 100644 index 000000000000..7e766c02a5e8 --- /dev/null +++ b/lib/arm/fixunsdfsivfp.S @@ -0,0 +1,25 @@ +//===-- fixunsdfsivfp.S - Implement fixunsdfsivfp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/fixunssfsivfp.S b/lib/arm/fixunssfsivfp.S new file mode 100644 index 000000000000..ba2344f587e7 --- /dev/null +++ b/lib/arm/fixunssfsivfp.S @@ -0,0 +1,25 @@ +//===-- fixunssfsivfp.S - Implement fixunssfsivfp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/floatsidfvfp.S b/lib/arm/floatsidfvfp.S new file mode 100644 index 000000000000..5ed4ace9b2c0 --- /dev/null +++ b/lib/arm/floatsidfvfp.S @@ -0,0 +1,24 @@ +//===-- floatsidfvfp.S - Implement floatsidfvfp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/floatsisfvfp.S b/lib/arm/floatsisfvfp.S new file mode 100644 index 000000000000..0114c789358a --- /dev/null +++ b/lib/arm/floatsisfvfp.S @@ -0,0 +1,24 @@ +//===-- floatsisfvfp.S - Implement floatsisfvfp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/floatunssidfvfp.S b/lib/arm/floatunssidfvfp.S new file mode 100644 index 000000000000..d1bfe3af5841 --- /dev/null +++ b/lib/arm/floatunssidfvfp.S @@ -0,0 +1,24 @@ +//===-- floatunssidfvfp.S - Implement floatunssidfvfp ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/floatunssisfvfp.S b/lib/arm/floatunssisfvfp.S new file mode 100644 index 000000000000..0b73577b1067 --- /dev/null +++ b/lib/arm/floatunssisfvfp.S @@ -0,0 +1,24 @@ +//===-- floatunssisfvfp.S - Implement floatunssisfvfp ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/gedf2vfp.S b/lib/arm/gedf2vfp.S new file mode 100644 index 000000000000..6ab856fe6f34 --- /dev/null +++ b/lib/arm/gedf2vfp.S @@ -0,0 +1,27 @@ +//===-- gedf2vfp.S - Implement gedf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/gesf2vfp.S b/lib/arm/gesf2vfp.S new file mode 100644 index 000000000000..b00d82107dc3 --- /dev/null +++ b/lib/arm/gesf2vfp.S @@ -0,0 +1,28 @@ +//===-- gesf2vfp.S - Implement gesf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/gtdf2vfp.S b/lib/arm/gtdf2vfp.S new file mode 100644 index 000000000000..65594c7d3f92 --- /dev/null +++ b/lib/arm/gtdf2vfp.S @@ -0,0 +1,27 @@ +//===-- gtdf2vfp.S - Implement gtdf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/gtsf2vfp.S b/lib/arm/gtsf2vfp.S new file mode 100644 index 000000000000..53ef2a00f804 --- /dev/null +++ b/lib/arm/gtsf2vfp.S @@ -0,0 +1,28 @@ +//===-- gtsf2vfp.S - Implement gtsf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/ledf2vfp.S b/lib/arm/ledf2vfp.S new file mode 100644 index 000000000000..327a7d5159f7 --- /dev/null +++ b/lib/arm/ledf2vfp.S @@ -0,0 +1,27 @@ +//===-- ledf2vfp.S - Implement ledf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/lesf2vfp.S b/lib/arm/lesf2vfp.S new file mode 100644 index 000000000000..b7e05da9b42b --- /dev/null +++ b/lib/arm/lesf2vfp.S @@ -0,0 +1,28 @@ +//===-- lesf2vfp.S - Implement lesf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/ltdf2vfp.S b/lib/arm/ltdf2vfp.S new file mode 100644 index 000000000000..55dfd808a3b8 --- /dev/null +++ b/lib/arm/ltdf2vfp.S @@ -0,0 +1,27 @@ +//===-- ltdf2vfp.S - Implement ltdf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/ltsf2vfp.S b/lib/arm/ltsf2vfp.S new file mode 100644 index 000000000000..3816a7123a64 --- /dev/null +++ b/lib/arm/ltsf2vfp.S @@ -0,0 +1,28 @@ +//===-- ltsf2vfp.S - Implement ltsf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/modsi3.S b/lib/arm/modsi3.S new file mode 100644 index 000000000000..64a3afd9aa06 --- /dev/null +++ b/lib/arm/modsi3.S @@ -0,0 +1,36 @@ +//===-------- modsi3.S - Implement modsi3 ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// +// extern int32_t __modsi3(int32_t a, int32_t b); +// +// Returns the remainder when dividing two 32-bit signed integers. +// Conceptually, the function is: { return a - (a / b) * b; } +// But if you write that in C, llvm compiles it to a call to __modsi3... +// + .align 2 +DEFINE_COMPILERRT_FUNCTION(__modsi3) + push {r4, r5, r7, lr} + add r7, sp, #8 // set stack frame + mov r5, r0 // save a + mov r4, r1 // save b + bl ___divsi3 // compute a/b +#if __ARM_ARCH_7A__ + mls r0, r4, r0, r5 // mulitple result * b and subtract from a +#else + // before armv7, does not have "mls" instruction + mul r3, r0, r4 // multiple result * b + sub r0, r5, r3 // a - result +#endif + pop {r4, r5, r7, pc} + + + diff --git a/lib/arm/muldf3vfp.S b/lib/arm/muldf3vfp.S new file mode 100644 index 000000000000..cb503d309121 --- /dev/null +++ b/lib/arm/muldf3vfp.S @@ -0,0 +1,24 @@ +//===-- muldf3vfp.S - Implement muldf3vfp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/mulsf3vfp.S b/lib/arm/mulsf3vfp.S new file mode 100644 index 000000000000..49b4d1df9468 --- /dev/null +++ b/lib/arm/mulsf3vfp.S @@ -0,0 +1,24 @@ +//===-- mulsf3vfp.S - Implement mulsf3vfp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/nedf2vfp.S b/lib/arm/nedf2vfp.S new file mode 100644 index 000000000000..813864e88302 --- /dev/null +++ b/lib/arm/nedf2vfp.S @@ -0,0 +1,27 @@ +//===-- nedf2vfp.S - Implement nedf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/negdf2vfp.S b/lib/arm/negdf2vfp.S new file mode 100644 index 000000000000..8013975445ad --- /dev/null +++ b/lib/arm/negdf2vfp.S @@ -0,0 +1,21 @@ +//===-- negdf2vfp.S - Implement negdf2vfp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/negsf2vfp.S b/lib/arm/negsf2vfp.S new file mode 100644 index 000000000000..243c0865c8cc --- /dev/null +++ b/lib/arm/negsf2vfp.S @@ -0,0 +1,21 @@ +//===-- negsf2vfp.S - Implement negsf2vfp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/nesf2vfp.S b/lib/arm/nesf2vfp.S new file mode 100644 index 000000000000..d470afa0ef7e --- /dev/null +++ b/lib/arm/nesf2vfp.S @@ -0,0 +1,28 @@ +//===-- nesf2vfp.S - Implement nesf2vfp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/restore_vfp_d8_d15_regs.S b/lib/arm/restore_vfp_d8_d15_regs.S new file mode 100644 index 000000000000..25404cd25076 --- /dev/null +++ b/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 distributed under the University of Illinois Open Source +// License. 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/lib/arm/save_vfp_d8_d15_regs.S b/lib/arm/save_vfp_d8_d15_regs.S new file mode 100644 index 000000000000..92de61bc6e8f --- /dev/null +++ b/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 distributed under the University of Illinois Open Source +// License. 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/lib/arm/subdf3vfp.S b/lib/arm/subdf3vfp.S new file mode 100644 index 000000000000..88416006a061 --- /dev/null +++ b/lib/arm/subdf3vfp.S @@ -0,0 +1,24 @@ +//===-- subdf3vfp.S - Implement subdf3vfp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/subsf3vfp.S b/lib/arm/subsf3vfp.S new file mode 100644 index 000000000000..4ead9c23e712 --- /dev/null +++ b/lib/arm/subsf3vfp.S @@ -0,0 +1,25 @@ +//===-- subsf3vfp.S - Implement subsf3vfp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/switch16.S b/lib/arm/switch16.S new file mode 100644 index 000000000000..05c7b98b01ab --- /dev/null +++ b/lib/arm/switch16.S @@ -0,0 +1,44 @@ +//===-- switch.S - Implement switch* --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/switch32.S b/lib/arm/switch32.S new file mode 100644 index 000000000000..a127cb79f534 --- /dev/null +++ b/lib/arm/switch32.S @@ -0,0 +1,46 @@ +//===-- switch.S - Implement switch* --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/switch8.S b/lib/arm/switch8.S new file mode 100644 index 000000000000..d05f6ac7f068 --- /dev/null +++ b/lib/arm/switch8.S @@ -0,0 +1,43 @@ +//===-- switch.S - Implement switch* --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/switchu8.S b/lib/arm/switchu8.S new file mode 100644 index 000000000000..faffddb50c1e --- /dev/null +++ b/lib/arm/switchu8.S @@ -0,0 +1,43 @@ +//===-- switch.S - Implement switch* --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/sync_synchronize.S b/lib/arm/sync_synchronize.S new file mode 100644 index 000000000000..76fdab1fbdb2 --- /dev/null +++ b/lib/arm/sync_synchronize.S @@ -0,0 +1,34 @@ +//===-- sync_synchronize - Implement memory barrier * ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/truncdfsf2vfp.S b/lib/arm/truncdfsf2vfp.S new file mode 100644 index 000000000000..5725e25c76a7 --- /dev/null +++ b/lib/arm/truncdfsf2vfp.S @@ -0,0 +1,24 @@ +//===-- truncdfsf2vfp.S - Implement truncdfsf2vfp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/unorddf2vfp.S b/lib/arm/unorddf2vfp.S new file mode 100644 index 000000000000..de00b07feef9 --- /dev/null +++ b/lib/arm/unorddf2vfp.S @@ -0,0 +1,27 @@ +//===-- unorddf2vfp.S - Implement unorddf2vfp ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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/lib/arm/unordsf2vfp.S b/lib/arm/unordsf2vfp.S new file mode 100644 index 000000000000..ab291a858dab --- /dev/null +++ b/lib/arm/unordsf2vfp.S @@ -0,0 +1,28 @@ +//===-- unordsf2vfp.S - Implement unordsf2vfp -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. 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 + |