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

« back to all changes in this revision

Viewing changes to .pc/ubuntu/arm64/0047-target-arm-A64-add-support-for-1-src-CLS-insn.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
/* C3.4.2 Bitfield
 
702
 *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
 
703
 * +----+-----+-------------+---+------+------+------+------+
 
704
 * | sf | opc | 1 0 0 1 1 0 | N | immr | imms |  Rn  |  Rd  |
 
705
 * +----+-----+-------------+---+------+------+------+------+
 
706
 */
 
707
static void disas_bitfield(DisasContext *s, uint32_t insn)
 
708
{
 
709
    unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
 
710
    TCGv_i64 tcg_rd, tcg_tmp;
 
711
 
 
712
    sf = extract32(insn, 31, 1);
 
713
    opc = extract32(insn, 29, 2);
 
714
    n = extract32(insn, 22, 1);
 
715
    ri = extract32(insn, 16, 6);
 
716
    si = extract32(insn, 10, 6);
 
717
    rn = extract32(insn, 5, 5);
 
718
    rd = extract32(insn, 0, 5);
 
719
    bitsize = sf ? 64 : 32;
 
720
 
 
721
    if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
 
722
        unallocated_encoding(s);
 
723
        return;
 
724
    }
 
725
 
 
726
    tcg_rd = cpu_reg(s, rd);
 
727
    tcg_tmp = read_cpu_reg(s, rn, sf);
 
728
 
 
729
    /* OPTME: probably worth recognizing common cases of ext{8,16,32}{u,s} */
 
730
 
 
731
    if (opc != 1) { /* SBFM or UBFM */
 
732
        tcg_gen_movi_i64(tcg_rd, 0);
 
733
    }
 
734
 
 
735
    /* do the bit move operation */
 
736
    if (si >= ri) {
 
737
        /* Wd<s-r:0> = Wn<s:r> */
 
738
        tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
 
739
        pos = 0;
 
740
        len = (si - ri) + 1;
 
741
    } else {
 
742
        /* Wd<32+s-r,32-r> = Wn<s:0> */
 
743
        pos = bitsize - ri;
 
744
        len = si + 1;
 
745
    }
 
746
 
 
747
    tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
 
748
 
 
749
    if (opc == 0) { /* SBFM - sign extend the destination field */
 
750
        tcg_gen_shli_i64(tcg_rd, tcg_rd, 64 - (pos + len));
 
751
        tcg_gen_sari_i64(tcg_rd, tcg_rd, 64 - (pos + len));
 
752
    }
 
753
 
 
754
    if (!sf) { /* zero extend final result */
 
755
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
 
756
    }
 
757
}
 
758
 
 
759
/* C3.4.3 Extract
 
760
 *   31  30  29 28         23 22   21  20  16 15    10 9    5 4    0
 
761
 * +----+------+-------------+---+----+------+--------+------+------+
 
762
 * | sf | op21 | 1 0 0 1 1 1 | N | o0 |  Rm  |  imms  |  Rn  |  Rd  |
 
763
 * +----+------+-------------+---+----+------+--------+------+------+
 
764
 */
 
765
static void disas_extract(DisasContext *s, uint32_t insn)
 
766
{
 
767
    unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
 
768
 
 
769
    sf = extract32(insn, 31, 1);
 
770
    n = extract32(insn, 22, 1);
 
771
    rm = extract32(insn, 16, 5);
 
772
    imm = extract32(insn, 10, 6);
 
773
    rn = extract32(insn, 5, 5);
 
774
    rd = extract32(insn, 0, 5);
 
775
    op21 = extract32(insn, 29, 2);
 
776
    op0 = extract32(insn, 21, 1);
 
777
    bitsize = sf ? 64 : 32;
 
778
 
 
779
    if (sf != n || op21 || op0 || imm >= bitsize) {
 
780
        unallocated_encoding(s);
 
781
    } else {
 
782
        TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
 
783
 
 
784
        tcg_rd = cpu_reg(s, rd);
 
785
 
 
786
        if (imm) {
 
787
            /* OPTME: we can special case rm==rn as a rotate */
 
788
            tcg_rm = read_cpu_reg(s, rm, sf);
 
789
            tcg_rn = read_cpu_reg(s, rn, sf);
 
790
            tcg_gen_shri_i64(tcg_rm, tcg_rm, imm);
 
791
            tcg_gen_shli_i64(tcg_rn, tcg_rn, bitsize - imm);
 
792
            tcg_gen_or_i64(tcg_rd, tcg_rm, tcg_rn);
 
793
            if (!sf) {
 
794
                tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
 
795
            }
 
796
        } else {
 
797
            /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
 
798
             * so an extract from bit 0 is a special case.
 
799
             */
 
800
            if (sf) {
 
801
                tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
 
802
            } else {
 
803
                tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
 
804
            }
 
805
        }
 
806
 
 
807
    }
 
808
}
 
