qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [SPARC][PATCH] Add a few missing illegal_instruction traps
@ 2007-03-31 21:43 Aurelien Jarno
  2007-03-31 22:03 ` Aurelien Jarno
  0 siblings, 1 reply; 2+ messages in thread
From: Aurelien Jarno @ 2007-03-31 21:43 UTC (permalink / raw)
  To: qemu-devel

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
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Qemu-devel] [SPARC][PATCH] Add a few missing illegal_instruction traps
  2007-03-31 21:43 [Qemu-devel] [SPARC][PATCH] Add a few missing illegal_instruction traps Aurelien Jarno
@ 2007-03-31 22:03 ` Aurelien Jarno
  0 siblings, 0 replies; 2+ messages in thread
From: Aurelien Jarno @ 2007-03-31 22:03 UTC (permalink / raw)
  To: qemu-devel

On Sat, Mar 31, 2007 at 11:43:34PM +0200, Aurelien Jarno wrote:
> 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 same applies for the LDD and LDDA instructions, please find an
updated patch below.


Index: cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-sparc/cpu.h,v
retrieving revision 1.30
diff -u -d -p -r1.30 cpu.h
--- cpu.h	25 Mar 2007 07:55:52 -0000	1.30
+++ cpu.h	31 Mar 2007 21:56:14 -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: 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
--- op_helper.c	6 Dec 2006 15:51:39 -0000	1.22
+++ op_helper.c	31 Mar 2007 21:56:14 -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: translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-sparc/translate.c,v
retrieving revision 1.38
diff -u -d -p -r1.38 translate.c
--- translate.c	25 Mar 2007 07:55:52 -0000	1.38
+++ translate.c	31 Mar 2007 21:56:14 -0000
@@ -2313,6 +2313,8 @@ static void disas_sparc_insn(DisasContex
 		    gen_op_ldst(lduh);
 		    break;
 		case 0x3:	/* load double word */
+		    if (rd & 1)
+                        goto illegal_insn;
 		    gen_op_ldst(ldd);
 		    gen_movl_T0_reg(rd + 1);
 		    break;
@@ -2332,6 +2334,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 +2343,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 +2352,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,14 +2361,20 @@ 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
+		    if (rd & 1)
+                        goto illegal_insn;
 		    gen_op_ldda(insn, 1, 8, 0);
 		    gen_movl_T0_reg(rd + 1);
 		    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 +2382,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 +2391,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 +2400,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 +2491,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 +2500,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 +2509,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 +2518,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 +2527,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
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-03-31 22:06 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-31 21:43 [Qemu-devel] [SPARC][PATCH] Add a few missing illegal_instruction traps Aurelien Jarno
2007-03-31 22:03 ` Aurelien Jarno

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).