From 19c23a9baafc91dd3881a7a4e9bf454e42d24e4e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 3 Aug 2020 12:18:44 +0100 Subject: [PATCH] target/arm: Separate decode from handling of coproc insns As a prelude to making coproc insns use decodetree, split out the part of disas_coproc_insn() which does instruction decoding from the part which does the actual work, and make do_coproc_insn() handle the UNDEF-on-bad-permissions and similar cases itself rather than returning 1 to eventually percolate up to a callsite that calls unallocated_encoding() for it. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20200803111849.13368-3-peter.maydell@linaro.org --- target/arm/translate.c | 76 +++++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index 99663236aa..01591f0e32 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -4544,34 +4544,12 @@ void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]); } -static int disas_coproc_insn(DisasContext *s, uint32_t insn) +static void do_coproc_insn(DisasContext *s, int cpnum, int is64, + int opc1, int crn, int crm, int opc2, + bool isread, int rt, int rt2) { - int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2; const ARMCPRegInfo *ri; - cpnum = (insn >> 8) & 0xf; - - is64 = (insn & (1 << 25)) == 0; - if (!is64 && ((insn & (1 << 4)) == 0)) { - /* cdp */ - return 1; - } - - crm = insn & 0xf; - if (is64) { - crn = 0; - opc1 = (insn >> 4) & 0xf; - opc2 = 0; - rt2 = (insn >> 16) & 0xf; - } else { - crn = (insn >> 16) & 0xf; - opc1 = (insn >> 21) & 7; - opc2 = (insn >> 5) & 7; - rt2 = 0; - } - isread = (insn >> 20) & 1; - rt = (insn >> 12) & 0xf; - ri = get_arm_cp_reginfo(s->cp_regs, ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2)); if (ri) { @@ -4579,7 +4557,8 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) /* Check access permissions */ if (!cp_access_ok(s->current_el, ri, isread)) { - return 1; + unallocated_encoding(s); + return; } if (s->hstr_active || ri->accessfn || @@ -4653,14 +4632,15 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) /* Handle special cases first */ switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) { case ARM_CP_NOP: - return 0; + return; case ARM_CP_WFI: if (isread) { - return 1; + unallocated_encoding(s); + return; } gen_set_pc_im(s, s->base.pc_next); s->base.is_jmp = DISAS_WFI; - return 0; + return; default: break; } @@ -4720,7 +4700,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) /* Write */ if (ri->type & ARM_CP_CONST) { /* If not forbidden by access permissions, treat as WI */ - return 0; + return; } if (is64) { @@ -4786,7 +4766,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) gen_lookup_tb(s); } - return 0; + return; } /* Unknown register; this might be a guest error or a QEMU @@ -4806,7 +4786,39 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn) s->ns ? "non-secure" : "secure"); } - return 1; + unallocated_encoding(s); + return; +} + +static int disas_coproc_insn(DisasContext *s, uint32_t insn) +{ + int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2; + + cpnum = (insn >> 8) & 0xf; + + is64 = (insn & (1 << 25)) == 0; + if (!is64 && ((insn & (1 << 4)) == 0)) { + /* cdp */ + return 1; + } + + crm = insn & 0xf; + if (is64) { + crn = 0; + opc1 = (insn >> 4) & 0xf; + opc2 = 0; + rt2 = (insn >> 16) & 0xf; + } else { + crn = (insn >> 16) & 0xf; + opc1 = (insn >> 21) & 7; + opc2 = (insn >> 5) & 7; + rt2 = 0; + } + isread = (insn >> 20) & 1; + rt = (insn >> 12) & 0xf; + + do_coproc_insn(s, cpnum, is64, opc1, crn, crm, opc2, isread, rt, rt2); + return 0; } /* Decode XScale DSP or iWMMXt insn (in the copro space, cp=0 or 1) */ -- 2.11.0