[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH, MIPS] MIPS R1/R2 instructions decoding
From: |
Aurelien Jarno |
Subject: |
Re: [Qemu-devel] [PATCH, MIPS] MIPS R1/R2 instructions decoding |
Date: |
Tue, 29 May 2007 08:20:29 +0200 |
User-agent: |
Mutt/1.5.13 (2006-08-11) |
On Tue, May 29, 2007 at 12:15:01AM +0200, Aurelien Jarno wrote:
> Hi,
>
> In the current implementation of the MIPS CPU, all instructions are
> regarded as valid, being R1 or R2 instructions.
>
> This patch fixes that by generating a reserved instruction exception
> when an R2 instructions is decoded on an R1 only CPU.
>
> Note that I have left the FPU code unchanged, as I don't know a lot
> about it. I will do the same later, after reading the FPU part of the
> manuals.
>
As discussed on IRC, please find below a new version of the patch which
uses an inline function instead of writting the if code each time.
Index: target-mips/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/translate.c,v
retrieving revision 1.89
diff -u -d -p -r1.89 translate.c
--- target-mips/translate.c 28 May 2007 20:36:48 -0000 1.89
+++ target-mips/translate.c 29 May 2007 06:14:49 -0000
@@ -703,6 +703,14 @@ static inline void generate_exception (D
generate_exception_err (ctx, excp, 0);
}
+/* This code generates a "reserved instruction" exception if the
+ CPU is not a MIPS R2 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)
@@ -1837,7 +1845,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";
@@ -1971,6 +1979,7 @@ static void gen_mfc0 (DisasContext *ctx,
rn = "PageMask";
break;
case 1:
+ check_mips_r2(env, ctx);
gen_op_mfc0_pagegrain();
rn = "PageGrain";
break;
@@ -2011,6 +2020,7 @@ static void gen_mfc0 (DisasContext *ctx,
case 7:
switch (sel) {
case 0:
+ check_mips_r2(env, ctx);
gen_op_mfc0_hwrena();
rn = "HWREna";
break;
@@ -2067,14 +2077,17 @@ static void gen_mfc0 (DisasContext *ctx,
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;
@@ -2109,6 +2122,7 @@ static void gen_mfc0 (DisasContext *ctx,
rn = "PRid";
break;
case 1:
+ check_mips_r2(env, ctx);
gen_op_mfc0_ebase();
rn = "EBase";
break;
@@ -2373,7 +2387,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";
@@ -2507,6 +2521,7 @@ static void gen_mtc0 (DisasContext *ctx,
rn = "PageMask";
break;
case 1:
+ check_mips_r2(env, ctx);
gen_op_mtc0_pagegrain();
rn = "PageGrain";
break;
@@ -2547,6 +2562,7 @@ static void gen_mtc0 (DisasContext *ctx,
case 7:
switch (sel) {
case 0:
+ check_mips_r2(env, ctx);
gen_op_mtc0_hwrena();
rn = "HWREna";
break;
@@ -2601,14 +2617,17 @@ static void gen_mtc0 (DisasContext *ctx,
rn = "Status";
break;
case 1:
+ check_mips_r2(env, ctx);
gen_op_mtc0_intctl();
rn = "IntCtl";
break;
case 2:
+ check_mips_r2(env, ctx);
gen_op_mtc0_srsctl();
rn = "SRSCtl";
break;
case 3:
+ check_mips_r2(env, ctx);
gen_op_mtc0_srsmap();
rn = "SRSMap";
break;
@@ -2647,6 +2666,7 @@ static void gen_mtc0 (DisasContext *ctx,
rn = "PRid";
break;
case 1:
+ check_mips_r2(env, ctx);
gen_op_mtc0_ebase();
rn = "EBase";
break;
@@ -2923,7 +2943,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";
@@ -3057,6 +3077,7 @@ static void gen_dmfc0 (DisasContext *ctx
rn = "PageMask";
break;
case 1:
+ check_mips_r2(env, ctx);
gen_op_mfc0_pagegrain();
rn = "PageGrain";
break;
@@ -3097,6 +3118,7 @@ static void gen_dmfc0 (DisasContext *ctx
case 7:
switch (sel) {
case 0:
+ check_mips_r2(env, ctx);
gen_op_mfc0_hwrena();
rn = "HWREna";
break;
@@ -3153,14 +3175,17 @@ static void gen_dmfc0 (DisasContext *ctx
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;
@@ -3195,6 +3220,7 @@ static void gen_dmfc0 (DisasContext *ctx
rn = "PRid";
break;
case 1:
+ check_mips_r2(env, ctx);
gen_op_mfc0_ebase();
rn = "EBase";
break;
@@ -3450,7 +3476,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";
@@ -3584,6 +3610,7 @@ static void gen_dmtc0 (DisasContext *ctx
rn = "PageMask";
break;
case 1:
+ check_mips_r2(env, ctx);
gen_op_mtc0_pagegrain();
rn = "PageGrain";
break;
@@ -3624,6 +3651,7 @@ static void gen_dmtc0 (DisasContext *ctx
case 7:
switch (sel) {
case 0:
+ check_mips_r2(env, ctx);
gen_op_mtc0_hwrena();
rn = "HWREna";
break;
@@ -3678,14 +3706,17 @@ static void gen_dmtc0 (DisasContext *ctx
rn = "Status";
break;
case 1:
+ check_mips_r2(env, ctx);
gen_op_mtc0_intctl();
rn = "IntCtl";
break;
case 2:
+ check_mips_r2(env, ctx);
gen_op_mtc0_srsctl();
rn = "SRSCtl";
break;
case 3:
+ check_mips_r2(env, ctx);
gen_op_mtc0_srsmap();
rn = "SRSMap";
break;
@@ -3724,6 +3755,7 @@ static void gen_dmtc0 (DisasContext *ctx
rn = "PRid";
break;
case 1:
+ check_mips_r2(env, ctx);
gen_op_mtc0_ebase();
rn = "EBase";
break;
@@ -4001,13 +4033,13 @@ static void gen_cp0 (CPUState *env, Disa
/* 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
@@ -4016,13 +4048,13 @@ static void gen_cp0 (CPUState *env, Disa
/* 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
@@ -5438,6 +5470,7 @@ static void decode_opc (CPUState *env, D
}
break;
case OPC_SPECIAL3:
+ check_mips_r2(env, ctx);
op1 = MASK_SPECIAL3(ctx->opcode);
switch (op1) {
case OPC_EXT:
@@ -5541,6 +5574,7 @@ static void decode_opc (CPUState *env, D
gen_trap(ctx, op1, rs, -1, imm);
break;
case OPC_SYNCI:
+ check_mips_r2(env, ctx);
/* treat as noop */
break;
default: /* Invalid */
@@ -5566,6 +5600,7 @@ static void decode_opc (CPUState *env, D
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:
@@ -5587,14 +5622,10 @@ static void decode_opc (CPUState *env, D
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");
@@ -5647,6 +5678,9 @@ static void decode_opc (CPUState *env, D
gen_op_cp1_enabled();
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:
@@ -5655,8 +5689,6 @@ static void decode_opc (CPUState *env, D
case OPC_DMFC1:
case OPC_DMTC1:
#endif
- case OPC_MFHC1:
- case OPC_MTHC1:
gen_cp1(ctx, op1, rt, rd);
break;
case OPC_BC1:
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' address@hidden | address@hidden
`- people.debian.org/~aurel32 | www.aurel32.net