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