From 5d530aa1809f41564e0779df6b1b207797deaa60 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 27 Jun 2024 11:18:20 -0700 Subject: [PATCH] Fixes for target x32 --- .github/workflows/ci.yaml | 18 +++++++++++++++++- src/biguint/addition.rs | 36 +++++++++++++++++++++++------------- src/biguint/division.rs | 15 ++++++++++++++- src/biguint/subtraction.rs | 36 +++++++++++++++++++++++------------- 4 files changed, 77 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ede5aaed..6ed00986 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -42,6 +42,22 @@ jobs: - run: cargo build - run: ./ci/test_full.sh + # try building the x32 target -- x86_64 with target_pointer_width="32" + # (we can't execute without kernel CONFIG_X86_X32_ABI though) + x32: + name: Test (x32) + runs-on: ubuntu-latest + steps: + - run: | + sudo apt-get update + sudo apt-get install gcc-multilib + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + target: x86_64-unknown-linux-gnux32 + - run: cargo build --target x86_64-unknown-linux-gnux32 --all-features + - run: cargo test --no-run --target x86_64-unknown-linux-gnux32 --all-features + # try a target that doesn't have std at all, but does have alloc no_std: name: No Std @@ -78,7 +94,7 @@ jobs: success: name: Success runs-on: ubuntu-latest - needs: [test, i686, no_std, fmt, doc] + needs: [test, i686, x32, no_std, fmt, doc] # Github branch protection is exceedingly silly and treats "jobs skipped because a dependency # failed" as success. So we have to do some contortions to ensure the job fails if any of its # dependencies fails. diff --git a/src/biguint/addition.rs b/src/biguint/addition.rs index 98b588b6..b6711314 100644 --- a/src/biguint/addition.rs +++ b/src/biguint/addition.rs @@ -7,22 +7,32 @@ use core::iter::Sum; use core::ops::{Add, AddAssign}; use num_traits::CheckedAdd; -// Add with carry: #[cfg(target_arch = "x86_64")] -#[inline] -fn adc(carry: u8, a: u64, b: u64, out: &mut u64) -> u8 { - // Safety: There are absolutely no safety concerns with calling `_addcarry_u64`. - // It's just unsafe for API consistency with other intrinsics. - unsafe { core::arch::x86_64::_addcarry_u64(carry, a, b, out) } -} +use core::arch::x86_64 as arch; #[cfg(target_arch = "x86")] -#[inline] -fn adc(carry: u8, a: u32, b: u32, out: &mut u32) -> u8 { - // Safety: There are absolutely no safety concerns with calling `_addcarry_u32`. - // It's just unsafe for API consistency with other intrinsics. - unsafe { core::arch::x86::_addcarry_u32(carry, a, b, out) } -} +use core::arch::x86 as arch; + +// Add with carry: +#[cfg(target_arch = "x86_64")] +cfg_64!( + #[inline] + fn adc(carry: u8, a: u64, b: u64, out: &mut u64) -> u8 { + // Safety: There are absolutely no safety concerns with calling `_addcarry_u64`. + // It's just unsafe for API consistency with other intrinsics. + unsafe { arch::_addcarry_u64(carry, a, b, out) } + } +); + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +cfg_32!( + #[inline] + fn adc(carry: u8, a: u32, b: u32, out: &mut u32) -> u8 { + // Safety: There are absolutely no safety concerns with calling `_addcarry_u32`. + // It's just unsafe for API consistency with other intrinsics. + unsafe { arch::_addcarry_u32(carry, a, b, out) } + } +); // fallback for environments where we don't have an addcarry intrinsic // (copied from the standard library's `carrying_add`) diff --git a/src/biguint/division.rs b/src/biguint/division.rs index adf9db89..3dfb0bbb 100644 --- a/src/biguint/division.rs +++ b/src/biguint/division.rs @@ -44,8 +44,21 @@ fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigi unsafe { let (div, rem); + cfg_digit!( + macro_rules! div { + () => { + "div {0:e}" + }; + } + macro_rules! div { + () => { + "div {0:r}" + }; + } + ); + core::arch::asm!( - "div {}", + div!(), in(reg) divisor, inout("dx") hi => rem, inout("ax") lo => div, diff --git a/src/biguint/subtraction.rs b/src/biguint/subtraction.rs index 0154a3b0..47a5015f 100644 --- a/src/biguint/subtraction.rs +++ b/src/biguint/subtraction.rs @@ -7,22 +7,32 @@ use core::cmp::Ordering::{Equal, Greater, Less}; use core::ops::{Sub, SubAssign}; use num_traits::CheckedSub; -// Subtract with borrow: #[cfg(target_arch = "x86_64")] -#[inline] -fn sbb(borrow: u8, a: u64, b: u64, out: &mut u64) -> u8 { - // Safety: There are absolutely no safety concerns with calling `_subborrow_u64`. - // It's just unsafe for API consistency with other intrinsics. - unsafe { core::arch::x86_64::_subborrow_u64(borrow, a, b, out) } -} +use core::arch::x86_64 as arch; #[cfg(target_arch = "x86")] -#[inline] -fn sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u8 { - // Safety: There are absolutely no safety concerns with calling `_subborrow_u32`. - // It's just unsafe for API consistency with other intrinsics. - unsafe { core::arch::x86::_subborrow_u32(borrow, a, b, out) } -} +use core::arch::x86 as arch; + +// Subtract with borrow: +#[cfg(target_arch = "x86_64")] +cfg_64!( + #[inline] + fn sbb(borrow: u8, a: u64, b: u64, out: &mut u64) -> u8 { + // Safety: There are absolutely no safety concerns with calling `_subborrow_u64`. + // It's just unsafe for API consistency with other intrinsics. + unsafe { arch::_subborrow_u64(borrow, a, b, out) } + } +); + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +cfg_32!( + #[inline] + fn sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u8 { + // Safety: There are absolutely no safety concerns with calling `_subborrow_u32`. + // It's just unsafe for API consistency with other intrinsics. + unsafe { arch::_subborrow_u32(borrow, a, b, out) } + } +); // fallback for environments where we don't have a subborrow intrinsic // (copied from the standard library's `borrowing_sub`)