target/arm: Convert ERET

Pass the T5 encoding of SUBS PC, LR, #IMM through the normal SUBS path
to make it clear exactly what's happening -- we hit ALUExceptionReturn
along that path.

Backports commit ef11bc3c461e2c650e8bef552146a4b08f81884e from qemu
This commit is contained in:
Richard Henderson 2019-11-19 22:33:07 -05:00 committed by Lioncash
parent 74040da34c
commit be2a259d3c
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 33 additions and 39 deletions

View file

@ -211,3 +211,5 @@ BXJ .... 0001 0010 1111 1111 1111 0010 .... @rm
BLX_r .... 0001 0010 1111 1111 1111 0011 .... @rm
CLZ .... 0001 0110 1111 .... 1111 0001 .... @rdm
ERET ---- 0001 0110 0000 0000 0000 0110 1110

View file

@ -218,4 +218,12 @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
MSR_v7m 1111 0011 100 0 rn:4 1000 mask:2 00 sysm:8
}
BXJ 1111 0011 1100 rm:4 1000 1111 0000 0000 &r
{
# At v6T2, this is the T5 encoding of SUBS PC, LR, #IMM, and works as for
# every other encoding of SUBS. With v7VE, IMM=0 is redefined as ERET.
# The distinction between the two only matters for Hyp mode.
ERET 1111 0011 1101 1110 1000 1111 0000 0000
SUB_rri 1111 0011 1101 1110 1000 1111 imm:8 \
&s_rri_rot rot=0 s=1 rd=15 rn=14
}
}

View file

@ -8731,6 +8731,27 @@ static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
return true;
}
static bool trans_ERET(DisasContext *s, arg_ERET *a)
{
TCGv_i32 tmp;
if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
return false;
}
if (IS_USER(s)) {
unallocated_encoding(s);
return true;
}
if (s->current_el == 2) {
/* ERET from Hyp uses ELR_Hyp, not LR */
tmp = load_cpu_field(s, elr_el[2]);
} else {
tmp = load_reg(s, 14);
}
gen_exception_return(s, tmp);
return true;
}
/*
* Legacy decoder.
*/
@ -9034,29 +9055,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
case 0x4: /* crc32 */
/* All done in decodetree. Illegal ops reach here. */
goto illegal_op;
case 0x5:
/* Saturating addition and subtraction. */
case 0x5: /* Saturating addition and subtraction. */
case 0x6: /* ERET */
/* All done in decodetree. Reach here for illegal ops. */
goto illegal_op;
case 0x6: /* ERET */
if (op1 != 3) {
goto illegal_op;
}
if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
goto illegal_op;
}
if ((insn & 0x000fff0f) != 0x0000000e) {
/* UNPREDICTABLE; we choose to UNDEF */
goto illegal_op;
}
if (s->current_el == 2) {
tmp = load_cpu_field(s, elr_el[2]);
} else {
tmp = load_reg(s, 14);
}
gen_exception_return(s, tmp);
break;
case 7:
{
int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
@ -10863,24 +10865,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
case 4: /* bxj, in decodetree */
goto illegal_op;
case 5: /* Exception return. */
if (IS_USER(s)) {
goto illegal_op;
}
if (rn != 14 || rd != 15) {
goto illegal_op;
}
if (s->current_el == 2) {
/* ERET from Hyp uses ELR_Hyp, not LR */
if (insn & 0xff) {
goto illegal_op;
}
tmp = load_cpu_field(s, elr_el[2]);
} else {
tmp = load_reg(s, rn);
tcg_gen_subi_i32(tcg_ctx, tmp, tmp, insn & 0xff);
}
gen_exception_return(s, tmp);
break;
case 6: /* MRS, in decodetree */
case 7: /* MSR, in decodetree */
goto illegal_op;