809
 
 
810
/* C3.4 Data processing - immediate */
 
811
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
 
812
{
 
813
    switch (extract32(insn, 23, 6)) {
 
814
    case 0x20: case 0x21: /* PC-rel. addressing */
 
815
        disas_pc_rel_adr(s, insn);
 
816
        break;
 
817
    case 0x22: case 0x23: /* Add/subtract (immediate) */
 
818
        disas_add_sub_imm(s, insn);
 
819
        break;
 
820
    case 0x24: /* Logical (immediate) */
 
821
        disas_logic_imm(s, insn);
 
822
        break;
 
823
    case 0x25: /* Move wide (immediate) */
 
824
        disas_movw_imm(s, insn);
 
825
        break;
 
826
    case 0x26: /* Bitfield */
 
827
        disas_bitfield(s, insn);
 
828
        break;
 
829
    case 0x27: /* Extract */
 
830
        disas_extract(s, insn);
 
831
        break;
 
832
    default:
 
833
        unallocated_encoding(s);
 
834
        break;
 
835
    }
 
836
}
 
837
 
 
838
/* Shift a TCGv src by TCGv shift_amount, put result in dst.
 
839
 * Note that it is the caller's responsibility to ensure that the
 
840
 * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
 
841
 * mandated semantics for out of range shifts.
 
842
 */
 
843
static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
 
844
                      enum a64_shift_type shift_type, TCGv_i64 shift_amount)
 
845
{
 
846
    switch (shift_type) {
 
847
    case A64_SHIFT_TYPE_LSL:
 
848
        tcg_gen_shl_i64(dst, src, shift_amount);
 
849
        break;
 
850
    case A64_SHIFT_TYPE_LSR:
 
851
        tcg_gen_shr_i64(dst, src, shift_amount);
 
852
        break;
 
853
    case A64_SHIFT_TYPE_ASR:
 
854
        if (!sf) {
 
855
            tcg_gen_ext32s_i64(dst, src);
 
856
        }
 
857
        tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
 
858
        break;
 
859
    case A64_SHIFT_TYPE_ROR:
 
860
        if (sf) {
 
861
            tcg_gen_rotr_i64(dst, src, shift_amount);
 
862
        } else {
 
863
            TCGv_i32 t0, t1;
 
864
            t0 = tcg_temp_new_i32();
 
865
            t1 = tcg_temp_new_i32();
 
866
            tcg_gen_trunc_i64_i32(t0, src);
 
867
            tcg_gen_trunc_i64_i32(t1, shift_amount);
 
868
            tcg_gen_rotr_i32(t0, t0, t1);
 
869
            tcg_gen_extu_i32_i64(dst, t0);
 
870
            tcg_temp_free_i32(t0);
 
871
            tcg_temp_free_i32(t1);
 
872
        }
 
873
        break;
 
874
    default:
 
875
        assert(FALSE); /* all shift types should be handled */
 
876
        break;
 
877
    }
 
878
 
 
879
    if (!sf) { /* zero extend final result */
 
880
        tcg_gen_ext32u_i64(dst, dst);
 
881
    }
 
882
}
 
883
 
 
884
/* Shift a TCGv src by immediate, put result in dst.
 
885
 * The shift amount must be in range (this should always be true as the
 
886
 * relevant instructions will UNDEF on bad shift immediates).
 
887
 */
 
888
static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
 
889
                          enum a64_shift_type shift_type, unsigned int shift_i)
 
890
{
 
891
    assert(shift_i < (sf ? 64 : 32));
 
892
 
 
893
    if (shift_i == 0) {
 
894
        tcg_gen_mov_i64(dst, src);
 
895
    } else {
 
896
        TCGv_i64 shift_const;
 
897
 
 
898
        shift_const = tcg_const_i64(shift_i);
 
899
        shift_reg(dst, src, sf, shift_type, shift_const);
 
900
        tcg_temp_free_i64(shift_const);
 
901
    }
 
902
}
 
