arm64: Add helper to decode register from instruction
authorSuzuki K Poulose <suzuki.poulose@arm.com>
Wed, 6 Apr 2022 16:45:27 +0000 (17:45 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 12 Apr 2022 05:52:15 +0000 (07:52 +0200)
commit 8c2dcbd2c4443bad0b4242fb62baa47b260b8f79 upstream.

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>
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/include/asm/insn.h
arch/arm64/kernel/insn.c

index bc853663dd517ee8a2f0f00ad8fd26cd715a26af..aecc07e09a18bd911a6df59554bf5261aa9f8ec7 100644 (file)
@@ -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,
index 6f2ac4fc66ca27bb3bd9ae29bdf96967e4b4580e..755b3dd3073e5b9ad8b3476cb77e62d28c1d1888 100644 (file)
@@ -418,6 +418,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)