From c6cd40461e6f8f8e47be6dd702b2589eeb087531 Mon Sep 17 00:00:00 2001
From: Roberto Hexsel <roberto@inf.ufpr.br>
Date: Tue, 15 Mar 2016 18:36:40 -0300
Subject: [PATCH] interrupt on a J/BR delay slot, with JR stalled, loaded the
 wrong EPC  (thnx Vanessa)

---
 cMIPS/bin/assemble.sh   |  4 +++-
 cMIPS/bin/compile.sh    |  3 ++-
 cMIPS/include/cMIPS.ld  |  2 +-
 cMIPS/include/cMIPSio.c |  4 ++--
 cMIPS/vhdl/core.vhd     | 29 ++++++++++++++++++++---------
 5 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/cMIPS/bin/assemble.sh b/cMIPS/bin/assemble.sh
index df07423..3fb87fa 100755
--- a/cMIPS/bin/assemble.sh
+++ b/cMIPS/bin/assemble.sh
@@ -117,7 +117,8 @@ dat=data.bin
   mips-objcopy -S -j .data -j .rodata -O binary $elf $dat &&\
   chmod a-x $bin $dat &&\
   if [ $verbose = true ] ; then
-    mips-objdump -z -D -EL -M reg-names=numeric --show-raw-insn \
+    mips-objdump -z -D -EL  -M reg-names=numeric -M cp0-names=mips2r2 \
+        --show-raw-insn \
         --section .text --section .data --section .rodata --section .bss  $elf
   fi &&\
   if [ $miffile = true ] ; then
@@ -125,5 +126,6 @@ dat=data.bin
 
   fi
 
+# -M reg-names=mips2r2 -M cp0-names=mips2r2 \
 #        --section .reginfo
 
diff --git a/cMIPS/bin/compile.sh b/cMIPS/bin/compile.sh
index b02825f..afe7779 100755
--- a/cMIPS/bin/compile.sh
+++ b/cMIPS/bin/compile.sh
@@ -150,7 +150,8 @@ mips-objcopy -S -j .text -O binary $elf $bin && \
      -O binary $elf $dat || exit 1
 
 if [ $? == 0  -a  $verbose = true ]; then
-  mips-objdump -z -D -EL -M reg-names=numeric --show-raw-insn \
+  mips-objdump -z -D -EL -M reg-names=mips2r2 -M cp0-names=mips2r2 \
+      --show-raw-insn \
       --section .text   --section .data \
       --section .rodata --section .sdata --section .sbss \
       --section .bss $elf
