blob: a81632fe46c6d656b1ecf9c0c29e53489d923e21 [file] [log] [blame]
Alexander Graf14ade102013-09-03 20:12:10 +01001/*
2 * AArch64 translation
3 *
4 * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
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
Peter Maydell089a8d92013-12-03 15:26:18 +000031#include "exec/gen-icount.h"
32
Alexander Graf14ade102013-09-03 20:12:10 +010033#include "helper.h"
34#define GEN_HELPER 1
35#include "helper.h"
36
37static TCGv_i64 cpu_X[32];
38static TCGv_i64 cpu_pc;
Claudio Fontanad41620e2013-12-03 15:12:19 +000039static TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
Alexander Graf14ade102013-09-03 20:12:10 +010040
41static 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
Claudio Fontanad41620e2013-12-03 15:12:19 +000048enum 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
Alexander Graf14ade102013-09-03 20:12:10 +010055/* initialize TCG globals. */
56void 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
Claudio Fontanad41620e2013-12-03 15:12:19 +000069 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");
Alexander Graf14ade102013-09-03 20:12:10 +010073}
74
75void 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;
Peter Maydell6cd096b2013-11-26 17:21:48 +000080 uint32_t psr = pstate_read(env);
Alexander Graf14ade102013-09-03 20:12:10 +010081 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 }
Peter Maydell6cd096b2013-11-26 17:21:48 +000093 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' : '-');
Alexander Graf14ade102013-09-03 20:12:10 +010099 cpu_fprintf(f, "\n");
100}
101
102void gen_a64_set_pc_im(uint64_t val)
103{
104 tcg_gen_movi_i64(cpu_pc, val);
105}
106
107static void gen_exception(int excp)
108{
109 TCGv_i32 tmp = tcg_temp_new_i32();
110 tcg_gen_movi_i32(tmp, excp);
111 gen_helper_exception(cpu_env, tmp);
112 tcg_temp_free_i32(tmp);
113}
114
115static void gen_exception_insn(DisasContext *s, int offset, int excp)
116{
117 gen_a64_set_pc_im(s->pc - offset);
118 gen_exception(excp);
Peter Maydell089a8d92013-12-03 15:26:18 +0000119 s->is_jmp = DISAS_EXC;
120}
121
122static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
123{
124 /* No direct tb linking with singlestep or deterministic io */
125 if (s->singlestep_enabled || (s->tb->cflags & CF_LAST_IO)) {
126 return false;
127 }
128
129 /* Only link tbs from inside the same guest page */
130 if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
131 return false;
132 }
133
134 return true;
135}
136
137static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
138{
139 TranslationBlock *tb;
140
141 tb = s->tb;
142 if (use_goto_tb(s, n, dest)) {
143 tcg_gen_goto_tb(n);
144 gen_a64_set_pc_im(dest);
145 tcg_gen_exit_tb((tcg_target_long)tb + n);
146 s->is_jmp = DISAS_TB_JUMP;
147 } else {
148 gen_a64_set_pc_im(dest);
149 if (s->singlestep_enabled) {
150 gen_exception(EXCP_DEBUG);
151 }
152 tcg_gen_exit_tb(0);
153 s->is_jmp = DISAS_JUMP;
154 }
Alexander Graf14ade102013-09-03 20:12:10 +0100155}
156
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000157static void unallocated_encoding(DisasContext *s)
Alexander Graf14ade102013-09-03 20:12:10 +0100158{
Alexander Graf14ade102013-09-03 20:12:10 +0100159 gen_exception_insn(s, 4, EXCP_UDEF);
160}
161
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000162#define unsupported_encoding(s, insn) \
163 do { \
164 qemu_log_mask(LOG_UNIMP, \
165 "%s:%d: unsupported instruction encoding 0x%08x " \
166 "at pc=%016" PRIx64 "\n", \
167 __FILE__, __LINE__, insn, s->pc - 4); \
168 unallocated_encoding(s); \
169 } while (0);
Alexander Graf14ade102013-09-03 20:12:10 +0100170
Alexander Grafeeed5002013-12-03 15:12:18 +0000171static void free_tmp_a64(DisasContext *s)
172{
173 int i;
174 for (i = 0; i < s->tmp_a64_count; i++) {
175 tcg_temp_free_i64(s->tmp_a64[i]);
176 }
177 s->tmp_a64_count = 0;
178}
179
180static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
181{
182 assert(s->tmp_a64_count < TMP_A64_MAX);
183 return s->tmp_a64[s->tmp_a64_count++] = tcg_const_i64(0);
184}
185
Claudio Fontanad41620e2013-12-03 15:12:19 +0000186/* for accessing a register in 64 bit mode (r/w) */
Alexander Grafeeed5002013-12-03 15:12:18 +0000187static TCGv_i64 cpu_reg(DisasContext *s, int reg)
188{
189 if (reg == 31) {
190 return new_tmp_a64_zero(s);
191 } else {
192 return cpu_X[reg];
193 }
194}
195
Claudio Fontanab5a339a2013-12-03 15:12:21 +0000196/* register access for when 31 == SP */
197static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
198{
199 return cpu_X[reg];
200}
201
Alexander Graf06905b52013-12-03 15:12:19 +0000202/* read a cpu register in 32bit/64bit mode to dst */
203static void read_cpu_reg(DisasContext *s, TCGv_i64 dst, int reg, int sf)
204{
205 if (reg == 31) {
206 tcg_gen_movi_i64(dst, 0);
207 } else if (sf) {
208 tcg_gen_mov_i64(dst, cpu_X[reg]);
209 } else { /* (!sf) */
210 tcg_gen_ext32u_i64(dst, cpu_X[reg]);
211 }
212}
213
Claudio Fontanad41620e2013-12-03 15:12:19 +0000214/* this matches the ARM target semantic for flag variables,
215 but it's not optimal for Aarch64. */
216static inline void gen_logic_CC(int sf, TCGv_i64 result)
217{
218 if (sf) {
219 TCGv_i64 flag = tcg_temp_new_i64();
220 tcg_gen_setcondi_i64(TCG_COND_NE, flag, result, 0);
221 tcg_gen_trunc_i64_i32(cpu_ZF, flag);
222
223 tcg_gen_shri_i64(flag, result, 32);
224 tcg_gen_trunc_i64_i32(cpu_NF, flag);
225 tcg_temp_free_i64(flag);
226 } else {
227 tcg_gen_trunc_i64_i32(cpu_ZF, result);
228 tcg_gen_trunc_i64_i32(cpu_NF, result);
229 }
230 tcg_gen_movi_i32(cpu_CF, 0);
231 tcg_gen_movi_i32(cpu_VF, 0);
232}
233
Claudio Fontana422426c2013-12-03 15:12:21 +0000234enum sysreg_access {
235 SYSTEM_GET,
236 SYSTEM_PUT
237};
238
239/* C4.3.10 - NZVC */
240static int get_nzcv(TCGv_i64 tcg_rt)
241{
242 TCGv_i32 nzcv, tmp;
243 tmp = tcg_temp_new_i32();
244 nzcv = tcg_temp_new_i32();
245
246 /* build bit 31, N */
247 tcg_gen_andi_i32(nzcv, cpu_NF, (1 << 31));
248 /* build bit 30, Z */
249 tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_ZF, 0);
250 tcg_gen_deposit_i32(nzcv, nzcv, tmp, 30, 1);
251 /* build bit 29, C */
252 tcg_gen_deposit_i32(nzcv, nzcv, cpu_CF, 29, 1);
253 /* build bit 28, V */
254 tcg_gen_shri_i32(tmp, cpu_VF, 31);
255 tcg_gen_deposit_i32(nzcv, nzcv, tmp, 28, 1);
256 /* generate result */
257 tcg_gen_extu_i32_i64(tcg_rt, nzcv);
258
259 tcg_temp_free_i32(nzcv);
260 tcg_temp_free_i32(tmp);
261 return 0;
262}
263
264static int put_nzcv(TCGv_i64 tcg_rt)
265{
266 TCGv_i32 nzcv;
267 nzcv = tcg_temp_new_i32();
268
269 /* take NZCV from R[t] */
270 tcg_gen_trunc_i64_i32(nzcv, tcg_rt);
271
272 /* bit 31, N */
273 tcg_gen_andi_i32(cpu_NF, nzcv, (1 << 31));
274 /* bit 30, Z */
275 tcg_gen_andi_i32(cpu_ZF, nzcv, (1 << 30));
276 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_ZF, cpu_ZF, 0);
277 /* bit 29, C */
278 tcg_gen_andi_i32(cpu_CF, nzcv, (1 << 29));
279 tcg_gen_shri_i32(cpu_CF, cpu_CF, 29);
280 /* bit 28, V */
281 tcg_gen_andi_i32(cpu_VF, nzcv, (1 << 28));
282 tcg_gen_shli_i32(cpu_VF, cpu_VF, 3); /* shift to position 31 */
283
284 tcg_temp_free_i32(nzcv);
285 return 0;
286}
287
288/* CTR_EL0 (D8.2.21) */
289static int get_ctr_el0(TCGv_i64 tcg_rt)
290{
291 tcg_gen_movi_i64(tcg_rt, 0x80030003);
292 return 0;
293}
294
295/* DCZID_EL0 (D8.2.23) */
296static int get_dczid_el0(TCGv_i64 tcg_rt)
297{
298 tcg_gen_movi_i64(tcg_rt, 0x10);
299 return 0;
300}
301
302/* TPIDR_EL0 (D8.2.87) */
303static int get_tpidr_el0(TCGv_i64 tcg_rt)
304{
305 tcg_gen_ld_i64(tcg_rt, cpu_env,
306 offsetof(CPUARMState, sr.tpidr_el0));
307 return 0;
308}
309
310static int put_tpidr_el0(TCGv_i64 tcg_rt)
311{
312 tcg_gen_st_i64(tcg_rt, cpu_env,
313 offsetof(CPUARMState, sr.tpidr_el0));
314 return 0;
315}
316
317
318/* manual: System_Get() / System_Put() */
319/* returns 0 on success, 1 on unsupported, 2 on unallocated */
320static int sysreg_access(enum sysreg_access access, DisasContext *s,
321 unsigned int op0, unsigned int op1, unsigned int op2,
322 unsigned int crn, unsigned int crm, unsigned int rt)
323{
324 if (op0 != 3) {
325 return 1; /* we only support non-debug system registers for now */
326 }
327
328 if (crn == 4) {
329 /* Table C4-8 Special-purpose register accesses */
330 if (op1 == 3 && crm == 2 && op2 == 0) {
331 /* NZVC C4.3.10 */
332 return access == SYSTEM_GET ?
333 get_nzcv(cpu_reg(s, rt)) : put_nzcv(cpu_reg(s, rt));
334 }
335 } else if (crn == 11 || crn == 15) {
336 /* C4.2.7 Reserved control space for IMPLEM.-DEFINED func. */
337 return 2;
338 } else {
339 /* Table C4-7 System insn encodings for System register access */
340 if (crn == 0 && op1 == 3 && crm == 0 && op2 == 1) {
341 /* CTR_EL0 (D8.2.21) */
342 return access == SYSTEM_GET ? get_ctr_el0(cpu_reg(s, rt)) : 2;
343 } else if (crn == 0 && op1 == 3 && crm == 0 && op2 == 7) {
344 /* DCZID_EL0 (D8.2.23) */
345 return access == SYSTEM_GET ? get_dczid_el0(cpu_reg(s, rt)) : 2;
346 } else if (crn == 13 && op1 == 3 && crm == 0 && op2 == 2) {
347 return access == SYSTEM_GET ?
348 get_tpidr_el0(cpu_reg(s, rt)) : put_tpidr_el0(cpu_reg(s, rt));
349 }
350 }
351
352 return 1; /* unsupported */
353}
354
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000355/*
356 * the instruction disassembly implemented here matches
357 * the instruction encoding classifications in chapter 3 (C3)
358 * of the ARM Architecture Reference Manual (DDI0487A_a)
359 */
360
Alexander Grafeeed5002013-12-03 15:12:18 +0000361/* C3.2.7 Unconditional branch (immediate)
362 * 31 30 26 25 0
363 * +----+-----------+-------------------------------------+
364 * | op | 0 0 1 0 1 | imm26 |
365 * +----+-----------+-------------------------------------+
366 */
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000367static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
368{
Alexander Grafeeed5002013-12-03 15:12:18 +0000369 uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
370
371 if (insn & (1 << 31)) {
372 /* C5.6.26 BL Branch with link */
373 tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
374 }
375
376 /* C5.6.20 B Branch / C5.6.26 BL Branch with link */
377 gen_goto_tb(s, 0, addr);
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000378}
379
Alexander Graf06905b52013-12-03 15:12:19 +0000380/* C3.2.1 Compare & branch (immediate)
381 * 31 30 25 24 23 5 4 0
382 * +----+-------------+----+---------------------+--------+
383 * | sf | 0 1 1 0 1 0 | op | imm19 | Rt |
384 * +----+-------------+----+---------------------+--------+
385 */
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000386static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
387{
Alexander Graf06905b52013-12-03 15:12:19 +0000388 unsigned int sf, op, rt;
389 uint64_t addr;
390 int label_nomatch;
391 TCGv_i64 tcg_cmp;
392
393 sf = extract32(insn, 31, 1);
394 op = extract32(insn, 24, 1);
395 rt = extract32(insn, 0, 5);
396 addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
397
398 tcg_cmp = tcg_temp_new_i64();
399 read_cpu_reg(s, tcg_cmp, rt, sf);
400 label_nomatch = gen_new_label();
401
402 if (op) { /* CBNZ */
403 tcg_gen_brcondi_i64(TCG_COND_EQ, tcg_cmp, 0, label_nomatch);
404 } else { /* CBZ */
405 tcg_gen_brcondi_i64(TCG_COND_NE, tcg_cmp, 0, label_nomatch);
406 }
407
408 tcg_temp_free_i64(tcg_cmp);
409
410 gen_goto_tb(s, 0, addr);
411 gen_set_label(label_nomatch);
412 gen_goto_tb(s, 1, s->pc);
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000413}
414
Alexander Grafee52d8c2013-12-03 15:12:19 +0000415/* C3.2.5 Test & branch (immediate)
416 * 31 30 25 24 23 19 18 5 4 0
417 * +----+-------------+----+-------+-------------+------+
418 * | b5 | 0 1 1 0 1 1 | op | b40 | imm14 | Rt |
419 * +----+-------------+----+-------+-------------+------+
420 */
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000421static void disas_test_b_imm(DisasContext *s, uint32_t insn)
422{
Alexander Grafee52d8c2013-12-03 15:12:19 +0000423 unsigned int bit_pos, op, rt;
424 uint64_t addr;
425 int label_nomatch;
426 TCGv_i64 tcg_cmp;
427
428 bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
429 op = extract32(insn, 24, 1);
430 addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
431 rt = extract32(insn, 0, 5);
432
433 tcg_cmp = tcg_temp_new_i64();
434 tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
435 label_nomatch = gen_new_label();
436 if (op) { /* TBNZ */
437 tcg_gen_brcondi_i64(TCG_COND_EQ, tcg_cmp, 0, label_nomatch);
438 } else { /* TBZ */
439 tcg_gen_brcondi_i64(TCG_COND_NE, tcg_cmp, 0, label_nomatch);
440 }
441 tcg_temp_free_i64(tcg_cmp);
442 gen_goto_tb(s, 0, addr);
443 gen_set_label(label_nomatch);
444 gen_goto_tb(s, 1, s->pc);
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000445}
446
Alexander Grafd0deb6c2013-12-03 15:12:18 +0000447/* C3.2.2 / C5.6.19 Conditional branch (immediate)
448 * 31 25 24 23 5 4 3 0
449 * +---------------+----+---------------------+----+------+
450 * | 0 1 0 1 0 1 0 | o1 | imm19 | o0 | cond |
451 * +---------------+----+---------------------+----+------+
452 */
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000453static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
454{
Alexander Grafd0deb6c2013-12-03 15:12:18 +0000455 unsigned int cond;
456 uint64_t addr;
457
458 if ((insn & (1 << 4)) || (insn & (1 << 24))) {
459 unallocated_encoding(s);
460 return;
461 }
462 addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
463 cond = extract32(insn, 0, 4);
464
465 if (cond < 0x0e) {
466 /* genuinely conditional branches */
467 int label_nomatch = gen_new_label();
468 arm_gen_test_cc(cond ^ 1, label_nomatch);
469 gen_goto_tb(s, 0, addr);
470 gen_set_label(label_nomatch);
471 gen_goto_tb(s, 1, s->pc);
472 } else {
473 /* 0xe and 0xf are both "always" conditions */
474 gen_goto_tb(s, 0, addr);
475 }
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000476}
477
Claudio Fontana20b3f312013-12-03 15:12:18 +0000478/* C5.6.68 HINT */
479static void handle_hint(DisasContext *s, uint32_t insn,
480 unsigned int op1, unsigned int op2, unsigned int crm)
481{
482 unsigned int selector = crm << 3 | op2;
483
484 if (op1 != 3) {
485 unallocated_encoding(s);
486 return;
487 }
488
489 switch (selector) {
490 case 0: /* NOP */
491 return;
492 case 1: /* YIELD */
493 case 2: /* WFE */
494 case 3: /* WFI */
495 case 4: /* SEV */
496 case 5: /* SEVL */
497 /* we treat all as NOP at least for now */
498 return;
499 default:
500 /* default specified as NOP equivalent */
501 return;
502 }
503}
504
505/* CLREX, DSB, DMB, ISB */
506static void handle_sync(DisasContext *s, uint32_t insn,
507 unsigned int op1, unsigned int op2, unsigned int crm)
508{
509 if (op1 != 3) {
510 unallocated_encoding(s);
511 return;
512 }
513
514 switch (op2) {
515 case 2: /* CLREX */
516 unsupported_encoding(s, insn);
517 return;
518 case 4: /* DSB */
519 case 5: /* DMB */
520 case 6: /* ISB */
521 /* We don't emulate caches so barriers are no-ops */
522 return;
523 default:
524 unallocated_encoding(s);
525 return;
526 }
527}
528
529/* C5.6.130 MSR (immediate) - move immediate to processor state field */
530static void handle_msr_i(DisasContext *s, uint32_t insn,
531 unsigned int op1, unsigned int op2, unsigned int crm)
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000532{
533 unsupported_encoding(s, insn);
534}
535
Claudio Fontana20b3f312013-12-03 15:12:18 +0000536/* C5.6.204 SYS */
537static void handle_sys(DisasContext *s, uint32_t insn, unsigned int l,
538 unsigned int op1, unsigned int op2,
539 unsigned int crn, unsigned int crm, unsigned int rt)
540{
541 unsupported_encoding(s, insn);
542}
543
544/* C5.6.129 MRS - move from system register */
545static void handle_mrs(DisasContext *s, uint32_t insn, unsigned int op0,
546 unsigned int op1, unsigned int op2,
547 unsigned int crn, unsigned int crm, unsigned int rt)
548{
Claudio Fontana422426c2013-12-03 15:12:21 +0000549 int rv = sysreg_access(SYSTEM_GET, s, op0, op1, op2, crn, crm, rt);
550
551 switch (rv) {
552 case 0:
553 return;
554 case 1: /* unsupported */
555 unsupported_encoding(s, insn);
556 break;
557 case 2: /* unallocated */
558 unallocated_encoding(s);
559 break;
560 default:
561 assert(FALSE);
562 }
563
564 qemu_log("MRS: [op0=%d,op1=%d,op2=%d,crn=%d,crm=%d]\n",
565 op0, op1, op2, crn, crm);
Claudio Fontana20b3f312013-12-03 15:12:18 +0000566}
567
568/* C5.6.131 MSR (register) - move to system register */
569static void handle_msr(DisasContext *s, uint32_t insn, unsigned int op0,
570 unsigned int op1, unsigned int op2,
571 unsigned int crn, unsigned int crm, unsigned int rt)
572{
Claudio Fontana422426c2013-12-03 15:12:21 +0000573 int rv = sysreg_access(SYSTEM_PUT, s, op0, op1, op2, crn, crm, rt);
574
575 switch (rv) {
576 case 0:
577 return;
578 case 1: /* unsupported */
579 unsupported_encoding(s, insn);
580 break;
581 case 2: /* unallocated */
582 unallocated_encoding(s);
583 break;
584 default:
585 assert(FALSE);
586 }
587
588 qemu_log("MSR: [op0=%d,op1=%d,op2=%d,crn=%d,crm=%d]\n",
589 op0, op1, op2, crn, crm);
Claudio Fontana20b3f312013-12-03 15:12:18 +0000590}
591
592/* C3.2.4 System */
593static void disas_system(DisasContext *s, uint32_t insn)
594{
595 /*
596 * 31 30 29 28 27 26 25 24 23 22 21 20 19 18 16 15 12 11 8 7 5 4 0
597 * 1 1 0 1 0 1 0 1 0 0 L op0 op1 CRn CRm op2 Rt
598 */
599 unsigned int l, op0, op1, crn, crm, op2, rt;
600 l = extract32(insn, 21, 1);
601 op0 = extract32(insn, 19, 2);
602 op1 = extract32(insn, 16, 3);
603 crn = extract32(insn, 12, 4);
604 crm = extract32(insn, 8, 4);
605 op2 = extract32(insn, 5, 3);
606 rt = extract32(insn, 0, 5);
607
608 if (op0 == 0) {
609 if (l || rt != 31) {
610 unallocated_encoding(s);
611 return;
612 }
613 switch (crn) {
614 case 2: /* C5.6.68 HINT */
615 handle_hint(s, insn, op1, op2, crm);
616 break;
617 case 3: /* CLREX, DSB, DMB, ISB */
618 handle_sync(s, insn, op1, op2, crm);
619 break;
620 case 4: /* C5.6.130 MSR (immediate) */
621 handle_msr_i(s, insn, op1, op2, crm);
622 break;
623 default:
624 unallocated_encoding(s);
625 break;
626 }
627 return;
628 }
629
630 if (op0 == 1) {
631 /* C5.6.204 SYS */
632 handle_sys(s, insn, l, op1, op2, crn, crm, rt);
633 } else if (l) { /* op0 > 1 */
634 /* C5.6.129 MRS - move from system register */
635 handle_mrs(s, insn, op0, op1, op2, crn, crm, rt);
636 } else {
637 /* C5.6.131 MSR (register) - move to system register */
638 handle_msr(s, insn, op0, op1, op2, crn, crm, rt);
639 }
640}
641
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000642/* Exception generation */
643static void disas_exc(DisasContext *s, uint32_t insn)
644{
645 unsupported_encoding(s, insn);
646}
647
Alexander Graf37699832013-12-03 15:12:18 +0000648/* C3.2.7 Unconditional branch (register)
649 * 31 25 24 21 20 16 15 10 9 5 4 0
650 * +---------------+-------+-------+-------+------+-------+
651 * | 1 1 0 1 0 1 1 | opc | op2 | op3 | Rn | op4 |
652 * +---------------+-------+-------+-------+------+-------+
653 */
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000654static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
655{
Alexander Graf37699832013-12-03 15:12:18 +0000656 unsigned int opc, op2, op3, rn, op4;
657
658 opc = extract32(insn, 21, 4);
659 op2 = extract32(insn, 16, 5);
660 op3 = extract32(insn, 10, 6);
661 rn = extract32(insn, 5, 5);
662 op4 = extract32(insn, 0, 5);
663
664 if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
665 unallocated_encoding(s);
666 return;
667 }
668
669 switch (opc) {
670 case 0: /* BR */
671 case 2: /* RET */
672 break;
673 case 1: /* BLR */
674 tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
675 break;
676 case 4: /* ERET */
677 case 5: /* DRPS */
678 if (rn != 0x1f) {
679 unallocated_encoding(s);
680 } else {
681 unsupported_encoding(s, insn);
682 }
683 return;
684 default:
685 unallocated_encoding(s);
686 return;
687 }
688
689 tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
690 s->is_jmp = DISAS_JUMP;
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000691}
692
693/* C3.2 Branches, exception generating and system instructions */
694static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
695{
696 switch (extract32(insn, 25, 7)) {
697 case 0x0a: case 0x0b:
698 case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
699 disas_uncond_b_imm(s, insn);
700 break;
701 case 0x1a: case 0x5a: /* Compare & branch (immediate) */
702 disas_comp_b_imm(s, insn);
703 break;
704 case 0x1b: case 0x5b: /* Test & branch (immediate) */
705 disas_test_b_imm(s, insn);
706 break;
707 case 0x2a: /* Conditional branch (immediate) */
708 disas_cond_b_imm(s, insn);
709 break;
710 case 0x6a: /* Exception generation / System */
711 if (insn & (1 << 24)) {
712 disas_system(s, insn);
713 } else {
714 disas_exc(s, insn);
715 }
716 break;
717 case 0x6b: /* Unconditional branch (register) */
718 disas_uncond_b_reg(s, insn);
719 break;
720 default:
721 unallocated_encoding(s);
722 break;
723 }
724}
725
726/* Load/store exclusive */
727static void disas_ldst_excl(DisasContext *s, uint32_t insn)
728{
729 unsupported_encoding(s, insn);
730}
731
732/* Load register (literal) */
733static void disas_ld_lit(DisasContext *s, uint32_t insn)
734{
735 unsupported_encoding(s, insn);
736}
737
738/* Load/store pair (all forms) */
739static void disas_ldst_pair(DisasContext *s, uint32_t insn)
740{
741 unsupported_encoding(s, insn);
742}
743
744/* Load/store register (all forms) */
745static void disas_ldst_reg(DisasContext *s, uint32_t insn)
746{
747 unsupported_encoding(s, insn);
748}
749
750/* AdvSIMD load/store multiple structures */
751static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
752{
753 unsupported_encoding(s, insn);
754}
755
756/* AdvSIMD load/store single structure */
757static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
758{
759 unsupported_encoding(s, insn);
760}
761
762/* C3.3 Loads and stores */
763static void disas_ldst(DisasContext *s, uint32_t insn)
764{
765 switch (extract32(insn, 24, 6)) {
766 case 0x08: /* Load/store exclusive */
767 disas_ldst_excl(s, insn);
768 break;
769 case 0x18: case 0x1c: /* Load register (literal) */
770 disas_ld_lit(s, insn);
771 break;
772 case 0x28: case 0x29:
773 case 0x2c: case 0x2d: /* Load/store pair (all forms) */
774 disas_ldst_pair(s, insn);
775 break;
776 case 0x38: case 0x39:
777 case 0x3c: case 0x3d: /* Load/store register (all forms) */
778 disas_ldst_reg(s, insn);
779 break;
780 case 0x0c: /* AdvSIMD load/store multiple structures */
781 disas_ldst_multiple_struct(s, insn);
782 break;
783 case 0x0d: /* AdvSIMD load/store single structure */
784 disas_ldst_single_struct(s, insn);
785 break;
786 default:
787 unallocated_encoding(s);
788 break;
789 }
790}
791
Claudio Fontana8ff4c2f2013-12-03 15:12:19 +0000792/* C3.4.6 PC-rel. addressing */
793
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000794static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
795{
Claudio Fontana8ff4c2f2013-12-03 15:12:19 +0000796 /*
797 * 31 30 29 28 27 26 25 24 23 5 4 0
798 * op immlo 1 0 0 0 0 immhi Rd
799 */
800 unsigned int page, rd; /* op -> page */
801 uint64_t base;
802 int64_t offset; /* SignExtend(immhi:immlo) -> offset */
803
804 page = insn & (1 << 31) ? 1 : 0;
805 offset = ((int64_t)sextract32(insn, 5, 19) << 2) | extract32(insn, 29, 2);
806 rd = extract32(insn, 0, 5);
807 base = s->pc - 4;
808
809 if (page) {
810 /* ADRP (page based) */
811 base &= ~0xfff;
812 offset <<= 12; /* apply Zeros */
813 }
814
815 tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000816}
817
818/* Add/subtract (immediate) */
819static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
820{
821 unsupported_encoding(s, insn);
822}
823
Claudio Fontanab5a339a2013-12-03 15:12:21 +0000824static uint64_t logic_imm_replicate(uint64_t mask, unsigned int esize)
825{
826 int i;
827 uint64_t out_mask = 0;
828 for (i = 0; (i * esize) < 64; i++) {
829 out_mask = out_mask | (mask << (i * esize));
830 }
831 return out_mask;
832}
833
834static inline uint64_t logic_imm_bitmask(unsigned int len)
835{
836 if (len == 64) {
837 return -1;
838 }
839 return (1ULL << len) - 1;
840}
841
842static uint64_t logic_imm_decode_wmask(unsigned int immn,
843 unsigned int imms, unsigned int immr)
844{
845 uint64_t mask;
846 unsigned len, esize, levels, s, r;
847
848 len = 31 - clz32((immn << 6) | (~imms & 0x3f));
849 esize = 1 << len;
850 levels = (esize - 1) & 0x3f;
851 s = imms & levels;
852 r = immr & levels;
853
854 mask = logic_imm_bitmask(s + 1);
855 mask = (mask >> r) | (mask << (esize - r));
856 mask &= logic_imm_bitmask(esize);
857 mask = logic_imm_replicate(mask, esize);
858 return mask;
859}
860
861/* C3.4.4 Logical (immediate) */
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000862static void disas_logic_imm(DisasContext *s, uint32_t insn)
863{
Claudio Fontanab5a339a2013-12-03 15:12:21 +0000864 /*
865 * 31 30 29 28 27 26 25 24 23 22 21 16 15 10 9 5 4 0
866 * sf opc 1 0 0 1 0 0 N immr imms Rn Rd
867 */
868 unsigned int sf, opc, is_n, immr, imms, rn, rd;
869 TCGv_i64 tcg_rd, tcg_rn;
870 uint64_t wmask;
871 sf = insn & (1 << 31) ? 1 : 0;
872 opc = extract32(insn, 29, 2);
873 is_n = insn & (1 << 22) ? 1 : 0;
874 immr = extract32(insn, 16, 6);
875 imms = extract32(insn, 10, 6);
876 rn = extract32(insn, 5, 5);
877 rd = extract32(insn, 0, 5);
878
879 if (!sf && is_n) {
880 unallocated_encoding(s);
881 return;
882 }
883
884 if (opc == 0x3) { /* ANDS */
885 tcg_rd = cpu_reg(s, rd);
886 } else {
887 tcg_rd = cpu_reg_sp(s, rd);
888 }
889 tcg_rn = cpu_reg(s, rn);
890
891 wmask = logic_imm_decode_wmask(is_n, imms, immr);
892 if (!sf) {
893 wmask &= 0xffffffff;
894 }
895
896 switch (opc) {
897 case 0x3: /* ANDS */
898 case 0x0: /* AND */
899 tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
900 break;
901 case 0x1: /* ORR */
902 tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
903 break;
904 case 0x2: /* EOR */
905 tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
906 break;
907 default:
908 assert(FALSE); /* must handle all above */
909 break;
910 }
911
912 if (!sf) { /* zero extend final result */
913 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
914 }
915
916 if (opc == 3) { /* ANDS */
917 gen_logic_CC(sf, tcg_rd);
918 }
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000919}
920
921/* Move wide (immediate) */
922static void disas_movw_imm(DisasContext *s, uint32_t insn)
923{
924 unsupported_encoding(s, insn);
925}
926
Claudio Fontana18f20eb2013-12-03 15:12:21 +0000927/* C3.4.2 Bitfield */
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000928static void disas_bitfield(DisasContext *s, uint32_t insn)
929{
Claudio Fontana18f20eb2013-12-03 15:12:21 +0000930 /*
931 * 31 30 29 28 27 26 25 24 23 22 21 16 15 10 9 5 4 0
932 * sf opc 1 0 0 1 1 0 N immr imms Rn Rd
933 */
934 unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
935 TCGv_i64 tcg_rd, tcg_tmp;
936 sf = insn & (1 << 31) ? 1 : 0;
937 opc = extract32(insn, 29, 2);
938 n = insn & (1 << 22) ? 1 : 0;
939 ri = extract32(insn, 16, 6);
940 si = extract32(insn, 10, 6);
941 rn = extract32(insn, 5, 5);
942 rd = extract32(insn, 0, 5);
943 bitsize = sf ? 64 : 32;
944
945 if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
946 unallocated_encoding(s);
947 return;
948 }
949
950 tcg_rd = cpu_reg(s, rd);
951 tcg_tmp = tcg_temp_new_i64();
952 read_cpu_reg(s, tcg_tmp, rn, sf);
953
954 if (opc != 1) { /* SBFM or UBFM */
955 tcg_gen_movi_i64(tcg_rd, 0);
956 }
957
958 /* do the bit move operation */
959 if (si >= ri) {
960 /* Wd<s-r:0> = Wn<s:r> */
961 tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
962 pos = 0;
963 len = (si - ri) + 1;
964 } else {
965 /* Wd<32+s-r,32-r> = Wn<s:0> */
966 pos = bitsize - ri;
967 len = si + 1;
968 }
969
970 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
971 tcg_temp_free_i64(tcg_tmp);
972
973 if (opc == 0) { /* SBFM - sign extend the destination field */
974 tcg_gen_shli_i64(tcg_rd, tcg_rd, 64 - (pos + len));
975 tcg_gen_sari_i64(tcg_rd, tcg_rd, 64 - (pos + len));
976 }
977
978 if (!sf) { /* zero extend final result */
979 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
980 }
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000981}
982
Claudio Fontana6e7015312013-12-03 15:12:19 +0000983/* C3.4.3 Extract */
Claudio Fontanaea5ca532013-12-03 15:12:18 +0000984static void disas_extract(DisasContext *s, uint32_t insn)
985{
Claudio Fontana6e7015312013-12-03 15:12:19 +0000986 /*
987 * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
988 * sf [op21] 1 0 0 1 1 1 N o0 Rm imm Rn Rd
989 * [0 0] [0]
990 */
991 unsigned int sf, n, rm, imm, rn, rd, bitsize, op;
992 sf = insn & (1 << 31) ? 1 : 0;
993 n = insn & (1 << 22) ? 1 : 0;
994 rm = extract32(insn, 16, 5);
995 imm = extract32(insn, 10, 6);
996 rn = extract32(insn, 5, 5);
997 rd = extract32(insn, 0, 5);
998 op = insn & (0x3 << 29 | 1 << 21);
999 bitsize = sf ? 64 : 32;
1000
1001 if (sf != n || op || imm >= bitsize) {
1002 unallocated_encoding(s);
1003 } else {
1004 TCGv_i64 tcg_tmp, tcg_rd;
1005 tcg_tmp = tcg_temp_new_i64();
1006 tcg_rd = cpu_reg(s, rd);
1007
1008 read_cpu_reg(s, tcg_tmp, rm, sf);
1009 tcg_gen_shri_i64(tcg_rd, tcg_tmp, imm);
1010 tcg_gen_shli_i64(tcg_tmp, cpu_reg(s, rn), bitsize - imm);
1011 tcg_gen_or_i64(tcg_rd, tcg_rd, tcg_tmp);
1012
1013 tcg_temp_free_i64(tcg_tmp);
1014 if (!sf) {
1015 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1016 }
1017 }
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001018}
1019
1020/* C3.4 Data processing - immediate */
1021static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
1022{
1023 switch (extract32(insn, 23, 6)) {
1024 case 0x20: case 0x21: /* PC-rel. addressing */
1025 disas_pc_rel_adr(s, insn);
1026 break;
1027 case 0x22: case 0x23: /* Add/subtract (immediate) */
1028 disas_add_sub_imm(s, insn);
1029 break;
1030 case 0x24: /* Logical (immediate) */
1031 disas_logic_imm(s, insn);
1032 break;
1033 case 0x25: /* Move wide (immediate) */
1034 disas_movw_imm(s, insn);
1035 break;
1036 case 0x26: /* Bitfield */
1037 disas_bitfield(s, insn);
1038 break;
1039 case 0x27: /* Extract */
1040 disas_extract(s, insn);
1041 break;
1042 default:
1043 unallocated_encoding(s);
1044 break;
1045 }
1046}
1047
Claudio Fontanad41620e2013-12-03 15:12:19 +00001048/* shift a TCGv src by TCGv shift_amount, put result in dst. */
1049static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
1050 enum a64_shift_type shift_type, TCGv_i64 shift_amount)
1051{
1052 switch (shift_type) {
1053 case A64_SHIFT_TYPE_LSL:
1054 tcg_gen_shl_i64(dst, src, shift_amount);
1055 break;
1056 case A64_SHIFT_TYPE_LSR:
1057 tcg_gen_shr_i64(dst, src, shift_amount);
1058 break;
1059 case A64_SHIFT_TYPE_ASR:
1060 if (!sf) {
1061 tcg_gen_ext32s_i64(dst, src);
1062 }
1063 tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
1064 break;
1065 case A64_SHIFT_TYPE_ROR:
1066 if (sf) {
1067 tcg_gen_rotr_i64(dst, src, shift_amount);
1068 } else {
1069 TCGv_i32 t0, t1;
1070 t0 = tcg_temp_new_i32();
1071 t1 = tcg_temp_new_i32();
1072 tcg_gen_trunc_i64_i32(t0, src);
1073 tcg_gen_trunc_i64_i32(t1, shift_amount);
1074 tcg_gen_rotr_i32(t0, t0, t1);
1075 tcg_gen_extu_i32_i64(dst, t0);
1076 tcg_temp_free_i32(t0);
1077 tcg_temp_free_i32(t1);
1078 }
1079 break;
1080 default:
1081 assert(FALSE); /* all shift types should be handled */
1082 break;
1083 }
1084
1085 if (!sf) { /* zero extend final result */
1086 tcg_gen_ext32u_i64(dst, dst);
1087 }
1088}
1089
1090/* shift a TCGv src by immediate, put result in dst. */
1091static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
1092 enum a64_shift_type shift_type, unsigned int shift_i)
1093{
1094 shift_i = shift_i & (sf ? 63 : 31);
1095
1096 if (shift_i == 0) {
1097 tcg_gen_mov_i64(dst, src);
1098 } else {
1099 TCGv_i64 shift_const;
1100 shift_const = tcg_const_i64(shift_i);
1101 shift_reg(dst, src, sf, shift_type, shift_const);
1102 tcg_temp_free_i64(shift_const);
1103 }
1104}
1105
1106/* C3.5.10 Logical (shifted register) */
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001107static void disas_logic_reg(DisasContext *s, uint32_t insn)
1108{
Claudio Fontanad41620e2013-12-03 15:12:19 +00001109 /*
1110 * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
1111 * sf opc 0 1 0 1 0 shift N Rm imm6 Rn Rd
1112 */
1113 TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
1114 unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
1115 sf = (insn & (1 << 31)) ? 1 : 0;
1116 opc = extract32(insn, 29, 2);
1117 shift_type = extract32(insn, 22, 2);
1118 invert = (insn & (1 << 21)) ? 1 : 0;
1119 rm = extract32(insn, 16, 5);
1120 shift_amount = extract32(insn, 10, 6);
1121 rn = extract32(insn, 5, 5);
1122 rd = extract32(insn, 0, 5);
1123
1124 if (!sf && (shift_amount & (1 << 5))) {
1125 unallocated_encoding(s);
1126 return;
1127 }
1128
1129 tcg_rm = tcg_temp_new_i64();
1130 read_cpu_reg(s, tcg_rm, rm, sf);
1131
1132 if (shift_amount) {
1133 shift_reg_imm(tcg_rm, tcg_rm, sf,
1134 shift_type, shift_amount);
1135 }
1136
1137 if (invert) {
1138 tcg_gen_not_i64(tcg_rm, tcg_rm);
1139 /* we zero extend later on (!sf) */
1140 }
1141
1142 tcg_rd = cpu_reg(s, rd);
1143 tcg_rn = cpu_reg(s, rn);
1144
1145 switch (opc) {
1146 case 0: /* AND, BIC */
1147 case 3: /* ANDS, BICS */
1148 tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
1149 break;
1150 case 1: /* ORR, ORN */
1151 tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
1152 break;
1153 case 2: /* EOR, EON */
1154 tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
1155 break;
1156 default:
1157 assert(FALSE); /* must handle all in switch */
1158 break;
1159 }
1160
1161 if (!sf) {
1162 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1163 }
1164
1165 if (opc == 3) {
1166 gen_logic_CC(sf, tcg_rd);
1167 }
1168
1169 tcg_temp_free_i64(tcg_rm);
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001170}
1171
1172/* Add/subtract (extended register) */
1173static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
1174{
1175 unsupported_encoding(s, insn);
1176}
1177
1178/* Add/subtract (shifted register) */
1179static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
1180{
1181 unsupported_encoding(s, insn);
1182}
1183
1184/* Data-processing (3 source) */
1185static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
1186{
1187 unsupported_encoding(s, insn);
1188}
1189
1190/* Add/subtract (with carry) */
1191static void disas_adc_sbc(DisasContext *s, uint32_t insn)
1192{
1193 unsupported_encoding(s, insn);
1194}
1195
1196/* Conditional compare (immediate) */
1197static void disas_cc_imm(DisasContext *s, uint32_t insn)
1198{
1199 unsupported_encoding(s, insn);
1200}
1201
1202/* Conditional compare (register) */
1203static void disas_cc_reg(DisasContext *s, uint32_t insn)
1204{
1205 unsupported_encoding(s, insn);
1206}
1207
Claudio Fontana926f3f32013-12-03 15:12:19 +00001208/* C3.5.6 Conditional select */
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001209static void disas_cond_select(DisasContext *s, uint32_t insn)
1210{
Claudio Fontana926f3f32013-12-03 15:12:19 +00001211 /*
1212 * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 12 11 10 9 5 4 0
1213 * sf op S 1 1 0 1 0 1 0 0 Rm cond op2 Rn Rd
1214 * [0]
1215 * op -> else_inv, op2 -> else_inc
1216 */
1217 unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
1218 TCGv_i64 tcg_rd;
1219 if (extract32(insn, 21, 9) != 0x0d4 || (insn & (1 << 11))) {
1220 unallocated_encoding(s);
1221 return;
1222 }
1223 sf = (insn & (1 << 31)) ? 1 : 0;
1224 else_inv = extract32(insn, 30, 1);
1225 rm = extract32(insn, 16, 5);
1226 cond = extract32(insn, 12, 4);
1227 else_inc = extract32(insn, 10, 1);
1228 rn = extract32(insn, 5, 5);
1229 rd = extract32(insn, 0, 5);
1230 tcg_rd = cpu_reg(s, rd);
1231
1232 if (cond >= 0x0e) { /* condition "always" */
1233 read_cpu_reg(s, tcg_rd, rn, sf);
1234 } else {
1235 int label_nomatch, label_continue;
1236 label_nomatch = gen_new_label();
1237 label_continue = gen_new_label();
1238
1239 arm_gen_test_cc(cond ^ 1, label_nomatch);
1240 /* match: */
1241 read_cpu_reg(s, tcg_rd, rn, sf);
1242 tcg_gen_br(label_continue);
1243 /* nomatch: */
1244 gen_set_label(label_nomatch);
1245 read_cpu_reg(s, tcg_rd, rm, sf);
1246 if (else_inv) {
1247 tcg_gen_not_i64(tcg_rd, tcg_rd);
1248 }
1249 if (else_inc) {
1250 tcg_gen_addi_i64(tcg_rd, tcg_rd, 1);
1251 }
1252 if (!sf) {
1253 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1254 }
1255 /* continue: */
1256 gen_set_label(label_continue);
1257 }
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001258}
1259
Claudio Fontana4d3b1c32013-12-03 15:12:20 +00001260static void handle_clz(DisasContext *s, unsigned int sf,
1261 unsigned int rn, unsigned int rd)
1262{
1263 TCGv_i64 tcg_rd, tcg_rn;
1264 tcg_rd = cpu_reg(s, rd);
1265 tcg_rn = cpu_reg(s, rn);
1266
1267 if (sf) {
1268 gen_helper_clz64(tcg_rd, tcg_rn);
1269 } else {
1270 TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
1271 tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
1272 gen_helper_clz(tcg_tmp32, tcg_tmp32);
1273 tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
1274 tcg_temp_free_i32(tcg_tmp32);
1275 }
1276}
1277
Claudio Fontanaded37772013-12-03 15:12:21 +00001278static void handle_cls(DisasContext *s, unsigned int sf,
1279 unsigned int rn, unsigned int rd)
1280{
1281 TCGv_i64 tcg_rd, tcg_rn;
1282 tcg_rd = cpu_reg(s, rd);
1283 tcg_rn = cpu_reg(s, rn);
1284
1285 if (sf) {
1286 gen_helper_cls64(tcg_rd, tcg_rn);
1287 } else {
1288 TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
1289 tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
1290 gen_helper_cls32(tcg_tmp32, tcg_tmp32);
1291 tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
1292 tcg_temp_free_i32(tcg_tmp32);
1293 }
1294}
1295
Claudio Fontana071b11d2013-12-03 15:12:20 +00001296static void handle_rbit(DisasContext *s, unsigned int sf,
1297 unsigned int rn, unsigned int rd)
1298{
1299 TCGv_i64 tcg_rd, tcg_rn;
1300 tcg_rd = cpu_reg(s, rd);
1301 tcg_rn = cpu_reg(s, rn);
1302
1303 if (sf) {
1304 gen_helper_rbit64(tcg_rd, tcg_rn);
1305 } else {
1306 TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
1307 tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
1308 gen_helper_rbit(tcg_tmp32, tcg_tmp32);
1309 tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
1310 tcg_temp_free_i32(tcg_tmp32);
1311 }
1312}
1313
Claudio Fontanacdd4f722013-12-03 15:12:20 +00001314/* C5.6.149 REV with sf==1, opcode==3 ("REV64") */
1315static void handle_rev64(DisasContext *s, unsigned int sf,
1316 unsigned int rn, unsigned int rd)
1317{
1318 if (!sf) {
1319 unallocated_encoding(s);
1320 return;
1321 }
1322 tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
1323}
1324
1325/* C5.6.149 REV with sf==0, opcode==2 */
1326/* C5.6.151 REV32 (sf==1, opcode==2) */
1327static void handle_rev32(DisasContext *s, unsigned int sf,
1328 unsigned int rn, unsigned int rd)
1329{
1330 TCGv_i64 tcg_rd, tcg_rn;
1331 tcg_rd = cpu_reg(s, rd);
1332 tcg_rn = cpu_reg(s, rn);
1333
1334 if (sf) {
1335 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1336 tcg_gen_andi_i64(tcg_tmp, tcg_rn, 0xffffffff);
1337 tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
1338 tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
1339 tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
1340 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 32, 32);
1341 tcg_temp_free_i64(tcg_tmp);
1342 } else {
1343 tcg_gen_ext32u_i64(tcg_rd, tcg_rn);
1344 tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
1345 }
1346}
1347
1348/* C5.6.150 REV16 (opcode==1) */
1349static void handle_rev16(DisasContext *s, unsigned int sf,
1350 unsigned int rn, unsigned int rd)
1351{
1352 TCGv_i64 tcg_rd, tcg_rn, tcg_tmp;
1353 tcg_rd = cpu_reg(s, rd);
1354 tcg_rn = cpu_reg(s, rn);
1355
1356 tcg_tmp = tcg_temp_new_i64();
1357 tcg_gen_andi_i64(tcg_tmp, tcg_rn, 0xffff);
1358 tcg_gen_bswap16_i64(tcg_rd, tcg_tmp);
1359
1360 tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16);
1361 tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
1362 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
1363 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 16, 16);
1364
1365 if (!sf) { /* done */
1366 tcg_temp_free_i64(tcg_tmp);
1367 return;
1368 }
1369
1370 tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
1371 tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
1372 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
1373 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 32, 16);
1374
1375 tcg_gen_shri_i64(tcg_tmp, tcg_rn, 48);
1376 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
1377 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 48, 16);
1378
1379 tcg_temp_free_i64(tcg_tmp);
1380}
1381
Claudio Fontana4d3b1c32013-12-03 15:12:20 +00001382/* C3.5.7 Data-processing (1 source) */
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001383static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
1384{
Claudio Fontana4d3b1c32013-12-03 15:12:20 +00001385 /*
1386 * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
1387 * sf 1 S 1 1 0 1 0 1 1 0 opcode2 opcode Rn Rd
1388 * [0] [0 0 0 0 0]
1389 */
1390 unsigned int sf, opcode, rn, rd;
1391 if (extract32(insn, 16, 15) != 0x5ac0) {
1392 unallocated_encoding(s);
1393 return;
1394 }
1395 sf = insn & (1 << 31) ? 1 : 0;
1396 opcode = extract32(insn, 10, 6);
1397 rn = extract32(insn, 5, 5);
1398 rd = extract32(insn, 0, 5);
1399
1400 switch (opcode) {
1401 case 0: /* RBIT */
Claudio Fontana071b11d2013-12-03 15:12:20 +00001402 handle_rbit(s, sf, rn, rd);
1403 break;
Claudio Fontana4d3b1c32013-12-03 15:12:20 +00001404 case 1: /* REV16 */
Claudio Fontanacdd4f722013-12-03 15:12:20 +00001405 handle_rev16(s, sf, rn, rd);
1406 break;
Claudio Fontana4d3b1c32013-12-03 15:12:20 +00001407 case 2: /* REV32 */
Claudio Fontanacdd4f722013-12-03 15:12:20 +00001408 handle_rev32(s, sf, rn, rd);
1409 break;
Claudio Fontana4d3b1c32013-12-03 15:12:20 +00001410 case 3: /* REV64 */
Claudio Fontanacdd4f722013-12-03 15:12:20 +00001411 handle_rev64(s, sf, rn, rd);
Claudio Fontana4d3b1c32013-12-03 15:12:20 +00001412 break;
1413 case 4: /* CLZ */
1414 handle_clz(s, sf, rn, rd);
1415 break;
1416 case 5: /* CLS */
Claudio Fontanaded37772013-12-03 15:12:21 +00001417 handle_cls(s, sf, rn, rd);
Claudio Fontana4d3b1c32013-12-03 15:12:20 +00001418 break;
1419 }
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001420}
1421
Claudio Fontana11861fc2013-12-03 15:12:20 +00001422static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
1423 unsigned int rm, unsigned int rn, unsigned int rd)
1424{
1425 TCGv_i64 tcg_n, tcg_m, tcg_rd;
1426 tcg_n = tcg_temp_new_i64();
1427 tcg_m = tcg_temp_new_i64();
1428 tcg_rd = cpu_reg(s, rd);
1429
1430 if (!sf && is_signed) {
1431 tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
1432 tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
1433 } else {
1434 read_cpu_reg(s, tcg_n, rn, sf);
1435 read_cpu_reg(s, tcg_m, rm, sf);
1436 }
1437
1438 if (is_signed) {
1439 gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
1440 } else {
1441 gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
1442 }
1443
1444 tcg_temp_free_i64(tcg_n);
1445 tcg_temp_free_i64(tcg_m);
1446
1447 if (!sf) { /* zero extend final result */
1448 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1449 }
1450}
1451
Claudio Fontanae03cad52013-12-03 15:12:20 +00001452/* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
1453static void handle_shift_reg(DisasContext *s,
1454 enum a64_shift_type shift_type, unsigned int sf,
1455 unsigned int rm, unsigned int rn, unsigned int rd)
1456{
1457 TCGv_i64 tcg_shift = tcg_temp_new_i64();
1458 tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
1459 shift_reg(cpu_reg(s, rd), cpu_reg(s, rn), sf, shift_type, tcg_shift);
1460 tcg_temp_free_i64(tcg_shift);
1461}
1462
Claudio Fontana11861fc2013-12-03 15:12:20 +00001463/* C3.5.8 Data-processing (2 source) */
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001464static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
1465{
Claudio Fontana11861fc2013-12-03 15:12:20 +00001466 /*
1467 * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
1468 * sf 0 S 1 1 0 1 0 1 1 0 Rm opcode Rn Rd
1469 * [0]
1470 */
1471 unsigned int sf, rm, opcode, rn, rd;
1472 sf = insn & (1 << 31) ? 1 : 0;
1473 rm = extract32(insn, 16, 5);
1474 opcode = extract32(insn, 10, 6);
1475 rn = extract32(insn, 5, 5);
1476 rd = extract32(insn, 0, 5);
1477
1478 if (extract32(insn, 21, 10) != 0x0d6) {
1479 unallocated_encoding(s);
1480 return;
1481 }
1482
1483 switch (opcode) {
1484 case 2: /* UDIV */
1485 handle_div(s, FALSE, sf, rm, rn, rd);
1486 break;
1487 case 3: /* SDIV */
1488 handle_div(s, TRUE, sf, rm, rn, rd);
1489 break;
1490 case 8: /* LSLV */
Claudio Fontanae03cad52013-12-03 15:12:20 +00001491 handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
1492 break;
Claudio Fontana11861fc2013-12-03 15:12:20 +00001493 case 9: /* LSRV */
Claudio Fontanae03cad52013-12-03 15:12:20 +00001494 handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
1495 break;
Claudio Fontana11861fc2013-12-03 15:12:20 +00001496 case 10: /* ASRV */
Claudio Fontanae03cad52013-12-03 15:12:20 +00001497 handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
1498 break;
Claudio Fontana11861fc2013-12-03 15:12:20 +00001499 case 11: /* RORV */
Claudio Fontanae03cad52013-12-03 15:12:20 +00001500 handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
1501 break;
Claudio Fontana11861fc2013-12-03 15:12:20 +00001502 case 16:
1503 case 17:
1504 case 18:
1505 case 19:
1506 case 20:
1507 case 21:
1508 case 22:
1509 case 23: /* CRC32 */
1510 unsupported_encoding(s, insn);
1511 break;
1512 default:
1513 unallocated_encoding(s);
1514 break;
1515 }
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001516}
1517
1518/* C3.5 Data processing - register */
1519static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
1520{
1521 switch (extract32(insn, 24, 5)) {
1522 case 0x0a: /* Logical (shifted register) */
1523 disas_logic_reg(s, insn);
1524 break;
1525 case 0x0b: /* Add/subtract */
1526 if (insn & (1 << 21)) { /* (extended register) */
1527 disas_add_sub_ext_reg(s, insn);
1528 } else {
1529 disas_add_sub_reg(s, insn);
1530 }
1531 break;
1532 case 0x1b: /* Data-processing (3 source) */
1533 disas_data_proc_3src(s, insn);
1534 break;
1535 case 0x1a:
1536 switch (extract32(insn, 21, 3)) {
1537 case 0x0: /* Add/subtract (with carry) */
1538 disas_adc_sbc(s, insn);
1539 break;
1540 case 0x2: /* Conditional compare */
1541 if (insn & (1 << 11)) { /* (immediate) */
1542 disas_cc_imm(s, insn);
1543 } else { /* (register) */
1544 disas_cc_reg(s, insn);
1545 }
1546 break;
1547 case 0x4: /* Conditional select */
1548 disas_cond_select(s, insn);
1549 break;
1550 case 0x6: /* Data-processing */
1551 if (insn & (1 << 30)) { /* (1 source) */
1552 disas_data_proc_1src(s, insn);
1553 } else { /* (2 source) */
1554 disas_data_proc_2src(s, insn);
1555 }
1556 break;
1557 default:
1558 unallocated_encoding(s);
1559 break;
1560 }
1561 break;
1562 default:
1563 unallocated_encoding(s);
1564 break;
1565 }
1566}
1567
1568/* C3.6 Data processing - SIMD and floating point */
1569static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
1570{
1571 unsupported_encoding(s, insn);
1572}
1573
1574/* C3.1 A64 instruction index by encoding */
Peter Maydell089a8d92013-12-03 15:26:18 +00001575static void disas_a64_insn(CPUARMState *env, DisasContext *s)
Alexander Graf14ade102013-09-03 20:12:10 +01001576{
1577 uint32_t insn;
1578
1579 insn = arm_ldl_code(env, s->pc, s->bswap_code);
1580 s->insn = insn;
1581 s->pc += 4;
1582
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001583 switch (extract32(insn, 25, 4)) {
1584 case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
Alexander Graf14ade102013-09-03 20:12:10 +01001585 unallocated_encoding(s);
1586 break;
Claudio Fontanaea5ca532013-12-03 15:12:18 +00001587 case 0x8: case 0x9: /* Data processing - immediate */
1588 disas_data_proc_imm(s, insn);
1589 break;
1590 case 0xa: case 0xb: /* Branch, exception generation and system insns */
1591 disas_b_exc_sys(s, insn);
1592 break;
1593 case 0x4:
1594 case 0x6:
1595 case 0xc:
1596 case 0xe: /* Loads and stores */
1597 disas_ldst(s, insn);
1598 break;
1599 case 0x5:
1600 case 0xd: /* Data processing - register */
1601 disas_data_proc_reg(s, insn);
1602 break;
1603 case 0x7:
1604 case 0xf: /* Data processing - SIMD and floating point */
1605 disas_data_proc_simd_fp(s, insn);
1606 break;
1607 default:
1608 assert(FALSE); /* all 15 cases should be handled above */
1609 break;
Alexander Graf14ade102013-09-03 20:12:10 +01001610 }
Alexander Grafeeed5002013-12-03 15:12:18 +00001611
1612 /* if we allocated any temporaries, free them here */
1613 free_tmp_a64(s);
Peter Maydell089a8d92013-12-03 15:26:18 +00001614}
Alexander Graf14ade102013-09-03 20:12:10 +01001615
Peter Maydell089a8d92013-12-03 15:26:18 +00001616void gen_intermediate_code_internal_a64(ARMCPU *cpu,
1617 TranslationBlock *tb,
1618 bool search_pc)
1619{
1620 CPUState *cs = CPU(cpu);
1621 CPUARMState *env = &cpu->env;
1622 DisasContext dc1, *dc = &dc1;
1623 CPUBreakpoint *bp;
1624 uint16_t *gen_opc_end;
1625 int j, lj;
1626 target_ulong pc_start;
1627 target_ulong next_page_start;
1628 int num_insns;
1629 int max_insns;
1630
1631 pc_start = tb->pc;
1632
1633 dc->tb = tb;
1634
1635 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
1636
1637 dc->is_jmp = DISAS_NEXT;
1638 dc->pc = pc_start;
1639 dc->singlestep_enabled = cs->singlestep_enabled;
1640 dc->condjmp = 0;
1641
1642 dc->aarch64 = 1;
Alexander Grafeeed5002013-12-03 15:12:18 +00001643 dc->tmp_a64_count = 0;
Peter Maydell089a8d92013-12-03 15:26:18 +00001644 dc->thumb = 0;
1645 dc->bswap_code = 0;
1646 dc->condexec_mask = 0;
1647 dc->condexec_cond = 0;
1648#if !defined(CONFIG_USER_ONLY)
1649 dc->user = 0;
1650#endif
1651 dc->vfp_enabled = 0;
1652 dc->vec_len = 0;
1653 dc->vec_stride = 0;
1654
1655 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1656 lj = -1;
1657 num_insns = 0;
1658 max_insns = tb->cflags & CF_COUNT_MASK;
1659 if (max_insns == 0) {
1660 max_insns = CF_COUNT_MASK;
1661 }
1662
1663 gen_tb_start();
1664
1665 tcg_clear_temp_count();
1666
1667 do {
1668 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
1669 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1670 if (bp->pc == dc->pc) {
1671 gen_exception_insn(dc, 0, EXCP_DEBUG);
1672 /* Advance PC so that clearing the breakpoint will
1673 invalidate this TB. */
1674 dc->pc += 2;
1675 goto done_generating;
1676 }
1677 }
1678 }
1679
1680 if (search_pc) {
1681 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
1682 if (lj < j) {
1683 lj++;
1684 while (lj < j) {
1685 tcg_ctx.gen_opc_instr_start[lj++] = 0;
1686 }
1687 }
1688 tcg_ctx.gen_opc_pc[lj] = dc->pc;
1689 tcg_ctx.gen_opc_instr_start[lj] = 1;
1690 tcg_ctx.gen_opc_icount[lj] = num_insns;
1691 }
1692
1693 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
1694 gen_io_start();
1695 }
1696
1697 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
1698 tcg_gen_debug_insn_start(dc->pc);
1699 }
1700
1701 disas_a64_insn(env, dc);
1702
1703 if (tcg_check_temp_count()) {
1704 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
1705 dc->pc);
1706 }
1707
1708 /* Translation stops when a conditional branch is encountered.
1709 * Otherwise the subsequent code could get translated several times.
1710 * Also stop translation when a page boundary is reached. This
1711 * ensures prefetch aborts occur at the right place.
1712 */
1713 num_insns++;
1714 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
1715 !cs->singlestep_enabled &&
1716 !singlestep &&
1717 dc->pc < next_page_start &&
1718 num_insns < max_insns);
1719
1720 if (tb->cflags & CF_LAST_IO) {
1721 gen_io_end();
1722 }
1723
1724 if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
1725 /* Note that this means single stepping WFI doesn't halt the CPU.
1726 * For conditional branch insns this is harmless unreachable code as
1727 * gen_goto_tb() has already handled emitting the debug exception
1728 * (and thus a tb-jump is not possible when singlestepping).
1729 */
1730 assert(dc->is_jmp != DISAS_TB_JUMP);
1731 if (dc->is_jmp != DISAS_JUMP) {
1732 gen_a64_set_pc_im(dc->pc);
1733 }
1734 gen_exception(EXCP_DEBUG);
1735 } else {
1736 switch (dc->is_jmp) {
1737 case DISAS_NEXT:
1738 gen_goto_tb(dc, 1, dc->pc);
1739 break;
1740 default:
1741 case DISAS_JUMP:
1742 case DISAS_UPDATE:
1743 /* indicate that the hash table must be used to find the next TB */
1744 tcg_gen_exit_tb(0);
1745 break;
1746 case DISAS_TB_JUMP:
1747 case DISAS_EXC:
1748 case DISAS_SWI:
1749 break;
1750 case DISAS_WFI:
1751 /* This is a special case because we don't want to just halt the CPU
1752 * if trying to debug across a WFI.
1753 */
1754 gen_helper_wfi(cpu_env);
1755 break;
1756 }
1757 }
1758
1759done_generating:
1760 gen_tb_end(tb, num_insns);
1761 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
1762
1763#ifdef DEBUG_DISAS
1764 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1765 qemu_log("----------------\n");
1766 qemu_log("IN: %s\n", lookup_symbol(pc_start));
1767 log_target_disas(env, pc_start, dc->pc - pc_start,
1768 dc->thumb | (dc->bswap_code << 1));
1769 qemu_log("\n");
1770 }
1771#endif
1772 if (search_pc) {
1773 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
1774 lj++;
1775 while (lj <= j) {
1776 tcg_ctx.gen_opc_instr_start[lj++] = 0;
1777 }
1778 } else {
1779 tb->size = dc->pc - pc_start;
1780 tb->icount = num_insns;
Alexander Graf14ade102013-09-03 20:12:10 +01001781 }
1782}