903
 
 
904
/* C3.5.10 Logical (shifted register)
 
905
 *   31  30 29 28       24 23   22 21  20  16 15    10 9    5 4    0
 
906
 * +----+-----+-----------+-------+---+------+--------+------+------+
 
907
 * | sf | opc | 0 1 0 1 0 | shift | N |  Rm  |  imm6  |  Rn  |  Rd  |
 
908
 * +----+-----+-----------+-------+---+------+--------+------+------+
 
909
 */
 
910
static void disas_logic_reg(DisasContext *s, uint32_t insn)
 
911
{
 
912
    TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
 
913
    unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
 
914
 
 
915
    sf = extract32(insn, 31, 1);
 
916
    opc = extract32(insn, 29, 2);
 
917
    shift_type = extract32(insn, 22, 2);
 
918
    invert = extract32(insn, 21, 1);
 
919
    rm = extract32(insn, 16, 5);
 
920
    shift_amount = extract32(insn, 10, 6);
 
921
    rn = extract32(insn, 5, 5);
 
922
    rd = extract32(insn, 0, 5);
 
923
 
 
924
    if (!sf && (shift_amount & (1 << 5))) {
 
925
        unallocated_encoding(s);
 
926
        return;
 
927
    }
 
928
 
 
929
    tcg_rd = cpu_reg(s, rd);
 
930
 
 
931
    if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
 
932
        /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
 
933
         * register-register MOV and MVN, so it is worth special casing.
 
934
         */
 
935
        tcg_rm = cpu_reg(s, rm);
 
936
        if (invert) {
 
937
            tcg_gen_not_i64(tcg_rd, tcg_rm);
 
938
            if (!sf) {
 
939
                tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
 
940
            }
 
941
        } else {
 
942
            if (sf) {
 
943
                tcg_gen_mov_i64(tcg_rd, tcg_rm);
 
944
            } else {
 
945
                tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
 
946
            }
 
947
        }
 
948
        return;
 
949
    }
 
950
 
 
951
    tcg_rm = read_cpu_reg(s, rm, sf);
 
952
 
 
953
    if (shift_amount) {
 
954
        shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
 
955
    }
 
956
 
 
957
    tcg_rn = cpu_reg(s, rn);
 
958
 
 
959
    switch (opc | (invert << 2)) {
 
960
    case 0: /* AND */
 
961
    case 3: /* ANDS */
 
962
        tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
 
963
        break;
 
964
    case 1: /* ORR */
 
965
        tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
 
966
        break;
 
967
    case 2: /* EOR */
 
968
        tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
 
969
        break;
 
970
    case 4: /* BIC */
 
971
    case 7: /* BICS */
 
972
        tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
 
973
        break;
 
974
    case 5: /* ORN */
 
975
        tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
 
976
        break;
 
977
    case 6: /* EON */
 
978
        tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
 
979
        break;
 
980
    default:
 
981
        assert(FALSE);
 
982
        break;
 
983
    }
 
984
 
 
985
    if (!sf) {
 
986
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
 
987
    }
 
988
 
 
989
    if (opc == 3) {
 
990
        gen_logic_CC(sf, tcg_rd);
 
991
    }
 
992
}
 
993
 
 
994
/* Add/subtract (extended register) */
 
995
static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
 
996
{
 
997
    unsupported_encoding(s, insn);
 
998
}
 
999
 
 
1000
/* Add/subtract (shifted register) */
 
1001
static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
 
1002
{
 
1003
    unsupported_encoding(s, insn);
 
1004
}
 
1005
 
 
1006
/* Data-processing (3 source) */
 
1007
static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
 
1008
{
 
1009
    unsupported_encoding(s, insn);
 
1010
}
 
1011
 
 
1012
/* Add/subtract (with carry) */
 
1013
static void disas_adc_sbc(DisasContext *s, uint32_t insn)
 
1014
{
 
1015
    unsupported_encoding(s, insn);
 
1016
}
 
1017
 
 
1018
/* Conditional compare (immediate) */
 
1019
static void disas_cc_imm(DisasContext *s, uint32_t insn)
 
1020
{
 
1021
    unsupported_encoding(s, insn);
 
1022
}
 
1023
 
 
1024
/* Conditional compare (register) */
 
1025
static void disas_cc_reg(DisasContext *s, uint32_t insn)
 
1026
{
 
1027
    unsupported_encoding(s, insn);
 
1028
}
 
1029
 
 
1030
/* C3.5.6 Conditional select
 
1031
 *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
 
1032
 * +----+----+---+-----------------+------+------+-----+------+------+
 
1033
 * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
 
1034
 * +----+----+---+-----------------+------+------+-----+------+------+
 
1035
 */
 
1036
static void disas_cond_select(DisasContext *s, uint32_t insn)
 
