The encoding of PREF, CACHE, LLD and SCD instruction changed in MIPS32R6.
Additionally, the hint codes in PREF instruction greater than or
equal to 24 generate Reserved Instruction Exception.

Signed-off-by: Leon Alrae <leon.al...@imgtec.com>
---
 disas/mips.c            |    4 ++++
 target-mips/translate.c |   29 ++++++++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/disas/mips.c b/disas/mips.c
index f41b89d..67da1f0 100644
--- a/disas/mips.c
+++ b/disas/mips.c
@@ -1219,6 +1219,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 /* name,    args,      match,      mask,       pinfo,                  
membership */
 {"ll",      "t,o(b)",   0x7c000036, 0xfc00003f, LDD|RD_b|WR_t,        0, 
I32R6},
 {"sc",      "t,o(b)",   0x7c000026, 0xfc00003f, LDD|RD_b|WR_t,        0, 
I32R6},
+{"lld",     "t,o(b)",   0x7c000037, 0xfc00003f, LDD|RD_b|WR_t,        0, 
I64R6},
+{"scd",     "t,o(b)",   0x7c000027, 0xfc00003f, LDD|RD_b|WR_t,        0, 
I64R6},
+{"pref",    "h,o(b)",   0x7c000035, 0xfc00003f, RD_b,                 0, 
I32R6},
+{"cache",   "k,o(b)",   0x7c000025, 0xfc00003f, RD_b,                 0, 
I32R6},
 {"seleqz",  "d,v,t",    0x00000035, 0xfc0007ff, WR_d|RD_s|RD_t,       0, 
I32R6},
 {"selnez",  "d,v,t",    0x00000037, 0xfc0007ff, WR_d|RD_s|RD_t,       0, 
I32R6},
 {"pref",    "k,o(b)",   0xcc000000, 0xfc000000, RD_b,                  0,      
        I4|I32|G3       },
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 8f1ade5..5557271 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -347,8 +347,12 @@ enum {
     OPC_DEXTR_W_DSP    = 0x3C | OPC_SPECIAL3,
 
     /* R6 */
+    R6_OPC_PREF        = 0x35 | OPC_SPECIAL3,
+    R6_OPC_CACHE       = 0x25 | OPC_SPECIAL3,
     R6_OPC_LL          = 0x36 | OPC_SPECIAL3,
     R6_OPC_SC          = 0x26 | OPC_SPECIAL3,
+    R6_OPC_LLD         = 0x37 | OPC_SPECIAL3,
+    R6_OPC_SCD         = 0x27 | OPC_SPECIAL3,
 };
 
 /* BSHFL opcodes */
@@ -1641,6 +1645,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
         opn = "ld";
         break;
     case OPC_LLD:
+    case R6_OPC_LLD:
         save_cpu_state(ctx, 1);
         op_ld_lld(t0, t0, ctx);
         gen_store_gpr(t0, rt);
@@ -1863,6 +1868,7 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, 
int rt,
     switch (opc) {
 #if defined(TARGET_MIPS64)
     case OPC_SCD:
+    case R6_OPC_SCD:
         save_cpu_state(ctx, 1);
         op_st_scd(t1, t0, rt, ctx);
         opn = "scd";
@@ -14815,12 +14821,30 @@ static void decode_opc_special3_r6(CPUMIPSState *env, 
DisasContext *ctx)
 
     op1 = MASK_SPECIAL3(ctx->opcode);
     switch (op1) {
+    case R6_OPC_PREF:
+        if (rt >= 24) {
+            /* hint codes 24-31 are reserved and signal RI */
+            generate_exception(ctx, EXCP_RI);
+        }
+        /* Treat as NOP. */
+        break;
+    case R6_OPC_CACHE:
+        /* Treat as NOP. */
+        break;
     case R6_OPC_SC:
         gen_st_cond(ctx, op1, rt, rs, imm >> 7);
         break;
     case R6_OPC_LL:
         gen_ld(ctx, op1, rt, rs, imm >> 7);
         break;
+#if defined(TARGET_MIPS64)
+    case R6_OPC_SCD:
+        gen_st_cond(ctx, op1, rt, rs, imm >> 7);
+        break;
+    case R6_OPC_LLD:
+        gen_ld(ctx, op1, rt, rs, imm >> 7);
+        break;
+#endif
     default:            /* Invalid */
         MIPS_INVAL("special3_r6");
         generate_exception(ctx, EXCP_RI);
@@ -15632,11 +15656,13 @@ static void decode_opc (CPUMIPSState *env, 
DisasContext *ctx)
          gen_st_cond(ctx, op, rt, rs, imm);
          break;
     case OPC_CACHE:
+        check_insn_opc_removed(ctx, ISA_MIPS32R6);
         check_cp0_enabled(ctx);
         check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
         /* Treat as NOP. */
         break;
     case OPC_PREF:
+        check_insn_opc_removed(ctx, ISA_MIPS32R6);
         check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
         /* Treat as NOP. */
         break;
@@ -15759,9 +15785,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext 
*ctx)
 #if defined(TARGET_MIPS64)
     /* MIPS64 opcodes */
     case OPC_LDL ... OPC_LDR:
+    case OPC_LLD:
         check_insn_opc_removed(ctx, ISA_MIPS32R6);
     case OPC_LWU:
-    case OPC_LLD:
     case OPC_LD:
         check_insn(ctx, ISA_MIPS3);
         check_mips_64(ctx);
@@ -15775,6 +15801,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext 
*ctx)
         gen_st(ctx, op, rt, rs, imm);
         break;
     case OPC_SCD:
+        check_insn_opc_removed(ctx, ISA_MIPS32R6);
         check_insn(ctx, ISA_MIPS3);
         check_mips_64(ctx);
         gen_st_cond(ctx, op, rt, rs, imm);
-- 
1.7.5.4


Reply via email to