8
8
9
9
#[ cfg( test) ]
10
10
extern crate core;
11
+ #[ cfg( test) ]
12
+ #[ macro_use]
13
+ extern crate quickcheck;
11
14
12
15
use core:: mem;
13
16
@@ -17,13 +20,13 @@ pub mod arm;
17
20
#[ cfg( test) ]
18
21
mod test;
19
22
20
- const CHAR_BITS : usize = 8 ;
23
+ const U8_BITS : usize = 8 ;
21
24
22
25
macro_rules! absv_i2 {
23
26
( $intrinsic: ident : $ty: ty) => {
24
27
#[ no_mangle]
25
28
pub extern "C" fn $intrinsic( x: $ty) -> $ty {
26
- let n = mem:: size_of:: <$ty>( ) * CHAR_BITS ;
29
+ let n = mem:: size_of:: <$ty>( ) * U8_BITS ;
27
30
if x == 1 << ( n - 1 ) {
28
31
panic!( ) ;
29
32
}
@@ -38,3 +41,257 @@ absv_i2!(__absvsi2: i32);
38
41
absv_i2 ! ( __absvdi2: i64 ) ;
39
42
// TODO(rust-lang/35118)?
40
43
// absv_i2!(__absvti2, i128);
44
+
45
+ #[ no_mangle]
46
+ pub extern "C" fn __udivmoddi4 ( a : u64 , b : u64 , rem : * mut u64 ) -> u64 {
47
+ #[ cfg( target_endian = "little" ) ]
48
+ #[ repr( C ) ]
49
+ #[ derive( Debug ) ]
50
+ struct words {
51
+ low : u32 ,
52
+ high : u32 ,
53
+ }
54
+
55
+ #[ cfg( target_endian = "big" ) ]
56
+ #[ repr( C ) ]
57
+ #[ derive( Debug ) ]
58
+ struct words {
59
+ high : u32 ,
60
+ low : u32 ,
61
+ }
62
+
63
+ impl words {
64
+ fn all ( & mut self ) -> & mut u64 {
65
+ unsafe { mem:: transmute ( self ) }
66
+ }
67
+
68
+ fn u64 ( & self ) -> u64 {
69
+ unsafe { * ( self as * const _ as * const u64 ) }
70
+ }
71
+ }
72
+
73
+ impl From < u64 > for words {
74
+ fn from ( x : u64 ) -> words {
75
+ unsafe { mem:: transmute ( x) }
76
+ }
77
+ }
78
+
79
+ let u32_bits = ( mem:: size_of :: < u32 > ( ) * U8_BITS ) as u32 ;
80
+ let u64_bits = ( mem:: size_of :: < u64 > ( ) * U8_BITS ) as u32 ;
81
+
82
+ let n = words:: from ( a) ;
83
+ let d = words:: from ( b) ;
84
+
85
+ // NOTE X is unknown, K != 0
86
+ if n. high == 0 {
87
+ return if d. high == 0 {
88
+ // 0 X
89
+ // ---
90
+ // 0 X
91
+
92
+ if let Some ( rem) = unsafe { rem. as_mut ( ) } {
93
+ * rem = u64:: from ( n. low % d. low ) ;
94
+ }
95
+ u64:: from ( n. low / d. low )
96
+ } else
97
+ // d.high != 0
98
+ {
99
+ // 0 X
100
+ // ---
101
+ // K X
102
+
103
+ if let Some ( rem) = unsafe { rem. as_mut ( ) } {
104
+ * rem = u64:: from ( n. low ) ;
105
+ }
106
+ 0
107
+ } ;
108
+ }
109
+
110
+ let mut sr;
111
+ // NOTE IMO it should be possible to leave these "uninitialized" (just declare them here)
112
+ // because these variables get initialized below, but if I do that the compiler complains about
113
+ // them being used before being initialized.
114
+ let mut q = words { low : 0 , high : 0 } ;
115
+ let mut r = words { low : 0 , high : 0 } ;
116
+
117
+ // n.high != 0
118
+ if d. low == 0 {
119
+ if d. high == 0 {
120
+ // K X
121
+ // ---
122
+ // 0 0
123
+
124
+ // NOTE copied verbatim from compiler-rt, but does division by zero even make sense?
125
+ if let Some ( rem) = unsafe { rem. as_mut ( ) } {
126
+ * rem = u64:: from ( n. high % d. low ) ;
127
+ }
128
+ return u64:: from ( n. high / d. low ) ;
129
+ }
130
+
131
+ // d.high != 0
132
+ if n. low == 0 {
133
+ // K 0
134
+ // ---
135
+ // K 0
136
+
137
+ if let Some ( rem) = unsafe { rem. as_mut ( ) } {
138
+ * rem = words {
139
+ low : 0 ,
140
+ high : n. high % d. high ,
141
+ }
142
+ . u64 ( ) ;
143
+ }
144
+ return u64:: from ( n. high / d. high ) ;
145
+ }
146
+
147
+ // n.low != 0
148
+ // K K
149
+ // ---
150
+ // K 0
151
+
152
+ if d. high . is_power_of_two ( ) {
153
+ if let Some ( rem) = unsafe { rem. as_mut ( ) } {
154
+ * rem = words {
155
+ low : n. low ,
156
+ high : n. high & ( d. high - 1 ) ,
157
+ }
158
+ . u64 ( )
159
+ }
160
+
161
+ return u64:: from ( n. high >> d. high . trailing_zeros ( ) ) ;
162
+ }
163
+
164
+ sr = d. high . leading_zeros ( ) . wrapping_sub ( n. high . leading_zeros ( ) ) ;
165
+
166
+ // D > N
167
+ if sr > u32_bits - 2 {
168
+ if let Some ( rem) = unsafe { rem. as_mut ( ) } {
169
+ * rem = n. u64 ( ) ;
170
+ }
171
+ return 0 ;
172
+ }
173
+
174
+ sr = sr + 1 ;
175
+
176
+ // 1 <= sr <= u32_bits - 1
177
+ // *q.all() = n.u64() << (u64_bits - sr);
178
+ q. low = 0 ;
179
+ q. high = n. low << ( u32_bits - sr) ;
180
+ // *r.all() = n.u64() >> sr
181
+ r. high = n. high >> sr;
182
+ r. low = ( n. high << ( u32_bits - sr) ) | ( n. low >> sr) ;
183
+ } else
184
+ // d.low != 0
185
+ {
186
+ if d. high == 0 {
187
+ // K X
188
+ // ---
189
+ // 0 K
190
+ if d. low . is_power_of_two ( ) {
191
+ if let Some ( rem) = unsafe { rem. as_mut ( ) } {
192
+ * rem = u64:: from ( n. low & ( d. low - 1 ) ) ;
193
+ }
194
+
195
+ return if d. low == 1 {
196
+ n. u64 ( )
197
+ } else {
198
+ let sr = d. low . trailing_zeros ( ) ;
199
+ words {
200
+ low : ( n. high << ( u32_bits - sr) ) | ( n. low >> sr) ,
201
+ high : n. high >> sr,
202
+ }
203
+ . u64 ( )
204
+ } ;
205
+ }
206
+
207
+ sr = 1 + u32_bits + d. low . leading_zeros ( ) - n. high . leading_zeros ( ) ;
208
+
209
+ // 2 <= sr <= u64_bits - 1
210
+ // *q.all() = n.u64() << (u64_bits - sr)
211
+ // *r.all() = n.u64() >> sr;
212
+ if sr == u32_bits {
213
+ q. low = 0 ;
214
+ q. high = n. low ;
215
+ r. high = 0 ;
216
+ r. low = n. high ;
217
+ } else if sr < u32_bits
218
+ // 2 <= sr <= u32_bits - 1
219
+ {
220
+ q. low = 0 ;
221
+ q. high = n. low << ( u32_bits - sr) ;
222
+ r. high = n. high >> sr;
223
+ r. low = ( n. high << ( u32_bits - sr) ) | ( n. low >> sr) ;
224
+ } else
225
+ // u32_bits + 1 <= sr <= u64_bits - 1
226
+ {
227
+ q. low = n. low << ( u64_bits - sr) ;
228
+ q. high = ( n. high << ( u64_bits - sr) ) | ( n. low >> ( sr - u32_bits) ) ;
229
+ r. high = 0 ;
230
+ r. low = n. high >> ( sr - u32_bits) ;
231
+ }
232
+
233
+ } else
234
+ // d.high != 0
235
+ {
236
+ // K X
237
+ // ---
238
+ // K K
239
+
240
+ sr = d. high . leading_zeros ( ) . wrapping_sub ( n. high . leading_zeros ( ) ) ;
241
+
242
+ // D > N
243
+ if sr > u32_bits - 1 {
244
+ if let Some ( rem) = unsafe { rem. as_mut ( ) } {
245
+ * rem = a;
246
+ return 0 ;
247
+ }
248
+ }
249
+
250
+ sr += 1 ;
251
+
252
+ // 1 <= sr <= u32_bits
253
+ // *q.all() = n.u64() << (u64_bits - sr)
254
+ q. low = 0 ;
255
+ if sr == u32_bits {
256
+ q. high = n. low ;
257
+ r. high = 0 ;
258
+ r. low = n. high ;
259
+ } else {
260
+ q. high = n. low << ( u32_bits - sr) ;
261
+ r. high = n. high >> sr;
262
+ r. low = ( n. high << ( u32_bits - sr) ) | ( n. low >> sr) ;
263
+ }
264
+ }
265
+ }
266
+
267
+ // Not a special case
268
+ // q and r are initialized with
269
+ // *q.all() = n.u64() << (u64_bits - sr)
270
+ // *.r.all() = n.u64() >> sr
271
+ // 1 <= sr <= u64_bits - 1
272
+ let mut carry = 0 ;
273
+
274
+ for _ in 0 ..sr {
275
+ // r:q = ((r:q) << 1) | carry
276
+ r. high = ( r. high << 1 ) | ( r. low >> ( u32_bits - 1 ) ) ;
277
+ r. low = ( r. low << 1 ) | ( q. high >> ( u32_bits - 1 ) ) ;
278
+ q. high = ( q. high << 1 ) | ( q. low >> ( u32_bits - 1 ) ) ;
279
+ q. low = ( q. low << 1 ) | carry;
280
+
281
+ // carry = 0
282
+ // if r.u64() >= d.u64() {
283
+ // *r.all() -= d.u64();
284
+ // carry = 1;
285
+ // }
286
+
287
+ let s = ( d. u64 ( ) . wrapping_sub ( r. u64 ( ) ) . wrapping_sub ( 1 ) ) as i64 >> ( u64_bits - 1 ) ;
288
+ carry = ( s & 1 ) as u32 ;
289
+ * r. all ( ) -= d. u64 ( ) & s as u64 ;
290
+ }
291
+
292
+ * q. all ( ) = ( q. u64 ( ) << 1 ) | carry as u64 ;
293
+ if let Some ( rem) = unsafe { rem. as_mut ( ) } {
294
+ * rem = r. u64 ( ) ;
295
+ }
296
+ q. u64 ( )
297
+ }
0 commit comments