target/arm: Convert T16, long branches

Backports commit 67b54c554b39fd24f0c3aabc546e83b3082ee7ff from qemu
This commit is contained in:
Richard Henderson 2019-11-20 12:47:55 -05:00 committed by Lioncash
parent 8d2fe3f6db
commit a91de478cc
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
2 changed files with 46 additions and 51 deletions

View file

@ -272,3 +272,10 @@ LDM_t16 1011 110 ......... \
%imm11_0x2 0:s11 !function=times_2
B 11100 ........... &i imm=%imm11_0x2
# thumb_insn_is_16bit() ensures we won't be decoding these as
# T16 instructions for a Thumb2 CPU, so these patterns must be
# a Thumb1 split BL/BLX.
BLX_suffix 11101 imm:11 &i
BL_BLX_prefix 11110 imm:s11 &i
BL_suffix 11111 imm:11 &i

View file

@ -10483,6 +10483,43 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
return true;
}
static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_R[14], read_pc(s) + (a->imm << 12));
return true;
}
static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
TCGv_i32 tmp = tcg_temp_new_i32(tcg_ctx);
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
tcg_gen_addi_i32(tcg_ctx, tmp, tcg_ctx->cpu_R[14], (a->imm << 1) | 1);
tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_R[14], s->base.pc_next | 1);
gen_bx(s, tmp);
return true;
}
static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
TCGv_i32 tmp;
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
if (!ENABLE_ARCH_5) {
return false;
}
tmp = tcg_temp_new_i32(tcg_ctx);
tcg_gen_addi_i32(tcg_ctx, tmp, tcg_ctx->cpu_R[14], a->imm << 1);
tcg_gen_andi_i32(tcg_ctx, tmp, tmp, 0xfffffffc);
tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_R[14], s->base.pc_next | 1);
gen_bx(s, tmp);
return true;
}
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
@ -11089,11 +11126,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
static void disas_thumb_insn(DisasContext *s, uint32_t insn)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
int32_t offset;
TCGv_i32 tmp;
TCGv_i32 tmp2;
if (disas_t16(s, insn)) {
return;
}
@ -11111,56 +11143,12 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
case 10: /* add PC/SP (immediate), in decodetree */
case 11: /* misc, in decodetree */
case 12: /* load/store multiple, in decodetree */
goto illegal_op;
case 13: /* conditional branch or swi, in decodetree */
goto illegal_op;
case 14:
if (insn & (1 << 11)) {
/* thumb_insn_is_16bit() ensures we can't get here for
* a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
*/
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
ARCH(5);
offset = ((insn & 0x7ff) << 1);
tmp = load_reg(s, 14);
tcg_gen_addi_i32(tcg_ctx, tmp, tmp, offset);
tcg_gen_andi_i32(tcg_ctx, tmp, tmp, 0xfffffffc);
tmp2 = tcg_temp_new_i32(tcg_ctx);
tcg_gen_movi_i32(tcg_ctx, tmp2, s->base.pc_next | 1);
store_reg(s, 14, tmp2);
gen_bx(s, tmp);
break;
}
/* unconditional branch, in decodetree */
goto illegal_op;
case 15:
/* thumb_insn_is_16bit() ensures we can't get here for
* a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
*/
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
if (insn & (1 << 11)) {
/* 0b1111_1xxx_xxxx_xxxx : BL suffix */
offset = ((insn & 0x7ff) << 1) | 1;
tmp = load_reg(s, 14);
tcg_gen_addi_i32(tcg_ctx, tmp, tmp, offset);
tmp2 = tcg_temp_new_i32(tcg_ctx);
tcg_gen_movi_i32(tcg_ctx, tmp2, s->base.pc_next | 1);
store_reg(s, 14, tmp2);
gen_bx(s, tmp);
} else {
/* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
uint32_t uoffset = ((int32_t)insn << 21) >> 9;
tcg_gen_movi_i32(tcg_ctx, tcg_ctx->cpu_R[14], read_pc(s) + uoffset);
}
break;
/* branches, in decodetree */
goto illegal_op;
}
return;
illegal_op: