~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to .pc/arm64/0045-target-arm-A64-add-support-for-bitfield-insns.patch/target-arm/translate-a64.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-02-04 12:13:08 UTC
  • mfrom: (10.1.45 sid)
  • Revision ID: package-import@ubuntu.com-20140204121308-1xq92lrfs75agw2g
Tags: 1.7.0+dfsg-3ubuntu1~ppa1
* Merge 1.7.0+dfsg-3 from debian.  Remaining changes:
  - debian/patches/ubuntu:
    * expose-vmx_qemu64cpu.patch
    * linaro (omap3) and arm64 patches
    * ubuntu/target-ppc-add-stubs-for-kvm-breakpoints: fix FTBFS
      on ppc
    * ubuntu/CVE-2013-4377.patch: fix denial of service via virtio
  - debian/qemu-system-x86.modprobe: set kvm_intel nested=1 options
  - debian/control:
    * add arm64 to Architectures
    * add qemu-common and qemu-system-aarch64 packages
  - debian/qemu-system-common.install: add debian/tmp/usr/lib
  - debian/qemu-system-common.preinst: add kvm group
  - debian/qemu-system-common.postinst: remove acl placed by udev,
    and add udevadm trigger.
  - qemu-system-x86.links: add eepro100.rom, remove pxe-virtio,
    pxe-e1000 and pxe-rtl8139.
  - add qemu-system-x86.qemu-kvm.upstart and .default
  - qemu-user-static.postinst-in: remove arm64 binfmt
  - debian/rules:
    * allow parallel build
    * add aarch64 to system_targets and sys_systems
    * add qemu-kvm-spice links
    * install qemu-system-x86.modprobe
  - add debian/qemu-system-common.links for OVMF.fd link
* Remove kvm-img, kvm-nbd, kvm-ifup and kvm-ifdown symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
/* C5.6.149 REV with sf==1, opcode==3 ("REV64") */
1084
 
static void handle_rev64(DisasContext *s, unsigned int sf,
1085
 
                         unsigned int rn, unsigned int rd)
1086
 
{
1087
 
    if (!sf) {
1088
 
        unallocated_encoding(s);
1089
 
        return;
1090
 
    }
1091
 
    tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
1092
 
}
1093
 
 
1094
 
/* C5.6.149 REV with sf==0, opcode==2
1095
 
 * C5.6.151 REV32 (sf==1, opcode==2)
1096
 
 */
1097
 
static void handle_rev32(DisasContext *s, unsigned int sf,
1098
 
                         unsigned int rn, unsigned int rd)
1099
 
{
1100
 
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
1101
 
 
1102
 
    if (sf) {
1103
 
        TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1104
 
        TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
1105
 
 
1106
 
        /* bswap32_i64 requires zero high word */
1107
 
        tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
1108
 
        tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
1109
 
        tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
1110
 
        tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
1111
 
        tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
1112
 
 
1113
 
        tcg_temp_free_i64(tcg_tmp);
1114
 
    } else {
1115
 
        tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
1116
 
        tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
1117
 
    }
1118
 
}
1119
 
 
1120
 
/* C5.6.150 REV16 (opcode==1) */
1121
 
static void handle_rev16(DisasContext *s, unsigned int sf,
1122
 
                         unsigned int rn, unsigned int rd)
1123
 
{
1124
 
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
1125
 
    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1126
 
    TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
1127
 
 
1128
 
    tcg_gen_andi_i64(tcg_tmp, tcg_rn, 0xffff);
1129
 
    tcg_gen_bswap16_i64(tcg_rd, tcg_tmp);
1130
 
 
1131
 
    tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16);
1132
 
    tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
1133
 
    tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
1134
 
    tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 16, 16);
1135
 
 
1136
 
    if (sf) {
1137
 
        tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
1138
 
        tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
1139
 
        tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
1140
 
        tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 32, 16);
1141
 
 
1142
 
        tcg_gen_shri_i64(tcg_tmp, tcg_rn, 48);
1143
 
        tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
1144
 
        tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 48, 16);
