diff options
author | Suzuki K Poulose <suzuki.poulose@arm.com> | 2017-01-09 17:28:29 +0000 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2017-01-10 17:11:23 +0000 |
commit | 8c2dcbd2c4443bad0b4242fb62baa47b260b8f79 (patch) | |
tree | 0ff1e138c7fdcccdc0ac75e44636f9252bd5df4a /arch/arm64 | |
parent | c9ee0f98662a6e358b5f2969755c938ce9c3a63a (diff) | |
download | linux-stable-8c2dcbd2c4443bad0b4242fb62baa47b260b8f79.tar.gz linux-stable-8c2dcbd2c4443bad0b4242fb62baa47b260b8f79.tar.bz2 linux-stable-8c2dcbd2c4443bad0b4242fb62baa47b260b8f79.zip |
arm64: Add helper to decode register from instruction
Add a helper to extract the register field from a given
instruction.
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/include/asm/insn.h | 2 | ||||
-rw-r--r-- | arch/arm64/kernel/insn.c | 29 |
2 files changed, 31 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index bc853663dd51..aecc07e09a18 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h @@ -332,6 +332,8 @@ bool aarch64_insn_is_branch(u32 insn); u64 aarch64_insn_decode_immediate(enum aarch64_insn_imm_type type, u32 insn); u32 aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type, u32 insn, u64 imm); +u32 aarch64_insn_decode_register(enum aarch64_insn_register_type type, + u32 insn); u32 aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr, enum aarch64_insn_branch_type type); u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c index 94b62c1fa4df..1f44cf8c73e6 100644 --- a/arch/arm64/kernel/insn.c +++ b/arch/arm64/kernel/insn.c @@ -417,6 +417,35 @@ u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type, return insn; } +u32 aarch64_insn_decode_register(enum aarch64_insn_register_type type, + u32 insn) +{ + int shift; + + switch (type) { + case AARCH64_INSN_REGTYPE_RT: + case AARCH64_INSN_REGTYPE_RD: + shift = 0; + break; + case AARCH64_INSN_REGTYPE_RN: + shift = 5; + break; + case AARCH64_INSN_REGTYPE_RT2: + case AARCH64_INSN_REGTYPE_RA: + shift = 10; + break; + case AARCH64_INSN_REGTYPE_RM: + shift = 16; + break; + default: + pr_err("%s: unknown register type encoding %d\n", __func__, + type); + return 0; + } + + return (insn >> shift) & GENMASK(4, 0); +} + static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, u32 insn, enum aarch64_insn_register reg) |