aboutsummaryrefslogtreecommitdiff
path: root/lib/arm64
diff options
context:
space:
mode:
Diffstat (limited to 'lib/arm64')
-rw-r--r--lib/arm64/arch-transform-dis.inc.h7
-rw-r--r--lib/arm64/assemble.h4
-rw-r--r--lib/arm64/dis-main.inc.h9
3 files changed, 11 insertions, 9 deletions
diff --git a/lib/arm64/arch-transform-dis.inc.h b/lib/arm64/arch-transform-dis.inc.h
index ac11e45..123c7ae 100644
--- a/lib/arm64/arch-transform-dis.inc.h
+++ b/lib/arm64/arch-transform-dis.inc.h
@@ -23,10 +23,7 @@ void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, int cc)
(unsigned long long) ctx->base.pc,
(unsigned long long) dpc);
#endif
- if (dpc >= ctx->pc_patch_start && dpc < ctx->pc_patch_end) {
- ctx->err = SUBSTITUTE_ERR_FUNC_BAD_INSN_AT_START;
- return;
- }
+ transform_dis_branch_top(ctx, dpc, cc);
ctx->write_newop_here = NULL;
int mov_br_size = size_of_MOVi64(dpc) + 4;
@@ -42,7 +39,7 @@ void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, int cc)
}
int reg = arm64_get_unwritten_temp_reg(&ctx->arch);
MOVi64(codep, reg, dpc);
- BR(codep, reg);
+ BR(codep, reg, /*link*/ cc & CC_CALL);
}
static void transform_dis_pre_dis(UNUSED struct transform_dis_ctx *ctx) {}
diff --git a/lib/arm64/assemble.h b/lib/arm64/assemble.h
index 1dca7eb..42c0f0c 100644
--- a/lib/arm64/assemble.h
+++ b/lib/arm64/assemble.h
@@ -56,8 +56,8 @@ static inline void ADRP_ADD(void **codep, int reg, uint64_t pc, uint64_t dpc) {
}
}
-static inline void BR(void **codep, int reg) {
- op32(codep, 0xd61f0000 | reg << 5);
+static inline void BR(void **codep, int reg, bool link) {
+ op32(codep, 0xd61f0000 | reg << 5 | link << 21);
}
static inline void Bccrel(void **codep, int cc, int offset) {
diff --git a/lib/arm64/dis-main.inc.h b/lib/arm64/dis-main.inc.h
index 0107715..a009189 100644
--- a/lib/arm64/dis-main.inc.h
+++ b/lib/arm64/dis-main.inc.h
@@ -55,8 +55,13 @@ static INLINE void P(am_ldrlit_label_unk_Rt_6_LDRDl)(tdis_ctx ctx, struct bitsli
return P(pcrel)(ctx, ctx->base.pc + sext(bs_get(label, ctx->base.op), 19) * 4,
(struct arch_pcrel_info) {bs_get(Rt, ctx->base.op), mode});
}
-static INLINE void P(GPR64_Rn_1_RET)(tdis_ctx ctx, UNUSED struct bitslice Rn) {
- return P(ret)(ctx);
+
+static INLINE void P(GPR64_Rn_2_BLR)(tdis_ctx ctx, UNUSED struct bitslice Rn) {
+ int op = ctx->base.op >> 21 & 3;
+ if (op == 1)
+ return P(indirect_call)(ctx);
+ else
+ return P(ret)(ctx);
}
static INLINE void P(dis)(tdis_ctx ctx) {