]> Git Repo - qemu.git/blob - target-arm/translate-a64.c
target-arm: A64: add support for add, addi, sub, subi
[qemu.git] / target-arm / translate-a64.c
1 /*
2  *  AArch64 translation
3  *
4  *  Copyright (c) 2013 Alexander Graf <[email protected]>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
24
25 #include "cpu.h"
26 #include "tcg-op.h"
27 #include "qemu/log.h"
28 #include "translate.h"
29 #include "qemu/host-utils.h"
30
31 #include "exec/gen-icount.h"
32
33 #include "helper.h"
34 #define GEN_HELPER 1
35 #include "helper.h"
36
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;
40
41 static const char *regnames[] = {
42     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
43     "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
44     "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
45     "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
46 };
47
48 enum a64_shift_type {
49     A64_SHIFT_TYPE_LSL = 0,
50     A64_SHIFT_TYPE_LSR = 1,
51     A64_SHIFT_TYPE_ASR = 2,
52     A64_SHIFT_TYPE_ROR = 3
53 };
54
55 /* initialize TCG globals.  */
56 void a64_translate_init(void)
57 {
58     int i;
59
60     cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
61                                     offsetof(CPUARMState, pc),
62                                     "pc");
63     for (i = 0; i < 32; i++) {
64         cpu_X[i] = tcg_global_mem_new_i64(TCG_AREG0,
65                                           offsetof(CPUARMState, xregs[i]),
66                                           regnames[i]);
67     }
68
69     cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
70     cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
71     cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
72     cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
73 }
74
75 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
76                             fprintf_function cpu_fprintf, int flags)
77 {
78     ARMCPU *cpu = ARM_CPU(cs);
79     CPUARMState *env = &cpu->env;
80     uint32_t psr = pstate_read(env);
81     int i;
82
83     cpu_fprintf(f, "PC=%016"PRIx64"  SP=%016"PRIx64"\n",
84             env->pc, env->xregs[31]);
85     for (i = 0; i < 31; i++) {
86         cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
87         if ((i % 4) == 3) {
88             cpu_fprintf(f, "\n");
89         } else {
90             cpu_fprintf(f, " ");
91         }
92     }
93     cpu_fprintf(f, "PSTATE=%08x (flags %c%c%c%c)\n",
94                 psr,
95                 psr & PSTATE_N ? 'N' : '-',
96                 psr & PSTATE_Z ? 'Z' : '-',
97                 psr & PSTATE_C ? 'C' : '-',
98                 psr & PSTATE_V ? 'V' : '-');
99     cpu_fprintf(f, "\n");
100 }
101
102 static int get_mem_index(DisasContext *s)
103 {
104 #ifdef CONFIG_USER_ONLY
105     return 1;
106 #else
107     return s->user;
108 #endif
109 }
110
111 void gen_a64_set_pc_im(uint64_t val)
112 {
113     tcg_gen_movi_i64(cpu_pc, val);
114 }
115
116 static void gen_exception(int excp)
117 {
118     TCGv_i32 tmp = tcg_temp_new_i32();
119     tcg_gen_movi_i32(tmp, excp);
120     gen_helper_exception(cpu_env, tmp);
121     tcg_temp_free_i32(tmp);
122 }
123
124 static void gen_exception_insn(DisasContext *s, int offset, int excp)
125 {
126     gen_a64_set_pc_im(s->pc - offset);
127     gen_exception(excp);
128     s->is_jmp = DISAS_EXC;
129 }
130
131 static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
132 {
133     /* No direct tb linking with singlestep or deterministic io */
134     if (s->singlestep_enabled || (s->tb->cflags & CF_LAST_IO)) {
135         return false;
136     }
137
138     /* Only link tbs from inside the same guest page */
139     if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
140         return false;
141     }
142
143     return true;
144 }
145
146 static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
147 {
148     TranslationBlock *tb;
149
150     tb = s->tb;
151     if (use_goto_tb(s, n, dest)) {
152         tcg_gen_goto_tb(n);
153         gen_a64_set_pc_im(dest);
154         tcg_gen_exit_tb((tcg_target_long)tb + n);
155         s->is_jmp = DISAS_TB_JUMP;
156     } else {
157         gen_a64_set_pc_im(dest);
158         if (s->singlestep_enabled) {
159             gen_exception(EXCP_DEBUG);
160         }
161         tcg_gen_exit_tb(0);
162         s->is_jmp = DISAS_JUMP;
163     }
164 }
165
166 static void unallocated_encoding(DisasContext *s)
167 {
168     gen_exception_insn(s, 4, EXCP_UDEF);
169 }
170
171 #define unsupported_encoding(s, insn)                                    \
172     do {                                                                 \
173         qemu_log_mask(LOG_UNIMP,                                         \
174                       "%s:%d: unsupported instruction encoding 0x%08x "  \
175                       "at pc=%016" PRIx64 "\n",                          \
176                       __FILE__, __LINE__, insn, s->pc - 4);              \
177         unallocated_encoding(s);                                         \
178     } while (0);
179
180 static void init_tmp_a64_array(DisasContext *s)
181 {
182 #ifdef CONFIG_DEBUG_TCG
183     int i;
184     for (i = 0; i < ARRAY_SIZE(s->tmp_a64); i++) {
185         TCGV_UNUSED_I64(s->tmp_a64[i]);
186     }
187 #endif
188     s->tmp_a64_count = 0;
189 }
190
191 static void free_tmp_a64(DisasContext *s)
192 {
193     int i;
194     for (i = 0; i < s->tmp_a64_count; i++) {
195         tcg_temp_free_i64(s->tmp_a64[i]);
196     }
197     init_tmp_a64_array(s);
198 }
199
200 static TCGv_i64 new_tmp_a64(DisasContext *s)
201 {
202     assert(s->tmp_a64_count < TMP_A64_MAX);
203     return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
204 }
205
206 static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
207 {
208     TCGv_i64 t = new_tmp_a64(s);
209     tcg_gen_movi_i64(t, 0);
210     return t;
211 }
212
213 /*
214  * Register access functions
215  *
216  * These functions are used for directly accessing a register in where
217  * changes to the final register value are likely to be made. If you
218  * need to use a register for temporary calculation (e.g. index type
219  * operations) use the read_* form.
220  *
221  * B1.2.1 Register mappings
222  *
223  * In instruction register encoding 31 can refer to ZR (zero register) or
224  * the SP (stack pointer) depending on context. In QEMU's case we map SP
225  * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
226  * This is the point of the _sp forms.
227  */
228 static TCGv_i64 cpu_reg(DisasContext *s, int reg)
229 {
230     if (reg == 31) {
231         return new_tmp_a64_zero(s);
232     } else {
233         return cpu_X[reg];
234     }
235 }
236
237 /* register access for when 31 == SP */
238 static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
239 {
240     return cpu_X[reg];
241 }
242
243 /* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
244  * representing the register contents. This TCGv is an auto-freed
245  * temporary so it need not be explicitly freed, and may be modified.
246  */
247 static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
248 {
249     TCGv_i64 v = new_tmp_a64(s);
250     if (reg != 31) {
251         if (sf) {
252             tcg_gen_mov_i64(v, cpu_X[reg]);
253         } else {
254             tcg_gen_ext32u_i64(v, cpu_X[reg]);
255         }
256     } else {
257         tcg_gen_movi_i64(v, 0);
258     }
259     return v;
260 }
261
262 static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
263 {
264     TCGv_i64 v = new_tmp_a64(s);
265     if (sf) {
266         tcg_gen_mov_i64(v, cpu_X[reg]);
267     } else {
268         tcg_gen_ext32u_i64(v, cpu_X[reg]);
269     }
270     return v;
271 }
272
273 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
274  * than the 32 bit equivalent.
275  */
276 static inline void gen_set_NZ64(TCGv_i64 result)
277 {
278     TCGv_i64 flag = tcg_temp_new_i64();
279
280     tcg_gen_setcondi_i64(TCG_COND_NE, flag, result, 0);
281     tcg_gen_trunc_i64_i32(cpu_ZF, flag);
282     tcg_gen_shri_i64(flag, result, 32);
283     tcg_gen_trunc_i64_i32(cpu_NF, flag);
284     tcg_temp_free_i64(flag);
285 }
286
287 /* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
288 static inline void gen_logic_CC(int sf, TCGv_i64 result)
289 {
290     if (sf) {
291         gen_set_NZ64(result);
292     } else {
293         tcg_gen_trunc_i64_i32(cpu_ZF, result);
294         tcg_gen_trunc_i64_i32(cpu_NF, result);
295     }
296     tcg_gen_movi_i32(cpu_CF, 0);
297     tcg_gen_movi_i32(cpu_VF, 0);
298 }
299
300 /* dest = T0 + T1; compute C, N, V and Z flags */
301 static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
302 {
303     if (sf) {
304         TCGv_i64 result, flag, tmp;
305         result = tcg_temp_new_i64();
306         flag = tcg_temp_new_i64();
307         tmp = tcg_temp_new_i64();
308
309         tcg_gen_movi_i64(tmp, 0);
310         tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
311
312         tcg_gen_trunc_i64_i32(cpu_CF, flag);
313
314         gen_set_NZ64(result);
315
316         tcg_gen_xor_i64(flag, result, t0);
317         tcg_gen_xor_i64(tmp, t0, t1);
318         tcg_gen_andc_i64(flag, flag, tmp);
319         tcg_temp_free_i64(tmp);
320         tcg_gen_shri_i64(flag, flag, 32);
321         tcg_gen_trunc_i64_i32(cpu_VF, flag);
322
323         tcg_gen_mov_i64(dest, result);
324         tcg_temp_free_i64(result);
325         tcg_temp_free_i64(flag);
326     } else {
327         /* 32 bit arithmetic */
328         TCGv_i32 t0_32 = tcg_temp_new_i32();
329         TCGv_i32 t1_32 = tcg_temp_new_i32();
330         TCGv_i32 tmp = tcg_temp_new_i32();
331
332         tcg_gen_movi_i32(tmp, 0);
333         tcg_gen_trunc_i64_i32(t0_32, t0);
334         tcg_gen_trunc_i64_i32(t1_32, t1);
335         tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
336         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
337         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
338         tcg_gen_xor_i32(tmp, t0_32, t1_32);
339         tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
340         tcg_gen_extu_i32_i64(dest, cpu_NF);
341
342         tcg_temp_free_i32(tmp);
343         tcg_temp_free_i32(t0_32);
344         tcg_temp_free_i32(t1_32);
345     }
346 }
347
348 /* dest = T0 - T1; compute C, N, V and Z flags */
349 static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
350 {
351     if (sf) {
352         /* 64 bit arithmetic */
353         TCGv_i64 result, flag, tmp;
354
355         result = tcg_temp_new_i64();
356         flag = tcg_temp_new_i64();
357         tcg_gen_sub_i64(result, t0, t1);
358
359         gen_set_NZ64(result);
360
361         tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
362         tcg_gen_trunc_i64_i32(cpu_CF, flag);
363
364         tcg_gen_xor_i64(flag, result, t0);
365         tmp = tcg_temp_new_i64();
366         tcg_gen_xor_i64(tmp, t0, t1);
367         tcg_gen_and_i64(flag, flag, tmp);
368         tcg_temp_free_i64(tmp);
369         tcg_gen_shri_i64(flag, flag, 32);
370         tcg_gen_trunc_i64_i32(cpu_VF, flag);
371         tcg_gen_mov_i64(dest, result);
372         tcg_temp_free_i64(flag);
373         tcg_temp_free_i64(result);
374     } else {
375         /* 32 bit arithmetic */
376         TCGv_i32 t0_32 = tcg_temp_new_i32();
377         TCGv_i32 t1_32 = tcg_temp_new_i32();
378         TCGv_i32 tmp;
379
380         tcg_gen_trunc_i64_i32(t0_32, t0);
381         tcg_gen_trunc_i64_i32(t1_32, t1);
382         tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
383         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
384         tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
385         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
386         tmp = tcg_temp_new_i32();
387         tcg_gen_xor_i32(tmp, t0_32, t1_32);
388         tcg_temp_free_i32(t0_32);
389         tcg_temp_free_i32(t1_32);
390         tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
391         tcg_temp_free_i32(tmp);
392         tcg_gen_extu_i32_i64(dest, cpu_NF);
393     }
394 }
395
396 /*
397  * Load/Store generators
398  */
399
400 /*
401  * Store from GPR register to memory
402  */
403 static void do_gpr_st(DisasContext *s, TCGv_i64 source,
404                       TCGv_i64 tcg_addr, int size)
405 {
406     g_assert(size <= 3);
407     tcg_gen_qemu_st_i64(source, tcg_addr, get_mem_index(s), MO_TE + size);
408 }
409
410 /*
411  * Load from memory to GPR register
412  */
413 static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
414                       int size, bool is_signed, bool extend)
415 {
416     TCGMemOp memop = MO_TE + size;
417
418     g_assert(size <= 3);
419
420     if (is_signed) {
421         memop += MO_SIGN;
422     }
423
424     tcg_gen_qemu_ld_i64(dest, tcg_addr, get_mem_index(s), memop);
425
426     if (extend && is_signed) {
427         g_assert(size < 3);
428         tcg_gen_ext32u_i64(dest, dest);
429     }
430 }
431
432 /*
433  * Store from FP register to memory
434  */
435 static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
436 {
437     /* This writes the bottom N bits of a 128 bit wide vector to memory */
438     int freg_offs = offsetof(CPUARMState, vfp.regs[srcidx * 2]);
439     TCGv_i64 tmp = tcg_temp_new_i64();
440
441     if (size < 4) {
442         switch (size) {
443         case 0:
444             tcg_gen_ld8u_i64(tmp, cpu_env, freg_offs);
445             break;
446         case 1:
447             tcg_gen_ld16u_i64(tmp, cpu_env, freg_offs);
448             break;
449         case 2:
450             tcg_gen_ld32u_i64(tmp, cpu_env, freg_offs);
451             break;
452         case 3:
453             tcg_gen_ld_i64(tmp, cpu_env, freg_offs);
454             break;
455         }
456         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
457     } else {
458         TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
459         tcg_gen_ld_i64(tmp, cpu_env, freg_offs);
460         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
461         tcg_gen_qemu_st64(tmp, tcg_addr, get_mem_index(s));
462         tcg_gen_ld_i64(tmp, cpu_env, freg_offs + sizeof(float64));
463         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
464         tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
465         tcg_temp_free_i64(tcg_hiaddr);
466     }
467
468     tcg_temp_free_i64(tmp);
469 }
470
471 /*
472  * Load from memory to FP register
473  */
474 static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
475 {
476     /* This always zero-extends and writes to a full 128 bit wide vector */
477     int freg_offs = offsetof(CPUARMState, vfp.regs[destidx * 2]);
478     TCGv_i64 tmplo = tcg_temp_new_i64();
479     TCGv_i64 tmphi;
480
481     if (size < 4) {
482         TCGMemOp memop = MO_TE + size;
483         tmphi = tcg_const_i64(0);
484         tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
485     } else {
486         TCGv_i64 tcg_hiaddr;
487         tmphi = tcg_temp_new_i64();
488         tcg_hiaddr = tcg_temp_new_i64();
489
490         tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
491         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
492         tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
493         tcg_temp_free_i64(tcg_hiaddr);
494     }
495
496     tcg_gen_st_i64(tmplo, cpu_env, freg_offs);
497     tcg_gen_st_i64(tmphi, cpu_env, freg_offs + sizeof(float64));
498
499     tcg_temp_free_i64(tmplo);
500     tcg_temp_free_i64(tmphi);
501 }
502
503 /*
504  * This utility function is for doing register extension with an
505  * optional shift. You will likely want to pass a temporary for the
506  * destination register. See DecodeRegExtend() in the ARM ARM.
507  */
508 static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
509                               int option, unsigned int shift)
510 {
511     int extsize = extract32(option, 0, 2);
512     bool is_signed = extract32(option, 2, 1);
513
514     if (is_signed) {
515         switch (extsize) {
516         case 0:
517             tcg_gen_ext8s_i64(tcg_out, tcg_in);
518             break;
519         case 1:
520             tcg_gen_ext16s_i64(tcg_out, tcg_in);
521             break;
522         case 2:
523             tcg_gen_ext32s_i64(tcg_out, tcg_in);
524             break;
525         case 3:
526             tcg_gen_mov_i64(tcg_out, tcg_in);
527             break;
528         }
529     } else {
530         switch (extsize) {
531         case 0:
532             tcg_gen_ext8u_i64(tcg_out, tcg_in);
533             break;
534         case 1:
535             tcg_gen_ext16u_i64(tcg_out, tcg_in);
536             break;
537         case 2:
538             tcg_gen_ext32u_i64(tcg_out, tcg_in);
539             break;
540         case 3:
541             tcg_gen_mov_i64(tcg_out, tcg_in);
542             break;
543         }
544     }
545
546     if (shift) {
547         tcg_gen_shli_i64(tcg_out, tcg_out, shift);
548     }
549 }
550
551 static inline void gen_check_sp_alignment(DisasContext *s)
552 {
553     /* The AArch64 architecture mandates that (if enabled via PSTATE
554      * or SCTLR bits) there is a check that SP is 16-aligned on every
555      * SP-relative load or store (with an exception generated if it is not).
556      * In line with general QEMU practice regarding misaligned accesses,
557      * we omit these checks for the sake of guest program performance.
558      * This function is provided as a hook so we can more easily add these
559      * checks in future (possibly as a "favour catching guest program bugs
560      * over speed" user selectable option).
561      */
562 }
563
564 /*
565  * the instruction disassembly implemented here matches
566  * the instruction encoding classifications in chapter 3 (C3)
567  * of the ARM Architecture Reference Manual (DDI0487A_a)
568  */
569
570 /* C3.2.7 Unconditional branch (immediate)
571  *   31  30       26 25                                  0
572  * +----+-----------+-------------------------------------+
573  * | op | 0 0 1 0 1 |                 imm26               |
574  * +----+-----------+-------------------------------------+
575  */
576 static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
577 {
578     uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
579
580     if (insn & (1 << 31)) {
581         /* C5.6.26 BL Branch with link */
582         tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
583     }
584
585     /* C5.6.20 B Branch / C5.6.26 BL Branch with link */
586     gen_goto_tb(s, 0, addr);
587 }
588
589 /* C3.2.1 Compare & branch (immediate)
590  *   31  30         25  24  23                  5 4      0
591  * +----+-------------+----+---------------------+--------+
592  * | sf | 0 1 1 0 1 0 | op |         imm19       |   Rt   |
593  * +----+-------------+----+---------------------+--------+
594  */
595 static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
596 {
597     unsigned int sf, op, rt;
598     uint64_t addr;
599     int label_match;
600     TCGv_i64 tcg_cmp;
601
602     sf = extract32(insn, 31, 1);
603     op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
604     rt = extract32(insn, 0, 5);
605     addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
606
607     tcg_cmp = read_cpu_reg(s, rt, sf);
608     label_match = gen_new_label();
609
610     tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
611                         tcg_cmp, 0, label_match);
612
613     gen_goto_tb(s, 0, s->pc);
614     gen_set_label(label_match);
615     gen_goto_tb(s, 1, addr);
616 }
617
618 /* C3.2.5 Test & branch (immediate)
619  *   31  30         25  24  23   19 18          5 4    0
620  * +----+-------------+----+-------+-------------+------+
621  * | b5 | 0 1 1 0 1 1 | op |  b40  |    imm14    |  Rt  |
622  * +----+-------------+----+-------+-------------+------+
623  */
624 static void disas_test_b_imm(DisasContext *s, uint32_t insn)
625 {
626     unsigned int bit_pos, op, rt;
627     uint64_t addr;
628     int label_match;
629     TCGv_i64 tcg_cmp;
630
631     bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
632     op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
633     addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
634     rt = extract32(insn, 0, 5);
635
636     tcg_cmp = tcg_temp_new_i64();
637     tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
638     label_match = gen_new_label();
639     tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
640                         tcg_cmp, 0, label_match);
641     tcg_temp_free_i64(tcg_cmp);
642     gen_goto_tb(s, 0, s->pc);
643     gen_set_label(label_match);
644     gen_goto_tb(s, 1, addr);
645 }
646
647 /* C3.2.2 / C5.6.19 Conditional branch (immediate)
648  *  31           25  24  23                  5   4  3    0
649  * +---------------+----+---------------------+----+------+
650  * | 0 1 0 1 0 1 0 | o1 |         imm19       | o0 | cond |
651  * +---------------+----+---------------------+----+------+
652  */
653 static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
654 {
655     unsigned int cond;
656     uint64_t addr;
657
658     if ((insn & (1 << 4)) || (insn & (1 << 24))) {
659         unallocated_encoding(s);
660         return;
661     }
662     addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
663     cond = extract32(insn, 0, 4);
664
665     if (cond < 0x0e) {
666         /* genuinely conditional branches */
667         int label_match = gen_new_label();
668         arm_gen_test_cc(cond, label_match);
669         gen_goto_tb(s, 0, s->pc);
670         gen_set_label(label_match);
671         gen_goto_tb(s, 1, addr);
672     } else {
673         /* 0xe and 0xf are both "always" conditions */
674         gen_goto_tb(s, 0, addr);
675     }
676 }
677
678 /* C5.6.68 HINT */
679 static void handle_hint(DisasContext *s, uint32_t insn,
680                         unsigned int op1, unsigned int op2, unsigned int crm)
681 {
682     unsigned int selector = crm << 3 | op2;
683
684     if (op1 != 3) {
685         unallocated_encoding(s);
686         return;
687     }
688
689     switch (selector) {
690     case 0: /* NOP */
691         return;
692     case 1: /* YIELD */
693     case 2: /* WFE */
694     case 3: /* WFI */
695     case 4: /* SEV */
696     case 5: /* SEVL */
697         /* we treat all as NOP at least for now */
698         return;
699     default:
700         /* default specified as NOP equivalent */
701         return;
702     }
703 }
704
705 /* CLREX, DSB, DMB, ISB */
706 static void handle_sync(DisasContext *s, uint32_t insn,
707                         unsigned int op1, unsigned int op2, unsigned int crm)
708 {
709     if (op1 != 3) {
710         unallocated_encoding(s);
711         return;
712     }
713
714     switch (op2) {
715     case 2: /* CLREX */
716         unsupported_encoding(s, insn);
717         return;
718     case 4: /* DSB */
719     case 5: /* DMB */
720     case 6: /* ISB */
721         /* We don't emulate caches so barriers are no-ops */
722         return;
723     default:
724         unallocated_encoding(s);
725         return;
726     }
727 }
728
729 /* C5.6.130 MSR (immediate) - move immediate to processor state field */
730 static void handle_msr_i(DisasContext *s, uint32_t insn,
731                          unsigned int op1, unsigned int op2, unsigned int crm)
732 {
733     unsupported_encoding(s, insn);
734 }
735
736 /* C5.6.204 SYS */
737 static void handle_sys(DisasContext *s, uint32_t insn, unsigned int l,
738                        unsigned int op1, unsigned int op2,
739                        unsigned int crn, unsigned int crm, unsigned int rt)
740 {
741     unsupported_encoding(s, insn);
742 }
743
744 /* C5.6.129 MRS - move from system register */
745 static void handle_mrs(DisasContext *s, uint32_t insn, unsigned int op0,
746                        unsigned int op1, unsigned int op2,
747                        unsigned int crn, unsigned int crm, unsigned int rt)
748 {
749     unsupported_encoding(s, insn);
750 }
751
752 /* C5.6.131 MSR (register) - move to system register */
753 static void handle_msr(DisasContext *s, uint32_t insn, unsigned int op0,
754                        unsigned int op1, unsigned int op2,
755                        unsigned int crn, unsigned int crm, unsigned int rt)
756 {
757     unsupported_encoding(s, insn);
758 }
759
760 /* C3.2.4 System
761  *  31                 22 21  20 19 18 16 15   12 11    8 7   5 4    0
762  * +---------------------+---+-----+-----+-------+-------+-----+------+
763  * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 |  CRn  |  CRm  | op2 |  Rt  |
764  * +---------------------+---+-----+-----+-------+-------+-----+------+
765  */
766 static void disas_system(DisasContext *s, uint32_t insn)
767 {
768     unsigned int l, op0, op1, crn, crm, op2, rt;
769     l = extract32(insn, 21, 1);
770     op0 = extract32(insn, 19, 2);
771     op1 = extract32(insn, 16, 3);
772     crn = extract32(insn, 12, 4);
773     crm = extract32(insn, 8, 4);
774     op2 = extract32(insn, 5, 3);
775     rt = extract32(insn, 0, 5);
776
777     if (op0 == 0) {
778         if (l || rt != 31) {
779             unallocated_encoding(s);
780             return;
781         }
782         switch (crn) {
783         case 2: /* C5.6.68 HINT */
784             handle_hint(s, insn, op1, op2, crm);
785             break;
786         case 3: /* CLREX, DSB, DMB, ISB */
787             handle_sync(s, insn, op1, op2, crm);
788             break;
789         case 4: /* C5.6.130 MSR (immediate) */
790             handle_msr_i(s, insn, op1, op2, crm);
791             break;
792         default:
793             unallocated_encoding(s);
794             break;
795         }
796         return;
797     }
798
799     if (op0 == 1) {
800         /* C5.6.204 SYS */
801         handle_sys(s, insn, l, op1, op2, crn, crm, rt);
802     } else if (l) { /* op0 > 1 */
803         /* C5.6.129 MRS - move from system register */
804         handle_mrs(s, insn, op0, op1, op2, crn, crm, rt);
805     } else {
806         /* C5.6.131 MSR (register) - move to system register */
807         handle_msr(s, insn, op0, op1, op2, crn, crm, rt);
808     }
809 }
810
811 /* Exception generation */
812 static void disas_exc(DisasContext *s, uint32_t insn)
813 {
814     unsupported_encoding(s, insn);
815 }
816
817 /* C3.2.7 Unconditional branch (register)
818  *  31           25 24   21 20   16 15   10 9    5 4     0
819  * +---------------+-------+-------+-------+------+-------+
820  * | 1 1 0 1 0 1 1 |  opc  |  op2  |  op3  |  Rn  |  op4  |
821  * +---------------+-------+-------+-------+------+-------+
822  */
823 static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
824 {
825     unsigned int opc, op2, op3, rn, op4;
826
827     opc = extract32(insn, 21, 4);
828     op2 = extract32(insn, 16, 5);
829     op3 = extract32(insn, 10, 6);
830     rn = extract32(insn, 5, 5);
831     op4 = extract32(insn, 0, 5);
832
833     if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
834         unallocated_encoding(s);
835         return;
836     }
837
838     switch (opc) {
839     case 0: /* BR */
840     case 2: /* RET */
841         break;
842     case 1: /* BLR */
843         tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
844         break;
845     case 4: /* ERET */
846     case 5: /* DRPS */
847         if (rn != 0x1f) {
848             unallocated_encoding(s);
849         } else {
850             unsupported_encoding(s, insn);
851         }
852         return;
853     default:
854         unallocated_encoding(s);
855         return;
856     }
857
858     tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
859     s->is_jmp = DISAS_JUMP;
860 }
861
862 /* C3.2 Branches, exception generating and system instructions */
863 static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
864 {
865     switch (extract32(insn, 25, 7)) {
866     case 0x0a: case 0x0b:
867     case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
868         disas_uncond_b_imm(s, insn);
869         break;
870     case 0x1a: case 0x5a: /* Compare & branch (immediate) */
871         disas_comp_b_imm(s, insn);
872         break;
873     case 0x1b: case 0x5b: /* Test & branch (immediate) */
874         disas_test_b_imm(s, insn);
875         break;
876     case 0x2a: /* Conditional branch (immediate) */
877         disas_cond_b_imm(s, insn);
878         break;
879     case 0x6a: /* Exception generation / System */
880         if (insn & (1 << 24)) {
881             disas_system(s, insn);
882         } else {
883             disas_exc(s, insn);
884         }
885         break;
886     case 0x6b: /* Unconditional branch (register) */
887         disas_uncond_b_reg(s, insn);
888         break;
889     default:
890         unallocated_encoding(s);
891         break;
892     }
893 }
894
895 /* Load/store exclusive */
896 static void disas_ldst_excl(DisasContext *s, uint32_t insn)
897 {
898     unsupported_encoding(s, insn);
899 }
900
901 /* Load register (literal) */
902 static void disas_ld_lit(DisasContext *s, uint32_t insn)
903 {
904     unsupported_encoding(s, insn);
905 }
906
907 /*
908  * C5.6.80 LDNP (Load Pair - non-temporal hint)
909  * C5.6.81 LDP (Load Pair - non vector)
910  * C5.6.82 LDPSW (Load Pair Signed Word - non vector)
911  * C5.6.176 STNP (Store Pair - non-temporal hint)
912  * C5.6.177 STP (Store Pair - non vector)
913  * C6.3.165 LDNP (Load Pair of SIMD&FP - non-temporal hint)
914  * C6.3.165 LDP (Load Pair of SIMD&FP)
915  * C6.3.284 STNP (Store Pair of SIMD&FP - non-temporal hint)
916  * C6.3.284 STP (Store Pair of SIMD&FP)
917  *
918  *  31 30 29   27  26  25 24   23  22 21   15 14   10 9    5 4    0
919  * +-----+-------+---+---+-------+---+-----------------------------+
920  * | opc | 1 0 1 | V | 0 | index | L |  imm7 |  Rt2  |  Rn  | Rt   |
921  * +-----+-------+---+---+-------+---+-------+-------+------+------+
922  *
923  * opc: LDP/STP/LDNP/STNP        00 -> 32 bit, 10 -> 64 bit
924  *      LDPSW                    01
925  *      LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
926  *   V: 0 -> GPR, 1 -> Vector
927  * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
928  *      10 -> signed offset, 11 -> pre-index
929  *   L: 0 -> Store 1 -> Load
930  *
931  * Rt, Rt2 = GPR or SIMD registers to be stored
932  * Rn = general purpose register containing address
933  * imm7 = signed offset (multiple of 4 or 8 depending on size)
934  */
935 static void disas_ldst_pair(DisasContext *s, uint32_t insn)
936 {
937     int rt = extract32(insn, 0, 5);
938     int rn = extract32(insn, 5, 5);
939     int rt2 = extract32(insn, 10, 5);
940     int64_t offset = sextract32(insn, 15, 7);
941     int index = extract32(insn, 23, 2);
942     bool is_vector = extract32(insn, 26, 1);
943     bool is_load = extract32(insn, 22, 1);
944     int opc = extract32(insn, 30, 2);
945
946     bool is_signed = false;
947     bool postindex = false;
948     bool wback = false;
949
950     TCGv_i64 tcg_addr; /* calculated address */
951     int size;
952
953     if (opc == 3) {
954         unallocated_encoding(s);
955         return;
956     }
957
958     if (is_vector) {
959         size = 2 + opc;
960     } else {
961         size = 2 + extract32(opc, 1, 1);
962         is_signed = extract32(opc, 0, 1);
963         if (!is_load && is_signed) {
964             unallocated_encoding(s);
965             return;
966         }
967     }
968
969     switch (index) {
970     case 1: /* post-index */
971         postindex = true;
972         wback = true;
973         break;
974     case 0:
975         /* signed offset with "non-temporal" hint. Since we don't emulate
976          * caches we don't care about hints to the cache system about
977          * data access patterns, and handle this identically to plain
978          * signed offset.
979          */
980         if (is_signed) {
981             /* There is no non-temporal-hint version of LDPSW */
982             unallocated_encoding(s);
983             return;
984         }
985         postindex = false;
986         break;
987     case 2: /* signed offset, rn not updated */
988         postindex = false;
989         break;
990     case 3: /* pre-index */
991         postindex = false;
992         wback = true;
993         break;
994     }
995
996     offset <<= size;
997
998     if (rn == 31) {
999         gen_check_sp_alignment(s);
1000     }
1001
1002     tcg_addr = read_cpu_reg_sp(s, rn, 1);
1003
1004     if (!postindex) {
1005         tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
1006     }
1007
1008     if (is_vector) {
1009         if (is_load) {
1010             do_fp_ld(s, rt, tcg_addr, size);
1011         } else {
1012             do_fp_st(s, rt, tcg_addr, size);
1013         }
1014     } else {
1015         TCGv_i64 tcg_rt = cpu_reg(s, rt);
1016         if (is_load) {
1017             do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
1018         } else {
1019             do_gpr_st(s, tcg_rt, tcg_addr, size);
1020         }
1021     }
1022     tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
1023     if (is_vector) {
1024         if (is_load) {
1025             do_fp_ld(s, rt2, tcg_addr, size);
1026         } else {
1027             do_fp_st(s, rt2, tcg_addr, size);
1028         }
1029     } else {
1030         TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
1031         if (is_load) {
1032             do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false);
1033         } else {
1034             do_gpr_st(s, tcg_rt2, tcg_addr, size);
1035         }
1036     }
1037
1038     if (wback) {
1039         if (postindex) {
1040             tcg_gen_addi_i64(tcg_addr, tcg_addr, offset - (1 << size));
1041         } else {
1042             tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size);
1043         }
1044         tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
1045     }
1046 }
1047
1048 /*
1049  * C3.3.8 Load/store (immediate post-indexed)
1050  * C3.3.9 Load/store (immediate pre-indexed)
1051  * C3.3.12 Load/store (unscaled immediate)
1052  *
1053  * 31 30 29   27  26 25 24 23 22 21  20    12 11 10 9    5 4    0
1054  * +----+-------+---+-----+-----+---+--------+-----+------+------+
1055  * |size| 1 1 1 | V | 0 0 | opc | 0 |  imm9  | idx |  Rn  |  Rt  |
1056  * +----+-------+---+-----+-----+---+--------+-----+------+------+
1057  *
1058  * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
1059  * V = 0 -> non-vector
1060  * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
1061  * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1062  */
1063 static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn)
1064 {
1065     int rt = extract32(insn, 0, 5);
1066     int rn = extract32(insn, 5, 5);
1067     int imm9 = sextract32(insn, 12, 9);
1068     int opc = extract32(insn, 22, 2);
1069     int size = extract32(insn, 30, 2);
1070     int idx = extract32(insn, 10, 2);
1071     bool is_signed = false;
1072     bool is_store = false;
1073     bool is_extended = false;
1074     bool is_vector = extract32(insn, 26, 1);
1075     bool post_index;
1076     bool writeback;
1077
1078     TCGv_i64 tcg_addr;
1079
1080     if (is_vector) {
1081         size |= (opc & 2) << 1;
1082         if (size > 4) {
1083             unallocated_encoding(s);
1084             return;
1085         }
1086         is_store = ((opc & 1) == 0);
1087     } else {
1088         if (size == 3 && opc == 2) {
1089             /* PRFM - prefetch */
1090             return;
1091         }
1092         if (opc == 3 && size > 1) {
1093             unallocated_encoding(s);
1094             return;
1095         }
1096         is_store = (opc == 0);
1097         is_signed = opc & (1<<1);
1098         is_extended = (size < 3) && (opc & 1);
1099     }
1100
1101     switch (idx) {
1102     case 0:
1103         post_index = false;
1104         writeback = false;
1105         break;
1106     case 1:
1107         post_index = true;
1108         writeback = true;
1109         break;
1110     case 3:
1111         post_index = false;
1112         writeback = true;
1113         break;
1114     case 2:
1115         g_assert(false);
1116         break;
1117     }
1118
1119     if (rn == 31) {
1120         gen_check_sp_alignment(s);
1121     }
1122     tcg_addr = read_cpu_reg_sp(s, rn, 1);
1123
1124     if (!post_index) {
1125         tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
1126     }
1127
1128     if (is_vector) {
1129         if (is_store) {
1130             do_fp_st(s, rt, tcg_addr, size);
1131         } else {
1132             do_fp_ld(s, rt, tcg_addr, size);
1133         }
1134     } else {
1135         TCGv_i64 tcg_rt = cpu_reg(s, rt);
1136         if (is_store) {
1137             do_gpr_st(s, tcg_rt, tcg_addr, size);
1138         } else {
1139             do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1140         }
1141     }
1142
1143     if (writeback) {
1144         TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
1145         if (post_index) {
1146             tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
1147         }
1148         tcg_gen_mov_i64(tcg_rn, tcg_addr);
1149     }
1150 }
1151
1152 /*
1153  * C3.3.10 Load/store (register offset)
1154  *
1155  * 31 30 29   27  26 25 24 23 22 21  20  16 15 13 12 11 10 9  5 4  0
1156  * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
1157  * |size| 1 1 1 | V | 0 0 | opc | 1 |  Rm  | opt | S| 1 0 | Rn | Rt |
1158  * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
1159  *
1160  * For non-vector:
1161  *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
1162  *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1163  * For vector:
1164  *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
1165  *   opc<0>: 0 -> store, 1 -> load
1166  * V: 1 -> vector/simd
1167  * opt: extend encoding (see DecodeRegExtend)
1168  * S: if S=1 then scale (essentially index by sizeof(size))
1169  * Rt: register to transfer into/out of
1170  * Rn: address register or SP for base
1171  * Rm: offset register or ZR for offset
1172  */
1173 static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn)
1174 {
1175     int rt = extract32(insn, 0, 5);
1176     int rn = extract32(insn, 5, 5);
1177     int shift = extract32(insn, 12, 1);
1178     int rm = extract32(insn, 16, 5);
1179     int opc = extract32(insn, 22, 2);
1180     int opt = extract32(insn, 13, 3);
1181     int size = extract32(insn, 30, 2);
1182     bool is_signed = false;
1183     bool is_store = false;
1184     bool is_extended = false;
1185     bool is_vector = extract32(insn, 26, 1);
1186
1187     TCGv_i64 tcg_rm;
1188     TCGv_i64 tcg_addr;
1189
1190     if (extract32(opt, 1, 1) == 0) {
1191         unallocated_encoding(s);
1192         return;
1193     }
1194
1195     if (is_vector) {
1196         size |= (opc & 2) << 1;
1197         if (size > 4) {
1198             unallocated_encoding(s);
1199             return;
1200         }
1201         is_store = !extract32(opc, 0, 1);
1202     } else {
1203         if (size == 3 && opc == 2) {
1204             /* PRFM - prefetch */
1205             return;
1206         }
1207         if (opc == 3 && size > 1) {
1208             unallocated_encoding(s);
1209             return;
1210         }
1211         is_store = (opc == 0);
1212         is_signed = extract32(opc, 1, 1);
1213         is_extended = (size < 3) && extract32(opc, 0, 1);
1214     }
1215
1216     if (rn == 31) {
1217         gen_check_sp_alignment(s);
1218     }
1219     tcg_addr = read_cpu_reg_sp(s, rn, 1);
1220
1221     tcg_rm = read_cpu_reg(s, rm, 1);
1222     ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
1223
1224     tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_rm);
1225
1226     if (is_vector) {
1227         if (is_store) {
1228             do_fp_st(s, rt, tcg_addr, size);
1229         } else {
1230             do_fp_ld(s, rt, tcg_addr, size);
1231         }
1232     } else {
1233         TCGv_i64 tcg_rt = cpu_reg(s, rt);
1234         if (is_store) {
1235             do_gpr_st(s, tcg_rt, tcg_addr, size);
1236         } else {
1237             do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1238         }
1239     }
1240 }
1241
1242 /*
1243  * C3.3.13 Load/store (unsigned immediate)
1244  *
1245  * 31 30 29   27  26 25 24 23 22 21        10 9     5
1246  * +----+-------+---+-----+-----+------------+-------+------+
1247  * |size| 1 1 1 | V | 0 1 | opc |   imm12    |  Rn   |  Rt  |
1248  * +----+-------+---+-----+-----+------------+-------+------+
1249  *
1250  * For non-vector:
1251  *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
1252  *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1253  * For vector:
1254  *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
1255  *   opc<0>: 0 -> store, 1 -> load
1256  * Rn: base address register (inc SP)
1257  * Rt: target register
1258  */
1259 static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn)
1260 {
1261     int rt = extract32(insn, 0, 5);
1262     int rn = extract32(insn, 5, 5);
1263     unsigned int imm12 = extract32(insn, 10, 12);
1264     bool is_vector = extract32(insn, 26, 1);
1265     int size = extract32(insn, 30, 2);
1266     int opc = extract32(insn, 22, 2);
1267     unsigned int offset;
1268
1269     TCGv_i64 tcg_addr;
1270
1271     bool is_store;
1272     bool is_signed = false;
1273     bool is_extended = false;
1274
1275     if (is_vector) {
1276         size |= (opc & 2) << 1;
1277         if (size > 4) {
1278             unallocated_encoding(s);
1279             return;
1280         }
1281         is_store = !extract32(opc, 0, 1);
1282     } else {
1283         if (size == 3 && opc == 2) {
1284             /* PRFM - prefetch */
1285             return;
1286         }
1287         if (opc == 3 && size > 1) {
1288             unallocated_encoding(s);
1289             return;
1290         }
1291         is_store = (opc == 0);
1292         is_signed = extract32(opc, 1, 1);
1293         is_extended = (size < 3) && extract32(opc, 0, 1);
1294     }
1295
1296     if (rn == 31) {
1297         gen_check_sp_alignment(s);
1298     }
1299     tcg_addr = read_cpu_reg_sp(s, rn, 1);
1300     offset = imm12 << size;
1301     tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
1302
1303     if (is_vector) {
1304         if (is_store) {
1305             do_fp_st(s, rt, tcg_addr, size);
1306         } else {
1307             do_fp_ld(s, rt, tcg_addr, size);
1308         }
1309     } else {
1310         TCGv_i64 tcg_rt = cpu_reg(s, rt);
1311         if (is_store) {
1312             do_gpr_st(s, tcg_rt, tcg_addr, size);
1313         } else {
1314             do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1315         }
1316     }
1317 }
1318
1319 /* Load/store register (immediate forms) */
1320 static void disas_ldst_reg_imm(DisasContext *s, uint32_t insn)
1321 {
1322     switch (extract32(insn, 10, 2)) {
1323     case 0: case 1: case 3:
1324         /* Load/store register (unscaled immediate) */
1325         /* Load/store immediate pre/post-indexed */
1326         disas_ldst_reg_imm9(s, insn);
1327         break;
1328     case 2:
1329         /* Load/store register unprivileged */
1330         unsupported_encoding(s, insn);
1331         break;
1332     default:
1333         unallocated_encoding(s);
1334         break;
1335     }
1336 }
1337
1338 /* Load/store register (all forms) */
1339 static void disas_ldst_reg(DisasContext *s, uint32_t insn)
1340 {
1341     switch (extract32(insn, 24, 2)) {
1342     case 0:
1343         if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) {
1344             disas_ldst_reg_roffset(s, insn);
1345         } else {
1346             disas_ldst_reg_imm(s, insn);
1347         }
1348         break;
1349     case 1:
1350         disas_ldst_reg_unsigned_imm(s, insn);
1351         break;
1352     default:
1353         unallocated_encoding(s);
1354         break;
1355     }
1356 }
1357
1358 /* AdvSIMD load/store multiple structures */
1359 static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
1360 {
1361     unsupported_encoding(s, insn);
1362 }
1363
1364 /* AdvSIMD load/store single structure */
1365 static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
1366 {
1367     unsupported_encoding(s, insn);
1368 }
1369
1370 /* C3.3 Loads and stores */
1371 static void disas_ldst(DisasContext *s, uint32_t insn)
1372 {
1373     switch (extract32(insn, 24, 6)) {
1374     case 0x08: /* Load/store exclusive */
1375         disas_ldst_excl(s, insn);
1376         break;
1377     case 0x18: case 0x1c: /* Load register (literal) */
1378         disas_ld_lit(s, insn);
1379         break;
1380     case 0x28: case 0x29:
1381     case 0x2c: case 0x2d: /* Load/store pair (all forms) */
1382         disas_ldst_pair(s, insn);
1383         break;
1384     case 0x38: case 0x39:
1385     case 0x3c: case 0x3d: /* Load/store register (all forms) */
1386         disas_ldst_reg(s, insn);
1387         break;
1388     case 0x0c: /* AdvSIMD load/store multiple structures */
1389         disas_ldst_multiple_struct(s, insn);
1390         break;
1391     case 0x0d: /* AdvSIMD load/store single structure */
1392         disas_ldst_single_struct(s, insn);
1393         break;
1394     default:
1395         unallocated_encoding(s);
1396         break;
1397     }
1398 }
1399
1400 /* C3.4.6 PC-rel. addressing
1401  *   31  30   29 28       24 23                5 4    0
1402  * +----+-------+-----------+-------------------+------+
1403  * | op | immlo | 1 0 0 0 0 |       immhi       |  Rd  |
1404  * +----+-------+-----------+-------------------+------+
1405  */
1406 static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
1407 {
1408     unsigned int page, rd;
1409     uint64_t base;
1410     int64_t offset;
1411
1412     page = extract32(insn, 31, 1);
1413     /* SignExtend(immhi:immlo) -> offset */
1414     offset = ((int64_t)sextract32(insn, 5, 19) << 2) | extract32(insn, 29, 2);
1415     rd = extract32(insn, 0, 5);
1416     base = s->pc - 4;
1417
1418     if (page) {
1419         /* ADRP (page based) */
1420         base &= ~0xfff;
1421         offset <<= 12;
1422     }
1423
1424     tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
1425 }
1426
1427 /*
1428  * C3.4.1 Add/subtract (immediate)
1429  *
1430  *  31 30 29 28       24 23 22 21         10 9   5 4   0
1431  * +--+--+--+-----------+-----+-------------+-----+-----+
1432  * |sf|op| S| 1 0 0 0 1 |shift|    imm12    |  Rn | Rd  |
1433  * +--+--+--+-----------+-----+-------------+-----+-----+
1434  *
1435  *    sf: 0 -> 32bit, 1 -> 64bit
1436  *    op: 0 -> add  , 1 -> sub
1437  *     S: 1 -> set flags
1438  * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
1439  */
1440 static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
1441 {
1442     int rd = extract32(insn, 0, 5);
1443     int rn = extract32(insn, 5, 5);
1444     uint64_t imm = extract32(insn, 10, 12);
1445     int shift = extract32(insn, 22, 2);
1446     bool setflags = extract32(insn, 29, 1);
1447     bool sub_op = extract32(insn, 30, 1);
1448     bool is_64bit = extract32(insn, 31, 1);
1449
1450     TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
1451     TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
1452     TCGv_i64 tcg_result;
1453
1454     switch (shift) {
1455     case 0x0:
1456         break;
1457     case 0x1:
1458         imm <<= 12;
1459         break;
1460     default:
1461         unallocated_encoding(s);
1462         return;
1463     }
1464
1465     tcg_result = tcg_temp_new_i64();
1466     if (!setflags) {
1467         if (sub_op) {
1468             tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
1469         } else {
1470             tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
1471         }
1472     } else {
1473         TCGv_i64 tcg_imm = tcg_const_i64(imm);
1474         if (sub_op) {
1475             gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
1476         } else {
1477             gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
1478         }
1479         tcg_temp_free_i64(tcg_imm);
1480     }
1481
1482     if (is_64bit) {
1483         tcg_gen_mov_i64(tcg_rd, tcg_result);
1484     } else {
1485         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
1486     }
1487
1488     tcg_temp_free_i64(tcg_result);
1489 }
1490
1491 /* The input should be a value in the bottom e bits (with higher
1492  * bits zero); returns that value replicated into every element
1493  * of size e in a 64 bit integer.
1494  */
1495 static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
1496 {
1497     assert(e != 0);
1498     while (e < 64) {
1499         mask |= mask << e;
1500         e *= 2;
1501     }
1502     return mask;
1503 }
1504
1505 /* Return a value with the bottom len bits set (where 0 < len <= 64) */
1506 static inline uint64_t bitmask64(unsigned int length)
1507 {
1508     assert(length > 0 && length <= 64);
1509     return ~0ULL >> (64 - length);
1510 }
1511
1512 /* Simplified variant of pseudocode DecodeBitMasks() for the case where we
1513  * only require the wmask. Returns false if the imms/immr/immn are a reserved
1514  * value (ie should cause a guest UNDEF exception), and true if they are
1515  * valid, in which case the decoded bit pattern is written to result.
1516  */
1517 static bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
1518                                    unsigned int imms, unsigned int immr)
1519 {
1520     uint64_t mask;
1521     unsigned e, levels, s, r;
1522     int len;
1523
1524     assert(immn < 2 && imms < 64 && immr < 64);
1525
1526     /* The bit patterns we create here are 64 bit patterns which
1527      * are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
1528      * 64 bits each. Each element contains the same value: a run
1529      * of between 1 and e-1 non-zero bits, rotated within the
1530      * element by between 0 and e-1 bits.
1531      *
1532      * The element size and run length are encoded into immn (1 bit)
1533      * and imms (6 bits) as follows:
1534      * 64 bit elements: immn = 1, imms = <length of run - 1>
1535      * 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
1536      * 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
1537      *  8 bit elements: immn = 0, imms = 110 : <length of run - 1>
1538      *  4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
1539      *  2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
1540      * Notice that immn = 0, imms = 11111x is the only combination
1541      * not covered by one of the above options; this is reserved.
1542      * Further, <length of run - 1> all-ones is a reserved pattern.
1543      *
1544      * In all cases the rotation is by immr % e (and immr is 6 bits).
1545      */
1546
1547     /* First determine the element size */
1548     len = 31 - clz32((immn << 6) | (~imms & 0x3f));
1549     if (len < 1) {
1550         /* This is the immn == 0, imms == 0x11111x case */
1551         return false;
1552     }
1553     e = 1 << len;
1554
1555     levels = e - 1;
1556     s = imms & levels;
1557     r = immr & levels;
1558
1559     if (s == levels) {
1560         /* <length of run - 1> mustn't be all-ones. */
1561         return false;
1562     }
1563
1564     /* Create the value of one element: s+1 set bits rotated
1565      * by r within the element (which is e bits wide)...
1566      */
1567     mask = bitmask64(s + 1);
1568     mask = (mask >> r) | (mask << (e - r));
1569     /* ...then replicate the element over the whole 64 bit value */
1570     mask = bitfield_replicate(mask, e);
1571     *result = mask;
1572     return true;
1573 }
1574
1575 /* C3.4.4 Logical (immediate)
1576  *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
1577  * +----+-----+-------------+---+------+------+------+------+
1578  * | sf | opc | 1 0 0 1 0 0 | N | immr | imms |  Rn  |  Rd  |
1579  * +----+-----+-------------+---+------+------+------+------+
1580  */
1581 static void disas_logic_imm(DisasContext *s, uint32_t insn)
1582 {
1583     unsigned int sf, opc, is_n, immr, imms, rn, rd;
1584     TCGv_i64 tcg_rd, tcg_rn;
1585     uint64_t wmask;
1586     bool is_and = false;
1587
1588     sf = extract32(insn, 31, 1);
1589     opc = extract32(insn, 29, 2);
1590     is_n = extract32(insn, 22, 1);
1591     immr = extract32(insn, 16, 6);
1592     imms = extract32(insn, 10, 6);
1593     rn = extract32(insn, 5, 5);
1594     rd = extract32(insn, 0, 5);
1595
1596     if (!sf && is_n) {
1597         unallocated_encoding(s);
1598         return;
1599     }
1600
1601     if (opc == 0x3) { /* ANDS */
1602         tcg_rd = cpu_reg(s, rd);
1603     } else {
1604         tcg_rd = cpu_reg_sp(s, rd);
1605     }
1606     tcg_rn = cpu_reg(s, rn);
1607
1608     if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
1609         /* some immediate field values are reserved */
1610         unallocated_encoding(s);
1611         return;
1612     }
1613
1614     if (!sf) {
1615         wmask &= 0xffffffff;
1616     }
1617
1618     switch (opc) {
1619     case 0x3: /* ANDS */
1620     case 0x0: /* AND */
1621         tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
1622         is_and = true;
1623         break;
1624     case 0x1: /* ORR */
1625         tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
1626         break;
1627     case 0x2: /* EOR */
1628         tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
1629         break;
1630     default:
1631         assert(FALSE); /* must handle all above */
1632         break;
1633     }
1634
1635     if (!sf && !is_and) {
1636         /* zero extend final result; we know we can skip this for AND
1637          * since the immediate had the high 32 bits clear.
1638          */
1639         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1640     }
1641
1642     if (opc == 3) { /* ANDS */
1643         gen_logic_CC(sf, tcg_rd);
1644     }
1645 }
1646
1647 /* Move wide (immediate) */
1648 static void disas_movw_imm(DisasContext *s, uint32_t insn)
1649 {
1650     unsupported_encoding(s, insn);
1651 }
1652
1653 /* C3.4.2 Bitfield
1654  *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
1655  * +----+-----+-------------+---+------+------+------+------+
1656  * | sf | opc | 1 0 0 1 1 0 | N | immr | imms |  Rn  |  Rd  |
1657  * +----+-----+-------------+---+------+------+------+------+
1658  */
1659 static void disas_bitfield(DisasContext *s, uint32_t insn)
1660 {
1661     unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
1662     TCGv_i64 tcg_rd, tcg_tmp;
1663
1664     sf = extract32(insn, 31, 1);
1665     opc = extract32(insn, 29, 2);
1666     n = extract32(insn, 22, 1);
1667     ri = extract32(insn, 16, 6);
1668     si = extract32(insn, 10, 6);
1669     rn = extract32(insn, 5, 5);
1670     rd = extract32(insn, 0, 5);
1671     bitsize = sf ? 64 : 32;
1672
1673     if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
1674         unallocated_encoding(s);
1675         return;
1676     }
1677
1678     tcg_rd = cpu_reg(s, rd);
1679     tcg_tmp = read_cpu_reg(s, rn, sf);
1680
1681     /* OPTME: probably worth recognizing common cases of ext{8,16,32}{u,s} */
1682
1683     if (opc != 1) { /* SBFM or UBFM */
1684         tcg_gen_movi_i64(tcg_rd, 0);
1685     }
1686
1687     /* do the bit move operation */
1688     if (si >= ri) {
1689         /* Wd<s-r:0> = Wn<s:r> */
1690         tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
1691         pos = 0;
1692         len = (si - ri) + 1;
1693     } else {
1694         /* Wd<32+s-r,32-r> = Wn<s:0> */
1695         pos = bitsize - ri;
1696         len = si + 1;
1697     }
1698
1699     tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
1700
1701     if (opc == 0) { /* SBFM - sign extend the destination field */
1702         tcg_gen_shli_i64(tcg_rd, tcg_rd, 64 - (pos + len));
1703         tcg_gen_sari_i64(tcg_rd, tcg_rd, 64 - (pos + len));
1704     }
1705
1706     if (!sf) { /* zero extend final result */
1707         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1708     }
1709 }
1710
1711 /* C3.4.3 Extract
1712  *   31  30  29 28         23 22   21  20  16 15    10 9    5 4    0
1713  * +----+------+-------------+---+----+------+--------+------+------+
1714  * | sf | op21 | 1 0 0 1 1 1 | N | o0 |  Rm  |  imms  |  Rn  |  Rd  |
1715  * +----+------+-------------+---+----+------+--------+------+------+
1716  */
1717 static void disas_extract(DisasContext *s, uint32_t insn)
1718 {
1719     unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
1720
1721     sf = extract32(insn, 31, 1);
1722     n = extract32(insn, 22, 1);
1723     rm = extract32(insn, 16, 5);
1724     imm = extract32(insn, 10, 6);
1725     rn = extract32(insn, 5, 5);
1726     rd = extract32(insn, 0, 5);
1727     op21 = extract32(insn, 29, 2);
1728     op0 = extract32(insn, 21, 1);
1729     bitsize = sf ? 64 : 32;
1730
1731     if (sf != n || op21 || op0 || imm >= bitsize) {
1732         unallocated_encoding(s);
1733     } else {
1734         TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
1735
1736         tcg_rd = cpu_reg(s, rd);
1737
1738         if (imm) {
1739             /* OPTME: we can special case rm==rn as a rotate */
1740             tcg_rm = read_cpu_reg(s, rm, sf);
1741             tcg_rn = read_cpu_reg(s, rn, sf);
1742             tcg_gen_shri_i64(tcg_rm, tcg_rm, imm);
1743             tcg_gen_shli_i64(tcg_rn, tcg_rn, bitsize - imm);
1744             tcg_gen_or_i64(tcg_rd, tcg_rm, tcg_rn);
1745             if (!sf) {
1746                 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1747             }
1748         } else {
1749             /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
1750              * so an extract from bit 0 is a special case.
1751              */
1752             if (sf) {
1753                 tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
1754             } else {
1755                 tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
1756             }
1757         }
1758
1759     }
1760 }
1761
1762 /* C3.4 Data processing - immediate */
1763 static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
1764 {
1765     switch (extract32(insn, 23, 6)) {
1766     case 0x20: case 0x21: /* PC-rel. addressing */
1767         disas_pc_rel_adr(s, insn);
1768         break;
1769     case 0x22: case 0x23: /* Add/subtract (immediate) */
1770         disas_add_sub_imm(s, insn);
1771         break;
1772     case 0x24: /* Logical (immediate) */
1773         disas_logic_imm(s, insn);
1774         break;
1775     case 0x25: /* Move wide (immediate) */
1776         disas_movw_imm(s, insn);
1777         break;
1778     case 0x26: /* Bitfield */
1779         disas_bitfield(s, insn);
1780         break;
1781     case 0x27: /* Extract */
1782         disas_extract(s, insn);
1783         break;
1784     default:
1785         unallocated_encoding(s);
1786         break;
1787     }
1788 }
1789
1790 /* Shift a TCGv src by TCGv shift_amount, put result in dst.
1791  * Note that it is the caller's responsibility to ensure that the
1792  * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
1793  * mandated semantics for out of range shifts.
1794  */
1795 static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
1796                       enum a64_shift_type shift_type, TCGv_i64 shift_amount)
1797 {
1798     switch (shift_type) {
1799     case A64_SHIFT_TYPE_LSL:
1800         tcg_gen_shl_i64(dst, src, shift_amount);
1801         break;
1802     case A64_SHIFT_TYPE_LSR:
1803         tcg_gen_shr_i64(dst, src, shift_amount);
1804         break;
1805     case A64_SHIFT_TYPE_ASR:
1806         if (!sf) {
1807             tcg_gen_ext32s_i64(dst, src);
1808         }
1809         tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
1810         break;
1811     case A64_SHIFT_TYPE_ROR:
1812         if (sf) {
1813             tcg_gen_rotr_i64(dst, src, shift_amount);
1814         } else {
1815             TCGv_i32 t0, t1;
1816             t0 = tcg_temp_new_i32();
1817             t1 = tcg_temp_new_i32();
1818             tcg_gen_trunc_i64_i32(t0, src);
1819             tcg_gen_trunc_i64_i32(t1, shift_amount);
1820             tcg_gen_rotr_i32(t0, t0, t1);
1821             tcg_gen_extu_i32_i64(dst, t0);
1822             tcg_temp_free_i32(t0);
1823             tcg_temp_free_i32(t1);
1824         }
1825         break;
1826     default:
1827         assert(FALSE); /* all shift types should be handled */
1828         break;
1829     }
1830
1831     if (!sf) { /* zero extend final result */
1832         tcg_gen_ext32u_i64(dst, dst);
1833     }
1834 }
1835
1836 /* Shift a TCGv src by immediate, put result in dst.
1837  * The shift amount must be in range (this should always be true as the
1838  * relevant instructions will UNDEF on bad shift immediates).
1839  */
1840 static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
1841                           enum a64_shift_type shift_type, unsigned int shift_i)
1842 {
1843     assert(shift_i < (sf ? 64 : 32));
1844
1845     if (shift_i == 0) {
1846         tcg_gen_mov_i64(dst, src);
1847     } else {
1848         TCGv_i64 shift_const;
1849
1850         shift_const = tcg_const_i64(shift_i);
1851         shift_reg(dst, src, sf, shift_type, shift_const);
1852         tcg_temp_free_i64(shift_const);
1853     }
1854 }
1855
1856 /* C3.5.10 Logical (shifted register)
1857  *   31  30 29 28       24 23   22 21  20  16 15    10 9    5 4    0
1858  * +----+-----+-----------+-------+---+------+--------+------+------+
1859  * | sf | opc | 0 1 0 1 0 | shift | N |  Rm  |  imm6  |  Rn  |  Rd  |
1860  * +----+-----+-----------+-------+---+------+--------+------+------+
1861  */
1862 static void disas_logic_reg(DisasContext *s, uint32_t insn)
1863 {
1864     TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
1865     unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
1866
1867     sf = extract32(insn, 31, 1);
1868     opc = extract32(insn, 29, 2);
1869     shift_type = extract32(insn, 22, 2);
1870     invert = extract32(insn, 21, 1);
1871     rm = extract32(insn, 16, 5);
1872     shift_amount = extract32(insn, 10, 6);
1873     rn = extract32(insn, 5, 5);
1874     rd = extract32(insn, 0, 5);
1875
1876     if (!sf && (shift_amount & (1 << 5))) {
1877         unallocated_encoding(s);
1878         return;
1879     }
1880
1881     tcg_rd = cpu_reg(s, rd);
1882
1883     if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
1884         /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
1885          * register-register MOV and MVN, so it is worth special casing.
1886          */
1887         tcg_rm = cpu_reg(s, rm);
1888         if (invert) {
1889             tcg_gen_not_i64(tcg_rd, tcg_rm);
1890             if (!sf) {
1891                 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1892             }
1893         } else {
1894             if (sf) {
1895                 tcg_gen_mov_i64(tcg_rd, tcg_rm);
1896             } else {
1897                 tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
1898             }
1899         }
1900         return;
1901     }
1902
1903     tcg_rm = read_cpu_reg(s, rm, sf);
1904
1905     if (shift_amount) {
1906         shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
1907     }
1908
1909     tcg_rn = cpu_reg(s, rn);
1910
1911     switch (opc | (invert << 2)) {
1912     case 0: /* AND */
1913     case 3: /* ANDS */
1914         tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
1915         break;
1916     case 1: /* ORR */
1917         tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
1918         break;
1919     case 2: /* EOR */
1920         tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
1921         break;
1922     case 4: /* BIC */
1923     case 7: /* BICS */
1924         tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
1925         break;
1926     case 5: /* ORN */
1927         tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
1928         break;
1929     case 6: /* EON */
1930         tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
1931         break;
1932     default:
1933         assert(FALSE);
1934         break;
1935     }
1936
1937     if (!sf) {
1938         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1939     }
1940
1941     if (opc == 3) {
1942         gen_logic_CC(sf, tcg_rd);
1943     }
1944 }
1945
1946 /*
1947  * C3.5.1 Add/subtract (extended register)
1948  *
1949  *  31|30|29|28       24|23 22|21|20   16|15  13|12  10|9  5|4  0|
1950  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
1951  * |sf|op| S| 0 1 0 1 1 | opt | 1|  Rm   |option| imm3 | Rn | Rd |
1952  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
1953  *
1954  *  sf: 0 -> 32bit, 1 -> 64bit
1955  *  op: 0 -> add  , 1 -> sub
1956  *   S: 1 -> set flags
1957  * opt: 00
1958  * option: extension type (see DecodeRegExtend)
1959  * imm3: optional shift to Rm
1960  *
1961  * Rd = Rn + LSL(extend(Rm), amount)
1962  */
1963 static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
1964 {
1965     int rd = extract32(insn, 0, 5);
1966     int rn = extract32(insn, 5, 5);
1967     int imm3 = extract32(insn, 10, 3);
1968     int option = extract32(insn, 13, 3);
1969     int rm = extract32(insn, 16, 5);
1970     bool setflags = extract32(insn, 29, 1);
1971     bool sub_op = extract32(insn, 30, 1);
1972     bool sf = extract32(insn, 31, 1);
1973
1974     TCGv_i64 tcg_rm, tcg_rn; /* temps */
1975     TCGv_i64 tcg_rd;
1976     TCGv_i64 tcg_result;
1977
1978     if (imm3 > 4) {
1979         unallocated_encoding(s);
1980         return;
1981     }
1982
1983     /* non-flag setting ops may use SP */
1984     if (!setflags) {
1985         tcg_rn = read_cpu_reg_sp(s, rn, sf);
1986         tcg_rd = cpu_reg_sp(s, rd);
1987     } else {
1988         tcg_rn = read_cpu_reg(s, rn, sf);
1989         tcg_rd = cpu_reg(s, rd);
1990     }
1991
1992     tcg_rm = read_cpu_reg(s, rm, sf);
1993     ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
1994
1995     tcg_result = tcg_temp_new_i64();
1996
1997     if (!setflags) {
1998         if (sub_op) {
1999             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
2000         } else {
2001             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
2002         }
2003     } else {
2004         if (sub_op) {
2005             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
2006         } else {
2007             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
2008         }
2009     }
2010
2011     if (sf) {
2012         tcg_gen_mov_i64(tcg_rd, tcg_result);
2013     } else {
2014         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
2015     }
2016
2017     tcg_temp_free_i64(tcg_result);
2018 }
2019
2020 /*
2021  * C3.5.2 Add/subtract (shifted register)
2022  *
2023  *  31 30 29 28       24 23 22 21 20   16 15     10 9    5 4    0
2024  * +--+--+--+-----------+-----+--+-------+---------+------+------+
2025  * |sf|op| S| 0 1 0 1 1 |shift| 0|  Rm   |  imm6   |  Rn  |  Rd  |
2026  * +--+--+--+-----------+-----+--+-------+---------+------+------+
2027  *
2028  *    sf: 0 -> 32bit, 1 -> 64bit
2029  *    op: 0 -> add  , 1 -> sub
2030  *     S: 1 -> set flags
2031  * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
2032  *  imm6: Shift amount to apply to Rm before the add/sub
2033  */
2034 static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
2035 {
2036     int rd = extract32(insn, 0, 5);
2037     int rn = extract32(insn, 5, 5);
2038     int imm6 = extract32(insn, 10, 6);
2039     int rm = extract32(insn, 16, 5);
2040     int shift_type = extract32(insn, 22, 2);
2041     bool setflags = extract32(insn, 29, 1);
2042     bool sub_op = extract32(insn, 30, 1);
2043     bool sf = extract32(insn, 31, 1);
2044
2045     TCGv_i64 tcg_rd = cpu_reg(s, rd);
2046     TCGv_i64 tcg_rn, tcg_rm;
2047     TCGv_i64 tcg_result;
2048
2049     if ((shift_type == 3) || (!sf && (imm6 > 31))) {
2050         unallocated_encoding(s);
2051         return;
2052     }
2053
2054     tcg_rn = read_cpu_reg(s, rn, sf);
2055     tcg_rm = read_cpu_reg(s, rm, sf);
2056
2057     shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
2058
2059     tcg_result = tcg_temp_new_i64();
2060
2061     if (!setflags) {
2062         if (sub_op) {
2063             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
2064         } else {
2065             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
2066         }
2067     } else {
2068         if (sub_op) {
2069             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
2070         } else {
2071             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
2072         }
2073     }
2074
2075     if (sf) {
2076         tcg_gen_mov_i64(tcg_rd, tcg_result);
2077     } else {
2078         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
2079     }
2080
2081     tcg_temp_free_i64(tcg_result);
2082 }
2083
2084 /* Data-processing (3 source) */
2085 static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
2086 {
2087     unsupported_encoding(s, insn);
2088 }
2089
2090 /* Add/subtract (with carry) */
2091 static void disas_adc_sbc(DisasContext *s, uint32_t insn)
2092 {
2093     unsupported_encoding(s, insn);
2094 }
2095
2096 /* Conditional compare (immediate) */
2097 static void disas_cc_imm(DisasContext *s, uint32_t insn)
2098 {
2099     unsupported_encoding(s, insn);
2100 }
2101
2102 /* Conditional compare (register) */
2103 static void disas_cc_reg(DisasContext *s, uint32_t insn)
2104 {
2105     unsupported_encoding(s, insn);
2106 }
2107
2108 /* C3.5.6 Conditional select
2109  *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
2110  * +----+----+---+-----------------+------+------+-----+------+------+
2111  * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
2112  * +----+----+---+-----------------+------+------+-----+------+------+
2113  */
2114 static void disas_cond_select(DisasContext *s, uint32_t insn)
2115 {
2116     unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
2117     TCGv_i64 tcg_rd, tcg_src;
2118
2119     if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
2120         /* S == 1 or op2<1> == 1 */
2121         unallocated_encoding(s);
2122         return;
2123     }
2124     sf = extract32(insn, 31, 1);
2125     else_inv = extract32(insn, 30, 1);
2126     rm = extract32(insn, 16, 5);
2127     cond = extract32(insn, 12, 4);
2128     else_inc = extract32(insn, 10, 1);
2129     rn = extract32(insn, 5, 5);
2130     rd = extract32(insn, 0, 5);
2131
2132     if (rd == 31) {
2133         /* silly no-op write; until we use movcond we must special-case
2134          * this to avoid a dead temporary across basic blocks.
2135          */
2136         return;
2137     }
2138
2139     tcg_rd = cpu_reg(s, rd);
2140
2141     if (cond >= 0x0e) { /* condition "always" */
2142         tcg_src = read_cpu_reg(s, rn, sf);
2143         tcg_gen_mov_i64(tcg_rd, tcg_src);
2144     } else {
2145         /* OPTME: we could use movcond here, at the cost of duplicating
2146          * a lot of the arm_gen_test_cc() logic.
2147          */
2148         int label_match = gen_new_label();
2149         int label_continue = gen_new_label();
2150
2151         arm_gen_test_cc(cond, label_match);
2152         /* nomatch: */
2153         tcg_src = cpu_reg(s, rm);
2154
2155         if (else_inv && else_inc) {
2156             tcg_gen_neg_i64(tcg_rd, tcg_src);
2157         } else if (else_inv) {
2158             tcg_gen_not_i64(tcg_rd, tcg_src);
2159         } else if (else_inc) {
2160             tcg_gen_addi_i64(tcg_rd, tcg_src, 1);
2161         } else {
2162             tcg_gen_mov_i64(tcg_rd, tcg_src);
2163         }
2164         if (!sf) {
2165             tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2166         }
2167         tcg_gen_br(label_continue);
2168         /* match: */
2169         gen_set_label(label_match);
2170         tcg_src = read_cpu_reg(s, rn, sf);
2171         tcg_gen_mov_i64(tcg_rd, tcg_src);
2172         /* continue: */
2173         gen_set_label(label_continue);
2174     }
2175 }
2176
2177 static void handle_clz(DisasContext *s, unsigned int sf,
2178                        unsigned int rn, unsigned int rd)
2179 {
2180     TCGv_i64 tcg_rd, tcg_rn;
2181     tcg_rd = cpu_reg(s, rd);
2182     tcg_rn = cpu_reg(s, rn);
2183
2184     if (sf) {
2185         gen_helper_clz64(tcg_rd, tcg_rn);
2186     } else {
2187         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
2188         tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
2189         gen_helper_clz(tcg_tmp32, tcg_tmp32);
2190         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
2191         tcg_temp_free_i32(tcg_tmp32);
2192     }
2193 }
2194
2195 static void handle_cls(DisasContext *s, unsigned int sf,
2196                        unsigned int rn, unsigned int rd)
2197 {
2198     TCGv_i64 tcg_rd, tcg_rn;
2199     tcg_rd = cpu_reg(s, rd);
2200     tcg_rn = cpu_reg(s, rn);
2201
2202     if (sf) {
2203         gen_helper_cls64(tcg_rd, tcg_rn);
2204     } else {
2205         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
2206         tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
2207         gen_helper_cls32(tcg_tmp32, tcg_tmp32);
2208         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
2209         tcg_temp_free_i32(tcg_tmp32);
2210     }
2211 }
2212
2213 static void handle_rbit(DisasContext *s, unsigned int sf,
2214                         unsigned int rn, unsigned int rd)
2215 {
2216     TCGv_i64 tcg_rd, tcg_rn;
2217     tcg_rd = cpu_reg(s, rd);
2218     tcg_rn = cpu_reg(s, rn);
2219
2220     if (sf) {
2221         gen_helper_rbit64(tcg_rd, tcg_rn);
2222     } else {
2223         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
2224         tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
2225         gen_helper_rbit(tcg_tmp32, tcg_tmp32);
2226         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
2227         tcg_temp_free_i32(tcg_tmp32);
2228     }
2229 }
2230
2231 /* C5.6.149 REV with sf==1, opcode==3 ("REV64") */
2232 static void handle_rev64(DisasContext *s, unsigned int sf,
2233                          unsigned int rn, unsigned int rd)
2234 {
2235     if (!sf) {
2236         unallocated_encoding(s);
2237         return;
2238     }
2239     tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
2240 }
2241
2242 /* C5.6.149 REV with sf==0, opcode==2
2243  * C5.6.151 REV32 (sf==1, opcode==2)
2244  */
2245 static void handle_rev32(DisasContext *s, unsigned int sf,
2246                          unsigned int rn, unsigned int rd)
2247 {
2248     TCGv_i64 tcg_rd = cpu_reg(s, rd);
2249
2250     if (sf) {
2251         TCGv_i64 tcg_tmp = tcg_temp_new_i64();
2252         TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
2253
2254         /* bswap32_i64 requires zero high word */
2255         tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
2256         tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
2257         tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
2258         tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
2259         tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
2260
2261         tcg_temp_free_i64(tcg_tmp);
2262     } else {
2263         tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
2264         tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
2265     }
2266 }
2267
2268 /* C5.6.150 REV16 (opcode==1) */
2269 static void handle_rev16(DisasContext *s, unsigned int sf,
2270                          unsigned int rn, unsigned int rd)
2271 {
2272     TCGv_i64 tcg_rd = cpu_reg(s, rd);
2273     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
2274     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
2275
2276     tcg_gen_andi_i64(tcg_tmp, tcg_rn, 0xffff);
2277     tcg_gen_bswap16_i64(tcg_rd, tcg_tmp);
2278
2279     tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16);
2280     tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
2281     tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
2282     tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 16, 16);
2283
2284     if (sf) {
2285         tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
2286         tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
2287         tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
2288         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 32, 16);
2289
2290         tcg_gen_shri_i64(tcg_tmp, tcg_rn, 48);
2291         tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
2292         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 48, 16);
2293     }
2294
2295     tcg_temp_free_i64(tcg_tmp);
2296 }
2297
2298 /* C3.5.7 Data-processing (1 source)
2299  *   31  30  29  28             21 20     16 15    10 9    5 4    0
2300  * +----+---+---+-----------------+---------+--------+------+------+
2301  * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
2302  * +----+---+---+-----------------+---------+--------+------+------+
2303  */
2304 static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
2305 {
2306     unsigned int sf, opcode, rn, rd;
2307
2308     if (extract32(insn, 29, 1) || extract32(insn, 16, 5)) {
2309         unallocated_encoding(s);
2310         return;
2311     }
2312
2313     sf = extract32(insn, 31, 1);
2314     opcode = extract32(insn, 10, 6);
2315     rn = extract32(insn, 5, 5);
2316     rd = extract32(insn, 0, 5);
2317
2318     switch (opcode) {
2319     case 0: /* RBIT */
2320         handle_rbit(s, sf, rn, rd);
2321         break;
2322     case 1: /* REV16 */
2323         handle_rev16(s, sf, rn, rd);
2324         break;
2325     case 2: /* REV32 */
2326         handle_rev32(s, sf, rn, rd);
2327         break;
2328     case 3: /* REV64 */
2329         handle_rev64(s, sf, rn, rd);
2330         break;
2331     case 4: /* CLZ */
2332         handle_clz(s, sf, rn, rd);
2333         break;
2334     case 5: /* CLS */
2335         handle_cls(s, sf, rn, rd);
2336         break;
2337     }
2338 }
2339
2340 static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
2341                        unsigned int rm, unsigned int rn, unsigned int rd)
2342 {
2343     TCGv_i64 tcg_n, tcg_m, tcg_rd;
2344     tcg_rd = cpu_reg(s, rd);
2345
2346     if (!sf && is_signed) {
2347         tcg_n = new_tmp_a64(s);
2348         tcg_m = new_tmp_a64(s);
2349         tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
2350         tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
2351     } else {
2352         tcg_n = read_cpu_reg(s, rn, sf);
2353         tcg_m = read_cpu_reg(s, rm, sf);
2354     }
2355
2356     if (is_signed) {
2357         gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
2358     } else {
2359         gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
2360     }
2361
2362     if (!sf) { /* zero extend final result */
2363         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2364     }
2365 }
2366
2367 /* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
2368 static void handle_shift_reg(DisasContext *s,
2369                              enum a64_shift_type shift_type, unsigned int sf,
2370                              unsigned int rm, unsigned int rn, unsigned int rd)
2371 {
2372     TCGv_i64 tcg_shift = tcg_temp_new_i64();
2373     TCGv_i64 tcg_rd = cpu_reg(s, rd);
2374     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
2375
2376     tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
2377     shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
2378     tcg_temp_free_i64(tcg_shift);
2379 }
2380
2381 /* C3.5.8 Data-processing (2 source)
2382  *   31   30  29 28             21 20  16 15    10 9    5 4    0
2383  * +----+---+---+-----------------+------+--------+------+------+
2384  * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
2385  * +----+---+---+-----------------+------+--------+------+------+
2386  */
2387 static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
2388 {
2389     unsigned int sf, rm, opcode, rn, rd;
2390     sf = extract32(insn, 31, 1);
2391     rm = extract32(insn, 16, 5);
2392     opcode = extract32(insn, 10, 6);
2393     rn = extract32(insn, 5, 5);
2394     rd = extract32(insn, 0, 5);
2395
2396     if (extract32(insn, 29, 1)) {
2397         unallocated_encoding(s);
2398         return;
2399     }
2400
2401     switch (opcode) {
2402     case 2: /* UDIV */
2403         handle_div(s, false, sf, rm, rn, rd);
2404         break;
2405     case 3: /* SDIV */
2406         handle_div(s, true, sf, rm, rn, rd);
2407         break;
2408     case 8: /* LSLV */
2409         handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
2410         break;
2411     case 9: /* LSRV */
2412         handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
2413         break;
2414     case 10: /* ASRV */
2415         handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
2416         break;
2417     case 11: /* RORV */
2418         handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
2419         break;
2420     case 16:
2421     case 17:
2422     case 18:
2423     case 19:
2424     case 20:
2425     case 21:
2426     case 22:
2427     case 23: /* CRC32 */
2428         unsupported_encoding(s, insn);
2429         break;
2430     default:
2431         unallocated_encoding(s);
2432         break;
2433     }
2434 }
2435
2436 /* C3.5 Data processing - register */
2437 static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
2438 {
2439     switch (extract32(insn, 24, 5)) {
2440     case 0x0a: /* Logical (shifted register) */
2441         disas_logic_reg(s, insn);
2442         break;
2443     case 0x0b: /* Add/subtract */
2444         if (insn & (1 << 21)) { /* (extended register) */
2445             disas_add_sub_ext_reg(s, insn);
2446         } else {
2447             disas_add_sub_reg(s, insn);
2448         }
2449         break;
2450     case 0x1b: /* Data-processing (3 source) */
2451         disas_data_proc_3src(s, insn);
2452         break;
2453     case 0x1a:
2454         switch (extract32(insn, 21, 3)) {
2455         case 0x0: /* Add/subtract (with carry) */
2456             disas_adc_sbc(s, insn);
2457             break;
2458         case 0x2: /* Conditional compare */
2459             if (insn & (1 << 11)) { /* (immediate) */
2460                 disas_cc_imm(s, insn);
2461             } else {            /* (register) */
2462                 disas_cc_reg(s, insn);
2463             }
2464             break;
2465         case 0x4: /* Conditional select */
2466             disas_cond_select(s, insn);
2467             break;
2468         case 0x6: /* Data-processing */
2469             if (insn & (1 << 30)) { /* (1 source) */
2470                 disas_data_proc_1src(s, insn);
2471             } else {            /* (2 source) */
2472                 disas_data_proc_2src(s, insn);
2473             }
2474             break;
2475         default:
2476             unallocated_encoding(s);
2477             break;
2478         }
2479         break;
2480     default:
2481         unallocated_encoding(s);
2482         break;
2483     }
2484 }
2485
2486 /* C3.6 Data processing - SIMD and floating point */
2487 static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
2488 {
2489     unsupported_encoding(s, insn);
2490 }
2491
2492 /* C3.1 A64 instruction index by encoding */
2493 static void disas_a64_insn(CPUARMState *env, DisasContext *s)
2494 {
2495     uint32_t insn;
2496
2497     insn = arm_ldl_code(env, s->pc, s->bswap_code);
2498     s->insn = insn;
2499     s->pc += 4;
2500
2501     switch (extract32(insn, 25, 4)) {
2502     case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
2503         unallocated_encoding(s);
2504         break;
2505     case 0x8: case 0x9: /* Data processing - immediate */
2506         disas_data_proc_imm(s, insn);
2507         break;
2508     case 0xa: case 0xb: /* Branch, exception generation and system insns */
2509         disas_b_exc_sys(s, insn);
2510         break;
2511     case 0x4:
2512     case 0x6:
2513     case 0xc:
2514     case 0xe:      /* Loads and stores */
2515         disas_ldst(s, insn);
2516         break;
2517     case 0x5:
2518     case 0xd:      /* Data processing - register */
2519         disas_data_proc_reg(s, insn);
2520         break;
2521     case 0x7:
2522     case 0xf:      /* Data processing - SIMD and floating point */
2523         disas_data_proc_simd_fp(s, insn);
2524         break;
2525     default:
2526         assert(FALSE); /* all 15 cases should be handled above */
2527         break;
2528     }
2529
2530     /* if we allocated any temporaries, free them here */
2531     free_tmp_a64(s);
2532 }
2533
2534 void gen_intermediate_code_internal_a64(ARMCPU *cpu,
2535                                         TranslationBlock *tb,
2536                                         bool search_pc)
2537 {
2538     CPUState *cs = CPU(cpu);
2539     CPUARMState *env = &cpu->env;
2540     DisasContext dc1, *dc = &dc1;
2541     CPUBreakpoint *bp;
2542     uint16_t *gen_opc_end;
2543     int j, lj;
2544     target_ulong pc_start;
2545     target_ulong next_page_start;
2546     int num_insns;
2547     int max_insns;
2548
2549     pc_start = tb->pc;
2550
2551     dc->tb = tb;
2552
2553     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
2554
2555     dc->is_jmp = DISAS_NEXT;
2556     dc->pc = pc_start;
2557     dc->singlestep_enabled = cs->singlestep_enabled;
2558     dc->condjmp = 0;
2559
2560     dc->aarch64 = 1;
2561     dc->thumb = 0;
2562     dc->bswap_code = 0;
2563     dc->condexec_mask = 0;
2564     dc->condexec_cond = 0;
2565 #if !defined(CONFIG_USER_ONLY)
2566     dc->user = 0;
2567 #endif
2568     dc->vfp_enabled = 0;
2569     dc->vec_len = 0;
2570     dc->vec_stride = 0;
2571
2572     init_tmp_a64_array(dc);
2573
2574     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2575     lj = -1;
2576     num_insns = 0;
2577     max_insns = tb->cflags & CF_COUNT_MASK;
2578     if (max_insns == 0) {
2579         max_insns = CF_COUNT_MASK;
2580     }
2581
2582     gen_tb_start();
2583
2584     tcg_clear_temp_count();
2585
2586     do {
2587         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
2588             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
2589                 if (bp->pc == dc->pc) {
2590                     gen_exception_insn(dc, 0, EXCP_DEBUG);
2591                     /* Advance PC so that clearing the breakpoint will
2592                        invalidate this TB.  */
2593                     dc->pc += 2;
2594                     goto done_generating;
2595                 }
2596             }
2597         }
2598
2599         if (search_pc) {
2600             j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
2601             if (lj < j) {
2602                 lj++;
2603                 while (lj < j) {
2604                     tcg_ctx.gen_opc_instr_start[lj++] = 0;
2605                 }
2606             }
2607             tcg_ctx.gen_opc_pc[lj] = dc->pc;
2608             tcg_ctx.gen_opc_instr_start[lj] = 1;
2609             tcg_ctx.gen_opc_icount[lj] = num_insns;
2610         }
2611
2612         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
2613             gen_io_start();
2614         }
2615
2616         if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
2617             tcg_gen_debug_insn_start(dc->pc);
2618         }
2619
2620         disas_a64_insn(env, dc);
2621
2622         if (tcg_check_temp_count()) {
2623             fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
2624                     dc->pc);
2625         }
2626
2627         /* Translation stops when a conditional branch is encountered.
2628          * Otherwise the subsequent code could get translated several times.
2629          * Also stop translation when a page boundary is reached.  This
2630          * ensures prefetch aborts occur at the right place.
2631          */
2632         num_insns++;
2633     } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
2634              !cs->singlestep_enabled &&
2635              !singlestep &&
2636              dc->pc < next_page_start &&
2637              num_insns < max_insns);
2638
2639     if (tb->cflags & CF_LAST_IO) {
2640         gen_io_end();
2641     }
2642
2643     if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
2644         /* Note that this means single stepping WFI doesn't halt the CPU.
2645          * For conditional branch insns this is harmless unreachable code as
2646          * gen_goto_tb() has already handled emitting the debug exception
2647          * (and thus a tb-jump is not possible when singlestepping).
2648          */
2649         assert(dc->is_jmp != DISAS_TB_JUMP);
2650         if (dc->is_jmp != DISAS_JUMP) {
2651             gen_a64_set_pc_im(dc->pc);
2652         }
2653         gen_exception(EXCP_DEBUG);
2654     } else {
2655         switch (dc->is_jmp) {
2656         case DISAS_NEXT:
2657             gen_goto_tb(dc, 1, dc->pc);
2658             break;
2659         default:
2660         case DISAS_JUMP:
2661         case DISAS_UPDATE:
2662             /* indicate that the hash table must be used to find the next TB */
2663             tcg_gen_exit_tb(0);
2664             break;
2665         case DISAS_TB_JUMP:
2666         case DISAS_EXC:
2667         case DISAS_SWI:
2668             break;
2669         case DISAS_WFI:
2670             /* This is a special case because we don't want to just halt the CPU
2671              * if trying to debug across a WFI.
2672              */
2673             gen_helper_wfi(cpu_env);
2674             break;
2675         }
2676     }
2677
2678 done_generating:
2679     gen_tb_end(tb, num_insns);
2680     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
2681
2682 #ifdef DEBUG_DISAS
2683     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
2684         qemu_log("----------------\n");
2685         qemu_log("IN: %s\n", lookup_symbol(pc_start));
2686         log_target_disas(env, pc_start, dc->pc - pc_start,
2687                          dc->thumb | (dc->bswap_code << 1));
2688         qemu_log("\n");
2689     }
2690 #endif
2691     if (search_pc) {
2692         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
2693         lj++;
2694         while (lj <= j) {
2695             tcg_ctx.gen_opc_instr_start[lj++] = 0;
2696         }
2697     } else {
2698         tb->size = dc->pc - pc_start;
2699         tb->icount = num_insns;
2700     }
2701 }
This page took 0.169361 seconds and 4 git commands to generate.