[compiler-rt] 70a66c0 - [compiler-rt][builtins] Add helper functions for uint16/sint16/uint8/sint8 div and mod
Ben Shi via llvm-commits
llvm-commits at lists.llvm.org
Thu May 5 16:29:41 PDT 2022
Author: Ben Shi
Date: 2022-05-05T23:29:14Z
New Revision: 70a66c08fc6534c78eb5104b3293a9fa81350da3
URL: https://github.com/llvm/llvm-project/commit/70a66c08fc6534c78eb5104b3293a9fa81350da3
DIFF: https://github.com/llvm/llvm-project/commit/70a66c08fc6534c78eb5104b3293a9fa81350da3.diff
LOG: [compiler-rt][builtins] Add helper functions for uint16/sint16/uint8/sint8 div and mod
__udivmodhi4 : uint16 div and mod
__udivmodqi4 : uint8 div and mod
__divmodhi4 : sint16 div and mod
__divmodqi4 : sint8 div and mod
The above helper functions in libgcc have special ABI as described at
https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention .
Reviewed By: aykevl
Differential Revision: https://reviews.llvm.org/D124600
Added:
compiler-rt/lib/builtins/avr/divmodhi4.S
compiler-rt/lib/builtins/avr/divmodqi4.S
compiler-rt/lib/builtins/avr/udivmodhi4.S
compiler-rt/lib/builtins/avr/udivmodqi4.S
Modified:
compiler-rt/lib/builtins/CMakeLists.txt
Removed:
################################################################################
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index c9438879f279d..1b2c7b201c229 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -572,6 +572,10 @@ set(avr_SOURCES
avr/mulqi3.S
avr/mulhi3.S
avr/exit.S
+ avr/divmodhi4.S
+ avr/udivmodhi4.S
+ avr/divmodqi4.S
+ avr/udivmodqi4.S
${GENERIC_SOURCES}
)
diff --git a/compiler-rt/lib/builtins/avr/divmodhi4.S b/compiler-rt/lib/builtins/avr/divmodhi4.S
new file mode 100644
index 0000000000000..37171331f4b32
--- /dev/null
+++ b/compiler-rt/lib/builtins/avr/divmodhi4.S
@@ -0,0 +1,57 @@
+//===------------- divmodhi4.S - sint16 div & mod -------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// As described at
+// https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention, the
+// prototype is `struct {sint16, sint16} __divmodhi4(sint16, sint16)`.
+// The sint16 quotient is returned via R23:R22, and the sint16 remainder is
+// returned via R25:R24, while registers R21/R26/27/Rtmp and bit T in SREG
+// are clobbered.
+//
+//===----------------------------------------------------------------------===//
+
+ .text
+ .align 2
+
+#ifdef __AVR_TINY__
+ .set __tmp_reg__, 16
+#else
+ .set __tmp_reg__, 0
+#endif
+
+ .globl __divmodhi4
+ .type __divmodhi4, @function
+
+__divmodhi4:
+ bst r25, 7
+ mov __tmp_reg__, r23
+ brtc __divmodhi4_a
+ com __tmp_reg__
+ rcall __divmodhi4_b
+
+__divmodhi4_a:
+ sbrc r23, 7
+ rcall __divmodhi4_c
+ rcall __udivmodhi4 ; Call __udivmodhi4 to do real calculation.
+ sbrc __tmp_reg__, 7
+ rcall __divmodhi4_c
+ brtc __divmodhi4_exit
+
+__divmodhi4_b:
+ com r25
+ neg r24
+ sbci r25, 255
+ ret ; Return quotient via R23:R22 and remainder via R25:R24.
+
+__divmodhi4_c:
+ com r23
+ neg r22
+ sbci r23, 255
+
+__divmodhi4_exit:
+ ret ; Return quotient via R23:R22 and remainder via R25:r24.
diff --git a/compiler-rt/lib/builtins/avr/divmodqi4.S b/compiler-rt/lib/builtins/avr/divmodqi4.S
new file mode 100644
index 0000000000000..66cfc0c69bbaa
--- /dev/null
+++ b/compiler-rt/lib/builtins/avr/divmodqi4.S
@@ -0,0 +1,44 @@
+//===------------- divmodqi4.S - sint8 div & mod --------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// As described at
+// https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention, the
+// prototype is `struct {sint8, sint8} __divmodqi4(sint8, sint8)`.
+// The sint8 quotient is returned via R24, and the sint8 remainder is returned
+// via R25, while registers R23/Rtmp and bit T in SREG are clobbered.
+//
+//===----------------------------------------------------------------------===//
+
+ .text
+ .align 2
+
+#ifdef __AVR_TINY__
+ .set __tmp_reg__, 16
+#else
+ .set __tmp_reg__, 0
+#endif
+
+ .globl __divmodqi4
+ .type __divmodqi4, @function
+
+__divmodqi4:
+ bst r24, 7
+ mov __tmp_reg__, r24
+ eor __tmp_reg__, r22
+ sbrc r24, 7
+ neg r24
+ sbrc r22, 7
+ neg r22
+ rcall __udivmodqi4 ; Call __udivmodqi4 to do real calculation.
+ brtc __divmodqi4_1
+ neg r25
+
+__divmodqi4_1:
+ sbrc __tmp_reg__, 7
+ neg r24
+ ret ; Return quotient via R24 and remainder via R25.
diff --git a/compiler-rt/lib/builtins/avr/udivmodhi4.S b/compiler-rt/lib/builtins/avr/udivmodhi4.S
new file mode 100644
index 0000000000000..0e52b86ec797b
--- /dev/null
+++ b/compiler-rt/lib/builtins/avr/udivmodhi4.S
@@ -0,0 +1,49 @@
+//===------------ udivmodhi4.S - uint16 div & mod -------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// As described at
+// https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention, the
+// prototype is `struct {uint16, uint16} __udivmodhi4(uint16, uint16)`.
+// The uint16 quotient is returned via R23:R22, and the uint16 remainder is
+// returned via R25:R24, while R21/R26/R27 are clobbered.
+//
+//===----------------------------------------------------------------------===//
+
+ .text
+ .align 2
+
+ .globl __udivmodhi4
+ .type __udivmodhi4, @function
+
+__udivmodhi4:
+ sub r26, r26
+ sub r27, r27 ; Initialize the remainder to zero.
+ ldi r21, 17 ; Only loop 16 rounds for uint16.
+
+__udivmodhi4_loop:
+ adc r24, r24
+ adc r25, r25
+ dec r21
+ breq __udivmodhi4_end
+ adc r26, r26
+ adc r27, r27
+ cp r26, r22
+ cpc r27, r23 ; Compare with the divisor.
+ brcs __udivmodhi4_loop
+ sub r26, r22
+ sbc r27, r23 ; Subtract the divisor.
+ rjmp __udivmodhi4_loop
+
+__udivmodhi4_end:
+ com r24
+ com r25
+ mov r22, r24
+ mov r23, r25 ; The quotient is returned in R23:R22.
+ mov r24, r26
+ mov r25, r27 ; The remainder is returned in in R25:R24.
+ ret
diff --git a/compiler-rt/lib/builtins/avr/udivmodqi4.S b/compiler-rt/lib/builtins/avr/udivmodqi4.S
new file mode 100644
index 0000000000000..99aec34429361
--- /dev/null
+++ b/compiler-rt/lib/builtins/avr/udivmodqi4.S
@@ -0,0 +1,39 @@
+//===------------ udivmodqi4.S - uint8 div & mod --------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// As described at
+// https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention, the
+// prototype is `struct {uint8, uint8} __udivmodqi4(uint8, uint8)`.
+// The uint8 quotient is returned via R24, and the uint8 remainder is returned
+// via R25, while R23 is clobbered.
+//
+//===----------------------------------------------------------------------===//
+
+ .text
+ .align 2
+
+ .globl __udivmodqi4
+ .type __udivmodqi4, @function
+
+__udivmodqi4:
+ sub r25, r25 ; Initialize the remainder to zero.
+ ldi r23, 9 ; Only loop 8 rounds for uint8.
+
+__udivmodqi4_loop:
+ adc r24, r24
+ dec r23
+ breq __udivmodqi4_end
+ adc r25, r25
+ cp r25, r22 ; Compare with the divisor.
+ brcs __udivmodqi4_loop
+ sub r25, r22 ; Subtract the divisor.
+ rjmp __udivmodqi4_loop
+
+__udivmodqi4_end:
+ com r24 ; The uint8 quotient is returned via R24.
+ ret ; The uint8 remainder is returned via R25.
More information about the llvm-commits
mailing list