Skip to content

Commit

Permalink
Fixes for target x32
Browse files Browse the repository at this point in the history
  • Loading branch information
cuviper committed Jun 27, 2024
1 parent 71b78bc commit 5d530aa
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 28 deletions.
18 changes: 17 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
36 changes: 23 additions & 13 deletions src/biguint/addition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand Down
15 changes: 14 additions & 1 deletion src/biguint/division.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
36 changes: 23 additions & 13 deletions src/biguint/subtraction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand Down

0 comments on commit 5d530aa

Please sign in to comment.