1145
 
    }
1146
 
 
1147
 
    tcg_temp_free_i64(tcg_tmp);
1148
 
}
1149
 
 
1150
 
/* C3.5.7 Data-processing (1 source)
1151
 
 *   31  30  29  28             21 20     16 15    10 9    5 4    0
1152
 
 * +----+---+---+-----------------+---------+--------+------+------+
1153
 
 * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
1154
 
 * +----+---+---+-----------------+---------+--------+------+------+
1155
 
 */
1156
 
static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
1157
 
{
1158
 
    unsigned int sf, opcode, rn, rd;
1159
 
 
1160
 
    if (extract32(insn, 29, 1) || extract32(insn, 16, 5)) {
1161
 
        unallocated_encoding(s);
1162
 
        return;
1163
 
    }
1164
 
 
1165
 
    sf = extract32(insn, 31, 1);
1166
 
    opcode = extract32(insn, 10, 6);
1167
 
    rn = extract32(insn, 5, 5);
1168
 
    rd = extract32(insn, 0, 5);
1169
 
 
1170
 
    switch (opcode) {
1171
 
    case 0: /* RBIT */
1172
 
        handle_rbit(s, sf, rn, rd);
1173
 
        break;
1174
 
    case 1: /* REV16 */
1175
 
        handle_rev16(s, sf, rn, rd);
1176
 
        break;
1177
 
    case 2: /* REV32 */
1178
 
        handle_rev32(s, sf, rn, rd);
1179
 
        break;
1180
 
    case 3: /* REV64 */
1181
 
        handle_rev64(s, sf, rn, rd);
1182
 
        break;
1183
 
    case 4: /* CLZ */
1184
 
        handle_clz(s, sf, rn, rd);
1185
 
        break;
1186
 
    case 5: /* CLS */
1187
 
        unsupported_encoding(s, insn);
1188
 
        break;
1189
 
    }
1190
 
}
1191
 
 
1192
 
static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
1193
 
                       unsigned int rm, unsigned int rn, unsigned int rd)
1194
 
{
1195
 
    TCGv_i64 tcg_n, tcg_m, tcg_rd;
1196
 
    tcg_rd = cpu_reg(s, rd);
1197
 
 
1198
 
    if (!sf && is_signed) {
1199
 
        tcg_n = new_tmp_a64(s);
1200
 
        tcg_m = new_tmp_a64(s);
1201
 
        tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
1202
 
        tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
1203
 
    } else {
1204
 
        tcg_n = read_cpu_reg(s, rn, sf);
1205
 
        tcg_m = read_cpu_reg(s, rm, sf);
1206
 
    }
1207
 
 
1208
 
    if (is_signed) {
1209
 
        gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
1210
 
    } else {
1211
 
        gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
1212
 
    }
1213
 
 
1214
 
    if (!sf) { /* zero extend final result */
1215
 
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
1216
 
    }
1217
 
}
1218
 
 
1219
 
/* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
1220
 
static void handle_shift_reg(DisasContext *s,
1221
 
                             enum a64_shift_type shift_type, unsigned int sf,
1222
 
                             unsigned int rm, unsigned int rn, unsigned int rd)
1223
 
{
1224
 
    TCGv_i64 tcg_shift = tcg_temp_new_i64();
1225
 
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
1226
 
    TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
1227
 
 
1228
 
    tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
1229
 
    shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
1230
 
    tcg_temp_free_i64(tcg_shift);
1231
 
}
1232
 
 
1233
 
/* C3.5.8 Data-processing (2 source)
1234
 
 *   31   30  29 28             21 20  16 15    10 9    5 4    0
1235
 
 * +----+---+---+-----------------+------+--------+------+------+
1236
 
 * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
1237
 
 * +----+---+---+-----------------+------+--------+------+------+
1238
 
 */
1239
 
static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
1240
 
