target/sparc: Add decodetree infrastructure

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>
This commit is contained in:
Richard Henderson 2023-10-01 14:56:04 -07:00
parent 554abe47c7
commit 878cc6773a
3 changed files with 55 additions and 22 deletions

View File

@ -0,0 +1,5 @@
# SPDX-License-Identifier: LGPL-2.0+
#
# Sparc instruction decode definitions.
# Copyright (c) 2023 Richard Henderson <rth@twiddle.net>

View File

@ -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',

View File

@ -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;