@@ -43,6 +43,92 @@ intrinsics! {
43
43
44
44
( ( rem as u64 ) << 32 ) | ( div as u64 )
45
45
}
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
+
46
132
}
47
133
48
134
intrinsics ! {
0 commit comments