bpf: Remove is_valid_bpf_tramp_flags()
[linux-block.git] / arch / arm64 / lib / insn.c
CommitLineData
caab277b 1// SPDX-License-Identifier: GPL-2.0-only
b11a64a4
JL
2/*
3 * Copyright (C) 2013 Huawei Ltd.
4 * Author: Jiang Liu <liuj97@gmail.com>
5 *
c94ae4f7 6 * Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com>
b11a64a4 7 */
5c5bf25d 8#include <linux/bitops.h>
2f896d58 9#include <linux/bug.h>
5f154c4e
JT
10#include <linux/printk.h>
11#include <linux/sizes.h>
2f896d58 12#include <linux/types.h>
a9ae04c9 13
a9ae04c9 14#include <asm/debug-monitors.h>
5f154c4e 15#include <asm/errno.h>
b11a64a4 16#include <asm/insn.h>
7d134b2c 17#include <asm/kprobes.h>
b11a64a4 18
617d2fbc 19#define AARCH64_INSN_SF_BIT BIT(31)
4a89d2c9 20#define AARCH64_INSN_N_BIT BIT(22)
11d76407 21#define AARCH64_INSN_LSL_12 BIT(22)
617d2fbc 22
0da23df2 23static const int aarch64_insn_encoding_class[] = {
b11a64a4
JL
24 AARCH64_INSN_CLS_UNKNOWN,
25 AARCH64_INSN_CLS_UNKNOWN,
427bfc59 26 AARCH64_INSN_CLS_SVE,
b11a64a4
JL
27 AARCH64_INSN_CLS_UNKNOWN,
28 AARCH64_INSN_CLS_LDST,
29 AARCH64_INSN_CLS_DP_REG,
30 AARCH64_INSN_CLS_LDST,
31 AARCH64_INSN_CLS_DP_FPSIMD,
32 AARCH64_INSN_CLS_DP_IMM,
33 AARCH64_INSN_CLS_DP_IMM,
34 AARCH64_INSN_CLS_BR_SYS,
35 AARCH64_INSN_CLS_BR_SYS,
36 AARCH64_INSN_CLS_LDST,
37 AARCH64_INSN_CLS_DP_REG,
38 AARCH64_INSN_CLS_LDST,
39 AARCH64_INSN_CLS_DP_FPSIMD,
40};
41
42enum aarch64_insn_encoding_class __kprobes aarch64_get_insn_class(u32 insn)
43{
44 return aarch64_insn_encoding_class[(insn >> 25) & 0xf];
45}
46
07dcd967 47bool __kprobes aarch64_insn_is_steppable_hint(u32 insn)
b11a64a4
JL
48{
49 if (!aarch64_insn_is_hint(insn))
50 return false;
51
52 switch (insn & 0xFE0) {
47d67e4d
MB
53 case AARCH64_INSN_HINT_XPACLRI:
54 case AARCH64_INSN_HINT_PACIA_1716:
55 case AARCH64_INSN_HINT_PACIB_1716:
47d67e4d
MB
56 case AARCH64_INSN_HINT_PACIAZ:
57 case AARCH64_INSN_HINT_PACIASP:
58 case AARCH64_INSN_HINT_PACIBZ:
59 case AARCH64_INSN_HINT_PACIBSP:
47d67e4d
MB
60 case AARCH64_INSN_HINT_BTI:
61 case AARCH64_INSN_HINT_BTIC:
62 case AARCH64_INSN_HINT_BTIJ:
63 case AARCH64_INSN_HINT_BTIJC:
c71052cc 64 case AARCH64_INSN_HINT_NOP:
b11a64a4 65 return true;
c71052cc
MB
66 default:
67 return false;
b11a64a4
JL
68 }
69}
70
10b48f7e
MZ
71bool aarch64_insn_is_branch_imm(u32 insn)
72{
73 return (aarch64_insn_is_b(insn) || aarch64_insn_is_bl(insn) ||
74 aarch64_insn_is_tbz(insn) || aarch64_insn_is_tbnz(insn) ||
75 aarch64_insn_is_cbz(insn) || aarch64_insn_is_cbnz(insn) ||
76 aarch64_insn_is_bcond(insn));
77}
78
d59bee88
DL
79bool __kprobes aarch64_insn_uses_literal(u32 insn)
80{
81 /* ldr/ldrsw (literal), prfm */
82
83 return aarch64_insn_is_ldr_lit(insn) ||
84 aarch64_insn_is_ldrsw_lit(insn) ||
85 aarch64_insn_is_adr_adrp(insn) ||
86 aarch64_insn_is_prfm_lit(insn);
87}
88
89bool __kprobes aarch64_insn_is_branch(u32 insn)
90{
93396936 91 /* b, bl, cb*, tb*, ret*, b.cond, br*, blr* */
d59bee88
DL
92
93 return aarch64_insn_is_b(insn) ||
94 aarch64_insn_is_bl(insn) ||
95 aarch64_insn_is_cbz(insn) ||
96 aarch64_insn_is_cbnz(insn) ||
97 aarch64_insn_is_tbz(insn) ||
98 aarch64_insn_is_tbnz(insn) ||
99 aarch64_insn_is_ret(insn) ||
93396936 100 aarch64_insn_is_ret_auth(insn) ||
d59bee88 101 aarch64_insn_is_br(insn) ||
93396936 102 aarch64_insn_is_br_auth(insn) ||
d59bee88 103 aarch64_insn_is_blr(insn) ||
93396936 104 aarch64_insn_is_blr_auth(insn) ||
d59bee88
DL
105 aarch64_insn_is_bcond(insn);
106}
107
0978fb25
MZ
108static int __kprobes aarch64_get_imm_shift_mask(enum aarch64_insn_imm_type type,
109 u32 *maskp, int *shiftp)
c84fced8 110{
0978fb25 111 u32 mask;
c84fced8
JL
112 int shift;
113
114 switch (type) {
c84fced8
JL
115 case AARCH64_INSN_IMM_26:
116 mask = BIT(26) - 1;
117 shift = 0;
118 break;
119 case AARCH64_INSN_IMM_19:
120 mask = BIT(19) - 1;
121 shift = 5;
122 break;
123 case AARCH64_INSN_IMM_16:
124 mask = BIT(16) - 1;
125 shift = 5;
126 break;
127 case AARCH64_INSN_IMM_14:
128 mask = BIT(14) - 1;
129 shift = 5;
130 break;
131 case AARCH64_INSN_IMM_12:
132 mask = BIT(12) - 1;
133 shift = 10;
134 break;
135 case AARCH64_INSN_IMM_9:
136 mask = BIT(9) - 1;
137 shift = 12;
138 break;
1bba567d
ZSL
139 case AARCH64_INSN_IMM_7:
140 mask = BIT(7) - 1;
141 shift = 15;
142 break;
5fdc639a 143 case AARCH64_INSN_IMM_6:
4a89d2c9
ZSL
144 case AARCH64_INSN_IMM_S:
145 mask = BIT(6) - 1;
146 shift = 10;
147 break;
148 case AARCH64_INSN_IMM_R:
149 mask = BIT(6) - 1;
150 shift = 16;
151 break;
a264bf34
MZ
152 case AARCH64_INSN_IMM_N:
153 mask = 1;
154 shift = 22;
155 break;
c84fced8 156 default:
0978fb25
MZ
157 return -EINVAL;
158 }
159
160 *maskp = mask;
161 *shiftp = shift;
162
163 return 0;
164}
165
166#define ADR_IMM_HILOSPLIT 2
167#define ADR_IMM_SIZE SZ_2M
168#define ADR_IMM_LOMASK ((1 << ADR_IMM_HILOSPLIT) - 1)
169#define ADR_IMM_HIMASK ((ADR_IMM_SIZE >> ADR_IMM_HILOSPLIT) - 1)
170#define ADR_IMM_LOSHIFT 29
171#define ADR_IMM_HISHIFT 5
172
173u64 aarch64_insn_decode_immediate(enum aarch64_insn_imm_type type, u32 insn)
174{
175 u32 immlo, immhi, mask;
176 int shift;
177
178 switch (type) {
179 case AARCH64_INSN_IMM_ADR:
180 shift = 0;
181 immlo = (insn >> ADR_IMM_LOSHIFT) & ADR_IMM_LOMASK;
182 immhi = (insn >> ADR_IMM_HISHIFT) & ADR_IMM_HIMASK;
183 insn = (immhi << ADR_IMM_HILOSPLIT) | immlo;
184 mask = ADR_IMM_SIZE - 1;
185 break;
186 default:
187 if (aarch64_get_imm_shift_mask(type, &mask, &shift) < 0) {
2806556c 188 pr_err("%s: unknown immediate encoding %d\n", __func__,
0978fb25
MZ
189 type);
190 return 0;
191 }
192 }
193
194 return (insn >> shift) & mask;
195}
196
197u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type,
198 u32 insn, u64 imm)
199{
200 u32 immlo, immhi, mask;
201 int shift;
202
c94ae4f7
ZSL
203 if (insn == AARCH64_BREAK_FAULT)
204 return AARCH64_BREAK_FAULT;
205
0978fb25
MZ
206 switch (type) {
207 case AARCH64_INSN_IMM_ADR:
208 shift = 0;
209 immlo = (imm & ADR_IMM_LOMASK) << ADR_IMM_LOSHIFT;
210 imm >>= ADR_IMM_HILOSPLIT;
211 immhi = (imm & ADR_IMM_HIMASK) << ADR_IMM_HISHIFT;
212 imm = immlo | immhi;
213 mask = ((ADR_IMM_LOMASK << ADR_IMM_LOSHIFT) |
214 (ADR_IMM_HIMASK << ADR_IMM_HISHIFT));
215 break;
216 default:
217 if (aarch64_get_imm_shift_mask(type, &mask, &shift) < 0) {
2806556c 218 pr_err("%s: unknown immediate encoding %d\n", __func__,
0978fb25 219 type);
c94ae4f7 220 return AARCH64_BREAK_FAULT;
0978fb25 221 }
c84fced8
JL
222 }
223
224 /* Update the immediate field. */
225 insn &= ~(mask << shift);
226 insn |= (imm & mask) << shift;
227
228 return insn;
229}
5c5bf25d 230
8c2dcbd2
SP
231u32 aarch64_insn_decode_register(enum aarch64_insn_register_type type,
232 u32 insn)
233{
234 int shift;
235
236 switch (type) {
237 case AARCH64_INSN_REGTYPE_RT:
238 case AARCH64_INSN_REGTYPE_RD:
239 shift = 0;
240 break;
241 case AARCH64_INSN_REGTYPE_RN:
242 shift = 5;
243 break;
244 case AARCH64_INSN_REGTYPE_RT2:
245 case AARCH64_INSN_REGTYPE_RA:
246 shift = 10;
247 break;
248 case AARCH64_INSN_REGTYPE_RM:
249 shift = 16;
250 break;
251 default:
252 pr_err("%s: unknown register type encoding %d\n", __func__,
253 type);
254 return 0;
255 }
256
257 return (insn >> shift) & GENMASK(4, 0);
258}
259
617d2fbc
ZSL
260static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type,
261 u32 insn,
262 enum aarch64_insn_register reg)
263{
264 int shift;
265
c94ae4f7
ZSL
266 if (insn == AARCH64_BREAK_FAULT)
267 return AARCH64_BREAK_FAULT;
268
617d2fbc
ZSL
269 if (reg < AARCH64_INSN_REG_0 || reg > AARCH64_INSN_REG_SP) {
270 pr_err("%s: unknown register encoding %d\n", __func__, reg);
c94ae4f7 271 return AARCH64_BREAK_FAULT;
617d2fbc
ZSL
272 }
273
274 switch (type) {
275 case AARCH64_INSN_REGTYPE_RT:
9951a157 276 case AARCH64_INSN_REGTYPE_RD:
617d2fbc
ZSL
277 shift = 0;
278 break;
c0cafbae
ZSL
279 case AARCH64_INSN_REGTYPE_RN:
280 shift = 5;
281 break;
1bba567d 282 case AARCH64_INSN_REGTYPE_RT2:
27f95ba5 283 case AARCH64_INSN_REGTYPE_RA:
1bba567d
ZSL
284 shift = 10;
285 break;
17cac179 286 case AARCH64_INSN_REGTYPE_RM:
85f68fe8 287 case AARCH64_INSN_REGTYPE_RS:
17cac179
ZSL
288 shift = 16;
289 break;
617d2fbc
ZSL
290 default:
291 pr_err("%s: unknown register type encoding %d\n", __func__,
292 type);
c94ae4f7 293 return AARCH64_BREAK_FAULT;
617d2fbc
ZSL
294 }
295
296 insn &= ~(GENMASK(4, 0) << shift);
297 insn |= reg << shift;
298
299 return insn;
300}
301
30c90f67
XK
302static const u32 aarch64_insn_ldst_size[] = {
303 [AARCH64_INSN_SIZE_8] = 0,
304 [AARCH64_INSN_SIZE_16] = 1,
305 [AARCH64_INSN_SIZE_32] = 2,
306 [AARCH64_INSN_SIZE_64] = 3,
307};
308
17cac179
ZSL
309static u32 aarch64_insn_encode_ldst_size(enum aarch64_insn_size_type type,
310 u32 insn)
311{
312 u32 size;
313
30c90f67 314 if (type < AARCH64_INSN_SIZE_8 || type > AARCH64_INSN_SIZE_64) {
17cac179 315 pr_err("%s: unknown size encoding %d\n", __func__, type);
c94ae4f7 316 return AARCH64_BREAK_FAULT;
17cac179
ZSL
317 }
318
30c90f67 319 size = aarch64_insn_ldst_size[type];
17cac179
ZSL
320 insn &= ~GENMASK(31, 30);
321 insn |= size << 30;
322
323 return insn;
324}
325
617d2fbc
ZSL
326static inline long branch_imm_common(unsigned long pc, unsigned long addr,
327 long range)
5c5bf25d 328{
5c5bf25d
JL
329 long offset;
330
c94ae4f7
ZSL
331 if ((pc & 0x3) || (addr & 0x3)) {
332 pr_err("%s: A64 instructions must be word aligned\n", __func__);
333 return range;
334 }
5c5bf25d 335
617d2fbc 336 offset = ((long)addr - (long)pc);
c94ae4f7
ZSL
337
338 if (offset < -range || offset >= range) {
339 pr_err("%s: offset out of range\n", __func__);
340 return range;
341 }
617d2fbc
ZSL
342
343 return offset;
344}
345
346u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr,
347 enum aarch64_insn_branch_type type)
348{
349 u32 insn;
350 long offset;
351
5c5bf25d
JL
352 /*
353 * B/BL support [-128M, 128M) offset
354 * ARM64 virtual address arrangement guarantees all kernel and module
355 * texts are within +/-128M.
356 */
617d2fbc 357 offset = branch_imm_common(pc, addr, SZ_128M);
c94ae4f7
ZSL
358 if (offset >= SZ_128M)
359 return AARCH64_BREAK_FAULT;
5c5bf25d 360
c0cafbae
ZSL
361 switch (type) {
362 case AARCH64_INSN_BRANCH_LINK:
5c5bf25d 363 insn = aarch64_insn_get_bl_value();
c0cafbae
ZSL
364 break;
365 case AARCH64_INSN_BRANCH_NOLINK:
5c5bf25d 366 insn = aarch64_insn_get_b_value();
c0cafbae
ZSL
367 break;
368 default:
c94ae4f7 369 pr_err("%s: unknown branch encoding %d\n", __func__, type);
a9ae04c9 370 return AARCH64_BREAK_FAULT;
c0cafbae 371 }
5c5bf25d
JL
372
373 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_26, insn,
374 offset >> 2);
375}
376
617d2fbc
ZSL
377u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr,
378 enum aarch64_insn_register reg,
379 enum aarch64_insn_variant variant,
380 enum aarch64_insn_branch_type type)
381{
382 u32 insn;
383 long offset;
384
385 offset = branch_imm_common(pc, addr, SZ_1M);
c94ae4f7
ZSL
386 if (offset >= SZ_1M)
387 return AARCH64_BREAK_FAULT;
617d2fbc
ZSL
388
389 switch (type) {
390 case AARCH64_INSN_BRANCH_COMP_ZERO:
391 insn = aarch64_insn_get_cbz_value();
392 break;
393 case AARCH64_INSN_BRANCH_COMP_NONZERO:
394 insn = aarch64_insn_get_cbnz_value();
395 break;
396 default:
c94ae4f7 397 pr_err("%s: unknown branch encoding %d\n", __func__, type);
a9ae04c9 398 return AARCH64_BREAK_FAULT;
617d2fbc
ZSL
399 }
400
401 switch (variant) {
402 case AARCH64_INSN_VARIANT_32BIT:
403 break;
404 case AARCH64_INSN_VARIANT_64BIT:
405 insn |= AARCH64_INSN_SF_BIT;
406 break;
407 default:
c94ae4f7 408 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
a9ae04c9 409 return AARCH64_BREAK_FAULT;
617d2fbc
ZSL
410 }
411
412 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg);
413
414 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
415 offset >> 2);
416}
417
345e0d35
ZSL
418u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr,
419 enum aarch64_insn_condition cond)
420{
421 u32 insn;
422 long offset;
423
424 offset = branch_imm_common(pc, addr, SZ_1M);
425
426 insn = aarch64_insn_get_bcond_value();
427
c94ae4f7
ZSL
428 if (cond < AARCH64_INSN_COND_EQ || cond > AARCH64_INSN_COND_AL) {
429 pr_err("%s: unknown condition encoding %d\n", __func__, cond);
430 return AARCH64_BREAK_FAULT;
431 }
345e0d35
ZSL
432 insn |= cond;
433
434 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
435 offset >> 2);
436}
437
bd507ca2 438u32 __kprobes aarch64_insn_gen_hint(enum aarch64_insn_hint_cr_op op)
5c5bf25d
JL
439{
440 return aarch64_insn_get_hint_value() | op;
441}
442
443u32 __kprobes aarch64_insn_gen_nop(void)
444{
445 return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP);
446}
c0cafbae
ZSL
447
448u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg,
449 enum aarch64_insn_branch_type type)
450{
451 u32 insn;
452
453 switch (type) {
454 case AARCH64_INSN_BRANCH_NOLINK:
455 insn = aarch64_insn_get_br_value();
456 break;
457 case AARCH64_INSN_BRANCH_LINK:
458 insn = aarch64_insn_get_blr_value();
459 break;
460 case AARCH64_INSN_BRANCH_RETURN:
461 insn = aarch64_insn_get_ret_value();
462 break;
463 default:
c94ae4f7 464 pr_err("%s: unknown branch encoding %d\n", __func__, type);
a9ae04c9 465 return AARCH64_BREAK_FAULT;
c0cafbae
ZSL
466 }
467
468 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, reg);
469}
17cac179
ZSL
470
471u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg,
472 enum aarch64_insn_register base,
473 enum aarch64_insn_register offset,
474 enum aarch64_insn_size_type size,
475 enum aarch64_insn_ldst_type type)
476{
477 u32 insn;
478
479 switch (type) {
480 case AARCH64_INSN_LDST_LOAD_REG_OFFSET:
481 insn = aarch64_insn_get_ldr_reg_value();
482 break;
483 case AARCH64_INSN_LDST_STORE_REG_OFFSET:
484 insn = aarch64_insn_get_str_reg_value();
485 break;
486 default:
c94ae4f7 487 pr_err("%s: unknown load/store encoding %d\n", __func__, type);
a9ae04c9 488 return AARCH64_BREAK_FAULT;
17cac179
ZSL
489 }
490
491 insn = aarch64_insn_encode_ldst_size(size, insn);
492
493 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg);
494
495 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
496 base);
497
498 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn,
499 offset);
500}
1bba567d 501
30c90f67
XK
502u32 aarch64_insn_gen_load_store_imm(enum aarch64_insn_register reg,
503 enum aarch64_insn_register base,
504 unsigned int imm,
505 enum aarch64_insn_size_type size,
506 enum aarch64_insn_ldst_type type)
507{
508 u32 insn;
509 u32 shift;
510
511 if (size < AARCH64_INSN_SIZE_8 || size > AARCH64_INSN_SIZE_64) {
512 pr_err("%s: unknown size encoding %d\n", __func__, type);
513 return AARCH64_BREAK_FAULT;
514 }
515
516 shift = aarch64_insn_ldst_size[size];
517 if (imm & ~(BIT(12 + shift) - BIT(shift))) {
518 pr_err("%s: invalid imm: %d\n", __func__, imm);
519 return AARCH64_BREAK_FAULT;
520 }
521
522 imm >>= shift;
523
524 switch (type) {
525 case AARCH64_INSN_LDST_LOAD_IMM_OFFSET:
526 insn = aarch64_insn_get_ldr_imm_value();
527 break;
528 case AARCH64_INSN_LDST_STORE_IMM_OFFSET:
529 insn = aarch64_insn_get_str_imm_value();
530 break;
531 default:
532 pr_err("%s: unknown load/store encoding %d\n", __func__, type);
533 return AARCH64_BREAK_FAULT;
534 }
535
536 insn = aarch64_insn_encode_ldst_size(size, insn);
537
538 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg);
539
540 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
541 base);
542
543 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, imm);
544}
545
1bba567d
ZSL
546u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
547 enum aarch64_insn_register reg2,
548 enum aarch64_insn_register base,
549 int offset,
550 enum aarch64_insn_variant variant,
551 enum aarch64_insn_ldst_type type)
552{
553 u32 insn;
554 int shift;
555
556 switch (type) {
557 case AARCH64_INSN_LDST_LOAD_PAIR_PRE_INDEX:
558 insn = aarch64_insn_get_ldp_pre_value();
559 break;
560 case AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX:
561 insn = aarch64_insn_get_stp_pre_value();
562 break;
563 case AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX:
564 insn = aarch64_insn_get_ldp_post_value();
565 break;
566 case AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX:
567 insn = aarch64_insn_get_stp_post_value();
568 break;
569 default:
c94ae4f7 570 pr_err("%s: unknown load/store encoding %d\n", __func__, type);
a9ae04c9 571 return AARCH64_BREAK_FAULT;
1bba567d
ZSL
572 }
573
574 switch (variant) {
575 case AARCH64_INSN_VARIANT_32BIT:
c94ae4f7
ZSL
576 if ((offset & 0x3) || (offset < -256) || (offset > 252)) {
577 pr_err("%s: offset must be multiples of 4 in the range of [-256, 252] %d\n",
578 __func__, offset);
579 return AARCH64_BREAK_FAULT;
580 }
1bba567d
ZSL
581 shift = 2;
582 break;
583 case AARCH64_INSN_VARIANT_64BIT:
c94ae4f7
ZSL
584 if ((offset & 0x7) || (offset < -512) || (offset > 504)) {
585 pr_err("%s: offset must be multiples of 8 in the range of [-512, 504] %d\n",
586 __func__, offset);
587 return AARCH64_BREAK_FAULT;
588 }
1bba567d
ZSL
589 shift = 3;
590 insn |= AARCH64_INSN_SF_BIT;
591 break;
592 default:
c94ae4f7 593 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
a9ae04c9 594 return AARCH64_BREAK_FAULT;
1bba567d
ZSL
595 }
596
597 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
598 reg1);
599
600 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT2, insn,
601 reg2);
602
603 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
604 base);
605
606 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_7, insn,
607 offset >> shift);
608}
9951a157 609
85f68fe8
DB
610u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
611 enum aarch64_insn_register base,
612 enum aarch64_insn_register state,
613 enum aarch64_insn_size_type size,
614 enum aarch64_insn_ldst_type type)
615{
616 u32 insn;
617
618 switch (type) {
619 case AARCH64_INSN_LDST_LOAD_EX:
fa1114d9 620 case AARCH64_INSN_LDST_LOAD_ACQ_EX:
85f68fe8 621 insn = aarch64_insn_get_load_ex_value();
fa1114d9
HT
622 if (type == AARCH64_INSN_LDST_LOAD_ACQ_EX)
623 insn |= BIT(15);
85f68fe8
DB
624 break;
625 case AARCH64_INSN_LDST_STORE_EX:
fa1114d9 626 case AARCH64_INSN_LDST_STORE_REL_EX:
85f68fe8 627 insn = aarch64_insn_get_store_ex_value();
fa1114d9
HT
628 if (type == AARCH64_INSN_LDST_STORE_REL_EX)
629 insn |= BIT(15);
85f68fe8
DB
630 break;
631 default:
632 pr_err("%s: unknown load/store exclusive encoding %d\n", __func__, type);
633 return AARCH64_BREAK_FAULT;
634 }
635
636 insn = aarch64_insn_encode_ldst_size(size, insn);
637
638 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
639 reg);
640
641 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
642 base);
643
644 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT2, insn,
645 AARCH64_INSN_REG_ZR);
646
647 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RS, insn,
648 state);
649}
650
fa1114d9
HT
651#ifdef CONFIG_ARM64_LSE_ATOMICS
652static u32 aarch64_insn_encode_ldst_order(enum aarch64_insn_mem_order_type type,
653 u32 insn)
34b8ab09 654{
fa1114d9
HT
655 u32 order;
656
657 switch (type) {
658 case AARCH64_INSN_MEM_ORDER_NONE:
659 order = 0;
660 break;
661 case AARCH64_INSN_MEM_ORDER_ACQ:
662 order = 2;
663 break;
664 case AARCH64_INSN_MEM_ORDER_REL:
665 order = 1;
666 break;
667 case AARCH64_INSN_MEM_ORDER_ACQREL:
668 order = 3;
669 break;
670 default:
671 pr_err("%s: unknown mem order %d\n", __func__, type);
672 return AARCH64_BREAK_FAULT;
673 }
674
675 insn &= ~GENMASK(23, 22);
676 insn |= order << 22;
677
678 return insn;
679}
680
681u32 aarch64_insn_gen_atomic_ld_op(enum aarch64_insn_register result,
682 enum aarch64_insn_register address,
683 enum aarch64_insn_register value,
684 enum aarch64_insn_size_type size,
685 enum aarch64_insn_mem_atomic_op op,
686 enum aarch64_insn_mem_order_type order)
687{
688 u32 insn;
689
690 switch (op) {
691 case AARCH64_INSN_MEM_ATOMIC_ADD:
692 insn = aarch64_insn_get_ldadd_value();
693 break;
694 case AARCH64_INSN_MEM_ATOMIC_CLR:
695 insn = aarch64_insn_get_ldclr_value();
696 break;
697 case AARCH64_INSN_MEM_ATOMIC_EOR:
698 insn = aarch64_insn_get_ldeor_value();
699 break;
700 case AARCH64_INSN_MEM_ATOMIC_SET:
701 insn = aarch64_insn_get_ldset_value();
702 break;
703 case AARCH64_INSN_MEM_ATOMIC_SWP:
704 insn = aarch64_insn_get_swp_value();
705 break;
706 default:
707 pr_err("%s: unimplemented mem atomic op %d\n", __func__, op);
708 return AARCH64_BREAK_FAULT;
709 }
34b8ab09
DB
710
711 switch (size) {
712 case AARCH64_INSN_SIZE_32:
713 case AARCH64_INSN_SIZE_64:
714 break;
715 default:
716 pr_err("%s: unimplemented size encoding %d\n", __func__, size);
717 return AARCH64_BREAK_FAULT;
718 }
719
720 insn = aarch64_insn_encode_ldst_size(size, insn);
721
fa1114d9
HT
722 insn = aarch64_insn_encode_ldst_order(order, insn);
723
34b8ab09
DB
724 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
725 result);
726
727 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
728 address);
729
730 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RS, insn,
731 value);
732}
733
fa1114d9
HT
734static u32 aarch64_insn_encode_cas_order(enum aarch64_insn_mem_order_type type,
735 u32 insn)
34b8ab09 736{
fa1114d9
HT
737 u32 order;
738
739 switch (type) {
740 case AARCH64_INSN_MEM_ORDER_NONE:
741 order = 0;
742 break;
743 case AARCH64_INSN_MEM_ORDER_ACQ:
744 order = BIT(22);
745 break;
746 case AARCH64_INSN_MEM_ORDER_REL:
747 order = BIT(15);
748 break;
749 case AARCH64_INSN_MEM_ORDER_ACQREL:
750 order = BIT(15) | BIT(22);
751 break;
752 default:
753 pr_err("%s: unknown mem order %d\n", __func__, type);
754 return AARCH64_BREAK_FAULT;
755 }
756
757 insn &= ~(BIT(15) | BIT(22));
758 insn |= order;
759
760 return insn;
761}
762
763u32 aarch64_insn_gen_cas(enum aarch64_insn_register result,
764 enum aarch64_insn_register address,
765 enum aarch64_insn_register value,
766 enum aarch64_insn_size_type size,
767 enum aarch64_insn_mem_order_type order)
768{
769 u32 insn;
770
771 switch (size) {
772 case AARCH64_INSN_SIZE_32:
773 case AARCH64_INSN_SIZE_64:
774 break;
775 default:
776 pr_err("%s: unimplemented size encoding %d\n", __func__, size);
777 return AARCH64_BREAK_FAULT;
778 }
779
780 insn = aarch64_insn_get_cas_value();
781
782 insn = aarch64_insn_encode_ldst_size(size, insn);
783
784 insn = aarch64_insn_encode_cas_order(order, insn);
785
786 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
787 result);
788
789 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
790 address);
791
792 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RS, insn,
793 value);
34b8ab09 794}
fa1114d9 795#endif
34b8ab09 796
85f68fe8
DB
797static u32 aarch64_insn_encode_prfm_imm(enum aarch64_insn_prfm_type type,
798 enum aarch64_insn_prfm_target target,
799 enum aarch64_insn_prfm_policy policy,
800 u32 insn)
801{
802 u32 imm_type = 0, imm_target = 0, imm_policy = 0;
803
804 switch (type) {
805 case AARCH64_INSN_PRFM_TYPE_PLD:
806 break;
807 case AARCH64_INSN_PRFM_TYPE_PLI:
808 imm_type = BIT(0);
809 break;
810 case AARCH64_INSN_PRFM_TYPE_PST:
811 imm_type = BIT(1);
812 break;
813 default:
814 pr_err("%s: unknown prfm type encoding %d\n", __func__, type);
815 return AARCH64_BREAK_FAULT;
816 }
817
818 switch (target) {
819 case AARCH64_INSN_PRFM_TARGET_L1:
820 break;
821 case AARCH64_INSN_PRFM_TARGET_L2:
822 imm_target = BIT(0);
823 break;
824 case AARCH64_INSN_PRFM_TARGET_L3:
825 imm_target = BIT(1);
826 break;
827 default:
828 pr_err("%s: unknown prfm target encoding %d\n", __func__, target);
829 return AARCH64_BREAK_FAULT;
830 }
831
832 switch (policy) {
833 case AARCH64_INSN_PRFM_POLICY_KEEP:
834 break;
835 case AARCH64_INSN_PRFM_POLICY_STRM:
836 imm_policy = BIT(0);
837 break;
838 default:
839 pr_err("%s: unknown prfm policy encoding %d\n", __func__, policy);
840 return AARCH64_BREAK_FAULT;
841 }
842
843 /* In this case, imm5 is encoded into Rt field. */
844 insn &= ~GENMASK(4, 0);
845 insn |= imm_policy | (imm_target << 1) | (imm_type << 3);
846
847 return insn;
848}
849
850u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base,
851 enum aarch64_insn_prfm_type type,
852 enum aarch64_insn_prfm_target target,
853 enum aarch64_insn_prfm_policy policy)
854{
855 u32 insn = aarch64_insn_get_prfm_value();
856
857 insn = aarch64_insn_encode_ldst_size(AARCH64_INSN_SIZE_64, insn);
858
859 insn = aarch64_insn_encode_prfm_imm(type, target, policy, insn);
860
861 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
862 base);
863
864 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, 0);
865}
866
9951a157
ZSL
867u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
868 enum aarch64_insn_register src,
869 int imm, enum aarch64_insn_variant variant,
870 enum aarch64_insn_adsb_type type)
871{
872 u32 insn;
873
874 switch (type) {
875 case AARCH64_INSN_ADSB_ADD:
876 insn = aarch64_insn_get_add_imm_value();
877 break;
878 case AARCH64_INSN_ADSB_SUB:
879 insn = aarch64_insn_get_sub_imm_value();
880 break;
881 case AARCH64_INSN_ADSB_ADD_SETFLAGS:
882 insn = aarch64_insn_get_adds_imm_value();
883 break;
884 case AARCH64_INSN_ADSB_SUB_SETFLAGS:
885 insn = aarch64_insn_get_subs_imm_value();
886 break;
887 default:
c94ae4f7 888 pr_err("%s: unknown add/sub encoding %d\n", __func__, type);
a9ae04c9 889 return AARCH64_BREAK_FAULT;
9951a157
ZSL
890 }
891
892 switch (variant) {
893 case AARCH64_INSN_VARIANT_32BIT:
894 break;
895 case AARCH64_INSN_VARIANT_64BIT:
896 insn |= AARCH64_INSN_SF_BIT;
897 break;
898 default:
c94ae4f7 899 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
a9ae04c9 900 return AARCH64_BREAK_FAULT;
9951a157
ZSL
901 }
902
11d76407
MZ
903 /* We can't encode more than a 24bit value (12bit + 12bit shift) */
904 if (imm & ~(BIT(24) - 1))
905 goto out;
906
907 /* If we have something in the top 12 bits... */
c94ae4f7 908 if (imm & ~(SZ_4K - 1)) {
11d76407
MZ
909 /* ... and in the low 12 bits -> error */
910 if (imm & (SZ_4K - 1))
911 goto out;
912
913 imm >>= 12;
914 insn |= AARCH64_INSN_LSL_12;
c94ae4f7 915 }
9951a157
ZSL
916
917 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
918
919 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
920
921 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, imm);
11d76407
MZ
922
923out:
924 pr_err("%s: invalid immediate encoding %d\n", __func__, imm);
925 return AARCH64_BREAK_FAULT;
9951a157 926}
4a89d2c9
ZSL
927
928u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst,
929 enum aarch64_insn_register src,
930 int immr, int imms,
931 enum aarch64_insn_variant variant,
932 enum aarch64_insn_bitfield_type type)
933{
934 u32 insn;
935 u32 mask;
936
937 switch (type) {
938 case AARCH64_INSN_BITFIELD_MOVE:
939 insn = aarch64_insn_get_bfm_value();
940 break;
941 case AARCH64_INSN_BITFIELD_MOVE_UNSIGNED:
942 insn = aarch64_insn_get_ubfm_value();
943 break;
944 case AARCH64_INSN_BITFIELD_MOVE_SIGNED:
945 insn = aarch64_insn_get_sbfm_value();
946 break;
947 default:
c94ae4f7 948 pr_err("%s: unknown bitfield encoding %d\n", __func__, type);
a9ae04c9 949 return AARCH64_BREAK_FAULT;
4a89d2c9
ZSL
950 }
951
952 switch (variant) {
953 case AARCH64_INSN_VARIANT_32BIT:
954 mask = GENMASK(4, 0);
955 break;
956 case AARCH64_INSN_VARIANT_64BIT:
957 insn |= AARCH64_INSN_SF_BIT | AARCH64_INSN_N_BIT;
958 mask = GENMASK(5, 0);
959 break;
960 default:
c94ae4f7 961 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
a9ae04c9 962 return AARCH64_BREAK_FAULT;
4a89d2c9
ZSL
963 }
964
c94ae4f7
ZSL
965 if (immr & ~mask) {
966 pr_err("%s: invalid immr encoding %d\n", __func__, immr);
967 return AARCH64_BREAK_FAULT;
968 }
969 if (imms & ~mask) {
970 pr_err("%s: invalid imms encoding %d\n", __func__, imms);
971 return AARCH64_BREAK_FAULT;
972 }
4a89d2c9
ZSL
973
974 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
975
976 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
977
978 insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_R, insn, immr);
979
980 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_S, insn, imms);
981}
6098f2d5
ZSL
982
983u32 aarch64_insn_gen_movewide(enum aarch64_insn_register dst,
984 int imm, int shift,
985 enum aarch64_insn_variant variant,
986 enum aarch64_insn_movewide_type type)
987{
988 u32 insn;
989
990 switch (type) {
991 case AARCH64_INSN_MOVEWIDE_ZERO:
992 insn = aarch64_insn_get_movz_value();
993 break;
994 case AARCH64_INSN_MOVEWIDE_KEEP:
995 insn = aarch64_insn_get_movk_value();
996 break;
997 case AARCH64_INSN_MOVEWIDE_INVERSE:
998 insn = aarch64_insn_get_movn_value();
999 break;
1000 default:
c94ae4f7 1001 pr_err("%s: unknown movewide encoding %d\n", __func__, type);
a9ae04c9 1002 return AARCH64_BREAK_FAULT;
6098f2d5
ZSL
1003 }
1004
c94ae4f7
ZSL
1005 if (imm & ~(SZ_64K - 1)) {
1006 pr_err("%s: invalid immediate encoding %d\n", __func__, imm);
1007 return AARCH64_BREAK_FAULT;
1008 }
6098f2d5
ZSL
1009
1010 switch (variant) {
1011 case AARCH64_INSN_VARIANT_32BIT:
c94ae4f7
ZSL
1012 if (shift != 0 && shift != 16) {
1013 pr_err("%s: invalid shift encoding %d\n", __func__,
1014 shift);
1015 return AARCH64_BREAK_FAULT;
1016 }
6098f2d5
ZSL
1017 break;
1018 case AARCH64_INSN_VARIANT_64BIT:
1019 insn |= AARCH64_INSN_SF_BIT;
c94ae4f7
ZSL
1020 if (shift != 0 && shift != 16 && shift != 32 && shift != 48) {
1021 pr_err("%s: invalid shift encoding %d\n", __func__,
1022 shift);
1023 return AARCH64_BREAK_FAULT;
1024 }
6098f2d5
ZSL
1025 break;
1026 default:
c94ae4f7 1027 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
a9ae04c9 1028 return AARCH64_BREAK_FAULT;
6098f2d5
ZSL
1029 }
1030
1031 insn |= (shift >> 4) << 21;
1032
1033 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
1034
1035 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_16, insn, imm);
1036}
5fdc639a
ZSL
1037
1038u32 aarch64_insn_gen_add_sub_shifted_reg(enum aarch64_insn_register dst,
1039 enum aarch64_insn_register src,
1040 enum aarch64_insn_register reg,
1041 int shift,
1042 enum aarch64_insn_variant variant,
1043 enum aarch64_insn_adsb_type type)
1044{
1045 u32 insn;
1046
1047 switch (type) {
1048 case AARCH64_INSN_ADSB_ADD:
1049 insn = aarch64_insn_get_add_value();
1050 break;
1051 case AARCH64_INSN_ADSB_SUB:
1052 insn = aarch64_insn_get_sub_value();
1053 break;
1054 case AARCH64_INSN_ADSB_ADD_SETFLAGS:
1055 insn = aarch64_insn_get_adds_value();
1056 break;
1057 case AARCH64_INSN_ADSB_SUB_SETFLAGS:
1058 insn = aarch64_insn_get_subs_value();
1059 break;
1060 default:
c94ae4f7 1061 pr_err("%s: unknown add/sub encoding %d\n", __func__, type);
a9ae04c9 1062 return AARCH64_BREAK_FAULT;
5fdc639a
ZSL
1063 }
1064
1065 switch (variant) {
1066 case AARCH64_INSN_VARIANT_32BIT:
c94ae4f7
ZSL
1067 if (shift & ~(SZ_32 - 1)) {
1068 pr_err("%s: invalid shift encoding %d\n", __func__,
1069 shift);
1070 return AARCH64_BREAK_FAULT;
1071 }
5fdc639a
ZSL
1072 break;
1073 case AARCH64_INSN_VARIANT_64BIT:
1074 insn |= AARCH64_INSN_SF_BIT;
c94ae4f7
ZSL
1075 if (shift & ~(SZ_64 - 1)) {
1076 pr_err("%s: invalid shift encoding %d\n", __func__,
1077 shift);
1078 return AARCH64_BREAK_FAULT;
1079 }
5fdc639a
ZSL
1080 break;
1081 default:
c94ae4f7 1082 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
a9ae04c9 1083 return AARCH64_BREAK_FAULT;
5fdc639a
ZSL
1084 }
1085
1086
1087 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
1088
1089 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
1090
1091 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg);
1092
1093 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_6, insn, shift);
1094}
546dd36b
ZSL
1095
1096u32 aarch64_insn_gen_data1(enum aarch64_insn_register dst,
1097 enum aarch64_insn_register src,
1098 enum aarch64_insn_variant variant,
1099 enum aarch64_insn_data1_type type)
1100{
1101 u32 insn;
1102
1103 switch (type) {
1104 case AARCH64_INSN_DATA1_REVERSE_16:
1105 insn = aarch64_insn_get_rev16_value();
1106 break;
1107 case AARCH64_INSN_DATA1_REVERSE_32:
1108 insn = aarch64_insn_get_rev32_value();
1109 break;
1110 case AARCH64_INSN_DATA1_REVERSE_64:
c94ae4f7
ZSL
1111 if (variant != AARCH64_INSN_VARIANT_64BIT) {
1112 pr_err("%s: invalid variant for reverse64 %d\n",
1113 __func__, variant);
1114 return AARCH64_BREAK_FAULT;
1115 }
546dd36b
ZSL
1116 insn = aarch64_insn_get_rev64_value();
1117 break;
1118 default:
c94ae4f7 1119 pr_err("%s: unknown data1 encoding %d\n", __func__, type);
a9ae04c9 1120 return AARCH64_BREAK_FAULT;
546dd36b
ZSL
1121 }
1122
1123 switch (variant) {
1124 case AARCH64_INSN_VARIANT_32BIT:
1125 break;
1126 case AARCH64_INSN_VARIANT_64BIT:
1127 insn |= AARCH64_INSN_SF_BIT;
1128 break;
1129 default:
c94ae4f7 1130 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
a9ae04c9 1131 return AARCH64_BREAK_FAULT;
546dd36b
ZSL
1132 }
1133
1134 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
1135
1136 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
1137}
64810639
ZSL
1138
1139u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst,
1140 enum aarch64_insn_register src,
1141 enum aarch64_insn_register reg,
1142 enum aarch64_insn_variant variant,
1143 enum aarch64_insn_data2_type type)
1144{
1145 u32 insn;
1146
1147 switch (type) {
1148 case AARCH64_INSN_DATA2_UDIV:
1149 insn = aarch64_insn_get_udiv_value();
1150 break;
1151 case AARCH64_INSN_DATA2_SDIV:
1152 insn = aarch64_insn_get_sdiv_value();
1153 break;
1154 case AARCH64_INSN_DATA2_LSLV:
1155 insn = aarch64_insn_get_lslv_value();
1156 break;
1157 case AARCH64_INSN_DATA2_LSRV:
1158 insn = aarch64_insn_get_lsrv_value();
1159 break;
1160 case AARCH64_INSN_DATA2_ASRV:
1161 insn = aarch64_insn_get_asrv_value();
1162 break;
1163 case AARCH64_INSN_DATA2_RORV:
1164 insn = aarch64_insn_get_rorv_value();
1165 break;
1166 default:
c94ae4f7 1167 pr_err("%s: unknown data2 encoding %d\n", __func__, type);
a9ae04c9 1168 return AARCH64_BREAK_FAULT;
64810639
ZSL
1169 }
1170
1171 switch (variant) {
1172 case AARCH64_INSN_VARIANT_32BIT:
1173 break;
1174 case AARCH64_INSN_VARIANT_64BIT:
1175 insn |= AARCH64_INSN_SF_BIT;
1176 break;
1177 default:
c94ae4f7 1178 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
a9ae04c9 1179 return AARCH64_BREAK_FAULT;
64810639
ZSL
1180 }
1181
1182 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
1183
1184 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
1185
1186 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg);
1187}
27f95ba5
ZSL
1188
1189u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst,
1190 enum aarch64_insn_register src,
1191 enum aarch64_insn_register reg1,
1192 enum aarch64_insn_register reg2,
1193 enum aarch64_insn_variant variant,
1194 enum aarch64_insn_data3_type type)
1195{
1196 u32 insn;
1197
1198 switch (type) {
1199 case AARCH64_INSN_DATA3_MADD:
1200 insn = aarch64_insn_get_madd_value();
1201 break;
1202 case AARCH64_INSN_DATA3_MSUB:
1203 insn = aarch64_insn_get_msub_value();
1204 break;
1205 default:
c94ae4f7 1206 pr_err("%s: unknown data3 encoding %d\n", __func__, type);
a9ae04c9 1207 return AARCH64_BREAK_FAULT;
27f95ba5
ZSL
1208 }
1209
1210 switch (variant) {
1211 case AARCH64_INSN_VARIANT_32BIT:
1212 break;
1213 case AARCH64_INSN_VARIANT_64BIT:
1214 insn |= AARCH64_INSN_SF_BIT;
1215 break;
1216 default:
c94ae4f7 1217 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
a9ae04c9 1218 return AARCH64_BREAK_FAULT;
27f95ba5
ZSL
1219 }
1220
1221 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
1222
1223 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RA, insn, src);
1224
1225 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
1226 reg1);
1227
1228 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn,
1229 reg2);
1230}
5e6e15a2
ZSL
1231
1232u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst,
1233 enum aarch64_insn_register src,
1234 enum aarch64_insn_register reg,
1235 int shift,
1236 enum aarch64_insn_variant variant,
1237 enum aarch64_insn_logic_type type)
1238{
1239 u32 insn;
1240
1241 switch (type) {
1242 case AARCH64_INSN_LOGIC_AND:
1243 insn = aarch64_insn_get_and_value();
1244 break;
1245 case AARCH64_INSN_LOGIC_BIC:
1246 insn = aarch64_insn_get_bic_value();
1247 break;
1248 case AARCH64_INSN_LOGIC_ORR:
1249 insn = aarch64_insn_get_orr_value();
1250 break;
1251 case AARCH64_INSN_LOGIC_ORN:
1252 insn = aarch64_insn_get_orn_value();
1253 break;
1254 case AARCH64_INSN_LOGIC_EOR:
1255 insn = aarch64_insn_get_eor_value();
1256 break;
1257 case AARCH64_INSN_LOGIC_EON:
1258 insn = aarch64_insn_get_eon_value();
1259 break;
1260 case AARCH64_INSN_LOGIC_AND_SETFLAGS:
1261 insn = aarch64_insn_get_ands_value();
1262 break;
1263 case AARCH64_INSN_LOGIC_BIC_SETFLAGS:
1264 insn = aarch64_insn_get_bics_value();
1265 break;
1266 default:
c94ae4f7 1267 pr_err("%s: unknown logical encoding %d\n", __func__, type);
a9ae04c9 1268 return AARCH64_BREAK_FAULT;
5e6e15a2
ZSL
1269 }
1270
1271 switch (variant) {
1272 case AARCH64_INSN_VARIANT_32BIT:
c94ae4f7
ZSL
1273 if (shift & ~(SZ_32 - 1)) {
1274 pr_err("%s: invalid shift encoding %d\n", __func__,
1275 shift);
1276 return AARCH64_BREAK_FAULT;
1277 }
5e6e15a2
ZSL
1278 break;
1279 case AARCH64_INSN_VARIANT_64BIT:
1280 insn |= AARCH64_INSN_SF_BIT;
c94ae4f7
ZSL
1281 if (shift & ~(SZ_64 - 1)) {
1282 pr_err("%s: invalid shift encoding %d\n", __func__,
1283 shift);
1284 return AARCH64_BREAK_FAULT;
1285 }
5e6e15a2
ZSL
1286 break;
1287 default:
c94ae4f7 1288 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
a9ae04c9 1289 return AARCH64_BREAK_FAULT;
5e6e15a2
ZSL
1290 }
1291
1292
1293 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
1294
1295 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
1296
1297 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg);
1298
1299 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_6, insn, shift);
1300}
9b79f52d 1301
e3bf8a67
MR
1302/*
1303 * MOV (register) is architecturally an alias of ORR (shifted register) where
1304 * MOV <*d>, <*m> is equivalent to ORR <*d>, <*ZR>, <*m>
1305 */
1306u32 aarch64_insn_gen_move_reg(enum aarch64_insn_register dst,
1307 enum aarch64_insn_register src,
1308 enum aarch64_insn_variant variant)
1309{
1310 return aarch64_insn_gen_logical_shifted_reg(dst, AARCH64_INSN_REG_ZR,
1311 src, 0, variant,
1312 AARCH64_INSN_LOGIC_ORR);
1313}
1314
7aaf7b2f
AB
1315u32 aarch64_insn_gen_adr(unsigned long pc, unsigned long addr,
1316 enum aarch64_insn_register reg,
1317 enum aarch64_insn_adr_type type)
1318{
1319 u32 insn;
1320 s32 offset;
1321
1322 switch (type) {
1323 case AARCH64_INSN_ADR_TYPE_ADR:
1324 insn = aarch64_insn_get_adr_value();
1325 offset = addr - pc;
1326 break;
1327 case AARCH64_INSN_ADR_TYPE_ADRP:
1328 insn = aarch64_insn_get_adrp_value();
1329 offset = (addr - ALIGN_DOWN(pc, SZ_4K)) >> 12;
1330 break;
1331 default:
1332 pr_err("%s: unknown adr encoding %d\n", __func__, type);
1333 return AARCH64_BREAK_FAULT;
1334 }
1335
1336 if (offset < -SZ_1M || offset >= SZ_1M)
1337 return AARCH64_BREAK_FAULT;
1338
1339 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, reg);
1340
1341 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_ADR, insn, offset);
1342}
1343
10b48f7e
MZ
1344/*
1345 * Decode the imm field of a branch, and return the byte offset as a
1346 * signed value (so it can be used when computing a new branch
1347 * target).
1348 */
1349s32 aarch64_get_branch_offset(u32 insn)
1350{
1351 s32 imm;
1352
1353 if (aarch64_insn_is_b(insn) || aarch64_insn_is_bl(insn)) {
1354 imm = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_26, insn);
1355 return (imm << 6) >> 4;
1356 }
1357
1358 if (aarch64_insn_is_cbz(insn) || aarch64_insn_is_cbnz(insn) ||
1359 aarch64_insn_is_bcond(insn)) {
1360 imm = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_19, insn);
1361 return (imm << 13) >> 11;
1362 }
1363
1364 if (aarch64_insn_is_tbz(insn) || aarch64_insn_is_tbnz(insn)) {
1365 imm = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_14, insn);
1366 return (imm << 18) >> 16;
1367 }
1368
1369 /* Unhandled instruction */
1370 BUG();
1371}
1372
1373/*
1374 * Encode the displacement of a branch in the imm field and return the
1375 * updated instruction.
1376 */
1377u32 aarch64_set_branch_offset(u32 insn, s32 offset)
1378{
1379 if (aarch64_insn_is_b(insn) || aarch64_insn_is_bl(insn))
1380 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_26, insn,
1381 offset >> 2);
1382
1383 if (aarch64_insn_is_cbz(insn) || aarch64_insn_is_cbnz(insn) ||
1384 aarch64_insn_is_bcond(insn))
1385 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
1386 offset >> 2);
1387
1388 if (aarch64_insn_is_tbz(insn) || aarch64_insn_is_tbnz(insn))
1389 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_14, insn,
1390 offset >> 2);
1391
1392 /* Unhandled instruction */
1393 BUG();
1394}
1395
46084bc2
SP
1396s32 aarch64_insn_adrp_get_offset(u32 insn)
1397{
1398 BUG_ON(!aarch64_insn_is_adrp(insn));
1399 return aarch64_insn_decode_immediate(AARCH64_INSN_IMM_ADR, insn) << 12;
1400}
1401
1402u32 aarch64_insn_adrp_set_offset(u32 insn, s32 offset)
1403{
1404 BUG_ON(!aarch64_insn_is_adrp(insn));
1405 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_ADR, insn,
1406 offset >> 12);
1407}
1408
d59bee88
DL
1409/*
1410 * Extract the Op/CR data from a msr/mrs instruction.
1411 */
1412u32 aarch64_insn_extract_system_reg(u32 insn)
1413{
1414 return (insn & 0x1FFFE0) >> 5;
1415}
1416
9b79f52d
PA
1417bool aarch32_insn_is_wide(u32 insn)
1418{
1419 return insn >= 0xe800;
1420}
bd35a4ad
PA
1421
1422/*
1423 * Macros/defines for extracting register numbers from instruction.
1424 */
1425u32 aarch32_insn_extract_reg_num(u32 insn, int offset)
1426{
1427 return (insn & (0xf << offset)) >> offset;
1428}
c852f320
PA
1429
1430#define OPC2_MASK 0x7
1431#define OPC2_OFFSET 5
1432u32 aarch32_insn_mcr_extract_opc2(u32 insn)
1433{
1434 return (insn & (OPC2_MASK << OPC2_OFFSET)) >> OPC2_OFFSET;
1435}
1436
1437#define CRM_MASK 0xf
1438u32 aarch32_insn_mcr_extract_crm(u32 insn)
1439{
1440 return insn & CRM_MASK;
1441}
2af3ec08 1442
ef3935ee
MZ
1443static bool range_of_ones(u64 val)
1444{
1445 /* Doesn't handle full ones or full zeroes */
1446 u64 sval = val >> __ffs64(val);
1447
1448 /* One of Sean Eron Anderson's bithack tricks */
1449 return ((sval + 1) & (sval)) == 0;
1450}
1451
1452static u32 aarch64_encode_immediate(u64 imm,
1453 enum aarch64_insn_variant variant,
1454 u32 insn)
1455{
1456 unsigned int immr, imms, n, ones, ror, esz, tmp;
579d1b3f 1457 u64 mask;
ef3935ee
MZ
1458
1459 switch (variant) {
1460 case AARCH64_INSN_VARIANT_32BIT:
ef3935ee
MZ
1461 esz = 32;
1462 break;
1463 case AARCH64_INSN_VARIANT_64BIT:
1464 insn |= AARCH64_INSN_SF_BIT;
1465 esz = 64;
1466 break;
1467 default:
1468 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
1469 return AARCH64_BREAK_FAULT;
1470 }
1471
579d1b3f
LN
1472 mask = GENMASK(esz - 1, 0);
1473
1474 /* Can't encode full zeroes, full ones, or value wider than the mask */
1475 if (!imm || imm == mask || imm & ~mask)
1476 return AARCH64_BREAK_FAULT;
1477
ef3935ee
MZ
1478 /*
1479 * Inverse of Replicate(). Try to spot a repeating pattern
1480 * with a pow2 stride.
1481 */
1482 for (tmp = esz / 2; tmp >= 2; tmp /= 2) {
1483 u64 emask = BIT(tmp) - 1;
1484
1485 if ((imm & emask) != ((imm >> tmp) & emask))
1486 break;
1487
1488 esz = tmp;
1489 mask = emask;
1490 }
1491
1492 /* N is only set if we're encoding a 64bit value */
1493 n = esz == 64;
1494
1495 /* Trim imm to the element size */
1496 imm &= mask;
1497
1498 /* That's how many ones we need to encode */
1499 ones = hweight64(imm);
1500
1501 /*
1502 * imms is set to (ones - 1), prefixed with a string of ones
1503 * and a zero if they fit. Cap it to 6 bits.
1504 */
1505 imms = ones - 1;
1506 imms |= 0xf << ffs(esz);
1507 imms &= BIT(6) - 1;
1508
1509 /* Compute the rotation */
1510 if (range_of_ones(imm)) {
1511 /*
1512 * Pattern: 0..01..10..0
1513 *
1514 * Compute how many rotate we need to align it right
1515 */
1516 ror = __ffs64(imm);
1517 } else {
1518 /*
1519 * Pattern: 0..01..10..01..1
1520 *
1521 * Fill the unused top bits with ones, and check if
1522 * the result is a valid immediate (all ones with a
1523 * contiguous ranges of zeroes).
1524 */
1525 imm |= ~mask;
1526 if (!range_of_ones(~imm))
1527 return AARCH64_BREAK_FAULT;
1528
1529 /*
1530 * Compute the rotation to get a continuous set of
1531 * ones, with the first bit set at position 0
1532 */
a6aab018 1533 ror = fls64(~imm);
ef3935ee
MZ
1534 }
1535
1536 /*
1537 * immr is the number of bits we need to rotate back to the
1538 * original set of ones. Note that this is relative to the
1539 * element size...
1540 */
1541 immr = (esz - ror) % esz;
1542
1543 insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_N, insn, n);
1544 insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_R, insn, immr);
1545 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_S, insn, imms);
1546}
1547
1548u32 aarch64_insn_gen_logical_immediate(enum aarch64_insn_logic_type type,
1549 enum aarch64_insn_variant variant,
1550 enum aarch64_insn_register Rn,
1551 enum aarch64_insn_register Rd,
1552 u64 imm)
1553{
1554 u32 insn;
1555
1556 switch (type) {
1557 case AARCH64_INSN_LOGIC_AND:
1558 insn = aarch64_insn_get_and_imm_value();
1559 break;
1560 case AARCH64_INSN_LOGIC_ORR:
1561 insn = aarch64_insn_get_orr_imm_value();
1562 break;
1563 case AARCH64_INSN_LOGIC_EOR:
1564 insn = aarch64_insn_get_eor_imm_value();
1565 break;
1566 case AARCH64_INSN_LOGIC_AND_SETFLAGS:
1567 insn = aarch64_insn_get_ands_imm_value();
1568 break;
1569 default:
1570 pr_err("%s: unknown logical encoding %d\n", __func__, type);
1571 return AARCH64_BREAK_FAULT;
1572 }
1573
1574 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, Rd);
1575 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, Rn);
1576 return aarch64_encode_immediate(imm, variant, insn);
1577}
9f2efa32
MZ
1578
1579u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
1580 enum aarch64_insn_register Rm,
1581 enum aarch64_insn_register Rn,
1582 enum aarch64_insn_register Rd,
1583 u8 lsb)
1584{
1585 u32 insn;
1586
1587 insn = aarch64_insn_get_extr_value();
1588
1589 switch (variant) {
1590 case AARCH64_INSN_VARIANT_32BIT:
1591 if (lsb > 31)
1592 return AARCH64_BREAK_FAULT;
1593 break;
1594 case AARCH64_INSN_VARIANT_64BIT:
1595 if (lsb > 63)
1596 return AARCH64_BREAK_FAULT;
1597 insn |= AARCH64_INSN_SF_BIT;
1598 insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_N, insn, 1);
1599 break;
1600 default:
1601 pr_err("%s: unknown variant encoding %d\n", __func__, variant);
1602 return AARCH64_BREAK_FAULT;
1603 }
1604
1605 insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_S, insn, lsb);
1606 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, Rd);
1607 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, Rn);
1608 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm);
1609}
fa1114d9
HT
1610
1611u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
1612{
1613 u32 opt;
1614 u32 insn;
1615
1616 switch (type) {
1617 case AARCH64_INSN_MB_SY:
1618 opt = 0xf;
1619 break;
1620 case AARCH64_INSN_MB_ST:
1621 opt = 0xe;
1622 break;
1623 case AARCH64_INSN_MB_LD:
1624 opt = 0xd;
1625 break;
1626 case AARCH64_INSN_MB_ISH:
1627 opt = 0xb;
1628 break;
1629 case AARCH64_INSN_MB_ISHST:
1630 opt = 0xa;
1631 break;
1632 case AARCH64_INSN_MB_ISHLD:
1633 opt = 0x9;
1634 break;
1635 case AARCH64_INSN_MB_NSH:
1636 opt = 0x7;
1637 break;
1638 case AARCH64_INSN_MB_NSHST:
1639 opt = 0x6;
1640 break;
1641 case AARCH64_INSN_MB_NSHLD:
1642 opt = 0x5;
1643 break;
1644 default:
1645 pr_err("%s: unknown dmb type %d\n", __func__, type);
1646 return AARCH64_BREAK_FAULT;
1647 }
1648
1649 insn = aarch64_insn_get_dmb_value();
1650 insn &= ~GENMASK(11, 8);
1651 insn |= (opt << 8);
1652
1653 return insn;
1654}