Statistics
| Branch: | Revision:

root / target-arm / translate-a64.c @ 82e14b02

History | View | Annotate | Download (41.9 kB)

1 14ade10f Alexander Graf
/*
2 14ade10f Alexander Graf
 *  AArch64 translation
3 14ade10f Alexander Graf
 *
4 14ade10f Alexander Graf
 *  Copyright (c) 2013 Alexander Graf <agraf@suse.de>
5 14ade10f Alexander Graf
 *
6 14ade10f Alexander Graf
 * This library is free software; you can redistribute it and/or
7 14ade10f Alexander Graf
 * modify it under the terms of the GNU Lesser General Public
8 14ade10f Alexander Graf
 * License as published by the Free Software Foundation; either
9 14ade10f Alexander Graf
 * version 2 of the License, or (at your option) any later version.
10 14ade10f Alexander Graf
 *
11 14ade10f Alexander Graf
 * This library is distributed in the hope that it will be useful,
12 14ade10f Alexander Graf
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 14ade10f Alexander Graf
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 14ade10f Alexander Graf
 * Lesser General Public License for more details.
15 14ade10f Alexander Graf
 *
16 14ade10f Alexander Graf
 * You should have received a copy of the GNU Lesser General Public
17 14ade10f Alexander Graf
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 14ade10f Alexander Graf
 */
19 14ade10f Alexander Graf
#include <stdarg.h>
20 14ade10f Alexander Graf
#include <stdlib.h>
21 14ade10f Alexander Graf
#include <stdio.h>
22 14ade10f Alexander Graf
#include <string.h>
23 14ade10f Alexander Graf
#include <inttypes.h>
24 14ade10f Alexander Graf
25 14ade10f Alexander Graf
#include "cpu.h"
26 14ade10f Alexander Graf
#include "tcg-op.h"
27 14ade10f Alexander Graf
#include "qemu/log.h"
28 14ade10f Alexander Graf
#include "translate.h"
29 14ade10f Alexander Graf
#include "qemu/host-utils.h"
30 14ade10f Alexander Graf
31 40f860cd Peter Maydell
#include "exec/gen-icount.h"
32 40f860cd Peter Maydell
33 14ade10f Alexander Graf
#include "helper.h"
34 14ade10f Alexander Graf
#define GEN_HELPER 1
35 14ade10f Alexander Graf
#include "helper.h"
36 14ade10f Alexander Graf
37 14ade10f Alexander Graf
static TCGv_i64 cpu_X[32];
38 14ade10f Alexander Graf
static TCGv_i64 cpu_pc;
39 832ffa1c Alexander Graf
static TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
40 14ade10f Alexander Graf
41 14ade10f Alexander Graf
static const char *regnames[] = {
42 14ade10f Alexander Graf
    "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
43 14ade10f Alexander Graf
    "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
44 14ade10f Alexander Graf
    "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
45 14ade10f Alexander Graf
    "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
46 14ade10f Alexander Graf
};
47 14ade10f Alexander Graf
48 832ffa1c Alexander Graf
enum a64_shift_type {
49 832ffa1c Alexander Graf
    A64_SHIFT_TYPE_LSL = 0,
50 832ffa1c Alexander Graf
    A64_SHIFT_TYPE_LSR = 1,
51 832ffa1c Alexander Graf
    A64_SHIFT_TYPE_ASR = 2,
52 832ffa1c Alexander Graf
    A64_SHIFT_TYPE_ROR = 3
53 832ffa1c Alexander Graf
};
54 832ffa1c Alexander Graf
55 14ade10f Alexander Graf
/* initialize TCG globals.  */
56 14ade10f Alexander Graf
void a64_translate_init(void)
57 14ade10f Alexander Graf
{
58 14ade10f Alexander Graf
    int i;
59 14ade10f Alexander Graf
60 14ade10f Alexander Graf
    cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
61 14ade10f Alexander Graf
                                    offsetof(CPUARMState, pc),
62 14ade10f Alexander Graf
                                    "pc");
63 14ade10f Alexander Graf
    for (i = 0; i < 32; i++) {
64 14ade10f Alexander Graf
        cpu_X[i] = tcg_global_mem_new_i64(TCG_AREG0,
65 14ade10f Alexander Graf
                                          offsetof(CPUARMState, xregs[i]),
66 14ade10f Alexander Graf
                                          regnames[i]);
67 14ade10f Alexander Graf
    }
68 14ade10f Alexander Graf
69 832ffa1c Alexander Graf
    cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
70 832ffa1c Alexander Graf
    cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
71 832ffa1c Alexander Graf
    cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
72 832ffa1c Alexander Graf
    cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
73 14ade10f Alexander Graf
}
74 14ade10f Alexander Graf
75 14ade10f Alexander Graf
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
76 14ade10f Alexander Graf
                            fprintf_function cpu_fprintf, int flags)
77 14ade10f Alexander Graf
{
78 14ade10f Alexander Graf
    ARMCPU *cpu = ARM_CPU(cs);
79 14ade10f Alexander Graf
    CPUARMState *env = &cpu->env;
80 d356312f Peter Maydell
    uint32_t psr = pstate_read(env);
81 14ade10f Alexander Graf
    int i;
82 14ade10f Alexander Graf
83 14ade10f Alexander Graf
    cpu_fprintf(f, "PC=%016"PRIx64"  SP=%016"PRIx64"\n",
84 14ade10f Alexander Graf
            env->pc, env->xregs[31]);
85 14ade10f Alexander Graf
    for (i = 0; i < 31; i++) {
86 14ade10f Alexander Graf
        cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
87 14ade10f Alexander Graf
        if ((i % 4) == 3) {
88 14ade10f Alexander Graf
            cpu_fprintf(f, "\n");
89 14ade10f Alexander Graf
        } else {
90 14ade10f Alexander Graf
            cpu_fprintf(f, " ");
91 14ade10f Alexander Graf
        }
92 14ade10f Alexander Graf
    }
93 d356312f Peter Maydell
    cpu_fprintf(f, "PSTATE=%08x (flags %c%c%c%c)\n",
94 d356312f Peter Maydell
                psr,
95 d356312f Peter Maydell
                psr & PSTATE_N ? 'N' : '-',
96 d356312f Peter Maydell
                psr & PSTATE_Z ? 'Z' : '-',
97 d356312f Peter Maydell
                psr & PSTATE_C ? 'C' : '-',
98 d356312f Peter Maydell
                psr & PSTATE_V ? 'V' : '-');
99 14ade10f Alexander Graf
    cpu_fprintf(f, "\n");
100 14ade10f Alexander Graf
}
101 14ade10f Alexander Graf
102 14ade10f Alexander Graf
void gen_a64_set_pc_im(uint64_t val)
103 14ade10f Alexander Graf
{
104 14ade10f Alexander Graf
    tcg_gen_movi_i64(cpu_pc, val);
105 14ade10f Alexander Graf
}
106 14ade10f Alexander Graf
107 14ade10f Alexander Graf
static void gen_exception(int excp)
108 14ade10f Alexander Graf
{
109 14ade10f Alexander Graf
    TCGv_i32 tmp = tcg_temp_new_i32();
110 14ade10f Alexander Graf
    tcg_gen_movi_i32(tmp, excp);
111 14ade10f Alexander Graf
    gen_helper_exception(cpu_env, tmp);
112 14ade10f Alexander Graf
    tcg_temp_free_i32(tmp);
113 14ade10f Alexander Graf
}
114 14ade10f Alexander Graf
115 14ade10f Alexander Graf
static void gen_exception_insn(DisasContext *s, int offset, int excp)
116 14ade10f Alexander Graf
{
117 14ade10f Alexander Graf
    gen_a64_set_pc_im(s->pc - offset);
118 14ade10f Alexander Graf
    gen_exception(excp);
119 40f860cd Peter Maydell
    s->is_jmp = DISAS_EXC;
120 40f860cd Peter Maydell
}
121 40f860cd Peter Maydell
122 40f860cd Peter Maydell
static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
123 40f860cd Peter Maydell
{
124 40f860cd Peter Maydell
    /* No direct tb linking with singlestep or deterministic io */
125 40f860cd Peter Maydell
    if (s->singlestep_enabled || (s->tb->cflags & CF_LAST_IO)) {
126 40f860cd Peter Maydell
        return false;
127 40f860cd Peter Maydell
    }
128 40f860cd Peter Maydell
129 40f860cd Peter Maydell
    /* Only link tbs from inside the same guest page */
130 40f860cd Peter Maydell
    if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
131 40f860cd Peter Maydell
        return false;
132 40f860cd Peter Maydell
    }
133 40f860cd Peter Maydell
134 40f860cd Peter Maydell
    return true;
135 40f860cd Peter Maydell
}
136 40f860cd Peter Maydell
137 40f860cd Peter Maydell
static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
138 40f860cd Peter Maydell
{
139 40f860cd Peter Maydell
    TranslationBlock *tb;
140 40f860cd Peter Maydell
141 40f860cd Peter Maydell
    tb = s->tb;
142 40f860cd Peter Maydell
    if (use_goto_tb(s, n, dest)) {
143 40f860cd Peter Maydell
        tcg_gen_goto_tb(n);
144 40f860cd Peter Maydell
        gen_a64_set_pc_im(dest);
145 40f860cd Peter Maydell
        tcg_gen_exit_tb((tcg_target_long)tb + n);
146 40f860cd Peter Maydell
        s->is_jmp = DISAS_TB_JUMP;
147 40f860cd Peter Maydell
    } else {
148 40f860cd Peter Maydell
        gen_a64_set_pc_im(dest);
149 40f860cd Peter Maydell
        if (s->singlestep_enabled) {
150 40f860cd Peter Maydell
            gen_exception(EXCP_DEBUG);
151 40f860cd Peter Maydell
        }
152 40f860cd Peter Maydell
        tcg_gen_exit_tb(0);
153 40f860cd Peter Maydell
        s->is_jmp = DISAS_JUMP;
154 40f860cd Peter Maydell
    }
155 14ade10f Alexander Graf
}
156 14ade10f Alexander Graf
157 ad7ee8a2 Claudio Fontana
static void unallocated_encoding(DisasContext *s)
158 14ade10f Alexander Graf
{
159 14ade10f Alexander Graf
    gen_exception_insn(s, 4, EXCP_UDEF);
160 14ade10f Alexander Graf
}
161 14ade10f Alexander Graf
162 ad7ee8a2 Claudio Fontana
#define unsupported_encoding(s, insn)                                    \
163 ad7ee8a2 Claudio Fontana
    do {                                                                 \
164 ad7ee8a2 Claudio Fontana
        qemu_log_mask(LOG_UNIMP,                                         \
165 ad7ee8a2 Claudio Fontana
                      "%s:%d: unsupported instruction encoding 0x%08x "  \
166 ad7ee8a2 Claudio Fontana
                      "at pc=%016" PRIx64 "\n",                          \
167 ad7ee8a2 Claudio Fontana
                      __FILE__, __LINE__, insn, s->pc - 4);              \
168 ad7ee8a2 Claudio Fontana
        unallocated_encoding(s);                                         \
169 ad7ee8a2 Claudio Fontana
    } while (0);
170 14ade10f Alexander Graf
171 11e169de Alexander Graf
static void init_tmp_a64_array(DisasContext *s)
172 11e169de Alexander Graf
{
173 11e169de Alexander Graf
#ifdef CONFIG_DEBUG_TCG
174 11e169de Alexander Graf
    int i;
175 11e169de Alexander Graf
    for (i = 0; i < ARRAY_SIZE(s->tmp_a64); i++) {
176 11e169de Alexander Graf
        TCGV_UNUSED_I64(s->tmp_a64[i]);
177 11e169de Alexander Graf
    }
178 11e169de Alexander Graf
#endif
179 11e169de Alexander Graf
    s->tmp_a64_count = 0;
180 11e169de Alexander Graf
}
181 11e169de Alexander Graf
182 11e169de Alexander Graf
static void free_tmp_a64(DisasContext *s)
183 11e169de Alexander Graf
{
184 11e169de Alexander Graf
    int i;
185 11e169de Alexander Graf
    for (i = 0; i < s->tmp_a64_count; i++) {
186 11e169de Alexander Graf
        tcg_temp_free_i64(s->tmp_a64[i]);
187 11e169de Alexander Graf
    }
188 11e169de Alexander Graf
    init_tmp_a64_array(s);
189 11e169de Alexander Graf
}
190 11e169de Alexander Graf
191 11e169de Alexander Graf
static TCGv_i64 new_tmp_a64(DisasContext *s)
192 11e169de Alexander Graf
{
193 11e169de Alexander Graf
    assert(s->tmp_a64_count < TMP_A64_MAX);
194 11e169de Alexander Graf
    return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
195 11e169de Alexander Graf
}
196 11e169de Alexander Graf
197 11e169de Alexander Graf
static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
198 11e169de Alexander Graf
{
199 11e169de Alexander Graf
    TCGv_i64 t = new_tmp_a64(s);
200 11e169de Alexander Graf
    tcg_gen_movi_i64(t, 0);
201 11e169de Alexander Graf
    return t;
202 11e169de Alexander Graf
}
203 11e169de Alexander Graf
204 11e169de Alexander Graf
static TCGv_i64 cpu_reg(DisasContext *s, int reg)
205 11e169de Alexander Graf
{
206 11e169de Alexander Graf
    if (reg == 31) {
207 11e169de Alexander Graf
        return new_tmp_a64_zero(s);
208 11e169de Alexander Graf
    } else {
209 11e169de Alexander Graf
        return cpu_X[reg];
210 11e169de Alexander Graf
    }
211 11e169de Alexander Graf
}
212 11e169de Alexander Graf
213 60e53388 Alexander Graf
/* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
214 60e53388 Alexander Graf
 * representing the register contents. This TCGv is an auto-freed
215 60e53388 Alexander Graf
 * temporary so it need not be explicitly freed, and may be modified.
216 60e53388 Alexander Graf
 */
