[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH, MIPS64] Check for UX & PX while decoding 64-bit ins
From: |
Aurelien Jarno |
Subject: |
[Qemu-devel] [PATCH, MIPS64] Check for UX & PX while decoding 64-bit instructions |
Date: |
Mon, 28 May 2007 19:48:40 +0200 |
User-agent: |
Mutt/1.5.13 (2006-08-11) |
Hi,
According to the MIPS64 manual, the 64-bit instructions should be
decoded when:
- the CPU is not in user mode
- the CPU is in user mode, and PX and/or UX bits are set.
Otherwise those instructions must generate a reserved instruction
exception.
The patch below implements that. It also moves the decoding of the LWU
instruction in a #ifdef TARGET_MIPS64 #erndif block, as it is a MIPS64
instruction only.
Cheers,
Aurelien
Index: target-mips/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/cpu.h,v
retrieving revision 1.35
diff -u -d -p -r1.35 cpu.h
--- target-mips/cpu.h 23 May 2007 08:24:25 -0000 1.35
+++ target-mips/cpu.h 28 May 2007 17:44:21 -0000
@@ -260,6 +260,7 @@ struct CPUMIPSState {
#define MIPS_HFLAG_UM 0x0001 /* user mode */
#define MIPS_HFLAG_DM 0x0008 /* Debug mode */
#define MIPS_HFLAG_SM 0x0010 /* Supervisor mode */
+#define MIPS_HFLAG_64 0x0020 /* 64-bit instructions enabled */
#define MIPS_HFLAG_RE 0x0040 /* Reversed endianness */
/* If translation is interrupted between the branch instruction and
* the delay slot, record what type of branch it is so that we can
Index: target-mips/helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/helper.c,v
retrieving revision 1.41
diff -u -d -p -r1.41 helper.c
--- target-mips/helper.c 23 May 2007 08:24:25 -0000 1.41
+++ target-mips/helper.c 28 May 2007 17:44:21 -0000
@@ -370,6 +370,7 @@ void do_interrupt (CPUState *env)
}
enter_debug_mode:
env->hflags |= MIPS_HFLAG_DM;
+ env->hflags |= MIPS_HFLAG_64;
env->hflags &= ~MIPS_HFLAG_UM;
/* EJTAG probe trap enable is not implemented... */
if (!(env->CP0_Status & (1 << CP0St_EXL)))
@@ -395,6 +396,7 @@ void do_interrupt (CPUState *env)
env->CP0_ErrorEPC = env->PC;
}
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
+ env->hflags |= MIPS_HFLAG_64;
env->hflags &= ~MIPS_HFLAG_UM;
if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1 << CP0Ca_BD);
@@ -493,6 +495,7 @@ void do_interrupt (CPUState *env)
env->CP0_Cause &= ~(1 << CP0Ca_BD);
}
env->CP0_Status |= (1 << CP0St_EXL);
+ env->hflags |= MIPS_HFLAG_64;
env->hflags &= ~MIPS_HFLAG_UM;
}
env->hflags &= ~MIPS_HFLAG_BMASK;
Index: target-mips/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op.c,v
retrieving revision 1.63
diff -u -d -p -r1.63 op.c
--- target-mips/op.c 28 May 2007 17:03:27 -0000 1.63
+++ target-mips/op.c 28 May 2007 17:44:21 -0000
@@ -1358,6 +1358,12 @@ void op_mtc0_status (void)
!(env->hflags & MIPS_HFLAG_DM) &&
(val & (1 << CP0St_UM)))
env->hflags |= MIPS_HFLAG_UM;
+#ifdef TARGET_MIPS64
+ if ((env->hflags & MIPS_HFLAG_UM) &&
+ !(val & (1 << CP0St_PX)) &&
+ !(val & (1 << CP0St_UX)))
+ env->hflags &= ~MIPS_HFLAG_64;
+#endif
env->CP0_Status = (env->CP0_Status & ~mask) | val;
if (loglevel & CPU_LOG_EXEC)
CALL_FROM_TB2(do_mtc0_status_debug, old, val);
@@ -2338,6 +2344,12 @@ void op_eret (void)
!(env->hflags & MIPS_HFLAG_DM) &&
(env->CP0_Status & (1 << CP0St_UM)))
env->hflags |= MIPS_HFLAG_UM;
+#ifdef TARGET_MIPS64
+ if ((env->hflags & MIPS_HFLAG_UM) &&
+ !(env->CP0_Status & (1 << CP0St_PX)) &&
+ !(env->CP0_Status & (1 << CP0St_UX)))
+ env->hflags &= ~MIPS_HFLAG_64;
+#endif
if (loglevel & CPU_LOG_EXEC)
CALL_FROM_TB0(debug_post_eret);
env->CP0_LLAddr = 1;
@@ -2355,6 +2367,12 @@ void op_deret (void)
!(env->hflags & MIPS_HFLAG_DM) &&
(env->CP0_Status & (1 << CP0St_UM)))
env->hflags |= MIPS_HFLAG_UM;
+#ifdef TARGET_MIPS64
+ if ((env->hflags & MIPS_HFLAG_UM) &&
+ !(env->CP0_Status & (1 << CP0St_PX)) &&
+ !(env->CP0_Status & (1 << CP0St_UX)))
+ env->hflags &= ~MIPS_HFLAG_64;
+#endif
if (loglevel & CPU_LOG_EXEC)
CALL_FROM_TB0(debug_post_eret);
env->CP0_LLAddr = 1;
Index: target-mips/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/translate.c,v
retrieving revision 1.88
diff -u -d -p -r1.88 translate.c
--- target-mips/translate.c 28 May 2007 17:03:28 -0000 1.88
+++ target-mips/translate.c 28 May 2007 17:44:22 -0000
@@ -730,9 +730,9 @@ OP_ST_TABLE(dl);
OP_ST_TABLE(dr);
OP_LD_TABLE(ld);
OP_ST_TABLE(cd);
+OP_LD_TABLE(wu);
#endif
OP_LD_TABLE(w);
-OP_LD_TABLE(wu);
OP_LD_TABLE(wl);
OP_LD_TABLE(wr);
OP_ST_TABLE(w);
@@ -773,6 +773,11 @@ static void gen_ldst (DisasContext *ctx,
*/
switch (opc) {
#ifdef TARGET_MIPS64
+ case OPC_LWU:
+ op_ldst(lwu);
+ GEN_STORE_TN_REG(rt, T0);
+ opn = "lwu";
+ break;
case OPC_LD:
op_ldst(ld);
GEN_STORE_TN_REG(rt, T0);
@@ -823,11 +828,6 @@ static void gen_ldst (DisasContext *ctx,
GEN_STORE_TN_REG(rt, T0);
opn = "lw";
break;
- case OPC_LWU:
- op_ldst(lwu);
- GEN_STORE_TN_REG(rt, T0);
- opn = "lwu";
- break;
case OPC_SW:
GEN_LOAD_REG_TN(T1, rt);
op_ldst(sw);
@@ -5377,14 +5377,20 @@ static void decode_opc (CPUState *env, D
case OPC_DSRL ... OPC_DSRA:
case OPC_DSLL32:
case OPC_DSRL32 ... OPC_DSRA32:
+ if (!(ctx->hflags & MIPS_HFLAG_64))
+ generate_exception(ctx, EXCP_RI);
gen_arith_imm(ctx, op1, rd, rt, sa);
break;
case OPC_DSLLV:
case OPC_DSRLV ... OPC_DSRAV:
case OPC_DADD ... OPC_DSUBU:
+ if (!(ctx->hflags & MIPS_HFLAG_64))
+ generate_exception(ctx, EXCP_RI);
gen_arith(ctx, op1, rd, rs, rt);
break;
case OPC_DMULT ... OPC_DDIVU:
+ if (!(ctx->hflags & MIPS_HFLAG_64))
+ generate_exception(ctx, EXCP_RI);
gen_muldiv(ctx, op1, rs, rt);
break;
#endif
@@ -5420,6 +5426,8 @@ static void decode_opc (CPUState *env, D
break;
#ifdef TARGET_MIPS64
case OPC_DCLZ ... OPC_DCLO:
+ if (!(ctx->hflags & MIPS_HFLAG_64))
+ generate_exception(ctx, EXCP_RI);
gen_cl(ctx, op1, rd, rs);
break;
#endif
@@ -5491,9 +5499,13 @@ static void decode_opc (CPUState *env, D
#ifdef TARGET_MIPS64
case OPC_DEXTM ... OPC_DEXT:
case OPC_DINSM ... OPC_DINS:
+ if (!(ctx->hflags & MIPS_HFLAG_64))
+ generate_exception(ctx, EXCP_RI);
gen_bitops(ctx, op1, rt, rs, sa, rd);
break;
case OPC_DBSHFL:
+ if (!(ctx->hflags & MIPS_HFLAG_64))
+ generate_exception(ctx, EXCP_RI);
op2 = MASK_DBSHFL(ctx->opcode);
switch (op2) {
case OPC_DSBH:
@@ -5732,9 +5744,13 @@ static void decode_opc (CPUState *env, D
case OPC_LD:
case OPC_SCD:
case OPC_SD:
+ if (!(ctx->hflags & MIPS_HFLAG_64))
+ generate_exception(ctx, EXCP_RI);
gen_ldst(ctx, op, rt, rs, imm);
break;
case OPC_DADDI ... OPC_DADDIU:
+ if (!(ctx->hflags & MIPS_HFLAG_64))
+ generate_exception(ctx, EXCP_RI);
gen_arith_imm(ctx, op, rt, rs, imm);
break;
#endif
@@ -6072,11 +6088,14 @@ void cpu_reset (CPUMIPSState *env)
/* If the exception was raised from a delay slot,
* come back to the jump. */
env->CP0_ErrorEPC = env->PC - 4;
- env->hflags &= ~MIPS_HFLAG_BMASK;
} else {
env->CP0_ErrorEPC = env->PC;
}
+#ifdef TARGET_MIPS64
+ env->hflags = MIPS_HFLAG_64;
+#else
env->hflags = 0;
+#endif
env->PC = (int32_t)0xBFC00000;
env->CP0_Wired = 0;
/* SMP not implemented */
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' address@hidden | address@hidden
`- people.debian.org/~aurel32 | www.aurel32.net
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH, MIPS64] Check for UX & PX while decoding 64-bit instructions,
Aurelien Jarno <=