summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/builtins/arm/sync-ops.h
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2014-03-04 10:10:17 +0000
committerTim Northover <tnorthover@apple.com>2014-03-04 10:10:17 +0000
commit1683caab3a3e0aabe5f25351a928913382494a7c (patch)
treef5eeb74e6dddbe2d89ca3de3316eda2f46b6c979 /compiler-rt/lib/builtins/arm/sync-ops.h
parent442f784814262e1271354ee208f1dedc7b8053de (diff)
downloadbcm5719-llvm-1683caab3a3e0aabe5f25351a928913382494a7c.tar.gz
bcm5719-llvm-1683caab3a3e0aabe5f25351a928913382494a7c.zip
ARM: implement __sync_fetch_and_* operations
Since these are primarily useful for deeply embedded targets where code size is very important, they are each in a separate file making use of infrastructure in sync-ops.h. This allows a linker to include just the functions that are actually used. rdar://problem/14736665 llvm-svn: 202812
Diffstat (limited to 'compiler-rt/lib/builtins/arm/sync-ops.h')
-rw-r--r--compiler-rt/lib/builtins/arm/sync-ops.h61
1 files changed, 61 insertions, 0 deletions
diff --git a/compiler-rt/lib/builtins/arm/sync-ops.h b/compiler-rt/lib/builtins/arm/sync-ops.h
new file mode 100644
index 00000000000..0c13394f2c5
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/sync-ops.h
@@ -0,0 +1,61 @@
+/*===-- sync-ops.h - --===//
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ *===----------------------------------------------------------------------===//
+ *
+ * FIXME: description
+ * This file implements the __udivsi3 (32-bit unsigned integer divide)
+ * function for the ARM architecture. A naive digit-by-digit computation is
+ * employed for simplicity.
+ *
+ *===----------------------------------------------------------------------===*/
+
+#include "../assembly.h"
+
+#define SYNC_OP_4(op) \
+ .align 2 ; \
+ .thumb ; \
+ DEFINE_COMPILERRT_FUNCTION(__sync_fetch_and_ ## op) \
+ dmb ; \
+ mov r12, r0 ; \
+ LOCAL_LABEL(tryatomic_ ## op): \
+ ldrex r0, [r12] ; \
+ op(r2, r0, r1) ; \
+ strex r3, r2, [r12] ; \
+ cbnz r3, LOCAL_LABEL(tryatomic_ ## op) ; \
+ dmb ; \
+ bx lr
+
+#define SYNC_OP_8(op) \
+ .align 2 ; \
+ .thumb ; \
+ DEFINE_COMPILERRT_FUNCTION(__sync_fetch_and_ ## op) \
+ push {r4, r5, r6, lr} ; \
+ dmb ; \
+ mov r12, r0 ; \
+ LOCAL_LABEL(tryatomic_ ## op): \
+ ldrexd r0, r1, [r12] ; \
+ op(r4, r5, r0, r1, r2, r3) ; \
+ strexd r6, r4, r5, [r12] ; \
+ cbnz r6, LOCAL_LABEL(tryatomic_ ## op) ; \
+ dmb ; \
+ pop {r4, r5, r6, pc}
+
+#define MINMAX_4(rD, rN, rM, cmp_kind) \
+ cmp rN, rM ; \
+ mov rD, rM ; \
+ it cmp_kind ; \
+ mov##cmp_kind rD, rN
+
+#define MINMAX_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI, cmp_kind) \
+ cmp rN_LO, rM_LO ; \
+ sbcs rN_HI, rM_HI ; \
+ mov rD_LO, rM_LO ; \
+ mov rD_HI, rM_HI ; \
+ itt cmp_kind ; \
+ mov##cmp_kind rD_LO, rN_LO ; \
+ mov##cmp_kind rD_HI, rN_HI
OpenPOWER on IntegriCloud