1037
{
 
1038
    unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
 
1039
    TCGv_i64 tcg_rd, tcg_src;
 
1040
 
 
1041
    if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
 
1042
        /* S == 1 or op2<1> == 1 */
 
1043
        unallocated_encoding(s);
 
1044
        return;
 
1045
    }
 
1046
    sf = extract32(insn, 31, 1);
 
1047
    else_inv = extract32(insn, 30, 1);
 
1048
    rm = extract32(insn, 16, 5);
 
1049
    cond = extract32(insn, 12, 4);
 
1050
    else_inc = extract32(insn, 10, 1);
 
1051
    rn = extract32(insn, 5, 5);
 
1052
    rd = extract32(insn, 0, 5);
 
1053
 
 
1054
    if (rd == 31) {
 
1055
        /* silly no-op write; until we use movcond we must special-case
 
1056
         * this to avoid a dead temporary across basic blocks.
 
1057
         */
 
1058
        return;
 
1059
    }
 
1060
 
 
1061
    tcg_rd = cpu_reg(s, rd);
 
1062
 
 
1063
    if (cond >= 0x0e) { /* condition "always" */
 
1064
        tcg_src = read_cpu_reg(s, rn, sf);
 
1065
        tcg_gen_mov_i64(tcg_rd, tcg_src);
 
1066
    } else {
 
1067
        /* OPTME: we could use movcond here, at the cost of duplicating
 
1068
         * a lot of the arm_gen_test_cc() logic.
 
1069
         */
 
1070
        int label_match = gen_new_label();
 
1071
        int label_continue = gen_new_label();
 
1072
 
 
1073
        arm_gen_test_cc(cond, label_match);
 
1074
        /* nomatch: */
 
1075
        tcg_src = cpu_reg(s, rm);
 
1076
 
 
1077
        if (else_inv && else_inc) {
 
1078
            tcg_gen_neg_i64(tcg_rd, tcg_src);
 
1079
        } else if (else_inv) {
 
1080
            tcg_gen_not_i64(tcg_rd, tcg_src);
 
1081
        } else if (else_inc) {
 
1082
            tcg_gen_addi_i64(tcg_rd, tcg_src, 1);
 
1083
        } else {
 
1084
            tcg_gen_mov_i64(tcg_rd, tcg_src);
 
1085
        }
 
1086
        if (!sf) {
 
1087
            tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
 
1088
        }
 
1089
        tcg_gen_br(label_continue);
 
1090
        /* match: */
 
1091
        gen_set_label(label_match);
 
1092
        tcg_src = read_cpu_reg(s, rn, sf);
 
1093
        tcg_gen_mov_i64(tcg_rd, tcg_src);
 
1094
        /* continue: */
 
1095
        gen_set_label(label_continue);
 
1096
    }
 
1097
}
 
1098
 
 
1099
static void handle_clz(DisasContext *s, unsigned int sf,
 
1100
                       unsigned int rn, unsigned int rd)
 
1101
{
 
1102
    TCGv_i64 tcg_rd, tcg_rn;
 
1103
    tcg_rd = cpu_reg(s, rd);
 
1104
    tcg_rn = cpu_reg(s, rn);
 
1105
 
 
1106
    if (sf) {
 
1107
        gen_helper_clz64(tcg_rd, tcg_rn);
 
1108
    } else {
 
1109
        TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
 
1110
        tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
 
1111
        gen_helper_clz(tcg_tmp32, tcg_tmp32);
 
1112
        tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
 
1113
        tcg_temp_free_i32(tcg_tmp32);
 
1114
    }
 
1115
}
 
1116
 
 
1117
static void handle_rbit(DisasContext *s, unsigned int sf,
 
1118
                        unsigned int rn, unsigned int rd)
 
1119
{
 
1120
    TCGv_i64 tcg_rd, tcg_rn;
 
1121
    tcg_rd = cpu_reg(s, rd);
 
1122
    tcg_rn = cpu_reg(s, rn);
 
1123
 
 
1124
    if (sf) {
 
1125
        gen_helper_rbit64(tcg_rd, tcg_rn);
 
1126
    } else {
 
1127
        TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
 
1128
        tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
 
1129
        gen_helper_rbit(tcg_tmp32, tcg_tmp32);
 
1130
        tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
 
1131
        tcg_temp_free_i32(tcg_tmp32);
 
1132
    }
 
1133
}
 
1134
 
 
1135
/* C5.6.149 REV with sf==1, opcode==3 ("REV64") */
 
