diff options
author | Zi Shen Lim <zlim.lnx@gmail.com> | 2014-08-27 05:15:22 +0100 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2014-09-08 14:39:20 +0100 |
commit | 9951a157fa678db0ec92e5fc4c6320c038ffb67e (patch) | |
tree | ee66008edd5ba09f12a418d9562e6d929236664e /arch/arm64/kernel/insn.c | |
parent | 1bba567d0f3050e33b4dd1404fdcbceaf5a73034 (diff) | |
download | linux-stable-9951a157fa678db0ec92e5fc4c6320c038ffb67e.tar.gz linux-stable-9951a157fa678db0ec92e5fc4c6320c038ffb67e.tar.bz2 linux-stable-9951a157fa678db0ec92e5fc4c6320c038ffb67e.zip |
arm64: introduce aarch64_insn_gen_add_sub_imm()
Introduce function to generate add/subtract (immediate) instructions.
Signed-off-by: Zi Shen Lim <zlim.lnx@gmail.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64/kernel/insn.c')
-rw-r--r-- | arch/arm64/kernel/insn.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c index 7880c060f684..ec3a90256ff9 100644 --- a/arch/arm64/kernel/insn.c +++ b/arch/arm64/kernel/insn.c @@ -285,6 +285,7 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, switch (type) { case AARCH64_INSN_REGTYPE_RT: + case AARCH64_INSN_REGTYPE_RD: shift = 0; break; case AARCH64_INSN_REGTYPE_RN: @@ -555,3 +556,46 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1, return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_7, insn, offset >> shift); } + +u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst, + enum aarch64_insn_register src, + int imm, enum aarch64_insn_variant variant, + enum aarch64_insn_adsb_type type) +{ + u32 insn; + + switch (type) { + case AARCH64_INSN_ADSB_ADD: + insn = aarch64_insn_get_add_imm_value(); + break; + case AARCH64_INSN_ADSB_SUB: + insn = aarch64_insn_get_sub_imm_value(); + break; + case AARCH64_INSN_ADSB_ADD_SETFLAGS: + insn = aarch64_insn_get_adds_imm_value(); + break; + case AARCH64_INSN_ADSB_SUB_SETFLAGS: + insn = aarch64_insn_get_subs_imm_value(); + break; + default: + BUG_ON(1); + } + + switch (variant) { + case AARCH64_INSN_VARIANT_32BIT: + break; + case AARCH64_INSN_VARIANT_64BIT: + insn |= AARCH64_INSN_SF_BIT; + break; + default: + BUG_ON(1); + } + + BUG_ON(imm & ~(SZ_4K - 1)); + + insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst); + + insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src); + + return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, imm); +} |