Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (41.9 kB)

1
/*
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

    
31
#include "exec/gen-icount.h"
32

    
33
#include "helper.h"
34
#define GEN_HELPER 1
35
#include "helper.h"
36

    
37
static TCGv_i64 cpu_X[32];
38
static TCGv_i64 cpu_pc;
39
static TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
40

    
41
static const char *regnames[] = {
42
    "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
43
    "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
44
    "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
45
    "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
46
};
47

    
48
enum a64_shift_type {
49
    A64_SHIFT_TYPE_LSL = 0,
50
    A64_SHIFT_TYPE_LSR = 1,
51
    A64_SHIFT_TYPE_ASR = 2,
52
    A64_SHIFT_TYPE_ROR = 3
53
};
54

    
55
/* initialize TCG globals.  */
56
void a64_translate_init(void)
57
{
58
    int i;
59

    
60
    cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
61
                                    offsetof(CPUARMState, pc),
62
                                    "pc");
63
    for (i = 0; i < 32; i++) {
64
        cpu_X[i] = tcg_global_mem_new_i64(TCG_AREG0,
65
                                          offsetof(CPUARMState, xregs[i]),
66
                                          regnames[i]);
67
    }
68

    
69
    cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
70
    cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
71
    cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
72
    cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
73
}
74

    
75
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
76
                            fprintf_function cpu_fprintf, int flags)
77
{
78
    ARMCPU *cpu = ARM_CPU(cs);
79
    CPUARMState *env = &cpu->env;
80
    uint32_t psr = pstate_read(env);
81
    int i;
82

    
83
    cpu_fprintf(f, "PC=%016"PRIx64"  SP=%016"PRIx64"\n",
84
            env->pc, env->xregs[31]);
85
    for (i = 0; i < 31; i++) {
86
        cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
87
        if ((i % 4) == 3) {
88
            cpu_fprintf(f, "\n");
89
        } else {
90
            cpu_fprintf(f, " ");
91
        }
92
    }
93
    cpu_fprintf(f, "PSTATE=%08x (flags %c%c%c%c)\n",
94
                psr,
95
                psr & PSTATE_N ? 'N' : '-',
96
                psr & PSTATE_Z ? 'Z' : '-',
97
                psr & PSTATE_C ? 'C' : '-',
98
                psr & PSTATE_V ? 'V' : '-');
99
    cpu_fprintf(f, "\n");
100
}
101

    
102
void gen_a64_set_pc_im(uint64_t val)
103
{
104
    tcg_gen_movi_i64(cpu_pc, val);
105
}
106

    
107
static void gen_exception(int excp)
108
{
109
    TCGv_i32 tmp = tcg_temp_new_i32();
110
    tcg_gen_movi_i32(tmp, excp);
111
    gen_helper_exception(cpu_env, tmp);
112
    tcg_temp_free_i32(tmp);
113
}
114

    
115
static void gen_exception_insn(DisasContext *s, int offset, int excp)
116
{
117
    gen_a64_set_pc_im(s->pc - offset);
118
    gen_exception(excp);
119
    s->is_jmp = DISAS_EXC;
120
}
121

    
122
static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
123
{
124
    /* No direct tb linking with singlestep or deterministic io */
125
    if (s->singlestep_enabled || (s->tb->cflags & CF_LAST_IO)) {
126
        return false;
127
    }
128

    
129
    /* Only link tbs from inside the same guest page */
130
    if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
131
        return false;
132
    }
133

    
134
    return true;
135
}
136

    
137
static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
138
{
139
    TranslationBlock *tb;
140

    
141
    tb = s->tb;
142
    if (use_goto_tb(s, n, dest)) {
143
        tcg_gen_goto_tb(n);
144
        gen_a64_set_pc_im(dest);
145
        tcg_gen_exit_tb((tcg_target_long)tb + n);
146
        s->is_jmp = DISAS_TB_JUMP;
147
    } else {
148
        gen_a64_set_pc_im(dest);
149
        if (s->singlestep_enabled) {
150
            gen_exception(EXCP_DEBUG);
151
        }
152
        tcg_gen_exit_tb(0);
153
        s->is_jmp = DISAS_JUMP;
154
    }
155
}
156

    
157
static void unallocated_encoding(DisasContext *s)
158
{
159
    gen_exception_insn(s, 4, EXCP_UDEF);
160
}
161

    
162
#define unsupported_encoding(s, insn)                                    \
163
    do {                                                                 \
164
        qemu_log_mask(LOG_UNIMP,                                         \
165
                      "%s:%d: unsupported instruction encoding 0x%08x "  \
166
                      "at pc=%016" PRIx64 "\n",                          \
167
                      __FILE__, __LINE__, insn, s->pc - 4);              \
168
        unallocated_encoding(s);                                         \
169
    } while (0);
170

    
171
static void init_tmp_a64_array(DisasContext *s)
172
{
173
#ifdef CONFIG_DEBUG_TCG
174
    int i;
175
    for (i = 0; i < ARRAY_SIZE(s->tmp_a64); i++) {
176
        TCGV_UNUSED_I64(s->tmp_a64[i]);
177
    }
178
#endif
179
    s->tmp_a64_count = 0;
180
}
181

    
182
static void free_tmp_a64(DisasContext *s)
183
{
184
    int i;
185
    for (i = 0; i < s->tmp_a64_count; i++) {
186
        tcg_temp_free_i64(s->tmp_a64[i]);
187
    }
188
    init_tmp_a64_array(s);
189
}
190

    
191
static TCGv_i64 new_tmp_a64(DisasContext *s)
192
{
193
    assert(s->tmp_a64_count < TMP_A64_MAX);
194
    return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
195
}
196

    
197
static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
198
{
199
    TCGv_i64 t = new_tmp_a64(s);
200
    tcg_gen_movi_i64(t, 0);
201
    return t;
202
}
203

    
204
static TCGv_i64 cpu_reg(DisasContext *s, int reg)
205
{
206
    if (reg == 31) {
207
        return new_tmp_a64_zero(s);
208
    } else {
209
        return cpu_X[reg];
210
    }
211
}
212

    
213
/* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
214
 * representing the register contents. This TCGv is an auto-freed
215
 * temporary so it need not be explicitly freed, and may be modified.
216
 */
