compiler-builtins-zynq/src/int/mod.rs

135 lines
2.7 KiB
Rust
Executable File

macro_rules! hty {
($ty:ty) => {
<$ty as LargeInt>::HighHalf
}
}
macro_rules! os_ty {
($ty:ty) => {
<$ty as Int>::OtherSign
}
}
pub mod mul;
pub mod sdiv;
pub mod shift;
pub mod udiv;
/// Trait for some basic operations on integers
pub trait Int {
/// Type with the same width but other signedness
type OtherSign;
/// Unsigned version of Self
type UnsignedInt;
/// Returns the bitwidth of the int type
fn bits() -> u32;
/// Extracts the sign from self and returns a tuple.
///
/// # Examples
///
/// ```rust,ignore
/// let i = -25_i32;
/// let (sign, u) = i.extract_sign();
/// assert_eq!(sign, true);
/// assert_eq!(u, 25_u32);
/// ```
fn extract_sign(self) -> (bool, Self::UnsignedInt);
}
// TODO: Once i128/u128 support lands, we'll want to add impls for those as well
impl Int for u32 {
type OtherSign = i32;
type UnsignedInt = u32;
fn bits() -> u32 {
32
}
fn extract_sign(self) -> (bool, u32) {
(false, self)
}
}
impl Int for i32 {
type OtherSign = u32;
type UnsignedInt = u32;
fn bits() -> u32 {
32
}
fn extract_sign(self) -> (bool, u32) {
if self < 0 {
(true, !(self as u32) + 1)
} else {
(false, self as u32)
}
}
}
impl Int for u64 {
type OtherSign = i64;
type UnsignedInt = u64;
fn bits() -> u32 {
64
}
fn extract_sign(self) -> (bool, u64) {
(false, self)
}
}
impl Int for i64 {
type OtherSign = u64;
type UnsignedInt = u64;
fn bits() -> u32 {
64
}
fn extract_sign(self) -> (bool, u64) {
if self < 0 {
(true, !(self as u64) + 1)
} else {
(false, self as u64)
}
}
}
/// Trait to convert an integer to/from smaller parts
pub trait LargeInt {
type LowHalf;
type HighHalf;
fn low(self) -> Self::LowHalf;
fn high(self) -> Self::HighHalf;
fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
}
macro_rules! large_int {
($ty:ty, $tylow:ty, $tyhigh:ty, $halfbits:expr) => {
impl LargeInt for $ty {
type LowHalf = $tylow;
type HighHalf = $tyhigh;
fn low(self) -> $tylow {
self as $tylow
}
fn high(self) -> $tyhigh {
(self >> $halfbits) as $tyhigh
}
fn from_parts(low: $tylow, high: $tyhigh) -> $ty {
low as $ty | ((high as $ty) << $halfbits)
}
}
}
}
large_int!(u64, u32, u32, 32);
large_int!(i64, u32, i32, 32);
large_int!(u128, u64, u64, 64);
large_int!(i128, u64, i64, 64);