target-mips: add ERETNC instruction and Config5.LLB bit
authorLeon Alrae <leon.alrae@imgtec.com>
Thu, 4 Jun 2015 16:00:31 +0000 (17:00 +0100)
committerLeon Alrae <leon.alrae@imgtec.com>
Thu, 11 Jun 2015 09:13:29 +0000 (10:13 +0100)
ERETNC is identical to ERET except that an ERETNC will not clear the LLbit
that is set by execution of an LL instruction, and thus when placed between
an LL and SC sequence, will never cause the SC to fail.

Presence of ERETNC is denoted by the Config5.LLB.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
disas/mips.c
target-mips/cpu.h
target-mips/helper.h
target-mips/op_helper.c
target-mips/translate.c
target-mips/translate_init.c

index 1afe0c55110a179245e88a430525797e10b18d4d..832468c0a706ce5738b429a8a8adf510e697f7d3 100644 (file)
@@ -2407,6 +2407,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"emt",     "",                0x41600be1, 0xffffffff, TRAP,                   0,              MT32    },
 {"emt",     "t",       0x41600be1, 0xffe0ffff, TRAP|WR_t,              0,              MT32    },
 {"eret",    "",         0x42000018, 0xffffffff, 0,                     0,              I3|I32  },
+{"eretnc",  "",         0x42000058, 0xffffffff, 0,                    0, I33},
 {"evpe",    "",                0x41600021, 0xffffffff, TRAP,                   0,              MT32    },
 {"evpe",    "t",       0x41600021, 0xffe0ffff, TRAP|WR_t,              0,              MT32    },
 {"ext",     "t,r,+A,+C", 0x7c000000, 0xfc00003f, WR_t|RD_s,                    0,              I33     },
index 03eb888361bf1d5f5e888d9d1e845bf51d52b6f9..2c68782763e704c99a0529587ab6677f9c1a85a6 100644 (file)
@@ -466,6 +466,7 @@ struct CPUMIPSState {
 #define CP0C5_UFE        9
 #define CP0C5_FRE        8
 #define CP0C5_SBRI       6
+#define CP0C5_LLB        4
 #define CP0C5_UFR        2
 #define CP0C5_NFExists   0
     int32_t CP0_Config6;
index bdd5ba5e929c92a9a3856a02c768372d0f4776b2..8df98c71b85e8a1e7366b42e2b224e50aec621bb 100644 (file)
@@ -348,6 +348,7 @@ DEF_HELPER_1(tlbinvf, void, env)
 DEF_HELPER_1(di, tl, env)
 DEF_HELPER_1(ei, tl, env)
 DEF_HELPER_1(eret, void, env)
+DEF_HELPER_1(eretnc, void, env)
 DEF_HELPER_1(deret, void, env)
 #endif /* !CONFIG_USER_ONLY */
 DEF_HELPER_1(rdhwr_cpunum, tl, env)
index 2fe862a4cf0f556f156a97583239e16c48bf4603..b412f94f82a378bf2e4d24745782d756b16f987c 100644 (file)
@@ -2099,7 +2099,7 @@ static void set_pc(CPUMIPSState *env, target_ulong error_pc)
     }
 }
 
-void helper_eret(CPUMIPSState *env)
+static inline void exception_return(CPUMIPSState *env)
 {
     debug_pre_eret(env);
     if (env->CP0_Status & (1 << CP0St_ERL)) {
@@ -2111,9 +2111,19 @@ void helper_eret(CPUMIPSState *env)
     }
     compute_hflags(env);
     debug_post_eret(env);
+}
+
+void helper_eret(CPUMIPSState *env)
+{
+    exception_return(env);
     env->lladdr = 1;
 }
 
+void helper_eretnc(CPUMIPSState *env)
+{
+    exception_return(env);
+}
+
 void helper_deret(CPUMIPSState *env)
 {
     debug_pre_eret(env);
index fe6bc16b186d53f4b144f74c7be8d89f3067ceda..f6ae0d3aec1f2430d87ca7e539aeec9c7a8fd484 100644 (file)
@@ -7917,16 +7917,26 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
             goto die;
         gen_helper_tlbr(cpu_env);
         break;
-    case OPC_ERET:
-        opn = "eret";
-        check_insn(ctx, ISA_MIPS2);
+    case OPC_ERET: /* OPC_ERETNC */
         if ((ctx->insn_flags & ISA_MIPS32R6) &&
             (ctx->hflags & MIPS_HFLAG_BMASK)) {
             MIPS_DEBUG("CTI in delay / forbidden slot");
             goto die;
+        } else {
+            int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
+            if (ctx->opcode & (1 << bit_shift)) {
+                /* OPC_ERETNC */
+                opn = "eretnc";
+                check_insn(ctx, ISA_MIPS32R5);
+                gen_helper_eretnc(cpu_env);
+            } else {
+                /* OPC_ERET */
+                opn = "eret";
+                check_insn(ctx, ISA_MIPS2);
+                gen_helper_eret(cpu_env);
+            }
+            ctx->bstate = BS_EXCP;
         }
-        gen_helper_eret(cpu_env);
-        ctx->bstate = BS_EXCP;
         break;
     case OPC_DERET:
         opn = "deret";
index 00369f1b01640b3ba7a913d5a8e0df84e558fcd2..51e7c986e472a67fe6b5436407f941191408397a 100644 (file)
@@ -403,7 +403,7 @@ static const mips_def_t mips_defs[] =
         .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP),
         .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M),
         .CP0_Config4_rw_bitmask = 0,
-        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR),
+        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR) | (1 << CP0C5_LLB),
         .CP0_Config5_rw_bitmask = (0 << CP0C5_M) | (1 << CP0C5_K) |
                                   (1 << CP0C5_CV) | (0 << CP0C5_EVA) |
                                   (1 << CP0C5_MSAEn) | (1 << CP0C5_UFR) |
@@ -622,6 +622,7 @@ static const mips_def_t mips_defs[] =
                        (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M),
         .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
                        (3 << CP0C4_IE) | (1 << CP0C4_M),
+        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_LLB),
         .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) |
                                   (1 << CP0C5_UFE),
         .CP0_LLAddr_rw_bitmask = 0,