217
static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
218
{
219
    TCGv_i64 v = new_tmp_a64(s);
220
    if (reg != 31) {
221
        if (sf) {
222
            tcg_gen_mov_i64(v, cpu_X[reg]);
223
        } else {
224
            tcg_gen_ext32u_i64(v, cpu_X[reg]);
225
        }
226
    } else {
227
        tcg_gen_movi_i64(v, 0);
228
    }
229
    return v;
230
}
231

    
232
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
233
 * than the 32 bit equivalent.
234
 */
235
static inline void gen_set_NZ64(TCGv_i64 result)
236
{
237
    TCGv_i64 flag = tcg_temp_new_i64();
238

    
239
    tcg_gen_setcondi_i64(TCG_COND_NE, flag, result, 0);
240
    tcg_gen_trunc_i64_i32(cpu_ZF, flag);
241
    tcg_gen_shri_i64(flag, result, 32);
242
    tcg_gen_trunc_i64_i32(cpu_NF, flag);
243
    tcg_temp_free_i64(flag);
244
}
245

    
246
/* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
247
static inline void gen_logic_CC(int sf, TCGv_i64 result)
248
{
249
    if (sf) {
250
        gen_set_NZ64(result);
251
    } else {
252
        tcg_gen_trunc_i64_i32(cpu_ZF, result);
253
        tcg_gen_trunc_i64_i32(cpu_NF, result);
254
    }
255
    tcg_gen_movi_i32(cpu_CF, 0);
256
    tcg_gen_movi_i32(cpu_VF, 0);
257
}
258

    
259
/*
260
 * the instruction disassembly implemented here matches
261
 * the instruction encoding classifications in chapter 3 (C3)
262
 * of the ARM Architecture Reference Manual (DDI0487A_a)
263
 */
264

    
265
/* C3.2.7 Unconditional branch (immediate)
266
 *   31  30       26 25                                  0
267
 * +----+-----------+-------------------------------------+
268
 * | op | 0 0 1 0 1 |                 imm26               |
269
 * +----+-----------+-------------------------------------+
270
 */
271
static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
272
{
273
    uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
274

    
275
    if (insn & (1 << 31)) {
276
        /* C5.6.26 BL Branch with link */
277
        tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
278
    }
279

    
280
    /* C5.6.20 B Branch / C5.6.26 BL Branch with link */
281
    gen_goto_tb(s, 0, addr);
282
}
283

    
284
/* C3.2.1 Compare & branch (immediate)
285
 *   31  30         25  24  23                  5 4      0
286
 * +----+-------------+----+---------------------+--------+
287
 * | sf | 0 1 1 0 1 0 | op |         imm19       |   Rt   |
288
 * +----+-------------+----+---------------------+--------+
289
 */
290
static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
291
{
292
    unsigned int sf, op, rt;
293
    uint64_t addr;
294
    int label_match;
295
    TCGv_i64 tcg_cmp;
296

    
297
    sf = extract32(insn, 31, 1);
298
    op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
299
    rt = extract32(insn, 0, 5);
300
    addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
301

    
302
    tcg_cmp = read_cpu_reg(s, rt, sf);
303
    label_match = gen_new_label();
304

    
305
    tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
306
                        tcg_cmp, 0, label_match);
307

    
308
    gen_goto_tb(s, 0, s->pc);
309
    gen_set_label(label_match);
310
    gen_goto_tb(s, 1, addr);
311
}
312

    
313
/* C3.2.5 Test & branch (immediate)
314
 *   31  30         25  24  23   19 18          5 4    0
315
 * +----+-------------+----+-------+-------------+------+
316
 * | b5 | 0 1 1 0 1 1 | op |  b40  |    imm14    |  Rt  |
317
 * +----+-------------+----+-------+-------------+------+
318
 */
319
static void disas_test_b_imm(DisasContext *s, uint32_t insn)
320
{
321
    unsigned int bit_pos, op, rt;
322
    uint64_t addr;
323
    int label_match;
324
    TCGv_i64 tcg_cmp;
325

    
326
    bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
327
    op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
328
    addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
329
    rt = extract32(insn, 0, 5);
330

    
331
    tcg_cmp = tcg_temp_new_i64();
332
    tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
333
    label_match = gen_new_label();
334
    tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
335
                        tcg_cmp, 0, label_match);
336
    tcg_temp_free_i64(tcg_cmp);
337
    gen_goto_tb(s, 0, s->pc);
338
    gen_set_label(label_match);
339
    gen_goto_tb(s, 1, addr);
340
}
341

    
342
/* C3.2.2 / C5.6.19 Conditional branch (immediate)
343
 *  31           25  24  23                  5   4  3    0
344
 * +---------------+----+---------------------+----+------+
345
 * | 0 1 0 1 0 1 0 | o1 |         imm19       | o0 | cond |
346
 * +---------------+----+---------------------+----+------+
347
 */
348
static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
349
{
350
    unsigned int cond;
351
    uint64_t addr;
352

    
353
    if ((insn & (1 << 4)) || (insn & (1 << 24))) {
354
        unallocated_encoding(s);
355
        return;
356
    }
357
    addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
358
    cond = extract32(insn, 0, 4);
359

    
360
    if (cond < 0x0e) {
361
        /* genuinely conditional branches */
362
        int label_match = gen_new_label();
363
        arm_gen_test_cc(cond, label_match);
364
        gen_goto_tb(s, 0, s->pc);
365
        gen_set_label(label_match);
366
        gen_goto_tb(s, 1, addr);
367
    } else {
368
        /* 0xe and 0xf are both "always" conditions */
369
        gen_goto_tb(s, 0, addr);
370
    }
371
}
372

    
373
/* C5.6.68 HINT */
374
static void handle_hint(DisasContext *s, uint32_t insn,
375
                        unsigned int op1, unsigned int op2, unsigned int crm)
376
{
377
    unsigned int selector = crm << 3 | op2;
378

    
379
    if (op1 != 3) {
380
        unallocated_encoding(s);
381
        return;
382
    }
383

    
384
    switch (selector) {
385
    case 0: /* NOP */
386
        return;
387
    case 1: /* YIELD */
388
    case 2: /* WFE */
389
    case 3: /* WFI */
390
    case 4: /* SEV */
391
    case 5: /* SEVL */
392
        /* we treat all as NOP at least for now */
393
        return;
394
    default:
395
        /* default specified as NOP equivalent */
396
        return;
397
    }
398
}
399

    
400
/* CLREX, DSB, DMB, ISB */
401
static void handle_sync(DisasContext *s, uint32_t insn,
402
                        unsigned int op1, unsigned int op2, unsigned int crm)
