2023-10-18 05:14:24 -05:00
|
|
|
use {core::arch::asm, hbbytecode::RoundingMode};
|
|
|
|
|
|
|
|
macro_rules! fnsdef {
|
|
|
|
{$(
|
|
|
|
$(#[$attr:meta])*
|
|
|
|
$vis:vis fn $name:ident[$inreg:ident -> $outreg:ident]($from:ident -> $to:ident): $ins:literal;
|
|
|
|
)*} => {$(
|
|
|
|
$(#[$attr])*
|
|
|
|
$vis fn $name(val: $from, mode: RoundingMode) -> $to {
|
|
|
|
let result: $to;
|
|
|
|
unsafe {
|
2024-02-04 15:36:52 -06:00
|
|
|
let fpcr: u64;
|
2024-09-10 13:50:36 -05:00
|
|
|
|
2024-02-04 15:36:52 -06:00
|
|
|
unsafe { asm!("mrs {}, fpcr", out(reg) fpcr) };
|
|
|
|
|
|
|
|
let fpcr_new = fpcr & !(0b11 << 22)
|
|
|
|
| (match mode {
|
|
|
|
RoundingMode::NearestEven => 0b00,
|
|
|
|
RoundingMode::Truncate => 0b11,
|
|
|
|
RoundingMode::Up => 0b01,
|
|
|
|
RoundingMode::Down => 0b10,
|
|
|
|
}) << 22;
|
|
|
|
|
|
|
|
unsafe { asm!("msr fpcr, {}", in(reg) fpcr_new) };
|
2023-10-18 05:14:24 -05:00
|
|
|
asm!(
|
|
|
|
$ins,
|
|
|
|
out($outreg) result,
|
|
|
|
in($inreg) val,
|
|
|
|
);
|
2024-02-04 15:36:52 -06:00
|
|
|
unsafe { asm!("msr fpcr, {}", in(reg) fpcr) };
|
2023-10-18 05:14:24 -05:00
|
|
|
}
|
|
|
|
result
|
|
|
|
}
|
|
|
|
)*};
|
|
|
|
}
|
|
|
|
|
|
|
|
fnsdef! {
|
|
|
|
/// Convert [`f64`] to [`f32`] with chosen rounding mode
|
|
|
|
pub fn conv64to32[vreg -> vreg](f64 -> f32): "fcvt {:s}, {:d}";
|
|
|
|
|
|
|
|
/// Convert [`f32`] to [`i64`] with chosen rounding mode
|
|
|
|
pub fn f32toint[vreg -> reg](f32 -> i64): "fcvtzs {}, {:s}";
|
|
|
|
|
|
|
|
/// Convert [`f64`] to [`i64`] with chosen rounding mode
|
|
|
|
pub fn f64toint[vreg -> reg](f64 -> i64): "fcvtzs {}, {:d}";
|
|
|
|
}
|