Bläddra i källkod

Add basic FPU initialization

mini-ninja-64 1 år sedan
förälder
incheckning
02fd8a0f57
1 ändrade filer med 25 tillägg och 1 borttagningar
  1. 25 1
      riscv-rt/src/lib.rs

+ 25 - 1
riscv-rt/src/lib.rs

@@ -377,6 +377,12 @@ use riscv::register::{mcause as xcause, mtvec as xtvec, mtvec::TrapMode as xTrap
 #[cfg(all(not(feature = "single-hart"), not(feature = "s-mode")))]
 use riscv::register::mhartid;
 
+#[cfg(all(feature = "s-mode", any(riscvf, riscvd)))]
+use riscv::register::sstatus as xstatus;
+
+#[cfg(all(not(feature = "s-mode"), any(riscvf, riscvd)))]
+use riscv::register::mstatus as xstatus;
+
 pub use riscv_rt_macros::{entry, pre_init};
 
 #[export_name = "error: riscv-rt appears more than once in the dependency graph"]
@@ -512,7 +518,25 @@ pub unsafe extern "C" fn start_rust(a0: usize, a1: usize, a2: usize) -> ! {
         compiler_fence(Ordering::SeqCst);
     }
 
-    // TODO: Enable FPU when available
+    #[cfg(any(riscvf, riscvd))]
+    {
+        xstatus::set_fs(xstatus::FS::Initial); // Enable fpu in xstatus
+        core::arch::asm!("fscsr x0"); // Zero out fcsr register csrrw x0, fcsr, x0
+
+        // Zero out floating point registers
+        for i in 0..32 { 
+            if cfg!(all(riscv32, riscvd)) {
+                // rv32 targets with double precision floating point can use fmvp.d.x 
+                // to combine 2 32 bit registers to fill the 64 bit floating point 
+                // register
+                core::arch::asm!("fmvp.d.x f{}, x0, x0", i);
+            } else if cfg!(riscvd) {
+                core::arch::asm!("fmv.d.x f{}, x0", i);
+            } else {
+                core::arch::asm!("fmv.w.x f{}, x0", i);
+            }
+        }
+    }
 
     _setup_interrupts();