403
{
404
    if (op1 != 3) {
405
        unallocated_encoding(s);
406
        return;
407
    }
408

    
409
    switch (op2) {
410
    case 2: /* CLREX */
411
        unsupported_encoding(s, insn);
412
        return;
413
    case 4: /* DSB */
414
    case 5: /* DMB */
415
    case 6: /* ISB */
416
        /* We don't emulate caches so barriers are no-ops */
417
        return;
418
    default:
419
        unallocated_encoding(s);
420
        return;
421
    }
422
}
423

    
424
/* C5.6.130 MSR (immediate) - move immediate to processor state field */
425
static void handle_msr_i(DisasContext *s, uint32_t insn,
426
                         unsigned int op1, unsigned int op2, unsigned int crm)
427
{
428
    unsupported_encoding(s, insn);
429
}
430

    
431
/* C5.6.204 SYS */
432
static void handle_sys(DisasContext *s, uint32_t insn, unsigned int l,
433
                       unsigned int op1, unsigned int op2,
434
                       unsigned int crn, unsigned int crm, unsigned int rt)
435
{
436
    unsupported_encoding(s, insn);
437
}
438

    
439
/* C5.6.129 MRS - move from system register */
440
static void handle_mrs(DisasContext *s, uint32_t insn, unsigned int op0,
441
                       unsigned int op1, unsigned int op2,
442
                       unsigned int crn, unsigned int crm, unsigned int rt)
443
{
444
    unsupported_encoding(s, insn);
445
}
446

    
447
/* C5.6.131 MSR (register) - move to system register */
448
static void handle_msr(DisasContext *s, uint32_t insn, unsigned int op0,
449
                       unsigned int op1, unsigned int op2,
450
                       unsigned int crn, unsigned int crm, unsigned int rt)
451
{
452
    unsupported_encoding(s, insn);
453
}
454

    
455
/* C3.2.4 System
456
 *  31                 22 21  20 19 18 16 15   12 11    8 7   5 4    0
457
 * +---------------------+---+-----+-----+-------+-------+-----+------+
458
 * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 |  CRn  |  CRm  | op2 |  Rt  |
459
 * +---------------------+---+-----+-----+-------+-------+-----+------+
460
 */
461
static void disas_system(DisasContext *s, uint32_t insn)
462
{
463
    unsigned int l, op0, op1, crn, crm, op2, rt;
464
    l = extract32(insn, 21, 1);
465
    op0 = extract32(insn, 19, 2);
466
    op1 = extract32(insn, 16, 3);
467
    crn = extract32(insn, 12, 4);
468
    crm = extract32(insn, 8, 4);
469
    op2 = extract32(insn, 5, 3);
470
    rt = extract32(insn, 0, 5);
471

    
472
    if (op0 == 0) {
473
        if (l || rt != 31) {
474
            unallocated_encoding(s);
475
            return;
476
        }
477
        switch (crn) {
478
        case 2: /* C5.6.68 HINT */
479
            handle_hint(s, insn, op1, op2, crm);
480
            break;
481
        case 3: /* CLREX, DSB, DMB, ISB */
482
            handle_sync(s, insn, op1, op2, crm);
483
            break;
484
        case 4: /* C5.6.130 MSR (immediate) */
485
            handle_msr_i(s, insn, op1, op2, crm);
486
            break;
487
        default:
488
            unallocated_encoding(s);
489
            break;
490
        }
491
        return;
492
    }
493

    
494
    if (op0 == 1) {
495
        /* C5.6.204 SYS */
496
        handle_sys(s, insn, l, op1, op2, crn, crm, rt);
497
    } else if (l) { /* op0 > 1 */
498
        /* C5.6.129 MRS - move from system register */
499
        handle_mrs(s, insn, op0, op1, op2, crn, crm, rt);
500
    } else {
501
        /* C5.6.131 MSR (register) - move to system register */
502
        handle_msr(s, insn, op0, op1, op2, crn, crm, rt);
503
    }
504
}
505

    
506
/* Exception generation */
507
static void disas_exc(DisasContext *s, uint32_t insn)
508
{
509
    unsupported_encoding(s, insn);
510
}
511

    
512
/* C3.2.7 Unconditional branch (register)
513
 *  31           25 24   21 20   16 15   10 9    5 4     0
514
 * +---------------+-------+-------+-------+------+-------+
515
 * | 1 1 0 1 0 1 1 |  opc  |  op2  |  op3  |  Rn  |  op4  |
516
 * +---------------+-------+-------+-------+------+-------+
517
 */
518
static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
519
{
520
    unsigned int opc, op2, op3, rn, op4;
521

    
522
    opc = extract32(insn, 21, 4);
523
    op2 = extract32(insn, 16, 5);
524
    op3 = extract32(insn, 10, 6);
525
    rn = extract32(insn, 5, 5);
526
    op4 = extract32(insn, 0, 5);
527

    
528
    if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
529
        unallocated_encoding(s);
530
        return;
531
    }
532

    
533
    switch (opc) {
534
    case 0: /* BR */
535
    case 2: /* RET */
536
        break;
537
    case 1: /* BLR */
538
        tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
539
        break;
540
    case 4: /* ERET */
541
    case 5: /* DRPS */
542
        if (rn != 0x1f) {
543
            unallocated_encoding(s);
544
        } else {
545
            unsupported_encoding(s, insn);
546
        }
547
        return;
548
    default:
549
        unallocated_encoding(s);
550
        return;
551
    }
552

    
553
    tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
554
    s->is_jmp = DISAS_JUMP;
