Implement Hauser misa.C misalignment proposal (#187)
authorAndrew Waterman <aswaterman@gmail.com>
Thu, 22 Mar 2018 00:19:16 +0000 (17:19 -0700)
committerGitHub <noreply@github.com>
Thu, 22 Mar 2018 00:19:16 +0000 (17:19 -0700)
See https://github.com/riscv/riscv-isa-manual/commit/0472bcdd166f45712492829a250e228bb45fa5e7

- Reads of xEPC[1] are masked when RVC is disabled
- Writes to MISA are suppressed if they would cause a misaligned fetch
- Misaligned PCs no longer need to be checked upon fetch

riscv/decode.h
riscv/execute.cc
riscv/processor.cc
riscv/processor.h

index 596a2ad9bfea1bfe24b38ed1b733e5a8c91bb688..8fc8ada1b269cad40ecf04203a5fac245aec0584 100644 (file)
@@ -206,7 +206,7 @@ private:
      } while(0)
 
 #define set_pc_and_serialize(x) \
      } while(0)
 
 #define set_pc_and_serialize(x) \
-  do { reg_t __npc = (x); \
+  do { reg_t __npc = (x) & p->pc_alignment_mask(); \
        npc = PC_SERIALIZE_AFTER; \
        STATE.pc = __npc; \
      } while(0)
        npc = PC_SERIALIZE_AFTER; \
        STATE.pc = __npc; \
      } while(0)
index b302daac78b8f29b83df6945314c9f665ecc588e..9d1fb87ad2da6a8cccca13eb3f01e5ff61147ac4 100644 (file)
@@ -113,7 +113,6 @@ void processor_t::step(size_t n)
          default: abort(); \
        } \
        pc = state.pc; \
          default: abort(); \
        } \
        pc = state.pc; \
-       check_pc_alignment(pc); \
        break; \
      } else { \
        state.pc = pc; \
        break; \
      } else { \
        state.pc = pc; \
index 7a5df901b315c7a5b1642c45415520cdcb659ef3..548c649cd2fafd76fe92bb8929544cffac7d8433 100644 (file)
@@ -450,6 +450,10 @@ void processor_t::set_csr(int which, reg_t val)
     case CSR_MCAUSE: state.mcause = val; break;
     case CSR_MTVAL: state.mtval = val; break;
     case CSR_MISA: {
     case CSR_MCAUSE: state.mcause = val; break;
     case CSR_MTVAL: state.mtval = val; break;
     case CSR_MISA: {
+      // the write is ignored if increasing IALIGN would misalign the PC
+      if (!(val & (1L << ('C' - 'A'))) && (state.pc & 2))
+        break;
+
       if (!(val & (1L << ('F' - 'A'))))
         val &= ~(1L << ('D' - 'A'));
 
       if (!(val & (1L << ('F' - 'A'))))
         val &= ~(1L << ('D' - 'A'));
 
@@ -592,7 +596,7 @@ reg_t processor_t::get_csr(int which)
     }
     case CSR_SIP: return state.mip & state.mideleg;
     case CSR_SIE: return state.mie & state.mideleg;
     }
     case CSR_SIP: return state.mip & state.mideleg;
     case CSR_SIE: return state.mie & state.mideleg;
-    case CSR_SEPC: return state.sepc;
+    case CSR_SEPC: return state.sepc & pc_alignment_mask();
     case CSR_STVAL: return state.stval;
     case CSR_STVEC: return state.stvec;
     case CSR_SCAUSE:
     case CSR_STVAL: return state.stval;
     case CSR_STVEC: return state.stvec;
     case CSR_SCAUSE:
@@ -607,7 +611,7 @@ reg_t processor_t::get_csr(int which)
     case CSR_MSTATUS: return state.mstatus;
     case CSR_MIP: return state.mip;
     case CSR_MIE: return state.mie;
     case CSR_MSTATUS: return state.mstatus;
     case CSR_MIP: return state.mip;
     case CSR_MIE: return state.mie;
-    case CSR_MEPC: return state.mepc;
+    case CSR_MEPC: return state.mepc & pc_alignment_mask();
     case CSR_MSCRATCH: return state.mscratch;
     case CSR_MCAUSE: return state.mcause;
     case CSR_MTVAL: return state.mtval;
     case CSR_MSCRATCH: return state.mscratch;
     case CSR_MCAUSE: return state.mcause;
     case CSR_MTVAL: return state.mtval;
@@ -668,7 +672,7 @@ reg_t processor_t::get_csr(int which)
         return v;
       }
     case CSR_DPC:
         return v;
       }
     case CSR_DPC:
-      return state.dpc;
+      return state.dpc & pc_alignment_mask();
     case CSR_DSCRATCH:
       return state.dscratch;
   }
     case CSR_DSCRATCH:
       return state.dscratch;
   }
index ace86f963959145e3e8a7227f4fa2e91f0395e71..3e67215b46df9e29493b050c2d59e5cd586507cf 100644 (file)
@@ -188,8 +188,11 @@ public:
     if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
     return ext >= 'A' && ext <= 'Z' && ((state.misa >> (ext - 'A')) & 1);
   }
     if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
     return ext >= 'A' && ext <= 'Z' && ((state.misa >> (ext - 'A')) & 1);
   }
+  reg_t pc_alignment_mask() {
+    return ~(reg_t)(supports_extension('C') ? 0 : 2);
+  }
   void check_pc_alignment(reg_t pc) {
   void check_pc_alignment(reg_t pc) {
-    if (unlikely(pc & 2) && !supports_extension('C'))
+    if (unlikely(pc & ~pc_alignment_mask()))
       throw trap_instruction_address_misaligned(pc);
   }
   reg_t legalize_privilege(reg_t);
       throw trap_instruction_address_misaligned(pc);
   }
   reg_t legalize_privilege(reg_t);