@@ -43,6 +43,92 @@ intrinsics! {
4343
4444 ( ( rem as u64 ) << 32 ) | ( div as u64 )
4545 }
46+
47+ #[ unsafe ( 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+ #[ unsafe ( 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
48134intrinsics ! {
0 commit comments