217 60e53388 Alexander Graf
static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
218 60e53388 Alexander Graf
{
219 60e53388 Alexander Graf
    TCGv_i64 v = new_tmp_a64(s);
220 60e53388 Alexander Graf
    if (reg != 31) {
221 60e53388 Alexander Graf
        if (sf) {
222 60e53388 Alexander Graf
            tcg_gen_mov_i64(v, cpu_X[reg]);
223 60e53388 Alexander Graf
        } else {
224 60e53388 Alexander Graf
            tcg_gen_ext32u_i64(v, cpu_X[reg]);
225 60e53388 Alexander Graf
        }
226 60e53388 Alexander Graf
    } else {
227 60e53388 Alexander Graf
        tcg_gen_movi_i64(v, 0);
228 60e53388 Alexander Graf
    }
229 60e53388 Alexander Graf
    return v;
230 60e53388 Alexander Graf
}
231 60e53388 Alexander Graf
232 832ffa1c Alexander Graf
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
233 832ffa1c Alexander Graf
 * than the 32 bit equivalent.
234 832ffa1c Alexander Graf
 */
235 832ffa1c Alexander Graf
static inline void gen_set_NZ64(TCGv_i64 result)
236 832ffa1c Alexander Graf
{
237 832ffa1c Alexander Graf
    TCGv_i64 flag = tcg_temp_new_i64();
238 832ffa1c Alexander Graf
239 832ffa1c Alexander Graf
    tcg_gen_setcondi_i64(TCG_COND_NE, flag, result, 0);
240 832ffa1c Alexander Graf
    tcg_gen_trunc_i64_i32(cpu_ZF, flag);
241 832ffa1c Alexander Graf
    tcg_gen_shri_i64(flag, result, 32);
242 832ffa1c Alexander Graf
    tcg_gen_trunc_i64_i32(cpu_NF, flag);
243 832ffa1c Alexander Graf
    tcg_temp_free_i64(flag);
244 832ffa1c Alexander Graf
}
245 832ffa1c Alexander Graf
246 832ffa1c Alexander Graf
/* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
247 832ffa1c Alexander Graf
static inline void gen_logic_CC(int sf, TCGv_i64 result)
248 832ffa1c Alexander Graf
{
249 832ffa1c Alexander Graf
    if (sf) {
250 832ffa1c Alexander Graf
        gen_set_NZ64(result);
251 832ffa1c Alexander Graf
    } else {
252 832ffa1c Alexander Graf
        tcg_gen_trunc_i64_i32(cpu_ZF, result);
253 832ffa1c Alexander Graf
        tcg_gen_trunc_i64_i32(cpu_NF, result);
254 832ffa1c Alexander Graf
    }
255 832ffa1c Alexander Graf
    tcg_gen_movi_i32(cpu_CF, 0);
256 832ffa1c Alexander Graf
    tcg_gen_movi_i32(cpu_VF, 0);
257 832ffa1c Alexander Graf
}
258 832ffa1c Alexander Graf
259 ad7ee8a2 Claudio Fontana
/*
260 ad7ee8a2 Claudio Fontana
 * the instruction disassembly implemented here matches
261 ad7ee8a2 Claudio Fontana
 * the instruction encoding classifications in chapter 3 (C3)
262 ad7ee8a2 Claudio Fontana
 * of the ARM Architecture Reference Manual (DDI0487A_a)
263 ad7ee8a2 Claudio Fontana
 */
264 ad7ee8a2 Claudio Fontana
265 11e169de Alexander Graf
/* C3.2.7 Unconditional branch (immediate)
266 11e169de Alexander Graf
 *   31  30       26 25                                  0
267 11e169de Alexander Graf
 * +----+-----------+-------------------------------------+
268 11e169de Alexander Graf
 * | op | 0 0 1 0 1 |                 imm26               |
269 11e169de Alexander Graf
 * +----+-----------+-------------------------------------+
270 11e169de Alexander Graf
 */
271 ad7ee8a2 Claudio Fontana
static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
272 ad7ee8a2 Claudio Fontana
{
273 11e169de Alexander Graf
    uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
274 11e169de Alexander Graf
275 11e169de Alexander Graf
    if (insn & (1 << 31)) {
276 11e169de Alexander Graf
        /* C5.6.26 BL Branch with link */
277 11e169de Alexander Graf
        tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
278 11e169de Alexander Graf
    }
279 11e169de Alexander Graf
280 11e169de Alexander Graf
    /* C5.6.20 B Branch / C5.6.26 BL Branch with link */
281 11e169de Alexander Graf
    gen_goto_tb(s, 0, addr);
282 ad7ee8a2 Claudio Fontana
}
283 ad7ee8a2 Claudio Fontana
284 60e53388 Alexander Graf
/* C3.2.1 Compare & branch (immediate)
285 60e53388 Alexander Graf
 *   31  30         25  24  23                  5 4      0
286 60e53388 Alexander Graf
 * +----+-------------+----+---------------------+--------+
287 60e53388 Alexander Graf
 * | sf | 0 1 1 0 1 0 | op |         imm19       |   Rt   |
288 60e53388 Alexander Graf
 * +----+-------------+----+---------------------+--------+
289 60e53388 Alexander Graf
 */
290 ad7ee8a2 Claudio Fontana
static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
291 ad7ee8a2 Claudio Fontana
{
292 60e53388 Alexander Graf
    unsigned int sf, op, rt;
293 60e53388 Alexander Graf
    uint64_t addr;
294 60e53388 Alexander Graf
    int label_match;
295 60e53388 Alexander Graf
    TCGv_i64 tcg_cmp;
296 60e53388 Alexander Graf
297 60e53388 Alexander Graf
    sf = extract32(insn, 31, 1);
298 60e53388 Alexander Graf
    op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
299 60e53388 Alexander Graf
    rt = extract32(insn, 0, 5);
300 60e53388 Alexander Graf
    addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
301 60e53388 Alexander Graf
302 60e53388 Alexander Graf
    tcg_cmp = read_cpu_reg(s, rt, sf);
303 60e53388 Alexander Graf
    label_match = gen_new_label();
304 60e53388 Alexander Graf
305 60e53388 Alexander Graf
    tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
306 60e53388 Alexander Graf
                        tcg_cmp, 0, label_match);
307 60e53388 Alexander Graf
308 60e53388 Alexander Graf
    gen_goto_tb(s, 0, s->pc);
309 60e53388 Alexander Graf
    gen_set_label(label_match);
310 60e53388 Alexander Graf
    gen_goto_tb(s, 1, addr);
311 ad7ee8a2 Claudio Fontana
}
312 ad7ee8a2 Claudio Fontana
313 db0f7958 Alexander Graf
/* C3.2.5 Test & branch (immediate)
314 db0f7958 Alexander Graf
 *   31  30         25  24  23   19 18          5 4    0
315 db0f7958 Alexander Graf
 * +----+-------------+----+-------+-------------+------+
316 db0f7958 Alexander Graf
 * | b5 | 0 1 1 0 1 1 | op |  b40  |    imm14    |  Rt  |
317 db0f7958 Alexander Graf
 * +----+-------------+----+-------+-------------+------+
318 db0f7958 Alexander Graf
 */
319 ad7ee8a2 Claudio Fontana
static void disas_test_b_imm(DisasContext *s, uint32_t insn)
320 ad7ee8a2 Claudio Fontana
{
321 db0f7958 Alexander Graf
    unsigned int bit_pos, op, rt;
322 db0f7958 Alexander Graf
    uint64_t addr;
323 db0f7958 Alexander Graf
    int label_match;
324 db0f7958 Alexander Graf
    TCGv_i64 tcg_cmp;
325 db0f7958 Alexander Graf
326 db0f7958 Alexander Graf
    bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
327 db0f7958 Alexander Graf
    op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
328 db0f7958 Alexander Graf
    addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
329 db0f7958 Alexander Graf
    rt = extract32(insn, 0, 5);
330 db0f7958 Alexander Graf
331 db0f7958 Alexander Graf
    tcg_cmp = tcg_temp_new_i64();
332 db0f7958 Alexander Graf
    tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
333 db0f7958 Alexander Graf
    label_match = gen_new_label();
334 db0f7958 Alexander Graf
    tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
335 db0f7958 Alexander Graf
                        tcg_cmp, 0, label_match);
336 db0f7958 Alexander Graf
    tcg_temp_free_i64(tcg_cmp);
337 db0f7958 Alexander Graf
    gen_goto_tb(s, 0, s->pc);
338 db0f7958 Alexander Graf
    gen_set_label(label_match);
339 db0f7958 Alexander Graf
    gen_goto_tb(s, 1, addr);
340 ad7ee8a2 Claudio Fontana
}
341 ad7ee8a2 Claudio Fontana
342 39fb730a Alexander Graf
/* C3.2.2 / C5.6.19 Conditional branch (immediate)
343 39fb730a Alexander Graf
 *  31           25  24  23                  5   4  3    0
344 39fb730a Alexander Graf
 * +---------------+----+---------------------+----+------+
345 39fb730a Alexander Graf
 * | 0 1 0 1 0 1 0 | o1 |         imm19       | o0 | cond |
346 39fb730a Alexander Graf
 * +---------------+----+---------------------+----+------+
347 39fb730a Alexander Graf
 */
348 ad7ee8a2 Claudio Fontana
static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
349 ad7ee8a2 Claudio Fontana
{
350 39fb730a Alexander Graf
    unsigned int cond;
351 39fb730a Alexander Graf
    uint64_t addr;
352 39fb730a Alexander Graf
353 39fb730a Alexander Graf
    if ((insn & (1 << 4)) || (insn & (1 << 24))) {
354 39fb730a Alexander Graf
        unallocated_encoding(s);
355 39fb730a Alexander Graf
        return;
356 39fb730a Alexander Graf
    }
357 39fb730a Alexander Graf
    addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
358 39fb730a Alexander Graf
    cond = extract32(insn, 0, 4);
359 39fb730a Alexander Graf
360 39fb730a Alexander Graf
    if (cond < 0x0e) {
361 39fb730a Alexander Graf
        /* genuinely conditional branches */
362 39fb730a Alexander Graf
        int label_match = gen_new_label();
363 39fb730a Alexander Graf
        arm_gen_test_cc(cond, label_match);
364 39fb730a Alexander Graf
        gen_goto_tb(s, 0, s->pc);
365 39fb730a Alexander Graf
        gen_set_label(label_match);
366 39fb730a Alexander Graf
        gen_goto_tb(s, 1, addr);
367 39fb730a Alexander Graf
    } else {
368 39fb730a Alexander Graf
        /* 0xe and 0xf are both "always" conditions */
369 39fb730a Alexander Graf
        gen_goto_tb(s, 0, addr);
370 39fb730a Alexander Graf
    }
371 ad7ee8a2 Claudio Fontana
}
372 ad7ee8a2 Claudio Fontana
373 87462e0f Claudio Fontana
/* C5.6.68 HINT */
374 87462e0f Claudio Fontana
static void handle_hint(DisasContext *s, uint32_t insn,
375 87462e0f Claudio Fontana
                        unsigned int op1, unsigned int op2, unsigned int crm)
