diff options
Diffstat (limited to 'arch/arm64/include/asm/insn.h')
-rw-r--r-- | arch/arm64/include/asm/insn.h | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index dc1f73b13e74..56a9e63b6c33 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h | |||
@@ -2,6 +2,8 @@ | |||
2 | * Copyright (C) 2013 Huawei Ltd. | 2 | * Copyright (C) 2013 Huawei Ltd. |
3 | * Author: Jiang Liu <liuj97@gmail.com> | 3 | * Author: Jiang Liu <liuj97@gmail.com> |
4 | * | 4 | * |
5 | * Copyright (C) 2014 Zi Shen Lim <zlim.lnx@gmail.com> | ||
6 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
@@ -64,12 +66,155 @@ enum aarch64_insn_imm_type { | |||
64 | AARCH64_INSN_IMM_14, | 66 | AARCH64_INSN_IMM_14, |
65 | AARCH64_INSN_IMM_12, | 67 | AARCH64_INSN_IMM_12, |
66 | AARCH64_INSN_IMM_9, | 68 | AARCH64_INSN_IMM_9, |
69 | AARCH64_INSN_IMM_7, | ||
70 | AARCH64_INSN_IMM_6, | ||
71 | AARCH64_INSN_IMM_S, | ||
72 | AARCH64_INSN_IMM_R, | ||
67 | AARCH64_INSN_IMM_MAX | 73 | AARCH64_INSN_IMM_MAX |
68 | }; | 74 | }; |
69 | 75 | ||
76 | enum aarch64_insn_register_type { | ||
77 | AARCH64_INSN_REGTYPE_RT, | ||
78 | AARCH64_INSN_REGTYPE_RN, | ||
79 | AARCH64_INSN_REGTYPE_RT2, | ||
80 | AARCH64_INSN_REGTYPE_RM, | ||
81 | AARCH64_INSN_REGTYPE_RD, | ||
82 | AARCH64_INSN_REGTYPE_RA, | ||
83 | }; | ||
84 | |||
85 | enum aarch64_insn_register { | ||
86 | AARCH64_INSN_REG_0 = 0, | ||
87 | AARCH64_INSN_REG_1 = 1, | ||
88 | AARCH64_INSN_REG_2 = 2, | ||
89 | AARCH64_INSN_REG_3 = 3, | ||
90 | AARCH64_INSN_REG_4 = 4, | ||
91 | AARCH64_INSN_REG_5 = 5, | ||
92 | AARCH64_INSN_REG_6 = 6, | ||
93 | AARCH64_INSN_REG_7 = 7, | ||
94 | AARCH64_INSN_REG_8 = 8, | ||
95 | AARCH64_INSN_REG_9 = 9, | ||
96 | AARCH64_INSN_REG_10 = 10, | ||
97 | AARCH64_INSN_REG_11 = 11, | ||
98 | AARCH64_INSN_REG_12 = 12, | ||
99 | AARCH64_INSN_REG_13 = 13, | ||
100 | AARCH64_INSN_REG_14 = 14, | ||
101 | AARCH64_INSN_REG_15 = 15, | ||
102 | AARCH64_INSN_REG_16 = 16, | ||
103 | AARCH64_INSN_REG_17 = 17, | ||
104 | AARCH64_INSN_REG_18 = 18, | ||
105 | AARCH64_INSN_REG_19 = 19, | ||
106 | AARCH64_INSN_REG_20 = 20, | ||
107 | AARCH64_INSN_REG_21 = 21, | ||
108 | AARCH64_INSN_REG_22 = 22, | ||
109 | AARCH64_INSN_REG_23 = 23, | ||
110 | AARCH64_INSN_REG_24 = 24, | ||
111 | AARCH64_INSN_REG_25 = 25, | ||
112 | AARCH64_INSN_REG_26 = 26, | ||
113 | AARCH64_INSN_REG_27 = 27, | ||
114 | AARCH64_INSN_REG_28 = 28, | ||
115 | AARCH64_INSN_REG_29 = 29, | ||
116 | AARCH64_INSN_REG_FP = 29, /* Frame pointer */ | ||
117 | AARCH64_INSN_REG_30 = 30, | ||
118 | AARCH64_INSN_REG_LR = 30, /* Link register */ | ||
119 | AARCH64_INSN_REG_ZR = 31, /* Zero: as source register */ | ||
120 | AARCH64_INSN_REG_SP = 31 /* Stack pointer: as load/store base reg */ | ||
121 | }; | ||
122 | |||
123 | enum aarch64_insn_variant { | ||
124 | AARCH64_INSN_VARIANT_32BIT, | ||
125 | AARCH64_INSN_VARIANT_64BIT | ||
126 | }; | ||
127 | |||
128 | enum aarch64_insn_condition { | ||
129 | AARCH64_INSN_COND_EQ = 0x0, /* == */ | ||
130 | AARCH64_INSN_COND_NE = 0x1, /* != */ | ||
131 | AARCH64_INSN_COND_CS = 0x2, /* unsigned >= */ | ||
132 | AARCH64_INSN_COND_CC = 0x3, /* unsigned < */ | ||
133 | AARCH64_INSN_COND_MI = 0x4, /* < 0 */ | ||
134 | AARCH64_INSN_COND_PL = 0x5, /* >= 0 */ | ||
135 | AARCH64_INSN_COND_VS = 0x6, /* overflow */ | ||
136 | AARCH64_INSN_COND_VC = 0x7, /* no overflow */ | ||
137 | AARCH64_INSN_COND_HI = 0x8, /* unsigned > */ | ||
138 | AARCH64_INSN_COND_LS = 0x9, /* unsigned <= */ | ||
139 | AARCH64_INSN_COND_GE = 0xa, /* signed >= */ | ||
140 | AARCH64_INSN_COND_LT = 0xb, /* signed < */ | ||
141 | AARCH64_INSN_COND_GT = 0xc, /* signed > */ | ||
142 | AARCH64_INSN_COND_LE = 0xd, /* signed <= */ | ||
143 | AARCH64_INSN_COND_AL = 0xe, /* always */ | ||
144 | }; | ||
145 | |||
70 | enum aarch64_insn_branch_type { | 146 | enum aarch64_insn_branch_type { |
71 | AARCH64_INSN_BRANCH_NOLINK, | 147 | AARCH64_INSN_BRANCH_NOLINK, |
72 | AARCH64_INSN_BRANCH_LINK, | 148 | AARCH64_INSN_BRANCH_LINK, |
149 | AARCH64_INSN_BRANCH_RETURN, | ||
150 | AARCH64_INSN_BRANCH_COMP_ZERO, | ||
151 | AARCH64_INSN_BRANCH_COMP_NONZERO, | ||
152 | }; | ||
153 | |||
154 | enum aarch64_insn_size_type { | ||
155 | AARCH64_INSN_SIZE_8, | ||
156 | AARCH64_INSN_SIZE_16, | ||
157 | AARCH64_INSN_SIZE_32, | ||
158 | AARCH64_INSN_SIZE_64, | ||
159 | }; | ||
160 | |||
161 | enum aarch64_insn_ldst_type { | ||
162 | AARCH64_INSN_LDST_LOAD_REG_OFFSET, | ||
163 | AARCH64_INSN_LDST_STORE_REG_OFFSET, | ||
164 | AARCH64_INSN_LDST_LOAD_PAIR_PRE_INDEX, | ||
165 | AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX, | ||
166 | AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX, | ||
167 | AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX, | ||
168 | }; | ||
169 | |||
170 | enum aarch64_insn_adsb_type { | ||
171 | AARCH64_INSN_ADSB_ADD, | ||
172 | AARCH64_INSN_ADSB_SUB, | ||
173 | AARCH64_INSN_ADSB_ADD_SETFLAGS, | ||
174 | AARCH64_INSN_ADSB_SUB_SETFLAGS | ||
175 | }; | ||
176 | |||
177 | enum aarch64_insn_movewide_type { | ||
178 | AARCH64_INSN_MOVEWIDE_ZERO, | ||
179 | AARCH64_INSN_MOVEWIDE_KEEP, | ||
180 | AARCH64_INSN_MOVEWIDE_INVERSE | ||
181 | }; | ||
182 | |||
183 | enum aarch64_insn_bitfield_type { | ||
184 | AARCH64_INSN_BITFIELD_MOVE, | ||
185 | AARCH64_INSN_BITFIELD_MOVE_UNSIGNED, | ||
186 | AARCH64_INSN_BITFIELD_MOVE_SIGNED | ||
187 | }; | ||
188 | |||
189 | enum aarch64_insn_data1_type { | ||
190 | AARCH64_INSN_DATA1_REVERSE_16, | ||
191 | AARCH64_INSN_DATA1_REVERSE_32, | ||
192 | AARCH64_INSN_DATA1_REVERSE_64, | ||
193 | }; | ||
194 | |||
195 | enum aarch64_insn_data2_type { | ||
196 | AARCH64_INSN_DATA2_UDIV, | ||
197 | AARCH64_INSN_DATA2_SDIV, | ||
198 | AARCH64_INSN_DATA2_LSLV, | ||
199 | AARCH64_INSN_DATA2_LSRV, | ||
200 | AARCH64_INSN_DATA2_ASRV, | ||
201 | AARCH64_INSN_DATA2_RORV, | ||
202 | }; | ||
203 | |||
204 | enum aarch64_insn_data3_type { | ||
205 | AARCH64_INSN_DATA3_MADD, | ||
206 | AARCH64_INSN_DATA3_MSUB, | ||
207 | }; | ||
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 | ||
73 | }; | 218 | }; |
74 | 219 | ||
75 | #define __AARCH64_INSN_FUNCS(abbr, mask, val) \ | 220 | #define __AARCH64_INSN_FUNCS(abbr, mask, val) \ |
@@ -78,13 +223,58 @@ static __always_inline bool aarch64_insn_is_##abbr(u32 code) \ | |||
78 | static __always_inline u32 aarch64_insn_get_##abbr##_value(void) \ | 223 | static __always_inline u32 aarch64_insn_get_##abbr##_value(void) \ |
79 | { return (val); } | 224 | { return (val); } |
80 | 225 | ||
226 | __AARCH64_INSN_FUNCS(str_reg, 0x3FE0EC00, 0x38206800) | ||
227 | __AARCH64_INSN_FUNCS(ldr_reg, 0x3FE0EC00, 0x38606800) | ||
228 | __AARCH64_INSN_FUNCS(stp_post, 0x7FC00000, 0x28800000) | ||
229 | __AARCH64_INSN_FUNCS(ldp_post, 0x7FC00000, 0x28C00000) | ||
230 | __AARCH64_INSN_FUNCS(stp_pre, 0x7FC00000, 0x29800000) | ||
231 | __AARCH64_INSN_FUNCS(ldp_pre, 0x7FC00000, 0x29C00000) | ||
232 | __AARCH64_INSN_FUNCS(add_imm, 0x7F000000, 0x11000000) | ||
233 | __AARCH64_INSN_FUNCS(adds_imm, 0x7F000000, 0x31000000) | ||
234 | __AARCH64_INSN_FUNCS(sub_imm, 0x7F000000, 0x51000000) | ||
235 | __AARCH64_INSN_FUNCS(subs_imm, 0x7F000000, 0x71000000) | ||
236 | __AARCH64_INSN_FUNCS(movn, 0x7F800000, 0x12800000) | ||
237 | __AARCH64_INSN_FUNCS(sbfm, 0x7F800000, 0x13000000) | ||
238 | __AARCH64_INSN_FUNCS(bfm, 0x7F800000, 0x33000000) | ||
239 | __AARCH64_INSN_FUNCS(movz, 0x7F800000, 0x52800000) | ||
240 | __AARCH64_INSN_FUNCS(ubfm, 0x7F800000, 0x53000000) | ||
241 | __AARCH64_INSN_FUNCS(movk, 0x7F800000, 0x72800000) | ||
242 | __AARCH64_INSN_FUNCS(add, 0x7F200000, 0x0B000000) | ||
243 | __AARCH64_INSN_FUNCS(adds, 0x7F200000, 0x2B000000) | ||
244 | __AARCH64_INSN_FUNCS(sub, 0x7F200000, 0x4B000000) | ||
245 | __AARCH64_INSN_FUNCS(subs, 0x7F200000, 0x6B000000) | ||
246 | __AARCH64_INSN_FUNCS(madd, 0x7FE08000, 0x1B000000) | ||
247 | __AARCH64_INSN_FUNCS(msub, 0x7FE08000, 0x1B008000) | ||
248 | __AARCH64_INSN_FUNCS(udiv, 0x7FE0FC00, 0x1AC00800) | ||
249 | __AARCH64_INSN_FUNCS(sdiv, 0x7FE0FC00, 0x1AC00C00) | ||
250 | __AARCH64_INSN_FUNCS(lslv, 0x7FE0FC00, 0x1AC02000) | ||
251 | __AARCH64_INSN_FUNCS(lsrv, 0x7FE0FC00, 0x1AC02400) | ||
252 | __AARCH64_INSN_FUNCS(asrv, 0x7FE0FC00, 0x1AC02800) | ||
253 | __AARCH64_INSN_FUNCS(rorv, 0x7FE0FC00, 0x1AC02C00) | ||
254 | __AARCH64_INSN_FUNCS(rev16, 0x7FFFFC00, 0x5AC00400) | ||
255 | __AARCH64_INSN_FUNCS(rev32, 0x7FFFFC00, 0x5AC00800) | ||
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) | ||
81 | __AARCH64_INSN_FUNCS(b, 0xFC000000, 0x14000000) | 265 | __AARCH64_INSN_FUNCS(b, 0xFC000000, 0x14000000) |
82 | __AARCH64_INSN_FUNCS(bl, 0xFC000000, 0x94000000) | 266 | __AARCH64_INSN_FUNCS(bl, 0xFC000000, 0x94000000) |
267 | __AARCH64_INSN_FUNCS(cbz, 0xFE000000, 0x34000000) | ||
268 | __AARCH64_INSN_FUNCS(cbnz, 0xFE000000, 0x35000000) | ||
269 | __AARCH64_INSN_FUNCS(bcond, 0xFF000010, 0x54000000) | ||
83 | __AARCH64_INSN_FUNCS(svc, 0xFFE0001F, 0xD4000001) | 270 | __AARCH64_INSN_FUNCS(svc, 0xFFE0001F, 0xD4000001) |
84 | __AARCH64_INSN_FUNCS(hvc, 0xFFE0001F, 0xD4000002) | 271 | __AARCH64_INSN_FUNCS(hvc, 0xFFE0001F, 0xD4000002) |
85 | __AARCH64_INSN_FUNCS(smc, 0xFFE0001F, 0xD4000003) | 272 | __AARCH64_INSN_FUNCS(smc, 0xFFE0001F, 0xD4000003) |
86 | __AARCH64_INSN_FUNCS(brk, 0xFFE0001F, 0xD4200000) | 273 | __AARCH64_INSN_FUNCS(brk, 0xFFE0001F, 0xD4200000) |
87 | __AARCH64_INSN_FUNCS(hint, 0xFFFFF01F, 0xD503201F) | 274 | __AARCH64_INSN_FUNCS(hint, 0xFFFFF01F, 0xD503201F) |
275 | __AARCH64_INSN_FUNCS(br, 0xFFFFFC1F, 0xD61F0000) | ||
276 | __AARCH64_INSN_FUNCS(blr, 0xFFFFFC1F, 0xD63F0000) | ||
277 | __AARCH64_INSN_FUNCS(ret, 0xFFFFFC1F, 0xD65F0000) | ||
88 | 278 | ||
89 | #undef __AARCH64_INSN_FUNCS | 279 | #undef __AARCH64_INSN_FUNCS |
90 | 280 | ||
@@ -97,8 +287,67 @@ u32 aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type, | |||
97 | u32 insn, u64 imm); | 287 | u32 insn, u64 imm); |
98 | u32 aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr, | 288 | u32 aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr, |
99 | enum aarch64_insn_branch_type type); | 289 | enum aarch64_insn_branch_type type); |
290 | u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, | ||
291 | enum aarch64_insn_register reg, | ||
292 | enum aarch64_insn_variant variant, | ||
293 | enum aarch64_insn_branch_type type); | ||
294 | u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr, | ||
295 | enum aarch64_insn_condition cond); | ||
100 | u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_op op); | 296 | u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_op op); |
101 | u32 aarch64_insn_gen_nop(void); | 297 | u32 aarch64_insn_gen_nop(void); |
298 | u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, | ||
299 | enum aarch64_insn_branch_type type); | ||
300 | u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg, | ||
301 | enum aarch64_insn_register base, | ||
302 | enum aarch64_insn_register offset, | ||
303 | enum aarch64_insn_size_type size, | ||
304 | enum aarch64_insn_ldst_type type); | ||
305 | u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1, | ||
306 | enum aarch64_insn_register reg2, | ||
307 | enum aarch64_insn_register base, | ||
308 | int offset, | ||
309 | enum aarch64_insn_variant variant, | ||
310 | enum aarch64_insn_ldst_type type); | ||
311 | u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst, | ||
312 | enum aarch64_insn_register src, | ||
313 | int imm, enum aarch64_insn_variant variant, | ||
314 | enum aarch64_insn_adsb_type type); | ||
315 | u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst, | ||
316 | enum aarch64_insn_register src, | ||
317 | int immr, int imms, | ||
318 | enum aarch64_insn_variant variant, | ||
319 | enum aarch64_insn_bitfield_type type); | ||
320 | u32 aarch64_insn_gen_movewide(enum aarch64_insn_register dst, | ||
321 | int imm, int shift, | ||
322 | enum aarch64_insn_variant variant, | ||
323 | enum aarch64_insn_movewide_type type); | ||
324 | u32 aarch64_insn_gen_add_sub_shifted_reg(enum aarch64_insn_register dst, | ||
325 | enum aarch64_insn_register src, | ||
326 | enum aarch64_insn_register reg, | ||
327 | int shift, | ||
328 | enum aarch64_insn_variant variant, | ||
329 | enum aarch64_insn_adsb_type type); | ||
330 | u32 aarch64_insn_gen_data1(enum aarch64_insn_register dst, | ||
331 | enum aarch64_insn_register src, | ||
332 | enum aarch64_insn_variant variant, | ||
333 | enum aarch64_insn_data1_type type); | ||
334 | u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst, | ||
335 | enum aarch64_insn_register src, | ||
336 | enum aarch64_insn_register reg, | ||
337 | enum aarch64_insn_variant variant, | ||
338 | enum aarch64_insn_data2_type type); | ||
339 | u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst, | ||
340 | enum aarch64_insn_register src, | ||
341 | enum aarch64_insn_register reg1, | ||
342 | enum aarch64_insn_register reg2, | ||
343 | enum aarch64_insn_variant variant, | ||
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); | ||
102 | 351 | ||
103 | bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn); | 352 | bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn); |
104 | 353 | ||