Add a few missing illegal_instruction traps
PATCH 1/1 Add a few missing illegal_instruction traps
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
cpu.h +1 -1
@@ -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
op_helper.c +5 -0
@@ -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
translate.c +28 -0
@@ -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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexgen_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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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 );
Signature · 4 lines
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' [email protected] | [email protected] `- people.debian.org/~aurel32 | www.aurel32.net
Quoted 5 lines · Aurelien Jarno
Hi all,
The current implementation of the SPARC CPU in QEMU does not generate an
illegal_instructiontrap in a few cases:
Quoted 11 lines
- The wrpsr instruction should generate an
illegal_instructiontrap 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 anillegal_instructionin this case. This is however supported on a SPARCv9 CPU.
- The STD and STDA *may* generate anillegal_instructiontrap 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
cpu.h +1 -1
@@ -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
op_helper.c +5 -0
@@ -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
translate.c +32 -0
@@ -2313,6 +2313,8 @@ static void disas_sparc_insn(DisasContexgen_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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexgen_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(DisasContexbreak ;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(DisasContexbreak ;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(DisasContexbreak ;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 );
Signature · 4 lines
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' [email protected] | [email protected] `- people.debian.org/~aurel32 | www.aurel32.net