1136
static void handle_rev64(DisasContext *s, unsigned int sf,
 
1137
                         unsigned int rn, unsigned int rd)
 
1138
{
 
1139
    if (!sf) {
 
1140
        unallocated_encoding(s);
 
1141
        return;
 
1142
    }
 
1143
    tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
 
1144
}
 
1145
 
 
1146
/* C5.6.149 REV with sf==0, opcode==2
 
1147
 * C5.6.151 REV32 (sf==1, opcode==2)
 
1148
 */
 
1149
static void handle_rev32(DisasContext *s, unsigned int sf,
 
1150
                         unsigned int rn, unsigned int rd)
 
1151
{
 
1152
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
 
1153
 
 
1154
    if (sf) {
 
1155
        TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 
1156
        TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
 
1157
 
 
1158
        /* bswap32_i64 requires zero high word */
 
1159
        tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
 
1160
        tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
 
1161
        tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
 
1162
        tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
 
1163
        tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
 
1164
 
 
1165
        tcg_temp_free_i64(tcg_tmp);
 
1166
    } else {
 
1167
        tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
 
1168
        tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
 
1169
    }
 
1170
}
 
1171
 
 
1172
/* C5.6.150 REV16 (opcode==1) */
 
1173
static void handle_rev16(DisasContext *s, unsigned int sf,
 
1174
                         unsigned int rn, unsigned int rd)
 
1175
{
 
1176
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
 
1177
    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 
1178
    TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
 
1179
 
 
1180
    tcg_gen_andi_i64(tcg_tmp, tcg_rn, 0xffff);
 
1181
    tcg_gen_bswap16_i64(tcg_rd, tcg_tmp);
 
1182
 
 
1183
    tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16);
 
1184
    tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
 
1185
    tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
 
1186
    tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 16, 16);
 
1187
 
 
1188
    if (sf) {
 
1189
        tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
 
1190
        tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
 
1191
        tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
 
1192
        tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 32, 16);
 
1193
 
 
1194
        tcg_gen_shri_i64(tcg_tmp, tcg_rn, 48);
 
1195
        tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
 
1196
        tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 48, 16);
 
1197
    }
 
1198
 
 
1199
    tcg_temp_free_i64(tcg_tmp);
 
1200
}
 
1201
 
 
1202
/* C3.5.7 Data-processing (1 source)
 
1203
 *   31  30  29  28             21 20     16 15    10 9    5 4    0
 
1204
 * +----+---+---+-----------------+---------+--------+------+------+
 
1205
 * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
 
1206
 * +----+---+---+-----------------+---------+--------+------+------+
 
1207
 */
 
1208
static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
 
1209
{
 
1210
    unsigned int sf, opcode, rn, rd;
 
1211
 
 
1212
    if (extract32(insn, 29, 1) || extract32(insn, 16, 5)) {
 
1213
        unallocated_encoding(s);
 
1214
        return;
 
1215
    }
 
1216
 
 
1217
    sf = extract32(insn, 31, 1);
 
1218
    opcode = extract32(insn, 10, 6);
 
1219
    rn = extract32(insn, 5, 5);
 
1220
    rd = extract32(insn, 0, 5);
 
1221
 
 
1222
    switch (opcode) {
 
1223
    case 0: /* RBIT */
 
1224
        handle_rbit(s, sf, rn, rd);
 
1225
        break;
 
1226
    case 1: /* REV16 */
 
1227
        handle_rev16(s, sf, rn, rd);
 
1228
        break;
 
1229
    case 2: /* REV32 */
 
1230
        handle_rev32(s, sf, rn, rd);
 
1231
        break;
 
1232
    case 3: /* REV64 */
 
1233
        handle_rev64(s, sf, rn, rd);
 
1234
        break;
 
1235
    case 4: /* CLZ */
 
1236
        handle_clz(s, sf, rn, rd);
 
1237
        break;
 
1238
    case 5: /* CLS */
 
1239
        unsupported_encoding(s, insn);
 
1240
        break;
 
1241
    }
 
1242
}
 
1243
 
 
1244
static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
 
1245
                       unsigned int rm, unsigned int rn, unsigned int rd)
 
1246
{
 
1247
    TCGv_i64 tcg_n, tcg_m, tcg_rd;
 
1248
    tcg_rd = cpu_reg(s, rd);
 
1249
 
 
1250
    if (!sf && is_signed) {
 
1251
        tcg_n = new_tmp_a64(s);
 
1252
        tcg_m = new_tmp_a64(s);
 
1253
        tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
 
1254
        tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
 
1255
    } else {
 
1256
        tcg_n = read_cpu_reg(s, rn, sf);
 
1257
        tcg_m = read_cpu_reg(s, rm, sf);
 
1258
    }
 
1259
 
 
1260
    if (is_signed) {
 
1261
        gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
 
1262
    } else {
 
1263
        gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
 
1264
    }
 
1265
 
 
1266
    if (!sf) { /* zero extend final result */
 
1267
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
 
1268
    }
 
1269
}
 