555
}
556

    
557
/* C3.2 Branches, exception generating and system instructions */
558
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
559
{
560
    switch (extract32(insn, 25, 7)) {
561
    case 0x0a: case 0x0b:
562
    case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
563
        disas_uncond_b_imm(s, insn);
564
        break;
565
    case 0x1a: case 0x5a: /* Compare & branch (immediate) */
566
        disas_comp_b_imm(s, insn);
567
        break;
568
    case 0x1b: case 0x5b: /* Test & branch (immediate) */
569
        disas_test_b_imm(s, insn);
570
        break;
571
    case 0x2a: /* Conditional branch (immediate) */
572
        disas_cond_b_imm(s, insn);
573
        break;
574
    case 0x6a: /* Exception generation / System */
575
        if (insn & (1 << 24)) {
576
            disas_system(s, insn);
577
        } else {
578
            disas_exc(s, insn);
579
        }
580
        break;
581
    case 0x6b: /* Unconditional branch (register) */
582
        disas_uncond_b_reg(s, insn);
583
        break;
584
    default:
585
        unallocated_encoding(s);
586
        break;
587
    }
588
}
589

    
590
/* Load/store exclusive */
591
static void disas_ldst_excl(DisasContext *s, uint32_t insn)
592
{
593
    unsupported_encoding(s, insn);
594
}
595

    
596
/* Load register (literal) */
597
static void disas_ld_lit(DisasContext *s, uint32_t insn)
598
{
599
    unsupported_encoding(s, insn);
600
}
601

    
602
/* Load/store pair (all forms) */
603
static void disas_ldst_pair(DisasContext *s, uint32_t insn)
604
{
605
    unsupported_encoding(s, insn);
606
}
607

    
608
/* Load/store register (all forms) */
609
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
610
{
611
    unsupported_encoding(s, insn);
612
}
613

    
614
/* AdvSIMD load/store multiple structures */
615
static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
616
{
617
    unsupported_encoding(s, insn);
618
}
619

    
620
/* AdvSIMD load/store single structure */
621
static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
622
{
623
    unsupported_encoding(s, insn);
624
}
625

    
626
/* C3.3 Loads and stores */
627
static void disas_ldst(DisasContext *s, uint32_t insn)
628
{
629
    switch (extract32(insn, 24, 6)) {
630
    case 0x08: /* Load/store exclusive */
631
        disas_ldst_excl(s, insn);
632
        break;
633
    case 0x18: case 0x1c: /* Load register (literal) */
634
        disas_ld_lit(s, insn);
635
        break;
636
    case 0x28: case 0x29:
637
    case 0x2c: case 0x2d: /* Load/store pair (all forms) */
638
        disas_ldst_pair(s, insn);
639
        break;
640
    case 0x38: case 0x39:
641
    case 0x3c: case 0x3d: /* Load/store register (all forms) */
642
        disas_ldst_reg(s, insn);
643
        break;
644
    case 0x0c: /* AdvSIMD load/store multiple structures */
645
        disas_ldst_multiple_struct(s, insn);
646
        break;
647
    case 0x0d: /* AdvSIMD load/store single structure */
648
        disas_ldst_single_struct(s, insn);
649
        break;
650
    default:
651
        unallocated_encoding(s);
652
        break;
653
    }
654
}
655

    
656
/* C3.4.6 PC-rel. addressing
657
 *   31  30   29 28       24 23                5 4    0
658
 * +----+-------+-----------+-------------------+------+
659
 * | op | immlo | 1 0 0 0 0 |       immhi       |  Rd  |
660
 * +----+-------+-----------+-------------------+------+
661
 */
662
static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
663
{
664
    unsigned int page, rd;
665
    uint64_t base;
666
    int64_t offset;
667

    
668
    page = extract32(insn, 31, 1);
669
    /* SignExtend(immhi:immlo) -> offset */
670
    offset = ((int64_t)sextract32(insn, 5, 19) << 2) | extract32(insn, 29, 2);
671
    rd = extract32(insn, 0, 5);
672
    base = s->pc - 4;
673

    
674
    if (page) {
675
        /* ADRP (page based) */
676
        base &= ~0xfff;
677
        offset <<= 12;
678
    }
679

    
680
    tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
681
}
682

    
683
/* Add/subtract (immediate) */
684
static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
685
{
686
    unsupported_encoding(s, insn);
687
}
688

    
689
/* Logical (immediate) */
690
static void disas_logic_imm(DisasContext *s, uint32_t insn)
691
{
692
    unsupported_encoding(s, insn);
693
}
694

    
695
/* Move wide (immediate) */
696
static void disas_movw_imm(DisasContext *s, uint32_t insn)
697
{
698
    unsupported_encoding(s, insn);
699
}
700

    
701
/* Bitfield */
702
static void disas_bitfield(DisasContext *s, uint32_t insn)
703
{
704
    unsupported_encoding(s, insn);
705
}
706

    
707
/* C3.4.3 Extract
708
 *   31  30  29 28         23 22   21  20  16 15    10 9    5 4    0
709
 * +----+------+-------------+---+----+------+--------+------+------+
710
 * | sf | op21 | 1 0 0 1 1 1 | N | o0 |  Rm  |  imms  |  Rn  |  Rd  |
711
 * +----+------+-------------+---+----+------+--------+------+------+
712
 */
713
static void disas_extract(DisasContext *s, uint32_t insn)
714
{
715
    unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
716

    
717
    sf = extract32(insn, 31, 1);
718
    n = extract32(insn, 22, 1);
719
    rm = extract32(insn, 16, 5);
720
    imm = extract32(insn, 10, 6);
721
    rn = extract32(insn, 5, 5);
722
    rd = extract32(insn, 0, 5);
723
    op21 = extract32(insn, 29, 2);
724
    op0 = extract32(insn, 21, 1);
725
    bitsize = sf ? 64 : 32;
726

    
727
    if (sf != n || op21 || op0 || imm >= bitsize) {
728
        unallocated_encoding(s);
729
    } else {
730
        TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
731

    
732
        tcg_rd = cpu_reg(s, rd);
733

    
734
        if (imm) {
735
            /* OPTME: we can special case rm==rn as a rotate */
736
            tcg_rm = read_cpu_reg(s, rm, sf);
737
            tcg_rn = read_cpu_reg(s, rn, sf);
738
            tcg_gen_shri_i64(tcg_rm, tcg_rm, imm);
739
            tcg_gen_shli_i64(tcg_rn, tcg_rn, bitsize - imm);
740
            tcg_gen_or_i64(tcg_rd, tcg_rm, tcg_rn);
741
            if (!sf) {
742
                tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
743
            }
744
        } else {
745
            /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
746
             * so an extract from bit 0 is a special case.
747
             */
748
            if (sf) {
749
                tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
750
            } else {
751
                tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
752
            }
753
        }
754

    
755
    }
756
}
757

    
758
/* C3.4 Data processing - immediate */
759
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
760
{
761
    switch (extract32(insn, 23, 6)) {
762
    case 0x20: case 0x21: /* PC-rel. addressing */
763
        disas_pc_rel_adr(s, insn);
764
        break;
765
    case 0x22: case 0x23: /* Add/subtract (immediate) */
766
        disas_add_sub_imm(s, insn);
767
        break;
768
    case 0x24: /* Logical (immediate) */
769
        disas_logic_imm(s, insn);
770
        break;
771
    case 0x25: /* Move wide (immediate) */
772
        disas_movw_imm(s, insn);
773
        break;
774
    case 0x26: /* Bitfield */
775
        disas_bitfield(s, insn);
776
        break;
777
    case 0x27: /* Extract */
778
        disas_extract(s, insn);
779
        break;
780
    default:
781
        unallocated_encoding(s);
782
        break;
783
    }
784
}
785

    
786
/* Shift a TCGv src by TCGv shift_amount, put result in dst.
787
 * Note that it is the caller's responsibility to ensure that the
788
 * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
789
 * mandated semantics for out of range shifts.
790
 */
