Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/sparc/insns.decode | 3 ++
target/sparc/translate.c | 88 ++++++++++++---------------------------
2 files changed, 29 insertions(+), 62 deletions(-)
diff --git a/target/sparc/insns.decode b/target/sparc/insns.decode
index aa90b5c5bb..137b7eb3c6 100644
--- a/target/sparc/insns.decode
+++ b/target/sparc/insns.decode
@@ -228,6 +228,9 @@ NOP 10 00000 111011 ----- 1 ------------- # FLUSH reg+imm
SAVE 10 ..... 111100 ..... . ............. @r_r_ri
RESTORE 10 ..... 111101 ..... . ............. @r_r_ri
+DONE 10 00000 111110 00000 0 0000000000000
+RETRY 10 00001 111110 00000 0 0000000000000
+
NCP 10 ----- 110110 ----- --------- ----- # v8 CPop1
NCP 10 ----- 110111 ----- --------- ----- # v8 CPop2
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index e0a13e5d29..8faf2c59b2 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -43,10 +43,12 @@
# define gen_helper_wrpsr(E, S) qemu_build_not_reached()
#else
# define gen_helper_clear_softint(E, S) qemu_build_not_reached()
+# define gen_helper_done(E) qemu_build_not_reached()
# define gen_helper_flushw(E) qemu_build_not_reached()
# define gen_helper_rdccr(D, E) qemu_build_not_reached()
# define gen_helper_rdcwp(D, E) qemu_build_not_reached()
# define gen_helper_restored(E) qemu_build_not_reached()
+# define gen_helper_retry(E) qemu_build_not_reached()
# define gen_helper_saved(E) qemu_build_not_reached()
# define gen_helper_sdivx(D, E, A, B) qemu_build_not_reached()
# define gen_helper_set_softint(E, S) qemu_build_not_reached()
@@ -4480,6 +4482,25 @@ static bool do_restore(DisasContext *dc, int rd, TCGv src)
TRANS(RESTORE, ALL, do_add_special, a, do_restore)
+static bool do_done_retry(DisasContext *dc, bool done)
+{
+ if (!supervisor(dc)) {
+ return raise_priv(dc);
+ }
+ dc->npc = DYNAMIC_PC;
+ dc->pc = DYNAMIC_PC;
+ translator_io_start(&dc->base);
+ if (done) {
+ gen_helper_done(tcg_env);
+ } else {
+ gen_helper_retry(tcg_env);
+ }
+ return true;
+}
+
+TRANS(DONE, 64, do_done_retry, true)
+TRANS(RETRY, 64, do_done_retry, false)
+
#define CHECK_IU_FEATURE(dc, FEATURE) \
if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
goto illegal_insn;
@@ -4491,7 +4512,8 @@ TRANS(RESTORE, ALL, do_add_special, a, do_restore)
static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
{
unsigned int opc, rs1, rs2, rd;
- TCGv cpu_src1, cpu_src2;
+ TCGv cpu_src1;
+ TCGv cpu_src2 __attribute__((unused));
TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
target_long simm;
@@ -4506,9 +4528,8 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
g_assert_not_reached(); /* in decodetree */
case 2: /* FPU & Logical Operations */
{
- unsigned int xop __attribute__((unused)) = GET_FIELD(insn, 7, 12);
+ unsigned int xop = GET_FIELD(insn, 7, 12);
TCGv cpu_dst __attribute__((unused)) = tcg_temp_new();
- TCGv cpu_tmp0 __attribute__((unused));
if (xop == 0x34) { /* FPU Operations */
if (gen_trap_ifnofpu(dc)) {
@@ -4828,8 +4849,6 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
default:
goto illegal_insn;
}
- } else if (xop < 0x36) {
- goto illegal_insn; /* in decodetree */
} else if (xop == 0x36) {
#ifdef TARGET_SPARC64
/* VIS */
@@ -5271,65 +5290,10 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
default:
goto illegal_insn;
}
-#else
- g_assert_not_reached(); /* in decodetree */
#endif
- } else if (xop == 0x37) {
- /* V8 CPop2, V9 impdep2 */
- goto illegal_insn; /* in decodetree */
} else {
- cpu_src1 = get_src1(dc, insn);
- cpu_tmp0 = tcg_temp_new();
- if (IS_IMM) { /* immediate */
- simm = GET_FIELDs(insn, 19, 31);
- tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm);
- } else { /* register */
- rs2 = GET_FIELD(insn, 27, 31);
- if (rs2) {
- cpu_src2 = gen_load_gpr(dc, rs2);
- tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2);
- } else {
- tcg_gen_mov_tl(cpu_tmp0, cpu_src1);
- }
- }
- switch (xop) {
- case 0x38: /* jmpl */
- case 0x39: /* rett, V9 return */
- case 0x3b: /* flush */
- case 0x3c: /* save */
- case 0x3d: /* restore */
- g_assert_not_reached(); /* in decode tree */
-#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
- case 0x3e: /* V9 done/retry */
- {
- switch (rd) {
- case 0:
- if (!supervisor(dc))
- goto priv_insn;
- dc->npc = DYNAMIC_PC;
- dc->pc = DYNAMIC_PC;
- translator_io_start(&dc->base);
- gen_helper_done(tcg_env);
- goto jmp_insn;
- case 1:
- if (!supervisor(dc))
- goto priv_insn;
- dc->npc = DYNAMIC_PC;
- dc->pc = DYNAMIC_PC;
- translator_io_start(&dc->base);
- gen_helper_retry(tcg_env);
- goto jmp_insn;
- default:
- goto illegal_insn;
- }
- }
- break;
-#endif
- default:
- goto illegal_insn;
- }
+ goto illegal_insn; /* in decodetree */
}
- break;
}
break;
case 3: /* load/store instructions */
@@ -5726,7 +5690,7 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
illegal_insn:
gen_exception(dc, TT_ILL_INSN);
return;
-#if !defined(CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
priv_insn:
gen_exception(dc, TT_PRIV_INSN);
return;
--
2.34.1