376 87462e0f Claudio Fontana
{
377 87462e0f Claudio Fontana
    unsigned int selector = crm << 3 | op2;
378 87462e0f Claudio Fontana
379 87462e0f Claudio Fontana
    if (op1 != 3) {
380 87462e0f Claudio Fontana
        unallocated_encoding(s);
381 87462e0f Claudio Fontana
        return;
382 87462e0f Claudio Fontana
    }
383 87462e0f Claudio Fontana
384 87462e0f Claudio Fontana
    switch (selector) {
385 87462e0f Claudio Fontana
    case 0: /* NOP */
386 87462e0f Claudio Fontana
        return;
387 87462e0f Claudio Fontana
    case 1: /* YIELD */
388 87462e0f Claudio Fontana
    case 2: /* WFE */
389 87462e0f Claudio Fontana
    case 3: /* WFI */
390 87462e0f Claudio Fontana
    case 4: /* SEV */
391 87462e0f Claudio Fontana
    case 5: /* SEVL */
392 87462e0f Claudio Fontana
        /* we treat all as NOP at least for now */
393 87462e0f Claudio Fontana
        return;
394 87462e0f Claudio Fontana
    default:
395 87462e0f Claudio Fontana
        /* default specified as NOP equivalent */
396 87462e0f Claudio Fontana
        return;
397 87462e0f Claudio Fontana
    }
398 87462e0f Claudio Fontana
}
399 87462e0f Claudio Fontana
400 87462e0f Claudio Fontana
/* CLREX, DSB, DMB, ISB */
401 87462e0f Claudio Fontana
static void handle_sync(DisasContext *s, uint32_t insn,
402 87462e0f Claudio Fontana
                        unsigned int op1, unsigned int op2, unsigned int crm)
403 87462e0f Claudio Fontana
{
404 87462e0f Claudio Fontana
    if (op1 != 3) {
405 87462e0f Claudio Fontana
        unallocated_encoding(s);
406 87462e0f Claudio Fontana
        return;
407 87462e0f Claudio Fontana
    }
408 87462e0f Claudio Fontana
409 87462e0f Claudio Fontana
    switch (op2) {
410 87462e0f Claudio Fontana
    case 2: /* CLREX */
411 87462e0f Claudio Fontana
        unsupported_encoding(s, insn);
412 87462e0f Claudio Fontana
        return;
413 87462e0f Claudio Fontana
    case 4: /* DSB */
414 87462e0f Claudio Fontana
    case 5: /* DMB */
415 87462e0f Claudio Fontana
    case 6: /* ISB */
416 87462e0f Claudio Fontana
        /* We don't emulate caches so barriers are no-ops */
417 87462e0f Claudio Fontana
        return;
418 87462e0f Claudio Fontana
    default:
419 87462e0f Claudio Fontana
        unallocated_encoding(s);
420 87462e0f Claudio Fontana
        return;
421 87462e0f Claudio Fontana
    }
422 87462e0f Claudio Fontana
}
423 87462e0f Claudio Fontana
424 87462e0f Claudio Fontana
/* C5.6.130 MSR (immediate) - move immediate to processor state field */
425 87462e0f Claudio Fontana
static void handle_msr_i(DisasContext *s, uint32_t insn,
426 87462e0f Claudio Fontana
                         unsigned int op1, unsigned int op2, unsigned int crm)
427 87462e0f Claudio Fontana
{
428 87462e0f Claudio Fontana
    unsupported_encoding(s, insn);
429 87462e0f Claudio Fontana
}
430 87462e0f Claudio Fontana
431 87462e0f Claudio Fontana
/* C5.6.204 SYS */
432 87462e0f Claudio Fontana
static void handle_sys(DisasContext *s, uint32_t insn, unsigned int l,
433 87462e0f Claudio Fontana
                       unsigned int op1, unsigned int op2,
434 87462e0f Claudio Fontana
                       unsigned int crn, unsigned int crm, unsigned int rt)
435 87462e0f Claudio Fontana
{
436 87462e0f Claudio Fontana
    unsupported_encoding(s, insn);
437 87462e0f Claudio Fontana
}
438 87462e0f Claudio Fontana
439 87462e0f Claudio Fontana
/* C5.6.129 MRS - move from system register */
440 87462e0f Claudio Fontana
static void handle_mrs(DisasContext *s, uint32_t insn, unsigned int op0,
441 87462e0f Claudio Fontana
                       unsigned int op1, unsigned int op2,
442 87462e0f Claudio Fontana
                       unsigned int crn, unsigned int crm, unsigned int rt)
443 87462e0f Claudio Fontana
{
444 87462e0f Claudio Fontana
    unsupported_encoding(s, insn);
445 87462e0f Claudio Fontana
}
446 87462e0f Claudio Fontana
447 87462e0f Claudio Fontana
/* C5.6.131 MSR (register) - move to system register */
448 87462e0f Claudio Fontana
static void handle_msr(DisasContext *s, uint32_t insn, unsigned int op0,
449 87462e0f Claudio Fontana
                       unsigned int op1, unsigned int op2,
450 87462e0f Claudio Fontana
                       unsigned int crn, unsigned int crm, unsigned int rt)
451 ad7ee8a2 Claudio Fontana
{
452 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
453 ad7ee8a2 Claudio Fontana
}
454 ad7ee8a2 Claudio Fontana
455 87462e0f Claudio Fontana
/* C3.2.4 System
456 87462e0f Claudio Fontana
 *  31                 22 21  20 19 18 16 15   12 11    8 7   5 4    0
457 87462e0f Claudio Fontana
 * +---------------------+---+-----+-----+-------+-------+-----+------+
458 87462e0f Claudio Fontana
 * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 |  CRn  |  CRm  | op2 |  Rt  |
459 87462e0f Claudio Fontana
 * +---------------------+---+-----+-----+-------+-------+-----+------+
460 87462e0f Claudio Fontana
 */
461 87462e0f Claudio Fontana
static void disas_system(DisasContext *s, uint32_t insn)
462 87462e0f Claudio Fontana
{
463 87462e0f Claudio Fontana
    unsigned int l, op0, op1, crn, crm, op2, rt;
464 87462e0f Claudio Fontana
    l = extract32(insn, 21, 1);
465 87462e0f Claudio Fontana
    op0 = extract32(insn, 19, 2);
466 87462e0f Claudio Fontana
    op1 = extract32(insn, 16, 3);
467 87462e0f Claudio Fontana
    crn = extract32(insn, 12, 4);
468 87462e0f Claudio Fontana
    crm = extract32(insn, 8, 4);
469 87462e0f Claudio Fontana
    op2 = extract32(insn, 5, 3);
470 87462e0f Claudio Fontana
    rt = extract32(insn, 0, 5);
471 87462e0f Claudio Fontana
472 87462e0f Claudio Fontana
    if (op0 == 0) {
473 87462e0f Claudio Fontana
        if (l || rt != 31) {
474 87462e0f Claudio Fontana
            unallocated_encoding(s);
475 87462e0f Claudio Fontana
            return;
476 87462e0f Claudio Fontana
        }
477 87462e0f Claudio Fontana
        switch (crn) {
478 87462e0f Claudio Fontana
        case 2: /* C5.6.68 HINT */
479 87462e0f Claudio Fontana
            handle_hint(s, insn, op1, op2, crm);
480 87462e0f Claudio Fontana
            break;
481 87462e0f Claudio Fontana
        case 3: /* CLREX, DSB, DMB, ISB */
482 87462e0f Claudio Fontana
            handle_sync(s, insn, op1, op2, crm);
483 87462e0f Claudio Fontana
            break;
484 87462e0f Claudio Fontana
        case 4: /* C5.6.130 MSR (immediate) */
485 87462e0f Claudio Fontana
            handle_msr_i(s, insn, op1, op2, crm);
486 87462e0f Claudio Fontana
            break;
487 87462e0f Claudio Fontana
        default:
488 87462e0f Claudio Fontana
            unallocated_encoding(s);
489 87462e0f Claudio Fontana
            break;
490 87462e0f Claudio Fontana
        }
491 87462e0f Claudio Fontana
        return;
492 87462e0f Claudio Fontana
    }
493 87462e0f Claudio Fontana
494 87462e0f Claudio Fontana
    if (op0 == 1) {
495 87462e0f Claudio Fontana
        /* C5.6.204 SYS */
496 87462e0f Claudio Fontana
        handle_sys(s, insn, l, op1, op2, crn, crm, rt);
497 87462e0f Claudio Fontana
    } else if (l) { /* op0 > 1 */
498 87462e0f Claudio Fontana
        /* C5.6.129 MRS - move from system register */
499 87462e0f Claudio Fontana
        handle_mrs(s, insn, op0, op1, op2, crn, crm, rt);
500 87462e0f Claudio Fontana
    } else {
501 87462e0f Claudio Fontana
        /* C5.6.131 MSR (register) - move to system register */
502 87462e0f Claudio Fontana
        handle_msr(s, insn, op0, op1, op2, crn, crm, rt);
503 87462e0f Claudio Fontana
    }
504 87462e0f Claudio Fontana
}
505 87462e0f Claudio Fontana
506 ad7ee8a2 Claudio Fontana
/* Exception generation */
507 ad7ee8a2 Claudio Fontana
static void disas_exc(DisasContext *s, uint32_t insn)
508 ad7ee8a2 Claudio Fontana
{
509 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
510 ad7ee8a2 Claudio Fontana
}
511 ad7ee8a2 Claudio Fontana
512 b001c8c3 Alexander Graf
/* C3.2.7 Unconditional branch (register)
513 b001c8c3 Alexander Graf
 *  31           25 24   21 20   16 15   10 9    5 4     0
514 b001c8c3 Alexander Graf
 * +---------------+-------+-------+-------+------+-------+
515 b001c8c3 Alexander Graf
 * | 1 1 0 1 0 1 1 |  opc  |  op2  |  op3  |  Rn  |  op4  |
516 b001c8c3 Alexander Graf
 * +---------------+-------+-------+-------+------+-------+
517 b001c8c3 Alexander Graf
 */
518 ad7ee8a2 Claudio Fontana
static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
519 ad7ee8a2 Claudio Fontana
{
520 b001c8c3 Alexander Graf
    unsigned int opc, op2, op3, rn, op4;
521 b001c8c3 Alexander Graf
522 b001c8c3 Alexander Graf
    opc = extract32(insn, 21, 4);
523 b001c8c3 Alexander Graf
    op2 = extract32(insn, 16, 5);
524 b001c8c3 Alexander Graf
    op3 = extract32(insn, 10, 6);
525 b001c8c3 Alexander Graf
    rn = extract32(insn, 5, 5);
526 b001c8c3 Alexander Graf
    op4 = extract32(insn, 0, 5);
527 b001c8c3 Alexander Graf
528 b001c8c3 Alexander Graf
    if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
529 b001c8c3 Alexander Graf
        unallocated_encoding(s);
530 b001c8c3 Alexander Graf
        return;
531 b001c8c3 Alexander Graf
    }
532 b001c8c3 Alexander Graf
533 b001c8c3 Alexander Graf
    switch (opc) {
534 b001c8c3 Alexander Graf
    case 0: /* BR */
535 b001c8c3 Alexander Graf
    case 2: /* RET */
536 b001c8c3 Alexander Graf
        break;
537 b001c8c3 Alexander Graf
    case 1: /* BLR */
538 b001c8c3 Alexander Graf
        tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
539 b001c8c3 Alexander Graf
        break;
540 b001c8c3 Alexander Graf
    case 4: /* ERET */
541 b001c8c3 Alexander Graf
    case 5: /* DRPS */
542 b001c8c3 Alexander Graf
        if (rn != 0x1f) {
543 b001c8c3 Alexander Graf
            unallocated_encoding(s);
544 b001c8c3 Alexander Graf
        } else {
545 b001c8c3 Alexander Graf
            unsupported_encoding(s, insn);
546 b001c8c3 Alexander Graf
        }
547 b001c8c3 Alexander Graf
        return;
548 b001c8c3 Alexander Graf
    default:
549 b001c8c3 Alexander Graf
        unallocated_encoding(s);
550 b001c8c3 Alexander Graf
        return;
551 b001c8c3 Alexander Graf
    }
552 b001c8c3 Alexander Graf
553 b001c8c3 Alexander Graf
    tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
554 b001c8c3 Alexander Graf
    s->is_jmp = DISAS_JUMP;
