target/ppc: Split out decode_legacy
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Luis Pires <luis.pires@eldorado.org.br> Signed-off-by: Matheus Ferst <matheus.ferst@eldorado.org.br> Message-Id: <20210512185441.3619828-3-matheus.ferst@eldorado.org.br> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
2c2bcb1b50
commit
624cb07fde
|
@ -9062,6 +9062,62 @@ void ppc_cpu_dump_statistics(CPUState *cs, int flags)
|
|||
#endif
|
||||
}
|
||||
|
||||
static bool decode_legacy(PowerPCCPU *cpu, DisasContext *ctx, uint32_t insn)
|
||||
{
|
||||
opc_handler_t **table, *handler;
|
||||
uint32_t inval;
|
||||
|
||||
ctx->opcode = insn;
|
||||
|
||||
LOG_DISAS("translate opcode %08x (%02x %02x %02x %02x) (%s)\n",
|
||||
insn, opc1(insn), opc2(insn), opc3(insn), opc4(insn),
|
||||
ctx->le_mode ? "little" : "big");
|
||||
|
||||
table = cpu->opcodes;
|
||||
handler = table[opc1(insn)];
|
||||
if (is_indirect_opcode(handler)) {
|
||||
table = ind_table(handler);
|
||||
handler = table[opc2(insn)];
|
||||
if (is_indirect_opcode(handler)) {
|
||||
table = ind_table(handler);
|
||||
handler = table[opc3(insn)];
|
||||
if (is_indirect_opcode(handler)) {
|
||||
table = ind_table(handler);
|
||||
handler = table[opc4(insn)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Is opcode *REALLY* valid ? */
|
||||
if (unlikely(handler->handler == &gen_invalid)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
|
||||
"%02x - %02x - %02x - %02x (%08x) "
|
||||
TARGET_FMT_lx "\n",
|
||||
opc1(insn), opc2(insn), opc3(insn), opc4(insn),
|
||||
insn, ctx->cia);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE)
|
||||
&& Rc(insn))) {
|
||||
inval = handler->inval2;
|
||||
} else {
|
||||
inval = handler->inval1;
|
||||
}
|
||||
|
||||
if (unlikely((insn & inval) != 0)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: "
|
||||
"%02x - %02x - %02x - %02x (%08x) "
|
||||
TARGET_FMT_lx "\n", insn & inval,
|
||||
opc1(insn), opc2(insn), opc3(insn), opc4(insn),
|
||||
insn, ctx->cia);
|
||||
return false;
|
||||
}
|
||||
|
||||
handler->handler(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
|
@ -9143,66 +9199,23 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
|||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
CPUPPCState *env = cs->env_ptr;
|
||||
opc_handler_t **table, *handler;
|
||||
uint32_t insn;
|
||||
bool ok;
|
||||
|
||||
LOG_DISAS("----------------\n");
|
||||
LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
|
||||
ctx->base.pc_next, ctx->mem_idx, (int)msr_ir);
|
||||
|
||||
ctx->cia = ctx->base.pc_next;
|
||||
ctx->opcode = translator_ldl_swap(env, ctx->base.pc_next,
|
||||
need_byteswap(ctx));
|
||||
|
||||
LOG_DISAS("translate opcode %08x (%02x %02x %02x %02x) (%s)\n",
|
||||
ctx->opcode, opc1(ctx->opcode), opc2(ctx->opcode),
|
||||
opc3(ctx->opcode), opc4(ctx->opcode),
|
||||
ctx->le_mode ? "little" : "big");
|
||||
insn = translator_ldl_swap(env, ctx->base.pc_next, need_byteswap(ctx));
|
||||
ctx->base.pc_next += 4;
|
||||
table = cpu->opcodes;
|
||||
handler = table[opc1(ctx->opcode)];
|
||||
if (is_indirect_opcode(handler)) {
|
||||
table = ind_table(handler);
|
||||
handler = table[opc2(ctx->opcode)];
|
||||
if (is_indirect_opcode(handler)) {
|
||||
table = ind_table(handler);
|
||||
handler = table[opc3(ctx->opcode)];
|
||||
if (is_indirect_opcode(handler)) {
|
||||
table = ind_table(handler);
|
||||
handler = table[opc4(ctx->opcode)];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Is opcode *REALLY* valid ? */
|
||||
if (unlikely(handler->handler == &gen_invalid)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
|
||||
"%02x - %02x - %02x - %02x (%08x) "
|
||||
TARGET_FMT_lx " %d\n",
|
||||
opc1(ctx->opcode), opc2(ctx->opcode),
|
||||
opc3(ctx->opcode), opc4(ctx->opcode),
|
||||
ctx->opcode, ctx->cia, (int)msr_ir);
|
||||
} else {
|
||||
uint32_t inval;
|
||||
|
||||
if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE)
|
||||
&& Rc(ctx->opcode))) {
|
||||
inval = handler->inval2;
|
||||
} else {
|
||||
inval = handler->inval1;
|
||||
}
|
||||
|
||||
if (unlikely((ctx->opcode & inval) != 0)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: "
|
||||
"%02x - %02x - %02x - %02x (%08x) "
|
||||
TARGET_FMT_lx "\n", ctx->opcode & inval,
|
||||
opc1(ctx->opcode), opc2(ctx->opcode),
|
||||
opc3(ctx->opcode), opc4(ctx->opcode),
|
||||
ctx->opcode, ctx->cia);
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
return;
|
||||
}
|
||||
ok = decode_legacy(cpu, ctx, insn);
|
||||
if (!ok) {
|
||||
gen_invalid(ctx);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
(*(handler->handler))(ctx);
|
||||
|
||||
#if defined(DO_PPC_STATISTICS)
|
||||
handler->count++;
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue