diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-06-02 00:25:12 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-06-02 00:25:12 +0000 |
commit | 3a95e3a7d9a6fd7610fe483778ff7016d23be5ec (patch) | |
tree | b76570cb9b660409392d582f1e977671be63999b /target-mips | |
parent | 2538deb29249094e73a7f294cc4a2741fd1b9bb9 (diff) | |
download | qemu-3a95e3a7d9a6fd7610fe483778ff7016d23be5ec.zip |
Check for R2 instructions, and throw RI if we don't emulate R2.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2921 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips')
-rw-r--r-- | target-mips/translate.c | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/target-mips/translate.c b/target-mips/translate.c index 7ea7886ec8..b5a8b5b0a6 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -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: |