about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2018-11-17 18:52:47 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2019-06-23 17:32:32 +0200
commitdb5ffdedf7ed64bde30a55e14e67efbb0f6ea538 (patch)
treef296babefb9fe51d098a77ddfa4a4765f33ca800
parentd425116bdc764bdd46bf482c91aeef38fe4480e7 (diff)
downloadrust-db5ffdedf7ed64bde30a55e14e67efbb0f6ea538.tar.gz
rust-db5ffdedf7ed64bde30a55e14e67efbb0f6ea538.zip
Implement bswap intrinsic
-rw-r--r--example/mini_core.rs11
-rw-r--r--example/mini_core_hello_world.rs5
-rw-r--r--patches/0013-Patch-away-bswap-usage.patch25
-rw-r--r--src/intrinsics.rs73
4 files changed, 89 insertions, 25 deletions
diff --git a/example/mini_core.rs b/example/mini_core.rs
index dd42257b194..56ab9578e78 100644
--- a/example/mini_core.rs
+++ b/example/mini_core.rs
@@ -208,6 +208,16 @@ impl PartialEq for u32 {
     }
 }
 
+
+impl PartialEq for u64 {
+    fn eq(&self, other: &u64) -> bool {
+        (*self) == (*other)
+    }
+    fn ne(&self, other: &u64) -> bool {
+        (*self) != (*other)
+    }
+}
+
 impl PartialEq for usize {
     fn eq(&self, other: &usize) -> bool {
         (*self) == (*other)
@@ -375,6 +385,7 @@ pub mod intrinsics {
         pub fn ctlz_nonzero<T>(x: T) -> T;
         pub fn needs_drop<T>() -> bool;
         pub fn bitreverse<T>(x: T) -> T;
+        pub fn bswap<T>(x: T) -> T;
     }
 }
 
diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs
index fdd26f8791d..f9e820da76c 100644
--- a/example/mini_core_hello_world.rs
+++ b/example/mini_core_hello_world.rs
@@ -139,6 +139,11 @@ fn main() {
 
         assert_eq!(intrinsics::bitreverse(0b10101000u8), 0b00010101u8);
 
+        assert_eq!(intrinsics::bswap(0xabu8), 0xabu8);
+        assert_eq!(intrinsics::bswap(0xddccu16), 0xccddu16);
+        assert_eq!(intrinsics::bswap(0xffee_ddccu32), 0xccdd_eeffu32);
+        assert_eq!(intrinsics::bswap(0x1234_5678_ffee_ddccu64), 0xccdd_eeff_7856_3412u64);
+
         assert_eq!(intrinsics::size_of_val(hello) as u8, 6);
 
         let chars = &['C', 'h', 'a', 'r', 's'];
diff --git a/patches/0013-Patch-away-bswap-usage.patch b/patches/0013-Patch-away-bswap-usage.patch
deleted file mode 100644
index e29042c7297..00000000000
--- a/patches/0013-Patch-away-bswap-usage.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From da996dae0b95f986de46a916aca00e03257ba4f9 Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Wed, 30 Jan 2019 14:51:57 +0100
-Subject: [PATCH] Patch away bswap usage
-
----
- src/libcore/num/mod.rs | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
-index f928d40..6a146f5 100644
---- a/src/libcore/num/mod.rs
-+++ b/src/libcore/num/mod.rs
-@@ -2303,7 +2303,7 @@ assert_eq!(m, ", $swapped, ");
-             #[stable(feature = "rust1", since = "1.0.0")]
-             #[inline]
-             pub const fn swap_bytes(self) -> Self {
--                intrinsics::bswap(self as $ActualT) as Self
-+                42 // bswap is unsupported by cg_clif
-             }
-         }
- 
--- 
-2.11.0
-
diff --git a/src/intrinsics.rs b/src/intrinsics.rs
index 18a300ed12e..4f455454a2f 100644
--- a/src/intrinsics.rs
+++ b/src/intrinsics.rs
@@ -415,6 +415,79 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
             let res = CValue::by_val(fx.bcx.ins().bitrev(arg), fx.layout_of(T));
             ret.write_cvalue(fx, res);
         };