555 ad7ee8a2 Claudio Fontana
}
556 ad7ee8a2 Claudio Fontana
557 ad7ee8a2 Claudio Fontana
/* C3.2 Branches, exception generating and system instructions */
558 ad7ee8a2 Claudio Fontana
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
559 ad7ee8a2 Claudio Fontana
{
560 ad7ee8a2 Claudio Fontana
    switch (extract32(insn, 25, 7)) {
561 ad7ee8a2 Claudio Fontana
    case 0x0a: case 0x0b:
562 ad7ee8a2 Claudio Fontana
    case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
563 ad7ee8a2 Claudio Fontana
        disas_uncond_b_imm(s, insn);
564 ad7ee8a2 Claudio Fontana
        break;
565 ad7ee8a2 Claudio Fontana
    case 0x1a: case 0x5a: /* Compare & branch (immediate) */
566 ad7ee8a2 Claudio Fontana
        disas_comp_b_imm(s, insn);
567 ad7ee8a2 Claudio Fontana
        break;
568 ad7ee8a2 Claudio Fontana
    case 0x1b: case 0x5b: /* Test & branch (immediate) */
569 ad7ee8a2 Claudio Fontana
        disas_test_b_imm(s, insn);
570 ad7ee8a2 Claudio Fontana
        break;
571 ad7ee8a2 Claudio Fontana
    case 0x2a: /* Conditional branch (immediate) */
572 ad7ee8a2 Claudio Fontana
        disas_cond_b_imm(s, insn);
573 ad7ee8a2 Claudio Fontana
        break;
574 ad7ee8a2 Claudio Fontana
    case 0x6a: /* Exception generation / System */
575 ad7ee8a2 Claudio Fontana
        if (insn & (1 << 24)) {
576 ad7ee8a2 Claudio Fontana
            disas_system(s, insn);
577 ad7ee8a2 Claudio Fontana
        } else {
578 ad7ee8a2 Claudio Fontana
            disas_exc(s, insn);
579 ad7ee8a2 Claudio Fontana
        }
580 ad7ee8a2 Claudio Fontana
        break;
581 ad7ee8a2 Claudio Fontana
    case 0x6b: /* Unconditional branch (register) */
582 ad7ee8a2 Claudio Fontana
        disas_uncond_b_reg(s, insn);
583 ad7ee8a2 Claudio Fontana
        break;
584 ad7ee8a2 Claudio Fontana
    default:
585 ad7ee8a2 Claudio Fontana
        unallocated_encoding(s);
586 ad7ee8a2 Claudio Fontana
        break;
587 ad7ee8a2 Claudio Fontana
    }
588 ad7ee8a2 Claudio Fontana
}
589 ad7ee8a2 Claudio Fontana
590 ad7ee8a2 Claudio Fontana
/* Load/store exclusive */
591 ad7ee8a2 Claudio Fontana
static void disas_ldst_excl(DisasContext *s, uint32_t insn)
592 ad7ee8a2 Claudio Fontana
{
593 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
594 ad7ee8a2 Claudio Fontana
}
595 ad7ee8a2 Claudio Fontana
596 ad7ee8a2 Claudio Fontana
/* Load register (literal) */
597 ad7ee8a2 Claudio Fontana
static void disas_ld_lit(DisasContext *s, uint32_t insn)
598 ad7ee8a2 Claudio Fontana
{
599 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
600 ad7ee8a2 Claudio Fontana
}
601 ad7ee8a2 Claudio Fontana
602 ad7ee8a2 Claudio Fontana
/* Load/store pair (all forms) */
603 ad7ee8a2 Claudio Fontana
static void disas_ldst_pair(DisasContext *s, uint32_t insn)
604 ad7ee8a2 Claudio Fontana
{
605 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
606 ad7ee8a2 Claudio Fontana
}
607 ad7ee8a2 Claudio Fontana
608 ad7ee8a2 Claudio Fontana
/* Load/store register (all forms) */
609 ad7ee8a2 Claudio Fontana
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
610 ad7ee8a2 Claudio Fontana
{
611 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
612 ad7ee8a2 Claudio Fontana
}
613 ad7ee8a2 Claudio Fontana
614 ad7ee8a2 Claudio Fontana
/* AdvSIMD load/store multiple structures */
615 ad7ee8a2 Claudio Fontana
static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
616 ad7ee8a2 Claudio Fontana
{
617 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
618 ad7ee8a2 Claudio Fontana
}
619 ad7ee8a2 Claudio Fontana
620 ad7ee8a2 Claudio Fontana
/* AdvSIMD load/store single structure */
621 ad7ee8a2 Claudio Fontana
static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
622 ad7ee8a2 Claudio Fontana
{
623 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
624 ad7ee8a2 Claudio Fontana
}
625 ad7ee8a2 Claudio Fontana
626 ad7ee8a2 Claudio Fontana
/* C3.3 Loads and stores */
627 ad7ee8a2 Claudio Fontana
static void disas_ldst(DisasContext *s, uint32_t insn)
628 ad7ee8a2 Claudio Fontana
{
629 ad7ee8a2 Claudio Fontana
    switch (extract32(insn, 24, 6)) {
630 ad7ee8a2 Claudio Fontana
    case 0x08: /* Load/store exclusive */
631 ad7ee8a2 Claudio Fontana
        disas_ldst_excl(s, insn);
632 ad7ee8a2 Claudio Fontana
        break;
633 ad7ee8a2 Claudio Fontana
    case 0x18: case 0x1c: /* Load register (literal) */
634 ad7ee8a2 Claudio Fontana
        disas_ld_lit(s, insn);
635 ad7ee8a2 Claudio Fontana
        break;
636 ad7ee8a2 Claudio Fontana
    case 0x28: case 0x29:
637 ad7ee8a2 Claudio Fontana
    case 0x2c: case 0x2d: /* Load/store pair (all forms) */
638 ad7ee8a2 Claudio Fontana
        disas_ldst_pair(s, insn);
639 ad7ee8a2 Claudio Fontana
        break;
640 ad7ee8a2 Claudio Fontana
    case 0x38: case 0x39:
641 ad7ee8a2 Claudio Fontana
    case 0x3c: case 0x3d: /* Load/store register (all forms) */
642 ad7ee8a2 Claudio Fontana
        disas_ldst_reg(s, insn);
643 ad7ee8a2 Claudio Fontana
        break;
644 ad7ee8a2 Claudio Fontana
    case 0x0c: /* AdvSIMD load/store multiple structures */
645 ad7ee8a2 Claudio Fontana
        disas_ldst_multiple_struct(s, insn);
646 ad7ee8a2 Claudio Fontana
        break;
647 ad7ee8a2 Claudio Fontana
    case 0x0d: /* AdvSIMD load/store single structure */
648 ad7ee8a2 Claudio Fontana
        disas_ldst_single_struct(s, insn);
649 ad7ee8a2 Claudio Fontana
        break;
650 ad7ee8a2 Claudio Fontana
    default:
651 ad7ee8a2 Claudio Fontana
        unallocated_encoding(s);
652 ad7ee8a2 Claudio Fontana
        break;
653 ad7ee8a2 Claudio Fontana
    }
654 ad7ee8a2 Claudio Fontana
}
655 ad7ee8a2 Claudio Fontana
656 15bfe8b6 Alexander Graf
/* C3.4.6 PC-rel. addressing
657 15bfe8b6 Alexander Graf
 *   31  30   29 28       24 23                5 4    0
658 15bfe8b6 Alexander Graf
 * +----+-------+-----------+-------------------+------+
659 15bfe8b6 Alexander Graf
 * | op | immlo | 1 0 0 0 0 |       immhi       |  Rd  |
660 15bfe8b6 Alexander Graf
 * +----+-------+-----------+-------------------+------+
661 15bfe8b6 Alexander Graf
 */
662 ad7ee8a2 Claudio Fontana
static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
663 ad7ee8a2 Claudio Fontana
{
664 15bfe8b6 Alexander Graf
    unsigned int page, rd;
665 15bfe8b6 Alexander Graf
    uint64_t base;
666 15bfe8b6 Alexander Graf
    int64_t offset;
667 15bfe8b6 Alexander Graf
668 15bfe8b6 Alexander Graf
    page = extract32(insn, 31, 1);
669 15bfe8b6 Alexander Graf
    /* SignExtend(immhi:immlo) -> offset */
670 15bfe8b6 Alexander Graf
    offset = ((int64_t)sextract32(insn, 5, 19) << 2) | extract32(insn, 29, 2);
671 15bfe8b6 Alexander Graf
    rd = extract32(insn, 0, 5);
672 15bfe8b6 Alexander Graf
    base = s->pc - 4;
673 15bfe8b6 Alexander Graf
674 15bfe8b6 Alexander Graf
    if (page) {
675 15bfe8b6 Alexander Graf
        /* ADRP (page based) */
676 15bfe8b6 Alexander Graf
        base &= ~0xfff;
677 15bfe8b6 Alexander Graf
        offset <<= 12;
678 15bfe8b6 Alexander Graf
    }
679 15bfe8b6 Alexander Graf
680 15bfe8b6 Alexander Graf
    tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
681 ad7ee8a2 Claudio Fontana
}
682 ad7ee8a2 Claudio Fontana
683 ad7ee8a2 Claudio Fontana
/* Add/subtract (immediate) */
684 ad7ee8a2 Claudio Fontana
static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
685 ad7ee8a2 Claudio Fontana
{
686 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
687 ad7ee8a2 Claudio Fontana
}
688 ad7ee8a2 Claudio Fontana
689 ad7ee8a2 Claudio Fontana
/* Logical (immediate) */
690 ad7ee8a2 Claudio Fontana
static void disas_logic_imm(DisasContext *s, uint32_t insn)
691 ad7ee8a2 Claudio Fontana
{
692 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
693 ad7ee8a2 Claudio Fontana
}
694 ad7ee8a2 Claudio Fontana
695 ad7ee8a2 Claudio Fontana
/* Move wide (immediate) */
696 ad7ee8a2 Claudio Fontana
static void disas_movw_imm(DisasContext *s, uint32_t insn)
697 ad7ee8a2 Claudio Fontana
{
698 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
699 ad7ee8a2 Claudio Fontana
}
700 ad7ee8a2 Claudio Fontana
701 ad7ee8a2 Claudio Fontana
/* Bitfield */
702 ad7ee8a2 Claudio Fontana
static void disas_bitfield(DisasContext *s, uint32_t insn)
703 ad7ee8a2 Claudio Fontana
{
704 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
705 ad7ee8a2 Claudio Fontana
}
706 ad7ee8a2 Claudio Fontana
707 e801de93 Alexander Graf
/* C3.4.3 Extract
708 e801de93 Alexander Graf
 *   31  30  29 28         23 22   21  20  16 15    10 9    5 4    0
709 e801de93 Alexander Graf
 * +----+------+-------------+---+----+------+--------+------+------+
710 e801de93 Alexander Graf
 * | sf | op21 | 1 0 0 1 1 1 | N | o0 |  Rm  |  imms  |  Rn  |  Rd  |
711 e801de93 Alexander Graf
 * +----+------+-------------+---+----+------+--------+------+------+
712 e801de93 Alexander Graf
 */
