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
/* initialize TCG globals. */
76
void a64_translate_init(void)
80
cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
81
offsetof(CPUARMState, pc),
83
for (i = 0; i < 32; i++) {
84
cpu_X[i] = tcg_global_mem_new_i64(TCG_AREG0,
85
offsetof(CPUARMState, xregs[i]),
89
cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
90
cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
91
cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
92
cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
94
cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
95
offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
96
cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
97
offsetof(CPUARMState, exclusive_val), "exclusive_val");
98
cpu_exclusive_high = tcg_global_mem_new_i64(TCG_AREG0,
99
offsetof(CPUARMState, exclusive_high), "exclusive_high");
100
#ifdef CONFIG_USER_ONLY
101
cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
102
offsetof(CPUARMState, exclusive_test), "exclusive_test");
103
cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
104
offsetof(CPUARMState, exclusive_info), "exclusive_info");
108
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
109
fprintf_function cpu_fprintf, int flags)
111
ARMCPU *cpu = ARM_CPU(cs);
112
CPUARMState *env = &cpu->env;
113
uint32_t psr = pstate_read(env);
116
cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n",
117
env->pc, env->xregs[31]);
118
for (i = 0; i < 31; i++) {
119
cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
121
cpu_fprintf(f, "\n");
126
cpu_fprintf(f, "PSTATE=%08x (flags %c%c%c%c)\n",
128
psr & PSTATE_N ? 'N' : '-',
129
psr & PSTATE_Z ? 'Z' : '-',
130
psr & PSTATE_C ? 'C' : '-',
131
psr & PSTATE_V ? 'V' : '-');
132
cpu_fprintf(f, "\n");
134
if (flags & CPU_DUMP_FPU) {
136
for (i = 0; i < numvfpregs; i += 2) {
137
uint64_t vlo = float64_val(env->vfp.regs[i * 2]);
138
uint64_t vhi = float64_val(env->vfp.regs[(i * 2) + 1]);
139
cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
141
vlo = float64_val(env->vfp.regs[(i + 1) * 2]);
142
vhi = float64_val(env->vfp.regs[((i + 1) * 2) + 1]);
143
cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
146
cpu_fprintf(f, "FPCR: %08x FPSR: %08x\n",
147
vfp_get_fpcr(env), vfp_get_fpsr(env));
151
static int get_mem_index(DisasContext *s)
153
#ifdef CONFIG_USER_ONLY
160
void gen_a64_set_pc_im(uint64_t val)
162
tcg_gen_movi_i64(cpu_pc, val);
165
static void gen_exception(int excp)
167
TCGv_i32 tmp = tcg_temp_new_i32();
168
tcg_gen_movi_i32(tmp, excp);
169
gen_helper_exception(cpu_env, tmp);
170
tcg_temp_free_i32(tmp);
173
static void gen_exception_insn(DisasContext *s, int offset, int excp)
175
gen_a64_set_pc_im(s->pc - offset);
177
s->is_jmp = DISAS_EXC;
180
static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
182
/* No direct tb linking with singlestep or deterministic io */
183
if (s->singlestep_enabled || (s->tb->cflags & CF_LAST_IO)) {
187
/* Only link tbs from inside the same guest page */
188
if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
195
static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
197
TranslationBlock *tb;
200
if (use_goto_tb(s, n, dest)) {
202
gen_a64_set_pc_im(dest);
203
tcg_gen_exit_tb((tcg_target_long)tb + n);
204
s->is_jmp = DISAS_TB_JUMP;
206
gen_a64_set_pc_im(dest);
207
if (s->singlestep_enabled) {
208
gen_exception(EXCP_DEBUG);
211
s->is_jmp = DISAS_JUMP;
215
static void unallocated_encoding(DisasContext *s)
217
gen_exception_insn(s, 4, EXCP_UDEF);
220
#define unsupported_encoding(s, insn) \
222
qemu_log_mask(LOG_UNIMP, \
223
"%s:%d: unsupported instruction encoding 0x%08x " \
224
"at pc=%016" PRIx64 "\n", \
225
__FILE__, __LINE__, insn, s->pc - 4); \
226
unallocated_encoding(s); \
229
static void init_tmp_a64_array(DisasContext *s)
231
#ifdef CONFIG_DEBUG_TCG
233
for (i = 0; i < ARRAY_SIZE(s->tmp_a64); i++) {
234
TCGV_UNUSED_I64(s->tmp_a64[i]);
237
s->tmp_a64_count = 0;
240
static void free_tmp_a64(DisasContext *s)
243
for (i = 0; i < s->tmp_a64_count; i++) {
244
tcg_temp_free_i64(s->tmp_a64[i]);
246
init_tmp_a64_array(s);
249
static TCGv_i64 new_tmp_a64(DisasContext *s)
251
assert(s->tmp_a64_count < TMP_A64_MAX);
252
return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
255
static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
257
TCGv_i64 t = new_tmp_a64(s);
258
tcg_gen_movi_i64(t, 0);
263
* Register access functions
265
* These functions are used for directly accessing a register in where
266
* changes to the final register value are likely to be made. If you
267
* need to use a register for temporary calculation (e.g. index type
268
* operations) use the read_* form.
270
* B1.2.1 Register mappings
272
* In instruction register encoding 31 can refer to ZR (zero register) or
273
* the SP (stack pointer) depending on context. In QEMU's case we map SP
274
* to cpu_X[31] and ZR accesses to a temporary which can be discarded.
275
* This is the point of the _sp forms.
277
static TCGv_i64 cpu_reg(DisasContext *s, int reg)
280
return new_tmp_a64_zero(s);
286
/* register access for when 31 == SP */
287
static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
292
/* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
293
* representing the register contents. This TCGv is an auto-freed
294
* temporary so it need not be explicitly freed, and may be modified.
296
static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
298
TCGv_i64 v = new_tmp_a64(s);
301
tcg_gen_mov_i64(v, cpu_X[reg]);
303
tcg_gen_ext32u_i64(v, cpu_X[reg]);
306
tcg_gen_movi_i64(v, 0);
311
static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
313
TCGv_i64 v = new_tmp_a64(s);
315
tcg_gen_mov_i64(v, cpu_X[reg]);
317
tcg_gen_ext32u_i64(v, cpu_X[reg]);
322
/* Return the offset into CPUARMState of an element of specified
323
* size, 'element' places in from the least significant end of
324
* the FP/vector register Qn.
326
static inline int vec_reg_offset(int regno, int element, TCGMemOp size)
328
int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
329
#ifdef HOST_WORDS_BIGENDIAN
330
/* This is complicated slightly because vfp.regs[2n] is
331
* still the low half and vfp.regs[2n+1] the high half
332
* of the 128 bit vector, even on big endian systems.
333
* Calculate the offset assuming a fully bigendian 128 bits,
334
* then XOR to account for the order of the two 64 bit halves.
336
offs += (16 - ((element + 1) * (1 << size)));
339
offs += element * (1 << size);
344
/* Return the offset into CPUARMState of a slice (from
345
* the least significant end) of FP register Qn (ie
347
* (Note that this is not the same mapping as for A32; see cpu.h)
349
static inline int fp_reg_offset(int regno, TCGMemOp size)
351
int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
352
#ifdef HOST_WORDS_BIGENDIAN
353
offs += (8 - (1 << size));
358
/* Offset of the high half of the 128 bit vector Qn */
359
static inline int fp_reg_hi_offset(int regno)
361
return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
364
/* Convenience accessors for reading and writing single and double
365
* FP registers. Writing clears the upper parts of the associated
366
* 128 bit vector register, as required by the architecture.
367
* Note that unlike the GP register accessors, the values returned
368
* by the read functions must be manually freed.
370
static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
372
TCGv_i64 v = tcg_temp_new_i64();
374
tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
378
static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
380
TCGv_i32 v = tcg_temp_new_i32();
382
tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(reg, MO_32));
386
static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
388
TCGv_i64 tcg_zero = tcg_const_i64(0);
390
tcg_gen_st_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
391
tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(reg));
392
tcg_temp_free_i64(tcg_zero);
395
static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
397
TCGv_i64 tmp = tcg_temp_new_i64();
399
tcg_gen_extu_i32_i64(tmp, v);
400
write_fp_dreg(s, reg, tmp);
401
tcg_temp_free_i64(tmp);
404
static TCGv_ptr get_fpstatus_ptr(void)
406
TCGv_ptr statusptr = tcg_temp_new_ptr();
409
/* In A64 all instructions (both FP and Neon) use the FPCR;
410
* there is no equivalent of the A32 Neon "standard FPSCR value"
411
* and all operations use vfp.fp_status.
413
offset = offsetof(CPUARMState, vfp.fp_status);
414
tcg_gen_addi_ptr(statusptr, cpu_env, offset);
418
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
419
* than the 32 bit equivalent.
421
static inline void gen_set_NZ64(TCGv_i64 result)
423
TCGv_i64 flag = tcg_temp_new_i64();
425
tcg_gen_setcondi_i64(TCG_COND_NE, flag, result, 0);
426
tcg_gen_trunc_i64_i32(cpu_ZF, flag);
427
tcg_gen_shri_i64(flag, result, 32);
428
tcg_gen_trunc_i64_i32(cpu_NF, flag);
429
tcg_temp_free_i64(flag);
432
/* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
433
static inline void gen_logic_CC(int sf, TCGv_i64 result)
436
gen_set_NZ64(result);
438
tcg_gen_trunc_i64_i32(cpu_ZF, result);
439
tcg_gen_trunc_i64_i32(cpu_NF, result);
441
tcg_gen_movi_i32(cpu_CF, 0);
442
tcg_gen_movi_i32(cpu_VF, 0);
445
/* dest = T0 + T1; compute C, N, V and Z flags */
446
static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
449
TCGv_i64 result, flag, tmp;
450
result = tcg_temp_new_i64();
451
flag = tcg_temp_new_i64();
452
tmp = tcg_temp_new_i64();
454
tcg_gen_movi_i64(tmp, 0);
455
tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
457
tcg_gen_trunc_i64_i32(cpu_CF, flag);
459
gen_set_NZ64(result);
461
tcg_gen_xor_i64(flag, result, t0);
462
tcg_gen_xor_i64(tmp, t0, t1);
463
tcg_gen_andc_i64(flag, flag, tmp);
464
tcg_temp_free_i64(tmp);
465
tcg_gen_shri_i64(flag, flag, 32);
466
tcg_gen_trunc_i64_i32(cpu_VF, flag);
468
tcg_gen_mov_i64(dest, result);
469
tcg_temp_free_i64(result);
470
tcg_temp_free_i64(flag);
472
/* 32 bit arithmetic */
473
TCGv_i32 t0_32 = tcg_temp_new_i32();
474
TCGv_i32 t1_32 = tcg_temp_new_i32();
475
TCGv_i32 tmp = tcg_temp_new_i32();
477
tcg_gen_movi_i32(tmp, 0);
478
tcg_gen_trunc_i64_i32(t0_32, t0);
479
tcg_gen_trunc_i64_i32(t1_32, t1);
480
tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
481
tcg_gen_mov_i32(cpu_ZF, cpu_NF);
482
tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
483
tcg_gen_xor_i32(tmp, t0_32, t1_32);
484
tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
485
tcg_gen_extu_i32_i64(dest, cpu_NF);
487
tcg_temp_free_i32(tmp);
488
tcg_temp_free_i32(t0_32);
489
tcg_temp_free_i32(t1_32);
493
/* dest = T0 - T1; compute C, N, V and Z flags */
494
static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
497
/* 64 bit arithmetic */
498
TCGv_i64 result, flag, tmp;
500
result = tcg_temp_new_i64();
501
flag = tcg_temp_new_i64();
502
tcg_gen_sub_i64(result, t0, t1);
504
gen_set_NZ64(result);
506
tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
507
tcg_gen_trunc_i64_i32(cpu_CF, flag);
509
tcg_gen_xor_i64(flag, result, t0);
510
tmp = tcg_temp_new_i64();
511
tcg_gen_xor_i64(tmp, t0, t1);
512
tcg_gen_and_i64(flag, flag, tmp);
513
tcg_temp_free_i64(tmp);
514
tcg_gen_shri_i64(flag, flag, 32);
515
tcg_gen_trunc_i64_i32(cpu_VF, flag);
516
tcg_gen_mov_i64(dest, result);
517
tcg_temp_free_i64(flag);
518
tcg_temp_free_i64(result);
520
/* 32 bit arithmetic */
521
TCGv_i32 t0_32 = tcg_temp_new_i32();
522
TCGv_i32 t1_32 = tcg_temp_new_i32();
525
tcg_gen_trunc_i64_i32(t0_32, t0);
526
tcg_gen_trunc_i64_i32(t1_32, t1);
527
tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
528
tcg_gen_mov_i32(cpu_ZF, cpu_NF);
529
tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
530
tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
531
tmp = tcg_temp_new_i32();
532
tcg_gen_xor_i32(tmp, t0_32, t1_32);
533
tcg_temp_free_i32(t0_32);
534
tcg_temp_free_i32(t1_32);
535
tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
536
tcg_temp_free_i32(tmp);
537
tcg_gen_extu_i32_i64(dest, cpu_NF);
541
/* dest = T0 + T1 + CF; do not compute flags. */
542
static void gen_adc(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
544
TCGv_i64 flag = tcg_temp_new_i64();
545
tcg_gen_extu_i32_i64(flag, cpu_CF);
546
tcg_gen_add_i64(dest, t0, t1);
547
tcg_gen_add_i64(dest, dest, flag);
548
tcg_temp_free_i64(flag);
551
tcg_gen_ext32u_i64(dest, dest);
555
/* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
556
static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
559
TCGv_i64 result, cf_64, vf_64, tmp;
560
result = tcg_temp_new_i64();
561
cf_64 = tcg_temp_new_i64();
562
vf_64 = tcg_temp_new_i64();
563
tmp = tcg_const_i64(0);
565
tcg_gen_extu_i32_i64(cf_64, cpu_CF);
566
tcg_gen_add2_i64(result, cf_64, t0, tmp, cf_64, tmp);
567
tcg_gen_add2_i64(result, cf_64, result, cf_64, t1, tmp);
568
tcg_gen_trunc_i64_i32(cpu_CF, cf_64);
569
gen_set_NZ64(result);
571
tcg_gen_xor_i64(vf_64, result, t0);
572
tcg_gen_xor_i64(tmp, t0, t1);
573
tcg_gen_andc_i64(vf_64, vf_64, tmp);
574
tcg_gen_shri_i64(vf_64, vf_64, 32);
575
tcg_gen_trunc_i64_i32(cpu_VF, vf_64);
577
tcg_gen_mov_i64(dest, result);
579
tcg_temp_free_i64(tmp);
580
tcg_temp_free_i64(vf_64);
581
tcg_temp_free_i64(cf_64);
582
tcg_temp_free_i64(result);
584
TCGv_i32 t0_32, t1_32, tmp;
585
t0_32 = tcg_temp_new_i32();
586
t1_32 = tcg_temp_new_i32();
587
tmp = tcg_const_i32(0);
589
tcg_gen_trunc_i64_i32(t0_32, t0);
590
tcg_gen_trunc_i64_i32(t1_32, t1);
591
tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, cpu_CF, tmp);
592
tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1_32, tmp);
594
tcg_gen_mov_i32(cpu_ZF, cpu_NF);
595
tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
596
tcg_gen_xor_i32(tmp, t0_32, t1_32);
597
tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
598
tcg_gen_extu_i32_i64(dest, cpu_NF);
600
tcg_temp_free_i32(tmp);
601
tcg_temp_free_i32(t1_32);
602
tcg_temp_free_i32(t0_32);
607
* Load/Store generators
611
* Store from GPR register to memory
613
static void do_gpr_st(DisasContext *s, TCGv_i64 source,
614
TCGv_i64 tcg_addr, int size)
617
tcg_gen_qemu_st_i64(source, tcg_addr, get_mem_index(s), MO_TE + size);
621
* Load from memory to GPR register
623
static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
624
int size, bool is_signed, bool extend)
626
TCGMemOp memop = MO_TE + size;
634
tcg_gen_qemu_ld_i64(dest, tcg_addr, get_mem_index(s), memop);
636
if (extend && is_signed) {
638
tcg_gen_ext32u_i64(dest, dest);
643
* Store from FP register to memory
645
static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
647
/* This writes the bottom N bits of a 128 bit wide vector to memory */
648
TCGv_i64 tmp = tcg_temp_new_i64();
649
tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_64));
651
tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
653
TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
654
tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
655
tcg_gen_qemu_st64(tmp, tcg_addr, get_mem_index(s));
656
tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(srcidx));
657
tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
658
tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
659
tcg_temp_free_i64(tcg_hiaddr);
662
tcg_temp_free_i64(tmp);
666
* Load from memory to FP register
668
static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
670
/* This always zero-extends and writes to a full 128 bit wide vector */
671
TCGv_i64 tmplo = tcg_temp_new_i64();
675
TCGMemOp memop = MO_TE + size;
676
tmphi = tcg_const_i64(0);
677
tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
680
tmphi = tcg_temp_new_i64();
681
tcg_hiaddr = tcg_temp_new_i64();
683
tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
684
tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
685
tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
686
tcg_temp_free_i64(tcg_hiaddr);
689
tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(destidx, MO_64));
690
tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(destidx));
692
tcg_temp_free_i64(tmplo);
693
tcg_temp_free_i64(tmphi);
697
* Vector load/store helpers.
699
* The principal difference between this and a FP load is that we don't
700
* zero extend as we are filling a partial chunk of the vector register.
701
* These functions don't support 128 bit loads/stores, which would be
702
* normal load/store operations.
705
/* Get value of an element within a vector register */
706
static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
707
int element, TCGMemOp memop)
709
int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE);
712
tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
715
tcg_gen_ld16u_i64(tcg_dest, cpu_env, vect_off);
718
tcg_gen_ld32u_i64(tcg_dest, cpu_env, vect_off);
721
tcg_gen_ld8s_i64(tcg_dest, cpu_env, vect_off);
724
tcg_gen_ld16s_i64(tcg_dest, cpu_env, vect_off);
727
tcg_gen_ld32s_i64(tcg_dest, cpu_env, vect_off);
731
tcg_gen_ld_i64(tcg_dest, cpu_env, vect_off);
734
g_assert_not_reached();
738
/* Set value of an element within a vector register */
739
static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
740
int element, TCGMemOp memop)
742
int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
745
tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
748
tcg_gen_st16_i64(tcg_src, cpu_env, vect_off);
751
tcg_gen_st32_i64(tcg_src, cpu_env, vect_off);
754
tcg_gen_st_i64(tcg_src, cpu_env, vect_off);
757
g_assert_not_reached();
761
/* Clear the high 64 bits of a 128 bit vector (in general non-quad
762
* vector ops all need to do this).
764
static void clear_vec_high(DisasContext *s, int rd)
766
TCGv_i64 tcg_zero = tcg_const_i64(0);
768
write_vec_element(s, tcg_zero, rd, 1, MO_64);
769
tcg_temp_free_i64(tcg_zero);
772
/* Store from vector register to memory */
773
static void do_vec_st(DisasContext *s, int srcidx, int element,
774
TCGv_i64 tcg_addr, int size)
776
TCGMemOp memop = MO_TE + size;
777
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
779
read_vec_element(s, tcg_tmp, srcidx, element, size);
780
tcg_gen_qemu_st_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
782
tcg_temp_free_i64(tcg_tmp);
785
/* Load from memory to vector register */
786
static void do_vec_ld(DisasContext *s, int destidx, int element,
787
TCGv_i64 tcg_addr, int size)
789
TCGMemOp memop = MO_TE + size;
790
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
792
tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
793
write_vec_element(s, tcg_tmp, destidx, element, size);
795
tcg_temp_free_i64(tcg_tmp);
799
* This utility function is for doing register extension with an
800
* optional shift. You will likely want to pass a temporary for the
801
* destination register. See DecodeRegExtend() in the ARM ARM.
803
static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
804
int option, unsigned int shift)
806
int extsize = extract32(option, 0, 2);
807
bool is_signed = extract32(option, 2, 1);
812
tcg_gen_ext8s_i64(tcg_out, tcg_in);
815
tcg_gen_ext16s_i64(tcg_out, tcg_in);
818
tcg_gen_ext32s_i64(tcg_out, tcg_in);
821
tcg_gen_mov_i64(tcg_out, tcg_in);
827
tcg_gen_ext8u_i64(tcg_out, tcg_in);
830
tcg_gen_ext16u_i64(tcg_out, tcg_in);
833
tcg_gen_ext32u_i64(tcg_out, tcg_in);
836
tcg_gen_mov_i64(tcg_out, tcg_in);
842
tcg_gen_shli_i64(tcg_out, tcg_out, shift);
846
static inline void gen_check_sp_alignment(DisasContext *s)
848
/* The AArch64 architecture mandates that (if enabled via PSTATE
849
* or SCTLR bits) there is a check that SP is 16-aligned on every
850
* SP-relative load or store (with an exception generated if it is not).
851
* In line with general QEMU practice regarding misaligned accesses,
852
* we omit these checks for the sake of guest program performance.
853
* This function is provided as a hook so we can more easily add these
854
* checks in future (possibly as a "favour catching guest program bugs
855
* over speed" user selectable option).
860
* This provides a simple table based table lookup decoder. It is
861
* intended to be used when the relevant bits for decode are too
862
* awkwardly placed and switch/if based logic would be confusing and
863
* deeply nested. Since it's a linear search through the table, tables
864
* should be kept small.
866
* It returns the first handler where insn & mask == pattern, or
867
* NULL if there is no match.
868
* The table is terminated by an empty mask (i.e. 0)
870
static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
873
const AArch64DecodeTable *tptr = table;
876
if ((insn & tptr->mask) == tptr->pattern) {
877
return tptr->disas_fn;
885
* the instruction disassembly implemented here matches
886
* the instruction encoding classifications in chapter 3 (C3)
887
* of the ARM Architecture Reference Manual (DDI0487A_a)
890
/* C3.2.7 Unconditional branch (immediate)
892
* +----+-----------+-------------------------------------+
893
* | op | 0 0 1 0 1 | imm26 |
894
* +----+-----------+-------------------------------------+
896
static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
898
uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
900
if (insn & (1 << 31)) {
901
/* C5.6.26 BL Branch with link */
902
tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
905
/* C5.6.20 B Branch / C5.6.26 BL Branch with link */
906
gen_goto_tb(s, 0, addr);
909
/* C3.2.1 Compare & branch (immediate)
910
* 31 30 25 24 23 5 4 0
911
* +----+-------------+----+---------------------+--------+
912
* | sf | 0 1 1 0 1 0 | op | imm19 | Rt |
913
* +----+-------------+----+---------------------+--------+
915
static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
917
unsigned int sf, op, rt;
922
sf = extract32(insn, 31, 1);
923
op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
924
rt = extract32(insn, 0, 5);
925
addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
927
tcg_cmp = read_cpu_reg(s, rt, sf);
928
label_match = gen_new_label();
930
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
931
tcg_cmp, 0, label_match);
933
gen_goto_tb(s, 0, s->pc);
934
gen_set_label(label_match);
935
gen_goto_tb(s, 1, addr);
938
/* C3.2.5 Test & branch (immediate)
939
* 31 30 25 24 23 19 18 5 4 0
940
* +----+-------------+----+-------+-------------+------+
941
* | b5 | 0 1 1 0 1 1 | op | b40 | imm14 | Rt |
942
* +----+-------------+----+-------+-------------+------+
944
static void disas_test_b_imm(DisasContext *s, uint32_t insn)
946
unsigned int bit_pos, op, rt;
951
bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
952
op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
953
addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
954
rt = extract32(insn, 0, 5);
956
tcg_cmp = tcg_temp_new_i64();
957
tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
958
label_match = gen_new_label();
959
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
960
tcg_cmp, 0, label_match);
961
tcg_temp_free_i64(tcg_cmp);
962
gen_goto_tb(s, 0, s->pc);
963
gen_set_label(label_match);
964
gen_goto_tb(s, 1, addr);
967
/* C3.2.2 / C5.6.19 Conditional branch (immediate)
968
* 31 25 24 23 5 4 3 0
969
* +---------------+----+---------------------+----+------+
970
* | 0 1 0 1 0 1 0 | o1 | imm19 | o0 | cond |
971
* +---------------+----+---------------------+----+------+
973
static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
978
if ((insn & (1 << 4)) || (insn & (1 << 24))) {
979
unallocated_encoding(s);
982
addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
983
cond = extract32(insn, 0, 4);
986
/* genuinely conditional branches */
987
int label_match = gen_new_label();
988
arm_gen_test_cc(cond, label_match);
989
gen_goto_tb(s, 0, s->pc);
990
gen_set_label(label_match);
991
gen_goto_tb(s, 1, addr);
993
/* 0xe and 0xf are both "always" conditions */
994
gen_goto_tb(s, 0, addr);
999
static void handle_hint(DisasContext *s, uint32_t insn,
1000
unsigned int op1, unsigned int op2, unsigned int crm)
1002
unsigned int selector = crm << 3 | op2;
1005
unallocated_encoding(s);
1017
/* we treat all as NOP at least for now */
1020
/* default specified as NOP equivalent */
1025
static void gen_clrex(DisasContext *s, uint32_t insn)
1027
tcg_gen_movi_i64(cpu_exclusive_addr, -1);
1030
/* CLREX, DSB, DMB, ISB */
1031
static void handle_sync(DisasContext *s, uint32_t insn,
1032
unsigned int op1, unsigned int op2, unsigned int crm)
1035
unallocated_encoding(s);
1046
/* We don't emulate caches so barriers are no-ops */
1049
unallocated_encoding(s);
1054
/* C5.6.130 MSR (immediate) - move immediate to processor state field */
1055
static void handle_msr_i(DisasContext *s, uint32_t insn,
1056
unsigned int op1, unsigned int op2, unsigned int crm)
1058
unsupported_encoding(s, insn);
1061
static void gen_get_nzcv(TCGv_i64 tcg_rt)
1063
TCGv_i32 tmp = tcg_temp_new_i32();
1064
TCGv_i32 nzcv = tcg_temp_new_i32();
1066
/* build bit 31, N */
1067
tcg_gen_andi_i32(nzcv, cpu_NF, (1 << 31));
1068
/* build bit 30, Z */
1069
tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_ZF, 0);
1070
tcg_gen_deposit_i32(nzcv, nzcv, tmp, 30, 1);
1071
/* build bit 29, C */
1072
tcg_gen_deposit_i32(nzcv, nzcv, cpu_CF, 29, 1);
1073
/* build bit 28, V */
1074
tcg_gen_shri_i32(tmp, cpu_VF, 31);
1075
tcg_gen_deposit_i32(nzcv, nzcv, tmp, 28, 1);
1076
/* generate result */
1077
tcg_gen_extu_i32_i64(tcg_rt, nzcv);
1079
tcg_temp_free_i32(nzcv);
1080
tcg_temp_free_i32(tmp);
1083
static void gen_set_nzcv(TCGv_i64 tcg_rt)
1086
TCGv_i32 nzcv = tcg_temp_new_i32();
1088
/* take NZCV from R[t] */
1089
tcg_gen_trunc_i64_i32(nzcv, tcg_rt);
1092
tcg_gen_andi_i32(cpu_NF, nzcv, (1 << 31));
1094
tcg_gen_andi_i32(cpu_ZF, nzcv, (1 << 30));
1095
tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_ZF, cpu_ZF, 0);
1097
tcg_gen_andi_i32(cpu_CF, nzcv, (1 << 29));
1098
tcg_gen_shri_i32(cpu_CF, cpu_CF, 29);
1100
tcg_gen_andi_i32(cpu_VF, nzcv, (1 << 28));
1101
tcg_gen_shli_i32(cpu_VF, cpu_VF, 3);
1102
tcg_temp_free_i32(nzcv);
1105
/* C5.6.129 MRS - move from system register
1106
* C5.6.131 MSR (register) - move to system register
1109
* These are all essentially the same insn in 'read' and 'write'
1110
* versions, with varying op0 fields.
1112
static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
1113
unsigned int op0, unsigned int op1, unsigned int op2,
1114
unsigned int crn, unsigned int crm, unsigned int rt)
1116
const ARMCPRegInfo *ri;
1119
ri = get_arm_cp_reginfo(s->cp_regs,
1120
ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
1121
crn, crm, op0, op1, op2));
1124
/* Unknown register */
1125
unallocated_encoding(s);
1129
/* Check access permissions */
1130
if (!cp_access_ok(s->current_pl, ri, isread)) {
1131
unallocated_encoding(s);
1135
/* Handle special cases first */
1136
switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
1140
tcg_rt = cpu_reg(s, rt);
1142
gen_get_nzcv(tcg_rt);
1144
gen_set_nzcv(tcg_rt);
1151
if (use_icount && (ri->type & ARM_CP_IO)) {
1155
tcg_rt = cpu_reg(s, rt);
1158
if (ri->type & ARM_CP_CONST) {
1159
tcg_gen_movi_i64(tcg_rt, ri->resetvalue);
1160
} else if (ri->readfn) {
1162
gen_a64_set_pc_im(s->pc - 4);
1163
tmpptr = tcg_const_ptr(ri);
1164
gen_helper_get_cp_reg64(tcg_rt, cpu_env, tmpptr);
1165
tcg_temp_free_ptr(tmpptr);
1167
tcg_gen_ld_i64(tcg_rt, cpu_env, ri->fieldoffset);
1170
if (ri->type & ARM_CP_CONST) {
1171
/* If not forbidden by access permissions, treat as WI */
1173
} else if (ri->writefn) {
1175
gen_a64_set_pc_im(s->pc - 4);
1176
tmpptr = tcg_const_ptr(ri);
1177
gen_helper_set_cp_reg64(cpu_env, tmpptr, tcg_rt);
1178
tcg_temp_free_ptr(tmpptr);
1180
tcg_gen_st_i64(tcg_rt, cpu_env, ri->fieldoffset);
1184
if (use_icount && (ri->type & ARM_CP_IO)) {
1185
/* I/O operations must end the TB here (whether read or write) */
1187
s->is_jmp = DISAS_UPDATE;
1188
} else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
1189
/* We default to ending the TB on a coprocessor register write,
1190
* but allow this to be suppressed by the register definition
1191
* (usually only necessary to work around guest bugs).
1193
s->is_jmp = DISAS_UPDATE;
1198
* 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
1199
* +---------------------+---+-----+-----+-------+-------+-----+------+
1200
* | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 | CRn | CRm | op2 | Rt |
1201
* +---------------------+---+-----+-----+-------+-------+-----+------+
1203
static void disas_system(DisasContext *s, uint32_t insn)
1205
unsigned int l, op0, op1, crn, crm, op2, rt;
1206
l = extract32(insn, 21, 1);
1207
op0 = extract32(insn, 19, 2);
1208
op1 = extract32(insn, 16, 3);
1209
crn = extract32(insn, 12, 4);
1210
crm = extract32(insn, 8, 4);
1211
op2 = extract32(insn, 5, 3);
1212
rt = extract32(insn, 0, 5);
1215
if (l || rt != 31) {
1216
unallocated_encoding(s);
1220
case 2: /* C5.6.68 HINT */
1221
handle_hint(s, insn, op1, op2, crm);
1223
case 3: /* CLREX, DSB, DMB, ISB */
1224
handle_sync(s, insn, op1, op2, crm);
1226
case 4: /* C5.6.130 MSR (immediate) */
1227
handle_msr_i(s, insn, op1, op2, crm);
1230
unallocated_encoding(s);
1235
handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
1238
/* C3.2.3 Exception generation
1240
* 31 24 23 21 20 5 4 2 1 0
1241
* +-----------------+-----+------------------------+-----+----+
1242
* | 1 1 0 1 0 1 0 0 | opc | imm16 | op2 | LL |
1243
* +-----------------------+------------------------+----------+
1245
static void disas_exc(DisasContext *s, uint32_t insn)
1247
int opc = extract32(insn, 21, 3);
1248
int op2_ll = extract32(insn, 0, 5);
1252
/* SVC, HVC, SMC; since we don't support the Virtualization
1253
* or TrustZone extensions these all UNDEF except SVC.
1256
unallocated_encoding(s);
1259
gen_exception_insn(s, 0, EXCP_SWI);
1263
unallocated_encoding(s);
1267
gen_exception_insn(s, 0, EXCP_BKPT);
1271
unallocated_encoding(s);
1275
unsupported_encoding(s, insn);
1278
if (op2_ll < 1 || op2_ll > 3) {
1279
unallocated_encoding(s);
1282
/* DCPS1, DCPS2, DCPS3 */
1283
unsupported_encoding(s, insn);
1286
unallocated_encoding(s);
1291
/* C3.2.7 Unconditional branch (register)
1292
* 31 25 24 21 20 16 15 10 9 5 4 0
1293
* +---------------+-------+-------+-------+------+-------+
1294
* | 1 1 0 1 0 1 1 | opc | op2 | op3 | Rn | op4 |
1295
* +---------------+-------+-------+-------+------+-------+
1297
static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
1299
unsigned int opc, op2, op3, rn, op4;
1301
opc = extract32(insn, 21, 4);
1302
op2 = extract32(insn, 16, 5);
1303
op3 = extract32(insn, 10, 6);
1304
rn = extract32(insn, 5, 5);
1305
op4 = extract32(insn, 0, 5);
1307
if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
1308
unallocated_encoding(s);
1317
tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
1322
unallocated_encoding(s);
1324
unsupported_encoding(s, insn);
1328
unallocated_encoding(s);
1332
tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
1333
s->is_jmp = DISAS_JUMP;
1336
/* C3.2 Branches, exception generating and system instructions */
1337
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
1339
switch (extract32(insn, 25, 7)) {
1340
case 0x0a: case 0x0b:
1341
case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
1342
disas_uncond_b_imm(s, insn);
1344
case 0x1a: case 0x5a: /* Compare & branch (immediate) */
1345
disas_comp_b_imm(s, insn);
1347
case 0x1b: case 0x5b: /* Test & branch (immediate) */
1348
disas_test_b_imm(s, insn);
1350
case 0x2a: /* Conditional branch (immediate) */
1351
disas_cond_b_imm(s, insn);
1353
case 0x6a: /* Exception generation / System */
1354
if (insn & (1 << 24)) {
1355
disas_system(s, insn);
1360
case 0x6b: /* Unconditional branch (register) */
1361
disas_uncond_b_reg(s, insn);
1364
unallocated_encoding(s);
1370
* Load/Store exclusive instructions are implemented by remembering
1371
* the value/address loaded, and seeing if these are the same
1372
* when the store is performed. This is not actually the architecturally
1373
* mandated semantics, but it works for typical guest code sequences
1374
* and avoids having to monitor regular stores.
1376
* In system emulation mode only one CPU will be running at once, so
1377
* this sequence is effectively atomic. In user emulation mode we
1378
* throw an exception and handle the atomic operation elsewhere.
1380
static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
1381
TCGv_i64 addr, int size, bool is_pair)
1383
TCGv_i64 tmp = tcg_temp_new_i64();
1384
TCGMemOp memop = MO_TE + size;
1386
g_assert(size <= 3);
1387
tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
1390
TCGv_i64 addr2 = tcg_temp_new_i64();
1391
TCGv_i64 hitmp = tcg_temp_new_i64();
1393
g_assert(size >= 2);
1394
tcg_gen_addi_i64(addr2, addr, 1 << size);
1395
tcg_gen_qemu_ld_i64(hitmp, addr2, get_mem_index(s), memop);
1396
tcg_temp_free_i64(addr2);
1397
tcg_gen_mov_i64(cpu_exclusive_high, hitmp);
1398
tcg_gen_mov_i64(cpu_reg(s, rt2), hitmp);
1399
tcg_temp_free_i64(hitmp);
1402
tcg_gen_mov_i64(cpu_exclusive_val, tmp);
1403
tcg_gen_mov_i64(cpu_reg(s, rt), tmp);
1405
tcg_temp_free_i64(tmp);
1406
tcg_gen_mov_i64(cpu_exclusive_addr, addr);
1409
#ifdef CONFIG_USER_ONLY
1410
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
1411
TCGv_i64 addr, int size, int is_pair)
1413
tcg_gen_mov_i64(cpu_exclusive_test, addr);
1414
tcg_gen_movi_i32(cpu_exclusive_info,
1415
size | is_pair << 2 | (rd << 4) | (rt << 9) | (rt2 << 14));
1416
gen_exception_insn(s, 4, EXCP_STREX);
1419
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
1420
TCGv_i64 addr, int size, int is_pair)
1422
qemu_log_mask(LOG_UNIMP,
1423
"%s:%d: system mode store_exclusive unsupported "
1424
"at pc=%016" PRIx64 "\n",
1425
__FILE__, __LINE__, s->pc - 4);
1429
/* C3.3.6 Load/store exclusive
1431
* 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
1432
* +-----+-------------+----+---+----+------+----+-------+------+------+
1433
* | sz | 0 0 1 0 0 0 | o2 | L | o1 | Rs | o0 | Rt2 | Rn | Rt |
1434
* +-----+-------------+----+---+----+------+----+-------+------+------+
1436
* sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
1437
* L: 0 -> store, 1 -> load
1438
* o2: 0 -> exclusive, 1 -> not
1439
* o1: 0 -> single register, 1 -> register pair
1440
* o0: 1 -> load-acquire/store-release, 0 -> not
1442
* o0 == 0 AND o2 == 1 is un-allocated
1443
* o1 == 1 is un-allocated except for 32 and 64 bit sizes
1445
static void disas_ldst_excl(DisasContext *s, uint32_t insn)
1447
int rt = extract32(insn, 0, 5);
1448
int rn = extract32(insn, 5, 5);
1449
int rt2 = extract32(insn, 10, 5);
1450
int is_lasr = extract32(insn, 15, 1);
1451
int rs = extract32(insn, 16, 5);
1452
int is_pair = extract32(insn, 21, 1);
1453
int is_store = !extract32(insn, 22, 1);
1454
int is_excl = !extract32(insn, 23, 1);
1455
int size = extract32(insn, 30, 2);
1458
if ((!is_excl && !is_lasr) ||
1459
(is_pair && size < 2)) {
1460
unallocated_encoding(s);
1465
gen_check_sp_alignment(s);
1467
tcg_addr = read_cpu_reg_sp(s, rn, 1);
1469
/* Note that since TCG is single threaded load-acquire/store-release
1470
* semantics require no extra if (is_lasr) { ... } handling.
1475
gen_load_exclusive(s, rt, rt2, tcg_addr, size, is_pair);
1477
gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, is_pair);
1480
TCGv_i64 tcg_rt = cpu_reg(s, rt);
1482
do_gpr_st(s, tcg_rt, tcg_addr, size);
1484
do_gpr_ld(s, tcg_rt, tcg_addr, size, false, false);
1487
TCGv_i64 tcg_rt2 = cpu_reg(s, rt);
1488
tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
1490
do_gpr_st(s, tcg_rt2, tcg_addr, size);
1492
do_gpr_ld(s, tcg_rt2, tcg_addr, size, false, false);
1499
* C3.3.5 Load register (literal)
1501
* 31 30 29 27 26 25 24 23 5 4 0
1502
* +-----+-------+---+-----+-------------------+-------+
1503
* | opc | 0 1 1 | V | 0 0 | imm19 | Rt |
1504
* +-----+-------+---+-----+-------------------+-------+
1506
* V: 1 -> vector (simd/fp)
1507
* opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
1508
* 10-> 32 bit signed, 11 -> prefetch
1509
* opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
1511
static void disas_ld_lit(DisasContext *s, uint32_t insn)
1513
int rt = extract32(insn, 0, 5);
1514
int64_t imm = sextract32(insn, 5, 19) << 2;
1515
bool is_vector = extract32(insn, 26, 1);
1516
int opc = extract32(insn, 30, 2);
1517
bool is_signed = false;
1519
TCGv_i64 tcg_rt, tcg_addr;
1523
unallocated_encoding(s);
1529
/* PRFM (literal) : prefetch */
1532
size = 2 + extract32(opc, 0, 1);
1533
is_signed = extract32(opc, 1, 1);
1536
tcg_rt = cpu_reg(s, rt);
1538
tcg_addr = tcg_const_i64((s->pc - 4) + imm);
1540
do_fp_ld(s, rt, tcg_addr, size);
1542
do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
1544
tcg_temp_free_i64(tcg_addr);
1548
* C5.6.80 LDNP (Load Pair - non-temporal hint)
1549
* C5.6.81 LDP (Load Pair - non vector)
1550
* C5.6.82 LDPSW (Load Pair Signed Word - non vector)
1551
* C5.6.176 STNP (Store Pair - non-temporal hint)
1552
* C5.6.177 STP (Store Pair - non vector)
1553
* C6.3.165 LDNP (Load Pair of SIMD&FP - non-temporal hint)
1554
* C6.3.165 LDP (Load Pair of SIMD&FP)
1555
* C6.3.284 STNP (Store Pair of SIMD&FP - non-temporal hint)
1556
* C6.3.284 STP (Store Pair of SIMD&FP)
1558
* 31 30 29 27 26 25 24 23 22 21 15 14 10 9 5 4 0
1559
* +-----+-------+---+---+-------+---+-----------------------------+
1560
* | opc | 1 0 1 | V | 0 | index | L | imm7 | Rt2 | Rn | Rt |
1561
* +-----+-------+---+---+-------+---+-------+-------+------+------+
1563
* opc: LDP/STP/LDNP/STNP 00 -> 32 bit, 10 -> 64 bit
1565
* LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
1566
* V: 0 -> GPR, 1 -> Vector
1567
* idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
1568
* 10 -> signed offset, 11 -> pre-index
1569
* L: 0 -> Store 1 -> Load
1571
* Rt, Rt2 = GPR or SIMD registers to be stored
1572
* Rn = general purpose register containing address
1573
* imm7 = signed offset (multiple of 4 or 8 depending on size)
1575
static void disas_ldst_pair(DisasContext *s, uint32_t insn)
1577
int rt = extract32(insn, 0, 5);
1578
int rn = extract32(insn, 5, 5);
1579
int rt2 = extract32(insn, 10, 5);
1580
int64_t offset = sextract32(insn, 15, 7);
1581
int index = extract32(insn, 23, 2);
1582
bool is_vector = extract32(insn, 26, 1);
1583
bool is_load = extract32(insn, 22, 1);
1584
int opc = extract32(insn, 30, 2);
1586
bool is_signed = false;
1587
bool postindex = false;
1590
TCGv_i64 tcg_addr; /* calculated address */
1594
unallocated_encoding(s);
1601
size = 2 + extract32(opc, 1, 1);
1602
is_signed = extract32(opc, 0, 1);
1603
if (!is_load && is_signed) {
1604
unallocated_encoding(s);
1610
case 1: /* post-index */
1615
/* signed offset with "non-temporal" hint. Since we don't emulate
1616
* caches we don't care about hints to the cache system about
1617
* data access patterns, and handle this identically to plain
1621
/* There is no non-temporal-hint version of LDPSW */
1622
unallocated_encoding(s);
1627
case 2: /* signed offset, rn not updated */
1630
case 3: /* pre-index */
1639
gen_check_sp_alignment(s);
1642
tcg_addr = read_cpu_reg_sp(s, rn, 1);
1645
tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
1650
do_fp_ld(s, rt, tcg_addr, size);
1652
do_fp_st(s, rt, tcg_addr, size);
1655
TCGv_i64 tcg_rt = cpu_reg(s, rt);
1657
do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
1659
do_gpr_st(s, tcg_rt, tcg_addr, size);
1662
tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
1665
do_fp_ld(s, rt2, tcg_addr, size);
1667
do_fp_st(s, rt2, tcg_addr, size);
1670
TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
1672
do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false);
1674
do_gpr_st(s, tcg_rt2, tcg_addr, size);
1680
tcg_gen_addi_i64(tcg_addr, tcg_addr, offset - (1 << size));
1682
tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size);
1684
tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
1689
* C3.3.8 Load/store (immediate post-indexed)
1690
* C3.3.9 Load/store (immediate pre-indexed)
1691
* C3.3.12 Load/store (unscaled immediate)
1693
* 31 30 29 27 26 25 24 23 22 21 20 12 11 10 9 5 4 0
1694
* +----+-------+---+-----+-----+---+--------+-----+------+------+
1695
* |size| 1 1 1 | V | 0 0 | opc | 0 | imm9 | idx | Rn | Rt |
1696
* +----+-------+---+-----+-----+---+--------+-----+------+------+
1698
* idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
1699
* V = 0 -> non-vector
1700
* size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
1701
* opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1703
static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn)
1705
int rt = extract32(insn, 0, 5);
1706
int rn = extract32(insn, 5, 5);
1707
int imm9 = sextract32(insn, 12, 9);
1708
int opc = extract32(insn, 22, 2);
1709
int size = extract32(insn, 30, 2);
1710
int idx = extract32(insn, 10, 2);
1711
bool is_signed = false;
1712
bool is_store = false;
1713
bool is_extended = false;
1714
bool is_vector = extract32(insn, 26, 1);
1721
size |= (opc & 2) << 1;
1723
unallocated_encoding(s);
1726
is_store = ((opc & 1) == 0);
1728
if (size == 3 && opc == 2) {
1729
/* PRFM - prefetch */
1732
if (opc == 3 && size > 1) {
1733
unallocated_encoding(s);
1736
is_store = (opc == 0);
1737
is_signed = opc & (1<<1);
1738
is_extended = (size < 3) && (opc & 1);
1760
gen_check_sp_alignment(s);
1762
tcg_addr = read_cpu_reg_sp(s, rn, 1);
1765
tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
1770
do_fp_st(s, rt, tcg_addr, size);
1772
do_fp_ld(s, rt, tcg_addr, size);
1775
TCGv_i64 tcg_rt = cpu_reg(s, rt);
1777
do_gpr_st(s, tcg_rt, tcg_addr, size);
1779
do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1784
TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
1786
tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
1788
tcg_gen_mov_i64(tcg_rn, tcg_addr);
1793
* C3.3.10 Load/store (register offset)
1795
* 31 30 29 27 26 25 24 23 22 21 20 16 15 13 12 11 10 9 5 4 0
1796
* +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
1797
* |size| 1 1 1 | V | 0 0 | opc | 1 | Rm | opt | S| 1 0 | Rn | Rt |
1798
* +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
1801
* size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
1802
* opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1804
* size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
1805
* opc<0>: 0 -> store, 1 -> load
1806
* V: 1 -> vector/simd
1807
* opt: extend encoding (see DecodeRegExtend)
1808
* S: if S=1 then scale (essentially index by sizeof(size))
1809
* Rt: register to transfer into/out of
1810
* Rn: address register or SP for base
1811
* Rm: offset register or ZR for offset
1813
static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn)
1815
int rt = extract32(insn, 0, 5);
1816
int rn = extract32(insn, 5, 5);
1817
int shift = extract32(insn, 12, 1);
1818
int rm = extract32(insn, 16, 5);
1819
int opc = extract32(insn, 22, 2);
1820
int opt = extract32(insn, 13, 3);
1821
int size = extract32(insn, 30, 2);
1822
bool is_signed = false;
1823
bool is_store = false;
1824
bool is_extended = false;
1825
bool is_vector = extract32(insn, 26, 1);
1830
if (extract32(opt, 1, 1) == 0) {
1831
unallocated_encoding(s);
1836
size |= (opc & 2) << 1;
1838
unallocated_encoding(s);
1841
is_store = !extract32(opc, 0, 1);
1843
if (size == 3 && opc == 2) {
1844
/* PRFM - prefetch */
1847
if (opc == 3 && size > 1) {
1848
unallocated_encoding(s);
1851
is_store = (opc == 0);
1852
is_signed = extract32(opc, 1, 1);
1853
is_extended = (size < 3) && extract32(opc, 0, 1);
1857
gen_check_sp_alignment(s);
1859
tcg_addr = read_cpu_reg_sp(s, rn, 1);
1861
tcg_rm = read_cpu_reg(s, rm, 1);
1862
ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
1864
tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_rm);
1868
do_fp_st(s, rt, tcg_addr, size);
1870
do_fp_ld(s, rt, tcg_addr, size);
1873
TCGv_i64 tcg_rt = cpu_reg(s, rt);
1875
do_gpr_st(s, tcg_rt, tcg_addr, size);
1877
do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1883
* C3.3.13 Load/store (unsigned immediate)
1885
* 31 30 29 27 26 25 24 23 22 21 10 9 5
1886
* +----+-------+---+-----+-----+------------+-------+------+
1887
* |size| 1 1 1 | V | 0 1 | opc | imm12 | Rn | Rt |
1888
* +----+-------+---+-----+-----+------------+-------+------+
1891
* size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
1892
* opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1894
* size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
1895
* opc<0>: 0 -> store, 1 -> load
1896
* Rn: base address register (inc SP)
1897
* Rt: target register
1899
static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn)
1901
int rt = extract32(insn, 0, 5);
1902
int rn = extract32(insn, 5, 5);
1903
unsigned int imm12 = extract32(insn, 10, 12);
1904
bool is_vector = extract32(insn, 26, 1);
1905
int size = extract32(insn, 30, 2);
1906
int opc = extract32(insn, 22, 2);
1907
unsigned int offset;
1912
bool is_signed = false;
1913
bool is_extended = false;
1916
size |= (opc & 2) << 1;
1918
unallocated_encoding(s);
1921
is_store = !extract32(opc, 0, 1);
1923
if (size == 3 && opc == 2) {
1924
/* PRFM - prefetch */
1927
if (opc == 3 && size > 1) {
1928
unallocated_encoding(s);
1931
is_store = (opc == 0);
1932
is_signed = extract32(opc, 1, 1);
1933
is_extended = (size < 3) && extract32(opc, 0, 1);
1937
gen_check_sp_alignment(s);
1939
tcg_addr = read_cpu_reg_sp(s, rn, 1);
1940
offset = imm12 << size;
1941
tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
1945
do_fp_st(s, rt, tcg_addr, size);
1947
do_fp_ld(s, rt, tcg_addr, size);
1950
TCGv_i64 tcg_rt = cpu_reg(s, rt);
1952
do_gpr_st(s, tcg_rt, tcg_addr, size);
1954
do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1959
/* Load/store register (immediate forms) */
1960
static void disas_ldst_reg_imm(DisasContext *s, uint32_t insn)
1962
switch (extract32(insn, 10, 2)) {
1963
case 0: case 1: case 3:
1964
/* Load/store register (unscaled immediate) */
1965
/* Load/store immediate pre/post-indexed */
1966
disas_ldst_reg_imm9(s, insn);
1969
/* Load/store register unprivileged */
1970
unsupported_encoding(s, insn);
1973
unallocated_encoding(s);
1978
/* Load/store register (all forms) */
1979
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
1981
switch (extract32(insn, 24, 2)) {
1983
if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) {
1984
disas_ldst_reg_roffset(s, insn);
1986
disas_ldst_reg_imm(s, insn);
1990
disas_ldst_reg_unsigned_imm(s, insn);
1993
unallocated_encoding(s);
1998
/* C3.3.1 AdvSIMD load/store multiple structures
2000
* 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
2001
* +---+---+---------------+---+-------------+--------+------+------+------+
2002
* | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size | Rn | Rt |
2003
* +---+---+---------------+---+-------------+--------+------+------+------+
2005
* C3.3.2 AdvSIMD load/store multiple structures (post-indexed)
2007
* 31 30 29 23 22 21 20 16 15 12 11 10 9 5 4 0
2008
* +---+---+---------------+---+---+---------+--------+------+------+------+
2009
* | 0 | Q | 0 0 1 1 0 0 1 | L | 0 | Rm | opcode | size | Rn | Rt |
2010
* +---+---+---------------+---+---+---------+--------+------+------+------+
2012
* Rt: first (or only) SIMD&FP register to be transferred
2013
* Rn: base address or SP
2014
* Rm (post-index only): post-index register (when !31) or size dependent #imm
2016
static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
2018
int rt = extract32(insn, 0, 5);
2019
int rn = extract32(insn, 5, 5);
2020
int size = extract32(insn, 10, 2);
2021
int opcode = extract32(insn, 12, 4);
2022
bool is_store = !extract32(insn, 22, 1);
2023
bool is_postidx = extract32(insn, 23, 1);
2024
bool is_q = extract32(insn, 30, 1);
2025
TCGv_i64 tcg_addr, tcg_rn;
2027
int ebytes = 1 << size;
2028
int elements = (is_q ? 128 : 64) / (8 << size);
2029
int rpt; /* num iterations */
2030
int selem; /* structure elements */
2033
if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
2034
unallocated_encoding(s);
2038
/* From the shared decode logic */
2069
unallocated_encoding(s);
2073
if (size == 3 && !is_q && selem != 1) {
2075
unallocated_encoding(s);
2080
gen_check_sp_alignment(s);
2083
tcg_rn = cpu_reg_sp(s, rn);
2084
tcg_addr = tcg_temp_new_i64();
2085
tcg_gen_mov_i64(tcg_addr, tcg_rn);
2087
for (r = 0; r < rpt; r++) {
2089
for (e = 0; e < elements; e++) {
2090
int tt = (rt + r) % 32;
2092
for (xs = 0; xs < selem; xs++) {
2094
do_vec_st(s, tt, e, tcg_addr, size);
2096
do_vec_ld(s, tt, e, tcg_addr, size);
2098
/* For non-quad operations, setting a slice of the low
2099
* 64 bits of the register clears the high 64 bits (in
2100
* the ARM ARM pseudocode this is implicit in the fact
2101
* that 'rval' is a 64 bit wide variable). We optimize
2102
* by noticing that we only need to do this the first
2103
* time we touch a register.
2105
if (!is_q && e == 0 && (r == 0 || xs == selem - 1)) {
2106
clear_vec_high(s, tt);
2109
tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
2116
int rm = extract32(insn, 16, 5);
2118
tcg_gen_mov_i64(tcg_rn, tcg_addr);
2120
tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
2123
tcg_temp_free_i64(tcg_addr);
2126
/* C3.3.3 AdvSIMD load/store single structure
2128
* 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
2129
* +---+---+---------------+-----+-----------+-----+---+------+------+------+
2130
* | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size | Rn | Rt |
2131
* +---+---+---------------+-----+-----------+-----+---+------+------+------+
2133
* C3.3.4 AdvSIMD load/store single structure (post-indexed)
2135
* 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
2136
* +---+---+---------------+-----+-----------+-----+---+------+------+------+
2137
* | 0 | Q | 0 0 1 1 0 1 1 | L R | Rm | opc | S | size | Rn | Rt |
2138
* +---+---+---------------+-----+-----------+-----+---+------+------+------+
2140
* Rt: first (or only) SIMD&FP register to be transferred
2141
* Rn: base address or SP
2142
* Rm (post-index only): post-index register (when !31) or size dependent #imm
2143
* index = encoded in Q:S:size dependent on size
2145
* lane_size = encoded in R, opc
2146
* transfer width = encoded in opc, S, size
2148
static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
2150
int rt = extract32(insn, 0, 5);
2151
int rn = extract32(insn, 5, 5);
2152
int size = extract32(insn, 10, 2);
2153
int S = extract32(insn, 12, 1);
2154
int opc = extract32(insn, 13, 3);
2155
int R = extract32(insn, 21, 1);
2156
int is_load = extract32(insn, 22, 1);
2157
int is_postidx = extract32(insn, 23, 1);
2158
int is_q = extract32(insn, 30, 1);
2160
int scale = extract32(opc, 1, 2);
2161
int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
2162
bool replicate = false;
2163
int index = is_q << 3 | S << 2 | size;
2165
TCGv_i64 tcg_addr, tcg_rn;
2169
if (!is_load || S) {
2170
unallocated_encoding(s);
2179
if (extract32(size, 0, 1)) {
2180
unallocated_encoding(s);
2186
if (extract32(size, 1, 1)) {
2187
unallocated_encoding(s);
2190
if (!extract32(size, 0, 1)) {
2194
unallocated_encoding(s);
2202
g_assert_not_reached();
2205
ebytes = 1 << scale;
2208
gen_check_sp_alignment(s);
2211
tcg_rn = cpu_reg_sp(s, rn);
2212
tcg_addr = tcg_temp_new_i64();
2213
tcg_gen_mov_i64(tcg_addr, tcg_rn);
2215
for (xs = 0; xs < selem; xs++) {
2217
/* Load and replicate to all elements */
2219
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
2221
tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
2222
get_mem_index(s), MO_TE + scale);
2225
mulconst = 0x0101010101010101ULL;
2228
mulconst = 0x0001000100010001ULL;
2231
mulconst = 0x0000000100000001ULL;
2237
g_assert_not_reached();
2240
tcg_gen_muli_i64(tcg_tmp, tcg_tmp, mulconst);
2242
write_vec_element(s, tcg_tmp, rt, 0, MO_64);
2244
write_vec_element(s, tcg_tmp, rt, 1, MO_64);
2246
clear_vec_high(s, rt);
2248
tcg_temp_free_i64(tcg_tmp);
2250
/* Load/store one element per register */
2252
do_vec_ld(s, rt, index, tcg_addr, MO_TE + scale);
2254
do_vec_st(s, rt, index, tcg_addr, MO_TE + scale);
2257
tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
2262
int rm = extract32(insn, 16, 5);
2264
tcg_gen_mov_i64(tcg_rn, tcg_addr);
2266
tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
2269
tcg_temp_free_i64(tcg_addr);
2272
/* C3.3 Loads and stores */
2273
static void disas_ldst(DisasContext *s, uint32_t insn)
2275
switch (extract32(insn, 24, 6)) {
2276
case 0x08: /* Load/store exclusive */
2277
disas_ldst_excl(s, insn);
2279
case 0x18: case 0x1c: /* Load register (literal) */
2280
disas_ld_lit(s, insn);
2282
case 0x28: case 0x29:
2283
case 0x2c: case 0x2d: /* Load/store pair (all forms) */
2284
disas_ldst_pair(s, insn);
2286
case 0x38: case 0x39:
2287
case 0x3c: case 0x3d: /* Load/store register (all forms) */
2288
disas_ldst_reg(s, insn);
2290
case 0x0c: /* AdvSIMD load/store multiple structures */
2291
disas_ldst_multiple_struct(s, insn);
2293
case 0x0d: /* AdvSIMD load/store single structure */
2294
disas_ldst_single_struct(s, insn);
2297
unallocated_encoding(s);
2302
/* C3.4.6 PC-rel. addressing
2303
* 31 30 29 28 24 23 5 4 0
2304
* +----+-------+-----------+-------------------+------+
2305
* | op | immlo | 1 0 0 0 0 | immhi | Rd |
2306
* +----+-------+-----------+-------------------+------+
2308
static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
2310
unsigned int page, rd;
2314
page = extract32(insn, 31, 1);
2315
/* SignExtend(immhi:immlo) -> offset */
2316
offset = ((int64_t)sextract32(insn, 5, 19) << 2) | extract32(insn, 29, 2);
2317
rd = extract32(insn, 0, 5);
2321
/* ADRP (page based) */
2326
tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
2330
* C3.4.1 Add/subtract (immediate)
2332
* 31 30 29 28 24 23 22 21 10 9 5 4 0
2333
* +--+--+--+-----------+-----+-------------+-----+-----+
2334
* |sf|op| S| 1 0 0 0 1 |shift| imm12 | Rn | Rd |
2335
* +--+--+--+-----------+-----+-------------+-----+-----+
2337
* sf: 0 -> 32bit, 1 -> 64bit
2338
* op: 0 -> add , 1 -> sub
2340
* shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
2342
static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
2344
int rd = extract32(insn, 0, 5);
2345
int rn = extract32(insn, 5, 5);
2346
uint64_t imm = extract32(insn, 10, 12);
2347
int shift = extract32(insn, 22, 2);
2348
bool setflags = extract32(insn, 29, 1);
2349
bool sub_op = extract32(insn, 30, 1);
2350
bool is_64bit = extract32(insn, 31, 1);
2352
TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
2353
TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
2354
TCGv_i64 tcg_result;
2363
unallocated_encoding(s);
2367
tcg_result = tcg_temp_new_i64();
2370
tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
2372
tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
2375
TCGv_i64 tcg_imm = tcg_const_i64(imm);
2377
gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
2379
gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
2381
tcg_temp_free_i64(tcg_imm);
2385
tcg_gen_mov_i64(tcg_rd, tcg_result);
2387
tcg_gen_ext32u_i64(tcg_rd, tcg_result);
2390
tcg_temp_free_i64(tcg_result);
2393
/* The input should be a value in the bottom e bits (with higher
2394
* bits zero); returns that value replicated into every element
2395
* of size e in a 64 bit integer.
2397
static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
2407
/* Return a value with the bottom len bits set (where 0 < len <= 64) */
2408
static inline uint64_t bitmask64(unsigned int length)
2410
assert(length > 0 && length <= 64);
2411
return ~0ULL >> (64 - length);
2414
/* Simplified variant of pseudocode DecodeBitMasks() for the case where we
2415
* only require the wmask. Returns false if the imms/immr/immn are a reserved
2416
* value (ie should cause a guest UNDEF exception), and true if they are
2417
* valid, in which case the decoded bit pattern is written to result.
2419
static bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
2420
unsigned int imms, unsigned int immr)
2423
unsigned e, levels, s, r;
2426
assert(immn < 2 && imms < 64 && immr < 64);
2428
/* The bit patterns we create here are 64 bit patterns which
2429
* are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
2430
* 64 bits each. Each element contains the same value: a run
2431
* of between 1 and e-1 non-zero bits, rotated within the
2432
* element by between 0 and e-1 bits.
2434
* The element size and run length are encoded into immn (1 bit)
2435
* and imms (6 bits) as follows:
2436
* 64 bit elements: immn = 1, imms = <length of run - 1>
2437
* 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
2438
* 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
2439
* 8 bit elements: immn = 0, imms = 110 : <length of run - 1>
2440
* 4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
2441
* 2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
2442
* Notice that immn = 0, imms = 11111x is the only combination
2443
* not covered by one of the above options; this is reserved.
2444
* Further, <length of run - 1> all-ones is a reserved pattern.
2446
* In all cases the rotation is by immr % e (and immr is 6 bits).
2449
/* First determine the element size */
2450
len = 31 - clz32((immn << 6) | (~imms & 0x3f));
2452
/* This is the immn == 0, imms == 0x11111x case */
2462
/* <length of run - 1> mustn't be all-ones. */
2466
/* Create the value of one element: s+1 set bits rotated
2467
* by r within the element (which is e bits wide)...
2469
mask = bitmask64(s + 1);
2470
mask = (mask >> r) | (mask << (e - r));
2471
/* ...then replicate the element over the whole 64 bit value */
2472
mask = bitfield_replicate(mask, e);
2477
/* C3.4.4 Logical (immediate)
2478
* 31 30 29 28 23 22 21 16 15 10 9 5 4 0
2479
* +----+-----+-------------+---+------+------+------+------+
2480
* | sf | opc | 1 0 0 1 0 0 | N | immr | imms | Rn | Rd |
2481
* +----+-----+-------------+---+------+------+------+------+
2483
static void disas_logic_imm(DisasContext *s, uint32_t insn)
2485
unsigned int sf, opc, is_n, immr, imms, rn, rd;
2486
TCGv_i64 tcg_rd, tcg_rn;
2488
bool is_and = false;
2490
sf = extract32(insn, 31, 1);
2491
opc = extract32(insn, 29, 2);
2492
is_n = extract32(insn, 22, 1);
2493
immr = extract32(insn, 16, 6);
2494
imms = extract32(insn, 10, 6);
2495
rn = extract32(insn, 5, 5);
2496
rd = extract32(insn, 0, 5);
2499
unallocated_encoding(s);
2503
if (opc == 0x3) { /* ANDS */
2504
tcg_rd = cpu_reg(s, rd);
2506
tcg_rd = cpu_reg_sp(s, rd);
2508
tcg_rn = cpu_reg(s, rn);
2510
if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
2511
/* some immediate field values are reserved */
2512
unallocated_encoding(s);
2517
wmask &= 0xffffffff;
2521
case 0x3: /* ANDS */
2523
tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
2527
tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
2530
tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
2533
assert(FALSE); /* must handle all above */
2537
if (!sf && !is_and) {
2538
/* zero extend final result; we know we can skip this for AND
2539
* since the immediate had the high 32 bits clear.
2541
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2544
if (opc == 3) { /* ANDS */
2545
gen_logic_CC(sf, tcg_rd);
2550
* C3.4.5 Move wide (immediate)
2552
* 31 30 29 28 23 22 21 20 5 4 0
2553
* +--+-----+-------------+-----+----------------+------+
2554
* |sf| opc | 1 0 0 1 0 1 | hw | imm16 | Rd |
2555
* +--+-----+-------------+-----+----------------+------+
2557
* sf: 0 -> 32 bit, 1 -> 64 bit
2558
* opc: 00 -> N, 10 -> Z, 11 -> K
2559
* hw: shift/16 (0,16, and sf only 32, 48)
2561
static void disas_movw_imm(DisasContext *s, uint32_t insn)
2563
int rd = extract32(insn, 0, 5);
2564
uint64_t imm = extract32(insn, 5, 16);
2565
int sf = extract32(insn, 31, 1);
2566
int opc = extract32(insn, 29, 2);
2567
int pos = extract32(insn, 21, 2) << 4;
2568
TCGv_i64 tcg_rd = cpu_reg(s, rd);
2571
if (!sf && (pos >= 32)) {
2572
unallocated_encoding(s);
2586
tcg_gen_movi_i64(tcg_rd, imm);
2589
tcg_imm = tcg_const_i64(imm);
2590
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_imm, pos, 16);
2591
tcg_temp_free_i64(tcg_imm);
2593
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2597
unallocated_encoding(s);
2603
* 31 30 29 28 23 22 21 16 15 10 9 5 4 0
2604
* +----+-----+-------------+---+------+------+------+------+
2605
* | sf | opc | 1 0 0 1 1 0 | N | immr | imms | Rn | Rd |
2606
* +----+-----+-------------+---+------+------+------+------+
2608
static void disas_bitfield(DisasContext *s, uint32_t insn)
2610
unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
2611
TCGv_i64 tcg_rd, tcg_tmp;
2613
sf = extract32(insn, 31, 1);
2614
opc = extract32(insn, 29, 2);
2615
n = extract32(insn, 22, 1);
2616
ri = extract32(insn, 16, 6);
2617
si = extract32(insn, 10, 6);
2618
rn = extract32(insn, 5, 5);
2619
rd = extract32(insn, 0, 5);
2620
bitsize = sf ? 64 : 32;
2622
if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
2623
unallocated_encoding(s);
2627
tcg_rd = cpu_reg(s, rd);
2628
tcg_tmp = read_cpu_reg(s, rn, sf);
2630
/* OPTME: probably worth recognizing common cases of ext{8,16,32}{u,s} */
2632
if (opc != 1) { /* SBFM or UBFM */
2633
tcg_gen_movi_i64(tcg_rd, 0);
2636
/* do the bit move operation */
2638
/* Wd<s-r:0> = Wn<s:r> */
2639
tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
2641
len = (si - ri) + 1;
2643
/* Wd<32+s-r,32-r> = Wn<s:0> */
2648
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
2650
if (opc == 0) { /* SBFM - sign extend the destination field */
2651
tcg_gen_shli_i64(tcg_rd, tcg_rd, 64 - (pos + len));
2652
tcg_gen_sari_i64(tcg_rd, tcg_rd, 64 - (pos + len));
2655
if (!sf) { /* zero extend final result */
2656
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2661
* 31 30 29 28 23 22 21 20 16 15 10 9 5 4 0
2662
* +----+------+-------------+---+----+------+--------+------+------+
2663
* | sf | op21 | 1 0 0 1 1 1 | N | o0 | Rm | imms | Rn | Rd |
2664
* +----+------+-------------+---+----+------+--------+------+------+
2666
static void disas_extract(DisasContext *s, uint32_t insn)
2668
unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
2670
sf = extract32(insn, 31, 1);
2671
n = extract32(insn, 22, 1);
2672
rm = extract32(insn, 16, 5);
2673
imm = extract32(insn, 10, 6);
2674
rn = extract32(insn, 5, 5);
2675
rd = extract32(insn, 0, 5);
2676
op21 = extract32(insn, 29, 2);
2677
op0 = extract32(insn, 21, 1);
2678
bitsize = sf ? 64 : 32;
2680
if (sf != n || op21 || op0 || imm >= bitsize) {
2681
unallocated_encoding(s);
2683
TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
2685
tcg_rd = cpu_reg(s, rd);
2688
/* OPTME: we can special case rm==rn as a rotate */
2689
tcg_rm = read_cpu_reg(s, rm, sf);
2690
tcg_rn = read_cpu_reg(s, rn, sf);
2691
tcg_gen_shri_i64(tcg_rm, tcg_rm, imm);
2692
tcg_gen_shli_i64(tcg_rn, tcg_rn, bitsize - imm);
2693
tcg_gen_or_i64(tcg_rd, tcg_rm, tcg_rn);
2695
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2698
/* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
2699
* so an extract from bit 0 is a special case.
2702
tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
2704
tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
2711
/* C3.4 Data processing - immediate */
2712
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
2714
switch (extract32(insn, 23, 6)) {
2715
case 0x20: case 0x21: /* PC-rel. addressing */
2716
disas_pc_rel_adr(s, insn);
2718
case 0x22: case 0x23: /* Add/subtract (immediate) */
2719
disas_add_sub_imm(s, insn);
2721
case 0x24: /* Logical (immediate) */
2722
disas_logic_imm(s, insn);
2724
case 0x25: /* Move wide (immediate) */
2725
disas_movw_imm(s, insn);
2727
case 0x26: /* Bitfield */
2728
disas_bitfield(s, insn);
2730
case 0x27: /* Extract */
2731
disas_extract(s, insn);
2734
unallocated_encoding(s);
2739
/* Shift a TCGv src by TCGv shift_amount, put result in dst.
2740
* Note that it is the caller's responsibility to ensure that the
2741
* shift amount is in range (ie 0..31 or 0..63) and provide the ARM
2742
* mandated semantics for out of range shifts.
2744
static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
2745
enum a64_shift_type shift_type, TCGv_i64 shift_amount)
2747
switch (shift_type) {
2748
case A64_SHIFT_TYPE_LSL:
2749
tcg_gen_shl_i64(dst, src, shift_amount);
2751
case A64_SHIFT_TYPE_LSR:
2752
tcg_gen_shr_i64(dst, src, shift_amount);
2754
case A64_SHIFT_TYPE_ASR:
2756
tcg_gen_ext32s_i64(dst, src);
2758
tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
2760
case A64_SHIFT_TYPE_ROR:
2762
tcg_gen_rotr_i64(dst, src, shift_amount);
2765
t0 = tcg_temp_new_i32();
2766
t1 = tcg_temp_new_i32();
2767
tcg_gen_trunc_i64_i32(t0, src);
2768
tcg_gen_trunc_i64_i32(t1, shift_amount);
2769
tcg_gen_rotr_i32(t0, t0, t1);
2770
tcg_gen_extu_i32_i64(dst, t0);
2771
tcg_temp_free_i32(t0);
2772
tcg_temp_free_i32(t1);
2776
assert(FALSE); /* all shift types should be handled */
2780
if (!sf) { /* zero extend final result */
2781
tcg_gen_ext32u_i64(dst, dst);
2785
/* Shift a TCGv src by immediate, put result in dst.
2786
* The shift amount must be in range (this should always be true as the
2787
* relevant instructions will UNDEF on bad shift immediates).
2789
static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
2790
enum a64_shift_type shift_type, unsigned int shift_i)
2792
assert(shift_i < (sf ? 64 : 32));
2795
tcg_gen_mov_i64(dst, src);
2797
TCGv_i64 shift_const;
2799
shift_const = tcg_const_i64(shift_i);
2800
shift_reg(dst, src, sf, shift_type, shift_const);
2801
tcg_temp_free_i64(shift_const);
2805
/* C3.5.10 Logical (shifted register)
2806
* 31 30 29 28 24 23 22 21 20 16 15 10 9 5 4 0
2807
* +----+-----+-----------+-------+---+------+--------+------+------+
2808
* | sf | opc | 0 1 0 1 0 | shift | N | Rm | imm6 | Rn | Rd |
2809
* +----+-----+-----------+-------+---+------+--------+------+------+
2811
static void disas_logic_reg(DisasContext *s, uint32_t insn)
2813
TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
2814
unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
2816
sf = extract32(insn, 31, 1);
2817
opc = extract32(insn, 29, 2);
2818
shift_type = extract32(insn, 22, 2);
2819
invert = extract32(insn, 21, 1);
2820
rm = extract32(insn, 16, 5);
2821
shift_amount = extract32(insn, 10, 6);
2822
rn = extract32(insn, 5, 5);
2823
rd = extract32(insn, 0, 5);
2825
if (!sf && (shift_amount & (1 << 5))) {
2826
unallocated_encoding(s);
2830
tcg_rd = cpu_reg(s, rd);
2832
if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
2833
/* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
2834
* register-register MOV and MVN, so it is worth special casing.
2836
tcg_rm = cpu_reg(s, rm);
2838
tcg_gen_not_i64(tcg_rd, tcg_rm);
2840
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2844
tcg_gen_mov_i64(tcg_rd, tcg_rm);
2846
tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
2852
tcg_rm = read_cpu_reg(s, rm, sf);
2855
shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
2858
tcg_rn = cpu_reg(s, rn);
2860
switch (opc | (invert << 2)) {
2863
tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
2866
tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
2869
tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
2873
tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
2876
tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
2879
tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
2887
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2891
gen_logic_CC(sf, tcg_rd);
2896
* C3.5.1 Add/subtract (extended register)
2898
* 31|30|29|28 24|23 22|21|20 16|15 13|12 10|9 5|4 0|
2899
* +--+--+--+-----------+-----+--+-------+------+------+----+----+
2900
* |sf|op| S| 0 1 0 1 1 | opt | 1| Rm |option| imm3 | Rn | Rd |
2901
* +--+--+--+-----------+-----+--+-------+------+------+----+----+
2903
* sf: 0 -> 32bit, 1 -> 64bit
2904
* op: 0 -> add , 1 -> sub
2907
* option: extension type (see DecodeRegExtend)
2908
* imm3: optional shift to Rm
2910
* Rd = Rn + LSL(extend(Rm), amount)
2912
static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
2914
int rd = extract32(insn, 0, 5);
2915
int rn = extract32(insn, 5, 5);
2916
int imm3 = extract32(insn, 10, 3);
2917
int option = extract32(insn, 13, 3);
2918
int rm = extract32(insn, 16, 5);
2919
bool setflags = extract32(insn, 29, 1);
2920
bool sub_op = extract32(insn, 30, 1);
2921
bool sf = extract32(insn, 31, 1);
2923
TCGv_i64 tcg_rm, tcg_rn; /* temps */
2925
TCGv_i64 tcg_result;
2928
unallocated_encoding(s);
2932
/* non-flag setting ops may use SP */
2934
tcg_rn = read_cpu_reg_sp(s, rn, sf);
2935
tcg_rd = cpu_reg_sp(s, rd);
2937
tcg_rn = read_cpu_reg(s, rn, sf);
2938
tcg_rd = cpu_reg(s, rd);
2941
tcg_rm = read_cpu_reg(s, rm, sf);
2942
ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
2944
tcg_result = tcg_temp_new_i64();
2948
tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
2950
tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
2954
gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
2956
gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
2961
tcg_gen_mov_i64(tcg_rd, tcg_result);
2963
tcg_gen_ext32u_i64(tcg_rd, tcg_result);
2966
tcg_temp_free_i64(tcg_result);
2970
* C3.5.2 Add/subtract (shifted register)
2972
* 31 30 29 28 24 23 22 21 20 16 15 10 9 5 4 0
2973
* +--+--+--+-----------+-----+--+-------+---------+------+------+
2974
* |sf|op| S| 0 1 0 1 1 |shift| 0| Rm | imm6 | Rn | Rd |
2975
* +--+--+--+-----------+-----+--+-------+---------+------+------+
2977
* sf: 0 -> 32bit, 1 -> 64bit
2978
* op: 0 -> add , 1 -> sub
2980
* shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
2981
* imm6: Shift amount to apply to Rm before the add/sub
2983
static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
2985
int rd = extract32(insn, 0, 5);
2986
int rn = extract32(insn, 5, 5);
2987
int imm6 = extract32(insn, 10, 6);
2988
int rm = extract32(insn, 16, 5);
2989
int shift_type = extract32(insn, 22, 2);
2990
bool setflags = extract32(insn, 29, 1);
2991
bool sub_op = extract32(insn, 30, 1);
2992
bool sf = extract32(insn, 31, 1);
2994
TCGv_i64 tcg_rd = cpu_reg(s, rd);
2995
TCGv_i64 tcg_rn, tcg_rm;
2996
TCGv_i64 tcg_result;
2998
if ((shift_type == 3) || (!sf && (imm6 > 31))) {
2999
unallocated_encoding(s);
3003
tcg_rn = read_cpu_reg(s, rn, sf);
3004
tcg_rm = read_cpu_reg(s, rm, sf);
3006
shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
3008
tcg_result = tcg_temp_new_i64();
3012
tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
3014
tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
3018
gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
3020
gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
3025
tcg_gen_mov_i64(tcg_rd, tcg_result);
3027
tcg_gen_ext32u_i64(tcg_rd, tcg_result);
3030
tcg_temp_free_i64(tcg_result);
3033
/* C3.5.9 Data-processing (3 source)
3035
31 30 29 28 24 23 21 20 16 15 14 10 9 5 4 0
3036
+--+------+-----------+------+------+----+------+------+------+
3037
|sf| op54 | 1 1 0 1 1 | op31 | Rm | o0 | Ra | Rn | Rd |
3038
+--+------+-----------+------+------+----+------+------+------+
3041
static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
3043
int rd = extract32(insn, 0, 5);
3044
int rn = extract32(insn, 5, 5);
3045
int ra = extract32(insn, 10, 5);
3046
int rm = extract32(insn, 16, 5);
3047
int op_id = (extract32(insn, 29, 3) << 4) |
3048
(extract32(insn, 21, 3) << 1) |
3049
extract32(insn, 15, 1);
3050
bool sf = extract32(insn, 31, 1);
3051
bool is_sub = extract32(op_id, 0, 1);
3052
bool is_high = extract32(op_id, 2, 1);
3053
bool is_signed = false;
3058
/* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
3060
case 0x42: /* SMADDL */
3061
case 0x43: /* SMSUBL */
3062
case 0x44: /* SMULH */
3065
case 0x0: /* MADD (32bit) */
3066
case 0x1: /* MSUB (32bit) */
3067
case 0x40: /* MADD (64bit) */
3068
case 0x41: /* MSUB (64bit) */
3069
case 0x4a: /* UMADDL */
3070
case 0x4b: /* UMSUBL */
3071
case 0x4c: /* UMULH */
3074
unallocated_encoding(s);
3079
TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */
3080
TCGv_i64 tcg_rd = cpu_reg(s, rd);
3081
TCGv_i64 tcg_rn = cpu_reg(s, rn);
3082
TCGv_i64 tcg_rm = cpu_reg(s, rm);
3085
tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
3087
tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
3090
tcg_temp_free_i64(low_bits);
3094
tcg_op1 = tcg_temp_new_i64();
3095
tcg_op2 = tcg_temp_new_i64();
3096
tcg_tmp = tcg_temp_new_i64();
3099
tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn));
3100
tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm));
3103
tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn));
3104
tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm));
3106
tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn));
3107
tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm));
3111
if (ra == 31 && !is_sub) {
3112
/* Special-case MADD with rA == XZR; it is the standard MUL alias */
3113
tcg_gen_mul_i64(cpu_reg(s, rd), tcg_op1, tcg_op2);
3115
tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2);
3117
tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
3119
tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
3124
tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd));
3127
tcg_temp_free_i64(tcg_op1);
3128
tcg_temp_free_i64(tcg_op2);
3129
tcg_temp_free_i64(tcg_tmp);
3132
/* C3.5.3 - Add/subtract (with carry)
3133
* 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
3134
* +--+--+--+------------------------+------+---------+------+-----+
3135
* |sf|op| S| 1 1 0 1 0 0 0 0 | rm | opcode2 | Rn | Rd |
3136
* +--+--+--+------------------------+------+---------+------+-----+
3140
static void disas_adc_sbc(DisasContext *s, uint32_t insn)
3142
unsigned int sf, op, setflags, rm, rn, rd;
3143
TCGv_i64 tcg_y, tcg_rn, tcg_rd;
3145
if (extract32(insn, 10, 6) != 0) {
3146
unallocated_encoding(s);
3150
sf = extract32(insn, 31, 1);
3151
op = extract32(insn, 30, 1);
3152
setflags = extract32(insn, 29, 1);
3153
rm = extract32(insn, 16, 5);
3154
rn = extract32(insn, 5, 5);
3155
rd = extract32(insn, 0, 5);
3157
tcg_rd = cpu_reg(s, rd);
3158
tcg_rn = cpu_reg(s, rn);
3161
tcg_y = new_tmp_a64(s);
3162
tcg_gen_not_i64(tcg_y, cpu_reg(s, rm));
3164
tcg_y = cpu_reg(s, rm);
3168
gen_adc_CC(sf, tcg_rd, tcg_rn, tcg_y);
3170
gen_adc(sf, tcg_rd, tcg_rn, tcg_y);
3174
/* C3.5.4 - C3.5.5 Conditional compare (immediate / register)
3175
* 31 30 29 28 27 26 25 24 23 22 21 20 16 15 12 11 10 9 5 4 3 0
3176
* +--+--+--+------------------------+--------+------+----+--+------+--+-----+
3177
* |sf|op| S| 1 1 0 1 0 0 1 0 |imm5/rm | cond |i/r |o2| Rn |o3|nzcv |
3178
* +--+--+--+------------------------+--------+------+----+--+------+--+-----+
3181
static void disas_cc(DisasContext *s, uint32_t insn)
3183
unsigned int sf, op, y, cond, rn, nzcv, is_imm;
3184
int label_continue = -1;
3185
TCGv_i64 tcg_tmp, tcg_y, tcg_rn;
3187
if (!extract32(insn, 29, 1)) {
3188
unallocated_encoding(s);
3191
if (insn & (1 << 10 | 1 << 4)) {
3192
unallocated_encoding(s);
3195
sf = extract32(insn, 31, 1);
3196
op = extract32(insn, 30, 1);
3197
is_imm = extract32(insn, 11, 1);
3198
y = extract32(insn, 16, 5); /* y = rm (reg) or imm5 (imm) */
3199
cond = extract32(insn, 12, 4);
3200
rn = extract32(insn, 5, 5);
3201
nzcv = extract32(insn, 0, 4);
3203
if (cond < 0x0e) { /* not always */
3204
int label_match = gen_new_label();
3205
label_continue = gen_new_label();
3206
arm_gen_test_cc(cond, label_match);
3208
tcg_tmp = tcg_temp_new_i64();
3209
tcg_gen_movi_i64(tcg_tmp, nzcv << 28);
3210
gen_set_nzcv(tcg_tmp);
3211
tcg_temp_free_i64(tcg_tmp);
3212
tcg_gen_br(label_continue);
3213
gen_set_label(label_match);
3215
/* match, or condition is always */
3217
tcg_y = new_tmp_a64(s);
3218
tcg_gen_movi_i64(tcg_y, y);
3220
tcg_y = cpu_reg(s, y);
3222
tcg_rn = cpu_reg(s, rn);
3224
tcg_tmp = tcg_temp_new_i64();
3226
gen_sub_CC(sf, tcg_tmp, tcg_rn, tcg_y);
3228
gen_add_CC(sf, tcg_tmp, tcg_rn, tcg_y);
3230
tcg_temp_free_i64(tcg_tmp);
3232
if (cond < 0x0e) { /* continue */
3233
gen_set_label(label_continue);
3237
/* C3.5.6 Conditional select
3238
* 31 30 29 28 21 20 16 15 12 11 10 9 5 4 0
3239
* +----+----+---+-----------------+------+------+-----+------+------+
3240
* | sf | op | S | 1 1 0 1 0 1 0 0 | Rm | cond | op2 | Rn | Rd |
3241
* +----+----+---+-----------------+------+------+-----+------+------+
3243
static void disas_cond_select(DisasContext *s, uint32_t insn)
3245
unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
3246
TCGv_i64 tcg_rd, tcg_src;
3248
if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
3249
/* S == 1 or op2<1> == 1 */
3250
unallocated_encoding(s);
3253
sf = extract32(insn, 31, 1);
3254
else_inv = extract32(insn, 30, 1);
3255
rm = extract32(insn, 16, 5);
3256
cond = extract32(insn, 12, 4);
3257
else_inc = extract32(insn, 10, 1);
3258
rn = extract32(insn, 5, 5);
3259
rd = extract32(insn, 0, 5);
3262
/* silly no-op write; until we use movcond we must special-case
3263
* this to avoid a dead temporary across basic blocks.
3268
tcg_rd = cpu_reg(s, rd);
3270
if (cond >= 0x0e) { /* condition "always" */
3271
tcg_src = read_cpu_reg(s, rn, sf);
3272
tcg_gen_mov_i64(tcg_rd, tcg_src);
3274
/* OPTME: we could use movcond here, at the cost of duplicating
3275
* a lot of the arm_gen_test_cc() logic.
3277
int label_match = gen_new_label();
3278
int label_continue = gen_new_label();
3280
arm_gen_test_cc(cond, label_match);
3282
tcg_src = cpu_reg(s, rm);
3284
if (else_inv && else_inc) {
3285
tcg_gen_neg_i64(tcg_rd, tcg_src);
3286
} else if (else_inv) {
3287
tcg_gen_not_i64(tcg_rd, tcg_src);
3288
} else if (else_inc) {
3289
tcg_gen_addi_i64(tcg_rd, tcg_src, 1);
3291
tcg_gen_mov_i64(tcg_rd, tcg_src);
3294
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3296
tcg_gen_br(label_continue);
3298
gen_set_label(label_match);
3299
tcg_src = read_cpu_reg(s, rn, sf);
3300
tcg_gen_mov_i64(tcg_rd, tcg_src);
3302
gen_set_label(label_continue);
3306
static void handle_clz(DisasContext *s, unsigned int sf,
3307
unsigned int rn, unsigned int rd)
3309
TCGv_i64 tcg_rd, tcg_rn;
3310
tcg_rd = cpu_reg(s, rd);
3311
tcg_rn = cpu_reg(s, rn);
3314
gen_helper_clz64(tcg_rd, tcg_rn);
3316
TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3317
tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3318
gen_helper_clz(tcg_tmp32, tcg_tmp32);
3319
tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3320
tcg_temp_free_i32(tcg_tmp32);
3324
static void handle_cls(DisasContext *s, unsigned int sf,
3325
unsigned int rn, unsigned int rd)
3327
TCGv_i64 tcg_rd, tcg_rn;
3328
tcg_rd = cpu_reg(s, rd);
3329
tcg_rn = cpu_reg(s, rn);
3332
gen_helper_cls64(tcg_rd, tcg_rn);
3334
TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3335
tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3336
gen_helper_cls32(tcg_tmp32, tcg_tmp32);
3337
tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3338
tcg_temp_free_i32(tcg_tmp32);
3342
static void handle_rbit(DisasContext *s, unsigned int sf,
3343
unsigned int rn, unsigned int rd)
3345
TCGv_i64 tcg_rd, tcg_rn;
3346
tcg_rd = cpu_reg(s, rd);
3347
tcg_rn = cpu_reg(s, rn);
3350
gen_helper_rbit64(tcg_rd, tcg_rn);
3352
TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3353
tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3354
gen_helper_rbit(tcg_tmp32, tcg_tmp32);
3355
tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3356
tcg_temp_free_i32(tcg_tmp32);
3360
/* C5.6.149 REV with sf==1, opcode==3 ("REV64") */
3361
static void handle_rev64(DisasContext *s, unsigned int sf,
3362
unsigned int rn, unsigned int rd)
3365
unallocated_encoding(s);
3368
tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
3371
/* C5.6.149 REV with sf==0, opcode==2
3372
* C5.6.151 REV32 (sf==1, opcode==2)
3374
static void handle_rev32(DisasContext *s, unsigned int sf,
3375
unsigned int rn, unsigned int rd)
3377
TCGv_i64 tcg_rd = cpu_reg(s, rd);
3380
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3381
TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3383
/* bswap32_i64 requires zero high word */
3384
tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
3385
tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
3386
tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
3387
tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
3388
tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
3390
tcg_temp_free_i64(tcg_tmp);
3392
tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
3393
tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
3397
/* C5.6.150 REV16 (opcode==1) */
3398
static void handle_rev16(DisasContext *s, unsigned int sf,
3399
unsigned int rn, unsigned int rd)
3401
TCGv_i64 tcg_rd = cpu_reg(s, rd);
3402
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3403
TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3405
tcg_gen_andi_i64(tcg_tmp, tcg_rn, 0xffff);
3406
tcg_gen_bswap16_i64(tcg_rd, tcg_tmp);
3408
tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16);
3409
tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
3410
tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3411
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 16, 16);
3414
tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
3415
tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
3416
tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3417
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 32, 16);
3419
tcg_gen_shri_i64(tcg_tmp, tcg_rn, 48);
3420
tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3421
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 48, 16);
3424
tcg_temp_free_i64(tcg_tmp);
3427
/* C3.5.7 Data-processing (1 source)
3428
* 31 30 29 28 21 20 16 15 10 9 5 4 0
3429
* +----+---+---+-----------------+---------+--------+------+------+
3430
* | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode | Rn | Rd |
3431
* +----+---+---+-----------------+---------+--------+------+------+
3433
static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
3435
unsigned int sf, opcode, rn, rd;
3437
if (extract32(insn, 29, 1) || extract32(insn, 16, 5)) {
3438
unallocated_encoding(s);
3442
sf = extract32(insn, 31, 1);
3443
opcode = extract32(insn, 10, 6);
3444
rn = extract32(insn, 5, 5);
3445
rd = extract32(insn, 0, 5);
3449
handle_rbit(s, sf, rn, rd);
3452
handle_rev16(s, sf, rn, rd);
3455
handle_rev32(s, sf, rn, rd);
3458
handle_rev64(s, sf, rn, rd);
3461
handle_clz(s, sf, rn, rd);
3464
handle_cls(s, sf, rn, rd);
3469
static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
3470
unsigned int rm, unsigned int rn, unsigned int rd)
3472
TCGv_i64 tcg_n, tcg_m, tcg_rd;
3473
tcg_rd = cpu_reg(s, rd);
3475
if (!sf && is_signed) {
3476
tcg_n = new_tmp_a64(s);
3477
tcg_m = new_tmp_a64(s);
3478
tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
3479
tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
3481
tcg_n = read_cpu_reg(s, rn, sf);
3482
tcg_m = read_cpu_reg(s, rm, sf);
3486
gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
3488
gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
3491
if (!sf) { /* zero extend final result */
3492
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3496
/* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
3497
static void handle_shift_reg(DisasContext *s,
3498
enum a64_shift_type shift_type, unsigned int sf,
3499
unsigned int rm, unsigned int rn, unsigned int rd)
3501
TCGv_i64 tcg_shift = tcg_temp_new_i64();
3502
TCGv_i64 tcg_rd = cpu_reg(s, rd);
3503
TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3505
tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
3506
shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
3507
tcg_temp_free_i64(tcg_shift);
3510
/* C3.5.8 Data-processing (2 source)
3511
* 31 30 29 28 21 20 16 15 10 9 5 4 0
3512
* +----+---+---+-----------------+------+--------+------+------+
3513
* | sf | 0 | S | 1 1 0 1 0 1 1 0 | Rm | opcode | Rn | Rd |
3514
* +----+---+---+-----------------+------+--------+------+------+
3516
static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
3518
unsigned int sf, rm, opcode, rn, rd;
3519
sf = extract32(insn, 31, 1);
3520
rm = extract32(insn, 16, 5);
3521
opcode = extract32(insn, 10, 6);
3522
rn = extract32(insn, 5, 5);
3523
rd = extract32(insn, 0, 5);
3525
if (extract32(insn, 29, 1)) {
3526
unallocated_encoding(s);
3532
handle_div(s, false, sf, rm, rn, rd);
3535
handle_div(s, true, sf, rm, rn, rd);
3538
handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
3541
handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
3544
handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
3547
handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
3556
case 23: /* CRC32 */
3557
unsupported_encoding(s, insn);
3560
unallocated_encoding(s);
3565
/* C3.5 Data processing - register */
3566
static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
3568
switch (extract32(insn, 24, 5)) {
3569
case 0x0a: /* Logical (shifted register) */
3570
disas_logic_reg(s, insn);
3572
case 0x0b: /* Add/subtract */
3573
if (insn & (1 << 21)) { /* (extended register) */
3574
disas_add_sub_ext_reg(s, insn);
3576
disas_add_sub_reg(s, insn);
3579
case 0x1b: /* Data-processing (3 source) */
3580
disas_data_proc_3src(s, insn);
3583
switch (extract32(insn, 21, 3)) {
3584
case 0x0: /* Add/subtract (with carry) */
3585
disas_adc_sbc(s, insn);
3587
case 0x2: /* Conditional compare */
3588
disas_cc(s, insn); /* both imm and reg forms */
3590
case 0x4: /* Conditional select */
3591
disas_cond_select(s, insn);
3593
case 0x6: /* Data-processing */
3594
if (insn & (1 << 30)) { /* (1 source) */
3595
disas_data_proc_1src(s, insn);
3596
} else { /* (2 source) */
3597
disas_data_proc_2src(s, insn);
3601
unallocated_encoding(s);
3606
unallocated_encoding(s);
3611
/* Convert ARM rounding mode to softfloat */
3612
static inline int arm_rmode_to_sf(int rmode)
3615
case FPROUNDING_TIEAWAY:
3616
rmode = float_round_ties_away;
3618
case FPROUNDING_ODD:
3619
/* FIXME: add support for TIEAWAY and ODD */
3620
qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
3622
case FPROUNDING_TIEEVEN:
3624
rmode = float_round_nearest_even;
3626
case FPROUNDING_POSINF:
3627
rmode = float_round_up;
3629
case FPROUNDING_NEGINF:
3630
rmode = float_round_down;
3632
case FPROUNDING_ZERO:
3633
rmode = float_round_to_zero;
3639
static void handle_fp_compare(DisasContext *s, bool is_double,
3640
unsigned int rn, unsigned int rm,
3641
bool cmp_with_zero, bool signal_all_nans)
3643
TCGv_i64 tcg_flags = tcg_temp_new_i64();
3644
TCGv_ptr fpst = get_fpstatus_ptr();
3647
TCGv_i64 tcg_vn, tcg_vm;
3649
tcg_vn = read_fp_dreg(s, rn);
3650
if (cmp_with_zero) {
3651
tcg_vm = tcg_const_i64(0);
3653
tcg_vm = read_fp_dreg(s, rm);
3655
if (signal_all_nans) {
3656
gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3658
gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3660
tcg_temp_free_i64(tcg_vn);
3661
tcg_temp_free_i64(tcg_vm);
3663
TCGv_i32 tcg_vn, tcg_vm;
3665
tcg_vn = read_fp_sreg(s, rn);
3666
if (cmp_with_zero) {
3667
tcg_vm = tcg_const_i32(0);
3669
tcg_vm = read_fp_sreg(s, rm);
3671
if (signal_all_nans) {
3672
gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3674
gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3676
tcg_temp_free_i32(tcg_vn);
3677
tcg_temp_free_i32(tcg_vm);
3680
tcg_temp_free_ptr(fpst);
3682
gen_set_nzcv(tcg_flags);
3684
tcg_temp_free_i64(tcg_flags);
3687
/* C3.6.22 Floating point compare
3688
* 31 30 29 28 24 23 22 21 20 16 15 14 13 10 9 5 4 0
3689
* +---+---+---+-----------+------+---+------+-----+---------+------+-------+
3690
* | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | op | 1 0 0 0 | Rn | op2 |
3691
* +---+---+---+-----------+------+---+------+-----+---------+------+-------+
3693
static void disas_fp_compare(DisasContext *s, uint32_t insn)
3695
unsigned int mos, type, rm, op, rn, opc, op2r;
3697
mos = extract32(insn, 29, 3);
3698
type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3699
rm = extract32(insn, 16, 5);
3700
op = extract32(insn, 14, 2);
3701
rn = extract32(insn, 5, 5);
3702
opc = extract32(insn, 3, 2);
3703
op2r = extract32(insn, 0, 3);
3705
if (mos || op || op2r || type > 1) {
3706
unallocated_encoding(s);
3710
handle_fp_compare(s, type, rn, rm, opc & 1, opc & 2);
3713
/* C3.6.23 Floating point conditional compare
3714
* 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 3 0
3715
* +---+---+---+-----------+------+---+------+------+-----+------+----+------+
3716
* | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | cond | 0 1 | Rn | op | nzcv |
3717
* +---+---+---+-----------+------+---+------+------+-----+------+----+------+
3719
static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
3721
unsigned int mos, type, rm, cond, rn, op, nzcv;
3723
int label_continue = -1;
3725
mos = extract32(insn, 29, 3);
3726
type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3727
rm = extract32(insn, 16, 5);
3728
cond = extract32(insn, 12, 4);
3729
rn = extract32(insn, 5, 5);
3730
op = extract32(insn, 4, 1);
3731
nzcv = extract32(insn, 0, 4);
3733
if (mos || type > 1) {
3734
unallocated_encoding(s);
3738
if (cond < 0x0e) { /* not always */
3739
int label_match = gen_new_label();
3740
label_continue = gen_new_label();
3741
arm_gen_test_cc(cond, label_match);
3743
tcg_flags = tcg_const_i64(nzcv << 28);
3744
gen_set_nzcv(tcg_flags);
3745
tcg_temp_free_i64(tcg_flags);
3746
tcg_gen_br(label_continue);
3747
gen_set_label(label_match);
3750
handle_fp_compare(s, type, rn, rm, false, op);
3753
gen_set_label(label_continue);
3757
/* copy src FP register to dst FP register; type specifies single or double */
3758
static void gen_mov_fp2fp(DisasContext *s, int type, int dst, int src)
3761
TCGv_i64 v = read_fp_dreg(s, src);
3762
write_fp_dreg(s, dst, v);
3763
tcg_temp_free_i64(v);
3765
TCGv_i32 v = read_fp_sreg(s, src);
3766
write_fp_sreg(s, dst, v);
3767
tcg_temp_free_i32(v);
3771
/* C3.6.24 Floating point conditional select
3772
* 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
3773
* +---+---+---+-----------+------+---+------+------+-----+------+------+
3774
* | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | cond | 1 1 | Rn | Rd |
3775
* +---+---+---+-----------+------+---+------+------+-----+------+------+
3777
static void disas_fp_csel(DisasContext *s, uint32_t insn)
3779
unsigned int mos, type, rm, cond, rn, rd;
3780
int label_continue = -1;
3782
mos = extract32(insn, 29, 3);
3783
type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3784
rm = extract32(insn, 16, 5);
3785
cond = extract32(insn, 12, 4);
3786
rn = extract32(insn, 5, 5);
3787
rd = extract32(insn, 0, 5);
3789
if (mos || type > 1) {
3790
unallocated_encoding(s);
3794
if (cond < 0x0e) { /* not always */
3795
int label_match = gen_new_label();
3796
label_continue = gen_new_label();
3797
arm_gen_test_cc(cond, label_match);
3799
gen_mov_fp2fp(s, type, rd, rm);
3800
tcg_gen_br(label_continue);
3801
gen_set_label(label_match);
3804
gen_mov_fp2fp(s, type, rd, rn);
3806
if (cond < 0x0e) { /* continue */
3807
gen_set_label(label_continue);
3811
/* C3.6.25 Floating-point data-processing (1 source) - single precision */
3812
static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
3818
fpst = get_fpstatus_ptr();
3819
tcg_op = read_fp_sreg(s, rn);
3820
tcg_res = tcg_temp_new_i32();
3823
case 0x0: /* FMOV */
3824
tcg_gen_mov_i32(tcg_res, tcg_op);
3826
case 0x1: /* FABS */
3827
gen_helper_vfp_abss(tcg_res, tcg_op);
3829
case 0x2: /* FNEG */
3830
gen_helper_vfp_negs(tcg_res, tcg_op);
3832
case 0x3: /* FSQRT */
3833
gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
3835
case 0x8: /* FRINTN */
3836
case 0x9: /* FRINTP */
3837
case 0xa: /* FRINTM */
3838
case 0xb: /* FRINTZ */
3839
case 0xc: /* FRINTA */
3841
TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
3843
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3844
gen_helper_rints(tcg_res, tcg_op, fpst);
3846
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3847
tcg_temp_free_i32(tcg_rmode);
3850
case 0xe: /* FRINTX */
3851
gen_helper_rints_exact(tcg_res, tcg_op, fpst);
3853
case 0xf: /* FRINTI */
3854
gen_helper_rints(tcg_res, tcg_op, fpst);
3860
write_fp_sreg(s, rd, tcg_res);
3862
tcg_temp_free_ptr(fpst);
3863
tcg_temp_free_i32(tcg_op);
3864
tcg_temp_free_i32(tcg_res);
3867
/* C3.6.25 Floating-point data-processing (1 source) - double precision */
3868
static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
3874
fpst = get_fpstatus_ptr();
3875
tcg_op = read_fp_dreg(s, rn);
3876
tcg_res = tcg_temp_new_i64();
3879
case 0x0: /* FMOV */
3880
tcg_gen_mov_i64(tcg_res, tcg_op);
3882
case 0x1: /* FABS */
3883
gen_helper_vfp_absd(tcg_res, tcg_op);
3885
case 0x2: /* FNEG */
3886
gen_helper_vfp_negd(tcg_res, tcg_op);
3888
case 0x3: /* FSQRT */
3889
gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
3891
case 0x8: /* FRINTN */
3892
case 0x9: /* FRINTP */
3893
case 0xa: /* FRINTM */
3894
case 0xb: /* FRINTZ */
3895
case 0xc: /* FRINTA */
3897
TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
3899
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3900
gen_helper_rintd(tcg_res, tcg_op, fpst);
3902
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3903
tcg_temp_free_i32(tcg_rmode);
3906
case 0xe: /* FRINTX */
3907
gen_helper_rintd_exact(tcg_res, tcg_op, fpst);
3909
case 0xf: /* FRINTI */
3910
gen_helper_rintd(tcg_res, tcg_op, fpst);
3916
write_fp_dreg(s, rd, tcg_res);
3918
tcg_temp_free_ptr(fpst);
3919
tcg_temp_free_i64(tcg_op);
3920
tcg_temp_free_i64(tcg_res);
3923
static void handle_fp_fcvt(DisasContext *s, int opcode,
3924
int rd, int rn, int dtype, int ntype)
3929
TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
3931
/* Single to double */
3932
TCGv_i64 tcg_rd = tcg_temp_new_i64();
3933
gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, cpu_env);
3934
write_fp_dreg(s, rd, tcg_rd);
3935
tcg_temp_free_i64(tcg_rd);
3937
/* Single to half */
3938
TCGv_i32 tcg_rd = tcg_temp_new_i32();
3939
gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, cpu_env);
3940
/* write_fp_sreg is OK here because top half of tcg_rd is zero */
3941
write_fp_sreg(s, rd, tcg_rd);
3942
tcg_temp_free_i32(tcg_rd);
3944
tcg_temp_free_i32(tcg_rn);
3949
TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
3950
TCGv_i32 tcg_rd = tcg_temp_new_i32();
3952
/* Double to single */
3953
gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
3955
/* Double to half */
3956
gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, cpu_env);
3957
/* write_fp_sreg is OK here because top half of tcg_rd is zero */
3959
write_fp_sreg(s, rd, tcg_rd);
3960
tcg_temp_free_i32(tcg_rd);
3961
tcg_temp_free_i64(tcg_rn);
3966
TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
3967
tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
3969
/* Half to single */
3970
TCGv_i32 tcg_rd = tcg_temp_new_i32();
3971
gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, cpu_env);
3972
write_fp_sreg(s, rd, tcg_rd);
3973
tcg_temp_free_i32(tcg_rd);
3975
/* Half to double */
3976
TCGv_i64 tcg_rd = tcg_temp_new_i64();
3977
gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, cpu_env);
3978
write_fp_dreg(s, rd, tcg_rd);
3979
tcg_temp_free_i64(tcg_rd);
3981
tcg_temp_free_i32(tcg_rn);
3989
/* C3.6.25 Floating point data-processing (1 source)
3990
* 31 30 29 28 24 23 22 21 20 15 14 10 9 5 4 0
3991
* +---+---+---+-----------+------+---+--------+-----------+------+------+
3992
* | M | 0 | S | 1 1 1 1 0 | type | 1 | opcode | 1 0 0 0 0 | Rn | Rd |
3993
* +---+---+---+-----------+------+---+--------+-----------+------+------+
3995
static void disas_fp_1src(DisasContext *s, uint32_t insn)
3997
int type = extract32(insn, 22, 2);
3998
int opcode = extract32(insn, 15, 6);
3999
int rn = extract32(insn, 5, 5);
4000
int rd = extract32(insn, 0, 5);
4003
case 0x4: case 0x5: case 0x7:
4005
/* FCVT between half, single and double precision */
4006
int dtype = extract32(opcode, 0, 2);
4007
if (type == 2 || dtype == type) {
4008
unallocated_encoding(s);
4011
handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
4017
/* 32-to-32 and 64-to-64 ops */
4020
handle_fp_1src_single(s, opcode, rd, rn);
4023
handle_fp_1src_double(s, opcode, rd, rn);
4026
unallocated_encoding(s);
4030
unallocated_encoding(s);
4035
/* C3.6.26 Floating-point data-processing (2 source) - single precision */
4036
static void handle_fp_2src_single(DisasContext *s, int opcode,
4037
int rd, int rn, int rm)
4044
tcg_res = tcg_temp_new_i32();
4045
fpst = get_fpstatus_ptr();
4046
tcg_op1 = read_fp_sreg(s, rn);
4047
tcg_op2 = read_fp_sreg(s, rm);
4050
case 0x0: /* FMUL */
4051
gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
4053
case 0x1: /* FDIV */
4054
gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
4056
case 0x2: /* FADD */
4057
gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
4059
case 0x3: /* FSUB */
4060
gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
4062
case 0x4: /* FMAX */
4063
gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
4065
case 0x5: /* FMIN */
4066
gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
4068
case 0x6: /* FMAXNM */
4069
gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
4071
case 0x7: /* FMINNM */
4072
gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
4074
case 0x8: /* FNMUL */
4075
gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
4076
gen_helper_vfp_negs(tcg_res, tcg_res);
4080
write_fp_sreg(s, rd, tcg_res);
4082
tcg_temp_free_ptr(fpst);
4083
tcg_temp_free_i32(tcg_op1);
4084
tcg_temp_free_i32(tcg_op2);
4085
tcg_temp_free_i32(tcg_res);
4088
/* C3.6.26 Floating-point data-processing (2 source) - double precision */
4089
static void handle_fp_2src_double(DisasContext *s, int opcode,
4090
int rd, int rn, int rm)
4097
tcg_res = tcg_temp_new_i64();
4098
fpst = get_fpstatus_ptr();
4099
tcg_op1 = read_fp_dreg(s, rn);
4100
tcg_op2 = read_fp_dreg(s, rm);
4103
case 0x0: /* FMUL */
4104
gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
4106
case 0x1: /* FDIV */
4107
gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
4109
case 0x2: /* FADD */
4110
gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
4112
case 0x3: /* FSUB */
4113
gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
4115
case 0x4: /* FMAX */
4116
gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
4118
case 0x5: /* FMIN */
4119
gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
4121
case 0x6: /* FMAXNM */
4122
gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
4124
case 0x7: /* FMINNM */
4125
gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
4127
case 0x8: /* FNMUL */
4128
gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
4129
gen_helper_vfp_negd(tcg_res, tcg_res);
4133
write_fp_dreg(s, rd, tcg_res);
4135
tcg_temp_free_ptr(fpst);
4136
tcg_temp_free_i64(tcg_op1);
4137
tcg_temp_free_i64(tcg_op2);
4138
tcg_temp_free_i64(tcg_res);
4141
/* C3.6.26 Floating point data-processing (2 source)
4142
* 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
4143
* +---+---+---+-----------+------+---+------+--------+-----+------+------+
4144
* | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | opcode | 1 0 | Rn | Rd |
4145
* +---+---+---+-----------+------+---+------+--------+-----+------+------+
4147
static void disas_fp_2src(DisasContext *s, uint32_t insn)
4149
int type = extract32(insn, 22, 2);
4150
int rd = extract32(insn, 0, 5);
4151
int rn = extract32(insn, 5, 5);
4152
int rm = extract32(insn, 16, 5);
4153
int opcode = extract32(insn, 12, 4);
4156
unallocated_encoding(s);
4162
handle_fp_2src_single(s, opcode, rd, rn, rm);
4165
handle_fp_2src_double(s, opcode, rd, rn, rm);
4168
unallocated_encoding(s);
4172
/* C3.6.27 Floating-point data-processing (3 source) - single precision */
4173
static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
4174
int rd, int rn, int rm, int ra)
4176
TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
4177
TCGv_i32 tcg_res = tcg_temp_new_i32();
4178
TCGv_ptr fpst = get_fpstatus_ptr();
4180
tcg_op1 = read_fp_sreg(s, rn);
4181
tcg_op2 = read_fp_sreg(s, rm);
4182
tcg_op3 = read_fp_sreg(s, ra);
4184
/* These are fused multiply-add, and must be done as one
4185
* floating point operation with no rounding between the
4186
* multiplication and addition steps.
4187
* NB that doing the negations here as separate steps is
4188
* correct : an input NaN should come out with its sign bit
4189
* flipped if it is a negated-input.
4192
gen_helper_vfp_negs(tcg_op3, tcg_op3);
4196
gen_helper_vfp_negs(tcg_op1, tcg_op1);
4199
gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
4201
write_fp_sreg(s, rd, tcg_res);
4203
tcg_temp_free_ptr(fpst);
4204
tcg_temp_free_i32(tcg_op1);
4205
tcg_temp_free_i32(tcg_op2);
4206
tcg_temp_free_i32(tcg_op3);
4207
tcg_temp_free_i32(tcg_res);
4210
/* C3.6.27 Floating-point data-processing (3 source) - double precision */
4211
static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
4212
int rd, int rn, int rm, int ra)
4214
TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
4215
TCGv_i64 tcg_res = tcg_temp_new_i64();
4216
TCGv_ptr fpst = get_fpstatus_ptr();
4218
tcg_op1 = read_fp_dreg(s, rn);
4219
tcg_op2 = read_fp_dreg(s, rm);
4220
tcg_op3 = read_fp_dreg(s, ra);
4222
/* These are fused multiply-add, and must be done as one
4223
* floating point operation with no rounding between the
4224
* multiplication and addition steps.
4225
* NB that doing the negations here as separate steps is
4226
* correct : an input NaN should come out with its sign bit
4227
* flipped if it is a negated-input.
4230
gen_helper_vfp_negd(tcg_op3, tcg_op3);
4234
gen_helper_vfp_negd(tcg_op1, tcg_op1);
4237
gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
4239
write_fp_dreg(s, rd, tcg_res);
4241
tcg_temp_free_ptr(fpst);
4242
tcg_temp_free_i64(tcg_op1);
4243
tcg_temp_free_i64(tcg_op2);
4244
tcg_temp_free_i64(tcg_op3);
4245
tcg_temp_free_i64(tcg_res);
4248
/* C3.6.27 Floating point data-processing (3 source)
4249
* 31 30 29 28 24 23 22 21 20 16 15 14 10 9 5 4 0
4250
* +---+---+---+-----------+------+----+------+----+------+------+------+
4251
* | M | 0 | S | 1 1 1 1 1 | type | o1 | Rm | o0 | Ra | Rn | Rd |
4252
* +---+---+---+-----------+------+----+------+----+------+------+------+
4254
static void disas_fp_3src(DisasContext *s, uint32_t insn)
4256
int type = extract32(insn, 22, 2);
4257
int rd = extract32(insn, 0, 5);
4258
int rn = extract32(insn, 5, 5);
4259
int ra = extract32(insn, 10, 5);
4260
int rm = extract32(insn, 16, 5);
4261
bool o0 = extract32(insn, 15, 1);
4262
bool o1 = extract32(insn, 21, 1);
4266
handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
4269
handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
4272
unallocated_encoding(s);
4276
/* C3.6.28 Floating point immediate
4277
* 31 30 29 28 24 23 22 21 20 13 12 10 9 5 4 0
4278
* +---+---+---+-----------+------+---+------------+-------+------+------+
4279
* | M | 0 | S | 1 1 1 1 0 | type | 1 | imm8 | 1 0 0 | imm5 | Rd |
4280
* +---+---+---+-----------+------+---+------------+-------+------+------+
4282
static void disas_fp_imm(DisasContext *s, uint32_t insn)
4284
int rd = extract32(insn, 0, 5);
4285
int imm8 = extract32(insn, 13, 8);
4286
int is_double = extract32(insn, 22, 2);
4290
if (is_double > 1) {
4291
unallocated_encoding(s);
4295
/* The imm8 encodes the sign bit, enough bits to represent
4296
* an exponent in the range 01....1xx to 10....0xx,
4297
* and the most significant 4 bits of the mantissa; see
4298
* VFPExpandImm() in the v8 ARM ARM.
4301
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
4302
(extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
4303
extract32(imm8, 0, 6);
4306
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
4307
(extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
4308
(extract32(imm8, 0, 6) << 3);
4312
tcg_res = tcg_const_i64(imm);
4313
write_fp_dreg(s, rd, tcg_res);
4314
tcg_temp_free_i64(tcg_res);
4317
/* Handle floating point <=> fixed point conversions. Note that we can
4318
* also deal with fp <=> integer conversions as a special case (scale == 64)
4319
* OPTME: consider handling that special case specially or at least skipping
4320
* the call to scalbn in the helpers for zero shifts.
4322
static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
4323
bool itof, int rmode, int scale, int sf, int type)
4325
bool is_signed = !(opcode & 1);
4326
bool is_double = type;
4327
TCGv_ptr tcg_fpstatus;
4330
tcg_fpstatus = get_fpstatus_ptr();
4332
tcg_shift = tcg_const_i32(64 - scale);
4335
TCGv_i64 tcg_int = cpu_reg(s, rn);
4337
TCGv_i64 tcg_extend = new_tmp_a64(s);
4340
tcg_gen_ext32s_i64(tcg_extend, tcg_int);
4342
tcg_gen_ext32u_i64(tcg_extend, tcg_int);
4345
tcg_int = tcg_extend;
4349
TCGv_i64 tcg_double = tcg_temp_new_i64();
4351
gen_helper_vfp_sqtod(tcg_double, tcg_int,
4352
tcg_shift, tcg_fpstatus);
4354
gen_helper_vfp_uqtod(tcg_double, tcg_int,
4355
tcg_shift, tcg_fpstatus);
4357
write_fp_dreg(s, rd, tcg_double);
4358
tcg_temp_free_i64(tcg_double);
4360
TCGv_i32 tcg_single = tcg_temp_new_i32();
4362
gen_helper_vfp_sqtos(tcg_single, tcg_int,
4363
tcg_shift, tcg_fpstatus);
4365
gen_helper_vfp_uqtos(tcg_single, tcg_int,
4366
tcg_shift, tcg_fpstatus);
4368
write_fp_sreg(s, rd, tcg_single);
4369
tcg_temp_free_i32(tcg_single);
4372
TCGv_i64 tcg_int = cpu_reg(s, rd);
4375
if (extract32(opcode, 2, 1)) {
4376
/* There are too many rounding modes to all fit into rmode,
4377
* so FCVTA[US] is a special case.
4379
rmode = FPROUNDING_TIEAWAY;
4382
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
4384
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4387
TCGv_i64 tcg_double = read_fp_dreg(s, rn);
4390
gen_helper_vfp_tosld(tcg_int, tcg_double,
4391
tcg_shift, tcg_fpstatus);
4393
gen_helper_vfp_tosqd(tcg_int, tcg_double,
4394
tcg_shift, tcg_fpstatus);
4398
gen_helper_vfp_tould(tcg_int, tcg_double,
4399
tcg_shift, tcg_fpstatus);
4401
gen_helper_vfp_touqd(tcg_int, tcg_double,
4402
tcg_shift, tcg_fpstatus);
4405
tcg_temp_free_i64(tcg_double);
4407
TCGv_i32 tcg_single = read_fp_sreg(s, rn);
4410
gen_helper_vfp_tosqs(tcg_int, tcg_single,
4411
tcg_shift, tcg_fpstatus);
4413
gen_helper_vfp_touqs(tcg_int, tcg_single,
4414
tcg_shift, tcg_fpstatus);
4417
TCGv_i32 tcg_dest = tcg_temp_new_i32();
4419
gen_helper_vfp_tosls(tcg_dest, tcg_single,
4420
tcg_shift, tcg_fpstatus);
4422
gen_helper_vfp_touls(tcg_dest, tcg_single,
4423
tcg_shift, tcg_fpstatus);
4425
tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
4426
tcg_temp_free_i32(tcg_dest);
4428
tcg_temp_free_i32(tcg_single);
4431
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4432
tcg_temp_free_i32(tcg_rmode);
4435
tcg_gen_ext32u_i64(tcg_int, tcg_int);
4439
tcg_temp_free_ptr(tcg_fpstatus);
4440
tcg_temp_free_i32(tcg_shift);
4443
/* C3.6.29 Floating point <-> fixed point conversions
4444
* 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
4445
* +----+---+---+-----------+------+---+-------+--------+-------+------+------+
4446
* | sf | 0 | S | 1 1 1 1 0 | type | 0 | rmode | opcode | scale | Rn | Rd |
4447
* +----+---+---+-----------+------+---+-------+--------+-------+------+------+
4449
static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
4451
int rd = extract32(insn, 0, 5);
4452
int rn = extract32(insn, 5, 5);
4453
int scale = extract32(insn, 10, 6);
4454
int opcode = extract32(insn, 16, 3);
4455
int rmode = extract32(insn, 19, 2);
4456
int type = extract32(insn, 22, 2);
4457
bool sbit = extract32(insn, 29, 1);
4458
bool sf = extract32(insn, 31, 1);
4461
if (sbit || (type > 1)
4462
|| (!sf && scale < 32)) {
4463
unallocated_encoding(s);
4467
switch ((rmode << 3) | opcode) {
4468
case 0x2: /* SCVTF */
4469
case 0x3: /* UCVTF */
4472
case 0x18: /* FCVTZS */
4473
case 0x19: /* FCVTZU */
4477
unallocated_encoding(s);
4481
handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
4484
static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
4486
/* FMOV: gpr to or from float, double, or top half of quad fp reg,
4487
* without conversion.
4491
TCGv_i64 tcg_rn = cpu_reg(s, rn);
4497
TCGv_i64 tmp = tcg_temp_new_i64();
4498
tcg_gen_ext32u_i64(tmp, tcg_rn);
4499
tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(rd, MO_64));
4500
tcg_gen_movi_i64(tmp, 0);
4501
tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
4502
tcg_temp_free_i64(tmp);
4508
TCGv_i64 tmp = tcg_const_i64(0);
4509
tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(rd, MO_64));
4510
tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
4511
tcg_temp_free_i64(tmp);
4515
/* 64 bit to top half. */
4516
tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(rd));
4520
TCGv_i64 tcg_rd = cpu_reg(s, rd);
4525
tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_32));
4529
tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_64));
4532
/* 64 bits from top half */
4533
tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(rn));
4539
/* C3.6.30 Floating point <-> integer conversions
4540
* 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
4541
* +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
4542
* | sf | 0 | S | 1 1 1 1 0 | type | 1 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
4543
* +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
4545
static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
4547
int rd = extract32(insn, 0, 5);
4548
int rn = extract32(insn, 5, 5);
4549
int opcode = extract32(insn, 16, 3);
4550
int rmode = extract32(insn, 19, 2);
4551
int type = extract32(insn, 22, 2);
4552
bool sbit = extract32(insn, 29, 1);
4553
bool sf = extract32(insn, 31, 1);
4556
unallocated_encoding(s);
4562
bool itof = opcode & 1;
4565
unallocated_encoding(s);
4569
switch (sf << 3 | type << 1 | rmode) {
4570
case 0x0: /* 32 bit */
4571
case 0xa: /* 64 bit */
4572
case 0xd: /* 64 bit to top half of quad */
4575
/* all other sf/type/rmode combinations are invalid */
4576
unallocated_encoding(s);
4580
handle_fmov(s, rd, rn, type, itof);
4582
/* actual FP conversions */
4583
bool itof = extract32(opcode, 1, 1);
4585
if (type > 1 || (rmode != 0 && opcode > 1)) {
4586
unallocated_encoding(s);
4590
handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
4594
/* FP-specific subcases of table C3-6 (SIMD and FP data processing)
4595
* 31 30 29 28 25 24 0
4596
* +---+---+---+---------+-----------------------------+
4597
* | | 0 | | 1 1 1 1 | |
4598
* +---+---+---+---------+-----------------------------+
4600
static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
4602
if (extract32(insn, 24, 1)) {
4603
/* Floating point data-processing (3 source) */
4604
disas_fp_3src(s, insn);
4605
} else if (extract32(insn, 21, 1) == 0) {
4606
/* Floating point to fixed point conversions */
4607
disas_fp_fixed_conv(s, insn);
4609
switch (extract32(insn, 10, 2)) {
4611
/* Floating point conditional compare */
4612
disas_fp_ccomp(s, insn);
4615
/* Floating point data-processing (2 source) */
4616
disas_fp_2src(s, insn);
4619
/* Floating point conditional select */
4620
disas_fp_csel(s, insn);
4623
switch (ctz32(extract32(insn, 12, 4))) {
4624
case 0: /* [15:12] == xxx1 */
4625
/* Floating point immediate */
4626
disas_fp_imm(s, insn);
4628
case 1: /* [15:12] == xx10 */
4629
/* Floating point compare */
4630
disas_fp_compare(s, insn);
4632
case 2: /* [15:12] == x100 */
4633
/* Floating point data-processing (1 source) */
4634
disas_fp_1src(s, insn);
4636
case 3: /* [15:12] == 1000 */
4637
unallocated_encoding(s);
4639
default: /* [15:12] == 0000 */
4640
/* Floating point <-> integer conversions */
4641
disas_fp_int_conv(s, insn);
4649
static void do_ext64(DisasContext *s, TCGv_i64 tcg_left, TCGv_i64 tcg_right,
4652
/* Extract 64 bits from the middle of two concatenated 64 bit
4653
* vector register slices left:right. The extracted bits start
4654
* at 'pos' bits into the right (least significant) side.
4655
* We return the result in tcg_right, and guarantee not to
4658
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4659
assert(pos > 0 && pos < 64);
4661
tcg_gen_shri_i64(tcg_right, tcg_right, pos);
4662
tcg_gen_shli_i64(tcg_tmp, tcg_left, 64 - pos);
4663
tcg_gen_or_i64(tcg_right, tcg_right, tcg_tmp);
4665
tcg_temp_free_i64(tcg_tmp);
4669
* 31 30 29 24 23 22 21 20 16 15 14 11 10 9 5 4 0
4670
* +---+---+-------------+-----+---+------+---+------+---+------+------+
4671
* | 0 | Q | 1 0 1 1 1 0 | op2 | 0 | Rm | 0 | imm4 | 0 | Rn | Rd |
4672
* +---+---+-------------+-----+---+------+---+------+---+------+------+
4674
static void disas_simd_ext(DisasContext *s, uint32_t insn)
4676
int is_q = extract32(insn, 30, 1);
4677
int op2 = extract32(insn, 22, 2);
4678
int imm4 = extract32(insn, 11, 4);
4679
int rm = extract32(insn, 16, 5);
4680
int rn = extract32(insn, 5, 5);
4681
int rd = extract32(insn, 0, 5);
4682
int pos = imm4 << 3;
4683
TCGv_i64 tcg_resl, tcg_resh;
4685
if (op2 != 0 || (!is_q && extract32(imm4, 3, 1))) {
4686
unallocated_encoding(s);
4690
tcg_resh = tcg_temp_new_i64();
4691
tcg_resl = tcg_temp_new_i64();
4693
/* Vd gets bits starting at pos bits into Vm:Vn. This is
4694
* either extracting 128 bits from a 128:128 concatenation, or
4695
* extracting 64 bits from a 64:64 concatenation.
4698
read_vec_element(s, tcg_resl, rn, 0, MO_64);
4700
read_vec_element(s, tcg_resh, rm, 0, MO_64);
4701
do_ext64(s, tcg_resh, tcg_resl, pos);
4703
tcg_gen_movi_i64(tcg_resh, 0);
4710
EltPosns eltposns[] = { {rn, 0}, {rn, 1}, {rm, 0}, {rm, 1} };
4711
EltPosns *elt = eltposns;
4718
read_vec_element(s, tcg_resl, elt->reg, elt->elt, MO_64);
4720
read_vec_element(s, tcg_resh, elt->reg, elt->elt, MO_64);
4723
do_ext64(s, tcg_resh, tcg_resl, pos);
4724
tcg_hh = tcg_temp_new_i64();
4725
read_vec_element(s, tcg_hh, elt->reg, elt->elt, MO_64);
4726
do_ext64(s, tcg_hh, tcg_resh, pos);
4727
tcg_temp_free_i64(tcg_hh);
4731
write_vec_element(s, tcg_resl, rd, 0, MO_64);
4732
tcg_temp_free_i64(tcg_resl);
4733
write_vec_element(s, tcg_resh, rd, 1, MO_64);
4734
tcg_temp_free_i64(tcg_resh);
4738
* 31 30 29 24 23 22 21 20 16 15 14 13 12 11 10 9 5 4 0
4739
* +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
4740
* | 0 | Q | 0 0 1 1 1 0 | op2 | 0 | Rm | 0 | len | op | 0 0 | Rn | Rd |
4741
* +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
4743
static void disas_simd_tb(DisasContext *s, uint32_t insn)
4745
int op2 = extract32(insn, 22, 2);
4746
int is_q = extract32(insn, 30, 1);
4747
int rm = extract32(insn, 16, 5);
4748
int rn = extract32(insn, 5, 5);
4749
int rd = extract32(insn, 0, 5);
4750
int is_tblx = extract32(insn, 12, 1);
4751
int len = extract32(insn, 13, 2);
4752
TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
4753
TCGv_i32 tcg_regno, tcg_numregs;
4756
unallocated_encoding(s);
4760
/* This does a table lookup: for every byte element in the input
4761
* we index into a table formed from up to four vector registers,
4762
* and then the output is the result of the lookups. Our helper
4763
* function does the lookup operation for a single 64 bit part of
4766
tcg_resl = tcg_temp_new_i64();
4767
tcg_resh = tcg_temp_new_i64();
4770
read_vec_element(s, tcg_resl, rd, 0, MO_64);
4772
tcg_gen_movi_i64(tcg_resl, 0);
4774
if (is_tblx && is_q) {
4775
read_vec_element(s, tcg_resh, rd, 1, MO_64);
4777
tcg_gen_movi_i64(tcg_resh, 0);
4780
tcg_idx = tcg_temp_new_i64();
4781
tcg_regno = tcg_const_i32(rn);
4782
tcg_numregs = tcg_const_i32(len + 1);
4783
read_vec_element(s, tcg_idx, rm, 0, MO_64);
4784
gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
4785
tcg_regno, tcg_numregs);
4787
read_vec_element(s, tcg_idx, rm, 1, MO_64);
4788
gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
4789
tcg_regno, tcg_numregs);
4791
tcg_temp_free_i64(tcg_idx);
4792
tcg_temp_free_i32(tcg_regno);
4793
tcg_temp_free_i32(tcg_numregs);
4795
write_vec_element(s, tcg_resl, rd, 0, MO_64);
4796
tcg_temp_free_i64(tcg_resl);
4797
write_vec_element(s, tcg_resh, rd, 1, MO_64);
4798
tcg_temp_free_i64(tcg_resh);
4801
/* C3.6.3 ZIP/UZP/TRN
4802
* 31 30 29 24 23 22 21 20 16 15 14 12 11 10 9 5 4 0
4803
* +---+---+-------------+------+---+------+---+------------------+------+
4804
* | 0 | Q | 0 0 1 1 1 0 | size | 0 | Rm | 0 | opc | 1 0 | Rn | Rd |
4805
* +---+---+-------------+------+---+------+---+------------------+------+
4807
static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
4809
unsupported_encoding(s, insn);
4812
/* C3.6.4 AdvSIMD across lanes
4813
* 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
4814
* +---+---+---+-----------+------+-----------+--------+-----+------+------+
4815
* | 0 | Q | U | 0 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 | Rn | Rd |
4816
* +---+---+---+-----------+------+-----------+--------+-----+------+------+
4818
static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
4820
unsupported_encoding(s, insn);
4823
/* C3.6.5 AdvSIMD copy
4824
* 31 30 29 28 21 20 16 15 14 11 10 9 5 4 0
4825
* +---+---+----+-----------------+------+---+------+---+------+------+
4826
* | 0 | Q | op | 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 | Rn | Rd |
4827
* +---+---+----+-----------------+------+---+------+---+------+------+
4829
static void disas_simd_copy(DisasContext *s, uint32_t insn)
4831
unsupported_encoding(s, insn);
4834
/* C3.6.6 AdvSIMD modified immediate
4835
* 31 30 29 28 19 18 16 15 12 11 10 9 5 4 0
4836
* +---+---+----+---------------------+-----+-------+----+---+-------+------+
4837
* | 0 | Q | op | 0 1 1 1 1 0 0 0 0 0 | abc | cmode | o2 | 1 | defgh | Rd |
4838
* +---+---+----+---------------------+-----+-------+----+---+-------+------+
4840
static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
4842
unsupported_encoding(s, insn);
4845
/* C3.6.7 AdvSIMD scalar copy
4846
* 31 30 29 28 21 20 16 15 14 11 10 9 5 4 0
4847
* +-----+----+-----------------+------+---+------+---+------+------+
4848
* | 0 1 | op | 1 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 | Rn | Rd |
4849
* +-----+----+-----------------+------+---+------+---+------+------+
4851
static void disas_simd_scalar_copy(DisasContext *s, uint32_t insn)
4853
unsupported_encoding(s, insn);
4856
/* C3.6.8 AdvSIMD scalar pairwise
4857
* 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
4858
* +-----+---+-----------+------+-----------+--------+-----+------+------+
4859
* | 0 1 | U | 1 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 | Rn | Rd |
4860
* +-----+---+-----------+------+-----------+--------+-----+------+------+
4862
static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
4864
unsupported_encoding(s, insn);
4867
/* C3.6.9 AdvSIMD scalar shift by immediate
4868
* 31 30 29 28 23 22 19 18 16 15 11 10 9 5 4 0
4869
* +-----+---+-------------+------+------+--------+---+------+------+
4870
* | 0 1 | U | 1 1 1 1 1 0 | immh | immb | opcode | 1 | Rn | Rd |
4871
* +-----+---+-------------+------+------+--------+---+------+------+
4873
static void disas_simd_scalar_shift_imm(DisasContext *s, uint32_t insn)
4875
unsupported_encoding(s, insn);
4878
/* C3.6.10 AdvSIMD scalar three different
4879
* 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
4880
* +-----+---+-----------+------+---+------+--------+-----+------+------+
4881
* | 0 1 | U | 1 1 1 1 0 | size | 1 | Rm | opcode | 0 0 | Rn | Rd |
4882
* +-----+---+-----------+------+---+------+--------+-----+------+------+
4884
static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
4886
unsupported_encoding(s, insn);
4889
/* C3.6.11 AdvSIMD scalar three same
4890
* 31 30 29 28 24 23 22 21 20 16 15 11 10 9 5 4 0
4891
* +-----+---+-----------+------+---+------+--------+---+------+------+
4892
* | 0 1 | U | 1 1 1 1 0 | size | 1 | Rm | opcode | 1 | Rn | Rd |
4893
* +-----+---+-----------+------+---+------+--------+---+------+------+
4895
static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
4897
unsupported_encoding(s, insn);
4900
/* C3.6.12 AdvSIMD scalar two reg misc
4901
* 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
4902
* +-----+---+-----------+------+-----------+--------+-----+------+------+
4903
* | 0 1 | U | 1 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 | Rn | Rd |
4904
* +-----+---+-----------+------+-----------+--------+-----+------+------+
4906
static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
4908
unsupported_encoding(s, insn);
4911
/* C3.6.13 AdvSIMD scalar x indexed element
4912
* 31 30 29 28 24 23 22 21 20 19 16 15 12 11 10 9 5 4 0
4913
* +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
4914
* | 0 1 | U | 1 1 1 1 1 | size | L | M | Rm | opc | H | 0 | Rn | Rd |
4915
* +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
4917
static void disas_simd_scalar_indexed(DisasContext *s, uint32_t insn)
4919
unsupported_encoding(s, insn);
4922
/* C3.6.14 AdvSIMD shift by immediate
4923
* 31 30 29 28 23 22 19 18 16 15 11 10 9 5 4 0
4924
* +---+---+---+-------------+------+------+--------+---+------+------+
4925
* | 0 | Q | U | 0 1 1 1 1 0 | immh | immb | opcode | 1 | Rn | Rd |
4926
* +---+---+---+-------------+------+------+--------+---+------+------+
4928
static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
4930
unsupported_encoding(s, insn);
4933
/* C3.6.15 AdvSIMD three different
4934
* 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
4935
* +---+---+---+-----------+------+---+------+--------+-----+------+------+
4936
* | 0 | Q | U | 0 1 1 1 0 | size | 1 | Rm | opcode | 0 0 | Rn | Rd |
4937
* +---+---+---+-----------+------+---+------+--------+-----+------+------+
4939
static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
4941
unsupported_encoding(s, insn);
4944
/* C3.6.16 AdvSIMD three same
4945
* 31 30 29 28 24 23 22 21 20 16 15 11 10 9 5 4 0
4946
* +---+---+---+-----------+------+---+------+--------+---+------+------+
4947
* | 0 | Q | U | 0 1 1 1 0 | size | 1 | Rm | opcode | 1 | Rn | Rd |
4948
* +---+---+---+-----------+------+---+------+--------+---+------+------+
4950
static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
4952
unsupported_encoding(s, insn);
4955
/* C3.6.17 AdvSIMD two reg misc
4956
* 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
4957
* +---+---+---+-----------+------+-----------+--------+-----+------+------+
4958
* | 0 | Q | U | 0 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 | Rn | Rd |
4959
* +---+---+---+-----------+------+-----------+--------+-----+------+------+
4961
static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
4963
unsupported_encoding(s, insn);
4966
/* C3.6.18 AdvSIMD vector x indexed element
4967
* 31 30 29 28 24 23 22 21 20 19 16 15 12 11 10 9 5 4 0
4968
* +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
4969
* | 0 | Q | U | 0 1 1 1 1 | size | L | M | Rm | opc | H | 0 | Rn | Rd |
4970
* +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
4972
static void disas_simd_indexed_vector(DisasContext *s, uint32_t insn)
4974
unsupported_encoding(s, insn);
4977
/* C3.6.19 Crypto AES
4978
* 31 24 23 22 21 17 16 12 11 10 9 5 4 0
4979
* +-----------------+------+-----------+--------+-----+------+------+
4980
* | 0 1 0 0 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 | Rn | Rd |
4981
* +-----------------+------+-----------+--------+-----+------+------+
4983
static void disas_crypto_aes(DisasContext *s, uint32_t insn)
4985
unsupported_encoding(s, insn);
4988
/* C3.6.20 Crypto three-reg SHA
4989
* 31 24 23 22 21 20 16 15 14 12 11 10 9 5 4 0
4990
* +-----------------+------+---+------+---+--------+-----+------+------+
4991
* | 0 1 0 1 1 1 1 0 | size | 0 | Rm | 0 | opcode | 0 0 | Rn | Rd |
4992
* +-----------------+------+---+------+---+--------+-----+------+------+
4994
static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
4996
unsupported_encoding(s, insn);
4999
/* C3.6.21 Crypto two-reg SHA
5000
* 31 24 23 22 21 17 16 12 11 10 9 5 4 0
5001
* +-----------------+------+-----------+--------+-----+------+------+
5002
* | 0 1 0 1 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 | Rn | Rd |
5003
* +-----------------+------+-----------+--------+-----+------+------+
5005
static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
5007
unsupported_encoding(s, insn);
5010
/* C3.6 Data processing - SIMD, inc Crypto
5012
* As the decode gets a little complex we are using a table based
5013
* approach for this part of the decode.
5015
static const AArch64DecodeTable data_proc_simd[] = {
5016
/* pattern , mask , fn */
5017
{ 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
5018
{ 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
5019
{ 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
5020
{ 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
5021
{ 0x0e000400, 0x9fe08400, disas_simd_copy },
5022
{ 0x0f000000, 0x9f000400, disas_simd_indexed_vector },
5023
/* simd_mod_imm decode is a subset of simd_shift_imm, so must precede it */
5024
{ 0x0f000400, 0x9ff80400, disas_simd_mod_imm },
5025
{ 0x0f000400, 0x9f800400, disas_simd_shift_imm },
5026
{ 0x0e000000, 0xbf208c00, disas_simd_tb },
5027
{ 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
5028
{ 0x2e000000, 0xbf208400, disas_simd_ext },
5029
{ 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
5030
{ 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
5031
{ 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
5032
{ 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
5033
{ 0x5e000400, 0xdfe08400, disas_simd_scalar_copy },
5034
{ 0x5f000000, 0xdf000400, disas_simd_scalar_indexed },
5035
{ 0x5f000400, 0xdf800400, disas_simd_scalar_shift_imm },
5036
{ 0x4e280800, 0xff3e0c00, disas_crypto_aes },
5037
{ 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha },
5038
{ 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
5039
{ 0x00000000, 0x00000000, NULL }
5042
static void disas_data_proc_simd(DisasContext *s, uint32_t insn)
5044
/* Note that this is called with all non-FP cases from
5045
* table C3-6 so it must UNDEF for entries not specifically
5046
* allocated to instructions in that table.
5048
AArch64DecodeFn *fn = lookup_disas_fn(&data_proc_simd[0], insn);
5052
unallocated_encoding(s);
5056
/* C3.6 Data processing - SIMD and floating point */
5057
static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
5059
if (extract32(insn, 28, 1) == 1 && extract32(insn, 30, 1) == 0) {
5060
disas_data_proc_fp(s, insn);
5062
/* SIMD, including crypto */
5063
disas_data_proc_simd(s, insn);
5067
/* C3.1 A64 instruction index by encoding */
5068
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
5072
insn = arm_ldl_code(env, s->pc, s->bswap_code);
5076
switch (extract32(insn, 25, 4)) {
5077
case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
5078
unallocated_encoding(s);
5080
case 0x8: case 0x9: /* Data processing - immediate */
5081
disas_data_proc_imm(s, insn);
5083
case 0xa: case 0xb: /* Branch, exception generation and system insns */
5084
disas_b_exc_sys(s, insn);
5089
case 0xe: /* Loads and stores */
5090
disas_ldst(s, insn);
5093
case 0xd: /* Data processing - register */
5094
disas_data_proc_reg(s, insn);
5097
case 0xf: /* Data processing - SIMD and floating point */
5098
disas_data_proc_simd_fp(s, insn);
5101
assert(FALSE); /* all 15 cases should be handled above */
5105
/* if we allocated any temporaries, free them here */
5109
void gen_intermediate_code_internal_a64(ARMCPU *cpu,
5110
TranslationBlock *tb,
5113
CPUState *cs = CPU(cpu);
5114
CPUARMState *env = &cpu->env;
5115
DisasContext dc1, *dc = &dc1;
5117
uint16_t *gen_opc_end;
5119
target_ulong pc_start;
5120
target_ulong next_page_start;
5128
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
5130
dc->is_jmp = DISAS_NEXT;
5132
dc->singlestep_enabled = cs->singlestep_enabled;
5138
dc->condexec_mask = 0;
5139
dc->condexec_cond = 0;
5140
#if !defined(CONFIG_USER_ONLY)
5143
dc->vfp_enabled = 0;
5146
dc->cp_regs = cpu->cp_regs;
5147
dc->current_pl = arm_current_pl(env);
5149
init_tmp_a64_array(dc);
5151
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
5154
max_insns = tb->cflags & CF_COUNT_MASK;
5155
if (max_insns == 0) {
5156
max_insns = CF_COUNT_MASK;
5161
tcg_clear_temp_count();
5164
if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
5165
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
5166
if (bp->pc == dc->pc) {
5167
gen_exception_insn(dc, 0, EXCP_DEBUG);
5168
/* Advance PC so that clearing the breakpoint will
5169
invalidate this TB. */
5171
goto done_generating;
5177
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
5181
tcg_ctx.gen_opc_instr_start[lj++] = 0;
5184
tcg_ctx.gen_opc_pc[lj] = dc->pc;
5185
tcg_ctx.gen_opc_instr_start[lj] = 1;
5186
tcg_ctx.gen_opc_icount[lj] = num_insns;
5189
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
5193
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
5194
tcg_gen_debug_insn_start(dc->pc);
5197
disas_a64_insn(env, dc);
5199
if (tcg_check_temp_count()) {
5200
fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
5204
/* Translation stops when a conditional branch is encountered.
5205
* Otherwise the subsequent code could get translated several times.
5206
* Also stop translation when a page boundary is reached. This
5207
* ensures prefetch aborts occur at the right place.
5210
} while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
5211
!cs->singlestep_enabled &&
5213
dc->pc < next_page_start &&
5214
num_insns < max_insns);
5216
if (tb->cflags & CF_LAST_IO) {
5220
if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
5221
/* Note that this means single stepping WFI doesn't halt the CPU.
5222
* For conditional branch insns this is harmless unreachable code as
5223
* gen_goto_tb() has already handled emitting the debug exception
5224
* (and thus a tb-jump is not possible when singlestepping).
5226
assert(dc->is_jmp != DISAS_TB_JUMP);
5227
if (dc->is_jmp != DISAS_JUMP) {
5228
gen_a64_set_pc_im(dc->pc);
5230
gen_exception(EXCP_DEBUG);
5232
switch (dc->is_jmp) {
5234
gen_goto_tb(dc, 1, dc->pc);
5238
gen_a64_set_pc_im(dc->pc);
5241
/* indicate that the hash table must be used to find the next TB */
5249
/* This is a special case because we don't want to just halt the CPU
5250
* if trying to debug across a WFI.
5252
gen_helper_wfi(cpu_env);
5258
gen_tb_end(tb, num_insns);
5259
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
5262
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
5263
qemu_log("----------------\n");
5264
qemu_log("IN: %s\n", lookup_symbol(pc_start));
5265
log_target_disas(env, pc_start, dc->pc - pc_start,
5266
dc->thumb | (dc->bswap_code << 1));
5271
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
5274
tcg_ctx.gen_opc_instr_start[lj++] = 0;
5277
tb->size = dc->pc - pc_start;
5278
tb->icount = num_insns;