summaryrefslogtreecommitdiffstats
path: root/vendor/compiler_builtins/src/int/sdiv.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/compiler_builtins/src/int/sdiv.rs')
-rw-r--r--vendor/compiler_builtins/src/int/sdiv.rs169
1 files changed, 169 insertions, 0 deletions
diff --git a/vendor/compiler_builtins/src/int/sdiv.rs b/vendor/compiler_builtins/src/int/sdiv.rs
new file mode 100644
index 000000000..f1822f0f8
--- /dev/null
+++ b/vendor/compiler_builtins/src/int/sdiv.rs
@@ -0,0 +1,169 @@
+use 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! {
+ #[avr_skip]
+ $(
+ #[$attr]
+ )*
+ /// Returns `n / d` and sets `*rem = n % d`
+ 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! {
+ #[avr_skip]
+ $(
+ #[$attr]
+ )*
+ /// Returns `n / d`
+ 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! {
+ #[avr_skip]
+ $(
+ #[$attr]
+ )*
+ /// Returns `n % d`
+ 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
+ }
+ }
+ }
+ }
+}
+
+sdivmod!(
+ __udivmodsi4,
+ __divmodsi4,
+ u32,
+ i32,
+ maybe_use_optimized_c_shim
+);
+// The `#[arm_aeabi_alias = __aeabi_idiv]` attribute cannot be made to work with `intrinsics!` in macros
+intrinsics! {
+ #[maybe_use_optimized_c_shim]
+ #[arm_aeabi_alias = __aeabi_idiv]
+ /// Returns `n / d`
+ 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);
+
+// LLVM does not currently have a `__divmodti4` function, but GCC does
+sdivmod!(
+ __udivmodti4,
+ __divmodti4,
+ u128,
+ i128,
+ maybe_use_optimized_c_shim
+);
+sdiv!(__udivti3, __divti3, u128, i128, win64_128bit_abi_hack);
+smod!(__umodti3, __modti3, u128, i128, win64_128bit_abi_hack);