@@ -92,4 +92,243 @@ pub fn bitreverse_u128(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
9292pub fn math ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
9393 ldexp ( asm, patcher) ;
9494 ldexpf ( asm, patcher) ;
95+ bitreverse_u32 ( asm, patcher) ;
96+ bitreverse_u64 ( asm, patcher) ;
97+ bitreverse_u128 ( asm, patcher) ;
9598}
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