791
static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
792
                      enum a64_shift_type shift_type, TCGv_i64 shift_amount)
793
{
794
    switch (shift_type) {
795
    case A64_SHIFT_TYPE_LSL:
796
        tcg_gen_shl_i64(dst, src, shift_amount);
797
        break;
798
    case A64_SHIFT_TYPE_LSR:
799
        tcg_gen_shr_i64(dst, src, shift_amount);
800
        break;
801
    case A64_SHIFT_TYPE_ASR:
802
        if (!sf) {
803
            tcg_gen_ext32s_i64(dst, src);
804
        }
805
        tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
806
        break;
807
    case A64_SHIFT_TYPE_ROR:
808
        if (sf) {
809
            tcg_gen_rotr_i64(dst, src, shift_amount);
810
        } else {
811
            TCGv_i32 t0, t1;
812
            t0 = tcg_temp_new_i32();
813
            t1 = tcg_temp_new_i32();
814
            tcg_gen_trunc_i64_i32(t0, src);
815
            tcg_gen_trunc_i64_i32(t1, shift_amount);
816
            tcg_gen_rotr_i32(t0, t0, t1);
817
            tcg_gen_extu_i32_i64(dst, t0);
818
            tcg_temp_free_i32(t0);
819
            tcg_temp_free_i32(t1);
820
        }
821
        break;
822
    default:
823
        assert(FALSE); /* all shift types should be handled */
824
        break;
825
    }
826

    
827
    if (!sf) { /* zero extend final result */
828
        tcg_gen_ext32u_i64(dst, dst);
829
    }
830
}
831

    
832
/* Shift a TCGv src by immediate, put result in dst.
833
 * The shift amount must be in range (this should always be true as the
834
 * relevant instructions will UNDEF on bad shift immediates).
835
 */
836
static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
837
                          enum a64_shift_type shift_type, unsigned int shift_i)
838
{
839
    assert(shift_i < (sf ? 64 : 32));
840

    
841
    if (shift_i == 0) {
842
        tcg_gen_mov_i64(dst, src);
843
    } else {
844
        TCGv_i64 shift_const;
845

    
846
        shift_const = tcg_const_i64(shift_i);
847
        shift_reg(dst, src, sf, shift_type, shift_const);
848
        tcg_temp_free_i64(shift_const);
849
    }
850
}
851

    
852
/* C3.5.10 Logical (shifted register)
853
 *   31  30 29 28       24 23   22 21  20  16 15    10 9    5 4    0
854
 * +----+-----+-----------+-------+---+------+--------+------+------+
855
 * | sf | opc | 0 1 0 1 0 | shift | N |  Rm  |  imm6  |  Rn  |  Rd  |
856
 * +----+-----+-----------+-------+---+------+--------+------+------+
857
 */
858
static void disas_logic_reg(DisasContext *s, uint32_t insn)
859
{
860
    TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
861
    unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
862

    
863
    sf = extract32(insn, 31, 1);
864
    opc = extract32(insn, 29, 2);
865
    shift_type = extract32(insn, 22, 2);
866
    invert = extract32(insn, 21, 1);
867
    rm = extract32(insn, 16, 5);
868
    shift_amount = extract32(insn, 10, 6);
869
    rn = extract32(insn, 5, 5);
870
    rd = extract32(insn, 0, 5);
871

    
872
    if (!sf && (shift_amount & (1 << 5))) {
873
        unallocated_encoding(s);
874
        return;
875
    }
876

    
877
    tcg_rd = cpu_reg(s, rd);
878

    
879
    if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
880
        /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
881
         * register-register MOV and MVN, so it is worth special casing.
882
         */
883
        tcg_rm = cpu_reg(s, rm);
884
        if (invert) {
885
            tcg_gen_not_i64(tcg_rd, tcg_rm);
886
            if (!sf) {
887
                tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
888
            }
889
        } else {
890
            if (sf) {
891
                tcg_gen_mov_i64(tcg_rd, tcg_rm);
892
            } else {
893
                tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
894
            }
895
        }
896
        return;
897
    }
898

    
899
    tcg_rm = read_cpu_reg(s, rm, sf);
900

    
901
    if (shift_amount) {
902
        shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
903
    }
904

    
905
    tcg_rn = cpu_reg(s, rn);
906

    
907
    switch (opc | (invert << 2)) {
908
    case 0: /* AND */
909
    case 3: /* ANDS */
910
        tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
911
        break;
912
    case 1: /* ORR */
913
        tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
914
        break;
915
    case 2: /* EOR */
916
        tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
917
        break;
918
    case 4: /* BIC */
919
    case 7: /* BICS */
920
        tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
921
        break;
922
    case 5: /* ORN */
923
        tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
924
        break;
925
    case 6: /* EON */
926
        tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
927
        break;
928
    default:
929
        assert(FALSE);
930
        break;
931
    }
932

    
933
    if (!sf) {
934
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
935
    }
936

    
937
    if (opc == 3) {
938
        gen_logic_CC(sf, tcg_rd);
939
    }