713 ad7ee8a2 Claudio Fontana
static void disas_extract(DisasContext *s, uint32_t insn)
714 ad7ee8a2 Claudio Fontana
{
715 e801de93 Alexander Graf
    unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
716 e801de93 Alexander Graf
717 e801de93 Alexander Graf
    sf = extract32(insn, 31, 1);
718 e801de93 Alexander Graf
    n = extract32(insn, 22, 1);
719 e801de93 Alexander Graf
    rm = extract32(insn, 16, 5);
720 e801de93 Alexander Graf
    imm = extract32(insn, 10, 6);
721 e801de93 Alexander Graf
    rn = extract32(insn, 5, 5);
722 e801de93 Alexander Graf
    rd = extract32(insn, 0, 5);
723 e801de93 Alexander Graf
    op21 = extract32(insn, 29, 2);
724 e801de93 Alexander Graf
    op0 = extract32(insn, 21, 1);
725 e801de93 Alexander Graf
    bitsize = sf ? 64 : 32;
726 e801de93 Alexander Graf
727 e801de93 Alexander Graf
    if (sf != n || op21 || op0 || imm >= bitsize) {
728 e801de93 Alexander Graf
        unallocated_encoding(s);
729 e801de93 Alexander Graf
    } else {
730 e801de93 Alexander Graf
        TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
731 e801de93 Alexander Graf
732 e801de93 Alexander Graf
        tcg_rd = cpu_reg(s, rd);
733 e801de93 Alexander Graf
734 e801de93 Alexander Graf
        if (imm) {
735 e801de93 Alexander Graf
            /* OPTME: we can special case rm==rn as a rotate */
736 e801de93 Alexander Graf
            tcg_rm = read_cpu_reg(s, rm, sf);
737 e801de93 Alexander Graf
            tcg_rn = read_cpu_reg(s, rn, sf);
738 e801de93 Alexander Graf
            tcg_gen_shri_i64(tcg_rm, tcg_rm, imm);
739 e801de93 Alexander Graf
            tcg_gen_shli_i64(tcg_rn, tcg_rn, bitsize - imm);
740 e801de93 Alexander Graf
            tcg_gen_or_i64(tcg_rd, tcg_rm, tcg_rn);
741 e801de93 Alexander Graf
            if (!sf) {
742 e801de93 Alexander Graf
                tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
743 e801de93 Alexander Graf
            }
744 e801de93 Alexander Graf
        } else {
745 e801de93 Alexander Graf
            /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
746 e801de93 Alexander Graf
             * so an extract from bit 0 is a special case.
747 e801de93 Alexander Graf
             */
748 e801de93 Alexander Graf
            if (sf) {
749 e801de93 Alexander Graf
                tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
750 e801de93 Alexander Graf
            } else {
751 e801de93 Alexander Graf
                tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
752 e801de93 Alexander Graf
            }
753 e801de93 Alexander Graf
        }
754 e801de93 Alexander Graf
755 e801de93 Alexander Graf
    }
756 ad7ee8a2 Claudio Fontana
}
757 ad7ee8a2 Claudio Fontana
758 ad7ee8a2 Claudio Fontana
/* C3.4 Data processing - immediate */
759 ad7ee8a2 Claudio Fontana
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
760 ad7ee8a2 Claudio Fontana
{
761 ad7ee8a2 Claudio Fontana
    switch (extract32(insn, 23, 6)) {
762 ad7ee8a2 Claudio Fontana
    case 0x20: case 0x21: /* PC-rel. addressing */
763 ad7ee8a2 Claudio Fontana
        disas_pc_rel_adr(s, insn);
764 ad7ee8a2 Claudio Fontana
        break;
765 ad7ee8a2 Claudio Fontana
    case 0x22: case 0x23: /* Add/subtract (immediate) */
766 ad7ee8a2 Claudio Fontana
        disas_add_sub_imm(s, insn);
767 ad7ee8a2 Claudio Fontana
        break;
768 ad7ee8a2 Claudio Fontana
    case 0x24: /* Logical (immediate) */
769 ad7ee8a2 Claudio Fontana
        disas_logic_imm(s, insn);
770 ad7ee8a2 Claudio Fontana
        break;
771 ad7ee8a2 Claudio Fontana
    case 0x25: /* Move wide (immediate) */
772 ad7ee8a2 Claudio Fontana
        disas_movw_imm(s, insn);
773 ad7ee8a2 Claudio Fontana
        break;
774 ad7ee8a2 Claudio Fontana
    case 0x26: /* Bitfield */
775 ad7ee8a2 Claudio Fontana
        disas_bitfield(s, insn);
776 ad7ee8a2 Claudio Fontana
        break;
777 ad7ee8a2 Claudio Fontana
    case 0x27: /* Extract */
778 ad7ee8a2 Claudio Fontana
        disas_extract(s, insn);
779 ad7ee8a2 Claudio Fontana
        break;
780 ad7ee8a2 Claudio Fontana
    default:
781 ad7ee8a2 Claudio Fontana
        unallocated_encoding(s);
782 ad7ee8a2 Claudio Fontana
        break;
783 ad7ee8a2 Claudio Fontana
    }
784 ad7ee8a2 Claudio Fontana
}
785 ad7ee8a2 Claudio Fontana
786 832ffa1c Alexander Graf
/* Shift a TCGv src by TCGv shift_amount, put result in dst.
787 832ffa1c Alexander Graf
 * Note that it is the caller's responsibility to ensure that the
788 832ffa1c Alexander Graf
 * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
789 832ffa1c Alexander Graf
 * mandated semantics for out of range shifts.
790 832ffa1c Alexander Graf
 */
791 832ffa1c Alexander Graf
static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
792 832ffa1c Alexander Graf
                      enum a64_shift_type shift_type, TCGv_i64 shift_amount)
793 832ffa1c Alexander Graf
{
794 832ffa1c Alexander Graf
    switch (shift_type) {
795 832ffa1c Alexander Graf
    case A64_SHIFT_TYPE_LSL:
796 832ffa1c Alexander Graf
        tcg_gen_shl_i64(dst, src, shift_amount);
797 832ffa1c Alexander Graf
        break;
798 832ffa1c Alexander Graf
    case A64_SHIFT_TYPE_LSR:
799 832ffa1c Alexander Graf
        tcg_gen_shr_i64(dst, src, shift_amount);
800 832ffa1c Alexander Graf
        break;
801 832ffa1c Alexander Graf
    case A64_SHIFT_TYPE_ASR:
802 832ffa1c Alexander Graf
        if (!sf) {
803 832ffa1c Alexander Graf
            tcg_gen_ext32s_i64(dst, src);
804 832ffa1c Alexander Graf
        }
805 832ffa1c Alexander Graf
        tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
806 832ffa1c Alexander Graf
        break;
807 832ffa1c Alexander Graf
    case A64_SHIFT_TYPE_ROR:
808 832ffa1c Alexander Graf
        if (sf) {
809 832ffa1c Alexander Graf
            tcg_gen_rotr_i64(dst, src, shift_amount);
810 832ffa1c Alexander Graf
        } else {
811 832ffa1c Alexander Graf
            TCGv_i32 t0, t1;
812 832ffa1c Alexander Graf
            t0 = tcg_temp_new_i32();
813 832ffa1c Alexander Graf
            t1 = tcg_temp_new_i32();
814 832ffa1c Alexander Graf
            tcg_gen_trunc_i64_i32(t0, src);
815 832ffa1c Alexander Graf
            tcg_gen_trunc_i64_i32(t1, shift_amount);
816 832ffa1c Alexander Graf
            tcg_gen_rotr_i32(t0, t0, t1);
817 832ffa1c Alexander Graf
            tcg_gen_extu_i32_i64(dst, t0);
818 832ffa1c Alexander Graf
            tcg_temp_free_i32(t0);
819 832ffa1c Alexander Graf
            tcg_temp_free_i32(t1);
820 832ffa1c Alexander Graf
        }
821 832ffa1c Alexander Graf
        break;
822 832ffa1c Alexander Graf
    default:
823 832ffa1c Alexander Graf
        assert(FALSE); /* all shift types should be handled */
824 832ffa1c Alexander Graf
        break;
825 832ffa1c Alexander Graf
    }
826 832ffa1c Alexander Graf
827 832ffa1c Alexander Graf
    if (!sf) { /* zero extend final result */
828 832ffa1c Alexander Graf
        tcg_gen_ext32u_i64(dst, dst);
829 832ffa1c Alexander Graf
    }
830 832ffa1c Alexander Graf
}
831 832ffa1c Alexander Graf
832 832ffa1c Alexander Graf
/* Shift a TCGv src by immediate, put result in dst.
833 832ffa1c Alexander Graf
 * The shift amount must be in range (this should always be true as the
834 832ffa1c Alexander Graf
 * relevant instructions will UNDEF on bad shift immediates).
835 832ffa1c Alexander Graf
 */
836 832ffa1c Alexander Graf
static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
837 832ffa1c Alexander Graf
                          enum a64_shift_type shift_type, unsigned int shift_i)
838 832ffa1c Alexander Graf
{
839 832ffa1c Alexander Graf
    assert(shift_i < (sf ? 64 : 32));
840 832ffa1c Alexander Graf
841 832ffa1c Alexander Graf
    if (shift_i == 0) {
842 832ffa1c Alexander Graf
        tcg_gen_mov_i64(dst, src);
843 832ffa1c Alexander Graf
    } else {
844 832ffa1c Alexander Graf
        TCGv_i64 shift_const;
845 832ffa1c Alexander Graf
846 832ffa1c Alexander Graf
        shift_const = tcg_const_i64(shift_i);
847 832ffa1c Alexander Graf
        shift_reg(dst, src, sf, shift_type, shift_const);
848 832ffa1c Alexander Graf
        tcg_temp_free_i64(shift_const);
849 832ffa1c Alexander Graf
    }
850 832ffa1c Alexander Graf
}
851 832ffa1c Alexander Graf
852 832ffa1c Alexander Graf
/* C3.5.10 Logical (shifted register)
853 832ffa1c Alexander Graf
 *   31  30 29 28       24 23   22 21  20  16 15    10 9    5 4    0
854 832ffa1c Alexander Graf
 * +----+-----+-----------+-------+---+------+--------+------+------+
855 832ffa1c Alexander Graf
 * | sf | opc | 0 1 0 1 0 | shift | N |  Rm  |  imm6  |  Rn  |  Rd  |
856 832ffa1c Alexander Graf
 * +----+-----+-----------+-------+---+------+--------+------+------+
857 832ffa1c Alexander Graf
 */
858 ad7ee8a2 Claudio Fontana
static void disas_logic_reg(DisasContext *s, uint32_t insn)
859 ad7ee8a2 Claudio Fontana
{
860 832ffa1c Alexander Graf
    TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
861 832ffa1c Alexander Graf
    unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
862 832ffa1c Alexander Graf
863 832ffa1c Alexander Graf
    sf = extract32(insn, 31, 1);
864 832ffa1c Alexander Graf
    opc = extract32(insn, 29, 2);
865 832ffa1c Alexander Graf
    shift_type = extract32(insn, 22, 2);
866 832ffa1c Alexander Graf
    invert = extract32(insn, 21, 1);
867 832ffa1c Alexander Graf
    rm = extract32(insn, 16, 5);
868 832ffa1c Alexander Graf
    shift_amount = extract32(insn, 10, 6);
869 832ffa1c Alexander Graf
    rn = extract32(insn, 5, 5);
870 832ffa1c Alexander Graf
    rd = extract32(insn, 0, 5);
871 832ffa1c Alexander Graf
872 832ffa1c Alexander Graf
    if (!sf && (shift_amount & (1 << 5))) {
873 832ffa1c Alexander Graf
        unallocated_encoding(s);
874 832ffa1c Alexander Graf
        return;
875 832ffa1c Alexander Graf
    }
876 832ffa1c Alexander Graf
877 832ffa1c Alexander Graf
    tcg_rd = cpu_reg(s, rd);
878 832ffa1c Alexander Graf
879 832ffa1c Alexander Graf
    if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
880 832ffa1c Alexander Graf
        /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
881 832ffa1c Alexander Graf
         * register-register MOV and MVN, so it is worth special casing.
882 832ffa1c Alexander Graf
         */
883 832ffa1c Alexander Graf
        tcg_rm = cpu_reg(s, rm);
884 832ffa1c Alexander Graf
        if (invert) {
885 832ffa1c Alexander Graf
            tcg_gen_not_i64(tcg_rd, tcg_rm);
886 832ffa1c Alexander Graf
            if (!sf) {
887 832ffa1c Alexander Graf
                tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
888 832ffa1c Alexander Graf
            }
889 832ffa1c Alexander Graf
        } else {
890 832ffa1c Alexander Graf
            if (sf) {
891 832ffa1c Alexander Graf
                tcg_gen_mov_i64(tcg_rd, tcg_rm);
892 832ffa1c Alexander Graf
            } else {
893 832ffa1c Alexander Graf
                tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
894 832ffa1c Alexander Graf
            }
895 832ffa1c Alexander Graf
        }
896 832ffa1c Alexander Graf
        return;
897 832ffa1c Alexander Graf
    }
898 832ffa1c Alexander Graf
899 832ffa1c Alexander Graf
    tcg_rm = read_cpu_reg(s, rm, sf);
900 832ffa1c Alexander Graf
901 832ffa1c Alexander Graf
    if (shift_amount) {
902 832ffa1c Alexander Graf
        shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
903 832ffa1c Alexander Graf
    }
904 832ffa1c Alexander Graf
905 832ffa1c Alexander Graf
    tcg_rn = cpu_reg(s, rn);
906 832ffa1c Alexander Graf
907 832ffa1c Alexander Graf
    switch (opc | (invert << 2)) {
908 832ffa1c Alexander Graf
    case 0: /* AND */
909 832ffa1c Alexander Graf
    case 3: /* ANDS */
910 832ffa1c Alexander Graf
        tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
911 832ffa1c Alexander Graf
        break;
912 832ffa1c Alexander Graf
    case 1: /* ORR */
913 832ffa1c Alexander Graf
        tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
914 832ffa1c Alexander Graf
        break;
915 832ffa1c Alexander Graf
    case 2: /* EOR */
916 832ffa1c Alexander Graf
        tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
917 832ffa1c Alexander Graf
        break;
918 832ffa1c Alexander Graf
    case 4: /* BIC */
919 832ffa1c Alexander Graf
    case 7: /* BICS */
920 832ffa1c Alexander Graf
        tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
921 832ffa1c Alexander Graf
        break;
922 832ffa1c Alexander Graf
    case 5: /* ORN */
923 832ffa1c Alexander Graf
        tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
924 832ffa1c Alexander Graf
        break;
925 832ffa1c Alexander Graf
    case 6: /* EON */
926 832ffa1c Alexander Graf
        tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
927 832ffa1c Alexander Graf
        break;
928 832ffa1c Alexander Graf
    default:
929 832ffa1c Alexander Graf
        assert(FALSE);
930 832ffa1c Alexander Graf
        break;
931 832ffa1c Alexander Graf
    }
