Skip to content

Commit

Permalink
Add integer to f128 conversions
Browse files Browse the repository at this point in the history
  • Loading branch information
tgross35 committed Jun 23, 2024
1 parent 857ecab commit 3d2857a
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 26 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,12 @@ These builtins are needed to support `f16` and `f128`, which are in the process
- [x] fixunstfdi.c
- [x] fixunstfsi.c
- [x] fixunstfti.c
- [ ] floatditf.c
- [ ] floatsitf.c
- [ ] floatunditf.c
- [ ] floatunsitf.c
- [x] floatditf.c
- [x] floatsitf.c
- [x] floattitf.c
- [x] floatunditf.c
- [x] floatunsitf.c
- [x] floatuntitf.c
- [x] multf3.c
- [ ] powitf2.c
- [ ] ppc/fixtfdi.c
Expand Down
18 changes: 2 additions & 16 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,10 +524,6 @@ mod c {
if (target_arch == "aarch64" || target_arch == "arm64ec") && consider_float_intrinsics {
sources.extend(&[
("__comparetf2", "comparetf2.c"),
("__floatditf", "floatditf.c"),
("__floatsitf", "floatsitf.c"),
("__floatunditf", "floatunditf.c"),
("__floatunsitf", "floatunsitf.c"),
("__divtf3", "divtf3.c"),
("__powitf2", "powitf2.c"),
("__fe_getround", "fp_mode.c"),
Expand All @@ -544,21 +540,11 @@ mod c {
}

if target_arch == "mips64" {
sources.extend(&[
("__netf2", "comparetf2.c"),
("__floatsitf", "floatsitf.c"),
("__floatunsitf", "floatunsitf.c"),
("__fe_getround", "fp_mode.c"),
]);
sources.extend(&[("__netf2", "comparetf2.c"), ("__fe_getround", "fp_mode.c")]);
}

if target_arch == "loongarch64" {
sources.extend(&[
("__netf2", "comparetf2.c"),
("__floatsitf", "floatsitf.c"),
("__floatunsitf", "floatunsitf.c"),
("__fe_getround", "fp_mode.c"),
]);
sources.extend(&[("__netf2", "comparetf2.c"), ("__fe_getround", "fp_mode.c")]);
}

// Remove the assembly implementations that won't compile for the target
Expand Down
62 changes: 56 additions & 6 deletions examples/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,14 +262,18 @@ mod intrinsics {

/* i32 operations */

// floatsisf
pub fn aeabi_i2f(x: i32) -> f32 {
x as f32
}

// floatsidf
pub fn aeabi_i2d(x: i32) -> f64 {
x as f64
}

// floatsisf
pub fn aeabi_i2f(x: i32) -> f32 {
x as f32
pub fn floatsitf(x: i32) -> f128 {
x as f128
}

pub fn aeabi_idiv(a: i32, b: i32) -> i32 {
Expand All @@ -292,6 +296,10 @@ mod intrinsics {
x as f64
}

pub fn floatditf(x: i64) -> f128 {
x as f128
}

pub fn mulodi4(a: i64, b: i64) -> i64 {
a * b
}
Expand All @@ -312,6 +320,18 @@ mod intrinsics {

/* i128 operations */

pub fn floattisf(x: i128) -> f32 {
x as f32
}

pub fn floattidf(x: i128) -> f64 {
x as f64
}

pub fn floattitf(x: i128) -> f128 {
x as f128
}

pub fn lshrti3(a: i128, b: usize) -> i128 {
a >> b
}
Expand All @@ -326,14 +346,18 @@ mod intrinsics {

/* u32 operations */

// floatunsisf
pub fn aeabi_ui2f(x: u32) -> f32 {
x as f32
}

// floatunsidf
pub fn aeabi_ui2d(x: u32) -> f64 {
x as f64
}

// floatunsisf
pub fn aeabi_ui2f(x: u32) -> f32 {
x as f32
pub fn floatunsitf(x: u32) -> f128 {
x as f128
}

pub fn aeabi_uidiv(a: u32, b: u32) -> u32 {
Expand All @@ -356,6 +380,10 @@ mod intrinsics {
x as f64
}

pub fn floatunditf(x: u64) -> f128 {
x as f128
}

// udivdi3
pub fn aeabi_uldivmod(a: u64, b: u64) -> u64 {
a * b
Expand All @@ -367,6 +395,18 @@ mod intrinsics {

/* u128 operations */

pub fn floatuntisf(x: u128) -> f32 {
x as f32
}

pub fn floatuntidf(x: u128) -> f64 {
x as f64
}

pub fn floatuntitf(x: u128) -> f128 {
x as f128
}

pub fn muloti4(a: u128, b: u128) -> Option<u128> {
a.checked_mul(b)
}
Expand Down Expand Up @@ -463,6 +503,16 @@ fn run() {
bb(fixunstfsi(bb(2.)));
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
bb(fixunstfti(bb(2.)));
bb(floatditf(bb(2)));
bb(floatsitf(bb(2)));
bb(floattidf(bb(2)));
bb(floattisf(bb(2)));
bb(floattitf(bb(2)));
bb(floatunditf(bb(2)));
bb(floatunsitf(bb(2)));
bb(floatuntidf(bb(2)));
bb(floatuntisf(bb(2)));
bb(floatuntitf(bb(2)));
bb(gttf(bb(2.), bb(2.)));
bb(lshrti3(bb(2), bb(2)));
bb(lttf(bb(2.), bb(2.)));
Expand Down
76 changes: 76 additions & 0 deletions src/float/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,23 @@ mod int_to_float {
repr::<f64>(e, m)
}

#[cfg(not(feature = "no-f16-f128"))]
pub fn u32_to_f128_bits(i: u32) -> u128 {
if i == 0 {
return 0;
}
let n = i.leading_zeros();

// High 64 significant bits, with bit 113 still in tact.
let m = (i as u64) << (f128::SIGNIFICAND_BITS - u32::BITS + 1 - 64 + n);
let e = (u32::BITS + f128::EXPONENT_BIAS - 2 - n) as u64;
// High 64 bits of f128 representation.
let h = (e << (f128::SIGNIFICAND_BITS - 64)) + m;

// Result was calculated as a u64 to avoid 128-bit operations (lower bits are always 0).
(h as u128) << 64
}

pub fn u64_to_f32_bits(i: u64) -> u32 {
let n = i.leading_zeros();
let i_m = i.wrapping_shl(n); // Mantissa, shifted so the first bit is nonzero
Expand All @@ -114,6 +131,17 @@ mod int_to_float {
repr::<f64>(e, m)
}

#[cfg(not(feature = "no-f16-f128"))]
pub fn u64_to_f128_bits(i: u64) -> u128 {
if i == 0 {
return 0;
}
let n = i.leading_zeros();
let m = m_f_gt_i::<_, f128>(i, n);
let e = exp::<u64, f128>(n);
repr::<f128>(e, m)
}

pub fn u128_to_f32_bits(i: u128) -> u32 {
let n = i.leading_zeros();
let i_m = i.wrapping_shl(n); // Mantissa, shifted so the first bit is nonzero
Expand Down Expand Up @@ -144,6 +172,18 @@ mod int_to_float {
let e = if i == 0 { 0 } else { exp::<u128, f64>(n) };
repr::<f64>(e, m)
}

#[cfg(not(feature = "no-f16-f128"))]
pub fn u128_to_f128_bits(i: u128) -> u128 {
if i == 0 {
return 0;
}
let n = i.leading_zeros();
let (m_base, adj) = m_f_eq_i::<u128, f128>(i, n);
let m = m_adj::<f128>(m_base, adj);
let e = exp::<u128, f128>(n);
repr::<f128>(e, m)
}
}

// Conversions from unsigned integers to floats.
Expand Down Expand Up @@ -177,6 +217,24 @@ intrinsics! {
pub extern "C" fn __floatuntidf(i: u128) -> f64 {
f64::from_bits(int_to_float::u128_to_f64_bits(i))
}

#[ppc_alias = __floatunsikf]
#[cfg(not(feature = "no-f16-f128"))]
pub extern "C" fn __floatunsitf(i: u32) -> f128 {
f128::from_bits(int_to_float::u32_to_f128_bits(i))
}

#[ppc_alias = __floatundikf]
#[cfg(not(feature = "no-f16-f128"))]
pub extern "C" fn __floatunditf(i: u64) -> f128 {
f128::from_bits(int_to_float::u64_to_f128_bits(i))
}

#[ppc_alias = __floatuntikf]
#[cfg(not(feature = "no-f16-f128"))]
pub extern "C" fn __floatuntitf(i: u128) -> f128 {
f128::from_bits(int_to_float::u128_to_f128_bits(i))
}
}

// Conversions from signed integers to floats.
Expand Down Expand Up @@ -210,6 +268,24 @@ intrinsics! {
pub extern "C" fn __floattidf(i: i128) -> f64 {
int_to_float::signed(i, int_to_float::u128_to_f64_bits)
}

#[ppc_alias = __floatsikf]
#[cfg(not(feature = "no-f16-f128"))]
pub extern "C" fn __floatsitf(i: i32) -> f128 {
int_to_float::signed(i, int_to_float::u32_to_f128_bits)
}

#[ppc_alias = __floatdikf]
#[cfg(not(feature = "no-f16-f128"))]
pub extern "C" fn __floatditf(i: i64) -> f128 {
int_to_float::signed(i, int_to_float::u64_to_f128_bits)
}

#[ppc_alias = __floattikf]
#[cfg(not(feature = "no-f16-f128"))]
pub extern "C" fn __floattitf(i: i128) -> f128 {
int_to_float::signed(i, int_to_float::u128_to_f128_bits)
}
}

/// Generic float to unsigned int conversions.
Expand Down
Loading

0 comments on commit 3d2857a

Please sign in to comment.