@@ -205,6 +205,7 @@ pub fn insert_ffi_functions(asm: &mut Assembly, tcx: TyCtxt) {
205205 swap_at_generic ( asm) ;
206206 bounds_check ( asm) ;
207207 atomic:: atomics ( asm) ;
208+ bitreverse_u128 ( asm) ;
208209 let c_void = crate :: r#type:: c_void ( tcx) ;
209210
210211 asm. add_typedef ( TypeDef :: new (
@@ -1328,3 +1329,198 @@ add_method_from_trees!(
13281329 ) ] ,
13291330 vec![ Some ( "thread_handle" . into( ) ) , Some ( "result_ptr" . into( ) ) ]
13301331) ;
1332+
1333+ fn shr_u128 ( value : CILNode , shift : CILNode ) -> CILNode {
1334+ call ! (
1335+ CallSite :: boxed(
1336+ DotnetTypeRef :: uint_128( ) . into( ) ,
1337+ "op_RightShift" . into( ) ,
1338+ FnSig :: new( & [ Type :: U128 , Type :: I32 ] , Type :: U128 ) ,
1339+ true ,
1340+ ) ,
1341+ [ value, shift]
1342+ )
1343+ }
1344+ fn or_u128 ( lhs : CILNode , rhs : CILNode ) -> CILNode {
1345+ call ! (
1346+ CallSite :: boxed(
1347+ DotnetTypeRef :: uint_128( ) . into( ) ,
1348+ "op_BitwiseOr" . into( ) ,
1349+ FnSig :: new( & [ Type :: U128 , Type :: U128 ] , Type :: U128 ) ,
1350+ true ,
1351+ ) ,
1352+ [ lhs, rhs]
1353+ )
1354+ }
1355+ fn and_u128 ( lhs : CILNode , rhs : CILNode ) -> CILNode {
1356+ call ! (
1357+ CallSite :: boxed(
1358+ DotnetTypeRef :: uint_128( ) . into( ) ,
1359+ "op_BitwiseAnd" . into( ) ,
1360+ FnSig :: new( & [ Type :: U128 , Type :: U128 ] , Type :: U128 ) ,
1361+ true ,
1362+ ) ,
1363+ [ lhs, rhs]
1364+ )
1365+ }
1366+ fn shl_u128 ( value : CILNode , shift : CILNode ) -> CILNode {
1367+ call ! (
1368+ CallSite :: boxed(
1369+ DotnetTypeRef :: uint_128( ) . into( ) ,
1370+ "op_LeftShift" . into( ) ,
1371+ FnSig :: new( & [ Type :: U128 , Type :: I32 ] , Type :: U128 ) ,
1372+ true ,
1373+ ) ,
1374+ [ value, shift]
1375+ )
1376+ }
1377+ fn const_u128 ( value : u128 ) -> CILNode {
1378+ let low = u128_low_u64 ( value) ;
1379+ let high = ( value >> 64 ) as u64 ;
1380+ let ctor_sig = FnSig :: new (
1381+ & [
1382+ Type :: ManagedReference ( Type :: U128 . into ( ) ) ,
1383+ Type :: U64 ,
1384+ Type :: U64 ,
1385+ ] ,
1386+ Type :: Void ,
1387+ ) ;
1388+ CILNode :: NewObj ( Box :: new ( CallOpArgs {
1389+ site : CallSite :: boxed (
1390+ Some ( DotnetTypeRef :: uint_128 ( ) ) ,
1391+ ".ctor" . into ( ) ,
1392+ ctor_sig,
1393+ false ,
1394+ ) ,
1395+ args : [ conv_u64 ! ( ldc_u64!( high) ) , conv_u64 ! ( ldc_u64!( low) ) ] . into ( ) ,
1396+ } ) )
1397+ }
1398+ add_method_from_trees ! (
1399+ bitreverse_u128,
1400+ & [ Type :: U128 ] ,
1401+ Type :: U128 ,
1402+ vec![ BasicBlock :: new(
1403+ vec![
1404+ CILRoot :: STLoc {
1405+ local: 0 ,
1406+ tree: or_u128(
1407+ and_u128(
1408+ shr_u128( CILNode :: LDArg ( 0 ) , ldc_i32!( 1 ) ) ,
1409+ const_u128( 0x5555_5555_5555_5555_5555_5555_5555_5555_u128 ) ,
1410+ ) ,
1411+ shl_u128(
1412+ and_u128(
1413+ CILNode :: LDArg ( 0 ) ,
1414+ const_u128( 0x5555_5555_5555_5555_5555_5555_5555_5555_u128 ) ,
1415+ ) ,
1416+ ldc_i32!( 1 ) ,
1417+ ) ,
1418+ ) ,
1419+ }
1420+ . into( ) ,
1421+ CILRoot :: STLoc {
1422+ local: 0 ,
1423+ tree: or_u128(
1424+ and_u128(
1425+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 2 ) ) ,
1426+ const_u128( 0x3333_3333_3333_3333_3333_3333_3333_3333_u128 ) ,
1427+ ) ,
1428+ shl_u128(
1429+ and_u128(
1430+ CILNode :: LDLoc ( 0 ) ,
1431+ const_u128( 0x3333_3333_3333_3333_3333_3333_3333_3333_u128 ) ,
1432+ ) ,
1433+ ldc_i32!( 2 ) ,
1434+ ) ,
1435+ ) ,
1436+ }
1437+ . into( ) ,
1438+ CILRoot :: STLoc {
1439+ local: 0 ,
1440+ tree: or_u128(
1441+ and_u128(
1442+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 4 ) ) ,
1443+ const_u128( 0x0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_u128 ) ,
1444+ ) ,
1445+ shl_u128(
1446+ and_u128(
1447+ CILNode :: LDLoc ( 0 ) ,
1448+ const_u128( 0x0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_u128 ) ,
1449+ ) ,
1450+ ldc_i32!( 4 ) ,
1451+ ) ,
1452+ ) ,
1453+ }
1454+ . into( ) ,
1455+ CILRoot :: STLoc {
1456+ local: 0 ,
1457+ tree: or_u128(
1458+ and_u128(
1459+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 8 ) ) ,
1460+ const_u128( 0x00FF_00FF_00FF_00FF_00FF_00FF_00FF_00FF_u128 ) ,
1461+ ) ,
1462+ shl_u128(
1463+ and_u128(
1464+ CILNode :: LDLoc ( 0 ) ,
1465+ const_u128( 0x00FF_00FF_00FF_00FF_00FF_00FF_00FF_00FF_u128 ) ,
1466+ ) ,
1467+ ldc_i32!( 8 ) ,
1468+ ) ,
1469+ ) ,
1470+ }
1471+ . into( ) ,
1472+ CILRoot :: STLoc {
1473+ local: 0 ,
1474+ tree: or_u128(
1475+ and_u128(
1476+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 16 ) ) ,
1477+ const_u128( 0x0000_FFFF_0000_FFFF_0000_FFFF_0000_FFFF_u128 ) ,
1478+ ) ,
1479+ shl_u128(
1480+ and_u128(
1481+ CILNode :: LDLoc ( 0 ) ,
1482+ const_u128( 0x0000_FFFF_0000_FFFF_0000_FFFF_0000_FFFF_u128 ) ,
1483+ ) ,
1484+ ldc_i32!( 16 ) ,
1485+ ) ,
1486+ ) ,
1487+ }
1488+ . into( ) ,
1489+ CILRoot :: STLoc {
1490+ local: 0 ,
1491+ tree: or_u128(
1492+ and_u128(
1493+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 32 ) ) ,
1494+ const_u128( 0x0000_0000_FFFF_FFFF_0000_0000_FFFF_FFFF_u128 ) ,
1495+ ) ,
1496+ shl_u128(
1497+ and_u128(
1498+ CILNode :: LDLoc ( 0 ) ,
1499+ const_u128( 0x0000_0000_FFFF_FFFF_0000_0000_FFFF_FFFF_u128 ) ,
1500+ ) ,
1501+ ldc_i32!( 32 ) ,
1502+ ) ,
1503+ ) ,
1504+ }
1505+ . into( ) ,
1506+ CILRoot :: Ret {
1507+ tree: or_u128(
1508+ shr_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 64 ) ) ,
1509+ shl_u128( CILNode :: LDLoc ( 0 ) , ldc_i32!( 64 ) ) ,
1510+ ) ,
1511+ }
1512+ . into( ) ,
1513+ ] ,
1514+ 0 ,
1515+ None
1516+ ) ] ,
1517+ vec![ ( Some ( "n" . into( ) ) , Type :: U128 ) ] ,
1518+ vec![
1519+ Some ( "buf1" . into( ) ) ,
1520+ Some ( "buf2" . into( ) ) ,
1521+ Some ( "size" . into( ) )
1522+ ]
1523+ ) ;
1524+ fn u128_low_u64 ( value : u128 ) -> u64 {
1525+ u64:: try_from ( value & u128:: from ( u64:: MAX ) ) . expect ( "trucating cast error" )
1526+ }
0 commit comments