aboutsummaryrefslogtreecommitdiff
path: root/lib/arm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/arm')
-rw-r--r--lib/arm/CMakeLists.txt0
-rw-r--r--lib/arm/Makefile.mk19
-rw-r--r--lib/arm/adddf3vfp.S24
-rw-r--r--lib/arm/addsf3vfp.S24
-rw-r--r--lib/arm/bswapdi2.S36
-rw-r--r--lib/arm/bswapsi2.S28
-rw-r--r--lib/arm/comparesf2.S130
-rw-r--r--lib/arm/divdf3vfp.S24
-rw-r--r--lib/arm/divsf3vfp.S24
-rw-r--r--lib/arm/eqdf2vfp.S27
-rw-r--r--lib/arm/eqsf2vfp.S28
-rw-r--r--lib/arm/extendsfdf2vfp.S24
-rw-r--r--lib/arm/fixdfsivfp.S24
-rw-r--r--lib/arm/fixsfsivfp.S24
-rw-r--r--lib/arm/fixunsdfsivfp.S25
-rw-r--r--lib/arm/fixunssfsivfp.S25
-rw-r--r--lib/arm/floatsidfvfp.S24
-rw-r--r--lib/arm/floatsisfvfp.S24
-rw-r--r--lib/arm/floatunssidfvfp.S24
-rw-r--r--lib/arm/floatunssisfvfp.S24
-rw-r--r--lib/arm/gedf2vfp.S27
-rw-r--r--lib/arm/gesf2vfp.S28
-rw-r--r--lib/arm/gtdf2vfp.S27
-rw-r--r--lib/arm/gtsf2vfp.S28
-rw-r--r--lib/arm/ledf2vfp.S27
-rw-r--r--lib/arm/lesf2vfp.S28
-rw-r--r--lib/arm/ltdf2vfp.S27
-rw-r--r--lib/arm/ltsf2vfp.S28
-rw-r--r--lib/arm/modsi3.S36
-rw-r--r--lib/arm/muldf3vfp.S24
-rw-r--r--lib/arm/mulsf3vfp.S24
-rw-r--r--lib/arm/nedf2vfp.S27
-rw-r--r--lib/arm/negdf2vfp.S21
-rw-r--r--lib/arm/negsf2vfp.S21
-rw-r--r--lib/arm/nesf2vfp.S28
-rw-r--r--lib/arm/restore_vfp_d8_d15_regs.S37
-rw-r--r--lib/arm/save_vfp_d8_d15_regs.S35
-rw-r--r--lib/arm/subdf3vfp.S24
-rw-r--r--lib/arm/subsf3vfp.S25
-rw-r--r--lib/arm/switch16.S44
-rw-r--r--lib/arm/switch32.S46
-rw-r--r--lib/arm/switch8.S43
-rw-r--r--lib/arm/switchu8.S43
-rw-r--r--lib/arm/sync_synchronize.S34
-rw-r--r--lib/arm/truncdfsf2vfp.S24
-rw-r--r--lib/arm/unorddf2vfp.S27
-rw-r--r--lib/arm/unordsf2vfp.S28
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
+