diff options
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/include/asm/insn.h | 25 | ||||
-rw-r--r-- | arch/arm64/kernel/insn.c | 60 |
2 files changed, 85 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index 36e8465cdf71..56a9e63b6c33 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h | |||
@@ -206,6 +206,17 @@ enum aarch64_insn_data3_type { | |||
206 | AARCH64_INSN_DATA3_MSUB, | 206 | AARCH64_INSN_DATA3_MSUB, |
207 | }; | 207 | }; |
208 | 208 | ||
209 | enum aarch64_insn_logic_type { | ||
210 | AARCH64_INSN_LOGIC_AND, | ||
211 | AARCH64_INSN_LOGIC_BIC, | ||
212 | AARCH64_INSN_LOGIC_ORR, | ||
213 | AARCH64_INSN_LOGIC_ORN, | ||
214 | AARCH64_INSN_LOGIC_EOR, | ||
215 | AARCH64_INSN_LOGIC_EON, | ||
216 | AARCH64_INSN_LOGIC_AND_SETFLAGS, | ||
217 | AARCH64_INSN_LOGIC_BIC_SETFLAGS | ||
218 | }; | ||
219 | |||
209 | #define __AARCH64_INSN_FUNCS(abbr, mask, val) \ | 220 | #define __AARCH64_INSN_FUNCS(abbr, mask, val) \ |
210 | static __always_inline bool aarch64_insn_is_##abbr(u32 code) \ | 221 | static __always_inline bool aarch64_insn_is_##abbr(u32 code) \ |
211 | { return (code & (mask)) == (val); } \ | 222 | { return (code & (mask)) == (val); } \ |
@@ -243,6 +254,14 @@ __AARCH64_INSN_FUNCS(rorv, 0x7FE0FC00, 0x1AC02C00) | |||
243 | __AARCH64_INSN_FUNCS(rev16, 0x7FFFFC00, 0x5AC00400) | 254 | __AARCH64_INSN_FUNCS(rev16, 0x7FFFFC00, 0x5AC00400) |
244 | __AARCH64_INSN_FUNCS(rev32, 0x7FFFFC00, 0x5AC00800) | 255 | __AARCH64_INSN_FUNCS(rev32, 0x7FFFFC00, 0x5AC00800) |
245 | __AARCH64_INSN_FUNCS(rev64, 0x7FFFFC00, 0x5AC00C00) | 256 | __AARCH64_INSN_FUNCS(rev64, 0x7FFFFC00, 0x5AC00C00) |
257 | __AARCH64_INSN_FUNCS(and, 0x7F200000, 0x0A000000) | ||
258 | __AARCH64_INSN_FUNCS(bic, 0x7F200000, 0x0A200000) | ||
259 | __AARCH64_INSN_FUNCS(orr, 0x7F200000, 0x2A000000) | ||
260 | __AARCH64_INSN_FUNCS(orn, 0x7F200000, 0x2A200000) | ||
261 | __AARCH64_INSN_FUNCS(eor, 0x7F200000, 0x4A000000) | ||
262 | __AARCH64_INSN_FUNCS(eon, 0x7F200000, 0x4A200000) | ||
263 | __AARCH64_INSN_FUNCS(ands, 0x7F200000, 0x6A000000) | ||
264 | __AARCH64_INSN_FUNCS(bics, 0x7F200000, 0x6A200000) | ||
246 | __AARCH64_INSN_FUNCS(b, 0xFC000000, 0x14000000) | 265 | __AARCH64_INSN_FUNCS(b, 0xFC000000, 0x14000000) |
247 | __AARCH64_INSN_FUNCS(bl, 0xFC000000, 0x94000000) | 266 | __AARCH64_INSN_FUNCS(bl, 0xFC000000, 0x94000000) |
248 | __AARCH64_INSN_FUNCS(cbz, 0xFE000000, 0x34000000) | 267 | __AARCH64_INSN_FUNCS(cbz, 0xFE000000, 0x34000000) |
@@ -323,6 +342,12 @@ u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst, | |||
323 | enum aarch64_insn_register reg2, | 342 | enum aarch64_insn_register reg2, |
324 | enum aarch64_insn_variant variant, | 343 | enum aarch64_insn_variant variant, |
325 | enum aarch64_insn_data3_type type); | 344 | enum aarch64_insn_data3_type type); |
345 | u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst, | ||
346 | enum aarch64_insn_register src, | ||
347 | enum aarch64_insn_register reg, | ||
348 | int shift, | ||
349 | enum aarch64_insn_variant variant, | ||
350 | enum aarch64_insn_logic_type type); | ||
326 | 351 | ||
327 | bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn); | 352 | bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn); |
328 | 353 | ||
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c index f73a4bfbb946..0668ee5c5bf9 100644 --- a/arch/arm64/kernel/insn.c +++ b/arch/arm64/kernel/insn.c | |||
@@ -874,3 +874,63 @@ u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst, | |||
874 | return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, | 874 | return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, |
875 | reg2); | 875 | reg2); |
876 | } | 876 | } |
877 | |||
878 | u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst, | ||
879 | enum aarch64_insn_register src, | ||
880 | enum aarch64_insn_register reg, | ||
881 | int shift, | ||
882 | enum aarch64_insn_variant variant, | ||
883 | enum aarch64_insn_logic_type type) | ||
884 | { | ||
885 | u32 insn; | ||
886 | |||
887 | switch (type) { | ||
888 | case AARCH64_INSN_LOGIC_AND: | ||
889 | insn = aarch64_insn_get_and_value(); | ||
890 | break; | ||
891 | case AARCH64_INSN_LOGIC_BIC: | ||
892 | insn = aarch64_insn_get_bic_value(); | ||
893 | break; | ||
894 | case AARCH64_INSN_LOGIC_ORR: | ||
895 | insn = aarch64_insn_get_orr_value(); | ||
896 | break; | ||
897 | case AARCH64_INSN_LOGIC_ORN: | ||
898 | insn = aarch64_insn_get_orn_value(); | ||
899 | break; | ||
900 | case AARCH64_INSN_LOGIC_EOR: | ||
901 | insn = aarch64_insn_get_eor_value(); | ||
902 | break; | ||
903 | case AARCH64_INSN_LOGIC_EON: | ||
904 | insn = aarch64_insn_get_eon_value(); | ||
905 | break; | ||
906 | case AARCH64_INSN_LOGIC_AND_SETFLAGS: | ||
907 | insn = aarch64_insn_get_ands_value(); | ||
908 | break; | ||
909 | case AARCH64_INSN_LOGIC_BIC_SETFLAGS: | ||
910 | insn = aarch64_insn_get_bics_value(); | ||
911 | break; | ||
912 | default: | ||
913 | BUG_ON(1); | ||
914 | } | ||
915 | |||
916 | switch (variant) { | ||
917 | case AARCH64_INSN_VARIANT_32BIT: | ||
918 | BUG_ON(shift & ~(SZ_32 - 1)); | ||
919 | break; | ||
920 | case AARCH64_INSN_VARIANT_64BIT: | ||
921 | insn |= AARCH64_INSN_SF_BIT; | ||
922 | BUG_ON(shift & ~(SZ_64 - 1)); | ||
923 | break; | ||
924 | default: | ||
925 | BUG_ON(1); | ||
926 | } | ||
927 | |||
928 | |||
929 | insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst); | ||
930 | |||
931 | insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src); | ||
932 | |||
933 | insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg); | ||
934 | |||
935 | return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_6, insn, shift); | ||
936 | } | ||