@@ -92,4 +92,243 @@ pub fn bitreverse_u128(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
92
92
pub fn math ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
93
93
ldexp ( asm, patcher) ;
94
94
ldexpf ( asm, patcher) ;
95
+ bitreverse_u32 ( asm, patcher) ;
96
+ bitreverse_u64 ( asm, patcher) ;
97
+ bitreverse_u128 ( asm, patcher) ;
95
98
}
99
+
100
+ fn bitreverse_u32 ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
101
+ let name = asm. alloc_string ( "bitreverse_u32" ) ;
102
+ let generator = move |_, asm : & mut Assembly | {
103
+ let curr = asm. alloc_node ( CILNode :: LdLoc ( 0 ) ) ;
104
+ let mut shift = 16 ;
105
+ let arg0 = asm. alloc_node ( CILNode :: LdArg ( 0 ) ) ;
106
+ let mut trees = vec ! [ asm. alloc_root( CILRoot :: StLoc ( 0 , arg0) ) ] ;
107
+ let mut i = 0 ;
108
+ let masks = [
109
+ 0b11111111111111110000000000000000 ,
110
+ 0b11111111000000001111111100000000 ,
111
+ 0b11110000111100001111000011110000 ,
112
+ 0b11001100110011001100110011001100 ,
113
+ 0b10101010101010101010101010101010 ,
114
+ ] ;
115
+ while shift > 0 {
116
+ let mask = asm. alloc_node ( Const :: U32 ( masks[ i] ) ) ;
117
+ let inv_mask = asm. alloc_node ( Const :: U32 ( !masks[ i] ) ) ;
118
+ let masked = asm. alloc_node ( CILNode :: BinOp ( curr, mask, BinOp :: And ) ) ;
119
+ let inv_masked = asm. alloc_node ( CILNode :: BinOp ( curr, inv_mask, BinOp :: And ) ) ;
120
+ let shift_ammount = asm. alloc_node ( Const :: I32 ( shift) ) ;
121
+ let masked_shifted =
122
+ asm. alloc_node ( CILNode :: BinOp ( masked, shift_ammount, BinOp :: ShrUn ) ) ;
123
+ let inv_masked_shifted =
124
+ asm. alloc_node ( CILNode :: BinOp ( inv_masked, shift_ammount, BinOp :: Shl ) ) ;
125
+ let curr_val = asm. alloc_node ( CILNode :: BinOp (
126
+ masked_shifted,
127
+ inv_masked_shifted,
128
+ BinOp :: Or ,
129
+ ) ) ;
130
+ trees. push ( asm. alloc_root ( CILRoot :: StLoc ( 0 , curr_val) ) ) ;
131
+ i += 1 ;
132
+ shift /= 2 ;
133
+ }
134
+ trees. push ( asm. alloc_root ( CILRoot :: Ret ( curr) ) ) ;
135
+ MethodImpl :: MethodBody {
136
+ blocks : vec ! [ BasicBlock :: new( trees, 0 , None ) ] ,
137
+ locals : vec ! [ ( None , asm. alloc_type( Type :: Int ( Int :: U32 ) ) ) ] ,
138
+ }
139
+ } ;
140
+ patcher. insert ( name, Box :: new ( generator) ) ;
141
+ }
142
+ fn bitreverse_u64 ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
143
+ let name = asm. alloc_string ( "bitreverse_u64" ) ;
144
+ let generator = move |_, asm : & mut Assembly | {
145
+ let curr = asm. alloc_node ( CILNode :: LdLoc ( 0 ) ) ;
146
+ let mut shift = 32 ;
147
+ let arg0 = asm. alloc_node ( CILNode :: LdArg ( 0 ) ) ;
148
+ let mut trees = vec ! [ asm. alloc_root( CILRoot :: StLoc ( 0 , arg0) ) ] ;
149
+ let mut i = 0 ;
150
+ let masks = [
151
+ 0b1111111111111111111111111111111100000000000000000000000000000000 ,
152
+ 0b1111111111111111000000000000000011111111111111110000000000000000 ,
153
+ 0b1111111100000000111111110000000011111111000000001111111100000000 ,
154
+ 0b1111000011110000111100001111000011110000111100001111000011110000 ,
155
+ 0b1100110011001100110011001100110011001100110011001100110011001100 ,
156
+ 0b1010101010101010101010101010101010101010101010101010101010101010 ,
157
+ ] ;
158
+ while shift > 0 {
159
+ let mask = asm. alloc_node ( Const :: U64 ( masks[ i] ) ) ;
160
+ let inv_mask = asm. alloc_node ( Const :: U64 ( !masks[ i] ) ) ;
161
+ let masked = asm. alloc_node ( CILNode :: BinOp ( curr, mask, BinOp :: And ) ) ;
162
+ let inv_masked = asm. alloc_node ( CILNode :: BinOp ( curr, inv_mask, BinOp :: And ) ) ;
163
+ let shift_ammount = asm. alloc_node ( Const :: I64 ( shift) ) ;
164
+ let masked_shifted =
165
+ asm. alloc_node ( CILNode :: BinOp ( masked, shift_ammount, BinOp :: ShrUn ) ) ;
166
+ let inv_masked_shifted =
167
+ asm. alloc_node ( CILNode :: BinOp ( inv_masked, shift_ammount, BinOp :: Shl ) ) ;
168
+ let curr_val = asm. alloc_node ( CILNode :: BinOp (
169
+ masked_shifted,
170
+ inv_masked_shifted,
171
+ BinOp :: Or ,
172
+ ) ) ;
173
+ trees. push ( asm. alloc_root ( CILRoot :: StLoc ( 0 , curr_val) ) ) ;
174
+ i += 1 ;
175
+ shift /= 2 ;
176
+ }
177
+ trees. push ( asm. alloc_root ( CILRoot :: Ret ( curr) ) ) ;
178
+ MethodImpl :: MethodBody {
179
+ blocks : vec ! [ BasicBlock :: new( trees, 0 , None ) ] ,
180
+ locals : vec ! [ ( None , asm. alloc_type( Type :: Int ( Int :: U64 ) ) ) ] ,
181
+ }
182
+ } ;
183
+ patcher. insert ( name, Box :: new ( generator) ) ;
184
+ }
185
+ fn bitreverse_u128 ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
186
+ let name = asm. alloc_string ( "bitreverse_u128" ) ;
187
+ let generator = move |_, asm : & mut Assembly | {
188
+ let u64_max = asm. alloc_node ( Const :: U64 ( u64:: MAX ) ) ;
189
+ let u64_zero = asm. alloc_node ( Const :: U64 ( 0 ) ) ;
190
+ let u128_class = ClassRef :: uint_128 ( asm) ;
191
+ let u128_class = asm[ u128_class] . clone ( ) ;
192
+ let u128_ctor = u128_class. ctor ( & [ Type :: Int ( Int :: U64 ) , Type :: Int ( Int :: U64 ) ] , asm) ;
193
+
194
+ let mut shift = 64 ;
195
+ //let op_add = asm.alloc_string("op_Addition");
196
+ let op_and = asm. alloc_string ( "op_BitwiseAnd" ) ;
197
+ let and = u128_class. static_mref (
198
+ & [ Type :: Int ( Int :: U128 ) , Type :: Int ( Int :: U128 ) ] ,
199
+ Type :: Int ( Int :: U128 ) ,
200
+ op_and,
201
+ asm,
202
+ ) ;
203
+ let op_or = asm. alloc_string ( "op_BitwiseOr" ) ;
204
+ let or = u128_class. static_mref (
205
+ & [ Type :: Int ( Int :: U128 ) , Type :: Int ( Int :: U128 ) ] ,
206
+ Type :: Int ( Int :: U128 ) ,
207
+ op_or,
208
+ asm,
209
+ ) ;
210
+ let op_lshift = asm. alloc_string ( "op_LeftShift" ) ;
211
+ let lshift = u128_class. static_mref (
212
+ & [ Type :: Int ( Int :: U128 ) , Type :: Int ( Int :: I32 ) ] ,
213
+ Type :: Int ( Int :: U128 ) ,
214
+ op_lshift,
215
+ asm,
216
+ ) ;
217
+ let op_rshift = asm. alloc_string ( "op_RightShift" ) ;
218
+ let rshift = u128_class. static_mref (
219
+ & [ Type :: Int ( Int :: U128 ) , Type :: Int ( Int :: I32 ) ] ,
220
+ Type :: Int ( Int :: U128 ) ,
221
+ op_rshift,
222
+ asm,
223
+ ) ;
224
+ let curr = asm. alloc_node ( CILNode :: LdLoc ( 0 ) ) ;
225
+ let arg0 = asm. alloc_node ( CILNode :: LdArg ( 0 ) ) ;
226
+ let mut trees = vec ! [ asm. alloc_root( CILRoot :: StLoc ( 0 , arg0) ) ] ;
227
+ let mut i = 0 ;
228
+ let masks = [
229
+ 0b11111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000 ,
230
+ 0b11111111111111111111111111111111000000000000000000000000000000001111111111111111111111111111111100000000000000000000000000000000 ,
231
+ 0b11111111111111110000000000000000111111111111111100000000000000001111111111111111000000000000000011111111111111110000000000000000 ,
232
+ 0b11111111000000001111111100000000111111110000000011111111000000001111111100000000111111110000000011111111000000001111111100000000 ,
233
+ 0b11110000111100001111000011110000111100001111000011110000111100001111000011110000111100001111000011110000111100001111000011110000 ,
234
+ 0b11001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100 ,
235
+ 0b10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010_u128 ,
236
+ ] ;
237
+ while shift > 0 {
238
+ let curr_mask = masks[ i] ;
239
+ let mask = CILNode :: Call ( Box :: new ( (
240
+ u128_ctor,
241
+ ( [
242
+ asm. alloc_node ( Const :: U64 ( ( curr_mask >> 64 ) as u64 ) ) ,
243
+ asm. alloc_node ( Const :: U64 ( curr_mask as u64 ) ) ,
244
+ ] )
245
+ . into ( ) ,
246
+ ) ) ) ;
247
+ let mask = asm. alloc_node ( mask) ;
248
+ let curr_mask = !masks[ i] ;
249
+ let inv_mask = CILNode :: Call ( Box :: new ( (
250
+ u128_ctor,
251
+ ( [
252
+ asm. alloc_node ( Const :: U64 ( ( curr_mask >> 64 ) as u64 ) ) ,
253
+ asm. alloc_node ( Const :: U64 ( curr_mask as u64 ) ) ,
254
+ ] )
255
+ . into ( ) ,
256
+ ) ) ) ;
257
+ let inv_mask = asm. alloc_node ( inv_mask) ;
258
+ let masked = asm. alloc_node ( CILNode :: Call ( Box :: new ( ( and, [ curr, mask] . into ( ) ) ) ) ) ;
259
+ let inv_masked =
260
+ asm. alloc_node ( CILNode :: Call ( Box :: new ( ( and, [ curr, inv_mask] . into ( ) ) ) ) ) ;
261
+ let shift_ammount = asm. alloc_node ( Const :: I64 ( shift) ) ;
262
+ let masked_shifted = asm. alloc_node ( CILNode :: Call ( Box :: new ( (
263
+ rshift,
264
+ [ masked, shift_ammount] . into ( ) ,
265
+ ) ) ) ) ;
266
+ let inv_masked_shifted = asm. alloc_node ( CILNode :: Call ( Box :: new ( (
267
+ lshift,
268
+ [ inv_masked, shift_ammount] . into ( ) ,
269
+ ) ) ) ) ;
270
+
271
+ let curr_val = asm. alloc_node ( CILNode :: Call ( Box :: new ( (
272
+ or,
273
+ [ masked_shifted, inv_masked_shifted] . into ( ) ,
274
+ ) ) ) ) ;
275
+ trees. push ( asm. alloc_root ( CILRoot :: StLoc ( 0 , curr_val) ) ) ;
276
+ i += 1 ;
277
+ shift /= 2 ;
278
+ }
279
+ trees. push ( asm. alloc_root ( CILRoot :: Ret ( curr) ) ) ;
280
+ MethodImpl :: MethodBody {
281
+ blocks : vec ! [ BasicBlock :: new( trees, 0 , None ) ] ,
282
+ locals : vec ! [ ( None , asm. alloc_type( Type :: Int ( Int :: U128 ) ) ) ] ,
283
+ }
284
+ } ;
285
+ patcher. insert ( name, Box :: new ( generator) ) ;
286
+ }
287
+ /*
288
+ fn bitreverse_u128(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
289
+ let name = asm.alloc_string("bitreverse_u64");
290
+ let generator = move |_, asm: &mut Assembly| {
291
+ let u64_max = asm.alloc_node(Const::U64(u64::MAX));
292
+ let u64_zero = asm.alloc_node(Const::U64(0));
293
+ let u128_class = ClassRef::uint_128(asm);
294
+ let u128_class = asm[u128_class].clone();
295
+ let u128_ctor = u128_class.ctor(&[Type::Int(Int::U64), Type::Int(Int::U64)], asm);
296
+ let mask = asm.alloc_node(CILNode::Call(Box::new((
297
+ u128_ctor,
298
+ ([u64_max, u64_zero]).into(),
299
+ ))));
300
+ let inv_mask = asm.alloc_node(CILNode::Call(Box::new((
301
+ u128_ctor,
302
+ ([u64_zero, u64_max]).into(),
303
+ ))));
304
+ let mut curr = asm.alloc_node(CILNode::LdArg(0));
305
+ let mut shift = 32;
306
+ let op_add = asm.alloc_string("op_Addition");
307
+ let op_and = asm.alloc_string("op_BitwiseAnd");
308
+ let op_or = asm.alloc_string("op_BitwiseOr");
309
+ let op_lshift = asm.alloc_string("op_LeftShift");
310
+ let op_rshift = asm.alloc_string("op_RightShift");
311
+ while shift > 0 {
312
+ let masked = asm.alloc_node(CILNode::BinOp(curr, mask, BinOp::And));
313
+ let inv_masked = asm.alloc_node(CILNode::BinOp(curr, inv_mask, BinOp::And));
314
+ let shift_ammount = asm.alloc_node(Const::I64(shift));
315
+ let masked_shifted =
316
+ asm.alloc_node(CILNode::BinOp(masked, shift_ammount, BinOp::ShrUn));
317
+ let inv_masked_shifted =
318
+ asm.alloc_node(CILNode::BinOp(inv_masked, shift_ammount, BinOp::Shl));
319
+ curr = asm.alloc_node(CILNode::BinOp(
320
+ masked_shifted,
321
+ inv_masked_shifted,
322
+ BinOp::Or,
323
+ ));
324
+ shift /= 2;
325
+ }
326
+ let ret = asm.alloc_root(CILRoot::Ret(curr));
327
+ MethodImpl::MethodBody {
328
+ blocks: vec![BasicBlock::new(vec![ret], 0, None)],
329
+ locals: vec![],
330
+ }
331
+ };
332
+ patcher.insert(name, Box::new(generator));
333
+ }
334
+ */
0 commit comments