diff options
Diffstat (limited to 'lib/arm')
-rw-r--r-- | lib/arm/arch-transform-dis.inc.h | 3 | ||||
-rw-r--r-- | lib/arm/assemble.h | 16 | ||||
-rw-r--r-- | lib/arm/jump-patch.h | 4 |
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, |