Skip to content

Commit bea0c78

Browse files
committed
avr: __udivmod(h|q)i4
1 parent 9978a8b commit bea0c78

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

Diff for: compiler-builtins/src/int/udiv.rs

+86
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,92 @@ 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+
}
81+
82+
#[naked]
83+
pub unsafe extern "C" fn __udivmodhi4() {
84+
// compute unsigned 16-bit `n / d` and `n % d`.
85+
//
86+
// Note: GCC implements a [non-standard calling convention](https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention) for this function.
87+
// Inputs:
88+
// R24: dividend [low]
89+
// R25: dividend [high]
90+
// R22: divisor [low]
91+
// R23: divisor [high]
92+
// Outputs:
93+
// R22: quotient [low] (dividend / divisor)
94+
// R23: quotient [high]
95+
// R24: remainder [low] (dividend % divisor)
96+
// R25: remainder [high]
97+
// Clobbers:
98+
// R21: loop counter
99+
// R26: divisor [low]
100+
// R27: divisor [high]
101+
core::arch::naked_asm!(
102+
// This assembly routine implements the [long division](https://en.wikipedia.org/wiki/Division_algorithm#Long_division) algorithm.
103+
// Bits shift out of the dividend and into the quotient, so R24+R25 are used for both.
104+
"mov R26, R22", // move divisor to make room for quotient
105+
"mov R27, R23",
106+
"mov R22, R24", // move dividend to output location (becomes quotient)
107+
"mov R23, R25",
108+
"clr R24", // remainder = 0
109+
"clr R25",
110+
111+
"ldi R21, 16", // for each bit
112+
"1:",
113+
"lsl R22", // shift the dividend MSb
114+
"rol R23",
115+
"rol R24", // into the remainder LSb
116+
"rol R25",
117+
118+
"cp R24, R26", // if remainder >= divisor
119+
"cpc R25, R27",
120+
"brlo 2f",
121+
"sub R24, R26", // remainder -= divisor
122+
"sbc R25, R27",
123+
"sbr R22, 1", // quotient |= 1
124+
"2:",
125+
126+
"dec R21", // end loop
127+
"brne 1b",
128+
"ret",
129+
);
130+
}
131+
46132
}
47133

48134
intrinsics! {

0 commit comments

Comments
 (0)