diff --git a/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile b/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile index 67f5f4cdef..7ea795cac2 100644 --- a/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile +++ b/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile @@ -5,5 +5,5 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gcc-riscv64-linux-gnu libc6-dev-riscv64-cross ENV CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER=riscv64-linux-gnu-gcc \ - CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER="qemu-riscv64 -L /usr/riscv64-linux-gnu -cpu rv64,zk=true" \ + CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER="qemu-riscv64 -L /usr/riscv64-linux-gnu -cpu rv64,zk=true,zbb=true,zbc=true" \ OBJDUMP=riscv64-linux-gnu-objdump diff --git a/ci/run.sh b/ci/run.sh index 9923fa8e36..7b2416fdad 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -47,7 +47,7 @@ case ${TARGET} in # Some of our test dependencies use the deprecated `gcc` crates which # doesn't detect RISC-V compilers automatically, so do it manually here. riscv64*) - export RUSTFLAGS="${RUSTFLAGS} -Ctarget-feature=+zk" + export RUSTFLAGS="${RUSTFLAGS} -Ctarget-feature=+zk,+zbb,+zbc" export TARGET_CC="riscv64-linux-gnu-gcc" ;; esac diff --git a/crates/core_arch/src/riscv_shared/mod.rs b/crates/core_arch/src/riscv_shared/mod.rs index d14431ead4..14f6989d20 100644 --- a/crates/core_arch/src/riscv_shared/mod.rs +++ b/crates/core_arch/src/riscv_shared/mod.rs @@ -1,10 +1,12 @@ //! Shared RISC-V intrinsics mod p; +mod zb; mod zk; #[unstable(feature = "stdsimd", issue = "27731")] pub use p::*; +pub use zb::*; pub use zk::*; use crate::arch::asm; diff --git a/crates/core_arch/src/riscv_shared/zb.rs b/crates/core_arch/src/riscv_shared/zb.rs new file mode 100644 index 0000000000..cfae6caa53 --- /dev/null +++ b/crates/core_arch/src/riscv_shared/zb.rs @@ -0,0 +1,150 @@ +#[cfg(test)] +use stdarch_test::assert_instr; + +#[cfg(target_arch = "riscv32")] +extern "unadjusted" { + #[link_name = "llvm.riscv.orc.b.i32"] + fn _orc_b_32(rs: i32) -> i32; + + #[link_name = "llvm.riscv.clmul.i32"] + fn _clmul_32(rs1: i32, rs2: i32) -> i32; + + #[link_name = "llvm.riscv.clmulh.i32"] + fn _clmulh_32(rs1: i32, rs2: i32) -> i32; + + #[link_name = "llvm.riscv.clmulr.i32"] + fn _clmulr_32(rs1: i32, rs2: i32) -> i32; +} + +#[cfg(target_arch = "riscv64")] +extern "unadjusted" { + #[link_name = "llvm.riscv.orc.b.i64"] + fn _orc_b_64(rs1: i64) -> i64; + + #[link_name = "llvm.riscv.clmul.i64"] + fn _clmul_64(rs1: i64, rs2: i64) -> i64; + + #[link_name = "llvm.riscv.clmulh.i64"] + fn _clmulh_64(rs1: i64, rs2: i64) -> i64; + + #[link_name = "llvm.riscv.clmulr.i64"] + fn _clmulr_64(rs1: i64, rs2: i64) -> i64; +} + +/// Bitwise OR-Combine, byte granule +/// +/// Combines the bits within every byte through a reciprocal bitwise logical OR. This sets the bits of each byte in +/// the result rd to all zeros if no bit within the respective byte of rs is set, or to all ones if any bit within the +/// respective byte of rs is set. +/// +/// Source: RISC-V Bit-Manipulation ISA-extensions +/// +/// Version: v1.0.0 +/// +/// Section: 2.24 +/// +/// # Safety +/// +/// This function is safe to use if the `zbb` target feature is present. +#[target_feature(enable = "zbb")] +// See #1464 +// #[cfg_attr(test, assert_instr(orc.b))] +#[inline] +pub unsafe fn orc_b(rs: usize) -> usize { + #[cfg(target_arch = "riscv32")] + { + _orc_b_32(rs as i32) as usize + } + + #[cfg(target_arch = "riscv64")] + { + _orc_b_64(rs as i64) as usize + } +} + +/// Carry-less multiply (low-part) +/// +/// clmul produces the lower half of the 2·XLEN carry-less product. +/// +/// Source: RISC-V Bit-Manipulation ISA-extensions +/// +/// Version: v1.0.0 +/// +/// Section: 2.11 +/// +/// # Safety +/// +/// This function is safe to use if the `zbc` target feature is present. +#[target_feature(enable = "zbc")] +// See #1464 +// #[cfg_attr(test, assert_instr(clmul))] +#[inline] +pub unsafe fn clmul(rs1: usize, rs2: usize) -> usize { + #[cfg(target_arch = "riscv32")] + { + _clmul_32(rs1 as i32, rs2 as i32) as usize + } + + #[cfg(target_arch = "riscv64")] + { + _clmul_64(rs1 as i64, rs2 as i64) as usize + } +} + +/// Carry-less multiply (high-part) +/// +/// clmulh produces the upper half of the 2·XLEN carry-less product. +/// +/// Source: RISC-V Bit-Manipulation ISA-extensions +/// +/// Version: v1.0.0 +/// +/// Section: 2.12 +/// +/// # Safety +/// +/// This function is safe to use if the `zbc` target feature is present. +#[target_feature(enable = "zbc")] +// See #1464 +// #[cfg_attr(test, assert_instr(clmulh))] +#[inline] +pub unsafe fn clmulh(rs1: usize, rs2: usize) -> usize { + #[cfg(target_arch = "riscv32")] + { + _clmulh_32(rs1 as i32, rs2 as i32) as usize + } + + #[cfg(target_arch = "riscv64")] + { + _clmulh_64(rs1 as i64, rs2 as i64) as usize + } +} + +/// Carry-less multiply (reversed) +/// +/// clmulr produces bits 2·XLEN−2:XLEN-1 of the 2·XLEN carry-less product. +/// +/// Source: RISC-V Bit-Manipulation ISA-extensions +/// +/// Version: v1.0.0 +/// +/// Section: 2.13 +/// +/// # Safety +/// +/// This function is safe to use if the `zbc` target feature is present. +#[target_feature(enable = "zbc")] +// See #1464 +// #[cfg_attr(test, assert_instr(clmulr))] +#[inline] +pub unsafe fn clmulr(rs1: usize, rs2: usize) -> usize { + #[cfg(target_arch = "riscv32")] + { + _clmulr_32(rs1 as i32, rs2 as i32) as usize + } + + #[cfg(target_arch = "riscv64")] + { + _clmulr_64(rs1 as i64, rs2 as i64) as usize + } +}