target/arm: Fix SVE system register access checks
[qemu.git] / target / arm / translate-a64.c
1 /*
2 * AArch64 translation
3 *
4 * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "qemu/osdep.h"
20
21 #include "cpu.h"
22 #include "exec/exec-all.h"
23 #include "tcg-op.h"
24 #include "tcg-op-gvec.h"
25 #include "qemu/log.h"
26 #include "arm_ldst.h"
27 #include "translate.h"
28 #include "internals.h"
29 #include "qemu/host-utils.h"
30
31 #include "exec/semihost.h"
32 #include "exec/gen-icount.h"
33
34 #include "exec/helper-proto.h"
35 #include "exec/helper-gen.h"
36 #include "exec/log.h"
37
38 #include "trace-tcg.h"
39 #include "translate-a64.h"
40
41 static TCGv_i64 cpu_X[32];
42 static TCGv_i64 cpu_pc;
43
44 /* Load/store exclusive handling */
45 static TCGv_i64 cpu_exclusive_high;
46
47 static const char *regnames[] = {
48 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
49 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
50 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
51 "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
52 };
53
54 enum a64_shift_type {
55 A64_SHIFT_TYPE_LSL = 0,
56 A64_SHIFT_TYPE_LSR = 1,
57 A64_SHIFT_TYPE_ASR = 2,
58 A64_SHIFT_TYPE_ROR = 3
59 };
60
61 /* Table based decoder typedefs - used when the relevant bits for decode
62 * are too awkwardly scattered across the instruction (eg SIMD).
63 */
64 typedef void AArch64DecodeFn(DisasContext *s, uint32_t insn);
65
66 typedef struct AArch64DecodeTable {
67 uint32_t pattern;
68 uint32_t mask;
69 AArch64DecodeFn *disas_fn;
70 } AArch64DecodeTable;
71
72 /* Function prototype for gen_ functions for calling Neon helpers */
73 typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
74 typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
75 typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
76 typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
77 typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
78 typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
79 typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
80 typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
81 typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
82 typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
83 typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
84 typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
85 typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
86 typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
87 typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, TCGMemOp);
88
89 /* initialize TCG globals. */
90 void a64_translate_init(void)
91 {
92 int i;
93
94 cpu_pc = tcg_global_mem_new_i64(cpu_env,
95 offsetof(CPUARMState, pc),
96 "pc");
97 for (i = 0; i < 32; i++) {
98 cpu_X[i] = tcg_global_mem_new_i64(cpu_env,
99 offsetof(CPUARMState, xregs[i]),
100 regnames[i]);
101 }
102
103 cpu_exclusive_high = tcg_global_mem_new_i64(cpu_env,
104 offsetof(CPUARMState, exclusive_high), "exclusive_high");
105 }
106
107 static inline int get_a64_user_mem_index(DisasContext *s)
108 {
109 /* Return the core mmu_idx to use for A64 "unprivileged load/store" insns:
110 * if EL1, access as if EL0; otherwise access at current EL
111 */
112 ARMMMUIdx useridx;
113
114 switch (s->mmu_idx) {
115 case ARMMMUIdx_S12NSE1:
116 useridx = ARMMMUIdx_S12NSE0;
117 break;
118 case ARMMMUIdx_S1SE1:
119 useridx = ARMMMUIdx_S1SE0;
120 break;
121 case ARMMMUIdx_S2NS:
122 g_assert_not_reached();
123 default:
124 useridx = s->mmu_idx;
125 break;
126 }
127 return arm_to_core_mmu_idx(useridx);
128 }
129
130 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
131 fprintf_function cpu_fprintf, int flags)
132 {
133 ARMCPU *cpu = ARM_CPU(cs);
134 CPUARMState *env = &cpu->env;
135 uint32_t psr = pstate_read(env);
136 int i;
137 int el = arm_current_el(env);
138 const char *ns_status;
139
140 cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n",
141 env->pc, env->xregs[31]);
142 for (i = 0; i < 31; i++) {
143 cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
144 if ((i % 4) == 3) {
145 cpu_fprintf(f, "\n");
146 } else {
147 cpu_fprintf(f, " ");
148 }
149 }
150
151 if (arm_feature(env, ARM_FEATURE_EL3) && el != 3) {
152 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
153 } else {
154 ns_status = "";
155 }
156
157 cpu_fprintf(f, "\nPSTATE=%08x %c%c%c%c %sEL%d%c\n",
158 psr,
159 psr & PSTATE_N ? 'N' : '-',
160 psr & PSTATE_Z ? 'Z' : '-',
161 psr & PSTATE_C ? 'C' : '-',
162 psr & PSTATE_V ? 'V' : '-',
163 ns_status,
164 el,
165 psr & PSTATE_SP ? 'h' : 't');
166
167 if (flags & CPU_DUMP_FPU) {
168 int numvfpregs = 32;
169 for (i = 0; i < numvfpregs; i++) {
170 uint64_t *q = aa64_vfp_qreg(env, i);
171 uint64_t vlo = q[0];
172 uint64_t vhi = q[1];
173 cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "%c",
174 i, vhi, vlo, (i & 1 ? '\n' : ' '));
175 }
176 cpu_fprintf(f, "FPCR: %08x FPSR: %08x\n",
177 vfp_get_fpcr(env), vfp_get_fpsr(env));
178 }
179 }
180
181 void gen_a64_set_pc_im(uint64_t val)
182 {
183 tcg_gen_movi_i64(cpu_pc, val);
184 }
185
186 /* Load the PC from a generic TCG variable.
187 *
188 * If address tagging is enabled via the TCR TBI bits, then loading
189 * an address into the PC will clear out any tag in the it:
190 * + for EL2 and EL3 there is only one TBI bit, and if it is set
191 * then the address is zero-extended, clearing bits [63:56]
192 * + for EL0 and EL1, TBI0 controls addresses with bit 55 == 0
193 * and TBI1 controls addressses with bit 55 == 1.
194 * If the appropriate TBI bit is set for the address then
195 * the address is sign-extended from bit 55 into bits [63:56]
196 *
197 * We can avoid doing this for relative-branches, because the
198 * PC + offset can never overflow into the tag bits (assuming
199 * that virtual addresses are less than 56 bits wide, as they
200 * are currently), but we must handle it for branch-to-register.
201 */
202 static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
203 {
204
205 if (s->current_el <= 1) {
206 /* Test if NEITHER or BOTH TBI values are set. If so, no need to
207 * examine bit 55 of address, can just generate code.
208 * If mixed, then test via generated code
209 */
210 if (s->tbi0 && s->tbi1) {
211 TCGv_i64 tmp_reg = tcg_temp_new_i64();
212 /* Both bits set, sign extension from bit 55 into [63:56] will
213 * cover both cases
214 */
215 tcg_gen_shli_i64(tmp_reg, src, 8);
216 tcg_gen_sari_i64(cpu_pc, tmp_reg, 8);
217 tcg_temp_free_i64(tmp_reg);
218 } else if (!s->tbi0 && !s->tbi1) {
219 /* Neither bit set, just load it as-is */
220 tcg_gen_mov_i64(cpu_pc, src);
221 } else {
222 TCGv_i64 tcg_tmpval = tcg_temp_new_i64();
223 TCGv_i64 tcg_bit55 = tcg_temp_new_i64();
224 TCGv_i64 tcg_zero = tcg_const_i64(0);
225
226 tcg_gen_andi_i64(tcg_bit55, src, (1ull << 55));
227
228 if (s->tbi0) {
229 /* tbi0==1, tbi1==0, so 0-fill upper byte if bit 55 = 0 */
230 tcg_gen_andi_i64(tcg_tmpval, src,
231 0x00FFFFFFFFFFFFFFull);
232 tcg_gen_movcond_i64(TCG_COND_EQ, cpu_pc, tcg_bit55, tcg_zero,
233 tcg_tmpval, src);
234 } else {
235 /* tbi0==0, tbi1==1, so 1-fill upper byte if bit 55 = 1 */
236 tcg_gen_ori_i64(tcg_tmpval, src,
237 0xFF00000000000000ull);
238 tcg_gen_movcond_i64(TCG_COND_NE, cpu_pc, tcg_bit55, tcg_zero,
239 tcg_tmpval, src);
240 }
241 tcg_temp_free_i64(tcg_zero);
242 tcg_temp_free_i64(tcg_bit55);
243 tcg_temp_free_i64(tcg_tmpval);
244 }
245 } else { /* EL > 1 */
246 if (s->tbi0) {
247 /* Force tag byte to all zero */
248 tcg_gen_andi_i64(cpu_pc, src, 0x00FFFFFFFFFFFFFFull);
249 } else {
250 /* Load unmodified address */
251 tcg_gen_mov_i64(cpu_pc, src);
252 }
253 }
254 }
255
256 typedef struct DisasCompare64 {
257 TCGCond cond;
258 TCGv_i64 value;
259 } DisasCompare64;
260
261 static void a64_test_cc(DisasCompare64 *c64, int cc)
262 {
263 DisasCompare c32;
264
265 arm_test_cc(&c32, cc);
266
267 /* Sign-extend the 32-bit value so that the GE/LT comparisons work
268 * properly. The NE/EQ comparisons are also fine with this choice. */
269 c64->cond = c32.cond;
270 c64->value = tcg_temp_new_i64();
271 tcg_gen_ext_i32_i64(c64->value, c32.value);
272
273 arm_free_cc(&c32);
274 }
275
276 static void a64_free_cc(DisasCompare64 *c64)
277 {
278 tcg_temp_free_i64(c64->value);
279 }
280
281 static void gen_exception_internal(int excp)
282 {
283 TCGv_i32 tcg_excp = tcg_const_i32(excp);
284
285 assert(excp_is_internal(excp));
286 gen_helper_exception_internal(cpu_env, tcg_excp);
287 tcg_temp_free_i32(tcg_excp);
288 }
289
290 static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
291 {
292 TCGv_i32 tcg_excp = tcg_const_i32(excp);
293 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
294 TCGv_i32 tcg_el = tcg_const_i32(target_el);
295
296 gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
297 tcg_syn, tcg_el);
298 tcg_temp_free_i32(tcg_el);
299 tcg_temp_free_i32(tcg_syn);
300 tcg_temp_free_i32(tcg_excp);
301 }
302
303 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
304 {
305 gen_a64_set_pc_im(s->pc - offset);
306 gen_exception_internal(excp);
307 s->base.is_jmp = DISAS_NORETURN;
308 }
309
310 static void gen_exception_insn(DisasContext *s, int offset, int excp,
311 uint32_t syndrome, uint32_t target_el)
312 {
313 gen_a64_set_pc_im(s->pc - offset);
314 gen_exception(excp, syndrome, target_el);
315 s->base.is_jmp = DISAS_NORETURN;
316 }
317
318 static void gen_exception_bkpt_insn(DisasContext *s, int offset,
319 uint32_t syndrome)
320 {
321 TCGv_i32 tcg_syn;
322
323 gen_a64_set_pc_im(s->pc - offset);
324 tcg_syn = tcg_const_i32(syndrome);
325 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
326 tcg_temp_free_i32(tcg_syn);
327 s->base.is_jmp = DISAS_NORETURN;
328 }
329
330 static void gen_ss_advance(DisasContext *s)
331 {
332 /* If the singlestep state is Active-not-pending, advance to
333 * Active-pending.
334 */
335 if (s->ss_active) {
336 s->pstate_ss = 0;
337 gen_helper_clear_pstate_ss(cpu_env);
338 }
339 }
340
341 static void gen_step_complete_exception(DisasContext *s)
342 {
343 /* We just completed step of an insn. Move from Active-not-pending
344 * to Active-pending, and then also take the swstep exception.
345 * This corresponds to making the (IMPDEF) choice to prioritize
346 * swstep exceptions over asynchronous exceptions taken to an exception
347 * level where debug is disabled. This choice has the advantage that
348 * we do not need to maintain internal state corresponding to the
349 * ISV/EX syndrome bits between completion of the step and generation
350 * of the exception, and our syndrome information is always correct.
351 */
352 gen_ss_advance(s);
353 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
354 default_exception_el(s));
355 s->base.is_jmp = DISAS_NORETURN;
356 }
357
358 static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
359 {
360 /* No direct tb linking with singlestep (either QEMU's or the ARM
361 * debug architecture kind) or deterministic io
362 */
363 if (s->base.singlestep_enabled || s->ss_active ||
364 (tb_cflags(s->base.tb) & CF_LAST_IO)) {
365 return false;
366 }
367
368 #ifndef CONFIG_USER_ONLY
369 /* Only link tbs from inside the same guest page */
370 if ((s->base.tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
371 return false;
372 }
373 #endif
374
375 return true;
376 }
377
378 static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
379 {
380 TranslationBlock *tb;
381
382 tb = s->base.tb;
383 if (use_goto_tb(s, n, dest)) {
384 tcg_gen_goto_tb(n);
385 gen_a64_set_pc_im(dest);
386 tcg_gen_exit_tb(tb, n);
387 s->base.is_jmp = DISAS_NORETURN;
388 } else {
389 gen_a64_set_pc_im(dest);
390 if (s->ss_active) {
391 gen_step_complete_exception(s);
392 } else if (s->base.singlestep_enabled) {
393 gen_exception_internal(EXCP_DEBUG);
394 } else {
395 tcg_gen_lookup_and_goto_ptr();
396 s->base.is_jmp = DISAS_NORETURN;
397 }
398 }
399 }
400
401 void unallocated_encoding(DisasContext *s)
402 {
403 /* Unallocated and reserved encodings are uncategorized */
404 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
405 default_exception_el(s));
406 }
407
408 static void init_tmp_a64_array(DisasContext *s)
409 {
410 #ifdef CONFIG_DEBUG_TCG
411 memset(s->tmp_a64, 0, sizeof(s->tmp_a64));
412 #endif
413 s->tmp_a64_count = 0;
414 }
415
416 static void free_tmp_a64(DisasContext *s)
417 {
418 int i;
419 for (i = 0; i < s->tmp_a64_count; i++) {
420 tcg_temp_free_i64(s->tmp_a64[i]);
421 }
422 init_tmp_a64_array(s);
423 }
424
425 TCGv_i64 new_tmp_a64(DisasContext *s)
426 {
427 assert(s->tmp_a64_count < TMP_A64_MAX);
428 return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
429 }
430
431 TCGv_i64 new_tmp_a64_zero(DisasContext *s)
432 {
433 TCGv_i64 t = new_tmp_a64(s);
434 tcg_gen_movi_i64(t, 0);
435 return t;
436 }
437
438 /*
439 * Register access functions
440 *
441 * These functions are used for directly accessing a register in where
442 * changes to the final register value are likely to be made. If you
443 * need to use a register for temporary calculation (e.g. index type
444 * operations) use the read_* form.
445 *
446 * B1.2.1 Register mappings
447 *
448 * In instruction register encoding 31 can refer to ZR (zero register) or
449 * the SP (stack pointer) depending on context. In QEMU's case we map SP
450 * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
451 * This is the point of the _sp forms.
452 */
453 TCGv_i64 cpu_reg(DisasContext *s, int reg)
454 {
455 if (reg == 31) {
456 return new_tmp_a64_zero(s);
457 } else {
458 return cpu_X[reg];
459 }
460 }
461
462 /* register access for when 31 == SP */
463 TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
464 {
465 return cpu_X[reg];
466 }
467
468 /* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
469 * representing the register contents. This TCGv is an auto-freed
470 * temporary so it need not be explicitly freed, and may be modified.
471 */
472 TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
473 {
474 TCGv_i64 v = new_tmp_a64(s);
475 if (reg != 31) {
476 if (sf) {
477 tcg_gen_mov_i64(v, cpu_X[reg]);
478 } else {
479 tcg_gen_ext32u_i64(v, cpu_X[reg]);
480 }
481 } else {
482 tcg_gen_movi_i64(v, 0);
483 }
484 return v;
485 }
486
487 TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
488 {
489 TCGv_i64 v = new_tmp_a64(s);
490 if (sf) {
491 tcg_gen_mov_i64(v, cpu_X[reg]);
492 } else {
493 tcg_gen_ext32u_i64(v, cpu_X[reg]);
494 }
495 return v;
496 }
497
498 /* Return the offset into CPUARMState of a slice (from
499 * the least significant end) of FP register Qn (ie
500 * Dn, Sn, Hn or Bn).
501 * (Note that this is not the same mapping as for A32; see cpu.h)
502 */
503 static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size)
504 {
505 return vec_reg_offset(s, regno, 0, size);
506 }
507
508 /* Offset of the high half of the 128 bit vector Qn */
509 static inline int fp_reg_hi_offset(DisasContext *s, int regno)
510 {
511 return vec_reg_offset(s, regno, 1, MO_64);
512 }
513
514 /* Convenience accessors for reading and writing single and double
515 * FP registers. Writing clears the upper parts of the associated
516 * 128 bit vector register, as required by the architecture.
517 * Note that unlike the GP register accessors, the values returned
518 * by the read functions must be manually freed.
519 */
520 static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
521 {
522 TCGv_i64 v = tcg_temp_new_i64();
523
524 tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
525 return v;
526 }
527
528 static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
529 {
530 TCGv_i32 v = tcg_temp_new_i32();
531
532 tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(s, reg, MO_32));
533 return v;
534 }
535
536 static TCGv_i32 read_fp_hreg(DisasContext *s, int reg)
537 {
538 TCGv_i32 v = tcg_temp_new_i32();
539
540 tcg_gen_ld16u_i32(v, cpu_env, fp_reg_offset(s, reg, MO_16));
541 return v;
542 }
543
544 /* Clear the bits above an N-bit vector, for N = (is_q ? 128 : 64).
545 * If SVE is not enabled, then there are only 128 bits in the vector.
546 */
547 static void clear_vec_high(DisasContext *s, bool is_q, int rd)
548 {
549 unsigned ofs = fp_reg_offset(s, rd, MO_64);
550 unsigned vsz = vec_full_reg_size(s);
551
552 if (!is_q) {
553 TCGv_i64 tcg_zero = tcg_const_i64(0);
554 tcg_gen_st_i64(tcg_zero, cpu_env, ofs + 8);
555 tcg_temp_free_i64(tcg_zero);
556 }
557 if (vsz > 16) {
558 tcg_gen_gvec_dup8i(ofs + 16, vsz - 16, vsz - 16, 0);
559 }
560 }
561
562 void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
563 {
564 unsigned ofs = fp_reg_offset(s, reg, MO_64);
565
566 tcg_gen_st_i64(v, cpu_env, ofs);
567 clear_vec_high(s, false, reg);
568 }
569
570 static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
571 {
572 TCGv_i64 tmp = tcg_temp_new_i64();
573
574 tcg_gen_extu_i32_i64(tmp, v);
575 write_fp_dreg(s, reg, tmp);
576 tcg_temp_free_i64(tmp);
577 }
578
579 TCGv_ptr get_fpstatus_ptr(bool is_f16)
580 {
581 TCGv_ptr statusptr = tcg_temp_new_ptr();
582 int offset;
583
584 /* In A64 all instructions (both FP and Neon) use the FPCR; there
585 * is no equivalent of the A32 Neon "standard FPSCR value".
586 * However half-precision operations operate under a different
587 * FZ16 flag and use vfp.fp_status_f16 instead of vfp.fp_status.
588 */
589 if (is_f16) {
590 offset = offsetof(CPUARMState, vfp.fp_status_f16);
591 } else {
592 offset = offsetof(CPUARMState, vfp.fp_status);
593 }
594 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
595 return statusptr;
596 }
597
598 /* Expand a 2-operand AdvSIMD vector operation using an expander function. */
599 static void gen_gvec_fn2(DisasContext *s, bool is_q, int rd, int rn,
600 GVecGen2Fn *gvec_fn, int vece)
601 {
602 gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
603 is_q ? 16 : 8, vec_full_reg_size(s));
604 }
605
606 /* Expand a 2-operand + immediate AdvSIMD vector operation using
607 * an expander function.
608 */
609 static void gen_gvec_fn2i(DisasContext *s, bool is_q, int rd, int rn,
610 int64_t imm, GVecGen2iFn *gvec_fn, int vece)
611 {
612 gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
613 imm, is_q ? 16 : 8, vec_full_reg_size(s));
614 }
615
616 /* Expand a 3-operand AdvSIMD vector operation using an expander function. */
617 static void gen_gvec_fn3(DisasContext *s, bool is_q, int rd, int rn, int rm,
618 GVecGen3Fn *gvec_fn, int vece)
619 {
620 gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
621 vec_full_reg_offset(s, rm), is_q ? 16 : 8, vec_full_reg_size(s));
622 }
623
624 /* Expand a 2-operand + immediate AdvSIMD vector operation using
625 * an op descriptor.
626 */
627 static void gen_gvec_op2i(DisasContext *s, bool is_q, int rd,
628 int rn, int64_t imm, const GVecGen2i *gvec_op)
629 {
630 tcg_gen_gvec_2i(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
631 is_q ? 16 : 8, vec_full_reg_size(s), imm, gvec_op);
632 }
633
634 /* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
635 static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
636 int rn, int rm, const GVecGen3 *gvec_op)
637 {
638 tcg_gen_gvec_3(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
639 vec_full_reg_offset(s, rm), is_q ? 16 : 8,
640 vec_full_reg_size(s), gvec_op);
641 }
642
643 /* Expand a 3-operand operation using an out-of-line helper. */
644 static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
645 int rn, int rm, int data, gen_helper_gvec_3 *fn)
646 {
647 tcg_gen_gvec_3_ool(vec_full_reg_offset(s, rd),
648 vec_full_reg_offset(s, rn),
649 vec_full_reg_offset(s, rm),
650 is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
651 }
652
653 /* Expand a 3-operand + env pointer operation using
654 * an out-of-line helper.
655 */
656 static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
657 int rn, int rm, gen_helper_gvec_3_ptr *fn)
658 {
659 tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
660 vec_full_reg_offset(s, rn),
661 vec_full_reg_offset(s, rm), cpu_env,
662 is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
663 }
664
665 /* Expand a 3-operand + fpstatus pointer + simd data value operation using
666 * an out-of-line helper.
667 */
668 static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
669 int rm, bool is_fp16, int data,
670 gen_helper_gvec_3_ptr *fn)
671 {
672 TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
673 tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
674 vec_full_reg_offset(s, rn),
675 vec_full_reg_offset(s, rm), fpst,
676 is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
677 tcg_temp_free_ptr(fpst);
678 }
679
680 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
681 * than the 32 bit equivalent.
682 */
683 static inline void gen_set_NZ64(TCGv_i64 result)
684 {
685 tcg_gen_extr_i64_i32(cpu_ZF, cpu_NF, result);
686 tcg_gen_or_i32(cpu_ZF, cpu_ZF, cpu_NF);
687 }
688
689 /* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
690 static inline void gen_logic_CC(int sf, TCGv_i64 result)
691 {
692 if (sf) {
693 gen_set_NZ64(result);
694 } else {
695 tcg_gen_extrl_i64_i32(cpu_ZF, result);
696 tcg_gen_mov_i32(cpu_NF, cpu_ZF);
697 }
698 tcg_gen_movi_i32(cpu_CF, 0);
699 tcg_gen_movi_i32(cpu_VF, 0);
700 }
701
702 /* dest = T0 + T1; compute C, N, V and Z flags */
703 static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
704 {
705 if (sf) {
706 TCGv_i64 result, flag, tmp;
707 result = tcg_temp_new_i64();
708 flag = tcg_temp_new_i64();
709 tmp = tcg_temp_new_i64();
710
711 tcg_gen_movi_i64(tmp, 0);
712 tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
713
714 tcg_gen_extrl_i64_i32(cpu_CF, flag);
715
716 gen_set_NZ64(result);
717
718 tcg_gen_xor_i64(flag, result, t0);
719 tcg_gen_xor_i64(tmp, t0, t1);
720 tcg_gen_andc_i64(flag, flag, tmp);
721 tcg_temp_free_i64(tmp);
722 tcg_gen_extrh_i64_i32(cpu_VF, flag);
723
724 tcg_gen_mov_i64(dest, result);
725 tcg_temp_free_i64(result);
726 tcg_temp_free_i64(flag);
727 } else {
728 /* 32 bit arithmetic */
729 TCGv_i32 t0_32 = tcg_temp_new_i32();
730 TCGv_i32 t1_32 = tcg_temp_new_i32();
731 TCGv_i32 tmp = tcg_temp_new_i32();
732
733 tcg_gen_movi_i32(tmp, 0);
734 tcg_gen_extrl_i64_i32(t0_32, t0);
735 tcg_gen_extrl_i64_i32(t1_32, t1);
736 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
737 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
738 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
739 tcg_gen_xor_i32(tmp, t0_32, t1_32);
740 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
741 tcg_gen_extu_i32_i64(dest, cpu_NF);
742
743 tcg_temp_free_i32(tmp);
744 tcg_temp_free_i32(t0_32);
745 tcg_temp_free_i32(t1_32);
746 }
747 }
748
749 /* dest = T0 - T1; compute C, N, V and Z flags */
750 static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
751 {
752 if (sf) {
753 /* 64 bit arithmetic */
754 TCGv_i64 result, flag, tmp;
755
756 result = tcg_temp_new_i64();
757 flag = tcg_temp_new_i64();
758 tcg_gen_sub_i64(result, t0, t1);
759
760 gen_set_NZ64(result);
761
762 tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
763 tcg_gen_extrl_i64_i32(cpu_CF, flag);
764
765 tcg_gen_xor_i64(flag, result, t0);
766 tmp = tcg_temp_new_i64();
767 tcg_gen_xor_i64(tmp, t0, t1);
768 tcg_gen_and_i64(flag, flag, tmp);
769 tcg_temp_free_i64(tmp);
770 tcg_gen_extrh_i64_i32(cpu_VF, flag);
771 tcg_gen_mov_i64(dest, result);
772 tcg_temp_free_i64(flag);
773 tcg_temp_free_i64(result);
774 } else {
775 /* 32 bit arithmetic */
776 TCGv_i32 t0_32 = tcg_temp_new_i32();
777 TCGv_i32 t1_32 = tcg_temp_new_i32();
778 TCGv_i32 tmp;
779
780 tcg_gen_extrl_i64_i32(t0_32, t0);
781 tcg_gen_extrl_i64_i32(t1_32, t1);
782 tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
783 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
784 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
785 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
786 tmp = tcg_temp_new_i32();
787 tcg_gen_xor_i32(tmp, t0_32, t1_32);
788 tcg_temp_free_i32(t0_32);
789 tcg_temp_free_i32(t1_32);
790 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
791 tcg_temp_free_i32(tmp);
792 tcg_gen_extu_i32_i64(dest, cpu_NF);
793 }
794 }
795
796 /* dest = T0 + T1 + CF; do not compute flags. */
797 static void gen_adc(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
798 {
799 TCGv_i64 flag = tcg_temp_new_i64();
800 tcg_gen_extu_i32_i64(flag, cpu_CF);
801 tcg_gen_add_i64(dest, t0, t1);
802 tcg_gen_add_i64(dest, dest, flag);
803 tcg_temp_free_i64(flag);
804
805 if (!sf) {
806 tcg_gen_ext32u_i64(dest, dest);
807 }
808 }
809
810 /* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
811 static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
812 {
813 if (sf) {
814 TCGv_i64 result, cf_64, vf_64, tmp;
815 result = tcg_temp_new_i64();
816 cf_64 = tcg_temp_new_i64();
817 vf_64 = tcg_temp_new_i64();
818 tmp = tcg_const_i64(0);
819
820 tcg_gen_extu_i32_i64(cf_64, cpu_CF);
821 tcg_gen_add2_i64(result, cf_64, t0, tmp, cf_64, tmp);
822 tcg_gen_add2_i64(result, cf_64, result, cf_64, t1, tmp);
823 tcg_gen_extrl_i64_i32(cpu_CF, cf_64);
824 gen_set_NZ64(result);
825
826 tcg_gen_xor_i64(vf_64, result, t0);
827 tcg_gen_xor_i64(tmp, t0, t1);
828 tcg_gen_andc_i64(vf_64, vf_64, tmp);
829 tcg_gen_extrh_i64_i32(cpu_VF, vf_64);
830
831 tcg_gen_mov_i64(dest, result);
832
833 tcg_temp_free_i64(tmp);
834 tcg_temp_free_i64(vf_64);
835 tcg_temp_free_i64(cf_64);
836 tcg_temp_free_i64(result);
837 } else {
838 TCGv_i32 t0_32, t1_32, tmp;
839 t0_32 = tcg_temp_new_i32();
840 t1_32 = tcg_temp_new_i32();
841 tmp = tcg_const_i32(0);
842
843 tcg_gen_extrl_i64_i32(t0_32, t0);
844 tcg_gen_extrl_i64_i32(t1_32, t1);
845 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, cpu_CF, tmp);
846 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1_32, tmp);
847
848 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
849 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
850 tcg_gen_xor_i32(tmp, t0_32, t1_32);
851 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
852 tcg_gen_extu_i32_i64(dest, cpu_NF);
853
854 tcg_temp_free_i32(tmp);
855 tcg_temp_free_i32(t1_32);
856 tcg_temp_free_i32(t0_32);
857 }
858 }
859
860 /*
861 * Load/Store generators
862 */
863
864 /*
865 * Store from GPR register to memory.
866 */
867 static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source,
868 TCGv_i64 tcg_addr, int size, int memidx,
869 bool iss_valid,
870 unsigned int iss_srt,
871 bool iss_sf, bool iss_ar)
872 {
873 g_assert(size <= 3);
874 tcg_gen_qemu_st_i64(source, tcg_addr, memidx, s->be_data + size);
875
876 if (iss_valid) {
877 uint32_t syn;
878
879 syn = syn_data_abort_with_iss(0,
880 size,
881 false,
882 iss_srt,
883 iss_sf,
884 iss_ar,
885 0, 0, 0, 0, 0, false);
886 disas_set_insn_syndrome(s, syn);
887 }
888 }
889
890 static void do_gpr_st(DisasContext *s, TCGv_i64 source,
891 TCGv_i64 tcg_addr, int size,
892 bool iss_valid,
893 unsigned int iss_srt,
894 bool iss_sf, bool iss_ar)
895 {
896 do_gpr_st_memidx(s, source, tcg_addr, size, get_mem_index(s),
897 iss_valid, iss_srt, iss_sf, iss_ar);
898 }
899
900 /*
901 * Load from memory to GPR register
902 */
903 static void do_gpr_ld_memidx(DisasContext *s,
904 TCGv_i64 dest, TCGv_i64 tcg_addr,
905 int size, bool is_signed,
906 bool extend, int memidx,
907 bool iss_valid, unsigned int iss_srt,
908 bool iss_sf, bool iss_ar)
909 {
910 TCGMemOp memop = s->be_data + size;
911
912 g_assert(size <= 3);
913
914 if (is_signed) {
915 memop += MO_SIGN;
916 }
917
918 tcg_gen_qemu_ld_i64(dest, tcg_addr, memidx, memop);
919
920 if (extend && is_signed) {
921 g_assert(size < 3);
922 tcg_gen_ext32u_i64(dest, dest);
923 }
924
925 if (iss_valid) {
926 uint32_t syn;
927
928 syn = syn_data_abort_with_iss(0,
929 size,
930 is_signed,
931 iss_srt,
932 iss_sf,
933 iss_ar,
934 0, 0, 0, 0, 0, false);
935 disas_set_insn_syndrome(s, syn);
936 }
937 }
938
939 static void do_gpr_ld(DisasContext *s,
940 TCGv_i64 dest, TCGv_i64 tcg_addr,
941 int size, bool is_signed, bool extend,
942 bool iss_valid, unsigned int iss_srt,
943 bool iss_sf, bool iss_ar)
944 {
945 do_gpr_ld_memidx(s, dest, tcg_addr, size, is_signed, extend,
946 get_mem_index(s),
947 iss_valid, iss_srt, iss_sf, iss_ar);
948 }
949
950 /*
951 * Store from FP register to memory
952 */
953 static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
954 {
955 /* This writes the bottom N bits of a 128 bit wide vector to memory */
956 TCGv_i64 tmp = tcg_temp_new_i64();
957 tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
958 if (size < 4) {
959 tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s),
960 s->be_data + size);
961 } else {
962 bool be = s->be_data == MO_BE;
963 TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
964
965 tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
966 tcg_gen_qemu_st_i64(tmp, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
967 s->be_data | MO_Q);
968 tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
969 tcg_gen_qemu_st_i64(tmp, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
970 s->be_data | MO_Q);
971 tcg_temp_free_i64(tcg_hiaddr);
972 }
973
974 tcg_temp_free_i64(tmp);
975 }
976
977 /*
978 * Load from memory to FP register
979 */
980 static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
981 {
982 /* This always zero-extends and writes to a full 128 bit wide vector */
983 TCGv_i64 tmplo = tcg_temp_new_i64();
984 TCGv_i64 tmphi;
985
986 if (size < 4) {
987 TCGMemOp memop = s->be_data + size;
988 tmphi = tcg_const_i64(0);
989 tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
990 } else {
991 bool be = s->be_data == MO_BE;
992 TCGv_i64 tcg_hiaddr;
993
994 tmphi = tcg_temp_new_i64();
995 tcg_hiaddr = tcg_temp_new_i64();
996
997 tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
998 tcg_gen_qemu_ld_i64(tmplo, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
999 s->be_data | MO_Q);
1000 tcg_gen_qemu_ld_i64(tmphi, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
1001 s->be_data | MO_Q);
1002 tcg_temp_free_i64(tcg_hiaddr);
1003 }
1004
1005 tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
1006 tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
1007
1008 tcg_temp_free_i64(tmplo);
1009 tcg_temp_free_i64(tmphi);
1010
1011 clear_vec_high(s, true, destidx);
1012 }
1013
1014 /*
1015 * Vector load/store helpers.
1016 *
1017 * The principal difference between this and a FP load is that we don't
1018 * zero extend as we are filling a partial chunk of the vector register.
1019 * These functions don't support 128 bit loads/stores, which would be
1020 * normal load/store operations.
1021 *
1022 * The _i32 versions are useful when operating on 32 bit quantities
1023 * (eg for floating point single or using Neon helper functions).
1024 */
1025
1026 /* Get value of an element within a vector register */
1027 static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
1028 int element, TCGMemOp memop)
1029 {
1030 int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
1031 switch (memop) {
1032 case MO_8:
1033 tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
1034 break;
1035 case MO_16:
1036 tcg_gen_ld16u_i64(tcg_dest, cpu_env, vect_off);
1037 break;
1038 case MO_32:
1039 tcg_gen_ld32u_i64(tcg_dest, cpu_env, vect_off);
1040 break;
1041 case MO_8|MO_SIGN:
1042 tcg_gen_ld8s_i64(tcg_dest, cpu_env, vect_off);
1043 break;
1044 case MO_16|MO_SIGN:
1045 tcg_gen_ld16s_i64(tcg_dest, cpu_env, vect_off);
1046 break;
1047 case MO_32|MO_SIGN:
1048 tcg_gen_ld32s_i64(tcg_dest, cpu_env, vect_off);
1049 break;
1050 case MO_64:
1051 case MO_64|MO_SIGN:
1052 tcg_gen_ld_i64(tcg_dest, cpu_env, vect_off);
1053 break;
1054 default:
1055 g_assert_not_reached();
1056 }
1057 }
1058
1059 static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
1060 int element, TCGMemOp memop)
1061 {
1062 int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
1063 switch (memop) {
1064 case MO_8:
1065 tcg_gen_ld8u_i32(tcg_dest, cpu_env, vect_off);
1066 break;
1067 case MO_16:
1068 tcg_gen_ld16u_i32(tcg_dest, cpu_env, vect_off);
1069 break;
1070 case MO_8|MO_SIGN:
1071 tcg_gen_ld8s_i32(tcg_dest, cpu_env, vect_off);
1072 break;
1073 case MO_16|MO_SIGN:
1074 tcg_gen_ld16s_i32(tcg_dest, cpu_env, vect_off);
1075 break;
1076 case MO_32:
1077 case MO_32|MO_SIGN:
1078 tcg_gen_ld_i32(tcg_dest, cpu_env, vect_off);
1079 break;
1080 default:
1081 g_assert_not_reached();
1082 }
1083 }
1084
1085 /* Set value of an element within a vector register */
1086 static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
1087 int element, TCGMemOp memop)
1088 {
1089 int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
1090 switch (memop) {
1091 case MO_8:
1092 tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
1093 break;
1094 case MO_16:
1095 tcg_gen_st16_i64(tcg_src, cpu_env, vect_off);
1096 break;
1097 case MO_32:
1098 tcg_gen_st32_i64(tcg_src, cpu_env, vect_off);
1099 break;
1100 case MO_64:
1101 tcg_gen_st_i64(tcg_src, cpu_env, vect_off);
1102 break;
1103 default:
1104 g_assert_not_reached();
1105 }
1106 }
1107
1108 static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
1109 int destidx, int element, TCGMemOp memop)
1110 {
1111 int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
1112 switch (memop) {
1113 case MO_8:
1114 tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);
1115 break;
1116 case MO_16:
1117 tcg_gen_st16_i32(tcg_src, cpu_env, vect_off);
1118 break;
1119 case MO_32:
1120 tcg_gen_st_i32(tcg_src, cpu_env, vect_off);
1121 break;
1122 default:
1123 g_assert_not_reached();
1124 }
1125 }
1126
1127 /* Store from vector register to memory */
1128 static void do_vec_st(DisasContext *s, int srcidx, int element,
1129 TCGv_i64 tcg_addr, int size)
1130 {
1131 TCGMemOp memop = s->be_data + size;
1132 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1133
1134 read_vec_element(s, tcg_tmp, srcidx, element, size);
1135 tcg_gen_qemu_st_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
1136
1137 tcg_temp_free_i64(tcg_tmp);
1138 }
1139
1140 /* Load from memory to vector register */
1141 static void do_vec_ld(DisasContext *s, int destidx, int element,
1142 TCGv_i64 tcg_addr, int size)
1143 {
1144 TCGMemOp memop = s->be_data + size;
1145 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1146
1147 tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
1148 write_vec_element(s, tcg_tmp, destidx, element, size);
1149
1150 tcg_temp_free_i64(tcg_tmp);
1151 }
1152
1153 /* Check that FP/Neon access is enabled. If it is, return
1154 * true. If not, emit code to generate an appropriate exception,
1155 * and return false; the caller should not emit any code for
1156 * the instruction. Note that this check must happen after all
1157 * unallocated-encoding checks (otherwise the syndrome information
1158 * for the resulting exception will be incorrect).
1159 */
1160 static inline bool fp_access_check(DisasContext *s)
1161 {
1162 assert(!s->fp_access_checked);
1163 s->fp_access_checked = true;
1164
1165 if (!s->fp_excp_el) {
1166 return true;
1167 }
1168
1169 gen_exception_insn(s, 4, EXCP_UDEF, syn_fp_access_trap(1, 0xe, false),
1170 s->fp_excp_el);
1171 return false;
1172 }
1173
1174 /* Check that SVE access is enabled. If it is, return true.
1175 * If not, emit code to generate an appropriate exception and return false.
1176 */
1177 bool sve_access_check(DisasContext *s)
1178 {
1179 if (s->sve_excp_el) {
1180 gen_exception_insn(s, 4, EXCP_UDEF, syn_sve_access_trap(),
1181 s->sve_excp_el);
1182 return false;
1183 }
1184 return fp_access_check(s);
1185 }
1186
1187 /*
1188 * This utility function is for doing register extension with an
1189 * optional shift. You will likely want to pass a temporary for the
1190 * destination register. See DecodeRegExtend() in the ARM ARM.
1191 */
1192 static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
1193 int option, unsigned int shift)
1194 {
1195 int extsize = extract32(option, 0, 2);
1196 bool is_signed = extract32(option, 2, 1);
1197
1198 if (is_signed) {
1199 switch (extsize) {
1200 case 0:
1201 tcg_gen_ext8s_i64(tcg_out, tcg_in);
1202 break;
1203 case 1:
1204 tcg_gen_ext16s_i64(tcg_out, tcg_in);
1205 break;
1206 case 2:
1207 tcg_gen_ext32s_i64(tcg_out, tcg_in);
1208 break;
1209 case 3:
1210 tcg_gen_mov_i64(tcg_out, tcg_in);
1211 break;
1212 }
1213 } else {
1214 switch (extsize) {
1215 case 0:
1216 tcg_gen_ext8u_i64(tcg_out, tcg_in);
1217 break;
1218 case 1:
1219 tcg_gen_ext16u_i64(tcg_out, tcg_in);
1220 break;
1221 case 2:
1222 tcg_gen_ext32u_i64(tcg_out, tcg_in);
1223 break;
1224 case 3:
1225 tcg_gen_mov_i64(tcg_out, tcg_in);
1226 break;
1227 }
1228 }
1229
1230 if (shift) {
1231 tcg_gen_shli_i64(tcg_out, tcg_out, shift);
1232 }
1233 }
1234
1235 static inline void gen_check_sp_alignment(DisasContext *s)
1236 {
1237 /* The AArch64 architecture mandates that (if enabled via PSTATE
1238 * or SCTLR bits) there is a check that SP is 16-aligned on every
1239 * SP-relative load or store (with an exception generated if it is not).
1240 * In line with general QEMU practice regarding misaligned accesses,
1241 * we omit these checks for the sake of guest program performance.
1242 * This function is provided as a hook so we can more easily add these
1243 * checks in future (possibly as a "favour catching guest program bugs
1244 * over speed" user selectable option).
1245 */
1246 }
1247
1248 /*
1249 * This provides a simple table based table lookup decoder. It is
1250 * intended to be used when the relevant bits for decode are too
1251 * awkwardly placed and switch/if based logic would be confusing and
1252 * deeply nested. Since it's a linear search through the table, tables
1253 * should be kept small.
1254 *
1255 * It returns the first handler where insn & mask == pattern, or
1256 * NULL if there is no match.
1257 * The table is terminated by an empty mask (i.e. 0)
1258 */
1259 static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
1260 uint32_t insn)
1261 {
1262 const AArch64DecodeTable *tptr = table;
1263
1264 while (tptr->mask) {
1265 if ((insn & tptr->mask) == tptr->pattern) {
1266 return tptr->disas_fn;
1267 }
1268 tptr++;
1269 }
1270 return NULL;
1271 }
1272
1273 /*
1274 * The instruction disassembly implemented here matches
1275 * the instruction encoding classifications in chapter C4
1276 * of the ARM Architecture Reference Manual (DDI0487B_a);
1277 * classification names and decode diagrams here should generally
1278 * match up with those in the manual.
1279 */
1280
1281 /* Unconditional branch (immediate)
1282 * 31 30 26 25 0
1283 * +----+-----------+-------------------------------------+
1284 * | op | 0 0 1 0 1 | imm26 |
1285 * +----+-----------+-------------------------------------+
1286 */
1287 static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
1288 {
1289 uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
1290
1291 if (insn & (1U << 31)) {
1292 /* BL Branch with link */
1293 tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
1294 }
1295
1296 /* B Branch / BL Branch with link */
1297 gen_goto_tb(s, 0, addr);
1298 }
1299
1300 /* Compare and branch (immediate)
1301 * 31 30 25 24 23 5 4 0
1302 * +----+-------------+----+---------------------+--------+
1303 * | sf | 0 1 1 0 1 0 | op | imm19 | Rt |
1304 * +----+-------------+----+---------------------+--------+
1305 */
1306 static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
1307 {
1308 unsigned int sf, op, rt;
1309 uint64_t addr;
1310 TCGLabel *label_match;
1311 TCGv_i64 tcg_cmp;
1312
1313 sf = extract32(insn, 31, 1);
1314 op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
1315 rt = extract32(insn, 0, 5);
1316 addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
1317
1318 tcg_cmp = read_cpu_reg(s, rt, sf);
1319 label_match = gen_new_label();
1320
1321 tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
1322 tcg_cmp, 0, label_match);
1323
1324 gen_goto_tb(s, 0, s->pc);
1325 gen_set_label(label_match);
1326 gen_goto_tb(s, 1, addr);
1327 }
1328
1329 /* Test and branch (immediate)
1330 * 31 30 25 24 23 19 18 5 4 0
1331 * +----+-------------+----+-------+-------------+------+
1332 * | b5 | 0 1 1 0 1 1 | op | b40 | imm14 | Rt |
1333 * +----+-------------+----+-------+-------------+------+
1334 */
1335 static void disas_test_b_imm(DisasContext *s, uint32_t insn)
1336 {
1337 unsigned int bit_pos, op, rt;
1338 uint64_t addr;
1339 TCGLabel *label_match;
1340 TCGv_i64 tcg_cmp;
1341
1342 bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
1343 op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
1344 addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
1345 rt = extract32(insn, 0, 5);
1346
1347 tcg_cmp = tcg_temp_new_i64();
1348 tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
1349 label_match = gen_new_label();
1350 tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
1351 tcg_cmp, 0, label_match);
1352 tcg_temp_free_i64(tcg_cmp);
1353 gen_goto_tb(s, 0, s->pc);
1354 gen_set_label(label_match);
1355 gen_goto_tb(s, 1, addr);
1356 }
1357
1358 /* Conditional branch (immediate)
1359 * 31 25 24 23 5 4 3 0
1360 * +---------------+----+---------------------+----+------+
1361 * | 0 1 0 1 0 1 0 | o1 | imm19 | o0 | cond |
1362 * +---------------+----+---------------------+----+------+
1363 */
1364 static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
1365 {
1366 unsigned int cond;
1367 uint64_t addr;
1368
1369 if ((insn & (1 << 4)) || (insn & (1 << 24))) {
1370 unallocated_encoding(s);
1371 return;
1372 }
1373 addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
1374 cond = extract32(insn, 0, 4);
1375
1376 if (cond < 0x0e) {
1377 /* genuinely conditional branches */
1378 TCGLabel *label_match = gen_new_label();
1379 arm_gen_test_cc(cond, label_match);
1380 gen_goto_tb(s, 0, s->pc);
1381 gen_set_label(label_match);
1382 gen_goto_tb(s, 1, addr);
1383 } else {
1384 /* 0xe and 0xf are both "always" conditions */
1385 gen_goto_tb(s, 0, addr);
1386 }
1387 }
1388
1389 /* HINT instruction group, including various allocated HINTs */
1390 static void handle_hint(DisasContext *s, uint32_t insn,
1391 unsigned int op1, unsigned int op2, unsigned int crm)
1392 {
1393 unsigned int selector = crm << 3 | op2;
1394
1395 if (op1 != 3) {
1396 unallocated_encoding(s);
1397 return;
1398 }
1399
1400 switch (selector) {
1401 case 0: /* NOP */
1402 return;
1403 case 3: /* WFI */
1404 s->base.is_jmp = DISAS_WFI;
1405 return;
1406 /* When running in MTTCG we don't generate jumps to the yield and
1407 * WFE helpers as it won't affect the scheduling of other vCPUs.
1408 * If we wanted to more completely model WFE/SEV so we don't busy
1409 * spin unnecessarily we would need to do something more involved.
1410 */
1411 case 1: /* YIELD */
1412 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
1413 s->base.is_jmp = DISAS_YIELD;
1414 }
1415 return;
1416 case 2: /* WFE */
1417 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
1418 s->base.is_jmp = DISAS_WFE;
1419 }
1420 return;
1421 case 4: /* SEV */
1422 case 5: /* SEVL */
1423 /* we treat all as NOP at least for now */
1424 return;
1425 default:
1426 /* default specified as NOP equivalent */
1427 return;
1428 }
1429 }
1430
1431 static void gen_clrex(DisasContext *s, uint32_t insn)
1432 {
1433 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
1434 }
1435
1436 /* CLREX, DSB, DMB, ISB */
1437 static void handle_sync(DisasContext *s, uint32_t insn,
1438 unsigned int op1, unsigned int op2, unsigned int crm)
1439 {
1440 TCGBar bar;
1441
1442 if (op1 != 3) {
1443 unallocated_encoding(s);
1444 return;
1445 }
1446
1447 switch (op2) {
1448 case 2: /* CLREX */
1449 gen_clrex(s, insn);
1450 return;
1451 case 4: /* DSB */
1452 case 5: /* DMB */
1453 switch (crm & 3) {
1454 case 1: /* MBReqTypes_Reads */
1455 bar = TCG_BAR_SC | TCG_MO_LD_LD | TCG_MO_LD_ST;
1456 break;
1457 case 2: /* MBReqTypes_Writes */
1458 bar = TCG_BAR_SC | TCG_MO_ST_ST;
1459 break;
1460 default: /* MBReqTypes_All */
1461 bar = TCG_BAR_SC | TCG_MO_ALL;
1462 break;
1463 }
1464 tcg_gen_mb(bar);
1465 return;
1466 case 6: /* ISB */
1467 /* We need to break the TB after this insn to execute
1468 * a self-modified code correctly and also to take
1469 * any pending interrupts immediately.
1470 */
1471 gen_goto_tb(s, 0, s->pc);
1472 return;
1473 default:
1474 unallocated_encoding(s);
1475 return;
1476 }
1477 }
1478
1479 /* MSR (immediate) - move immediate to processor state field */
1480 static void handle_msr_i(DisasContext *s, uint32_t insn,
1481 unsigned int op1, unsigned int op2, unsigned int crm)
1482 {
1483 int op = op1 << 3 | op2;
1484 switch (op) {
1485 case 0x05: /* SPSel */
1486 if (s->current_el == 0) {
1487 unallocated_encoding(s);
1488 return;
1489 }
1490 /* fall through */
1491 case 0x1e: /* DAIFSet */
1492 case 0x1f: /* DAIFClear */
1493 {
1494 TCGv_i32 tcg_imm = tcg_const_i32(crm);
1495 TCGv_i32 tcg_op = tcg_const_i32(op);
1496 gen_a64_set_pc_im(s->pc - 4);
1497 gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm);
1498 tcg_temp_free_i32(tcg_imm);
1499 tcg_temp_free_i32(tcg_op);
1500 /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs. */
1501 gen_a64_set_pc_im(s->pc);
1502 s->base.is_jmp = (op == 0x1f ? DISAS_EXIT : DISAS_JUMP);
1503 break;
1504 }
1505 default:
1506 unallocated_encoding(s);
1507 return;
1508 }
1509 }
1510
1511 static void gen_get_nzcv(TCGv_i64 tcg_rt)
1512 {
1513 TCGv_i32 tmp = tcg_temp_new_i32();
1514 TCGv_i32 nzcv = tcg_temp_new_i32();
1515
1516 /* build bit 31, N */
1517 tcg_gen_andi_i32(nzcv, cpu_NF, (1U << 31));
1518 /* build bit 30, Z */
1519 tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_ZF, 0);
1520 tcg_gen_deposit_i32(nzcv, nzcv, tmp, 30, 1);
1521 /* build bit 29, C */
1522 tcg_gen_deposit_i32(nzcv, nzcv, cpu_CF, 29, 1);
1523 /* build bit 28, V */
1524 tcg_gen_shri_i32(tmp, cpu_VF, 31);
1525 tcg_gen_deposit_i32(nzcv, nzcv, tmp, 28, 1);
1526 /* generate result */
1527 tcg_gen_extu_i32_i64(tcg_rt, nzcv);
1528
1529 tcg_temp_free_i32(nzcv);
1530 tcg_temp_free_i32(tmp);
1531 }
1532
1533 static void gen_set_nzcv(TCGv_i64 tcg_rt)
1534
1535 {
1536 TCGv_i32 nzcv = tcg_temp_new_i32();
1537
1538 /* take NZCV from R[t] */
1539 tcg_gen_extrl_i64_i32(nzcv, tcg_rt);
1540
1541 /* bit 31, N */
1542 tcg_gen_andi_i32(cpu_NF, nzcv, (1U << 31));
1543 /* bit 30, Z */
1544 tcg_gen_andi_i32(cpu_ZF, nzcv, (1 << 30));
1545 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_ZF, cpu_ZF, 0);
1546 /* bit 29, C */
1547 tcg_gen_andi_i32(cpu_CF, nzcv, (1 << 29));
1548 tcg_gen_shri_i32(cpu_CF, cpu_CF, 29);
1549 /* bit 28, V */
1550 tcg_gen_andi_i32(cpu_VF, nzcv, (1 << 28));
1551 tcg_gen_shli_i32(cpu_VF, cpu_VF, 3);
1552 tcg_temp_free_i32(nzcv);
1553 }
1554
1555 /* MRS - move from system register
1556 * MSR (register) - move to system register
1557 * SYS
1558 * SYSL
1559 * These are all essentially the same insn in 'read' and 'write'
1560 * versions, with varying op0 fields.
1561 */
1562 static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
1563 unsigned int op0, unsigned int op1, unsigned int op2,
1564 unsigned int crn, unsigned int crm, unsigned int rt)
1565 {
1566 const ARMCPRegInfo *ri;
1567 TCGv_i64 tcg_rt;
1568
1569 ri = get_arm_cp_reginfo(s->cp_regs,
1570 ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
1571 crn, crm, op0, op1, op2));
1572
1573 if (!ri) {
1574 /* Unknown register; this might be a guest error or a QEMU
1575 * unimplemented feature.
1576 */
1577 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch64 "
1578 "system register op0:%d op1:%d crn:%d crm:%d op2:%d\n",
1579 isread ? "read" : "write", op0, op1, crn, crm, op2);
1580 unallocated_encoding(s);
1581 return;
1582 }
1583
1584 /* Check access permissions */
1585 if (!cp_access_ok(s->current_el, ri, isread)) {
1586 unallocated_encoding(s);
1587 return;
1588 }
1589
1590 if (ri->accessfn) {
1591 /* Emit code to perform further access permissions checks at
1592 * runtime; this may result in an exception.
1593 */
1594 TCGv_ptr tmpptr;
1595 TCGv_i32 tcg_syn, tcg_isread;
1596 uint32_t syndrome;
1597
1598 gen_a64_set_pc_im(s->pc - 4);
1599 tmpptr = tcg_const_ptr(ri);
1600 syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
1601 tcg_syn = tcg_const_i32(syndrome);
1602 tcg_isread = tcg_const_i32(isread);
1603 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn, tcg_isread);
1604 tcg_temp_free_ptr(tmpptr);
1605 tcg_temp_free_i32(tcg_syn);
1606 tcg_temp_free_i32(tcg_isread);
1607 }
1608
1609 /* Handle special cases first */
1610 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
1611 case ARM_CP_NOP:
1612 return;
1613 case ARM_CP_NZCV:
1614 tcg_rt = cpu_reg(s, rt);
1615 if (isread) {
1616 gen_get_nzcv(tcg_rt);
1617 } else {
1618 gen_set_nzcv(tcg_rt);
1619 }
1620 return;
1621 case ARM_CP_CURRENTEL:
1622 /* Reads as current EL value from pstate, which is
1623 * guaranteed to be constant by the tb flags.
1624 */
1625 tcg_rt = cpu_reg(s, rt);
1626 tcg_gen_movi_i64(tcg_rt, s->current_el << 2);
1627 return;
1628 case ARM_CP_DC_ZVA:
1629 /* Writes clear the aligned block of memory which rt points into. */
1630 tcg_rt = cpu_reg(s, rt);
1631 gen_helper_dc_zva(cpu_env, tcg_rt);
1632 return;
1633 default:
1634 break;
1635 }
1636 if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
1637 return;
1638 } else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
1639 return;
1640 }
1641
1642 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
1643 gen_io_start();
1644 }
1645
1646 tcg_rt = cpu_reg(s, rt);
1647
1648 if (isread) {
1649 if (ri->type & ARM_CP_CONST) {
1650 tcg_gen_movi_i64(tcg_rt, ri->resetvalue);
1651 } else if (ri->readfn) {
1652 TCGv_ptr tmpptr;
1653 tmpptr = tcg_const_ptr(ri);
1654 gen_helper_get_cp_reg64(tcg_rt, cpu_env, tmpptr);
1655 tcg_temp_free_ptr(tmpptr);
1656 } else {
1657 tcg_gen_ld_i64(tcg_rt, cpu_env, ri->fieldoffset);
1658 }
1659 } else {
1660 if (ri->type & ARM_CP_CONST) {
1661 /* If not forbidden by access permissions, treat as WI */
1662 return;
1663 } else if (ri->writefn) {
1664 TCGv_ptr tmpptr;
1665 tmpptr = tcg_const_ptr(ri);
1666 gen_helper_set_cp_reg64(cpu_env, tmpptr, tcg_rt);
1667 tcg_temp_free_ptr(tmpptr);
1668 } else {
1669 tcg_gen_st_i64(tcg_rt, cpu_env, ri->fieldoffset);
1670 }
1671 }
1672
1673 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
1674 /* I/O operations must end the TB here (whether read or write) */
1675 gen_io_end();
1676 s->base.is_jmp = DISAS_UPDATE;
1677 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
1678 /* We default to ending the TB on a coprocessor register write,
1679 * but allow this to be suppressed by the register definition
1680 * (usually only necessary to work around guest bugs).
1681 */
1682 s->base.is_jmp = DISAS_UPDATE;
1683 }
1684 }
1685
1686 /* System
1687 * 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
1688 * +---------------------+---+-----+-----+-------+-------+-----+------+
1689 * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 | CRn | CRm | op2 | Rt |
1690 * +---------------------+---+-----+-----+-------+-------+-----+------+
1691 */
1692 static void disas_system(DisasContext *s, uint32_t insn)
1693 {
1694 unsigned int l, op0, op1, crn, crm, op2, rt;
1695 l = extract32(insn, 21, 1);
1696 op0 = extract32(insn, 19, 2);
1697 op1 = extract32(insn, 16, 3);
1698 crn = extract32(insn, 12, 4);
1699 crm = extract32(insn, 8, 4);
1700 op2 = extract32(insn, 5, 3);
1701 rt = extract32(insn, 0, 5);
1702
1703 if (op0 == 0) {
1704 if (l || rt != 31) {
1705 unallocated_encoding(s);
1706 return;
1707 }
1708 switch (crn) {
1709 case 2: /* HINT (including allocated hints like NOP, YIELD, etc) */
1710 handle_hint(s, insn, op1, op2, crm);
1711 break;
1712 case 3: /* CLREX, DSB, DMB, ISB */
1713 handle_sync(s, insn, op1, op2, crm);
1714 break;
1715 case 4: /* MSR (immediate) */
1716 handle_msr_i(s, insn, op1, op2, crm);
1717 break;
1718 default:
1719 unallocated_encoding(s);
1720 break;
1721 }
1722 return;
1723 }
1724 handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
1725 }
1726
1727 /* Exception generation
1728 *
1729 * 31 24 23 21 20 5 4 2 1 0
1730 * +-----------------+-----+------------------------+-----+----+
1731 * | 1 1 0 1 0 1 0 0 | opc | imm16 | op2 | LL |
1732 * +-----------------------+------------------------+----------+
1733 */
1734 static void disas_exc(DisasContext *s, uint32_t insn)
1735 {
1736 int opc = extract32(insn, 21, 3);
1737 int op2_ll = extract32(insn, 0, 5);
1738 int imm16 = extract32(insn, 5, 16);
1739 TCGv_i32 tmp;
1740
1741 switch (opc) {
1742 case 0:
1743 /* For SVC, HVC and SMC we advance the single-step state
1744 * machine before taking the exception. This is architecturally
1745 * mandated, to ensure that single-stepping a system call
1746 * instruction works properly.
1747 */
1748 switch (op2_ll) {
1749 case 1: /* SVC */
1750 gen_ss_advance(s);
1751 gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16),
1752 default_exception_el(s));
1753 break;
1754 case 2: /* HVC */
1755 if (s->current_el == 0) {
1756 unallocated_encoding(s);
1757 break;
1758 }
1759 /* The pre HVC helper handles cases when HVC gets trapped
1760 * as an undefined insn by runtime configuration.
1761 */
1762 gen_a64_set_pc_im(s->pc - 4);
1763 gen_helper_pre_hvc(cpu_env);
1764 gen_ss_advance(s);
1765 gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16), 2);
1766 break;
1767 case 3: /* SMC */
1768 if (s->current_el == 0) {
1769 unallocated_encoding(s);
1770 break;
1771 }
1772 gen_a64_set_pc_im(s->pc - 4);
1773 tmp = tcg_const_i32(syn_aa64_smc(imm16));
1774 gen_helper_pre_smc(cpu_env, tmp);
1775 tcg_temp_free_i32(tmp);
1776 gen_ss_advance(s);
1777 gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_smc(imm16), 3);
1778 break;
1779 default:
1780 unallocated_encoding(s);
1781 break;
1782 }
1783 break;
1784 case 1:
1785 if (op2_ll != 0) {
1786 unallocated_encoding(s);
1787 break;
1788 }
1789 /* BRK */
1790 gen_exception_bkpt_insn(s, 4, syn_aa64_bkpt(imm16));
1791 break;
1792 case 2:
1793 if (op2_ll != 0) {
1794 unallocated_encoding(s);
1795 break;
1796 }
1797 /* HLT. This has two purposes.
1798 * Architecturally, it is an external halting debug instruction.
1799 * Since QEMU doesn't implement external debug, we treat this as
1800 * it is required for halting debug disabled: it will UNDEF.
1801 * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
1802 */
1803 if (semihosting_enabled() && imm16 == 0xf000) {
1804 #ifndef CONFIG_USER_ONLY
1805 /* In system mode, don't allow userspace access to semihosting,
1806 * to provide some semblance of security (and for consistency
1807 * with our 32-bit semihosting).
1808 */
1809 if (s->current_el == 0) {
1810 unsupported_encoding(s, insn);
1811 break;
1812 }
1813 #endif
1814 gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
1815 } else {
1816 unsupported_encoding(s, insn);
1817 }
1818 break;
1819 case 5:
1820 if (op2_ll < 1 || op2_ll > 3) {
1821 unallocated_encoding(s);
1822 break;
1823 }
1824 /* DCPS1, DCPS2, DCPS3 */
1825 unsupported_encoding(s, insn);
1826 break;
1827 default:
1828 unallocated_encoding(s);
1829 break;
1830 }
1831 }
1832
1833 /* Unconditional branch (register)
1834 * 31 25 24 21 20 16 15 10 9 5 4 0
1835 * +---------------+-------+-------+-------+------+-------+
1836 * | 1 1 0 1 0 1 1 | opc | op2 | op3 | Rn | op4 |
1837 * +---------------+-------+-------+-------+------+-------+
1838 */
1839 static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
1840 {
1841 unsigned int opc, op2, op3, rn, op4;
1842
1843 opc = extract32(insn, 21, 4);
1844 op2 = extract32(insn, 16, 5);
1845 op3 = extract32(insn, 10, 6);
1846 rn = extract32(insn, 5, 5);
1847 op4 = extract32(insn, 0, 5);
1848
1849 if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
1850 unallocated_encoding(s);
1851 return;
1852 }
1853
1854 switch (opc) {
1855 case 0: /* BR */
1856 case 1: /* BLR */
1857 case 2: /* RET */
1858 gen_a64_set_pc(s, cpu_reg(s, rn));
1859 /* BLR also needs to load return address */
1860 if (opc == 1) {
1861 tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
1862 }
1863 break;
1864 case 4: /* ERET */
1865 if (s->current_el == 0) {
1866 unallocated_encoding(s);
1867 return;
1868 }
1869 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
1870 gen_io_start();
1871 }
1872 gen_helper_exception_return(cpu_env);
1873 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
1874 gen_io_end();
1875 }
1876 /* Must exit loop to check un-masked IRQs */
1877 s->base.is_jmp = DISAS_EXIT;
1878 return;
1879 case 5: /* DRPS */
1880 if (rn != 0x1f) {
1881 unallocated_encoding(s);
1882 } else {
1883 unsupported_encoding(s, insn);
1884 }
1885 return;
1886 default:
1887 unallocated_encoding(s);
1888 return;
1889 }
1890
1891 s->base.is_jmp = DISAS_JUMP;
1892 }
1893
1894 /* Branches, exception generating and system instructions */
1895 static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
1896 {
1897 switch (extract32(insn, 25, 7)) {
1898 case 0x0a: case 0x0b:
1899 case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
1900 disas_uncond_b_imm(s, insn);
1901 break;
1902 case 0x1a: case 0x5a: /* Compare & branch (immediate) */
1903 disas_comp_b_imm(s, insn);
1904 break;
1905 case 0x1b: case 0x5b: /* Test & branch (immediate) */
1906 disas_test_b_imm(s, insn);
1907 break;
1908 case 0x2a: /* Conditional branch (immediate) */
1909 disas_cond_b_imm(s, insn);
1910 break;
1911 case 0x6a: /* Exception generation / System */
1912 if (insn & (1 << 24)) {
1913 disas_system(s, insn);
1914 } else {
1915 disas_exc(s, insn);
1916 }
1917 break;
1918 case 0x6b: /* Unconditional branch (register) */
1919 disas_uncond_b_reg(s, insn);
1920 break;
1921 default:
1922 unallocated_encoding(s);
1923 break;
1924 }
1925 }
1926
1927 /*
1928 * Load/Store exclusive instructions are implemented by remembering
1929 * the value/address loaded, and seeing if these are the same
1930 * when the store is performed. This is not actually the architecturally
1931 * mandated semantics, but it works for typical guest code sequences
1932 * and avoids having to monitor regular stores.
1933 *
1934 * The store exclusive uses the atomic cmpxchg primitives to avoid
1935 * races in multi-threaded linux-user and when MTTCG softmmu is
1936 * enabled.
1937 */
1938 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
1939 TCGv_i64 addr, int size, bool is_pair)
1940 {
1941 int idx = get_mem_index(s);
1942 TCGMemOp memop = s->be_data;
1943
1944 g_assert(size <= 3);
1945 if (is_pair) {
1946 g_assert(size >= 2);
1947 if (size == 2) {
1948 /* The pair must be single-copy atomic for the doubleword. */
1949 memop |= MO_64 | MO_ALIGN;
1950 tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
1951 if (s->be_data == MO_LE) {
1952 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 0, 32);
1953 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 32, 32);
1954 } else {
1955 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 32, 32);
1956 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 0, 32);
1957 }
1958 } else {
1959 /* The pair must be single-copy atomic for *each* doubleword, not
1960 the entire quadword, however it must be quadword aligned. */
1961 memop |= MO_64;
1962 tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx,
1963 memop | MO_ALIGN_16);
1964
1965 TCGv_i64 addr2 = tcg_temp_new_i64();
1966 tcg_gen_addi_i64(addr2, addr, 8);
1967 tcg_gen_qemu_ld_i64(cpu_exclusive_high, addr2, idx, memop);
1968 tcg_temp_free_i64(addr2);
1969
1970 tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
1971 tcg_gen_mov_i64(cpu_reg(s, rt2), cpu_exclusive_high);
1972 }
1973 } else {
1974 memop |= size | MO_ALIGN;
1975 tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
1976 tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
1977 }
1978 tcg_gen_mov_i64(cpu_exclusive_addr, addr);
1979 }
1980
1981 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
1982 TCGv_i64 addr, int size, int is_pair)
1983 {
1984 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]
1985 * && (!is_pair || env->exclusive_high == [addr + datasize])) {
1986 * [addr] = {Rt};
1987 * if (is_pair) {
1988 * [addr + datasize] = {Rt2};
1989 * }
1990 * {Rd} = 0;
1991 * } else {
1992 * {Rd} = 1;
1993 * }
1994 * env->exclusive_addr = -1;
1995 */
1996 TCGLabel *fail_label = gen_new_label();
1997 TCGLabel *done_label = gen_new_label();
1998 TCGv_i64 tmp;
1999
2000 tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
2001
2002 tmp = tcg_temp_new_i64();
2003 if (is_pair) {
2004 if (size == 2) {
2005 if (s->be_data == MO_LE) {
2006 tcg_gen_concat32_i64(tmp, cpu_reg(s, rt), cpu_reg(s, rt2));
2007 } else {
2008 tcg_gen_concat32_i64(tmp, cpu_reg(s, rt2), cpu_reg(s, rt));
2009 }
2010 tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr,
2011 cpu_exclusive_val, tmp,
2012 get_mem_index(s),
2013 MO_64 | MO_ALIGN | s->be_data);
2014 tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
2015 } else if (s->be_data == MO_LE) {
2016 if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2017 gen_helper_paired_cmpxchg64_le_parallel(tmp, cpu_env,
2018 cpu_exclusive_addr,
2019 cpu_reg(s, rt),
2020 cpu_reg(s, rt2));
2021 } else {
2022 gen_helper_paired_cmpxchg64_le(tmp, cpu_env, cpu_exclusive_addr,
2023 cpu_reg(s, rt), cpu_reg(s, rt2));
2024 }
2025 } else {
2026 if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2027 gen_helper_paired_cmpxchg64_be_parallel(tmp, cpu_env,
2028 cpu_exclusive_addr,
2029 cpu_reg(s, rt),
2030 cpu_reg(s, rt2));
2031 } else {
2032 gen_helper_paired_cmpxchg64_be(tmp, cpu_env, cpu_exclusive_addr,
2033 cpu_reg(s, rt), cpu_reg(s, rt2));
2034 }
2035 }
2036 } else {
2037 tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr, cpu_exclusive_val,
2038 cpu_reg(s, rt), get_mem_index(s),
2039 size | MO_ALIGN | s->be_data);
2040 tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
2041 }
2042 tcg_gen_mov_i64(cpu_reg(s, rd), tmp);
2043 tcg_temp_free_i64(tmp);
2044 tcg_gen_br(done_label);
2045
2046 gen_set_label(fail_label);
2047 tcg_gen_movi_i64(cpu_reg(s, rd), 1);
2048 gen_set_label(done_label);
2049 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
2050 }
2051
2052 static void gen_compare_and_swap(DisasContext *s, int rs, int rt,
2053 int rn, int size)
2054 {
2055 TCGv_i64 tcg_rs = cpu_reg(s, rs);
2056 TCGv_i64 tcg_rt = cpu_reg(s, rt);
2057 int memidx = get_mem_index(s);
2058 TCGv_i64 addr = cpu_reg_sp(s, rn);
2059
2060 if (rn == 31) {
2061 gen_check_sp_alignment(s);
2062 }
2063 tcg_gen_atomic_cmpxchg_i64(tcg_rs, addr, tcg_rs, tcg_rt, memidx,
2064 size | MO_ALIGN | s->be_data);
2065 }
2066
2067 static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
2068 int rn, int size)
2069 {
2070 TCGv_i64 s1 = cpu_reg(s, rs);
2071 TCGv_i64 s2 = cpu_reg(s, rs + 1);
2072 TCGv_i64 t1 = cpu_reg(s, rt);
2073 TCGv_i64 t2 = cpu_reg(s, rt + 1);
2074 TCGv_i64 addr = cpu_reg_sp(s, rn);
2075 int memidx = get_mem_index(s);
2076
2077 if (rn == 31) {
2078 gen_check_sp_alignment(s);
2079 }
2080
2081 if (size == 2) {
2082 TCGv_i64 cmp = tcg_temp_new_i64();
2083 TCGv_i64 val = tcg_temp_new_i64();
2084
2085 if (s->be_data == MO_LE) {
2086 tcg_gen_concat32_i64(val, t1, t2);
2087 tcg_gen_concat32_i64(cmp, s1, s2);
2088 } else {
2089 tcg_gen_concat32_i64(val, t2, t1);
2090 tcg_gen_concat32_i64(cmp, s2, s1);
2091 }
2092
2093 tcg_gen_atomic_cmpxchg_i64(cmp, addr, cmp, val, memidx,
2094 MO_64 | MO_ALIGN | s->be_data);
2095 tcg_temp_free_i64(val);
2096
2097 if (s->be_data == MO_LE) {
2098 tcg_gen_extr32_i64(s1, s2, cmp);
2099 } else {
2100 tcg_gen_extr32_i64(s2, s1, cmp);
2101 }
2102 tcg_temp_free_i64(cmp);
2103 } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2104 TCGv_i32 tcg_rs = tcg_const_i32(rs);
2105
2106 if (s->be_data == MO_LE) {
2107 gen_helper_casp_le_parallel(cpu_env, tcg_rs, addr, t1, t2);
2108 } else {
2109 gen_helper_casp_be_parallel(cpu_env, tcg_rs, addr, t1, t2);
2110 }
2111 tcg_temp_free_i32(tcg_rs);
2112 } else {
2113 TCGv_i64 d1 = tcg_temp_new_i64();
2114 TCGv_i64 d2 = tcg_temp_new_i64();
2115 TCGv_i64 a2 = tcg_temp_new_i64();
2116 TCGv_i64 c1 = tcg_temp_new_i64();
2117 TCGv_i64 c2 = tcg_temp_new_i64();
2118 TCGv_i64 zero = tcg_const_i64(0);
2119
2120 /* Load the two words, in memory order. */
2121 tcg_gen_qemu_ld_i64(d1, addr, memidx,
2122 MO_64 | MO_ALIGN_16 | s->be_data);
2123 tcg_gen_addi_i64(a2, addr, 8);
2124 tcg_gen_qemu_ld_i64(d2, addr, memidx, MO_64 | s->be_data);
2125
2126 /* Compare the two words, also in memory order. */
2127 tcg_gen_setcond_i64(TCG_COND_EQ, c1, d1, s1);
2128 tcg_gen_setcond_i64(TCG_COND_EQ, c2, d2, s2);
2129 tcg_gen_and_i64(c2, c2, c1);
2130
2131 /* If compare equal, write back new data, else write back old data. */
2132 tcg_gen_movcond_i64(TCG_COND_NE, c1, c2, zero, t1, d1);
2133 tcg_gen_movcond_i64(TCG_COND_NE, c2, c2, zero, t2, d2);
2134 tcg_gen_qemu_st_i64(c1, addr, memidx, MO_64 | s->be_data);
2135 tcg_gen_qemu_st_i64(c2, a2, memidx, MO_64 | s->be_data);
2136 tcg_temp_free_i64(a2);
2137 tcg_temp_free_i64(c1);
2138 tcg_temp_free_i64(c2);
2139 tcg_temp_free_i64(zero);
2140
2141 /* Write back the data from memory to Rs. */
2142 tcg_gen_mov_i64(s1, d1);
2143 tcg_gen_mov_i64(s2, d2);
2144 tcg_temp_free_i64(d1);
2145 tcg_temp_free_i64(d2);
2146 }
2147 }
2148
2149 /* Update the Sixty-Four bit (SF) registersize. This logic is derived
2150 * from the ARMv8 specs for LDR (Shared decode for all encodings).
2151 */
2152 static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
2153 {
2154 int opc0 = extract32(opc, 0, 1);
2155 int regsize;
2156
2157 if (is_signed) {
2158 regsize = opc0 ? 32 : 64;
2159 } else {
2160 regsize = size == 3 ? 64 : 32;
2161 }
2162 return regsize == 64;
2163 }
2164
2165 /* Load/store exclusive
2166 *
2167 * 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
2168 * +-----+-------------+----+---+----+------+----+-------+------+------+
2169 * | sz | 0 0 1 0 0 0 | o2 | L | o1 | Rs | o0 | Rt2 | Rn | Rt |
2170 * +-----+-------------+----+---+----+------+----+-------+------+------+
2171 *
2172 * sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
2173 * L: 0 -> store, 1 -> load
2174 * o2: 0 -> exclusive, 1 -> not
2175 * o1: 0 -> single register, 1 -> register pair
2176 * o0: 1 -> load-acquire/store-release, 0 -> not
2177 */
2178 static void disas_ldst_excl(DisasContext *s, uint32_t insn)
2179 {
2180 int rt = extract32(insn, 0, 5);
2181 int rn = extract32(insn, 5, 5);
2182 int rt2 = extract32(insn, 10, 5);
2183 int rs = extract32(insn, 16, 5);
2184 int is_lasr = extract32(insn, 15, 1);
2185 int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
2186 int size = extract32(insn, 30, 2);
2187 TCGv_i64 tcg_addr;
2188
2189 switch (o2_L_o1_o0) {
2190 case 0x0: /* STXR */
2191 case 0x1: /* STLXR */
2192 if (rn == 31) {
2193 gen_check_sp_alignment(s);
2194 }
2195 if (is_lasr) {
2196 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2197 }
2198 tcg_addr = read_cpu_reg_sp(s, rn, 1);
2199 gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, false);
2200 return;
2201
2202 case 0x4: /* LDXR */
2203 case 0x5: /* LDAXR */
2204 if (rn == 31) {
2205 gen_check_sp_alignment(s);
2206 }
2207 tcg_addr = read_cpu_reg_sp(s, rn, 1);
2208 s->is_ldex = true;
2209 gen_load_exclusive(s, rt, rt2, tcg_addr, size, false);
2210 if (is_lasr) {
2211 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2212 }
2213 return;
2214
2215 case 0x9: /* STLR */
2216 /* Generate ISS for non-exclusive accesses including LASR. */
2217 if (rn == 31) {
2218 gen_check_sp_alignment(s);
2219 }
2220 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2221 tcg_addr = read_cpu_reg_sp(s, rn, 1);
2222 do_gpr_st(s, cpu_reg(s, rt), tcg_addr, size, true, rt,
2223 disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
2224 return;
2225
2226 case 0xd: /* LDAR */
2227 /* Generate ISS for non-exclusive accesses including LASR. */
2228 if (rn == 31) {
2229 gen_check_sp_alignment(s);
2230 }
2231 tcg_addr = read_cpu_reg_sp(s, rn, 1);
2232 do_gpr_ld(s, cpu_reg(s, rt), tcg_addr, size, false, false, true, rt,
2233 disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
2234 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2235 return;
2236
2237 case 0x2: case 0x3: /* CASP / STXP */
2238 if (size & 2) { /* STXP / STLXP */
2239 if (rn == 31) {
2240 gen_check_sp_alignment(s);
2241 }
2242 if (is_lasr) {
2243 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2244 }
2245 tcg_addr = read_cpu_reg_sp(s, rn, 1);
2246 gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, true);
2247 return;
2248 }
2249 if (rt2 == 31
2250 && ((rt | rs) & 1) == 0
2251 && arm_dc_feature(s, ARM_FEATURE_V8_ATOMICS)) {
2252 /* CASP / CASPL */
2253 gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
2254 return;
2255 }
2256 break;
2257
2258 case 0x6: case 0x7: /* CASPA / LDXP */
2259 if (size & 2) { /* LDXP / LDAXP */
2260 if (rn == 31) {
2261 gen_check_sp_alignment(s);
2262 }
2263 tcg_addr = read_cpu_reg_sp(s, rn, 1);
2264 s->is_ldex = true;
2265 gen_load_exclusive(s, rt, rt2, tcg_addr, size, true);
2266 if (is_lasr) {
2267 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2268 }
2269 return;
2270 }
2271 if (rt2 == 31
2272 && ((rt | rs) & 1) == 0
2273 && arm_dc_feature(s, ARM_FEATURE_V8_ATOMICS)) {
2274 /* CASPA / CASPAL */
2275 gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
2276 return;
2277 }
2278 break;
2279
2280 case 0xa: /* CAS */
2281 case 0xb: /* CASL */
2282 case 0xe: /* CASA */
2283 case 0xf: /* CASAL */
2284 if (rt2 == 31 && arm_dc_feature(s, ARM_FEATURE_V8_ATOMICS)) {
2285 gen_compare_and_swap(s, rs, rt, rn, size);
2286 return;
2287 }
2288 break;
2289 }
2290 unallocated_encoding(s);
2291 }
2292
2293 /*
2294 * Load register (literal)
2295 *
2296 * 31 30 29 27 26 25 24 23 5 4 0
2297 * +-----+-------+---+-----+-------------------+-------+
2298 * | opc | 0 1 1 | V | 0 0 | imm19 | Rt |
2299 * +-----+-------+---+-----+-------------------+-------+
2300 *
2301 * V: 1 -> vector (simd/fp)
2302 * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
2303 * 10-> 32 bit signed, 11 -> prefetch
2304 * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
2305 */
2306 static void disas_ld_lit(DisasContext *s, uint32_t insn)
2307 {
2308 int rt = extract32(insn, 0, 5);
2309 int64_t imm = sextract32(insn, 5, 19) << 2;
2310 bool is_vector = extract32(insn, 26, 1);
2311 int opc = extract32(insn, 30, 2);
2312 bool is_signed = false;
2313 int size = 2;
2314 TCGv_i64 tcg_rt, tcg_addr;
2315
2316 if (is_vector) {
2317 if (opc == 3) {
2318 unallocated_encoding(s);
2319 return;
2320 }
2321 size = 2 + opc;
2322 if (!fp_access_check(s)) {
2323 return;
2324 }
2325 } else {
2326 if (opc == 3) {
2327 /* PRFM (literal) : prefetch */
2328 return;
2329 }
2330 size = 2 + extract32(opc, 0, 1);
2331 is_signed = extract32(opc, 1, 1);
2332 }
2333
2334 tcg_rt = cpu_reg(s, rt);
2335
2336 tcg_addr = tcg_const_i64((s->pc - 4) + imm);
2337 if (is_vector) {
2338 do_fp_ld(s, rt, tcg_addr, size);
2339 } else {
2340 /* Only unsigned 32bit loads target 32bit registers. */
2341 bool iss_sf = opc != 0;
2342
2343 do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false,
2344 true, rt, iss_sf, false);
2345 }
2346 tcg_temp_free_i64(tcg_addr);
2347 }
2348
2349 /*
2350 * LDNP (Load Pair - non-temporal hint)
2351 * LDP (Load Pair - non vector)
2352 * LDPSW (Load Pair Signed Word - non vector)
2353 * STNP (Store Pair - non-temporal hint)
2354 * STP (Store Pair - non vector)
2355 * LDNP (Load Pair of SIMD&FP - non-temporal hint)
2356 * LDP (Load Pair of SIMD&FP)
2357 * STNP (Store Pair of SIMD&FP - non-temporal hint)
2358 * STP (Store Pair of SIMD&FP)
2359 *
2360 * 31 30 29 27 26 25 24 23 22 21 15 14 10 9 5 4 0
2361 * +-----+-------+---+---+-------+---+-----------------------------+
2362 * | opc | 1 0 1 | V | 0 | index | L | imm7 | Rt2 | Rn | Rt |
2363 * +-----+-------+---+---+-------+---+-------+-------+------+------+
2364 *
2365 * opc: LDP/STP/LDNP/STNP 00 -> 32 bit, 10 -> 64 bit
2366 * LDPSW 01
2367 * LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
2368 * V: 0 -> GPR, 1 -> Vector
2369 * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
2370 * 10 -> signed offset, 11 -> pre-index
2371 * L: 0 -> Store 1 -> Load
2372 *
2373 * Rt, Rt2 = GPR or SIMD registers to be stored
2374 * Rn = general purpose register containing address
2375 * imm7 = signed offset (multiple of 4 or 8 depending on size)
2376 */
2377 static void disas_ldst_pair(DisasContext *s, uint32_t insn)
2378 {
2379 int rt = extract32(insn, 0, 5);
2380 int rn = extract32(insn, 5, 5);
2381 int rt2 = extract32(insn, 10, 5);
2382 uint64_t offset = sextract64(insn, 15, 7);
2383 int index = extract32(insn, 23, 2);
2384 bool is_vector = extract32(insn, 26, 1);
2385 bool is_load = extract32(insn, 22, 1);
2386 int opc = extract32(insn, 30, 2);
2387
2388 bool is_signed = false;
2389 bool postindex = false;
2390 bool wback = false;
2391
2392 TCGv_i64 tcg_addr; /* calculated address */
2393 int size;
2394
2395 if (opc == 3) {
2396 unallocated_encoding(s);
2397 return;
2398 }
2399
2400 if (is_vector) {
2401 size = 2 + opc;
2402 } else {
2403 size = 2 + extract32(opc, 1, 1);
2404 is_signed = extract32(opc, 0, 1);
2405 if (!is_load && is_signed) {
2406 unallocated_encoding(s);
2407 return;
2408 }
2409 }
2410
2411 switch (index) {
2412 case 1: /* post-index */
2413 postindex = true;
2414 wback = true;
2415 break;
2416 case 0:
2417 /* signed offset with "non-temporal" hint. Since we don't emulate
2418 * caches we don't care about hints to the cache system about
2419 * data access patterns, and handle this identically to plain
2420 * signed offset.
2421 */
2422 if (is_signed) {
2423 /* There is no non-temporal-hint version of LDPSW */
2424 unallocated_encoding(s);
2425 return;
2426 }
2427 postindex = false;
2428 break;
2429 case 2: /* signed offset, rn not updated */
2430 postindex = false;
2431 break;
2432 case 3: /* pre-index */
2433 postindex = false;
2434 wback = true;
2435 break;
2436 }
2437
2438 if (is_vector && !fp_access_check(s)) {
2439 return;
2440 }
2441
2442 offset <<= size;
2443
2444 if (rn == 31) {
2445 gen_check_sp_alignment(s);
2446 }
2447
2448 tcg_addr = read_cpu_reg_sp(s, rn, 1);
2449
2450 if (!postindex) {
2451 tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
2452 }
2453
2454 if (is_vector) {
2455 if (is_load) {
2456 do_fp_ld(s, rt, tcg_addr, size);
2457 } else {
2458 do_fp_st(s, rt, tcg_addr, size);
2459 }
2460 tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
2461 if (is_load) {
2462 do_fp_ld(s, rt2, tcg_addr, size);
2463 } else {
2464 do_fp_st(s, rt2, tcg_addr, size);
2465 }
2466 } else {
2467 TCGv_i64 tcg_rt = cpu_reg(s, rt);
2468 TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
2469
2470 if (is_load) {
2471 TCGv_i64 tmp = tcg_temp_new_i64();
2472
2473 /* Do not modify tcg_rt before recognizing any exception
2474 * from the second load.
2475 */
2476 do_gpr_ld(s, tmp, tcg_addr, size, is_signed, false,
2477 false, 0, false, false);
2478 tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
2479 do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false,
2480 false, 0, false, false);
2481
2482 tcg_gen_mov_i64(tcg_rt, tmp);
2483 tcg_temp_free_i64(tmp);
2484 } else {
2485 do_gpr_st(s, tcg_rt, tcg_addr, size,
2486 false, 0, false, false);
2487 tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
2488 do_gpr_st(s, tcg_rt2, tcg_addr, size,
2489 false, 0, false, false);
2490 }
2491 }
2492
2493 if (wback) {
2494 if (postindex) {
2495 tcg_gen_addi_i64(tcg_addr, tcg_addr, offset - (1 << size));
2496 } else {
2497 tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size);
2498 }
2499 tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
2500 }
2501 }
2502
2503 /*
2504 * Load/store (immediate post-indexed)
2505 * Load/store (immediate pre-indexed)
2506 * Load/store (unscaled immediate)
2507 *
2508 * 31 30 29 27 26 25 24 23 22 21 20 12 11 10 9 5 4 0
2509 * +----+-------+---+-----+-----+---+--------+-----+------+------+
2510 * |size| 1 1 1 | V | 0 0 | opc | 0 | imm9 | idx | Rn | Rt |
2511 * +----+-------+---+-----+-----+---+--------+-----+------+------+
2512 *
2513 * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
2514 10 -> unprivileged
2515 * V = 0 -> non-vector
2516 * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
2517 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2518 */
2519 static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
2520 int opc,
2521 int size,
2522 int rt,
2523 bool is_vector)
2524 {
2525 int rn = extract32(insn, 5, 5);
2526 int imm9 = sextract32(insn, 12, 9);
2527 int idx = extract32(insn, 10, 2);
2528 bool is_signed = false;
2529 bool is_store = false;
2530 bool is_extended = false;
2531 bool is_unpriv = (idx == 2);
2532 bool iss_valid = !is_vector;
2533 bool post_index;
2534 bool writeback;
2535
2536 TCGv_i64 tcg_addr;
2537
2538 if (is_vector) {
2539 size |= (opc & 2) << 1;
2540 if (size > 4 || is_unpriv) {
2541 unallocated_encoding(s);
2542 return;
2543 }
2544 is_store = ((opc & 1) == 0);
2545 if (!fp_access_check(s)) {
2546 return;
2547 }
2548 } else {
2549 if (size == 3 && opc == 2) {
2550 /* PRFM - prefetch */
2551 if (is_unpriv) {
2552 unallocated_encoding(s);
2553 return;
2554 }
2555 return;
2556 }
2557 if (opc == 3 && size > 1) {
2558 unallocated_encoding(s);
2559 return;
2560 }
2561 is_store = (opc == 0);
2562 is_signed = extract32(opc, 1, 1);
2563 is_extended = (size < 3) && extract32(opc, 0, 1);
2564 }
2565
2566 switch (idx) {
2567 case 0:
2568 case 2:
2569 post_index = false;
2570 writeback = false;
2571 break;
2572 case 1:
2573 post_index = true;
2574 writeback = true;
2575 break;
2576 case 3:
2577 post_index = false;
2578 writeback = true;
2579 break;
2580 default:
2581 g_assert_not_reached();
2582 }
2583
2584 if (rn == 31) {
2585 gen_check_sp_alignment(s);
2586 }
2587 tcg_addr = read_cpu_reg_sp(s, rn, 1);
2588
2589 if (!post_index) {
2590 tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
2591 }
2592
2593 if (is_vector) {
2594 if (is_store) {
2595 do_fp_st(s, rt, tcg_addr, size);
2596 } else {
2597 do_fp_ld(s, rt, tcg_addr, size);
2598 }
2599 } else {
2600 TCGv_i64 tcg_rt = cpu_reg(s, rt);
2601 int memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
2602 bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
2603
2604 if (is_store) {
2605 do_gpr_st_memidx(s, tcg_rt, tcg_addr, size, memidx,
2606 iss_valid, rt, iss_sf, false);
2607 } else {
2608 do_gpr_ld_memidx(s, tcg_rt, tcg_addr, size,
2609 is_signed, is_extended, memidx,
2610 iss_valid, rt, iss_sf, false);
2611 }
2612 }
2613
2614 if (writeback) {
2615 TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
2616 if (post_index) {
2617 tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
2618 }
2619 tcg_gen_mov_i64(tcg_rn, tcg_addr);
2620 }
2621 }
2622
2623 /*
2624 * Load/store (register offset)
2625 *
2626 * 31 30 29 27 26 25 24 23 22 21 20 16 15 13 12 11 10 9 5 4 0
2627 * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
2628 * |size| 1 1 1 | V | 0 0 | opc | 1 | Rm | opt | S| 1 0 | Rn | Rt |
2629 * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
2630 *
2631 * For non-vector:
2632 * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
2633 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2634 * For vector:
2635 * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
2636 * opc<0>: 0 -> store, 1 -> load
2637 * V: 1 -> vector/simd
2638 * opt: extend encoding (see DecodeRegExtend)
2639 * S: if S=1 then scale (essentially index by sizeof(size))
2640 * Rt: register to transfer into/out of
2641 * Rn: address register or SP for base
2642 * Rm: offset register or ZR for offset
2643 */
2644 static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
2645 int opc,
2646 int size,
2647 int rt,
2648 bool is_vector)
2649 {
2650 int rn = extract32(insn, 5, 5);
2651 int shift = extract32(insn, 12, 1);
2652 int rm = extract32(insn, 16, 5);
2653 int opt = extract32(insn, 13, 3);
2654 bool is_signed = false;
2655 bool is_store = false;
2656 bool is_extended = false;
2657
2658 TCGv_i64 tcg_rm;
2659 TCGv_i64 tcg_addr;
2660
2661 if (extract32(opt, 1, 1) == 0) {
2662 unallocated_encoding(s);
2663 return;
2664 }
2665
2666 if (is_vector) {
2667 size |= (opc & 2) << 1;
2668 if (size > 4) {
2669 unallocated_encoding(s);
2670 return;
2671 }
2672 is_store = !extract32(opc, 0, 1);
2673 if (!fp_access_check(s)) {
2674 return;
2675 }
2676 } else {
2677 if (size == 3 && opc == 2) {
2678 /* PRFM - prefetch */
2679 return;
2680 }
2681 if (opc == 3 && size > 1) {
2682 unallocated_encoding(s);
2683 return;
2684 }
2685 is_store = (opc == 0);
2686 is_signed = extract32(opc, 1, 1);
2687 is_extended = (size < 3) && extract32(opc, 0, 1);
2688 }
2689
2690 if (rn == 31) {
2691 gen_check_sp_alignment(s);
2692 }
2693 tcg_addr = read_cpu_reg_sp(s, rn, 1);
2694
2695 tcg_rm = read_cpu_reg(s, rm, 1);
2696 ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
2697
2698 tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_rm);
2699
2700 if (is_vector) {
2701 if (is_store) {
2702 do_fp_st(s, rt, tcg_addr, size);
2703 } else {
2704 do_fp_ld(s, rt, tcg_addr, size);
2705 }
2706 } else {
2707 TCGv_i64 tcg_rt = cpu_reg(s, rt);
2708 bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
2709 if (is_store) {
2710 do_gpr_st(s, tcg_rt, tcg_addr, size,
2711 true, rt, iss_sf, false);
2712 } else {
2713 do_gpr_ld(s, tcg_rt, tcg_addr, size,
2714 is_signed, is_extended,
2715 true, rt, iss_sf, false);
2716 }
2717 }
2718 }
2719
2720 /*
2721 * Load/store (unsigned immediate)
2722 *
2723 * 31 30 29 27 26 25 24 23 22 21 10 9 5
2724 * +----+-------+---+-----+-----+------------+-------+------+
2725 * |size| 1 1 1 | V | 0 1 | opc | imm12 | Rn | Rt |
2726 * +----+-------+---+-----+-----+------------+-------+------+
2727 *
2728 * For non-vector:
2729 * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
2730 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2731 * For vector:
2732 * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
2733 * opc<0>: 0 -> store, 1 -> load
2734 * Rn: base address register (inc SP)
2735 * Rt: target register
2736 */
2737 static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
2738 int opc,
2739 int size,
2740 int rt,
2741 bool is_vector)
2742 {
2743 int rn = extract32(insn, 5, 5);
2744 unsigned int imm12 = extract32(insn, 10, 12);
2745 unsigned int offset;
2746
2747 TCGv_i64 tcg_addr;
2748
2749 bool is_store;
2750 bool is_signed = false;
2751 bool is_extended = false;
2752
2753 if (is_vector) {
2754 size |= (opc & 2) << 1;
2755 if (size > 4) {
2756 unallocated_encoding(s);
2757 return;
2758 }
2759 is_store = !extract32(opc, 0, 1);
2760 if (!fp_access_check(s)) {
2761 return;
2762 }
2763 } else {
2764 if (size == 3 && opc == 2) {
2765 /* PRFM - prefetch */
2766 return;
2767 }
2768 if (opc == 3 && size > 1) {
2769 unallocated_encoding(s);
2770 return;
2771 }
2772 is_store = (opc == 0);
2773 is_signed = extract32(opc, 1, 1);
2774 is_extended = (size < 3) && extract32(opc, 0, 1);
2775 }
2776
2777 if (rn == 31) {
2778 gen_check_sp_alignment(s);
2779 }
2780 tcg_addr = read_cpu_reg_sp(s, rn, 1);
2781 offset = imm12 << size;
2782 tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
2783
2784 if (is_vector) {
2785 if (is_store) {
2786 do_fp_st(s, rt, tcg_addr, size);
2787 } else {
2788 do_fp_ld(s, rt, tcg_addr, size);
2789 }
2790 } else {
2791 TCGv_i64 tcg_rt = cpu_reg(s, rt);
2792 bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
2793 if (is_store) {
2794 do_gpr_st(s, tcg_rt, tcg_addr, size,
2795 true, rt, iss_sf, false);
2796 } else {
2797 do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended,
2798 true, rt, iss_sf, false);
2799 }
2800 }
2801 }
2802
2803 /* Atomic memory operations
2804 *
2805 * 31 30 27 26 24 22 21 16 15 12 10 5 0
2806 * +------+-------+---+-----+-----+---+----+----+-----+-----+----+-----+
2807 * | size | 1 1 1 | V | 0 0 | A R | 1 | Rs | o3 | opc | 0 0 | Rn | Rt |
2808 * +------+-------+---+-----+-----+--------+----+-----+-----+----+-----+
2809 *
2810 * Rt: the result register
2811 * Rn: base address or SP
2812 * Rs: the source register for the operation
2813 * V: vector flag (always 0 as of v8.3)
2814 * A: acquire flag
2815 * R: release flag
2816 */
2817 static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
2818 int size, int rt, bool is_vector)
2819 {
2820 int rs = extract32(insn, 16, 5);
2821 int rn = extract32(insn, 5, 5);
2822 int o3_opc = extract32(insn, 12, 4);
2823 int feature = ARM_FEATURE_V8_ATOMICS;
2824 TCGv_i64 tcg_rn, tcg_rs;
2825 AtomicThreeOpFn *fn;
2826
2827 if (is_vector) {
2828 unallocated_encoding(s);
2829 return;
2830 }
2831 switch (o3_opc) {
2832 case 000: /* LDADD */
2833 fn = tcg_gen_atomic_fetch_add_i64;
2834 break;
2835 case 001: /* LDCLR */
2836 fn = tcg_gen_atomic_fetch_and_i64;
2837 break;
2838 case 002: /* LDEOR */
2839 fn = tcg_gen_atomic_fetch_xor_i64;
2840 break;
2841 case 003: /* LDSET */
2842 fn = tcg_gen_atomic_fetch_or_i64;
2843 break;
2844 case 004: /* LDSMAX */
2845 fn = tcg_gen_atomic_fetch_smax_i64;
2846 break;
2847 case 005: /* LDSMIN */
2848 fn = tcg_gen_atomic_fetch_smin_i64;
2849 break;
2850 case 006: /* LDUMAX */
2851 fn = tcg_gen_atomic_fetch_umax_i64;
2852 break;
2853 case 007: /* LDUMIN */
2854 fn = tcg_gen_atomic_fetch_umin_i64;
2855 break;
2856 case 010: /* SWP */
2857 fn = tcg_gen_atomic_xchg_i64;
2858 break;
2859 default:
2860 unallocated_encoding(s);
2861 return;
2862 }
2863 if (!arm_dc_feature(s, feature)) {
2864 unallocated_encoding(s);
2865 return;
2866 }
2867
2868 if (rn == 31) {
2869 gen_check_sp_alignment(s);
2870 }
2871 tcg_rn = cpu_reg_sp(s, rn);
2872 tcg_rs = read_cpu_reg(s, rs, true);
2873
2874 if (o3_opc == 1) { /* LDCLR */
2875 tcg_gen_not_i64(tcg_rs, tcg_rs);
2876 }
2877
2878 /* The tcg atomic primitives are all full barriers. Therefore we
2879 * can ignore the Acquire and Release bits of this instruction.
2880 */
2881 fn(cpu_reg(s, rt), tcg_rn, tcg_rs, get_mem_index(s),
2882 s->be_data | size | MO_ALIGN);
2883 }
2884
2885 /* Load/store register (all forms) */
2886 static void disas_ldst_reg(DisasContext *s, uint32_t insn)
2887 {
2888 int rt = extract32(insn, 0, 5);
2889 int opc = extract32(insn, 22, 2);
2890 bool is_vector = extract32(insn, 26, 1);
2891 int size = extract32(insn, 30, 2);
2892
2893 switch (extract32(insn, 24, 2)) {
2894 case 0:
2895 if (extract32(insn, 21, 1) == 0) {
2896 /* Load/store register (unscaled immediate)
2897 * Load/store immediate pre/post-indexed
2898 * Load/store register unprivileged
2899 */
2900 disas_ldst_reg_imm9(s, insn, opc, size, rt, is_vector);
2901 return;
2902 }
2903 switch (extract32(insn, 10, 2)) {
2904 case 0:
2905 disas_ldst_atomic(s, insn, size, rt, is_vector);
2906 return;
2907 case 2:
2908 disas_ldst_reg_roffset(s, insn, opc, size, rt, is_vector);
2909 return;
2910 }
2911 break;
2912 case 1:
2913 disas_ldst_reg_unsigned_imm(s, insn, opc, size, rt, is_vector);
2914 return;
2915 }
2916 unallocated_encoding(s);
2917 }
2918
2919 /* AdvSIMD load/store multiple structures
2920 *
2921 * 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
2922 * +---+---+---------------+---+-------------+--------+------+------+------+
2923 * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size | Rn | Rt |
2924 * +---+---+---------------+---+-------------+--------+------+------+------+
2925 *
2926 * AdvSIMD load/store multiple structures (post-indexed)
2927 *
2928 * 31 30 29 23 22 21 20 16 15 12 11 10 9 5 4 0
2929 * +---+---+---------------+---+---+---------+--------+------+------+------+
2930 * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 | Rm | opcode | size | Rn | Rt |
2931 * +---+---+---------------+---+---+---------+--------+------+------+------+
2932 *
2933 * Rt: first (or only) SIMD&FP register to be transferred
2934 * Rn: base address or SP
2935 * Rm (post-index only): post-index register (when !31) or size dependent #imm
2936 */
2937 static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
2938 {
2939 int rt = extract32(insn, 0, 5);
2940 int rn = extract32(insn, 5, 5);
2941 int size = extract32(insn, 10, 2);
2942 int opcode = extract32(insn, 12, 4);
2943 bool is_store = !extract32(insn, 22, 1);
2944 bool is_postidx = extract32(insn, 23, 1);
2945 bool is_q = extract32(insn, 30, 1);
2946 TCGv_i64 tcg_addr, tcg_rn;
2947
2948 int ebytes = 1 << size;
2949 int elements = (is_q ? 128 : 64) / (8 << size);
2950 int rpt; /* num iterations */
2951 int selem; /* structure elements */
2952 int r;
2953
2954 if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
2955 unallocated_encoding(s);
2956 return;
2957 }
2958
2959 /* From the shared decode logic */
2960 switch (opcode) {
2961 case 0x0:
2962 rpt = 1;
2963 selem = 4;
2964 break;
2965 case 0x2:
2966 rpt = 4;
2967 selem = 1;
2968 break;
2969 case 0x4:
2970 rpt = 1;
2971 selem = 3;
2972 break;
2973 case 0x6:
2974 rpt = 3;
2975 selem = 1;
2976 break;
2977 case 0x7:
2978 rpt = 1;
2979 selem = 1;
2980 break;
2981 case 0x8:
2982 rpt = 1;
2983 selem = 2;
2984 break;
2985 case 0xa:
2986 rpt = 2;
2987 selem = 1;
2988 break;
2989 default:
2990 unallocated_encoding(s);
2991 return;
2992 }
2993
2994 if (size == 3 && !is_q && selem != 1) {
2995 /* reserved */
2996 unallocated_encoding(s);
2997 return;
2998 }
2999
3000 if (!fp_access_check(s)) {
3001 return;
3002 }
3003
3004 if (rn == 31) {
3005 gen_check_sp_alignment(s);
3006 }
3007
3008 tcg_rn = cpu_reg_sp(s, rn);
3009 tcg_addr = tcg_temp_new_i64();
3010 tcg_gen_mov_i64(tcg_addr, tcg_rn);
3011
3012 for (r = 0; r < rpt; r++) {
3013 int e;
3014 for (e = 0; e < elements; e++) {
3015 int tt = (rt + r) % 32;
3016 int xs;
3017 for (xs = 0; xs < selem; xs++) {
3018 if (is_store) {
3019 do_vec_st(s, tt, e, tcg_addr, size);
3020 } else {
3021 do_vec_ld(s, tt, e, tcg_addr, size);
3022
3023 /* For non-quad operations, setting a slice of the low
3024 * 64 bits of the register clears the high 64 bits (in
3025 * the ARM ARM pseudocode this is implicit in the fact
3026 * that 'rval' is a 64 bit wide variable).
3027 * For quad operations, we might still need to zero the
3028 * high bits of SVE. We optimize by noticing that we only
3029 * need to do this the first time we touch a register.
3030 */
3031 if (e == 0 && (r == 0 || xs == selem - 1)) {
3032 clear_vec_high(s, is_q, tt);
3033 }
3034 }
3035 tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
3036 tt = (tt + 1) % 32;
3037 }
3038 }
3039 }
3040
3041 if (is_postidx) {
3042 int rm = extract32(insn, 16, 5);
3043 if (rm == 31) {
3044 tcg_gen_mov_i64(tcg_rn, tcg_addr);
3045 } else {
3046 tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
3047 }
3048 }
3049 tcg_temp_free_i64(tcg_addr);
3050 }
3051
3052 /* AdvSIMD load/store single structure
3053 *
3054 * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
3055 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3056 * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size | Rn | Rt |
3057 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3058 *
3059 * AdvSIMD load/store single structure (post-indexed)
3060 *
3061 * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
3062 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3063 * | 0 | Q | 0 0 1 1 0 1 1 | L R | Rm | opc | S | size | Rn | Rt |
3064 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3065 *
3066 * Rt: first (or only) SIMD&FP register to be transferred
3067 * Rn: base address or SP
3068 * Rm (post-index only): post-index register (when !31) or size dependent #imm
3069 * index = encoded in Q:S:size dependent on size
3070 *
3071 * lane_size = encoded in R, opc
3072 * transfer width = encoded in opc, S, size
3073 */
3074 static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
3075 {
3076 int rt = extract32(insn, 0, 5);
3077 int rn = extract32(insn, 5, 5);
3078 int size = extract32(insn, 10, 2);
3079 int S = extract32(insn, 12, 1);
3080 int opc = extract32(insn, 13, 3);
3081 int R = extract32(insn, 21, 1);
3082 int is_load = extract32(insn, 22, 1);
3083 int is_postidx = extract32(insn, 23, 1);
3084 int is_q = extract32(insn, 30, 1);
3085
3086 int scale = extract32(opc, 1, 2);
3087 int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
3088 bool replicate = false;
3089 int index = is_q << 3 | S << 2 | size;
3090 int ebytes, xs;
3091 TCGv_i64 tcg_addr, tcg_rn;
3092
3093 switch (scale) {
3094 case 3:
3095 if (!is_load || S) {
3096 unallocated_encoding(s);
3097 return;
3098 }
3099 scale = size;
3100 replicate = true;
3101 break;
3102 case 0:
3103 break;
3104 case 1:
3105 if (extract32(size, 0, 1)) {
3106 unallocated_encoding(s);
3107 return;
3108 }
3109 index >>= 1;
3110 break;
3111 case 2:
3112 if (extract32(size, 1, 1)) {
3113 unallocated_encoding(s);
3114 return;
3115 }
3116 if (!extract32(size, 0, 1)) {
3117 index >>= 2;
3118 } else {
3119 if (S) {
3120 unallocated_encoding(s);
3121 return;
3122 }
3123 index >>= 3;
3124 scale = 3;
3125 }
3126 break;
3127 default:
3128 g_assert_not_reached();
3129 }
3130
3131 if (!fp_access_check(s)) {
3132 return;
3133 }
3134
3135 ebytes = 1 << scale;
3136
3137 if (rn == 31) {
3138 gen_check_sp_alignment(s);
3139 }
3140
3141 tcg_rn = cpu_reg_sp(s, rn);
3142 tcg_addr = tcg_temp_new_i64();
3143 tcg_gen_mov_i64(tcg_addr, tcg_rn);
3144
3145 for (xs = 0; xs < selem; xs++) {
3146 if (replicate) {
3147 /* Load and replicate to all elements */
3148 uint64_t mulconst;
3149 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3150
3151 tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
3152 get_mem_index(s), s->be_data + scale);
3153 switch (scale) {
3154 case 0:
3155 mulconst = 0x0101010101010101ULL;
3156 break;
3157 case 1:
3158 mulconst = 0x0001000100010001ULL;
3159 break;
3160 case 2:
3161 mulconst = 0x0000000100000001ULL;
3162 break;
3163 case 3:
3164 mulconst = 0;
3165 break;
3166 default:
3167 g_assert_not_reached();
3168 }
3169 if (mulconst) {
3170 tcg_gen_muli_i64(tcg_tmp, tcg_tmp, mulconst);
3171 }
3172 write_vec_element(s, tcg_tmp, rt, 0, MO_64);
3173 if (is_q) {
3174 write_vec_element(s, tcg_tmp, rt, 1, MO_64);
3175 }
3176 tcg_temp_free_i64(tcg_tmp);
3177 clear_vec_high(s, is_q, rt);
3178 } else {
3179 /* Load/store one element per register */
3180 if (is_load) {
3181 do_vec_ld(s, rt, index, tcg_addr, scale);
3182 } else {
3183 do_vec_st(s, rt, index, tcg_addr, scale);
3184 }
3185 }
3186 tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
3187 rt = (rt + 1) % 32;
3188 }
3189
3190 if (is_postidx) {
3191 int rm = extract32(ins