932 832ffa1c Alexander Graf
933 832ffa1c Alexander Graf
    if (!sf) {
934 832ffa1c Alexander Graf
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
935 832ffa1c Alexander Graf
    }
936 832ffa1c Alexander Graf
937 832ffa1c Alexander Graf
    if (opc == 3) {
938 832ffa1c Alexander Graf
        gen_logic_CC(sf, tcg_rd);
939 832ffa1c Alexander Graf
    }
940 ad7ee8a2 Claudio Fontana
}
941 ad7ee8a2 Claudio Fontana
942 ad7ee8a2 Claudio Fontana
/* Add/subtract (extended register) */
943 ad7ee8a2 Claudio Fontana
static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
944 ad7ee8a2 Claudio Fontana
{
945 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
946 ad7ee8a2 Claudio Fontana
}
947 ad7ee8a2 Claudio Fontana
948 ad7ee8a2 Claudio Fontana
/* Add/subtract (shifted register) */
949 ad7ee8a2 Claudio Fontana
static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
950 ad7ee8a2 Claudio Fontana
{
951 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
952 ad7ee8a2 Claudio Fontana
}
953 ad7ee8a2 Claudio Fontana
954 ad7ee8a2 Claudio Fontana
/* Data-processing (3 source) */
955 ad7ee8a2 Claudio Fontana
static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
956 ad7ee8a2 Claudio Fontana
{
957 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
958 ad7ee8a2 Claudio Fontana
}
959 ad7ee8a2 Claudio Fontana
960 ad7ee8a2 Claudio Fontana
/* Add/subtract (with carry) */
961 ad7ee8a2 Claudio Fontana
static void disas_adc_sbc(DisasContext *s, uint32_t insn)
962 ad7ee8a2 Claudio Fontana
{
963 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
964 ad7ee8a2 Claudio Fontana
}
965 ad7ee8a2 Claudio Fontana
966 ad7ee8a2 Claudio Fontana
/* Conditional compare (immediate) */
967 ad7ee8a2 Claudio Fontana
static void disas_cc_imm(DisasContext *s, uint32_t insn)
968 ad7ee8a2 Claudio Fontana
{
969 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
970 ad7ee8a2 Claudio Fontana
}
971 ad7ee8a2 Claudio Fontana
972 ad7ee8a2 Claudio Fontana
/* Conditional compare (register) */
973 ad7ee8a2 Claudio Fontana
static void disas_cc_reg(DisasContext *s, uint32_t insn)
974 ad7ee8a2 Claudio Fontana
{
975 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
976 ad7ee8a2 Claudio Fontana
}
977 ad7ee8a2 Claudio Fontana
978 e952d8c7 Claudio Fontana
/* C3.5.6 Conditional select
979 e952d8c7 Claudio Fontana
 *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
980 e952d8c7 Claudio Fontana
 * +----+----+---+-----------------+------+------+-----+------+------+
981 e952d8c7 Claudio Fontana
 * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
982 e952d8c7 Claudio Fontana
 * +----+----+---+-----------------+------+------+-----+------+------+
983 e952d8c7 Claudio Fontana
 */
984 ad7ee8a2 Claudio Fontana
static void disas_cond_select(DisasContext *s, uint32_t insn)
985 ad7ee8a2 Claudio Fontana
{
986 e952d8c7 Claudio Fontana
    unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
987 e952d8c7 Claudio Fontana
    TCGv_i64 tcg_rd, tcg_src;
988 e952d8c7 Claudio Fontana
989 e952d8c7 Claudio Fontana
    if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
990 e952d8c7 Claudio Fontana
        /* S == 1 or op2<1> == 1 */
991 e952d8c7 Claudio Fontana
        unallocated_encoding(s);
992 e952d8c7 Claudio Fontana
        return;
993 e952d8c7 Claudio Fontana
    }
994 e952d8c7 Claudio Fontana
    sf = extract32(insn, 31, 1);
995 e952d8c7 Claudio Fontana
    else_inv = extract32(insn, 30, 1);
996 e952d8c7 Claudio Fontana
    rm = extract32(insn, 16, 5);
997 e952d8c7 Claudio Fontana
    cond = extract32(insn, 12, 4);
998 e952d8c7 Claudio Fontana
    else_inc = extract32(insn, 10, 1);
999 e952d8c7 Claudio Fontana
    rn = extract32(insn, 5, 5);
1000 e952d8c7 Claudio Fontana
    rd = extract32(insn, 0, 5);
1001 e952d8c7 Claudio Fontana
1002 e952d8c7 Claudio Fontana
    if (rd == 31) {
1003 e952d8c7 Claudio Fontana
        /* silly no-op write; until we use movcond we must special-case
1004 e952d8c7 Claudio Fontana
         * this to avoid a dead temporary across basic blocks.
1005 e952d8c7 Claudio Fontana
         */
1006 e952d8c7 Claudio Fontana
        return;
1007 e952d8c7 Claudio Fontana
    }
1008 e952d8c7 Claudio Fontana
1009 e952d8c7 Claudio Fontana
    tcg_rd = cpu_reg(s, rd);
1010 e952d8c7 Claudio Fontana
1011 e952d8c7 Claudio Fontana
    if (cond >= 0x0e) { /* condition "always" */
1012 e952d8c7 Claudio Fontana
        tcg_src = read_cpu_reg(s, rn, sf);
1013 e952d8c7 Claudio Fontana
        tcg_gen_mov_i64(tcg_rd, tcg_src);
1014 e952d8c7 Claudio Fontana
    } else {
1015 e952d8c7 Claudio Fontana
        /* OPTME: we could use movcond here, at the cost of duplicating
1016 e952d8c7 Claudio Fontana
         * a lot of the arm_gen_test_cc() logic.
1017 e952d8c7 Claudio Fontana
         */
1018 e952d8c7 Claudio Fontana
        int label_match = gen_new_label();
1019 e952d8c7 Claudio Fontana
        int label_continue = gen_new_label();
1020 e952d8c7 Claudio Fontana
1021 e952d8c7 Claudio Fontana
        arm_gen_test_cc(cond, label_match);
1022 e952d8c7 Claudio Fontana
        /* nomatch: */
1023 e952d8c7 Claudio Fontana
        tcg_src = cpu_reg(s, rm);
1024 e952d8c7 Claudio Fontana
1025 e952d8c7 Claudio Fontana
        if (else_inv && else_inc) {
1026 e952d8c7 Claudio Fontana
            tcg_gen_neg_i64(tcg_rd, tcg_src);
1027 e952d8c7 Claudio Fontana
        } else if (else_inv) {
1028 e952d8c7 Claudio Fontana
            tcg_gen_not_i64(tcg_rd, tcg_src);
1029 e952d8c7 Claudio Fontana
        } else if (else_inc) {
1030 e952d8c7 Claudio Fontana
            tcg_gen_addi_i64(tcg_rd, tcg_src, 1);
1031 e952d8c7 Claudio Fontana
        } else {
1032 e952d8c7 Claudio Fontana
            tcg_gen_mov_i64(tcg_rd, tcg_src);
1033 e952d8c7 Claudio Fontana
        }
1034 e952d8c7 Claudio Fontana
        if (!sf) {
1035 e952d8c7 Claudio Fontana
            tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1036 e952d8c7 Claudio Fontana
        }
1037 e952d8c7 Claudio Fontana
        tcg_gen_br(label_continue);
1038 e952d8c7 Claudio Fontana
        /* match: */
1039 e952d8c7 Claudio Fontana
        gen_set_label(label_match);
1040 e952d8c7 Claudio Fontana
        tcg_src = read_cpu_reg(s, rn, sf);
1041 e952d8c7 Claudio Fontana
        tcg_gen_mov_i64(tcg_rd, tcg_src);
1042 e952d8c7 Claudio Fontana
        /* continue: */
1043 e952d8c7 Claudio Fontana
        gen_set_label(label_continue);
1044 e952d8c7 Claudio Fontana
    }
1045 ad7ee8a2 Claudio Fontana
}
1046 ad7ee8a2 Claudio Fontana
1047 680ead21 Claudio Fontana
static void handle_clz(DisasContext *s, unsigned int sf,
1048 680ead21 Claudio Fontana
                       unsigned int rn, unsigned int rd)
1049 680ead21 Claudio Fontana
{
1050 680ead21 Claudio Fontana
    TCGv_i64 tcg_rd, tcg_rn;
1051 680ead21 Claudio Fontana
    tcg_rd = cpu_reg(s, rd);
1052 680ead21 Claudio Fontana
    tcg_rn = cpu_reg(s, rn);
1053 680ead21 Claudio Fontana
1054 680ead21 Claudio Fontana
    if (sf) {
1055 680ead21 Claudio Fontana
        gen_helper_clz64(tcg_rd, tcg_rn);
1056 680ead21 Claudio Fontana
    } else {
1057 680ead21 Claudio Fontana
        TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
1058 680ead21 Claudio Fontana
        tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
1059 680ead21 Claudio Fontana
        gen_helper_clz(tcg_tmp32, tcg_tmp32);
1060 680ead21 Claudio Fontana
        tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
1061 680ead21 Claudio Fontana
        tcg_temp_free_i32(tcg_tmp32);
1062 680ead21 Claudio Fontana
    }
1063 680ead21 Claudio Fontana
}
1064 680ead21 Claudio Fontana
1065 82e14b02 Alexander Graf
static void handle_rbit(DisasContext *s, unsigned int sf,
1066 82e14b02 Alexander Graf
                        unsigned int rn, unsigned int rd)
1067 82e14b02 Alexander Graf
{
1068 82e14b02 Alexander Graf
    TCGv_i64 tcg_rd, tcg_rn;
1069 82e14b02 Alexander Graf
    tcg_rd = cpu_reg(s, rd);
1070 82e14b02 Alexander Graf
    tcg_rn = cpu_reg(s, rn);
1071 82e14b02 Alexander Graf
1072 82e14b02 Alexander Graf
    if (sf) {
1073 82e14b02 Alexander Graf
        gen_helper_rbit64(tcg_rd, tcg_rn);
1074 82e14b02 Alexander Graf
    } else {
1075 82e14b02 Alexander Graf
        TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
1076 82e14b02 Alexander Graf
        tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
1077 82e14b02 Alexander Graf
        gen_helper_rbit(tcg_tmp32, tcg_tmp32);
1078 82e14b02 Alexander Graf
        tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
1079 82e14b02 Alexander Graf
        tcg_temp_free_i32(tcg_tmp32);
1080 82e14b02 Alexander Graf
    }
1081 82e14b02 Alexander Graf
}
1082 82e14b02 Alexander Graf
1083 680ead21 Claudio Fontana
/* C3.5.7 Data-processing (1 source)
1084 680ead21 Claudio Fontana
 *   31  30  29  28             21 20     16 15    10 9    5 4    0
1085 680ead21 Claudio Fontana
 * +----+---+---+-----------------+---------+--------+------+------+
1086 680ead21 Claudio Fontana
 * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
1087 680ead21 Claudio Fontana
 * +----+---+---+-----------------+---------+--------+------+------+
1088 680ead21 Claudio Fontana
 */
1089 ad7ee8a2 Claudio Fontana
static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
1090 ad7ee8a2 Claudio Fontana
{
1091 680ead21 Claudio Fontana
    unsigned int sf, opcode, rn, rd;
1092 680ead21 Claudio Fontana
1093 680ead21 Claudio Fontana
    if (extract32(insn, 29, 1) || extract32(insn, 16, 5)) {
1094 680ead21 Claudio Fontana
        unallocated_encoding(s);
1095 680ead21 Claudio Fontana
        return;
1096 680ead21 Claudio Fontana
    }
1097 680ead21 Claudio Fontana
1098 680ead21 Claudio Fontana
    sf = extract32(insn, 31, 1);
1099 680ead21 Claudio Fontana
    opcode = extract32(insn, 10, 6);
1100 680ead21 Claudio Fontana
    rn = extract32(insn, 5, 5);
1101 680ead21 Claudio Fontana
    rd = extract32(insn, 0, 5);
1102 680ead21 Claudio Fontana
1103 680ead21 Claudio Fontana
    switch (opcode) {
1104 680ead21 Claudio Fontana
    case 0: /* RBIT */
1105 82e14b02 Alexander Graf
        handle_rbit(s, sf, rn, rd);
1106 82e14b02 Alexander Graf
        break;
1107 680ead21 Claudio Fontana
    case 1: /* REV16 */
1108 680ead21 Claudio Fontana
    case 2: /* REV32 */
1109 680ead21 Claudio Fontana
    case 3: /* REV64 */
1110 680ead21 Claudio Fontana
        unsupported_encoding(s, insn);
1111 680ead21 Claudio Fontana
        break;
1112 680ead21 Claudio Fontana
    case 4: /* CLZ */
1113 680ead21 Claudio Fontana
        handle_clz(s, sf, rn, rd);
1114 680ead21 Claudio Fontana
        break;
1115 680ead21 Claudio Fontana
    case 5: /* CLS */
1116 680ead21 Claudio Fontana
        unsupported_encoding(s, insn);
1117 680ead21 Claudio Fontana
        break;
1118 680ead21 Claudio Fontana
    }
1119 ad7ee8a2 Claudio Fontana
}
1120 ad7ee8a2 Claudio Fontana
1121 8220e911 Alexander Graf
static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
1122 8220e911 Alexander Graf
                       unsigned int rm, unsigned int rn, unsigned int rd)
