@@ -114,152 +114,159 @@ pub extern "C" fn __umoddi3(a: u64, b: u64) -> u64 {
114
114
rem
115
115
}
116
116
117
- /// Returns `n / d` and sets `*rem = n % d`
118
- #[ cfg_attr( not( test) , no_mangle) ]
119
- pub extern "C" fn __udivmoddi4 ( n : u64 , d : u64 , rem : Option < & mut u64 > ) -> u64 {
120
- // NOTE X is unknown, K != 0
121
- if n. high ( ) == 0 {
122
- if d. high ( ) == 0 {
123
- // 0 X
124
- // ---
125
- // 0 X
117
+ macro_rules! udivmod_inner {
118
+ ( $n: expr, $d: expr, $rem: expr, $ty: ty, $tys: ty, $tyh: ty) => { {
119
+ let ( n, d, rem) = ( $n, $d, $rem) ;
120
+ // NOTE X is unknown, K != 0
121
+ if n. high( ) == 0 {
122
+ if d. high( ) == 0 {
123
+ // 0 X
124
+ // ---
125
+ // 0 X
126
+
127
+ if let Some ( rem) = rem {
128
+ * rem = <$ty>:: from( urem!( n. low( ) , d. low( ) ) ) ;
129
+ }
130
+ return <$ty>:: from( udiv!( n. low( ) , d. low( ) ) ) ;
131
+ } else {
132
+ // 0 X
133
+ // ---
134
+ // K X
135
+ if let Some ( rem) = rem {
136
+ * rem = n;
137
+ }
138
+ return 0 ;
139
+ } ;
140
+ }
126
141
127
- if let Some ( rem) = rem {
128
- * rem = u64:: from ( urem ! ( n. low( ) , d. low( ) ) ) ;
142
+ let mut sr;
143
+ let mut q;
144
+ let mut r;
145
+
146
+ if d. low( ) == 0 {
147
+ if d. high( ) == 0 {
148
+ // K X
149
+ // ---
150
+ // 0 0
151
+ // NOTE This should be unreachable in safe Rust because the program will panic before
152
+ // this intrinsic is called
153
+ unsafe {
154
+ intrinsics:: abort( )
155
+ }
129
156
}
130
- return u64:: from ( udiv ! ( n. low( ) , d. low( ) ) ) ;
131
- } else {
132
- // 0 X
133
- // ---
134
- // K X
135
- if let Some ( rem) = rem {
136
- * rem = n;
137
- }
138
- return 0 ;
139
- } ;
140
- }
141
-
142
- let mut sr;
143
- let mut q;
144
- let mut r;
145
157
146
- if d. low ( ) == 0 {
147
- if d. high ( ) == 0 {
148
- // K X
149
- // ---
150
- // 0 0
151
- // NOTE This should be unreachable in safe Rust because the program will panic before
152
- // this intrinsic is called
153
- unsafe {
154
- intrinsics:: abort ( )
158
+ if n. low( ) == 0 {
159
+ // K 0
160
+ // ---
161
+ // K 0
162
+ if let Some ( rem) = rem {
163
+ * rem = <$ty>:: from_parts( 0 , urem!( n. high( ) , d. high( ) ) ) ;
164
+ }
165
+ return <$ty>:: from( udiv!( n. high( ) , d. high( ) ) ) ;
155
166
}
156
- }
157
167
158
- if n. low ( ) == 0 {
159
- // K 0
168
+ // K K
160
169
// ---
161
170
// K 0
162
- if let Some ( rem) = rem {
163
- * rem = u64:: from_parts ( 0 , urem ! ( n. high( ) , d. high( ) ) ) ;
171
+
172
+ if d. high( ) . is_power_of_two( ) {
173
+ if let Some ( rem) = rem {
174
+ * rem = <$ty>:: from_parts( n. low( ) , n. high( ) & ( d. high( ) - 1 ) ) ;
175
+ }
176
+ return <$ty>:: from( n. high( ) >> d. high( ) . trailing_zeros( ) ) ;
164
177
}
165
- return u64:: from ( udiv ! ( n. high( ) , d. high( ) ) ) ;
166
- }
167
178
168
- // K K
169
- // ---
170
- // K 0
179
+ sr = d. high( ) . leading_zeros( ) . wrapping_sub( n. high( ) . leading_zeros( ) ) ;
171
180
172
- if d. high ( ) . is_power_of_two ( ) {
173
- if let Some ( rem) = rem {
174
- * rem = u64:: from_parts ( n. low ( ) , n. high ( ) & ( d. high ( ) - 1 ) ) ;
181
+ // D > N
182
+ if sr > <$tyh>:: bits( ) - 2 {
183
+ if let Some ( rem) = rem {
184
+ * rem = n;
185
+ }
186
+ return 0 ;
175
187
}
176
- return u64:: from ( n. high ( ) >> d. high ( ) . trailing_zeros ( ) ) ;
177
- }
178
188
179
- sr = d . high ( ) . leading_zeros ( ) . wrapping_sub ( n . high ( ) . leading_zeros ( ) ) ;
189
+ sr += 1 ;
180
190
181
- // D > N
182
- if sr > u32:: bits ( ) - 2 {
183
- if let Some ( rem) = rem {
184
- * rem = n;
191
+ // 1 <= sr <= <$tyh>::bits() - 1
192
+ q = n << ( <$ty>:: bits( ) - sr) ;
193
+ r = n >> sr;
194
+ } else if d. high( ) == 0 {
195
+ // K X
196
+ // ---
197
+ // 0 K
198
+ if d. low( ) . is_power_of_two( ) {
199
+ if let Some ( rem) = rem {
200
+ * rem = <$ty>:: from( n. low( ) & ( d. low( ) - 1 ) ) ;
201
+ }
202
+
203
+ if d. low( ) == 1 {
204
+ return n;
205
+ } else {
206
+ let sr = d. low( ) . trailing_zeros( ) ;
207
+ return n >> sr;
208
+ } ;
185
209
}
186
- return 0 ;
187
- }
188
210
189
- sr += 1 ;
190
-
191
- // 1 <= sr <= u32::bits() - 1
192
- q = n << ( u64:: bits ( ) - sr) ;
193
- r = n >> sr;
194
- } else if d. high ( ) == 0 {
195
- // K X
196
- // ---
197
- // 0 K
198
- if d. low ( ) . is_power_of_two ( ) {
199
- if let Some ( rem) = rem {
200
- * rem = u64:: from ( n. low ( ) & ( d. low ( ) - 1 ) ) ;
201
- }
211
+ sr = 1 + <$tyh>:: bits( ) + d. low( ) . leading_zeros( ) - n. high( ) . leading_zeros( ) ;
202
212
203
- if d. low ( ) == 1 {
204
- return n;
205
- } else {
206
- let sr = d. low ( ) . trailing_zeros ( ) ;
207
- return n >> sr;
208
- } ;
209
- }
210
-
211
- sr = 1 + u32:: bits ( ) + d. low ( ) . leading_zeros ( ) - n. high ( ) . leading_zeros ( ) ;
212
-
213
- // 2 <= sr <= u64::bits() - 1
214
- q = n << ( u64:: bits ( ) - sr) ;
215
- r = n >> sr;
216
- } else {
217
- // K X
218
- // ---
219
- // K K
220
- sr = d. high ( ) . leading_zeros ( ) . wrapping_sub ( n. high ( ) . leading_zeros ( ) ) ;
221
-
222
- // D > N
223
- if sr > u32:: bits ( ) - 1 {
224
- if let Some ( rem) = rem {
225
- * rem = n;
213
+ // 2 <= sr <= u64::bits() - 1
214
+ q = n << ( <$ty>:: bits( ) - sr) ;
215
+ r = n >> sr;
216
+ } else {
217
+ // K X
218
+ // ---
219
+ // K K
220
+ sr = d. high( ) . leading_zeros( ) . wrapping_sub( n. high( ) . leading_zeros( ) ) ;
221
+
222
+ // D > N
223
+ if sr > <$tyh>:: bits( ) - 1 {
224
+ if let Some ( rem) = rem {
225
+ * rem = n;
226
+ }
227
+ return 0 ;
226
228
}
227
- return 0 ;
228
- }
229
229
230
- sr += 1 ;
230
+ sr += 1 ;
231
231
232
- // 1 <= sr <= u32::bits()
233
- q = n << ( u64:: bits ( ) - sr) ;
234
- r = n >> sr;
235
- }
236
-
237
- // Not a special case
238
- // q and r are initialized with
239
- // q = n << (u64::bits() - sr)
240
- // r = n >> sr
241
- // 1 <= sr <= u64::bits() - 1
242
- let mut carry = 0 ;
232
+ // 1 <= sr <= <$tyh>::bits()
233
+ q = n << ( <$ty>:: bits( ) - sr) ;
234
+ r = n >> sr;
235
+ }
243
236
244
- for _ in 0 ..sr {
245
- // r:q = ((r:q) << 1) | carry
246
- r = ( r << 1 ) | ( q >> ( u64:: bits ( ) - 1 ) ) ;
247
- q = ( q << 1 ) | carry as u64 ;
237
+ // Not a special case
238
+ // q and r are initialized with
239
+ // q = n << (u64::bits() - sr)
240
+ // r = n >> sr
241
+ // 1 <= sr <= u64::bits() - 1
242
+ let mut carry = 0 ;
243
+
244
+ for _ in 0 ..sr {
245
+ // r:q = ((r:q) << 1) | carry
246
+ r = ( r << 1 ) | ( q >> ( <$ty>:: bits( ) - 1 ) ) ;
247
+ q = ( q << 1 ) | carry as $ty;
248
+
249
+ // carry = 0
250
+ // if r >= d {
251
+ // r -= d;
252
+ // carry = 1;
253
+ // }
254
+ let s = ( d. wrapping_sub( r) . wrapping_sub( 1 ) ) as $tys >> ( <$ty>:: bits( ) - 1 ) ;
255
+ carry = ( s & 1 ) as $tyh;
256
+ r -= d & s as $ty;
257
+ }
248
258
249
- // carry = 0
250
- // if r >= d {
251
- // r -= d;
252
- // carry = 1;
253
- // }
254
- let s = ( d. wrapping_sub ( r) . wrapping_sub ( 1 ) ) as i64 >> ( u64:: bits ( ) - 1 ) ;
255
- carry = ( s & 1 ) as u32 ;
256
- r -= d & s as u64 ;
257
- }
259
+ if let Some ( rem) = rem {
260
+ * rem = r;
261
+ }
262
+ ( q << 1 ) | carry as $ty
263
+ } }
264
+ }
258
265
259
- if let Some ( rem) = rem {
260
- * rem = r ;
261
- }
262
- ( q << 1 ) | carry as u64
266
+ /// Returns `n / d` and sets `* rem = n % d`
267
+ # [ cfg_attr ( not ( test ) , no_mangle ) ]
268
+ pub extern "C" fn __udivmoddi4 ( n : u64 , d : u64 , rem : Option < & mut u64 > ) -> u64 {
269
+ udivmod_inner ! ( n , d , rem , u64 , i64 , u32 )
263
270
}
264
271
265
272
#[ cfg( test) ]
0 commit comments