4 * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
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 /* Function prototype for gen_ functions for calling Neon helpers */
76 typedef void NeonGenTwoOpFn(TCGv_i32
, TCGv_i32
, TCGv_i32
);
78 /* initialize TCG globals. */
79 void a64_translate_init(void)
83 cpu_pc
= tcg_global_mem_new_i64(TCG_AREG0
,
84 offsetof(CPUARMState
, pc
),
86 for (i
= 0; i
< 32; i
++) {
87 cpu_X
[i
] = tcg_global_mem_new_i64(TCG_AREG0
,
88 offsetof(CPUARMState
, xregs
[i
]),
92 cpu_NF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUARMState
, NF
), "NF");
93 cpu_ZF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUARMState
, ZF
), "ZF");
94 cpu_CF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUARMState
, CF
), "CF");
95 cpu_VF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUARMState
, VF
), "VF");
97 cpu_exclusive_addr
= tcg_global_mem_new_i64(TCG_AREG0
,
98 offsetof(CPUARMState
, exclusive_addr
), "exclusive_addr");
99 cpu_exclusive_val
= tcg_global_mem_new_i64(TCG_AREG0
,
100 offsetof(CPUARMState
, exclusive_val
), "exclusive_val");
101 cpu_exclusive_high
= tcg_global_mem_new_i64(TCG_AREG0
,
102 offsetof(CPUARMState
, exclusive_high
), "exclusive_high");
103 #ifdef CONFIG_USER_ONLY
104 cpu_exclusive_test
= tcg_global_mem_new_i64(TCG_AREG0
,
105 offsetof(CPUARMState
, exclusive_test
), "exclusive_test");
106 cpu_exclusive_info
= tcg_global_mem_new_i32(TCG_AREG0
,
107 offsetof(CPUARMState
, exclusive_info
), "exclusive_info");
111 void aarch64_cpu_dump_state(CPUState
*cs
, FILE *f
,
112 fprintf_function cpu_fprintf
, int flags
)
114 ARMCPU
*cpu
= ARM_CPU(cs
);
115 CPUARMState
*env
= &cpu
->env
;
116 uint32_t psr
= pstate_read(env
);
119 cpu_fprintf(f
, "PC=%016"PRIx64
" SP=%016"PRIx64
"\n",
120 env
->pc
, env
->xregs
[31]);
121 for (i
= 0; i
< 31; i
++) {
122 cpu_fprintf(f
, "X%02d=%016"PRIx64
, i
, env
->xregs
[i
]);
124 cpu_fprintf(f
, "\n");
129 cpu_fprintf(f
, "PSTATE=%08x (flags %c%c%c%c)\n",
131 psr
& PSTATE_N
? 'N' : '-',
132 psr
& PSTATE_Z
? 'Z' : '-',
133 psr
& PSTATE_C
? 'C' : '-',
134 psr
& PSTATE_V
? 'V' : '-');
135 cpu_fprintf(f
, "\n");
137 if (flags
& CPU_DUMP_FPU
) {
139 for (i
= 0; i
< numvfpregs
; i
+= 2) {
140 uint64_t vlo
= float64_val(env
->vfp
.regs
[i
* 2]);
141 uint64_t vhi
= float64_val(env
->vfp
.regs
[(i
* 2) + 1]);
142 cpu_fprintf(f
, "q%02d=%016" PRIx64
":%016" PRIx64
" ",
144 vlo
= float64_val(env
->vfp
.regs
[(i
+ 1) * 2]);
145 vhi
= float64_val(env
->vfp
.regs
[((i
+ 1) * 2) + 1]);
146 cpu_fprintf(f
, "q%02d=%016" PRIx64
":%016" PRIx64
"\n",
149 cpu_fprintf(f
, "FPCR: %08x FPSR: %08x\n",
150 vfp_get_fpcr(env
), vfp_get_fpsr(env
));
154 static int get_mem_index(DisasContext
*s
)
156 #ifdef CONFIG_USER_ONLY
163 void gen_a64_set_pc_im(uint64_t val
)
165 tcg_gen_movi_i64(cpu_pc
, val
);
168 static void gen_exception(int excp
)
170 TCGv_i32 tmp
= tcg_temp_new_i32();
171 tcg_gen_movi_i32(tmp
, excp
);
172 gen_helper_exception(cpu_env
, tmp
);
173 tcg_temp_free_i32(tmp
);
176 static void gen_exception_insn(DisasContext
*s
, int offset
, int excp
)
178 gen_a64_set_pc_im(s
->pc
- offset
);
180 s
->is_jmp
= DISAS_EXC
;
183 static inline bool use_goto_tb(DisasContext
*s
, int n
, uint64_t dest
)
185 /* No direct tb linking with singlestep or deterministic io */
186 if (s
->singlestep_enabled
|| (s
->tb
->cflags
& CF_LAST_IO
)) {
190 /* Only link tbs from inside the same guest page */
191 if ((s
->tb
->pc
& TARGET_PAGE_MASK
) != (dest
& TARGET_PAGE_MASK
)) {
198 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint64_t dest
)
200 TranslationBlock
*tb
;
203 if (use_goto_tb(s
, n
, dest
)) {
205 gen_a64_set_pc_im(dest
);
206 tcg_gen_exit_tb((tcg_target_long
)tb
+ n
);
207 s
->is_jmp
= DISAS_TB_JUMP
;
209 gen_a64_set_pc_im(dest
);
210 if (s
->singlestep_enabled
) {
211 gen_exception(EXCP_DEBUG
);
214 s
->is_jmp
= DISAS_JUMP
;
218 static void unallocated_encoding(DisasContext
*s
)
220 gen_exception_insn(s
, 4, EXCP_UDEF
);
223 #define unsupported_encoding(s, insn) \
225 qemu_log_mask(LOG_UNIMP, \
226 "%s:%d: unsupported instruction encoding 0x%08x " \
227 "at pc=%016" PRIx64 "\n", \
228 __FILE__, __LINE__, insn, s->pc - 4); \
229 unallocated_encoding(s); \
232 static void init_tmp_a64_array(DisasContext
*s
)
234 #ifdef CONFIG_DEBUG_TCG
236 for (i
= 0; i
< ARRAY_SIZE(s
->tmp_a64
); i
++) {
237 TCGV_UNUSED_I64(s
->tmp_a64
[i
]);
240 s
->tmp_a64_count
= 0;
243 static void free_tmp_a64(DisasContext
*s
)
246 for (i
= 0; i
< s
->tmp_a64_count
; i
++) {
247 tcg_temp_free_i64(s
->tmp_a64
[i
]);
249 init_tmp_a64_array(s
);
252 static TCGv_i64
new_tmp_a64(DisasContext
*s
)
254 assert(s
->tmp_a64_count
< TMP_A64_MAX
);
255 return s
->tmp_a64
[s
->tmp_a64_count
++] = tcg_temp_new_i64();
258 static TCGv_i64
new_tmp_a64_zero(DisasContext
*s
)
260 TCGv_i64 t
= new_tmp_a64(s
);
261 tcg_gen_movi_i64(t
, 0);
266 * Register access functions
268 * These functions are used for directly accessing a register in where
269 * changes to the final register value are likely to be made. If you
270 * need to use a register for temporary calculation (e.g. index type
271 * operations) use the read_* form.
273 * B1.2.1 Register mappings
275 * In instruction register encoding 31 can refer to ZR (zero register) or
276 * the SP (stack pointer) depending on context. In QEMU's case we map SP
277 * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
278 * This is the point of the _sp forms.
280 static TCGv_i64
cpu_reg(DisasContext
*s
, int reg
)
283 return new_tmp_a64_zero(s
);
289 /* register access for when 31 == SP */
290 static TCGv_i64
cpu_reg_sp(DisasContext
*s
, int reg
)
295 /* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
296 * representing the register contents. This TCGv is an auto-freed
297 * temporary so it need not be explicitly freed, and may be modified.
299 static TCGv_i64
read_cpu_reg(DisasContext
*s
, int reg
, int sf
)
301 TCGv_i64 v
= new_tmp_a64(s
);
304 tcg_gen_mov_i64(v
, cpu_X
[reg
]);
306 tcg_gen_ext32u_i64(v
, cpu_X
[reg
]);
309 tcg_gen_movi_i64(v
, 0);
314 static TCGv_i64
read_cpu_reg_sp(DisasContext
*s
, int reg
, int sf
)
316 TCGv_i64 v
= new_tmp_a64(s
);
318 tcg_gen_mov_i64(v
, cpu_X
[reg
]);
320 tcg_gen_ext32u_i64(v
, cpu_X
[reg
]);
325 /* Return the offset into CPUARMState of an element of specified
326 * size, 'element' places in from the least significant end of
327 * the FP/vector register Qn.
329 static inline int vec_reg_offset(int regno
, int element
, TCGMemOp size
)
331 int offs
= offsetof(CPUARMState
, vfp
.regs
[regno
* 2]);
332 #ifdef HOST_WORDS_BIGENDIAN
333 /* This is complicated slightly because vfp.regs[2n] is
334 * still the low half and vfp.regs[2n+1] the high half
335 * of the 128 bit vector, even on big endian systems.
336 * Calculate the offset assuming a fully bigendian 128 bits,
337 * then XOR to account for the order of the two 64 bit halves.
339 offs
+= (16 - ((element
+ 1) * (1 << size
)));
342 offs
+= element
* (1 << size
);
347 /* Return the offset into CPUARMState of a slice (from
348 * the least significant end) of FP register Qn (ie
350 * (Note that this is not the same mapping as for A32; see cpu.h)
352 static inline int fp_reg_offset(int regno
, TCGMemOp size
)
354 int offs
= offsetof(CPUARMState
, vfp
.regs
[regno
* 2]);
355 #ifdef HOST_WORDS_BIGENDIAN
356 offs
+= (8 - (1 << size
));
361 /* Offset of the high half of the 128 bit vector Qn */
362 static inline int fp_reg_hi_offset(int regno
)
364 return offsetof(CPUARMState
, vfp
.regs
[regno
* 2 + 1]);
367 /* Convenience accessors for reading and writing single and double
368 * FP registers. Writing clears the upper parts of the associated
369 * 128 bit vector register, as required by the architecture.
370 * Note that unlike the GP register accessors, the values returned
371 * by the read functions must be manually freed.
373 static TCGv_i64
read_fp_dreg(DisasContext
*s
, int reg
)
375 TCGv_i64 v
= tcg_temp_new_i64();
377 tcg_gen_ld_i64(v
, cpu_env
, fp_reg_offset(reg
, MO_64
));
381 static TCGv_i32
read_fp_sreg(DisasContext
*s
, int reg
)
383 TCGv_i32 v
= tcg_temp_new_i32();
385 tcg_gen_ld_i32(v
, cpu_env
, fp_reg_offset(reg
, MO_32
));
389 static void write_fp_dreg(DisasContext
*s
, int reg
, TCGv_i64 v
)
391 TCGv_i64 tcg_zero
= tcg_const_i64(0);
393 tcg_gen_st_i64(v
, cpu_env
, fp_reg_offset(reg
, MO_64
));
394 tcg_gen_st_i64(tcg_zero
, cpu_env
, fp_reg_hi_offset(reg
));
395 tcg_temp_free_i64(tcg_zero
);
398 static void write_fp_sreg(DisasContext
*s
, int reg
, TCGv_i32 v
)
400 TCGv_i64 tmp
= tcg_temp_new_i64();
402 tcg_gen_extu_i32_i64(tmp
, v
);
403 write_fp_dreg(s
, reg
, tmp
);
404 tcg_temp_free_i64(tmp
);
407 static TCGv_ptr
get_fpstatus_ptr(void)
409 TCGv_ptr statusptr
= tcg_temp_new_ptr();
412 /* In A64 all instructions (both FP and Neon) use the FPCR;
413 * there is no equivalent of the A32 Neon "standard FPSCR value"
414 * and all operations use vfp.fp_status.
416 offset
= offsetof(CPUARMState
, vfp
.fp_status
);
417 tcg_gen_addi_ptr(statusptr
, cpu_env
, offset
);
421 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
422 * than the 32 bit equivalent.
424 static inline void gen_set_NZ64(TCGv_i64 result
)
426 TCGv_i64 flag
= tcg_temp_new_i64();
428 tcg_gen_setcondi_i64(TCG_COND_NE
, flag
, result
, 0);
429 tcg_gen_trunc_i64_i32(cpu_ZF
, flag
);
430 tcg_gen_shri_i64(flag
, result
, 32);
431 tcg_gen_trunc_i64_i32(cpu_NF
, flag
);
432 tcg_temp_free_i64(flag
);
435 /* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
436 static inline void gen_logic_CC(int sf
, TCGv_i64 result
)
439 gen_set_NZ64(result
);
441 tcg_gen_trunc_i64_i32(cpu_ZF
, result
);
442 tcg_gen_trunc_i64_i32(cpu_NF
, result
);
444 tcg_gen_movi_i32(cpu_CF
, 0);
445 tcg_gen_movi_i32(cpu_VF
, 0);
448 /* dest = T0 + T1; compute C, N, V and Z flags */
449 static void gen_add_CC(int sf
, TCGv_i64 dest
, TCGv_i64 t0
, TCGv_i64 t1
)
452 TCGv_i64 result
, flag
, tmp
;
453 result
= tcg_temp_new_i64();
454 flag
= tcg_temp_new_i64();
455 tmp
= tcg_temp_new_i64();
457 tcg_gen_movi_i64(tmp
, 0);
458 tcg_gen_add2_i64(result
, flag
, t0
, tmp
, t1
, tmp
);
460 tcg_gen_trunc_i64_i32(cpu_CF
, flag
);
462 gen_set_NZ64(result
);
464 tcg_gen_xor_i64(flag
, result
, t0
);
465 tcg_gen_xor_i64(tmp
, t0
, t1
);
466 tcg_gen_andc_i64(flag
, flag
, tmp
);
467 tcg_temp_free_i64(tmp
);
468 tcg_gen_shri_i64(flag
, flag
, 32);
469 tcg_gen_trunc_i64_i32(cpu_VF
, flag
);
471 tcg_gen_mov_i64(dest
, result
);
472 tcg_temp_free_i64(result
);
473 tcg_temp_free_i64(flag
);
475 /* 32 bit arithmetic */
476 TCGv_i32 t0_32
= tcg_temp_new_i32();
477 TCGv_i32 t1_32
= tcg_temp_new_i32();
478 TCGv_i32 tmp
= tcg_temp_new_i32();
480 tcg_gen_movi_i32(tmp
, 0);
481 tcg_gen_trunc_i64_i32(t0_32
, t0
);
482 tcg_gen_trunc_i64_i32(t1_32
, t1
);
483 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, t0_32
, tmp
, t1_32
, tmp
);
484 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
485 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0_32
);
486 tcg_gen_xor_i32(tmp
, t0_32
, t1_32
);
487 tcg_gen_andc_i32(cpu_VF
, cpu_VF
, tmp
);
488 tcg_gen_extu_i32_i64(dest
, cpu_NF
);
490 tcg_temp_free_i32(tmp
);
491 tcg_temp_free_i32(t0_32
);
492 tcg_temp_free_i32(t1_32
);
496 /* dest = T0 - T1; compute C, N, V and Z flags */
497 static void gen_sub_CC(int sf
, TCGv_i64 dest
, TCGv_i64 t0
, TCGv_i64 t1
)
500 /* 64 bit arithmetic */
501 TCGv_i64 result
, flag
, tmp
;
503 result
= tcg_temp_new_i64();
504 flag
= tcg_temp_new_i64();
505 tcg_gen_sub_i64(result
, t0
, t1
);
507 gen_set_NZ64(result
);
509 tcg_gen_setcond_i64(TCG_COND_GEU
, flag
, t0
, t1
);
510 tcg_gen_trunc_i64_i32(cpu_CF
, flag
);
512 tcg_gen_xor_i64(flag
, result
, t0
);
513 tmp
= tcg_temp_new_i64();
514 tcg_gen_xor_i64(tmp
, t0
, t1
);
515 tcg_gen_and_i64(flag
, flag
, tmp
);
516 tcg_temp_free_i64(tmp
);
517 tcg_gen_shri_i64(flag
, flag
, 32);
518 tcg_gen_trunc_i64_i32(cpu_VF
, flag
);
519 tcg_gen_mov_i64(dest
, result
);
520 tcg_temp_free_i64(flag
);
521 tcg_temp_free_i64(result
);
523 /* 32 bit arithmetic */
524 TCGv_i32 t0_32
= tcg_temp_new_i32();
525 TCGv_i32 t1_32
= tcg_temp_new_i32();
528 tcg_gen_trunc_i64_i32(t0_32
, t0
);
529 tcg_gen_trunc_i64_i32(t1_32
, t1
);
530 tcg_gen_sub_i32(cpu_NF
, t0_32
, t1_32
);
531 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
532 tcg_gen_setcond_i32(TCG_COND_GEU
, cpu_CF
, t0_32
, t1_32
);
533 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0_32
);
534 tmp
= tcg_temp_new_i32();
535 tcg_gen_xor_i32(tmp
, t0_32
, t1_32
);
536 tcg_temp_free_i32(t0_32
);
537 tcg_temp_free_i32(t1_32
);
538 tcg_gen_and_i32(cpu_VF
, cpu_VF
, tmp
);
539 tcg_temp_free_i32(tmp
);
540 tcg_gen_extu_i32_i64(dest
, cpu_NF
);
544 /* dest = T0 + T1 + CF; do not compute flags. */
545 static void gen_adc(int sf
, TCGv_i64 dest
, TCGv_i64 t0
, TCGv_i64 t1
)
547 TCGv_i64 flag
= tcg_temp_new_i64();
548 tcg_gen_extu_i32_i64(flag
, cpu_CF
);
549 tcg_gen_add_i64(dest
, t0
, t1
);
550 tcg_gen_add_i64(dest
, dest
, flag
);
551 tcg_temp_free_i64(flag
);
554 tcg_gen_ext32u_i64(dest
, dest
);
558 /* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
559 static void gen_adc_CC(int sf
, TCGv_i64 dest
, TCGv_i64 t0
, TCGv_i64 t1
)
562 TCGv_i64 result
, cf_64
, vf_64
, tmp
;
563 result
= tcg_temp_new_i64();
564 cf_64
= tcg_temp_new_i64();
565 vf_64
= tcg_temp_new_i64();
566 tmp
= tcg_const_i64(0);
568 tcg_gen_extu_i32_i64(cf_64
, cpu_CF
);
569 tcg_gen_add2_i64(result
, cf_64
, t0
, tmp
, cf_64
, tmp
);
570 tcg_gen_add2_i64(result
, cf_64
, result
, cf_64
, t1
, tmp
);
571 tcg_gen_trunc_i64_i32(cpu_CF
, cf_64
);
572 gen_set_NZ64(result
);
574 tcg_gen_xor_i64(vf_64
, result
, t0
);
575 tcg_gen_xor_i64(tmp
, t0
, t1
);
576 tcg_gen_andc_i64(vf_64
, vf_64
, tmp
);
577 tcg_gen_shri_i64(vf_64
, vf_64
, 32);
578 tcg_gen_trunc_i64_i32(cpu_VF
, vf_64
);
580 tcg_gen_mov_i64(dest
, result
);
582 tcg_temp_free_i64(tmp
);
583 tcg_temp_free_i64(vf_64
);
584 tcg_temp_free_i64(cf_64
);
585 tcg_temp_free_i64(result
);
587 TCGv_i32 t0_32
, t1_32
, tmp
;
588 t0_32
= tcg_temp_new_i32();
589 t1_32
= tcg_temp_new_i32();
590 tmp
= tcg_const_i32(0);
592 tcg_gen_trunc_i64_i32(t0_32
, t0
);
593 tcg_gen_trunc_i64_i32(t1_32
, t1
);
594 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, t0_32
, tmp
, cpu_CF
, tmp
);
595 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, cpu_NF
, cpu_CF
, t1_32
, tmp
);
597 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
598 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0_32
);
599 tcg_gen_xor_i32(tmp
, t0_32
, t1_32
);
600 tcg_gen_andc_i32(cpu_VF
, cpu_VF
, tmp
);
601 tcg_gen_extu_i32_i64(dest
, cpu_NF
);
603 tcg_temp_free_i32(tmp
);
604 tcg_temp_free_i32(t1_32
);
605 tcg_temp_free_i32(t0_32
);
610 * Load/Store generators
614 * Store from GPR register to memory
616 static void do_gpr_st(DisasContext
*s
, TCGv_i64 source
,
617 TCGv_i64 tcg_addr
, int size
)
620 tcg_gen_qemu_st_i64(source
, tcg_addr
, get_mem_index(s
), MO_TE
+ size
);
624 * Load from memory to GPR register
626 static void do_gpr_ld(DisasContext
*s
, TCGv_i64 dest
, TCGv_i64 tcg_addr
,
627 int size
, bool is_signed
, bool extend
)
629 TCGMemOp memop
= MO_TE
+ size
;
637 tcg_gen_qemu_ld_i64(dest
, tcg_addr
, get_mem_index(s
), memop
);
639 if (extend
&& is_signed
) {
641 tcg_gen_ext32u_i64(dest
, dest
);
646 * Store from FP register to memory
648 static void do_fp_st(DisasContext
*s
, int srcidx
, TCGv_i64 tcg_addr
, int size
)
650 /* This writes the bottom N bits of a 128 bit wide vector to memory */
651 TCGv_i64 tmp
= tcg_temp_new_i64();
652 tcg_gen_ld_i64(tmp
, cpu_env
, fp_reg_offset(srcidx
, MO_64
));
654 tcg_gen_qemu_st_i64(tmp
, tcg_addr
, get_mem_index(s
), MO_TE
+ size
);
656 TCGv_i64 tcg_hiaddr
= tcg_temp_new_i64();
657 tcg_gen_qemu_st_i64(tmp
, tcg_addr
, get_mem_index(s
), MO_TEQ
);
658 tcg_gen_qemu_st64(tmp
, tcg_addr
, get_mem_index(s
));
659 tcg_gen_ld_i64(tmp
, cpu_env
, fp_reg_hi_offset(srcidx
));
660 tcg_gen_addi_i64(tcg_hiaddr
, tcg_addr
, 8);
661 tcg_gen_qemu_st_i64(tmp
, tcg_hiaddr
, get_mem_index(s
), MO_TEQ
);
662 tcg_temp_free_i64(tcg_hiaddr
);
665 tcg_temp_free_i64(tmp
);
669 * Load from memory to FP register
671 static void do_fp_ld(DisasContext
*s
, int destidx
, TCGv_i64 tcg_addr
, int size
)
673 /* This always zero-extends and writes to a full 128 bit wide vector */
674 TCGv_i64 tmplo
= tcg_temp_new_i64();
678 TCGMemOp memop
= MO_TE
+ size
;
679 tmphi
= tcg_const_i64(0);
680 tcg_gen_qemu_ld_i64(tmplo
, tcg_addr
, get_mem_index(s
), memop
);
683 tmphi
= tcg_temp_new_i64();
684 tcg_hiaddr
= tcg_temp_new_i64();
686 tcg_gen_qemu_ld_i64(tmplo
, tcg_addr
, get_mem_index(s
), MO_TEQ
);
687 tcg_gen_addi_i64(tcg_hiaddr
, tcg_addr
, 8);
688 tcg_gen_qemu_ld_i64(tmphi
, tcg_hiaddr
, get_mem_index(s
), MO_TEQ
);
689 tcg_temp_free_i64(tcg_hiaddr
);
692 tcg_gen_st_i64(tmplo
, cpu_env
, fp_reg_offset(destidx
, MO_64
));
693 tcg_gen_st_i64(tmphi
, cpu_env
, fp_reg_hi_offset(destidx
));
695 tcg_temp_free_i64(tmplo
);
696 tcg_temp_free_i64(tmphi
);
700 * Vector load/store helpers.
702 * The principal difference between this and a FP load is that we don't
703 * zero extend as we are filling a partial chunk of the vector register.
704 * These functions don't support 128 bit loads/stores, which would be
705 * normal load/store operations.
707 * The _i32 versions are useful when operating on 32 bit quantities
708 * (eg for floating point single or using Neon helper functions).
711 /* Get value of an element within a vector register */
712 static void read_vec_element(DisasContext
*s
, TCGv_i64 tcg_dest
, int srcidx
,
713 int element
, TCGMemOp memop
)
715 int vect_off
= vec_reg_offset(srcidx
, element
, memop
& MO_SIZE
);
718 tcg_gen_ld8u_i64(tcg_dest
, cpu_env
, vect_off
);
721 tcg_gen_ld16u_i64(tcg_dest
, cpu_env
, vect_off
);
724 tcg_gen_ld32u_i64(tcg_dest
, cpu_env
, vect_off
);
727 tcg_gen_ld8s_i64(tcg_dest
, cpu_env
, vect_off
);
730 tcg_gen_ld16s_i64(tcg_dest
, cpu_env
, vect_off
);
733 tcg_gen_ld32s_i64(tcg_dest
, cpu_env
, vect_off
);
737 tcg_gen_ld_i64(tcg_dest
, cpu_env
, vect_off
);
740 g_assert_not_reached();
744 static void read_vec_element_i32(DisasContext
*s
, TCGv_i32 tcg_dest
, int srcidx
,
745 int element
, TCGMemOp memop
)
747 int vect_off
= vec_reg_offset(srcidx
, element
, memop
& MO_SIZE
);
750 tcg_gen_ld8u_i32(tcg_dest
, cpu_env
, vect_off
);
753 tcg_gen_ld16u_i32(tcg_dest
, cpu_env
, vect_off
);
756 tcg_gen_ld8s_i32(tcg_dest
, cpu_env
, vect_off
);
759 tcg_gen_ld16s_i32(tcg_dest
, cpu_env
, vect_off
);
763 tcg_gen_ld_i32(tcg_dest
, cpu_env
, vect_off
);
766 g_assert_not_reached();
770 /* Set value of an element within a vector register */
771 static void write_vec_element(DisasContext
*s
, TCGv_i64 tcg_src
, int destidx
,
772 int element
, TCGMemOp memop
)
774 int vect_off
= vec_reg_offset(destidx
, element
, memop
& MO_SIZE
);
777 tcg_gen_st8_i64(tcg_src
, cpu_env
, vect_off
);
780 tcg_gen_st16_i64(tcg_src
, cpu_env
, vect_off
);
783 tcg_gen_st32_i64(tcg_src
, cpu_env
, vect_off
);
786 tcg_gen_st_i64(tcg_src
, cpu_env
, vect_off
);
789 g_assert_not_reached();
793 static void write_vec_element_i32(DisasContext
*s
, TCGv_i32 tcg_src
,
794 int destidx
, int element
, TCGMemOp memop
)
796 int vect_off
= vec_reg_offset(destidx
, element
, memop
& MO_SIZE
);
799 tcg_gen_st8_i32(tcg_src
, cpu_env
, vect_off
);
802 tcg_gen_st16_i32(tcg_src
, cpu_env
, vect_off
);
805 tcg_gen_st_i32(tcg_src
, cpu_env
, vect_off
);
808 g_assert_not_reached();
812 /* Clear the high 64 bits of a 128 bit vector (in general non-quad
813 * vector ops all need to do this).
815 static void clear_vec_high(DisasContext
*s
, int rd
)
817 TCGv_i64 tcg_zero
= tcg_const_i64(0);
819 write_vec_element(s
, tcg_zero
, rd
, 1, MO_64
);
820 tcg_temp_free_i64(tcg_zero
);
823 /* Store from vector register to memory */
824 static void do_vec_st(DisasContext
*s
, int srcidx
, int element
,
825 TCGv_i64 tcg_addr
, int size
)
827 TCGMemOp memop
= MO_TE
+ size
;
828 TCGv_i64 tcg_tmp
= tcg_temp_new_i64();
830 read_vec_element(s
, tcg_tmp
, srcidx
, element
, size
);
831 tcg_gen_qemu_st_i64(tcg_tmp
, tcg_addr
, get_mem_index(s
), memop
);
833 tcg_temp_free_i64(tcg_tmp
);
836 /* Load from memory to vector register */
837 static void do_vec_ld(DisasContext
*s
, int destidx
, int element
,
838 TCGv_i64 tcg_addr
, int size
)
840 TCGMemOp memop
= MO_TE
+ size
;
841 TCGv_i64 tcg_tmp
= tcg_temp_new_i64();
843 tcg_gen_qemu_ld_i64(tcg_tmp
, tcg_addr
, get_mem_index(s
), memop
);
844 write_vec_element(s
, tcg_tmp
, destidx
, element
, size
);
846 tcg_temp_free_i64(tcg_tmp
);
850 * This utility function is for doing register extension with an
851 * optional shift. You will likely want to pass a temporary for the
852 * destination register. See DecodeRegExtend() in the ARM ARM.
854 static void ext_and_shift_reg(TCGv_i64 tcg_out
, TCGv_i64 tcg_in
,
855 int option
, unsigned int shift
)
857 int extsize
= extract32(option
, 0, 2);
858 bool is_signed
= extract32(option
, 2, 1);
863 tcg_gen_ext8s_i64(tcg_out
, tcg_in
);
866 tcg_gen_ext16s_i64(tcg_out
, tcg_in
);
869 tcg_gen_ext32s_i64(tcg_out
, tcg_in
);
872 tcg_gen_mov_i64(tcg_out
, tcg_in
);
878 tcg_gen_ext8u_i64(tcg_out
, tcg_in
);
881 tcg_gen_ext16u_i64(tcg_out
, tcg_in
);
884 tcg_gen_ext32u_i64(tcg_out
, tcg_in
);
887 tcg_gen_mov_i64(tcg_out
, tcg_in
);
893 tcg_gen_shli_i64(tcg_out
, tcg_out
, shift
);
897 static inline void gen_check_sp_alignment(DisasContext
*s
)
899 /* The AArch64 architecture mandates that (if enabled via PSTATE
900 * or SCTLR bits) there is a check that SP is 16-aligned on every
901 * SP-relative load or store (with an exception generated if it is not).
902 * In line with general QEMU practice regarding misaligned accesses,
903 * we omit these checks for the sake of guest program performance.
904 * This function is provided as a hook so we can more easily add these
905 * checks in future (possibly as a "favour catching guest program bugs
906 * over speed" user selectable option).
911 * This provides a simple table based table lookup decoder. It is
912 * intended to be used when the relevant bits for decode are too
913 * awkwardly placed and switch/if based logic would be confusing and
914 * deeply nested. Since it's a linear search through the table, tables
915 * should be kept small.
917 * It returns the first handler where insn & mask == pattern, or
918 * NULL if there is no match.
919 * The table is terminated by an empty mask (i.e. 0)
921 static inline AArch64DecodeFn
*lookup_disas_fn(const AArch64DecodeTable
*table
,
924 const AArch64DecodeTable
*tptr
= table
;
927 if ((insn
& tptr
->mask
) == tptr
->pattern
) {
928 return tptr
->disas_fn
;
936 * the instruction disassembly implemented here matches
937 * the instruction encoding classifications in chapter 3 (C3)
938 * of the ARM Architecture Reference Manual (DDI0487A_a)
941 /* C3.2.7 Unconditional branch (immediate)
943 * +----+-----------+-------------------------------------+
944 * | op | 0 0 1 0 1 | imm26 |
945 * +----+-----------+-------------------------------------+
947 static void disas_uncond_b_imm(DisasContext
*s
, uint32_t insn
)
949 uint64_t addr
= s
->pc
+ sextract32(insn
, 0, 26) * 4 - 4;
951 if (insn
& (1 << 31)) {
952 /* C5.6.26 BL Branch with link */
953 tcg_gen_movi_i64(cpu_reg(s
, 30), s
->pc
);
956 /* C5.6.20 B Branch / C5.6.26 BL Branch with link */
957 gen_goto_tb(s
, 0, addr
);
960 /* C3.2.1 Compare & branch (immediate)
961 * 31 30 25 24 23 5 4 0
962 * +----+-------------+----+---------------------+--------+
963 * | sf | 0 1 1 0 1 0 | op | imm19 | Rt |
964 * +----+-------------+----+---------------------+--------+
966 static void disas_comp_b_imm(DisasContext
*s
, uint32_t insn
)
968 unsigned int sf
, op
, rt
;
973 sf
= extract32(insn
, 31, 1);
974 op
= extract32(insn
, 24, 1); /* 0: CBZ; 1: CBNZ */
975 rt
= extract32(insn
, 0, 5);
976 addr
= s
->pc
+ sextract32(insn
, 5, 19) * 4 - 4;
978 tcg_cmp
= read_cpu_reg(s
, rt
, sf
);
979 label_match
= gen_new_label();
981 tcg_gen_brcondi_i64(op
? TCG_COND_NE
: TCG_COND_EQ
,
982 tcg_cmp
, 0, label_match
);
984 gen_goto_tb(s
, 0, s
->pc
);
985 gen_set_label(label_match
);
986 gen_goto_tb(s
, 1, addr
);
989 /* C3.2.5 Test & branch (immediate)
990 * 31 30 25 24 23 19 18 5 4 0
991 * +----+-------------+----+-------+-------------+------+
992 * | b5 | 0 1 1 0 1 1 | op | b40 | imm14 | Rt |
993 * +----+-------------+----+-------+-------------+------+
995 static void disas_test_b_imm(DisasContext
*s
, uint32_t insn
)
997 unsigned int bit_pos
, op
, rt
;
1002 bit_pos
= (extract32(insn
, 31, 1) << 5) | extract32(insn
, 19, 5);
1003 op
= extract32(insn
, 24, 1); /* 0: TBZ; 1: TBNZ */
1004 addr
= s
->pc
+ sextract32(insn
, 5, 14) * 4 - 4;
1005 rt
= extract32(insn
, 0, 5);
1007 tcg_cmp
= tcg_temp_new_i64();
1008 tcg_gen_andi_i64(tcg_cmp
, cpu_reg(s
, rt
), (1ULL << bit_pos
));
1009 label_match
= gen_new_label();
1010 tcg_gen_brcondi_i64(op
? TCG_COND_NE
: TCG_COND_EQ
,
1011 tcg_cmp
, 0, label_match
);
1012 tcg_temp_free_i64(tcg_cmp
);
1013 gen_goto_tb(s
, 0, s
->pc
);
1014 gen_set_label(label_match
);
1015 gen_goto_tb(s
, 1, addr
);
1018 /* C3.2.2 / C5.6.19 Conditional branch (immediate)
1019 * 31 25 24 23 5 4 3 0
1020 * +---------------+----+---------------------+----+------+
1021 * | 0 1 0 1 0 1 0 | o1 | imm19 | o0 | cond |
1022 * +---------------+----+---------------------+----+------+
1024 static void disas_cond_b_imm(DisasContext
*s
, uint32_t insn
)
1029 if ((insn
& (1 << 4)) || (insn
& (1 << 24))) {
1030 unallocated_encoding(s
);
1033 addr
= s
->pc
+ sextract32(insn
, 5, 19) * 4 - 4;
1034 cond
= extract32(insn
, 0, 4);
1037 /* genuinely conditional branches */
1038 int label_match
= gen_new_label();
1039 arm_gen_test_cc(cond
, label_match
);
1040 gen_goto_tb(s
, 0, s
->pc
);
1041 gen_set_label(label_match
);
1042 gen_goto_tb(s
, 1, addr
);
1044 /* 0xe and 0xf are both "always" conditions */
1045 gen_goto_tb(s
, 0, addr
);
1050 static void handle_hint(DisasContext
*s
, uint32_t insn
,
1051 unsigned int op1
, unsigned int op2
, unsigned int crm
)
1053 unsigned int selector
= crm
<< 3 | op2
;
1056 unallocated_encoding(s
);
1068 /* we treat all as NOP at least for now */
1071 /* default specified as NOP equivalent */
1076 static void gen_clrex(DisasContext
*s
, uint32_t insn
)
1078 tcg_gen_movi_i64(cpu_exclusive_addr
, -1);
1081 /* CLREX, DSB, DMB, ISB */
1082 static void handle_sync(DisasContext
*s
, uint32_t insn
,
1083 unsigned int op1
, unsigned int op2
, unsigned int crm
)
1086 unallocated_encoding(s
);
1097 /* We don't emulate caches so barriers are no-ops */
1100 unallocated_encoding(s
);
1105 /* C5.6.130 MSR (immediate) - move immediate to processor state field */
1106 static void handle_msr_i(DisasContext
*s
, uint32_t insn
,
1107 unsigned int op1
, unsigned int op2
, unsigned int crm
)
1109 unsupported_encoding(s
, insn
);
1112 static void gen_get_nzcv(TCGv_i64 tcg_rt
)
1114 TCGv_i32 tmp
= tcg_temp_new_i32();
1115 TCGv_i32 nzcv
= tcg_temp_new_i32();
1117 /* build bit 31, N */
1118 tcg_gen_andi_i32(nzcv
, cpu_NF
, (1 << 31));
1119 /* build bit 30, Z */
1120 tcg_gen_setcondi_i32(TCG_COND_EQ
, tmp
, cpu_ZF
, 0);
1121 tcg_gen_deposit_i32(nzcv
, nzcv
, tmp
, 30, 1);
1122 /* build bit 29, C */
1123 tcg_gen_deposit_i32(nzcv
, nzcv
, cpu_CF
, 29, 1);
1124 /* build bit 28, V */
1125 tcg_gen_shri_i32(tmp
, cpu_VF
, 31);
1126 tcg_gen_deposit_i32(nzcv
, nzcv
, tmp
, 28, 1);
1127 /* generate result */
1128 tcg_gen_extu_i32_i64(tcg_rt
, nzcv
);
1130 tcg_temp_free_i32(nzcv
);
1131 tcg_temp_free_i32(tmp
);
1134 static void gen_set_nzcv(TCGv_i64 tcg_rt
)
1137 TCGv_i32 nzcv
= tcg_temp_new_i32();
1139 /* take NZCV from R[t] */
1140 tcg_gen_trunc_i64_i32(nzcv
, tcg_rt
);
1143 tcg_gen_andi_i32(cpu_NF
, nzcv
, (1 << 31));
1145 tcg_gen_andi_i32(cpu_ZF
, nzcv
, (1 << 30));
1146 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_ZF
, cpu_ZF
, 0);
1148 tcg_gen_andi_i32(cpu_CF
, nzcv
, (1 << 29));
1149 tcg_gen_shri_i32(cpu_CF
, cpu_CF
, 29);
1151 tcg_gen_andi_i32(cpu_VF
, nzcv
, (1 << 28));
1152 tcg_gen_shli_i32(cpu_VF
, cpu_VF
, 3);
1153 tcg_temp_free_i32(nzcv
);
1156 /* C5.6.129 MRS - move from system register
1157 * C5.6.131 MSR (register) - move to system register
1160 * These are all essentially the same insn in 'read' and 'write'
1161 * versions, with varying op0 fields.
1163 static void handle_sys(DisasContext
*s
, uint32_t insn
, bool isread
,
1164 unsigned int op0
, unsigned int op1
, unsigned int op2
,
1165 unsigned int crn
, unsigned int crm
, unsigned int rt
)
1167 const ARMCPRegInfo
*ri
;
1170 ri
= get_arm_cp_reginfo(s
->cp_regs
,
1171 ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP
,
1172 crn
, crm
, op0
, op1
, op2
));
1175 /* Unknown register */
1176 unallocated_encoding(s
);
1180 /* Check access permissions */
1181 if (!cp_access_ok(s
->current_pl
, ri
, isread
)) {
1182 unallocated_encoding(s
);
1186 /* Handle special cases first */
1187 switch (ri
->type
& ~(ARM_CP_FLAG_MASK
& ~ARM_CP_SPECIAL
)) {
1191 tcg_rt
= cpu_reg(s
, rt
);
1193 gen_get_nzcv(tcg_rt
);
1195 gen_set_nzcv(tcg_rt
);
1202 if (use_icount
&& (ri
->type
& ARM_CP_IO
)) {
1206 tcg_rt
= cpu_reg(s
, rt
);
1209 if (ri
->type
& ARM_CP_CONST
) {
1210 tcg_gen_movi_i64(tcg_rt
, ri
->resetvalue
);
1211 } else if (ri
->readfn
) {
1213 gen_a64_set_pc_im(s
->pc
- 4);
1214 tmpptr
= tcg_const_ptr(ri
);
1215 gen_helper_get_cp_reg64(tcg_rt
, cpu_env
, tmpptr
);
1216 tcg_temp_free_ptr(tmpptr
);
1218 tcg_gen_ld_i64(tcg_rt
, cpu_env
, ri
->fieldoffset
);
1221 if (ri
->type
& ARM_CP_CONST
) {
1222 /* If not forbidden by access permissions, treat as WI */
1224 } else if (ri
->writefn
) {
1226 gen_a64_set_pc_im(s
->pc
- 4);
1227 tmpptr
= tcg_const_ptr(ri
);
1228 gen_helper_set_cp_reg64(cpu_env
, tmpptr
, tcg_rt
);
1229 tcg_temp_free_ptr(tmpptr
);
1231 tcg_gen_st_i64(tcg_rt
, cpu_env
, ri
->fieldoffset
);
1235 if (use_icount
&& (ri
->type
& ARM_CP_IO
)) {
1236 /* I/O operations must end the TB here (whether read or write) */
1238 s
->is_jmp
= DISAS_UPDATE
;
1239 } else if (!isread
&& !(ri
->type
& ARM_CP_SUPPRESS_TB_END
)) {
1240 /* We default to ending the TB on a coprocessor register write,
1241 * but allow this to be suppressed by the register definition
1242 * (usually only necessary to work around guest bugs).
1244 s
->is_jmp
= DISAS_UPDATE
;
1249 * 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
1250 * +---------------------+---+-----+-----+-------+-------+-----+------+
1251 * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 | CRn | CRm | op2 | Rt |
1252 * +---------------------+---+-----+-----+-------+-------+-----+------+
1254 static void disas_system(DisasContext
*s
, uint32_t insn
)
1256 unsigned int l
, op0
, op1
, crn
, crm
, op2
, rt
;
1257 l
= extract32(insn
, 21, 1);
1258 op0
= extract32(insn
, 19, 2);
1259 op1
= extract32(insn
, 16, 3);
1260 crn
= extract32(insn
, 12, 4);
1261 crm
= extract32(insn
, 8, 4);
1262 op2
= extract32(insn
, 5, 3);
1263 rt
= extract32(insn
, 0, 5);
1266 if (l
|| rt
!= 31) {
1267 unallocated_encoding(s
);
1271 case 2: /* C5.6.68 HINT */
1272 handle_hint(s
, insn
, op1
, op2
, crm
);
1274 case 3: /* CLREX, DSB, DMB, ISB */
1275 handle_sync(s
, insn
, op1
, op2
, crm
);
1277 case 4: /* C5.6.130 MSR (immediate) */
1278 handle_msr_i(s
, insn
, op1
, op2
, crm
);
1281 unallocated_encoding(s
);
1286 handle_sys(s
, insn
, l
, op0
, op1
, op2
, crn
, crm
, rt
);
1289 /* C3.2.3 Exception generation
1291 * 31 24 23 21 20 5 4 2 1 0
1292 * +-----------------+-----+------------------------+-----+----+
1293 * | 1 1 0 1 0 1 0 0 | opc | imm16 | op2 | LL |
1294 * +-----------------------+------------------------+----------+
1296 static void disas_exc(DisasContext
*s
, uint32_t insn
)
1298 int opc
= extract32(insn
, 21, 3);
1299 int op2_ll
= extract32(insn
, 0, 5);
1303 /* SVC, HVC, SMC; since we don't support the Virtualization
1304 * or TrustZone extensions these all UNDEF except SVC.
1307 unallocated_encoding(s
);
1310 gen_exception_insn(s
, 0, EXCP_SWI
);
1314 unallocated_encoding(s
);
1318 gen_exception_insn(s
, 0, EXCP_BKPT
);
1322 unallocated_encoding(s
);
1326 unsupported_encoding(s
, insn
);
1329 if (op2_ll
< 1 || op2_ll
> 3) {
1330 unallocated_encoding(s
);
1333 /* DCPS1, DCPS2, DCPS3 */
1334 unsupported_encoding(s
, insn
);
1337 unallocated_encoding(s
);
1342 /* C3.2.7 Unconditional branch (register)
1343 * 31 25 24 21 20 16 15 10 9 5 4 0
1344 * +---------------+-------+-------+-------+------+-------+
1345 * | 1 1 0 1 0 1 1 | opc | op2 | op3 | Rn | op4 |
1346 * +---------------+-------+-------+-------+------+-------+
1348 static void disas_uncond_b_reg(DisasContext
*s
, uint32_t insn
)
1350 unsigned int opc
, op2
, op3
, rn
, op4
;
1352 opc
= extract32(insn
, 21, 4);
1353 op2
= extract32(insn
, 16, 5);
1354 op3
= extract32(insn
, 10, 6);
1355 rn
= extract32(insn
, 5, 5);
1356 op4
= extract32(insn
, 0, 5);
1358 if (op4
!= 0x0 || op3
!= 0x0 || op2
!= 0x1f) {
1359 unallocated_encoding(s
);
1368 tcg_gen_movi_i64(cpu_reg(s
, 30), s
->pc
);
1373 unallocated_encoding(s
);
1375 unsupported_encoding(s
, insn
);
1379 unallocated_encoding(s
);
1383 tcg_gen_mov_i64(cpu_pc
, cpu_reg(s
, rn
));
1384 s
->is_jmp
= DISAS_JUMP
;
1387 /* C3.2 Branches, exception generating and system instructions */
1388 static void disas_b_exc_sys(DisasContext
*s
, uint32_t insn
)
1390 switch (extract32(insn
, 25, 7)) {
1391 case 0x0a: case 0x0b:
1392 case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
1393 disas_uncond_b_imm(s
, insn
);
1395 case 0x1a: case 0x5a: /* Compare & branch (immediate) */
1396 disas_comp_b_imm(s
, insn
);
1398 case 0x1b: case 0x5b: /* Test & branch (immediate) */
1399 disas_test_b_imm(s
, insn
);
1401 case 0x2a: /* Conditional branch (immediate) */
1402 disas_cond_b_imm(s
, insn
);
1404 case 0x6a: /* Exception generation / System */
1405 if (insn
& (1 << 24)) {
1406 disas_system(s
, insn
);
1411 case 0x6b: /* Unconditional branch (register) */
1412 disas_uncond_b_reg(s
, insn
);
1415 unallocated_encoding(s
);
1421 * Load/Store exclusive instructions are implemented by remembering
1422 * the value/address loaded, and seeing if these are the same
1423 * when the store is performed. This is not actually the architecturally
1424 * mandated semantics, but it works for typical guest code sequences
1425 * and avoids having to monitor regular stores.
1427 * In system emulation mode only one CPU will be running at once, so
1428 * this sequence is effectively atomic. In user emulation mode we
1429 * throw an exception and handle the atomic operation elsewhere.
1431 static void gen_load_exclusive(DisasContext
*s
, int rt
, int rt2
,
1432 TCGv_i64 addr
, int size
, bool is_pair
)
1434 TCGv_i64 tmp
= tcg_temp_new_i64();
1435 TCGMemOp memop
= MO_TE
+ size
;
1437 g_assert(size
<= 3);
1438 tcg_gen_qemu_ld_i64(tmp
, addr
, get_mem_index(s
), memop
);
1441 TCGv_i64 addr2
= tcg_temp_new_i64();
1442 TCGv_i64 hitmp
= tcg_temp_new_i64();
1444 g_assert(size
>= 2);
1445 tcg_gen_addi_i64(addr2
, addr
, 1 << size
);
1446 tcg_gen_qemu_ld_i64(hitmp
, addr2
, get_mem_index(s
), memop
);
1447 tcg_temp_free_i64(addr2
);
1448 tcg_gen_mov_i64(cpu_exclusive_high
, hitmp
);
1449 tcg_gen_mov_i64(cpu_reg(s
, rt2
), hitmp
);
1450 tcg_temp_free_i64(hitmp
);
1453 tcg_gen_mov_i64(cpu_exclusive_val
, tmp
);
1454 tcg_gen_mov_i64(cpu_reg(s
, rt
), tmp
);
1456 tcg_temp_free_i64(tmp
);
1457 tcg_gen_mov_i64(cpu_exclusive_addr
, addr
);
1460 #ifdef CONFIG_USER_ONLY
1461 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
1462 TCGv_i64 addr
, int size
, int is_pair
)
1464 tcg_gen_mov_i64(cpu_exclusive_test
, addr
);
1465 tcg_gen_movi_i32(cpu_exclusive_info
,
1466 size
| is_pair
<< 2 | (rd
<< 4) | (rt
<< 9) | (rt2
<< 14));
1467 gen_exception_insn(s
, 4, EXCP_STREX
);
1470 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
1471 TCGv_i64 addr
, int size
, int is_pair
)
1473 qemu_log_mask(LOG_UNIMP
,
1474 "%s:%d: system mode store_exclusive unsupported "
1475 "at pc=%016" PRIx64
"\n",
1476 __FILE__
, __LINE__
, s
->pc
- 4);
1480 /* C3.3.6 Load/store exclusive
1482 * 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
1483 * +-----+-------------+----+---+----+------+----+-------+------+------+
1484 * | sz | 0 0 1 0 0 0 | o2 | L | o1 | Rs | o0 | Rt2 | Rn | Rt |
1485 * +-----+-------------+----+---+----+------+----+-------+------+------+
1487 * sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
1488 * L: 0 -> store, 1 -> load
1489 * o2: 0 -> exclusive, 1 -> not
1490 * o1: 0 -> single register, 1 -> register pair
1491 * o0: 1 -> load-acquire/store-release, 0 -> not
1493 * o0 == 0 AND o2 == 1 is un-allocated
1494 * o1 == 1 is un-allocated except for 32 and 64 bit sizes
1496 static void disas_ldst_excl(DisasContext
*s
, uint32_t insn
)
1498 int rt
= extract32(insn
, 0, 5);
1499 int rn
= extract32(insn
, 5, 5);
1500 int rt2
= extract32(insn
, 10, 5);
1501 int is_lasr
= extract32(insn
, 15, 1);
1502 int rs
= extract32(insn
, 16, 5);
1503 int is_pair
= extract32(insn
, 21, 1);
1504 int is_store
= !extract32(insn
, 22, 1);
1505 int is_excl
= !extract32(insn
, 23, 1);
1506 int size
= extract32(insn
, 30, 2);
1509 if ((!is_excl
&& !is_lasr
) ||
1510 (is_pair
&& size
< 2)) {
1511 unallocated_encoding(s
);
1516 gen_check_sp_alignment(s
);
1518 tcg_addr
= read_cpu_reg_sp(s
, rn
, 1);
1520 /* Note that since TCG is single threaded load-acquire/store-release
1521 * semantics require no extra if (is_lasr) { ... } handling.
1526 gen_load_exclusive(s
, rt
, rt2
, tcg_addr
, size
, is_pair
);
1528 gen_store_exclusive(s
, rs
, rt
, rt2
, tcg_addr
, size
, is_pair
);
1531 TCGv_i64 tcg_rt
= cpu_reg(s
, rt
);
1533 do_gpr_st(s
, tcg_rt
, tcg_addr
, size
);
1535 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, false, false);
1538 TCGv_i64 tcg_rt2
= cpu_reg(s
, rt
);
1539 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, 1 << size
);
1541 do_gpr_st(s
, tcg_rt2
, tcg_addr
, size
);
1543 do_gpr_ld(s
, tcg_rt2
, tcg_addr
, size
, false, false);
1550 * C3.3.5 Load register (literal)
1552 * 31 30 29 27 26 25 24 23 5 4 0
1553 * +-----+-------+---+-----+-------------------+-------+
1554 * | opc | 0 1 1 | V | 0 0 | imm19 | Rt |
1555 * +-----+-------+---+-----+-------------------+-------+
1557 * V: 1 -> vector (simd/fp)
1558 * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
1559 * 10-> 32 bit signed, 11 -> prefetch
1560 * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
1562 static void disas_ld_lit(DisasContext
*s
, uint32_t insn
)
1564 int rt
= extract32(insn
, 0, 5);
1565 int64_t imm
= sextract32(insn
, 5, 19) << 2;
1566 bool is_vector
= extract32(insn
, 26, 1);
1567 int opc
= extract32(insn
, 30, 2);
1568 bool is_signed
= false;
1570 TCGv_i64 tcg_rt
, tcg_addr
;
1574 unallocated_encoding(s
);
1580 /* PRFM (literal) : prefetch */
1583 size
= 2 + extract32(opc
, 0, 1);
1584 is_signed
= extract32(opc
, 1, 1);
1587 tcg_rt
= cpu_reg(s
, rt
);
1589 tcg_addr
= tcg_const_i64((s
->pc
- 4) + imm
);
1591 do_fp_ld(s
, rt
, tcg_addr
, size
);
1593 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, is_signed
, false);
1595 tcg_temp_free_i64(tcg_addr
);
1599 * C5.6.80 LDNP (Load Pair - non-temporal hint)
1600 * C5.6.81 LDP (Load Pair - non vector)
1601 * C5.6.82 LDPSW (Load Pair Signed Word - non vector)
1602 * C5.6.176 STNP (Store Pair - non-temporal hint)
1603 * C5.6.177 STP (Store Pair - non vector)
1604 * C6.3.165 LDNP (Load Pair of SIMD&FP - non-temporal hint)
1605 * C6.3.165 LDP (Load Pair of SIMD&FP)
1606 * C6.3.284 STNP (Store Pair of SIMD&FP - non-temporal hint)
1607 * C6.3.284 STP (Store Pair of SIMD&FP)
1609 * 31 30 29 27 26 25 24 23 22 21 15 14 10 9 5 4 0
1610 * +-----+-------+---+---+-------+---+-----------------------------+
1611 * | opc | 1 0 1 | V | 0 | index | L | imm7 | Rt2 | Rn | Rt |
1612 * +-----+-------+---+---+-------+---+-------+-------+------+------+
1614 * opc: LDP/STP/LDNP/STNP 00 -> 32 bit, 10 -> 64 bit
1616 * LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
1617 * V: 0 -> GPR, 1 -> Vector
1618 * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
1619 * 10 -> signed offset, 11 -> pre-index
1620 * L: 0 -> Store 1 -> Load
1622 * Rt, Rt2 = GPR or SIMD registers to be stored
1623 * Rn = general purpose register containing address
1624 * imm7 = signed offset (multiple of 4 or 8 depending on size)
1626 static void disas_ldst_pair(DisasContext
*s
, uint32_t insn
)
1628 int rt
= extract32(insn
, 0, 5);
1629 int rn
= extract32(insn
, 5, 5);
1630 int rt2
= extract32(insn
, 10, 5);
1631 int64_t offset
= sextract32(insn
, 15, 7);
1632 int index
= extract32(insn
, 23, 2);
1633 bool is_vector
= extract32(insn
, 26, 1);
1634 bool is_load
= extract32(insn
, 22, 1);
1635 int opc
= extract32(insn
, 30, 2);
1637 bool is_signed
= false;
1638 bool postindex
= false;
1641 TCGv_i64 tcg_addr
; /* calculated address */
1645 unallocated_encoding(s
);
1652 size
= 2 + extract32(opc
, 1, 1);
1653 is_signed
= extract32(opc
, 0, 1);
1654 if (!is_load
&& is_signed
) {
1655 unallocated_encoding(s
);
1661 case 1: /* post-index */
1666 /* signed offset with "non-temporal" hint. Since we don't emulate
1667 * caches we don't care about hints to the cache system about
1668 * data access patterns, and handle this identically to plain
1672 /* There is no non-temporal-hint version of LDPSW */
1673 unallocated_encoding(s
);
1678 case 2: /* signed offset, rn not updated */
1681 case 3: /* pre-index */
1690 gen_check_sp_alignment(s
);
1693 tcg_addr
= read_cpu_reg_sp(s
, rn
, 1);
1696 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, offset
);
1701 do_fp_ld(s
, rt
, tcg_addr
, size
);
1703 do_fp_st(s
, rt
, tcg_addr
, size
);
1706 TCGv_i64 tcg_rt
= cpu_reg(s
, rt
);
1708 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, is_signed
, false);
1710 do_gpr_st(s
, tcg_rt
, tcg_addr
, size
);
1713 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, 1 << size
);
1716 do_fp_ld(s
, rt2
, tcg_addr
, size
);
1718 do_fp_st(s
, rt2
, tcg_addr
, size
);
1721 TCGv_i64 tcg_rt2
= cpu_reg(s
, rt2
);
1723 do_gpr_ld(s
, tcg_rt2
, tcg_addr
, size
, is_signed
, false);
1725 do_gpr_st(s
, tcg_rt2
, tcg_addr
, size
);
1731 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, offset
- (1 << size
));
1733 tcg_gen_subi_i64(tcg_addr
, tcg_addr
, 1 << size
);
1735 tcg_gen_mov_i64(cpu_reg_sp(s
, rn
), tcg_addr
);
1740 * C3.3.8 Load/store (immediate post-indexed)
1741 * C3.3.9 Load/store (immediate pre-indexed)
1742 * C3.3.12 Load/store (unscaled immediate)
1744 * 31 30 29 27 26 25 24 23 22 21 20 12 11 10 9 5 4 0
1745 * +----+-------+---+-----+-----+---+--------+-----+------+------+
1746 * |size| 1 1 1 | V | 0 0 | opc | 0 | imm9 | idx | Rn | Rt |
1747 * +----+-------+---+-----+-----+---+--------+-----+------+------+
1749 * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
1750 * V = 0 -> non-vector
1751 * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
1752 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1754 static void disas_ldst_reg_imm9(DisasContext
*s
, uint32_t insn
)
1756 int rt
= extract32(insn
, 0, 5);
1757 int rn
= extract32(insn
, 5, 5);
1758 int imm9
= sextract32(insn
, 12, 9);
1759 int opc
= extract32(insn
, 22, 2);
1760 int size
= extract32(insn
, 30, 2);
1761 int idx
= extract32(insn
, 10, 2);
1762 bool is_signed
= false;
1763 bool is_store
= false;
1764 bool is_extended
= false;
1765 bool is_vector
= extract32(insn
, 26, 1);
1772 size
|= (opc
& 2) << 1;
1774 unallocated_encoding(s
);
1777 is_store
= ((opc
& 1) == 0);
1779 if (size
== 3 && opc
== 2) {
1780 /* PRFM - prefetch */
1783 if (opc
== 3 && size
> 1) {
1784 unallocated_encoding(s
);
1787 is_store
= (opc
== 0);
1788 is_signed
= opc
& (1<<1);
1789 is_extended
= (size
< 3) && (opc
& 1);
1811 gen_check_sp_alignment(s
);
1813 tcg_addr
= read_cpu_reg_sp(s
, rn
, 1);
1816 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, imm9
);
1821 do_fp_st(s
, rt
, tcg_addr
, size
);
1823 do_fp_ld(s
, rt
, tcg_addr
, size
);
1826 TCGv_i64 tcg_rt
= cpu_reg(s
, rt
);
1828 do_gpr_st(s
, tcg_rt
, tcg_addr
, size
);
1830 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, is_signed
, is_extended
);
1835 TCGv_i64 tcg_rn
= cpu_reg_sp(s
, rn
);
1837 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, imm9
);
1839 tcg_gen_mov_i64(tcg_rn
, tcg_addr
);
1844 * C3.3.10 Load/store (register offset)
1846 * 31 30 29 27 26 25 24 23 22 21 20 16 15 13 12 11 10 9 5 4 0
1847 * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
1848 * |size| 1 1 1 | V | 0 0 | opc | 1 | Rm | opt | S| 1 0 | Rn | Rt |
1849 * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
1852 * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
1853 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1855 * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
1856 * opc<0>: 0 -> store, 1 -> load
1857 * V: 1 -> vector/simd
1858 * opt: extend encoding (see DecodeRegExtend)
1859 * S: if S=1 then scale (essentially index by sizeof(size))
1860 * Rt: register to transfer into/out of
1861 * Rn: address register or SP for base
1862 * Rm: offset register or ZR for offset
1864 static void disas_ldst_reg_roffset(DisasContext
*s
, uint32_t insn
)
1866 int rt
= extract32(insn
, 0, 5);
1867 int rn
= extract32(insn
, 5, 5);
1868 int shift
= extract32(insn
, 12, 1);
1869 int rm
= extract32(insn
, 16, 5);
1870 int opc
= extract32(insn
, 22, 2);
1871 int opt
= extract32(insn
, 13, 3);
1872 int size
= extract32(insn
, 30, 2);
1873 bool is_signed
= false;
1874 bool is_store
= false;
1875 bool is_extended
= false;
1876 bool is_vector
= extract32(insn
, 26, 1);
1881 if (extract32(opt
, 1, 1) == 0) {
1882 unallocated_encoding(s
);
1887 size
|= (opc
& 2) << 1;
1889 unallocated_encoding(s
);
1892 is_store
= !extract32(opc
, 0, 1);
1894 if (size
== 3 && opc
== 2) {
1895 /* PRFM - prefetch */
1898 if (opc
== 3 && size
> 1) {
1899 unallocated_encoding(s
);
1902 is_store
= (opc
== 0);
1903 is_signed
= extract32(opc
, 1, 1);
1904 is_extended
= (size
< 3) && extract32(opc
, 0, 1);
1908 gen_check_sp_alignment(s
);
1910 tcg_addr
= read_cpu_reg_sp(s
, rn
, 1);
1912 tcg_rm
= read_cpu_reg(s
, rm
, 1);
1913 ext_and_shift_reg(tcg_rm
, tcg_rm
, opt
, shift
? size
: 0);
1915 tcg_gen_add_i64(tcg_addr
, tcg_addr
, tcg_rm
);
1919 do_fp_st(s
, rt
, tcg_addr
, size
);
1921 do_fp_ld(s
, rt
, tcg_addr
, size
);
1924 TCGv_i64 tcg_rt
= cpu_reg(s
, rt
);
1926 do_gpr_st(s
, tcg_rt
, tcg_addr
, size
);
1928 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, is_signed
, is_extended
);
1934 * C3.3.13 Load/store (unsigned immediate)
1936 * 31 30 29 27 26 25 24 23 22 21 10 9 5
1937 * +----+-------+---+-----+-----+------------+-------+------+
1938 * |size| 1 1 1 | V | 0 1 | opc | imm12 | Rn | Rt |
1939 * +----+-------+---+-----+-----+------------+-------+------+
1942 * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
1943 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1945 * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
1946 * opc<0>: 0 -> store, 1 -> load
1947 * Rn: base address register (inc SP)
1948 * Rt: target register
1950 static void disas_ldst_reg_unsigned_imm(DisasContext
*s
, uint32_t insn
)
1952 int rt
= extract32(insn
, 0, 5);
1953 int rn
= extract32(insn
, 5, 5);
1954 unsigned int imm12
= extract32(insn
, 10, 12);
1955 bool is_vector
= extract32(insn
, 26, 1);
1956 int size
= extract32(insn
, 30, 2);
1957 int opc
= extract32(insn
, 22, 2);
1958 unsigned int offset
;
1963 bool is_signed
= false;
1964 bool is_extended
= false;
1967 size
|= (opc
& 2) << 1;
1969 unallocated_encoding(s
);
1972 is_store
= !extract32(opc
, 0, 1);
1974 if (size
== 3 && opc
== 2) {
1975 /* PRFM - prefetch */
1978 if (opc
== 3 && size
> 1) {
1979 unallocated_encoding(s
);
1982 is_store
= (opc
== 0);
1983 is_signed
= extract32(opc
, 1, 1);
1984 is_extended
= (size
< 3) && extract32(opc
, 0, 1);
1988 gen_check_sp_alignment(s
);
1990 tcg_addr
= read_cpu_reg_sp(s
, rn
, 1);
1991 offset
= imm12
<< size
;
1992 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, offset
);
1996 do_fp_st(s
, rt
, tcg_addr
, size
);
1998 do_fp_ld(s
, rt
, tcg_addr
, size
);
2001 TCGv_i64 tcg_rt
= cpu_reg(s
, rt
);
2003 do_gpr_st(s
, tcg_rt
, tcg_addr
, size
);
2005 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, is_signed
, is_extended
);
2010 /* Load/store register (immediate forms) */
2011 static void disas_ldst_reg_imm(DisasContext
*s
, uint32_t insn
)
2013 switch (extract32(insn
, 10, 2)) {
2014 case 0: case 1: case 3:
2015 /* Load/store register (unscaled immediate) */
2016 /* Load/store immediate pre/post-indexed */
2017 disas_ldst_reg_imm9(s
, insn
);
2020 /* Load/store register unprivileged */
2021 unsupported_encoding(s
, insn
);
2024 unallocated_encoding(s
);
2029 /* Load/store register (all forms) */
2030 static void disas_ldst_reg(DisasContext
*s
, uint32_t insn
)
2032 switch (extract32(insn
, 24, 2)) {
2034 if (extract32(insn
, 21, 1) == 1 && extract32(insn
, 10, 2) == 2) {
2035 disas_ldst_reg_roffset(s
, insn
);
2037 disas_ldst_reg_imm(s
, insn
);
2041 disas_ldst_reg_unsigned_imm(s
, insn
);
2044 unallocated_encoding(s
);
2049 /* C3.3.1 AdvSIMD load/store multiple structures
2051 * 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
2052 * +---+---+---------------+---+-------------+--------+------+------+------+
2053 * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size | Rn | Rt |
2054 * +---+---+---------------+---+-------------+--------+------+------+------+
2056 * C3.3.2 AdvSIMD load/store multiple structures (post-indexed)
2058 * 31 30 29 23 22 21 20 16 15 12 11 10 9 5 4 0
2059 * +---+---+---------------+---+---+---------+--------+------+------+------+
2060 * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 | Rm | opcode | size | Rn | Rt |
2061 * +---+---+---------------+---+---+---------+--------+------+------+------+
2063 * Rt: first (or only) SIMD&FP register to be transferred
2064 * Rn: base address or SP
2065 * Rm (post-index only): post-index register (when !31) or size dependent #imm
2067 static void disas_ldst_multiple_struct(DisasContext
*s
, uint32_t insn
)
2069 int rt
= extract32(insn
, 0, 5);
2070 int rn
= extract32(insn
, 5, 5);
2071 int size
= extract32(insn
, 10, 2);
2072 int opcode
= extract32(insn
, 12, 4);
2073 bool is_store
= !extract32(insn
, 22, 1);
2074 bool is_postidx
= extract32(insn
, 23, 1);
2075 bool is_q
= extract32(insn
, 30, 1);
2076 TCGv_i64 tcg_addr
, tcg_rn
;
2078 int ebytes
= 1 << size
;
2079 int elements
= (is_q
? 128 : 64) / (8 << size
);
2080 int rpt
; /* num iterations */
2081 int selem
; /* structure elements */
2084 if (extract32(insn
, 31, 1) || extract32(insn
, 21, 1)) {
2085 unallocated_encoding(s
);
2089 /* From the shared decode logic */
2120 unallocated_encoding(s
);
2124 if (size
== 3 && !is_q
&& selem
!= 1) {
2126 unallocated_encoding(s
);
2131 gen_check_sp_alignment(s
);
2134 tcg_rn
= cpu_reg_sp(s
, rn
);
2135 tcg_addr
= tcg_temp_new_i64();
2136 tcg_gen_mov_i64(tcg_addr
, tcg_rn
);
2138 for (r
= 0; r
< rpt
; r
++) {
2140 for (e
= 0; e
< elements
; e
++) {
2141 int tt
= (rt
+ r
) % 32;
2143 for (xs
= 0; xs
< selem
; xs
++) {
2145 do_vec_st(s
, tt
, e
, tcg_addr
, size
);
2147 do_vec_ld(s
, tt
, e
, tcg_addr
, size
);
2149 /* For non-quad operations, setting a slice of the low
2150 * 64 bits of the register clears the high 64 bits (in
2151 * the ARM ARM pseudocode this is implicit in the fact
2152 * that 'rval' is a 64 bit wide variable). We optimize
2153 * by noticing that we only need to do this the first
2154 * time we touch a register.
2156 if (!is_q
&& e
== 0 && (r
== 0 || xs
== selem
- 1)) {
2157 clear_vec_high(s
, tt
);
2160 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, ebytes
);
2167 int rm
= extract32(insn
, 16, 5);
2169 tcg_gen_mov_i64(tcg_rn
, tcg_addr
);
2171 tcg_gen_add_i64(tcg_rn
, tcg_rn
, cpu_reg(s
, rm
));
2174 tcg_temp_free_i64(tcg_addr
);
2177 /* C3.3.3 AdvSIMD load/store single structure
2179 * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
2180 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2181 * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size | Rn | Rt |
2182 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2184 * C3.3.4 AdvSIMD load/store single structure (post-indexed)
2186 * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
2187 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2188 * | 0 | Q | 0 0 1 1 0 1 1 | L R | Rm | opc | S | size | Rn | Rt |
2189 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2191 * Rt: first (or only) SIMD&FP register to be transferred
2192 * Rn: base address or SP
2193 * Rm (post-index only): post-index register (when !31) or size dependent #imm
2194 * index = encoded in Q:S:size dependent on size
2196 * lane_size = encoded in R, opc
2197 * transfer width = encoded in opc, S, size
2199 static void disas_ldst_single_struct(DisasContext
*s
, uint32_t insn
)
2201 int rt
= extract32(insn
, 0, 5);
2202 int rn
= extract32(insn
, 5, 5);
2203 int size
= extract32(insn
, 10, 2);
2204 int S
= extract32(insn
, 12, 1);
2205 int opc
= extract32(insn
, 13, 3);
2206 int R
= extract32(insn
, 21, 1);
2207 int is_load
= extract32(insn
, 22, 1);
2208 int is_postidx
= extract32(insn
, 23, 1);
2209 int is_q
= extract32(insn
, 30, 1);
2211 int scale
= extract32(opc
, 1, 2);
2212 int selem
= (extract32(opc
, 0, 1) << 1 | R
) + 1;
2213 bool replicate
= false;
2214 int index
= is_q
<< 3 | S
<< 2 | size
;
2216 TCGv_i64 tcg_addr
, tcg_rn
;
2220 if (!is_load
|| S
) {
2221 unallocated_encoding(s
);
2230 if (extract32(size
, 0, 1)) {
2231 unallocated_encoding(s
);
2237 if (extract32(size
, 1, 1)) {
2238 unallocated_encoding(s
);
2241 if (!extract32(size
, 0, 1)) {
2245 unallocated_encoding(s
);
2253 g_assert_not_reached();
2256 ebytes
= 1 << scale
;
2259 gen_check_sp_alignment(s
);
2262 tcg_rn
= cpu_reg_sp(s
, rn
);
2263 tcg_addr
= tcg_temp_new_i64();
2264 tcg_gen_mov_i64(tcg_addr
, tcg_rn
);
2266 for (xs
= 0; xs
< selem
; xs
++) {
2268 /* Load and replicate to all elements */
2270 TCGv_i64 tcg_tmp
= tcg_temp_new_i64();
2272 tcg_gen_qemu_ld_i64(tcg_tmp
, tcg_addr
,
2273 get_mem_index(s
), MO_TE
+ scale
);
2276 mulconst
= 0x0101010101010101ULL
;
2279 mulconst
= 0x0001000100010001ULL
;
2282 mulconst
= 0x0000000100000001ULL
;
2288 g_assert_not_reached();
2291 tcg_gen_muli_i64(tcg_tmp
, tcg_tmp
, mulconst
);
2293 write_vec_element(s
, tcg_tmp
, rt
, 0, MO_64
);
2295 write_vec_element(s
, tcg_tmp
, rt
, 1, MO_64
);
2297 clear_vec_high(s
, rt
);
2299 tcg_temp_free_i64(tcg_tmp
);
2301 /* Load/store one element per register */
2303 do_vec_ld(s
, rt
, index
, tcg_addr
, MO_TE
+ scale
);
2305 do_vec_st(s
, rt
, index
, tcg_addr
, MO_TE
+ scale
);
2308 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, ebytes
);
2313 int rm
= extract32(insn
, 16, 5);
2315 tcg_gen_mov_i64(tcg_rn
, tcg_addr
);
2317 tcg_gen_add_i64(tcg_rn
, tcg_rn
, cpu_reg(s
, rm
));
2320 tcg_temp_free_i64(tcg_addr
);
2323 /* C3.3 Loads and stores */
2324 static void disas_ldst(DisasContext
*s
, uint32_t insn
)
2326 switch (extract32(insn
, 24, 6)) {
2327 case 0x08: /* Load/store exclusive */
2328 disas_ldst_excl(s
, insn
);
2330 case 0x18: case 0x1c: /* Load register (literal) */
2331 disas_ld_lit(s
, insn
);
2333 case 0x28: case 0x29:
2334 case 0x2c: case 0x2d: /* Load/store pair (all forms) */
2335 disas_ldst_pair(s
, insn
);
2337 case 0x38: case 0x39:
2338 case 0x3c: case 0x3d: /* Load/store register (all forms) */
2339 disas_ldst_reg(s
, insn
);
2341 case 0x0c: /* AdvSIMD load/store multiple structures */
2342 disas_ldst_multiple_struct(s
, insn
);
2344 case 0x0d: /* AdvSIMD load/store single structure */
2345 disas_ldst_single_struct(s
, insn
);
2348 unallocated_encoding(s
);
2353 /* C3.4.6 PC-rel. addressing
2354 * 31 30 29 28 24 23 5 4 0
2355 * +----+-------+-----------+-------------------+------+
2356 * | op | immlo | 1 0 0 0 0 | immhi | Rd |
2357 * +----+-------+-----------+-------------------+------+
2359 static void disas_pc_rel_adr(DisasContext
*s
, uint32_t insn
)
2361 unsigned int page
, rd
;
2365 page
= extract32(insn
, 31, 1);
2366 /* SignExtend(immhi:immlo) -> offset */
2367 offset
= ((int64_t)sextract32(insn
, 5, 19) << 2) | extract32(insn
, 29, 2);
2368 rd
= extract32(insn
, 0, 5);
2372 /* ADRP (page based) */
2377 tcg_gen_movi_i64(cpu_reg(s
, rd
), base
+ offset
);
2381 * C3.4.1 Add/subtract (immediate)
2383 * 31 30 29 28 24 23 22 21 10 9 5 4 0
2384 * +--+--+--+-----------+-----+-------------+-----+-----+
2385 * |sf|op| S| 1 0 0 0 1 |shift| imm12 | Rn | Rd |
2386 * +--+--+--+-----------+-----+-------------+-----+-----+
2388 * sf: 0 -> 32bit, 1 -> 64bit
2389 * op: 0 -> add , 1 -> sub
2391 * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
2393 static void disas_add_sub_imm(DisasContext
*s
, uint32_t insn
)
2395 int rd
= extract32(insn
, 0, 5);
2396 int rn
= extract32(insn
, 5, 5);
2397 uint64_t imm
= extract32(insn
, 10, 12);
2398 int shift
= extract32(insn
, 22, 2);
2399 bool setflags
= extract32(insn
, 29, 1);
2400 bool sub_op
= extract32(insn
, 30, 1);
2401 bool is_64bit
= extract32(insn
, 31, 1);
2403 TCGv_i64 tcg_rn
= cpu_reg_sp(s
, rn
);
2404 TCGv_i64 tcg_rd
= setflags
? cpu_reg(s
, rd
) : cpu_reg_sp(s
, rd
);
2405 TCGv_i64 tcg_result
;
2414 unallocated_encoding(s
);
2418 tcg_result
= tcg_temp_new_i64();
2421 tcg_gen_subi_i64(tcg_result
, tcg_rn
, imm
);
2423 tcg_gen_addi_i64(tcg_result
, tcg_rn
, imm
);
2426 TCGv_i64 tcg_imm
= tcg_const_i64(imm
);
2428 gen_sub_CC(is_64bit
, tcg_result
, tcg_rn
, tcg_imm
);
2430 gen_add_CC(is_64bit
, tcg_result
, tcg_rn
, tcg_imm
);
2432 tcg_temp_free_i64(tcg_imm
);
2436 tcg_gen_mov_i64(tcg_rd
, tcg_result
);
2438 tcg_gen_ext32u_i64(tcg_rd
, tcg_result
);
2441 tcg_temp_free_i64(tcg_result
);
2444 /* The input should be a value in the bottom e bits (with higher
2445 * bits zero); returns that value replicated into every element
2446 * of size e in a 64 bit integer.
2448 static uint64_t bitfield_replicate(uint64_t mask
, unsigned int e
)
2458 /* Return a value with the bottom len bits set (where 0 < len <= 64) */
2459 static inline uint64_t bitmask64(unsigned int length
)
2461 assert(length
> 0 && length
<= 64);
2462 return ~0ULL >> (64 - length
);
2465 /* Simplified variant of pseudocode DecodeBitMasks() for the case where we
2466 * only require the wmask. Returns false if the imms/immr/immn are a reserved
2467 * value (ie should cause a guest UNDEF exception), and true if they are
2468 * valid, in which case the decoded bit pattern is written to result.
2470 static bool logic_imm_decode_wmask(uint64_t *result
, unsigned int immn
,
2471 unsigned int imms
, unsigned int immr
)
2474 unsigned e
, levels
, s
, r
;
2477 assert(immn
< 2 && imms
< 64 && immr
< 64);
2479 /* The bit patterns we create here are 64 bit patterns which
2480 * are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
2481 * 64 bits each. Each element contains the same value: a run
2482 * of between 1 and e-1 non-zero bits, rotated within the
2483 * element by between 0 and e-1 bits.
2485 * The element size and run length are encoded into immn (1 bit)
2486 * and imms (6 bits) as follows:
2487 * 64 bit elements: immn = 1, imms = <length of run - 1>
2488 * 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
2489 * 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
2490 * 8 bit elements: immn = 0, imms = 110 : <length of run - 1>
2491 * 4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
2492 * 2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
2493 * Notice that immn = 0, imms = 11111x is the only combination
2494 * not covered by one of the above options; this is reserved.
2495 * Further, <length of run - 1> all-ones is a reserved pattern.
2497 * In all cases the rotation is by immr % e (and immr is 6 bits).
2500 /* First determine the element size */
2501 len
= 31 - clz32((immn
<< 6) | (~imms
& 0x3f));
2503 /* This is the immn == 0, imms == 0x11111x case */
2513 /* <length of run - 1> mustn't be all-ones. */
2517 /* Create the value of one element: s+1 set bits rotated
2518 * by r within the element (which is e bits wide)...
2520 mask
= bitmask64(s
+ 1);
2521 mask
= (mask
>> r
) | (mask
<< (e
- r
));
2522 /* ...then replicate the element over the whole 64 bit value */
2523 mask
= bitfield_replicate(mask
, e
);
2528 /* C3.4.4 Logical (immediate)
2529 * 31 30 29 28 23 22 21 16 15 10 9 5 4 0
2530 * +----+-----+-------------+---+------+------+------+------+
2531 * | sf | opc | 1 0 0 1 0 0 | N | immr | imms | Rn | Rd |
2532 * +----+-----+-------------+---+------+------+------+------+
2534 static void disas_logic_imm(DisasContext
*s
, uint32_t insn
)
2536 unsigned int sf
, opc
, is_n
, immr
, imms
, rn
, rd
;
2537 TCGv_i64 tcg_rd
, tcg_rn
;
2539 bool is_and
= false;
2541 sf
= extract32(insn
, 31, 1);
2542 opc
= extract32(insn
, 29, 2);
2543 is_n
= extract32(insn
, 22, 1);
2544 immr
= extract32(insn
, 16, 6);
2545 imms
= extract32(insn
, 10, 6);
2546 rn
= extract32(insn
, 5, 5);
2547 rd
= extract32(insn
, 0, 5);
2550 unallocated_encoding(s
);
2554 if (opc
== 0x3) { /* ANDS */
2555 tcg_rd
= cpu_reg(s
, rd
);
2557 tcg_rd
= cpu_reg_sp(s
, rd
);
2559 tcg_rn
= cpu_reg(s
, rn
);
2561 if (!logic_imm_decode_wmask(&wmask
, is_n
, imms
, immr
)) {
2562 /* some immediate field values are reserved */
2563 unallocated_encoding(s
);
2568 wmask
&= 0xffffffff;
2572 case 0x3: /* ANDS */
2574 tcg_gen_andi_i64(tcg_rd
, tcg_rn
, wmask
);
2578 tcg_gen_ori_i64(tcg_rd
, tcg_rn
, wmask
);
2581 tcg_gen_xori_i64(tcg_rd
, tcg_rn
, wmask
);
2584 assert(FALSE
); /* must handle all above */
2588 if (!sf
&& !is_and
) {
2589 /* zero extend final result; we know we can skip this for AND
2590 * since the immediate had the high 32 bits clear.
2592 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
2595 if (opc
== 3) { /* ANDS */
2596 gen_logic_CC(sf
, tcg_rd
);
2601 * C3.4.5 Move wide (immediate)
2603 * 31 30 29 28 23 22 21 20 5 4 0
2604 * +--+-----+-------------+-----+----------------+------+
2605 * |sf| opc | 1 0 0 1 0 1 | hw | imm16 | Rd |
2606 * +--+-----+-------------+-----+----------------+------+
2608 * sf: 0 -> 32 bit, 1 -> 64 bit
2609 * opc: 00 -> N, 10 -> Z, 11 -> K
2610 * hw: shift/16 (0,16, and sf only 32, 48)
2612 static void disas_movw_imm(DisasContext
*s
, uint32_t insn
)
2614 int rd
= extract32(insn
, 0, 5);
2615 uint64_t imm
= extract32(insn
, 5, 16);
2616 int sf
= extract32(insn
, 31, 1);
2617 int opc
= extract32(insn
, 29, 2);
2618 int pos
= extract32(insn
, 21, 2) << 4;
2619 TCGv_i64 tcg_rd
= cpu_reg(s
, rd
);
2622 if (!sf
&& (pos
>= 32)) {
2623 unallocated_encoding(s
);
2637 tcg_gen_movi_i64(tcg_rd
, imm
);
2640 tcg_imm
= tcg_const_i64(imm
);
2641 tcg_gen_deposit_i64(tcg_rd
, tcg_rd
, tcg_imm
, pos
, 16);
2642 tcg_temp_free_i64(tcg_imm
);
2644 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
2648 unallocated_encoding(s
);
2654 * 31 30 29 28 23 22 21 16 15 10 9 5 4 0
2655 * +----+-----+-------------+---+------+------+------+------+
2656 * | sf | opc | 1 0 0 1 1 0 | N | immr | imms | Rn | Rd |
2657 * +----+-----+-------------+---+------+------+------+------+
2659 static void disas_bitfield(DisasContext
*s
, uint32_t insn
)
2661 unsigned int sf
, n
, opc
, ri
, si
, rn
, rd
, bitsize
, pos
, len
;
2662 TCGv_i64 tcg_rd
, tcg_tmp
;
2664 sf
= extract32(insn
, 31, 1);
2665 opc
= extract32(insn
, 29, 2);
2666 n
= extract32(insn
, 22, 1);
2667 ri
= extract32(insn
, 16, 6);
2668 si
= extract32(insn
, 10, 6);
2669 rn
= extract32(insn
, 5, 5);
2670 rd
= extract32(insn
, 0, 5);
2671 bitsize
= sf
? 64 : 32;
2673 if (sf
!= n
|| ri
>= bitsize
|| si
>= bitsize
|| opc
> 2) {
2674 unallocated_encoding(s
);
2678 tcg_rd
= cpu_reg(s
, rd
);
2679 tcg_tmp
= read_cpu_reg(s
, rn
, sf
);
2681 /* OPTME: probably worth recognizing common cases of ext{8,16,32}{u,s} */
2683 if (opc
!= 1) { /* SBFM or UBFM */
2684 tcg_gen_movi_i64(tcg_rd
, 0);
2687 /* do the bit move operation */
2689 /* Wd<s-r:0> = Wn<s:r> */
2690 tcg_gen_shri_i64(tcg_tmp
, tcg_tmp
, ri
);
2692 len
= (si
- ri
) + 1;
2694 /* Wd<32+s-r,32-r> = Wn<s:0> */
2699 tcg_gen_deposit_i64(tcg_rd
, tcg_rd
, tcg_tmp
, pos
, len
);
2701 if (opc
== 0) { /* SBFM - sign extend the destination field */
2702 tcg_gen_shli_i64(tcg_rd
, tcg_rd
, 64 - (pos
+ len
));
2703 tcg_gen_sari_i64(tcg_rd
, tcg_rd
, 64 - (pos
+ len
));
2706 if (!sf
) { /* zero extend final result */
2707 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
2712 * 31 30 29 28 23 22 21 20 16 15 10 9 5 4 0
2713 * +----+------+-------------+---+----+------+--------+------+------+
2714 * | sf | op21 | 1 0 0 1 1 1 | N | o0 | Rm | imms | Rn | Rd |
2715 * +----+------+-------------+---+----+------+--------+------+------+
2717 static void disas_extract(DisasContext
*s
, uint32_t insn
)
2719 unsigned int sf
, n
, rm
, imm
, rn
, rd
, bitsize
, op21
, op0
;
2721 sf
= extract32(insn
, 31, 1);
2722 n
= extract32(insn
, 22, 1);
2723 rm
= extract32(insn
, 16, 5);
2724 imm
= extract32(insn
, 10, 6);
2725 rn
= extract32(insn
, 5, 5);
2726 rd
= extract32(insn
, 0, 5);
2727 op21
= extract32(insn
, 29, 2);
2728 op0
= extract32(insn
, 21, 1);
2729 bitsize
= sf
? 64 : 32;
2731 if (sf
!= n
|| op21
|| op0
|| imm
>= bitsize
) {
2732 unallocated_encoding(s
);
2734 TCGv_i64 tcg_rd
, tcg_rm
, tcg_rn
;
2736 tcg_rd
= cpu_reg(s
, rd
);
2739 /* OPTME: we can special case rm==rn as a rotate */
2740 tcg_rm
= read_cpu_reg(s
, rm
, sf
);
2741 tcg_rn
= read_cpu_reg(s
, rn
, sf
);
2742 tcg_gen_shri_i64(tcg_rm
, tcg_rm
, imm
);
2743 tcg_gen_shli_i64(tcg_rn
, tcg_rn
, bitsize
- imm
);
2744 tcg_gen_or_i64(tcg_rd
, tcg_rm
, tcg_rn
);
2746 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
2749 /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
2750 * so an extract from bit 0 is a special case.
2753 tcg_gen_mov_i64(tcg_rd
, cpu_reg(s
, rm
));
2755 tcg_gen_ext32u_i64(tcg_rd
, cpu_reg(s
, rm
));
2762 /* C3.4 Data processing - immediate */
2763 static void disas_data_proc_imm(DisasContext
*s
, uint32_t insn
)
2765 switch (extract32(insn
, 23, 6)) {
2766 case 0x20: case 0x21: /* PC-rel. addressing */
2767 disas_pc_rel_adr(s
, insn
);
2769 case 0x22: case 0x23: /* Add/subtract (immediate) */
2770 disas_add_sub_imm(s
, insn
);
2772 case 0x24: /* Logical (immediate) */
2773 disas_logic_imm(s
, insn
);
2775 case 0x25: /* Move wide (immediate) */
2776 disas_movw_imm(s
, insn
);
2778 case 0x26: /* Bitfield */
2779 disas_bitfield(s
, insn
);
2781 case 0x27: /* Extract */
2782 disas_extract(s
, insn
);
2785 unallocated_encoding(s
);
2790 /* Shift a TCGv src by TCGv shift_amount, put result in dst.
2791 * Note that it is the caller's responsibility to ensure that the
2792 * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
2793 * mandated semantics for out of range shifts.
2795 static void shift_reg(TCGv_i64 dst
, TCGv_i64 src
, int sf
,
2796 enum a64_shift_type shift_type
, TCGv_i64 shift_amount
)
2798 switch (shift_type
) {
2799 case A64_SHIFT_TYPE_LSL
:
2800 tcg_gen_shl_i64(dst
, src
, shift_amount
);
2802 case A64_SHIFT_TYPE_LSR
:
2803 tcg_gen_shr_i64(dst
, src
, shift_amount
);
2805 case A64_SHIFT_TYPE_ASR
:
2807 tcg_gen_ext32s_i64(dst
, src
);
2809 tcg_gen_sar_i64(dst
, sf
? src
: dst
, shift_amount
);
2811 case A64_SHIFT_TYPE_ROR
:
2813 tcg_gen_rotr_i64(dst
, src
, shift_amount
);
2816 t0
= tcg_temp_new_i32();
2817 t1
= tcg_temp_new_i32();
2818 tcg_gen_trunc_i64_i32(t0
, src
);
2819 tcg_gen_trunc_i64_i32(t1
, shift_amount
);
2820 tcg_gen_rotr_i32(t0
, t0
, t1
);
2821 tcg_gen_extu_i32_i64(dst
, t0
);
2822 tcg_temp_free_i32(t0
);
2823 tcg_temp_free_i32(t1
);
2827 assert(FALSE
); /* all shift types should be handled */
2831 if (!sf
) { /* zero extend final result */
2832 tcg_gen_ext32u_i64(dst
, dst
);
2836 /* Shift a TCGv src by immediate, put result in dst.
2837 * The shift amount must be in range (this should always be true as the
2838 * relevant instructions will UNDEF on bad shift immediates).
2840 static void shift_reg_imm(TCGv_i64 dst
, TCGv_i64 src
, int sf
,
2841 enum a64_shift_type shift_type
, unsigned int shift_i
)
2843 assert(shift_i
< (sf
? 64 : 32));
2846 tcg_gen_mov_i64(dst
, src
);
2848 TCGv_i64 shift_const
;
2850 shift_const
= tcg_const_i64(shift_i
);
2851 shift_reg(dst
, src
, sf
, shift_type
, shift_const
);
2852 tcg_temp_free_i64(shift_const
);
2856 /* C3.5.10 Logical (shifted register)
2857 * 31 30 29 28 24 23 22 21 20 16 15 10 9 5 4 0
2858 * +----+-----+-----------+-------+---+------+--------+------+------+
2859 * | sf | opc | 0 1 0 1 0 | shift | N | Rm | imm6 | Rn | Rd |
2860 * +----+-----+-----------+-------+---+------+--------+------+------+
2862 static void disas_logic_reg(DisasContext
*s
, uint32_t insn
)
2864 TCGv_i64 tcg_rd
, tcg_rn
, tcg_rm
;
2865 unsigned int sf
, opc
, shift_type
, invert
, rm
, shift_amount
, rn
, rd
;
2867 sf
= extract32(insn
, 31, 1);
2868 opc
= extract32(insn
, 29, 2);
2869 shift_type
= extract32(insn
, 22, 2);
2870 invert
= extract32(insn
, 21, 1);
2871 rm
= extract32(insn
, 16, 5);
2872 shift_amount
= extract32(insn
, 10, 6);
2873 rn
= extract32(insn
, 5, 5);
2874 rd
= extract32(insn
, 0, 5);
2876 if (!sf
&& (shift_amount
& (1 << 5))) {
2877 unallocated_encoding(s
);
2881 tcg_rd
= cpu_reg(s
, rd
);
2883 if (opc
== 1 && shift_amount
== 0 && shift_type
== 0 && rn
== 31) {
2884 /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
2885 * register-register MOV and MVN, so it is worth special casing.
2887 tcg_rm
= cpu_reg(s
, rm
);
2889 tcg_gen_not_i64(tcg_rd
, tcg_rm
);
2891 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
2895 tcg_gen_mov_i64(tcg_rd
, tcg_rm
);
2897 tcg_gen_ext32u_i64(tcg_rd
, tcg_rm
);
2903 tcg_rm
= read_cpu_reg(s
, rm
, sf
);
2906 shift_reg_imm(tcg_rm
, tcg_rm
, sf
, shift_type
, shift_amount
);
2909 tcg_rn
= cpu_reg(s
, rn
);
2911 switch (opc
| (invert
<< 2)) {
2914 tcg_gen_and_i64(tcg_rd
, tcg_rn
, tcg_rm
);
2917 tcg_gen_or_i64(tcg_rd
, tcg_rn
, tcg_rm
);
2920 tcg_gen_xor_i64(tcg_rd
, tcg_rn
, tcg_rm
);
2924 tcg_gen_andc_i64(tcg_rd
, tcg_rn
, tcg_rm
);
2927 tcg_gen_orc_i64(tcg_rd
, tcg_rn
, tcg_rm
);
2930 tcg_gen_eqv_i64(tcg_rd
, tcg_rn
, tcg_rm
);
2938 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
2942 gen_logic_CC(sf
, tcg_rd
);
2947 * C3.5.1 Add/subtract (extended register)
2949 * 31|30|29|28 24|23 22|21|20 16|15 13|12 10|9 5|4 0|
2950 * +--+--+--+-----------+-----+--+-------+------+------+----+----+
2951 * |sf|op| S| 0 1 0 1 1 | opt | 1| Rm |option| imm3 | Rn | Rd |
2952 * +--+--+--+-----------+-----+--+-------+------+------+----+----+
2954 * sf: 0 -> 32bit, 1 -> 64bit
2955 * op: 0 -> add , 1 -> sub
2958 * option: extension type (see DecodeRegExtend)
2959 * imm3: optional shift to Rm
2961 * Rd = Rn + LSL(extend(Rm), amount)
2963 static void disas_add_sub_ext_reg(DisasContext
*s
, uint32_t insn
)
2965 int rd
= extract32(insn
, 0, 5);
2966 int rn
= extract32(insn
, 5, 5);
2967 int imm3
= extract32(insn
, 10, 3);
2968 int option
= extract32(insn
, 13, 3);
2969 int rm
= extract32(insn
, 16, 5);
2970 bool setflags
= extract32(insn
, 29, 1);
2971 bool sub_op
= extract32(insn
, 30, 1);
2972 bool sf
= extract32(insn
, 31, 1);
2974 TCGv_i64 tcg_rm
, tcg_rn
; /* temps */
2976 TCGv_i64 tcg_result
;
2979 unallocated_encoding(s
);
2983 /* non-flag setting ops may use SP */
2985 tcg_rn
= read_cpu_reg_sp(s
, rn
, sf
);
2986 tcg_rd
= cpu_reg_sp(s
, rd
);
2988 tcg_rn
= read_cpu_reg(s
, rn
, sf
);
2989 tcg_rd
= cpu_reg(s
, rd
);
2992 tcg_rm
= read_cpu_reg(s
, rm
, sf
);
2993 ext_and_shift_reg(tcg_rm
, tcg_rm
, option
, imm3
);
2995 tcg_result
= tcg_temp_new_i64();
2999 tcg_gen_sub_i64(tcg_result
, tcg_rn
, tcg_rm
);
3001 tcg_gen_add_i64(tcg_result
, tcg_rn
, tcg_rm
);
3005 gen_sub_CC(sf
, tcg_result
, tcg_rn
, tcg_rm
);
3007 gen_add_CC(sf
, tcg_result
, tcg_rn
, tcg_rm
);
3012 tcg_gen_mov_i64(tcg_rd
, tcg_result
);
3014 tcg_gen_ext32u_i64(tcg_rd
, tcg_result
);
3017 tcg_temp_free_i64(tcg_result
);
3021 * C3.5.2 Add/subtract (shifted register)
3023 * 31 30 29 28 24 23 22 21 20 16 15 10 9 5 4 0
3024 * +--+--+--+-----------+-----+--+-------+---------+------+------+
3025 * |sf|op| S| 0 1 0 1 1 |shift| 0| Rm | imm6 | Rn | Rd |
3026 * +--+--+--+-----------+-----+--+-------+---------+------+------+
3028 * sf: 0 -> 32bit, 1 -> 64bit
3029 * op: 0 -> add , 1 -> sub
3031 * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
3032 * imm6: Shift amount to apply to Rm before the add/sub
3034 static void disas_add_sub_reg(DisasContext
*s
, uint32_t insn
)
3036 int rd
= extract32(insn
, 0, 5);
3037 int rn
= extract32(insn
, 5, 5);
3038 int imm6
= extract32(insn
, 10, 6);
3039 int rm
= extract32(insn
, 16, 5);
3040 int shift_type
= extract32(insn
, 22, 2);
3041 bool setflags
= extract32(insn
, 29, 1);
3042 bool sub_op
= extract32(insn
, 30, 1);
3043 bool sf
= extract32(insn
, 31, 1);
3045 TCGv_i64 tcg_rd
= cpu_reg(s
, rd
);
3046 TCGv_i64 tcg_rn
, tcg_rm
;
3047 TCGv_i64 tcg_result
;
3049 if ((shift_type
== 3) || (!sf
&& (imm6
> 31))) {
3050 unallocated_encoding(s
);
3054 tcg_rn
= read_cpu_reg(s
, rn
, sf
);
3055 tcg_rm
= read_cpu_reg(s
, rm
, sf
);
3057 shift_reg_imm(tcg_rm
, tcg_rm
, sf
, shift_type
, imm6
);
3059 tcg_result
= tcg_temp_new_i64();
3063 tcg_gen_sub_i64(tcg_result
, tcg_rn
, tcg_rm
);
3065 tcg_gen_add_i64(tcg_result
, tcg_rn
, tcg_rm
);
3069 gen_sub_CC(sf
, tcg_result
, tcg_rn
, tcg_rm
);
3071 gen_add_CC(sf
, tcg_result
, tcg_rn
, tcg_rm
);
3076 tcg_gen_mov_i64(tcg_rd
, tcg_result
);
3078 tcg_gen_ext32u_i64(tcg_rd
, tcg_result
);
3081 tcg_temp_free_i64(tcg_result
);
3084 /* C3.5.9 Data-processing (3 source)
3086 31 30 29 28 24 23 21 20 16 15 14 10 9 5 4 0
3087 +--+------+-----------+------+------+----+------+------+------+
3088 |sf| op54 | 1 1 0 1 1 | op31 | Rm | o0 | Ra | Rn | Rd |
3089 +--+------+-----------+------+------+----+------+------+------+
3092 static void disas_data_proc_3src(DisasContext
*s
, uint32_t insn
)
3094 int rd
= extract32(insn
, 0, 5);
3095 int rn
= extract32(insn
, 5, 5);
3096 int ra
= extract32(insn
, 10, 5);
3097 int rm
= extract32(insn
, 16, 5);
3098 int op_id
= (extract32(insn
, 29, 3) << 4) |
3099 (extract32(insn
, 21, 3) << 1) |
3100 extract32(insn
, 15, 1);
3101 bool sf
= extract32(insn
, 31, 1);
3102 bool is_sub
= extract32(op_id
, 0, 1);
3103 bool is_high
= extract32(op_id
, 2, 1);
3104 bool is_signed
= false;
3109 /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
3111 case 0x42: /* SMADDL */
3112 case 0x43: /* SMSUBL */
3113 case 0x44: /* SMULH */
3116 case 0x0: /* MADD (32bit) */
3117 case 0x1: /* MSUB (32bit) */
3118 case 0x40: /* MADD (64bit) */
3119 case 0x41: /* MSUB (64bit) */
3120 case 0x4a: /* UMADDL */
3121 case 0x4b: /* UMSUBL */
3122 case 0x4c: /* UMULH */
3125 unallocated_encoding(s
);
3130 TCGv_i64 low_bits
= tcg_temp_new_i64(); /* low bits discarded */
3131 TCGv_i64 tcg_rd
= cpu_reg(s
, rd
);
3132 TCGv_i64 tcg_rn
= cpu_reg(s
, rn
);
3133 TCGv_i64 tcg_rm
= cpu_reg(s
, rm
);
3136 tcg_gen_muls2_i64(low_bits
, tcg_rd
, tcg_rn
, tcg_rm
);
3138 tcg_gen_mulu2_i64(low_bits
, tcg_rd
, tcg_rn
, tcg_rm
);
3141 tcg_temp_free_i64(low_bits
);
3145 tcg_op1
= tcg_temp_new_i64();
3146 tcg_op2
= tcg_temp_new_i64();
3147 tcg_tmp
= tcg_temp_new_i64();
3150 tcg_gen_mov_i64(tcg_op1
, cpu_reg(s
, rn
));
3151 tcg_gen_mov_i64(tcg_op2
, cpu_reg(s
, rm
));
3154 tcg_gen_ext32s_i64(tcg_op1
, cpu_reg(s
, rn
));
3155 tcg_gen_ext32s_i64(tcg_op2
, cpu_reg(s
, rm
));
3157 tcg_gen_ext32u_i64(tcg_op1
, cpu_reg(s
, rn
));
3158 tcg_gen_ext32u_i64(tcg_op2
, cpu_reg(s
, rm
));
3162 if (ra
== 31 && !is_sub
) {
3163 /* Special-case MADD with rA == XZR; it is the standard MUL alias */
3164 tcg_gen_mul_i64(cpu_reg(s
, rd
), tcg_op1
, tcg_op2
);
3166 tcg_gen_mul_i64(tcg_tmp
, tcg_op1
, tcg_op2
);
3168 tcg_gen_sub_i64(cpu_reg(s
, rd
), cpu_reg(s
, ra
), tcg_tmp
);
3170 tcg_gen_add_i64(cpu_reg(s
, rd
), cpu_reg(s
, ra
), tcg_tmp
);
3175 tcg_gen_ext32u_i64(cpu_reg(s
, rd
), cpu_reg(s
, rd
));
3178 tcg_temp_free_i64(tcg_op1
);
3179 tcg_temp_free_i64(tcg_op2
);
3180 tcg_temp_free_i64(tcg_tmp
);
3183 /* C3.5.3 - Add/subtract (with carry)
3184 * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
3185 * +--+--+--+------------------------+------+---------+------+-----+
3186 * |sf|op| S| 1 1 0 1 0 0 0 0 | rm | opcode2 | Rn | Rd |
3187 * +--+--+--+------------------------+------+---------+------+-----+
3191 static void disas_adc_sbc(DisasContext
*s
, uint32_t insn
)
3193 unsigned int sf
, op
, setflags
, rm
, rn
, rd
;
3194 TCGv_i64 tcg_y
, tcg_rn
, tcg_rd
;
3196 if (extract32(insn
, 10, 6) != 0) {
3197 unallocated_encoding(s
);
3201 sf
= extract32(insn
, 31, 1);
3202 op
= extract32(insn
, 30, 1);
3203 setflags
= extract32(insn
, 29, 1);
3204 rm
= extract32(insn
, 16, 5);
3205 rn
= extract32(insn
, 5, 5);
3206 rd
= extract32(insn
, 0, 5);
3208 tcg_rd
= cpu_reg(s
, rd
);
3209 tcg_rn
= cpu_reg(s
, rn
);
3212 tcg_y
= new_tmp_a64(s
);
3213 tcg_gen_not_i64(tcg_y
, cpu_reg(s
, rm
));
3215 tcg_y
= cpu_reg(s
, rm
);
3219 gen_adc_CC(sf
, tcg_rd
, tcg_rn
, tcg_y
);
3221 gen_adc(sf
, tcg_rd
, tcg_rn
, tcg_y
);
3225 /* C3.5.4 - C3.5.5 Conditional compare (immediate / register)
3226 * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 12 11 10 9 5 4 3 0
3227 * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
3228 * |sf|op| S| 1 1 0 1 0 0 1 0 |imm5/rm | cond |i/r |o2| Rn |o3|nzcv |
3229 * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
3232 static void disas_cc(DisasContext
*s
, uint32_t insn
)
3234 unsigned int sf
, op
, y
, cond
, rn
, nzcv
, is_imm
;
3235 int label_continue
= -1;
3236 TCGv_i64 tcg_tmp
, tcg_y
, tcg_rn
;
3238 if (!extract32(insn
, 29, 1)) {
3239 unallocated_encoding(s
);
3242 if (insn
& (1 << 10 | 1 << 4)) {
3243 unallocated_encoding(s
);
3246 sf
= extract32(insn
, 31, 1);
3247 op
= extract32(insn
, 30, 1);
3248 is_imm
= extract32(insn
, 11, 1);
3249 y
= extract32(insn
, 16, 5); /* y = rm (reg) or imm5 (imm) */
3250 cond
= extract32(insn
, 12, 4);
3251 rn
= extract32(insn
, 5, 5);
3252 nzcv
= extract32(insn
, 0, 4);
3254 if (cond
< 0x0e) { /* not always */
3255 int label_match
= gen_new_label();
3256 label_continue
= gen_new_label();
3257 arm_gen_test_cc(cond
, label_match
);
3259 tcg_tmp
= tcg_temp_new_i64();
3260 tcg_gen_movi_i64(tcg_tmp
, nzcv
<< 28);
3261 gen_set_nzcv(tcg_tmp
);
3262 tcg_temp_free_i64(tcg_tmp
);
3263 tcg_gen_br(label_continue
);
3264 gen_set_label(label_match
);
3266 /* match, or condition is always */
3268 tcg_y
= new_tmp_a64(s
);
3269 tcg_gen_movi_i64(tcg_y
, y
);
3271 tcg_y
= cpu_reg(s
, y
);
3273 tcg_rn
= cpu_reg(s
, rn
);
3275 tcg_tmp
= tcg_temp_new_i64();
3277 gen_sub_CC(sf
, tcg_tmp
, tcg_rn
, tcg_y
);
3279 gen_add_CC(sf
, tcg_tmp
, tcg_rn
, tcg_y
);
3281 tcg_temp_free_i64(tcg_tmp
);
3283 if (cond
< 0x0e) { /* continue */
3284 gen_set_label(label_continue
);
3288 /* C3.5.6 Conditional select
3289 * 31 30 29 28 21 20 16 15 12 11 10 9 5 4 0
3290 * +----+----+---+-----------------+------+------+-----+------+------+
3291 * | sf | op | S | 1 1 0 1 0 1 0 0 | Rm | cond | op2 | Rn | Rd |
3292 * +----+----+---+-----------------+------+------+-----+------+------+
3294 static void disas_cond_select(DisasContext
*s
, uint32_t insn
)
3296 unsigned int sf
, else_inv
, rm
, cond
, else_inc
, rn
, rd
;
3297 TCGv_i64 tcg_rd
, tcg_src
;
3299 if (extract32(insn
, 29, 1) || extract32(insn
, 11, 1)) {
3300 /* S == 1 or op2<1> == 1 */
3301 unallocated_encoding(s
);
3304 sf
= extract32(insn
, 31, 1);
3305 else_inv
= extract32(insn
, 30, 1);
3306 rm
= extract32(insn
, 16, 5);
3307 cond
= extract32(insn
, 12, 4);
3308 else_inc
= extract32(insn
, 10, 1);
3309 rn
= extract32(insn
, 5, 5);
3310 rd
= extract32(insn
, 0, 5);
3313 /* silly no-op write; until we use movcond we must special-case
3314 * this to avoid a dead temporary across basic blocks.
3319 tcg_rd
= cpu_reg(s
, rd
);
3321 if (cond
>= 0x0e) { /* condition "always" */
3322 tcg_src
= read_cpu_reg(s
, rn
, sf
);
3323 tcg_gen_mov_i64(tcg_rd
, tcg_src
);
3325 /* OPTME: we could use movcond here, at the cost of duplicating
3326 * a lot of the arm_gen_test_cc() logic.
3328 int label_match
= gen_new_label();
3329 int label_continue
= gen_new_label();
3331 arm_gen_test_cc(cond
, label_match
);
3333 tcg_src
= cpu_reg(s
, rm
);
3335 if (else_inv
&& else_inc
) {
3336 tcg_gen_neg_i64(tcg_rd
, tcg_src
);
3337 } else if (else_inv
) {
3338 tcg_gen_not_i64(tcg_rd
, tcg_src
);
3339 } else if (else_inc
) {
3340 tcg_gen_addi_i64(tcg_rd
, tcg_src
, 1);
3342 tcg_gen_mov_i64(tcg_rd
, tcg_src
);
3345 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
3347 tcg_gen_br(label_continue
);
3349 gen_set_label(label_match
);
3350 tcg_src
= read_cpu_reg(s
, rn
, sf
);
3351 tcg_gen_mov_i64(tcg_rd
, tcg_src
);
3353 gen_set_label(label_continue
);
3357 static void handle_clz(DisasContext
*s
, unsigned int sf
,
3358 unsigned int rn
, unsigned int rd
)
3360 TCGv_i64 tcg_rd
, tcg_rn
;
3361 tcg_rd
= cpu_reg(s
, rd
);
3362 tcg_rn
= cpu_reg(s
, rn
);
3365 gen_helper_clz64(tcg_rd
, tcg_rn
);
3367 TCGv_i32 tcg_tmp32
= tcg_temp_new_i32();
3368 tcg_gen_trunc_i64_i32(tcg_tmp32
, tcg_rn
);
3369 gen_helper_clz(tcg_tmp32
, tcg_tmp32
);
3370 tcg_gen_extu_i32_i64(tcg_rd
, tcg_tmp32
);
3371 tcg_temp_free_i32(tcg_tmp32
);
3375 static void handle_cls(DisasContext
*s
, unsigned int sf
,
3376 unsigned int rn
, unsigned int rd
)
3378 TCGv_i64 tcg_rd
, tcg_rn
;
3379 tcg_rd
= cpu_reg(s
, rd
);
3380 tcg_rn
= cpu_reg(s
, rn
);
3383 gen_helper_cls64(tcg_rd
, tcg_rn
);
3385 TCGv_i32 tcg_tmp32
= tcg_temp_new_i32();
3386 tcg_gen_trunc_i64_i32(tcg_tmp32
, tcg_rn
);
3387 gen_helper_cls32(tcg_tmp32
, tcg_tmp32
);
3388 tcg_gen_extu_i32_i64(tcg_rd
, tcg_tmp32
);
3389 tcg_temp_free_i32(tcg_tmp32
);
3393 static void handle_rbit(DisasContext
*s
, unsigned int sf
,
3394 unsigned int rn
, unsigned int rd
)
3396 TCGv_i64 tcg_rd
, tcg_rn
;
3397 tcg_rd
= cpu_reg(s
, rd
);
3398 tcg_rn
= cpu_reg(s
, rn
);
3401 gen_helper_rbit64(tcg_rd
, tcg_rn
);
3403 TCGv_i32 tcg_tmp32
= tcg_temp_new_i32();
3404 tcg_gen_trunc_i64_i32(tcg_tmp32
, tcg_rn
);
3405 gen_helper_rbit(tcg_tmp32
, tcg_tmp32
);
3406 tcg_gen_extu_i32_i64(tcg_rd
, tcg_tmp32
);
3407 tcg_temp_free_i32(tcg_tmp32
);
3411 /* C5.6.149 REV with sf==1, opcode==3 ("REV64") */
3412 static void handle_rev64(DisasContext
*s
, unsigned int sf
,
3413 unsigned int rn
, unsigned int rd
)
3416 unallocated_encoding(s
);
3419 tcg_gen_bswap64_i64(cpu_reg(s
, rd
), cpu_reg(s
, rn
));
3422 /* C5.6.149 REV with sf==0, opcode==2
3423 * C5.6.151 REV32 (sf==1, opcode==2)
3425 static void handle_rev32(DisasContext
*s
, unsigned int sf
,
3426 unsigned int rn
, unsigned int rd
)
3428 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 /* bswap32_i64 requires zero high word */
3435 tcg_gen_ext32u_i64(tcg_tmp
, tcg_rn
);
3436 tcg_gen_bswap32_i64(tcg_rd
, tcg_tmp
);
3437 tcg_gen_shri_i64(tcg_tmp
, tcg_rn
, 32);
3438 tcg_gen_bswap32_i64(tcg_tmp
, tcg_tmp
);
3439 tcg_gen_concat32_i64(tcg_rd
, tcg_rd
, tcg_tmp
);
3441 tcg_temp_free_i64(tcg_tmp
);
3443 tcg_gen_ext32u_i64(tcg_rd
, cpu_reg(s
, rn
));
3444 tcg_gen_bswap32_i64(tcg_rd
, tcg_rd
);
3448 /* C5.6.150 REV16 (opcode==1) */
3449 static void handle_rev16(DisasContext
*s
, unsigned int sf
,
3450 unsigned int rn
, unsigned int rd
)
3452 TCGv_i64 tcg_rd
= cpu_reg(s
, rd
);
3453 TCGv_i64 tcg_tmp
= tcg_temp_new_i64();
3454 TCGv_i64 tcg_rn
= read_cpu_reg(s
, rn
, sf
);
3456 tcg_gen_andi_i64(tcg_tmp
, tcg_rn
, 0xffff);
3457 tcg_gen_bswap16_i64(tcg_rd
, tcg_tmp
);
3459 tcg_gen_shri_i64(tcg_tmp
, tcg_rn
, 16);
3460 tcg_gen_andi_i64(tcg_tmp
, tcg_tmp
, 0xffff);
3461 tcg_gen_bswap16_i64(tcg_tmp
, tcg_tmp
);
3462 tcg_gen_deposit_i64(tcg_rd
, tcg_rd
, tcg_tmp
, 16, 16);
3465 tcg_gen_shri_i64(tcg_tmp
, tcg_rn
, 32);
3466 tcg_gen_andi_i64(tcg_tmp
, tcg_tmp
, 0xffff);
3467 tcg_gen_bswap16_i64(tcg_tmp
, tcg_tmp
);
3468 tcg_gen_deposit_i64(tcg_rd
, tcg_rd
, tcg_tmp
, 32, 16);
3470 tcg_gen_shri_i64(tcg_tmp
, tcg_rn
, 48);
3471 tcg_gen_bswap16_i64(tcg_tmp
, tcg_tmp
);
3472 tcg_gen_deposit_i64(tcg_rd
, tcg_rd
, tcg_tmp
, 48, 16);
3475 tcg_temp_free_i64(tcg_tmp
);
3478 /* C3.5.7 Data-processing (1 source)
3479 * 31 30 29 28 21 20 16 15 10 9 5 4 0
3480 * +----+---+---+-----------------+---------+--------+------+------+
3481 * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode | Rn | Rd |
3482 * +----+---+---+-----------------+---------+--------+------+------+
3484 static void disas_data_proc_1src(DisasContext
*s
, uint32_t insn
)
3486 unsigned int sf
, opcode
, rn
, rd
;
3488 if (extract32(insn
, 29, 1) || extract32(insn
, 16, 5)) {
3489 unallocated_encoding(s
);
3493 sf
= extract32(insn
, 31, 1);
3494 opcode
= extract32(insn
, 10, 6);
3495 rn
= extract32(insn
, 5, 5);
3496 rd
= extract32(insn
, 0, 5);
3500 handle_rbit(s
, sf
, rn
, rd
);
3503 handle_rev16(s
, sf
, rn
, rd
);
3506 handle_rev32(s
, sf
, rn
, rd
);
3509 handle_rev64(s
, sf
, rn
, rd
);
3512 handle_clz(s
, sf
, rn
, rd
);
3515 handle_cls(s
, sf
, rn
, rd
);
3520 static void handle_div(DisasContext
*s
, bool is_signed
, unsigned int sf
,
3521 unsigned int rm
, unsigned int rn
, unsigned int rd
)
3523 TCGv_i64 tcg_n
, tcg_m
, tcg_rd
;
3524 tcg_rd
= cpu_reg(s
, rd
);
3526 if (!sf
&& is_signed
) {
3527 tcg_n
= new_tmp_a64(s
);
3528 tcg_m
= new_tmp_a64(s
);
3529 tcg_gen_ext32s_i64(tcg_n
, cpu_reg(s
, rn
));
3530 tcg_gen_ext32s_i64(tcg_m
, cpu_reg(s
, rm
));
3532 tcg_n
= read_cpu_reg(s
, rn
, sf
);
3533 tcg_m
= read_cpu_reg(s
, rm
, sf
);
3537 gen_helper_sdiv64(tcg_rd
, tcg_n
, tcg_m
);
3539 gen_helper_udiv64(tcg_rd
, tcg_n
, tcg_m
);
3542 if (!sf
) { /* zero extend final result */
3543 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
3547 /* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
3548 static void handle_shift_reg(DisasContext
*s
,
3549 enum a64_shift_type shift_type
, unsigned int sf
,
3550 unsigned int rm
, unsigned int rn
, unsigned int rd
)
3552 TCGv_i64 tcg_shift
= tcg_temp_new_i64();
3553 TCGv_i64 tcg_rd
= cpu_reg(s
, rd
);
3554 TCGv_i64 tcg_rn
= read_cpu_reg(s
, rn
, sf
);
3556 tcg_gen_andi_i64(tcg_shift
, cpu_reg(s
, rm
), sf
? 63 : 31);
3557 shift_reg(tcg_rd
, tcg_rn
, sf
, shift_type
, tcg_shift
);
3558 tcg_temp_free_i64(tcg_shift
);
3561 /* C3.5.8 Data-processing (2 source)
3562 * 31 30 29 28 21 20 16 15 10 9 5 4 0
3563 * +----+---+---+-----------------+------+--------+------+------+
3564 * | sf | 0 | S | 1 1 0 1 0 1 1 0 | Rm | opcode | Rn | Rd |
3565 * +----+---+---+-----------------+------+--------+------+------+
3567 static void disas_data_proc_2src(DisasContext
*s
, uint32_t insn
)
3569 unsigned int sf
, rm
, opcode
, rn
, rd
;
3570 sf
= extract32(insn
, 31, 1);
3571 rm
= extract32(insn
, 16, 5);
3572 opcode
= extract32(insn
, 10, 6);
3573 rn
= extract32(insn
, 5, 5);
3574 rd
= extract32(insn
, 0, 5);
3576 if (extract32(insn
, 29, 1)) {
3577 unallocated_encoding(s
);
3583 handle_div(s
, false, sf
, rm
, rn
, rd
);
3586 handle_div(s
, true, sf
, rm
, rn
, rd
);
3589 handle_shift_reg(s
, A64_SHIFT_TYPE_LSL
, sf
, rm
, rn
, rd
);
3592 handle_shift_reg(s
, A64_SHIFT_TYPE_LSR
, sf
, rm
, rn
, rd
);
3595 handle_shift_reg(s
, A64_SHIFT_TYPE_ASR
, sf
, rm
, rn
, rd
);
3598 handle_shift_reg(s
, A64_SHIFT_TYPE_ROR
, sf
, rm
, rn
, rd
);
3607 case 23: /* CRC32 */
3608 unsupported_encoding(s
, insn
);
3611 unallocated_encoding(s
);
3616 /* C3.5 Data processing - register */
3617 static void disas_data_proc_reg(DisasContext
*s
, uint32_t insn
)
3619 switch (extract32(insn
, 24, 5)) {
3620 case 0x0a: /* Logical (shifted register) */
3621 disas_logic_reg(s
, insn
);
3623 case 0x0b: /* Add/subtract */
3624 if (insn
& (1 << 21)) { /* (extended register) */
3625 disas_add_sub_ext_reg(s
, insn
);
3627 disas_add_sub_reg(s
, insn
);
3630 case 0x1b: /* Data-processing (3 source) */
3631 disas_data_proc_3src(s
, insn
);
3634 switch (extract32(insn
, 21, 3)) {
3635 case 0x0: /* Add/subtract (with carry) */
3636 disas_adc_sbc(s
, insn
);
3638 case 0x2: /* Conditional compare */
3639 disas_cc(s
, insn
); /* both imm and reg forms */
3641 case 0x4: /* Conditional select */
3642 disas_cond_select(s
, insn
);
3644 case 0x6: /* Data-processing */
3645 if (insn
& (1 << 30)) { /* (1 source) */
3646 disas_data_proc_1src(s
, insn
);
3647 } else { /* (2 source) */
3648 disas_data_proc_2src(s
, insn
);
3652 unallocated_encoding(s
);
3657 unallocated_encoding(s
);
3662 static void handle_fp_compare(DisasContext
*s
, bool is_double
,
3663 unsigned int rn
, unsigned int rm
,
3664 bool cmp_with_zero
, bool signal_all_nans
)
3666 TCGv_i64 tcg_flags
= tcg_temp_new_i64();
3667 TCGv_ptr fpst
= get_fpstatus_ptr();
3670 TCGv_i64 tcg_vn
, tcg_vm
;
3672 tcg_vn
= read_fp_dreg(s
, rn
);
3673 if (cmp_with_zero
) {
3674 tcg_vm
= tcg_const_i64(0);
3676 tcg_vm
= read_fp_dreg(s
, rm
);
3678 if (signal_all_nans
) {
3679 gen_helper_vfp_cmped_a64(tcg_flags
, tcg_vn
, tcg_vm
, fpst
);
3681 gen_helper_vfp_cmpd_a64(tcg_flags
, tcg_vn
, tcg_vm
, fpst
);
3683 tcg_temp_free_i64(tcg_vn
);
3684 tcg_temp_free_i64(tcg_vm
);
3686 TCGv_i32 tcg_vn
, tcg_vm
;
3688 tcg_vn
= read_fp_sreg(s
, rn
);
3689 if (cmp_with_zero
) {
3690 tcg_vm
= tcg_const_i32(0);
3692 tcg_vm
= read_fp_sreg(s
, rm
);
3694 if (signal_all_nans
) {
3695 gen_helper_vfp_cmpes_a64(tcg_flags
, tcg_vn
, tcg_vm
, fpst
);
3697 gen_helper_vfp_cmps_a64(tcg_flags
, tcg_vn
, tcg_vm
, fpst
);
3699 tcg_temp_free_i32(tcg_vn
);
3700 tcg_temp_free_i32(tcg_vm
);
3703 tcg_temp_free_ptr(fpst
);
3705 gen_set_nzcv(tcg_flags
);
3707 tcg_temp_free_i64(tcg_flags
);
3710 /* C3.6.22 Floating point compare
3711 * 31 30 29 28 24 23 22 21 20 16 15 14 13 10 9 5 4 0
3712 * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
3713 * | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | op | 1 0 0 0 | Rn | op2 |
3714 * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
3716 static void disas_fp_compare(DisasContext
*s
, uint32_t insn
)
3718 unsigned int mos
, type
, rm
, op
, rn
, opc
, op2r
;
3720 mos
= extract32(insn
, 29, 3);
3721 type
= extract32(insn
, 22, 2); /* 0 = single, 1 = double */
3722 rm
= extract32(insn
, 16, 5);
3723 op
= extract32(insn
, 14, 2);
3724 rn
= extract32(insn
, 5, 5);
3725 opc
= extract32(insn
, 3, 2);
3726 op2r
= extract32(insn
, 0, 3);
3728 if (mos
|| op
|| op2r
|| type
> 1) {
3729 unallocated_encoding(s
);
3733 handle_fp_compare(s
, type
, rn
, rm
, opc
& 1, opc
& 2);
3736 /* C3.6.23 Floating point conditional compare
3737 * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 3 0
3738 * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
3739 * | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | cond | 0 1 | Rn | op | nzcv |
3740 * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
3742 static void disas_fp_ccomp(DisasContext
*s
, uint32_t insn
)
3744 unsigned int mos
, type
, rm
, cond
, rn
, op
, nzcv
;
3746 int label_continue
= -1;
3748 mos
= extract32(insn
, 29, 3);
3749 type
= extract32(insn
, 22, 2); /* 0 = single, 1 = double */
3750 rm
= extract32(insn
, 16, 5);
3751 cond
= extract32(insn
, 12, 4);
3752 rn
= extract32(insn
, 5, 5);
3753 op
= extract32(insn
, 4, 1);
3754 nzcv
= extract32(insn
, 0, 4);
3756 if (mos
|| type
> 1) {
3757 unallocated_encoding(s
);
3761 if (cond
< 0x0e) { /* not always */
3762 int label_match
= gen_new_label();
3763 label_continue
= gen_new_label();
3764 arm_gen_test_cc(cond
, label_match
);
3766 tcg_flags
= tcg_const_i64(nzcv
<< 28);
3767 gen_set_nzcv(tcg_flags
);
3768 tcg_temp_free_i64(tcg_flags
);
3769 tcg_gen_br(label_continue
);
3770 gen_set_label(label_match
);
3773 handle_fp_compare(s
, type
, rn
, rm
, false, op
);
3776 gen_set_label(label_continue
);
3780 /* copy src FP register to dst FP register; type specifies single or double */
3781 static void gen_mov_fp2fp(DisasContext
*s
, int type
, int dst
, int src
)
3784 TCGv_i64 v
= read_fp_dreg(s
, src
);
3785 write_fp_dreg(s
, dst
, v
);
3786 tcg_temp_free_i64(v
);
3788 TCGv_i32 v
= read_fp_sreg(s
, src
);
3789 write_fp_sreg(s
, dst
, v
);
3790 tcg_temp_free_i32(v
);
3794 /* C3.6.24 Floating point conditional select
3795 * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
3796 * +---+---+---+-----------+------+---+------+------+-----+------+------+
3797 * | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | cond | 1 1 | Rn | Rd |
3798 * +---+---+---+-----------+------+---+------+------+-----+------+------+
3800 static void disas_fp_csel(DisasContext
*s
, uint32_t insn
)
3802 unsigned int mos
, type
, rm
, cond
, rn
, rd
;
3803 int label_continue
= -1;
3805 mos
= extract32(insn
, 29, 3);
3806 type
= extract32(insn
, 22, 2); /* 0 = single, 1 = double */
3807 rm
= extract32(insn
, 16, 5);
3808 cond
= extract32(insn
, 12, 4);
3809 rn
= extract32(insn
, 5, 5);
3810 rd
= extract32(insn
, 0, 5);
3812 if (mos
|| type
> 1) {
3813 unallocated_encoding(s
);
3817 if (cond
< 0x0e) { /* not always */
3818 int label_match
= gen_new_label();
3819 label_continue
= gen_new_label();
3820 arm_gen_test_cc(cond
, label_match
);
3822 gen_mov_fp2fp(s
, type
, rd
, rm
);
3823 tcg_gen_br(label_continue
);
3824 gen_set_label(label_match
);
3827 gen_mov_fp2fp(s
, type
, rd
, rn
);
3829 if (cond
< 0x0e) { /* continue */
3830 gen_set_label(label_continue
);
3834 /* C3.6.25 Floating-point data-processing (1 source) - single precision */
3835 static void handle_fp_1src_single(DisasContext
*s
, int opcode
, int rd
, int rn
)
3841 fpst
= get_fpstatus_ptr();
3842 tcg_op
= read_fp_sreg(s
, rn
);
3843 tcg_res
= tcg_temp_new_i32();
3846 case 0x0: /* FMOV */
3847 tcg_gen_mov_i32(tcg_res
, tcg_op
);
3849 case 0x1: /* FABS */
3850 gen_helper_vfp_abss(tcg_res
, tcg_op
);
3852 case 0x2: /* FNEG */
3853 gen_helper_vfp_negs(tcg_res
, tcg_op
);
3855 case 0x3: /* FSQRT */
3856 gen_helper_vfp_sqrts(tcg_res
, tcg_op
, cpu_env
);
3858 case 0x8: /* FRINTN */
3859 case 0x9: /* FRINTP */
3860 case 0xa: /* FRINTM */
3861 case 0xb: /* FRINTZ */
3862 case 0xc: /* FRINTA */
3864 TCGv_i32 tcg_rmode
= tcg_const_i32(arm_rmode_to_sf(opcode
& 7));
3866 gen_helper_set_rmode(tcg_rmode
, tcg_rmode
, cpu_env
);
3867 gen_helper_rints(tcg_res
, tcg_op
, fpst
);
3869 gen_helper_set_rmode(tcg_rmode
, tcg_rmode
, cpu_env
);
3870 tcg_temp_free_i32(tcg_rmode
);
3873 case 0xe: /* FRINTX */
3874 gen_helper_rints_exact(tcg_res
, tcg_op
, fpst
);
3876 case 0xf: /* FRINTI */
3877 gen_helper_rints(tcg_res
, tcg_op
, fpst
);
3883 write_fp_sreg(s
, rd
, tcg_res
);
3885 tcg_temp_free_ptr(fpst
);
3886 tcg_temp_free_i32(tcg_op
);
3887 tcg_temp_free_i32(tcg_res
);
3890 /* C3.6.25 Floating-point data-processing (1 source) - double precision */
3891 static void handle_fp_1src_double(DisasContext
*s
, int opcode
, int rd
, int rn
)
3897 fpst
= get_fpstatus_ptr();
3898 tcg_op
= read_fp_dreg(s
, rn
);
3899 tcg_res
= tcg_temp_new_i64();
3902 case 0x0: /* FMOV */
3903 tcg_gen_mov_i64(tcg_res
, tcg_op
);
3905 case 0x1: /* FABS */
3906 gen_helper_vfp_absd(tcg_res
, tcg_op
);
3908 case 0x2: /* FNEG */
3909 gen_helper_vfp_negd(tcg_res
, tcg_op
);
3911 case 0x3: /* FSQRT */
3912 gen_helper_vfp_sqrtd(tcg_res
, tcg_op
, cpu_env
);
3914 case 0x8: /* FRINTN */
3915 case 0x9: /* FRINTP */
3916 case 0xa: /* FRINTM */
3917 case 0xb: /* FRINTZ */
3918 case 0xc: /* FRINTA */
3920 TCGv_i32 tcg_rmode
= tcg_const_i32(arm_rmode_to_sf(opcode
& 7));
3922 gen_helper_set_rmode(tcg_rmode
, tcg_rmode
, cpu_env
);
3923 gen_helper_rintd(tcg_res
, tcg_op
, fpst
);
3925 gen_helper_set_rmode(tcg_rmode
, tcg_rmode
, cpu_env
);
3926 tcg_temp_free_i32(tcg_rmode
);
3929 case 0xe: /* FRINTX */
3930 gen_helper_rintd_exact(tcg_res
, tcg_op
, fpst
);
3932 case 0xf: /* FRINTI */
3933 gen_helper_rintd(tcg_res
, tcg_op
, fpst
);
3939 write_fp_dreg(s
, rd
, tcg_res
);
3941 tcg_temp_free_ptr(fpst
);
3942 tcg_temp_free_i64(tcg_op
);
3943 tcg_temp_free_i64(tcg_res
);
3946 static void handle_fp_fcvt(DisasContext
*s
, int opcode
,
3947 int rd
, int rn
, int dtype
, int ntype
)
3952 TCGv_i32 tcg_rn
= read_fp_sreg(s
, rn
);
3954 /* Single to double */
3955 TCGv_i64 tcg_rd
= tcg_temp_new_i64();
3956 gen_helper_vfp_fcvtds(tcg_rd
, tcg_rn
, cpu_env
);
3957 write_fp_dreg(s
, rd
, tcg_rd
);
3958 tcg_temp_free_i64(tcg_rd
);
3960 /* Single to half */
3961 TCGv_i32 tcg_rd
= tcg_temp_new_i32();
3962 gen_helper_vfp_fcvt_f32_to_f16(tcg_rd
, tcg_rn
, cpu_env
);
3963 /* write_fp_sreg is OK here because top half of tcg_rd is zero */
3964 write_fp_sreg(s
, rd
, tcg_rd
);
3965 tcg_temp_free_i32(tcg_rd
);
3967 tcg_temp_free_i32(tcg_rn
);
3972 TCGv_i64 tcg_rn
= read_fp_dreg(s
, rn
);
3973 TCGv_i32 tcg_rd
= tcg_temp_new_i32();
3975 /* Double to single */
3976 gen_helper_vfp_fcvtsd(tcg_rd
, tcg_rn
, cpu_env
);
3978 /* Double to half */
3979 gen_helper_vfp_fcvt_f64_to_f16(tcg_rd
, tcg_rn
, cpu_env
);
3980 /* write_fp_sreg is OK here because top half of tcg_rd is zero */
3982 write_fp_sreg(s
, rd
, tcg_rd
);
3983 tcg_temp_free_i32(tcg_rd
);
3984 tcg_temp_free_i64(tcg_rn
);
3989 TCGv_i32 tcg_rn
= read_fp_sreg(s
, rn
);
3990 tcg_gen_ext16u_i32(tcg_rn
, tcg_rn
);
3992 /* Half to single */
3993 TCGv_i32 tcg_rd
= tcg_temp_new_i32();
3994 gen_helper_vfp_fcvt_f16_to_f32(tcg_rd
, tcg_rn
, cpu_env
);
3995 write_fp_sreg(s
, rd
, tcg_rd
);
3996 tcg_temp_free_i32(tcg_rd
);
3998 /* Half to double */
3999 TCGv_i64 tcg_rd
= tcg_temp_new_i64();
4000 gen_helper_vfp_fcvt_f16_to_f64(tcg_rd
, tcg_rn
, cpu_env
);
4001 write_fp_dreg(s
, rd
, tcg_rd
);
4002 tcg_temp_free_i64(tcg_rd
);
4004 tcg_temp_free_i32(tcg_rn
);
4012 /* C3.6.25 Floating point data-processing (1 source)
4013 * 31 30 29 28 24 23 22 21 20 15 14 10 9 5 4 0
4014 * +---+---+---+-----------+------+---+--------+-----------+------+------+
4015 * | M | 0 | S | 1 1 1 1 0 | type | 1 | opcode | 1 0 0 0 0 | Rn | Rd |
4016 * +---+---+---+-----------+------+---+--------+-----------+------+------+
4018 static void disas_fp_1src(DisasContext
*s
, uint32_t insn
)
4020 int type
= extract32(insn
, 22, 2);
4021 int opcode
= extract32(insn
, 15, 6);
4022 int rn
= extract32(insn
, 5, 5);
4023 int rd
= extract32(insn
, 0, 5);
4026 case 0x4: case 0x5: case 0x7:
4028 /* FCVT between half, single and double precision */
4029 int dtype
= extract32(opcode
, 0, 2);
4030 if (type
== 2 || dtype
== type
) {
4031 unallocated_encoding(s
);
4034 handle_fp_fcvt(s
, opcode
, rd
, rn
, dtype
, type
);
4040 /* 32-to-32 and 64-to-64 ops */
4043 handle_fp_1src_single(s
, opcode
, rd
, rn
);
4046 handle_fp_1src_double(s
, opcode
, rd
, rn
);
4049 unallocated_encoding(s
);
4053 unallocated_encoding(s
);
4058 /* C3.6.26 Floating-point data-processing (2 source) - single precision */
4059 static void handle_fp_2src_single(DisasContext
*s
, int opcode
,
4060 int rd
, int rn
, int rm
)
4067 tcg_res
= tcg_temp_new_i32();
4068 fpst
= get_fpstatus_ptr();
4069 tcg_op1
= read_fp_sreg(s
, rn
);
4070 tcg_op2
= read_fp_sreg(s
, rm
);
4073 case 0x0: /* FMUL */
4074 gen_helper_vfp_muls(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4076 case 0x1: /* FDIV */
4077 gen_helper_vfp_divs(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4079 case 0x2: /* FADD */
4080 gen_helper_vfp_adds(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4082 case 0x3: /* FSUB */
4083 gen_helper_vfp_subs(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4085 case 0x4: /* FMAX */
4086 gen_helper_vfp_maxs(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4088 case 0x5: /* FMIN */
4089 gen_helper_vfp_mins(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4091 case 0x6: /* FMAXNM */
4092 gen_helper_vfp_maxnums(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4094 case 0x7: /* FMINNM */
4095 gen_helper_vfp_minnums(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4097 case 0x8: /* FNMUL */
4098 gen_helper_vfp_muls(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4099 gen_helper_vfp_negs(tcg_res
, tcg_res
);
4103 write_fp_sreg(s
, rd
, tcg_res
);
4105 tcg_temp_free_ptr(fpst
);
4106 tcg_temp_free_i32(tcg_op1
);
4107 tcg_temp_free_i32(tcg_op2
);
4108 tcg_temp_free_i32(tcg_res
);
4111 /* C3.6.26 Floating-point data-processing (2 source) - double precision */
4112 static void handle_fp_2src_double(DisasContext
*s
, int opcode
,
4113 int rd
, int rn
, int rm
)
4120 tcg_res
= tcg_temp_new_i64();
4121 fpst
= get_fpstatus_ptr();
4122 tcg_op1
= read_fp_dreg(s
, rn
);
4123 tcg_op2
= read_fp_dreg(s
, rm
);
4126 case 0x0: /* FMUL */
4127 gen_helper_vfp_muld(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4129 case 0x1: /* FDIV */
4130 gen_helper_vfp_divd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4132 case 0x2: /* FADD */
4133 gen_helper_vfp_addd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4135 case 0x3: /* FSUB */
4136 gen_helper_vfp_subd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4138 case 0x4: /* FMAX */
4139 gen_helper_vfp_maxd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4141 case 0x5: /* FMIN */
4142 gen_helper_vfp_mind(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4144 case 0x6: /* FMAXNM */
4145 gen_helper_vfp_maxnumd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4147 case 0x7: /* FMINNM */
4148 gen_helper_vfp_minnumd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4150 case 0x8: /* FNMUL */
4151 gen_helper_vfp_muld(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
4152 gen_helper_vfp_negd(tcg_res
, tcg_res
);
4156 write_fp_dreg(s
, rd
, tcg_res
);
4158 tcg_temp_free_ptr(fpst
);
4159 tcg_temp_free_i64(tcg_op1
);
4160 tcg_temp_free_i64(tcg_op2
);
4161 tcg_temp_free_i64(tcg_res
);
4164 /* C3.6.26 Floating point data-processing (2 source)
4165 * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
4166 * +---+---+---+-----------+------+---+------+--------+-----+------+------+
4167 * | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | opcode | 1 0 | Rn | Rd |
4168 * +---+---+---+-----------+------+---+------+--------+-----+------+------+
4170 static void disas_fp_2src(DisasContext
*s
, uint32_t insn
)
4172 int type
= extract32(insn
, 22, 2);
4173 int rd
= extract32(insn
, 0, 5);
4174 int rn
= extract32(insn
, 5, 5);
4175 int rm
= extract32(insn
, 16, 5);
4176 int opcode
= extract32(insn
, 12, 4);
4179 unallocated_encoding(s
);
4185 handle_fp_2src_single(s
, opcode
, rd
, rn
, rm
);
4188 handle_fp_2src_double(s
, opcode
, rd
, rn
, rm
);
4191 unallocated_encoding(s
);
4195 /* C3.6.27 Floating-point data-processing (3 source) - single precision */
4196 static void handle_fp_3src_single(DisasContext
*s
, bool o0
, bool o1
,
4197 int rd
, int rn
, int rm
, int ra
)
4199 TCGv_i32 tcg_op1
, tcg_op2
, tcg_op3
;
4200 TCGv_i32 tcg_res
= tcg_temp_new_i32();
4201 TCGv_ptr fpst
= get_fpstatus_ptr();
4203 tcg_op1
= read_fp_sreg(s
, rn
);
4204 tcg_op2
= read_fp_sreg(s
, rm
);
4205 tcg_op3
= read_fp_sreg(s
, ra
);
4207 /* These are fused multiply-add, and must be done as one
4208 * floating point operation with no rounding between the
4209 * multiplication and addition steps.
4210 * NB that doing the negations here as separate steps is
4211 * correct : an input NaN should come out with its sign bit
4212 * flipped if it is a negated-input.
4215 gen_helper_vfp_negs(tcg_op3
, tcg_op3
);
4219 gen_helper_vfp_negs(tcg_op1
, tcg_op1
);
4222 gen_helper_vfp_muladds(tcg_res
, tcg_op1
, tcg_op2
, tcg_op3
, fpst
);
4224 write_fp_sreg(s
, rd
, tcg_res
);
4226 tcg_temp_free_ptr(fpst
);
4227 tcg_temp_free_i32(tcg_op1
);
4228 tcg_temp_free_i32(tcg_op2
);
4229 tcg_temp_free_i32(tcg_op3
);
4230 tcg_temp_free_i32(tcg_res
);
4233 /* C3.6.27 Floating-point data-processing (3 source) - double precision */
4234 static void handle_fp_3src_double(DisasContext
*s
, bool o0
, bool o1
,
4235 int rd
, int rn
, int rm
, int ra
)
4237 TCGv_i64 tcg_op1
, tcg_op2
, tcg_op3
;
4238 TCGv_i64 tcg_res
= tcg_temp_new_i64();
4239 TCGv_ptr fpst
= get_fpstatus_ptr();
4241 tcg_op1
= read_fp_dreg(s
, rn
);
4242 tcg_op2
= read_fp_dreg(s
, rm
);
4243 tcg_op3
= read_fp_dreg(s
, ra
);
4245 /* These are fused multiply-add, and must be done as one
4246 * floating point operation with no rounding between the
4247 * multiplication and addition steps.
4248 * NB that doing the negations here as separate steps is
4249 * correct : an input NaN should come out with its sign bit
4250 * flipped if it is a negated-input.
4253 gen_helper_vfp_negd(tcg_op3
, tcg_op3
);
4257 gen_helper_vfp_negd(tcg_op1
, tcg_op1
);
4260 gen_helper_vfp_muladdd(tcg_res
, tcg_op1
, tcg_op2
, tcg_op3
, fpst
);
4262 write_fp_dreg(s
, rd
, tcg_res
);
4264 tcg_temp_free_ptr(fpst
);
4265 tcg_temp_free_i64(tcg_op1
);
4266 tcg_temp_free_i64(tcg_op2
);
4267 tcg_temp_free_i64(tcg_op3
);
4268 tcg_temp_free_i64(tcg_res
);
4271 /* C3.6.27 Floating point data-processing (3 source)
4272 * 31 30 29 28 24 23 22 21 20 16 15 14 10 9 5 4 0
4273 * +---+---+---+-----------+------+----+------+----+------+------+------+
4274 * | M | 0 | S | 1 1 1 1 1 | type | o1 | Rm | o0 | Ra | Rn | Rd |
4275 * +---+---+---+-----------+------+----+------+----+------+------+------+
4277 static void disas_fp_3src(DisasContext
*s
, uint32_t insn
)
4279 int type
= extract32(insn
, 22, 2);
4280 int rd
= extract32(insn
, 0, 5);
4281 int rn
= extract32(insn
, 5, 5);
4282 int ra
= extract32(insn
, 10, 5);
4283 int rm
= extract32(insn
, 16, 5);
4284 bool o0
= extract32(insn
, 15, 1);
4285 bool o1
= extract32(insn
, 21, 1);
4289 handle_fp_3src_single(s
, o0
, o1
, rd
, rn
, rm
, ra
);
4292 handle_fp_3src_double(s
, o0
, o1
, rd
, rn
, rm
, ra
);
4295 unallocated_encoding(s
);
4299 /* C3.6.28 Floating point immediate
4300 * 31 30 29 28 24 23 22 21 20 13 12 10 9 5 4 0
4301 * +---+---+---+-----------+------+---+------------+-------+------+------+
4302 * | M | 0 | S | 1 1 1 1 0 | type | 1 | imm8 | 1 0 0 | imm5 | Rd |
4303 * +---+---+---+-----------+------+---+------------+-------+------+------+
4305 static void disas_fp_imm(DisasContext
*s
, uint32_t insn
)
4307 int rd
= extract32(insn
, 0, 5);
4308 int imm8
= extract32(insn
, 13, 8);
4309 int is_double
= extract32(insn
, 22, 2);
4313 if (is_double
> 1) {
4314 unallocated_encoding(s
);
4318 /* The imm8 encodes the sign bit, enough bits to represent
4319 * an exponent in the range 01....1xx to 10....0xx,
4320 * and the most significant 4 bits of the mantissa; see
4321 * VFPExpandImm() in the v8 ARM ARM.
4324 imm
= (extract32(imm8
, 7, 1) ? 0x8000 : 0) |
4325 (extract32(imm8
, 6, 1) ? 0x3fc0 : 0x4000) |
4326 extract32(imm8
, 0, 6);
4329 imm
= (extract32(imm8
, 7, 1) ? 0x8000 : 0) |
4330 (extract32(imm8
, 6, 1) ? 0x3e00 : 0x4000) |
4331 (extract32(imm8
, 0, 6) << 3);
4335 tcg_res
= tcg_const_i64(imm
);
4336 write_fp_dreg(s
, rd
, tcg_res
);
4337 tcg_temp_free_i64(tcg_res
);
4340 /* Handle floating point <=> fixed point conversions. Note that we can
4341 * also deal with fp <=> integer conversions as a special case (scale == 64)
4342 * OPTME: consider handling that special case specially or at least skipping
4343 * the call to scalbn in the helpers for zero shifts.
4345 static void handle_fpfpcvt(DisasContext
*s
, int rd
, int rn
, int opcode
,
4346 bool itof
, int rmode
, int scale
, int sf
, int type
)
4348 bool is_signed
= !(opcode
& 1);
4349 bool is_double
= type
;
4350 TCGv_ptr tcg_fpstatus
;
4353 tcg_fpstatus
= get_fpstatus_ptr();
4355 tcg_shift
= tcg_const_i32(64 - scale
);
4358 TCGv_i64 tcg_int
= cpu_reg(s
, rn
);
4360 TCGv_i64 tcg_extend
= new_tmp_a64(s
);
4363 tcg_gen_ext32s_i64(tcg_extend
, tcg_int
);
4365 tcg_gen_ext32u_i64(tcg_extend
, tcg_int
);
4368 tcg_int
= tcg_extend
;
4372 TCGv_i64 tcg_double
= tcg_temp_new_i64();
4374 gen_helper_vfp_sqtod(tcg_double
, tcg_int
,
4375 tcg_shift
, tcg_fpstatus
);
4377 gen_helper_vfp_uqtod(tcg_double
, tcg_int
,
4378 tcg_shift
, tcg_fpstatus
);
4380 write_fp_dreg(s
, rd
, tcg_double
);
4381 tcg_temp_free_i64(tcg_double
);
4383 TCGv_i32 tcg_single
= tcg_temp_new_i32();
4385 gen_helper_vfp_sqtos(tcg_single
, tcg_int
,
4386 tcg_shift
, tcg_fpstatus
);
4388 gen_helper_vfp_uqtos(tcg_single
, tcg_int
,
4389 tcg_shift
, tcg_fpstatus
);
4391 write_fp_sreg(s
, rd
, tcg_single
);
4392 tcg_temp_free_i32(tcg_single
);
4395 TCGv_i64 tcg_int
= cpu_reg(s
, rd
);
4398 if (extract32(opcode
, 2, 1)) {
4399 /* There are too many rounding modes to all fit into rmode,
4400 * so FCVTA[US] is a special case.
4402 rmode
= FPROUNDING_TIEAWAY
;
4405 tcg_rmode
= tcg_const_i32(arm_rmode_to_sf(rmode
));
4407 gen_helper_set_rmode(tcg_rmode
, tcg_rmode
, cpu_env
);
4410 TCGv_i64 tcg_double
= read_fp_dreg(s
, rn
);
4413 gen_helper_vfp_tosld(tcg_int
, tcg_double
,
4414 tcg_shift
, tcg_fpstatus
);
4416 gen_helper_vfp_tosqd(tcg_int
, tcg_double
,
4417 tcg_shift
, tcg_fpstatus
);
4421 gen_helper_vfp_tould(tcg_int
, tcg_double
,
4422 tcg_shift
, tcg_fpstatus
);
4424 gen_helper_vfp_touqd(tcg_int
, tcg_double
,
4425 tcg_shift
, tcg_fpstatus
);
4428 tcg_temp_free_i64(tcg_double
);
4430 TCGv_i32 tcg_single
= read_fp_sreg(s
, rn
);
4433 gen_helper_vfp_tosqs(tcg_int
, tcg_single
,
4434 tcg_shift
, tcg_fpstatus
);
4436 gen_helper_vfp_touqs(tcg_int
, tcg_single
,
4437 tcg_shift
, tcg_fpstatus
);
4440 TCGv_i32 tcg_dest
= tcg_temp_new_i32();
4442 gen_helper_vfp_tosls(tcg_dest
, tcg_single
,
4443 tcg_shift
, tcg_fpstatus
);
4445 gen_helper_vfp_touls(tcg_dest
, tcg_single
,
4446 tcg_shift
, tcg_fpstatus
);
4448 tcg_gen_extu_i32_i64(tcg_int
, tcg_dest
);
4449 tcg_temp_free_i32(tcg_dest
);
4451 tcg_temp_free_i32(tcg_single
);
4454 gen_helper_set_rmode(tcg_rmode
, tcg_rmode
, cpu_env
);
4455 tcg_temp_free_i32(tcg_rmode
);
4458 tcg_gen_ext32u_i64(tcg_int
, tcg_int
);
4462 tcg_temp_free_ptr(tcg_fpstatus
);
4463 tcg_temp_free_i32(tcg_shift
);
4466 /* C3.6.29 Floating point <-> fixed point conversions
4467 * 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
4468 * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
4469 * | sf | 0 | S | 1 1 1 1 0 | type | 0 | rmode | opcode | scale | Rn | Rd |
4470 * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
4472 static void disas_fp_fixed_conv(DisasContext
*s
, uint32_t insn
)
4474 int rd
= extract32(insn
, 0, 5);
4475 int rn
= extract32(insn
, 5, 5);
4476 int scale
= extract32(insn
, 10, 6);
4477 int opcode
= extract32(insn
, 16, 3);
4478 int rmode
= extract32(insn
, 19, 2);
4479 int type
= extract32(insn
, 22, 2);
4480 bool sbit
= extract32(insn
, 29, 1);
4481 bool sf
= extract32(insn
, 31, 1);
4484 if (sbit
|| (type
> 1)
4485 || (!sf
&& scale
< 32)) {
4486 unallocated_encoding(s
);
4490 switch ((rmode
<< 3) | opcode
) {
4491 case 0x2: /* SCVTF */
4492 case 0x3: /* UCVTF */
4495 case 0x18: /* FCVTZS */
4496 case 0x19: /* FCVTZU */
4500 unallocated_encoding(s
);
4504 handle_fpfpcvt(s
, rd
, rn
, opcode
, itof
, FPROUNDING_ZERO
, scale
, sf
, type
);
4507 static void handle_fmov(DisasContext
*s
, int rd
, int rn
, int type
, bool itof
)
4509 /* FMOV: gpr to or from float, double, or top half of quad fp reg,
4510 * without conversion.
4514 TCGv_i64 tcg_rn
= cpu_reg(s
, rn
);
4520 TCGv_i64 tmp
= tcg_temp_new_i64();
4521 tcg_gen_ext32u_i64(tmp
, tcg_rn
);
4522 tcg_gen_st_i64(tmp
, cpu_env
, fp_reg_offset(rd
, MO_64
));
4523 tcg_gen_movi_i64(tmp
, 0);
4524 tcg_gen_st_i64(tmp
, cpu_env
, fp_reg_hi_offset(rd
));
4525 tcg_temp_free_i64(tmp
);
4531 TCGv_i64 tmp
= tcg_const_i64(0);
4532 tcg_gen_st_i64(tcg_rn
, cpu_env
, fp_reg_offset(rd
, MO_64
));
4533 tcg_gen_st_i64(tmp
, cpu_env
, fp_reg_hi_offset(rd
));
4534 tcg_temp_free_i64(tmp
);
4538 /* 64 bit to top half. */
4539 tcg_gen_st_i64(tcg_rn
, cpu_env
, fp_reg_hi_offset(rd
));
4543 TCGv_i64 tcg_rd
= cpu_reg(s
, rd
);
4548 tcg_gen_ld32u_i64(tcg_rd
, cpu_env
, fp_reg_offset(rn
, MO_32
));
4552 tcg_gen_ld_i64(tcg_rd
, cpu_env
, fp_reg_offset(rn
, MO_64
));
4555 /* 64 bits from top half */
4556 tcg_gen_ld_i64(tcg_rd
, cpu_env
, fp_reg_hi_offset(rn
));
4562 /* C3.6.30 Floating point <-> integer conversions
4563 * 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
4564 * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
4565 * | sf | 0 | S | 1 1 1 1 0 | type | 1 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
4566 * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
4568 static void disas_fp_int_conv(DisasContext
*s
, uint32_t insn
)
4570 int rd
= extract32(insn
, 0, 5);
4571 int rn
= extract32(insn
, 5, 5);
4572 int opcode
= extract32(insn
, 16, 3);
4573 int rmode
= extract32(insn
, 19, 2);
4574 int type
= extract32(insn
, 22, 2);
4575 bool sbit
= extract32(insn
, 29, 1);
4576 bool sf
= extract32(insn
, 31, 1);
4579 unallocated_encoding(s
);
4585 bool itof
= opcode
& 1;
4588 unallocated_encoding(s
);
4592 switch (sf
<< 3 | type
<< 1 | rmode
) {
4593 case 0x0: /* 32 bit */
4594 case 0xa: /* 64 bit */
4595 case 0xd: /* 64 bit to top half of quad */
4598 /* all other sf/type/rmode combinations are invalid */
4599 unallocated_encoding(s
);
4603 handle_fmov(s
, rd
, rn
, type
, itof
);
4605 /* actual FP conversions */
4606 bool itof
= extract32(opcode
, 1, 1);
4608 if (type
> 1 || (rmode
!= 0 && opcode
> 1)) {
4609 unallocated_encoding(s
);
4613 handle_fpfpcvt(s
, rd
, rn
, opcode
, itof
, rmode
, 64, sf
, type
);
4617 /* FP-specific subcases of table C3-6 (SIMD and FP data processing)
4618 * 31 30 29 28 25 24 0
4619 * +---+---+---+---------+-----------------------------+
4620 * | | 0 | | 1 1 1 1 | |
4621 * +---+---+---+---------+-----------------------------+
4623 static void disas_data_proc_fp(DisasContext
*s
, uint32_t insn
)
4625 if (extract32(insn
, 24, 1)) {
4626 /* Floating point data-processing (3 source) */
4627 disas_fp_3src(s
, insn
);
4628 } else if (extract32(insn
, 21, 1) == 0) {
4629 /* Floating point to fixed point conversions */
4630 disas_fp_fixed_conv(s
, insn
);
4632 switch (extract32(insn
, 10, 2)) {
4634 /* Floating point conditional compare */
4635 disas_fp_ccomp(s
, insn
);
4638 /* Floating point data-processing (2 source) */
4639 disas_fp_2src(s
, insn
);
4642 /* Floating point conditional select */
4643 disas_fp_csel(s
, insn
);
4646 switch (ctz32(extract32(insn
, 12, 4))) {
4647 case 0: /* [15:12] == xxx1 */
4648 /* Floating point immediate */
4649 disas_fp_imm(s
, insn
);
4651 case 1: /* [15:12] == xx10 */
4652 /* Floating point compare */
4653 disas_fp_compare(s
, insn
);
4655 case 2: /* [15:12] == x100 */
4656 /* Floating point data-processing (1 source) */
4657 disas_fp_1src(s
, insn
);
4659 case 3: /* [15:12] == 1000 */
4660 unallocated_encoding(s
);
4662 default: /* [15:12] == 0000 */
4663 /* Floating point <-> integer conversions */
4664 disas_fp_int_conv(s
, insn
);
4672 static void do_ext64(DisasContext
*s
, TCGv_i64 tcg_left
, TCGv_i64 tcg_right
,
4675 /* Extract 64 bits from the middle of two concatenated 64 bit
4676 * vector register slices left:right. The extracted bits start
4677 * at 'pos' bits into the right (least significant) side.
4678 * We return the result in tcg_right, and guarantee not to
4681 TCGv_i64 tcg_tmp
= tcg_temp_new_i64();
4682 assert(pos
> 0 && pos
< 64);
4684 tcg_gen_shri_i64(tcg_right
, tcg_right
, pos
);
4685 tcg_gen_shli_i64(tcg_tmp
, tcg_left
, 64 - pos
);
4686 tcg_gen_or_i64(tcg_right
, tcg_right
, tcg_tmp
);
4688 tcg_temp_free_i64(tcg_tmp
);
4692 * 31 30 29 24 23 22 21 20 16 15 14 11 10 9 5 4 0
4693 * +---+---+-------------+-----+---+------+---+------+---+------+------+
4694 * | 0 | Q | 1 0 1 1 1 0 | op2 | 0 | Rm | 0 | imm4 | 0 | Rn | Rd |
4695 * +---+---+-------------+-----+---+------+---+------+---+------+------+
4697 static void disas_simd_ext(DisasContext
*s
, uint32_t insn
)
4699 int is_q
= extract32(insn
, 30, 1);
4700 int op2
= extract32(insn
, 22, 2);
4701 int imm4
= extract32(insn
, 11, 4);
4702 int rm
= extract32(insn
, 16, 5);
4703 int rn
= extract32(insn
, 5, 5);
4704 int rd
= extract32(insn
, 0, 5);
4705 int pos
= imm4
<< 3;
4706 TCGv_i64 tcg_resl
, tcg_resh
;
4708 if (op2
!= 0 || (!is_q
&& extract32(imm4
, 3, 1))) {
4709 unallocated_encoding(s
);
4713 tcg_resh
= tcg_temp_new_i64();
4714 tcg_resl
= tcg_temp_new_i64();
4716 /* Vd gets bits starting at pos bits into Vm:Vn. This is
4717 * either extracting 128 bits from a 128:128 concatenation, or
4718 * extracting 64 bits from a 64:64 concatenation.
4721 read_vec_element(s
, tcg_resl
, rn
, 0, MO_64
);
4723 read_vec_element(s
, tcg_resh
, rm
, 0, MO_64
);
4724 do_ext64(s
, tcg_resh
, tcg_resl
, pos
);
4726 tcg_gen_movi_i64(tcg_resh
, 0);
4733 EltPosns eltposns
[] = { {rn
, 0}, {rn
, 1}, {rm
, 0}, {rm
, 1} };
4734 EltPosns
*elt
= eltposns
;
4741 read_vec_element(s
, tcg_resl
, elt
->reg
, elt
->elt
, MO_64
);
4743 read_vec_element(s
, tcg_resh
, elt
->reg
, elt
->elt
, MO_64
);
4746 do_ext64(s
, tcg_resh
, tcg_resl
, pos
);
4747 tcg_hh
= tcg_temp_new_i64();
4748 read_vec_element(s
, tcg_hh
, elt
->reg
, elt
->elt
, MO_64
);
4749 do_ext64(s
, tcg_hh
, tcg_resh
, pos
);
4750 tcg_temp_free_i64(tcg_hh
);
4754 write_vec_element(s
, tcg_resl
, rd
, 0, MO_64
);
4755 tcg_temp_free_i64(tcg_resl
);
4756 write_vec_element(s
, tcg_resh
, rd
, 1, MO_64
);
4757 tcg_temp_free_i64(tcg_resh
);
4761 * 31 30 29 24 23 22 21 20 16 15 14 13 12 11 10 9 5 4 0
4762 * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
4763 * | 0 | Q | 0 0 1 1 1 0 | op2 | 0 | Rm | 0 | len | op | 0 0 | Rn | Rd |
4764 * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
4766 static void disas_simd_tb(DisasContext
*s
, uint32_t insn
)
4768 int op2
= extract32(insn
, 22, 2);
4769 int is_q
= extract32(insn
, 30, 1);
4770 int rm
= extract32(insn
, 16, 5);
4771 int rn
= extract32(insn
, 5, 5);
4772 int rd
= extract32(insn
, 0, 5);
4773 int is_tblx
= extract32(insn
, 12, 1);
4774 int len
= extract32(insn
, 13, 2);
4775 TCGv_i64 tcg_resl
, tcg_resh
, tcg_idx
;
4776 TCGv_i32 tcg_regno
, tcg_numregs
;
4779 unallocated_encoding(s
);
4783 /* This does a table lookup: for every byte element in the input
4784 * we index into a table formed from up to four vector registers,
4785 * and then the output is the result of the lookups. Our helper
4786 * function does the lookup operation for a single 64 bit part of
4789 tcg_resl
= tcg_temp_new_i64();
4790 tcg_resh
= tcg_temp_new_i64();
4793 read_vec_element(s
, tcg_resl
, rd
, 0, MO_64
);
4795 tcg_gen_movi_i64(tcg_resl
, 0);
4797 if (is_tblx
&& is_q
) {
4798 read_vec_element(s
, tcg_resh
, rd
, 1, MO_64
);
4800 tcg_gen_movi_i64(tcg_resh
, 0);
4803 tcg_idx
= tcg_temp_new_i64();
4804 tcg_regno
= tcg_const_i32(rn
);
4805 tcg_numregs
= tcg_const_i32(len
+ 1);
4806 read_vec_element(s
, tcg_idx
, rm
, 0, MO_64
);
4807 gen_helper_simd_tbl(tcg_resl
, cpu_env
, tcg_resl
, tcg_idx
,
4808 tcg_regno
, tcg_numregs
);
4810 read_vec_element(s
, tcg_idx
, rm
, 1, MO_64
);
4811 gen_helper_simd_tbl(tcg_resh
, cpu_env
, tcg_resh
, tcg_idx
,
4812 tcg_regno
, tcg_numregs
);
4814 tcg_temp_free_i64(tcg_idx
);
4815 tcg_temp_free_i32(tcg_regno
);
4816 tcg_temp_free_i32(tcg_numregs
);
4818 write_vec_element(s
, tcg_resl
, rd
, 0, MO_64
);
4819 tcg_temp_free_i64(tcg_resl
);
4820 write_vec_element(s
, tcg_resh
, rd
, 1, MO_64
);
4821 tcg_temp_free_i64(tcg_resh
);
4824 /* C3.6.3 ZIP/UZP/TRN
4825 * 31 30 29 24 23 22 21 20 16 15 14 12 11 10 9 5 4 0
4826 * +---+---+-------------+------+---+------+---+------------------+------+
4827 * | 0 | Q | 0 0 1 1 1 0 | size | 0 | Rm | 0 | opc | 1 0 | Rn | Rd |
4828 * +---+---+-------------+------+---+------+---+------------------+------+
4830 static void disas_simd_zip_trn(DisasContext
*s
, uint32_t insn
)
4832 int rd
= extract32(insn
, 0, 5);
4833 int rn
= extract32(insn
, 5, 5);
4834 int rm
= extract32(insn
, 16, 5);
4835 int size
= extract32(insn
, 22, 2);
4836 /* opc field bits [1:0] indicate ZIP/UZP/TRN;
4837 * bit 2 indicates 1 vs 2 variant of the insn.
4839 int opcode
= extract32(insn
, 12, 2);
4840 bool part
= extract32(insn
, 14, 1);
4841 bool is_q
= extract32(insn
, 30, 1);
4842 int esize
= 8 << size
;
4844 int datasize
= is_q
? 128 : 64;
4845 int elements
= datasize
/ esize
;
4846 TCGv_i64 tcg_res
, tcg_resl
, tcg_resh
;
4848 if (opcode
== 0 || (size
== 3 && !is_q
)) {
4849 unallocated_encoding(s
);
4853 tcg_resl
= tcg_const_i64(0);
4854 tcg_resh
= tcg_const_i64(0);
4855 tcg_res
= tcg_temp_new_i64();
4857 for (i
= 0; i
< elements
; i
++) {
4859 case 1: /* UZP1/2 */
4861 int midpoint
= elements
/ 2;
4863 read_vec_element(s
, tcg_res
, rn
, 2 * i
+ part
, size
);
4865 read_vec_element(s
, tcg_res
, rm
,
4866 2 * (i
- midpoint
) + part
, size
);
4870 case 2: /* TRN1/2 */
4872 read_vec_element(s
, tcg_res
, rm
, (i
& ~1) + part
, size
);
4874 read_vec_element(s
, tcg_res
, rn
, (i
& ~1) + part
, size
);
4877 case 3: /* ZIP1/2 */
4879 int base
= part
* elements
/ 2;
4881 read_vec_element(s
, tcg_res
, rm
, base
+ (i
>> 1), size
);
4883 read_vec_element(s
, tcg_res
, rn
, base
+ (i
>> 1), size
);
4888 g_assert_not_reached();
4893 tcg_gen_shli_i64(tcg_res
, tcg_res
, ofs
);
4894 tcg_gen_or_i64(tcg_resl
, tcg_resl
, tcg_res
);
4896 tcg_gen_shli_i64(tcg_res
, tcg_res
, ofs
- 64);
4897 tcg_gen_or_i64(tcg_resh
, tcg_resh
, tcg_res
);
4901 tcg_temp_free_i64(tcg_res
);
4903 write_vec_element(s
, tcg_resl
, rd
, 0, MO_64
);
4904 tcg_temp_free_i64(tcg_resl
);
4905 write_vec_element(s
, tcg_resh
, rd
, 1, MO_64
);
4906 tcg_temp_free_i64(tcg_resh
);
4909 static void do_minmaxop(DisasContext
*s
, TCGv_i32 tcg_elt1
, TCGv_i32 tcg_elt2
,
4910 int opc
, bool is_min
, TCGv_ptr fpst
)
4912 /* Helper function for disas_simd_across_lanes: do a single precision
4913 * min/max operation on the specified two inputs,
4914 * and return the result in tcg_elt1.
4918 gen_helper_vfp_minnums(tcg_elt1
, tcg_elt1
, tcg_elt2
, fpst
);
4920 gen_helper_vfp_maxnums(tcg_elt1
, tcg_elt1
, tcg_elt2
, fpst
);
4925 gen_helper_vfp_mins(tcg_elt1
, tcg_elt1
, tcg_elt2
, fpst
);
4927 gen_helper_vfp_maxs(tcg_elt1
, tcg_elt1
, tcg_elt2
, fpst
);
4932 /* C3.6.4 AdvSIMD across lanes
4933 * 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
4934 * +---+---+---+-----------+------+-----------+--------+-----+------+------+
4935 * | 0 | Q | U | 0 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 | Rn | Rd |
4936 * +---+---+---+-----------+------+-----------+--------+-----+------+------+
4938 static void disas_simd_across_lanes(DisasContext
*s
, uint32_t insn
)
4940 int rd
= extract32(insn
, 0, 5);
4941 int rn
= extract32(insn
, 5, 5);
4942 int size
= extract32(insn
, 22, 2);
4943 int opcode
= extract32(insn
, 12, 5);
4944 bool is_q
= extract32(insn
, 30, 1);
4945 bool is_u
= extract32(insn
, 29, 1);
4947 bool is_min
= false;
4951 TCGv_i64 tcg_res
, tcg_elt
;
4954 case 0x1b: /* ADDV */
4956 unallocated_encoding(s
);
4960 case 0x3: /* SADDLV, UADDLV */
4961 case 0xa: /* SMAXV, UMAXV */
4962 case 0x1a: /* SMINV, UMINV */
4963 if (size
== 3 || (size
== 2 && !is_q
)) {
4964 unallocated_encoding(s
);
4968 case 0xc: /* FMAXNMV, FMINNMV */
4969 case 0xf: /* FMAXV, FMINV */
4970 if (!is_u
|| !is_q
|| extract32(size
, 0, 1)) {
4971 unallocated_encoding(s
);
4974 /* Bit 1 of size field encodes min vs max, and actual size is always
4975 * 32 bits: adjust the size variable so following code can rely on it
4977 is_min
= extract32(size
, 1, 1);
4982 unallocated_encoding(s
);
4987 elements
= (is_q
? 128 : 64) / esize
;
4989 tcg_res
= tcg_temp_new_i64();
4990 tcg_elt
= tcg_temp_new_i64();
4992 /* These instructions operate across all lanes of a vector
4993 * to produce a single result. We can guarantee that a 64
4994 * bit intermediate is sufficient:
4995 * + for [US]ADDLV the maximum element size is 32 bits, and
4996 * the result type is 64 bits
4997 * + for FMAX*V, FMIN*V, ADDV the intermediate type is the
4998 * same as the element size, which is 32 bits at most
4999 * For the integer operations we can choose to work at 64
5000 * or 32 bits and truncate at the end; for simplicity
5001 * we use 64 bits always. The floating point
5002 * ops do require 32 bit intermediates, though.
5005 read_vec_element(s
, tcg_res
, rn
, 0, size
| (is_u
? 0 : MO_SIGN
));
5007 for (i
= 1; i
< elements
; i
++) {
5008 read_vec_element(s
, tcg_elt
, rn
, i
, size
| (is_u
? 0 : MO_SIGN
));
5011 case 0x03: /* SADDLV / UADDLV */
5012 case 0x1b: /* ADDV */
5013 tcg_gen_add_i64(tcg_res
, tcg_res
, tcg_elt
);
5015 case 0x0a: /* SMAXV / UMAXV */
5016 tcg_gen_movcond_i64(is_u
? TCG_COND_GEU
: TCG_COND_GE
,
5018 tcg_res
, tcg_elt
, tcg_res
, tcg_elt
);
5020 case 0x1a: /* SMINV / UMINV */
5021 tcg_gen_movcond_i64(is_u
? TCG_COND_LEU
: TCG_COND_LE
,
5023 tcg_res
, tcg_elt
, tcg_res
, tcg_elt
);
5027 g_assert_not_reached();
5032 /* Floating point ops which work on 32 bit (single) intermediates.
5033 * Note that correct NaN propagation requires that we do these
5034 * operations in exactly the order specified by the pseudocode.
5036 TCGv_i32 tcg_elt1
= tcg_temp_new_i32();
5037 TCGv_i32 tcg_elt2
= tcg_temp_new_i32();
5038 TCGv_i32 tcg_elt3
= tcg_temp_new_i32();
5039 TCGv_ptr fpst
= get_fpstatus_ptr();
5041 assert(esize
== 32);
5042 assert(elements
== 4);
5044 read_vec_element(s
, tcg_elt
, rn
, 0, MO_32
);
5045 tcg_gen_trunc_i64_i32(tcg_elt1
, tcg_elt
);
5046 read_vec_element(s
, tcg_elt
, rn
, 1, MO_32
);
5047 tcg_gen_trunc_i64_i32(tcg_elt2
, tcg_elt
);
5049 do_minmaxop(s
, tcg_elt1
, tcg_elt2
, opcode
, is_min
, fpst
);
5051 read_vec_element(s
, tcg_elt
, rn
, 2, MO_32
);
5052 tcg_gen_trunc_i64_i32(tcg_elt2
, tcg_elt
);
5053 read_vec_element(s
, tcg_elt
, rn
, 3, MO_32
);
5054 tcg_gen_trunc_i64_i32(tcg_elt3
, tcg_elt
);
5056 do_minmaxop(s
, tcg_elt2
, tcg_elt3
, opcode
, is_min
, fpst
);
5058 do_minmaxop(s
, tcg_elt1
, tcg_elt2
, opcode
, is_min
, fpst
);
5060 tcg_gen_extu_i32_i64(tcg_res
, tcg_elt1
);
5061 tcg_temp_free_i32(tcg_elt1
);
5062 tcg_temp_free_i32(tcg_elt2
);
5063 tcg_temp_free_i32(tcg_elt3
);
5064 tcg_temp_free_ptr(fpst
);
5067 tcg_temp_free_i64(tcg_elt
);
5069 /* Now truncate the result to the width required for the final output */
5070 if (opcode
== 0x03) {
5071 /* SADDLV, UADDLV: result is 2*esize */
5077 tcg_gen_ext8u_i64(tcg_res
, tcg_res
);
5080 tcg_gen_ext16u_i64(tcg_res
, tcg_res
);
5083 tcg_gen_ext32u_i64(tcg_res
, tcg_res
);
5088 g_assert_not_reached();
5091 write_fp_dreg(s
, rd
, tcg_res
);
5092 tcg_temp_free_i64(tcg_res
);
5095 /* C6.3.31 DUP (Element, Vector)
5097 * 31 30 29 21 20 16 15 10 9 5 4 0
5098 * +---+---+-------------------+--------+-------------+------+------+
5099 * | 0 | Q | 0 0 1 1 1 0 0 0 0 | imm5 | 0 0 0 0 0 1 | Rn | Rd |
5100 * +---+---+-------------------+--------+-------------+------+------+
5102 * size: encoded in imm5 (see ARM ARM LowestSetBit())
5104 static void handle_simd_dupe(DisasContext
*s
, int is_q
, int rd
, int rn
,
5107 int size
= ctz32(imm5
);
5108 int esize
= 8 << size
;
5109 int elements
= (is_q
? 128 : 64) / esize
;
5113 if (size
> 3 || (size
== 3 && !is_q
)) {
5114 unallocated_encoding(s
);
5118 index
= imm5
>> (size
+ 1);
5120 tmp
= tcg_temp_new_i64();
5121 read_vec_element(s
, tmp
, rn
, index
, size
);
5123 for (i
= 0; i
< elements
; i
++) {
5124 write_vec_element(s
, tmp
, rd
, i
, size
);
5128 clear_vec_high(s
, rd
);
5131 tcg_temp_free_i64(tmp
);
5134 /* C6.3.31 DUP (element, scalar)
5135 * 31 21 20 16 15 10 9 5 4 0
5136 * +-----------------------+--------+-------------+------+------+
5137 * | 0 1 0 1 1 1 1 0 0 0 0 | imm5 | 0 0 0 0 0 1 | Rn | Rd |
5138 * +-----------------------+--------+-------------+------+------+
5140 static void handle_simd_dupes(DisasContext
*s
, int rd
, int rn
,
5143 int size
= ctz32(imm5
);
5148 unallocated_encoding(s
);
5152 index
= imm5
>> (size
+ 1);
5154 /* This instruction just extracts the specified element and
5155 * zero-extends it into the bottom of the destination register.
5157 tmp
= tcg_temp_new_i64();
5158 read_vec_element(s
, tmp
, rn
, index
, size
);
5159 write_fp_dreg(s
, rd
, tmp
);
5160 tcg_temp_free_i64(tmp
);
5163 /* C6.3.32 DUP (General)
5165 * 31 30 29 21 20 16 15 10 9 5 4 0
5166 * +---+---+-------------------+--------+-------------+------+------+
5167 * | 0 | Q | 0 0 1 1 1 0 0 0 0 | imm5 | 0 0 0 0 1 1 | Rn | Rd |
5168 * +---+---+-------------------+--------+-------------+------+------+
5170 * size: encoded in imm5 (see ARM ARM LowestSetBit())
5172 static void handle_simd_dupg(DisasContext
*s
, int is_q
, int rd
, int rn
,
5175 int size
= ctz32(imm5
);
5176 int esize
= 8 << size
;
5177 int elements
= (is_q
? 128 : 64)/esize
;
5180 if (size
> 3 || ((size
== 3) && !is_q
)) {
5181 unallocated_encoding(s
);
5184 for (i
= 0; i
< elements
; i
++) {
5185 write_vec_element(s
, cpu_reg(s
, rn
), rd
, i
, size
);
5188 clear_vec_high(s
, rd
);
5192 /* C6.3.150 INS (Element)
5194 * 31 21 20 16 15 14 11 10 9 5 4 0
5195 * +-----------------------+--------+------------+---+------+------+
5196 * | 0 1 1 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 | Rn | Rd |
5197 * +-----------------------+--------+------------+---+------+------+
5199 * size: encoded in imm5 (see ARM ARM LowestSetBit())
5200 * index: encoded in imm5<4:size+1>
5202 static void handle_simd_inse(DisasContext
*s
, int rd
, int rn
,
5205 int size
= ctz32(imm5
);
5206 int src_index
, dst_index
;
5210 unallocated_encoding(s
);
5213 dst_index
= extract32(imm5
, 1+size
, 5);
5214 src_index
= extract32(imm4
, size
, 4);
5216 tmp
= tcg_temp_new_i64();
5218 read_vec_element(s
, tmp
, rn
, src_index
, size
);
5219 write_vec_element(s
, tmp
, rd
, dst_index
, size
);
5221 tcg_temp_free_i64(tmp
);
5225 /* C6.3.151 INS (General)
5227 * 31 21 20 16 15 10 9 5 4 0
5228 * +-----------------------+--------+-------------+------+------+
5229 * | 0 1 0 0 1 1 1 0 0 0 0 | imm5 | 0 0 0 1 1 1 | Rn | Rd |
5230 * +-----------------------+--------+-------------+------+------+
5232 * size: encoded in imm5 (see ARM ARM LowestSetBit())
5233 * index: encoded in imm5<4:size+1>
5235 static void handle_simd_insg(DisasContext
*s
, int rd
, int rn
, int imm5
)
5237 int size
= ctz32(imm5
);
5241 unallocated_encoding(s
);
5245 idx
= extract32(imm5
, 1 + size
, 4 - size
);
5246 write_vec_element(s
, cpu_reg(s
, rn
), rd
, idx
, size
);
5250 * C6.3.321 UMOV (General)
5251 * C6.3.237 SMOV (General)
5253 * 31 30 29 21 20 16 15 12 10 9 5 4 0
5254 * +---+---+-------------------+--------+-------------+------+------+
5255 * | 0 | Q | 0 0 1 1 1 0 0 0 0 | imm5 | 0 0 1 U 1 1 | Rn | Rd |
5256 * +---+---+-------------------+--------+-------------+------+------+
5258 * U: unsigned when set
5259 * size: encoded in imm5 (see ARM ARM LowestSetBit())
5261 static void handle_simd_umov_smov(DisasContext
*s
, int is_q
, int is_signed
,
5262 int rn
, int rd
, int imm5
)
5264 int size
= ctz32(imm5
);
5268 /* Check for UnallocatedEncodings */
5270 if (size
> 2 || (size
== 2 && !is_q
)) {
5271 unallocated_encoding(s
);
5276 || (size
< 3 && is_q
)
5277 || (size
== 3 && !is_q
)) {
5278 unallocated_encoding(s
);
5282 element
= extract32(imm5
, 1+size
, 4);
5284 tcg_rd
= cpu_reg(s
, rd
);
5285 read_vec_element(s
, tcg_rd
, rn
, element
, size
| (is_signed
? MO_SIGN
: 0));
5286 if (is_signed
&& !is_q
) {
5287 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
5291 /* C3.6.5 AdvSIMD copy
5292 * 31 30 29 28 21 20 16 15 14 11 10 9 5 4 0
5293 * +---+---+----+-----------------+------+---+------+---+------+------+
5294 * | 0 | Q | op | 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 | Rn | Rd |
5295 * +---+---+----+-----------------+------+---+------+---+------+------+
5297 static void disas_simd_copy(DisasContext
*s
, uint32_t insn
)
5299 int rd
= extract32(insn
, 0, 5);
5300 int rn
= extract32(insn
, 5, 5);
5301 int imm4
= extract32(insn
, 11, 4);
5302 int op
= extract32(insn
, 29, 1);
5303 int is_q
= extract32(insn
, 30, 1);
5304 int imm5
= extract32(insn
, 16, 5);
5309 handle_simd_inse(s
, rd
, rn
, imm4
, imm5
);
5311 unallocated_encoding(s
);
5316 /* DUP (element - vector) */
5317 handle_simd_dupe(s
, is_q
, rd
, rn
, imm5
);
5321 handle_simd_dupg(s
, is_q
, rd
, rn
, imm5
);
5326 handle_simd_insg(s
, rd
, rn
, imm5
);
5328 unallocated_encoding(s
);
5333 /* UMOV/SMOV (is_q indicates 32/64; imm4 indicates signedness) */
5334 handle_simd_umov_smov(s
, is_q
, (imm4
== 5), rn
, rd
, imm5
);
5337 unallocated_encoding(s
);
5343 /* C3.6.6 AdvSIMD modified immediate
5344 * 31 30 29 28 19 18 16 15 12 11 10 9 5 4 0
5345 * +---+---+----+---------------------+-----+-------+----+---+-------+------+
5346 * | 0 | Q | op | 0 1 1 1 1 0 0 0 0 0 | abc | cmode | o2 | 1 | defgh | Rd |
5347 * +---+---+----+---------------------+-----+-------+----+---+-------+------+
5349 * There are a number of operations that can be carried out here:
5350 * MOVI - move (shifted) imm into register
5351 * MVNI - move inverted (shifted) imm into register
5352 * ORR - bitwise OR of (shifted) imm with register
5353 * BIC - bitwise clear of (shifted) imm with register
5355 static void disas_simd_mod_imm(DisasContext
*s
, uint32_t insn
)
5357 int rd
= extract32(insn
, 0, 5);
5358 int cmode
= extract32(insn
, 12, 4);
5359 int cmode_3_1
= extract32(cmode
, 1, 3);
5360 int cmode_0
= extract32(cmode
, 0, 1);
5361 int o2
= extract32(insn
, 11, 1);
5362 uint64_t abcdefgh
= extract32(insn
, 5, 5) | (extract32(insn
, 16, 3) << 5);
5363 bool is_neg
= extract32(insn
, 29, 1);
5364 bool is_q
= extract32(insn
, 30, 1);
5366 TCGv_i64 tcg_rd
, tcg_imm
;
5369 if (o2
!= 0 || ((cmode
== 0xf) && is_neg
&& !is_q
)) {
5370 unallocated_encoding(s
);
5374 /* See AdvSIMDExpandImm() in ARM ARM */
5375 switch (cmode_3_1
) {
5376 case 0: /* Replicate(Zeros(24):imm8, 2) */
5377 case 1: /* Replicate(Zeros(16):imm8:Zeros(8), 2) */
5378 case 2: /* Replicate(Zeros(8):imm8:Zeros(16), 2) */
5379 case 3: /* Replicate(imm8:Zeros(24), 2) */
5381 int shift
= cmode_3_1
* 8;
5382 imm
= bitfield_replicate(abcdefgh
<< shift
, 32);
5385 case 4: /* Replicate(Zeros(8):imm8, 4) */
5386 case 5: /* Replicate(imm8:Zeros(8), 4) */
5388 int shift
= (cmode_3_1
& 0x1) * 8;
5389 imm
= bitfield_replicate(abcdefgh
<< shift
, 16);
5394 /* Replicate(Zeros(8):imm8:Ones(16), 2) */
5395 imm
= (abcdefgh
<< 16) | 0xffff;
5397 /* Replicate(Zeros(16):imm8:Ones(8), 2) */
5398 imm
= (abcdefgh
<< 8) | 0xff;
5400 imm
= bitfield_replicate(imm
, 32);
5403 if (!cmode_0
&& !is_neg
) {
5404 imm
= bitfield_replicate(abcdefgh
, 8);
5405 } else if (!cmode_0
&& is_neg
) {
5408 for (i
= 0; i
< 8; i
++) {
5409 if ((abcdefgh
) & (1 << i
)) {
5410 imm
|= 0xffULL
<< (i
* 8);
5413 } else if (cmode_0
) {
5415 imm
= (abcdefgh
& 0x3f) << 48;
5416 if (abcdefgh
& 0x80) {
5417 imm
|= 0x8000000000000000ULL
;
5419 if (abcdefgh
& 0x40) {
5420 imm
|= 0x3fc0000000000000ULL
;
5422 imm
|= 0x4000000000000000ULL
;
5425 imm
= (abcdefgh
& 0x3f) << 19;
5426 if (abcdefgh
& 0x80) {
5429 if (abcdefgh
& 0x40) {
5440 if (cmode_3_1
!= 7 && is_neg
) {
5444 tcg_imm
= tcg_const_i64(imm
);
5445 tcg_rd
= new_tmp_a64(s
);
5447 for (i
= 0; i
< 2; i
++) {
5448 int foffs
= i
? fp_reg_hi_offset(rd
) : fp_reg_offset(rd
, MO_64
);
5450 if (i
== 1 && !is_q
) {
5451 /* non-quad ops clear high half of vector */
5452 tcg_gen_movi_i64(tcg_rd
, 0);
5453 } else if ((cmode
& 0x9) == 0x1 || (cmode
& 0xd) == 0x9) {
5454 tcg_gen_ld_i64(tcg_rd
, cpu_env
, foffs
);
5457 tcg_gen_and_i64(tcg_rd
, tcg_rd
, tcg_imm
);
5460 tcg_gen_or_i64(tcg_rd
, tcg_rd
, tcg_imm
);
5464 tcg_gen_mov_i64(tcg_rd
, tcg_imm
);
5466 tcg_gen_st_i64(tcg_rd
, cpu_env
, foffs
);
5469 tcg_temp_free_i64(tcg_imm
);
5472 /* C3.6.7 AdvSIMD scalar copy
5473 * 31 30 29 28 21 20 16 15 14 11 10 9 5 4 0
5474 * +-----+----+-----------------+------+---+------+---+------+------+
5475 * | 0 1 | op | 1 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 | Rn | Rd |
5476 * +-----+----+-----------------+------+---+------+---+------+------+
5478 static void disas_simd_scalar_copy(DisasContext
*s
, uint32_t insn
)
5480 int rd
= extract32(insn
, 0, 5);
5481 int rn
= extract32(insn
, 5, 5);
5482 int imm4
= extract32(insn
, 11, 4);
5483 int imm5
= extract32(insn
, 16, 5);
5484 int op
= extract32(insn
, 29, 1);
5486 if (op
!= 0 || imm4
!= 0) {
5487 unallocated_encoding(s
);
5491 /* DUP (element, scalar) */
5492 handle_simd_dupes(s
, rd
, rn
, imm5
);
5495 /* C3.6.8 AdvSIMD scalar pairwise
5496 * 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
5497 * +-----+---+-----------+------+-----------+--------+-----+------+------+
5498 * | 0 1 | U | 1 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 | Rn | Rd |
5499 * +-----+---+-----------+------+-----------+--------+-----+------+------+
5501 static void disas_simd_scalar_pairwise(DisasContext
*s
, uint32_t insn
)
5503 unsupported_encoding(s
, insn
);
5507 * Common SSHR[RA]/USHR[RA] - Shift right (optional rounding/accumulate)
5509 * This code is handles the common shifting code and is used by both
5510 * the vector and scalar code.
5512 static void handle_shri_with_rndacc(TCGv_i64 tcg_res
, TCGv_i64 tcg_src
,
5513 TCGv_i64 tcg_rnd
, bool accumulate
,
5514 bool is_u
, int size
, int shift
)
5516 bool extended_result
= false;
5517 bool round
= !TCGV_IS_UNUSED_I64(tcg_rnd
);
5519 TCGv_i64 tcg_src_hi
;
5521 if (round
&& size
== 3) {
5522 extended_result
= true;
5523 ext_lshift
= 64 - shift
;
5524 tcg_src_hi
= tcg_temp_new_i64();
5525 } else if (shift
== 64) {
5526 if (!accumulate
&& is_u
) {
5527 /* result is zero */
5528 tcg_gen_movi_i64(tcg_res
, 0);
5533 /* Deal with the rounding step */
5535 if (extended_result
) {
5536 TCGv_i64 tcg_zero
= tcg_const_i64(0);
5538 /* take care of sign extending tcg_res */
5539 tcg_gen_sari_i64(tcg_src_hi
, tcg_src
, 63);
5540 tcg_gen_add2_i64(tcg_src
, tcg_src_hi
,
5541 tcg_src
, tcg_src_hi
,
5544 tcg_gen_add2_i64(tcg_src
, tcg_src_hi
,
5548 tcg_temp_free_i64(tcg_zero
);
5550 tcg_gen_add_i64(tcg_src
, tcg_src
, tcg_rnd
);
5554 /* Now do the shift right */
5555 if (round
&& extended_result
) {
5556 /* extended case, >64 bit precision required */
5557 if (ext_lshift
== 0) {
5558 /* special case, only high bits matter */
5559 tcg_gen_mov_i64(tcg_src
, tcg_src_hi
);
5561 tcg_gen_shri_i64(tcg_src
, tcg_src
, shift
);
5562 tcg_gen_shli_i64(tcg_src_hi
, tcg_src_hi
, ext_lshift
);
5563 tcg_gen_or_i64(tcg_src
, tcg_src
, tcg_src_hi
);
5568 /* essentially shifting in 64 zeros */
5569 tcg_gen_movi_i64(tcg_src
, 0);
5571 tcg_gen_shri_i64(tcg_src
, tcg_src
, shift
);
5575 /* effectively extending the sign-bit */
5576 tcg_gen_sari_i64(tcg_src
, tcg_src
, 63);
5578 tcg_gen_sari_i64(tcg_src
, tcg_src
, shift
);
5584 tcg_gen_add_i64(tcg_res
, tcg_res
, tcg_src
);
5586 tcg_gen_mov_i64(tcg_res
, tcg_src
);
5589 if (extended_result
) {
5590 tcg_temp_free_i64(tcg_src_hi
);
5594 /* Common SHL/SLI - Shift left with an optional insert */
5595 static void handle_shli_with_ins(TCGv_i64 tcg_res
, TCGv_i64 tcg_src
,
5596 bool insert
, int shift
)
5598 if (insert
) { /* SLI */
5599 tcg_gen_deposit_i64(tcg_res
, tcg_res
, tcg_src
, shift
, 64 - shift
);
5601 tcg_gen_shli_i64(tcg_res
, tcg_src
, shift
);
5605 /* SSHR[RA]/USHR[RA] - Scalar shift right (optional rounding/accumulate) */
5606 static void handle_scalar_simd_shri(DisasContext
*s
,
5607 bool is_u
, int immh
, int immb
,
5608 int opcode
, int rn
, int rd
)
5611 int immhb
= immh
<< 3 | immb
;
5612 int shift
= 2 * (8 << size
) - immhb
;
5613 bool accumulate
= false;
5619 if (!extract32(immh
, 3, 1)) {
5620 unallocated_encoding(s
);
5625 case 0x02: /* SSRA / USRA (accumulate) */
5628 case 0x04: /* SRSHR / URSHR (rounding) */
5631 case 0x06: /* SRSRA / URSRA (accum + rounding) */
5632 accumulate
= round
= true;
5637 uint64_t round_const
= 1ULL << (shift
- 1);
5638 tcg_round
= tcg_const_i64(round_const
);
5640 TCGV_UNUSED_I64(tcg_round
);
5643 tcg_rn
= read_fp_dreg(s
, rn
);
5644 tcg_rd
= accumulate
? read_fp_dreg(s
, rd
) : tcg_temp_new_i64();
5646 handle_shri_with_rndacc(tcg_rd
, tcg_rn
, tcg_round
,
5647 accumulate
, is_u
, size
, shift
);
5649 write_fp_dreg(s
, rd
, tcg_rd
);
5651 tcg_temp_free_i64(tcg_rn
);
5652 tcg_temp_free_i64(tcg_rd
);
5654 tcg_temp_free_i64(tcg_round
);
5658 /* SHL/SLI - Scalar shift left */
5659 static void handle_scalar_simd_shli(DisasContext
*s
, bool insert
,
5660 int immh
, int immb
, int opcode
,
5663 int size
= 32 - clz32(immh
) - 1;
5664 int immhb
= immh
<< 3 | immb
;
5665 int shift
= immhb
- (8 << size
);
5666 TCGv_i64 tcg_rn
= new_tmp_a64(s
);
5667 TCGv_i64 tcg_rd
= new_tmp_a64(s
);
5669 if (!extract32(immh
, 3, 1)) {
5670 unallocated_encoding(s
);
5674 tcg_rn
= read_fp_dreg(s
, rn
);
5675 tcg_rd
= insert
? read_fp_dreg(s
, rd
) : tcg_temp_new_i64();
5677 handle_shli_with_ins(tcg_rd
, tcg_rn
, insert
, shift
);
5679 write_fp_dreg(s
, rd
, tcg_rd
);
5681 tcg_temp_free_i64(tcg_rn
);
5682 tcg_temp_free_i64(tcg_rd
);
5685 /* C3.6.9 AdvSIMD scalar shift by immediate
5686 * 31 30 29 28 23 22 19 18 16 15 11 10 9 5 4 0
5687 * +-----+---+-------------+------+------+--------+---+------+------+
5688 * | 0 1 | U | 1 1 1 1 1 0 | immh | immb | opcode | 1 | Rn | Rd |
5689 * +-----+---+-------------+------+------+--------+---+------+------+
5691 * This is the scalar version so it works on a fixed sized registers
5693 static void disas_simd_scalar_shift_imm(DisasContext
*s
, uint32_t insn
)
5695 int rd
= extract32(insn
, 0, 5);
5696 int rn
= extract32(insn
, 5, 5);
5697 int opcode
= extract32(insn
, 11, 5);
5698 int immb
= extract32(insn
, 16, 3);
5699 int immh
= extract32(insn
, 19, 4);
5700 bool is_u
= extract32(insn
, 29, 1);
5703 case 0x00: /* SSHR / USHR */
5704 case 0x02: /* SSRA / USRA */
5705 case 0x04: /* SRSHR / URSHR */
5706 case 0x06: /* SRSRA / URSRA */
5707 handle_scalar_simd_shri(s
, is_u
, immh
, immb
, opcode
, rn
, rd
);
5709 case 0x0a: /* SHL / SLI */
5710 handle_scalar_simd_shli(s
, is_u
, immh
, immb
, opcode
, rn
, rd
);
5713 unsupported_encoding(s
, insn
);
5718 /* C3.6.10 AdvSIMD scalar three different
5719 * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
5720 * +-----+---+-----------+------+---+------+--------+-----+------+------+
5721 * | 0 1 | U | 1 1 1 1 0 | size | 1 | Rm | opcode | 0 0 | Rn | Rd |
5722 * +-----+---+-----------+------+---+------+--------+-----+------+------+
5724 static void disas_simd_scalar_three_reg_diff(DisasContext
*s
, uint32_t insn
)
5726 unsupported_encoding(s
, insn
);
5729 static void handle_3same_64(DisasContext
*s
, int opcode
, bool u
,
5730 TCGv_i64 tcg_rd
, TCGv_i64 tcg_rn
, TCGv_i64 tcg_rm
)
5732 /* Handle 64x64->64 opcodes which are shared between the scalar
5733 * and vector 3-same groups. We cover every opcode where size == 3
5734 * is valid in either the three-reg-same (integer, not pairwise)
5735 * or scalar-three-reg-same groups. (Some opcodes are not yet
5741 case 0x6: /* CMGT, CMHI */
5742 /* 64 bit integer comparison, result = test ? (2^64 - 1) : 0.
5743 * We implement this using setcond (test) and then negating.
5745 cond
= u
? TCG_COND_GTU
: TCG_COND_GT
;
5747 tcg_gen_setcond_i64(cond
, tcg_rd
, tcg_rn
, tcg_rm
);
5748 tcg_gen_neg_i64(tcg_rd
, tcg_rd
);
5750 case 0x7: /* CMGE, CMHS */
5751 cond
= u
? TCG_COND_GEU
: TCG_COND_GE
;
5753 case 0x11: /* CMTST, CMEQ */
5758 /* CMTST : test is "if (X & Y != 0)". */
5759 tcg_gen_and_i64(tcg_rd
, tcg_rn
, tcg_rm
);
5760 tcg_gen_setcondi_i64(TCG_COND_NE
, tcg_rd
, tcg_rd
, 0);
5761 tcg_gen_neg_i64(tcg_rd
, tcg_rd
);
5763 case 0x10: /* ADD, SUB */
5765 tcg_gen_sub_i64(tcg_rd
, tcg_rn
, tcg_rm
);
5767 tcg_gen_add_i64(tcg_rd
, tcg_rn
, tcg_rm
);
5770 case 0x1: /* SQADD */
5771 case 0x5: /* SQSUB */
5772 case 0x8: /* SSHL, USHL */
5773 case 0x9: /* SQSHL, UQSHL */
5774 case 0xa: /* SRSHL, URSHL */
5775 case 0xb: /* SQRSHL, UQRSHL */
5777 g_assert_not_reached();
5781 /* Handle the 3-same-operands float operations; shared by the scalar
5782 * and vector encodings. The caller must filter out any encodings
5783 * not allocated for the encoding it is dealing with.
5785 static void handle_3same_float(DisasContext
*s
, int size
, int elements
,
5786 int fpopcode
, int rd
, int rn
, int rm
)
5789 TCGv_ptr fpst
= get_fpstatus_ptr();
5791 for (pass
= 0; pass
< elements
; pass
++) {
5794 TCGv_i64 tcg_op1
= tcg_temp_new_i64();
5795 TCGv_i64 tcg_op2
= tcg_temp_new_i64();
5796 TCGv_i64 tcg_res
= tcg_temp_new_i64();
5798 read_vec_element(s
, tcg_op1
, rn
, pass
, MO_64
);
5799 read_vec_element(s
, tcg_op2
, rm
, pass
, MO_64
);
5802 case 0x18: /* FMAXNM */
5803 gen_helper_vfp_maxnumd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5805 case 0x1a: /* FADD */
5806 gen_helper_vfp_addd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5808 case 0x1e: /* FMAX */
5809 gen_helper_vfp_maxd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5811 case 0x38: /* FMINNM */
5812 gen_helper_vfp_minnumd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5814 case 0x3a: /* FSUB */
5815 gen_helper_vfp_subd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5817 case 0x3e: /* FMIN */
5818 gen_helper_vfp_mind(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5820 case 0x5b: /* FMUL */
5821 gen_helper_vfp_muld(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5823 case 0x5f: /* FDIV */
5824 gen_helper_vfp_divd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5826 case 0x7a: /* FABD */
5827 gen_helper_vfp_subd(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5828 gen_helper_vfp_absd(tcg_res
, tcg_res
);
5831 g_assert_not_reached();
5834 write_vec_element(s
, tcg_res
, rd
, pass
, MO_64
);
5836 tcg_temp_free_i64(tcg_res
);
5837 tcg_temp_free_i64(tcg_op1
);
5838 tcg_temp_free_i64(tcg_op2
);
5841 TCGv_i32 tcg_op1
= tcg_temp_new_i32();
5842 TCGv_i32 tcg_op2
= tcg_temp_new_i32();
5843 TCGv_i32 tcg_res
= tcg_temp_new_i32();
5845 read_vec_element_i32(s
, tcg_op1
, rn
, pass
, MO_32
);
5846 read_vec_element_i32(s
, tcg_op2
, rm
, pass
, MO_32
);
5849 case 0x1a: /* FADD */
5850 gen_helper_vfp_adds(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5852 case 0x1e: /* FMAX */
5853 gen_helper_vfp_maxs(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5855 case 0x18: /* FMAXNM */
5856 gen_helper_vfp_maxnums(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5858 case 0x38: /* FMINNM */
5859 gen_helper_vfp_minnums(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5861 case 0x3a: /* FSUB */
5862 gen_helper_vfp_subs(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5864 case 0x3e: /* FMIN */
5865 gen_helper_vfp_mins(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5867 case 0x5b: /* FMUL */
5868 gen_helper_vfp_muls(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5870 case 0x5f: /* FDIV */
5871 gen_helper_vfp_divs(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5873 case 0x7a: /* FABD */
5874 gen_helper_vfp_subs(tcg_res
, tcg_op1
, tcg_op2
, fpst
);
5875 gen_helper_vfp_abss(tcg_res
, tcg_res
);
5878 g_assert_not_reached();
5881 if (elements
== 1) {
5882 /* scalar single so clear high part */
5883 TCGv_i64 tcg_tmp
= tcg_temp_new_i64();
5885 tcg_gen_extu_i32_i64(tcg_tmp
, tcg_res
);
5886 write_vec_element(s
, tcg_tmp
, rd
, pass
, MO_64
);
5887 tcg_temp_free_i64(tcg_tmp
);
5889 write_vec_element_i32(s
, tcg_res
, rd
, pass
, MO_32
);
5892 tcg_temp_free_i32(tcg_res
);
5893 tcg_temp_free_i32(tcg_op1
);
5894 tcg_temp_free_i32(tcg_op2
);
5898 tcg_temp_free_ptr(fpst
);
5900 if ((elements
<< size
) < 4) {
5901 /* scalar, or non-quad vector op */
5902 clear_vec_high(s
, rd
);
5906 /* C3.6.11 AdvSIMD scalar three same
5907 * 31 30 29 28 24 23 22 21 20 16 15 11 10 9 5 4 0
5908 * +-----+---+-----------+------+---+------+--------+---+------+------+
5909 * | 0 1 | U | 1 1 1 1 0 | size | 1 | Rm | opcode | 1 | Rn | Rd |
5910 * +-----+---+-----------+------+---+------+--------+---+------+------+
5912 static void disas_simd_scalar_three_reg_same(DisasContext
*s
, uint32_t insn
)
5914 int rd
= extract32(insn
, 0, 5);
5915 int rn
= extract32(insn
, 5, 5);
5916 int opcode
= extract32(insn
, 11, 5);
5917 int rm
= extract32(insn
, 16, 5);
5918 int size
= extract32(insn
, 22, 2);
5919 bool u
= extract32(insn
, 29, 1);
5924 if (opcode
>= 0x18) {
5925 /* Floating point: U, size[1] and opcode indicate operation */
5926 int fpopcode
= opcode
| (extract32(size
, 1, 1) << 5) | (u
<< 6);
5928 case 0x1b: /* FMULX */
5929 case 0x1c: /* FCMEQ */
5930 case 0x1f: /* FRECPS */
5931 case 0x3f: /* FRSQRTS */
5932 case 0x5c: /* FCMGE */
5933 case 0x5d: /* FACGE */
5934 case 0x7c: /* FCMGT */
5935 case 0x7d: /* FACGT */
5936 unsupported_encoding(s
, insn
);
5938 case 0x7a: /* FABD */
5941 unallocated_encoding(s
);
5945 handle_3same_float(s
, extract32(size
, 0, 1), 1, fpopcode
, rd
, rn
, rm
);
5950 case 0x1: /* SQADD, UQADD */
5951 case 0x5: /* SQSUB, UQSUB */
5952 case 0x8: /* SSHL, USHL */
5953 case 0xa: /* SRSHL, URSHL */
5954 unsupported_encoding(s
, insn
);
5956 case 0x6: /* CMGT, CMHI */
5957 case 0x7: /* CMGE, CMHS */
5958 case 0x11: /* CMTST, CMEQ */
5959 case 0x10: /* ADD, SUB (vector) */
5961 unallocated_encoding(s
);
5965 case 0x9: /* SQSHL, UQSHL */
5966 case 0xb: /* SQRSHL, UQRSHL */
5967 unsupported_encoding(s
, insn
);
5969 case 0x16: /* SQDMULH, SQRDMULH (vector) */
5970 if (size
!= 1 && size
!= 2) {
5971 unallocated_encoding(s
);
5974 unsupported_encoding(s
, insn
);
5977 unallocated_encoding(s
);
5981 tcg_rn
= read_fp_dreg(s
, rn
); /* op1 */
5982 tcg_rm
= read_fp_dreg(s
, rm
); /* op2 */
5983 tcg_rd
= tcg_temp_new_i64();
5985 /* For the moment we only support the opcodes which are
5986 * 64-bit-width only. The size != 3 cases will
5987 * be handled later when the relevant ops are implemented.
5989 handle_3same_64(s
, opcode
, u
, tcg_rd
, tcg_rn
, tcg_rm
);
5991 write_fp_dreg(s
, rd
, tcg_rd
);
5993 tcg_temp_free_i64(tcg_rn
);
5994 tcg_temp_free_i64(tcg_rm
);
5995 tcg_temp_free_i64(tcg_rd
);
5998 /* C3.6.12 AdvSIMD scalar two reg misc
5999 * 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
6000 * +-----+---+-----------+------+-----------+--------+-----+------+------+
6001 * | 0 1 | U | 1 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 | Rn | Rd |
6002 * +-----+---+-----------+------+-----------+--------+-----+------+------+
6004 static void disas_simd_scalar_two_reg_misc(DisasContext
*s
, uint32_t insn
)
6006 unsupported_encoding(s
, insn
);
6009 /* C3.6.13 AdvSIMD scalar x indexed element
6010 * 31 30 29 28 24 23 22 21 20 19 16 15 12 11 10 9 5 4 0
6011 * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
6012 * | 0 1 | U | 1 1 1 1 1 | size | L | M | Rm | opc | H | 0 | Rn | Rd |
6013 * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
6015 static void disas_simd_scalar_indexed(DisasContext
*s
, uint32_t insn
)
6017 unsupported_encoding(s
, insn
);
6020 /* SSHR[RA]/USHR[RA] - Vector shift right (optional rounding/accumulate) */
6021 static void handle_vec_simd_shri(DisasContext
*s
, bool is_q
, bool is_u
,
6022 int immh
, int immb
, int opcode
, int rn
, int rd
)
6024 int size
= 32 - clz32(immh
) - 1;
6025 int immhb
= immh
<< 3 | immb
;
6026 int shift
= 2 * (8 << size
) - immhb
;
6027 bool accumulate
= false;
6029 int dsize
= is_q
? 128 : 64;
6030 int esize
= 8 << size
;
6031 int elements
= dsize
/esize
;
6032 TCGMemOp memop
= size
| (is_u
? 0 : MO_SIGN
);
6033 TCGv_i64 tcg_rn
= new_tmp_a64(s
);
6034 TCGv_i64 tcg_rd
= new_tmp_a64(s
);
6038 if (extract32(immh
, 3, 1) && !is_q
) {
6039 unallocated_encoding(s
);
6043 if (size
> 3 && !is_q
) {
6044 unallocated_encoding(s
);
6049 case 0x02: /* SSRA / USRA (accumulate) */
6052 case 0x04: /* SRSHR / URSHR (rounding) */
6055 case 0x06: /* SRSRA / URSRA (accum + rounding) */
6056 accumulate
= round
= true;
6061 uint64_t round_const
= 1ULL << (shift
- 1);
6062 tcg_round
= tcg_const_i64(round_const
);
6064 TCGV_UNUSED_I64(tcg_round
);
6067 for (i
= 0; i
< elements
; i
++) {
6068 read_vec_element(s
, tcg_rn
, rn
, i
, memop
);
6070 read_vec_element(s
, tcg_rd
, rd
, i
, memop
);
6073 handle_shri_with_rndacc(tcg_rd
, tcg_rn
, tcg_round
,
6074 accumulate
, is_u
, size
, shift
);
6076 write_vec_element(s
, tcg_rd
, rd
, i
, size
);
6080 clear_vec_high(s
, rd
);
6084 tcg_temp_free_i64(tcg_round
);
6088 /* SHL/SLI - Vector shift left */
6089 static void handle_vec_simd_shli(DisasContext
*s
, bool is_q
, bool insert
,
6090 int immh
, int immb
, int opcode
, int rn
, int rd
)
6092 int size
= 32 - clz32(immh
) - 1;
6093 int immhb
= immh
<< 3 | immb
;
6094 int shift
= immhb
- (8 << size
);
6095 int dsize
= is_q
? 128 : 64;
6096 int esize
= 8 << size
;
6097 int elements
= dsize
/esize
;
6098 TCGv_i64 tcg_rn
= new_tmp_a64(s
);
6099 TCGv_i64 tcg_rd
= new_tmp_a64(s
);
6102 if (extract32(immh
, 3, 1) && !is_q
) {
6103 unallocated_encoding(s
);
6107 if (size
> 3 && !is_q
) {
6108 unallocated_encoding(s
);
6112 for (i
= 0; i
< elements
; i
++) {
6113 read_vec_element(s
, tcg_rn
, rn
, i
, size
);
6115 read_vec_element(s
, tcg_rd
, rd
, i
, size
);
6118 handle_shli_with_ins(tcg_rd
, tcg_rn
, insert
, shift
);
6120 write_vec_element(s
, tcg_rd
, rd
, i
, size
);
6124 clear_vec_high(s
, rd
);
6128 /* USHLL/SHLL - Vector shift left with widening */
6129 static void handle_vec_simd_wshli(DisasContext
*s
, bool is_q
, bool is_u
,
6130 int immh
, int immb
, int opcode
, int rn
, int rd
)
6132 int size
= 32 - clz32(immh
) - 1;
6133 int immhb
= immh
<< 3 | immb
;
6134 int shift
= immhb
- (8 << size
);
6136 int esize
= 8 << size
;
6137 int elements
= dsize
/esize
;
6138 TCGv_i64 tcg_rn
= new_tmp_a64(s
);
6139 TCGv_i64 tcg_rd
= new_tmp_a64(s
);
6143 unallocated_encoding(s
);
6147 /* For the LL variants the store is larger than the load,
6148 * so if rd == rn we would overwrite parts of our input.
6149 * So load everything right now and use shifts in the main loop.
6151 read_vec_element(s
, tcg_rn
, rn
, is_q
? 1 : 0, MO_64
);
6153 for (i
= 0; i
< elements
; i
++) {
6154 tcg_gen_shri_i64(tcg_rd
, tcg_rn
, i
* esize
);
6155 ext_and_shift_reg(tcg_rd
, tcg_rd
, size
| (!is_u
<< 2), 0);
6156 tcg_gen_shli_i64(tcg_rd
, tcg_rd
, shift
);
6157 write_vec_element(s
, tcg_rd
, rd
, i
, size
+ 1);
6162 /* C3.6.14 AdvSIMD shift by immediate
6163 * 31 30 29 28 23 22 19 18 16 15 11 10 9 5 4 0
6164 * +---+---+---+-------------+------+------+--------+---+------+------+
6165 * | 0 | Q | U | 0 1 1 1 1 0 | immh | immb | opcode | 1 | Rn | Rd |
6166 * +---+---+---+-------------+------+------+--------+---+------+------+
6168 static void disas_simd_shift_imm(DisasContext
*s
, uint32_t insn
)
6170 int rd
= extract32(insn
, 0, 5);
6171 int rn
= extract32(insn
, 5, 5);
6172 int opcode
= extract32(insn
, 11, 5);
6173 int immb
= extract32(insn
, 16, 3);
6174 int immh
= extract32(insn
, 19, 4);
6175 bool is_u
= extract32(insn
, 29, 1);
6176 bool is_q
= extract32(insn
, 30, 1);
6179 case 0x00: /* SSHR / USHR */
6180 case 0x02: /* SSRA / USRA (accumulate) */
6181 case 0x04: /* SRSHR / URSHR (rounding) */
6182 case 0x06: /* SRSRA / URSRA (accum + rounding) */
6183 handle_vec_simd_shri(s
, is_q
, is_u
, immh
, immb
, opcode
, rn
, rd
);
6185 case 0x0a: /* SHL / SLI */
6186 handle_vec_simd_shli(s
, is_q
, is_u
, immh
, immb
, opcode
, rn
, rd
);
6188 case 0x14: /* SSHLL / USHLL */
6189 handle_vec_simd_wshli(s
, is_q
, is_u
, immh
, immb
, opcode
, rn
, rd
);
6192 /* We don't currently implement any of the Narrow or saturating shifts;
6193 * nor do we implement the fixed-point conversions in this
6194 * encoding group (SCVTF, FCVTZS, UCVTF, FCVTZU).
6196 unsupported_encoding(s
, insn
);
6201 static void handle_3rd_widening(DisasContext
*s
, int is_q
, int is_u
, int size
,
6202 int opcode
, int rd
, int rn
, int rm
)
6204 /* 3-reg-different widening insns: 64 x 64 -> 128 */
6205 TCGv_i64 tcg_res
[2];
6208 tcg_res
[0] = tcg_temp_new_i64();
6209 tcg_res
[1] = tcg_temp_new_i64();
6211 /* Does this op do an adding accumulate, a subtracting accumulate,
6212 * or no accumulate at all?
6230 read_vec_element(s
, tcg_res
[0], rd
, 0, MO_64
);
6231 read_vec_element(s
, tcg_res
[1], rd
, 1, MO_64
);
6234 /* size == 2 means two 32x32->64 operations; this is worth special
6235 * casing because we can generally handle it inline.
6238 for (pass
= 0; pass
< 2; pass
++) {
6239 TCGv_i64 tcg_op1
= tcg_temp_new_i64();
6240 TCGv_i64 tcg_op2
= tcg_temp_new_i64();
6241 TCGv_i64 tcg_passres
;
6242 TCGMemOp memop
= MO_32
| (is_u
? 0 : MO_SIGN
);
6244 int elt
= pass
+ is_q
* 2;
6246 read_vec_element(s
, tcg_op1
, rn
, elt
, memop
);
6247 read_vec_element(s
, tcg_op2
, rm
, elt
, memop
);
6250 tcg_passres
= tcg_res
[pass
];
6252 tcg_passres
= tcg_temp_new_i64();
6256 case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
6257 case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
6259 TCGv_i64 tcg_tmp1
= tcg_temp_new_i64();
6260 TCGv_i64 tcg_tmp2
= tcg_temp_new_i64();
6262 tcg_gen_sub_i64(tcg_tmp1
, tcg_op1
, tcg_op2
);
6263 tcg_gen_sub_i64(tcg_tmp2
, tcg_op2
, tcg_op1
);
6264 tcg_gen_movcond_i64(is_u
? TCG_COND_GEU
: TCG_COND_GE
,
6266 tcg_op1
, tcg_op2
, tcg_tmp1
, tcg_tmp2
);
6267 tcg_temp_free_i64(tcg_tmp1
);
6268 tcg_temp_free_i64(tcg_tmp2
);
6271 case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
6272 case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
6273 case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
6274 tcg_gen_mul_i64(tcg_passres
, tcg_op1
, tcg_op2
);
6277 g_assert_not_reached();
6281 tcg_gen_add_i64(tcg_res
[pass
], tcg_res
[pass
], tcg_passres
);
6282 tcg_temp_free_i64(tcg_passres
);
6283 } else if (accop
< 0) {
6284 tcg_gen_sub_i64(tcg_res
[pass
], tcg_res
[pass
], tcg_passres
);
6285 tcg_temp_free_i64(tcg_passres
);
6288 tcg_temp_free_i64(tcg_op1
);
6289 tcg_temp_free_i64(tcg_op2
);
6292 /* size 0 or 1, generally helper functions */
6293 for (pass
= 0; pass
< 2; pass
++) {
6294 TCGv_i32 tcg_op1
= tcg_temp_new_i32();
6295 TCGv_i32 tcg_op2
= tcg_temp_new_i32();
6296 TCGv_i64 tcg_passres
;
6297 int elt
= pass
+ is_q
* 2;
6299 read_vec_element_i32(s
, tcg_op1
, rn
, elt
, MO_32
);
6300 read_vec_element_i32(s
, tcg_op2
, rm
, elt
, MO_32
);
6303 tcg_passres
= tcg_res
[pass
];
6305 tcg_passres
= tcg_temp_new_i64();
6309 case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
6310 case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
6313 gen_helper_neon_abdl_u16(tcg_passres
, tcg_op1
, tcg_op2
);
6315 gen_helper_neon_abdl_s16(tcg_passres
, tcg_op1
, tcg_op2
);
6319 gen_helper_neon_abdl_u32(tcg_passres
, tcg_op1
, tcg_op2
);
6321 gen_helper_neon_abdl_s32(tcg_passres
, tcg_op1
, tcg_op2
);
6325 case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
6326 case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
6327 case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
6330 gen_helper_neon_mull_u8(tcg_passres
, tcg_op1
, tcg_op2
);
6332 gen_helper_neon_mull_s8(tcg_passres
, tcg_op1
, tcg_op2
);
6336 gen_helper_neon_mull_u16(tcg_passres
, tcg_op1
, tcg_op2
);
6338 gen_helper_neon_mull_s16(tcg_passres
, tcg_op1
, tcg_op2
);
6343 g_assert_not_reached();
6345 tcg_temp_free_i32(tcg_op1
);
6346 tcg_temp_free_i32(tcg_op2
);
6350 gen_helper_neon_addl_u16(tcg_res
[pass
], tcg_res
[pass
],
6353 gen_helper_neon_addl_u32(tcg_res
[pass
], tcg_res
[pass
],
6356 tcg_temp_free_i64(tcg_passres
);
6357 } else if (accop
< 0) {
6359 gen_helper_neon_subl_u16(tcg_res
[pass
], tcg_res
[pass
],
6362 gen_helper_neon_subl_u32(tcg_res
[pass
], tcg_res
[pass
],
6365 tcg_temp_free_i64(tcg_passres
);
6370 write_vec_element(s
, tcg_res
[0], rd
, 0, MO_64
);
6371 write_vec_element(s
, tcg_res
[1], rd
, 1, MO_64
);
6372 tcg_temp_free_i64(tcg_res
[0]);
6373 tcg_temp_free_i64(tcg_res
[1]);
6376 /* C3.6.15 AdvSIMD three different
6377 * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
6378 * +---+---+---+-----------+------+---+------+--------+-----+------+------+
6379 * | 0 | Q | U | 0 1 1 1 0 | size | 1 | Rm | opcode | 0 0 | Rn | Rd |
6380 * +---+---+---+-----------+------+---+------+--------+-----+------+------+
6382 static void disas_simd_three_reg_diff(DisasContext
*s
, uint32_t insn
)
6384 /* Instructions in this group fall into three basic classes
6385 * (in each case with the operation working on each element in
6386 * the input vectors):
6387 * (1) widening 64 x 64 -> 128 (with possibly Vd as an extra
6389 * (2) wide 64 x 128 -> 128
6390 * (3) narrowing 128 x 128 -> 64
6391 * Here we do initial decode, catch unallocated cases and
6392 * dispatch to separate functions for each class.
6394 int is_q
= extract32(insn
, 30, 1);
6395 int is_u
= extract32(insn
, 29, 1);
6396 int size
= extract32(insn
, 22, 2);
6397 int opcode
= extract32(insn
, 12, 4);
6398 int rm
= extract32(insn
, 16, 5);
6399 int rn
= extract32(insn
, 5, 5);
6400 int rd
= extract32(insn
, 0, 5);
6403 case 1: /* SADDW, SADDW2, UADDW, UADDW2 */
6404 case 3: /* SSUBW, SSUBW2, USUBW, USUBW2 */
6405 /* 64 x 128 -> 128 */
6406 unsupported_encoding(s
, insn
);
6408 case 4: /* ADDHN, ADDHN2, RADDHN, RADDHN2 */
6409 case 6: /* SUBHN, SUBHN2, RSUBHN, RSUBHN2 */
6410 /* 128 x 128 -> 64 */
6411 unsupported_encoding(s
, insn
);
6418 unallocated_encoding(s
);
6424 unsupported_encoding(s
, insn
);
6431 /* 64 x 64 -> 128 */
6433 unallocated_encoding(s
);
6436 handle_3rd_widening(s
, is_q
, is_u
, size
, opcode
, rd
, rn
, rm
);
6439 /* opcode 15 not allocated */
6440 unallocated_encoding(s
);
6445 /* Logic op (opcode == 3) subgroup of C3.6.16. */
6446 static void disas_simd_3same_logic(DisasContext
*s
, uint32_t insn
)
6448 int rd
= extract32(insn
, 0, 5);
6449 int rn
= extract32(insn
, 5, 5);
6450 int rm
= extract32(insn
, 16, 5);
6451 int size
= extract32(insn
, 22, 2);
6452 bool is_u
= extract32(insn
, 29, 1);
6453 bool is_q
= extract32(insn
, 30, 1);
6454 TCGv_i64 tcg_op1
= tcg_temp_new_i64();
6455 TCGv_i64 tcg_op2
= tcg_temp_new_i64();
6456 TCGv_i64 tcg_res
[2];
6459 tcg_res
[0] = tcg_temp_new_i64();
6460 tcg_res
[1] = tcg_temp_new_i64();
6462 for (pass
= 0; pass
< (is_q
? 2 : 1); pass
++) {
6463 read_vec_element(s
, tcg_op1
, rn
, pass
, MO_64
);
6464 read_vec_element(s
, tcg_op2
, rm
, pass
, MO_64
);
6469 tcg_gen_and_i64(tcg_res
[pass
], tcg_op1
, tcg_op2
);
6472 tcg_gen_andc_i64(tcg_res
[pass
], tcg_op1
, tcg_op2
);
6475 tcg_gen_or_i64(tcg_res
[pass
], tcg_op1
, tcg_op2
);
6478 tcg_gen_orc_i64(tcg_res
[pass
], tcg_op1
, tcg_op2
);
6483 /* B* ops need res loaded to operate on */
6484 read_vec_element(s
, tcg_res
[pass
], rd
, pass
, MO_64
);
6489 tcg_gen_xor_i64(tcg_res
[pass
], tcg_op1
, tcg_op2
);
6491 case 1: /* BSL bitwise select */
6492 tcg_gen_xor_i64(tcg_op1
, tcg_op1
, tcg_op2
);
6493 tcg_gen_and_i64(tcg_op1
, tcg_op1
, tcg_res
[pass
]);
6494 tcg_gen_xor_i64(tcg_res
[pass
], tcg_op2
, tcg_op1
);
6496 case 2: /* BIT, bitwise insert if true */
6497 tcg_gen_xor_i64(tcg_op1
, tcg_op1
, tcg_res
[pass
]);
6498 tcg_gen_and_i64(tcg_op1
, tcg_op1
, tcg_op2
);
6499 tcg_gen_xor_i64(tcg_res
[pass
], tcg_res
[pass
], tcg_op1
);
6501 case 3: /* BIF, bitwise insert if false */
6502 tcg_gen_xor_i64(tcg_op1
, tcg_op1
, tcg_res
[pass
]);
6503 tcg_gen_andc_i64(tcg_op1
, tcg_op1
, tcg_op2
);
6504 tcg_gen_xor_i64(tcg_res
[pass
], tcg_res
[pass
], tcg_op1
);
6510 write_vec_element(s
, tcg_res
[0], rd
, 0, MO_64
);
6512 tcg_gen_movi_i64(tcg_res
[1], 0);
6514 write_vec_element(s
, tcg_res
[1], rd
, 1, MO_64
);
6516 tcg_temp_free_i64(tcg_op1
);
6517 tcg_temp_free_i64(tcg_op2
);
6518 tcg_temp_free_i64(tcg_res
[0]);
6519 tcg_temp_free_i64(tcg_res
[1]);
6522 /* Pairwise op subgroup of C3.6.16. */
6523 static void disas_simd_3same_pair(DisasContext
*s
, uint32_t insn
)
6525 unsupported_encoding(s
, insn
);
6528 /* Floating point op subgroup of C3.6.16. */
6529 static void disas_simd_3same_float(DisasContext
*s
, uint32_t insn
)
6531 /* For floating point ops, the U, size[1] and opcode bits
6532 * together indicate the operation. size[0] indicates single
6535 int fpopcode
= extract32(insn
, 11, 5)
6536 | (extract32(insn
, 23, 1) << 5)
6537 | (extract32(insn
, 29, 1) << 6);
6538 int is_q
= extract32(insn
, 30, 1);
6539 int size
= extract32(insn
, 22, 1);
6540 int rm
= extract32(insn
, 16, 5);
6541 int rn
= extract32(insn
, 5, 5);
6542 int rd
= extract32(insn
, 0, 5);
6544 int datasize
= is_q
? 128 : 64;
6545 int esize
= 32 << size
;
6546 int elements
= datasize
/ esize
;
6548 if (size
== 1 && !is_q
) {
6549 unallocated_encoding(s
);
6554 case 0x58: /* FMAXNMP */
6555 case 0x5a: /* FADDP */
6556 case 0x5e: /* FMAXP */
6557 case 0x78: /* FMINNMP */
6558 case 0x7e: /* FMINP */
6560 unsupported_encoding(s
, insn
);
6562 case 0x1b: /* FMULX */
6563 case 0x1c: /* FCMEQ */
6564 case 0x1f: /* FRECPS */
6565 case 0x3f: /* FRSQRTS */
6566 case 0x5c: /* FCMGE */
6567 case 0x5d: /* FACGE */
6568 case 0x7c: /* FCMGT */
6569 case 0x7d: /* FACGT */
6570 case 0x19: /* FMLA */
6571 case 0x39: /* FMLS */
6572 unsupported_encoding(s
, insn
);
6574 case 0x18: /* FMAXNM */
6575 case 0x1a: /* FADD */
6576 case 0x1e: /* FMAX */
6577 case 0x38: /* FMINNM */
6578 case 0x3a: /* FSUB */
6579 case 0x3e: /* FMIN */
6580 case 0x5b: /* FMUL */
6581 case 0x5f: /* FDIV */
6582 case 0x7a: /* FABD */
6583 handle_3same_float(s
, size
, elements
, fpopcode
, rd
, rn
, rm
);
6586 unallocated_encoding(s
);
6591 /* Integer op subgroup of C3.6.16. */
6592 static void disas_simd_3same_int(DisasContext
*s
, uint32_t insn
)
6594 int is_q
= extract32(insn
, 30, 1);
6595 int u
= extract32(insn
, 29, 1);
6596 int size
= extract32(insn
, 22, 2);
6597 int opcode
= extract32(insn
, 11, 5);
6598 int rm
= extract32(insn
, 16, 5);
6599 int rn
= extract32(insn
, 5, 5);
6600 int rd
= extract32(insn
, 0, 5);
6604 case 0x13: /* MUL, PMUL */
6605 if (u
&& size
!= 0) {
6606 unallocated_encoding(s
);
6610 case 0x0: /* SHADD, UHADD */
6611 case 0x2: /* SRHADD, URHADD */
6612 case 0x4: /* SHSUB, UHSUB */
6613 case 0xc: /* SMAX, UMAX */
6614 case 0xd: /* SMIN, UMIN */
6615 case 0xe: /* SABD, UABD */
6616 case 0xf: /* SABA, UABA */
6617 case 0x12: /* MLA, MLS */
6619 unallocated_encoding(s
);
6622 unsupported_encoding(s
, insn
);
6624 case 0x1: /* SQADD */
6625 case 0x5: /* SQSUB */
6626 case 0x8: /* SSHL, USHL */
6627 case 0x9: /* SQSHL, UQSHL */
6628 case 0xa: /* SRSHL, URSHL */
6629 case 0xb: /* SQRSHL, UQRSHL */
6630 if (size
== 3 && !is_q
) {
6631 unallocated_encoding(s
);
6634 unsupported_encoding(s
, insn
);
6636 case 0x16: /* SQDMULH, SQRDMULH */
6637 if (size
== 0 || size
== 3) {
6638 unallocated_encoding(s
);
6641 unsupported_encoding(s
, insn
);
6644 if (size
== 3 && !is_q
) {
6645 unallocated_encoding(s
);
6652 for (pass
= 0; pass
< (is_q
? 2 : 1); pass
++) {
6653 TCGv_i64 tcg_op1
= tcg_temp_new_i64();
6654 TCGv_i64 tcg_op2
= tcg_temp_new_i64();
6655 TCGv_i64 tcg_res
= tcg_temp_new_i64();
6657 read_vec_element(s
, tcg_op1
, rn
, pass
, MO_64
);
6658 read_vec_element(s
, tcg_op2
, rm
, pass
, MO_64
);
6660 handle_3same_64(s
, opcode
, u
, tcg_res
, tcg_op1
, tcg_op2
);
6662 write_vec_element(s
, tcg_res
, rd
, pass
, MO_64
);
6664 tcg_temp_free_i64(tcg_res
);
6665 tcg_temp_free_i64(tcg_op1
);
6666 tcg_temp_free_i64(tcg_op2
);
6669 for (pass
= 0; pass
< (is_q
? 4 : 2); pass
++) {
6670 TCGv_i32 tcg_op1
= tcg_temp_new_i32();
6671 TCGv_i32 tcg_op2
= tcg_temp_new_i32();
6672 TCGv_i32 tcg_res
= tcg_temp_new_i32();
6673 NeonGenTwoOpFn
*genfn
;
6675 read_vec_element_i32(s
, tcg_op1
, rn
, pass
, MO_32
);
6676 read_vec_element_i32(s
, tcg_op2
, rm
, pass
, MO_32
);
6679 case 0x6: /* CMGT, CMHI */
6681 static NeonGenTwoOpFn
* const fns
[3][2] = {
6682 { gen_helper_neon_cgt_s8
, gen_helper_neon_cgt_u8
},
6683 { gen_helper_neon_cgt_s16
, gen_helper_neon_cgt_u16
},
6684 { gen_helper_neon_cgt_s32
, gen_helper_neon_cgt_u32
},
6686 genfn
= fns
[size
][u
];
6689 case 0x7: /* CMGE, CMHS */
6691 static NeonGenTwoOpFn
* const fns
[3][2] = {
6692 { gen_helper_neon_cge_s8
, gen_helper_neon_cge_u8
},
6693 { gen_helper_neon_cge_s16
, gen_helper_neon_cge_u16
},
6694 { gen_helper_neon_cge_s32
, gen_helper_neon_cge_u32
},
6696 genfn
= fns
[size
][u
];
6699 case 0x10: /* ADD, SUB */
6701 static NeonGenTwoOpFn
* const fns
[3][2] = {
6702 { gen_helper_neon_add_u8
, gen_helper_neon_sub_u8
},
6703 { gen_helper_neon_add_u16
, gen_helper_neon_sub_u16
},
6704 { tcg_gen_add_i32
, tcg_gen_sub_i32
},
6706 genfn
= fns
[size
][u
];
6709 case 0x11: /* CMTST, CMEQ */
6711 static NeonGenTwoOpFn
* const fns
[3][2] = {
6712 { gen_helper_neon_tst_u8
, gen_helper_neon_ceq_u8
},
6713 { gen_helper_neon_tst_u16
, gen_helper_neon_ceq_u16
},
6714 { gen_helper_neon_tst_u32
, gen_helper_neon_ceq_u32
},
6716 genfn
= fns
[size
][u
];
6720 g_assert_not_reached();
6723 genfn(tcg_res
, tcg_op1
, tcg_op2
);
6725 write_vec_element_i32(s
, tcg_res
, rd
, pass
, MO_32
);
6727 tcg_temp_free_i32(tcg_res
);
6728 tcg_temp_free_i32(tcg_op1
);
6729 tcg_temp_free_i32(tcg_op2
);
6734 clear_vec_high(s
, rd
);
6738 /* C3.6.16 AdvSIMD three same
6739 * 31 30 29 28 24 23 22 21 20 16 15 11 10 9 5 4 0
6740 * +---+---+---+-----------+------+---+------+--------+---+------+------+
6741 * | 0 | Q | U | 0 1 1 1 0 | size | 1 | Rm | opcode | 1 | Rn | Rd |
6742 * +---+---+---+-----------+------+---+------+--------+---+------+------+
6744 static void disas_simd_three_reg_same(DisasContext
*s
, uint32_t insn
)
6746 int opcode
= extract32(insn
, 11, 5);
6749 case 0x3: /* logic ops */
6750 disas_simd_3same_logic(s
, insn
);
6752 case 0x17: /* ADDP */
6753 case 0x14: /* SMAXP, UMAXP */
6754 case 0x15: /* SMINP, UMINP */
6755 /* Pairwise operations */
6756 disas_simd_3same_pair(s
, insn
);
6759 /* floating point ops, sz[1] and U are part of opcode */
6760 disas_simd_3same_float(s
, insn
);
6763 disas_simd_3same_int(s
, insn
);
6768 /* C3.6.17 AdvSIMD two reg misc
6769 * 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
6770 * +---+---+---+-----------+------+-----------+--------+-----+------+------+
6771 * | 0 | Q | U | 0 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 | Rn | Rd |
6772 * +---+---+---+-----------+------+-----------+--------+-----+------+------+
6774 static void disas_simd_two_reg_misc(DisasContext
*s
, uint32_t insn
)
6776 unsupported_encoding(s
, insn
);
6779 /* C3.6.18 AdvSIMD vector x indexed element
6780 * 31 30 29 28 24 23 22 21 20 19 16 15 12 11 10 9 5 4 0
6781 * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
6782 * | 0 | Q | U | 0 1 1 1 1 | size | L | M | Rm | opc | H | 0 | Rn | Rd |
6783 * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
6785 static void disas_simd_indexed_vector(DisasContext
*s
, uint32_t insn
)
6787 unsupported_encoding(s
, insn
);
6790 /* C3.6.19 Crypto AES
6791 * 31 24 23 22 21 17 16 12 11 10 9 5 4 0
6792 * +-----------------+------+-----------+--------+-----+------+------+
6793 * | 0 1 0 0 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 | Rn | Rd |
6794 * +-----------------+------+-----------+--------+-----+------+------+
6796 static void disas_crypto_aes(DisasContext
*s
, uint32_t insn
)
6798 unsupported_encoding(s
, insn
);
6801 /* C3.6.20 Crypto three-reg SHA
6802 * 31 24 23 22 21 20 16 15 14 12 11 10 9 5 4 0
6803 * +-----------------+------+---+------+---+--------+-----+------+------+
6804 * | 0 1 0 1 1 1 1 0 | size | 0 | Rm | 0 | opcode | 0 0 | Rn | Rd |
6805 * +-----------------+------+---+------+---+--------+-----+------+------+
6807 static void disas_crypto_three_reg_sha(DisasContext
*s
, uint32_t insn
)
6809 unsupported_encoding(s
, insn
);
6812 /* C3.6.21 Crypto two-reg SHA
6813 * 31 24 23 22 21 17 16 12 11 10 9 5 4 0
6814 * +-----------------+------+-----------+--------+-----+------+------+
6815 * | 0 1 0 1 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 | Rn | Rd |
6816 * +-----------------+------+-----------+--------+-----+------+------+
6818 static void disas_crypto_two_reg_sha(DisasContext
*s
, uint32_t insn
)
6820 unsupported_encoding(s
, insn
);
6823 /* C3.6 Data processing - SIMD, inc Crypto
6825 * As the decode gets a little complex we are using a table based
6826 * approach for this part of the decode.
6828 static const AArch64DecodeTable data_proc_simd
[] = {
6829 /* pattern , mask , fn */
6830 { 0x0e200400, 0x9f200400, disas_simd_three_reg_same
},
6831 { 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff
},
6832 { 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc
},
6833 { 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes
},
6834 { 0x0e000400, 0x9fe08400, disas_simd_copy
},
6835 { 0x0f000000, 0x9f000400, disas_simd_indexed_vector
},
6836 /* simd_mod_imm decode is a subset of simd_shift_imm, so must precede it */
6837 { 0x0f000400, 0x9ff80400, disas_simd_mod_imm
},
6838 { 0x0f000400, 0x9f800400, disas_simd_shift_imm
},
6839 { 0x0e000000, 0xbf208c00, disas_simd_tb
},
6840 { 0x0e000800, 0xbf208c00, disas_simd_zip_trn
},
6841 { 0x2e000000, 0xbf208400, disas_simd_ext
},
6842 { 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same
},
6843 { 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff
},
6844 { 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc
},
6845 { 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise
},
6846 { 0x5e000400, 0xdfe08400, disas_simd_scalar_copy
},
6847 { 0x5f000000, 0xdf000400, disas_simd_scalar_indexed
},
6848 { 0x5f000400, 0xdf800400, disas_simd_scalar_shift_imm
},
6849 { 0x4e280800, 0xff3e0c00, disas_crypto_aes
},
6850 { 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha
},
6851 { 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha
},
6852 { 0x00000000, 0x00000000, NULL
}
6855 static void disas_data_proc_simd(DisasContext
*s
, uint32_t insn
)
6857 /* Note that this is called with all non-FP cases from
6858 * table C3-6 so it must UNDEF for entries not specifically
6859 * allocated to instructions in that table.
6861 AArch64DecodeFn
*fn
= lookup_disas_fn(&data_proc_simd
[0], insn
);
6865 unallocated_encoding(s
);
6869 /* C3.6 Data processing - SIMD and floating point */
6870 static void disas_data_proc_simd_fp(DisasContext
*s
, uint32_t insn
)
6872 if (extract32(insn
, 28, 1) == 1 && extract32(insn
, 30, 1) == 0) {
6873 disas_data_proc_fp(s
, insn
);
6875 /* SIMD, including crypto */
6876 disas_data_proc_simd(s
, insn
);
6880 /* C3.1 A64 instruction index by encoding */
6881 static void disas_a64_insn(CPUARMState
*env
, DisasContext
*s
)
6885 insn
= arm_ldl_code(env
, s
->pc
, s
->bswap_code
);
6889 switch (extract32(insn
, 25, 4)) {
6890 case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
6891 unallocated_encoding(s
);
6893 case 0x8: case 0x9: /* Data processing - immediate */
6894 disas_data_proc_imm(s
, insn
);
6896 case 0xa: case 0xb: /* Branch, exception generation and system insns */
6897 disas_b_exc_sys(s
, insn
);
6902 case 0xe: /* Loads and stores */
6903 disas_ldst(s
, insn
);
6906 case 0xd: /* Data processing - register */
6907 disas_data_proc_reg(s
, insn
);
6910 case 0xf: /* Data processing - SIMD and floating point */
6911 disas_data_proc_simd_fp(s
, insn
);
6914 assert(FALSE
); /* all 15 cases should be handled above */
6918 /* if we allocated any temporaries, free them here */
6922 void gen_intermediate_code_internal_a64(ARMCPU
*cpu
,
6923 TranslationBlock
*tb
,
6926 CPUState
*cs
= CPU(cpu
);
6927 CPUARMState
*env
= &cpu
->env
;
6928 DisasContext dc1
, *dc
= &dc1
;
6930 uint16_t *gen_opc_end
;
6932 target_ulong pc_start
;
6933 target_ulong next_page_start
;
6941 gen_opc_end
= tcg_ctx
.gen_opc_buf
+ OPC_MAX_SIZE
;
6943 dc
->is_jmp
= DISAS_NEXT
;
6945 dc
->singlestep_enabled
= cs
->singlestep_enabled
;
6951 dc
->condexec_mask
= 0;
6952 dc
->condexec_cond
= 0;
6953 #if !defined(CONFIG_USER_ONLY)
6956 dc
->vfp_enabled
= 0;
6959 dc
->cp_regs
= cpu
->cp_regs
;
6960 dc
->current_pl
= arm_current_pl(env
);
6962 init_tmp_a64_array(dc
);
6964 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
6967 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
6968 if (max_insns
== 0) {
6969 max_insns
= CF_COUNT_MASK
;
6974 tcg_clear_temp_count();
6977 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
6978 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
6979 if (bp
->pc
== dc
->pc
) {
6980 gen_exception_insn(dc
, 0, EXCP_DEBUG
);
6981 /* Advance PC so that clearing the breakpoint will
6982 invalidate this TB. */
6984 goto done_generating
;
6990 j
= tcg_ctx
.gen_opc_ptr
- tcg_ctx
.gen_opc_buf
;
6994 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
6997 tcg_ctx
.gen_opc_pc
[lj
] = dc
->pc
;
6998 tcg_ctx
.gen_opc_instr_start
[lj
] = 1;
6999 tcg_ctx
.gen_opc_icount
[lj
] = num_insns
;
7002 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
)) {
7006 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
| CPU_LOG_TB_OP_OPT
))) {
7007 tcg_gen_debug_insn_start(dc
->pc
);
7010 disas_a64_insn(env
, dc
);
7012 if (tcg_check_temp_count()) {
7013 fprintf(stderr
, "TCG temporary leak before "TARGET_FMT_lx
"\n",
7017 /* Translation stops when a conditional branch is encountered.
7018 * Otherwise the subsequent code could get translated several times.
7019 * Also stop translation when a page boundary is reached. This
7020 * ensures prefetch aborts occur at the right place.
7023 } while (!dc
->is_jmp
&& tcg_ctx
.gen_opc_ptr
< gen_opc_end
&&
7024 !cs
->singlestep_enabled
&&
7026 dc
->pc
< next_page_start
&&
7027 num_insns
< max_insns
);
7029 if (tb
->cflags
& CF_LAST_IO
) {
7033 if (unlikely(cs
->singlestep_enabled
) && dc
->is_jmp
!= DISAS_EXC
) {
7034 /* Note that this means single stepping WFI doesn't halt the CPU.
7035 * For conditional branch insns this is harmless unreachable code as
7036 * gen_goto_tb() has already handled emitting the debug exception
7037 * (and thus a tb-jump is not possible when singlestepping).
7039 assert(dc
->is_jmp
!= DISAS_TB_JUMP
);
7040 if (dc
->is_jmp
!= DISAS_JUMP
) {
7041 gen_a64_set_pc_im(dc
->pc
);
7043 gen_exception(EXCP_DEBUG
);
7045 switch (dc
->is_jmp
) {
7047 gen_goto_tb(dc
, 1, dc
->pc
);
7051 gen_a64_set_pc_im(dc
->pc
);
7054 /* indicate that the hash table must be used to find the next TB */
7062 /* This is a special case because we don't want to just halt the CPU
7063 * if trying to debug across a WFI.
7065 gen_helper_wfi(cpu_env
);
7071 gen_tb_end(tb
, num_insns
);
7072 *tcg_ctx
.gen_opc_ptr
= INDEX_op_end
;
7075 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
7076 qemu_log("----------------\n");
7077 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
7078 log_target_disas(env
, pc_start
, dc
->pc
- pc_start
,
7079 dc
->thumb
| (dc
->bswap_code
<< 1));
7084 j
= tcg_ctx
.gen_opc_ptr
- tcg_ctx
.gen_opc_buf
;
7087 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
7090 tb
->size
= dc
->pc
- pc_start
;
7091 tb
->icount
= num_insns
;