xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/builtins/avr/divmodhi4.S (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*81ad6265SDimitry Andric//===------------- divmodhi4.S - sint16 div & mod -------------------------===//
2*81ad6265SDimitry Andric//
3*81ad6265SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*81ad6265SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
5*81ad6265SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*81ad6265SDimitry Andric//
7*81ad6265SDimitry Andric//===----------------------------------------------------------------------===//
8*81ad6265SDimitry Andric//
9*81ad6265SDimitry Andric// As described at
10*81ad6265SDimitry Andric// https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention, the
11*81ad6265SDimitry Andric// prototype is `struct {sint16, sint16}  __divmodhi4(sint16, sint16)`.
12*81ad6265SDimitry Andric// The sint16 quotient is returned via R23:R22, and the sint16 remainder is
13*81ad6265SDimitry Andric// returned via R25:R24, while registers R21/R26/27/Rtmp and bit T in SREG
14*81ad6265SDimitry Andric// are clobbered.
15*81ad6265SDimitry Andric//
16*81ad6265SDimitry Andric//===----------------------------------------------------------------------===//
17*81ad6265SDimitry Andric
18*81ad6265SDimitry Andric	.text
19*81ad6265SDimitry Andric	.align 2
20*81ad6265SDimitry Andric
21*81ad6265SDimitry Andric#ifdef __AVR_TINY__
22*81ad6265SDimitry Andric	.set __tmp_reg__, 16
23*81ad6265SDimitry Andric#else
24*81ad6265SDimitry Andric	.set __tmp_reg__, 0
25*81ad6265SDimitry Andric#endif
26*81ad6265SDimitry Andric
27*81ad6265SDimitry Andric	.globl __divmodhi4
28*81ad6265SDimitry Andric	.type  __divmodhi4, @function
29*81ad6265SDimitry Andric
30*81ad6265SDimitry Andric__divmodhi4:
31*81ad6265SDimitry Andric	bst     r25, 7
32*81ad6265SDimitry Andric	mov     __tmp_reg__, r23
33*81ad6265SDimitry Andric	brtc    __divmodhi4_a
34*81ad6265SDimitry Andric	com     __tmp_reg__
35*81ad6265SDimitry Andric	rcall   __divmodhi4_b
36*81ad6265SDimitry Andric
37*81ad6265SDimitry Andric__divmodhi4_a:
38*81ad6265SDimitry Andric	sbrc    r23, 7
39*81ad6265SDimitry Andric	rcall   __divmodhi4_c
40*81ad6265SDimitry Andric	rcall   __udivmodhi4 ; Call __udivmodhi4 to do real calculation.
41*81ad6265SDimitry Andric	sbrc    __tmp_reg__, 7
42*81ad6265SDimitry Andric	rcall   __divmodhi4_c
43*81ad6265SDimitry Andric	brtc    __divmodhi4_exit
44*81ad6265SDimitry Andric
45*81ad6265SDimitry Andric__divmodhi4_b:
46*81ad6265SDimitry Andric	com     r25
47*81ad6265SDimitry Andric	neg     r24
48*81ad6265SDimitry Andric	sbci    r25, 255
49*81ad6265SDimitry Andric	ret                  ; Return quotient via R23:R22 and remainder via R25:R24.
50*81ad6265SDimitry Andric
51*81ad6265SDimitry Andric__divmodhi4_c:
52*81ad6265SDimitry Andric	com     r23
53*81ad6265SDimitry Andric	neg     r22
54*81ad6265SDimitry Andric	sbci    r23, 255
55*81ad6265SDimitry Andric
56*81ad6265SDimitry Andric__divmodhi4_exit:
57*81ad6265SDimitry Andric	ret                  ; Return quotient via R23:R22 and remainder via R25:r24.
58