Merge pull request #210 from scottmcm/add-128bit-lang-items
Implement all the 128-bit operator lang items (Rust 45676 part 2)
This commit is contained in:
commit
60d949ba1d
482
build.rs
482
build.rs
@ -129,6 +129,16 @@ mod tests {
|
||||
Divsf3,
|
||||
Divdf3,
|
||||
|
||||
// int/addsub.rs
|
||||
AddU128,
|
||||
AddI128,
|
||||
AddoU128,
|
||||
AddoI128,
|
||||
SubU128,
|
||||
SubI128,
|
||||
SuboU128,
|
||||
SuboI128,
|
||||
|
||||
// int/mul.rs
|
||||
Muldi3,
|
||||
Mulodi4,
|
||||
@ -341,6 +351,242 @@ fn addsf3() {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct AddU128 {
|
||||
a: u128,
|
||||
b: u128,
|
||||
c: u128,
|
||||
}
|
||||
|
||||
impl TestCase for AddU128 {
|
||||
fn name() -> &'static str {
|
||||
"u128_add"
|
||||
}
|
||||
|
||||
fn generate<R>(rng: &mut R) -> Option<Self>
|
||||
where
|
||||
R: Rng,
|
||||
Self: Sized,
|
||||
{
|
||||
let a = gen_u128(rng);
|
||||
let b = gen_u128(rng);
|
||||
let c = a.wrapping_add(b);
|
||||
|
||||
Some(AddU128 { a, b, c })
|
||||
}
|
||||
|
||||
fn to_string(&self, buffer: &mut String) {
|
||||
writeln!(
|
||||
buffer,
|
||||
"(({a}, {b}), {c}),",
|
||||
a = self.a,
|
||||
b = self.b,
|
||||
c = self.c
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn prologue() -> &'static str {
|
||||
"
|
||||
use compiler_builtins::int::addsub::rust_u128_add;
|
||||
|
||||
static TEST_CASES: &[((u128, u128), u128)] = &[
|
||||
"
|
||||
}
|
||||
|
||||
fn epilogue() -> &'static str {
|
||||
"
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn u128_add() {
|
||||
for &((a, b), c) in TEST_CASES {
|
||||
let c_ = rust_u128_add(a, b);
|
||||
assert_eq!(((a, b), c), ((a, b), c_));
|
||||
}
|
||||
}
|
||||
"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct AddI128 {
|
||||
a: i128,
|
||||
b: i128,
|
||||
c: i128,
|
||||
}
|
||||
|
||||
impl TestCase for AddI128 {
|
||||
fn name() -> &'static str {
|
||||
"i128_add"
|
||||
}
|
||||
|
||||
fn generate<R>(rng: &mut R) -> Option<Self>
|
||||
where
|
||||
R: Rng,
|
||||
Self: Sized,
|
||||
{
|
||||
let a = gen_i128(rng);
|
||||
let b = gen_i128(rng);
|
||||
let c = a.wrapping_add(b);
|
||||
|
||||
Some(AddI128 { a, b, c })
|
||||
}
|
||||
|
||||
fn to_string(&self, buffer: &mut String) {
|
||||
writeln!(
|
||||
buffer,
|
||||
"(({a}, {b}), {c}),",
|
||||
a = self.a,
|
||||
b = self.b,
|
||||
c = self.c
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn prologue() -> &'static str {
|
||||
"
|
||||
use compiler_builtins::int::addsub::rust_i128_add;
|
||||
|
||||
static TEST_CASES: &[((i128, i128), i128)] = &[
|
||||
"
|
||||
}
|
||||
|
||||
fn epilogue() -> &'static str {
|
||||
"
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn i128_add() {
|
||||
for &((a, b), c) in TEST_CASES {
|
||||
let c_ = rust_i128_add(a, b);
|
||||
assert_eq!(((a, b), c), ((a, b), c_));
|
||||
}
|
||||
}
|
||||
"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct AddoU128 {
|
||||
a: u128,
|
||||
b: u128,
|
||||
c: u128,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
impl TestCase for AddoU128 {
|
||||
fn name() -> &'static str {
|
||||
"u128_addo"
|
||||
}
|
||||
|
||||
fn generate<R>(rng: &mut R) -> Option<Self>
|
||||
where
|
||||
R: Rng,
|
||||
Self: Sized,
|
||||
{
|
||||
let a = gen_u128(rng);
|
||||
let b = gen_u128(rng);
|
||||
let (c, d) = a.overflowing_add(b);
|
||||
|
||||
Some(AddoU128 { a, b, c, d })
|
||||
}
|
||||
|
||||
fn to_string(&self, buffer: &mut String) {
|
||||
writeln!(
|
||||
buffer,
|
||||
"(({a}, {b}), ({c}, {d})),",
|
||||
a = self.a,
|
||||
b = self.b,
|
||||
c = self.c,
|
||||
d = self.d
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn prologue() -> &'static str {
|
||||
"
|
||||
use compiler_builtins::int::addsub::rust_u128_addo;
|
||||
|
||||
static TEST_CASES: &[((u128, u128), (u128, bool))] = &[
|
||||
"
|
||||
}
|
||||
|
||||
fn epilogue() -> &'static str {
|
||||
"
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn u128_addo() {
|
||||
for &((a, b), (c, d)) in TEST_CASES {
|
||||
let (c_, d_) = rust_u128_addo(a, b);
|
||||
assert_eq!(((a, b), (c, d)), ((a, b), (c_, d_)));
|
||||
}
|
||||
}
|
||||
"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct AddoI128 {
|
||||
a: i128,
|
||||
b: i128,
|
||||
c: i128,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
impl TestCase for AddoI128 {
|
||||
fn name() -> &'static str {
|
||||
"i128_addo"
|
||||
}
|
||||
|
||||
fn generate<R>(rng: &mut R) -> Option<Self>
|
||||
where
|
||||
R: Rng,
|
||||
Self: Sized,
|
||||
{
|
||||
let a = gen_i128(rng);
|
||||
let b = gen_i128(rng);
|
||||
let (c, d) = a.overflowing_add(b);
|
||||
|
||||
Some(AddoI128 { a, b, c, d })
|
||||
}
|
||||
|
||||
fn to_string(&self, buffer: &mut String) {
|
||||
writeln!(
|
||||
buffer,
|
||||
"(({a}, {b}), ({c}, {d})),",
|
||||
a = self.a,
|
||||
b = self.b,
|
||||
c = self.c,
|
||||
d = self.d
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn prologue() -> &'static str {
|
||||
"
|
||||
use compiler_builtins::int::addsub::rust_i128_addo;
|
||||
|
||||
static TEST_CASES: &[((i128, i128), (i128, bool))] = &[
|
||||
"
|
||||
}
|
||||
|
||||
fn epilogue() -> &'static str {
|
||||
"
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn i128_addo() {
|
||||
for &((a, b), (c, d)) in TEST_CASES {
|
||||
let (c_, d_) = rust_i128_addo(a, b);
|
||||
assert_eq!(((a, b), (c, d)), ((a, b), (c_, d_)));
|
||||
}
|
||||
}
|
||||
"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct Ashldi3 {
|
||||
a: u64,
|
||||
@ -3229,6 +3475,242 @@ fn subsf3() {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct SubU128 {
|
||||
a: u128,
|
||||
b: u128,
|
||||
c: u128,
|
||||
}
|
||||
|
||||
impl TestCase for SubU128 {
|
||||
fn name() -> &'static str {
|
||||
"u128_sub"
|
||||
}
|
||||
|
||||
fn generate<R>(rng: &mut R) -> Option<Self>
|
||||
where
|
||||
R: Rng,
|
||||
Self: Sized,
|
||||
{
|
||||
let a = gen_u128(rng);
|
||||
let b = gen_u128(rng);
|
||||
let c = a.wrapping_sub(b);
|
||||
|
||||
Some(SubU128 { a, b, c })
|
||||
}
|
||||
|
||||
fn to_string(&self, buffer: &mut String) {
|
||||
writeln!(
|
||||
buffer,
|
||||
"(({a}, {b}), {c}),",
|
||||
a = self.a,
|
||||
b = self.b,
|
||||
c = self.c
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn prologue() -> &'static str {
|
||||
"
|
||||
use compiler_builtins::int::addsub::rust_u128_sub;
|
||||
|
||||
static TEST_CASES: &[((u128, u128), u128)] = &[
|
||||
"
|
||||
}
|
||||
|
||||
fn epilogue() -> &'static str {
|
||||
"
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn u128_sub() {
|
||||
for &((a, b), c) in TEST_CASES {
|
||||
let c_ = rust_u128_sub(a, b);
|
||||
assert_eq!(((a, b), c), ((a, b), c_));
|
||||
}
|
||||
}
|
||||
"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct SubI128 {
|
||||
a: i128,
|
||||
b: i128,
|
||||
c: i128,
|
||||
}
|
||||
|
||||
impl TestCase for SubI128 {
|
||||
fn name() -> &'static str {
|
||||
"i128_sub"
|
||||
}
|
||||
|
||||
fn generate<R>(rng: &mut R) -> Option<Self>
|
||||
where
|
||||
R: Rng,
|
||||
Self: Sized,
|
||||
{
|
||||
let a = gen_i128(rng);
|
||||
let b = gen_i128(rng);
|
||||
let c = a.wrapping_sub(b);
|
||||
|
||||
Some(SubI128 { a, b, c })
|
||||
}
|
||||
|
||||
fn to_string(&self, buffer: &mut String) {
|
||||
writeln!(
|
||||
buffer,
|
||||
"(({a}, {b}), {c}),",
|
||||
a = self.a,
|
||||
b = self.b,
|
||||
c = self.c
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn prologue() -> &'static str {
|
||||
"
|
||||
use compiler_builtins::int::addsub::rust_i128_sub;
|
||||
|
||||
static TEST_CASES: &[((i128, i128), i128)] = &[
|
||||
"
|
||||
}
|
||||
|
||||
fn epilogue() -> &'static str {
|
||||
"
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn i128_sub() {
|
||||
for &((a, b), c) in TEST_CASES {
|
||||
let c_ = rust_i128_sub(a, b);
|
||||
assert_eq!(((a, b), c), ((a, b), c_));
|
||||
}
|
||||
}
|
||||
"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct SuboU128 {
|
||||
a: u128,
|
||||
b: u128,
|
||||
c: u128,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
impl TestCase for SuboU128 {
|
||||
fn name() -> &'static str {
|
||||
"u128_subo"
|
||||
}
|
||||
|
||||
fn generate<R>(rng: &mut R) -> Option<Self>
|
||||
where
|
||||
R: Rng,
|
||||
Self: Sized,
|
||||
{
|
||||
let a = gen_u128(rng);
|
||||
let b = gen_u128(rng);
|
||||
let (c, d) = a.overflowing_sub(b);
|
||||
|
||||
Some(SuboU128 { a, b, c, d })
|
||||
}
|
||||
|
||||
fn to_string(&self, buffer: &mut String) {
|
||||
writeln!(
|
||||
buffer,
|
||||
"(({a}, {b}), ({c}, {d})),",
|
||||
a = self.a,
|
||||
b = self.b,
|
||||
c = self.c,
|
||||
d = self.d
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn prologue() -> &'static str {
|
||||
"
|
||||
use compiler_builtins::int::addsub::rust_u128_subo;
|
||||
|
||||
static TEST_CASES: &[((u128, u128), (u128, bool))] = &[
|
||||
"
|
||||
}
|
||||
|
||||
fn epilogue() -> &'static str {
|
||||
"
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn u128_subo() {
|
||||
for &((a, b), (c, d)) in TEST_CASES {
|
||||
let (c_, d_) = rust_u128_subo(a, b);
|
||||
assert_eq!(((a, b), (c, d)), ((a, b), (c_, d_)));
|
||||
}
|
||||
}
|
||||
"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct SuboI128 {
|
||||
a: i128,
|
||||
b: i128,
|
||||
c: i128,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
impl TestCase for SuboI128 {
|
||||
fn name() -> &'static str {
|
||||
"i128_subo"
|
||||
}
|
||||
|
||||
fn generate<R>(rng: &mut R) -> Option<Self>
|
||||
where
|
||||
R: Rng,
|
||||
Self: Sized,
|
||||
{
|
||||
let a = gen_i128(rng);
|
||||
let b = gen_i128(rng);
|
||||
let (c, d) = a.overflowing_sub(b);
|
||||
|
||||
Some(SuboI128 { a, b, c, d })
|
||||
}
|
||||
|
||||
fn to_string(&self, buffer: &mut String) {
|
||||
writeln!(
|
||||
buffer,
|
||||
"(({a}, {b}), ({c}, {d})),",
|
||||
a = self.a,
|
||||
b = self.b,
|
||||
c = self.c,
|
||||
d = self.d
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn prologue() -> &'static str {
|
||||
"
|
||||
use compiler_builtins::int::addsub::rust_i128_subo;
|
||||
|
||||
static TEST_CASES: &[((i128, i128), (i128, bool))] = &[
|
||||
"
|
||||
}
|
||||
|
||||
fn epilogue() -> &'static str {
|
||||
"
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn i128_subo() {
|
||||
for &((a, b), (c, d)) in TEST_CASES {
|
||||
let (c_, d_) = rust_i128_subo(a, b);
|
||||
assert_eq!(((a, b), (c, d)), ((a, b), (c_, d_)));
|
||||
}
|
||||
}
|
||||
"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct Mulsf3 {
|
||||
a: u32, // f32
|
||||
|
122
src/int/addsub.rs
Normal file
122
src/int/addsub.rs
Normal file
@ -0,0 +1,122 @@
|
||||
use int::LargeInt;
|
||||
use int::Int;
|
||||
|
||||
trait UAddSub: LargeInt {
|
||||
fn uadd(self, other: Self) -> Self {
|
||||
let (low, carry) = self.low().overflowing_add(other.low());
|
||||
let high = self.high().wrapping_add(other.high());
|
||||
let carry = if carry { Self::HighHalf::ONE } else { Self::HighHalf::ZERO };
|
||||
Self::from_parts(low, high.wrapping_add(carry))
|
||||
}
|
||||
fn uadd_one(self) -> Self {
|
||||
let (low, carry) = self.low().overflowing_add(Self::LowHalf::ONE);
|
||||
let carry = if carry { Self::HighHalf::ONE } else { Self::HighHalf::ZERO };
|
||||
Self::from_parts(low, self.high().wrapping_add(carry))
|
||||
}
|
||||
fn usub(self, other: Self) -> Self {
|
||||
let uneg = (!other).uadd_one();
|
||||
self.uadd(uneg)
|
||||
}
|
||||
}
|
||||
|
||||
impl UAddSub for u128 {}
|
||||
|
||||
trait AddSub: Int
|
||||
where <Self as Int>::UnsignedInt: UAddSub
|
||||
{
|
||||
fn add(self, other: Self) -> Self {
|
||||
Self::from_unsigned(self.unsigned().uadd(other.unsigned()))
|
||||
}
|
||||
fn sub(self, other: Self) -> Self {
|
||||
Self::from_unsigned(self.unsigned().usub(other.unsigned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl AddSub for u128 {}
|
||||
impl AddSub for i128 {}
|
||||
|
||||
trait Addo: AddSub
|
||||
where <Self as Int>::UnsignedInt: UAddSub
|
||||
{
|
||||
fn addo(self, other: Self, overflow: &mut i32) -> Self {
|
||||
*overflow = 0;
|
||||
let result = AddSub::add(self, other);
|
||||
if other >= Self::ZERO {
|
||||
if result < self {
|
||||
*overflow = 1;
|
||||
}
|
||||
} else {
|
||||
if result >= self {
|
||||
*overflow = 1;
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl Addo for i128 {}
|
||||
impl Addo for u128 {}
|
||||
|
||||
trait Subo: AddSub
|
||||
where <Self as Int>::UnsignedInt: UAddSub
|
||||
{
|
||||
fn subo(self, other: Self, overflow: &mut i32) -> Self {
|
||||
*overflow = 0;
|
||||
let result = AddSub::sub(self, other);
|
||||
if other >= Self::ZERO {
|
||||
if result > self {
|
||||
*overflow = 1;
|
||||
}
|
||||
} else {
|
||||
if result <= self {
|
||||
*overflow = 1;
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl Subo for i128 {}
|
||||
impl Subo for u128 {}
|
||||
|
||||
#[cfg_attr(not(stage0), lang = "i128_add")]
|
||||
pub fn rust_i128_add(a: i128, b: i128) -> i128 {
|
||||
rust_u128_add(a as _, b as _) as _
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "i128_addo")]
|
||||
pub fn rust_i128_addo(a: i128, b: i128) -> (i128, bool) {
|
||||
let mut oflow = 0;
|
||||
let r = a.addo(b, &mut oflow);
|
||||
(r, oflow != 0)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_add")]
|
||||
pub fn rust_u128_add(a: u128, b: u128) -> u128 {
|
||||
a.add(b)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_addo")]
|
||||
pub fn rust_u128_addo(a: u128, b: u128) -> (u128, bool) {
|
||||
let mut oflow = 0;
|
||||
let r = a.addo(b, &mut oflow);
|
||||
(r, oflow != 0)
|
||||
}
|
||||
|
||||
#[cfg_attr(not(stage0), lang = "i128_sub")]
|
||||
pub fn rust_i128_sub(a: i128, b: i128) -> i128 {
|
||||
rust_u128_sub(a as _, b as _) as _
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "i128_subo")]
|
||||
pub fn rust_i128_subo(a: i128, b: i128) -> (i128, bool) {
|
||||
let mut oflow = 0;
|
||||
let r = a.subo(b, &mut oflow);
|
||||
(r, oflow != 0)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_sub")]
|
||||
pub fn rust_u128_sub(a: u128, b: u128) -> u128 {
|
||||
a.sub(b)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_subo")]
|
||||
pub fn rust_u128_subo(a: u128, b: u128) -> (u128, bool) {
|
||||
let mut oflow = 0;
|
||||
let r = a.subo(b, &mut oflow);
|
||||
(r, oflow != 0)
|
||||
}
|
@ -12,6 +12,7 @@ macro_rules! os_ty {
|
||||
}
|
||||
}
|
||||
|
||||
pub mod addsub;
|
||||
pub mod mul;
|
||||
pub mod sdiv;
|
||||
pub mod shift;
|
||||
@ -72,6 +73,7 @@ pub trait Int:
|
||||
fn wrapping_mul(self, other: Self) -> Self;
|
||||
fn wrapping_sub(self, other: Self) -> Self;
|
||||
fn wrapping_shl(self, other: u32) -> Self;
|
||||
fn overflowing_add(self, other: Self) -> (Self, bool);
|
||||
fn aborting_div(self, other: Self) -> Self;
|
||||
fn aborting_rem(self, other: Self) -> Self;
|
||||
fn leading_zeros(self) -> u32;
|
||||
@ -119,6 +121,10 @@ macro_rules! int_impl_common {
|
||||
<Self>::wrapping_shl(self, other)
|
||||
}
|
||||
|
||||
fn overflowing_add(self, other: Self) -> (Self, bool) {
|
||||
<Self>::overflowing_add(self, other)
|
||||
}
|
||||
|
||||
fn aborting_div(self, other: Self) -> Self {
|
||||
unwrap(<Self>::checked_div(self, other))
|
||||
}
|
||||
|
@ -70,6 +70,18 @@ impl Mulo for i32 {}
|
||||
impl Mulo for i64 {}
|
||||
impl Mulo for i128 {}
|
||||
|
||||
trait UMulo : Int {
|
||||
fn mulo(self, other: Self, overflow: &mut i32) -> Self {
|
||||
*overflow = 0;
|
||||
let result = self.wrapping_mul(other);
|
||||
if self > Self::max_value().aborting_div(other) {
|
||||
*overflow = 1;
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
impl UMulo for u128 {}
|
||||
|
||||
intrinsics! {
|
||||
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))]
|
||||
#[arm_aeabi_alias = __aeabi_lmul]
|
||||
@ -95,3 +107,24 @@ intrinsics! {
|
||||
a.mulo(b, oflow)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(stage0), lang = "i128_mul")]
|
||||
pub fn rust_i128_mul(a: i128, b: i128) -> i128 {
|
||||
__multi3(a, b)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "i128_mulo")]
|
||||
pub fn rust_i128_mulo(a: i128, b: i128) -> (i128, bool) {
|
||||
let mut oflow = 0;
|
||||
let r = __muloti4(a, b, &mut oflow);
|
||||
(r, oflow != 0)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_mul")]
|
||||
pub fn rust_u128_mul(a: u128, b: u128) -> u128 {
|
||||
__multi3(a as _, b as _) as _
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_mulo")]
|
||||
pub fn rust_u128_mulo(a: u128, b: u128) -> (u128, bool) {
|
||||
let mut oflow = 0;
|
||||
let r = a.mulo(b, &mut oflow);
|
||||
(r, oflow != 0)
|
||||
}
|
||||
|
@ -97,3 +97,12 @@ intrinsics! {
|
||||
a.divmod(b, rem, |a, b| __divdi3(a, b))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(stage0), lang = "i128_div")]
|
||||
pub fn rust_i128_div(a: i128, b: i128) -> i128 {
|
||||
__divti3(a, b)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "i128_rem")]
|
||||
pub fn rust_i128_rem(a: i128, b: i128) -> i128 {
|
||||
__modti3(a, b)
|
||||
}
|
||||
|
@ -95,3 +95,37 @@ intrinsics! {
|
||||
a.lshr(b)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(stage0), lang = "i128_shl")]
|
||||
pub fn rust_i128_shl(a: i128, b: u32) -> i128 {
|
||||
__ashlti3(a as _, b) as _
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "i128_shlo")]
|
||||
pub fn rust_i128_shlo(a: i128, b: u128) -> (i128, bool) {
|
||||
(rust_i128_shl(a, b as _), b >= 128)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_shl")]
|
||||
pub fn rust_u128_shl(a: u128, b: u32) -> u128 {
|
||||
__ashlti3(a, b)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_shlo")]
|
||||
pub fn rust_u128_shlo(a: u128, b: u128) -> (u128, bool) {
|
||||
(rust_u128_shl(a, b as _), b >= 128)
|
||||
}
|
||||
|
||||
#[cfg_attr(not(stage0), lang = "i128_shr")]
|
||||
pub fn rust_i128_shr(a: i128, b: u32) -> i128 {
|
||||
__ashrti3(a, b)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "i128_shro")]
|
||||
pub fn rust_i128_shro(a: i128, b: u128) -> (i128, bool) {
|
||||
(rust_i128_shr(a, b as _), b >= 128)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_shr")]
|
||||
pub fn rust_u128_shr(a: u128, b: u32) -> u128 {
|
||||
__lshrti3(a, b)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_shro")]
|
||||
pub fn rust_u128_shro(a: u128, b: u128) -> (u128, bool) {
|
||||
(rust_u128_shr(a, b as _), b >= 128)
|
||||
}
|
||||
|
@ -269,3 +269,12 @@ intrinsics! {
|
||||
udivmod_inner!(n, d, rem, u128)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(stage0), lang = "u128_div")]
|
||||
pub fn rust_u128_div(a: u128, b: u128) -> u128 {
|
||||
__udivti3(a, b)
|
||||
}
|
||||
#[cfg_attr(not(stage0), lang = "u128_rem")]
|
||||
pub fn rust_u128_rem(a: u128, b: u128) -> u128 {
|
||||
__umodti3(a, b)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#![feature(repr_simd)]
|
||||
#![feature(abi_unadjusted)]
|
||||
#![feature(linkage)]
|
||||
#![feature(lang_items)]
|
||||
#![allow(unused_features)]
|
||||
#![no_builtins]
|
||||
#![unstable(feature = "compiler_builtins_lib",
|
||||
|
8
tests/i128_add.rs
Normal file
8
tests/i128_add.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![feature(compiler_builtins_lib)]
|
||||
#![feature(i128_type)]
|
||||
#![cfg_attr(all(target_arch = "arm",
|
||||
not(any(target_env = "gnu", target_env = "musl")),
|
||||
target_os = "linux",
|
||||
test), no_std)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/i128_add.rs"));
|
8
tests/i128_addo.rs
Normal file
8
tests/i128_addo.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![feature(compiler_builtins_lib)]
|
||||
#![feature(i128_type)]
|
||||
#![cfg_attr(all(target_arch = "arm",
|
||||
not(any(target_env = "gnu", target_env = "musl")),
|
||||
target_os = "linux",
|
||||
test), no_std)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/i128_addo.rs"));
|
8
tests/i128_sub.rs
Normal file
8
tests/i128_sub.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![feature(compiler_builtins_lib)]
|
||||
#![feature(i128_type)]
|
||||
#![cfg_attr(all(target_arch = "arm",
|
||||
not(any(target_env = "gnu", target_env = "musl")),
|
||||
target_os = "linux",
|
||||
test), no_std)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/i128_sub.rs"));
|
8
tests/i128_subo.rs
Normal file
8
tests/i128_subo.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![feature(compiler_builtins_lib)]
|
||||
#![feature(i128_type)]
|
||||
#![cfg_attr(all(target_arch = "arm",
|
||||
not(any(target_env = "gnu", target_env = "musl")),
|
||||
target_os = "linux",
|
||||
test), no_std)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/i128_subo.rs"));
|
8
tests/u128_add.rs
Normal file
8
tests/u128_add.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![feature(compiler_builtins_lib)]
|
||||
#![feature(i128_type)]
|
||||
#![cfg_attr(all(target_arch = "arm",
|
||||
not(any(target_env = "gnu", target_env = "musl")),
|
||||
target_os = "linux",
|
||||
test), no_std)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/u128_add.rs"));
|
8
tests/u128_addo.rs
Normal file
8
tests/u128_addo.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![feature(compiler_builtins_lib)]
|
||||
#![feature(i128_type)]
|
||||
#![cfg_attr(all(target_arch = "arm",
|
||||
not(any(target_env = "gnu", target_env = "musl")),
|
||||
target_os = "linux",
|
||||
test), no_std)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/u128_addo.rs"));
|
8
tests/u128_sub.rs
Normal file
8
tests/u128_sub.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![feature(compiler_builtins_lib)]
|
||||
#![feature(i128_type)]
|
||||
#![cfg_attr(all(target_arch = "arm",
|
||||
not(any(target_env = "gnu", target_env = "musl")),
|
||||
target_os = "linux",
|
||||
test), no_std)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/u128_sub.rs"));
|
8
tests/u128_subo.rs
Normal file
8
tests/u128_subo.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![feature(compiler_builtins_lib)]
|
||||
#![feature(i128_type)]
|
||||
#![cfg_attr(all(target_arch = "arm",
|
||||
not(any(target_env = "gnu", target_env = "musl")),
|
||||
target_os = "linux",
|
||||
test), no_std)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/u128_subo.rs"));
|
Loading…
Reference in New Issue
Block a user