]> xenbits.xensource.com Git - qemu-xen-4.4-testing.git/commitdiff
Check for R2 instructions, and throw RI if we don't emulate R2.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 2 Jun 2007 00:25:12 +0000 (00:25 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 2 Jun 2007 00:25:12 +0000 (00:25 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2921 c046a42c-6fe2-441c-8c8c-71466251a162

target-mips/translate.c

index 7ea7886ec8c2a2ce0870ae794cde8d9ddb9e5fff..b5a8b5b0a6c738c86ed294c6adad8a364ba18982 100644 (file)
@@ -732,6 +732,14 @@ void check_cp1_registers(DisasContext *ctx, int regs)
         generate_exception(ctx, EXCP_RI);
 }
 
+/* This code generates a "reserved instruction" exception if the
+   CPU is not a MIPS R2 (or higher) CPU. */
+static inline void check_mips_r2(CPUState *env, DisasContext *ctx)
+{
+    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) < (1 << CP0C0_AR))
+        generate_exception(ctx, EXCP_RI);
+}
+
 #if defined(CONFIG_USER_ONLY)
 #define op_ldst(name)        gen_op_##name##_raw()
 #define OP_LD_TABLE(width)
@@ -1866,7 +1874,7 @@ fail:
 }
 
 /* CP0 (MMU and control) */
-static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
+static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -2000,6 +2008,7 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
             rn = "PageMask";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -2040,6 +2049,7 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
     case 7:
         switch (sel) {
         case 0:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_hwrena();
             rn = "HWREna";
             break;
@@ -2096,14 +2106,17 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
             rn = "Status";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_intctl();
             rn = "IntCtl";
             break;
         case 2:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_srsctl();
             rn = "SRSCtl";
             break;
         case 3:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_srsmap();
             rn = "SRSMap";
             break;
@@ -2138,6 +2151,7 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
             rn = "PRid";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_ebase();
             rn = "EBase";
             break;
@@ -2402,7 +2416,7 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
+static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -2536,6 +2550,7 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
             rn = "PageMask";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -2576,6 +2591,7 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
     case 7:
         switch (sel) {
         case 0:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_hwrena();
             rn = "HWREna";
             break;
@@ -2633,18 +2649,21 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
             rn = "Status";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_intctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "IntCtl";
             break;
         case 2:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_srsctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSCtl";
             break;
         case 3:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_srsmap();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
@@ -2683,6 +2702,7 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
             rn = "PRid";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_ebase();
             rn = "EBase";
             break;
@@ -2970,7 +2990,7 @@ die:
 }
 
 #ifdef TARGET_MIPS64
-static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
+static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -3104,6 +3124,7 @@ static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
             rn = "PageMask";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -3144,6 +3165,7 @@ static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
     case 7:
         switch (sel) {
         case 0:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_hwrena();
             rn = "HWREna";
             break;
@@ -3200,14 +3222,17 @@ static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
             rn = "Status";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_intctl();
             rn = "IntCtl";
             break;
         case 2:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_srsctl();
             rn = "SRSCtl";
             break;
         case 3:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_srsmap(); /* shadow registers */
             rn = "SRSMap";
             break;
@@ -3242,6 +3267,7 @@ static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
             rn = "PRid";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mfc0_ebase();
             rn = "EBase";
             break;
@@ -3497,7 +3523,7 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
+static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -3631,6 +3657,7 @@ static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
             rn = "PageMask";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -3671,6 +3698,7 @@ static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
     case 7:
         switch (sel) {
         case 0:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_hwrena();
             rn = "HWREna";
             break;
@@ -3728,18 +3756,21 @@ static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
             rn = "Status";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_intctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "IntCtl";
             break;
         case 2:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_srsctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSCtl";
             break;
         case 3:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_srsmap();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
@@ -3778,6 +3809,7 @@ static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
             rn = "PRid";
             break;
         case 1:
+            check_mips_r2(env, ctx);
             gen_op_mtc0_ebase();
             rn = "EBase";
             break;
@@ -4064,13 +4096,13 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
             /* Treat as NOP */
             return;
         }
-        gen_mfc0(ctx, rd, ctx->opcode & 0x7);
+        gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
         gen_op_store_T0_gpr(rt);
         opn = "mfc0";
         break;
     case OPC_MTC0:
         GEN_LOAD_REG_TN(T0, rt);
-        gen_mtc0(ctx, rd, ctx->opcode & 0x7);
+        gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
         opn = "mtc0";
         break;
 #ifdef TARGET_MIPS64
@@ -4079,13 +4111,13 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
             /* Treat as NOP */
             return;
         }
-        gen_dmfc0(ctx, rd, ctx->opcode & 0x7);
+        gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
         gen_op_store_T0_gpr(rt);
         opn = "dmfc0";
         break;
     case OPC_DMTC0:
         GEN_LOAD_REG_TN(T0, rt);
-        gen_dmtc0(ctx, rd, ctx->opcode & 0x7);
+        gen_dmtc0(env,ctx, rd, ctx->opcode & 0x7);
         opn = "dmtc0";
         break;
 #endif
@@ -5501,6 +5533,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
         }
         break;
     case OPC_SPECIAL3:
+         check_mips_r2(env, ctx);
          op1 = MASK_SPECIAL3(ctx->opcode);
          switch (op1) {
          case OPC_EXT:
@@ -5604,6 +5637,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
             gen_trap(ctx, op1, rs, -1, imm);
             break;
         case OPC_SYNCI:
+            check_mips_r2(env, ctx);
             /* treat as noop */
             break;
         default:            /* Invalid */
@@ -5629,6 +5663,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
             gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
             break;
         case OPC_MFMC0:
+            check_mips_r2(env, ctx);
             op2 = MASK_MFMC0(ctx->opcode);
             switch (op2) {
             case OPC_DI:
@@ -5650,14 +5685,10 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
             break;
         case OPC_RDPGPR:
         case OPC_WRPGPR:
-            if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) {
-                /* Shadow registers not implemented. */
-                GEN_LOAD_REG_TN(T0, rt);
-                GEN_STORE_TN_REG(rd, T0);
-            } else {
-                MIPS_INVAL("shadow register move");
-                generate_exception(ctx, EXCP_RI);
-            }
+            check_mips_r2(env, ctx);
+            /* Shadow registers not implemented. */
+            GEN_LOAD_REG_TN(T0, rt);
+            GEN_STORE_TN_REG(rd, T0);
             break;
         default:
             MIPS_INVAL("cp0");
@@ -5710,6 +5741,9 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
             check_cp1_enabled(ctx);
             op1 = MASK_CP1(ctx->opcode);
             switch (op1) {
+            case OPC_MFHC1:
+            case OPC_MTHC1:
+                check_mips_r2(env, ctx);
             case OPC_MFC1:
             case OPC_CFC1:
             case OPC_MTC1:
@@ -5718,8 +5752,6 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
             case OPC_DMFC1:
             case OPC_DMTC1:
 #endif
-            case OPC_MFHC1:
-            case OPC_MTHC1:
                 gen_cp1(ctx, op1, rt, rd);
                 break;
             case OPC_BC1: