use {core::arch::asm, hbbytecode::RoundingMode}; macro_rules! roundm_op_litmode_internal { ($ins:literal, $in:expr, $out:expr => $outy:ident, $mode:literal $(,)?) => { asm!( concat!($ins, " {}, {}, ", $mode), out($outy) $out, in(freg) $in, ) }; } macro_rules! gen_roundm_op_litmode { [$($ty:ident => $reg:ident),* $(,)?] => { macro_rules! roundm_op_litmode { $( ($ins:literal, $in:expr, $out:expr => $ty, $mode:literal) => { roundm_op_litmode_internal!($ins, $in, $out => $reg, $mode) }; )* } }; } gen_roundm_op_litmode![ f32 => freg, f64 => freg, i64 => reg, ]; macro_rules! fnsdef { {$( $(#[$attr:meta])* $vis:vis fn $name:ident($from:ident -> $to:ident): $ins:literal; )*} => {$( $(#[$attr])* $vis fn $name(val: $from, mode: RoundingMode) -> $to { let result: $to; unsafe { match mode { RoundingMode::NearestEven => roundm_op_litmode!($ins, val, result => $to, "rne"), RoundingMode::Truncate => roundm_op_litmode!($ins, val, result => $to, "rtz"), RoundingMode::Up => roundm_op_litmode!($ins, val, result => $to, "rup"), RoundingMode::Down => roundm_op_litmode!($ins, val, result => $to, "rdn"), } } result } )*}; } fnsdef! { /// Convert [`f64`] to [`f32`] with chosen rounding mode pub fn conv64to32(f64 -> f32): "fcvt.s.d"; /// Convert [`f32`] to [`i64`] with chosen rounding mode pub fn f32toint(f32 -> i64): "fcvt.l.s"; /// Convert [`f64`] to [`i64`] with chosen rounding mode pub fn f64toint(f64 -> i64): "fcvt.l.d"; }