[pk, sim] added FPU emulation support to proxy kernel
[riscv-isa-sim.git] / riscv / processor.cc
index 5751c70006e2f2dc02d62857ea4bdbf12b14caff..a889f75ccc23f64cf1d1a5a29016ad5a31b011ce 100644 (file)
@@ -1,11 +1,13 @@
+#include "processor.h"
 #include <bfd.h>
 #include <dis-asm.h>
+#include <cmath>
 #include <cstdlib>
 #include <iostream>
-#include "processor.h"
 #include "common.h"
 #include "config.h"
 #include "sim.h"
+#include "softfloat.h"
 
 processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz)
   : sim(_sim), mmu(_mem,_memsz)
@@ -13,10 +15,20 @@ processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz)
   memset(R,0,sizeof(R));
   memset(FR,0,sizeof(FR));
   pc = 0;
-  ebase = 0;
+  evec = 0;
   epc = 0;
   badvaddr = 0;
-  set_sr(SR_S);
+  cause = 0;
+  tid = 0;
+  pcr_k0 = 0;
+  pcr_k1 = 0;
+  tohost = 0;
+  fromhost = 0;
+  count = 0;
+  compare = 0;
+  interrupts_pending = 0;
+  set_sr(SR_S | (support_64bit ? SR_SX : 0));
+  set_fsr(0);
 
   memset(counters,0,sizeof(counters));
 
@@ -37,12 +49,18 @@ void processor_t::init(uint32_t _id)
 void processor_t::set_sr(uint32_t val)
 {
   sr = val & ~SR_ZERO;
-  if(support_64bit)
-    sr |= SR_KX;
-  else
-    sr &= ~(SR_KX | SR_UX);
+  if(!support_64bit)
+    sr &= ~(SR_SX | SR_UX);
+  if(!support_fp)
+    sr &= ~SR_EF;
+
+  gprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32;
+}
 
-  gprlen = ((sr & SR_S) ? (sr & SR_KX) : (sr & SR_UX)) ? 64 : 32;
+void processor_t::set_fsr(uint32_t val)
+{
+  fsr = val & ~FSR_ZERO;
+  softfloat_roundingMode = (fsr & FSR_RD) >> FSR_RD_SHIFT;
 }
 
 void processor_t::step(size_t n, bool noisy)
@@ -52,6 +70,14 @@ void processor_t::step(size_t n, bool noisy)
   {
     for( ; i < n; i++)
     {
+      uint32_t interrupts = interrupts_pending & ((sr & SR_IM) >> SR_IM_SHIFT);
+      if((sr & SR_ET) && interrupts)
+      {
+        for(int i = 0; interrupts; i++, interrupts >>= 1)
+          if(interrupts & 1)
+            throw trap_t(16+i);
+      }
+
       insn_t insn = mmu.load_insn(pc);
   
       reg_t npc = pc+sizeof(insn);
@@ -64,26 +90,31 @@ void processor_t::step(size_t n, bool noisy)
       pc = npc;
       R[0] = 0;
 
-      counters[0]++;
+      if(count++ == compare)
+        interrupts_pending |= 1 << TIMER_IRQ;
     }
     return;
   }
   catch(trap_t t)
   {
     i++;
-    take_trap(t);
+    take_trap(t,noisy);
   }
 }
 
-void processor_t::take_trap(trap_t t)
+void processor_t::take_trap(trap_t t, bool noisy)
 {
   demand(t < NUM_TRAPS, "internal error: bad trap number %d", int(t));
   demand(sr & SR_ET, "error mode on core %d!\ntrap %s, pc 0x%016llx",
          id, trap_name(t), (unsigned long long)pc);
+  if(noisy)
+    printf("core %3d: trap %s, pc 0x%016llx\n",
+           id, trap_name(t), (unsigned long long)pc);
 
   set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
+  cause = t;
   epc = pc;
-  pc = ebase + t*128;
+  pc = evec;
   badvaddr = mmu.get_badvaddr();
 }