xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/builtins/avr/udivmodhi4.S (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*81ad6265SDimitry Andric//===------------ udivmodhi4.S - uint16 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 {uint16, uint16}  __udivmodhi4(uint16, uint16)`.
12*81ad6265SDimitry Andric// The uint16 quotient is returned via R23:R22, and the uint16 remainder is
13*81ad6265SDimitry Andric// returned via R25:R24, while R21/R26/R27 are clobbered.
14*81ad6265SDimitry Andric//
15*81ad6265SDimitry Andric//===----------------------------------------------------------------------===//
16*81ad6265SDimitry Andric
17*81ad6265SDimitry Andric	.text
18*81ad6265SDimitry Andric	.align 2
19*81ad6265SDimitry Andric
20*81ad6265SDimitry Andric	.globl __udivmodhi4
21*81ad6265SDimitry Andric	.type  __udivmodhi4, @function
22*81ad6265SDimitry Andric
23*81ad6265SDimitry Andric__udivmodhi4:
24*81ad6265SDimitry Andric	sub     r26, r26
25*81ad6265SDimitry Andric	sub     r27, r27           ; Initialize the remainder to zero.
26*81ad6265SDimitry Andric	ldi     r21, 17            ; Only loop 16 rounds for uint16.
27*81ad6265SDimitry Andric
28*81ad6265SDimitry Andric__udivmodhi4_loop:
29*81ad6265SDimitry Andric	adc     r24, r24
30*81ad6265SDimitry Andric	adc     r25, r25
31*81ad6265SDimitry Andric	dec     r21
32*81ad6265SDimitry Andric	breq    __udivmodhi4_end
33*81ad6265SDimitry Andric	adc     r26, r26
34*81ad6265SDimitry Andric	adc     r27, r27
35*81ad6265SDimitry Andric	cp      r26, r22
36*81ad6265SDimitry Andric	cpc     r27, r23           ; Compare with the divisor.
37*81ad6265SDimitry Andric	brcs    __udivmodhi4_loop
38*81ad6265SDimitry Andric	sub     r26, r22
39*81ad6265SDimitry Andric	sbc     r27, r23           ; Subtract the divisor.
40*81ad6265SDimitry Andric	rjmp    __udivmodhi4_loop
41*81ad6265SDimitry Andric
42*81ad6265SDimitry Andric__udivmodhi4_end:
43*81ad6265SDimitry Andric	com     r24
44*81ad6265SDimitry Andric	com     r25
45*81ad6265SDimitry Andric	mov     r22, r24
46*81ad6265SDimitry Andric	mov     r23, r25           ; The quotient is returned in R23:R22.
47*81ad6265SDimitry Andric	mov     r24, r26
48*81ad6265SDimitry Andric	mov     r25, r27           ; The remainder is returned in in R25:R24.
49*81ad6265SDimitry Andric	ret
50