use crate::int::udiv::*;
macro_rules! sdivmod {
(
$unsigned_fn:ident, // name of the unsigned division function
$signed_fn:ident, // name of the signed division function
$uX:ident, // unsigned integer type for the inputs and outputs of `$unsigned_name`
$iX:ident, // signed integer type for the inputs and outputs of `$signed_name`
$($attr:tt),* // attributes
) => {
intrinsics! {
$(
#[$attr]
)*
pub extern "C" fn $signed_fn(a: $iX, b: $iX, rem: &mut $iX) -> $iX {
let a_neg = a < 0;
let b_neg = b < 0;
let mut a = a;
let mut b = b;
if a_neg {
a = a.wrapping_neg();
}
if b_neg {
b = b.wrapping_neg();
}
let mut r = *rem as $uX;
let t = $unsigned_fn(a as $uX, b as $uX, Some(&mut r)) as $iX;
let mut r = r as $iX;
if a_neg {
r = r.wrapping_neg();
}
*rem = r;
if a_neg != b_neg {
t.wrapping_neg()
} else {
t
}
}
}
}
}
macro_rules! sdiv {
(
$unsigned_fn:ident, // name of the unsigned division function
$signed_fn:ident, // name of the signed division function
$uX:ident, // unsigned integer type for the inputs and outputs of `$unsigned_name`
$iX:ident, // signed integer type for the inputs and outputs of `$signed_name`
$($attr:tt),* // attributes
) => {
intrinsics! {
$(
#[$attr]
)*
pub extern "C" fn $signed_fn(a: $iX, b: $iX) -> $iX {
let a_neg = a < 0;
let b_neg = b < 0;
let mut a = a;
let mut b = b;
if a_neg {
a = a.wrapping_neg();
}
if b_neg {
b = b.wrapping_neg();
}
let t = $unsigned_fn(a as $uX, b as $uX) as $iX;
if a_neg != b_neg {
t.wrapping_neg()
} else {
t
}
}
}
}
}
macro_rules! smod {
(
$unsigned_fn:ident, // name of the unsigned division function
$signed_fn:ident, // name of the signed division function
$uX:ident, // unsigned integer type for the inputs and outputs of `$unsigned_name`
$iX:ident, // signed integer type for the inputs and outputs of `$signed_name`
$($attr:tt),* // attributes
) => {
intrinsics! {
$(
#[$attr]
)*
pub extern "C" fn $signed_fn(a: $iX, b: $iX) -> $iX {
let a_neg = a < 0;
let b_neg = b < 0;
let mut a = a;
let mut b = b;
if a_neg {
a = a.wrapping_neg();
}
if b_neg {
b = b.wrapping_neg();
}
let r = $unsigned_fn(a as $uX, b as $uX) as $iX;
if a_neg {
r.wrapping_neg()
} else {
r
}
}
}
}
}
#[cfg(not(target_arch = "avr"))]
sdivmod!(
__udivmodsi4,
__divmodsi4,
u32,
i32,
maybe_use_optimized_c_shim
);
#[cfg(target_arch = "avr")]
intrinsics! {
pub extern "C" fn __divmodsi4(a: i32, b: i32) -> u64 {
let a_neg = a < 0;
let b_neg = b < 0;
let mut a = a;
let mut b = b;
if a_neg {
a = a.wrapping_neg();
}
if b_neg {
b = b.wrapping_neg();
}
let tr = __udivmodsi4(a as u32, b as u32);
let mut t = tr as u32 as i32;
let mut r = (tr >> 32) as u32 as i32;
if a_neg {
r = r.wrapping_neg();
}
if a_neg != b_neg {
t = t.wrapping_neg();
}
((r as u32 as u64) << 32) | (t as u32 as u64)
}
}
intrinsics! {
#[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_idiv]
pub extern "C" fn __divsi3(a: i32, b: i32) -> i32 {
let a_neg = a < 0;
let b_neg = b < 0;
let mut a = a;
let mut b = b;
if a_neg {
a = a.wrapping_neg();
}
if b_neg {
b = b.wrapping_neg();
}
let t = __udivsi3(a as u32, b as u32) as i32;
if a_neg != b_neg {
t.wrapping_neg()
} else {
t
}
}
}
smod!(__umodsi3, __modsi3, u32, i32, maybe_use_optimized_c_shim);
sdivmod!(
__udivmoddi4,
__divmoddi4,
u64,
i64,
maybe_use_optimized_c_shim
);
sdiv!(__udivdi3, __divdi3, u64, i64, maybe_use_optimized_c_shim);
smod!(__umoddi3, __moddi3, u64, i64, maybe_use_optimized_c_shim);
sdivmod!(
__udivmodti4,
__divmodti4,
u128,
i128,
maybe_use_optimized_c_shim
);
sdiv!(__udivti3, __divti3, u128, i128,);
smod!(__umodti3, __modti3, u128, i128,);