Skip to content

Commit 4a89d2c

Browse files
zlimwildea01
authored andcommitted
arm64: introduce aarch64_insn_gen_bitfield()
Introduce function to generate bitfield 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>
1 parent 9951a15 commit 4a89d2c

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

arch/arm64/include/asm/insn.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ enum aarch64_insn_imm_type {
6767
AARCH64_INSN_IMM_12,
6868
AARCH64_INSN_IMM_9,
6969
AARCH64_INSN_IMM_7,
70+
AARCH64_INSN_IMM_S,
71+
AARCH64_INSN_IMM_R,
7072
AARCH64_INSN_IMM_MAX
7173
};
7274

@@ -170,6 +172,12 @@ enum aarch64_insn_adsb_type {
170172
AARCH64_INSN_ADSB_SUB_SETFLAGS
171173
};
172174

175+
enum aarch64_insn_bitfield_type {
176+
AARCH64_INSN_BITFIELD_MOVE,
177+
AARCH64_INSN_BITFIELD_MOVE_UNSIGNED,
178+
AARCH64_INSN_BITFIELD_MOVE_SIGNED
179+
};
180+
173181
#define __AARCH64_INSN_FUNCS(abbr, mask, val) \
174182
static __always_inline bool aarch64_insn_is_##abbr(u32 code) \
175183
{ return (code & (mask)) == (val); } \
@@ -186,6 +194,9 @@ __AARCH64_INSN_FUNCS(add_imm, 0x7F000000, 0x11000000)
186194
__AARCH64_INSN_FUNCS(adds_imm, 0x7F000000, 0x31000000)
187195
__AARCH64_INSN_FUNCS(sub_imm, 0x7F000000, 0x51000000)
188196
__AARCH64_INSN_FUNCS(subs_imm, 0x7F000000, 0x71000000)
197+
__AARCH64_INSN_FUNCS(sbfm, 0x7F800000, 0x13000000)
198+
__AARCH64_INSN_FUNCS(bfm, 0x7F800000, 0x33000000)
199+
__AARCH64_INSN_FUNCS(ubfm, 0x7F800000, 0x53000000)
189200
__AARCH64_INSN_FUNCS(b, 0xFC000000, 0x14000000)
190201
__AARCH64_INSN_FUNCS(bl, 0xFC000000, 0x94000000)
191202
__AARCH64_INSN_FUNCS(cbz, 0xFE000000, 0x34000000)
@@ -236,6 +247,11 @@ u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
236247
enum aarch64_insn_register src,
237248
int imm, enum aarch64_insn_variant variant,
238249
enum aarch64_insn_adsb_type type);
250+
u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst,
251+
enum aarch64_insn_register src,
252+
int immr, int imms,
253+
enum aarch64_insn_variant variant,
254+
enum aarch64_insn_bitfield_type type);
239255

240256
bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
241257

arch/arm64/kernel/insn.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <asm/insn.h>
2727

2828
#define AARCH64_INSN_SF_BIT BIT(31)
29+
#define AARCH64_INSN_N_BIT BIT(22)
2930

3031
static int aarch64_insn_encoding_class[] = {
3132
AARCH64_INSN_CLS_UNKNOWN,
@@ -259,6 +260,14 @@ u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type,
259260
mask = BIT(7) - 1;
260261
shift = 15;
261262
break;
263+
case AARCH64_INSN_IMM_S:
264+
mask = BIT(6) - 1;
265+
shift = 10;
266+
break;
267+
case AARCH64_INSN_IMM_R:
268+
mask = BIT(6) - 1;
269+
shift = 16;
270+
break;
262271
default:
263272
pr_err("aarch64_insn_encode_immediate: unknown immediate encoding %d\n",
264273
type);
@@ -599,3 +608,50 @@ u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
599608

600609
return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, imm);
601610
}
611+
612+
u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst,
613+
enum aarch64_insn_register src,
614+
int immr, int imms,
615+
enum aarch64_insn_variant variant,
616+
enum aarch64_insn_bitfield_type type)
617+
{
618+
u32 insn;
619+
u32 mask;
620+
621+
switch (type) {
622+
case AARCH64_INSN_BITFIELD_MOVE:
623+
insn = aarch64_insn_get_bfm_value();
624+
break;
625+
case AARCH64_INSN_BITFIELD_MOVE_UNSIGNED:
626+
insn = aarch64_insn_get_ubfm_value();
627+
break;
628+
case AARCH64_INSN_BITFIELD_MOVE_SIGNED:
629+
insn = aarch64_insn_get_sbfm_value();
630+
break;
631+
default:
632+
BUG_ON(1);
633+
}
634+
635+
switch (variant) {
636+
case AARCH64_INSN_VARIANT_32BIT:
637+
mask = GENMASK(4, 0);
638+
break;
639+
case AARCH64_INSN_VARIANT_64BIT:
640+
insn |= AARCH64_INSN_SF_BIT | AARCH64_INSN_N_BIT;
641+
mask = GENMASK(5, 0);
642+
break;
643+
default:
644+
BUG_ON(1);
645+
}
646+
647+
BUG_ON(immr & ~mask);
648+
BUG_ON(imms & ~mask);
649+
650+
insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
651+
652+
insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
653+
654+
insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_R, insn, immr);
655+
656+
return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_S, insn, imms);
657+
}

0 commit comments

Comments
 (0)