940
}
941

    
942
/* Add/subtract (extended register) */
943
static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
944
{
945
    unsupported_encoding(s, insn);
946
}
947

    
948
/* Add/subtract (shifted register) */
949
static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
950
{
951
    unsupported_encoding(s, insn);
952
}
953

    
954
/* Data-processing (3 source) */
955
static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
956
{
957
    unsupported_encoding(s, insn);
958
}
959

    
960
/* Add/subtract (with carry) */
961
static void disas_adc_sbc(DisasContext *s, uint32_t insn)
962
{
963
    unsupported_encoding(s, insn);
964
}
965

    
966
/* Conditional compare (immediate) */
967
static void disas_cc_imm(DisasContext *s, uint32_t insn)
968
{
969
    unsupported_encoding(s, insn);
970
}
971

    
972
/* Conditional compare (register) */
973
static void disas_cc_reg(DisasContext *s, uint32_t insn)
974
{
975
    unsupported_encoding(s, insn);
976
}
977

    
978
/* C3.5.6 Conditional select
979
 *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
980
 * +----+----+---+-----------------+------+------+-----+------+------+
981
 * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
982
 * +----+----+---+-----------------+------+------+-----+------+------+
983
 */
984
static void disas_cond_select(DisasContext *s, uint32_t insn)
985
{
986
    unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
987
    TCGv_i64 tcg_rd, tcg_src;
988

    
989
    if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
990
        /* S == 1 or op2<1> == 1 */
991
        unallocated_encoding(s);
992
        return;
993
    }
994
    sf = extract32(insn, 31, 1);
995
    else_inv = extract32(insn, 30, 1);
996
    rm = extract32(insn, 16, 5);
997
    cond = extract32(insn, 12, 4);
998
    else_inc = extract32(insn, 10, 1);
999
    rn = extract32(insn, 5, 5);
1000
    rd = extract32(insn, 0, 5);
1001

    
1002
    if (rd == 31) {
1003
        /* silly no-op write; until we use movcond we must special-case
1004
         * this to avoid a dead temporary across basic blocks.
1005
         */
1006
        return;
1007
    }
1008

    
1009
    tcg_rd = cpu_reg(s, rd);
1010

    
1011
    if (cond >= 0x0e) { /* condition "always" */
1012
        tcg_src = read_cpu_reg(s, rn, sf);
1013
        tcg_gen_mov_i64(tcg_rd, tcg_src);
1014
    } else {
1015
        /* OPTME: we could use movcond here, at the cost of duplicating
1016
         * a lot of the arm_gen_test_cc() logic.
1017
         */
1018
        int label_match = gen_new_label();
1019
        int label_continue = gen_new_label();
1020

    
1021
        arm_gen_test_cc(cond, label_match);
1022
        /* nomatch: */
1023
        tcg_src = cpu_reg(s, rm);
1024

    
1025
        if (else_inv && else_inc) {
1026
            tcg_gen_neg_i64(tcg_rd, tcg_src);
1027
        } else if (else_inv) {
1028
            tcg_gen_not_i64(tcg_rd, tcg_src);
1029
        } else if (else_inc) {
1030
            tcg_gen_addi_i64(tcg_rd, tcg_src, 1);
1031
        } else {
1032
            tcg_gen_mov_i64(tcg_rd, tcg_src);
1033
        }
1034
        if (!sf) {
1035
            tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1036
        }
1037
        tcg_gen_br(label_continue);
1038
        /* match: */
1039
        gen_set_label(label_match);
1040
        tcg_src = read_cpu_reg(s, rn, sf);
1041
        tcg_gen_mov_i64(tcg_rd, tcg_src);
1042
        /* continue: */
1043
        gen_set_label(label_continue);
1044
    }
1045
}
1046

    
1047
static void handle_clz(DisasContext *s, unsigned int sf,
1048
                       unsigned int rn, unsigned int rd)
1049
{
1050
    TCGv_i64 tcg_rd, tcg_rn;
1051
    tcg_rd = cpu_reg(s, rd);
1052
    tcg_rn = cpu_reg(s, rn);
1053

    
1054
    if (sf) {
1055
        gen_helper_clz64(tcg_rd, tcg_rn);
1056
    } else {
1057
        TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
1058
        tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
1059
        gen_helper_clz(tcg_tmp32, tcg_tmp32);
1060
        tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
1061
        tcg_temp_free_i32(tcg_tmp32);
1062
    }
1063
}
1064

    
1065
static void handle_rbit(DisasContext *s, unsigned int sf,
1066
                        unsigned int rn, unsigned int rd)
1067
{
1068
    TCGv_i64 tcg_rd, tcg_rn;
1069
    tcg_rd = cpu_reg(s, rd);
1070
    tcg_rn = cpu_reg(s, rn);
1071

    
1072
    if (sf) {
1073
        gen_helper_rbit64(tcg_rd, tcg_rn);
1074
    } else {
1075
        TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
1076
        tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
1077
        gen_helper_rbit(tcg_tmp32, tcg_tmp32);
1078
        tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
1079
        tcg_temp_free_i32(tcg_tmp32);
1080
    }
1081
}
1082

    
1083
/* C3.5.7 Data-processing (1 source)
1084
 *   31  30  29  28             21 20     16 15    10 9    5 4    0
1085
 * +----+---+---+-----------------+---------+--------+------+------+
1086
 * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
1087
 * +----+---+---+-----------------+---------+--------+------+------+
1088
 */
1089
static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
1090
{
1091
    unsigned int sf, opcode, rn, rd;
1092

    
1093
    if (extract32(insn, 29, 1) || extract32(insn, 16, 5)) {
1094
        unallocated_encoding(s);
1095
        return;
1096
    }
1097

    
1098
    sf = extract32(insn, 31, 1);
1099
    opcode = extract32(insn, 10, 6);
1100
    rn = extract32(insn, 5, 5);
1101
    rd = extract32(insn, 0, 5);
1102

    
1103
    switch (opcode) {
1104
    case 0: /* RBIT */
1105
        handle_rbit(s, sf, rn, rd);
1106
        break;
1107
    case 1: /* REV16 */
1108
    case 2: /* REV32 */
1109
    case 3: /* REV64 */
1110
        unsupported_encoding(s, insn);
1111
        break;
1112
    case 4: /* CLZ */
1113
        handle_clz(s, sf, rn, rd);
1114
        break;
1115
    case 5: /* CLS */
1116
        unsupported_encoding(s, insn);
1117
        break;
1118
    }
1119
}
1120

    
1121
static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
1122
                       unsigned int rm, unsigned int rn, unsigned int rd)