1270
 
 
1271
/* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
 
1272
static void handle_shift_reg(DisasContext *s,
 
1273
                             enum a64_shift_type shift_type, unsigned int sf,
 
1274
                             unsigned int rm, unsigned int rn, unsigned int rd)
 
1275
{
 
1276
    TCGv_i64 tcg_shift = tcg_temp_new_i64();
 
1277
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
 
1278
    TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
 
1279
 
 
1280
    tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
 
1281
    shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
 
1282
    tcg_temp_free_i64(tcg_shift);
 
1283
}
 
1284
 
 
1285
/* C3.5.8 Data-processing (2 source)
 
1286
 *   31   30  29 28             21 20  16 15    10 9    5 4    0
 
1287
 * +----+---+---+-----------------+------+--------+------+------+
 
1288
 * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
 
1289
 * +----+---+---+-----------------+------+--------+------+------+
 
1290
 */
 
1291
static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
 
1292
{
 
1293
    unsigned int sf, rm, opcode, rn, rd;
 
1294
    sf = extract32(insn, 31, 1);
 
1295
    rm = extract32(insn, 16, 5);
 
1296
    opcode = extract32(insn, 10, 6);
 
1297
    rn = extract32(insn, 5, 5);
 
1298
    rd = extract32(insn, 0, 5);
 
1299
 
 
1300
    if (extract32(insn, 29, 1)) {
 
1301
        unallocated_encoding(s);
 
1302
        return;
 
1303
    }
 
1304
 
 
1305
    switch (opcode) {
 
1306
    case 2: /* UDIV */
 
1307
        handle_div(s, false, sf, rm, rn, rd);
 
1308
        break;
 
1309
    case 3: /* SDIV */
 
1310
        handle_div(s, true, sf, rm, rn, rd);
 
1311
        break;
 
1312
    case 8: /* LSLV */
 
1313
        handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
 
1314
        break;
 
1315
    case 9: /* LSRV */
 
1316
        handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
 
1317
        break;
 
1318
    case 10: /* ASRV */
 
1319
        handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
 
1320
        break;
 
1321
    case 11: /* RORV */
 
1322
        handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
 
1323
        break;
 
1324
    case 16:
 
1325
    case 17:
 
1326
    case 18:
 
1327
    case 19:
 
1328
    case 20:
 
1329
    case 21:
 
1330
    case 22:
 
1331
    case 23: /* CRC32 */
 
1332
        unsupported_encoding(s, insn);
 
1333
        break;
 
1334
    default:
 
1335
        unallocated_encoding(s);
 
1336
        break;
 
1337
    }
 
1338
}
 
1339
 
 
1340
/* C3.5 Data processing - register */
 
1341
static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
 
1342
{
 
1343
    switch (extract32(insn, 24, 5)) {
 
1344
    case 0x0a: /* Logical (shifted register) */
 
1345
        disas_logic_reg(s, insn);
 
1346
        break;
 
1347
    case 0x0b: /* Add/subtract */
 
1348
        if (insn & (1 << 21)) { /* (extended register) */
 
1349
            disas_add_sub_ext_reg(s, insn);
 
1350
        } else {
 
1351
            disas_add_sub_reg(s, insn);
 
1352
        }
 
1353
        break;
 
1354
    case 0x1b: /* Data-processing (3 source) */
 
1355
        disas_data_proc_3src(s, insn);
 
1356
        break;
 
1357
    case 0x1a:
 
1358
        switch (extract32(insn, 21, 3)) {
 
1359
        case 0x0: /* Add/subtract (with carry) */
 
1360
            disas_adc_sbc(s, insn);
 
1361
            break;
 
1362
        case 0x2: /* Conditional compare */
 
1363
            if (insn & (1 << 11)) { /* (immediate) */
 
1364
                disas_cc_imm(s, insn);
 
1365
            } else {            /* (register) */
 
1366
                disas_cc_reg(s, insn);
 
1367
            }
 
1368
            break;
 
1369
        case 0x4: /* Conditional select */
 
1370
            disas_cond_select(s, insn);
 
1371
            break;
 
1372
        case 0x6: /* Data-processing */
 
1373
            if (insn & (1 << 30)) { /* (1 source) */
 
1374
                disas_data_proc_1src(s, insn);
 
1375
            } else {            /* (2 source) */
 
1376
                disas_data_proc_2src(s, insn);
 
1377
            }
 
1378
            break;
 
1379
        default:
 
1380
            unallocated_encoding(s);
 
1381
            break;
 
1382
        }
 
1383
        break;
 
1384
    default:
 
1385
        unallocated_encoding(s);
 
1386
        break;
 
1387
    }
 
1388
}
 