{
1241
 
    unsigned int sf, rm, opcode, rn, rd;
1242
 
    sf = extract32(insn, 31, 1);
1243
 
    rm = extract32(insn, 16, 5);
1244
 
    opcode = extract32(insn, 10, 6);
1245
 
    rn = extract32(insn, 5, 5);
1246
 
    rd = extract32(insn, 0, 5);
1247
 
 
1248
 
    if (extract32(insn, 29, 1)) {
1249
 
        unallocated_encoding(s);
1250
 
        return;
1251
 
    }
1252
 
 
1253
 
    switch (opcode) {
1254
 
    case 2: /* UDIV */
1255
 
        handle_div(s, false, sf, rm, rn, rd);
1256
 
        break;
1257
 
    case 3: /* SDIV */
1258
 
        handle_div(s, true, sf, rm, rn, rd);
1259
 
        break;
1260
 
    case 8: /* LSLV */
1261
 
        handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
1262
 
        break;
1263
 
    case 9: /* LSRV */
1264
 
        handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
1265
 
        break;
1266
 
    case 10: /* ASRV */
1267
 
        handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
1268
 
        break;
1269
 
    case 11: /* RORV */
1270
 
        handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
1271
 
        break;
1272
 
    case 16:
1273
 
    case 17:
1274
 
    case 18:
1275
 
    case 19:
1276
 
    case 20:
1277
 
    case 21:
1278
 
    case 22:
1279
 
    case 23: /* CRC32 */
1280
 
        unsupported_encoding(s, insn);
1281
 
        break;
1282
 
    default:
1283
 
        unallocated_encoding(s);
1284
 
        break;
1285
 
    }
1286
 
}
1287
 
 
1288
 
/* C3.5 Data processing - register */
1289
 
static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
1290
 
{
1291
 
    switch (extract32(insn, 24, 5)) {
1292
 
    case 0x0a: /* Logical (shifted register) */
1293
 
        disas_logic_reg(s, insn);
1294
 
        break;
1295
 
    case 0x0b: /* Add/subtract */
1296
 
        if (insn & (1 << 21)) { /* (extended register) */
1297
 
            disas_add_sub_ext_reg(s, insn);
1298
 
        } else {
1299
 
            disas_add_sub_reg(s, insn);
1300
 
        }
1301
 
        break;
1302
 
    case 0x1b: /* Data-processing (3 source) */
1303
 
        disas_data_proc_3src(s, insn);
1304
 
        break;
1305
 
    case 0x1a:
1306
 
        switch (extract32(insn, 21, 3)) {
1307
 
        case 0x0: /* Add/subtract (with carry) */
1308
 
            disas_adc_sbc(s, insn);
1309
 
            break;
1310
 
        case 0x2: /* Conditional compare */
1311
 
            if (insn & (1 << 11)) { /* (immediate) */
1312
 
                disas_cc_imm(s, insn);
1313
 
            } else {            /* (register) */
1314
 
                disas_cc_reg(s, insn);
1315
 
            }
1316
 
            break;
1317
 
        case 0x4: /* Conditional select */
1318
 
            disas_cond_select(s, insn);
1319
 
            break;
1320
 
        case 0x6: /* Data-processing */
1321
 
            if (insn & (1 << 30)) { /* (1 source) */
1322
 
                disas_data_proc_1src(s, insn);
1323
 
            } else {            /* (2 source) */
1324
 
                disas_data_proc_2src(s, insn);
1325
 
            }
1326
 
            break;
1327
 
        default:
1328
 
            unallocated_encoding(s);
1329
 
            break;
1330
 
        }
1331
 
        break;
1332
 
    default:
1333
 
        unallocated_encoding(s);
1334
 
        break;
1335
 
    }
1336
 
}
1337
 
 
1338
 
/* C3.6 Data processing - SIMD and floating point */
1339
 
static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
1340
 
{
1341
 
    unsupported_encoding(s, insn);
1342
 
}
1343
 
 
1344
 
/* C3.1 A64 instruction index by encoding */
1345
 
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
1346
 
