aboutsummaryrefslogtreecommitdiff
path: root/lib/arm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/arm')
-rw-r--r--lib/arm/arch-transform-dis.inc.h21
-rw-r--r--lib/arm/dis-arm.inc.h7
-rw-r--r--lib/arm/dis-thumb.inc.h3
-rw-r--r--lib/arm/dis-thumb2.inc.h18
4 files changed, 36 insertions, 13 deletions
diff --git a/lib/arm/arch-transform-dis.inc.h b/lib/arm/arch-transform-dis.inc.h
index c5963e1..8569300 100644
--- a/lib/arm/arch-transform-dis.inc.h
+++ b/lib/arm/arch-transform-dis.inc.h
@@ -113,7 +113,7 @@ void transform_dis_data(struct transform_dis_ctx *ctx, unsigned o0, unsigned o1,
POPone(actx, scratch);
}
}
- ctx->modify = true;
+ ctx->base.modify = true;
#ifdef TRANSFORM_DIS_VERBOSE
printf("transform_dis_data: => %x %x %x %x\n",
newval[0], newval[1], newval[2], newval[3]);
@@ -149,23 +149,18 @@ void transform_dis_pcrel(struct transform_dis_ctx *ctx, uintptr_t dpc,
}
static NOINLINE UNUSED
-void transform_dis_branch(struct transform_dis_ctx *ctx,
- uintptr_t dpc, int cc) {
+void transform_dis_branch(struct transform_dis_ctx *ctx, uintptr_t dpc, int cc) {
#ifdef TRANSFORM_DIS_VERBOSE
printf("transform_dis (0x%llx): branch => 0x%llx\n",
(unsigned long long) ctx->base.pc,
(unsigned long long) dpc);
#endif
- if (dpc >= ctx->pc_patch_start && dpc < ctx->pc_patch_end) {
- /* don't support this for now */
- /* making the simplifying assumption here that functions will not try
- * to branch into the middle of an IT block, which is the case where
- * pc_patch_end changes to include additional instructions (as opposed
- * to include the end of a partially included instruction, which is
- * common) */
- ctx->err = SUBSTITUTE_ERR_FUNC_BAD_INSN_AT_START;
- return;
- }
+ /* The check in transform_dis_branch_top is correct under the simplifying
+ * assumption here that functions will not try to branch into the middle of
+ * an IT block, which is the case where pc_patch_end changes to include
+ * additional instructions (as opposed to include the end of a partially
+ * included instruction, which is common). */
+ transform_dis_branch_top(ctx, dpc, cc);
struct assemble_ctx actx = tdctx_to_actx(ctx);
ctx->write_newop_here = NULL;
if ((cc & CC_ARMCC) == CC_ARMCC) {
diff --git a/lib/arm/dis-arm.inc.h b/lib/arm/dis-arm.inc.h
index 3ae0ab9..ab61877 100644
--- a/lib/arm/dis-arm.inc.h
+++ b/lib/arm/dis-arm.inc.h
@@ -206,6 +206,13 @@ static INLINE void P(GPR_Rt_addr_offset_none_addr_postidx_reg_Rm_S_1_STRHTr)(tdi
static INLINE void P(GPR_dst_B_2_BX)(tdis_ctx ctx, UNUSED struct bitslice dst) {
return P(ret)(ctx);
}
+static INLINE void P(GPR_func_3_BLX)(tdis_ctx ctx, UNUSED struct bitslice func) {
+ return P(indirect_call)(ctx);
+}
+static INLINE void P(bl_target_func_2_BL)(tdis_ctx ctx, struct bitslice func) {
+ return P(branch)(ctx, ctx->base.pc + 8 + sext(bs_get(func, ctx->base.op), 24),
+ CC_CALL);
+}
static INLINE void P(dis_arm)(tdis_ctx ctx) {
uint32_t op = ctx->base.op = *(uint32_t *) ctx->base.ptr;
diff --git a/lib/arm/dis-thumb.inc.h b/lib/arm/dis-thumb.inc.h
index 4a2b747..4f758bf 100644
--- a/lib/arm/dis-thumb.inc.h
+++ b/lib/arm/dis-thumb.inc.h
@@ -81,6 +81,9 @@ static INLINE void P(it_pred_cc_it_mask_mask_1_t2IT)(tdis_ctx ctx, struct bitsli
ctx->arch.it_conds[i+2] = (cc_val & ~1) | (mask_val >> (3 - i) & 1);
return P(thumb_it)(ctx);
}
+static INLINE void P(GPR_func_1_tBLXr)(tdis_ctx ctx, UNUSED struct bitslice func) {
+ return P(indirect_call)(ctx);
+}
static INLINE void P(thumb_do_it)(tdis_ctx ctx) {
uint16_t op = ctx->base.op = *(uint16_t *) ctx->base.ptr;
diff --git a/lib/arm/dis-thumb2.inc.h b/lib/arm/dis-thumb2.inc.h
index 43ca4ab..5f699c9 100644
--- a/lib/arm/dis-thumb2.inc.h
+++ b/lib/arm/dis-thumb2.inc.h
@@ -170,6 +170,24 @@ static INLINE void P(unk_Rm_B_2_t2TBB)(tdis_ctx ctx, UNUSED struct bitslice Rm)
static INLINE void P(unk_Rt_13_VMOVRRD)(tdis_ctx ctx, UNUSED struct bitslice Rt) {
return P(unidentified)(ctx);
}
+static INLINE void P(t_bltarget_func_1_tBL)(tdis_ctx ctx, struct bitslice func) {
+ unsigned crap = bs_get(func, ctx->base.op) << 1;
+ unsigned S = crap >> 24 & 1;
+ if (S)
+ crap ^= (3 << 22);
+ return P(branch)(ctx, ctx->base.pc + 4 + 2 * sext(crap, 25), CC_CALL);
+
+}
+static INLINE void P(t_blxtarget_func_1_tBLXi)(tdis_ctx ctx, struct bitslice func) {
+ unsigned crap = bs_get(func, ctx->base.op);
+ unsigned S = crap >> 24 & 1;
+ if (S)
+ crap ^= (3 << 22);
+ return P(branch)(ctx, ctx->base.pc + 4 + 2 * sext(crap, 25), CC_CALL);
+}
+static INLINE void P(rGPR_func_1_t2BXJ)(tdis_ctx ctx, UNUSED struct bitslice func) {
+ return P(unidentified)(ctx);
+}
static INLINE void P(thumb2_do_it)(tdis_ctx ctx) {
uint32_t op = ctx->base.op;