1123 8220e911 Alexander Graf
{
1124 8220e911 Alexander Graf
    TCGv_i64 tcg_n, tcg_m, tcg_rd;
1125 8220e911 Alexander Graf
    tcg_rd = cpu_reg(s, rd);
1126 8220e911 Alexander Graf
1127 8220e911 Alexander Graf
    if (!sf && is_signed) {
1128 8220e911 Alexander Graf
        tcg_n = new_tmp_a64(s);
1129 8220e911 Alexander Graf
        tcg_m = new_tmp_a64(s);
1130 8220e911 Alexander Graf
        tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
1131 8220e911 Alexander Graf
        tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
1132 8220e911 Alexander Graf
    } else {
1133 8220e911 Alexander Graf
        tcg_n = read_cpu_reg(s, rn, sf);
1134 8220e911 Alexander Graf
        tcg_m = read_cpu_reg(s, rm, sf);
1135 8220e911 Alexander Graf
    }
1136 8220e911 Alexander Graf
1137 8220e911 Alexander Graf
    if (is_signed) {
1138 8220e911 Alexander Graf
        gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
1139 8220e911 Alexander Graf
    } else {
1140 8220e911 Alexander Graf
        gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
1141 8220e911 Alexander Graf
    }
1142 8220e911 Alexander Graf
1143 8220e911 Alexander Graf
    if (!sf) { /* zero extend final result */
1144 8220e911 Alexander Graf
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1145 8220e911 Alexander Graf
    }
1146 8220e911 Alexander Graf
}
1147 8220e911 Alexander Graf
1148 6c1adc91 Alexander Graf
/* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
1149 6c1adc91 Alexander Graf
static void handle_shift_reg(DisasContext *s,
1150 6c1adc91 Alexander Graf
                             enum a64_shift_type shift_type, unsigned int sf,
1151 6c1adc91 Alexander Graf
                             unsigned int rm, unsigned int rn, unsigned int rd)
1152 6c1adc91 Alexander Graf
{
1153 6c1adc91 Alexander Graf
    TCGv_i64 tcg_shift = tcg_temp_new_i64();
1154 6c1adc91 Alexander Graf
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
1155 6c1adc91 Alexander Graf
    TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
1156 6c1adc91 Alexander Graf
1157 6c1adc91 Alexander Graf
    tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
1158 6c1adc91 Alexander Graf
    shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
1159 6c1adc91 Alexander Graf
    tcg_temp_free_i64(tcg_shift);
1160 6c1adc91 Alexander Graf
}
1161 6c1adc91 Alexander Graf
1162 8220e911 Alexander Graf
/* C3.5.8 Data-processing (2 source)
1163 8220e911 Alexander Graf
 *   31   30  29 28             21 20  16 15    10 9    5 4    0
1164 8220e911 Alexander Graf
 * +----+---+---+-----------------+------+--------+------+------+
1165 8220e911 Alexander Graf
 * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
1166 8220e911 Alexander Graf
 * +----+---+---+-----------------+------+--------+------+------+
1167 8220e911 Alexander Graf
 */
1168 ad7ee8a2 Claudio Fontana
static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
1169 ad7ee8a2 Claudio Fontana
{
1170 8220e911 Alexander Graf
    unsigned int sf, rm, opcode, rn, rd;
1171 8220e911 Alexander Graf
    sf = extract32(insn, 31, 1);
1172 8220e911 Alexander Graf
    rm = extract32(insn, 16, 5);
1173 8220e911 Alexander Graf
    opcode = extract32(insn, 10, 6);
1174 8220e911 Alexander Graf
    rn = extract32(insn, 5, 5);
1175 8220e911 Alexander Graf
    rd = extract32(insn, 0, 5);
1176 8220e911 Alexander Graf
1177 8220e911 Alexander Graf
    if (extract32(insn, 29, 1)) {
1178 8220e911 Alexander Graf
        unallocated_encoding(s);
1179 8220e911 Alexander Graf
        return;
1180 8220e911 Alexander Graf
    }
1181 8220e911 Alexander Graf
1182 8220e911 Alexander Graf
    switch (opcode) {
1183 8220e911 Alexander Graf
    case 2: /* UDIV */
1184 8220e911 Alexander Graf
        handle_div(s, false, sf, rm, rn, rd);
1185 8220e911 Alexander Graf
        break;
1186 8220e911 Alexander Graf
    case 3: /* SDIV */
1187 8220e911 Alexander Graf
        handle_div(s, true, sf, rm, rn, rd);
1188 8220e911 Alexander Graf
        break;
1189 8220e911 Alexander Graf
    case 8: /* LSLV */
1190 6c1adc91 Alexander Graf
        handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
1191 6c1adc91 Alexander Graf
        break;
1192 8220e911 Alexander Graf
    case 9: /* LSRV */
1193 6c1adc91 Alexander Graf
        handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
1194 6c1adc91 Alexander Graf
        break;
1195 8220e911 Alexander Graf
    case 10: /* ASRV */
1196 6c1adc91 Alexander Graf
        handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
1197 6c1adc91 Alexander Graf
        break;
1198 8220e911 Alexander Graf
    case 11: /* RORV */
1199 6c1adc91 Alexander Graf
        handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
1200 6c1adc91 Alexander Graf
        break;
1201 8220e911 Alexander Graf
    case 16:
1202 8220e911 Alexander Graf
    case 17:
1203 8220e911 Alexander Graf
    case 18:
1204 8220e911 Alexander Graf
    case 19:
1205 8220e911 Alexander Graf
    case 20:
1206 8220e911 Alexander Graf
    case 21:
1207 8220e911 Alexander Graf
    case 22:
1208 8220e911 Alexander Graf
    case 23: /* CRC32 */
1209 8220e911 Alexander Graf
        unsupported_encoding(s, insn);
1210 8220e911 Alexander Graf
        break;
1211 8220e911 Alexander Graf
    default:
1212 8220e911 Alexander Graf
        unallocated_encoding(s);
1213 8220e911 Alexander Graf
        break;
1214 8220e911 Alexander Graf
    }
1215 ad7ee8a2 Claudio Fontana
}
1216 ad7ee8a2 Claudio Fontana
1217 ad7ee8a2 Claudio Fontana
/* C3.5 Data processing - register */
1218 ad7ee8a2 Claudio Fontana
static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
1219 ad7ee8a2 Claudio Fontana
{
1220 ad7ee8a2 Claudio Fontana
    switch (extract32(insn, 24, 5)) {
1221 ad7ee8a2 Claudio Fontana
    case 0x0a: /* Logical (shifted register) */
1222 ad7ee8a2 Claudio Fontana
        disas_logic_reg(s, insn);
1223 ad7ee8a2 Claudio Fontana
        break;
1224 ad7ee8a2 Claudio Fontana
    case 0x0b: /* Add/subtract */
1225 ad7ee8a2 Claudio Fontana
        if (insn & (1 << 21)) { /* (extended register) */
1226 ad7ee8a2 Claudio Fontana
            disas_add_sub_ext_reg(s, insn);
1227 ad7ee8a2 Claudio Fontana
        } else {
1228 ad7ee8a2 Claudio Fontana
            disas_add_sub_reg(s, insn);
1229 ad7ee8a2 Claudio Fontana
        }
1230 ad7ee8a2 Claudio Fontana
        break;
1231 ad7ee8a2 Claudio Fontana
    case 0x1b: /* Data-processing (3 source) */
1232 ad7ee8a2 Claudio Fontana
        disas_data_proc_3src(s, insn);
1233 ad7ee8a2 Claudio Fontana
        break;
1234 ad7ee8a2 Claudio Fontana
    case 0x1a:
1235 ad7ee8a2 Claudio Fontana
        switch (extract32(insn, 21, 3)) {
1236 ad7ee8a2 Claudio Fontana
        case 0x0: /* Add/subtract (with carry) */
1237 ad7ee8a2 Claudio Fontana
            disas_adc_sbc(s, insn);
1238 ad7ee8a2 Claudio Fontana
            break;
1239 ad7ee8a2 Claudio Fontana
        case 0x2: /* Conditional compare */
1240 ad7ee8a2 Claudio Fontana
            if (insn & (1 << 11)) { /* (immediate) */
1241 ad7ee8a2 Claudio Fontana
                disas_cc_imm(s, insn);
1242 ad7ee8a2 Claudio Fontana
            } else {            /* (register) */
1243 ad7ee8a2 Claudio Fontana
                disas_cc_reg(s, insn);
1244 ad7ee8a2 Claudio Fontana
            }
1245 ad7ee8a2 Claudio Fontana
            break;
1246 ad7ee8a2 Claudio Fontana
        case 0x4: /* Conditional select */
1247 ad7ee8a2 Claudio Fontana
            disas_cond_select(s, insn);
1248 ad7ee8a2 Claudio Fontana
            break;
1249 ad7ee8a2 Claudio Fontana
        case 0x6: /* Data-processing */
1250 ad7ee8a2 Claudio Fontana
            if (insn & (1 << 30)) { /* (1 source) */
1251 ad7ee8a2 Claudio Fontana
                disas_data_proc_1src(s, insn);
1252 ad7ee8a2 Claudio Fontana
            } else {            /* (2 source) */
1253 ad7ee8a2 Claudio Fontana
                disas_data_proc_2src(s, insn);
1254 ad7ee8a2 Claudio Fontana
            }
1255 ad7ee8a2 Claudio Fontana
            break;
1256 ad7ee8a2 Claudio Fontana
        default:
1257 ad7ee8a2 Claudio Fontana
            unallocated_encoding(s);
1258 ad7ee8a2 Claudio Fontana
            break;
1259 ad7ee8a2 Claudio Fontana
        }
1260 ad7ee8a2 Claudio Fontana
        break;
1261 ad7ee8a2 Claudio Fontana
    default:
1262 ad7ee8a2 Claudio Fontana
        unallocated_encoding(s);
1263 ad7ee8a2 Claudio Fontana
        break;
1264 ad7ee8a2 Claudio Fontana
    }
1265 ad7ee8a2 Claudio Fontana
}
1266 ad7ee8a2 Claudio Fontana
1267 ad7ee8a2 Claudio Fontana
/* C3.6 Data processing - SIMD and floating point */
1268 ad7ee8a2 Claudio Fontana
static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
1269 ad7ee8a2 Claudio Fontana
{
1270 ad7ee8a2 Claudio Fontana
    unsupported_encoding(s, insn);
1271 ad7ee8a2 Claudio Fontana
}
1272 ad7ee8a2 Claudio Fontana
1273 ad7ee8a2 Claudio Fontana
/* C3.1 A64 instruction index by encoding */
1274 40f860cd Peter Maydell
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
1275 14ade10f Alexander Graf
{
1276 14ade10f Alexander Graf
    uint32_t insn;
1277 14ade10f Alexander Graf
1278 14ade10f Alexander Graf
    insn = arm_ldl_code(env, s->pc, s->bswap_code);
1279 14ade10f Alexander Graf
    s->insn = insn;
1280 14ade10f Alexander Graf
    s->pc += 4;
1281 14ade10f Alexander Graf
1282 ad7ee8a2 Claudio Fontana
    switch (extract32(insn, 25, 4)) {
1283 ad7ee8a2 Claudio Fontana
    case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
1284 14ade10f Alexander Graf
        unallocated_encoding(s);
1285 14ade10f Alexander Graf
        break;
1286 ad7ee8a2 Claudio Fontana
    case 0x8: case 0x9: /* Data processing - immediate */
1287 ad7ee8a2 Claudio Fontana
        disas_data_proc_imm(s, insn);
1288 ad7ee8a2 Claudio Fontana
        break;
1289 ad7ee8a2 Claudio Fontana
    case 0xa: case 0xb: /* Branch, exception generation and system insns */
1290 ad7ee8a2 Claudio Fontana
        disas_b_exc_sys(s, insn);
1291 ad7ee8a2 Claudio Fontana
        break;
1292 ad7ee8a2 Claudio Fontana
    case 0x4:
1293 ad7ee8a2 Claudio Fontana
    case 0x6:
1294 ad7ee8a2 Claudio Fontana
    case 0xc:
1295 ad7ee8a2 Claudio Fontana
    case 0xe:      /* Loads and stores */
1296 ad7ee8a2 Claudio Fontana
        disas_ldst(s, insn);
1297 ad7ee8a2 Claudio Fontana
        break;
1298 ad7ee8a2 Claudio Fontana
    case 0x5:
1299 ad7ee8a2 Claudio Fontana
    case 0xd:      /* Data processing - register */
1300 ad7ee8a2 Claudio Fontana
        disas_data_proc_reg(s, insn);
1301 ad7ee8a2 Claudio Fontana
        break;
1302 ad7ee8a2 Claudio Fontana
    case 0x7:
1303 ad7ee8a2 Claudio Fontana
    case 0xf:      /* Data processing - SIMD and floating point */
1304 ad7ee8a2 Claudio Fontana
        disas_data_proc_simd_fp(s, insn);
1305 ad7ee8a2 Claudio Fontana
        break;
1306 ad7ee8a2 Claudio Fontana
    default:
1307 ad7ee8a2 Claudio Fontana
        assert(FALSE); /* all 15 cases should be handled above */
1308 ad7ee8a2 Claudio Fontana
        break;
1309 14ade10f Alexander Graf
    }
1310 11e169de Alexander Graf
1311 11e169de Alexander Graf
    /* if we allocated any temporaries, free them here */
1312 11e169de Alexander Graf
    free_tmp_a64(s);
1313 40f860cd Peter Maydell
}
1314 14ade10f Alexander Graf
1315 40f860cd Peter Maydell
void gen_intermediate_code_internal_a64(ARMCPU *cpu,
1316 40f860cd Peter Maydell
                                        TranslationBlock *tb,
1317 40f860cd Peter Maydell
                                        bool search_pc)