{
1347
 
    uint32_t insn;
1348
 
 
1349
 
    insn = arm_ldl_code(env, s->pc, s->bswap_code);
1350
 
    s->insn = insn;
1351
 
    s->pc += 4;
1352
 
 
1353
 
    switch (extract32(insn, 25, 4)) {
1354
 
    case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
1355
 
        unallocated_encoding(s);
1356
 
        break;
1357
 
    case 0x8: case 0x9: /* Data processing - immediate */
1358
 
        disas_data_proc_imm(s, insn);
1359
 
        break;
1360
 
    case 0xa: case 0xb: /* Branch, exception generation and system insns */
1361
 
        disas_b_exc_sys(s, insn);
1362
 
        break;
1363
 
    case 0x4:
1364
 
    case 0x6:
1365
 
    case 0xc:
1366
 
    case 0xe:      /* Loads and stores */
1367
 
        disas_ldst(s, insn);
1368
 
        break;
1369
 
    case 0x5:
1370
 
    case 0xd:      /* Data processing - register */
1371
 
        disas_data_proc_reg(s, insn);
1372
 
        break;
1373
 
    case 0x7:
1374
 
    case 0xf:      /* Data processing - SIMD and floating point */
1375
 
        disas_data_proc_simd_fp(s, insn);
1376
 
        break;
1377
 
    default:
1378
 
        assert(FALSE); /* all 15 cases should be handled above */
1379
 
        break;
1380
 
    }
1381
 
 
1382
 
    /* if we allocated any temporaries, free them here */
1383
 
    free_tmp_a64(s);
1384
 
}
1385
 
 
1386
 
void gen_intermediate_code_internal_a64(ARMCPU *cpu,
1387
 
                                        TranslationBlock *tb,
1388
 
                                        bool search_pc)
1389
 
{
1390
 
    CPUState *cs = CPU(cpu);
1391
 
    CPUARMState *env = &cpu->env;
1392
 
    DisasContext dc1, *dc = &dc1;
1393
 
    CPUBreakpoint *bp;
1394
 
    uint16_t *gen_opc_end;
1395
 
    int j, lj;
1396
 
    target_ulong pc_start;
1397
 
    target_ulong next_page_start;
1398
 
    int num_insns;
1399
 
    int max_insns;
1400
 
 
1401
 
    pc_start = tb->pc;
1402
 
 
1403
 
    dc->tb = tb;
1404
 
 
1405
 
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
1406
 
 
1407
 
    dc->is_jmp = DISAS_NEXT;
1408
 
    dc->pc = pc_start;
1409
 
    dc->singlestep_enabled = cs->singlestep_enabled;
1410
 
    dc->condjmp = 0;
1411
 
 
1412
 
    dc->aarch64 = 1;
1413
 
    dc->thumb = 0;
1414
 
    dc->bswap_code = 0;
1415
 
    dc->condexec_mask = 0;
1416
 
    dc->condexec_cond = 0;
1417
 
#if !defined(CONFIG_USER_ONLY)
1418
 
    dc->user = 0;
1419
 
#endif
1420
 
    dc->vfp_enabled = 0;
1421
 
    dc->vec_len = 0;
1422
 
    dc->vec_stride = 0;
1423
 
 
1424
 
    init_tmp_a64_array(dc);
1425
 
 
1426
 
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1427
 
    lj = -1;
1428
 
    num_insns = 0;
1429
 
    max_insns = tb->cflags & CF_COUNT_MASK;
1430
 
    if (max_insns == 0) {
1431
 
        max_insns = CF_COUNT_MASK;
1432
 
    }
1433
 
 
1434
 
    gen_tb_start();
1435
 
 
1436
 
    tcg_clear_temp_count();
1437
 
 
1438
 
    do {
1439
 
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
1440
 
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1441
 
                if (bp->pc == dc->pc) {
1442
 
                    gen_exception_insn(dc, 0, EXCP_DEBUG);
1443
 
                    /* Advance PC so that clearing the breakpoint will
1444
 
                       invalidate this TB.  */
1445
 
                    dc->pc += 2;
1446
 
                    goto done_generating;
1447
 
                }
1448
 
            }
1449
 
        }
