Skip to content

Commit d05d6cd

Browse files
committed
avr: __udivmodqi4
1 parent 9978a8b commit d05d6cd

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

compiler-builtins/src/int/udiv.rs

+35
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,41 @@ intrinsics! {
4343

4444
((rem as u64) << 32) | (div as u64)
4545
}
46+
47+
#[naked]
48+
pub unsafe extern "C" fn __udivmodqi4() {
49+
// compute unsigned 8-bit `n / d` and `n % d`.
50+
//
51+
// Note: GCC implements a [non-standard calling convention](https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention) for this function.
52+
// Inputs:
53+
// R24: dividend
54+
// R22: divisor
55+
// Outputs:
56+
// R24: quotient (dividend / divisor)
57+
// R25: remainder (dividend % divisor)
58+
// Clobbers:
59+
// R23: loop counter
60+
core::arch::naked_asm!(
61+
// This assembly routine implements the [long division](https://en.wikipedia.org/wiki/Division_algorithm#Long_division) algorithm.
62+
// Bits shift out of the dividend and into the quotient, so R24 is used for both.
63+
"clr R25", // remainder = 0
64+
65+
"ldi R23, 8", // for each bit
66+
"1:",
67+
"lsl R24", // shift the dividend MSb
68+
"rol R25", // into the remainder LSb
69+
70+
"cp R25, R22", // if remainder >= divisor
71+
"brlo 2f",
72+
"sub R25, R22", // remainder -= divisor
73+
"sbr R24, 1", // quotient |= 1
74+
"2:",
75+
76+
"dec R23", // end loop
77+
"brne 1b",
78+
"ret",
79+
);
80+
}
4681
}
4782

4883
intrinsics! {

0 commit comments

Comments
 (0)