1123
{
1124
    TCGv_i64 tcg_n, tcg_m, tcg_rd;
1125
    tcg_rd = cpu_reg(s, rd);
1126

    
1127
    if (!sf && is_signed) {
1128
        tcg_n = new_tmp_a64(s);
1129
        tcg_m = new_tmp_a64(s);
1130
        tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
1131
        tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
1132
    } else {
1133
        tcg_n = read_cpu_reg(s, rn, sf);
1134
        tcg_m = read_cpu_reg(s, rm, sf);
1135
    }
1136

    
1137
    if (is_signed) {
1138
        gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
1139
    } else {
1140
        gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
1141
    }
1142

    
1143
    if (!sf) { /* zero extend final result */
1144
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1145
    }
1146
}
1147

    
1148
/* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
1149
static void handle_shift_reg(DisasContext *s,
1150
                             enum a64_shift_type shift_type, unsigned int sf,
1151
                             unsigned int rm, unsigned int rn, unsigned int rd)
1152
{
1153
    TCGv_i64 tcg_shift = tcg_temp_new_i64();
1154
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
1155
    TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
1156

    
1157
    tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
1158
    shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
1159
    tcg_temp_free_i64(tcg_shift);
1160
}
1161

    
1162
/* C3.5.8 Data-processing (2 source)
1163
 *   31   30  29 28             21 20  16 15    10 9    5 4    0
1164
 * +----+---+---+-----------------+------+--------+------+------+
1165
 * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
1166
 * +----+---+---+-----------------+------+--------+------+------+
1167
 */
1168
static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
1169
{
1170
    unsigned int sf, rm, opcode, rn, rd;
1171
    sf = extract32(insn, 31, 1);
1172
    rm = extract32(insn, 16, 5);
1173
    opcode = extract32(insn, 10, 6);
1174
    rn = extract32(insn, 5, 5);
1175
    rd = extract32(insn, 0, 5);
1176

    
1177
    if (extract32(insn, 29, 1)) {
1178
        unallocated_encoding(s);
1179
        return;
1180
    }
1181

    
1182
    switch (opcode) {
1183
    case 2: /* UDIV */
1184
        handle_div(s, false, sf, rm, rn, rd);
1185
        break;
1186
    case 3: /* SDIV */
1187
        handle_div(s, true, sf, rm, rn, rd);
1188
        break;
1189
    case 8: /* LSLV */
1190
        handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
1191
        break;
1192
    case 9: /* LSRV */
1193
        handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
1194
        break;
1195
    case 10: /* ASRV */
1196
        handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
1197
        break;
1198
    case 11: /* RORV */
1199
        handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
1200
        break;
1201
    case 16:
1202
    case 17:
1203
    case 18:
1204
    case 19:
1205
    case 20:
1206
    case 21:
1207
    case 22:
1208
    case 23: /* CRC32 */
1209
        unsupported_encoding(s, insn);
1210
        break;
1211
    default:
1212
        unallocated_encoding(s);
1213
        break;
1214
    }
1215
}
1216

    
1217
/* C3.5 Data processing - register */
1218
static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
1219
{
1220
    switch (extract32(insn, 24, 5)) {
1221
    case 0x0a: /* Logical (shifted register) */
1222
        disas_logic_reg(s, insn);
1223
        break;
1224
    case 0x0b: /* Add/subtract */
1225
        if (insn & (1 << 21)) { /* (extended register) */
1226
            disas_add_sub_ext_reg(s, insn);
1227
        } else {
1228
            disas_add_sub_reg(s, insn);
1229
        }
1230
        break;
1231
    case 0x1b: /* Data-processing (3 source) */
1232
        disas_data_proc_3src(s, insn);
1233
        break;
1234
    case 0x1a:
1235
        switch (extract32(insn, 21, 3)) {
1236
        case 0x0: /* Add/subtract (with carry) */
1237
            disas_adc_sbc(s, insn);
1238
            break;
1239
        case 0x2: /* Conditional compare */
1240
            if (insn & (1 << 11)) { /* (immediate) */
1241
                disas_cc_imm(s, insn);
1242
            } else {            /* (register) */
1243
                disas_cc_reg(s, insn);
1244
            }
1245
            break;
1246
        case 0x4: /* Conditional select */
1247
            disas_cond_select(s, insn);
1248
            break;
1249
        case 0x6: /* Data-processing */
1250
            if (insn & (1 << 30)) { /* (1 source) */
1251
                disas_data_proc_1src(s, insn);
1252
            } else {            /* (2 source) */
1253
                disas_data_proc_2src(s, insn);
1254
            }
1255
            break;
1256
        default:
1257
            unallocated_encoding(s);
1258
            break;
1259
        }
1260
        break;
1261
    default:
1262
        unallocated_encoding(s);
1263
        break;
1264
    }
1265
}
1266

    
1267
/* C3.6 Data processing - SIMD and floating point */
1268
static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
1269
{
1270
    unsupported_encoding(s, insn);
1271
}
1272

    
1273
/* C3.1 A64 instruction index by encoding */
1274
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
1275
{
1276
    uint32_t insn;
1277

    
1278
    insn = arm_ldl_code(env, s->pc, s->bswap_code);
1279
    s->insn = insn;
1280
    s->pc += 4;
1281

    
1282
    switch (extract32(insn, 25, 4)) {
1283
    case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
1284
        unallocated_encoding(s);
1285
        break;
1286
    case 0x8: case 0x9: /* Data processing - immediate */
1287
        disas_data_proc_imm(s, insn);
1288
        break;
1289
    case 0xa: case 0xb: /* Branch, exception generation and system insns */
1290
        disas_b_exc_sys(s, insn);
1291
        break;
1292
    case 0x4:
1293
    case 0x6:
1294
    case 0xc:
1295
    case 0xe:      /* Loads and stores */
1296
        disas_ldst(s, insn);
1297
        break;
1298
    case 0x5:
1299
    case 0xd:      /* Data processing - register */
1300
        disas_data_proc_reg(s, insn);
1301
        break;
1302
    case 0x7:
1303
    case 0xf:      /* Data processing - SIMD and floating point */
1304
        disas_data_proc_simd_fp(s, insn);
1305
        break;
1306
    default:
1307
        assert(FALSE); /* all 15 cases should be handled above */
1308
        break;
1309
    }
1310

    
1311
    /* if we allocated any temporaries, free them here */
1312
    free_tmp_a64(s);
1313
}
1314

    
1315
void gen_intermediate_code_internal_a64(ARMCPU *cpu,
1316
                                        TranslationBlock *tb,
1317
                                        bool search_pc)