1318 40f860cd Peter Maydell
{
1319 40f860cd Peter Maydell
    CPUState *cs = CPU(cpu);
1320 40f860cd Peter Maydell
    CPUARMState *env = &cpu->env;
1321 40f860cd Peter Maydell
    DisasContext dc1, *dc = &dc1;
1322 40f860cd Peter Maydell
    CPUBreakpoint *bp;
1323 40f860cd Peter Maydell
    uint16_t *gen_opc_end;
1324 40f860cd Peter Maydell
    int j, lj;
1325 40f860cd Peter Maydell
    target_ulong pc_start;
1326 40f860cd Peter Maydell
    target_ulong next_page_start;
1327 40f860cd Peter Maydell
    int num_insns;
1328 40f860cd Peter Maydell
    int max_insns;
1329 40f860cd Peter Maydell
1330 40f860cd Peter Maydell
    pc_start = tb->pc;
1331 40f860cd Peter Maydell
1332 40f860cd Peter Maydell
    dc->tb = tb;
1333 40f860cd Peter Maydell
1334 40f860cd Peter Maydell
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
1335 40f860cd Peter Maydell
1336 40f860cd Peter Maydell
    dc->is_jmp = DISAS_NEXT;
1337 40f860cd Peter Maydell
    dc->pc = pc_start;
1338 40f860cd Peter Maydell
    dc->singlestep_enabled = cs->singlestep_enabled;
1339 40f860cd Peter Maydell
    dc->condjmp = 0;
1340 40f860cd Peter Maydell
1341 40f860cd Peter Maydell
    dc->aarch64 = 1;
1342 40f860cd Peter Maydell
    dc->thumb = 0;
1343 40f860cd Peter Maydell
    dc->bswap_code = 0;
1344 40f860cd Peter Maydell
    dc->condexec_mask = 0;
1345 40f860cd Peter Maydell
    dc->condexec_cond = 0;
1346 40f860cd Peter Maydell
#if !defined(CONFIG_USER_ONLY)
1347 40f860cd Peter Maydell
    dc->user = 0;
1348 40f860cd Peter Maydell
#endif
1349 40f860cd Peter Maydell
    dc->vfp_enabled = 0;
1350 40f860cd Peter Maydell
    dc->vec_len = 0;
1351 40f860cd Peter Maydell
    dc->vec_stride = 0;
1352 40f860cd Peter Maydell
1353 11e169de Alexander Graf
    init_tmp_a64_array(dc);
1354 11e169de Alexander Graf
1355 40f860cd Peter Maydell
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1356 40f860cd Peter Maydell
    lj = -1;
1357 40f860cd Peter Maydell
    num_insns = 0;
1358 40f860cd Peter Maydell
    max_insns = tb->cflags & CF_COUNT_MASK;
1359 40f860cd Peter Maydell
    if (max_insns == 0) {
1360 40f860cd Peter Maydell
        max_insns = CF_COUNT_MASK;
1361 40f860cd Peter Maydell
    }
1362 40f860cd Peter Maydell
1363 40f860cd Peter Maydell
    gen_tb_start();
1364 40f860cd Peter Maydell
1365 40f860cd Peter Maydell
    tcg_clear_temp_count();
1366 40f860cd Peter Maydell
1367 40f860cd Peter Maydell
    do {
1368 40f860cd Peter Maydell
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
1369 40f860cd Peter Maydell
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1370 40f860cd Peter Maydell
                if (bp->pc == dc->pc) {
1371 40f860cd Peter Maydell
                    gen_exception_insn(dc, 0, EXCP_DEBUG);
1372 40f860cd Peter Maydell
                    /* Advance PC so that clearing the breakpoint will
1373 40f860cd Peter Maydell
                       invalidate this TB.  */
1374 40f860cd Peter Maydell
                    dc->pc += 2;
1375 40f860cd Peter Maydell
                    goto done_generating;
1376 40f860cd Peter Maydell
                }
1377 40f860cd Peter Maydell
            }
1378 40f860cd Peter Maydell
        }
1379 40f860cd Peter Maydell
1380 40f860cd Peter Maydell
        if (search_pc) {
1381 40f860cd Peter Maydell
            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
1382 40f860cd Peter Maydell
            if (lj < j) {
1383 40f860cd Peter Maydell
                lj++;
1384 40f860cd Peter Maydell
                while (lj < j) {
1385 40f860cd Peter Maydell
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
1386 40f860cd Peter Maydell
                }
1387 40f860cd Peter Maydell
            }
1388 40f860cd Peter Maydell
            tcg_ctx.gen_opc_pc[lj] = dc->pc;
1389 40f860cd Peter Maydell
            tcg_ctx.gen_opc_instr_start[lj] = 1;
1390 40f860cd Peter Maydell
            tcg_ctx.gen_opc_icount[lj] = num_insns;
1391 40f860cd Peter Maydell
        }
1392 40f860cd Peter Maydell
1393 40f860cd Peter Maydell
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
1394 40f860cd Peter Maydell
            gen_io_start();
1395 40f860cd Peter Maydell
        }
1396 40f860cd Peter Maydell
1397 40f860cd Peter Maydell
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
1398 40f860cd Peter Maydell
            tcg_gen_debug_insn_start(dc->pc);
1399 40f860cd Peter Maydell
        }
1400 40f860cd Peter Maydell
1401 40f860cd Peter Maydell
        disas_a64_insn(env, dc);
1402 40f860cd Peter Maydell
1403 40f860cd Peter Maydell
        if (tcg_check_temp_count()) {
1404 40f860cd Peter Maydell
            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
1405 40f860cd Peter Maydell
                    dc->pc);
1406 40f860cd Peter Maydell
        }
1407 40f860cd Peter Maydell
1408 40f860cd Peter Maydell
        /* Translation stops when a conditional branch is encountered.
1409 40f860cd Peter Maydell
         * Otherwise the subsequent code could get translated several times.
1410 40f860cd Peter Maydell
         * Also stop translation when a page boundary is reached.  This
1411 40f860cd Peter Maydell
         * ensures prefetch aborts occur at the right place.
1412 40f860cd Peter Maydell
         */
1413 40f860cd Peter Maydell
        num_insns++;
1414 40f860cd Peter Maydell
    } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
1415 40f860cd Peter Maydell
             !cs->singlestep_enabled &&
1416 40f860cd Peter Maydell
             !singlestep &&
1417 40f860cd Peter Maydell
             dc->pc < next_page_start &&
1418 40f860cd Peter Maydell
             num_insns < max_insns);
1419 40f860cd Peter Maydell
1420 40f860cd Peter Maydell
    if (tb->cflags & CF_LAST_IO) {
1421 40f860cd Peter Maydell
        gen_io_end();
1422 40f860cd Peter Maydell
    }
1423 40f860cd Peter Maydell
1424 40f860cd Peter Maydell
    if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
1425 40f860cd Peter Maydell
        /* Note that this means single stepping WFI doesn't halt the CPU.
1426 40f860cd Peter Maydell
         * For conditional branch insns this is harmless unreachable code as
1427 40f860cd Peter Maydell
         * gen_goto_tb() has already handled emitting the debug exception
1428 40f860cd Peter Maydell
         * (and thus a tb-jump is not possible when singlestepping).
1429 40f860cd Peter Maydell
         */
1430 40f860cd Peter Maydell
        assert(dc->is_jmp != DISAS_TB_JUMP);
1431 40f860cd Peter Maydell
        if (dc->is_jmp != DISAS_JUMP) {
1432 40f860cd Peter Maydell
            gen_a64_set_pc_im(dc->pc);
1433 40f860cd Peter Maydell
        }
1434 40f860cd Peter Maydell
        gen_exception(EXCP_DEBUG);
1435 40f860cd Peter Maydell
    } else {
1436 40f860cd Peter Maydell
        switch (dc->is_jmp) {
1437 40f860cd Peter Maydell
        case DISAS_NEXT:
1438 40f860cd Peter Maydell
            gen_goto_tb(dc, 1, dc->pc);
1439 40f860cd Peter Maydell
            break;
1440 40f860cd Peter Maydell
        default:
1441 40f860cd Peter Maydell
        case DISAS_JUMP:
1442 40f860cd Peter Maydell
        case DISAS_UPDATE:
1443 40f860cd Peter Maydell
            /* indicate that the hash table must be used to find the next TB */
1444 40f860cd Peter Maydell
            tcg_gen_exit_tb(0);
1445 40f860cd Peter Maydell
            break;
1446 40f860cd Peter Maydell
        case DISAS_TB_JUMP:
1447 40f860cd Peter Maydell
        case DISAS_EXC:
1448 40f860cd Peter Maydell
        case DISAS_SWI:
1449 40f860cd Peter Maydell
            break;
1450 40f860cd Peter Maydell
        case DISAS_WFI:
1451 40f860cd Peter Maydell
            /* This is a special case because we don't want to just halt the CPU
1452 40f860cd Peter Maydell
             * if trying to debug across a WFI.
1453 40f860cd Peter Maydell
             */
1454 40f860cd Peter Maydell
            gen_helper_wfi(cpu_env);
1455 40f860cd Peter Maydell
            break;
1456 40f860cd Peter Maydell
        }
1457 40f860cd Peter Maydell
    }
1458 40f860cd Peter Maydell
1459 40f860cd Peter Maydell
done_generating:
1460 40f860cd Peter Maydell
    gen_tb_end(tb, num_insns);
1461 40f860cd Peter Maydell
    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
1462 40f860cd Peter Maydell
1463 40f860cd Peter Maydell
#ifdef DEBUG_DISAS
1464 40f860cd Peter Maydell
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1465 40f860cd Peter Maydell
        qemu_log("----------------\n");
1466 40f860cd Peter Maydell
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
1467 40f860cd Peter Maydell
        log_target_disas(env, pc_start, dc->pc - pc_start,
1468 40f860cd Peter Maydell
                         dc->thumb | (dc->bswap_code << 1));
1469 40f860cd Peter Maydell
        qemu_log("\n");
1470 40f860cd Peter Maydell
    }
1471 40f860cd Peter Maydell
#endif
1472 40f860cd Peter Maydell
    if (search_pc) {
1473 40f860cd Peter Maydell
        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
1474 40f860cd Peter Maydell
        lj++;
1475 40f860cd Peter Maydell
        while (lj <= j) {
1476 40f860cd Peter Maydell
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
1477 40f860cd Peter Maydell
        }
1478 40f860cd Peter Maydell
    } else {
1479 40f860cd Peter Maydell
        tb->size = dc->pc - pc_start;
1480 40f860cd Peter Maydell
        tb->icount = num_insns;
1481 14ade10f Alexander Graf
    }
1482 14ade10f Alexander Graf
}