1450
 
 
1451
 
        if (search_pc) {
1452
 
            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
1453
 
            if (lj < j) {
1454
 
                lj++;
1455
 
                while (lj < j) {
1456
 
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
1457
 
                }
1458
 
            }
1459
 
            tcg_ctx.gen_opc_pc[lj] = dc->pc;
1460
 
            tcg_ctx.gen_opc_instr_start[lj] = 1;
1461
 
            tcg_ctx.gen_opc_icount[lj] = num_insns;
1462
 
        }
1463
 
 
1464
 
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
1465
 
            gen_io_start();
1466
 
        }
1467
 
 
1468
 
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
1469
 
            tcg_gen_debug_insn_start(dc->pc);
1470
 
        }
1471
 
 
1472
 
        disas_a64_insn(env, dc);
1473
 
 
1474
 
        if (tcg_check_temp_count()) {
1475
 
            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
1476
 
                    dc->pc);
1477
 
        }
1478
 
 
1479
 
        /* Translation stops when a conditional branch is encountered.
1480
 
         * Otherwise the subsequent code could get translated several times.
1481
 
         * Also stop translation when a page boundary is reached.  This
1482
 
         * ensures prefetch aborts occur at the right place.
1483
 
         */
1484
 
        num_insns++;
1485
 
    } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
1486
 
             !cs->singlestep_enabled &&
1487
 
             !singlestep &&
1488
 
             dc->pc < next_page_start &&
1489
 
             num_insns < max_insns);
1490
 
 
1491
 
    if (tb->cflags & CF_LAST_IO) {
1492
 
        gen_io_end();
1493
 
    }
1494
 
 
1495
 
    if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
1496
 
        /* Note that this means single stepping WFI doesn't halt the CPU.
1497
 
         * For conditional branch insns this is harmless unreachable code as
1498
 
         * gen_goto_tb() has already handled emitting the debug exception
1499
 
         * (and thus a tb-jump is not possible when singlestepping).
1500
 
         */
1501
 
        assert(dc->is_jmp != DISAS_TB_JUMP);
1502
 
        if (dc->is_jmp != DISAS_JUMP) {
1503
 
            gen_a64_set_pc_im(dc->pc);
1504
 
        }
1505
 
        gen_exception(EXCP_DEBUG);
1506
 
    } else {
1507
 
        switch (dc->is_jmp) {
1508
 
        case DISAS_NEXT:
1509
 
            gen_goto_tb(dc, 1, dc->pc);
1510
 
            break;
1511
 
        default:
1512
 
        case DISAS_JUMP:
1513
 
        case DISAS_UPDATE:
1514
 
            /* indicate that the hash table must be used to find the next TB */
1515
 
            tcg_gen_exit_tb(0);
1516
 
            break;
1517
 
        case DISAS_TB_JUMP:
1518
 
        case DISAS_EXC:
1519
 
        case DISAS_SWI:
1520
 
            break;
1521
 
        case DISAS_WFI:
1522
 
            /* This is a special case because we don't want to just halt the CPU
1523
 
             * if trying to debug across a WFI.
1524
 
             */
1525
 
            gen_helper_wfi(cpu_env);
1526
 
            break;
1527
 
        }
1528
 
    }
1529
 
 
1530
 
done_generating:
1531
 
    gen_tb_end(tb, num_insns);
1532
 
    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
1533
 
 
1534
 
#ifdef DEBUG_DISAS
1535
 
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1536
 
        qemu_log("----------------\n");
1537
 
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
1538
 
        log_target_disas(env, pc_start, dc->pc - pc_start,
1539
 
                         dc->thumb | (dc->bswap_code << 1));
1540
 
        qemu_log("\n");
1541
 
    }
1542
 
#endif
1543
 
    if (search_pc) {
1544
 
        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
1545
 
        lj++;
1546
 
        while (lj <= j) {
1547
 
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
1548
 
        }
1549
 
    } else {
1550
 
        tb->size = dc->pc - pc_start;
1551
 
        tb->icount = num_insns;
1552
 
    }
1553
 
}