1389
 
 
1390
/* C3.6 Data processing - SIMD and floating point */
 
1391
static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
 
1392
{
 
1393
    unsupported_encoding(s, insn);
 
1394
}
 
1395
 
 
1396
/* C3.1 A64 instruction index by encoding */
 
1397
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
 
1398
{
 
1399
    uint32_t insn;
 
1400
 
 
1401
    insn = arm_ldl_code(env, s->pc, s->bswap_code);
 
1402
    s->insn = insn;
 
1403
    s->pc += 4;
 
1404
 
 
1405
    switch (extract32(insn, 25, 4)) {
 
1406
    case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
 
1407
        unallocated_encoding(s);
 
1408
        break;
 
1409
    case 0x8: case 0x9: /* Data processing - immediate */
 
1410
        disas_data_proc_imm(s, insn);
 
1411
        break;
 
1412
    case 0xa: case 0xb: /* Branch, exception generation and system insns */
 
1413
        disas_b_exc_sys(s, insn);
 
1414
        break;
 
1415
    case 0x4:
 
1416
    case 0x6:
 
1417
    case 0xc:
 
1418
    case 0xe:      /* Loads and stores */
 
1419
        disas_ldst(s, insn);
 
1420
        break;
 
1421
    case 0x5:
 
1422
    case 0xd:      /* Data processing - register */
 
1423
        disas_data_proc_reg(s, insn);
 
1424
        break;
 
1425
    case 0x7:
 
1426
    case 0xf:      /* Data processing - SIMD and floating point */
 
1427
        disas_data_proc_simd_fp(s, insn);
 
1428
        break;
 
1429
    default:
 
1430
        assert(FALSE); /* all 15 cases should be handled above */
 
1431
        break;
 
1432
    }
 
1433
 
 
1434
    /* if we allocated any temporaries, free them here */
 
1435
    free_tmp_a64(s);
 
1436
}
 
1437
 
 
1438
void gen_intermediate_code_internal_a64(ARMCPU *cpu,
 
1439
                                        TranslationBlock *tb,
 
1440
                                        bool search_pc)
 
1441
{
 
1442
    CPUState *cs = CPU(cpu);
 
1443
    CPUARMState *env = &cpu->env;
 
1444
    DisasContext dc1, *dc = &dc1;
 
1445
    CPUBreakpoint *bp;
 
1446
    uint16_t *gen_opc_end;
 
1447
    int j, lj;
 
1448
    target_ulong pc_start;
 
1449
    target_ulong next_page_start;
 
1450
    int num_insns;
 
1451
    int max_insns;
 
1452
 
 
1453
    pc_start = tb->pc;
 
1454
 
 
1455
    dc->tb = tb;
 
1456
 
 
1457
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
1458
 
 
1459
    dc->is_jmp = DISAS_NEXT;
 
1460
    dc->pc = pc_start;
 
1461
    dc->singlestep_enabled = cs->singlestep_enabled;
 
1462
    dc->condjmp = 0;
 
1463
 
 
1464
    dc->aarch64 = 1;
 
1465
    dc->thumb = 0;
 
1466
    dc->bswap_code = 0;
 
1467
    dc->condexec_mask = 0;
 
1468
    dc->condexec_cond = 0;
 
1469
#if !defined(CONFIG_USER_ONLY)
 
1470
    dc->user = 0;
 
1471
#endif
 
1472
    dc->vfp_enabled = 0;
 
1473
    dc->vec_len = 0;
 
1474
    dc->vec_stride = 0;
 
1475
 
 
1476
    init_tmp_a64_array(dc);
 
1477
 
 
1478
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
 
1479
    lj = -1;
 
1480
    num_insns = 0;
 
1481
    max_insns = tb->cflags & CF_COUNT_MASK;
 
1482
    if (max_insns == 0) {
 
1483
        max_insns = CF_COUNT_MASK;
 
1484
    }
 
1485
 
 
1486
    gen_tb_start();
 
1487
 
 
1488
    tcg_clear_temp_count();
 
1489
 
 
1490
    do {
 
1491
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
 
1492
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
 
1493
                if (bp->pc == dc->pc) {
 
1494
                    gen_exception_insn(dc, 0, EXCP_DEBUG);
 
1495
                    /* Advance PC so that clearing the breakpoint will
 
1496
                       invalidate this TB.  */
 
1497
                    dc->pc += 2;
 
1498
                    goto done_generating;
 
1499
                }
 
1500
            }
 
1501
        }
 
