[xcc] minor performance tweaks
[riscv-isa-sim.git] / riscv / decode.h
index 63e71cd98193354f735179620861c5b2c3705ded..2078e58ae2cc028e1b5959a9f04ca0ce2abf4a62 100644 (file)
@@ -42,8 +42,10 @@ const int JUMP_ALIGN_BITS = 1;
 #define SR_UX    0x0000000000000040ULL
 #define SR_SX    0x0000000000000080ULL
 #define SR_IM    0x000000000000FF00ULL
-#define SR_ZERO  ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_UX|SR_SX|SR_IM)
+#define SR_VM    0x0000000000010000ULL
+#define SR_ZERO  ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_UX|SR_SX|SR_IM|SR_VM)
 #define SR_IM_SHIFT 8
+#define IPI_IRQ 5
 #define TIMER_IRQ 7
 
 #define CAUSE_EXCCODE 0x000000FF
@@ -141,29 +143,32 @@ union insn_t
   uint32_t bits;
 };
 
-#if 0
 #include <stdio.h>
-class trace_writeback
+class do_writeback
 {
 public:
-  trace_writeback(reg_t* _rf, int _rd) : rf(_rf), rd(_rd) {}
+  do_writeback(reg_t* _rf, int _rd) : rf(_rf), rd(_rd) {}
 
-  reg_t operator = (reg_t rhs)
+  const do_writeback& operator = (reg_t rhs)
   {
+#if 0
     printf("R[%x] <= %llx\n",rd,(long long)rhs);
+#endif
     rf[rd] = rhs;
-    return rhs;
+    rf[0] = 0;
+    return *this;
   }
 
+  operator reg_t() { return rf[rd]; }
+
 private:
   reg_t* rf;
   int rd;
 };
 
-#define do_writeback(rf,rd) trace_writeback(rf,rd)
-#else
-#define do_writeback(rf,rd) rf[rd]
-#endif
+#define throw_illegal_instruction \
+  ({ if (utmode) throw trap_vector_illegal_instruction; \
+     else throw trap_illegal_instruction; })
 
 // helpful macros, etc
 #define RS1 XPR[insn.rtype.rs1]
@@ -184,31 +189,47 @@ private:
 #define JUMP_TARGET (pc + (TARGET << JUMP_ALIGN_BITS))
 #define RM ({ int rm = insn.ftype.rm; \
               if(rm == 7) rm = (fsr & FSR_RD) >> FSR_RD_SHIFT; \
-              if(rm > 4) throw trap_illegal_instruction; \
+              if(rm > 4) throw_illegal_instruction; \
               rm; })
 
-#define require_supervisor if(!(sr & SR_S)) throw trap_privileged_instruction
+#define require_supervisor if(unlikely(!(sr & SR_S))) throw trap_privileged_instruction
 #define xpr64 (xprlen == 64)
-#define require_xpr64 if(!xpr64) throw trap_illegal_instruction
-#define require_xpr32 if(xpr64) throw trap_illegal_instruction
-#define require_fp if(!(sr & SR_EF)) throw trap_fp_disabled
-#define require_vector if(!(sr & SR_EV)) throw trap_vector_disabled
+#define require_xpr64 if(unlikely(!xpr64)) throw_illegal_instruction
+#define require_xpr32 if(unlikely(xpr64)) throw_illegal_instruction
+#define require_fp if(unlikely(!(sr & SR_EF))) throw trap_fp_disabled
+#define require_vector \
+  ({ if(!(sr & SR_EV)) throw trap_vector_disabled; \
+    else if (!utmode && (vecbanks_count < 3)) throw trap_vector_bank; \
+  })
 #define cmp_trunc(reg) (reg_t(reg) << (64-xprlen))
 #define set_fp_exceptions ({ set_fsr(fsr | \
                                (softfloat_exceptionFlags << FSR_AEXC_SHIFT)); \
                              softfloat_exceptionFlags = 0; })
 
-#define require_rvc if(!(sr & SR_EC)) throw trap_illegal_instruction
-#define insn_length(x) (((x).bits & 0x3) < 0x3 ? 2 : 4)
-
 #define sext32(x) ((sreg_t)(int32_t)(x))
 #define zext32(x) ((reg_t)(uint32_t)(x))
 #define sext_xprlen(x) ((sreg_t(x) << (64-xprlen)) >> (64-xprlen))
 #define zext_xprlen(x) ((reg_t(x) << (64-xprlen)) >> (64-xprlen))
 
+#ifndef RISCV_ENABLE_RVC
+# define set_pc(x) \
+  do { if((x) & (sizeof(insn_t)-1)) \
+       { badvaddr = (x); throw trap_instruction_address_misaligned; } \
+       npc = (x); \
+     } while(0)
+#else
+# define set_pc(x) \
+  do { if((x) & ((sr & SR_EC) ? 1 : 3)) \
+       { badvaddr = (x); throw trap_instruction_address_misaligned; } \
+       npc = (x); \
+     } while(0)
+#endif
+
 // RVC stuff
 
 #define INSN_IS_RVC(x) (((x) & 0x3) < 0x3)
+#define insn_length(x) (INSN_IS_RVC(x) ? 2 : 4)
+#define require_rvc if(!(sr & SR_EC)) throw_illegal_instruction
 
 #define CRD_REGNUM ((insn.bits >> 5) & 0x1f)
 #define CRD do_writeback(XPR, CRD_REGNUM)