[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