diff --git a/cMIPS/include/cMIPS.ld b/cMIPS/include/cMIPS.ld
index 9a67592..2855338 100644
--- a/cMIPS/include/cMIPS.ld
+++ b/cMIPS/include/cMIPS.ld
@@ -5,7 +5,7 @@ MEMORY
 {
         rom (rx)  : ORIGIN = 0x00000000, /* x_INST_BASE_ADDR */
                     LENGTH = 0x00004000, /* x_INST_MEM_SZ */
-        ram (!rx) : ORIGIN = 0x00020000, /* x_DATA_BASE_ADDR */
+        ram (!rx) : ORIGIN = 0x00010000, /* x_DATA_BASE_ADDR */
                     LENGTH = 0x00008000, /* x_DATA_MEM_SZ */
         io (!rx)  : ORIGIN = 0x0f000000, /* not used, do not remove       */
                     LENGTH = 0x00020000  /* edMemory.sh needs thess lines */
diff --git a/cMIPS/include/cMIPSio.c b/cMIPS/include/cMIPSio.c
index 8c8103e..b00322f 100644
--- a/cMIPS/include/cMIPSio.c
+++ b/cMIPS/include/cMIPSio.c
@@ -98,7 +98,7 @@ void readStats(sStats *s) {
 
 
 //=======================================================================
-// memcpy -- need this to fool GCC into believing this is libc
+// memcpy -- need this to fool GCC into believing we have libc
 //=======================================================================
 char *memcpy(char *dst, const char *src, int n) {
   int cnt;
@@ -133,7 +133,7 @@ char *memcpy(char *dst, const char *src, int n) {
 
 
 //=======================================================================
-// memset -- need this to fool GCC into believing this is libc
+// memset -- need this to fool GCC into believing we have libc
 //=======================================================================
 char *memset(char *dst, const int val, int len) {
   unsigned char *ptr = (unsigned char*)dst;
diff --git a/cMIPS/vhdl/core.vhd b/cMIPS/vhdl/core.vhd
index ffbc964..c866635 100644
--- a/cMIPS/vhdl/core.vhd
+++ b/cMIPS/vhdl/core.vhd
@@ -132,6 +132,7 @@ architecture rtl of core is
          WB_cop0_val:   out std_logic_vector);
   end component reg_excp_MM_WB;
 
+  signal nullify_MM_pre, nullify_MM_int :std_logic;
   signal annul_1, annul_2, annul_twice : std_logic;
   signal interrupt, exception_stall : std_logic;
   signal exception_taken, interrupt_taken : std_logic;
@@ -1596,10 +1597,15 @@ begin
     MM_B_data <= i_data;
   end process MM_FWD_LWLR;
 
+  -- if interrupt is in J/BR delaySlot, and JR was stalled, kill instr in MM
+  U_NULLIFY_THRICE:
+    FFD port map (clk, rst, '1', nullify_MM_pre, nullify_MM_int);
   
   MM_wreg_cond <= '1' when ( (ram_stall = '1')
                              or MM_addrError -- abort regWrite if excptn in MEM
-                             or (MM_move = '1' and MM_alu_move_ok = '0') )
+                             or (MM_move = '1' and MM_alu_move_ok = '0')
+                             or (nullify_MM_int = '1')
+                           )
                   else MM_wreg;
 
 
@@ -1863,6 +1869,7 @@ begin
     interrupt_taken <= '0';
     ExcCode         <= cop0code_NULL;
     is_delayslot    <= '0';
+    nullify_MM_pre  <= '0';
     
     newSTATUS             := STATUS;    -- preserve as needed
     newSTATUS(STATUS_BEV) := '0';  -- interrupts at offset 0x200
@@ -2172,11 +2179,13 @@ begin
           i_epc_update := '0';
           i_nullify    := TRUE;         -- nullify instructions in IF,RF,EX
           if MM_is_delayslot = '1' then -- instr is in delay slot
-            i_epc_source := EPC_src_MM; -- re-execute branch/jump
-            is_delayslot <= MM_is_delayslot;
+            i_epc_source   := EPC_src_MM; -- re-execute branch/jump
+            is_delayslot   <= MM_is_delayslot;
+            nullify_MM_pre <= '1';      -- if stalled, kill instrn in MM
           else
-            i_epc_source := EPC_src_EX;
-            is_delayslot <= EX_is_delayslot;
+            i_epc_source   := EPC_src_EX;
+            is_delayslot   <= EX_is_delayslot;
+            nullify_MM_pre <= '0';
           end if;
         end if;
 
@@ -2195,11 +2204,13 @@ begin
         i_epc_update := '0';
         i_nullify    := TRUE;         -- nullify instructions in IF,RF,EX
         if MM_is_delayslot = '1' then -- instr is in delay slot
-          i_epc_source := EPC_src_MM; -- re-execute branch/jump
-          is_delayslot <= MM_is_delayslot;
+          i_epc_source   := EPC_src_MM; -- re-execute branch/jump
+          is_delayslot   <= MM_is_delayslot;
+          nullify_MM_pre <= '1';      -- if stalled, kill instrn in MM
         else
-          i_epc_source := EPC_src_EX;
-          is_delayslot <= EX_is_delayslot;
+          i_epc_source   := EPC_src_EX;
+          is_delayslot   <= EX_is_delayslot;
+          nullify_MM_pre <= '0';
         end if;
         
       when others => null;
-- 
GitLab