1502
 
 
1503
        if (search_pc) {
 
1504
            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
 
1505
            if (lj < j) {
 
1506
                lj++;
 
1507
                while (lj < j) {
 
1508
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
 
1509
                }
 
1510
            }
 
1511
            tcg_ctx.gen_opc_pc[lj] = dc->pc;
 
1512
            tcg_ctx.gen_opc_instr_start[lj] = 1;
 
1513
            tcg_ctx.gen_opc_icount[lj] = num_insns;
 
1514
        }
 
1515
 
 
1516
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
 
1517
            gen_io_start();
 
1518
        }
 
1519
 
 
1520
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
 
1521
            tcg_gen_debug_insn_start(dc->pc);
 
1522
        }
 
1523
 
 
1524
        disas_a64_insn(env, dc);
 
1525
 
 
1526
        if (tcg_check_temp_count()) {
 
1527
            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
 
1528
                    dc->pc);
 
1529
        }
 
1530
 
 
1531
        /* Translation stops when a conditional branch is encountered.
 
1532
         * Otherwise the subsequent code could get translated several times.
 
1533
         * Also stop translation when a page boundary is reached.  This
 
1534
         * ensures prefetch aborts occur at the right place.
 
1535
         */
 
1536
        num_insns++;
 
1537
    } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
 
1538
             !cs->singlestep_enabled &&
 
1539
             !singlestep &&
 
1540
             dc->pc < next_page_start &&
 
1541
             num_insns < max_insns);
 
1542
 
 
1543
    if (tb->cflags & CF_LAST_IO) {
 
1544
        gen_io_end();
 
1545
    }
 
1546
 
 
1547
    if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
 
1548
        /* Note that this means single stepping WFI doesn't halt the CPU.
 
1549
         * For conditional branch insns this is harmless unreachable code as
 
1550
         * gen_goto_tb() has already handled emitting the debug exception
 
1551
         * (and thus a tb-jump is not possible when singlestepping).
 
1552
         */
 
1553
        assert(dc->is_jmp != DISAS_TB_JUMP);
 
1554
        if (dc->is_jmp != DISAS_JUMP) {
 
1555
            gen_a64_set_pc_im(dc->pc);
 
1556
        }
 
1557
        gen_exception(EXCP_DEBUG);
 
1558
    } else {
 
1559
        switch (dc->is_jmp) {
 
1560
        case DISAS_NEXT:
 
1561
            gen_goto_tb(dc, 1, dc->pc);
 
1562
            break;
 
1563
        default:
 
1564
        case DISAS_JUMP:
 
1565
        case DISAS_UPDATE:
 
1566
            /* indicate that the hash table must be used to find the next TB */
 
1567
            tcg_gen_exit_tb(0);
 
1568
            break;
 
1569
        case DISAS_TB_JUMP:
 
1570
        case DISAS_EXC:
 
1571
        case DISAS_SWI:
 
1572
            break;
 
1573
        case DISAS_WFI:
 
1574
            /* This is a special case because we don't want to just halt the CPU
 
1575
             * if trying to debug across a WFI.
 
1576
             */
 
1577
            gen_helper_wfi(cpu_env);
 
1578
            break;
 
1579
        }
 
1580
    }
 
1581
 
 
1582
done_generating:
 
1583
    gen_tb_end(tb, num_insns);
 
1584
    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
 
1585
 
 
1586
#ifdef DEBUG_DISAS
 
1587
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
 
1588
        qemu_log("----------------\n");
 
1589
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
 
1590
        log_target_disas(env, pc_start, dc->pc - pc_start,
 
1591
                         dc->thumb | (dc->bswap_code << 1));
 
1592
        qemu_log("\n");
 
1593
    }
 
1594
#endif
 
1595
    if (search_pc) {
 
1596
        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
 
1597
        lj++;
 
1598
        while (lj <= j) {
 
1599
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
 
1600
        }
 
1601
    } else {
 
1602
        tb->size = dc->pc - pc_start;
 
1603
        tb->icount = num_insns;
 
1604
    }
 
1605
}