+        bswap, <T> (v arg) {
+            // FIXME(CraneStation/cranelift#794) add bswap instruction to cranelift
+            fn swap(bcx: &mut FunctionBuilder, v: Value) -> Value {
+                match bcx.func.dfg.value_type(v) {
+                    types::I8 => v,
+
+                    // https://code.woboq.org/gcc/include/bits/byteswap.h.html
+                    types::I16 => {
+                        let tmp1 = bcx.ins().ishl_imm(v, 8);
+                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00);
+
+                        let tmp2 = bcx.ins().ushr_imm(v, 8);
+                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF);
+
+                        bcx.ins().bor(n1, n2)
+                    }
+                    types::I32 => {
+                        let tmp1 = bcx.ins().ishl_imm(v, 24);
+                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000);
+
+                        let tmp2 = bcx.ins().ishl_imm(v, 8);
+                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000);
+
+                        let tmp3 = bcx.ins().ushr_imm(v, 8);
+                        let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00);
+
+                        let tmp4 = bcx.ins().ushr_imm(v, 24);
+                        let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF);
+
+                        let or_tmp1 = bcx.ins().bor(n1, n2);
+                        let or_tmp2 = bcx.ins().bor(n3, n4);
+                        bcx.ins().bor(or_tmp1, or_tmp2)
+                    }
+                    types::I64 => {
+                        let tmp1 = bcx.ins().ishl_imm(v, 56);
+                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000_0000_0000u64 as i64);
+
+                        let tmp2 = bcx.ins().ishl_imm(v, 40);
+                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000_0000_0000u64 as i64);
+
+                        let tmp3 = bcx.ins().ishl_imm(v, 24);
+                        let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00_0000_0000u64 as i64);
+
+                        let tmp4 = bcx.ins().ishl_imm(v, 8);
+                        let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF_0000_0000u64 as i64);
+
+                        let tmp5 = bcx.ins().ushr_imm(v, 8);
+                        let n5 = bcx.ins().band_imm(tmp5, 0x0000_0000_FF00_0000u64 as i64);
+
+                        let tmp6 = bcx.ins().ushr_imm(v, 24);
+                        let n6 = bcx.ins().band_imm(tmp6, 0x0000_0000_00FF_0000u64 as i64);
+
+                        let tmp7 = bcx.ins().ushr_imm(v, 40);
+                        let n7 = bcx.ins().band_imm(tmp7, 0x0000_0000_0000_FF00u64 as i64);
+
+                        let tmp8 = bcx.ins().ushr_imm(v, 56);
+                        let n8 = bcx.ins().band_imm(tmp8, 0x0000_0000_0000_00FFu64 as i64);
+
+                        let or_tmp1 = bcx.ins().bor(n1, n2);
+                        let or_tmp2 = bcx.ins().bor(n3, n4);
+                        let or_tmp3 = bcx.ins().bor(n5, n6);
+                        let or_tmp4 = bcx.ins().bor(n7, n8);
+
+                        let or_tmp5 = bcx.ins().bor(or_tmp1, or_tmp2);
+                        let or_tmp6 = bcx.ins().bor(or_tmp3, or_tmp4);
+                        bcx.ins().bor(or_tmp5, or_tmp6)
+                    }
+                    ty => unimplemented!("bwap {}", ty),
+                }
+            };
+            let res = CValue::by_val(swap(&mut fx.bcx, arg), fx.layout_of(T));
+            ret.write_cvalue(fx, res);
+        };
         needs_drop, <T> () {
             let needs_drop = if T.needs_drop(fx.tcx, ParamEnv::reveal_all()) {
                 1