aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorZi Shen Lim <zlim.lnx@gmail.com>2014-08-27 00:15:28 -0400
committerWill Deacon <will.deacon@arm.com>2014-09-08 09:39:20 -0400
commit27f95ba59b34509dc8afa2f89ad51c044df9d7c7 (patch)
tree219c0e3152d4a5e3ccd323bb50f339948ff94876 /arch
parent6481063989283f7cbeb0b6c38506ba4dd319f93a (diff)
arm64: introduce aarch64_insn_gen_data3()
Introduce function to generate data-processing (3 source) 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')
-rw-r--r--arch/arm64/include/asm/insn.h14
-rw-r--r--arch/arm64/kernel/insn.c42
2 files changed, 56 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index 367245fab9b7..36e8465cdf71 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -79,6 +79,7 @@ enum aarch64_insn_register_type {
79 AARCH64_INSN_REGTYPE_RT2, 79 AARCH64_INSN_REGTYPE_RT2,
80 AARCH64_INSN_REGTYPE_RM, 80 AARCH64_INSN_REGTYPE_RM,
81 AARCH64_INSN_REGTYPE_RD, 81 AARCH64_INSN_REGTYPE_RD,
82 AARCH64_INSN_REGTYPE_RA,
82}; 83};
83 84
84enum aarch64_insn_register { 85enum aarch64_insn_register {
@@ -200,6 +201,11 @@ enum aarch64_insn_data2_type {
200 AARCH64_INSN_DATA2_RORV, 201 AARCH64_INSN_DATA2_RORV,
201}; 202};
202 203
204enum aarch64_insn_data3_type {
205 AARCH64_INSN_DATA3_MADD,
206 AARCH64_INSN_DATA3_MSUB,
207};
208
203#define __AARCH64_INSN_FUNCS(abbr, mask, val) \ 209#define __AARCH64_INSN_FUNCS(abbr, mask, val) \
204static __always_inline bool aarch64_insn_is_##abbr(u32 code) \ 210static __always_inline bool aarch64_insn_is_##abbr(u32 code) \
205{ return (code & (mask)) == (val); } \ 211{ return (code & (mask)) == (val); } \
@@ -226,6 +232,8 @@ __AARCH64_INSN_FUNCS(add, 0x7F200000, 0x0B000000)
226__AARCH64_INSN_FUNCS(adds, 0x7F200000, 0x2B000000) 232__AARCH64_INSN_FUNCS(adds, 0x7F200000, 0x2B000000)
227__AARCH64_INSN_FUNCS(sub, 0x7F200000, 0x4B000000) 233__AARCH64_INSN_FUNCS(sub, 0x7F200000, 0x4B000000)
228__AARCH64_INSN_FUNCS(subs, 0x7F200000, 0x6B000000) 234__AARCH64_INSN_FUNCS(subs, 0x7F200000, 0x6B000000)
235__AARCH64_INSN_FUNCS(madd, 0x7FE08000, 0x1B000000)
236__AARCH64_INSN_FUNCS(msub, 0x7FE08000, 0x1B008000)
229__AARCH64_INSN_FUNCS(udiv, 0x7FE0FC00, 0x1AC00800) 237__AARCH64_INSN_FUNCS(udiv, 0x7FE0FC00, 0x1AC00800)
230__AARCH64_INSN_FUNCS(sdiv, 0x7FE0FC00, 0x1AC00C00) 238__AARCH64_INSN_FUNCS(sdiv, 0x7FE0FC00, 0x1AC00C00)
231__AARCH64_INSN_FUNCS(lslv, 0x7FE0FC00, 0x1AC02000) 239__AARCH64_INSN_FUNCS(lslv, 0x7FE0FC00, 0x1AC02000)
@@ -309,6 +317,12 @@ u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst,
309 enum aarch64_insn_register reg, 317 enum aarch64_insn_register reg,
310 enum aarch64_insn_variant variant, 318 enum aarch64_insn_variant variant,
311 enum aarch64_insn_data2_type type); 319 enum aarch64_insn_data2_type type);
320u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst,
321 enum aarch64_insn_register src,
322 enum aarch64_insn_register reg1,
323 enum aarch64_insn_register reg2,
324 enum aarch64_insn_variant variant,
325 enum aarch64_insn_data3_type type);
312 326
313bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn); 327bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
314 328
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index c054164c677b..f73a4bfbb946 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -302,6 +302,7 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type,
302 shift = 5; 302 shift = 5;
303 break; 303 break;
304 case AARCH64_INSN_REGTYPE_RT2: 304 case AARCH64_INSN_REGTYPE_RT2:
305 case AARCH64_INSN_REGTYPE_RA:
305 shift = 10; 306 shift = 10;
306 break; 307 break;
307 case AARCH64_INSN_REGTYPE_RM: 308 case AARCH64_INSN_REGTYPE_RM:
@@ -832,3 +833,44 @@ u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst,
832 833
833 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg); 834 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg);
834} 835}
836
837u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst,
838 enum aarch64_insn_register src,
839 enum aarch64_insn_register reg1,
840 enum aarch64_insn_register reg2,
841 enum aarch64_insn_variant variant,
842 enum aarch64_insn_data3_type type)
843{
844 u32 insn;
845
846 switch (type) {
847 case AARCH64_INSN_DATA3_MADD:
848 insn = aarch64_insn_get_madd_value();
849 break;
850 case AARCH64_INSN_DATA3_MSUB:
851 insn = aarch64_insn_get_msub_value();
852 break;
853 default:
854 BUG_ON(1);
855 }
856
857 switch (variant) {
858 case AARCH64_INSN_VARIANT_32BIT:
859 break;
860 case AARCH64_INSN_VARIANT_64BIT:
861 insn |= AARCH64_INSN_SF_BIT;
862 break;
863 default:
864 BUG_ON(1);
865 }
866
867 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
868
869 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RA, insn, src);
870
871 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
872 reg1);
873
874 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn,
875 reg2);
876}