aboutsummaryrefslogtreecommitdiff
path: root/compiler-rt/lib/builtins/arm/divsi3.S
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/builtins/arm/divsi3.S')
-rw-r--r--compiler-rt/lib/builtins/arm/divsi3.S81
1 files changed, 81 insertions, 0 deletions
diff --git a/compiler-rt/lib/builtins/arm/divsi3.S b/compiler-rt/lib/builtins/arm/divsi3.S
new file mode 100644
index 000000000000..761bf49d3ed0
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/divsi3.S
@@ -0,0 +1,81 @@
+//===-- divsi3.S - 32-bit signed integer divide ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the __divsi3 (32-bit signed integer divide) function
+// for the ARM architecture as a wrapper around the unsigned routine.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+
+#define ESTABLISH_FRAME \
+ push {r4, r7, lr} ;\
+ add r7, sp, #4
+#define CLEAR_FRAME_AND_RETURN \
+ pop {r4, r7, pc}
+
+ .syntax unified
+ .text
+ DEFINE_CODE_STATE
+
+ .p2align 3
+// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine.
+DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_idiv, __divsi3)
+
+@ int __divsi3(int divident, int divisor)
+@ Calculate and return the quotient of the (signed) division.
+
+DEFINE_COMPILERRT_FUNCTION(__divsi3)
+#if __ARM_ARCH_EXT_IDIV__
+ tst r1,r1
+ beq LOCAL_LABEL(divzero)
+ sdiv r0, r0, r1
+ bx lr
+LOCAL_LABEL(divzero):
+ mov r0,#0
+ bx lr
+#else
+ESTABLISH_FRAME
+// Set aside the sign of the quotient.
+# if defined(USE_THUMB_1)
+ movs r4, r0
+ eors r4, r1
+# else
+ eor r4, r0, r1
+# endif
+// Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
+# if defined(USE_THUMB_1)
+ asrs r2, r0, #31
+ asrs r3, r1, #31
+ eors r0, r2
+ eors r1, r3
+ subs r0, r0, r2
+ subs r1, r1, r3
+# else
+ eor r2, r0, r0, asr #31
+ eor r3, r1, r1, asr #31
+ sub r0, r2, r0, asr #31
+ sub r1, r3, r1, asr #31
+# endif
+// abs(a) / abs(b)
+ bl SYMBOL_NAME(__udivsi3)
+// Apply sign of quotient to result and return.
+# if defined(USE_THUMB_1)
+ asrs r4, #31
+ eors r0, r4
+ subs r0, r0, r4
+# else
+ eor r0, r0, r4, asr #31
+ sub r0, r0, r4, asr #31
+# endif
+ CLEAR_FRAME_AND_RETURN
+#endif
+END_COMPILERRT_FUNCTION(__divsi3)
+
+NO_EXEC_STACK_DIRECTIVE
+