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 | 5 +++
target/sparc/translate.c | 69 ++++++++++++++++++++++++++-------------
target/sparc/meson.build | 3 ++
3 files changed, 55 insertions(+), 22 deletions(-)
create mode 100644 target/sparc/insns.decode
diff --git a/target/sparc/insns.decode b/target/sparc/insns.decode
new file mode 100644
index 0000000000..5811a679db
--- /dev/null
+++ b/target/sparc/insns.decode
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.0+
+#
+# Sparc instruction decode definitions.
+# Copyright (c) 2023 Richard Henderson <rth@twiddle.net>
+
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index cab9f13421..080bc5f8a2 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -3003,6 +3003,47 @@ static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
}
#endif
+/* Include the auto-generated decoder. */
+#include "decode-insns.c.inc"
+
+#define TRANS(NAME, AVAIL, FUNC, ...) \
+ static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
+ { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
+
+#define avail_ALL(C) true
+#ifdef TARGET_SPARC64
+# define avail_32(C) false
+# define avail_64(C) true
+#else
+# define avail_32(C) true
+# define avail_64(C) false
+#endif
+
+/* Default case for non jump instructions. */
+static bool advance_pc(DisasContext *dc)
+{
+ if (dc->npc & 3) {
+ switch (dc->npc) {
+ case DYNAMIC_PC:
+ case DYNAMIC_PC_LOOKUP:
+ dc->pc = dc->npc;
+ gen_op_next_insn();
+ break;
+ case JUMP_PC:
+ /* we can do a static jump */
+ gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
+ dc->base.is_jmp = DISAS_NORETURN;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ } else {
+ dc->pc = dc->npc;
+ dc->npc = dc->npc + 4;
+ }
+ return true;
+}
+
#define CHECK_IU_FEATURE(dc, FEATURE) \
if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
goto illegal_insn;
@@ -3011,7 +3052,7 @@ static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
goto nfpu_insn;
/* before an instruction, dc->pc must be static */
-static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
+static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
{
unsigned int opc, rs1, rs2, rd;
TCGv cpu_src1, cpu_src2;
@@ -5544,26 +5585,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
}
break;
}
- /* default case for non jump instructions */
- if (dc->npc & 3) {
- switch (dc->npc) {
- case DYNAMIC_PC:
- case DYNAMIC_PC_LOOKUP:
- dc->pc = dc->npc;
- gen_op_next_insn();
- break;
- case JUMP_PC:
- /* we can do a static jump */
- gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
- dc->base.is_jmp = DISAS_NORETURN;
- break;
- default:
- g_assert_not_reached();
- }
- } else {
- dc->pc = dc->npc;
- dc->npc = dc->npc + 4;
- }
+ advance_pc(dc);
jmp_insn:
return;
illegal_insn:
@@ -5654,7 +5676,10 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
insn = translator_ldl(env, &dc->base, dc->pc);
dc->base.pc_next += 4;
- disas_sparc_insn(dc, insn);
+
+ if (!decode(dc, insn)) {
+ disas_sparc_legacy(dc, insn);
+ }
if (dc->base.is_jmp == DISAS_NORETURN) {
return;
diff --git a/target/sparc/meson.build b/target/sparc/meson.build
index 48025cce76..c316773db6 100644
--- a/target/sparc/meson.build
+++ b/target/sparc/meson.build
@@ -1,4 +1,7 @@
+gen = decodetree.process('insns.decode')
+
sparc_ss = ss.source_set()
+sparc_ss.add(gen)
sparc_ss.add(files(
'cc_helper.c',
'cpu.c',
--
2.34.1