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/>.
19 #include "qemu/osdep.h"
22 #include "exec/exec-all.h"
26 #include "translate.h"
27 #include "internals.h"
28 #include "qemu/host-utils.h"
30 #include "exec/semihost.h"
31 #include "exec/gen-icount.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
37 #include "trace-tcg.h"
39 static TCGv_i64 cpu_X
[32];
40 static TCGv_i64 cpu_pc
;
42 /* Load/store exclusive handling */
43 static TCGv_i64 cpu_exclusive_high
;
45 static const char *regnames
[] = {
46 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
47 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
48 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
49 "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
53 A64_SHIFT_TYPE_LSL
= 0,
54 A64_SHIFT_TYPE_LSR
= 1,
55 A64_SHIFT_TYPE_ASR
= 2,
56 A64_SHIFT_TYPE_ROR
= 3
59 /* Table based decoder typedefs - used when the relevant bits for decode
60 * are too awkwardly scattered across the instruction (eg SIMD).
62 typedef void AArch64DecodeFn(DisasContext
*s
, uint32_t insn
);
64 typedef struct AArch64DecodeTable
{
67 AArch64DecodeFn
*disas_fn
;
70 /* Function prototype for gen_ functions for calling Neon helpers */
71 typedef void NeonGenOneOpEnvFn(TCGv_i32
, TCGv_ptr
, TCGv_i32
);
72 typedef void NeonGenTwoOpFn(TCGv_i32
, TCGv_i32
, TCGv_i32
);
73 typedef void NeonGenTwoOpEnvFn(TCGv_i32
, TCGv_ptr
, TCGv_i32
, TCGv_i32
);
74 typedef void NeonGenTwo64OpFn(TCGv_i64
, TCGv_i64
, TCGv_i64
);
75 typedef void NeonGenTwo64OpEnvFn(TCGv_i64
, TCGv_ptr
, TCGv_i64
, TCGv_i64
);
76 typedef void NeonGenNarrowFn(TCGv_i32
, TCGv_i64
);
77 typedef void NeonGenNarrowEnvFn(TCGv_i32
, TCGv_ptr
, TCGv_i64
);
78 typedef void NeonGenWidenFn(TCGv_i64
, TCGv_i32
);
79 typedef void NeonGenTwoSingleOPFn(TCGv_i32
, TCGv_i32
, TCGv_i32
, TCGv_ptr
);
80 typedef void NeonGenTwoDoubleOPFn(TCGv_i64
, TCGv_i64
, TCGv_i64
, TCGv_ptr
);
81 typedef void NeonGenOneOpFn(TCGv_i64
, TCGv_i64
);
82 typedef void CryptoTwoOpEnvFn(TCGv_ptr
, TCGv_i32
, TCGv_i32
);
83 typedef void CryptoThreeOpEnvFn(TCGv_ptr
, TCGv_i32
, TCGv_i32
, TCGv_i32
);
85 /* initialize TCG globals. */
86 void a64_translate_init(void)
90 cpu_pc
= tcg_global_mem_new_i64(cpu_env
,
91 offsetof(CPUARMState
, pc
),
93 for (i
= 0; i
< 32; i
++) {
94 cpu_X
[i
] = tcg_global_mem_new_i64(cpu_env
,
95 offsetof(CPUARMState
, xregs
[i
]),
99 cpu_exclusive_high
= tcg_global_mem_new_i64(cpu_env
,
100 offsetof(CPUARMState
, exclusive_high
), "exclusive_high");
103 static inline ARMMMUIdx
get_a64_user_mem_index(DisasContext
*s
)
105 /* Return the mmu_idx to use for A64 "unprivileged load/store" insns:
106 * if EL1, access as if EL0; otherwise access at current EL
108 switch (s
->mmu_idx
) {
109 case ARMMMUIdx_S12NSE1
:
110 return ARMMMUIdx_S12NSE0
;
111 case ARMMMUIdx_S1SE1
:
112 return ARMMMUIdx_S1SE0
;
114 g_assert_not_reached();
120 void aarch64_cpu_dump_state(CPUState
*cs
, FILE *f
,
121 fprintf_function cpu_fprintf
, int flags
)
123 ARMCPU
*cpu
= ARM_CPU(cs
);
124 CPUARMState
*env
= &cpu
->env
;
125 uint32_t psr
= pstate_read(env
);
127 int el
= arm_current_el(env
);
128 const char *ns_status
;
130 cpu_fprintf(f
, "PC=%016"PRIx64
" SP=%016"PRIx64
"\n",
131 env
->pc
, env
->xregs
[31]);
132 for (i
= 0; i
< 31; i
++) {
133 cpu_fprintf(f
, "X%02d=%016"PRIx64
, i
, env
->xregs
[i
]);
135 cpu_fprintf(f
, "\n");
141 if (arm_feature(env
, ARM_FEATURE_EL3
) && el
!= 3) {
142 ns_status
= env
->cp15
.scr_el3
& SCR_NS ?
"NS " : "S ";
147 cpu_fprintf(f
, "\nPSTATE=%08x %c%c%c%c %sEL%d%c\n",
149 psr
& PSTATE_N ?
'N' : '-',
150 psr
& PSTATE_Z ?
'Z' : '-',
151 psr
& PSTATE_C ?
'C' : '-',
152 psr
& PSTATE_V ?
'V' : '-',
155 psr
& PSTATE_SP ?
'h' : 't');
157 if (flags
& CPU_DUMP_FPU
) {
159 for (i
= 0; i
< numvfpregs
; i
+= 2) {
160 uint64_t vlo
= float64_val(env
->vfp
.regs
[i
* 2]);
161 uint64_t vhi
= float64_val(env
->vfp
.regs
[(i
* 2) + 1]);
162 cpu_fprintf(f
, "q%02d=%016" PRIx64
":%016" PRIx64
" ",
164 vlo
= float64_val(env
->vfp
.regs
[(i
+ 1) * 2]);
165 vhi
= float64_val(env
->vfp
.regs
[((i
+ 1) * 2) + 1]);
166 cpu_fprintf(f
, "q%02d=%016" PRIx64
":%016" PRIx64
"\n",
169 cpu_fprintf(f
, "FPCR: %08x FPSR: %08x\n",
170 vfp_get_fpcr(env
), vfp_get_fpsr(env
));
174 void gen_a64_set_pc_im(uint64_t val
)
176 tcg_gen_movi_i64(cpu_pc
, val
);
179 typedef struct DisasCompare64
{
184 static void a64_test_cc(DisasCompare64
*c64
, int cc
)
188 arm_test_cc(&c32
, cc
);
190 /* Sign-extend the 32-bit value so that the GE/LT comparisons work
191 * properly. The NE/EQ comparisons are also fine with this choice. */
192 c64
->cond
= c32
.cond
;
193 c64
->value
= tcg_temp_new_i64();
194 tcg_gen_ext_i32_i64(c64
->value
, c32
.value
);
199 static void a64_free_cc(DisasCompare64
*c64
)
201 tcg_temp_free_i64(c64
->value
);
204 static void gen_exception_internal(int excp
)
206 TCGv_i32 tcg_excp
= tcg_const_i32(excp
);
208 assert(excp_is_internal(excp
));
209 gen_helper_exception_internal(cpu_env
, tcg_excp
);
210 tcg_temp_free_i32(tcg_excp
);
213 static void gen_exception(int excp
, uint32_t syndrome
, uint32_t target_el
)
215 TCGv_i32 tcg_excp
= tcg_const_i32(excp
);
216 TCGv_i32 tcg_syn
= tcg_const_i32(syndrome
);
217 TCGv_i32 tcg_el
= tcg_const_i32(target_el
);
219 gen_helper_exception_with_syndrome(cpu_env
, tcg_excp
,
221 tcg_temp_free_i32(tcg_el
);
222 tcg_temp_free_i32(tcg_syn
);
223 tcg_temp_free_i32(tcg_excp
);
226 static void gen_exception_internal_insn(DisasContext
*s
, int offset
, int excp
)
228 gen_a64_set_pc_im(s
->pc
- offset
);
229 gen_exception_internal(excp
);
230 s
->is_jmp
= DISAS_EXC
;
233 static void gen_exception_insn(DisasContext
*s
, int offset
, int excp
,
234 uint32_t syndrome
, uint32_t target_el
)
236 gen_a64_set_pc_im(s
->pc
- offset
);
237 gen_exception(excp
, syndrome
, target_el
);
238 s
->is_jmp
= DISAS_EXC
;
241 static void gen_ss_advance(DisasContext
*s
)
243 /* If the singlestep state is Active-not-pending, advance to
248 gen_helper_clear_pstate_ss(cpu_env
);
252 static void gen_step_complete_exception(DisasContext
*s
)
254 /* We just completed step of an insn. Move from Active-not-pending
255 * to Active-pending, and then also take the swstep exception.
256 * This corresponds to making the (IMPDEF) choice to prioritize
257 * swstep exceptions over asynchronous exceptions taken to an exception
258 * level where debug is disabled. This choice has the advantage that
259 * we do not need to maintain internal state corresponding to the
260 * ISV/EX syndrome bits between completion of the step and generation
261 * of the exception, and our syndrome information is always correct.
264 gen_exception(EXCP_UDEF
, syn_swstep(s
->ss_same_el
, 1, s
->is_ldex
),
265 default_exception_el(s
));
266 s
->is_jmp
= DISAS_EXC
;
269 static inline bool use_goto_tb(DisasContext
*s
, int n
, uint64_t dest
)
271 /* No direct tb linking with singlestep (either QEMU's or the ARM
272 * debug architecture kind) or deterministic io
274 if (s
->singlestep_enabled
|| s
->ss_active
|| (s
->tb
->cflags
& CF_LAST_IO
)) {
278 #ifndef CONFIG_USER_ONLY
279 /* Only link tbs from inside the same guest page */
280 if ((s
->tb
->pc
& TARGET_PAGE_MASK
) != (dest
& TARGET_PAGE_MASK
)) {
288 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint64_t dest
)
290 TranslationBlock
*tb
;
293 if (use_goto_tb(s
, n
, dest
)) {
295 gen_a64_set_pc_im(dest
);
296 tcg_gen_exit_tb((intptr_t)tb
+ n
);
297 s
->is_jmp
= DISAS_TB_JUMP
;
299 gen_a64_set_pc_im(dest
);
301 gen_step_complete_exception(s
);
302 } else if (s
->singlestep_enabled
) {
303 gen_exception_internal(EXCP_DEBUG
);
306 s
->is_jmp
= DISAS_TB_JUMP
;
311 static void unallocated_encoding(DisasContext
*s
)
313 /* Unallocated and reserved encodings are uncategorized */
314 gen_exception_insn(s
, 4, EXCP_UDEF
, syn_uncategorized(),
315 default_exception_el(s
));
318 #define unsupported_encoding(s, insn) \
320 qemu_log_mask(LOG_UNIMP, \
321 "%s:%d: unsupported instruction encoding 0x%08x " \
322 "at pc=%016" PRIx64 "\n", \
323 __FILE__, __LINE__, insn, s->pc - 4); \
324 unallocated_encoding(s); \
327 static void init_tmp_a64_array(DisasContext
*s
)
329 #ifdef CONFIG_DEBUG_TCG
331 for (i
= 0; i
< ARRAY_SIZE(s
->tmp_a64
); i
++) {
332 TCGV_UNUSED_I64(s
->tmp_a64
[i
]);
335 s
->tmp_a64_count
= 0;
338 static void free_tmp_a64(DisasContext
*s
)
341 for (i
= 0; i
< s
->tmp_a64_count
; i
++) {
342 tcg_temp_free_i64(s
->tmp_a64
[i
]);
344 init_tmp_a64_array(s
);
347 static TCGv_i64
new_tmp_a64(DisasContext
*s
)
349 assert(s
->tmp_a64_count
< TMP_A64_MAX
);
350 return s
->tmp_a64
[s
->tmp_a64_count
++] = tcg_temp_new_i64();
353 static TCGv_i64
new_tmp_a64_zero(DisasContext
*s
)
355 TCGv_i64 t
= new_tmp_a64(s
);
356 tcg_gen_movi_i64(t
, 0);
361 * Register access functions
363 * These functions are used for directly accessing a register in where
364 * changes to the final register value are likely to be made. If you
365 * need to use a register for temporary calculation (e.g. index type
366 * operations) use the read_* form.
368 * B1.2.1 Register mappings
370 * In instruction register encoding 31 can refer to ZR (zero register) or
371 * the SP (stack pointer) depending on context. In QEMU's case we map SP
372 * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
373 * This is the point of the _sp forms.
375 static TCGv_i64
cpu_reg(DisasContext
*s
, int reg
)
378 return new_tmp_a64_zero(s
);
384 /* register access for when 31 == SP */
385 static TCGv_i64
cpu_reg_sp(DisasContext
*s
, int reg
)
390 /* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
391 * representing the register contents. This TCGv is an auto-freed
392 * temporary so it need not be explicitly freed, and may be modified.
394 static TCGv_i64
read_cpu_reg(DisasContext
*s
, int reg
, int sf
)
396 TCGv_i64 v
= new_tmp_a64(s
);
399 tcg_gen_mov_i64(v
, cpu_X
[reg
]);
401 tcg_gen_ext32u_i64(v
, cpu_X
[reg
]);
404 tcg_gen_movi_i64(v
, 0);
409 static TCGv_i64
read_cpu_reg_sp(DisasContext
*s
, int reg
, int sf
)
411 TCGv_i64 v
= new_tmp_a64(s
);
413 tcg_gen_mov_i64(v
, cpu_X
[reg
]);
415 tcg_gen_ext32u_i64(v
, cpu_X
[reg
]);
420 /* We should have at some point before trying to access an FP register
421 * done the necessary access check, so assert that
422 * (a) we did the check and
423 * (b) we didn't then just plough ahead anyway if it failed.
424 * Print the instruction pattern in the abort message so we can figure
425 * out what we need to fix if a user encounters this problem in the wild.
427 static inline void assert_fp_access_checked(DisasContext
*s
)
429 #ifdef CONFIG_DEBUG_TCG
430 if (unlikely(!s
->fp_access_checked
|| s
->fp_excp_el
)) {
431 fprintf(stderr
, "target-arm: FP access check missing for "
432 "instruction 0x%08x\n", s
->insn
);
438 /* Return the offset into CPUARMState of an element of specified
439 * size, 'element' places in from the least significant end of
440 * the FP/vector register Qn.
442 static inline int vec_reg_offset(DisasContext
*s
, int regno
,
443 int element
, TCGMemOp size
)
445 int offs
= offsetof(CPUARMState
, vfp
.regs
[regno
* 2]);
446 #ifdef HOST_WORDS_BIGENDIAN
447 /* This is complicated slightly because vfp.regs[2n] is
448 * still the low half and vfp.regs[2n+1] the high half
449 * of the 128 bit vector, even on big endian systems.
450 * Calculate the offset assuming a fully bigendian 128 bits,
451 * then XOR to account for the order of the two 64 bit halves.
453 offs
+= (16 - ((element
+ 1) * (1 << size
)));
456 offs
+= element
* (1 << size
);
458 assert_fp_access_checked(s
);
462 /* Return the offset into CPUARMState of a slice (from
463 * the least significant end) of FP register Qn (ie
465 * (Note that this is not the same mapping as for A32; see cpu.h)
467 static inline int fp_reg_offset(DisasContext
*s
, int regno
, TCGMemOp size
)
469 int offs
= offsetof(CPUARMState
, vfp
.regs
[regno
* 2]);
470 #ifdef HOST_WORDS_BIGENDIAN
471 offs
+= (8 - (1 << size
));
473 assert_fp_access_checked(s
);
477 /* Offset of the high half of the 128 bit vector Qn */
478 static inline int fp_reg_hi_offset(DisasContext
*s
, int regno
)
480 assert_fp_access_checked(s
);
481 return offsetof(CPUARMState
, vfp
.regs
[regno
* 2 + 1]);
484 /* Convenience accessors for reading and writing single and double
485 * FP registers. Writing clears the upper parts of the associated
486 * 128 bit vector register, as required by the architecture.
487 * Note that unlike the GP register accessors, the values returned
488 * by the read functions must be manually freed.
490 static TCGv_i64
read_fp_dreg(DisasContext
*s
, int reg
)
492 TCGv_i64 v
= tcg_temp_new_i64();
494 tcg_gen_ld_i64(v
, cpu_env
, fp_reg_offset(s
, reg
, MO_64
));
498 static TCGv_i32
read_fp_sreg(DisasContext
*s
, int reg
)
500 TCGv_i32 v
= tcg_temp_new_i32();
502 tcg_gen_ld_i32(v
, cpu_env
, fp_reg_offset(s
, reg
, MO_32
));
506 static void write_fp_dreg(DisasContext
*s
, int reg
, TCGv_i64 v
)
508 TCGv_i64 tcg_zero
= tcg_const_i64(0);
510 tcg_gen_st_i64(v
, cpu_env
, fp_reg_offset(s
, reg
, MO_64
));
511 tcg_gen_st_i64(tcg_zero
, cpu_env
, fp_reg_hi_offset(s
, reg
));
512 tcg_temp_free_i64(tcg_zero
);
515 static void write_fp_sreg(DisasContext
*s
, int reg
, TCGv_i32 v
)
517 TCGv_i64 tmp
= tcg_temp_new_i64();
519 tcg_gen_extu_i32_i64(tmp
, v
);
520 write_fp_dreg(s
, reg
, tmp
);
521 tcg_temp_free_i64(tmp
);
524 static TCGv_ptr
get_fpstatus_ptr(void)
526 TCGv_ptr statusptr
= tcg_temp_new_ptr();
529 /* In A64 all instructions (both FP and Neon) use the FPCR;
530 * there is no equivalent of the A32 Neon "standard FPSCR value"
531 * and all operations use vfp.fp_status.
533 offset
= offsetof(CPUARMState
, vfp
.fp_status
);
534 tcg_gen_addi_ptr(statusptr
, cpu_env
, offset
);
538 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
539 * than the 32 bit equivalent.
541 static inline void gen_set_NZ64(TCGv_i64 result
)
543 tcg_gen_extr_i64_i32(cpu_ZF
, cpu_NF
, result
);
544 tcg_gen_or_i32(cpu_ZF
, cpu_ZF
, cpu_NF
);
547 /* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
548 static inline void gen_logic_CC(int sf
, TCGv_i64 result
)
551 gen_set_NZ64(result
);
553 tcg_gen_extrl_i64_i32(cpu_ZF
, result
);
554 tcg_gen_mov_i32(cpu_NF
, cpu_ZF
);
556 tcg_gen_movi_i32(cpu_CF
, 0);
557 tcg_gen_movi_i32(cpu_VF
, 0);
560 /* dest = T0 + T1; compute C, N, V and Z flags */
561 static void gen_add_CC(int sf
, TCGv_i64 dest
, TCGv_i64 t0
, TCGv_i64 t1
)
564 TCGv_i64 result
, flag
, tmp
;
565 result
= tcg_temp_new_i64();
566 flag
= tcg_temp_new_i64();
567 tmp
= tcg_temp_new_i64();
569 tcg_gen_movi_i64(tmp
, 0);
570 tcg_gen_add2_i64(result
, flag
, t0
, tmp
, t1
, tmp
);
572 tcg_gen_extrl_i64_i32(cpu_CF
, flag
);
574 gen_set_NZ64(result
);
576 tcg_gen_xor_i64(flag
, result
, t0
);
577 tcg_gen_xor_i64(tmp
, t0
, t1
);
578 tcg_gen_andc_i64(flag
, flag
, tmp
);
579 tcg_temp_free_i64(tmp
);
580 tcg_gen_extrh_i64_i32(cpu_VF
, flag
);
582 tcg_gen_mov_i64(dest
, result
);
583 tcg_temp_free_i64(result
);
584 tcg_temp_free_i64(flag
);
586 /* 32 bit arithmetic */
587 TCGv_i32 t0_32
= tcg_temp_new_i32();
588 TCGv_i32 t1_32
= tcg_temp_new_i32();
589 TCGv_i32 tmp
= tcg_temp_new_i32();
591 tcg_gen_movi_i32(tmp
, 0);
592 tcg_gen_extrl_i64_i32(t0_32
, t0
);
593 tcg_gen_extrl_i64_i32(t1_32
, t1
);
594 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, t0_32
, tmp
, t1_32
, tmp
);
595 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
596 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0_32
);
597 tcg_gen_xor_i32(tmp
, t0_32
, t1_32
);
598 tcg_gen_andc_i32(cpu_VF
, cpu_VF
, tmp
);
599 tcg_gen_extu_i32_i64(dest
, cpu_NF
);
601 tcg_temp_free_i32(tmp
);
602 tcg_temp_free_i32(t0_32
);
603 tcg_temp_free_i32(t1_32
);
607 /* dest = T0 - T1; compute C, N, V and Z flags */
608 static void gen_sub_CC(int sf
, TCGv_i64 dest
, TCGv_i64 t0
, TCGv_i64 t1
)
611 /* 64 bit arithmetic */
612 TCGv_i64 result
, flag
, tmp
;
614 result
= tcg_temp_new_i64();
615 flag
= tcg_temp_new_i64();
616 tcg_gen_sub_i64(result
, t0
, t1
);
618 gen_set_NZ64(result
);
620 tcg_gen_setcond_i64(TCG_COND_GEU
, flag
, t0
, t1
);
621 tcg_gen_extrl_i64_i32(cpu_CF
, flag
);
623 tcg_gen_xor_i64(flag
, result
, t0
);
624 tmp
= tcg_temp_new_i64();
625 tcg_gen_xor_i64(tmp
, t0
, t1
);
626 tcg_gen_and_i64(flag
, flag
, tmp
);
627 tcg_temp_free_i64(tmp
);
628 tcg_gen_extrh_i64_i32(cpu_VF
, flag
);
629 tcg_gen_mov_i64(dest
, result
);
630 tcg_temp_free_i64(flag
);
631 tcg_temp_free_i64(result
);
633 /* 32 bit arithmetic */
634 TCGv_i32 t0_32
= tcg_temp_new_i32();
635 TCGv_i32 t1_32
= tcg_temp_new_i32();
638 tcg_gen_extrl_i64_i32(t0_32
, t0
);
639 tcg_gen_extrl_i64_i32(t1_32
, t1
);
640 tcg_gen_sub_i32(cpu_NF
, t0_32
, t1_32
);
641 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
642 tcg_gen_setcond_i32(TCG_COND_GEU
, cpu_CF
, t0_32
, t1_32
);
643 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0_32
);
644 tmp
= tcg_temp_new_i32();
645 tcg_gen_xor_i32(tmp
, t0_32
, t1_32
);
646 tcg_temp_free_i32(t0_32
);
647 tcg_temp_free_i32(t1_32
);
648 tcg_gen_and_i32(cpu_VF
, cpu_VF
, tmp
);
649 tcg_temp_free_i32(tmp
);
650 tcg_gen_extu_i32_i64(dest
, cpu_NF
);
654 /* dest = T0 + T1 + CF; do not compute flags. */
655 static void gen_adc(int sf
, TCGv_i64 dest
, TCGv_i64 t0
, TCGv_i64 t1
)
657 TCGv_i64 flag
= tcg_temp_new_i64();
658 tcg_gen_extu_i32_i64(flag
, cpu_CF
);
659 tcg_gen_add_i64(dest
, t0
, t1
);
660 tcg_gen_add_i64(dest
, dest
, flag
);
661 tcg_temp_free_i64(flag
);
664 tcg_gen_ext32u_i64(dest
, dest
);
668 /* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
669 static void gen_adc_CC(int sf
, TCGv_i64 dest
, TCGv_i64 t0
, TCGv_i64 t1
)
672 TCGv_i64 result
, cf_64
, vf_64
, tmp
;
673 result
= tcg_temp_new_i64();
674 cf_64
= tcg_temp_new_i64();
675 vf_64
= tcg_temp_new_i64();
676 tmp
= tcg_const_i64(0);
678 tcg_gen_extu_i32_i64(cf_64
, cpu_CF
);
679 tcg_gen_add2_i64(result
, cf_64
, t0
, tmp
, cf_64
, tmp
);
680 tcg_gen_add2_i64(result
, cf_64
, result
, cf_64
, t1
, tmp
);
681 tcg_gen_extrl_i64_i32(cpu_CF
, cf_64
);
682 gen_set_NZ64(result
);
684 tcg_gen_xor_i64(vf_64
, result
, t0
);
685 tcg_gen_xor_i64(tmp
, t0
, t1
);
686 tcg_gen_andc_i64(vf_64
, vf_64
, tmp
);
687 tcg_gen_extrh_i64_i32(cpu_VF
, vf_64
);
689 tcg_gen_mov_i64(dest
, result
);
691 tcg_temp_free_i64(tmp
);
692 tcg_temp_free_i64(vf_64
);
693 tcg_temp_free_i64(cf_64
);
694 tcg_temp_free_i64(result
);
696 TCGv_i32 t0_32
, t1_32
, tmp
;
697 t0_32
= tcg_temp_new_i32();
698 t1_32
= tcg_temp_new_i32();
699 tmp
= tcg_const_i32(0);
701 tcg_gen_extrl_i64_i32(t0_32
, t0
);
702 tcg_gen_extrl_i64_i32(t1_32
, t1
);
703 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, t0_32
, tmp
, cpu_CF
, tmp
);
704 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, cpu_NF
, cpu_CF
, t1_32
, tmp
);
706 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
707 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0_32
);
708 tcg_gen_xor_i32(tmp
, t0_32
, t1_32
);
709 tcg_gen_andc_i32(cpu_VF
, cpu_VF
, tmp
);
710 tcg_gen_extu_i32_i64(dest
, cpu_NF
);
712 tcg_temp_free_i32(tmp
);
713 tcg_temp_free_i32(t1_32
);
714 tcg_temp_free_i32(t0_32
);
719 * Load/Store generators
723 * Store from GPR register to memory.
725 static void do_gpr_st_memidx(DisasContext
*s
, TCGv_i64 source
,
726 TCGv_i64 tcg_addr
, int size
, int memidx
)
729 tcg_gen_qemu_st_i64(source
, tcg_addr
, memidx
, s
->be_data
+ size
);
732 static void do_gpr_st(DisasContext
*s
, TCGv_i64 source
,
733 TCGv_i64 tcg_addr
, int size
)
735 do_gpr_st_memidx(s
, source
, tcg_addr
, size
, get_mem_index(s
));
739 * Load from memory to GPR register
741 static void do_gpr_ld_memidx(DisasContext
*s
, TCGv_i64 dest
, TCGv_i64 tcg_addr
,
742 int size
, bool is_signed
, bool extend
, int memidx
)
744 TCGMemOp memop
= s
->be_data
+ size
;
752 tcg_gen_qemu_ld_i64(dest
, tcg_addr
, memidx
, memop
);
754 if (extend
&& is_signed
) {
756 tcg_gen_ext32u_i64(dest
, dest
);
760 static void do_gpr_ld(DisasContext
*s
, TCGv_i64 dest
, TCGv_i64 tcg_addr
,
761 int size
, bool is_signed
, bool extend
)
763 do_gpr_ld_memidx(s
, dest
, tcg_addr
, size
, is_signed
, extend
,
768 * Store from FP register to memory
770 static void do_fp_st(DisasContext
*s
, int srcidx
, TCGv_i64 tcg_addr
, int size
)
772 /* This writes the bottom N bits of a 128 bit wide vector to memory */
773 TCGv_i64 tmp
= tcg_temp_new_i64();
774 tcg_gen_ld_i64(tmp
, cpu_env
, fp_reg_offset(s
, srcidx
, MO_64
));
776 tcg_gen_qemu_st_i64(tmp
, tcg_addr
, get_mem_index(s
),
779 bool be
= s
->be_data
== MO_BE
;
780 TCGv_i64 tcg_hiaddr
= tcg_temp_new_i64();
782 tcg_gen_addi_i64(tcg_hiaddr
, tcg_addr
, 8);
783 tcg_gen_qemu_st_i64(tmp
, be ? tcg_hiaddr
: tcg_addr
, get_mem_index(s
),
785 tcg_gen_ld_i64(tmp
, cpu_env
, fp_reg_hi_offset(s
, srcidx
));
786 tcg_gen_qemu_st_i64(tmp
, be ? tcg_addr
: tcg_hiaddr
, get_mem_index(s
),
788 tcg_temp_free_i64(tcg_hiaddr
);
791 tcg_temp_free_i64(tmp
);
795 * Load from memory to FP register
797 static void do_fp_ld(DisasContext
*s
, int destidx
, TCGv_i64 tcg_addr
, int size
)
799 /* This always zero-extends and writes to a full 128 bit wide vector */
800 TCGv_i64 tmplo
= tcg_temp_new_i64();
804 TCGMemOp memop
= s
->be_data
+ size
;
805 tmphi
= tcg_const_i64(0);
806 tcg_gen_qemu_ld_i64(tmplo
, tcg_addr
, get_mem_index(s
), memop
);
808 bool be
= s
->be_data
== MO_BE
;
811 tmphi
= tcg_temp_new_i64();
812 tcg_hiaddr
= tcg_temp_new_i64();
814 tcg_gen_addi_i64(tcg_hiaddr
, tcg_addr
, 8);
815 tcg_gen_qemu_ld_i64(tmplo
, be ? tcg_hiaddr
: tcg_addr
, get_mem_index(s
),
817 tcg_gen_qemu_ld_i64(tmphi
, be ? tcg_addr
: tcg_hiaddr
, get_mem_index(s
),
819 tcg_temp_free_i64(tcg_hiaddr
);
822 tcg_gen_st_i64(tmplo
, cpu_env
, fp_reg_offset(s
, destidx
, MO_64
));
823 tcg_gen_st_i64(tmphi
, cpu_env
, fp_reg_hi_offset(s
, destidx
));
825 tcg_temp_free_i64(tmplo
);
826 tcg_temp_free_i64(tmphi
);
830 * Vector load/store helpers.
832 * The principal difference between this and a FP load is that we don't
833 * zero extend as we are filling a partial chunk of the vector register.
834 * These functions don't support 128 bit loads/stores, which would be
835 * normal load/store operations.
837 * The _i32 versions are useful when operating on 32 bit quantities
838 * (eg for floating point single or using Neon helper functions).
841 /* Get value of an element within a vector register */
842 static void read_vec_element(DisasContext
*s
, TCGv_i64 tcg_dest
, int srcidx
,
843 int element
, TCGMemOp memop
)
845 int vect_off
= vec_reg_offset(s
, srcidx
, element
, memop
& MO_SIZE
);
848 tcg_gen_ld8u_i64(tcg_dest
, cpu_env
, vect_off
);
851 tcg_gen_ld16u_i64(tcg_dest
, cpu_env
, vect_off
);
854 tcg_gen_ld32u_i64(tcg_dest
, cpu_env
, vect_off
);
857 tcg_gen_ld8s_i64(tcg_dest
, cpu_env
, vect_off
);
860 tcg_gen_ld16s_i64(tcg_dest
, cpu_env
, vect_off
);
863 tcg_gen_ld32s_i64(tcg_dest
, cpu_env
, vect_off
);
867 tcg_gen_ld_i64(tcg_dest
, cpu_env
, vect_off
);
870 g_assert_not_reached();
874 static void read_vec_element_i32(DisasContext
*s
, TCGv_i32 tcg_dest
, int srcidx
,
875 int element
, TCGMemOp memop
)
877 int vect_off
= vec_reg_offset(s
, srcidx
, element
, memop
& MO_SIZE
);
880 tcg_gen_ld8u_i32(tcg_dest
, cpu_env
, vect_off
);
883 tcg_gen_ld16u_i32(tcg_dest
, cpu_env
, vect_off
);
886 tcg_gen_ld8s_i32(tcg_dest
, cpu_env
, vect_off
);
889 tcg_gen_ld16s_i32(tcg_dest
, cpu_env
, vect_off
);
893 tcg_gen_ld_i32(tcg_dest
, cpu_env
, vect_off
);
896 g_assert_not_reached();
900 /* Set value of an element within a vector register */
901 static void write_vec_element(DisasContext
*s
, TCGv_i64 tcg_src
, int destidx
,
902 int element
, TCGMemOp memop
)
904 int vect_off
= vec_reg_offset(s
, destidx
, element
, memop
& MO_SIZE
);
907 tcg_gen_st8_i64(tcg_src
, cpu_env
, vect_off
);
910 tcg_gen_st16_i64(tcg_src
, cpu_env
, vect_off
);
913 tcg_gen_st32_i64(tcg_src
, cpu_env
, vect_off
);
916 tcg_gen_st_i64(tcg_src
, cpu_env
, vect_off
);
919 g_assert_not_reached();
923 static void write_vec_element_i32(DisasContext
*s
, TCGv_i32 tcg_src
,
924 int destidx
, int element
, TCGMemOp memop
)
926 int vect_off
= vec_reg_offset(s
, destidx
, element
, memop
& MO_SIZE
);
929 tcg_gen_st8_i32(tcg_src
, cpu_env
, vect_off
);
932 tcg_gen_st16_i32(tcg_src
, cpu_env
, vect_off
);
935 tcg_gen_st_i32(tcg_src
, cpu_env
, vect_off
);
938 g_assert_not_reached();
942 /* Clear the high 64 bits of a 128 bit vector (in general non-quad
943 * vector ops all need to do this).
945 static void clear_vec_high(DisasContext
*s
, int rd
)
947 TCGv_i64 tcg_zero
= tcg_const_i64(0);
949 write_vec_element(s
, tcg_zero
, rd
, 1, MO_64
);
950 tcg_temp_free_i64(tcg_zero
);
953 /* Store from vector register to memory */
954 static void do_vec_st(DisasContext
*s
, int srcidx
, int element
,
955 TCGv_i64 tcg_addr
, int size
)
957 TCGMemOp memop
= s
->be_data
+ size
;
958 TCGv_i64 tcg_tmp
= tcg_temp_new_i64();
960 read_vec_element(s
, tcg_tmp
, srcidx
, element
, size
);
961 tcg_gen_qemu_st_i64(tcg_tmp
, tcg_addr
, get_mem_index(s
), memop
);
963 tcg_temp_free_i64(tcg_tmp
);
966 /* Load from memory to vector register */
967 static void do_vec_ld(DisasContext
*s
, int destidx
, int element
,
968 TCGv_i64 tcg_addr
, int size
)
970 TCGMemOp memop
= s
->be_data
+ size
;
971 TCGv_i64 tcg_tmp
= tcg_temp_new_i64();
973 tcg_gen_qemu_ld_i64(tcg_tmp
, tcg_addr
, get_mem_index(s
), memop
);
974 write_vec_element(s
, tcg_tmp
, destidx
, element
, size
);
976 tcg_temp_free_i64(tcg_tmp
);
979 /* Check that FP/Neon access is enabled. If it is, return
980 * true. If not, emit code to generate an appropriate exception,
981 * and return false; the caller should not emit any code for
982 * the instruction. Note that this check must happen after all
983 * unallocated-encoding checks (otherwise the syndrome information
984 * for the resulting exception will be incorrect).
986 static inline bool fp_access_check(DisasContext
*s
)
988 assert(!s
->fp_access_checked
);
989 s
->fp_access_checked
= true;
991 if (!s
->fp_excp_el
) {
995 gen_exception_insn(s
, 4, EXCP_UDEF
, syn_fp_access_trap(1, 0xe, false),
1001 * This utility function is for doing register extension with an
1002 * optional shift. You will likely want to pass a temporary for the
1003 * destination register. See DecodeRegExtend() in the ARM ARM.
1005 static void ext_and_shift_reg(TCGv_i64 tcg_out
, TCGv_i64 tcg_in
,
1006 int option
, unsigned int shift
)
1008 int extsize
= extract32(option
, 0, 2);
1009 bool is_signed
= extract32(option
, 2, 1);
1014 tcg_gen_ext8s_i64(tcg_out
, tcg_in
);
1017 tcg_gen_ext16s_i64(tcg_out
, tcg_in
);
1020 tcg_gen_ext32s_i64(tcg_out
, tcg_in
);
1023 tcg_gen_mov_i64(tcg_out
, tcg_in
);
1029 tcg_gen_ext8u_i64(tcg_out
, tcg_in
);
1032 tcg_gen_ext16u_i64(tcg_out
, tcg_in
);
1035 tcg_gen_ext32u_i64(tcg_out
, tcg_in
);
1038 tcg_gen_mov_i64(tcg_out
, tcg_in
);
1044 tcg_gen_shli_i64(tcg_out
, tcg_out
, shift
);
1048 static inline void gen_check_sp_alignment(DisasContext
*s
)
1050 /* The AArch64 architecture mandates that (if enabled via PSTATE
1051 * or SCTLR bits) there is a check that SP is 16-aligned on every
1052 * SP-relative load or store (with an exception generated if it is not).
1053 * In line with general QEMU practice regarding misaligned accesses,
1054 * we omit these checks for the sake of guest program performance.
1055 * This function is provided as a hook so we can more easily add these
1056 * checks in future (possibly as a "favour catching guest program bugs
1057 * over speed" user selectable option).
1062 * This provides a simple table based table lookup decoder. It is
1063 * intended to be used when the relevant bits for decode are too
1064 * awkwardly placed and switch/if based logic would be confusing and
1065 * deeply nested. Since it's a linear search through the table, tables
1066 * should be kept small.
1068 * It returns the first handler where insn & mask == pattern, or
1069 * NULL if there is no match.
1070 * The table is terminated by an empty mask (i.e. 0)
1072 static inline AArch64DecodeFn
*lookup_disas_fn(const AArch64DecodeTable
*table
,
1075 const AArch64DecodeTable
*tptr
= table
;
1077 while (tptr
->mask
) {
1078 if ((insn
& tptr
->mask
) == tptr
->pattern
) {
1079 return tptr
->disas_fn
;
1087 * the instruction disassembly implemented here matches
1088 * the instruction encoding classifications in chapter 3 (C3)
1089 * of the ARM Architecture Reference Manual (DDI0487A_a)
1092 /* C3.2.7 Unconditional branch (immediate)
1094 * +----+-----------+-------------------------------------+
1095 * | op | 0 0 1 0 1 | imm26 |
1096 * +----+-----------+-------------------------------------+
1098 static void disas_uncond_b_imm(DisasContext
*s
, uint32_t insn
)
1100 uint64_t addr
= s
->pc
+ sextract32(insn
, 0, 26) * 4 - 4;
1102 if (insn
& (1U << 31)) {
1103 /* C5.6.26 BL Branch with link */
1104 tcg_gen_movi_i64(cpu_reg(s
, 30), s
->pc
);
1107 /* C5.6.20 B Branch / C5.6.26 BL Branch with link */
1108 gen_goto_tb(s
, 0, addr
);
1111 /* C3.2.1 Compare & branch (immediate)
1112 * 31 30 25 24 23 5 4 0
1113 * +----+-------------+----+---------------------+--------+
1114 * | sf | 0 1 1 0 1 0 | op | imm19 | Rt |
1115 * +----+-------------+----+---------------------+--------+
1117 static void disas_comp_b_imm(DisasContext
*s
, uint32_t insn
)
1119 unsigned int sf
, op
, rt
;
1121 TCGLabel
*label_match
;
1124 sf
= extract32(insn
, 31, 1);
1125 op
= extract32(insn
, 24, 1); /* 0: CBZ; 1: CBNZ */
1126 rt
= extract32(insn
, 0, 5);
1127 addr
= s
->pc
+ sextract32(insn
, 5, 19) * 4 - 4;
1129 tcg_cmp
= read_cpu_reg(s
, rt
, sf
);
1130 label_match
= gen_new_label();
1132 tcg_gen_brcondi_i64(op ? TCG_COND_NE
: TCG_COND_EQ
,
1133 tcg_cmp
, 0, label_match
);
1135 gen_goto_tb(s
, 0, s
->pc
);
1136 gen_set_label(label_match
);
1137 gen_goto_tb(s
, 1, addr
);
1140 /* C3.2.5 Test & branch (immediate)
1141 * 31 30 25 24 23 19 18 5 4 0
1142 * +----+-------------+----+-------+-------------+------+
1143 * | b5 | 0 1 1 0 1 1 | op | b40 | imm14 | Rt |
1144 * +----+-------------+----+-------+-------------+------+
1146 static void disas_test_b_imm(DisasContext
*s
, uint32_t insn
)
1148 unsigned int bit_pos
, op
, rt
;
1150 TCGLabel
*label_match
;
1153 bit_pos
= (extract32(insn
, 31, 1) << 5) | extract32(insn
, 19, 5);
1154 op
= extract32(insn
, 24, 1); /* 0: TBZ; 1: TBNZ */
1155 addr
= s
->pc
+ sextract32(insn
, 5, 14) * 4 - 4;
1156 rt
= extract32(insn
, 0, 5);
1158 tcg_cmp
= tcg_temp_new_i64();
1159 tcg_gen_andi_i64(tcg_cmp
, cpu_reg(s
, rt
), (1ULL << bit_pos
));
1160 label_match
= gen_new_label();
1161 tcg_gen_brcondi_i64(op ? TCG_COND_NE
: TCG_COND_EQ
,
1162 tcg_cmp
, 0, label_match
);
1163 tcg_temp_free_i64(tcg_cmp
);
1164 gen_goto_tb(s
, 0, s
->pc
);
1165 gen_set_label(label_match
);
1166 gen_goto_tb(s
, 1, addr
);
1169 /* C3.2.2 / C5.6.19 Conditional branch (immediate)
1170 * 31 25 24 23 5 4 3 0
1171 * +---------------+----+---------------------+----+------+
1172 * | 0 1 0 1 0 1 0 | o1 | imm19 | o0 | cond |
1173 * +---------------+----+---------------------+----+------+
1175 static void disas_cond_b_imm(DisasContext
*s
, uint32_t insn
)
1180 if ((insn
& (1 << 4)) || (insn
& (1 << 24))) {
1181 unallocated_encoding(s
);
1184 addr
= s
->pc
+ sextract32(insn
, 5, 19) * 4 - 4;
1185 cond
= extract32(insn
, 0, 4);
1188 /* genuinely conditional branches */
1189 TCGLabel
*label_match
= gen_new_label();
1190 arm_gen_test_cc(cond
, label_match
);
1191 gen_goto_tb(s
, 0, s
->pc
);
1192 gen_set_label(label_match
);
1193 gen_goto_tb(s
, 1, addr
);
1195 /* 0xe and 0xf are both "always" conditions */
1196 gen_goto_tb(s
, 0, addr
);
1201 static void handle_hint(DisasContext
*s
, uint32_t insn
,
1202 unsigned int op1
, unsigned int op2
, unsigned int crm
)
1204 unsigned int selector
= crm
<< 3 | op2
;
1207 unallocated_encoding(s
);
1215 s
->is_jmp
= DISAS_WFI
;
1218 s
->is_jmp
= DISAS_YIELD
;
1221 s
->is_jmp
= DISAS_WFE
;
1225 /* we treat all as NOP at least for now */
1228 /* default specified as NOP equivalent */
1233 static void gen_clrex(DisasContext
*s
, uint32_t insn
)
1235 tcg_gen_movi_i64(cpu_exclusive_addr
, -1);
1238 /* CLREX, DSB, DMB, ISB */
1239 static void handle_sync(DisasContext
*s
, uint32_t insn
,
1240 unsigned int op1
, unsigned int op2
, unsigned int crm
)
1243 unallocated_encoding(s
);
1253 /* We don't emulate caches so barriers are no-ops */
1256 /* We need to break the TB after this insn to execute
1257 * a self-modified code correctly and also to take
1258 * any pending interrupts immediately.
1260 s
->is_jmp
= DISAS_UPDATE
;
1263 unallocated_encoding(s
);
1268 /* C5.6.130 MSR (immediate) - move immediate to processor state field */
1269 static void handle_msr_i(DisasContext
*s
, uint32_t insn
,
1270 unsigned int op1
, unsigned int op2
, unsigned int crm
)
1272 int op
= op1
<< 3 | op2
;
1274 case 0x05: /* SPSel */
1275 if (s
->current_el
== 0) {
1276 unallocated_encoding(s
);
1280 case 0x1e: /* DAIFSet */
1281 case 0x1f: /* DAIFClear */
1283 TCGv_i32 tcg_imm
= tcg_const_i32(crm
);
1284 TCGv_i32 tcg_op
= tcg_const_i32(op
);
1285 gen_a64_set_pc_im(s
->pc
- 4);
1286 gen_helper_msr_i_pstate(cpu_env
, tcg_op
, tcg_imm
);
1287 tcg_temp_free_i32(tcg_imm
);
1288 tcg_temp_free_i32(tcg_op
);
1289 s
->is_jmp
= DISAS_UPDATE
;
1293 unallocated_encoding(s
);
1298 static void gen_get_nzcv(TCGv_i64 tcg_rt
)
1300 TCGv_i32 tmp
= tcg_temp_new_i32();
1301 TCGv_i32 nzcv
= tcg_temp_new_i32();
1303 /* build bit 31, N */
1304 tcg_gen_andi_i32(nzcv
, cpu_NF
, (1U << 31));
1305 /* build bit 30, Z */
1306 tcg_gen_setcondi_i32(TCG_COND_EQ
, tmp
, cpu_ZF
, 0);
1307 tcg_gen_deposit_i32(nzcv
, nzcv
, tmp
, 30, 1);
1308 /* build bit 29, C */
1309 tcg_gen_deposit_i32(nzcv
, nzcv
, cpu_CF
, 29, 1);
1310 /* build bit 28, V */
1311 tcg_gen_shri_i32(tmp
, cpu_VF
, 31);
1312 tcg_gen_deposit_i32(nzcv
, nzcv
, tmp
, 28, 1);
1313 /* generate result */
1314 tcg_gen_extu_i32_i64(tcg_rt
, nzcv
);
1316 tcg_temp_free_i32(nzcv
);
1317 tcg_temp_free_i32(tmp
);
1320 static void gen_set_nzcv(TCGv_i64 tcg_rt
)
1323 TCGv_i32 nzcv
= tcg_temp_new_i32();
1325 /* take NZCV from R[t] */
1326 tcg_gen_extrl_i64_i32(nzcv
, tcg_rt
);
1329 tcg_gen_andi_i32(cpu_NF
, nzcv
, (1U << 31));
1331 tcg_gen_andi_i32(cpu_ZF
, nzcv
, (1 << 30));
1332 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_ZF
, cpu_ZF
, 0);
1334 tcg_gen_andi_i32(cpu_CF
, nzcv
, (1 << 29));
1335 tcg_gen_shri_i32(cpu_CF
, cpu_CF
, 29);
1337 tcg_gen_andi_i32(cpu_VF
, nzcv
, (1 << 28));
1338 tcg_gen_shli_i32(cpu_VF
, cpu_VF
, 3);
1339 tcg_temp_free_i32(nzcv
);
1342 /* C5.6.129 MRS - move from system register
1343 * C5.6.131 MSR (register) - move to system register
1346 * These are all essentially the same insn in 'read' and 'write'
1347 * versions, with varying op0 fields.
1349 static void handle_sys(DisasContext
*s
, uint32_t insn
, bool isread
,
1350 unsigned int op0
, unsigned int op1
, unsigned int op2
,
1351 unsigned int crn
, unsigned int crm
, unsigned int rt
)
1353 const ARMCPRegInfo
*ri
;
1356 ri
= get_arm_cp_reginfo(s
->cp_regs
,
1357 ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP
,
1358 crn
, crm
, op0
, op1
, op2
));
1361 /* Unknown register; this might be a guest error or a QEMU
1362 * unimplemented feature.
1364 qemu_log_mask(LOG_UNIMP
, "%s access to unsupported AArch64 "
1365 "system register op0:%d op1:%d crn:%d crm:%d op2:%d\n",
1366 isread ?
"read" : "write", op0
, op1
, crn
, crm
, op2
);
1367 unallocated_encoding(s
);
1371 /* Check access permissions */
1372 if (!cp_access_ok(s
->current_el
, ri
, isread
)) {
1373 unallocated_encoding(s
);
1378 /* Emit code to perform further access permissions checks at
1379 * runtime; this may result in an exception.
1382 TCGv_i32 tcg_syn
, tcg_isread
;
1385 gen_a64_set_pc_im(s
->pc
- 4);
1386 tmpptr
= tcg_const_ptr(ri
);
1387 syndrome
= syn_aa64_sysregtrap(op0
, op1
, op2
, crn
, crm
, rt
, isread
);
1388 tcg_syn
= tcg_const_i32(syndrome
);
1389 tcg_isread
= tcg_const_i32(isread
);
1390 gen_helper_access_check_cp_reg(cpu_env
, tmpptr
, tcg_syn
, tcg_isread
);
1391 tcg_temp_free_ptr(tmpptr
);
1392 tcg_temp_free_i32(tcg_syn
);
1393 tcg_temp_free_i32(tcg_isread
);
1396 /* Handle special cases first */
1397 switch (ri
->type
& ~(ARM_CP_FLAG_MASK
& ~ARM_CP_SPECIAL
)) {
1401 tcg_rt
= cpu_reg(s
, rt
);
1403 gen_get_nzcv(tcg_rt
);
1405 gen_set_nzcv(tcg_rt
);
1408 case ARM_CP_CURRENTEL
:
1409 /* Reads as current EL value from pstate, which is
1410 * guaranteed to be constant by the tb flags.
1412 tcg_rt
= cpu_reg(s
, rt
);
1413 tcg_gen_movi_i64(tcg_rt
, s
->current_el
<< 2);
1416 /* Writes clear the aligned block of memory which rt points into. */
1417 tcg_rt
= cpu_reg(s
, rt
);
1418 gen_helper_dc_zva(cpu_env
, tcg_rt
);
1424 if ((s
->tb
->cflags
& CF_USE_ICOUNT
) && (ri
->type
& ARM_CP_IO
)) {
1428 tcg_rt
= cpu_reg(s
, rt
);
1431 if (ri
->type
& ARM_CP_CONST
) {
1432 tcg_gen_movi_i64(tcg_rt
, ri
->resetvalue
);
1433 } else if (ri
->readfn
) {
1435 tmpptr
= tcg_const_ptr(ri
);
1436 gen_helper_get_cp_reg64(tcg_rt
, cpu_env
, tmpptr
);
1437 tcg_temp_free_ptr(tmpptr
);
1439 tcg_gen_ld_i64(tcg_rt
, cpu_env
, ri
->fieldoffset
);
1442 if (ri
->type
& ARM_CP_CONST
) {
1443 /* If not forbidden by access permissions, treat as WI */
1445 } else if (ri
->writefn
) {
1447 tmpptr
= tcg_const_ptr(ri
);
1448 gen_helper_set_cp_reg64(cpu_env
, tmpptr
, tcg_rt
);
1449 tcg_temp_free_ptr(tmpptr
);
1451 tcg_gen_st_i64(tcg_rt
, cpu_env
, ri
->fieldoffset
);
1455 if ((s
->tb
->cflags
& CF_USE_ICOUNT
) && (ri
->type
& ARM_CP_IO
)) {
1456 /* I/O operations must end the TB here (whether read or write) */
1458 s
->is_jmp
= DISAS_UPDATE
;
1459 } else if (!isread
&& !(ri
->type
& ARM_CP_SUPPRESS_TB_END
)) {
1460 /* We default to ending the TB on a coprocessor register write,
1461 * but allow this to be suppressed by the register definition
1462 * (usually only necessary to work around guest bugs).
1464 s
->is_jmp
= DISAS_UPDATE
;
1469 * 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
1470 * +---------------------+---+-----+-----+-------+-------+-----+------+
1471 * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 | CRn | CRm | op2 | Rt |
1472 * +---------------------+---+-----+-----+-------+-------+-----+------+
1474 static void disas_system(DisasContext
*s
, uint32_t insn
)
1476 unsigned int l
, op0
, op1
, crn
, crm
, op2
, rt
;
1477 l
= extract32(insn
, 21, 1);
1478 op0
= extract32(insn
, 19, 2);
1479 op1
= extract32(insn
, 16, 3);
1480 crn
= extract32(insn
, 12, 4);
1481 crm
= extract32(insn
, 8, 4);
1482 op2
= extract32(insn
, 5, 3);
1483 rt
= extract32(insn
, 0, 5);
1486 if (l
|| rt
!= 31) {
1487 unallocated_encoding(s
);
1491 case 2: /* C5.6.68 HINT */
1492 handle_hint(s
, insn
, op1
, op2
, crm
);
1494 case 3: /* CLREX, DSB, DMB, ISB */
1495 handle_sync(s
, insn
, op1
, op2
, crm
);
1497 case 4: /* C5.6.130 MSR (immediate) */
1498 handle_msr_i(s
, insn
, op1
, op2
, crm
);
1501 unallocated_encoding(s
);
1506 handle_sys(s
, insn
, l
, op0
, op1
, op2
, crn
, crm
, rt
);
1509 /* C3.2.3 Exception generation
1511 * 31 24 23 21 20 5 4 2 1 0
1512 * +-----------------+-----+------------------------+-----+----+
1513 * | 1 1 0 1 0 1 0 0 | opc | imm16 | op2 | LL |
1514 * +-----------------------+------------------------+----------+
1516 static void disas_exc(DisasContext
*s
, uint32_t insn
)
1518 int opc
= extract32(insn
, 21, 3);
1519 int op2_ll
= extract32(insn
, 0, 5);
1520 int imm16
= extract32(insn
, 5, 16);
1525 /* For SVC, HVC and SMC we advance the single-step state
1526 * machine before taking the exception. This is architecturally
1527 * mandated, to ensure that single-stepping a system call
1528 * instruction works properly.
1533 gen_exception_insn(s
, 0, EXCP_SWI
, syn_aa64_svc(imm16
),
1534 default_exception_el(s
));
1537 if (s
->current_el
== 0) {
1538 unallocated_encoding(s
);
1541 /* The pre HVC helper handles cases when HVC gets trapped
1542 * as an undefined insn by runtime configuration.
1544 gen_a64_set_pc_im(s
->pc
- 4);
1545 gen_helper_pre_hvc(cpu_env
);
1547 gen_exception_insn(s
, 0, EXCP_HVC
, syn_aa64_hvc(imm16
), 2);
1550 if (s
->current_el
== 0) {
1551 unallocated_encoding(s
);
1554 gen_a64_set_pc_im(s
->pc
- 4);
1555 tmp
= tcg_const_i32(syn_aa64_smc(imm16
));
1556 gen_helper_pre_smc(cpu_env
, tmp
);
1557 tcg_temp_free_i32(tmp
);
1559 gen_exception_insn(s
, 0, EXCP_SMC
, syn_aa64_smc(imm16
), 3);
1562 unallocated_encoding(s
);
1568 unallocated_encoding(s
);
1572 gen_exception_insn(s
, 4, EXCP_BKPT
, syn_aa64_bkpt(imm16
),
1573 default_exception_el(s
));
1577 unallocated_encoding(s
);
1580 /* HLT. This has two purposes.
1581 * Architecturally, it is an external halting debug instruction.
1582 * Since QEMU doesn't implement external debug, we treat this as
1583 * it is required for halting debug disabled: it will UNDEF.
1584 * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
1586 if (semihosting_enabled() && imm16
== 0xf000) {
1587 #ifndef CONFIG_USER_ONLY
1588 /* In system mode, don't allow userspace access to semihosting,
1589 * to provide some semblance of security (and for consistency
1590 * with our 32-bit semihosting).
1592 if (s
->current_el
== 0) {
1593 unsupported_encoding(s
, insn
);
1597 gen_exception_internal_insn(s
, 0, EXCP_SEMIHOST
);
1599 unsupported_encoding(s
, insn
);
1603 if (op2_ll
< 1 || op2_ll
> 3) {
1604 unallocated_encoding(s
);
1607 /* DCPS1, DCPS2, DCPS3 */
1608 unsupported_encoding(s
, insn
);
1611 unallocated_encoding(s
);
1616 /* C3.2.7 Unconditional branch (register)
1617 * 31 25 24 21 20 16 15 10 9 5 4 0
1618 * +---------------+-------+-------+-------+------+-------+
1619 * | 1 1 0 1 0 1 1 | opc | op2 | op3 | Rn | op4 |
1620 * +---------------+-------+-------+-------+------+-------+
1622 static void disas_uncond_b_reg(DisasContext
*s
, uint32_t insn
)
1624 unsigned int opc
, op2
, op3
, rn
, op4
;
1626 opc
= extract32(insn
, 21, 4);
1627 op2
= extract32(insn
, 16, 5);
1628 op3
= extract32(insn
, 10, 6);
1629 rn
= extract32(insn
, 5, 5);
1630 op4
= extract32(insn
, 0, 5);
1632 if (op4
!= 0x0 || op3
!= 0x0 || op2
!= 0x1f) {
1633 unallocated_encoding(s
);
1640 tcg_gen_mov_i64(cpu_pc
, cpu_reg(s
, rn
));
1643 tcg_gen_mov_i64(cpu_pc
, cpu_reg(s
, rn
));
1644 tcg_gen_movi_i64(cpu_reg(s
, 30), s
->pc
);
1647 if (s
->current_el
== 0) {
1648 unallocated_encoding(s
);
1651 gen_helper_exception_return(cpu_env
);
1652 s
->is_jmp
= DISAS_JUMP
;
1656 unallocated_encoding(s
);
1658 unsupported_encoding(s
, insn
);
1662 unallocated_encoding(s
);
1666 s
->is_jmp
= DISAS_JUMP
;
1669 /* C3.2 Branches, exception generating and system instructions */
1670 static void disas_b_exc_sys(DisasContext
*s
, uint32_t insn
)
1672 switch (extract32(insn
, 25, 7)) {
1673 case 0x0a: case 0x0b:
1674 case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
1675 disas_uncond_b_imm(s
, insn
);
1677 case 0x1a: case 0x5a: /* Compare & branch (immediate) */
1678 disas_comp_b_imm(s
, insn
);
1680 case 0x1b: case 0x5b: /* Test & branch (immediate) */
1681 disas_test_b_imm(s
, insn
);
1683 case 0x2a: /* Conditional branch (immediate) */
1684 disas_cond_b_imm(s
, insn
);
1686 case 0x6a: /* Exception generation / System */
1687 if (insn
& (1 << 24)) {
1688 disas_system(s
, insn
);
1693 case 0x6b: /* Unconditional branch (register) */
1694 disas_uncond_b_reg(s
, insn
);
1697 unallocated_encoding(s
);
1703 * Load/Store exclusive instructions are implemented by remembering
1704 * the value/address loaded, and seeing if these are the same
1705 * when the store is performed. This is not actually the architecturally
1706 * mandated semantics, but it works for typical guest code sequences
1707 * and avoids having to monitor regular stores.
1709 * In system emulation mode only one CPU will be running at once, so
1710 * this sequence is effectively atomic. In user emulation mode we
1711 * throw an exception and handle the atomic operation elsewhere.
1713 static void gen_load_exclusive(DisasContext
*s
, int rt
, int rt2
,
1714 TCGv_i64 addr
, int size
, bool is_pair
)
1716 TCGv_i64 tmp
= tcg_temp_new_i64();
1717 TCGMemOp memop
= s
->be_data
+ size
;
1719 g_assert(size
<= 3);
1720 tcg_gen_qemu_ld_i64(tmp
, addr
, get_mem_index(s
), memop
);
1723 TCGv_i64 addr2
= tcg_temp_new_i64();
1724 TCGv_i64 hitmp
= tcg_temp_new_i64();
1726 g_assert(size
>= 2);
1727 tcg_gen_addi_i64(addr2
, addr
, 1 << size
);
1728 tcg_gen_qemu_ld_i64(hitmp
, addr2
, get_mem_index(s
), memop
);
1729 tcg_temp_free_i64(addr2
);
1730 tcg_gen_mov_i64(cpu_exclusive_high
, hitmp
);
1731 tcg_gen_mov_i64(cpu_reg(s
, rt2
), hitmp
);
1732 tcg_temp_free_i64(hitmp
);
1735 tcg_gen_mov_i64(cpu_exclusive_val
, tmp
);
1736 tcg_gen_mov_i64(cpu_reg(s
, rt
), tmp
);
1738 tcg_temp_free_i64(tmp
);
1739 tcg_gen_mov_i64(cpu_exclusive_addr
, addr
);
1742 #ifdef CONFIG_USER_ONLY
1743 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
1744 TCGv_i64 addr
, int size
, int is_pair
)
1746 tcg_gen_mov_i64(cpu_exclusive_test
, addr
);
1747 tcg_gen_movi_i32(cpu_exclusive_info
,
1748 size
| is_pair
<< 2 | (rd
<< 4) | (rt
<< 9) | (rt2
<< 14));
1749 gen_exception_internal_insn(s
, 4, EXCP_STREX
);
1752 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
1753 TCGv_i64 inaddr
, int size
, int is_pair
)
1755 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]
1756 * && (!is_pair || env->exclusive_high == [addr + datasize])) {
1759 * [addr + datasize] = {Rt2};
1765 * env->exclusive_addr = -1;
1767 TCGLabel
*fail_label
= gen_new_label();
1768 TCGLabel
*done_label
= gen_new_label();
1769 TCGv_i64 addr
= tcg_temp_local_new_i64();
1772 /* Copy input into a local temp so it is not trashed when the
1773 * basic block ends at the branch insn.
1775 tcg_gen_mov_i64(addr
, inaddr
);
1776 tcg_gen_brcond_i64(TCG_COND_NE
, addr
, cpu_exclusive_addr
, fail_label
);
1778 tmp
= tcg_temp_new_i64();
1779 tcg_gen_qemu_ld_i64(tmp
, addr
, get_mem_index(s
), s
->be_data
+ size
);
1780 tcg_gen_brcond_i64(TCG_COND_NE
, tmp
, cpu_exclusive_val
, fail_label
);
1781 tcg_temp_free_i64(tmp
);
1784 TCGv_i64 addrhi
= tcg_temp_new_i64();
1785 TCGv_i64 tmphi
= tcg_temp_new_i64();
1787 tcg_gen_addi_i64(addrhi
, addr
, 1 << size
);
1788 tcg_gen_qemu_ld_i64(tmphi
, addrhi
, get_mem_index(s
),
1790 tcg_gen_brcond_i64(TCG_COND_NE
, tmphi
, cpu_exclusive_high
, fail_label
);
1792 tcg_temp_free_i64(tmphi
);
1793 tcg_temp_free_i64(addrhi
);
1796 /* We seem to still have the exclusive monitor, so do the store */
1797 tcg_gen_qemu_st_i64(cpu_reg(s
, rt
), addr
, get_mem_index(s
),
1800 TCGv_i64 addrhi
= tcg_temp_new_i64();
1802 tcg_gen_addi_i64(addrhi
, addr
, 1 << size
);
1803 tcg_gen_qemu_st_i64(cpu_reg(s
, rt2
), addrhi
,
1804 get_mem_index(s
), s
->be_data
+ size
);
1805 tcg_temp_free_i64(addrhi
);
1808 tcg_temp_free_i64(addr
);
1810 tcg_gen_movi_i64(cpu_reg(s
, rd
), 0);
1811 tcg_gen_br(done_label
);
1812 gen_set_label(fail_label
);
1813 tcg_gen_movi_i64(cpu_reg(s
, rd
), 1);
1814 gen_set_label(done_label
);
1815 tcg_gen_movi_i64(cpu_exclusive_addr
, -1);
1820 /* C3.3.6 Load/store exclusive
1822 * 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
1823 * +-----+-------------+----+---+----+------+----+-------+------+------+
1824 * | sz | 0 0 1 0 0 0 | o2 | L | o1 | Rs | o0 | Rt2 | Rn | Rt |
1825 * +-----+-------------+----+---+----+------+----+-------+------+------+
1827 * sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
1828 * L: 0 -> store, 1 -> load
1829 * o2: 0 -> exclusive, 1 -> not
1830 * o1: 0 -> single register, 1 -> register pair
1831 * o0: 1 -> load-acquire/store-release, 0 -> not
1833 static void disas_ldst_excl(DisasContext
*s
, uint32_t insn
)
1835 int rt
= extract32(insn
, 0, 5);
1836 int rn
= extract32(insn
, 5, 5);
1837 int rt2
= extract32(insn
, 10, 5);
1838 int is_lasr
= extract32(insn
, 15, 1);
1839 int rs
= extract32(insn
, 16, 5);
1840 int is_pair
= extract32(insn
, 21, 1);
1841 int is_store
= !extract32(insn
, 22, 1);
1842 int is_excl
= !extract32(insn
, 23, 1);
1843 int size
= extract32(insn
, 30, 2);
1846 if ((!is_excl
&& !is_pair
&& !is_lasr
) ||
1847 (!is_excl
&& is_pair
) ||
1848 (is_pair
&& size
< 2)) {
1849 unallocated_encoding(s
);
1854 gen_check_sp_alignment(s
);
1856 tcg_addr
= read_cpu_reg_sp(s
, rn
, 1);
1858 /* Note that since TCG is single threaded load-acquire/store-release
1859 * semantics require no extra if (is_lasr) { ... } handling.
1865 gen_load_exclusive(s
, rt
, rt2
, tcg_addr
, size
, is_pair
);
1867 gen_store_exclusive(s
, rs
, rt
, rt2
, tcg_addr
, size
, is_pair
);
1870 TCGv_i64 tcg_rt
= cpu_reg(s
, rt
);
1872 do_gpr_st(s
, tcg_rt
, tcg_addr
, size
);
1874 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, false, false);
1880 * C3.3.5 Load register (literal)
1882 * 31 30 29 27 26 25 24 23 5 4 0
1883 * +-----+-------+---+-----+-------------------+-------+
1884 * | opc | 0 1 1 | V | 0 0 | imm19 | Rt |
1885 * +-----+-------+---+-----+-------------------+-------+
1887 * V: 1 -> vector (simd/fp)
1888 * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
1889 * 10-> 32 bit signed, 11 -> prefetch
1890 * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
1892 static void disas_ld_lit(DisasContext
*s
, uint32_t insn
)
1894 int rt
= extract32(insn
, 0, 5);
1895 int64_t imm
= sextract32(insn
, 5, 19) << 2;
1896 bool is_vector
= extract32(insn
, 26, 1);
1897 int opc
= extract32(insn
, 30, 2);
1898 bool is_signed
= false;
1900 TCGv_i64 tcg_rt
, tcg_addr
;
1904 unallocated_encoding(s
);
1908 if (!fp_access_check(s
)) {
1913 /* PRFM (literal) : prefetch */
1916 size
= 2 + extract32(opc
, 0, 1);
1917 is_signed
= extract32(opc
, 1, 1);
1920 tcg_rt
= cpu_reg(s
, rt
);
1922 tcg_addr
= tcg_const_i64((s
->pc
- 4) + imm
);
1924 do_fp_ld(s
, rt
, tcg_addr
, size
);
1926 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, is_signed
, false);
1928 tcg_temp_free_i64(tcg_addr
);
1932 * C5.6.80 LDNP (Load Pair - non-temporal hint)
1933 * C5.6.81 LDP (Load Pair - non vector)
1934 * C5.6.82 LDPSW (Load Pair Signed Word - non vector)
1935 * C5.6.176 STNP (Store Pair - non-temporal hint)
1936 * C5.6.177 STP (Store Pair - non vector)
1937 * C6.3.165 LDNP (Load Pair of SIMD&FP - non-temporal hint)
1938 * C6.3.165 LDP (Load Pair of SIMD&FP)
1939 * C6.3.284 STNP (Store Pair of SIMD&FP - non-temporal hint)
1940 * C6.3.284 STP (Store Pair of SIMD&FP)
1942 * 31 30 29 27 26 25 24 23 22 21 15 14 10 9 5 4 0
1943 * +-----+-------+---+---+-------+---+-----------------------------+
1944 * | opc | 1 0 1 | V | 0 | index | L | imm7 | Rt2 | Rn | Rt |
1945 * +-----+-------+---+---+-------+---+-------+-------+------+------+
1947 * opc: LDP/STP/LDNP/STNP 00 -> 32 bit, 10 -> 64 bit
1949 * LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
1950 * V: 0 -> GPR, 1 -> Vector
1951 * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
1952 * 10 -> signed offset, 11 -> pre-index
1953 * L: 0 -> Store 1 -> Load
1955 * Rt, Rt2 = GPR or SIMD registers to be stored
1956 * Rn = general purpose register containing address
1957 * imm7 = signed offset (multiple of 4 or 8 depending on size)
1959 static void disas_ldst_pair(DisasContext
*s
, uint32_t insn
)
1961 int rt
= extract32(insn
, 0, 5);
1962 int rn
= extract32(insn
, 5, 5);
1963 int rt2
= extract32(insn
, 10, 5);
1964 uint64_t offset
= sextract64(insn
, 15, 7);
1965 int index
= extract32(insn
, 23, 2);
1966 bool is_vector
= extract32(insn
, 26, 1);
1967 bool is_load
= extract32(insn
, 22, 1);
1968 int opc
= extract32(insn
, 30, 2);
1970 bool is_signed
= false;
1971 bool postindex
= false;
1974 TCGv_i64 tcg_addr
; /* calculated address */
1978 unallocated_encoding(s
);
1985 size
= 2 + extract32(opc
, 1, 1);
1986 is_signed
= extract32(opc
, 0, 1);
1987 if (!is_load
&& is_signed
) {
1988 unallocated_encoding(s
);
1994 case 1: /* post-index */
1999 /* signed offset with "non-temporal" hint. Since we don't emulate
2000 * caches we don't care about hints to the cache system about
2001 * data access patterns, and handle this identically to plain
2005 /* There is no non-temporal-hint version of LDPSW */
2006 unallocated_encoding(s
);
2011 case 2: /* signed offset, rn not updated */
2014 case 3: /* pre-index */
2020 if (is_vector
&& !fp_access_check(s
)) {
2027 gen_check_sp_alignment(s
);
2030 tcg_addr
= read_cpu_reg_sp(s
, rn
, 1);
2033 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, offset
);
2038 do_fp_ld(s
, rt
, tcg_addr
, size
);
2040 do_fp_st(s
, rt
, tcg_addr
, size
);
2043 TCGv_i64 tcg_rt
= cpu_reg(s
, rt
);
2045 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, is_signed
, false);
2047 do_gpr_st(s
, tcg_rt
, tcg_addr
, size
);
2050 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, 1 << size
);
2053 do_fp_ld(s
, rt2
, tcg_addr
, size
);
2055 do_fp_st(s
, rt2
, tcg_addr
, size
);
2058 TCGv_i64 tcg_rt2
= cpu_reg(s
, rt2
);
2060 do_gpr_ld(s
, tcg_rt2
, tcg_addr
, size
, is_signed
, false);
2062 do_gpr_st(s
, tcg_rt2
, tcg_addr
, size
);
2068 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, offset
- (1 << size
));
2070 tcg_gen_subi_i64(tcg_addr
, tcg_addr
, 1 << size
);
2072 tcg_gen_mov_i64(cpu_reg_sp(s
, rn
), tcg_addr
);
2077 * C3.3.8 Load/store (immediate post-indexed)
2078 * C3.3.9 Load/store (immediate pre-indexed)
2079 * C3.3.12 Load/store (unscaled immediate)
2081 * 31 30 29 27 26 25 24 23 22 21 20 12 11 10 9 5 4 0
2082 * +----+-------+---+-----+-----+---+--------+-----+------+------+
2083 * |size| 1 1 1 | V | 0 0 | opc | 0 | imm9 | idx | Rn | Rt |
2084 * +----+-------+---+-----+-----+---+--------+-----+------+------+
2086 * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
2088 * V = 0 -> non-vector
2089 * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
2090 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2092 static void disas_ldst_reg_imm9(DisasContext
*s
, uint32_t insn
,
2098 int rn
= extract32(insn
, 5, 5);
2099 int imm9
= sextract32(insn
, 12, 9);
2100 int idx
= extract32(insn
, 10, 2);
2101 bool is_signed
= false;
2102 bool is_store
= false;
2103 bool is_extended
= false;
2104 bool is_unpriv
= (idx
== 2);
2111 size
|= (opc
& 2) << 1;
2112 if (size
> 4 || is_unpriv
) {
2113 unallocated_encoding(s
);
2116 is_store
= ((opc
& 1) == 0);
2117 if (!fp_access_check(s
)) {
2121 if (size
== 3 && opc
== 2) {
2122 /* PRFM - prefetch */
2124 unallocated_encoding(s
);
2129 if (opc
== 3 && size
> 1) {
2130 unallocated_encoding(s
);
2133 is_store
= (opc
== 0);
2134 is_signed
= extract32(opc
, 1, 1);
2135 is_extended
= (size
< 3) && extract32(opc
, 0, 1);
2155 gen_check_sp_alignment(s
);
2157 tcg_addr
= read_cpu_reg_sp(s
, rn
, 1);
2160 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, imm9
);
2165 do_fp_st(s
, rt
, tcg_addr
, size
);
2167 do_fp_ld(s
, rt
, tcg_addr
, size
);
2170 TCGv_i64 tcg_rt
= cpu_reg(s
, rt
);
2171 int memidx
= is_unpriv ?
get_a64_user_mem_index(s
) : get_mem_index(s
);
2174 do_gpr_st_memidx(s
, tcg_rt
, tcg_addr
, size
, memidx
);
2176 do_gpr_ld_memidx(s
, tcg_rt
, tcg_addr
, size
,
2177 is_signed
, is_extended
, memidx
);
2182 TCGv_i64 tcg_rn
= cpu_reg_sp(s
, rn
);
2184 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, imm9
);
2186 tcg_gen_mov_i64(tcg_rn
, tcg_addr
);
2191 * C3.3.10 Load/store (register offset)
2193 * 31 30 29 27 26 25 24 23 22 21 20 16 15 13 12 11 10 9 5 4 0
2194 * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
2195 * |size| 1 1 1 | V | 0 0 | opc | 1 | Rm | opt | S| 1 0 | Rn | Rt |
2196 * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
2199 * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
2200 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2202 * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
2203 * opc<0>: 0 -> store, 1 -> load
2204 * V: 1 -> vector/simd
2205 * opt: extend encoding (see DecodeRegExtend)
2206 * S: if S=1 then scale (essentially index by sizeof(size))
2207 * Rt: register to transfer into/out of
2208 * Rn: address register or SP for base
2209 * Rm: offset register or ZR for offset
2211 static void disas_ldst_reg_roffset(DisasContext
*s
, uint32_t insn
,
2217 int rn
= extract32(insn
, 5, 5);
2218 int shift
= extract32(insn
, 12, 1);
2219 int rm
= extract32(insn
, 16, 5);
2220 int opt
= extract32(insn
, 13, 3);
2221 bool is_signed
= false;
2222 bool is_store
= false;
2223 bool is_extended
= false;
2228 if (extract32(opt
, 1, 1) == 0) {
2229 unallocated_encoding(s
);
2234 size
|= (opc
& 2) << 1;
2236 unallocated_encoding(s
);
2239 is_store
= !extract32(opc
, 0, 1);
2240 if (!fp_access_check(s
)) {
2244 if (size
== 3 && opc
== 2) {
2245 /* PRFM - prefetch */
2248 if (opc
== 3 && size
> 1) {
2249 unallocated_encoding(s
);
2252 is_store
= (opc
== 0);
2253 is_signed
= extract32(opc
, 1, 1);
2254 is_extended
= (size
< 3) && extract32(opc
, 0, 1);
2258 gen_check_sp_alignment(s
);
2260 tcg_addr
= read_cpu_reg_sp(s
, rn
, 1);
2262 tcg_rm
= read_cpu_reg(s
, rm
, 1);
2263 ext_and_shift_reg(tcg_rm
, tcg_rm
, opt
, shift ? size
: 0);
2265 tcg_gen_add_i64(tcg_addr
, tcg_addr
, tcg_rm
);
2269 do_fp_st(s
, rt
, tcg_addr
, size
);
2271 do_fp_ld(s
, rt
, tcg_addr
, size
);
2274 TCGv_i64 tcg_rt
= cpu_reg(s
, rt
);
2276 do_gpr_st(s
, tcg_rt
, tcg_addr
, size
);
2278 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, is_signed
, is_extended
);
2284 * C3.3.13 Load/store (unsigned immediate)
2286 * 31 30 29 27 26 25 24 23 22 21 10 9 5
2287 * +----+-------+---+-----+-----+------------+-------+------+
2288 * |size| 1 1 1 | V | 0 1 | opc | imm12 | Rn | Rt |
2289 * +----+-------+---+-----+-----+------------+-------+------+
2292 * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
2293 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2295 * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
2296 * opc<0>: 0 -> store, 1 -> load
2297 * Rn: base address register (inc SP)
2298 * Rt: target register
2300 static void disas_ldst_reg_unsigned_imm(DisasContext
*s
, uint32_t insn
,
2306 int rn
= extract32(insn
, 5, 5);
2307 unsigned int imm12
= extract32(insn
, 10, 12);
2308 unsigned int offset
;
2313 bool is_signed
= false;
2314 bool is_extended
= false;
2317 size
|= (opc
& 2) << 1;
2319 unallocated_encoding(s
);
2322 is_store
= !extract32(opc
, 0, 1);
2323 if (!fp_access_check(s
)) {
2327 if (size
== 3 && opc
== 2) {
2328 /* PRFM - prefetch */
2331 if (opc
== 3 && size
> 1) {
2332 unallocated_encoding(s
);
2335 is_store
= (opc
== 0);
2336 is_signed
= extract32(opc
, 1, 1);
2337 is_extended
= (size
< 3) && extract32(opc
, 0, 1);
2341 gen_check_sp_alignment(s
);
2343 tcg_addr
= read_cpu_reg_sp(s
, rn
, 1);
2344 offset
= imm12
<< size
;
2345 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, offset
);
2349 do_fp_st(s
, rt
, tcg_addr
, size
);
2351 do_fp_ld(s
, rt
, tcg_addr
, size
);
2354 TCGv_i64 tcg_rt
= cpu_reg(s
, rt
);
2356 do_gpr_st(s
, tcg_rt
, tcg_addr
, size
);
2358 do_gpr_ld(s
, tcg_rt
, tcg_addr
, size
, is_signed
, is_extended
);
2363 /* Load/store register (all forms) */
2364 static void disas_ldst_reg(DisasContext
*s
, uint32_t insn
)
2366 int rt
= extract32(insn
, 0, 5);
2367 int opc
= extract32(insn
, 22, 2);
2368 bool is_vector
= extract32(insn
, 26, 1);
2369 int size
= extract32(insn
, 30, 2);
2371 switch (extract32(insn
, 24, 2)) {
2373 if (extract32(insn
, 21, 1) == 1 && extract32(insn
, 10, 2) == 2) {
2374 disas_ldst_reg_roffset(s
, insn
, opc
, size
, rt
, is_vector
);
2376 /* Load/store register (unscaled immediate)
2377 * Load/store immediate pre/post-indexed
2378 * Load/store register unprivileged
2380 disas_ldst_reg_imm9(s
, insn
, opc
, size
, rt
, is_vector
);
2384 disas_ldst_reg_unsigned_imm(s
, insn
, opc
, size
, rt
, is_vector
);
2387 unallocated_encoding(s
);
2392 /* C3.3.1 AdvSIMD load/store multiple structures
2394 * 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
2395 * +---+---+---------------+---+-------------+--------+------+------+------+
2396 * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size | Rn | Rt |
2397 * +---+---+---------------+---+-------------+--------+------+------+------+
2399 * C3.3.2 AdvSIMD load/store multiple structures (post-indexed)
2401 * 31 30 29 23 22 21 20 16 15 12 11 10 9 5 4 0
2402 * +---+---+---------------+---+---+---------+--------+------+------+------+
2403 * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 | Rm | opcode | size | Rn | Rt |
2404 * +---+---+---------------+---+---+---------+--------+------+------+------+
2406 * Rt: first (or only) SIMD&FP register to be transferred
2407 * Rn: base address or SP
2408 * Rm (post-index only): post-index register (when !31) or size dependent #imm
2410 static void disas_ldst_multiple_struct(DisasContext
*s
, uint32_t insn
)
2412 int rt
= extract32(insn
, 0, 5);
2413 int rn
= extract32(insn
, 5, 5);
2414 int size
= extract32(insn
, 10, 2);
2415 int opcode
= extract32(insn
, 12, 4);
2416 bool is_store
= !extract32(insn
, 22, 1);
2417 bool is_postidx
= extract32(insn
, 23, 1);
2418 bool is_q
= extract32(insn
, 30, 1);
2419 TCGv_i64 tcg_addr
, tcg_rn
;
2421 int ebytes
= 1 << size
;
2422 int elements
= (is_q ?
128 : 64) / (8 << size
);
2423 int rpt
; /* num iterations */
2424 int selem
; /* structure elements */
2427 if (extract32(insn
, 31, 1) || extract32(insn
, 21, 1)) {
2428 unallocated_encoding(s
);
2432 /* From the shared decode logic */
2463 unallocated_encoding(s
);
2467 if (size
== 3 && !is_q
&& selem
!= 1) {
2469 unallocated_encoding(s
);
2473 if (!fp_access_check(s
)) {
2478 gen_check_sp_alignment(s
);
2481 tcg_rn
= cpu_reg_sp(s
, rn
);
2482 tcg_addr
= tcg_temp_new_i64();
2483 tcg_gen_mov_i64(tcg_addr
, tcg_rn
);
2485 for (r
= 0; r
< rpt
; r
++) {
2487 for (e
= 0; e
< elements
; e
++) {
2488 int tt
= (rt
+ r
) % 32;
2490 for (xs
= 0; xs
< selem
; xs
++) {
2492 do_vec_st(s
, tt
, e
, tcg_addr
, size
);
2494 do_vec_ld(s
, tt
, e
, tcg_addr
, size
);
2496 /* For non-quad operations, setting a slice of the low
2497 * 64 bits of the register clears the high 64 bits (in
2498 * the ARM ARM pseudocode this is implicit in the fact
2499 * that 'rval' is a 64 bit wide variable). We optimize
2500 * by noticing that we only need to do this the first
2501 * time we touch a register.
2503 if (!is_q
&& e
== 0 && (r
== 0 || xs
== selem
- 1)) {
2504 clear_vec_high(s
, tt
);
2507 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, ebytes
);
2514 int rm
= extract32(insn
, 16, 5);
2516 tcg_gen_mov_i64(tcg_rn
, tcg_addr
);
2518 tcg_gen_add_i64(tcg_rn
, tcg_rn
, cpu_reg(s
, rm
));
2521 tcg_temp_free_i64(tcg_addr
);
2524 /* C3.3.3 AdvSIMD load/store single structure
2526 * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
2527 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2528 * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size | Rn | Rt |
2529 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2531 * C3.3.4 AdvSIMD load/store single structure (post-indexed)
2533 * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
2534 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2535 * | 0 | Q | 0 0 1 1 0 1 1 | L R | Rm | opc | S | size | Rn | Rt |
2536 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2538 * Rt: first (or only) SIMD&FP register to be transferred
2539 * Rn: base address or SP
2540 * Rm (post-index only): post-index register (when !31) or size dependent #imm
2541 * index = encoded in Q:S:size dependent on size
2543 * lane_size = encoded in R, opc
2544 * transfer width = encoded in opc, S, size
2546 static void disas_ldst_single_struct(DisasContext
*s
, uint32_t insn
)
2548 int rt
= extract32(insn
, 0, 5);
2549 int rn
= extract32(insn
, 5, 5);
2550 int size
= extract32(insn
, 10, 2);
2551 int S
= extract32(insn
, 12, 1);
2552 int opc
= extract32(insn
, 13, 3);
2553 int R
= extract32(insn
, 21, 1);
2554 int is_load
= extract32(insn
, 22, 1);
2555 int is_postidx
= extract32(insn
, 23, 1);
2556 int is_q
= extract32(insn
, 30, 1);
2558 int scale
= extract32(opc
, 1, 2);
2559 int selem
= (extract32(opc
, 0, 1) << 1 | R
) + 1;
2560 bool replicate
= false;
2561 int index
= is_q
<< 3 | S
<< 2 | size
;
2563 TCGv_i64 tcg_addr
, tcg_rn
;
2567 if (!is_load
|| S
) {
2568 unallocated_encoding(s
);
2577 if (extract32(size
, 0, 1)) {
2578 unallocated_encoding(s
);
2584 if (extract32(size
, 1, 1)) {
2585 unallocated_encoding(s
);
2588 if (!extract32(size
, 0, 1)) {
2592 unallocated_encoding(s
);
2600 g_assert_not_reached();
2603 if (!fp_access_check(s
)) {
2607 ebytes
= 1 << scale
;
2610 gen_check_sp_alignment(s
);
2613 tcg_rn
= cpu_reg_sp(s
, rn
);
2614 tcg_addr
= tcg_temp_new_i64();
2615 tcg_gen_mov_i64(tcg_addr
, tcg_rn
);
2617 for (xs
= 0; xs
< selem
; xs
++) {
2619 /* Load and replicate to all elements */
2621 TCGv_i64 tcg_tmp
= tcg_temp_new_i64();
2623 tcg_gen_qemu_ld_i64(tcg_tmp
, tcg_addr
,
2624 get_mem_index(s
), s
->be_data
+ scale
);
2627 mulconst
= 0x0101010101010101ULL
;
2630 mulconst
= 0x0001000100010001ULL
;
2633 mulconst
= 0x0000000100000001ULL
;
2639 g_assert_not_reached();
2642 tcg_gen_muli_i64(tcg_tmp
, tcg_tmp
, mulconst
);
2644 write_vec_element(s
, tcg_tmp
, rt
, 0, MO_64
);
2646 write_vec_element(s
, tcg_tmp
, rt
, 1, MO_64
);
2648 clear_vec_high(s
, rt
);
2650 tcg_temp_free_i64(tcg_tmp
);
2652 /* Load/store one element per register */
2654 do_vec_ld(s
, rt
, index
, tcg_addr
, s
->be_data
+ scale
);
2656 do_vec_st(s
, rt
, index
, tcg_addr
, s
->be_data
+ scale
);
2659 tcg_gen_addi_i64(tcg_addr
, tcg_addr
, ebytes
);
2664 int rm
= extract32(insn
, 16, 5);
2666 tcg_gen_mov_i64(tcg_rn
, tcg_addr
);
2668 tcg_gen_add_i64(tcg_rn
, tcg_rn
, cpu_reg(s
, rm
));
2671 tcg_temp_free_i64(tcg_addr
);
2674 /* C3.3 Loads and stores */
2675 static void disas_ldst(DisasContext
*s
, uint32_t insn
)
2677 switch (extract32(insn
, 24, 6)) {
2678 case 0x08: /* Load/store exclusive */
2679 disas_ldst_excl(s
, insn
);
2681 case 0x18: case 0x1c: /* Load register (literal) */
2682 disas_ld_lit(s
, insn
);
2684 case 0x28: case 0x29:
2685 case 0x2c: case 0x2d: /* Load/store pair (all forms) */
2686 disas_ldst_pair(s
, insn
);
2688 case 0x38: case 0x39:
2689 case 0x3c: case 0x3d: /* Load/store register (all forms) */
2690 disas_ldst_reg(s
, insn
);
2692 case 0x0c: /* AdvSIMD load/store multiple structures */
2693 disas_ldst_multiple_struct(s
, insn
);
2695 case 0x0d: /* AdvSIMD load/store single structure */
2696 disas_ldst_single_struct(s
, insn
);
2699 unallocated_encoding(s
);
2704 /* C3.4.6 PC-rel. addressing
2705 * 31 30 29 28 24 23 5 4 0
2706 * +----+-------+-----------+-------------------+------+
2707 * | op | immlo | 1 0 0 0 0 | immhi | Rd |
2708 * +----+-------+-----------+-------------------+------+
2710 static void disas_pc_rel_adr(DisasContext
*s
, uint32_t insn
)
2712 unsigned int page
, rd
;
2716 page
= extract32(insn
, 31, 1);
2717 /* SignExtend(immhi:immlo) -> offset */
2718 offset
= sextract64(insn
, 5, 19);
2719 offset
= offset
<< 2 | extract32(insn
, 29, 2);
2720 rd
= extract32(insn
, 0, 5);
2724 /* ADRP (page based) */
2729 tcg_gen_movi_i64(cpu_reg(s
, rd
), base
+ offset
);
2733 * C3.4.1 Add/subtract (immediate)
2735 * 31 30 29 28 24 23 22 21 10 9 5 4 0
2736 * +--+--+--+-----------+-----+-------------+-----+-----+
2737 * |sf|op| S| 1 0 0 0 1 |shift| imm12 | Rn | Rd |
2738 * +--+--+--+-----------+-----+-------------+-----+-----+
2740 * sf: 0 -> 32bit, 1 -> 64bit
2741 * op: 0 -> add , 1 -> sub
2743 * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
2745 static void disas_add_sub_imm(DisasContext
*s
, uint32_t insn
)
2747 int rd
= extract32(insn
, 0, 5);
2748 int rn
= extract32(insn
, 5, 5);
2749 uint64_t imm
= extract32(insn
, 10, 12);
2750 int shift
= extract32(insn
, 22, 2);
2751 bool setflags
= extract32(insn
, 29, 1);
2752 bool sub_op
= extract32(insn
, 30, 1);
2753 bool is_64bit
= extract32(insn
, 31, 1);
2755 TCGv_i64 tcg_rn
= cpu_reg_sp(s
, rn
);
2756 TCGv_i64 tcg_rd
= setflags ?
cpu_reg(s
, rd
) : cpu_reg_sp(s
, rd
);
2757 TCGv_i64 tcg_result
;
2766 unallocated_encoding(s
);
2770 tcg_result
= tcg_temp_new_i64();
2773 tcg_gen_subi_i64(tcg_result
, tcg_rn
, imm
);
2775 tcg_gen_addi_i64(tcg_result
, tcg_rn
, imm
);
2778 TCGv_i64 tcg_imm
= tcg_const_i64(imm
);
2780 gen_sub_CC(is_64bit
, tcg_result
, tcg_rn
, tcg_imm
);
2782 gen_add_CC(is_64bit
, tcg_result
, tcg_rn
, tcg_imm
);
2784 tcg_temp_free_i64(tcg_imm
);
2788 tcg_gen_mov_i64(tcg_rd
, tcg_result
);
2790 tcg_gen_ext32u_i64(tcg_rd
, tcg_result
);
2793 tcg_temp_free_i64(tcg_result
);
2796 /* The input should be a value in the bottom e bits (with higher
2797 * bits zero); returns that value replicated into every element
2798 * of size e in a 64 bit integer.
2800 static uint64_t bitfield_replicate(uint64_t mask
, unsigned int e
)
2810 /* Return a value with the bottom len bits set (where 0 < len <= 64) */
2811 static inline uint64_t bitmask64(unsigned int length
)
2813 assert(length
> 0 && length
<= 64);
2814 return ~0ULL >> (64 - length
);
2817 /* Simplified variant of pseudocode DecodeBitMasks() for the case where we
2818 * only require the wmask. Returns false if the imms/immr/immn are a reserved
2819 * value (ie should cause a guest UNDEF exception), and true if they are
2820 * valid, in which case the decoded bit pattern is written to result.
2822 static bool logic_imm_decode_wmask(uint64_t *result
, unsigned int immn
,
2823 unsigned int imms
, unsigned int immr
)
2826 unsigned e
, levels
, s
, r
;
2829 assert(immn
< 2 && imms
< 64 && immr
< 64);
2831 /* The bit patterns we create here are 64 bit patterns which
2832 * are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
2833 * 64 bits each. Each element contains the same value: a run
2834 * of between 1 and e-1 non-zero bits, rotated within the
2835 * element by between 0 and e-1 bits.
2837 * The element size and run length are encoded into immn (1 bit)
2838 * and imms (6 bits) as follows:
2839 * 64 bit elements: immn = 1, imms = <length of run - 1>
2840 * 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
2841 * 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
2842 * 8 bit elements: immn = 0, imms = 110 : <length of run - 1>
2843 * 4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
2844 * 2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
2845 * Notice that immn = 0, imms = 11111x is the only combination
2846 * not covered by one of the above options; this is reserved.
2847 * Further, <length of run - 1> all-ones is a reserved pattern.
2849 * In all cases the rotation is by immr % e (and immr is 6 bits).
2852 /* First determine the element size */
2853 len
= 31 - clz32((immn
<< 6) | (~imms
& 0x3f));
2855 /* This is the immn == 0, imms == 0x11111x case */
2865 /* <length of run - 1> mustn't be all-ones. */
2869 /* Create the value of one element: s+1 set bits rotated
2870 * by r within the element (which is e bits wide)...
2872 mask
= bitmask64(s
+ 1);
2874 mask
= (mask
>> r
) | (mask
<< (e
- r
));
2875 mask
&= bitmask64(e
);
2877 /* ...then replicate the element over the whole 64 bit value */
2878 mask
= bitfield_replicate(mask
, e
);
2883 /* C3.4.4 Logical (immediate)
2884 * 31 30 29 28 23 22 21 16 15 10 9 5 4 0
2885 * +----+-----+-------------+---+------+------+------+------+
2886 * | sf | opc | 1 0 0 1 0 0 | N | immr | imms | Rn | Rd |
2887 * +----+-----+-------------+---+------+------+------+------+
2889 static void disas_logic_imm(DisasContext
*s
, uint32_t insn
)
2891 unsigned int sf
, opc
, is_n
, immr
, imms
, rn
, rd
;
2892 TCGv_i64 tcg_rd
, tcg_rn
;
2894 bool is_and
= false;
2896 sf
= extract32(insn
, 31, 1);
2897 opc
= extract32(insn
, 29, 2);
2898 is_n
= extract32(insn
, 22, 1);
2899 immr
= extract32(insn
, 16, 6);
2900 imms
= extract32(insn
, 10, 6);
2901 rn
= extract32(insn
, 5, 5);
2902 rd
= extract32(insn
, 0, 5);
2905 unallocated_encoding(s
);
2909 if (opc
== 0x3) { /* ANDS */
2910 tcg_rd
= cpu_reg(s
, rd
);
2912 tcg_rd
= cpu_reg_sp(s
, rd
);
2914 tcg_rn
= cpu_reg(s
, rn
);
2916 if (!logic_imm_decode_wmask(&wmask
, is_n
, imms
, immr
)) {
2917 /* some immediate field values are reserved */
2918 unallocated_encoding(s
);
2923 wmask
&= 0xffffffff;
2927 case 0x3: /* ANDS */
2929 tcg_gen_andi_i64(tcg_rd
, tcg_rn
, wmask
);
2933 tcg_gen_ori_i64(tcg_rd
, tcg_rn
, wmask
);
2936 tcg_gen_xori_i64(tcg_rd
, tcg_rn
, wmask
);
2939 assert(FALSE
); /* must handle all above */
2943 if (!sf
&& !is_and
) {
2944 /* zero extend final result; we know we can skip this for AND
2945 * since the immediate had the high 32 bits clear.
2947 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
2950 if (opc
== 3) { /* ANDS */
2951 gen_logic_CC(sf
, tcg_rd
);
2956 * C3.4.5 Move wide (immediate)
2958 * 31 30 29 28 23 22 21 20 5 4 0
2959 * +--+-----+-------------+-----+----------------+------+
2960 * |sf| opc | 1 0 0 1 0 1 | hw | imm16 | Rd |
2961 * +--+-----+-------------+-----+----------------+------+
2963 * sf: 0 -> 32 bit, 1 -> 64 bit
2964 * opc: 00 -> N, 10 -> Z, 11 -> K
2965 * hw: shift/16 (0,16, and sf only 32, 48)
2967 static void disas_movw_imm(DisasContext
*s
, uint32_t insn
)
2969 int rd
= extract32(insn
, 0, 5);
2970 uint64_t imm
= extract32(insn
, 5, 16);
2971 int sf
= extract32(insn
, 31, 1);
2972 int opc
= extract32(insn
, 29, 2);
2973 int pos
= extract32(insn
, 21, 2) << 4;
2974 TCGv_i64 tcg_rd
= cpu_reg(s
, rd
);
2977 if (!sf
&& (pos
>= 32)) {
2978 unallocated_encoding(s
);
2992 tcg_gen_movi_i64(tcg_rd
, imm
);
2995 tcg_imm
= tcg_const_i64(imm
);
2996 tcg_gen_deposit_i64(tcg_rd
, tcg_rd
, tcg_imm
, pos
, 16);
2997 tcg_temp_free_i64(tcg_imm
);
2999 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
3003 unallocated_encoding(s
);
3009 * 31 30 29 28 23 22 21 16 15 10 9 5 4 0
3010 * +----+-----+-------------+---+------+------+------+------+
3011 * | sf | opc | 1 0 0 1 1 0 | N | immr | imms | Rn | Rd |
3012 * +----+-----+-------------+---+------+------+------+------+
3014 static void disas_bitfield(DisasContext
*s
, uint32_t insn
)
3016 unsigned int sf
, n
, opc
, ri
, si
, rn
, rd
, bitsize
, pos
, len
;
3017 TCGv_i64 tcg_rd
, tcg_tmp
;
3019 sf
= extract32(insn
, 31, 1);
3020 opc
= extract32(insn
, 29, 2);
3021 n
= extract32(insn
, 22, 1);
3022 ri
= extract32(insn
, 16, 6);
3023 si
= extract32(insn
, 10, 6);
3024 rn
= extract32(insn
, 5, 5);
3025 rd
= extract32(insn
, 0, 5);
3026 bitsize
= sf ?
64 : 32;
3028 if (sf
!= n
|| ri
>= bitsize
|| si
>= bitsize
|| opc
> 2) {
3029 unallocated_encoding(s
);
3033 tcg_rd
= cpu_reg(s
, rd
);
3035 /* Suppress the zero-extend for !sf. Since RI and SI are constrained
3036 to be smaller than bitsize, we'll never reference data outside the
3037 low 32-bits anyway. */
3038 tcg_tmp
= read_cpu_reg(s
, rn
, 1);
3040 /* Recognize the common aliases. */
3041 if (opc
== 0) { /* SBFM */
3043 if (si
== 7) { /* SXTB */
3044 tcg_gen_ext8s_i64(tcg_rd
, tcg_tmp
);
3046 } else if (si
== 15) { /* SXTH */
3047 tcg_gen_ext16s_i64(tcg_rd
, tcg_tmp
);
3049 } else if (si
== 31) { /* SXTW */
3050 tcg_gen_ext32s_i64(tcg_rd
, tcg_tmp
);
3054 if (si
== 63 || (si
== 31 && ri
<= si
)) { /* ASR */
3056 tcg_gen_ext32s_i64(tcg_tmp
, tcg_tmp
);
3058 tcg_gen_sari_i64(tcg_rd
, tcg_tmp
, ri
);
3061 } else if (opc
== 2) { /* UBFM */
3062 if (ri
== 0) { /* UXTB, UXTH, plus non-canonical AND */
3063 tcg_gen_andi_i64(tcg_rd
, tcg_tmp
, bitmask64(si
+ 1));
3066 if (si
== 63 || (si
== 31 && ri
<= si
)) { /* LSR */
3068 tcg_gen_ext32u_i64(tcg_tmp
, tcg_tmp
);
3070 tcg_gen_shri_i64(tcg_rd
, tcg_tmp
, ri
);
3073 if (si
+ 1 == ri
&& si
!= bitsize
- 1) { /* LSL */
3074 int shift
= bitsize
- 1 - si
;
3075 tcg_gen_shli_i64(tcg_rd
, tcg_tmp
, shift
);
3080 if (opc
!= 1) { /* SBFM or UBFM */
3081 tcg_gen_movi_i64(tcg_rd
, 0);
3084 /* do the bit move operation */
3086 /* Wd<s-r:0> = Wn<s:r> */
3087 tcg_gen_shri_i64(tcg_tmp
, tcg_tmp
, ri
);
3089 len
= (si
- ri
) + 1;
3091 /* Wd<32+s-r,32-r> = Wn<s:0> */
3096 tcg_gen_deposit_i64(tcg_rd
, tcg_rd
, tcg_tmp
, pos
, len
);
3098 if (opc
== 0) { /* SBFM - sign extend the destination field */
3099 tcg_gen_shli_i64(tcg_rd
, tcg_rd
, 64 - (pos
+ len
));
3100 tcg_gen_sari_i64(tcg_rd
, tcg_rd
, 64 - (pos
+ len
));
3104 if (!sf
) { /* zero extend final result */
3105 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
3110 * 31 30 29 28 23 22 21 20 16 15 10 9 5 4 0
3111 * +----+------+-------------+---+----+------+--------+------+------+
3112 * | sf | op21 | 1 0 0 1 1 1 | N | o0 | Rm | imms | Rn | Rd |
3113 * +----+------+-------------+---+----+------+--------+------+------+
3115 static void disas_extract(DisasContext
*s
, uint32_t insn
)
3117 unsigned int sf
, n
, rm
, imm
, rn
, rd
, bitsize
, op21
, op0
;
3119 sf
= extract32(insn
, 31, 1);
3120 n
= extract32(insn
, 22, 1);
3121 rm
= extract32(insn
, 16, 5);
3122 imm
= extract32(insn
, 10, 6);
3123 rn
= extract32(insn
, 5, 5);
3124 rd
= extract32(insn
, 0, 5);
3125 op21
= extract32(insn
, 29, 2);
3126 op0
= extract32(insn
, 21, 1);
3127 bitsize
= sf ?
64 : 32;
3129 if (sf
!= n
|| op21
|| op0
|| imm
>= bitsize
) {
3130 unallocated_encoding(s
);
3132 TCGv_i64 tcg_rd
, tcg_rm
, tcg_rn
;
3134 tcg_rd
= cpu_reg(s
, rd
);
3136 if (unlikely(imm
== 0)) {
3137 /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
3138 * so an extract from bit 0 is a special case.
3141 tcg_gen_mov_i64(tcg_rd
, cpu_reg(s
, rm
));
3143 tcg_gen_ext32u_i64(tcg_rd
, cpu_reg(s
, rm
));
3145 } else if (rm
== rn
) { /* ROR */
3146 tcg_rm
= cpu_reg(s
, rm
);
3148 tcg_gen_rotri_i64(tcg_rd
, tcg_rm
, imm
);
3150 TCGv_i32 tmp
= tcg_temp_new_i32();
3151 tcg_gen_extrl_i64_i32(tmp
, tcg_rm
);
3152 tcg_gen_rotri_i32(tmp
, tmp
, imm
);
3153 tcg_gen_extu_i32_i64(tcg_rd
, tmp
);
3154 tcg_temp_free_i32(tmp
);
3157 tcg_rm
= read_cpu_reg(s
, rm
, sf
);
3158 tcg_rn
= read_cpu_reg(s
, rn
, sf
);
3159 tcg_gen_shri_i64(tcg_rm
, tcg_rm
, imm
);
3160 tcg_gen_shli_i64(tcg_rn
, tcg_rn
, bitsize
- imm
);
3161 tcg_gen_or_i64(tcg_rd
, tcg_rm
, tcg_rn
);
3163 tcg_gen_ext32u_i64(tcg_rd
, tcg_rd
);
3169 /* C3.4 Data processing - immediate */
3170 static void disas_data_proc_imm(DisasContext
*s
, uint32_t insn
)
3172 switch (extract32(insn
, 23, 6)) {
3173 case 0x20: case 0x21: /* PC-rel. addressing */
3174 disas_pc_rel_adr(s
, insn
);
3176 case 0x22: case 0x23: /* Add/subtract (immediate) */
3177 disas_add_sub_imm(s
, insn
);
3179 case 0x24: /* Logical (immediate) */
3180 disas_logic_imm(s
, insn
);
3182 case 0x25: /* Move wide (immediate) */
3183 disas_movw_imm(s
, insn
);
3185 case 0x26: /* Bitfield */
3186 disas_bitfield(s
, insn
);
3188 case 0x27: /* Extract */
3189 disas_extract(s
, insn
);
3192 unallocated_encoding(s
);
3197 /* Shift a TCGv src by TCGv shift_amount, put result in dst.
3198 * Note that it is the caller's responsibility to ensure that the
3199 * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
3200 * mandated semantics for out of range shifts.
3202 static void shift_reg(TCGv_i64 dst
, TCGv_i64 src
, int sf
,
3203 enum a64_shift_type shift_type
, TCGv_i64 shift_amount
)
3205 switch (shift_type
) {
3206 case A64_SHIFT_TYPE_LSL
:
3207 tcg_gen_shl_i64(dst
, src
, shift_amount
);
3209 case A64_SHIFT_TYPE_LSR
:
3210 tcg_gen_shr_i64(dst
, src
, shift_amount
);
3212 case A64_SHIFT_TYPE_ASR
:
3214 tcg_gen_ext32s_i64(dst
, src
);
3216 tcg_gen_sar_i64(dst
, sf ? src
: dst
, shift_amount
);