[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [SPARC][PATCH] Add a few missing illegal_instruction traps
From: |
Aurelien Jarno |
Subject: |
[Qemu-devel] [SPARC][PATCH] Add a few missing illegal_instruction traps |
Date: |
Sat, 31 Mar 2007 23:43:34 +0200 |
User-agent: |
Mutt/1.5.13 (2006-08-11) |
Hi all,
The current implementation of the SPARC CPU in QEMU does not generate
an illegal_instruction trap in a few cases:
- The wrpsr instruction should generate an illegal_instruction trap if
CWP is greater than NWINDOWS. The current implementation ignores the
higher bits instead.
- The load or store alternate instructions does not support specifying
the ASI as an immediate value on a SPARCv8 CPU, which generates an
illegal_instruction in this case. This is however supported on a
SPARCv9 CPU.
- The STD and STDA *may* generate an illegal_instruction trap for a
mis-aligned rd. However, both emulated CPU (microSPARC II &
ultraSPARC) does actually generate a trap in this case.
The patch below fixes that.
Bye,
Aurelien
Index: target-sparc/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-sparc/cpu.h,v
retrieving revision 1.30
diff -u -d -p -r1.30 cpu.h
--- target-sparc/cpu.h 25 Mar 2007 07:55:52 -0000 1.30
+++ target-sparc/cpu.h 31 Mar 2007 21:28:50 -0000
@@ -268,7 +268,7 @@ void cpu_set_cwp(CPUSPARCState *env1, in
env->psrs = (_tmp & PSR_S)? 1 : 0; \
env->psrps = (_tmp & PSR_PS)? 1 : 0; \
env->psret = (_tmp & PSR_ET)? 1 : 0; \
- cpu_set_cwp(env, _tmp & PSR_CWP & (NWINDOWS - 1)); \
+ cpu_set_cwp(env, _tmp & PSR_CWP); \
} while (0)
#ifdef TARGET_SPARC64
Index: target-sparc/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v
retrieving revision 1.22
diff -u -d -p -r1.22 op_helper.c
--- target-sparc/op_helper.c 6 Dec 2006 15:51:39 -0000 1.22
+++ target-sparc/op_helper.c 31 Mar 2007 21:28:50 -0000
@@ -615,6 +615,9 @@ void helper_rett()
{
unsigned int cwp;
+ if (env->psret == 1)
+ raise_exception(TT_ILL_INSN);
+
env->psret = 1;
cwp = (env->cwp + 1) & (NWINDOWS - 1);
if (env->wim & (1 << cwp)) {
@@ -655,6 +658,8 @@ void helper_debug()
#ifndef TARGET_SPARC64
void do_wrpsr()
{
+ if ((T0 & PSR_CWP) >= NWINDOWS)
+ raise_exception(TT_ILL_INSN);
PUT_PSR(env, T0);
}
Index: target-sparc/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-sparc/translate.c,v
retrieving revision 1.38
diff -u -d -p -r1.38 translate.c
--- target-sparc/translate.c 25 Mar 2007 07:55:52 -0000 1.38
+++ target-sparc/translate.c 31 Mar 2007 21:28:51 -0000
@@ -2332,6 +2332,8 @@ static void disas_sparc_insn(DisasContex
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
case 0x10: /* load word alternate */
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2339,6 +2341,8 @@ static void disas_sparc_insn(DisasContex
break;
case 0x11: /* load unsigned byte alternate */
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2346,6 +2350,8 @@ static void disas_sparc_insn(DisasContex
break;
case 0x12: /* load unsigned halfword alternate */
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2353,6 +2359,8 @@ static void disas_sparc_insn(DisasContex
break;
case 0x13: /* load double word alternate */
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2361,6 +2369,8 @@ static void disas_sparc_insn(DisasContex
break;
case 0x19: /* load signed byte alternate */
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2368,6 +2378,8 @@ static void disas_sparc_insn(DisasContex
break;
case 0x1a: /* load signed halfword alternate */
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2375,6 +2387,8 @@ static void disas_sparc_insn(DisasContex
break;
case 0x1d: /* ldstuba -- XXX: should be atomically */
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2382,6 +2396,8 @@ static void disas_sparc_insn(DisasContex
break;
case 0x1f: /* swap reg with alt. memory. Also atomically */
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2471,6 +2487,8 @@ static void disas_sparc_insn(DisasContex
gen_op_ldst(sth);
break;
case 0x7:
+ if (rd & 1)
+ goto illegal_insn;
flush_T2(dc);
gen_movl_reg_T2(rd + 1);
gen_op_ldst(std);
@@ -2478,6 +2496,8 @@ static void disas_sparc_insn(DisasContex
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
case 0x14:
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2485,6 +2505,8 @@ static void disas_sparc_insn(DisasContex
break;
case 0x15:
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2492,6 +2514,8 @@ static void disas_sparc_insn(DisasContex
break;
case 0x16:
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
@@ -2499,9 +2523,13 @@ static void disas_sparc_insn(DisasContex
break;
case 0x17:
#ifndef TARGET_SPARC64
+ if (IS_IMM)
+ goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
#endif
+ if (rd & 1)
+ goto illegal_insn;
flush_T2(dc);
gen_movl_reg_T2(rd + 1);
gen_op_stda(insn, 0, 8, 0);
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' address@hidden | address@hidden
`- people.debian.org/~aurel32 | www.aurel32.net
- [Qemu-devel] [SPARC][PATCH] Add a few missing illegal_instruction traps,
Aurelien Jarno <=