Messages in this thread Patch in this message | | | From | Wang ShaoBo <> | Subject | [RFC PATCH -next v2 1/4] arm64: introduce aarch64_insn_gen_load_literal | Date | Wed, 16 Mar 2022 18:01:29 +0800 |
| |
From: Cheng Jian <cj.chengjian@huawei.com>
This introduces helper to generate ldr(literal) instructions.
LDR <Xt>, <label>
Signed-off-by: Cheng Jian <cj.chengjian@huawei.com> Signed-off-by: Wang ShaoBo <bobo.shaobowang@huawei.com> --- arch/arm64/include/asm/insn.h | 6 +++++ arch/arm64/lib/insn.c | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+)
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index 6b776c8667b2..95b3562843c2 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h @@ -458,6 +458,9 @@ u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_cr_op op); u32 aarch64_insn_gen_nop(void); u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, enum aarch64_insn_branch_type type); +u32 aarch64_insn_gen_load_literal(enum aarch64_insn_register reg, + enum aarch64_insn_variant variant, + long offset); u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg, enum aarch64_insn_register base, enum aarch64_insn_register offset, @@ -544,6 +547,9 @@ u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base, s32 aarch64_get_branch_offset(u32 insn); u32 aarch64_set_branch_offset(u32 insn, s32 offset); +s32 aarch64_insn_get_ldr_lit_offset(u32 insn); +u32 aarch64_insn_set_ldr_lit_offset(u32 insn, u32 offset); + s32 aarch64_insn_adrp_get_offset(u32 insn); u32 aarch64_insn_adrp_set_offset(u32 insn, s32 offset); diff --git a/arch/arm64/lib/insn.c b/arch/arm64/lib/insn.c index fccfe363e567..9ac5fb4e76e8 100644 --- a/arch/arm64/lib/insn.c +++ b/arch/arm64/lib/insn.c @@ -17,6 +17,7 @@ #include <asm/kprobes.h> #define AARCH64_INSN_SF_BIT BIT(31) +#define AARCH64_INSN_OPC_BIT BIT(30) #define AARCH64_INSN_N_BIT BIT(22) #define AARCH64_INSN_LSL_12 BIT(22) @@ -473,6 +474,54 @@ u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, reg); } +s32 aarch64_insn_get_ldr_lit_offset(u32 insn) +{ + s32 imm; + + if (aarch64_insn_is_ldr_lit(insn)) { + imm = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_19, insn); + return (imm << 13) >> 11; + } + + /* Unhandled instruction */ + BUG(); +} + +u32 aarch64_insn_set_ldr_lit_offset(u32 insn, u32 offset) +{ + if (aarch64_insn_is_ldr_lit(insn)) + return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn, + offset >> 2); + /* Unhandled instruction */ + BUG(); +} + +u32 aarch64_insn_gen_load_literal(enum aarch64_insn_register reg, + enum aarch64_insn_variant variant, + long offset) +{ + u32 insn; + + insn = aarch64_insn_get_ldr_lit_value(); + + switch (variant) { + case AARCH64_INSN_VARIANT_32BIT: + /* 32-bit ops == 00 */ + break; + case AARCH64_INSN_VARIANT_64BIT: + /* 64-bit opc == 01 */ + insn |= AARCH64_INSN_OPC_BIT; + break; + default: + pr_err("%s: unknown variant encoding %d\n", __func__, variant); + return AARCH64_BREAK_FAULT; + } + + insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg); + + return aarch64_insn_set_ldr_lit_offset(insn, offset); +} + u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg, enum aarch64_insn_register base, enum aarch64_insn_register offset, -- 2.25.1
| |