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.
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.
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/>.
28 #include "translate.h"
29 #include "qemu/host-utils.h"
31 #include "exec/gen-icount.h"
37 static TCGv_i64 cpu_X[32];
38 static TCGv_i64 cpu_pc;
39 static TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
41 /* Load/store exclusive handling */
42 static TCGv_i64 cpu_exclusive_addr;
43 static TCGv_i64 cpu_exclusive_val;
44 static TCGv_i64 cpu_exclusive_high;
45 #ifdef CONFIG_USER_ONLY
46 static TCGv_i64 cpu_exclusive_test;
47 static TCGv_i32 cpu_exclusive_info;
50 static const char *regnames[] = {
51 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
52 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
53 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
54 "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
58 A64_SHIFT_TYPE_LSL = 0,
59 A64_SHIFT_TYPE_LSR = 1,
60 A64_SHIFT_TYPE_ASR = 2,
61 A64_SHIFT_TYPE_ROR = 3
64 /* Table based decoder typedefs - used when the relevant bits for decode
65 * are too awkwardly scattered across the instruction (eg SIMD).
67 typedef void AArch64DecodeFn(DisasContext *s, uint32_t insn);
69 typedef struct AArch64DecodeTable {
72 AArch64DecodeFn *disas_fn;
75 /* initialize TCG globals. */
76 void a64_translate_init(void)
80 cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
81 offsetof(CPUARMState, pc),
83 for (i = 0; i < 32; i++) {
84 cpu_X[i] = tcg_global_mem_new_i64(TCG_AREG0,
85 offsetof(CPUARMState, xregs[i]),
89 cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
90 cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
91 cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
92 cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
94 cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
95 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
96 cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
97 offsetof(CPUARMState, exclusive_val), "exclusive_val");
98 cpu_exclusive_high = tcg_global_mem_new_i64(TCG_AREG0,
99 offsetof(CPUARMState, exclusive_high), "exclusive_high");
100 #ifdef CONFIG_USER_ONLY
101 cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
102 offsetof(CPUARMState, exclusive_test), "exclusive_test");
103 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
104 offsetof(CPUARMState, exclusive_info), "exclusive_info");
108 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
109 fprintf_function cpu_fprintf, int flags)
111 ARMCPU *cpu = ARM_CPU(cs);
112 CPUARMState *env = &cpu->env;
113 uint32_t psr = pstate_read(env);
116 cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n",
117 env->pc, env->xregs[31]);
118 for (i = 0; i < 31; i++) {
119 cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
121 cpu_fprintf(f, "\n");
126 cpu_fprintf(f, "PSTATE=%08x (flags %c%c%c%c)\n",
128 psr & PSTATE_N ? 'N' : '-',
129 psr & PSTATE_Z ? 'Z' : '-',
130 psr & PSTATE_C ? 'C' : '-',
131 psr & PSTATE_V ? 'V' : '-');
132 cpu_fprintf(f, "\n");
134 if (flags & CPU_DUMP_FPU) {
136 for (i = 0; i < numvfpregs; i += 2) {
137 uint64_t vlo = float64_val(env->vfp.regs[i * 2]);
138 uint64_t vhi = float64_val(env->vfp.regs[(i * 2) + 1]);
139 cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
141 vlo = float64_val(env->vfp.regs[(i + 1) * 2]);
142 vhi = float64_val(env->vfp.regs[((i + 1) * 2) + 1]);
143 cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
146 cpu_fprintf(f, "FPCR: %08x FPSR: %08x\n",
147 vfp_get_fpcr(env), vfp_get_fpsr(env));
151 static int get_mem_index(DisasContext *s)
153 #ifdef CONFIG_USER_ONLY
160 void gen_a64_set_pc_im(uint64_t val)
162 tcg_gen_movi_i64(cpu_pc, val);
165 static void gen_exception(int excp)
167 TCGv_i32 tmp = tcg_temp_new_i32();
168 tcg_gen_movi_i32(tmp, excp);
169 gen_helper_exception(cpu_env, tmp);
170 tcg_temp_free_i32(tmp);
173 static void gen_exception_insn(DisasContext *s, int offset, int excp)
175 gen_a64_set_pc_im(s->pc - offset);
177 s->is_jmp = DISAS_EXC;
180 static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
182 /* No direct tb linking with singlestep or deterministic io */
183 if (s->singlestep_enabled || (s->tb->cflags & CF_LAST_IO)) {
187 /* Only link tbs from inside the same guest page */
188 if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
195 static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
197 TranslationBlock *tb;
200 if (use_goto_tb(s, n, dest)) {
202 gen_a64_set_pc_im(dest);
203 tcg_gen_exit_tb((tcg_target_long)tb + n);
204 s->is_jmp = DISAS_TB_JUMP;
206 gen_a64_set_pc_im(dest);
207 if (s->singlestep_enabled) {
208 gen_exception(EXCP_DEBUG);
211 s->is_jmp = DISAS_JUMP;
215 static void unallocated_encoding(DisasContext *s)
217 gen_exception_insn(s, 4, EXCP_UDEF);
220 #define unsupported_encoding(s, insn) \
222 qemu_log_mask(LOG_UNIMP, \
223 "%s:%d: unsupported instruction encoding 0x%08x " \
224 "at pc=%016" PRIx64 "\n", \
225 __FILE__, __LINE__, insn, s->pc - 4); \
226 unallocated_encoding(s); \
229 static void init_tmp_a64_array(DisasContext *s)
231 #ifdef CONFIG_DEBUG_TCG
233 for (i = 0; i < ARRAY_SIZE(s->tmp_a64); i++) {
234 TCGV_UNUSED_I64(s->tmp_a64[i]);
237 s->tmp_a64_count = 0;
240 static void free_tmp_a64(DisasContext *s)
243 for (i = 0; i < s->tmp_a64_count; i++) {
244 tcg_temp_free_i64(s->tmp_a64[i]);
246 init_tmp_a64_array(s);
249 static TCGv_i64 new_tmp_a64(DisasContext *s)
251 assert(s->tmp_a64_count < TMP_A64_MAX);
252 return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
255 static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
257 TCGv_i64 t = new_tmp_a64(s);
258 tcg_gen_movi_i64(t, 0);
263 * Register access functions
265 * These functions are used for directly accessing a register in where
266 * changes to the final register value are likely to be made. If you
267 * need to use a register for temporary calculation (e.g. index type
268 * operations) use the read_* form.
270 * B1.2.1 Register mappings
272 * In instruction register encoding 31 can refer to ZR (zero register) or
273 * the SP (stack pointer) depending on context. In QEMU's case we map SP
274 * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
275 * This is the point of the _sp forms.
277 static TCGv_i64 cpu_reg(DisasContext *s, int reg)
280 return new_tmp_a64_zero(s);
286 /* register access for when 31 == SP */
287 static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
292 /* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
293 * representing the register contents. This TCGv is an auto-freed
294 * temporary so it need not be explicitly freed, and may be modified.
296 static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
298 TCGv_i64 v = new_tmp_a64(s);
301 tcg_gen_mov_i64(v, cpu_X[reg]);
303 tcg_gen_ext32u_i64(v, cpu_X[reg]);
306 tcg_gen_movi_i64(v, 0);
311 static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
313 TCGv_i64 v = new_tmp_a64(s);
315 tcg_gen_mov_i64(v, cpu_X[reg]);
317 tcg_gen_ext32u_i64(v, cpu_X[reg]);
322 /* Return the offset into CPUARMState of an element of specified
323 * size, 'element' places in from the least significant end of
324 * the FP/vector register Qn.
326 static inline int vec_reg_offset(int regno, int element, TCGMemOp size)
328 int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
329 #ifdef HOST_WORDS_BIGENDIAN
330 /* This is complicated slightly because vfp.regs[2n] is
331 * still the low half and vfp.regs[2n+1] the high half
332 * of the 128 bit vector, even on big endian systems.
333 * Calculate the offset assuming a fully bigendian 128 bits,
334 * then XOR to account for the order of the two 64 bit halves.
336 offs += (16 - ((element + 1) * (1 << size)));
339 offs += element * (1 << size);
344 /* Return the offset into CPUARMState of a slice (from
345 * the least significant end) of FP register Qn (ie
347 * (Note that this is not the same mapping as for A32; see cpu.h)
349 static inline int fp_reg_offset(int regno, TCGMemOp size)
351 int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
352 #ifdef HOST_WORDS_BIGENDIAN
353 offs += (8 - (1 << size));
358 /* Offset of the high half of the 128 bit vector Qn */
359 static inline int fp_reg_hi_offset(int regno)
361 return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
364 /* Convenience accessors for reading and writing single and double
365 * FP registers. Writing clears the upper parts of the associated
366 * 128 bit vector register, as required by the architecture.
367 * Note that unlike the GP register accessors, the values returned
368 * by the read functions must be manually freed.
370 static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
372 TCGv_i64 v = tcg_temp_new_i64();
374 tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
378 static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
380 TCGv_i32 v = tcg_temp_new_i32();
382 tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(reg, MO_32));
386 static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
388 TCGv_i64 tcg_zero = tcg_const_i64(0);
390 tcg_gen_st_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
391 tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(reg));
392 tcg_temp_free_i64(tcg_zero);
395 static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
397 TCGv_i64 tmp = tcg_temp_new_i64();
399 tcg_gen_extu_i32_i64(tmp, v);
400 write_fp_dreg(s, reg, tmp);
401 tcg_temp_free_i64(tmp);
404 static TCGv_ptr get_fpstatus_ptr(void)
406 TCGv_ptr statusptr = tcg_temp_new_ptr();
409 /* In A64 all instructions (both FP and Neon) use the FPCR;
410 * there is no equivalent of the A32 Neon "standard FPSCR value"
411 * and all operations use vfp.fp_status.
413 offset = offsetof(CPUARMState, vfp.fp_status);
414 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
418 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
419 * than the 32 bit equivalent.
421 static inline void gen_set_NZ64(TCGv_i64 result)
423 TCGv_i64 flag = tcg_temp_new_i64();
425 tcg_gen_setcondi_i64(TCG_COND_NE, flag, result, 0);
426 tcg_gen_trunc_i64_i32(cpu_ZF, flag);
427 tcg_gen_shri_i64(flag, result, 32);
428 tcg_gen_trunc_i64_i32(cpu_NF, flag);
429 tcg_temp_free_i64(flag);
432 /* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
433 static inline void gen_logic_CC(int sf, TCGv_i64 result)
436 gen_set_NZ64(result);
438 tcg_gen_trunc_i64_i32(cpu_ZF, result);
439 tcg_gen_trunc_i64_i32(cpu_NF, result);
441 tcg_gen_movi_i32(cpu_CF, 0);
442 tcg_gen_movi_i32(cpu_VF, 0);
445 /* dest = T0 + T1; compute C, N, V and Z flags */
446 static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
449 TCGv_i64 result, flag, tmp;
450 result = tcg_temp_new_i64();
451 flag = tcg_temp_new_i64();
452 tmp = tcg_temp_new_i64();
454 tcg_gen_movi_i64(tmp, 0);
455 tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
457 tcg_gen_trunc_i64_i32(cpu_CF, flag);
459 gen_set_NZ64(result);
461 tcg_gen_xor_i64(flag, result, t0);
462 tcg_gen_xor_i64(tmp, t0, t1);
463 tcg_gen_andc_i64(flag, flag, tmp);
464 tcg_temp_free_i64(tmp);
465 tcg_gen_shri_i64(flag, flag, 32);
466 tcg_gen_trunc_i64_i32(cpu_VF, flag);
468 tcg_gen_mov_i64(dest, result);
469 tcg_temp_free_i64(result);
470 tcg_temp_free_i64(flag);
472 /* 32 bit arithmetic */
473 TCGv_i32 t0_32 = tcg_temp_new_i32();
474 TCGv_i32 t1_32 = tcg_temp_new_i32();
475 TCGv_i32 tmp = tcg_temp_new_i32();
477 tcg_gen_movi_i32(tmp, 0);
478 tcg_gen_trunc_i64_i32(t0_32, t0);
479 tcg_gen_trunc_i64_i32(t1_32, t1);
480 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
481 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
482 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
483 tcg_gen_xor_i32(tmp, t0_32, t1_32);
484 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
485 tcg_gen_extu_i32_i64(dest, cpu_NF);
487 tcg_temp_free_i32(tmp);
488 tcg_temp_free_i32(t0_32);
489 tcg_temp_free_i32(t1_32);
493 /* dest = T0 - T1; compute C, N, V and Z flags */
494 static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
497 /* 64 bit arithmetic */
498 TCGv_i64 result, flag, tmp;
500 result = tcg_temp_new_i64();
501 flag = tcg_temp_new_i64();
502 tcg_gen_sub_i64(result, t0, t1);
504 gen_set_NZ64(result);
506 tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
507 tcg_gen_trunc_i64_i32(cpu_CF, flag);
509 tcg_gen_xor_i64(flag, result, t0);
510 tmp = tcg_temp_new_i64();
511 tcg_gen_xor_i64(tmp, t0, t1);
512 tcg_gen_and_i64(flag, flag, tmp);
513 tcg_temp_free_i64(tmp);
514 tcg_gen_shri_i64(flag, flag, 32);
515 tcg_gen_trunc_i64_i32(cpu_VF, flag);
516 tcg_gen_mov_i64(dest, result);
517 tcg_temp_free_i64(flag);
518 tcg_temp_free_i64(result);
520 /* 32 bit arithmetic */
521 TCGv_i32 t0_32 = tcg_temp_new_i32();
522 TCGv_i32 t1_32 = tcg_temp_new_i32();
525 tcg_gen_trunc_i64_i32(t0_32, t0);
526 tcg_gen_trunc_i64_i32(t1_32, t1);
527 tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
528 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
529 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
530 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
531 tmp = tcg_temp_new_i32();
532 tcg_gen_xor_i32(tmp, t0_32, t1_32);
533 tcg_temp_free_i32(t0_32);
534 tcg_temp_free_i32(t1_32);
535 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
536 tcg_temp_free_i32(tmp);
537 tcg_gen_extu_i32_i64(dest, cpu_NF);
541 /* dest = T0 + T1 + CF; do not compute flags. */
542 static void gen_adc(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
544 TCGv_i64 flag = tcg_temp_new_i64();
545 tcg_gen_extu_i32_i64(flag, cpu_CF);
546 tcg_gen_add_i64(dest, t0, t1);
547 tcg_gen_add_i64(dest, dest, flag);
548 tcg_temp_free_i64(flag);
551 tcg_gen_ext32u_i64(dest, dest);
555 /* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
556 static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
559 TCGv_i64 result, cf_64, vf_64, tmp;
560 result = tcg_temp_new_i64();
561 cf_64 = tcg_temp_new_i64();
562 vf_64 = tcg_temp_new_i64();
563 tmp = tcg_const_i64(0);
565 tcg_gen_extu_i32_i64(cf_64, cpu_CF);
566 tcg_gen_add2_i64(result, cf_64, t0, tmp, cf_64, tmp);
567 tcg_gen_add2_i64(result, cf_64, result, cf_64, t1, tmp);
568 tcg_gen_trunc_i64_i32(cpu_CF, cf_64);
569 gen_set_NZ64(result);
571 tcg_gen_xor_i64(vf_64, result, t0);
572 tcg_gen_xor_i64(tmp, t0, t1);
573 tcg_gen_andc_i64(vf_64, vf_64, tmp);
574 tcg_gen_shri_i64(vf_64, vf_64, 32);
575 tcg_gen_trunc_i64_i32(cpu_VF, vf_64);
577 tcg_gen_mov_i64(dest, result);
579 tcg_temp_free_i64(tmp);
580 tcg_temp_free_i64(vf_64);
581 tcg_temp_free_i64(cf_64);
582 tcg_temp_free_i64(result);
584 TCGv_i32 t0_32, t1_32, tmp;
585 t0_32 = tcg_temp_new_i32();
586 t1_32 = tcg_temp_new_i32();
587 tmp = tcg_const_i32(0);
589 tcg_gen_trunc_i64_i32(t0_32, t0);
590 tcg_gen_trunc_i64_i32(t1_32, t1);
591 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, cpu_CF, tmp);
592 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1_32, tmp);
594 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
595 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
596 tcg_gen_xor_i32(tmp, t0_32, t1_32);
597 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
598 tcg_gen_extu_i32_i64(dest, cpu_NF);
600 tcg_temp_free_i32(tmp);
601 tcg_temp_free_i32(t1_32);
602 tcg_temp_free_i32(t0_32);
607 * Load/Store generators
611 * Store from GPR register to memory
613 static void do_gpr_st(DisasContext *s, TCGv_i64 source,
614 TCGv_i64 tcg_addr, int size)
617 tcg_gen_qemu_st_i64(source, tcg_addr, get_mem_index(s), MO_TE + size);
621 * Load from memory to GPR register
623 static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
624 int size, bool is_signed, bool extend)
626 TCGMemOp memop = MO_TE + size;
634 tcg_gen_qemu_ld_i64(dest, tcg_addr, get_mem_index(s), memop);
636 if (extend && is_signed) {
638 tcg_gen_ext32u_i64(dest, dest);
643 * Store from FP register to memory
645 static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
647 /* This writes the bottom N bits of a 128 bit wide vector to memory */
648 TCGv_i64 tmp = tcg_temp_new_i64();
649 tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_64));
651 tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
653 TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
654 tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
655 tcg_gen_qemu_st64(tmp, tcg_addr, get_mem_index(s));
656 tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(srcidx));
657 tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
658 tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
659 tcg_temp_free_i64(tcg_hiaddr);
662 tcg_temp_free_i64(tmp);
666 * Load from memory to FP register
668 static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
670 /* This always zero-extends and writes to a full 128 bit wide vector */
671 TCGv_i64 tmplo = tcg_temp_new_i64();
675 TCGMemOp memop = MO_TE + size;
676 tmphi = tcg_const_i64(0);
677 tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
680 tmphi = tcg_temp_new_i64();
681 tcg_hiaddr = tcg_temp_new_i64();
683 tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
684 tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
685 tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
686 tcg_temp_free_i64(tcg_hiaddr);
689 tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(destidx, MO_64));
690 tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(destidx));
692 tcg_temp_free_i64(tmplo);
693 tcg_temp_free_i64(tmphi);
697 * Vector load/store helpers.
699 * The principal difference between this and a FP load is that we don't
700 * zero extend as we are filling a partial chunk of the vector register.
701 * These functions don't support 128 bit loads/stores, which would be
702 * normal load/store operations.
704 * The _i32 versions are useful when operating on 32 bit quantities
705 * (eg for floating point single or using Neon helper functions).
708 /* Get value of an element within a vector register */
709 static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
710 int element, TCGMemOp memop)
712 int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE);
715 tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
718 tcg_gen_ld16u_i64(tcg_dest, cpu_env, vect_off);
721 tcg_gen_ld32u_i64(tcg_dest, cpu_env, vect_off);
724 tcg_gen_ld8s_i64(tcg_dest, cpu_env, vect_off);
727 tcg_gen_ld16s_i64(tcg_dest, cpu_env, vect_off);
730 tcg_gen_ld32s_i64(tcg_dest, cpu_env, vect_off);
734 tcg_gen_ld_i64(tcg_dest, cpu_env, vect_off);
737 g_assert_not_reached();
741 static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
742 int element, TCGMemOp memop)
744 int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE);
747 tcg_gen_ld8u_i32(tcg_dest, cpu_env, vect_off);
750 tcg_gen_ld16u_i32(tcg_dest, cpu_env, vect_off);
753 tcg_gen_ld8s_i32(tcg_dest, cpu_env, vect_off);
756 tcg_gen_ld16s_i32(tcg_dest, cpu_env, vect_off);
760 tcg_gen_ld_i32(tcg_dest, cpu_env, vect_off);
763 g_assert_not_reached();
767 /* Set value of an element within a vector register */
768 static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
769 int element, TCGMemOp memop)
771 int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
774 tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
777 tcg_gen_st16_i64(tcg_src, cpu_env, vect_off);
780 tcg_gen_st32_i64(tcg_src, cpu_env, vect_off);
783 tcg_gen_st_i64(tcg_src, cpu_env, vect_off);
786 g_assert_not_reached();
790 /* Clear the high 64 bits of a 128 bit vector (in general non-quad
791 * vector ops all need to do this).
793 static void clear_vec_high(DisasContext *s, int rd)
795 TCGv_i64 tcg_zero = tcg_const_i64(0);
797 write_vec_element(s, tcg_zero, rd, 1, MO_64);
798 tcg_temp_free_i64(tcg_zero);
801 /* Store from vector register to memory */
802 static void do_vec_st(DisasContext *s, int srcidx, int element,
803 TCGv_i64 tcg_addr, int size)
805 TCGMemOp memop = MO_TE + size;
806 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
808 read_vec_element(s, tcg_tmp, srcidx, element, size);
809 tcg_gen_qemu_st_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
811 tcg_temp_free_i64(tcg_tmp);
814 /* Load from memory to vector register */
815 static void do_vec_ld(DisasContext *s, int destidx, int element,
816 TCGv_i64 tcg_addr, int size)
818 TCGMemOp memop = MO_TE + size;
819 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
821 tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
822 write_vec_element(s, tcg_tmp, destidx, element, size);
824 tcg_temp_free_i64(tcg_tmp);
828 * This utility function is for doing register extension with an
829 * optional shift. You will likely want to pass a temporary for the
830 * destination register. See DecodeRegExtend() in the ARM ARM.
832 static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
833 int option, unsigned int shift)
835 int extsize = extract32(option, 0, 2);
836 bool is_signed = extract32(option, 2, 1);
841 tcg_gen_ext8s_i64(tcg_out, tcg_in);
844 tcg_gen_ext16s_i64(tcg_out, tcg_in);
847 tcg_gen_ext32s_i64(tcg_out, tcg_in);
850 tcg_gen_mov_i64(tcg_out, tcg_in);
856 tcg_gen_ext8u_i64(tcg_out, tcg_in);
859 tcg_gen_ext16u_i64(tcg_out, tcg_in);
862 tcg_gen_ext32u_i64(tcg_out, tcg_in);
865 tcg_gen_mov_i64(tcg_out, tcg_in);
871 tcg_gen_shli_i64(tcg_out, tcg_out, shift);
875 static inline void gen_check_sp_alignment(DisasContext *s)
877 /* The AArch64 architecture mandates that (if enabled via PSTATE
878 * or SCTLR bits) there is a check that SP is 16-aligned on every
879 * SP-relative load or store (with an exception generated if it is not).
880 * In line with general QEMU practice regarding misaligned accesses,
881 * we omit these checks for the sake of guest program performance.
882 * This function is provided as a hook so we can more easily add these
883 * checks in future (possibly as a "favour catching guest program bugs
884 * over speed" user selectable option).
889 * This provides a simple table based table lookup decoder. It is
890 * intended to be used when the relevant bits for decode are too
891 * awkwardly placed and switch/if based logic would be confusing and
892 * deeply nested. Since it's a linear search through the table, tables
893 * should be kept small.
895 * It returns the first handler where insn & mask == pattern, or
896 * NULL if there is no match.
897 * The table is terminated by an empty mask (i.e. 0)
899 static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
902 const AArch64DecodeTable *tptr = table;
905 if ((insn & tptr->mask) == tptr->pattern) {
906 return tptr->disas_fn;
914 * the instruction disassembly implemented here matches
915 * the instruction encoding classifications in chapter 3 (C3)
916 * of the ARM Architecture Reference Manual (DDI0487A_a)
919 /* C3.2.7 Unconditional branch (immediate)
921 * +----+-----------+-------------------------------------+
922 * | op | 0 0 1 0 1 | imm26 |
923 * +----+-----------+-------------------------------------+
925 static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
927 uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
929 if (insn & (1 << 31)) {
930 /* C5.6.26 BL Branch with link */
931 tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
934 /* C5.6.20 B Branch / C5.6.26 BL Branch with link */
935 gen_goto_tb(s, 0, addr);
938 /* C3.2.1 Compare & branch (immediate)
939 * 31 30 25 24 23 5 4 0
940 * +----+-------------+----+---------------------+--------+
941 * | sf | 0 1 1 0 1 0 | op | imm19 | Rt |
942 * +----+-------------+----+---------------------+--------+
944 static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
946 unsigned int sf, op, rt;
951 sf = extract32(insn, 31, 1);
952 op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
953 rt = extract32(insn, 0, 5);
954 addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
956 tcg_cmp = read_cpu_reg(s, rt, sf);
957 label_match = gen_new_label();
959 tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
960 tcg_cmp, 0, label_match);
962 gen_goto_tb(s, 0, s->pc);
963 gen_set_label(label_match);
964 gen_goto_tb(s, 1, addr);
967 /* C3.2.5 Test & branch (immediate)
968 * 31 30 25 24 23 19 18 5 4 0
969 * +----+-------------+----+-------+-------------+------+
970 * | b5 | 0 1 1 0 1 1 | op | b40 | imm14 | Rt |
971 * +----+-------------+----+-------+-------------+------+
973 static void disas_test_b_imm(DisasContext *s, uint32_t insn)
975 unsigned int bit_pos, op, rt;
980 bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
981 op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
982 addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
983 rt = extract32(insn, 0, 5);
985 tcg_cmp = tcg_temp_new_i64();
986 tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
987 label_match = gen_new_label();
988 tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
989 tcg_cmp, 0, label_match);
990 tcg_temp_free_i64(tcg_cmp);
991 gen_goto_tb(s, 0, s->pc);
992 gen_set_label(label_match);
993 gen_goto_tb(s, 1, addr);
996 /* C3.2.2 / C5.6.19 Conditional branch (immediate)
997 * 31 25 24 23 5 4 3 0
998 * +---------------+----+---------------------+----+------+
999 * | 0 1 0 1 0 1 0 | o1 | imm19 | o0 | cond |
1000 * +---------------+----+---------------------+----+------+
1002 static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
1007 if ((insn & (1 << 4)) || (insn & (1 << 24))) {
1008 unallocated_encoding(s);
1011 addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
1012 cond = extract32(insn, 0, 4);
1015 /* genuinely conditional branches */
1016 int label_match = gen_new_label();
1017 arm_gen_test_cc(cond, label_match);
1018 gen_goto_tb(s, 0, s->pc);
1019 gen_set_label(label_match);
1020 gen_goto_tb(s, 1, addr);
1022 /* 0xe and 0xf are both "always" conditions */
1023 gen_goto_tb(s, 0, addr);
1028 static void handle_hint(DisasContext *s, uint32_t insn,
1029 unsigned int op1, unsigned int op2, unsigned int crm)
1031 unsigned int selector = crm << 3 | op2;
1034 unallocated_encoding(s);
1046 /* we treat all as NOP at least for now */
1049 /* default specified as NOP equivalent */
1054 static void gen_clrex(DisasContext *s, uint32_t insn)
1056 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
1059 /* CLREX, DSB, DMB, ISB */
1060 static void handle_sync(DisasContext *s, uint32_t insn,
1061 unsigned int op1, unsigned int op2, unsigned int crm)
1064 unallocated_encoding(s);
1075 /* We don't emulate caches so barriers are no-ops */
1078 unallocated_encoding(s);
1083 /* C5.6.130 MSR (immediate) - move immediate to processor state field */
1084 static void handle_msr_i(DisasContext *s, uint32_t insn,
1085 unsigned int op1, unsigned int op2, unsigned int crm)
1087 unsupported_encoding(s, insn);
1090 static void gen_get_nzcv(TCGv_i64 tcg_rt)
1092 TCGv_i32 tmp = tcg_temp_new_i32();
1093 TCGv_i32 nzcv = tcg_temp_new_i32();
1095 /* build bit 31, N */
1096 tcg_gen_andi_i32(nzcv, cpu_NF, (1 << 31));
1097 /* build bit 30, Z */
1098 tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_ZF, 0);
1099 tcg_gen_deposit_i32(nzcv, nzcv, tmp, 30, 1);
1100 /* build bit 29, C */
1101 tcg_gen_deposit_i32(nzcv, nzcv, cpu_CF, 29, 1);
1102 /* build bit 28, V */
1103 tcg_gen_shri_i32(tmp, cpu_VF, 31);
1104 tcg_gen_deposit_i32(nzcv, nzcv, tmp, 28, 1);
1105 /* generate result */
1106 tcg_gen_extu_i32_i64(tcg_rt, nzcv);
1108 tcg_temp_free_i32(nzcv);
1109 tcg_temp_free_i32(tmp);
1112 static void gen_set_nzcv(TCGv_i64 tcg_rt)
1115 TCGv_i32 nzcv = tcg_temp_new_i32();
1117 /* take NZCV from R[t] */
1118 tcg_gen_trunc_i64_i32(nzcv, tcg_rt);
1121 tcg_gen_andi_i32(cpu_NF, nzcv, (1 << 31));
1123 tcg_gen_andi_i32(cpu_ZF, nzcv, (1 << 30));
1124 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_ZF, cpu_ZF, 0);
1126 tcg_gen_andi_i32(cpu_CF, nzcv, (1 << 29));
1127 tcg_gen_shri_i32(cpu_CF, cpu_CF, 29);
1129 tcg_gen_andi_i32(cpu_VF, nzcv, (1 << 28));
1130 tcg_gen_shli_i32(cpu_VF, cpu_VF, 3);
1131 tcg_temp_free_i32(nzcv);
1134 /* C5.6.129 MRS - move from system register
1135 * C5.6.131 MSR (register) - move to system register
1138 * These are all essentially the same insn in 'read' and 'write'
1139 * versions, with varying op0 fields.
1141 static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
1142 unsigned int op0, unsigned int op1, unsigned int op2,
1143 unsigned int crn, unsigned int crm, unsigned int rt)
1145 const ARMCPRegInfo *ri;
1148 ri = get_arm_cp_reginfo(s->cp_regs,
1149 ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
1150 crn, crm, op0, op1, op2));
1153 /* Unknown register */
1154 unallocated_encoding(s);
1158 /* Check access permissions */
1159 if (!cp_access_ok(s->current_pl, ri, isread)) {
1160 unallocated_encoding(s);
1164 /* Handle special cases first */
1165 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
1169 tcg_rt = cpu_reg(s, rt);
1171 gen_get_nzcv(tcg_rt);
1173 gen_set_nzcv(tcg_rt);
1180 if (use_icount && (ri->type & ARM_CP_IO)) {
1184 tcg_rt = cpu_reg(s, rt);
1187 if (ri->type & ARM_CP_CONST) {
1188 tcg_gen_movi_i64(tcg_rt, ri->resetvalue);
1189 } else if (ri->readfn) {
1191 gen_a64_set_pc_im(s->pc - 4);
1192 tmpptr = tcg_const_ptr(ri);
1193 gen_helper_get_cp_reg64(tcg_rt, cpu_env, tmpptr);
1194 tcg_temp_free_ptr(tmpptr);
1196 tcg_gen_ld_i64(tcg_rt, cpu_env, ri->fieldoffset);
1199 if (ri->type & ARM_CP_CONST) {
1200 /* If not forbidden by access permissions, treat as WI */
1202 } else if (ri->writefn) {
1204 gen_a64_set_pc_im(s->pc - 4);
1205 tmpptr = tcg_const_ptr(ri);
1206 gen_helper_set_cp_reg64(cpu_env, tmpptr, tcg_rt);
1207 tcg_temp_free_ptr(tmpptr);
1209 tcg_gen_st_i64(tcg_rt, cpu_env, ri->fieldoffset);
1213 if (use_icount && (ri->type & ARM_CP_IO)) {
1214 /* I/O operations must end the TB here (whether read or write) */
1216 s->is_jmp = DISAS_UPDATE;
1217 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
1218 /* We default to ending the TB on a coprocessor register write,
1219 * but allow this to be suppressed by the register definition
1220 * (usually only necessary to work around guest bugs).
1222 s->is_jmp = DISAS_UPDATE;
1227 * 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
1228 * +---------------------+---+-----+-----+-------+-------+-----+------+
1229 * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 | CRn | CRm | op2 | Rt |
1230 * +---------------------+---+-----+-----+-------+-------+-----+------+
1232 static void disas_system(DisasContext *s, uint32_t insn)
1234 unsigned int l, op0, op1, crn, crm, op2, rt;
1235 l = extract32(insn, 21, 1);
1236 op0 = extract32(insn, 19, 2);
1237 op1 = extract32(insn, 16, 3);
1238 crn = extract32(insn, 12, 4);
1239 crm = extract32(insn, 8, 4);
1240 op2 = extract32(insn, 5, 3);
1241 rt = extract32(insn, 0, 5);
1244 if (l || rt != 31) {
1245 unallocated_encoding(s);
1249 case 2: /* C5.6.68 HINT */
1250 handle_hint(s, insn, op1, op2, crm);
1252 case 3: /* CLREX, DSB, DMB, ISB */
1253 handle_sync(s, insn, op1, op2, crm);
1255 case 4: /* C5.6.130 MSR (immediate) */
1256 handle_msr_i(s, insn, op1, op2, crm);
1259 unallocated_encoding(s);
1264 handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
1267 /* C3.2.3 Exception generation
1269 * 31 24 23 21 20 5 4 2 1 0
1270 * +-----------------+-----+------------------------+-----+----+
1271 * | 1 1 0 1 0 1 0 0 | opc | imm16 | op2 | LL |
1272 * +-----------------------+------------------------+----------+
1274 static void disas_exc(DisasContext *s, uint32_t insn)
1276 int opc = extract32(insn, 21, 3);
1277 int op2_ll = extract32(insn, 0, 5);
1281 /* SVC, HVC, SMC; since we don't support the Virtualization
1282 * or TrustZone extensions these all UNDEF except SVC.
1285 unallocated_encoding(s);
1288 gen_exception_insn(s, 0, EXCP_SWI);
1292 unallocated_encoding(s);
1296 gen_exception_insn(s, 0, EXCP_BKPT);
1300 unallocated_encoding(s);
1304 unsupported_encoding(s, insn);
1307 if (op2_ll < 1 || op2_ll > 3) {
1308 unallocated_encoding(s);
1311 /* DCPS1, DCPS2, DCPS3 */
1312 unsupported_encoding(s, insn);
1315 unallocated_encoding(s);
1320 /* C3.2.7 Unconditional branch (register)
1321 * 31 25 24 21 20 16 15 10 9 5 4 0
1322 * +---------------+-------+-------+-------+------+-------+
1323 * | 1 1 0 1 0 1 1 | opc | op2 | op3 | Rn | op4 |
1324 * +---------------+-------+-------+-------+------+-------+
1326 static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
1328 unsigned int opc, op2, op3, rn, op4;
1330 opc = extract32(insn, 21, 4);
1331 op2 = extract32(insn, 16, 5);
1332 op3 = extract32(insn, 10, 6);
1333 rn = extract32(insn, 5, 5);
1334 op4 = extract32(insn, 0, 5);
1336 if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
1337 unallocated_encoding(s);
1346 tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
1351 unallocated_encoding(s);
1353 unsupported_encoding(s, insn);
1357 unallocated_encoding(s);
1361 tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
1362 s->is_jmp = DISAS_JUMP;
1365 /* C3.2 Branches, exception generating and system instructions */
1366 static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
1368 switch (extract32(insn, 25, 7)) {
1369 case 0x0a: case 0x0b:
1370 case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
1371 disas_uncond_b_imm(s, insn);
1373 case 0x1a: case 0x5a: /* Compare & branch (immediate) */
1374 disas_comp_b_imm(s, insn);
1376 case 0x1b: case 0x5b: /* Test & branch (immediate) */
1377 disas_test_b_imm(s, insn);
1379 case 0x2a: /* Conditional branch (immediate) */
1380 disas_cond_b_imm(s, insn);
1382 case 0x6a: /* Exception generation / System */
1383 if (insn & (1 << 24)) {
1384 disas_system(s, insn);
1389 case 0x6b: /* Unconditional branch (register) */
1390 disas_uncond_b_reg(s, insn);
1393 unallocated_encoding(s);
1399 * Load/Store exclusive instructions are implemented by remembering
1400 * the value/address loaded, and seeing if these are the same
1401 * when the store is performed. This is not actually the architecturally
1402 * mandated semantics, but it works for typical guest code sequences
1403 * and avoids having to monitor regular stores.
1405 * In system emulation mode only one CPU will be running at once, so
1406 * this sequence is effectively atomic. In user emulation mode we
1407 * throw an exception and handle the atomic operation elsewhere.
1409 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
1410 TCGv_i64 addr, int size, bool is_pair)
1412 TCGv_i64 tmp = tcg_temp_new_i64();
1413 TCGMemOp memop = MO_TE + size;
1415 g_assert(size <= 3);
1416 tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
1419 TCGv_i64 addr2 = tcg_temp_new_i64();
1420 TCGv_i64 hitmp = tcg_temp_new_i64();
1422 g_assert(size >= 2);
1423 tcg_gen_addi_i64(addr2, addr, 1 << size);
1424 tcg_gen_qemu_ld_i64(hitmp, addr2, get_mem_index(s), memop);
1425 tcg_temp_free_i64(addr2);
1426 tcg_gen_mov_i64(cpu_exclusive_high, hitmp);
1427 tcg_gen_mov_i64(cpu_reg(s, rt2), hitmp);
1428 tcg_temp_free_i64(hitmp);
1431 tcg_gen_mov_i64(cpu_exclusive_val, tmp);
1432 tcg_gen_mov_i64(cpu_reg(s, rt), tmp);
1434 tcg_temp_free_i64(tmp);
1435 tcg_gen_mov_i64(cpu_exclusive_addr, addr);
1438 #ifdef CONFIG_USER_ONLY
1439 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
1440 TCGv_i64 addr, int size, int is_pair)
1442 tcg_gen_mov_i64(cpu_exclusive_test, addr);
1443 tcg_gen_movi_i32(cpu_exclusive_info,
1444 size | is_pair << 2 | (rd << 4) | (rt << 9) | (rt2 << 14));
1445 gen_exception_insn(s, 4, EXCP_STREX);
1448 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
1449 TCGv_i64 addr, int size, int is_pair)
1451 qemu_log_mask(LOG_UNIMP,
1452 "%s:%d: system mode store_exclusive unsupported "
1453 "at pc=%016" PRIx64 "\n",
1454 __FILE__, __LINE__, s->pc - 4);
1458 /* C3.3.6 Load/store exclusive
1460 * 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
1461 * +-----+-------------+----+---+----+------+----+-------+------+------+
1462 * | sz | 0 0 1 0 0 0 | o2 | L | o1 | Rs | o0 | Rt2 | Rn | Rt |
1463 * +-----+-------------+----+---+----+------+----+-------+------+------+
1465 * sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
1466 * L: 0 -> store, 1 -> load
1467 * o2: 0 -> exclusive, 1 -> not
1468 * o1: 0 -> single register, 1 -> register pair
1469 * o0: 1 -> load-acquire/store-release, 0 -> not
1471 * o0 == 0 AND o2 == 1 is un-allocated
1472 * o1 == 1 is un-allocated except for 32 and 64 bit sizes
1474 static void disas_ldst_excl(DisasContext *s, uint32_t insn)
1476 int rt = extract32(insn, 0, 5);
1477 int rn = extract32(insn, 5, 5);
1478 int rt2 = extract32(insn, 10, 5);
1479 int is_lasr = extract32(insn, 15, 1);
1480 int rs = extract32(insn, 16, 5);
1481 int is_pair = extract32(insn, 21, 1);
1482 int is_store = !extract32(insn, 22, 1);
1483 int is_excl = !extract32(insn, 23, 1);
1484 int size = extract32(insn, 30, 2);
1487 if ((!is_excl && !is_lasr) ||
1488 (is_pair && size < 2)) {
1489 unallocated_encoding(s);
1494 gen_check_sp_alignment(s);
1496 tcg_addr = read_cpu_reg_sp(s, rn, 1);
1498 /* Note that since TCG is single threaded load-acquire/store-release
1499 * semantics require no extra if (is_lasr) { ... } handling.
1504 gen_load_exclusive(s, rt, rt2, tcg_addr, size, is_pair);
1506 gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, is_pair);
1509 TCGv_i64 tcg_rt = cpu_reg(s, rt);
1511 do_gpr_st(s, tcg_rt, tcg_addr, size);
1513 do_gpr_ld(s, tcg_rt, tcg_addr, size, false, false);
1516 TCGv_i64 tcg_rt2 = cpu_reg(s, rt);
1517 tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
1519 do_gpr_st(s, tcg_rt2, tcg_addr, size);
1521 do_gpr_ld(s, tcg_rt2, tcg_addr, size, false, false);
1528 * C3.3.5 Load register (literal)
1530 * 31 30 29 27 26 25 24 23 5 4 0
1531 * +-----+-------+---+-----+-------------------+-------+
1532 * | opc | 0 1 1 | V | 0 0 | imm19 | Rt |
1533 * +-----+-------+---+-----+-------------------+-------+
1535 * V: 1 -> vector (simd/fp)
1536 * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
1537 * 10-> 32 bit signed, 11 -> prefetch
1538 * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
1540 static void disas_ld_lit(DisasContext *s, uint32_t insn)
1542 int rt = extract32(insn, 0, 5);
1543 int64_t imm = sextract32(insn, 5, 19) << 2;
1544 bool is_vector = extract32(insn, 26, 1);
1545 int opc = extract32(insn, 30, 2);
1546 bool is_signed = false;
1548 TCGv_i64 tcg_rt, tcg_addr;
1552 unallocated_encoding(s);
1558 /* PRFM (literal) : prefetch */
1561 size = 2 + extract32(opc, 0, 1);
1562 is_signed = extract32(opc, 1, 1);
1565 tcg_rt = cpu_reg(s, rt);
1567 tcg_addr = tcg_const_i64((s->pc - 4) + imm);
1569 do_fp_ld(s, rt, tcg_addr, size);
1571 do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
1573 tcg_temp_free_i64(tcg_addr);
1577 * C5.6.80 LDNP (Load Pair - non-temporal hint)
1578 * C5.6.81 LDP (Load Pair - non vector)
1579 * C5.6.82 LDPSW (Load Pair Signed Word - non vector)
1580 * C5.6.176 STNP (Store Pair - non-temporal hint)
1581 * C5.6.177 STP (Store Pair - non vector)
1582 * C6.3.165 LDNP (Load Pair of SIMD&FP - non-temporal hint)
1583 * C6.3.165 LDP (Load Pair of SIMD&FP)
1584 * C6.3.284 STNP (Store Pair of SIMD&FP - non-temporal hint)
1585 * C6.3.284 STP (Store Pair of SIMD&FP)
1587 * 31 30 29 27 26 25 24 23 22 21 15 14 10 9 5 4 0
1588 * +-----+-------+---+---+-------+---+-----------------------------+
1589 * | opc | 1 0 1 | V | 0 | index | L | imm7 | Rt2 | Rn | Rt |
1590 * +-----+-------+---+---+-------+---+-------+-------+------+------+
1592 * opc: LDP/STP/LDNP/STNP 00 -> 32 bit, 10 -> 64 bit
1594 * LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
1595 * V: 0 -> GPR, 1 -> Vector
1596 * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
1597 * 10 -> signed offset, 11 -> pre-index
1598 * L: 0 -> Store 1 -> Load
1600 * Rt, Rt2 = GPR or SIMD registers to be stored
1601 * Rn = general purpose register containing address
1602 * imm7 = signed offset (multiple of 4 or 8 depending on size)
1604 static void disas_ldst_pair(DisasContext *s, uint32_t insn)
1606 int rt = extract32(insn, 0, 5);
1607 int rn = extract32(insn, 5, 5);
1608 int rt2 = extract32(insn, 10, 5);
1609 int64_t offset = sextract32(insn, 15, 7);
1610 int index = extract32(insn, 23, 2);
1611 bool is_vector = extract32(insn, 26, 1);
1612 bool is_load = extract32(insn, 22, 1);
1613 int opc = extract32(insn, 30, 2);
1615 bool is_signed = false;
1616 bool postindex = false;
1619 TCGv_i64 tcg_addr; /* calculated address */
1623 unallocated_encoding(s);
1630 size = 2 + extract32(opc, 1, 1);
1631 is_signed = extract32(opc, 0, 1);
1632 if (!is_load && is_signed) {
1633 unallocated_encoding(s);
1639 case 1: /* post-index */
1644 /* signed offset with "non-temporal" hint. Since we don't emulate
1645 * caches we don't care about hints to the cache system about
1646 * data access patterns, and handle this identically to plain
1650 /* There is no non-temporal-hint version of LDPSW */
1651 unallocated_encoding(s);
1656 case 2: /* signed offset, rn not updated */
1659 case 3: /* pre-index */
1668 gen_check_sp_alignment(s);
1671 tcg_addr = read_cpu_reg_sp(s, rn, 1);
1674 tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
1679 do_fp_ld(s, rt, tcg_addr, size);
1681 do_fp_st(s, rt, tcg_addr, size);
1684 TCGv_i64 tcg_rt = cpu_reg(s, rt);
1686 do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
1688 do_gpr_st(s, tcg_rt, tcg_addr, size);
1691 tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
1694 do_fp_ld(s, rt2, tcg_addr, size);
1696 do_fp_st(s, rt2, tcg_addr, size);
1699 TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
1701 do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false);
1703 do_gpr_st(s, tcg_rt2, tcg_addr, size);
1709 tcg_gen_addi_i64(tcg_addr, tcg_addr, offset - (1 << size));
1711 tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size);
1713 tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
1718 * C3.3.8 Load/store (immediate post-indexed)
1719 * C3.3.9 Load/store (immediate pre-indexed)
1720 * C3.3.12 Load/store (unscaled immediate)
1722 * 31 30 29 27 26 25 24 23 22 21 20 12 11 10 9 5 4 0
1723 * +----+-------+---+-----+-----+---+--------+-----+------+------+
1724 * |size| 1 1 1 | V | 0 0 | opc | 0 | imm9 | idx | Rn | Rt |
1725 * +----+-------+---+-----+-----+---+--------+-----+------+------+
1727 * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
1728 * V = 0 -> non-vector
1729 * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
1730 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1732 static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn)
1734 int rt = extract32(insn, 0, 5);
1735 int rn = extract32(insn, 5, 5);
1736 int imm9 = sextract32(insn, 12, 9);
1737 int opc = extract32(insn, 22, 2);
1738 int size = extract32(insn, 30, 2);
1739 int idx = extract32(insn, 10, 2);
1740 bool is_signed = false;
1741 bool is_store = false;
1742 bool is_extended = false;
1743 bool is_vector = extract32(insn, 26, 1);
1750 size |= (opc & 2) << 1;
1752 unallocated_encoding(s);
1755 is_store = ((opc & 1) == 0);
1757 if (size == 3 && opc == 2) {
1758 /* PRFM - prefetch */
1761 if (opc == 3 && size > 1) {
1762 unallocated_encoding(s);
1765 is_store = (opc == 0);
1766 is_signed = opc & (1<<1);
1767 is_extended = (size < 3) && (opc & 1);
1789 gen_check_sp_alignment(s);
1791 tcg_addr = read_cpu_reg_sp(s, rn, 1);
1794 tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
1799 do_fp_st(s, rt, tcg_addr, size);
1801 do_fp_ld(s, rt, tcg_addr, size);
1804 TCGv_i64 tcg_rt = cpu_reg(s, rt);
1806 do_gpr_st(s, tcg_rt, tcg_addr, size);
1808 do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1813 TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
1815 tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
1817 tcg_gen_mov_i64(tcg_rn, tcg_addr);
1822 * C3.3.10 Load/store (register offset)
1824 * 31 30 29 27 26 25 24 23 22 21 20 16 15 13 12 11 10 9 5 4 0
1825 * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
1826 * |size| 1 1 1 | V | 0 0 | opc | 1 | Rm | opt | S| 1 0 | Rn | Rt |
1827 * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
1830 * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
1831 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1833 * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
1834 * opc<0>: 0 -> store, 1 -> load
1835 * V: 1 -> vector/simd
1836 * opt: extend encoding (see DecodeRegExtend)
1837 * S: if S=1 then scale (essentially index by sizeof(size))
1838 * Rt: register to transfer into/out of
1839 * Rn: address register or SP for base
1840 * Rm: offset register or ZR for offset
1842 static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn)
1844 int rt = extract32(insn, 0, 5);
1845 int rn = extract32(insn, 5, 5);
1846 int shift = extract32(insn, 12, 1);
1847 int rm = extract32(insn, 16, 5);
1848 int opc = extract32(insn, 22, 2);
1849 int opt = extract32(insn, 13, 3);
1850 int size = extract32(insn, 30, 2);
1851 bool is_signed = false;
1852 bool is_store = false;
1853 bool is_extended = false;
1854 bool is_vector = extract32(insn, 26, 1);
1859 if (extract32(opt, 1, 1) == 0) {
1860 unallocated_encoding(s);
1865 size |= (opc & 2) << 1;
1867 unallocated_encoding(s);
1870 is_store = !extract32(opc, 0, 1);
1872 if (size == 3 && opc == 2) {
1873 /* PRFM - prefetch */
1876 if (opc == 3 && size > 1) {
1877 unallocated_encoding(s);
1880 is_store = (opc == 0);
1881 is_signed = extract32(opc, 1, 1);
1882 is_extended = (size < 3) && extract32(opc, 0, 1);
1886 gen_check_sp_alignment(s);
1888 tcg_addr = read_cpu_reg_sp(s, rn, 1);
1890 tcg_rm = read_cpu_reg(s, rm, 1);
1891 ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
1893 tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_rm);
1897 do_fp_st(s, rt, tcg_addr, size);
1899 do_fp_ld(s, rt, tcg_addr, size);
1902 TCGv_i64 tcg_rt = cpu_reg(s, rt);
1904 do_gpr_st(s, tcg_rt, tcg_addr, size);
1906 do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1912 * C3.3.13 Load/store (unsigned immediate)
1914 * 31 30 29 27 26 25 24 23 22 21 10 9 5
1915 * +----+-------+---+-----+-----+------------+-------+------+
1916 * |size| 1 1 1 | V | 0 1 | opc | imm12 | Rn | Rt |
1917 * +----+-------+---+-----+-----+------------+-------+------+
1920 * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
1921 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1923 * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
1924 * opc<0>: 0 -> store, 1 -> load
1925 * Rn: base address register (inc SP)
1926 * Rt: target register
1928 static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn)
1930 int rt = extract32(insn, 0, 5);
1931 int rn = extract32(insn, 5, 5);
1932 unsigned int imm12 = extract32(insn, 10, 12);
1933 bool is_vector = extract32(insn, 26, 1);
1934 int size = extract32(insn, 30, 2);
1935 int opc = extract32(insn, 22, 2);
1936 unsigned int offset;
1941 bool is_signed = false;
1942 bool is_extended = false;
1945 size |= (opc & 2) << 1;
1947 unallocated_encoding(s);
1950 is_store = !extract32(opc, 0, 1);
1952 if (size == 3 && opc == 2) {
1953 /* PRFM - prefetch */
1956 if (opc == 3 && size > 1) {
1957 unallocated_encoding(s);
1960 is_store = (opc == 0);
1961 is_signed = extract32(opc, 1, 1);
1962 is_extended = (size < 3) && extract32(opc, 0, 1);
1966 gen_check_sp_alignment(s);
1968 tcg_addr = read_cpu_reg_sp(s, rn, 1);
1969 offset = imm12 << size;
1970 tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
1974 do_fp_st(s, rt, tcg_addr, size);
1976 do_fp_ld(s, rt, tcg_addr, size);
1979 TCGv_i64 tcg_rt = cpu_reg(s, rt);
1981 do_gpr_st(s, tcg_rt, tcg_addr, size);
1983 do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1988 /* Load/store register (immediate forms) */
1989 static void disas_ldst_reg_imm(DisasContext *s, uint32_t insn)
1991 switch (extract32(insn, 10, 2)) {
1992 case 0: case 1: case 3:
1993 /* Load/store register (unscaled immediate) */
1994 /* Load/store immediate pre/post-indexed */
1995 disas_ldst_reg_imm9(s, insn);
1998 /* Load/store register unprivileged */
1999 unsupported_encoding(s, insn);
2002 unallocated_encoding(s);
2007 /* Load/store register (all forms) */
2008 static void disas_ldst_reg(DisasContext *s, uint32_t insn)
2010 switch (extract32(insn, 24, 2)) {
2012 if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) {
2013 disas_ldst_reg_roffset(s, insn);
2015 disas_ldst_reg_imm(s, insn);
2019 disas_ldst_reg_unsigned_imm(s, insn);
2022 unallocated_encoding(s);
2027 /* C3.3.1 AdvSIMD load/store multiple structures
2029 * 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
2030 * +---+---+---------------+---+-------------+--------+------+------+------+
2031 * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size | Rn | Rt |
2032 * +---+---+---------------+---+-------------+--------+------+------+------+
2034 * C3.3.2 AdvSIMD load/store multiple structures (post-indexed)
2036 * 31 30 29 23 22 21 20 16 15 12 11 10 9 5 4 0
2037 * +---+---+---------------+---+---+---------+--------+------+------+------+
2038 * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 | Rm | opcode | size | Rn | Rt |
2039 * +---+---+---------------+---+---+---------+--------+------+------+------+
2041 * Rt: first (or only) SIMD&FP register to be transferred
2042 * Rn: base address or SP
2043 * Rm (post-index only): post-index register (when !31) or size dependent #imm
2045 static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
2047 int rt = extract32(insn, 0, 5);
2048 int rn = extract32(insn, 5, 5);
2049 int size = extract32(insn, 10, 2);
2050 int opcode = extract32(insn, 12, 4);
2051 bool is_store = !extract32(insn, 22, 1);
2052 bool is_postidx = extract32(insn, 23, 1);
2053 bool is_q = extract32(insn, 30, 1);
2054 TCGv_i64 tcg_addr, tcg_rn;
2056 int ebytes = 1 << size;
2057 int elements = (is_q ? 128 : 64) / (8 << size);
2058 int rpt; /* num iterations */
2059 int selem; /* structure elements */
2062 if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
2063 unallocated_encoding(s);
2067 /* From the shared decode logic */
2098 unallocated_encoding(s);
2102 if (size == 3 && !is_q && selem != 1) {
2104 unallocated_encoding(s);
2109 gen_check_sp_alignment(s);
2112 tcg_rn = cpu_reg_sp(s, rn);
2113 tcg_addr = tcg_temp_new_i64();
2114 tcg_gen_mov_i64(tcg_addr, tcg_rn);
2116 for (r = 0; r < rpt; r++) {
2118 for (e = 0; e < elements; e++) {
2119 int tt = (rt + r) % 32;
2121 for (xs = 0; xs < selem; xs++) {
2123 do_vec_st(s, tt, e, tcg_addr, size);
2125 do_vec_ld(s, tt, e, tcg_addr, size);
2127 /* For non-quad operations, setting a slice of the low
2128 * 64 bits of the register clears the high 64 bits (in
2129 * the ARM ARM pseudocode this is implicit in the fact
2130 * that 'rval' is a 64 bit wide variable). We optimize
2131 * by noticing that we only need to do this the first
2132 * time we touch a register.
2134 if (!is_q && e == 0 && (r == 0 || xs == selem - 1)) {
2135 clear_vec_high(s, tt);
2138 tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
2145 int rm = extract32(insn, 16, 5);
2147 tcg_gen_mov_i64(tcg_rn, tcg_addr);
2149 tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
2152 tcg_temp_free_i64(tcg_addr);
2155 /* C3.3.3 AdvSIMD load/store single structure
2157 * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
2158 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2159 * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size | Rn | Rt |
2160 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2162 * C3.3.4 AdvSIMD load/store single structure (post-indexed)
2164 * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
2165 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2166 * | 0 | Q | 0 0 1 1 0 1 1 | L R | Rm | opc | S | size | Rn | Rt |
2167 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2169 * Rt: first (or only) SIMD&FP register to be transferred
2170 * Rn: base address or SP
2171 * Rm (post-index only): post-index register (when !31) or size dependent #imm
2172 * index = encoded in Q:S:size dependent on size
2174 * lane_size = encoded in R, opc
2175 * transfer width = encoded in opc, S, size
2177 static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
2179 int rt = extract32(insn, 0, 5);
2180 int rn = extract32(insn, 5, 5);
2181 int size = extract32(insn, 10, 2);
2182 int S = extract32(insn, 12, 1);
2183 int opc = extract32(insn, 13, 3);
2184 int R = extract32(insn, 21, 1);
2185 int is_load = extract32(insn, 22, 1);
2186 int is_postidx = extract32(insn, 23, 1);
2187 int is_q = extract32(insn, 30, 1);
2189 int scale = extract32(opc, 1, 2);
2190 int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
2191 bool replicate = false;
2192 int index = is_q << 3 | S << 2 | size;
2194 TCGv_i64 tcg_addr, tcg_rn;
2198 if (!is_load || S) {
2199 unallocated_encoding(s);
2208 if (extract32(size, 0, 1)) {
2209 unallocated_encoding(s);
2215 if (extract32(size, 1, 1)) {
2216 unallocated_encoding(s);
2219 if (!extract32(size, 0, 1)) {
2223 unallocated_encoding(s);
2231 g_assert_not_reached();
2234 ebytes = 1 << scale;
2237 gen_check_sp_alignment(s);
2240 tcg_rn = cpu_reg_sp(s, rn);
2241 tcg_addr = tcg_temp_new_i64();
2242 tcg_gen_mov_i64(tcg_addr, tcg_rn);
2244 for (xs = 0; xs < selem; xs++) {
2246 /* Load and replicate to all elements */
2248 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
2250 tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
2251 get_mem_index(s), MO_TE + scale);
2254 mulconst = 0x0101010101010101ULL;
2257 mulconst = 0x0001000100010001ULL;
2260 mulconst = 0x0000000100000001ULL;
2266 g_assert_not_reached();
2269 tcg_gen_muli_i64(tcg_tmp, tcg_tmp, mulconst);
2271 write_vec_element(s, tcg_tmp, rt, 0, MO_64);
2273 write_vec_element(s, tcg_tmp, rt, 1, MO_64);
2275 clear_vec_high(s, rt);
2277 tcg_temp_free_i64(tcg_tmp);
2279 /* Load/store one element per register */
2281 do_vec_ld(s, rt, index, tcg_addr, MO_TE + scale);
2283 do_vec_st(s, rt, index, tcg_addr, MO_TE + scale);
2286 tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
2291 int rm = extract32(insn, 16, 5);
2293 tcg_gen_mov_i64(tcg_rn, tcg_addr);
2295 tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
2298 tcg_temp_free_i64(tcg_addr);
2301 /* C3.3 Loads and stores */
2302 static void disas_ldst(DisasContext *s, uint32_t insn)
2304 switch (extract32(insn, 24, 6)) {
2305 case 0x08: /* Load/store exclusive */
2306 disas_ldst_excl(s, insn);
2308 case 0x18: case 0x1c: /* Load register (literal) */
2309 disas_ld_lit(s, insn);
2311 case 0x28: case 0x29:
2312 case 0x2c: case 0x2d: /* Load/store pair (all forms) */
2313 disas_ldst_pair(s, insn);
2315 case 0x38: case 0x39:
2316 case 0x3c: case 0x3d: /* Load/store register (all forms) */
2317 disas_ldst_reg(s, insn);
2319 case 0x0c: /* AdvSIMD load/store multiple structures */
2320 disas_ldst_multiple_struct(s, insn);
2322 case 0x0d: /* AdvSIMD load/store single structure */
2323 disas_ldst_single_struct(s, insn);
2326 unallocated_encoding(s);
2331 /* C3.4.6 PC-rel. addressing
2332 * 31 30 29 28 24 23 5 4 0
2333 * +----+-------+-----------+-------------------+------+
2334 * | op | immlo | 1 0 0 0 0 | immhi | Rd |
2335 * +----+-------+-----------+-------------------+------+
2337 static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
2339 unsigned int page, rd;
2343 page = extract32(insn, 31, 1);
2344 /* SignExtend(immhi:immlo) -> offset */
2345 offset = ((int64_t)sextract32(insn, 5, 19) << 2) | extract32(insn, 29, 2);
2346 rd = extract32(insn, 0, 5);
2350 /* ADRP (page based) */
2355 tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
2359 * C3.4.1 Add/subtract (immediate)
2361 * 31 30 29 28 24 23 22 21 10 9 5 4 0
2362 * +--+--+--+-----------+-----+-------------+-----+-----+
2363 * |sf|op| S| 1 0 0 0 1 |shift| imm12 | Rn | Rd |
2364 * +--+--+--+-----------+-----+-------------+-----+-----+
2366 * sf: 0 -> 32bit, 1 -> 64bit
2367 * op: 0 -> add , 1 -> sub
2369 * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
2371 static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
2373 int rd = extract32(insn, 0, 5);
2374 int rn = extract32(insn, 5, 5);
2375 uint64_t imm = extract32(insn, 10, 12);
2376 int shift = extract32(insn, 22, 2);
2377 bool setflags = extract32(insn, 29, 1);
2378 bool sub_op = extract32(insn, 30, 1);
2379 bool is_64bit = extract32(insn, 31, 1);
2381 TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
2382 TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
2383 TCGv_i64 tcg_result;
2392 unallocated_encoding(s);
2396 tcg_result = tcg_temp_new_i64();
2399 tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
2401 tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
2404 TCGv_i64 tcg_imm = tcg_const_i64(imm);
2406 gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
2408 gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
2410 tcg_temp_free_i64(tcg_imm);
2414 tcg_gen_mov_i64(tcg_rd, tcg_result);
2416 tcg_gen_ext32u_i64(tcg_rd, tcg_result);
2419 tcg_temp_free_i64(tcg_result);
2422 /* The input should be a value in the bottom e bits (with higher
2423 * bits zero); returns that value replicated into every element
2424 * of size e in a 64 bit integer.
2426 static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
2436 /* Return a value with the bottom len bits set (where 0 < len <= 64) */
2437 static inline uint64_t bitmask64(unsigned int length)
2439 assert(length > 0 && length <= 64);
2440 return ~0ULL >> (64 - length);
2443 /* Simplified variant of pseudocode DecodeBitMasks() for the case where we
2444 * only require the wmask. Returns false if the imms/immr/immn are a reserved
2445 * value (ie should cause a guest UNDEF exception), and true if they are
2446 * valid, in which case the decoded bit pattern is written to result.
2448 static bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
2449 unsigned int imms, unsigned int immr)
2452 unsigned e, levels, s, r;
2455 assert(immn < 2 && imms < 64 && immr < 64);
2457 /* The bit patterns we create here are 64 bit patterns which
2458 * are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
2459 * 64 bits each. Each element contains the same value: a run
2460 * of between 1 and e-1 non-zero bits, rotated within the
2461 * element by between 0 and e-1 bits.
2463 * The element size and run length are encoded into immn (1 bit)
2464 * and imms (6 bits) as follows:
2465 * 64 bit elements: immn = 1, imms = <length of run - 1>
2466 * 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
2467 * 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
2468 * 8 bit elements: immn = 0, imms = 110 : <length of run - 1>
2469 * 4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
2470 * 2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
2471 * Notice that immn = 0, imms = 11111x is the only combination
2472 * not covered by one of the above options; this is reserved.
2473 * Further, <length of run - 1> all-ones is a reserved pattern.
2475 * In all cases the rotation is by immr % e (and immr is 6 bits).
2478 /* First determine the element size */
2479 len = 31 - clz32((immn << 6) | (~imms & 0x3f));
2481 /* This is the immn == 0, imms == 0x11111x case */
2491 /* <length of run - 1> mustn't be all-ones. */
2495 /* Create the value of one element: s+1 set bits rotated
2496 * by r within the element (which is e bits wide)...
2498 mask = bitmask64(s + 1);
2499 mask = (mask >> r) | (mask << (e - r));
2500 /* ...then replicate the element over the whole 64 bit value */
2501 mask = bitfield_replicate(mask, e);
2506 /* C3.4.4 Logical (immediate)
2507 * 31 30 29 28 23 22 21 16 15 10 9 5 4 0
2508 * +----+-----+-------------+---+------+------+------+------+
2509 * | sf | opc | 1 0 0 1 0 0 | N | immr | imms | Rn | Rd |
2510 * +----+-----+-------------+---+------+------+------+------+
2512 static void disas_logic_imm(DisasContext *s, uint32_t insn)
2514 unsigned int sf, opc, is_n, immr, imms, rn, rd;
2515 TCGv_i64 tcg_rd, tcg_rn;
2517 bool is_and = false;
2519 sf = extract32(insn, 31, 1);
2520 opc = extract32(insn, 29, 2);
2521 is_n = extract32(insn, 22, 1);
2522 immr = extract32(insn, 16, 6);
2523 imms = extract32(insn, 10, 6);
2524 rn = extract32(insn, 5, 5);
2525 rd = extract32(insn, 0, 5);
2528 unallocated_encoding(s);
2532 if (opc == 0x3) { /* ANDS */
2533 tcg_rd = cpu_reg(s, rd);
2535 tcg_rd = cpu_reg_sp(s, rd);
2537 tcg_rn = cpu_reg(s, rn);
2539 if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
2540 /* some immediate field values are reserved */
2541 unallocated_encoding(s);
2546 wmask &= 0xffffffff;
2550 case 0x3: /* ANDS */
2552 tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
2556 tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
2559 tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
2562 assert(FALSE); /* must handle all above */
2566 if (!sf && !is_and) {
2567 /* zero extend final result; we know we can skip this for AND
2568 * since the immediate had the high 32 bits clear.
2570 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2573 if (opc == 3) { /* ANDS */
2574 gen_logic_CC(sf, tcg_rd);
2579 * C3.4.5 Move wide (immediate)
2581 * 31 30 29 28 23 22 21 20 5 4 0
2582 * +--+-----+-------------+-----+----------------+------+
2583 * |sf| opc | 1 0 0 1 0 1 | hw | imm16 | Rd |
2584 * +--+-----+-------------+-----+----------------+------+
2586 * sf: 0 -> 32 bit, 1 -> 64 bit
2587 * opc: 00 -> N, 10 -> Z, 11 -> K
2588 * hw: shift/16 (0,16, and sf only 32, 48)
2590 static void disas_movw_imm(DisasContext *s, uint32_t insn)
2592 int rd = extract32(insn, 0, 5);
2593 uint64_t imm = extract32(insn, 5, 16);
2594 int sf = extract32(insn, 31, 1);
2595 int opc = extract32(insn, 29, 2);
2596 int pos = extract32(insn, 21, 2) << 4;
2597 TCGv_i64 tcg_rd = cpu_reg(s, rd);
2600 if (!sf && (pos >= 32)) {
2601 unallocated_encoding(s);
2615 tcg_gen_movi_i64(tcg_rd, imm);
2618 tcg_imm = tcg_const_i64(imm);
2619 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_imm, pos, 16);
2620 tcg_temp_free_i64(tcg_imm);
2622 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2626 unallocated_encoding(s);
2632 * 31 30 29 28 23 22 21 16 15 10 9 5 4 0
2633 * +----+-----+-------------+---+------+------+------+------+
2634 * | sf | opc | 1 0 0 1 1 0 | N | immr | imms | Rn | Rd |
2635 * +----+-----+-------------+---+------+------+------+------+
2637 static void disas_bitfield(DisasContext *s, uint32_t insn)
2639 unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
2640 TCGv_i64 tcg_rd, tcg_tmp;
2642 sf = extract32(insn, 31, 1);
2643 opc = extract32(insn, 29, 2);
2644 n = extract32(insn, 22, 1);
2645 ri = extract32(insn, 16, 6);
2646 si = extract32(insn, 10, 6);
2647 rn = extract32(insn, 5, 5);
2648 rd = extract32(insn, 0, 5);
2649 bitsize = sf ? 64 : 32;
2651 if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
2652 unallocated_encoding(s);
2656 tcg_rd = cpu_reg(s, rd);
2657 tcg_tmp = read_cpu_reg(s, rn, sf);
2659 /* OPTME: probably worth recognizing common cases of ext{8,16,32}{u,s} */
2661 if (opc != 1) { /* SBFM or UBFM */
2662 tcg_gen_movi_i64(tcg_rd, 0);
2665 /* do the bit move operation */
2667 /* Wd<s-r:0> = Wn<s:r> */
2668 tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
2670 len = (si - ri) + 1;
2672 /* Wd<32+s-r,32-r> = Wn<s:0> */
2677 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
2679 if (opc == 0) { /* SBFM - sign extend the destination field */
2680 tcg_gen_shli_i64(tcg_rd, tcg_rd, 64 - (pos + len));
2681 tcg_gen_sari_i64(tcg_rd, tcg_rd, 64 - (pos + len));
2684 if (!sf) { /* zero extend final result */
2685 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2690 * 31 30 29 28 23 22 21 20 16 15 10 9 5 4 0
2691 * +----+------+-------------+---+----+------+--------+------+------+
2692 * | sf | op21 | 1 0 0 1 1 1 | N | o0 | Rm | imms | Rn | Rd |
2693 * +----+------+-------------+---+----+------+--------+------+------+
2695 static void disas_extract(DisasContext *s, uint32_t insn)
2697 unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
2699 sf = extract32(insn, 31, 1);
2700 n = extract32(insn, 22, 1);
2701 rm = extract32(insn, 16, 5);
2702 imm = extract32(insn, 10, 6);
2703 rn = extract32(insn, 5, 5);
2704 rd = extract32(insn, 0, 5);
2705 op21 = extract32(insn, 29, 2);
2706 op0 = extract32(insn, 21, 1);
2707 bitsize = sf ? 64 : 32;
2709 if (sf != n || op21 || op0 || imm >= bitsize) {
2710 unallocated_encoding(s);
2712 TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
2714 tcg_rd = cpu_reg(s, rd);
2717 /* OPTME: we can special case rm==rn as a rotate */
2718 tcg_rm = read_cpu_reg(s, rm, sf);
2719 tcg_rn = read_cpu_reg(s, rn, sf);
2720 tcg_gen_shri_i64(tcg_rm, tcg_rm, imm);
2721 tcg_gen_shli_i64(tcg_rn, tcg_rn, bitsize - imm);
2722 tcg_gen_or_i64(tcg_rd, tcg_rm, tcg_rn);
2724 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2727 /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
2728 * so an extract from bit 0 is a special case.
2731 tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
2733 tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
2740 /* C3.4 Data processing - immediate */
2741 static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
2743 switch (extract32(insn, 23, 6)) {
2744 case 0x20: case 0x21: /* PC-rel. addressing */
2745 disas_pc_rel_adr(s, insn);
2747 case 0x22: case 0x23: /* Add/subtract (immediate) */
2748 disas_add_sub_imm(s, insn);
2750 case 0x24: /* Logical (immediate) */
2751 disas_logic_imm(s, insn);
2753 case 0x25: /* Move wide (immediate) */
2754 disas_movw_imm(s, insn);
2756 case 0x26: /* Bitfield */
2757 disas_bitfield(s, insn);
2759 case 0x27: /* Extract */
2760 disas_extract(s, insn);
2763 unallocated_encoding(s);
2768 /* Shift a TCGv src by TCGv shift_amount, put result in dst.
2769 * Note that it is the caller's responsibility to ensure that the
2770 * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
2771 * mandated semantics for out of range shifts.
2773 static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
2774 enum a64_shift_type shift_type, TCGv_i64 shift_amount)
2776 switch (shift_type) {
2777 case A64_SHIFT_TYPE_LSL:
2778 tcg_gen_shl_i64(dst, src, shift_amount);
2780 case A64_SHIFT_TYPE_LSR:
2781 tcg_gen_shr_i64(dst, src, shift_amount);
2783 case A64_SHIFT_TYPE_ASR:
2785 tcg_gen_ext32s_i64(dst, src);
2787 tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
2789 case A64_SHIFT_TYPE_ROR:
2791 tcg_gen_rotr_i64(dst, src, shift_amount);
2794 t0 = tcg_temp_new_i32();
2795 t1 = tcg_temp_new_i32();
2796 tcg_gen_trunc_i64_i32(t0, src);
2797 tcg_gen_trunc_i64_i32(t1, shift_amount);
2798 tcg_gen_rotr_i32(t0, t0, t1);
2799 tcg_gen_extu_i32_i64(dst, t0);
2800 tcg_temp_free_i32(t0);
2801 tcg_temp_free_i32(t1);
2805 assert(FALSE); /* all shift types should be handled */
2809 if (!sf) { /* zero extend final result */
2810 tcg_gen_ext32u_i64(dst, dst);
2814 /* Shift a TCGv src by immediate, put result in dst.
2815 * The shift amount must be in range (this should always be true as the
2816 * relevant instructions will UNDEF on bad shift immediates).
2818 static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
2819 enum a64_shift_type shift_type, unsigned int shift_i)
2821 assert(shift_i < (sf ? 64 : 32));
2824 tcg_gen_mov_i64(dst, src);
2826 TCGv_i64 shift_const;
2828 shift_const = tcg_const_i64(shift_i);
2829 shift_reg(dst, src, sf, shift_type, shift_const);
2830 tcg_temp_free_i64(shift_const);
2834 /* C3.5.10 Logical (shifted register)
2835 * 31 30 29 28 24 23 22 21 20 16 15 10 9 5 4 0
2836 * +----+-----+-----------+-------+---+------+--------+------+------+
2837 * | sf | opc | 0 1 0 1 0 | shift | N | Rm | imm6 | Rn | Rd |
2838 * +----+-----+-----------+-------+---+------+--------+------+------+
2840 static void disas_logic_reg(DisasContext *s, uint32_t insn)
2842 TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
2843 unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
2845 sf = extract32(insn, 31, 1);
2846 opc = extract32(insn, 29, 2);
2847 shift_type = extract32(insn, 22, 2);
2848 invert = extract32(insn, 21, 1);
2849 rm = extract32(insn, 16, 5);
2850 shift_amount = extract32(insn, 10, 6);
2851 rn = extract32(insn, 5, 5);
2852 rd = extract32(insn, 0, 5);
2854 if (!sf && (shift_amount & (1 << 5))) {
2855 unallocated_encoding(s);
2859 tcg_rd = cpu_reg(s, rd);
2861 if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
2862 /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
2863 * register-register MOV and MVN, so it is worth special casing.
2865 tcg_rm = cpu_reg(s, rm);
2867 tcg_gen_not_i64(tcg_rd, tcg_rm);
2869 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2873 tcg_gen_mov_i64(tcg_rd, tcg_rm);
2875 tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
2881 tcg_rm = read_cpu_reg(s, rm, sf);
2884 shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
2887 tcg_rn = cpu_reg(s, rn);
2889 switch (opc | (invert << 2)) {
2892 tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
2895 tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
2898 tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
2902 tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
2905 tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
2908 tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
2916 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2920 gen_logic_CC(sf, tcg_rd);
2925 * C3.5.1 Add/subtract (extended register)
2927 * 31|30|29|28 24|23 22|21|20 16|15 13|12 10|9 5|4 0|
2928 * +--+--+--+-----------+-----+--+-------+------+------+----+----+
2929 * |sf|op| S| 0 1 0 1 1 | opt | 1| Rm |option| imm3 | Rn | Rd |
2930 * +--+--+--+-----------+-----+--+-------+------+------+----+----+
2932 * sf: 0 -> 32bit, 1 -> 64bit
2933 * op: 0 -> add , 1 -> sub
2936 * option: extension type (see DecodeRegExtend)
2937 * imm3: optional shift to Rm
2939 * Rd = Rn + LSL(extend(Rm), amount)
2941 static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
2943 int rd = extract32(insn, 0, 5);
2944 int rn = extract32(insn, 5, 5);
2945 int imm3 = extract32(insn, 10, 3);
2946 int option = extract32(insn, 13, 3);
2947 int rm = extract32(insn, 16, 5);
2948 bool setflags = extract32(insn, 29, 1);
2949 bool sub_op = extract32(insn, 30, 1);
2950 bool sf = extract32(insn, 31, 1);
2952 TCGv_i64 tcg_rm, tcg_rn; /* temps */
2954 TCGv_i64 tcg_result;
2957 unallocated_encoding(s);
2961 /* non-flag setting ops may use SP */
2963 tcg_rn = read_cpu_reg_sp(s, rn, sf);
2964 tcg_rd = cpu_reg_sp(s, rd);
2966 tcg_rn = read_cpu_reg(s, rn, sf);
2967 tcg_rd = cpu_reg(s, rd);
2970 tcg_rm = read_cpu_reg(s, rm, sf);
2971 ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
2973 tcg_result = tcg_temp_new_i64();
2977 tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
2979 tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
2983 gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
2985 gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
2990 tcg_gen_mov_i64(tcg_rd, tcg_result);
2992 tcg_gen_ext32u_i64(tcg_rd, tcg_result);
2995 tcg_temp_free_i64(tcg_result);
2999 * C3.5.2 Add/subtract (shifted register)
3001 * 31 30 29 28 24 23 22 21 20 16 15 10 9 5 4 0
3002 * +--+--+--+-----------+-----+--+-------+---------+------+------+
3003 * |sf|op| S| 0 1 0 1 1 |shift| 0| Rm | imm6 | Rn | Rd |
3004 * +--+--+--+-----------+-----+--+-------+---------+------+------+
3006 * sf: 0 -> 32bit, 1 -> 64bit
3007 * op: 0 -> add , 1 -> sub
3009 * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
3010 * imm6: Shift amount to apply to Rm before the add/sub
3012 static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
3014 int rd = extract32(insn, 0, 5);
3015 int rn = extract32(insn, 5, 5);
3016 int imm6 = extract32(insn, 10, 6);
3017 int rm = extract32(insn, 16, 5);
3018 int shift_type = extract32(insn, 22, 2);
3019 bool setflags = extract32(insn, 29, 1);
3020 bool sub_op = extract32(insn, 30, 1);
3021 bool sf = extract32(insn, 31, 1);
3023 TCGv_i64 tcg_rd = cpu_reg(s, rd);
3024 TCGv_i64 tcg_rn, tcg_rm;
3025 TCGv_i64 tcg_result;
3027 if ((shift_type == 3) || (!sf && (imm6 > 31))) {
3028 unallocated_encoding(s);
3032 tcg_rn = read_cpu_reg(s, rn, sf);
3033 tcg_rm = read_cpu_reg(s, rm, sf);
3035 shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
3037 tcg_result = tcg_temp_new_i64();
3041 tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
3043 tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
3047 gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
3049 gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
3054 tcg_gen_mov_i64(tcg_rd, tcg_result);
3056 tcg_gen_ext32u_i64(tcg_rd, tcg_result);
3059 tcg_temp_free_i64(tcg_result);
3062 /* C3.5.9 Data-processing (3 source)
3064 31 30 29 28 24 23 21 20 16 15 14 10 9 5 4 0
3065 +--+------+-----------+------+------+----+------+------+------+
3066 |sf| op54 | 1 1 0 1 1 | op31 | Rm | o0 | Ra | Rn | Rd |
3067 +--+------+-----------+------+------+----+------+------+------+
3070 static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
3072 int rd = extract32(insn, 0, 5);
3073 int rn = extract32(insn, 5, 5);
3074 int ra = extract32(insn, 10, 5);
3075 int rm = extract32(insn, 16, 5);
3076 int op_id = (extract32(insn, 29, 3) << 4) |
3077 (extract32(insn, 21, 3) << 1) |
3078 extract32(insn, 15, 1);
3079 bool sf = extract32(insn, 31, 1);
3080 bool is_sub = extract32(op_id, 0, 1);
3081 bool is_high = extract32(op_id, 2, 1);
3082 bool is_signed = false;
3087 /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
3089 case 0x42: /* SMADDL */
3090 case 0x43: /* SMSUBL */
3091 case 0x44: /* SMULH */
3094 case 0x0: /* MADD (32bit) */
3095 case 0x1: /* MSUB (32bit) */
3096 case 0x40: /* MADD (64bit) */
3097 case 0x41: /* MSUB (64bit) */
3098 case 0x4a: /* UMADDL */
3099 case 0x4b: /* UMSUBL */
3100 case 0x4c: /* UMULH */
3103 unallocated_encoding(s);
3108 TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */
3109 TCGv_i64 tcg_rd = cpu_reg(s, rd);
3110 TCGv_i64 tcg_rn = cpu_reg(s, rn);
3111 TCGv_i64 tcg_rm = cpu_reg(s, rm);
3114 tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
3116 tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
3119 tcg_temp_free_i64(low_bits);
3123 tcg_op1 = tcg_temp_new_i64();
3124 tcg_op2 = tcg_temp_new_i64();
3125 tcg_tmp = tcg_temp_new_i64();
3128 tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn));
3129 tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm));
3132 tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn));
3133 tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm));
3135 tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn));
3136 tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm));
3140 if (ra == 31 && !is_sub) {
3141 /* Special-case MADD with rA == XZR; it is the standard MUL alias */
3142 tcg_gen_mul_i64(cpu_reg(s, rd), tcg_op1, tcg_op2);
3144 tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2);
3146 tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
3148 tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
3153 tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd));
3156 tcg_temp_free_i64(tcg_op1);
3157 tcg_temp_free_i64(tcg_op2);
3158 tcg_temp_free_i64(tcg_tmp);
3161 /* C3.5.3 - Add/subtract (with carry)
3162 * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
3163 * +--+--+--+------------------------+------+---------+------+-----+
3164 * |sf|op| S| 1 1 0 1 0 0 0 0 | rm | opcode2 | Rn | Rd |
3165 * +--+--+--+------------------------+------+---------+------+-----+
3169 static void disas_adc_sbc(DisasContext *s, uint32_t insn)
3171 unsigned int sf, op, setflags, rm, rn, rd;
3172 TCGv_i64 tcg_y, tcg_rn, tcg_rd;
3174 if (extract32(insn, 10, 6) != 0) {
3175 unallocated_encoding(s);
3179 sf = extract32(insn, 31, 1);
3180 op = extract32(insn, 30, 1);
3181 setflags = extract32(insn, 29, 1);
3182 rm = extract32(insn, 16, 5);
3183 rn = extract32(insn, 5, 5);
3184 rd = extract32(insn, 0, 5);
3186 tcg_rd = cpu_reg(s, rd);
3187 tcg_rn = cpu_reg(s, rn);
3190 tcg_y = new_tmp_a64(s);
3191 tcg_gen_not_i64(tcg_y, cpu_reg(s, rm));
3193 tcg_y = cpu_reg(s, rm);
3197 gen_adc_CC(sf, tcg_rd, tcg_rn, tcg_y);
3199 gen_adc(sf, tcg_rd, tcg_rn, tcg_y);
3203 /* C3.5.4 - C3.5.5 Conditional compare (immediate / register)
3204 * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 12 11 10 9 5 4 3 0
3205 * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
3206 * |sf|op| S| 1 1 0 1 0 0 1 0 |imm5/rm | cond |i/r |o2| Rn |o3|nzcv |
3207 * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
3210 static void disas_cc(DisasContext *s, uint32_t insn)
3212 unsigned int sf, op, y, cond, rn, nzcv, is_imm;
3213 int label_continue = -1;
3214 TCGv_i64 tcg_tmp, tcg_y, tcg_rn;
3216 if (!extract32(insn, 29, 1)) {
3217 unallocated_encoding(s);
3220 if (insn & (1 << 10 | 1 << 4)) {
3221 unallocated_encoding(s);
3224 sf = extract32(insn, 31, 1);
3225 op = extract32(insn, 30, 1);
3226 is_imm = extract32(insn, 11, 1);
3227 y = extract32(insn, 16, 5); /* y = rm (reg) or imm5 (imm) */
3228 cond = extract32(insn, 12, 4);
3229 rn = extract32(insn, 5, 5);
3230 nzcv = extract32(insn, 0, 4);
3232 if (cond < 0x0e) { /* not always */
3233 int label_match = gen_new_label();
3234 label_continue = gen_new_label();
3235 arm_gen_test_cc(cond, label_match);
3237 tcg_tmp = tcg_temp_new_i64();
3238 tcg_gen_movi_i64(tcg_tmp, nzcv << 28);
3239 gen_set_nzcv(tcg_tmp);
3240 tcg_temp_free_i64(tcg_tmp);
3241 tcg_gen_br(label_continue);
3242 gen_set_label(label_match);
3244 /* match, or condition is always */
3246 tcg_y = new_tmp_a64(s);
3247 tcg_gen_movi_i64(tcg_y, y);
3249 tcg_y = cpu_reg(s, y);
3251 tcg_rn = cpu_reg(s, rn);
3253 tcg_tmp = tcg_temp_new_i64();
3255 gen_sub_CC(sf, tcg_tmp, tcg_rn, tcg_y);
3257 gen_add_CC(sf, tcg_tmp, tcg_rn, tcg_y);
3259 tcg_temp_free_i64(tcg_tmp);
3261 if (cond < 0x0e) { /* continue */
3262 gen_set_label(label_continue);
3266 /* C3.5.6 Conditional select
3267 * 31 30 29 28 21 20 16 15 12 11 10 9 5 4 0
3268 * +----+----+---+-----------------+------+------+-----+------+------+
3269 * | sf | op | S | 1 1 0 1 0 1 0 0 | Rm | cond | op2 | Rn | Rd |
3270 * +----+----+---+-----------------+------+------+-----+------+------+
3272 static void disas_cond_select(DisasContext *s, uint32_t insn)
3274 unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
3275 TCGv_i64 tcg_rd, tcg_src;
3277 if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
3278 /* S == 1 or op2<1> == 1 */
3279 unallocated_encoding(s);
3282 sf = extract32(insn, 31, 1);
3283 else_inv = extract32(insn, 30, 1);
3284 rm = extract32(insn, 16, 5);
3285 cond = extract32(insn, 12, 4);
3286 else_inc = extract32(insn, 10, 1);
3287 rn = extract32(insn, 5, 5);
3288 rd = extract32(insn, 0, 5);
3291 /* silly no-op write; until we use movcond we must special-case
3292 * this to avoid a dead temporary across basic blocks.
3297 tcg_rd = cpu_reg(s, rd);
3299 if (cond >= 0x0e) { /* condition "always" */
3300 tcg_src = read_cpu_reg(s, rn, sf);
3301 tcg_gen_mov_i64(tcg_rd, tcg_src);
3303 /* OPTME: we could use movcond here, at the cost of duplicating
3304 * a lot of the arm_gen_test_cc() logic.
3306 int label_match = gen_new_label();
3307 int label_continue = gen_new_label();
3309 arm_gen_test_cc(cond, label_match);
3311 tcg_src = cpu_reg(s, rm);
3313 if (else_inv && else_inc) {
3314 tcg_gen_neg_i64(tcg_rd, tcg_src);
3315 } else if (else_inv) {
3316 tcg_gen_not_i64(tcg_rd, tcg_src);
3317 } else if (else_inc) {
3318 tcg_gen_addi_i64(tcg_rd, tcg_src, 1);
3320 tcg_gen_mov_i64(tcg_rd, tcg_src);
3323 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3325 tcg_gen_br(label_continue);
3327 gen_set_label(label_match);
3328 tcg_src = read_cpu_reg(s, rn, sf);
3329 tcg_gen_mov_i64(tcg_rd, tcg_src);
3331 gen_set_label(label_continue);
3335 static void handle_clz(DisasContext *s, unsigned int sf,
3336 unsigned int rn, unsigned int rd)
3338 TCGv_i64 tcg_rd, tcg_rn;
3339 tcg_rd = cpu_reg(s, rd);
3340 tcg_rn = cpu_reg(s, rn);
3343 gen_helper_clz64(tcg_rd, tcg_rn);
3345 TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3346 tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3347 gen_helper_clz(tcg_tmp32, tcg_tmp32);
3348 tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3349 tcg_temp_free_i32(tcg_tmp32);
3353 static void handle_cls(DisasContext *s, unsigned int sf,
3354 unsigned int rn, unsigned int rd)
3356 TCGv_i64 tcg_rd, tcg_rn;
3357 tcg_rd = cpu_reg(s, rd);
3358 tcg_rn = cpu_reg(s, rn);
3361 gen_helper_cls64(tcg_rd, tcg_rn);
3363 TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3364 tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3365 gen_helper_cls32(tcg_tmp32, tcg_tmp32);
3366 tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3367 tcg_temp_free_i32(tcg_tmp32);
3371 static void handle_rbit(DisasContext *s, unsigned int sf,
3372 unsigned int rn, unsigned int rd)
3374 TCGv_i64 tcg_rd, tcg_rn;
3375 tcg_rd = cpu_reg(s, rd);
3376 tcg_rn = cpu_reg(s, rn);
3379 gen_helper_rbit64(tcg_rd, tcg_rn);
3381 TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3382 tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3383 gen_helper_rbit(tcg_tmp32, tcg_tmp32);
3384 tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3385 tcg_temp_free_i32(tcg_tmp32);
3389 /* C5.6.149 REV with sf==1, opcode==3 ("REV64") */
3390 static void handle_rev64(DisasContext *s, unsigned int sf,
3391 unsigned int rn, unsigned int rd)
3394 unallocated_encoding(s);
3397 tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
3400 /* C5.6.149 REV with sf==0, opcode==2
3401 * C5.6.151 REV32 (sf==1, opcode==2)
3403 static void handle_rev32(DisasContext *s, unsigned int sf,
3404 unsigned int rn, unsigned int rd)
3406 TCGv_i64 tcg_rd = cpu_reg(s, rd);
3409 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3410 TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3412 /* bswap32_i64 requires zero high word */
3413 tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
3414 tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
3415 tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
3416 tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
3417 tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
3419 tcg_temp_free_i64(tcg_tmp);
3421 tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
3422 tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
3426 /* C5.6.150 REV16 (opcode==1) */
3427 static void handle_rev16(DisasContext *s, unsigned int sf,
3428 unsigned int rn, unsigned int rd)
3430 TCGv_i64 tcg_rd = cpu_reg(s, rd);
3431 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3432 TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3434 tcg_gen_andi_i64(tcg_tmp, tcg_rn, 0xffff);
3435 tcg_gen_bswap16_i64(tcg_rd, tcg_tmp);
3437 tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16);
3438 tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
3439 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3440 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 16, 16);
3443 tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
3444 tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
3445 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3446 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 32, 16);
3448 tcg_gen_shri_i64(tcg_tmp, tcg_rn, 48);
3449 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3450 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 48, 16);
3453 tcg_temp_free_i64(tcg_tmp);
3456 /* C3.5.7 Data-processing (1 source)
3457 * 31 30 29 28 21 20 16 15 10 9 5 4 0
3458 * +----+---+---+-----------------+---------+--------+------+------+
3459 * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode | Rn | Rd |
3460 * +----+---+---+-----------------+---------+--------+------+------+
3462 static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
3464 unsigned int sf, opcode, rn, rd;
3466 if (extract32(insn, 29, 1) || extract32(insn, 16, 5)) {
3467 unallocated_encoding(s);
3471 sf = extract32(insn, 31, 1);
3472 opcode = extract32(insn, 10, 6);
3473 rn = extract32(insn, 5, 5);
3474 rd = extract32(insn, 0, 5);
3478 handle_rbit(s, sf, rn, rd);
3481 handle_rev16(s, sf, rn, rd);
3484 handle_rev32(s, sf, rn, rd);
3487 handle_rev64(s, sf, rn, rd);
3490 handle_clz(s, sf, rn, rd);
3493 handle_cls(s, sf, rn, rd);
3498 static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
3499 unsigned int rm, unsigned int rn, unsigned int rd)
3501 TCGv_i64 tcg_n, tcg_m, tcg_rd;
3502 tcg_rd = cpu_reg(s, rd);
3504 if (!sf && is_signed) {
3505 tcg_n = new_tmp_a64(s);
3506 tcg_m = new_tmp_a64(s);
3507 tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
3508 tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
3510 tcg_n = read_cpu_reg(s, rn, sf);
3511 tcg_m = read_cpu_reg(s, rm, sf);
3515 gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
3517 gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
3520 if (!sf) { /* zero extend final result */
3521 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3525 /* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
3526 static void handle_shift_reg(DisasContext *s,
3527 enum a64_shift_type shift_type, unsigned int sf,
3528 unsigned int rm, unsigned int rn, unsigned int rd)
3530 TCGv_i64 tcg_shift = tcg_temp_new_i64();
3531 TCGv_i64 tcg_rd = cpu_reg(s, rd);
3532 TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3534 tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
3535 shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
3536 tcg_temp_free_i64(tcg_shift);
3539 /* C3.5.8 Data-processing (2 source)
3540 * 31 30 29 28 21 20 16 15 10 9 5 4 0
3541 * +----+---+---+-----------------+------+--------+------+------+
3542 * | sf | 0 | S | 1 1 0 1 0 1 1 0 | Rm | opcode | Rn | Rd |
3543 * +----+---+---+-----------------+------+--------+------+------+
3545 static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
3547 unsigned int sf, rm, opcode, rn, rd;
3548 sf = extract32(insn, 31, 1);
3549 rm = extract32(insn, 16, 5);
3550 opcode = extract32(insn, 10, 6);
3551 rn = extract32(insn, 5, 5);
3552 rd = extract32(insn, 0, 5);
3554 if (extract32(insn, 29, 1)) {
3555 unallocated_encoding(s);
3561 handle_div(s, false, sf, rm, rn, rd);
3564 handle_div(s, true, sf, rm, rn, rd);
3567 handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
3570 handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
3573 handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
3576 handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
3585 case 23: /* CRC32 */
3586 unsupported_encoding(s, insn);
3589 unallocated_encoding(s);
3594 /* C3.5 Data processing - register */
3595 static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
3597 switch (extract32(insn, 24, 5)) {
3598 case 0x0a: /* Logical (shifted register) */
3599 disas_logic_reg(s, insn);
3601 case 0x0b: /* Add/subtract */
3602 if (insn & (1 << 21)) { /* (extended register) */
3603 disas_add_sub_ext_reg(s, insn);
3605 disas_add_sub_reg(s, insn);
3608 case 0x1b: /* Data-processing (3 source) */
3609 disas_data_proc_3src(s, insn);
3612 switch (extract32(insn, 21, 3)) {
3613 case 0x0: /* Add/subtract (with carry) */
3614 disas_adc_sbc(s, insn);
3616 case 0x2: /* Conditional compare */
3617 disas_cc(s, insn); /* both imm and reg forms */
3619 case 0x4: /* Conditional select */
3620 disas_cond_select(s, insn);
3622 case 0x6: /* Data-processing */
3623 if (insn & (1 << 30)) { /* (1 source) */
3624 disas_data_proc_1src(s, insn);
3625 } else { /* (2 source) */
3626 disas_data_proc_2src(s, insn);
3630 unallocated_encoding(s);
3635 unallocated_encoding(s);
3640 static void handle_fp_compare(DisasContext *s, bool is_double,
3641 unsigned int rn, unsigned int rm,
3642 bool cmp_with_zero, bool signal_all_nans)
3644 TCGv_i64 tcg_flags = tcg_temp_new_i64();
3645 TCGv_ptr fpst = get_fpstatus_ptr();
3648 TCGv_i64 tcg_vn, tcg_vm;
3650 tcg_vn = read_fp_dreg(s, rn);
3651 if (cmp_with_zero) {
3652 tcg_vm = tcg_const_i64(0);
3654 tcg_vm = read_fp_dreg(s, rm);
3656 if (signal_all_nans) {
3657 gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3659 gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3661 tcg_temp_free_i64(tcg_vn);
3662 tcg_temp_free_i64(tcg_vm);
3664 TCGv_i32 tcg_vn, tcg_vm;
3666 tcg_vn = read_fp_sreg(s, rn);
3667 if (cmp_with_zero) {
3668 tcg_vm = tcg_const_i32(0);
3670 tcg_vm = read_fp_sreg(s, rm);
3672 if (signal_all_nans) {
3673 gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3675 gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3677 tcg_temp_free_i32(tcg_vn);
3678 tcg_temp_free_i32(tcg_vm);
3681 tcg_temp_free_ptr(fpst);
3683 gen_set_nzcv(tcg_flags);
3685 tcg_temp_free_i64(tcg_flags);
3688 /* C3.6.22 Floating point compare
3689 * 31 30 29 28 24 23 22 21 20 16 15 14 13 10 9 5 4 0
3690 * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
3691 * | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | op | 1 0 0 0 | Rn | op2 |
3692 * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
3694 static void disas_fp_compare(DisasContext *s, uint32_t insn)
3696 unsigned int mos, type, rm, op, rn, opc, op2r;
3698 mos = extract32(insn, 29, 3);
3699 type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3700 rm = extract32(insn, 16, 5);
3701 op = extract32(insn, 14, 2);
3702 rn = extract32(insn, 5, 5);
3703 opc = extract32(insn, 3, 2);
3704 op2r = extract32(insn, 0, 3);
3706 if (mos || op || op2r || type > 1) {
3707 unallocated_encoding(s);
3711 handle_fp_compare(s, type, rn, rm, opc & 1, opc & 2);
3714 /* C3.6.23 Floating point conditional compare
3715 * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 3 0
3716 * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
3717 * | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | cond | 0 1 | Rn | op | nzcv |
3718 * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
3720 static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
3722 unsigned int mos, type, rm, cond, rn, op, nzcv;
3724 int label_continue = -1;
3726 mos = extract32(insn, 29, 3);
3727 type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3728 rm = extract32(insn, 16, 5);
3729 cond = extract32(insn, 12, 4);
3730 rn = extract32(insn, 5, 5);
3731 op = extract32(insn, 4, 1);
3732 nzcv = extract32(insn, 0, 4);
3734 if (mos || type > 1) {
3735 unallocated_encoding(s);
3739 if (cond < 0x0e) { /* not always */
3740 int label_match = gen_new_label();
3741 label_continue = gen_new_label();
3742 arm_gen_test_cc(cond, label_match);
3744 tcg_flags = tcg_const_i64(nzcv << 28);
3745 gen_set_nzcv(tcg_flags);
3746 tcg_temp_free_i64(tcg_flags);
3747 tcg_gen_br(label_continue);
3748 gen_set_label(label_match);
3751 handle_fp_compare(s, type, rn, rm, false, op);
3754 gen_set_label(label_continue);
3758 /* copy src FP register to dst FP register; type specifies single or double */
3759 static void gen_mov_fp2fp(DisasContext *s, int type, int dst, int src)
3762 TCGv_i64 v = read_fp_dreg(s, src);
3763 write_fp_dreg(s, dst, v);
3764 tcg_temp_free_i64(v);
3766 TCGv_i32 v = read_fp_sreg(s, src);
3767 write_fp_sreg(s, dst, v);
3768 tcg_temp_free_i32(v);
3772 /* C3.6.24 Floating point conditional select
3773 * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
3774 * +---+---+---+-----------+------+---+------+------+-----+------+------+
3775 * | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | cond | 1 1 | Rn | Rd |
3776 * +---+---+---+-----------+------+---+------+------+-----+------+------+
3778 static void disas_fp_csel(DisasContext *s, uint32_t insn)
3780 unsigned int mos, type, rm, cond, rn, rd;
3781 int label_continue = -1;
3783 mos = extract32(insn, 29, 3);
3784 type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3785 rm = extract32(insn, 16, 5);
3786 cond = extract32(insn, 12, 4);
3787 rn = extract32(insn, 5, 5);
3788 rd = extract32(insn, 0, 5);
3790 if (mos || type > 1) {
3791 unallocated_encoding(s);
3795 if (cond < 0x0e) { /* not always */
3796 int label_match = gen_new_label();
3797 label_continue = gen_new_label();
3798 arm_gen_test_cc(cond, label_match);
3800 gen_mov_fp2fp(s, type, rd, rm);
3801 tcg_gen_br(label_continue);
3802 gen_set_label(label_match);
3805 gen_mov_fp2fp(s, type, rd, rn);
3807 if (cond < 0x0e) { /* continue */
3808 gen_set_label(label_continue);
3812 /* C3.6.25 Floating-point data-processing (1 source) - single precision */
3813 static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
3819 fpst = get_fpstatus_ptr();
3820 tcg_op = read_fp_sreg(s, rn);
3821 tcg_res = tcg_temp_new_i32();
3824 case 0x0: /* FMOV */
3825 tcg_gen_mov_i32(tcg_res, tcg_op);
3827 case 0x1: /* FABS */
3828 gen_helper_vfp_abss(tcg_res, tcg_op);
3830 case 0x2: /* FNEG */
3831 gen_helper_vfp_negs(tcg_res, tcg_op);
3833 case 0x3: /* FSQRT */
3834 gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
3836 case 0x8: /* FRINTN */
3837 case 0x9: /* FRINTP */
3838 case 0xa: /* FRINTM */
3839 case 0xb: /* FRINTZ */
3840 case 0xc: /* FRINTA */
3842 TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
3844 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3845 gen_helper_rints(tcg_res, tcg_op, fpst);
3847 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3848 tcg_temp_free_i32(tcg_rmode);
3851 case 0xe: /* FRINTX */
3852 gen_helper_rints_exact(tcg_res, tcg_op, fpst);
3854 case 0xf: /* FRINTI */
3855 gen_helper_rints(tcg_res, tcg_op, fpst);
3861 write_fp_sreg(s, rd, tcg_res);
3863 tcg_temp_free_ptr(fpst);
3864 tcg_temp_free_i32(tcg_op);
3865 tcg_temp_free_i32(tcg_res);
3868 /* C3.6.25 Floating-point data-processing (1 source) - double precision */
3869 static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
3875 fpst = get_fpstatus_ptr();
3876 tcg_op = read_fp_dreg(s, rn);
3877 tcg_res = tcg_temp_new_i64();
3880 case 0x0: /* FMOV */
3881 tcg_gen_mov_i64(tcg_res, tcg_op);
3883 case 0x1: /* FABS */
3884 gen_helper_vfp_absd(tcg_res, tcg_op);
3886 case 0x2: /* FNEG */
3887 gen_helper_vfp_negd(tcg_res, tcg_op);
3889 case 0x3: /* FSQRT */
3890 gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
3892 case 0x8: /* FRINTN */
3893 case 0x9: /* FRINTP */
3894 case 0xa: /* FRINTM */
3895 case 0xb: /* FRINTZ */
3896 case 0xc: /* FRINTA */
3898 TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
3900 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3901 gen_helper_rintd(tcg_res, tcg_op, fpst);
3903 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3904 tcg_temp_free_i32(tcg_rmode);
3907 case 0xe: /* FRINTX */
3908 gen_helper_rintd_exact(tcg_res, tcg_op, fpst);
3910 case 0xf: /* FRINTI */
3911 gen_helper_rintd(tcg_res, tcg_op, fpst);
3917 write_fp_dreg(s, rd, tcg_res);
3919 tcg_temp_free_ptr(fpst);
3920 tcg_temp_free_i64(tcg_op);
3921 tcg_temp_free_i64(tcg_res);
3924 static void handle_fp_fcvt(DisasContext *s, int opcode,
3925 int rd, int rn, int dtype, int ntype)
3930 TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
3932 /* Single to double */
3933 TCGv_i64 tcg_rd = tcg_temp_new_i64();
3934 gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, cpu_env);
3935 write_fp_dreg(s, rd, tcg_rd);
3936 tcg_temp_free_i64(tcg_rd);
3938 /* Single to half */
3939 TCGv_i32 tcg_rd = tcg_temp_new_i32();
3940 gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, cpu_env);
3941 /* write_fp_sreg is OK here because top half of tcg_rd is zero */
3942 write_fp_sreg(s, rd, tcg_rd);
3943 tcg_temp_free_i32(tcg_rd);
3945 tcg_temp_free_i32(tcg_rn);
3950 TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
3951 TCGv_i32 tcg_rd = tcg_temp_new_i32();
3953 /* Double to single */
3954 gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
3956 /* Double to half */
3957 gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, cpu_env);
3958 /* write_fp_sreg is OK here because top half of tcg_rd is zero */
3960 write_fp_sreg(s, rd, tcg_rd);
3961 tcg_temp_free_i32(tcg_rd);
3962 tcg_temp_free_i64(tcg_rn);
3967 TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
3968 tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
3970 /* Half to single */
3971 TCGv_i32 tcg_rd = tcg_temp_new_i32();
3972 gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, cpu_env);
3973 write_fp_sreg(s, rd, tcg_rd);
3974 tcg_temp_free_i32(tcg_rd);
3976 /* Half to double */
3977 TCGv_i64 tcg_rd = tcg_temp_new_i64();
3978 gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, cpu_env);
3979 write_fp_dreg(s, rd, tcg_rd);
3980 tcg_temp_free_i64(tcg_rd);
3982 tcg_temp_free_i32(tcg_rn);
3990 /* C3.6.25 Floating point data-processing (1 source)
3991 * 31 30 29 28 24 23 22 21 20 15 14 10 9 5 4 0
3992 * +---+---+---+-----------+------+---+--------+-----------+------+------+
3993 * | M | 0 | S | 1 1 1 1 0 | type | 1 | opcode | 1 0 0 0 0 | Rn | Rd |
3994 * +---+---+---+-----------+------+---+--------+-----------+------+------+
3996 static void disas_fp_1src(DisasContext *s, uint32_t insn)
3998 int type = extract32(insn, 22, 2);
3999 int opcode = extract32(insn, 15, 6);
4000 int rn = extract32(insn, 5, 5);
4001 int rd = extract32(insn, 0, 5);
4004 case 0x4: case 0x5: case 0x7:
4006 /* FCVT between half, single and double precision */
4007 int dtype = extract32(opcode, 0, 2);
4008 if (type == 2 || dtype == type) {
4009 unallocated_encoding(s);
4012 handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
4018 /* 32-to-32 and 64-to-64 ops */
4021 handle_fp_1src_single(s, opcode, rd, rn);
4024 handle_fp_1src_double(s, opcode, rd, rn);
4027 unallocated_encoding(s);
4031 unallocated_encoding(s);
4036 /* C3.6.26 Floating-point data-processing (2 source) - single precision */
4037 static void handle_fp_2src_single(DisasContext *s, int opcode,
4038 int rd, int rn, int rm)
4045 tcg_res = tcg_temp_new_i32();
4046 fpst = get_fpstatus_ptr();
4047 tcg_op1 = read_fp_sreg(s, rn);
4048 tcg_op2 = read_fp_sreg(s, rm);
4051 case 0x0: /* FMUL */
4052 gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
4054 case 0x1: /* FDIV */
4055 gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
4057 case 0x2: /* FADD */
4058 gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
4060 case 0x3: /* FSUB */
4061 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
4063 case 0x4: /* FMAX */
4064 gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
4066 case 0x5: /* FMIN */
4067 gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
4069 case 0x6: /* FMAXNM */
4070 gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
4072 case 0x7: /* FMINNM */
4073 gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
4075 case 0x8: /* FNMUL */
4076 gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
4077 gen_helper_vfp_negs(tcg_res, tcg_res);
4081 write_fp_sreg(s, rd, tcg_res);
4083 tcg_temp_free_ptr(fpst);
4084 tcg_temp_free_i32(tcg_op1);
4085 tcg_temp_free_i32(tcg_op2);
4086 tcg_temp_free_i32(tcg_res);
4089 /* C3.6.26 Floating-point data-processing (2 source) - double precision */
4090 static void handle_fp_2src_double(DisasContext *s, int opcode,
4091 int rd, int rn, int rm)
4098 tcg_res = tcg_temp_new_i64();
4099 fpst = get_fpstatus_ptr();
4100 tcg_op1 = read_fp_dreg(s, rn);
4101 tcg_op2 = read_fp_dreg(s, rm);
4104 case 0x0: /* FMUL */
4105 gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
4107 case 0x1: /* FDIV */
4108 gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
4110 case 0x2: /* FADD */
4111 gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
4113 case 0x3: /* FSUB */
4114 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
4116 case 0x4: /* FMAX */
4117 gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
4119 case 0x5: /* FMIN */
4120 gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
4122 case 0x6: /* FMAXNM */
4123 gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
4125 case 0x7: /* FMINNM */
4126 gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
4128 case 0x8: /* FNMUL */
4129 gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
4130 gen_helper_vfp_negd(tcg_res, tcg_res);
4134 write_fp_dreg(s, rd, tcg_res);
4136 tcg_temp_free_ptr(fpst);
4137 tcg_temp_free_i64(tcg_op1);
4138 tcg_temp_free_i64(tcg_op2);
4139 tcg_temp_free_i64(tcg_res);
4142 /* C3.6.26 Floating point data-processing (2 source)
4143 * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
4144 * +---+---+---+-----------+------+---+------+--------+-----+------+------+
4145 * | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | opcode | 1 0 | Rn | Rd |
4146 * +---+---+---+-----------+------+---+------+--------+-----+------+------+
4148 static void disas_fp_2src(DisasContext *s, uint32_t insn)
4150 int type = extract32(insn, 22, 2);
4151 int rd = extract32(insn, 0, 5);
4152 int rn = extract32(insn, 5, 5);
4153 int rm = extract32(insn, 16, 5);
4154 int opcode = extract32(insn, 12, 4);
4157 unallocated_encoding(s);
4163 handle_fp_2src_single(s, opcode, rd, rn, rm);
4166 handle_fp_2src_double(s, opcode, rd, rn, rm);
4169 unallocated_encoding(s);
4173 /* C3.6.27 Floating-point data-processing (3 source) - single precision */
4174 static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
4175 int rd, int rn, int rm, int ra)
4177 TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
4178 TCGv_i32 tcg_res = tcg_temp_new_i32();
4179 TCGv_ptr fpst = get_fpstatus_ptr();
4181 tcg_op1 = read_fp_sreg(s, rn);
4182 tcg_op2 = read_fp_sreg(s, rm);
4183 tcg_op3 = read_fp_sreg(s, ra);
4185 /* These are fused multiply-add, and must be done as one
4186 * floating point operation with no rounding between the
4187 * multiplication and addition steps.
4188 * NB that doing the negations here as separate steps is
4189 * correct : an input NaN should come out with its sign bit
4190 * flipped if it is a negated-input.
4193 gen_helper_vfp_negs(tcg_op3, tcg_op3);
4197 gen_helper_vfp_negs(tcg_op1, tcg_op1);
4200 gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
4202 write_fp_sreg(s, rd, tcg_res);
4204 tcg_temp_free_ptr(fpst);
4205 tcg_temp_free_i32(tcg_op1);
4206 tcg_temp_free_i32(tcg_op2);
4207 tcg_temp_free_i32(tcg_op3);
4208 tcg_temp_free_i32(tcg_res);
4211 /* C3.6.27 Floating-point data-processing (3 source) - double precision */
4212 static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
4213 int rd, int rn, int rm, int ra)
4215 TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
4216 TCGv_i64 tcg_res = tcg_temp_new_i64();
4217 TCGv_ptr fpst = get_fpstatus_ptr();
4219 tcg_op1 = read_fp_dreg(s, rn);
4220 tcg_op2 = read_fp_dreg(s, rm);
4221 tcg_op3 = read_fp_dreg(s, ra);
4223 /* These are fused multiply-add, and must be done as one
4224 * floating point operation with no rounding between the
4225 * multiplication and addition steps.
4226 * NB that doing the negations here as separate steps is
4227 * correct : an input NaN should come out with its sign bit
4228 * flipped if it is a negated-input.
4231 gen_helper_vfp_negd(tcg_op3, tcg_op3);
4235 gen_helper_vfp_negd(tcg_op1, tcg_op1);
4238 gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
4240 write_fp_dreg(s, rd, tcg_res);
4242 tcg_temp_free_ptr(fpst);
4243 tcg_temp_free_i64(tcg_op1);
4244 tcg_temp_free_i64(tcg_op2);
4245 tcg_temp_free_i64(tcg_op3);
4246 tcg_temp_free_i64(tcg_res);
4249 /* C3.6.27 Floating point data-processing (3 source)
4250 * 31 30 29 28 24 23 22 21 20 16 15 14 10 9 5 4 0
4251 * +---+---+---+-----------+------+----+------+----+------+------+------+
4252 * | M | 0 | S | 1 1 1 1 1 | type | o1 | Rm | o0 | Ra | Rn | Rd |
4253 * +---+---+---+-----------+------+----+------+----+------+------+------+
4255 static void disas_fp_3src(DisasContext *s, uint32_t insn)
4257 int type = extract32(insn, 22, 2);
4258 int rd = extract32(insn, 0, 5);
4259 int rn = extract32(insn, 5, 5);
4260 int ra = extract32(insn, 10, 5);
4261 int rm = extract32(insn, 16, 5);
4262 bool o0 = extract32(insn, 15, 1);
4263 bool o1 = extract32(insn, 21, 1);
4267 handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
4270 handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
4273 unallocated_encoding(s);
4277 /* C3.6.28 Floating point immediate
4278 * 31 30 29 28 24 23 22 21 20 13 12 10 9 5 4 0
4279 * +---+---+---+-----------+------+---+------------+-------+------+------+
4280 * | M | 0 | S | 1 1 1 1 0 | type | 1 | imm8 | 1 0 0 | imm5 | Rd |
4281 * +---+---+---+-----------+------+---+------------+-------+------+------+
4283 static void disas_fp_imm(DisasContext *s, uint32_t insn)
4285 int rd = extract32(insn, 0, 5);
4286 int imm8 = extract32(insn, 13, 8);
4287 int is_double = extract32(insn, 22, 2);
4291 if (is_double > 1) {
4292 unallocated_encoding(s);
4296 /* The imm8 encodes the sign bit, enough bits to represent
4297 * an exponent in the range 01....1xx to 10....0xx,
4298 * and the most significant 4 bits of the mantissa; see
4299 * VFPExpandImm() in the v8 ARM ARM.
4302 imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
4303 (extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
4304 extract32(imm8, 0, 6);
4307 imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
4308 (extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
4309 (extract32(imm8, 0, 6) << 3);
4313 tcg_res = tcg_const_i64(imm);
4314 write_fp_dreg(s, rd, tcg_res);
4315 tcg_temp_free_i64(tcg_res);
4318 /* Handle floating point <=> fixed point conversions. Note that we can
4319 * also deal with fp <=> integer conversions as a special case (scale == 64)
4320 * OPTME: consider handling that special case specially or at least skipping
4321 * the call to scalbn in the helpers for zero shifts.
4323 static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
4324 bool itof, int rmode, int scale, int sf, int type)
4326 bool is_signed = !(opcode & 1);
4327 bool is_double = type;
4328 TCGv_ptr tcg_fpstatus;
4331 tcg_fpstatus = get_fpstatus_ptr();
4333 tcg_shift = tcg_const_i32(64 - scale);
4336 TCGv_i64 tcg_int = cpu_reg(s, rn);
4338 TCGv_i64 tcg_extend = new_tmp_a64(s);
4341 tcg_gen_ext32s_i64(tcg_extend, tcg_int);
4343 tcg_gen_ext32u_i64(tcg_extend, tcg_int);
4346 tcg_int = tcg_extend;
4350 TCGv_i64 tcg_double = tcg_temp_new_i64();
4352 gen_helper_vfp_sqtod(tcg_double, tcg_int,
4353 tcg_shift, tcg_fpstatus);
4355 gen_helper_vfp_uqtod(tcg_double, tcg_int,
4356 tcg_shift, tcg_fpstatus);
4358 write_fp_dreg(s, rd, tcg_double);
4359 tcg_temp_free_i64(tcg_double);
4361 TCGv_i32 tcg_single = tcg_temp_new_i32();
4363 gen_helper_vfp_sqtos(tcg_single, tcg_int,
4364 tcg_shift, tcg_fpstatus);
4366 gen_helper_vfp_uqtos(tcg_single, tcg_int,
4367 tcg_shift, tcg_fpstatus);
4369 write_fp_sreg(s, rd, tcg_single);
4370 tcg_temp_free_i32(tcg_single);
4373 TCGv_i64 tcg_int = cpu_reg(s, rd);
4376 if (extract32(opcode, 2, 1)) {
4377 /* There are too many rounding modes to all fit into rmode,
4378 * so FCVTA[US] is a special case.
4380 rmode = FPROUNDING_TIEAWAY;
4383 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
4385 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4388 TCGv_i64 tcg_double = read_fp_dreg(s, rn);
4391 gen_helper_vfp_tosld(tcg_int, tcg_double,
4392 tcg_shift, tcg_fpstatus);
4394 gen_helper_vfp_tosqd(tcg_int, tcg_double,
4395 tcg_shift, tcg_fpstatus);
4399 gen_helper_vfp_tould(tcg_int, tcg_double,
4400 tcg_shift, tcg_fpstatus);
4402 gen_helper_vfp_touqd(tcg_int, tcg_double,
4403 tcg_shift, tcg_fpstatus);
4406 tcg_temp_free_i64(tcg_double);
4408 TCGv_i32 tcg_single = read_fp_sreg(s, rn);
4411 gen_helper_vfp_tosqs(tcg_int, tcg_single,
4412 tcg_shift, tcg_fpstatus);
4414 gen_helper_vfp_touqs(tcg_int, tcg_single,
4415 tcg_shift, tcg_fpstatus);
4418 TCGv_i32 tcg_dest = tcg_temp_new_i32();
4420 gen_helper_vfp_tosls(tcg_dest, tcg_single,
4421 tcg_shift, tcg_fpstatus);
4423 gen_helper_vfp_touls(tcg_dest, tcg_single,
4424 tcg_shift, tcg_fpstatus);
4426 tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
4427 tcg_temp_free_i32(tcg_dest);
4429 tcg_temp_free_i32(tcg_single);
4432 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4433 tcg_temp_free_i32(tcg_rmode);
4436 tcg_gen_ext32u_i64(tcg_int, tcg_int);
4440 tcg_temp_free_ptr(tcg_fpstatus);
4441 tcg_temp_free_i32(tcg_shift);
4444 /* C3.6.29 Floating point <-> fixed point conversions
4445 * 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
4446 * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
4447 * | sf | 0 | S | 1 1 1 1 0 | type | 0 | rmode | opcode | scale | Rn | Rd |
4448 * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
4450 static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
4452 int rd = extract32(insn, 0, 5);
4453 int rn = extract32(insn, 5, 5);
4454 int scale = extract32(insn, 10, 6);
4455 int opcode = extract32(insn, 16, 3);
4456 int rmode = extract32(insn, 19, 2);
4457 int type = extract32(insn, 22, 2);
4458 bool sbit = extract32(insn, 29, 1);
4459 bool sf = extract32(insn, 31, 1);
4462 if (sbit || (type > 1)
4463 || (!sf && scale < 32)) {
4464 unallocated_encoding(s);
4468 switch ((rmode << 3) | opcode) {
4469 case 0x2: /* SCVTF */
4470 case 0x3: /* UCVTF */
4473 case 0x18: /* FCVTZS */
4474 case 0x19: /* FCVTZU */
4478 unallocated_encoding(s);
4482 handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
4485 static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
4487 /* FMOV: gpr to or from float, double, or top half of quad fp reg,
4488 * without conversion.
4492 TCGv_i64 tcg_rn = cpu_reg(s, rn);
4498 TCGv_i64 tmp = tcg_temp_new_i64();
4499 tcg_gen_ext32u_i64(tmp, tcg_rn);
4500 tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(rd, MO_64));
4501 tcg_gen_movi_i64(tmp, 0);
4502 tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
4503 tcg_temp_free_i64(tmp);
4509 TCGv_i64 tmp = tcg_const_i64(0);
4510 tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(rd, MO_64));
4511 tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
4512 tcg_temp_free_i64(tmp);
4516 /* 64 bit to top half. */
4517 tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(rd));
4521 TCGv_i64 tcg_rd = cpu_reg(s, rd);
4526 tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_32));
4530 tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_64));
4533 /* 64 bits from top half */
4534 tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(rn));
4540 /* C3.6.30 Floating point <-> integer conversions
4541 * 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
4542 * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
4543 * | sf | 0 | S | 1 1 1 1 0 | type | 1 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
4544 * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
4546 static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
4548 int rd = extract32(insn, 0, 5);
4549 int rn = extract32(insn, 5, 5);
4550 int opcode = extract32(insn, 16, 3);
4551 int rmode = extract32(insn, 19, 2);
4552 int type = extract32(insn, 22, 2);
4553 bool sbit = extract32(insn, 29, 1);
4554 bool sf = extract32(insn, 31, 1);
4557 unallocated_encoding(s);
4563 bool itof = opcode & 1;
4566 unallocated_encoding(s);
4570 switch (sf << 3 | type << 1 | rmode) {
4571 case 0x0: /* 32 bit */
4572 case 0xa: /* 64 bit */
4573 case 0xd: /* 64 bit to top half of quad */
4576 /* all other sf/type/rmode combinations are invalid */
4577 unallocated_encoding(s);
4581 handle_fmov(s, rd, rn, type, itof);
4583 /* actual FP conversions */
4584 bool itof = extract32(opcode, 1, 1);
4586 if (type > 1 || (rmode != 0 && opcode > 1)) {
4587 unallocated_encoding(s);
4591 handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
4595 /* FP-specific subcases of table C3-6 (SIMD and FP data processing)
4596 * 31 30 29 28 25 24 0
4597 * +---+---+---+---------+-----------------------------+
4598 * | | 0 | | 1 1 1 1 | |
4599 * +---+---+---+---------+-----------------------------+
4601 static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
4603 if (extract32(insn, 24, 1)) {
4604 /* Floating point data-processing (3 source) */
4605 disas_fp_3src(s, insn);
4606 } else if (extract32(insn, 21, 1) == 0) {
4607 /* Floating point to fixed point conversions */
4608 disas_fp_fixed_conv(s, insn);
4610 switch (extract32(insn, 10, 2)) {
4612 /* Floating point conditional compare */
4613 disas_fp_ccomp(s, insn);
4616 /* Floating point data-processing (2 source) */
4617 disas_fp_2src(s, insn);
4620 /* Floating point conditional select */
4621 disas_fp_csel(s, insn);
4624 switch (ctz32(extract32(insn, 12, 4))) {
4625 case 0: /* [15:12] == xxx1 */
4626 /* Floating point immediate */
4627 disas_fp_imm(s, insn);
4629 case 1: /* [15:12] == xx10 */
4630 /* Floating point compare */
4631 disas_fp_compare(s, insn);
4633 case 2: /* [15:12] == x100 */
4634 /* Floating point data-processing (1 source) */
4635 disas_fp_1src(s, insn);
4637 case 3: /* [15:12] == 1000 */
4638 unallocated_encoding(s);
4640 default: /* [15:12] == 0000 */
4641 /* Floating point <-> integer conversions */
4642 disas_fp_int_conv(s, insn);
4650 static void do_ext64(DisasContext *s, TCGv_i64 tcg_left, TCGv_i64 tcg_right,
4653 /* Extract 64 bits from the middle of two concatenated 64 bit
4654 * vector register slices left:right. The extracted bits start
4655 * at 'pos' bits into the right (least significant) side.
4656 * We return the result in tcg_right, and guarantee not to
4659 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4660 assert(pos > 0 && pos < 64);
4662 tcg_gen_shri_i64(tcg_right, tcg_right, pos);
4663 tcg_gen_shli_i64(tcg_tmp, tcg_left, 64 - pos);
4664 tcg_gen_or_i64(tcg_right, tcg_right, tcg_tmp);
4666 tcg_temp_free_i64(tcg_tmp);
4670 * 31 30 29 24 23 22 21 20 16 15 14 11 10 9 5 4 0
4671 * +---+---+-------------+-----+---+------+---+------+---+------+------+
4672 * | 0 | Q | 1 0 1 1 1 0 | op2 | 0 | Rm | 0 | imm4 | 0 | Rn | Rd |
4673 * +---+---+-------------+-----+---+------+---+------+---+------+------+
4675 static void disas_simd_ext(DisasContext *s, uint32_t insn)
4677 int is_q = extract32(insn, 30, 1);
4678 int op2 = extract32(insn, 22, 2);
4679 int imm4 = extract32(insn, 11, 4);
4680 int rm = extract32(insn, 16, 5);
4681 int rn = extract32(insn, 5, 5);
4682 int rd = extract32(insn, 0, 5);
4683 int pos = imm4 << 3;
4684 TCGv_i64 tcg_resl, tcg_resh;
4686 if (op2 != 0 || (!is_q && extract32(imm4, 3, 1))) {
4687 unallocated_encoding(s);
4691 tcg_resh = tcg_temp_new_i64();
4692 tcg_resl = tcg_temp_new_i64();
4694 /* Vd gets bits starting at pos bits into Vm:Vn. This is
4695 * either extracting 128 bits from a 128:128 concatenation, or
4696 * extracting 64 bits from a 64:64 concatenation.
4699 read_vec_element(s, tcg_resl, rn, 0, MO_64);
4701 read_vec_element(s, tcg_resh, rm, 0, MO_64);
4702 do_ext64(s, tcg_resh, tcg_resl, pos);
4704 tcg_gen_movi_i64(tcg_resh, 0);
4711 EltPosns eltposns[] = { {rn, 0}, {rn, 1}, {rm, 0}, {rm, 1} };
4712 EltPosns *elt = eltposns;
4719 read_vec_element(s, tcg_resl, elt->reg, elt->elt, MO_64);
4721 read_vec_element(s, tcg_resh, elt->reg, elt->elt, MO_64);
4724 do_ext64(s, tcg_resh, tcg_resl, pos);
4725 tcg_hh = tcg_temp_new_i64();
4726 read_vec_element(s, tcg_hh, elt->reg, elt->elt, MO_64);
4727 do_ext64(s, tcg_hh, tcg_resh, pos);
4728 tcg_temp_free_i64(tcg_hh);
4732 write_vec_element(s, tcg_resl, rd, 0, MO_64);
4733 tcg_temp_free_i64(tcg_resl);
4734 write_vec_element(s, tcg_resh, rd, 1, MO_64);
4735 tcg_temp_free_i64(tcg_resh);
4739 * 31 30 29 24 23 22 21 20 16 15 14 13 12 11 10 9 5 4 0
4740 * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
4741 * | 0 | Q | 0 0 1 1 1 0 | op2 | 0 | Rm | 0 | len | op | 0 0 | Rn | Rd |
4742 * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
4744 static void disas_simd_tb(DisasContext *s, uint32_t insn)
4746 int op2 = extract32(insn, 22, 2);
4747 int is_q = extract32(insn, 30, 1);
4748 int rm = extract32(insn, 16, 5);
4749 int rn = extract32(insn, 5, 5);
4750 int rd = extract32(insn, 0, 5);
4751 int is_tblx = extract32(insn, 12, 1);
4752 int len = extract32(insn, 13, 2);
4753 TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
4754 TCGv_i32 tcg_regno, tcg_numregs;
4757 unallocated_encoding(s);
4761 /* This does a table lookup: for every byte element in the input
4762 * we index into a table formed from up to four vector registers,
4763 * and then the output is the result of the lookups. Our helper
4764 * function does the lookup operation for a single 64 bit part of
4767 tcg_resl = tcg_temp_new_i64();
4768 tcg_resh = tcg_temp_new_i64();
4771 read_vec_element(s, tcg_resl, rd, 0, MO_64);
4773 tcg_gen_movi_i64(tcg_resl, 0);
4775 if (is_tblx && is_q) {
4776 read_vec_element(s, tcg_resh, rd, 1, MO_64);
4778 tcg_gen_movi_i64(tcg_resh, 0);
4781 tcg_idx = tcg_temp_new_i64();
4782 tcg_regno = tcg_const_i32(rn);
4783 tcg_numregs = tcg_const_i32(len + 1);
4784 read_vec_element(s, tcg_idx, rm, 0, MO_64);
4785 gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
4786 tcg_regno, tcg_numregs);
4788 read_vec_element(s, tcg_idx, rm, 1, MO_64);
4789 gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
4790 tcg_regno, tcg_numregs);
4792 tcg_temp_free_i64(tcg_idx);
4793 tcg_temp_free_i32(tcg_regno);
4794 tcg_temp_free_i32(tcg_numregs);
4796 write_vec_element(s, tcg_resl, rd, 0, MO_64);
4797 tcg_temp_free_i64(tcg_resl);
4798 write_vec_element(s, tcg_resh, rd, 1, MO_64);
4799 tcg_temp_free_i64(tcg_resh);
4802 /* C3.6.3 ZIP/UZP/TRN
4803 * 31 30 29 24 23 22 21 20 16 15 14 12 11 10 9 5 4 0
4804 * +---+---+-------------+------+---+------+---+------------------+------+
4805 * | 0 | Q | 0 0 1 1 1 0 | size | 0 | Rm | 0 | opc | 1 0 | Rn | Rd |
4806 * +---+---+-------------+------+---+------+---+------------------+------+
4808 static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
4810 int rd = extract32(insn, 0, 5);
4811 int rn = extract32(insn, 5, 5);
4812 int rm = extract32(insn, 16, 5);
4813 int size = extract32(insn, 22, 2);
4814 /* opc field bits [1:0] indicate ZIP/UZP/TRN;
4815 * bit 2 indicates 1 vs 2 variant of the insn.
4817 int opcode = extract32(insn, 12, 2);
4818 bool part = extract32(insn, 14, 1);
4819 bool is_q = extract32(insn, 30, 1);
4820 int esize = 8 << size;
4822 int datasize = is_q ? 128 : 64;
4823 int elements = datasize / esize;
4824 TCGv_i64 tcg_res, tcg_resl, tcg_resh;
4826 if (opcode == 0 || (size == 3 && !is_q)) {
4827 unallocated_encoding(s);
4831 tcg_resl = tcg_const_i64(0);
4832 tcg_resh = tcg_const_i64(0);
4833 tcg_res = tcg_temp_new_i64();
4835 for (i = 0; i < elements; i++) {
4837 case 1: /* UZP1/2 */
4839 int midpoint = elements / 2;
4841 read_vec_element(s, tcg_res, rn, 2 * i + part, size);
4843 read_vec_element(s, tcg_res, rm,
4844 2 * (i - midpoint) + part, size);
4848 case 2: /* TRN1/2 */
4850 read_vec_element(s, tcg_res, rm, (i & ~1) + part, size);
4852 read_vec_element(s, tcg_res, rn, (i & ~1) + part, size);
4855 case 3: /* ZIP1/2 */
4857 int base = part * elements / 2;
4859 read_vec_element(s, tcg_res, rm, base + (i >> 1), size);
4861 read_vec_element(s, tcg_res, rn, base + (i >> 1), size);
4866 g_assert_not_reached();
4871 tcg_gen_shli_i64(tcg_res, tcg_res, ofs);
4872 tcg_gen_or_i64(tcg_resl, tcg_resl, tcg_res);
4874 tcg_gen_shli_i64(tcg_res, tcg_res, ofs - 64);
4875 tcg_gen_or_i64(tcg_resh, tcg_resh, tcg_res);
4879 tcg_temp_free_i64(tcg_res);
4881 write_vec_element(s, tcg_resl, rd, 0, MO_64);
4882 tcg_temp_free_i64(tcg_resl);
4883 write_vec_element(s, tcg_resh, rd, 1, MO_64);
4884 tcg_temp_free_i64(tcg_resh);
4887 static void do_minmaxop(DisasContext *s, TCGv_i32 tcg_elt1, TCGv_i32 tcg_elt2,
4888 int opc, bool is_min, TCGv_ptr fpst)
4890 /* Helper function for disas_simd_across_lanes: do a single precision
4891 * min/max operation on the specified two inputs,
4892 * and return the result in tcg_elt1.
4896 gen_helper_vfp_minnums(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
4898 gen_helper_vfp_maxnums(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
4903 gen_helper_vfp_mins(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
4905 gen_helper_vfp_maxs(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
4910 /* C3.6.4 AdvSIMD across lanes
4911 * 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
4912 * +---+---+---+-----------+------+-----------+--------+-----+------+------+
4913 * | 0 | Q | U | 0 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 | Rn | Rd |
4914 * +---+---+---+-----------+------+-----------+--------+-----+------+------+
4916 static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
4918 int rd = extract32(insn, 0, 5);
4919 int rn = extract32(insn, 5, 5);
4920 int size = extract32(insn, 22, 2);
4921 int opcode = extract32(insn, 12, 5);
4922 bool is_q = extract32(insn, 30, 1);
4923 bool is_u = extract32(insn, 29, 1);
4925 bool is_min = false;
4929 TCGv_i64 tcg_res, tcg_elt;
4932 case 0x1b: /* ADDV */
4934 unallocated_encoding(s);
4938 case 0x3: /* SADDLV, UADDLV */
4939 case 0xa: /* SMAXV, UMAXV */
4940 case 0x1a: /* SMINV, UMINV */
4941 if (size == 3 || (size == 2 && !is_q)) {
4942 unallocated_encoding(s);
4946 case 0xc: /* FMAXNMV, FMINNMV */
4947 case 0xf: /* FMAXV, FMINV */
4948 if (!is_u || !is_q || extract32(size, 0, 1)) {
4949 unallocated_encoding(s);
4952 /* Bit 1 of size field encodes min vs max, and actual size is always
4953 * 32 bits: adjust the size variable so following code can rely on it
4955 is_min = extract32(size, 1, 1);
4960 unallocated_encoding(s);
4965 elements = (is_q ? 128 : 64) / esize;
4967 tcg_res = tcg_temp_new_i64();
4968 tcg_elt = tcg_temp_new_i64();
4970 /* These instructions operate across all lanes of a vector
4971 * to produce a single result. We can guarantee that a 64
4972 * bit intermediate is sufficient:
4973 * + for [US]ADDLV the maximum element size is 32 bits, and
4974 * the result type is 64 bits
4975 * + for FMAX*V, FMIN*V, ADDV the intermediate type is the
4976 * same as the element size, which is 32 bits at most
4977 * For the integer operations we can choose to work at 64
4978 * or 32 bits and truncate at the end; for simplicity
4979 * we use 64 bits always. The floating point
4980 * ops do require 32 bit intermediates, though.
4983 read_vec_element(s, tcg_res, rn, 0, size | (is_u ? 0 : MO_SIGN));
4985 for (i = 1; i < elements; i++) {
4986 read_vec_element(s, tcg_elt, rn, i, size | (is_u ? 0 : MO_SIGN));
4989 case 0x03: /* SADDLV / UADDLV */
4990 case 0x1b: /* ADDV */
4991 tcg_gen_add_i64(tcg_res, tcg_res, tcg_elt);
4993 case 0x0a: /* SMAXV / UMAXV */
4994 tcg_gen_movcond_i64(is_u ? TCG_COND_GEU : TCG_COND_GE,
4996 tcg_res, tcg_elt, tcg_res, tcg_elt);
4998 case 0x1a: /* SMINV / UMINV */
4999 tcg_gen_movcond_i64(is_u ? TCG_COND_LEU : TCG_COND_LE,
5001 tcg_res, tcg_elt, tcg_res, tcg_elt);
5005 g_assert_not_reached();
5010 /* Floating point ops which work on 32 bit (single) intermediates.
5011 * Note that correct NaN propagation requires that we do these
5012 * operations in exactly the order specified by the pseudocode.
5014 TCGv_i32 tcg_elt1 = tcg_temp_new_i32();
5015 TCGv_i32 tcg_elt2 = tcg_temp_new_i32();
5016 TCGv_i32 tcg_elt3 = tcg_temp_new_i32();
5017 TCGv_ptr fpst = get_fpstatus_ptr();
5019 assert(esize == 32);
5020 assert(elements == 4);
5022 read_vec_element(s, tcg_elt, rn, 0, MO_32);
5023 tcg_gen_trunc_i64_i32(tcg_elt1, tcg_elt);
5024 read_vec_element(s, tcg_elt, rn, 1, MO_32);
5025 tcg_gen_trunc_i64_i32(tcg_elt2, tcg_elt);
5027 do_minmaxop(s, tcg_elt1, tcg_elt2, opcode, is_min, fpst);
5029 read_vec_element(s, tcg_elt, rn, 2, MO_32);
5030 tcg_gen_trunc_i64_i32(tcg_elt2, tcg_elt);
5031 read_vec_element(s, tcg_elt, rn, 3, MO_32);
5032 tcg_gen_trunc_i64_i32(tcg_elt3, tcg_elt);
5034 do_minmaxop(s, tcg_elt2, tcg_elt3, opcode, is_min, fpst);
5036 do_minmaxop(s, tcg_elt1, tcg_elt2, opcode, is_min, fpst);
5038 tcg_gen_extu_i32_i64(tcg_res, tcg_elt1);
5039 tcg_temp_free_i32(tcg_elt1);
5040 tcg_temp_free_i32(tcg_elt2);
5041 tcg_temp_free_i32(tcg_elt3);
5042 tcg_temp_free_ptr(fpst);
5045 tcg_temp_free_i64(tcg_elt);
5047 /* Now truncate the result to the width required for the final output */
5048 if (opcode == 0x03) {
5049 /* SADDLV, UADDLV: result is 2*esize */
5055 tcg_gen_ext8u_i64(tcg_res, tcg_res);
5058 tcg_gen_ext16u_i64(tcg_res, tcg_res);
5061 tcg_gen_ext32u_i64(tcg_res, tcg_res);
5066 g_assert_not_reached();
5069 write_fp_dreg(s, rd, tcg_res);
5070 tcg_temp_free_i64(tcg_res);
5073 /* C6.3.31 DUP (Element, Vector)
5075 * 31 30 29 21 20 16 15 10 9 5 4 0
5076 * +---+---+-------------------+--------+-------------+------+------+
5077 * | 0 | Q | 0 0 1 1 1 0 0 0 0 | imm5 | 0 0 0 0 0 1 | Rn | Rd |
5078 * +---+---+-------------------+--------+-------------+------+------+
5080 * size: encoded in imm5 (see ARM ARM LowestSetBit())
5082 static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn,
5085 int size = ctz32(imm5);
5086 int esize = 8 << size;
5087 int elements = (is_q ? 128 : 64) / esize;
5091 if (size > 3 || (size == 3 && !is_q)) {
5092 unallocated_encoding(s);
5096 index = imm5 >> (size + 1);
5098 tmp = tcg_temp_new_i64();
5099 read_vec_element(s, tmp, rn, index, size);
5101 for (i = 0; i < elements; i++) {
5102 write_vec_element(s, tmp, rd, i, size);
5106 clear_vec_high(s, rd);
5109 tcg_temp_free_i64(tmp);
5112 /* C6.3.31 DUP (element, scalar)
5113 * 31 21 20 16 15 10 9 5 4 0
5114 * +-----------------------+--------+-------------+------+------+
5115 * | 0 1 0 1 1 1 1 0 0 0 0 | imm5 | 0 0 0 0 0 1 | Rn | Rd |
5116 * +-----------------------+--------+-------------+------+------+
5118 static void handle_simd_dupes(DisasContext *s, int rd, int rn,
5121 int size = ctz32(imm5);
5126 unallocated_encoding(s);
5130 index = imm5 >> (size + 1);
5132 /* This instruction just extracts the specified element and
5133 * zero-extends it into the bottom of the destination register.
5135 tmp = tcg_temp_new_i64();
5136 read_vec_element(s, tmp, rn, index, size);
5137 write_fp_dreg(s, rd, tmp);
5138 tcg_temp_free_i64(tmp);
5141 /* C6.3.32 DUP (General)
5143 * 31 30 29 21 20 16 15 10 9 5 4 0
5144 * +---+---+-------------------+--------+-------------+------+------+
5145 * | 0 | Q | 0 0 1 1 1 0 0 0 0 | imm5 | 0 0 0 0 1 1 | Rn | Rd |
5146 * +---+---+-------------------+--------+-------------+------+------+
5148 * size: encoded in imm5 (see ARM ARM LowestSetBit())
5150 static void handle_simd_dupg(DisasContext *s, int is_q, int rd, int rn,
5153 int size = ctz32(imm5);
5154 int esize = 8 << size;
5155 int elements = (is_q ? 128 : 64)/esize;
5158 if (size > 3 || ((size == 3) && !is_q)) {
5159 unallocated_encoding(s);
5162 for (i = 0; i < elements; i++) {
5163 write_vec_element(s, cpu_reg(s, rn), rd, i, size);
5166 clear_vec_high(s, rd);
5170 /* C6.3.150 INS (Element)
5172 * 31 21 20 16 15 14 11 10 9 5 4 0
5173 * +-----------------------+--------+------------+---+------+------+
5174 * | 0 1 1 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 | Rn | Rd |
5175 * +-----------------------+--------+------------+---+------+------+
5177 * size: encoded in imm5 (see ARM ARM LowestSetBit())
5178 * index: encoded in imm5<4:size+1>
5180 static void handle_simd_inse(DisasContext *s, int rd, int rn,
5183 int size = ctz32(imm5);
5184 int src_index, dst_index;
5188 unallocated_encoding(s);
5191 dst_index = extract32(imm5, 1+size, 5);
5192 src_index = extract32(imm4, size, 4);
5194 tmp = tcg_temp_new_i64();
5196 read_vec_element(s, tmp, rn, src_index, size);
5197 write_vec_element(s, tmp, rd, dst_index, size);
5199 tcg_temp_free_i64(tmp);
5203 /* C6.3.151 INS (General)
5205 * 31 21 20 16 15 10 9 5 4 0
5206 * +-----------------------+--------+-------------+------+------+
5207 * | 0 1 0 0 1 1 1 0 0 0 0 | imm5 | 0 0 0 1 1 1 | Rn | Rd |
5208 * +-----------------------+--------+-------------+------+------+
5210 * size: encoded in imm5 (see ARM ARM LowestSetBit())
5211 * index: encoded in imm5<4:size+1>
5213 static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5)
5215 int size = ctz32(imm5);
5219 unallocated_encoding(s);
5223 idx = extract32(imm5, 1 + size, 4 - size);
5224 write_vec_element(s, cpu_reg(s, rn), rd, idx, size);
5228 * C6.3.321 UMOV (General)
5229 * C6.3.237 SMOV (General)
5231 * 31 30 29 21 20 16 15 12 10 9 5 4 0
5232 * +---+---+-------------------+--------+-------------+------+------+
5233 * | 0 | Q | 0 0 1 1 1 0 0 0 0 | imm5 | 0 0 1 U 1 1 | Rn | Rd |
5234 * +---+---+-------------------+--------+-------------+------+------+
5236 * U: unsigned when set
5237 * size: encoded in imm5 (see ARM ARM LowestSetBit())
5239 static void handle_simd_umov_smov(DisasContext *s, int is_q, int is_signed,
5240 int rn, int rd, int imm5)
5242 int size = ctz32(imm5);
5246 /* Check for UnallocatedEncodings */
5248 if (size > 2 || (size == 2 && !is_q)) {
5249 unallocated_encoding(s);
5254 || (size < 3 && is_q)
5255 || (size == 3 && !is_q)) {
5256 unallocated_encoding(s);
5260 element = extract32(imm5, 1+size, 4);
5262 tcg_rd = cpu_reg(s, rd);
5263 read_vec_element(s, tcg_rd, rn, element, size | (is_signed ? MO_SIGN : 0));
5264 if (is_signed && !is_q) {
5265 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
5269 /* C3.6.5 AdvSIMD copy
5270 * 31 30 29 28 21 20 16 15 14 11 10 9 5 4 0
5271 * +---+---+----+-----------------+------+---+------+---+------+------+
5272 * | 0 | Q | op | 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 | Rn | Rd |
5273 * +---+---+----+-----------------+------+---+------+---+------+------+
5275 static void disas_simd_copy(DisasContext *s, uint32_t insn)
5277 int rd = extract32(insn, 0, 5);
5278 int rn = extract32(insn, 5, 5);
5279 int imm4 = extract32(insn, 11, 4);
5280 int op = extract32(insn, 29, 1);
5281 int is_q = extract32(insn, 30, 1);
5282 int imm5 = extract32(insn, 16, 5);
5287 handle_simd_inse(s, rd, rn, imm4, imm5);
5289 unallocated_encoding(s);
5294 /* DUP (element - vector) */
5295 handle_simd_dupe(s, is_q, rd, rn, imm5);
5299 handle_simd_dupg(s, is_q, rd, rn, imm5);
5304 handle_simd_insg(s, rd, rn, imm5);
5306 unallocated_encoding(s);
5311 /* UMOV/SMOV (is_q indicates 32/64; imm4 indicates signedness) */
5312 handle_simd_umov_smov(s, is_q, (imm4 == 5), rn, rd, imm5);
5315 unallocated_encoding(s);
5321 /* C3.6.6 AdvSIMD modified immediate
5322 * 31 30 29 28 19 18 16 15 12 11 10 9 5 4 0
5323 * +---+---+----+---------------------+-----+-------+----+---+-------+------+
5324 * | 0 | Q | op | 0 1 1 1 1 0 0 0 0 0 | abc | cmode | o2 | 1 | defgh | Rd |
5325 * +---+---+----+---------------------+-----+-------+----+---+-------+------+
5327 * There are a number of operations that can be carried out here:
5328 * MOVI - move (shifted) imm into register
5329 * MVNI - move inverted (shifted) imm into register
5330 * ORR - bitwise OR of (shifted) imm with register
5331 * BIC - bitwise clear of (shifted) imm with register
5333 static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
5335 int rd = extract32(insn, 0, 5);
5336 int cmode = extract32(insn, 12, 4);
5337 int cmode_3_1 = extract32(cmode, 1, 3);
5338 int cmode_0 = extract32(cmode, 0, 1);
5339 int o2 = extract32(insn, 11, 1);
5340 uint64_t abcdefgh = extract32(insn, 5, 5) | (extract32(insn, 16, 3) << 5);
5341 bool is_neg = extract32(insn, 29, 1);
5342 bool is_q = extract32(insn, 30, 1);
5344 TCGv_i64 tcg_rd, tcg_imm;
5347 if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) {
5348 unallocated_encoding(s);
5352 /* See AdvSIMDExpandImm() in ARM ARM */
5353 switch (cmode_3_1) {
5354 case 0: /* Replicate(Zeros(24):imm8, 2) */
5355 case 1: /* Replicate(Zeros(16):imm8:Zeros(8), 2) */
5356 case 2: /* Replicate(Zeros(8):imm8:Zeros(16), 2) */
5357 case 3: /* Replicate(imm8:Zeros(24), 2) */
5359 int shift = cmode_3_1 * 8;
5360 imm = bitfield_replicate(abcdefgh << shift, 32);
5363 case 4: /* Replicate(Zeros(8):imm8, 4) */
5364 case 5: /* Replicate(imm8:Zeros(8), 4) */
5366 int shift = (cmode_3_1 & 0x1) * 8;
5367 imm = bitfield_replicate(abcdefgh << shift, 16);
5372 /* Replicate(Zeros(8):imm8:Ones(16), 2) */
5373 imm = (abcdefgh << 16) | 0xffff;
5375 /* Replicate(Zeros(16):imm8:Ones(8), 2) */
5376 imm = (abcdefgh << 8) | 0xff;
5378 imm = bitfield_replicate(imm, 32);
5381 if (!cmode_0 && !is_neg) {
5382 imm = bitfield_replicate(abcdefgh, 8);
5383 } else if (!cmode_0 && is_neg) {
5386 for (i = 0; i < 8; i++) {
5387 if ((abcdefgh) & (1 << i)) {
5388 imm |= 0xffULL << (i * 8);
5391 } else if (cmode_0) {
5393 imm = (abcdefgh & 0x3f) << 48;
5394 if (abcdefgh & 0x80) {
5395 imm |= 0x8000000000000000ULL;
5397 if (abcdefgh & 0x40) {
5398 imm |= 0x3fc0000000000000ULL;
5400 imm |= 0x4000000000000000ULL;
5403 imm = (abcdefgh & 0x3f) << 19;
5404 if (abcdefgh & 0x80) {
5407 if (abcdefgh & 0x40) {
5418 if (cmode_3_1 != 7 && is_neg) {
5422 tcg_imm = tcg_const_i64(imm);
5423 tcg_rd = new_tmp_a64(s);
5425 for (i = 0; i < 2; i++) {
5426 int foffs = i ? fp_reg_hi_offset(rd) : fp_reg_offset(rd, MO_64);
5428 if (i == 1 && !is_q) {
5429 /* non-quad ops clear high half of vector */
5430 tcg_gen_movi_i64(tcg_rd, 0);
5431 } else if ((cmode & 0x9) == 0x1 || (cmode & 0xd) == 0x9) {
5432 tcg_gen_ld_i64(tcg_rd, cpu_env, foffs);
5435 tcg_gen_and_i64(tcg_rd, tcg_rd, tcg_imm);
5438 tcg_gen_or_i64(tcg_rd, tcg_rd, tcg_imm);
5442 tcg_gen_mov_i64(tcg_rd, tcg_imm);
5444 tcg_gen_st_i64(tcg_rd, cpu_env, foffs);
5447 tcg_temp_free_i64(tcg_imm);
5450 /* C3.6.7 AdvSIMD scalar copy
5451 * 31 30 29 28 21 20 16 15 14 11 10 9 5 4 0
5452 * +-----+----+-----------------+------+---+------+---+------+------+
5453 * | 0 1 | op | 1 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 | Rn | Rd |
5454 * +-----+----+-----------------+------+---+------+---+------+------+
5456 static void disas_simd_scalar_copy(DisasContext *s, uint32_t insn)
5458 int rd = extract32(insn, 0, 5);
5459 int rn = extract32(insn, 5, 5);
5460 int imm4 = extract32(insn, 11, 4);
5461 int imm5 = extract32(insn, 16, 5);
5462 int op = extract32(insn, 29, 1);
5464 if (op != 0 || imm4 != 0) {
5465 unallocated_encoding(s);
5469 /* DUP (element, scalar) */
5470 handle_simd_dupes(s, rd, rn, imm5);
5473 /* C3.6.8 AdvSIMD scalar pairwise
5474 * 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
5475 * +-----+---+-----------+------+-----------+--------+-----+------+------+
5476 * | 0 1 | U | 1 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 | Rn | Rd |
5477 * +-----+---+-----------+------+-----------+--------+-----+------+------+
5479 static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
5481 unsupported_encoding(s, insn);
5484 /* C3.6.9 AdvSIMD scalar shift by immediate
5485 * 31 30 29 28 23 22 19 18 16 15 11 10 9 5 4 0
5486 * +-----+---+-------------+------+------+--------+---+------+------+
5487 * | 0 1 | U | 1 1 1 1 1 0 | immh | immb | opcode | 1 | Rn | Rd |
5488 * +-----+---+-------------+------+------+--------+---+------+------+
5490 static void disas_simd_scalar_shift_imm(DisasContext *s, uint32_t insn)
5492 unsupported_encoding(s, insn);
5495 /* C3.6.10 AdvSIMD scalar three different
5496 * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
5497 * +-----+---+-----------+------+---+------+--------+-----+------+------+
5498 * | 0 1 | U | 1 1 1 1 0 | size | 1 | Rm | opcode | 0 0 | Rn | Rd |
5499 * +-----+---+-----------+------+---+------+--------+-----+------+------+
5501 static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
5503 unsupported_encoding(s, insn);
5506 /* C3.6.11 AdvSIMD scalar three same
5507 * 31 30 29 28 24 23 22 21 20 16 15 11 10 9 5 4 0
5508 * +-----+---+-----------+------+---+------+--------+---+------+------+
5509 * | 0 1 | U | 1 1 1 1 0 | size | 1 | Rm | opcode | 1 | Rn | Rd |
5510 * +-----+---+-----------+------+---+------+--------+---+------+------+
5512 static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
5514 unsupported_encoding(s, insn);
5517 /* C3.6.12 AdvSIMD scalar two reg misc
5518 * 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
5519 * +-----+---+-----------+------+-----------+--------+-----+------+------+
5520 * | 0 1 | U | 1 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 | Rn | Rd |
5521 * +-----+---+-----------+------+-----------+--------+-----+------+------+
5523 static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
5525 unsupported_encoding(s, insn);
5528 /* C3.6.13 AdvSIMD scalar x indexed element
5529 * 31 30 29 28 24 23 22 21 20 19 16 15 12 11 10 9 5 4 0
5530 * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
5531 * | 0 1 | U | 1 1 1 1 1 | size | L | M | Rm | opc | H | 0 | Rn | Rd |
5532 * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
5534 static void disas_simd_scalar_indexed(DisasContext *s, uint32_t insn)
5536 unsupported_encoding(s, insn);
5539 /* C3.6.14 AdvSIMD shift by immediate
5540 * 31 30 29 28 23 22 19 18 16 15 11 10 9 5 4 0
5541 * +---+---+---+-------------+------+------+--------+---+------+------+
5542 * | 0 | Q | U | 0 1 1 1 1 0 | immh | immb | opcode | 1 | Rn | Rd |
5543 * +---+---+---+-------------+------+------+--------+---+------+------+
5545 static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
5547 unsupported_encoding(s, insn);
5550 static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
5551 int opcode, int rd, int rn, int rm)
5553 /* 3-reg-different widening insns: 64 x 64 -> 128 */
5554 TCGv_i64 tcg_res[2];
5557 tcg_res[0] = tcg_temp_new_i64();
5558 tcg_res[1] = tcg_temp_new_i64();
5560 /* Does this op do an adding accumulate, a subtracting accumulate,
5561 * or no accumulate at all?
5579 read_vec_element(s, tcg_res[0], rd, 0, MO_64);
5580 read_vec_element(s, tcg_res[1], rd, 1, MO_64);
5583 /* size == 2 means two 32x32->64 operations; this is worth special
5584 * casing because we can generally handle it inline.
5587 for (pass = 0; pass < 2; pass++) {
5588 TCGv_i64 tcg_op1 = tcg_temp_new_i64();
5589 TCGv_i64 tcg_op2 = tcg_temp_new_i64();
5590 TCGv_i64 tcg_passres;
5591 TCGMemOp memop = MO_32 | (is_u ? 0 : MO_SIGN);
5593 int elt = pass + is_q * 2;
5595 read_vec_element(s, tcg_op1, rn, elt, memop);
5596 read_vec_element(s, tcg_op2, rm, elt, memop);
5599 tcg_passres = tcg_res[pass];
5601 tcg_passres = tcg_temp_new_i64();
5605 case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
5606 case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
5607 case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
5608 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
5611 g_assert_not_reached();
5615 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
5616 tcg_temp_free_i64(tcg_passres);
5617 } else if (accop < 0) {
5618 tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
5619 tcg_temp_free_i64(tcg_passres);
5622 tcg_temp_free_i64(tcg_op1);
5623 tcg_temp_free_i64(tcg_op2);
5626 /* size 0 or 1, generally helper functions */
5627 for (pass = 0; pass < 2; pass++) {
5628 TCGv_i32 tcg_op1 = tcg_temp_new_i32();
5629 TCGv_i32 tcg_op2 = tcg_temp_new_i32();
5630 TCGv_i64 tcg_passres;
5631 int elt = pass + is_q * 2;
5633 read_vec_element_i32(s, tcg_op1, rn, elt, MO_32);
5634 read_vec_element_i32(s, tcg_op2, rm, elt, MO_32);
5637 tcg_passres = tcg_res[pass];
5639 tcg_passres = tcg_temp_new_i64();
5643 case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
5644 case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
5645 case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
5648 gen_helper_neon_mull_u8(tcg_passres, tcg_op1, tcg_op2);
5650 gen_helper_neon_mull_s8(tcg_passres, tcg_op1, tcg_op2);
5654 gen_helper_neon_mull_u16(tcg_passres, tcg_op1, tcg_op2);
5656 gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
5661 g_assert_not_reached();
5663 tcg_temp_free_i32(tcg_op1);
5664 tcg_temp_free_i32(tcg_op2);
5668 gen_helper_neon_addl_u16(tcg_res[pass], tcg_res[pass],
5671 gen_helper_neon_addl_u32(tcg_res[pass], tcg_res[pass],
5674 tcg_temp_free_i64(tcg_passres);
5675 } else if (accop < 0) {
5677 gen_helper_neon_subl_u16(tcg_res[pass], tcg_res[pass],
5680 gen_helper_neon_subl_u32(tcg_res[pass], tcg_res[pass],
5683 tcg_temp_free_i64(tcg_passres);
5688 write_vec_element(s, tcg_res[0], rd, 0, MO_64);
5689 write_vec_element(s, tcg_res[1], rd, 1, MO_64);
5690 tcg_temp_free_i64(tcg_res[0]);
5691 tcg_temp_free_i64(tcg_res[1]);
5694 /* C3.6.15 AdvSIMD three different
5695 * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
5696 * +---+---+---+-----------+------+---+------+--------+-----+------+------+
5697 * | 0 | Q | U | 0 1 1 1 0 | size | 1 | Rm | opcode | 0 0 | Rn | Rd |
5698 * +---+---+---+-----------+------+---+------+--------+-----+------+------+
5700 static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
5702 /* Instructions in this group fall into three basic classes
5703 * (in each case with the operation working on each element in
5704 * the input vectors):
5705 * (1) widening 64 x 64 -> 128 (with possibly Vd as an extra
5707 * (2) wide 64 x 128 -> 128
5708 * (3) narrowing 128 x 128 -> 64
5709 * Here we do initial decode, catch unallocated cases and
5710 * dispatch to separate functions for each class.
5712 int is_q = extract32(insn, 30, 1);
5713 int is_u = extract32(insn, 29, 1);
5714 int size = extract32(insn, 22, 2);
5715 int opcode = extract32(insn, 12, 4);
5716 int rm = extract32(insn, 16, 5);
5717 int rn = extract32(insn, 5, 5);
5718 int rd = extract32(insn, 0, 5);
5721 case 1: /* SADDW, SADDW2, UADDW, UADDW2 */
5722 case 3: /* SSUBW, SSUBW2, USUBW, USUBW2 */
5723 /* 64 x 128 -> 128 */
5724 unsupported_encoding(s, insn);
5726 case 4: /* ADDHN, ADDHN2, RADDHN, RADDHN2 */
5727 case 6: /* SUBHN, SUBHN2, RSUBHN, RSUBHN2 */
5728 /* 128 x 128 -> 64 */
5729 unsupported_encoding(s, insn);
5736 unallocated_encoding(s);
5744 unsupported_encoding(s, insn);
5749 /* 64 x 64 -> 128 */
5751 unallocated_encoding(s);
5754 handle_3rd_widening(s, is_q, is_u, size, opcode, rd, rn, rm);
5757 /* opcode 15 not allocated */
5758 unallocated_encoding(s);
5763 /* C3.6.16 AdvSIMD three same
5764 * 31 30 29 28 24 23 22 21 20 16 15 11 10 9 5 4 0
5765 * +---+---+---+-----------+------+---+------+--------+---+------+------+
5766 * | 0 | Q | U | 0 1 1 1 0 | size | 1 | Rm | opcode | 1 | Rn | Rd |
5767 * +---+---+---+-----------+------+---+------+--------+---+------+------+
5769 static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
5771 unsupported_encoding(s, insn);
5774 /* C3.6.17 AdvSIMD two reg misc
5775 * 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
5776 * +---+---+---+-----------+------+-----------+--------+-----+------+------+
5777 * | 0 | Q | U | 0 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 | Rn | Rd |
5778 * +---+---+---+-----------+------+-----------+--------+-----+------+------+
5780 static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
5782 unsupported_encoding(s, insn);
5785 /* C3.6.18 AdvSIMD vector x indexed element
5786 * 31 30 29 28 24 23 22 21 20 19 16 15 12 11 10 9 5 4 0
5787 * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
5788 * | 0 | Q | U | 0 1 1 1 1 | size | L | M | Rm | opc | H | 0 | Rn | Rd |
5789 * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
5791 static void disas_simd_indexed_vector(DisasContext *s, uint32_t insn)
5793 unsupported_encoding(s, insn);
5796 /* C3.6.19 Crypto AES
5797 * 31 24 23 22 21 17 16 12 11 10 9 5 4 0
5798 * +-----------------+------+-----------+--------+-----+------+------+
5799 * | 0 1 0 0 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 | Rn | Rd |
5800 * +-----------------+------+-----------+--------+-----+------+------+
5802 static void disas_crypto_aes(DisasContext *s, uint32_t insn)
5804 unsupported_encoding(s, insn);
5807 /* C3.6.20 Crypto three-reg SHA
5808 * 31 24 23 22 21 20 16 15 14 12 11 10 9 5 4 0
5809 * +-----------------+------+---+------+---+--------+-----+------+------+
5810 * | 0 1 0 1 1 1 1 0 | size | 0 | Rm | 0 | opcode | 0 0 | Rn | Rd |
5811 * +-----------------+------+---+------+---+--------+-----+------+------+
5813 static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
5815 unsupported_encoding(s, insn);
5818 /* C3.6.21 Crypto two-reg SHA
5819 * 31 24 23 22 21 17 16 12 11 10 9 5 4 0
5820 * +-----------------+------+-----------+--------+-----+------+------+
5821 * | 0 1 0 1 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 | Rn | Rd |
5822 * +-----------------+------+-----------+--------+-----+------+------+
5824 static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
5826 unsupported_encoding(s, insn);
5829 /* C3.6 Data processing - SIMD, inc Crypto
5831 * As the decode gets a little complex we are using a table based
5832 * approach for this part of the decode.
5834 static const AArch64DecodeTable data_proc_simd[] = {
5835 /* pattern , mask , fn */
5836 { 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
5837 { 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
5838 { 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
5839 { 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
5840 { 0x0e000400, 0x9fe08400, disas_simd_copy },
5841 { 0x0f000000, 0x9f000400, disas_simd_indexed_vector },
5842 /* simd_mod_imm decode is a subset of simd_shift_imm, so must precede it */
5843 { 0x0f000400, 0x9ff80400, disas_simd_mod_imm },
5844 { 0x0f000400, 0x9f800400, disas_simd_shift_imm },
5845 { 0x0e000000, 0xbf208c00, disas_simd_tb },
5846 { 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
5847 { 0x2e000000, 0xbf208400, disas_simd_ext },
5848 { 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
5849 { 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
5850 { 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
5851 { 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
5852 { 0x5e000400, 0xdfe08400, disas_simd_scalar_copy },
5853 { 0x5f000000, 0xdf000400, disas_simd_scalar_indexed },
5854 { 0x5f000400, 0xdf800400, disas_simd_scalar_shift_imm },
5855 { 0x4e280800, 0xff3e0c00, disas_crypto_aes },
5856 { 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha },
5857 { 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
5858 { 0x00000000, 0x00000000, NULL }
5861 static void disas_data_proc_simd(DisasContext *s, uint32_t insn)
5863 /* Note that this is called with all non-FP cases from
5864 * table C3-6 so it must UNDEF for entries not specifically
5865 * allocated to instructions in that table.
5867 AArch64DecodeFn *fn = lookup_disas_fn(&data_proc_simd[0], insn);
5871 unallocated_encoding(s);
5875 /* C3.6 Data processing - SIMD and floating point */
5876 static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
5878 if (extract32(insn, 28, 1) == 1 && extract32(insn, 30, 1) == 0) {
5879 disas_data_proc_fp(s, insn);
5881 /* SIMD, including crypto */
5882 disas_data_proc_simd(s, insn);
5886 /* C3.1 A64 instruction index by encoding */
5887 static void disas_a64_insn(CPUARMState *env, DisasContext *s)
5891 insn = arm_ldl_code(env, s->pc, s->bswap_code);
5895 switch (extract32(insn, 25, 4)) {
5896 case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
5897 unallocated_encoding(s);
5899 case 0x8: case 0x9: /* Data processing - immediate */
5900 disas_data_proc_imm(s, insn);
5902 case 0xa: case 0xb: /* Branch, exception generation and system insns */
5903 disas_b_exc_sys(s, insn);
5908 case 0xe: /* Loads and stores */
5909 disas_ldst(s, insn);
5912 case 0xd: /* Data processing - register */
5913 disas_data_proc_reg(s, insn);
5916 case 0xf: /* Data processing - SIMD and floating point */
5917 disas_data_proc_simd_fp(s, insn);
5920 assert(FALSE); /* all 15 cases should be handled above */
5924 /* if we allocated any temporaries, free them here */
5928 void gen_intermediate_code_internal_a64(ARMCPU *cpu,
5929 TranslationBlock *tb,
5932 CPUState *cs = CPU(cpu);
5933 CPUARMState *env = &cpu->env;
5934 DisasContext dc1, *dc = &dc1;
5936 uint16_t *gen_opc_end;
5938 target_ulong pc_start;
5939 target_ulong next_page_start;
5947 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
5949 dc->is_jmp = DISAS_NEXT;
5951 dc->singlestep_enabled = cs->singlestep_enabled;
5957 dc->condexec_mask = 0;
5958 dc->condexec_cond = 0;
5959 #if !defined(CONFIG_USER_ONLY)
5962 dc->vfp_enabled = 0;
5965 dc->cp_regs = cpu->cp_regs;
5966 dc->current_pl = arm_current_pl(env);
5968 init_tmp_a64_array(dc);
5970 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
5973 max_insns = tb->cflags & CF_COUNT_MASK;
5974 if (max_insns == 0) {
5975 max_insns = CF_COUNT_MASK;
5980 tcg_clear_temp_count();
5983 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
5984 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
5985 if (bp->pc == dc->pc) {
5986 gen_exception_insn(dc, 0, EXCP_DEBUG);
5987 /* Advance PC so that clearing the breakpoint will
5988 invalidate this TB. */
5990 goto done_generating;
5996 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
6000 tcg_ctx.gen_opc_instr_start[lj++] = 0;
6003 tcg_ctx.gen_opc_pc[lj] = dc->pc;
6004 tcg_ctx.gen_opc_instr_start[lj] = 1;
6005 tcg_ctx.gen_opc_icount[lj] = num_insns;
6008 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
6012 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
6013 tcg_gen_debug_insn_start(dc->pc);
6016 disas_a64_insn(env, dc);
6018 if (tcg_check_temp_count()) {
6019 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
6023 /* Translation stops when a conditional branch is encountered.
6024 * Otherwise the subsequent code could get translated several times.
6025 * Also stop translation when a page boundary is reached. This
6026 * ensures prefetch aborts occur at the right place.
6029 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
6030 !cs->singlestep_enabled &&
6032 dc->pc < next_page_start &&
6033 num_insns < max_insns);
6035 if (tb->cflags & CF_LAST_IO) {
6039 if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
6040 /* Note that this means single stepping WFI doesn't halt the CPU.
6041 * For conditional branch insns this is harmless unreachable code as
6042 * gen_goto_tb() has already handled emitting the debug exception
6043 * (and thus a tb-jump is not possible when singlestepping).
6045 assert(dc->is_jmp != DISAS_TB_JUMP);
6046 if (dc->is_jmp != DISAS_JUMP) {
6047 gen_a64_set_pc_im(dc->pc);
6049 gen_exception(EXCP_DEBUG);
6051 switch (dc->is_jmp) {
6053 gen_goto_tb(dc, 1, dc->pc);
6057 gen_a64_set_pc_im(dc->pc);
6060 /* indicate that the hash table must be used to find the next TB */
6068 /* This is a special case because we don't want to just halt the CPU
6069 * if trying to debug across a WFI.
6071 gen_helper_wfi(cpu_env);
6077 gen_tb_end(tb, num_insns);
6078 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
6081 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
6082 qemu_log("----------------\n");
6083 qemu_log("IN: %s\n", lookup_symbol(pc_start));
6084 log_target_disas(env, pc_start, dc->pc - pc_start,
6085 dc->thumb | (dc->bswap_code << 1));
6090 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
6093 tcg_ctx.gen_opc_instr_start[lj++] = 0;
6096 tb->size = dc->pc - pc_start;
6097 tb->icount = num_insns;