Another attempt at making MIPS happy

(I really don't understand how arithmetic makes it segfault...)
master
Scott McMurray 2017-11-25 07:00:26 -08:00
parent bcc41a9b8d
commit ba750103a3
5 changed files with 136 additions and 136 deletions

View File

@ -129,11 +129,15 @@ mod tests {
Divsf3,
Divdf3,
// int/add.rs
// int/addsub.rs
AddU128,
AddI128,
AddoU128,
AddoI128,
SubU128,
SubI128,
SuboU128,
SuboI128,
// int/mul.rs
Muldi3,
@ -160,12 +164,6 @@ mod tests {
Lshrdi3,
Lshrti3,
// int/sub.rs
SubU128,
SubI128,
SuboU128,
SuboI128,
// int/udiv.rs
Udivdi3,
Udivmoddi4,
@ -390,7 +388,7 @@ fn addsf3() {
fn prologue() -> &'static str {
"
use compiler_builtins::int::add::rust_u128_add;
use compiler_builtins::int::addsub::rust_u128_add;
static TEST_CASES: &[((u128, u128), u128)] = &[
"
@ -448,7 +446,7 @@ fn u128_add() {
fn prologue() -> &'static str {
"
use compiler_builtins::int::add::rust_i128_add;
use compiler_builtins::int::addsub::rust_i128_add;
static TEST_CASES: &[((i128, i128), i128)] = &[
"
@ -508,7 +506,7 @@ fn i128_add() {
fn prologue() -> &'static str {
"
use compiler_builtins::int::add::rust_u128_addo;
use compiler_builtins::int::addsub::rust_u128_addo;
static TEST_CASES: &[((u128, u128), (u128, bool))] = &[
"
@ -568,7 +566,7 @@ fn u128_addo() {
fn prologue() -> &'static str {
"
use compiler_builtins::int::add::rust_i128_addo;
use compiler_builtins::int::addsub::rust_i128_addo;
static TEST_CASES: &[((i128, i128), (i128, bool))] = &[
"
@ -3514,7 +3512,7 @@ fn subsf3() {
fn prologue() -> &'static str {
"
use compiler_builtins::int::sub::rust_u128_sub;
use compiler_builtins::int::addsub::rust_u128_sub;
static TEST_CASES: &[((u128, u128), u128)] = &[
"
@ -3572,7 +3570,7 @@ fn u128_sub() {
fn prologue() -> &'static str {
"
use compiler_builtins::int::sub::rust_i128_sub;
use compiler_builtins::int::addsub::rust_i128_sub;
static TEST_CASES: &[((i128, i128), i128)] = &[
"
@ -3632,7 +3630,7 @@ fn i128_sub() {
fn prologue() -> &'static str {
"
use compiler_builtins::int::sub::rust_u128_subo;
use compiler_builtins::int::addsub::rust_u128_subo;
static TEST_CASES: &[((u128, u128), (u128, bool))] = &[
"
@ -3692,7 +3690,7 @@ fn u128_subo() {
fn prologue() -> &'static str {
"
use compiler_builtins::int::sub::rust_i128_subo;
use compiler_builtins::int::addsub::rust_i128_subo;
static TEST_CASES: &[((i128, i128), (i128, bool))] = &[
"

View File

@ -1,67 +0,0 @@
use int::LargeInt;
use int::Int;
trait UAdd: 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))
}
}
impl UAdd for u128 {}
trait Add: Int
where <Self as Int>::UnsignedInt: UAdd
{
fn add(self, other: Self) -> Self {
Self::from_unsigned(self.unsigned().uadd(other.unsigned()))
}
}
impl Add for u128 {}
impl Add for i128 {}
trait Addo: Add
where <Self as Int>::UnsignedInt: UAdd
{
fn addo(self, other: Self, overflow: &mut i32) -> Self {
*overflow = 0;
let result = Add::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 {}
#[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)
}

122
src/int/addsub.rs Normal file
View 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)
}

View File

@ -12,11 +12,10 @@ macro_rules! os_ty {
}
}
pub mod add;
pub mod addsub;
pub mod mul;
pub mod sdiv;
pub mod shift;
pub mod sub;
pub mod udiv;
/// Trait for some basic operations on integers

View File

@ -1,52 +0,0 @@
use int::LargeInt;
trait Sub: LargeInt {
fn sub(self, other: Self) -> Self {
let neg_other = (!other).wrapping_add(Self::ONE);
self.wrapping_add(neg_other)
}
}
impl Sub for i128 {}
impl Sub for u128 {}
trait Subo: Sub {
fn subo(self, other: Self, overflow: &mut i32) -> Self {
*overflow = 0;
let result = Sub::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_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)
}