Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for target x32 #312

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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