diff --git a/as.sh b/as.sh index b299cbb..41d5f52 100755 --- a/as.sh +++ b/as.sh @@ -1,4 +1,4 @@ #!/bin/sh -riscv64-unknown-elf-as $1 -march=rv64ima -o program.o +riscv64-unknown-elf-as $1 -march=rv64g -o program.o riscv64-unknown-elf-objcopy program.o -O binary program.bin diff --git a/emu/src/cpu/float.rs b/emu/src/cpu/float.rs index 32c3746..2ecc1f1 100644 --- a/emu/src/cpu/float.rs +++ b/emu/src/cpu/float.rs @@ -45,7 +45,12 @@ impl<'a> Cpu<'a> { } } + #[inline(always)] pub(crate) fn check_fpu(&mut self) { + core::hint::black_box(Self::_check_fpu)(self); + } + + fn _check_fpu(&mut self) { unsafe { let f = (fenv::fetestexcept(fenv::FE_INVALID as _) != 0) as u64 * NV | (fenv::fetestexcept(fenv::FE_DIVBYZERO as _) != 0) as u64 * DZ @@ -53,17 +58,18 @@ impl<'a> Cpu<'a> { | (fenv::fetestexcept(fenv::FE_OVERFLOW as _) != 0) as u64 * OF | (fenv::fetestexcept(fenv::FE_UNDERFLOW as _) != 0) as u64 * UF; self.float_set_flags(f); + println!("{f:02x}"); } } pub(crate) fn float_do_op T>(&mut self, f: F) -> T { - unsafe { fenv::feclearexcept(fenv::FE_ALL_EXCEPT as _); } + core::hint::black_box(|| unsafe { fenv::feclearexcept(fenv::FE_ALL_EXCEPT as _); })(); let v = f(self); v } pub(crate) fn float_do_op_f32 f32>(&mut self, f: F) -> f32 { - unsafe { fenv::feclearexcept(fenv::FE_ALL_EXCEPT as _); } + core::hint::black_box(|| unsafe { fenv::feclearexcept(fenv::FE_ALL_EXCEPT as _); })(); let v = f(); self.check_fpu(); if v.is_nan() { @@ -74,7 +80,7 @@ impl<'a> Cpu<'a> { } pub(crate) fn float_do_op_f64 f64>(&mut self, f: F) -> f64 { - unsafe { fenv::feclearexcept(fenv::FE_ALL_EXCEPT as _); } + core::hint::black_box(|| unsafe { fenv::feclearexcept(fenv::FE_ALL_EXCEPT as _); })(); let v = f(); self.check_fpu(); if v.is_nan() { @@ -117,6 +123,9 @@ macro_rules! cast { ($s: tt $v: tt $f: tt $t: tt s) => {{ let v = if $v.is_nan() { $t::MAX } else { $v as $t }; $s.check_fpu(); + if v as $f != $v.trunc() { + $s.float_set_flags($crate::cpu::float::NV); + } v }}; ($s: tt $v: tt $f: tt $t: tt u) => {{