mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-06-24 23:11:30 +00:00
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. Backports 19c23a9baafc91dd3881a7a4e9bf454e42d24e4e
This commit is contained in:
parent
2944a75b98
commit
ef0e23f1f9
|
@ -4639,41 +4639,20 @@ void gen_gvec_uaba(TCGContext *s, unsigned vece, uint32_t rd_ofs, uint32_t rn_of
|
||||||
tcg_gen_gvec_3(s, rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
|
tcg_gen_gvec_3(s, 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;
|
const ARMCPRegInfo *ri;
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
|
||||||
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,
|
ri = get_arm_cp_reginfo(s->cp_regs,
|
||||||
ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
|
ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
|
||||||
if (ri) {
|
if (ri) {
|
||||||
/* Check access permissions */
|
/* Check access permissions */
|
||||||
if (!cp_access_ok(s->current_el, ri, isread)) {
|
if (!cp_access_ok(s->current_el, ri, isread)) {
|
||||||
return 1;
|
unallocated_encoding(s);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->hstr_active || ri->accessfn ||
|
if (s->hstr_active || ri->accessfn ||
|
||||||
|
@ -4747,25 +4726,19 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
|
||||||
/* Handle special cases first */
|
/* Handle special cases first */
|
||||||
switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
|
switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
|
||||||
case ARM_CP_NOP:
|
case ARM_CP_NOP:
|
||||||
return 0;
|
return;
|
||||||
case ARM_CP_WFI:
|
case ARM_CP_WFI:
|
||||||
if (isread) {
|
if (isread) {
|
||||||
return 1;
|
unallocated_encoding(s);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
gen_set_pc_im(s, s->base.pc_next);
|
gen_set_pc_im(s, s->base.pc_next);
|
||||||
s->base.is_jmp = DISAS_WFI;
|
s->base.is_jmp = DISAS_WFI;
|
||||||
return 0;
|
return;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: if'd out
|
|
||||||
#if 0
|
|
||||||
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
|
|
||||||
gen_io_start();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (isread) {
|
if (isread) {
|
||||||
/* Read */
|
/* Read */
|
||||||
if (is64) {
|
if (is64) {
|
||||||
|
@ -4817,7 +4790,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
|
||||||
/* Write */
|
/* Write */
|
||||||
if (ri->type & ARM_CP_CONST) {
|
if (ri->type & ARM_CP_CONST) {
|
||||||
/* If not forbidden by access permissions, treat as WI */
|
/* If not forbidden by access permissions, treat as WI */
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is64) {
|
if (is64) {
|
||||||
|
@ -4865,7 +4838,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
|
||||||
gen_lookup_tb(s);
|
gen_lookup_tb(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unknown register; this might be a guest error or a QEMU
|
/* Unknown register; this might be a guest error or a QEMU
|
||||||
|
@ -4885,7 +4858,39 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
|
||||||
s->ns ? "non-secure" : "secure");
|
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) */
|
/* Decode XScale DSP or iWMMXt insn (in the copro space, cp=0 or 1) */
|
||||||
|
|
Loading…
Reference in a new issue