1318
{
1319
    CPUState *cs = CPU(cpu);
1320
    CPUARMState *env = &cpu->env;
1321
    DisasContext dc1, *dc = &dc1;
1322
    CPUBreakpoint *bp;
1323
    uint16_t *gen_opc_end;
1324
    int j, lj;
1325
    target_ulong pc_start;
1326
    target_ulong next_page_start;
1327
    int num_insns;
1328
    int max_insns;
1329

    
1330
    pc_start = tb->pc;
1331

    
1332
    dc->tb = tb;
1333

    
1334
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
1335

    
1336
    dc->is_jmp = DISAS_NEXT;
1337
    dc->pc = pc_start;
1338
    dc->singlestep_enabled = cs->singlestep_enabled;
1339
    dc->condjmp = 0;
1340

    
1341
    dc->aarch64 = 1;
1342
    dc->thumb = 0;
1343
    dc->bswap_code = 0;
1344
    dc->condexec_mask = 0;
1345
    dc->condexec_cond = 0;
1346
#if !defined(CONFIG_USER_ONLY)
1347
    dc->user = 0;
1348
#endif
1349
    dc->vfp_enabled = 0;
1350
    dc->vec_len = 0;
1351
    dc->vec_stride = 0;
1352

    
1353
    init_tmp_a64_array(dc);
1354

    
1355
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1356
    lj = -1;
1357
    num_insns = 0;
1358
    max_insns = tb->cflags & CF_COUNT_MASK;
1359
    if (max_insns == 0) {
1360
        max_insns = CF_COUNT_MASK;
1361
    }
1362

    
1363
    gen_tb_start();
1364

    
1365
    tcg_clear_temp_count();
1366

    
1367
    do {
1368
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
1369
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1370
                if (bp->pc == dc->pc) {
1371
                    gen_exception_insn(dc, 0, EXCP_DEBUG);
1372
                    /* Advance PC so that clearing the breakpoint will
1373
                       invalidate this TB.  */
1374
                    dc->pc += 2;
1375
                    goto done_generating;
1376
                }
1377
            }
1378
        }
1379

    
1380
        if (search_pc) {
1381
            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
1382
            if (lj < j) {
1383
                lj++;
1384
                while (lj < j) {
1385
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
1386
                }
1387
            }
1388
            tcg_ctx.gen_opc_pc[lj] = dc->pc;
1389
            tcg_ctx.gen_opc_instr_start[lj] = 1;
1390
            tcg_ctx.gen_opc_icount[lj] = num_insns;
1391
        }
1392

    
1393
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
1394
            gen_io_start();
1395
        }
1396

    
1397
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
1398
            tcg_gen_debug_insn_start(dc->pc);
1399
        }
1400

    
1401
        disas_a64_insn(env, dc);
1402

    
1403
        if (tcg_check_temp_count()) {
1404
            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
1405
                    dc->pc);
1406
        }
1407

    
1408
        /* Translation stops when a conditional branch is encountered.
1409
         * Otherwise the subsequent code could get translated several times.
1410
         * Also stop translation when a page boundary is reached.  This
1411
         * ensures prefetch aborts occur at the right place.
1412
         */
1413
        num_insns++;
1414
    } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
1415
             !cs->singlestep_enabled &&
1416
             !singlestep &&
1417
             dc->pc < next_page_start &&
1418
             num_insns < max_insns);
1419

    
1420
    if (tb->cflags & CF_LAST_IO) {
1421
        gen_io_end();
1422
    }
1423

    
1424
    if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
1425
        /* Note that this means single stepping WFI doesn't halt the CPU.
1426
         * For conditional branch insns this is harmless unreachable code as
1427
         * gen_goto_tb() has already handled emitting the debug exception
1428
         * (and thus a tb-jump is not possible when singlestepping).
1429
         */
1430
        assert(dc->is_jmp != DISAS_TB_JUMP);
1431
        if (dc->is_jmp != DISAS_JUMP) {
1432
            gen_a64_set_pc_im(dc->pc);
1433
        }
1434
        gen_exception(EXCP_DEBUG);
1435
    } else {
1436
        switch (dc->is_jmp) {
1437
        case DISAS_NEXT:
1438
            gen_goto_tb(dc, 1, dc->pc);
1439
            break;
1440
        default:
1441
        case DISAS_JUMP:
1442
        case DISAS_UPDATE:
1443
            /* indicate that the hash table must be used to find the next TB */
1444
            tcg_gen_exit_tb(0);
1445
            break;
1446
        case DISAS_TB_JUMP:
1447
        case DISAS_EXC:
1448
        case DISAS_SWI:
1449
            break;
1450
        case DISAS_WFI:
1451
            /* This is a special case because we don't want to just halt the CPU
1452
             * if trying to debug across a WFI.
1453
             */
1454
            gen_helper_wfi(cpu_env);
1455
            break;
1456
        }
1457
    }
1458

    
1459
done_generating:
1460
    gen_tb_end(tb, num_insns);
1461
    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
1462

    
1463
#ifdef DEBUG_DISAS
1464
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1465
        qemu_log("----------------\n");
1466
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
1467
        log_target_disas(env, pc_start, dc->pc - pc_start,
1468
                         dc->thumb | (dc->bswap_code << 1));
1469
        qemu_log("\n");
1470
    }
1471
#endif
1472
    if (search_pc) {
1473
        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
1474
        lj++;
1475
        while (lj <= j) {
1476
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
1477
        }
1478
    } else {
1479
        tb->size = dc->pc - pc_start;
1480
        tb->icount = num_insns;
1481
    }
1482
}