aboutsummaryrefslogtreecommitdiff
path: root/lib/arm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/arm')
-rw-r--r--lib/arm/arch-transform-dis.inc.h3
-rw-r--r--lib/arm/assemble.h16
-rw-r--r--lib/arm/jump-patch.h4
3 files changed, 20 insertions, 3 deletions
diff --git a/lib/arm/arch-transform-dis.inc.h b/lib/arm/arch-transform-dis.inc.h
index d74a06f..1e9579d 100644
--- a/lib/arm/arch-transform-dis.inc.h
+++ b/lib/arm/arch-transform-dis.inc.h
@@ -36,7 +36,7 @@ void transform_dis_data(struct transform_dis_ctx *ctx, unsigned o0, unsigned o1,
/* We only care if at least one op is PC, so quickly approximate that. */
if (((o0 | o1 | o2 | o3) & 15) != 15)
return;
- unsigned *newval = ctx->base.newval;
+ uint32_t *newval = ctx->base.newval;
newval[0] = o0;
newval[1] = o1;
newval[2] = o2;
@@ -178,6 +178,7 @@ void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, int cc)
void **codep = ctx->rewritten_ptr_ptr;
ctx->write_newop_here = *codep; *codep += 2;
}
+ /* If it's a call, we should jump back after the call */
actx.cond = 0xe;
MOVW_MOVT(actx, 14, dpc | ctx->arch.pc_low_bit);
BLXr(actx, 14);
diff --git a/lib/arm/assemble.h b/lib/arm/assemble.h
index 1d4250b..3066802 100644
--- a/lib/arm/assemble.h
+++ b/lib/arm/assemble.h
@@ -20,6 +20,13 @@ static inline void PUSHone(struct assemble_ctx ctx, int Rt) {
op32(ctx.codep, 0x052d0004 | Rt << 12 | ctx.cond << 28);
}
+static inline void PUSHmulti(struct assemble_ctx ctx, uint16_t mask) {
+ if (ctx.thumb)
+ op32(ctx.codep, 0x0000e92d | mask << 16);
+ else
+ op32(ctx.codep, 0x092d0000 | mask | ctx.cond << 28);
+}
+
static inline void POPone(struct assemble_ctx ctx, int Rt) {
if (ctx.thumb)
op32(ctx.codep, 0x0b04f85d | Rt << 28);
@@ -120,4 +127,13 @@ static inline void LDR_PC(struct assemble_ctx ctx, uint32_t dpc) {
else
op32(ctx.codep, 0x051ff004 | ctx.cond << 28);
op32(ctx.codep, (uint32_t) dpc);
+ if (ctx.pc & 2) // for alignment
+ op16(ctx.codep, 0xbf00);
+}
+
+static inline void ADD_PC(struct assemble_ctx ctx, uint32_t Rd, uint32_t imm12) {
+ if (ctx.thumb)
+ op32(ctx.codep, 0x0000f20f | ((imm12 >> 11) << 10) | (((imm12 & 0x700) >> 8) << 28) | Rd << 24 | (imm12 & 0xff) << 16);
+ else
+ op32(ctx.codep, 0x028f0000 | Rd << 12 | imm12 << 0 | ctx.cond << 28);
}
diff --git a/lib/arm/jump-patch.h b/lib/arm/jump-patch.h
index 8787070..8ba4c3a 100644
--- a/lib/arm/jump-patch.h
+++ b/lib/arm/jump-patch.h
@@ -1,14 +1,14 @@
#pragma once
#include "dis.h"
#include "arm/assemble.h"
-#define MAX_JUMP_PATCH_SIZE 8
+#define MAX_JUMP_PATCH_SIZE 12
#define MAX_EXTENDED_PATCH_SIZE (MAX_JUMP_PATCH_SIZE+14)
static inline int jump_patch_size(uint_tptr pc,
UNUSED uint_tptr dpc,
UNUSED struct arch_dis_ctx arch,
UNUSED bool force) {
- return (pc & 2) ? 10 : 8;
+ return (pc & 2) ? 12 : 8;
}
static inline void make_jump_patch(void **codep, uint_tptr pc,