Statistics
| Branch: | Revision:

root / target-arm / translate-a64.c @ df54e47d

History | View | Annotate | Download (141.5 kB)

1
/*
2
 *  AArch64 translation
3
 *
4
 *  Copyright (c) 2013 Alexander Graf <agraf@suse.de>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <stdarg.h>
20
#include <stdlib.h>
21
#include <stdio.h>
22
#include <string.h>
23
#include <inttypes.h>
24

    
25
#include "cpu.h"
26
#include "tcg-op.h"
27
#include "qemu/log.h"
28
#include "translate.h"
29
#include "qemu/host-utils.h"
30

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

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

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

    
41
/* Load/store exclusive handling */
42
static TCGv_i64 cpu_exclusive_addr;
43
static TCGv_i64 cpu_exclusive_val;
44
static TCGv_i64 cpu_exclusive_high;
45
#ifdef CONFIG_USER_ONLY
46
static TCGv_i64 cpu_exclusive_test;
47
static TCGv_i32 cpu_exclusive_info;
48
#endif
49

    
50
static const char *regnames[] = {
51
    "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
52
    "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
53
    "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
54
    "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
55
};
56

    
57
enum a64_shift_type {
58
    A64_SHIFT_TYPE_LSL = 0,
59
    A64_SHIFT_TYPE_LSR = 1,
60
    A64_SHIFT_TYPE_ASR = 2,
61
    A64_SHIFT_TYPE_ROR = 3
62
};
63

    
64
/* initialize TCG globals.  */
65
void a64_translate_init(void)
66
{
67
    int i;
68

    
69
    cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
70
                                    offsetof(CPUARMState, pc),
71
                                    "pc");
72
    for (i = 0; i < 32; i++) {
73
        cpu_X[i] = tcg_global_mem_new_i64(TCG_AREG0,
74
                                          offsetof(CPUARMState, xregs[i]),
75
                                          regnames[i]);
76
    }
77

    
78
    cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
79
    cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
80
    cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
81
    cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
82

    
83
    cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
84
        offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
85
    cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
86
        offsetof(CPUARMState, exclusive_val), "exclusive_val");
87
    cpu_exclusive_high = tcg_global_mem_new_i64(TCG_AREG0,
88
        offsetof(CPUARMState, exclusive_high), "exclusive_high");
89
#ifdef CONFIG_USER_ONLY
90
    cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
91
        offsetof(CPUARMState, exclusive_test), "exclusive_test");
92
    cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
93
        offsetof(CPUARMState, exclusive_info), "exclusive_info");
94
#endif
95
}
96

    
97
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
98
                            fprintf_function cpu_fprintf, int flags)
99
{
100
    ARMCPU *cpu = ARM_CPU(cs);
101
    CPUARMState *env = &cpu->env;
102
    uint32_t psr = pstate_read(env);
103
    int i;
104

    
105
    cpu_fprintf(f, "PC=%016"PRIx64"  SP=%016"PRIx64"\n",
106
            env->pc, env->xregs[31]);
107
    for (i = 0; i < 31; i++) {
108
        cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
109
        if ((i % 4) == 3) {
110
            cpu_fprintf(f, "\n");
111
        } else {
112
            cpu_fprintf(f, " ");
113
        }
114
    }
115
    cpu_fprintf(f, "PSTATE=%08x (flags %c%c%c%c)\n",
116
                psr,
117
                psr & PSTATE_N ? 'N' : '-',
118
                psr & PSTATE_Z ? 'Z' : '-',
119
                psr & PSTATE_C ? 'C' : '-',
120
                psr & PSTATE_V ? 'V' : '-');
121
    cpu_fprintf(f, "\n");
122

    
123
    if (flags & CPU_DUMP_FPU) {
124
        int numvfpregs = 32;
125
        for (i = 0; i < numvfpregs; i += 2) {
126
            uint64_t vlo = float64_val(env->vfp.regs[i * 2]);
127
            uint64_t vhi = float64_val(env->vfp.regs[(i * 2) + 1]);
128
            cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
129
                        i, vhi, vlo);
130
            vlo = float64_val(env->vfp.regs[(i + 1) * 2]);
131
            vhi = float64_val(env->vfp.regs[((i + 1) * 2) + 1]);
132
            cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
133
                        i + 1, vhi, vlo);
134
        }
135
        cpu_fprintf(f, "FPCR: %08x  FPSR: %08x\n",
136
                    vfp_get_fpcr(env), vfp_get_fpsr(env));
137
    }
138
}
139

    
140
static int get_mem_index(DisasContext *s)
141
{
142
#ifdef CONFIG_USER_ONLY
143
    return 1;
144
#else
145
    return s->user;
146
#endif
147
}
148

    
149
void gen_a64_set_pc_im(uint64_t val)
150
{
151
    tcg_gen_movi_i64(cpu_pc, val);
152
}
153

    
154
static void gen_exception(int excp)
155
{
156
    TCGv_i32 tmp = tcg_temp_new_i32();
157
    tcg_gen_movi_i32(tmp, excp);
158
    gen_helper_exception(cpu_env, tmp);
159
    tcg_temp_free_i32(tmp);
160
}
161

    
162
static void gen_exception_insn(DisasContext *s, int offset, int excp)
163
{
164
    gen_a64_set_pc_im(s->pc - offset);
165
    gen_exception(excp);
166
    s->is_jmp = DISAS_EXC;
167
}
168

    
169
static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
170
{
171
    /* No direct tb linking with singlestep or deterministic io */
172
    if (s->singlestep_enabled || (s->tb->cflags & CF_LAST_IO)) {
173
        return false;
174
    }
175

    
176
    /* Only link tbs from inside the same guest page */
177
    if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
178
        return false;
179
    }
180

    
181
    return true;
182
}
183

    
184
static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
185
{
186
    TranslationBlock *tb;
187

    
188
    tb = s->tb;
189
    if (use_goto_tb(s, n, dest)) {
190
        tcg_gen_goto_tb(n);
191
        gen_a64_set_pc_im(dest);
192
        tcg_gen_exit_tb((tcg_target_long)tb + n);
193
        s->is_jmp = DISAS_TB_JUMP;
194
    } else {
195
        gen_a64_set_pc_im(dest);
196
        if (s->singlestep_enabled) {
197
            gen_exception(EXCP_DEBUG);
198
        }
199
        tcg_gen_exit_tb(0);
200
        s->is_jmp = DISAS_JUMP;
201
    }
202
}
203

    
204
static void unallocated_encoding(DisasContext *s)
205
{
206
    gen_exception_insn(s, 4, EXCP_UDEF);
207
}
208

    
209
#define unsupported_encoding(s, insn)                                    \
210
    do {                                                                 \
211
        qemu_log_mask(LOG_UNIMP,                                         \
212
                      "%s:%d: unsupported instruction encoding 0x%08x "  \
213
                      "at pc=%016" PRIx64 "\n",                          \
214
                      __FILE__, __LINE__, insn, s->pc - 4);              \
215
        unallocated_encoding(s);                                         \
216
    } while (0);
217

    
218
static void init_tmp_a64_array(DisasContext *s)
219
{
220
#ifdef CONFIG_DEBUG_TCG
221
    int i;
222
    for (i = 0; i < ARRAY_SIZE(s->tmp_a64); i++) {
223
        TCGV_UNUSED_I64(s->tmp_a64[i]);
224
    }
225
#endif
226
    s->tmp_a64_count = 0;
227
}
228

    
229
static void free_tmp_a64(DisasContext *s)
230
{
231
    int i;
232
    for (i = 0; i < s->tmp_a64_count; i++) {
233
        tcg_temp_free_i64(s->tmp_a64[i]);
234
    }
235
    init_tmp_a64_array(s);
236
}
237

    
238
static TCGv_i64 new_tmp_a64(DisasContext *s)
239
{
240
    assert(s->tmp_a64_count < TMP_A64_MAX);
241
    return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
242
}
243

    
244
static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
245
{
246
    TCGv_i64 t = new_tmp_a64(s);
247
    tcg_gen_movi_i64(t, 0);
248
    return t;
249
}
250

    
251
/*
252
 * Register access functions
253
 *
254
 * These functions are used for directly accessing a register in where
255
 * changes to the final register value are likely to be made. If you
256
 * need to use a register for temporary calculation (e.g. index type
257
 * operations) use the read_* form.
258
 *
259
 * B1.2.1 Register mappings
260
 *
261
 * In instruction register encoding 31 can refer to ZR (zero register) or
262
 * the SP (stack pointer) depending on context. In QEMU's case we map SP
263
 * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
264
 * This is the point of the _sp forms.
265
 */
266
static TCGv_i64 cpu_reg(DisasContext *s, int reg)
267
{
268
    if (reg == 31) {
269
        return new_tmp_a64_zero(s);
270
    } else {
271
        return cpu_X[reg];
272
    }
273
}
274

    
275
/* register access for when 31 == SP */
276
static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
277
{
278
    return cpu_X[reg];
279
}
280

    
281
/* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
282
 * representing the register contents. This TCGv is an auto-freed
283
 * temporary so it need not be explicitly freed, and may be modified.
284
 */
285
static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
286
{
287
    TCGv_i64 v = new_tmp_a64(s);
288
    if (reg != 31) {
289
        if (sf) {
290
            tcg_gen_mov_i64(v, cpu_X[reg]);
291
        } else {
292
            tcg_gen_ext32u_i64(v, cpu_X[reg]);
293
        }
294
    } else {
295
        tcg_gen_movi_i64(v, 0);
296
    }
297
    return v;
298
}
299

    
300
static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
301
{
302
    TCGv_i64 v = new_tmp_a64(s);
303
    if (sf) {
304
        tcg_gen_mov_i64(v, cpu_X[reg]);
305
    } else {
306
        tcg_gen_ext32u_i64(v, cpu_X[reg]);
307
    }
308
    return v;
309
}
310

    
311
/* Return the offset into CPUARMState of an element of specified
312
 * size, 'element' places in from the least significant end of
313
 * the FP/vector register Qn.
314
 */
315
static inline int vec_reg_offset(int regno, int element, TCGMemOp size)
316
{
317
    int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
318
#ifdef HOST_WORDS_BIGENDIAN
319
    /* This is complicated slightly because vfp.regs[2n] is
320
     * still the low half and  vfp.regs[2n+1] the high half
321
     * of the 128 bit vector, even on big endian systems.
322
     * Calculate the offset assuming a fully bigendian 128 bits,
323
     * then XOR to account for the order of the two 64 bit halves.
324
     */
325
    offs += (16 - ((element + 1) * (1 << size)));
326
    offs ^= 8;
327
#else
328
    offs += element * (1 << size);
329
#endif
330
    return offs;
331
}
332

    
333
/* Return the offset into CPUARMState of a slice (from
334
 * the least significant end) of FP register Qn (ie
335
 * Dn, Sn, Hn or Bn).
336
 * (Note that this is not the same mapping as for A32; see cpu.h)
337
 */
338
static inline int fp_reg_offset(int regno, TCGMemOp size)
339
{
340
    int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
341
#ifdef HOST_WORDS_BIGENDIAN
342
    offs += (8 - (1 << size));
343
#endif
344
    return offs;
345
}
346

    
347
/* Offset of the high half of the 128 bit vector Qn */
348
static inline int fp_reg_hi_offset(int regno)
349
{
350
    return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
351
}
352

    
353
/* Convenience accessors for reading and writing single and double
354
 * FP registers. Writing clears the upper parts of the associated
355
 * 128 bit vector register, as required by the architecture.
356
 * Note that unlike the GP register accessors, the values returned
357
 * by the read functions must be manually freed.
358
 */
359
static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
360
{
361
    TCGv_i64 v = tcg_temp_new_i64();
362

    
363
    tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
364
    return v;
365
}
366

    
367
static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
368
{
369
    TCGv_i32 v = tcg_temp_new_i32();
370

    
371
    tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(reg, MO_32));
372
    return v;
373
}
374

    
375
static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
376
{
377
    TCGv_i64 tcg_zero = tcg_const_i64(0);
378

    
379
    tcg_gen_st_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
380
    tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(reg));
381
    tcg_temp_free_i64(tcg_zero);
382
}
383

    
384
static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
385
{
386
    TCGv_i64 tmp = tcg_temp_new_i64();
387

    
388
    tcg_gen_extu_i32_i64(tmp, v);
389
    write_fp_dreg(s, reg, tmp);
390
    tcg_temp_free_i64(tmp);
391
}
392

    
393
static TCGv_ptr get_fpstatus_ptr(void)
394
{
395
    TCGv_ptr statusptr = tcg_temp_new_ptr();
396
    int offset;
397

    
398
    /* In A64 all instructions (both FP and Neon) use the FPCR;
399
     * there is no equivalent of the A32 Neon "standard FPSCR value"
400
     * and all operations use vfp.fp_status.
401
     */
402
    offset = offsetof(CPUARMState, vfp.fp_status);
403
    tcg_gen_addi_ptr(statusptr, cpu_env, offset);
404
    return statusptr;
405
}
406

    
407
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
408
 * than the 32 bit equivalent.
409
 */
410
static inline void gen_set_NZ64(TCGv_i64 result)
411
{
412
    TCGv_i64 flag = tcg_temp_new_i64();
413

    
414
    tcg_gen_setcondi_i64(TCG_COND_NE, flag, result, 0);
415
    tcg_gen_trunc_i64_i32(cpu_ZF, flag);
416
    tcg_gen_shri_i64(flag, result, 32);
417
    tcg_gen_trunc_i64_i32(cpu_NF, flag);
418
    tcg_temp_free_i64(flag);
419
}
420

    
421
/* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
422
static inline void gen_logic_CC(int sf, TCGv_i64 result)
423
{
424
    if (sf) {
425
        gen_set_NZ64(result);
426
    } else {
427
        tcg_gen_trunc_i64_i32(cpu_ZF, result);
428
        tcg_gen_trunc_i64_i32(cpu_NF, result);
429
    }
430
    tcg_gen_movi_i32(cpu_CF, 0);
431
    tcg_gen_movi_i32(cpu_VF, 0);
432
}
433

    
434
/* dest = T0 + T1; compute C, N, V and Z flags */
435
static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
436
{
437
    if (sf) {
438
        TCGv_i64 result, flag, tmp;
439
        result = tcg_temp_new_i64();
440
        flag = tcg_temp_new_i64();
441
        tmp = tcg_temp_new_i64();
442

    
443
        tcg_gen_movi_i64(tmp, 0);
444
        tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
445

    
446
        tcg_gen_trunc_i64_i32(cpu_CF, flag);
447

    
448
        gen_set_NZ64(result);
449

    
450
        tcg_gen_xor_i64(flag, result, t0);
451
        tcg_gen_xor_i64(tmp, t0, t1);
452
        tcg_gen_andc_i64(flag, flag, tmp);
453
        tcg_temp_free_i64(tmp);
454
        tcg_gen_shri_i64(flag, flag, 32);
455
        tcg_gen_trunc_i64_i32(cpu_VF, flag);
456

    
457
        tcg_gen_mov_i64(dest, result);
458
        tcg_temp_free_i64(result);
459
        tcg_temp_free_i64(flag);
460
    } else {
461
        /* 32 bit arithmetic */
462
        TCGv_i32 t0_32 = tcg_temp_new_i32();
463
        TCGv_i32 t1_32 = tcg_temp_new_i32();
464
        TCGv_i32 tmp = tcg_temp_new_i32();
465

    
466
        tcg_gen_movi_i32(tmp, 0);
467
        tcg_gen_trunc_i64_i32(t0_32, t0);
468
        tcg_gen_trunc_i64_i32(t1_32, t1);
469
        tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
470
        tcg_gen_mov_i32(cpu_ZF, cpu_NF);
471
        tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
472
        tcg_gen_xor_i32(tmp, t0_32, t1_32);
473
        tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
474
        tcg_gen_extu_i32_i64(dest, cpu_NF);
475

    
476
        tcg_temp_free_i32(tmp);
477
        tcg_temp_free_i32(t0_32);
478
        tcg_temp_free_i32(t1_32);
479
    }
480
}
481

    
482
/* dest = T0 - T1; compute C, N, V and Z flags */
483
static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
484
{
485
    if (sf) {
486
        /* 64 bit arithmetic */
487
        TCGv_i64 result, flag, tmp;
488

    
489
        result = tcg_temp_new_i64();
490
        flag = tcg_temp_new_i64();
491
        tcg_gen_sub_i64(result, t0, t1);
492

    
493
        gen_set_NZ64(result);
494

    
495
        tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
496
        tcg_gen_trunc_i64_i32(cpu_CF, flag);
497

    
498
        tcg_gen_xor_i64(flag, result, t0);
499
        tmp = tcg_temp_new_i64();
500
        tcg_gen_xor_i64(tmp, t0, t1);
501
        tcg_gen_and_i64(flag, flag, tmp);
502
        tcg_temp_free_i64(tmp);
503
        tcg_gen_shri_i64(flag, flag, 32);
504
        tcg_gen_trunc_i64_i32(cpu_VF, flag);
505
        tcg_gen_mov_i64(dest, result);
506
        tcg_temp_free_i64(flag);
507
        tcg_temp_free_i64(result);
508
    } else {
509
        /* 32 bit arithmetic */
510
        TCGv_i32 t0_32 = tcg_temp_new_i32();
511
        TCGv_i32 t1_32 = tcg_temp_new_i32();
512
        TCGv_i32 tmp;
513

    
514
        tcg_gen_trunc_i64_i32(t0_32, t0);
515
        tcg_gen_trunc_i64_i32(t1_32, t1);
516
        tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
517
        tcg_gen_mov_i32(cpu_ZF, cpu_NF);
518
        tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
519
        tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
520
        tmp = tcg_temp_new_i32();
521
        tcg_gen_xor_i32(tmp, t0_32, t1_32);
522
        tcg_temp_free_i32(t0_32);
523
        tcg_temp_free_i32(t1_32);
524
        tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
525
        tcg_temp_free_i32(tmp);
526
        tcg_gen_extu_i32_i64(dest, cpu_NF);
527
    }
528
}
529

    
530
/* dest = T0 + T1 + CF; do not compute flags. */
531
static void gen_adc(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
532
{
533
    TCGv_i64 flag = tcg_temp_new_i64();
534
    tcg_gen_extu_i32_i64(flag, cpu_CF);
535
    tcg_gen_add_i64(dest, t0, t1);
536
    tcg_gen_add_i64(dest, dest, flag);
537
    tcg_temp_free_i64(flag);
538

    
539
    if (!sf) {
540
        tcg_gen_ext32u_i64(dest, dest);
541
    }
542
}
543

    
544
/* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
545
static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
546
{
547
    if (sf) {
548
        TCGv_i64 result, cf_64, vf_64, tmp;
549
        result = tcg_temp_new_i64();
550
        cf_64 = tcg_temp_new_i64();
551
        vf_64 = tcg_temp_new_i64();
552
        tmp = tcg_const_i64(0);
553

    
554
        tcg_gen_extu_i32_i64(cf_64, cpu_CF);
555
        tcg_gen_add2_i64(result, cf_64, t0, tmp, cf_64, tmp);
556
        tcg_gen_add2_i64(result, cf_64, result, cf_64, t1, tmp);
557
        tcg_gen_trunc_i64_i32(cpu_CF, cf_64);
558
        gen_set_NZ64(result);
559

    
560
        tcg_gen_xor_i64(vf_64, result, t0);
561
        tcg_gen_xor_i64(tmp, t0, t1);
562
        tcg_gen_andc_i64(vf_64, vf_64, tmp);
563
        tcg_gen_shri_i64(vf_64, vf_64, 32);
564
        tcg_gen_trunc_i64_i32(cpu_VF, vf_64);
565

    
566
        tcg_gen_mov_i64(dest, result);
567

    
568
        tcg_temp_free_i64(tmp);
569
        tcg_temp_free_i64(vf_64);
570
        tcg_temp_free_i64(cf_64);
571
        tcg_temp_free_i64(result);
572
    } else {
573
        TCGv_i32 t0_32, t1_32, tmp;
574
        t0_32 = tcg_temp_new_i32();
575
        t1_32 = tcg_temp_new_i32();
576
        tmp = tcg_const_i32(0);
577

    
578
        tcg_gen_trunc_i64_i32(t0_32, t0);
579
        tcg_gen_trunc_i64_i32(t1_32, t1);
580
        tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, cpu_CF, tmp);
581
        tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1_32, tmp);
582

    
583
        tcg_gen_mov_i32(cpu_ZF, cpu_NF);
584
        tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
585
        tcg_gen_xor_i32(tmp, t0_32, t1_32);
586
        tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
587
        tcg_gen_extu_i32_i64(dest, cpu_NF);
588

    
589
        tcg_temp_free_i32(tmp);
590
        tcg_temp_free_i32(t1_32);
591
        tcg_temp_free_i32(t0_32);
592
    }
593
}
594

    
595
/*
596
 * Load/Store generators
597
 */
598

    
599
/*
600
 * Store from GPR register to memory
601
 */
602
static void do_gpr_st(DisasContext *s, TCGv_i64 source,
603
                      TCGv_i64 tcg_addr, int size)
604
{
605
    g_assert(size <= 3);
606
    tcg_gen_qemu_st_i64(source, tcg_addr, get_mem_index(s), MO_TE + size);
607
}
608

    
609
/*
610
 * Load from memory to GPR register
611
 */
612
static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
613
                      int size, bool is_signed, bool extend)
614
{
615
    TCGMemOp memop = MO_TE + size;
616

    
617
    g_assert(size <= 3);
618

    
619
    if (is_signed) {
620
        memop += MO_SIGN;
621
    }
622

    
623
    tcg_gen_qemu_ld_i64(dest, tcg_addr, get_mem_index(s), memop);
624

    
625
    if (extend && is_signed) {
626
        g_assert(size < 3);
627
        tcg_gen_ext32u_i64(dest, dest);
628
    }
629
}
630

    
631
/*
632
 * Store from FP register to memory
633
 */
634
static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
635
{
636
    /* This writes the bottom N bits of a 128 bit wide vector to memory */
637
    TCGv_i64 tmp = tcg_temp_new_i64();
638
    tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_64));
639
    if (size < 4) {
640
        tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
641
    } else {
642
        TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
643
        tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
644
        tcg_gen_qemu_st64(tmp, tcg_addr, get_mem_index(s));
645
        tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(srcidx));
646
        tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
647
        tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
648
        tcg_temp_free_i64(tcg_hiaddr);
649
    }
650

    
651
    tcg_temp_free_i64(tmp);
652
}
653

    
654
/*
655
 * Load from memory to FP register
656
 */
657
static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
658
{
659
    /* This always zero-extends and writes to a full 128 bit wide vector */
660
    TCGv_i64 tmplo = tcg_temp_new_i64();
661
    TCGv_i64 tmphi;
662

    
663
    if (size < 4) {
664
        TCGMemOp memop = MO_TE + size;
665
        tmphi = tcg_const_i64(0);
666
        tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
667
    } else {
668
        TCGv_i64 tcg_hiaddr;
669
        tmphi = tcg_temp_new_i64();
670
        tcg_hiaddr = tcg_temp_new_i64();
671

    
672
        tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
673
        tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
674
        tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
675
        tcg_temp_free_i64(tcg_hiaddr);
676
    }
677

    
678
    tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(destidx, MO_64));
679
    tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(destidx));
680

    
681
    tcg_temp_free_i64(tmplo);
682
    tcg_temp_free_i64(tmphi);
683
}
684

    
685
/*
686
 * Vector load/store helpers.
687
 *
688
 * The principal difference between this and a FP load is that we don't
689
 * zero extend as we are filling a partial chunk of the vector register.
690
 * These functions don't support 128 bit loads/stores, which would be
691
 * normal load/store operations.
692
 */
693

    
694
/* Get value of an element within a vector register */
695
static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
696
                             int element, TCGMemOp memop)
697
{
698
    int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE);
699
    switch (memop) {
700
    case MO_8:
701
        tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
702
        break;
703
    case MO_16:
704
        tcg_gen_ld16u_i64(tcg_dest, cpu_env, vect_off);
705
        break;
706
    case MO_32:
707
        tcg_gen_ld32u_i64(tcg_dest, cpu_env, vect_off);
708
        break;
709
    case MO_8|MO_SIGN:
710
        tcg_gen_ld8s_i64(tcg_dest, cpu_env, vect_off);
711
        break;
712
    case MO_16|MO_SIGN:
713
        tcg_gen_ld16s_i64(tcg_dest, cpu_env, vect_off);
714
        break;
715
    case MO_32|MO_SIGN:
716
        tcg_gen_ld32s_i64(tcg_dest, cpu_env, vect_off);
717
        break;
718
    case MO_64:
719
    case MO_64|MO_SIGN:
720
        tcg_gen_ld_i64(tcg_dest, cpu_env, vect_off);
721
        break;
722
    default:
723
        g_assert_not_reached();
724
    }
725
}
726

    
727
/* Set value of an element within a vector register */
728
static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
729
                              int element, TCGMemOp memop)
730
{
731
    int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
732
    switch (memop) {
733
    case MO_8:
734
        tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
735
        break;
736
    case MO_16:
737
        tcg_gen_st16_i64(tcg_src, cpu_env, vect_off);
738
        break;
739
    case MO_32:
740
        tcg_gen_st32_i64(tcg_src, cpu_env, vect_off);
741
        break;
742
    case MO_64:
743
        tcg_gen_st_i64(tcg_src, cpu_env, vect_off);
744
        break;
745
    default:
746
        g_assert_not_reached();
747
    }
748
}
749

    
750
/* Clear the high 64 bits of a 128 bit vector (in general non-quad
751
 * vector ops all need to do this).
752
 */
753
static void clear_vec_high(DisasContext *s, int rd)
754
{
755
    TCGv_i64 tcg_zero = tcg_const_i64(0);
756

    
757
    write_vec_element(s, tcg_zero, rd, 1, MO_64);
758
    tcg_temp_free_i64(tcg_zero);
759
}
760

    
761
/* Store from vector register to memory */
762
static void do_vec_st(DisasContext *s, int srcidx, int element,
763
                      TCGv_i64 tcg_addr, int size)
764
{
765
    TCGMemOp memop = MO_TE + size;
766
    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
767

    
768
    read_vec_element(s, tcg_tmp, srcidx, element, size);
769
    tcg_gen_qemu_st_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
770

    
771
    tcg_temp_free_i64(tcg_tmp);
772
}
773

    
774
/* Load from memory to vector register */
775
static void do_vec_ld(DisasContext *s, int destidx, int element,
776
                      TCGv_i64 tcg_addr, int size)
777
{
778
    TCGMemOp memop = MO_TE + size;
779
    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
780

    
781
    tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
782
    write_vec_element(s, tcg_tmp, destidx, element, size);
783

    
784
    tcg_temp_free_i64(tcg_tmp);
785
}
786

    
787
/*
788
 * This utility function is for doing register extension with an
789
 * optional shift. You will likely want to pass a temporary for the
790
 * destination register. See DecodeRegExtend() in the ARM ARM.
791
 */
792
static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
793
                              int option, unsigned int shift)
794
{
795
    int extsize = extract32(option, 0, 2);
796
    bool is_signed = extract32(option, 2, 1);
797

    
798
    if (is_signed) {
799
        switch (extsize) {
800
        case 0:
801
            tcg_gen_ext8s_i64(tcg_out, tcg_in);
802
            break;
803
        case 1:
804
            tcg_gen_ext16s_i64(tcg_out, tcg_in);
805
            break;
806
        case 2:
807
            tcg_gen_ext32s_i64(tcg_out, tcg_in);
808
            break;
809
        case 3:
810
            tcg_gen_mov_i64(tcg_out, tcg_in);
811
            break;
812
        }
813
    } else {
814
        switch (extsize) {
815
        case 0:
816
            tcg_gen_ext8u_i64(tcg_out, tcg_in);
817
            break;
818
        case 1:
819
            tcg_gen_ext16u_i64(tcg_out, tcg_in);
820
            break;
821
        case 2:
822
            tcg_gen_ext32u_i64(tcg_out, tcg_in);
823
            break;
824
        case 3:
825
            tcg_gen_mov_i64(tcg_out, tcg_in);
826
            break;
827
        }
828
    }
829

    
830
    if (shift) {
831
        tcg_gen_shli_i64(tcg_out, tcg_out, shift);
832
    }
833
}
834

    
835
static inline void gen_check_sp_alignment(DisasContext *s)
836
{
837
    /* The AArch64 architecture mandates that (if enabled via PSTATE
838
     * or SCTLR bits) there is a check that SP is 16-aligned on every
839
     * SP-relative load or store (with an exception generated if it is not).
840
     * In line with general QEMU practice regarding misaligned accesses,
841
     * we omit these checks for the sake of guest program performance.
842
     * This function is provided as a hook so we can more easily add these
843
     * checks in future (possibly as a "favour catching guest program bugs
844
     * over speed" user selectable option).
845
     */
846
}
847

    
848
/*
849
 * the instruction disassembly implemented here matches
850
 * the instruction encoding classifications in chapter 3 (C3)
851
 * of the ARM Architecture Reference Manual (DDI0487A_a)
852
 */
853

    
854
/* C3.2.7 Unconditional branch (immediate)
855
 *   31  30       26 25                                  0
856
 * +----+-----------+-------------------------------------+
857
 * | op | 0 0 1 0 1 |                 imm26               |
858
 * +----+-----------+-------------------------------------+
859
 */
860
static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
861
{
862
    uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
863

    
864
    if (insn & (1 << 31)) {
865
        /* C5.6.26 BL Branch with link */
866
        tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
867
    }
868

    
869
    /* C5.6.20 B Branch / C5.6.26 BL Branch with link */
870
    gen_goto_tb(s, 0, addr);
871
}
872

    
873
/* C3.2.1 Compare & branch (immediate)
874
 *   31  30         25  24  23                  5 4      0
875
 * +----+-------------+----+---------------------+--------+
876
 * | sf | 0 1 1 0 1 0 | op |         imm19       |   Rt   |
877
 * +----+-------------+----+---------------------+--------+
878
 */
879
static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
880
{
881
    unsigned int sf, op, rt;
882
    uint64_t addr;
883
    int label_match;
884
    TCGv_i64 tcg_cmp;
885

    
886
    sf = extract32(insn, 31, 1);
887
    op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
888
    rt = extract32(insn, 0, 5);
889
    addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
890

    
891
    tcg_cmp = read_cpu_reg(s, rt, sf);
892
    label_match = gen_new_label();
893

    
894
    tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
895
                        tcg_cmp, 0, label_match);
896

    
897
    gen_goto_tb(s, 0, s->pc);
898
    gen_set_label(label_match);
899
    gen_goto_tb(s, 1, addr);
900
}
901

    
902
/* C3.2.5 Test & branch (immediate)
903
 *   31  30         25  24  23   19 18          5 4    0
904
 * +----+-------------+----+-------+-------------+------+
905
 * | b5 | 0 1 1 0 1 1 | op |  b40  |    imm14    |  Rt  |
906
 * +----+-------------+----+-------+-------------+------+
907
 */
908
static void disas_test_b_imm(DisasContext *s, uint32_t insn)
909
{
910
    unsigned int bit_pos, op, rt;
911
    uint64_t addr;
912
    int label_match;
913
    TCGv_i64 tcg_cmp;
914

    
915
    bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
916
    op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
917
    addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
918
    rt = extract32(insn, 0, 5);
919

    
920
    tcg_cmp = tcg_temp_new_i64();
921
    tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
922
    label_match = gen_new_label();
923
    tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
924
                        tcg_cmp, 0, label_match);
925
    tcg_temp_free_i64(tcg_cmp);
926
    gen_goto_tb(s, 0, s->pc);
927
    gen_set_label(label_match);
928
    gen_goto_tb(s, 1, addr);
929
}
930

    
931
/* C3.2.2 / C5.6.19 Conditional branch (immediate)
932
 *  31           25  24  23                  5   4  3    0
933
 * +---------------+----+---------------------+----+------+
934
 * | 0 1 0 1 0 1 0 | o1 |         imm19       | o0 | cond |
935
 * +---------------+----+---------------------+----+------+
936
 */
937
static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
938
{
939
    unsigned int cond;
940
    uint64_t addr;
941

    
942
    if ((insn & (1 << 4)) || (insn & (1 << 24))) {
943
        unallocated_encoding(s);
944
        return;
945
    }
946
    addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
947
    cond = extract32(insn, 0, 4);
948

    
949
    if (cond < 0x0e) {
950
        /* genuinely conditional branches */
951
        int label_match = gen_new_label();
952
        arm_gen_test_cc(cond, label_match);
953
        gen_goto_tb(s, 0, s->pc);
954
        gen_set_label(label_match);
955
        gen_goto_tb(s, 1, addr);
956
    } else {
957
        /* 0xe and 0xf are both "always" conditions */
958
        gen_goto_tb(s, 0, addr);
959
    }
960
}
961

    
962
/* C5.6.68 HINT */
963
static void handle_hint(DisasContext *s, uint32_t insn,
964
                        unsigned int op1, unsigned int op2, unsigned int crm)
965
{
966
    unsigned int selector = crm << 3 | op2;
967

    
968
    if (op1 != 3) {
969
        unallocated_encoding(s);
970
        return;
971
    }
972

    
973
    switch (selector) {
974
    case 0: /* NOP */
975
        return;
976
    case 1: /* YIELD */
977
    case 2: /* WFE */
978
    case 3: /* WFI */
979
    case 4: /* SEV */
980
    case 5: /* SEVL */
981
        /* we treat all as NOP at least for now */
982
        return;
983
    default:
984
        /* default specified as NOP equivalent */
985
        return;
986
    }
987
}
988

    
989
static void gen_clrex(DisasContext *s, uint32_t insn)
990
{
991
    tcg_gen_movi_i64(cpu_exclusive_addr, -1);
992
}
993

    
994
/* CLREX, DSB, DMB, ISB */
995
static void handle_sync(DisasContext *s, uint32_t insn,
996
                        unsigned int op1, unsigned int op2, unsigned int crm)
997
{
998
    if (op1 != 3) {
999
        unallocated_encoding(s);
1000
        return;
1001
    }
1002

    
1003
    switch (op2) {
1004
    case 2: /* CLREX */
1005
        gen_clrex(s, insn);
1006
        return;
1007
    case 4: /* DSB */
1008
    case 5: /* DMB */
1009
    case 6: /* ISB */
1010
        /* We don't emulate caches so barriers are no-ops */
1011
        return;
1012
    default:
1013
        unallocated_encoding(s);
1014
        return;
1015
    }
1016
}
1017

    
1018
/* C5.6.130 MSR (immediate) - move immediate to processor state field */
1019
static void handle_msr_i(DisasContext *s, uint32_t insn,
1020
                         unsigned int op1, unsigned int op2, unsigned int crm)
1021
{
1022
    unsupported_encoding(s, insn);
1023
}
1024

    
1025
static void gen_get_nzcv(TCGv_i64 tcg_rt)
1026
{
1027
    TCGv_i32 tmp = tcg_temp_new_i32();
1028
    TCGv_i32 nzcv = tcg_temp_new_i32();
1029

    
1030
    /* build bit 31, N */
1031
    tcg_gen_andi_i32(nzcv, cpu_NF, (1 << 31));
1032
    /* build bit 30, Z */
1033
    tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_ZF, 0);
1034
    tcg_gen_deposit_i32(nzcv, nzcv, tmp, 30, 1);
1035
    /* build bit 29, C */
1036
    tcg_gen_deposit_i32(nzcv, nzcv, cpu_CF, 29, 1);
1037
    /* build bit 28, V */
1038
    tcg_gen_shri_i32(tmp, cpu_VF, 31);
1039
    tcg_gen_deposit_i32(nzcv, nzcv, tmp, 28, 1);
1040
    /* generate result */
1041
    tcg_gen_extu_i32_i64(tcg_rt, nzcv);
1042

    
1043
    tcg_temp_free_i32(nzcv);
1044
    tcg_temp_free_i32(tmp);
1045
}
1046

    
1047
static void gen_set_nzcv(TCGv_i64 tcg_rt)
1048

    
1049
{
1050
    TCGv_i32 nzcv = tcg_temp_new_i32();
1051

    
1052
    /* take NZCV from R[t] */
1053
    tcg_gen_trunc_i64_i32(nzcv, tcg_rt);
1054

    
1055
    /* bit 31, N */
1056
    tcg_gen_andi_i32(cpu_NF, nzcv, (1 << 31));
1057
    /* bit 30, Z */
1058
    tcg_gen_andi_i32(cpu_ZF, nzcv, (1 << 30));
1059
    tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_ZF, cpu_ZF, 0);
1060
    /* bit 29, C */
1061
    tcg_gen_andi_i32(cpu_CF, nzcv, (1 << 29));
1062
    tcg_gen_shri_i32(cpu_CF, cpu_CF, 29);
1063
    /* bit 28, V */
1064
    tcg_gen_andi_i32(cpu_VF, nzcv, (1 << 28));
1065
    tcg_gen_shli_i32(cpu_VF, cpu_VF, 3);
1066
    tcg_temp_free_i32(nzcv);
1067
}
1068

    
1069
/* C5.6.129 MRS - move from system register
1070
 * C5.6.131 MSR (register) - move to system register
1071
 * C5.6.204 SYS
1072
 * C5.6.205 SYSL
1073
 * These are all essentially the same insn in 'read' and 'write'
1074
 * versions, with varying op0 fields.
1075
 */
1076
static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
1077
                       unsigned int op0, unsigned int op1, unsigned int op2,
1078
                       unsigned int crn, unsigned int crm, unsigned int rt)
1079
{
1080
    const ARMCPRegInfo *ri;
1081
    TCGv_i64 tcg_rt;
1082

    
1083
    ri = get_arm_cp_reginfo(s->cp_regs,
1084
                            ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
1085
                                               crn, crm, op0, op1, op2));
1086

    
1087
    if (!ri) {
1088
        /* Unknown register */
1089
        unallocated_encoding(s);
1090
        return;
1091
    }
1092

    
1093
    /* Check access permissions */
1094
    if (!cp_access_ok(s->current_pl, ri, isread)) {
1095
        unallocated_encoding(s);
1096
        return;
1097
    }
1098

    
1099
    /* Handle special cases first */
1100
    switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
1101
    case ARM_CP_NOP:
1102
        return;
1103
    case ARM_CP_NZCV:
1104
        tcg_rt = cpu_reg(s, rt);
1105
        if (isread) {
1106
            gen_get_nzcv(tcg_rt);
1107
        } else {
1108
            gen_set_nzcv(tcg_rt);
1109
        }
1110
        return;
1111
    default:
1112
        break;
1113
    }
1114

    
1115
    if (use_icount && (ri->type & ARM_CP_IO)) {
1116
        gen_io_start();
1117
    }
1118

    
1119
    tcg_rt = cpu_reg(s, rt);
1120

    
1121
    if (isread) {
1122
        if (ri->type & ARM_CP_CONST) {
1123
            tcg_gen_movi_i64(tcg_rt, ri->resetvalue);
1124
        } else if (ri->readfn) {
1125
            TCGv_ptr tmpptr;
1126
            gen_a64_set_pc_im(s->pc - 4);
1127
            tmpptr = tcg_const_ptr(ri);
1128
            gen_helper_get_cp_reg64(tcg_rt, cpu_env, tmpptr);
1129
            tcg_temp_free_ptr(tmpptr);
1130
        } else {
1131
            tcg_gen_ld_i64(tcg_rt, cpu_env, ri->fieldoffset);
1132
        }
1133
    } else {
1134
        if (ri->type & ARM_CP_CONST) {
1135
            /* If not forbidden by access permissions, treat as WI */
1136
            return;
1137
        } else if (ri->writefn) {
1138
            TCGv_ptr tmpptr;
1139
            gen_a64_set_pc_im(s->pc - 4);
1140
            tmpptr = tcg_const_ptr(ri);
1141
            gen_helper_set_cp_reg64(cpu_env, tmpptr, tcg_rt);
1142
            tcg_temp_free_ptr(tmpptr);
1143
        } else {
1144
            tcg_gen_st_i64(tcg_rt, cpu_env, ri->fieldoffset);
1145
        }
1146
    }
1147

    
1148
    if (use_icount && (ri->type & ARM_CP_IO)) {
1149
        /* I/O operations must end the TB here (whether read or write) */
1150
        gen_io_end();
1151
        s->is_jmp = DISAS_UPDATE;
1152
    } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
1153
        /* We default to ending the TB on a coprocessor register write,
1154
         * but allow this to be suppressed by the register definition
1155
         * (usually only necessary to work around guest bugs).
1156
         */
1157
        s->is_jmp = DISAS_UPDATE;
1158
    }
1159
}
1160

    
1161
/* C3.2.4 System
1162
 *  31                 22 21  20 19 18 16 15   12 11    8 7   5 4    0
1163
 * +---------------------+---+-----+-----+-------+-------+-----+------+
1164
 * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 |  CRn  |  CRm  | op2 |  Rt  |
1165
 * +---------------------+---+-----+-----+-------+-------+-----+------+
1166
 */
1167
static void disas_system(DisasContext *s, uint32_t insn)
1168
{
1169
    unsigned int l, op0, op1, crn, crm, op2, rt;
1170
    l = extract32(insn, 21, 1);
1171
    op0 = extract32(insn, 19, 2);
1172
    op1 = extract32(insn, 16, 3);
1173
    crn = extract32(insn, 12, 4);
1174
    crm = extract32(insn, 8, 4);
1175
    op2 = extract32(insn, 5, 3);
1176
    rt = extract32(insn, 0, 5);
1177

    
1178
    if (op0 == 0) {
1179
        if (l || rt != 31) {
1180
            unallocated_encoding(s);
1181
            return;
1182
        }
1183
        switch (crn) {
1184
        case 2: /* C5.6.68 HINT */
1185
            handle_hint(s, insn, op1, op2, crm);
1186
            break;
1187
        case 3: /* CLREX, DSB, DMB, ISB */
1188
            handle_sync(s, insn, op1, op2, crm);
1189
            break;
1190
        case 4: /* C5.6.130 MSR (immediate) */
1191
            handle_msr_i(s, insn, op1, op2, crm);
1192
            break;
1193
        default:
1194
            unallocated_encoding(s);
1195
            break;
1196
        }
1197
        return;
1198
    }
1199
    handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
1200
}
1201

    
1202
/* C3.2.3 Exception generation
1203
 *
1204
 *  31             24 23 21 20                     5 4   2 1  0
1205
 * +-----------------+-----+------------------------+-----+----+
1206
 * | 1 1 0 1 0 1 0 0 | opc |          imm16         | op2 | LL |
1207
 * +-----------------------+------------------------+----------+
1208
 */
1209
static void disas_exc(DisasContext *s, uint32_t insn)
1210
{
1211
    int opc = extract32(insn, 21, 3);
1212
    int op2_ll = extract32(insn, 0, 5);
1213

    
1214
    switch (opc) {
1215
    case 0:
1216
        /* SVC, HVC, SMC; since we don't support the Virtualization
1217
         * or TrustZone extensions these all UNDEF except SVC.
1218
         */
1219
        if (op2_ll != 1) {
1220
            unallocated_encoding(s);
1221
            break;
1222
        }
1223
        gen_exception_insn(s, 0, EXCP_SWI);
1224
        break;
1225
    case 1:
1226
        if (op2_ll != 0) {
1227
            unallocated_encoding(s);
1228
            break;
1229
        }
1230
        /* BRK */
1231
        gen_exception_insn(s, 0, EXCP_BKPT);
1232
        break;
1233
    case 2:
1234
        if (op2_ll != 0) {
1235
            unallocated_encoding(s);
1236
            break;
1237
        }
1238
        /* HLT */
1239
        unsupported_encoding(s, insn);
1240
        break;
1241
    case 5:
1242
        if (op2_ll < 1 || op2_ll > 3) {
1243
            unallocated_encoding(s);
1244
            break;
1245
        }
1246
        /* DCPS1, DCPS2, DCPS3 */
1247
        unsupported_encoding(s, insn);
1248
        break;
1249
    default:
1250
        unallocated_encoding(s);
1251
        break;
1252
    }
1253
}
1254

    
1255
/* C3.2.7 Unconditional branch (register)
1256
 *  31           25 24   21 20   16 15   10 9    5 4     0
1257
 * +---------------+-------+-------+-------+------+-------+
1258
 * | 1 1 0 1 0 1 1 |  opc  |  op2  |  op3  |  Rn  |  op4  |
1259
 * +---------------+-------+-------+-------+------+-------+
1260
 */
1261
static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
1262
{
1263
    unsigned int opc, op2, op3, rn, op4;
1264

    
1265
    opc = extract32(insn, 21, 4);
1266
    op2 = extract32(insn, 16, 5);
1267
    op3 = extract32(insn, 10, 6);
1268
    rn = extract32(insn, 5, 5);
1269
    op4 = extract32(insn, 0, 5);
1270

    
1271
    if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
1272
        unallocated_encoding(s);
1273
        return;
1274
    }
1275

    
1276
    switch (opc) {
1277
    case 0: /* BR */
1278
    case 2: /* RET */
1279
        break;
1280
    case 1: /* BLR */
1281
        tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
1282
        break;
1283
    case 4: /* ERET */
1284
    case 5: /* DRPS */
1285
        if (rn != 0x1f) {
1286
            unallocated_encoding(s);
1287
        } else {
1288
            unsupported_encoding(s, insn);
1289
        }
1290
        return;
1291
    default:
1292
        unallocated_encoding(s);
1293
        return;
1294
    }
1295

    
1296
    tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
1297
    s->is_jmp = DISAS_JUMP;
1298
}
1299

    
1300
/* C3.2 Branches, exception generating and system instructions */
1301
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
1302
{
1303
    switch (extract32(insn, 25, 7)) {
1304
    case 0x0a: case 0x0b:
1305
    case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
1306
        disas_uncond_b_imm(s, insn);
1307
        break;
1308
    case 0x1a: case 0x5a: /* Compare & branch (immediate) */
1309
        disas_comp_b_imm(s, insn);
1310
        break;
1311
    case 0x1b: case 0x5b: /* Test & branch (immediate) */
1312
        disas_test_b_imm(s, insn);
1313
        break;
1314
    case 0x2a: /* Conditional branch (immediate) */
1315
        disas_cond_b_imm(s, insn);
1316
        break;
1317
    case 0x6a: /* Exception generation / System */
1318
        if (insn & (1 << 24)) {
1319
            disas_system(s, insn);
1320
        } else {
1321
            disas_exc(s, insn);
1322
        }
1323
        break;
1324
    case 0x6b: /* Unconditional branch (register) */
1325
        disas_uncond_b_reg(s, insn);
1326
        break;
1327
    default:
1328
        unallocated_encoding(s);
1329
        break;
1330
    }
1331
}
1332

    
1333
/*
1334
 * Load/Store exclusive instructions are implemented by remembering
1335
 * the value/address loaded, and seeing if these are the same
1336
 * when the store is performed. This is not actually the architecturally
1337
 * mandated semantics, but it works for typical guest code sequences
1338
 * and avoids having to monitor regular stores.
1339
 *
1340
 * In system emulation mode only one CPU will be running at once, so
1341
 * this sequence is effectively atomic.  In user emulation mode we
1342
 * throw an exception and handle the atomic operation elsewhere.
1343
 */
1344
static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
1345
                               TCGv_i64 addr, int size, bool is_pair)
1346
{
1347
    TCGv_i64 tmp = tcg_temp_new_i64();
1348
    TCGMemOp memop = MO_TE + size;
1349

    
1350
    g_assert(size <= 3);
1351
    tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
1352

    
1353
    if (is_pair) {
1354
        TCGv_i64 addr2 = tcg_temp_new_i64();
1355
        TCGv_i64 hitmp = tcg_temp_new_i64();
1356

    
1357
        g_assert(size >= 2);
1358
        tcg_gen_addi_i64(addr2, addr, 1 << size);
1359
        tcg_gen_qemu_ld_i64(hitmp, addr2, get_mem_index(s), memop);
1360
        tcg_temp_free_i64(addr2);
1361
        tcg_gen_mov_i64(cpu_exclusive_high, hitmp);
1362
        tcg_gen_mov_i64(cpu_reg(s, rt2), hitmp);
1363
        tcg_temp_free_i64(hitmp);
1364
    }
1365

    
1366
    tcg_gen_mov_i64(cpu_exclusive_val, tmp);
1367
    tcg_gen_mov_i64(cpu_reg(s, rt), tmp);
1368

    
1369
    tcg_temp_free_i64(tmp);
1370
    tcg_gen_mov_i64(cpu_exclusive_addr, addr);
1371
}
1372

    
1373
#ifdef CONFIG_USER_ONLY
1374
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
1375
                                TCGv_i64 addr, int size, int is_pair)
1376
{
1377
    tcg_gen_mov_i64(cpu_exclusive_test, addr);
1378
    tcg_gen_movi_i32(cpu_exclusive_info,
1379
                     size | is_pair << 2 | (rd << 4) | (rt << 9) | (rt2 << 14));
1380
    gen_exception_insn(s, 4, EXCP_STREX);
1381
}
1382
#else
1383
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
1384
                                TCGv_i64 addr, int size, int is_pair)
1385
{
1386
    qemu_log_mask(LOG_UNIMP,
1387
                  "%s:%d: system mode store_exclusive unsupported "
1388
                  "at pc=%016" PRIx64 "\n",
1389
                  __FILE__, __LINE__, s->pc - 4);
1390
}
1391
#endif
1392

    
1393
/* C3.3.6 Load/store exclusive
1394
 *
1395
 *  31 30 29         24  23  22   21  20  16  15  14   10 9    5 4    0
1396
 * +-----+-------------+----+---+----+------+----+-------+------+------+
1397
 * | sz  | 0 0 1 0 0 0 | o2 | L | o1 |  Rs  | o0 |  Rt2  |  Rn  | Rt   |
1398
 * +-----+-------------+----+---+----+------+----+-------+------+------+
1399
 *
1400
 *  sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
1401
 *   L: 0 -> store, 1 -> load
1402
 *  o2: 0 -> exclusive, 1 -> not
1403
 *  o1: 0 -> single register, 1 -> register pair
1404
 *  o0: 1 -> load-acquire/store-release, 0 -> not
1405
 *
1406
 *  o0 == 0 AND o2 == 1 is un-allocated
1407
 *  o1 == 1 is un-allocated except for 32 and 64 bit sizes
1408
 */
1409
static void disas_ldst_excl(DisasContext *s, uint32_t insn)
1410
{
1411
    int rt = extract32(insn, 0, 5);
1412
    int rn = extract32(insn, 5, 5);
1413
    int rt2 = extract32(insn, 10, 5);
1414
    int is_lasr = extract32(insn, 15, 1);
1415
    int rs = extract32(insn, 16, 5);
1416
    int is_pair = extract32(insn, 21, 1);
1417
    int is_store = !extract32(insn, 22, 1);
1418
    int is_excl = !extract32(insn, 23, 1);
1419
    int size = extract32(insn, 30, 2);
1420
    TCGv_i64 tcg_addr;
1421

    
1422
    if ((!is_excl && !is_lasr) ||
1423
        (is_pair && size < 2)) {
1424
        unallocated_encoding(s);
1425
        return;
1426
    }
1427

    
1428
    if (rn == 31) {
1429
        gen_check_sp_alignment(s);
1430
    }
1431
    tcg_addr = read_cpu_reg_sp(s, rn, 1);
1432

    
1433
    /* Note that since TCG is single threaded load-acquire/store-release
1434
     * semantics require no extra if (is_lasr) { ... } handling.
1435
     */
1436

    
1437
    if (is_excl) {
1438
        if (!is_store) {
1439
            gen_load_exclusive(s, rt, rt2, tcg_addr, size, is_pair);
1440
        } else {
1441
            gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, is_pair);
1442
        }
1443
    } else {
1444
        TCGv_i64 tcg_rt = cpu_reg(s, rt);
1445
        if (is_store) {
1446
            do_gpr_st(s, tcg_rt, tcg_addr, size);
1447
        } else {
1448
            do_gpr_ld(s, tcg_rt, tcg_addr, size, false, false);
1449
        }
1450
        if (is_pair) {
1451
            TCGv_i64 tcg_rt2 = cpu_reg(s, rt);
1452
            tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
1453
            if (is_store) {
1454
                do_gpr_st(s, tcg_rt2, tcg_addr, size);
1455
            } else {
1456
                do_gpr_ld(s, tcg_rt2, tcg_addr, size, false, false);
1457
            }
1458
        }
1459
    }
1460
}
1461

    
1462
/*
1463
 * C3.3.5 Load register (literal)
1464
 *
1465
 *  31 30 29   27  26 25 24 23                5 4     0
1466
 * +-----+-------+---+-----+-------------------+-------+
1467
 * | opc | 0 1 1 | V | 0 0 |     imm19         |  Rt   |
1468
 * +-----+-------+---+-----+-------------------+-------+
1469
 *
1470
 * V: 1 -> vector (simd/fp)
1471
 * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
1472
 *                   10-> 32 bit signed, 11 -> prefetch
1473
 * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
1474
 */
1475
static void disas_ld_lit(DisasContext *s, uint32_t insn)
1476
{
1477
    int rt = extract32(insn, 0, 5);
1478
    int64_t imm = sextract32(insn, 5, 19) << 2;
1479
    bool is_vector = extract32(insn, 26, 1);
1480
    int opc = extract32(insn, 30, 2);
1481
    bool is_signed = false;
1482
    int size = 2;
1483
    TCGv_i64 tcg_rt, tcg_addr;
1484

    
1485
    if (is_vector) {
1486
        if (opc == 3) {
1487
            unallocated_encoding(s);
1488
            return;
1489
        }
1490
        size = 2 + opc;
1491
    } else {
1492
        if (opc == 3) {
1493
            /* PRFM (literal) : prefetch */
1494
            return;
1495
        }
1496
        size = 2 + extract32(opc, 0, 1);
1497
        is_signed = extract32(opc, 1, 1);
1498
    }
1499

    
1500
    tcg_rt = cpu_reg(s, rt);
1501

    
1502
    tcg_addr = tcg_const_i64((s->pc - 4) + imm);
1503
    if (is_vector) {
1504
        do_fp_ld(s, rt, tcg_addr, size);
1505
    } else {
1506
        do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
1507
    }
1508
    tcg_temp_free_i64(tcg_addr);
1509
}
1510

    
1511
/*
1512
 * C5.6.80 LDNP (Load Pair - non-temporal hint)
1513
 * C5.6.81 LDP (Load Pair - non vector)
1514
 * C5.6.82 LDPSW (Load Pair Signed Word - non vector)
1515
 * C5.6.176 STNP (Store Pair - non-temporal hint)
1516
 * C5.6.177 STP (Store Pair - non vector)
1517
 * C6.3.165 LDNP (Load Pair of SIMD&FP - non-temporal hint)
1518
 * C6.3.165 LDP (Load Pair of SIMD&FP)
1519
 * C6.3.284 STNP (Store Pair of SIMD&FP - non-temporal hint)
1520
 * C6.3.284 STP (Store Pair of SIMD&FP)
1521
 *
1522
 *  31 30 29   27  26  25 24   23  22 21   15 14   10 9    5 4    0
1523
 * +-----+-------+---+---+-------+---+-----------------------------+
1524
 * | opc | 1 0 1 | V | 0 | index | L |  imm7 |  Rt2  |  Rn  | Rt   |
1525
 * +-----+-------+---+---+-------+---+-------+-------+------+------+
1526
 *
1527
 * opc: LDP/STP/LDNP/STNP        00 -> 32 bit, 10 -> 64 bit
1528
 *      LDPSW                    01
1529
 *      LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
1530
 *   V: 0 -> GPR, 1 -> Vector
1531
 * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
1532
 *      10 -> signed offset, 11 -> pre-index
1533
 *   L: 0 -> Store 1 -> Load
1534
 *
1535
 * Rt, Rt2 = GPR or SIMD registers to be stored
1536
 * Rn = general purpose register containing address
1537
 * imm7 = signed offset (multiple of 4 or 8 depending on size)
1538
 */
1539
static void disas_ldst_pair(DisasContext *s, uint32_t insn)
1540
{
1541
    int rt = extract32(insn, 0, 5);
1542
    int rn = extract32(insn, 5, 5);
1543
    int rt2 = extract32(insn, 10, 5);
1544
    int64_t offset = sextract32(insn, 15, 7);
1545
    int index = extract32(insn, 23, 2);
1546
    bool is_vector = extract32(insn, 26, 1);
1547
    bool is_load = extract32(insn, 22, 1);
1548
    int opc = extract32(insn, 30, 2);
1549

    
1550
    bool is_signed = false;
1551
    bool postindex = false;
1552
    bool wback = false;
1553

    
1554
    TCGv_i64 tcg_addr; /* calculated address */
1555
    int size;
1556

    
1557
    if (opc == 3) {
1558
        unallocated_encoding(s);
1559
        return;
1560
    }
1561

    
1562
    if (is_vector) {
1563
        size = 2 + opc;
1564
    } else {
1565
        size = 2 + extract32(opc, 1, 1);
1566
        is_signed = extract32(opc, 0, 1);
1567
        if (!is_load && is_signed) {
1568
            unallocated_encoding(s);
1569
            return;
1570
        }
1571
    }
1572

    
1573
    switch (index) {
1574
    case 1: /* post-index */
1575
        postindex = true;
1576
        wback = true;
1577
        break;
1578
    case 0:
1579
        /* signed offset with "non-temporal" hint. Since we don't emulate
1580
         * caches we don't care about hints to the cache system about
1581
         * data access patterns, and handle this identically to plain
1582
         * signed offset.
1583
         */
1584
        if (is_signed) {
1585
            /* There is no non-temporal-hint version of LDPSW */
1586
            unallocated_encoding(s);
1587
            return;
1588
        }
1589
        postindex = false;
1590
        break;
1591
    case 2: /* signed offset, rn not updated */
1592
        postindex = false;
1593
        break;
1594
    case 3: /* pre-index */
1595
        postindex = false;
1596
        wback = true;
1597
        break;
1598
    }
1599

    
1600
    offset <<= size;
1601

    
1602
    if (rn == 31) {
1603
        gen_check_sp_alignment(s);
1604
    }
1605

    
1606
    tcg_addr = read_cpu_reg_sp(s, rn, 1);
1607

    
1608
    if (!postindex) {
1609
        tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
1610
    }
1611

    
1612
    if (is_vector) {
1613
        if (is_load) {
1614
            do_fp_ld(s, rt, tcg_addr, size);
1615
        } else {
1616
            do_fp_st(s, rt, tcg_addr, size);
1617
        }
1618
    } else {
1619
        TCGv_i64 tcg_rt = cpu_reg(s, rt);
1620
        if (is_load) {
1621
            do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
1622
        } else {
1623
            do_gpr_st(s, tcg_rt, tcg_addr, size);
1624
        }
1625
    }
1626
    tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
1627
    if (is_vector) {
1628
        if (is_load) {
1629
            do_fp_ld(s, rt2, tcg_addr, size);
1630
        } else {
1631
            do_fp_st(s, rt2, tcg_addr, size);
1632
        }
1633
    } else {
1634
        TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
1635
        if (is_load) {
1636
            do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false);
1637
        } else {
1638
            do_gpr_st(s, tcg_rt2, tcg_addr, size);
1639
        }
1640
    }
1641

    
1642
    if (wback) {
1643
        if (postindex) {
1644
            tcg_gen_addi_i64(tcg_addr, tcg_addr, offset - (1 << size));
1645
        } else {
1646
            tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size);
1647
        }
1648
        tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
1649
    }
1650
}
1651

    
1652
/*
1653
 * C3.3.8 Load/store (immediate post-indexed)
1654
 * C3.3.9 Load/store (immediate pre-indexed)
1655
 * C3.3.12 Load/store (unscaled immediate)
1656
 *
1657
 * 31 30 29   27  26 25 24 23 22 21  20    12 11 10 9    5 4    0
1658
 * +----+-------+---+-----+-----+---+--------+-----+------+------+
1659
 * |size| 1 1 1 | V | 0 0 | opc | 0 |  imm9  | idx |  Rn  |  Rt  |
1660
 * +----+-------+---+-----+-----+---+--------+-----+------+------+
1661
 *
1662
 * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
1663
 * V = 0 -> non-vector
1664
 * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
1665
 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1666
 */
1667
static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn)
1668
{
1669
    int rt = extract32(insn, 0, 5);
1670
    int rn = extract32(insn, 5, 5);
1671
    int imm9 = sextract32(insn, 12, 9);
1672
    int opc = extract32(insn, 22, 2);
1673
    int size = extract32(insn, 30, 2);
1674
    int idx = extract32(insn, 10, 2);
1675
    bool is_signed = false;
1676
    bool is_store = false;
1677
    bool is_extended = false;
1678
    bool is_vector = extract32(insn, 26, 1);
1679
    bool post_index;
1680
    bool writeback;
1681

    
1682
    TCGv_i64 tcg_addr;
1683

    
1684
    if (is_vector) {
1685
        size |= (opc & 2) << 1;
1686
        if (size > 4) {
1687
            unallocated_encoding(s);
1688
            return;
1689
        }
1690
        is_store = ((opc & 1) == 0);
1691
    } else {
1692
        if (size == 3 && opc == 2) {
1693
            /* PRFM - prefetch */
1694
            return;
1695
        }
1696
        if (opc == 3 && size > 1) {
1697
            unallocated_encoding(s);
1698
            return;
1699
        }
1700
        is_store = (opc == 0);
1701
        is_signed = opc & (1<<1);
1702
        is_extended = (size < 3) && (opc & 1);
1703
    }
1704

    
1705
    switch (idx) {
1706
    case 0:
1707
        post_index = false;
1708
        writeback = false;
1709
        break;
1710
    case 1:
1711
        post_index = true;
1712
        writeback = true;
1713
        break;
1714
    case 3:
1715
        post_index = false;
1716
        writeback = true;
1717
        break;
1718
    case 2:
1719
        g_assert(false);
1720
        break;
1721
    }
1722

    
1723
    if (rn == 31) {
1724
        gen_check_sp_alignment(s);
1725
    }
1726
    tcg_addr = read_cpu_reg_sp(s, rn, 1);
1727

    
1728
    if (!post_index) {
1729
        tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
1730
    }
1731

    
1732
    if (is_vector) {
1733
        if (is_store) {
1734
            do_fp_st(s, rt, tcg_addr, size);
1735
        } else {
1736
            do_fp_ld(s, rt, tcg_addr, size);
1737
        }
1738
    } else {
1739
        TCGv_i64 tcg_rt = cpu_reg(s, rt);
1740
        if (is_store) {
1741
            do_gpr_st(s, tcg_rt, tcg_addr, size);
1742
        } else {
1743
            do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1744
        }
1745
    }
1746

    
1747
    if (writeback) {
1748
        TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
1749
        if (post_index) {
1750
            tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
1751
        }
1752
        tcg_gen_mov_i64(tcg_rn, tcg_addr);
1753
    }
1754
}
1755

    
1756
/*
1757
 * C3.3.10 Load/store (register offset)
1758
 *
1759
 * 31 30 29   27  26 25 24 23 22 21  20  16 15 13 12 11 10 9  5 4  0
1760
 * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
1761
 * |size| 1 1 1 | V | 0 0 | opc | 1 |  Rm  | opt | S| 1 0 | Rn | Rt |
1762
 * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
1763
 *
1764
 * For non-vector:
1765
 *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
1766
 *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1767
 * For vector:
1768
 *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
1769
 *   opc<0>: 0 -> store, 1 -> load
1770
 * V: 1 -> vector/simd
1771
 * opt: extend encoding (see DecodeRegExtend)
1772
 * S: if S=1 then scale (essentially index by sizeof(size))
1773
 * Rt: register to transfer into/out of
1774
 * Rn: address register or SP for base
1775
 * Rm: offset register or ZR for offset
1776
 */
1777
static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn)
1778
{
1779
    int rt = extract32(insn, 0, 5);
1780
    int rn = extract32(insn, 5, 5);
1781
    int shift = extract32(insn, 12, 1);
1782
    int rm = extract32(insn, 16, 5);
1783
    int opc = extract32(insn, 22, 2);
1784
    int opt = extract32(insn, 13, 3);
1785
    int size = extract32(insn, 30, 2);
1786
    bool is_signed = false;
1787
    bool is_store = false;
1788
    bool is_extended = false;
1789
    bool is_vector = extract32(insn, 26, 1);
1790

    
1791
    TCGv_i64 tcg_rm;
1792
    TCGv_i64 tcg_addr;
1793

    
1794
    if (extract32(opt, 1, 1) == 0) {
1795
        unallocated_encoding(s);
1796
        return;
1797
    }
1798

    
1799
    if (is_vector) {
1800
        size |= (opc & 2) << 1;
1801
        if (size > 4) {
1802
            unallocated_encoding(s);
1803
            return;
1804
        }
1805
        is_store = !extract32(opc, 0, 1);
1806
    } else {
1807
        if (size == 3 && opc == 2) {
1808
            /* PRFM - prefetch */
1809
            return;
1810
        }
1811
        if (opc == 3 && size > 1) {
1812
            unallocated_encoding(s);
1813
            return;
1814
        }
1815
        is_store = (opc == 0);
1816
        is_signed = extract32(opc, 1, 1);
1817
        is_extended = (size < 3) && extract32(opc, 0, 1);
1818
    }
1819

    
1820
    if (rn == 31) {
1821
        gen_check_sp_alignment(s);
1822
    }
1823
    tcg_addr = read_cpu_reg_sp(s, rn, 1);
1824

    
1825
    tcg_rm = read_cpu_reg(s, rm, 1);
1826
    ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
1827

    
1828
    tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_rm);
1829

    
1830
    if (is_vector) {
1831
        if (is_store) {
1832
            do_fp_st(s, rt, tcg_addr, size);
1833
        } else {
1834
            do_fp_ld(s, rt, tcg_addr, size);
1835
        }
1836
    } else {
1837
        TCGv_i64 tcg_rt = cpu_reg(s, rt);
1838
        if (is_store) {
1839
            do_gpr_st(s, tcg_rt, tcg_addr, size);
1840
        } else {
1841
            do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1842
        }
1843
    }
1844
}
1845

    
1846
/*
1847
 * C3.3.13 Load/store (unsigned immediate)
1848
 *
1849
 * 31 30 29   27  26 25 24 23 22 21        10 9     5
1850
 * +----+-------+---+-----+-----+------------+-------+------+
1851
 * |size| 1 1 1 | V | 0 1 | opc |   imm12    |  Rn   |  Rt  |
1852
 * +----+-------+---+-----+-----+------------+-------+------+
1853
 *
1854
 * For non-vector:
1855
 *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
1856
 *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1857
 * For vector:
1858
 *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
1859
 *   opc<0>: 0 -> store, 1 -> load
1860
 * Rn: base address register (inc SP)
1861
 * Rt: target register
1862
 */
1863
static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn)
1864
{
1865
    int rt = extract32(insn, 0, 5);
1866
    int rn = extract32(insn, 5, 5);
1867
    unsigned int imm12 = extract32(insn, 10, 12);
1868
    bool is_vector = extract32(insn, 26, 1);
1869
    int size = extract32(insn, 30, 2);
1870
    int opc = extract32(insn, 22, 2);
1871
    unsigned int offset;
1872

    
1873
    TCGv_i64 tcg_addr;
1874

    
1875
    bool is_store;
1876
    bool is_signed = false;
1877
    bool is_extended = false;
1878

    
1879
    if (is_vector) {
1880
        size |= (opc & 2) << 1;
1881
        if (size > 4) {
1882
            unallocated_encoding(s);
1883
            return;
1884
        }
1885
        is_store = !extract32(opc, 0, 1);
1886
    } else {
1887
        if (size == 3 && opc == 2) {
1888
            /* PRFM - prefetch */
1889
            return;
1890
        }
1891
        if (opc == 3 && size > 1) {
1892
            unallocated_encoding(s);
1893
            return;
1894
        }
1895
        is_store = (opc == 0);
1896
        is_signed = extract32(opc, 1, 1);
1897
        is_extended = (size < 3) && extract32(opc, 0, 1);
1898
    }
1899

    
1900
    if (rn == 31) {
1901
        gen_check_sp_alignment(s);
1902
    }
1903
    tcg_addr = read_cpu_reg_sp(s, rn, 1);
1904
    offset = imm12 << size;
1905
    tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
1906

    
1907
    if (is_vector) {
1908
        if (is_store) {
1909
            do_fp_st(s, rt, tcg_addr, size);
1910
        } else {
1911
            do_fp_ld(s, rt, tcg_addr, size);
1912
        }
1913
    } else {
1914
        TCGv_i64 tcg_rt = cpu_reg(s, rt);
1915
        if (is_store) {
1916
            do_gpr_st(s, tcg_rt, tcg_addr, size);
1917
        } else {
1918
            do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1919
        }
1920
    }
1921
}
1922

    
1923
/* Load/store register (immediate forms) */
1924
static void disas_ldst_reg_imm(DisasContext *s, uint32_t insn)
1925
{
1926
    switch (extract32(insn, 10, 2)) {
1927
    case 0: case 1: case 3:
1928
        /* Load/store register (unscaled immediate) */
1929
        /* Load/store immediate pre/post-indexed */
1930
        disas_ldst_reg_imm9(s, insn);
1931
        break;
1932
    case 2:
1933
        /* Load/store register unprivileged */
1934
        unsupported_encoding(s, insn);
1935
        break;
1936
    default:
1937
        unallocated_encoding(s);
1938
        break;
1939
    }
1940
}
1941

    
1942
/* Load/store register (all forms) */
1943
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
1944
{
1945
    switch (extract32(insn, 24, 2)) {
1946
    case 0:
1947
        if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) {
1948
            disas_ldst_reg_roffset(s, insn);
1949
        } else {
1950
            disas_ldst_reg_imm(s, insn);
1951
        }
1952
        break;
1953
    case 1:
1954
        disas_ldst_reg_unsigned_imm(s, insn);
1955
        break;
1956
    default:
1957
        unallocated_encoding(s);
1958
        break;
1959
    }
1960
}
1961

    
1962
/* C3.3.1 AdvSIMD load/store multiple structures
1963
 *
1964
 *  31  30  29           23 22  21         16 15    12 11  10 9    5 4    0
1965
 * +---+---+---------------+---+-------------+--------+------+------+------+
1966
 * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size |  Rn  |  Rt  |
1967
 * +---+---+---------------+---+-------------+--------+------+------+------+
1968
 *
1969
 * C3.3.2 AdvSIMD load/store multiple structures (post-indexed)
1970
 *
1971
 *  31  30  29           23 22  21  20     16 15    12 11  10 9    5 4    0
1972
 * +---+---+---------------+---+---+---------+--------+------+------+------+
1973
 * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 |   Rm    | opcode | size |  Rn  |  Rt  |
1974
 * +---+---+---------------+---+---+---------+--------+------+------+------+
1975
 *
1976
 * Rt: first (or only) SIMD&FP register to be transferred
1977
 * Rn: base address or SP
1978
 * Rm (post-index only): post-index register (when !31) or size dependent #imm
1979
 */
1980
static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
1981
{
1982
    int rt = extract32(insn, 0, 5);
1983
    int rn = extract32(insn, 5, 5);
1984
    int size = extract32(insn, 10, 2);
1985
    int opcode = extract32(insn, 12, 4);
1986
    bool is_store = !extract32(insn, 22, 1);
1987
    bool is_postidx = extract32(insn, 23, 1);
1988
    bool is_q = extract32(insn, 30, 1);
1989
    TCGv_i64 tcg_addr, tcg_rn;
1990

    
1991
    int ebytes = 1 << size;
1992
    int elements = (is_q ? 128 : 64) / (8 << size);
1993
    int rpt;    /* num iterations */
1994
    int selem;  /* structure elements */
1995
    int r;
1996

    
1997
    if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
1998
        unallocated_encoding(s);
1999
        return;
2000
    }
2001

    
2002
    /* From the shared decode logic */
2003
    switch (opcode) {
2004
    case 0x0:
2005
        rpt = 1;
2006
        selem = 4;
2007
        break;
2008
    case 0x2:
2009
        rpt = 4;
2010
        selem = 1;
2011
        break;
2012
    case 0x4:
2013
        rpt = 1;
2014
        selem = 3;
2015
        break;
2016
    case 0x6:
2017
        rpt = 3;
2018
        selem = 1;
2019
        break;
2020
    case 0x7:
2021
        rpt = 1;
2022
        selem = 1;
2023
        break;
2024
    case 0x8:
2025
        rpt = 1;
2026
        selem = 2;
2027
        break;
2028
    case 0xa:
2029
        rpt = 2;
2030
        selem = 1;
2031
        break;
2032
    default:
2033
        unallocated_encoding(s);
2034
        return;
2035
    }
2036

    
2037
    if (size == 3 && !is_q && selem != 1) {
2038
        /* reserved */
2039
        unallocated_encoding(s);
2040
        return;
2041
    }
2042

    
2043
    if (rn == 31) {
2044
        gen_check_sp_alignment(s);
2045
    }
2046

    
2047
    tcg_rn = cpu_reg_sp(s, rn);
2048
    tcg_addr = tcg_temp_new_i64();
2049
    tcg_gen_mov_i64(tcg_addr, tcg_rn);
2050

    
2051
    for (r = 0; r < rpt; r++) {
2052
        int e;
2053
        for (e = 0; e < elements; e++) {
2054
            int tt = (rt + r) % 32;
2055
            int xs;
2056
            for (xs = 0; xs < selem; xs++) {
2057
                if (is_store) {
2058
                    do_vec_st(s, tt, e, tcg_addr, size);
2059
                } else {
2060
                    do_vec_ld(s, tt, e, tcg_addr, size);
2061

    
2062
                    /* For non-quad operations, setting a slice of the low
2063
                     * 64 bits of the register clears the high 64 bits (in
2064
                     * the ARM ARM pseudocode this is implicit in the fact
2065
                     * that 'rval' is a 64 bit wide variable). We optimize
2066
                     * by noticing that we only need to do this the first
2067
                     * time we touch a register.
2068
                     */
2069
                    if (!is_q && e == 0 && (r == 0 || xs == selem - 1)) {
2070
                        clear_vec_high(s, tt);
2071
                    }
2072
                }
2073
                tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
2074
                tt = (tt + 1) % 32;
2075
            }
2076
        }
2077
    }
2078

    
2079
    if (is_postidx) {
2080
        int rm = extract32(insn, 16, 5);
2081
        if (rm == 31) {
2082
            tcg_gen_mov_i64(tcg_rn, tcg_addr);
2083
        } else {
2084
            tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
2085
        }
2086
    }
2087
    tcg_temp_free_i64(tcg_addr);
2088
}
2089

    
2090
/* C3.3.3 AdvSIMD load/store single structure
2091
 *
2092
 *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
2093
 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2094
 * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size |  Rn  |  Rt  |
2095
 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2096
 *
2097
 * C3.3.4 AdvSIMD load/store single structure (post-indexed)
2098
 *
2099
 *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
2100
 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2101
 * | 0 | Q | 0 0 1 1 0 1 1 | L R |     Rm    | opc | S | size |  Rn  |  Rt  |
2102
 * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2103
 *
2104
 * Rt: first (or only) SIMD&FP register to be transferred
2105
 * Rn: base address or SP
2106
 * Rm (post-index only): post-index register (when !31) or size dependent #imm
2107
 * index = encoded in Q:S:size dependent on size
2108
 *
2109
 * lane_size = encoded in R, opc
2110
 * transfer width = encoded in opc, S, size
2111
 */
2112
static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
2113
{
2114
    int rt = extract32(insn, 0, 5);
2115
    int rn = extract32(insn, 5, 5);
2116
    int size = extract32(insn, 10, 2);
2117
    int S = extract32(insn, 12, 1);
2118
    int opc = extract32(insn, 13, 3);
2119
    int R = extract32(insn, 21, 1);
2120
    int is_load = extract32(insn, 22, 1);
2121
    int is_postidx = extract32(insn, 23, 1);
2122
    int is_q = extract32(insn, 30, 1);
2123

    
2124
    int scale = extract32(opc, 1, 2);
2125
    int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
2126
    bool replicate = false;
2127
    int index = is_q << 3 | S << 2 | size;
2128
    int ebytes, xs;
2129
    TCGv_i64 tcg_addr, tcg_rn;
2130

    
2131
    switch (scale) {
2132
    case 3:
2133
        if (!is_load || S) {
2134
            unallocated_encoding(s);
2135
            return;
2136
        }
2137
        scale = size;
2138
        replicate = true;
2139
        break;
2140
    case 0:
2141
        break;
2142
    case 1:
2143
        if (extract32(size, 0, 1)) {
2144
            unallocated_encoding(s);
2145
            return;
2146
        }
2147
        index >>= 1;
2148
        break;
2149
    case 2:
2150
        if (extract32(size, 1, 1)) {
2151
            unallocated_encoding(s);
2152
            return;
2153
        }
2154
        if (!extract32(size, 0, 1)) {
2155
            index >>= 2;
2156
        } else {
2157
            if (S) {
2158
                unallocated_encoding(s);
2159
                return;
2160
            }
2161
            index >>= 3;
2162
            scale = 3;
2163
        }
2164
        break;
2165
    default:
2166
        g_assert_not_reached();
2167
    }
2168

    
2169
    ebytes = 1 << scale;
2170

    
2171
    if (rn == 31) {
2172
        gen_check_sp_alignment(s);
2173
    }
2174

    
2175
    tcg_rn = cpu_reg_sp(s, rn);
2176
    tcg_addr = tcg_temp_new_i64();
2177
    tcg_gen_mov_i64(tcg_addr, tcg_rn);
2178

    
2179
    for (xs = 0; xs < selem; xs++) {
2180
        if (replicate) {
2181
            /* Load and replicate to all elements */
2182
            uint64_t mulconst;
2183
            TCGv_i64 tcg_tmp = tcg_temp_new_i64();
2184

    
2185
            tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
2186
                                get_mem_index(s), MO_TE + scale);
2187
            switch (scale) {
2188
            case 0:
2189
                mulconst = 0x0101010101010101ULL;
2190
                break;
2191
            case 1:
2192
                mulconst = 0x0001000100010001ULL;
2193
                break;
2194
            case 2:
2195
                mulconst = 0x0000000100000001ULL;
2196
                break;
2197
            case 3:
2198
                mulconst = 0;
2199
                break;
2200
            default:
2201
                g_assert_not_reached();
2202
            }
2203
            if (mulconst) {
2204
                tcg_gen_muli_i64(tcg_tmp, tcg_tmp, mulconst);
2205
            }
2206
            write_vec_element(s, tcg_tmp, rt, 0, MO_64);
2207
            if (is_q) {
2208
                write_vec_element(s, tcg_tmp, rt, 1, MO_64);
2209
            } else {
2210
                clear_vec_high(s, rt);
2211
            }
2212
            tcg_temp_free_i64(tcg_tmp);
2213
        } else {
2214
            /* Load/store one element per register */
2215
            if (is_load) {
2216
                do_vec_ld(s, rt, index, tcg_addr, MO_TE + scale);
2217
            } else {
2218
                do_vec_st(s, rt, index, tcg_addr, MO_TE + scale);
2219
            }
2220
        }
2221
        tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
2222
        rt = (rt + 1) % 32;
2223
    }
2224

    
2225
    if (is_postidx) {
2226
        int rm = extract32(insn, 16, 5);
2227
        if (rm == 31) {
2228
            tcg_gen_mov_i64(tcg_rn, tcg_addr);
2229
        } else {
2230
            tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
2231
        }
2232
    }
2233
    tcg_temp_free_i64(tcg_addr);
2234
}
2235

    
2236
/* C3.3 Loads and stores */
2237
static void disas_ldst(DisasContext *s, uint32_t insn)
2238
{
2239
    switch (extract32(insn, 24, 6)) {
2240
    case 0x08: /* Load/store exclusive */
2241
        disas_ldst_excl(s, insn);
2242
        break;
2243
    case 0x18: case 0x1c: /* Load register (literal) */
2244
        disas_ld_lit(s, insn);
2245
        break;
2246
    case 0x28: case 0x29:
2247
    case 0x2c: case 0x2d: /* Load/store pair (all forms) */
2248
        disas_ldst_pair(s, insn);
2249
        break;
2250
    case 0x38: case 0x39:
2251
    case 0x3c: case 0x3d: /* Load/store register (all forms) */
2252
        disas_ldst_reg(s, insn);
2253
        break;
2254
    case 0x0c: /* AdvSIMD load/store multiple structures */
2255
        disas_ldst_multiple_struct(s, insn);
2256
        break;
2257
    case 0x0d: /* AdvSIMD load/store single structure */
2258
        disas_ldst_single_struct(s, insn);
2259
        break;
2260
    default:
2261
        unallocated_encoding(s);
2262
        break;
2263
    }
2264
}
2265

    
2266
/* C3.4.6 PC-rel. addressing
2267
 *   31  30   29 28       24 23                5 4    0
2268
 * +----+-------+-----------+-------------------+------+
2269
 * | op | immlo | 1 0 0 0 0 |       immhi       |  Rd  |
2270
 * +----+-------+-----------+-------------------+------+
2271
 */
2272
static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
2273
{
2274
    unsigned int page, rd;
2275
    uint64_t base;
2276
    int64_t offset;
2277

    
2278
    page = extract32(insn, 31, 1);
2279
    /* SignExtend(immhi:immlo) -> offset */
2280
    offset = ((int64_t)sextract32(insn, 5, 19) << 2) | extract32(insn, 29, 2);
2281
    rd = extract32(insn, 0, 5);
2282
    base = s->pc - 4;
2283

    
2284
    if (page) {
2285
        /* ADRP (page based) */
2286
        base &= ~0xfff;
2287
        offset <<= 12;
2288
    }
2289

    
2290
    tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
2291
}
2292

    
2293
/*
2294
 * C3.4.1 Add/subtract (immediate)
2295
 *
2296
 *  31 30 29 28       24 23 22 21         10 9   5 4   0
2297
 * +--+--+--+-----------+-----+-------------+-----+-----+
2298
 * |sf|op| S| 1 0 0 0 1 |shift|    imm12    |  Rn | Rd  |
2299
 * +--+--+--+-----------+-----+-------------+-----+-----+
2300
 *
2301
 *    sf: 0 -> 32bit, 1 -> 64bit
2302
 *    op: 0 -> add  , 1 -> sub
2303
 *     S: 1 -> set flags
2304
 * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
2305
 */
2306
static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
2307
{
2308
    int rd = extract32(insn, 0, 5);
2309
    int rn = extract32(insn, 5, 5);
2310
    uint64_t imm = extract32(insn, 10, 12);
2311
    int shift = extract32(insn, 22, 2);
2312
    bool setflags = extract32(insn, 29, 1);
2313
    bool sub_op = extract32(insn, 30, 1);
2314
    bool is_64bit = extract32(insn, 31, 1);
2315

    
2316
    TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
2317
    TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
2318
    TCGv_i64 tcg_result;
2319

    
2320
    switch (shift) {
2321
    case 0x0:
2322
        break;
2323
    case 0x1:
2324
        imm <<= 12;
2325
        break;
2326
    default:
2327
        unallocated_encoding(s);
2328
        return;
2329
    }
2330

    
2331
    tcg_result = tcg_temp_new_i64();
2332
    if (!setflags) {
2333
        if (sub_op) {
2334
            tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
2335
        } else {
2336
            tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
2337
        }
2338
    } else {
2339
        TCGv_i64 tcg_imm = tcg_const_i64(imm);
2340
        if (sub_op) {
2341
            gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
2342
        } else {
2343
            gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
2344
        }
2345
        tcg_temp_free_i64(tcg_imm);
2346
    }
2347

    
2348
    if (is_64bit) {
2349
        tcg_gen_mov_i64(tcg_rd, tcg_result);
2350
    } else {
2351
        tcg_gen_ext32u_i64(tcg_rd, tcg_result);
2352
    }
2353

    
2354
    tcg_temp_free_i64(tcg_result);
2355
}
2356

    
2357
/* The input should be a value in the bottom e bits (with higher
2358
 * bits zero); returns that value replicated into every element
2359
 * of size e in a 64 bit integer.
2360
 */
2361
static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
2362
{
2363
    assert(e != 0);
2364
    while (e < 64) {
2365
        mask |= mask << e;
2366
        e *= 2;
2367
    }
2368
    return mask;
2369
}
2370

    
2371
/* Return a value with the bottom len bits set (where 0 < len <= 64) */
2372
static inline uint64_t bitmask64(unsigned int length)
2373
{
2374
    assert(length > 0 && length <= 64);
2375
    return ~0ULL >> (64 - length);
2376
}
2377

    
2378
/* Simplified variant of pseudocode DecodeBitMasks() for the case where we
2379
 * only require the wmask. Returns false if the imms/immr/immn are a reserved
2380
 * value (ie should cause a guest UNDEF exception), and true if they are
2381
 * valid, in which case the decoded bit pattern is written to result.
2382
 */
2383
static bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
2384
                                   unsigned int imms, unsigned int immr)
2385
{
2386
    uint64_t mask;
2387
    unsigned e, levels, s, r;
2388
    int len;
2389

    
2390
    assert(immn < 2 && imms < 64 && immr < 64);
2391

    
2392
    /* The bit patterns we create here are 64 bit patterns which
2393
     * are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
2394
     * 64 bits each. Each element contains the same value: a run
2395
     * of between 1 and e-1 non-zero bits, rotated within the
2396
     * element by between 0 and e-1 bits.
2397
     *
2398
     * The element size and run length are encoded into immn (1 bit)
2399
     * and imms (6 bits) as follows:
2400
     * 64 bit elements: immn = 1, imms = <length of run - 1>
2401
     * 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
2402
     * 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
2403
     *  8 bit elements: immn = 0, imms = 110 : <length of run - 1>
2404
     *  4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
2405
     *  2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
2406
     * Notice that immn = 0, imms = 11111x is the only combination
2407
     * not covered by one of the above options; this is reserved.
2408
     * Further, <length of run - 1> all-ones is a reserved pattern.
2409
     *
2410
     * In all cases the rotation is by immr % e (and immr is 6 bits).
2411
     */
2412

    
2413
    /* First determine the element size */
2414
    len = 31 - clz32((immn << 6) | (~imms & 0x3f));
2415
    if (len < 1) {
2416
        /* This is the immn == 0, imms == 0x11111x case */
2417
        return false;
2418
    }
2419
    e = 1 << len;
2420

    
2421
    levels = e - 1;
2422
    s = imms & levels;
2423
    r = immr & levels;
2424

    
2425
    if (s == levels) {
2426
        /* <length of run - 1> mustn't be all-ones. */
2427
        return false;
2428
    }
2429

    
2430
    /* Create the value of one element: s+1 set bits rotated
2431
     * by r within the element (which is e bits wide)...
2432
     */
2433
    mask = bitmask64(s + 1);
2434
    mask = (mask >> r) | (mask << (e - r));
2435
    /* ...then replicate the element over the whole 64 bit value */
2436
    mask = bitfield_replicate(mask, e);
2437
    *result = mask;
2438
    return true;
2439
}
2440

    
2441
/* C3.4.4 Logical (immediate)
2442
 *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
2443
 * +----+-----+-------------+---+------+------+------+------+
2444
 * | sf | opc | 1 0 0 1 0 0 | N | immr | imms |  Rn  |  Rd  |
2445
 * +----+-----+-------------+---+------+------+------+------+
2446
 */
2447
static void disas_logic_imm(DisasContext *s, uint32_t insn)
2448
{
2449
    unsigned int sf, opc, is_n, immr, imms, rn, rd;
2450
    TCGv_i64 tcg_rd, tcg_rn;
2451
    uint64_t wmask;
2452
    bool is_and = false;
2453

    
2454
    sf = extract32(insn, 31, 1);
2455
    opc = extract32(insn, 29, 2);
2456
    is_n = extract32(insn, 22, 1);
2457
    immr = extract32(insn, 16, 6);
2458
    imms = extract32(insn, 10, 6);
2459
    rn = extract32(insn, 5, 5);
2460
    rd = extract32(insn, 0, 5);
2461

    
2462
    if (!sf && is_n) {
2463
        unallocated_encoding(s);
2464
        return;
2465
    }
2466

    
2467
    if (opc == 0x3) { /* ANDS */
2468
        tcg_rd = cpu_reg(s, rd);
2469
    } else {
2470
        tcg_rd = cpu_reg_sp(s, rd);
2471
    }
2472
    tcg_rn = cpu_reg(s, rn);
2473

    
2474
    if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
2475
        /* some immediate field values are reserved */
2476
        unallocated_encoding(s);
2477
        return;
2478
    }
2479

    
2480
    if (!sf) {
2481
        wmask &= 0xffffffff;
2482
    }
2483

    
2484
    switch (opc) {
2485
    case 0x3: /* ANDS */
2486
    case 0x0: /* AND */
2487
        tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
2488
        is_and = true;
2489
        break;
2490
    case 0x1: /* ORR */
2491
        tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
2492
        break;
2493
    case 0x2: /* EOR */
2494
        tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
2495
        break;
2496
    default:
2497
        assert(FALSE); /* must handle all above */
2498
        break;
2499
    }
2500

    
2501
    if (!sf && !is_and) {
2502
        /* zero extend final result; we know we can skip this for AND
2503
         * since the immediate had the high 32 bits clear.
2504
         */
2505
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2506
    }
2507

    
2508
    if (opc == 3) { /* ANDS */
2509
        gen_logic_CC(sf, tcg_rd);
2510
    }
2511
}
2512

    
2513
/*
2514
 * C3.4.5 Move wide (immediate)
2515
 *
2516
 *  31 30 29 28         23 22 21 20             5 4    0
2517
 * +--+-----+-------------+-----+----------------+------+
2518
 * |sf| opc | 1 0 0 1 0 1 |  hw |  imm16         |  Rd  |
2519
 * +--+-----+-------------+-----+----------------+------+
2520
 *
2521
 * sf: 0 -> 32 bit, 1 -> 64 bit
2522
 * opc: 00 -> N, 10 -> Z, 11 -> K
2523
 * hw: shift/16 (0,16, and sf only 32, 48)
2524
 */
2525
static void disas_movw_imm(DisasContext *s, uint32_t insn)
2526
{
2527
    int rd = extract32(insn, 0, 5);
2528
    uint64_t imm = extract32(insn, 5, 16);
2529
    int sf = extract32(insn, 31, 1);
2530
    int opc = extract32(insn, 29, 2);
2531
    int pos = extract32(insn, 21, 2) << 4;
2532
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
2533
    TCGv_i64 tcg_imm;
2534

    
2535
    if (!sf && (pos >= 32)) {
2536
        unallocated_encoding(s);
2537
        return;
2538
    }
2539

    
2540
    switch (opc) {
2541
    case 0: /* MOVN */
2542
    case 2: /* MOVZ */
2543
        imm <<= pos;
2544
        if (opc == 0) {
2545
            imm = ~imm;
2546
        }
2547
        if (!sf) {
2548
            imm &= 0xffffffffu;
2549
        }
2550
        tcg_gen_movi_i64(tcg_rd, imm);
2551
        break;
2552
    case 3: /* MOVK */
2553
        tcg_imm = tcg_const_i64(imm);
2554
        tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_imm, pos, 16);
2555
        tcg_temp_free_i64(tcg_imm);
2556
        if (!sf) {
2557
            tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2558
        }
2559
        break;
2560
    default:
2561
        unallocated_encoding(s);
2562
        break;
2563
    }
2564
}
2565

    
2566
/* C3.4.2 Bitfield
2567
 *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
2568
 * +----+-----+-------------+---+------+------+------+------+
2569
 * | sf | opc | 1 0 0 1 1 0 | N | immr | imms |  Rn  |  Rd  |
2570
 * +----+-----+-------------+---+------+------+------+------+
2571
 */
2572
static void disas_bitfield(DisasContext *s, uint32_t insn)
2573
{
2574
    unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
2575
    TCGv_i64 tcg_rd, tcg_tmp;
2576

    
2577
    sf = extract32(insn, 31, 1);
2578
    opc = extract32(insn, 29, 2);
2579
    n = extract32(insn, 22, 1);
2580
    ri = extract32(insn, 16, 6);
2581
    si = extract32(insn, 10, 6);
2582
    rn = extract32(insn, 5, 5);
2583
    rd = extract32(insn, 0, 5);
2584
    bitsize = sf ? 64 : 32;
2585

    
2586
    if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
2587
        unallocated_encoding(s);
2588
        return;
2589
    }
2590

    
2591
    tcg_rd = cpu_reg(s, rd);
2592
    tcg_tmp = read_cpu_reg(s, rn, sf);
2593

    
2594
    /* OPTME: probably worth recognizing common cases of ext{8,16,32}{u,s} */
2595

    
2596
    if (opc != 1) { /* SBFM or UBFM */
2597
        tcg_gen_movi_i64(tcg_rd, 0);
2598
    }
2599

    
2600
    /* do the bit move operation */
2601
    if (si >= ri) {
2602
        /* Wd<s-r:0> = Wn<s:r> */
2603
        tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
2604
        pos = 0;
2605
        len = (si - ri) + 1;
2606
    } else {
2607
        /* Wd<32+s-r,32-r> = Wn<s:0> */
2608
        pos = bitsize - ri;
2609
        len = si + 1;
2610
    }
2611

    
2612
    tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
2613

    
2614
    if (opc == 0) { /* SBFM - sign extend the destination field */
2615
        tcg_gen_shli_i64(tcg_rd, tcg_rd, 64 - (pos + len));
2616
        tcg_gen_sari_i64(tcg_rd, tcg_rd, 64 - (pos + len));
2617
    }
2618

    
2619
    if (!sf) { /* zero extend final result */
2620
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2621
    }
2622
}
2623

    
2624
/* C3.4.3 Extract
2625
 *   31  30  29 28         23 22   21  20  16 15    10 9    5 4    0
2626
 * +----+------+-------------+---+----+------+--------+------+------+
2627
 * | sf | op21 | 1 0 0 1 1 1 | N | o0 |  Rm  |  imms  |  Rn  |  Rd  |
2628
 * +----+------+-------------+---+----+------+--------+------+------+
2629
 */
2630
static void disas_extract(DisasContext *s, uint32_t insn)
2631
{
2632
    unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
2633

    
2634
    sf = extract32(insn, 31, 1);
2635
    n = extract32(insn, 22, 1);
2636
    rm = extract32(insn, 16, 5);
2637
    imm = extract32(insn, 10, 6);
2638
    rn = extract32(insn, 5, 5);
2639
    rd = extract32(insn, 0, 5);
2640
    op21 = extract32(insn, 29, 2);
2641
    op0 = extract32(insn, 21, 1);
2642
    bitsize = sf ? 64 : 32;
2643

    
2644
    if (sf != n || op21 || op0 || imm >= bitsize) {
2645
        unallocated_encoding(s);
2646
    } else {
2647
        TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
2648

    
2649
        tcg_rd = cpu_reg(s, rd);
2650

    
2651
        if (imm) {
2652
            /* OPTME: we can special case rm==rn as a rotate */
2653
            tcg_rm = read_cpu_reg(s, rm, sf);
2654
            tcg_rn = read_cpu_reg(s, rn, sf);
2655
            tcg_gen_shri_i64(tcg_rm, tcg_rm, imm);
2656
            tcg_gen_shli_i64(tcg_rn, tcg_rn, bitsize - imm);
2657
            tcg_gen_or_i64(tcg_rd, tcg_rm, tcg_rn);
2658
            if (!sf) {
2659
                tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2660
            }
2661
        } else {
2662
            /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
2663
             * so an extract from bit 0 is a special case.
2664
             */
2665
            if (sf) {
2666
                tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
2667
            } else {
2668
                tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
2669
            }
2670
        }
2671

    
2672
    }
2673
}
2674

    
2675
/* C3.4 Data processing - immediate */
2676
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
2677
{
2678
    switch (extract32(insn, 23, 6)) {
2679
    case 0x20: case 0x21: /* PC-rel. addressing */
2680
        disas_pc_rel_adr(s, insn);
2681
        break;
2682
    case 0x22: case 0x23: /* Add/subtract (immediate) */
2683
        disas_add_sub_imm(s, insn);
2684
        break;
2685
    case 0x24: /* Logical (immediate) */
2686
        disas_logic_imm(s, insn);
2687
        break;
2688
    case 0x25: /* Move wide (immediate) */
2689
        disas_movw_imm(s, insn);
2690
        break;
2691
    case 0x26: /* Bitfield */
2692
        disas_bitfield(s, insn);
2693
        break;
2694
    case 0x27: /* Extract */
2695
        disas_extract(s, insn);
2696
        break;
2697
    default:
2698
        unallocated_encoding(s);
2699
        break;
2700
    }
2701
}
2702

    
2703
/* Shift a TCGv src by TCGv shift_amount, put result in dst.
2704
 * Note that it is the caller's responsibility to ensure that the
2705
 * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
2706
 * mandated semantics for out of range shifts.
2707
 */
2708
static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
2709
                      enum a64_shift_type shift_type, TCGv_i64 shift_amount)
2710
{
2711
    switch (shift_type) {
2712
    case A64_SHIFT_TYPE_LSL:
2713
        tcg_gen_shl_i64(dst, src, shift_amount);
2714
        break;
2715
    case A64_SHIFT_TYPE_LSR:
2716
        tcg_gen_shr_i64(dst, src, shift_amount);
2717
        break;
2718
    case A64_SHIFT_TYPE_ASR:
2719
        if (!sf) {
2720
            tcg_gen_ext32s_i64(dst, src);
2721
        }
2722
        tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
2723
        break;
2724
    case A64_SHIFT_TYPE_ROR:
2725
        if (sf) {
2726
            tcg_gen_rotr_i64(dst, src, shift_amount);
2727
        } else {
2728
            TCGv_i32 t0, t1;
2729
            t0 = tcg_temp_new_i32();
2730
            t1 = tcg_temp_new_i32();
2731
            tcg_gen_trunc_i64_i32(t0, src);
2732
            tcg_gen_trunc_i64_i32(t1, shift_amount);
2733
            tcg_gen_rotr_i32(t0, t0, t1);
2734
            tcg_gen_extu_i32_i64(dst, t0);
2735
            tcg_temp_free_i32(t0);
2736
            tcg_temp_free_i32(t1);
2737
        }
2738
        break;
2739
    default:
2740
        assert(FALSE); /* all shift types should be handled */
2741
        break;
2742
    }
2743

    
2744
    if (!sf) { /* zero extend final result */
2745
        tcg_gen_ext32u_i64(dst, dst);
2746
    }
2747
}
2748

    
2749
/* Shift a TCGv src by immediate, put result in dst.
2750
 * The shift amount must be in range (this should always be true as the
2751
 * relevant instructions will UNDEF on bad shift immediates).
2752
 */
2753
static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
2754
                          enum a64_shift_type shift_type, unsigned int shift_i)
2755
{
2756
    assert(shift_i < (sf ? 64 : 32));
2757

    
2758
    if (shift_i == 0) {
2759
        tcg_gen_mov_i64(dst, src);
2760
    } else {
2761
        TCGv_i64 shift_const;
2762

    
2763
        shift_const = tcg_const_i64(shift_i);
2764
        shift_reg(dst, src, sf, shift_type, shift_const);
2765
        tcg_temp_free_i64(shift_const);
2766
    }
2767
}
2768

    
2769
/* C3.5.10 Logical (shifted register)
2770
 *   31  30 29 28       24 23   22 21  20  16 15    10 9    5 4    0
2771
 * +----+-----+-----------+-------+---+------+--------+------+------+
2772
 * | sf | opc | 0 1 0 1 0 | shift | N |  Rm  |  imm6  |  Rn  |  Rd  |
2773
 * +----+-----+-----------+-------+---+------+--------+------+------+
2774
 */
2775
static void disas_logic_reg(DisasContext *s, uint32_t insn)
2776
{
2777
    TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
2778
    unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
2779

    
2780
    sf = extract32(insn, 31, 1);
2781
    opc = extract32(insn, 29, 2);
2782
    shift_type = extract32(insn, 22, 2);
2783
    invert = extract32(insn, 21, 1);
2784
    rm = extract32(insn, 16, 5);
2785
    shift_amount = extract32(insn, 10, 6);
2786
    rn = extract32(insn, 5, 5);
2787
    rd = extract32(insn, 0, 5);
2788

    
2789
    if (!sf && (shift_amount & (1 << 5))) {
2790
        unallocated_encoding(s);
2791
        return;
2792
    }
2793

    
2794
    tcg_rd = cpu_reg(s, rd);
2795

    
2796
    if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
2797
        /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
2798
         * register-register MOV and MVN, so it is worth special casing.
2799
         */
2800
        tcg_rm = cpu_reg(s, rm);
2801
        if (invert) {
2802
            tcg_gen_not_i64(tcg_rd, tcg_rm);
2803
            if (!sf) {
2804
                tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2805
            }
2806
        } else {
2807
            if (sf) {
2808
                tcg_gen_mov_i64(tcg_rd, tcg_rm);
2809
            } else {
2810
                tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
2811
            }
2812
        }
2813
        return;
2814
    }
2815

    
2816
    tcg_rm = read_cpu_reg(s, rm, sf);
2817

    
2818
    if (shift_amount) {
2819
        shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
2820
    }
2821

    
2822
    tcg_rn = cpu_reg(s, rn);
2823

    
2824
    switch (opc | (invert << 2)) {
2825
    case 0: /* AND */
2826
    case 3: /* ANDS */
2827
        tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
2828
        break;
2829
    case 1: /* ORR */
2830
        tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
2831
        break;
2832
    case 2: /* EOR */
2833
        tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
2834
        break;
2835
    case 4: /* BIC */
2836
    case 7: /* BICS */
2837
        tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
2838
        break;
2839
    case 5: /* ORN */
2840
        tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
2841
        break;
2842
    case 6: /* EON */
2843
        tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
2844
        break;
2845
    default:
2846
        assert(FALSE);
2847
        break;
2848
    }
2849

    
2850
    if (!sf) {
2851
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2852
    }
2853

    
2854
    if (opc == 3) {
2855
        gen_logic_CC(sf, tcg_rd);
2856
    }
2857
}
2858

    
2859
/*
2860
 * C3.5.1 Add/subtract (extended register)
2861
 *
2862
 *  31|30|29|28       24|23 22|21|20   16|15  13|12  10|9  5|4  0|
2863
 * +--+--+--+-----------+-----+--+-------+------+------+----+----+
2864
 * |sf|op| S| 0 1 0 1 1 | opt | 1|  Rm   |option| imm3 | Rn | Rd |
2865
 * +--+--+--+-----------+-----+--+-------+------+------+----+----+
2866
 *
2867
 *  sf: 0 -> 32bit, 1 -> 64bit
2868
 *  op: 0 -> add  , 1 -> sub
2869
 *   S: 1 -> set flags
2870
 * opt: 00
2871
 * option: extension type (see DecodeRegExtend)
2872
 * imm3: optional shift to Rm
2873
 *
2874
 * Rd = Rn + LSL(extend(Rm), amount)
2875
 */
2876
static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
2877
{
2878
    int rd = extract32(insn, 0, 5);
2879
    int rn = extract32(insn, 5, 5);
2880
    int imm3 = extract32(insn, 10, 3);
2881
    int option = extract32(insn, 13, 3);
2882
    int rm = extract32(insn, 16, 5);
2883
    bool setflags = extract32(insn, 29, 1);
2884
    bool sub_op = extract32(insn, 30, 1);
2885
    bool sf = extract32(insn, 31, 1);
2886

    
2887
    TCGv_i64 tcg_rm, tcg_rn; /* temps */
2888
    TCGv_i64 tcg_rd;
2889
    TCGv_i64 tcg_result;
2890

    
2891
    if (imm3 > 4) {
2892
        unallocated_encoding(s);
2893
        return;
2894
    }
2895

    
2896
    /* non-flag setting ops may use SP */
2897
    if (!setflags) {
2898
        tcg_rn = read_cpu_reg_sp(s, rn, sf);
2899
        tcg_rd = cpu_reg_sp(s, rd);
2900
    } else {
2901
        tcg_rn = read_cpu_reg(s, rn, sf);
2902
        tcg_rd = cpu_reg(s, rd);
2903
    }
2904

    
2905
    tcg_rm = read_cpu_reg(s, rm, sf);
2906
    ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
2907

    
2908
    tcg_result = tcg_temp_new_i64();
2909

    
2910
    if (!setflags) {
2911
        if (sub_op) {
2912
            tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
2913
        } else {
2914
            tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
2915
        }
2916
    } else {
2917
        if (sub_op) {
2918
            gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
2919
        } else {
2920
            gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
2921
        }
2922
    }
2923

    
2924
    if (sf) {
2925
        tcg_gen_mov_i64(tcg_rd, tcg_result);
2926
    } else {
2927
        tcg_gen_ext32u_i64(tcg_rd, tcg_result);
2928
    }
2929

    
2930
    tcg_temp_free_i64(tcg_result);
2931
}
2932

    
2933
/*
2934
 * C3.5.2 Add/subtract (shifted register)
2935
 *
2936
 *  31 30 29 28       24 23 22 21 20   16 15     10 9    5 4    0
2937
 * +--+--+--+-----------+-----+--+-------+---------+------+------+
2938
 * |sf|op| S| 0 1 0 1 1 |shift| 0|  Rm   |  imm6   |  Rn  |  Rd  |
2939
 * +--+--+--+-----------+-----+--+-------+---------+------+------+
2940
 *
2941
 *    sf: 0 -> 32bit, 1 -> 64bit
2942
 *    op: 0 -> add  , 1 -> sub
2943
 *     S: 1 -> set flags
2944
 * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
2945
 *  imm6: Shift amount to apply to Rm before the add/sub
2946
 */
2947
static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
2948
{
2949
    int rd = extract32(insn, 0, 5);
2950
    int rn = extract32(insn, 5, 5);
2951
    int imm6 = extract32(insn, 10, 6);
2952
    int rm = extract32(insn, 16, 5);
2953
    int shift_type = extract32(insn, 22, 2);
2954
    bool setflags = extract32(insn, 29, 1);
2955
    bool sub_op = extract32(insn, 30, 1);
2956
    bool sf = extract32(insn, 31, 1);
2957

    
2958
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
2959
    TCGv_i64 tcg_rn, tcg_rm;
2960
    TCGv_i64 tcg_result;
2961

    
2962
    if ((shift_type == 3) || (!sf && (imm6 > 31))) {
2963
        unallocated_encoding(s);
2964
        return;
2965
    }
2966

    
2967
    tcg_rn = read_cpu_reg(s, rn, sf);
2968
    tcg_rm = read_cpu_reg(s, rm, sf);
2969

    
2970
    shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
2971

    
2972
    tcg_result = tcg_temp_new_i64();
2973

    
2974
    if (!setflags) {
2975
        if (sub_op) {
2976
            tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
2977
        } else {
2978
            tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
2979
        }
2980
    } else {
2981
        if (sub_op) {
2982
            gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
2983
        } else {
2984
            gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
2985
        }
2986
    }
2987

    
2988
    if (sf) {
2989
        tcg_gen_mov_i64(tcg_rd, tcg_result);
2990
    } else {
2991
        tcg_gen_ext32u_i64(tcg_rd, tcg_result);
2992
    }
2993

    
2994
    tcg_temp_free_i64(tcg_result);
2995
}
2996

    
2997
/* C3.5.9 Data-processing (3 source)
2998

2999
   31 30  29 28       24 23 21  20  16  15  14  10 9    5 4    0
3000
  +--+------+-----------+------+------+----+------+------+------+
3001
  |sf| op54 | 1 1 0 1 1 | op31 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
3002
  +--+------+-----------+------+------+----+------+------+------+
3003

3004
 */
3005
static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
3006
{
3007
    int rd = extract32(insn, 0, 5);
3008
    int rn = extract32(insn, 5, 5);
3009
    int ra = extract32(insn, 10, 5);
3010
    int rm = extract32(insn, 16, 5);
3011
    int op_id = (extract32(insn, 29, 3) << 4) |
3012
        (extract32(insn, 21, 3) << 1) |
3013
        extract32(insn, 15, 1);
3014
    bool sf = extract32(insn, 31, 1);
3015
    bool is_sub = extract32(op_id, 0, 1);
3016
    bool is_high = extract32(op_id, 2, 1);
3017
    bool is_signed = false;
3018
    TCGv_i64 tcg_op1;
3019
    TCGv_i64 tcg_op2;
3020
    TCGv_i64 tcg_tmp;
3021

    
3022
    /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
3023
    switch (op_id) {
3024
    case 0x42: /* SMADDL */
3025
    case 0x43: /* SMSUBL */
3026
    case 0x44: /* SMULH */
3027
        is_signed = true;
3028
        break;
3029
    case 0x0: /* MADD (32bit) */
3030
    case 0x1: /* MSUB (32bit) */
3031
    case 0x40: /* MADD (64bit) */
3032
    case 0x41: /* MSUB (64bit) */
3033
    case 0x4a: /* UMADDL */
3034
    case 0x4b: /* UMSUBL */
3035
    case 0x4c: /* UMULH */
3036
        break;
3037
    default:
3038
        unallocated_encoding(s);
3039
        return;
3040
    }
3041

    
3042
    if (is_high) {
3043
        TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */
3044
        TCGv_i64 tcg_rd = cpu_reg(s, rd);
3045
        TCGv_i64 tcg_rn = cpu_reg(s, rn);
3046
        TCGv_i64 tcg_rm = cpu_reg(s, rm);
3047

    
3048
        if (is_signed) {
3049
            tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
3050
        } else {
3051
            tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
3052
        }
3053

    
3054
        tcg_temp_free_i64(low_bits);
3055
        return;
3056
    }
3057

    
3058
    tcg_op1 = tcg_temp_new_i64();
3059
    tcg_op2 = tcg_temp_new_i64();
3060
    tcg_tmp = tcg_temp_new_i64();
3061

    
3062
    if (op_id < 0x42) {
3063
        tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn));
3064
        tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm));
3065
    } else {
3066
        if (is_signed) {
3067
            tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn));
3068
            tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm));
3069
        } else {
3070
            tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn));
3071
            tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm));
3072
        }
3073
    }
3074

    
3075
    if (ra == 31 && !is_sub) {
3076
        /* Special-case MADD with rA == XZR; it is the standard MUL alias */
3077
        tcg_gen_mul_i64(cpu_reg(s, rd), tcg_op1, tcg_op2);
3078
    } else {
3079
        tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2);
3080
        if (is_sub) {
3081
            tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
3082
        } else {
3083
            tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
3084
        }
3085
    }
3086

    
3087
    if (!sf) {
3088
        tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd));
3089
    }
3090

    
3091
    tcg_temp_free_i64(tcg_op1);
3092
    tcg_temp_free_i64(tcg_op2);
3093
    tcg_temp_free_i64(tcg_tmp);
3094
}
3095

    
3096
/* C3.5.3 - Add/subtract (with carry)
3097
 *  31 30 29 28 27 26 25 24 23 22 21  20  16  15   10  9    5 4   0
3098
 * +--+--+--+------------------------+------+---------+------+-----+
3099
 * |sf|op| S| 1  1  0  1  0  0  0  0 |  rm  | opcode2 |  Rn  |  Rd |
3100
 * +--+--+--+------------------------+------+---------+------+-----+
3101
 *                                            [000000]
3102
 */
3103

    
3104
static void disas_adc_sbc(DisasContext *s, uint32_t insn)
3105
{
3106
    unsigned int sf, op, setflags, rm, rn, rd;
3107
    TCGv_i64 tcg_y, tcg_rn, tcg_rd;
3108

    
3109
    if (extract32(insn, 10, 6) != 0) {
3110
        unallocated_encoding(s);
3111
        return;
3112
    }
3113

    
3114
    sf = extract32(insn, 31, 1);
3115
    op = extract32(insn, 30, 1);
3116
    setflags = extract32(insn, 29, 1);
3117
    rm = extract32(insn, 16, 5);
3118
    rn = extract32(insn, 5, 5);
3119
    rd = extract32(insn, 0, 5);
3120

    
3121
    tcg_rd = cpu_reg(s, rd);
3122
    tcg_rn = cpu_reg(s, rn);
3123

    
3124
    if (op) {
3125
        tcg_y = new_tmp_a64(s);
3126
        tcg_gen_not_i64(tcg_y, cpu_reg(s, rm));
3127
    } else {
3128
        tcg_y = cpu_reg(s, rm);
3129
    }
3130

    
3131
    if (setflags) {
3132
        gen_adc_CC(sf, tcg_rd, tcg_rn, tcg_y);
3133
    } else {
3134
        gen_adc(sf, tcg_rd, tcg_rn, tcg_y);
3135
    }
3136
}
3137

    
3138
/* C3.5.4 - C3.5.5 Conditional compare (immediate / register)
3139
 *  31 30 29 28 27 26 25 24 23 22 21  20    16 15  12  11  10  9   5  4 3   0
3140
 * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
3141
 * |sf|op| S| 1  1  0  1  0  0  1  0 |imm5/rm | cond |i/r |o2|  Rn  |o3|nzcv |
3142
 * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
3143
 *        [1]                             y                [0]       [0]
3144
 */
3145
static void disas_cc(DisasContext *s, uint32_t insn)
3146
{
3147
    unsigned int sf, op, y, cond, rn, nzcv, is_imm;
3148
    int label_continue = -1;
3149
    TCGv_i64 tcg_tmp, tcg_y, tcg_rn;
3150

    
3151
    if (!extract32(insn, 29, 1)) {
3152
        unallocated_encoding(s);
3153
        return;
3154
    }
3155
    if (insn & (1 << 10 | 1 << 4)) {
3156
        unallocated_encoding(s);
3157
        return;
3158
    }
3159
    sf = extract32(insn, 31, 1);
3160
    op = extract32(insn, 30, 1);
3161
    is_imm = extract32(insn, 11, 1);
3162
    y = extract32(insn, 16, 5); /* y = rm (reg) or imm5 (imm) */
3163
    cond = extract32(insn, 12, 4);
3164
    rn = extract32(insn, 5, 5);
3165
    nzcv = extract32(insn, 0, 4);
3166

    
3167
    if (cond < 0x0e) { /* not always */
3168
        int label_match = gen_new_label();
3169
        label_continue = gen_new_label();
3170
        arm_gen_test_cc(cond, label_match);
3171
        /* nomatch: */
3172
        tcg_tmp = tcg_temp_new_i64();
3173
        tcg_gen_movi_i64(tcg_tmp, nzcv << 28);
3174
        gen_set_nzcv(tcg_tmp);
3175
        tcg_temp_free_i64(tcg_tmp);
3176
        tcg_gen_br(label_continue);
3177
        gen_set_label(label_match);
3178
    }
3179
    /* match, or condition is always */
3180
    if (is_imm) {
3181
        tcg_y = new_tmp_a64(s);
3182
        tcg_gen_movi_i64(tcg_y, y);
3183
    } else {
3184
        tcg_y = cpu_reg(s, y);
3185
    }
3186
    tcg_rn = cpu_reg(s, rn);
3187

    
3188
    tcg_tmp = tcg_temp_new_i64();
3189
    if (op) {
3190
        gen_sub_CC(sf, tcg_tmp, tcg_rn, tcg_y);
3191
    } else {
3192
        gen_add_CC(sf, tcg_tmp, tcg_rn, tcg_y);
3193
    }
3194
    tcg_temp_free_i64(tcg_tmp);
3195

    
3196
    if (cond < 0x0e) { /* continue */
3197
        gen_set_label(label_continue);
3198
    }
3199
}
3200

    
3201
/* C3.5.6 Conditional select
3202
 *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
3203
 * +----+----+---+-----------------+------+------+-----+------+------+
3204
 * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
3205
 * +----+----+---+-----------------+------+------+-----+------+------+
3206
 */
3207
static void disas_cond_select(DisasContext *s, uint32_t insn)
3208
{
3209
    unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
3210
    TCGv_i64 tcg_rd, tcg_src;
3211

    
3212
    if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
3213
        /* S == 1 or op2<1> == 1 */
3214
        unallocated_encoding(s);
3215
        return;
3216
    }
3217
    sf = extract32(insn, 31, 1);
3218
    else_inv = extract32(insn, 30, 1);
3219
    rm = extract32(insn, 16, 5);
3220
    cond = extract32(insn, 12, 4);
3221
    else_inc = extract32(insn, 10, 1);
3222
    rn = extract32(insn, 5, 5);
3223
    rd = extract32(insn, 0, 5);
3224

    
3225
    if (rd == 31) {
3226
        /* silly no-op write; until we use movcond we must special-case
3227
         * this to avoid a dead temporary across basic blocks.
3228
         */
3229
        return;
3230
    }
3231

    
3232
    tcg_rd = cpu_reg(s, rd);
3233

    
3234
    if (cond >= 0x0e) { /* condition "always" */
3235
        tcg_src = read_cpu_reg(s, rn, sf);
3236
        tcg_gen_mov_i64(tcg_rd, tcg_src);
3237
    } else {
3238
        /* OPTME: we could use movcond here, at the cost of duplicating
3239
         * a lot of the arm_gen_test_cc() logic.
3240
         */
3241
        int label_match = gen_new_label();
3242
        int label_continue = gen_new_label();
3243

    
3244
        arm_gen_test_cc(cond, label_match);
3245
        /* nomatch: */
3246
        tcg_src = cpu_reg(s, rm);
3247

    
3248
        if (else_inv && else_inc) {
3249
            tcg_gen_neg_i64(tcg_rd, tcg_src);
3250
        } else if (else_inv) {
3251
            tcg_gen_not_i64(tcg_rd, tcg_src);
3252
        } else if (else_inc) {
3253
            tcg_gen_addi_i64(tcg_rd, tcg_src, 1);
3254
        } else {
3255
            tcg_gen_mov_i64(tcg_rd, tcg_src);
3256
        }
3257
        if (!sf) {
3258
            tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3259
        }
3260
        tcg_gen_br(label_continue);
3261
        /* match: */
3262
        gen_set_label(label_match);
3263
        tcg_src = read_cpu_reg(s, rn, sf);
3264
        tcg_gen_mov_i64(tcg_rd, tcg_src);
3265
        /* continue: */
3266
        gen_set_label(label_continue);
3267
    }
3268
}
3269

    
3270
static void handle_clz(DisasContext *s, unsigned int sf,
3271
                       unsigned int rn, unsigned int rd)
3272
{
3273
    TCGv_i64 tcg_rd, tcg_rn;
3274
    tcg_rd = cpu_reg(s, rd);
3275
    tcg_rn = cpu_reg(s, rn);
3276

    
3277
    if (sf) {
3278
        gen_helper_clz64(tcg_rd, tcg_rn);
3279
    } else {
3280
        TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3281
        tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3282
        gen_helper_clz(tcg_tmp32, tcg_tmp32);
3283
        tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3284
        tcg_temp_free_i32(tcg_tmp32);
3285
    }
3286
}
3287

    
3288
static void handle_cls(DisasContext *s, unsigned int sf,
3289
                       unsigned int rn, unsigned int rd)
3290
{
3291
    TCGv_i64 tcg_rd, tcg_rn;
3292
    tcg_rd = cpu_reg(s, rd);
3293
    tcg_rn = cpu_reg(s, rn);
3294

    
3295
    if (sf) {
3296
        gen_helper_cls64(tcg_rd, tcg_rn);
3297
    } else {
3298
        TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3299
        tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3300
        gen_helper_cls32(tcg_tmp32, tcg_tmp32);
3301
        tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3302
        tcg_temp_free_i32(tcg_tmp32);
3303
    }
3304
}
3305

    
3306
static void handle_rbit(DisasContext *s, unsigned int sf,
3307
                        unsigned int rn, unsigned int rd)
3308
{
3309
    TCGv_i64 tcg_rd, tcg_rn;
3310
    tcg_rd = cpu_reg(s, rd);
3311
    tcg_rn = cpu_reg(s, rn);
3312

    
3313
    if (sf) {
3314
        gen_helper_rbit64(tcg_rd, tcg_rn);
3315
    } else {
3316
        TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3317
        tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3318
        gen_helper_rbit(tcg_tmp32, tcg_tmp32);
3319
        tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3320
        tcg_temp_free_i32(tcg_tmp32);
3321
    }
3322
}
3323

    
3324
/* C5.6.149 REV with sf==1, opcode==3 ("REV64") */
3325
static void handle_rev64(DisasContext *s, unsigned int sf,
3326
                         unsigned int rn, unsigned int rd)
3327
{
3328
    if (!sf) {
3329
        unallocated_encoding(s);
3330
        return;
3331
    }
3332
    tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
3333
}
3334

    
3335
/* C5.6.149 REV with sf==0, opcode==2
3336
 * C5.6.151 REV32 (sf==1, opcode==2)
3337
 */
3338
static void handle_rev32(DisasContext *s, unsigned int sf,
3339
                         unsigned int rn, unsigned int rd)
3340
{
3341
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
3342

    
3343
    if (sf) {
3344
        TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3345
        TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3346

    
3347
        /* bswap32_i64 requires zero high word */
3348
        tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
3349
        tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
3350
        tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
3351
        tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
3352
        tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
3353

    
3354
        tcg_temp_free_i64(tcg_tmp);
3355
    } else {
3356
        tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
3357
        tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
3358
    }
3359
}
3360

    
3361
/* C5.6.150 REV16 (opcode==1) */
3362
static void handle_rev16(DisasContext *s, unsigned int sf,
3363
                         unsigned int rn, unsigned int rd)
3364
{
3365
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
3366
    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3367
    TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3368

    
3369
    tcg_gen_andi_i64(tcg_tmp, tcg_rn, 0xffff);
3370
    tcg_gen_bswap16_i64(tcg_rd, tcg_tmp);
3371

    
3372
    tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16);
3373
    tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
3374
    tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3375
    tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 16, 16);
3376

    
3377
    if (sf) {
3378
        tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
3379
        tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
3380
        tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3381
        tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 32, 16);
3382

    
3383
        tcg_gen_shri_i64(tcg_tmp, tcg_rn, 48);
3384
        tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3385
        tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 48, 16);
3386
    }
3387

    
3388
    tcg_temp_free_i64(tcg_tmp);
3389
}
3390

    
3391
/* C3.5.7 Data-processing (1 source)
3392
 *   31  30  29  28             21 20     16 15    10 9    5 4    0
3393
 * +----+---+---+-----------------+---------+--------+------+------+
3394
 * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
3395
 * +----+---+---+-----------------+---------+--------+------+------+
3396
 */
3397
static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
3398
{
3399
    unsigned int sf, opcode, rn, rd;
3400

    
3401
    if (extract32(insn, 29, 1) || extract32(insn, 16, 5)) {
3402
        unallocated_encoding(s);
3403
        return;
3404
    }
3405

    
3406
    sf = extract32(insn, 31, 1);
3407
    opcode = extract32(insn, 10, 6);
3408
    rn = extract32(insn, 5, 5);
3409
    rd = extract32(insn, 0, 5);
3410

    
3411
    switch (opcode) {
3412
    case 0: /* RBIT */
3413
        handle_rbit(s, sf, rn, rd);
3414
        break;
3415
    case 1: /* REV16 */
3416
        handle_rev16(s, sf, rn, rd);
3417
        break;
3418
    case 2: /* REV32 */
3419
        handle_rev32(s, sf, rn, rd);
3420
        break;
3421
    case 3: /* REV64 */
3422
        handle_rev64(s, sf, rn, rd);
3423
        break;
3424
    case 4: /* CLZ */
3425
        handle_clz(s, sf, rn, rd);
3426
        break;
3427
    case 5: /* CLS */
3428
        handle_cls(s, sf, rn, rd);
3429
        break;
3430
    }
3431
}
3432

    
3433
static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
3434
                       unsigned int rm, unsigned int rn, unsigned int rd)
3435
{
3436
    TCGv_i64 tcg_n, tcg_m, tcg_rd;
3437
    tcg_rd = cpu_reg(s, rd);
3438

    
3439
    if (!sf && is_signed) {
3440
        tcg_n = new_tmp_a64(s);
3441
        tcg_m = new_tmp_a64(s);
3442
        tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
3443
        tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
3444
    } else {
3445
        tcg_n = read_cpu_reg(s, rn, sf);
3446
        tcg_m = read_cpu_reg(s, rm, sf);
3447
    }
3448

    
3449
    if (is_signed) {
3450
        gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
3451
    } else {
3452
        gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
3453
    }
3454

    
3455
    if (!sf) { /* zero extend final result */
3456
        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3457
    }
3458
}
3459

    
3460
/* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
3461
static void handle_shift_reg(DisasContext *s,
3462
                             enum a64_shift_type shift_type, unsigned int sf,
3463
                             unsigned int rm, unsigned int rn, unsigned int rd)
3464
{
3465
    TCGv_i64 tcg_shift = tcg_temp_new_i64();
3466
    TCGv_i64 tcg_rd = cpu_reg(s, rd);
3467
    TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3468

    
3469
    tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
3470
    shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
3471
    tcg_temp_free_i64(tcg_shift);
3472
}
3473

    
3474
/* C3.5.8 Data-processing (2 source)
3475
 *   31   30  29 28             21 20  16 15    10 9    5 4    0
3476
 * +----+---+---+-----------------+------+--------+------+------+
3477
 * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
3478
 * +----+---+---+-----------------+------+--------+------+------+
3479
 */
3480
static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
3481
{
3482
    unsigned int sf, rm, opcode, rn, rd;
3483
    sf = extract32(insn, 31, 1);
3484
    rm = extract32(insn, 16, 5);
3485
    opcode = extract32(insn, 10, 6);
3486
    rn = extract32(insn, 5, 5);
3487
    rd = extract32(insn, 0, 5);
3488

    
3489
    if (extract32(insn, 29, 1)) {
3490
        unallocated_encoding(s);
3491
        return;
3492
    }
3493

    
3494
    switch (opcode) {
3495
    case 2: /* UDIV */
3496
        handle_div(s, false, sf, rm, rn, rd);
3497
        break;
3498
    case 3: /* SDIV */
3499
        handle_div(s, true, sf, rm, rn, rd);
3500
        break;
3501
    case 8: /* LSLV */
3502
        handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
3503
        break;
3504
    case 9: /* LSRV */
3505
        handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
3506
        break;
3507
    case 10: /* ASRV */
3508
        handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
3509
        break;
3510
    case 11: /* RORV */
3511
        handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
3512
        break;
3513
    case 16:
3514
    case 17:
3515
    case 18:
3516
    case 19:
3517
    case 20:
3518
    case 21:
3519
    case 22:
3520
    case 23: /* CRC32 */
3521
        unsupported_encoding(s, insn);
3522
        break;
3523
    default:
3524
        unallocated_encoding(s);
3525
        break;
3526
    }
3527
}
3528

    
3529
/* C3.5 Data processing - register */
3530
static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
3531
{
3532
    switch (extract32(insn, 24, 5)) {
3533
    case 0x0a: /* Logical (shifted register) */
3534
        disas_logic_reg(s, insn);
3535
        break;
3536
    case 0x0b: /* Add/subtract */
3537
        if (insn & (1 << 21)) { /* (extended register) */
3538
            disas_add_sub_ext_reg(s, insn);
3539
        } else {
3540
            disas_add_sub_reg(s, insn);
3541
        }
3542
        break;
3543
    case 0x1b: /* Data-processing (3 source) */
3544
        disas_data_proc_3src(s, insn);
3545
        break;
3546
    case 0x1a:
3547
        switch (extract32(insn, 21, 3)) {
3548
        case 0x0: /* Add/subtract (with carry) */
3549
            disas_adc_sbc(s, insn);
3550
            break;
3551
        case 0x2: /* Conditional compare */
3552
            disas_cc(s, insn); /* both imm and reg forms */
3553
            break;
3554
        case 0x4: /* Conditional select */
3555
            disas_cond_select(s, insn);
3556
            break;
3557
        case 0x6: /* Data-processing */
3558
            if (insn & (1 << 30)) { /* (1 source) */
3559
                disas_data_proc_1src(s, insn);
3560
            } else {            /* (2 source) */
3561
                disas_data_proc_2src(s, insn);
3562
            }
3563
            break;
3564
        default:
3565
            unallocated_encoding(s);
3566
            break;
3567
        }
3568
        break;
3569
    default:
3570
        unallocated_encoding(s);
3571
        break;
3572
    }
3573
}
3574

    
3575
/* Convert ARM rounding mode to softfloat */
3576
static inline int arm_rmode_to_sf(int rmode)
3577
{
3578
    switch (rmode) {
3579
    case FPROUNDING_TIEAWAY:
3580
        rmode = float_round_ties_away;
3581
        break;
3582
    case FPROUNDING_ODD:
3583
        /* FIXME: add support for TIEAWAY and ODD */
3584
        qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
3585
                      rmode);
3586
    case FPROUNDING_TIEEVEN:
3587
    default:
3588
        rmode = float_round_nearest_even;
3589
        break;
3590
    case FPROUNDING_POSINF:
3591
        rmode = float_round_up;
3592
        break;
3593
    case FPROUNDING_NEGINF:
3594
        rmode = float_round_down;
3595
        break;
3596
    case FPROUNDING_ZERO:
3597
        rmode = float_round_to_zero;
3598
        break;
3599
    }
3600
    return rmode;
3601
}
3602

    
3603
static void handle_fp_compare(DisasContext *s, bool is_double,
3604
                              unsigned int rn, unsigned int rm,
3605
                              bool cmp_with_zero, bool signal_all_nans)
3606
{
3607
    TCGv_i64 tcg_flags = tcg_temp_new_i64();
3608
    TCGv_ptr fpst = get_fpstatus_ptr();
3609

    
3610
    if (is_double) {
3611
        TCGv_i64 tcg_vn, tcg_vm;
3612

    
3613
        tcg_vn = read_fp_dreg(s, rn);
3614
        if (cmp_with_zero) {
3615
            tcg_vm = tcg_const_i64(0);
3616
        } else {
3617
            tcg_vm = read_fp_dreg(s, rm);
3618
        }
3619
        if (signal_all_nans) {
3620
            gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3621
        } else {
3622
            gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3623
        }
3624
        tcg_temp_free_i64(tcg_vn);
3625
        tcg_temp_free_i64(tcg_vm);
3626
    } else {
3627
        TCGv_i32 tcg_vn, tcg_vm;
3628

    
3629
        tcg_vn = read_fp_sreg(s, rn);
3630
        if (cmp_with_zero) {
3631
            tcg_vm = tcg_const_i32(0);
3632
        } else {
3633
            tcg_vm = read_fp_sreg(s, rm);
3634
        }
3635
        if (signal_all_nans) {
3636
            gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3637
        } else {
3638
            gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3639
        }
3640
        tcg_temp_free_i32(tcg_vn);
3641
        tcg_temp_free_i32(tcg_vm);
3642
    }
3643

    
3644
    tcg_temp_free_ptr(fpst);
3645

    
3646
    gen_set_nzcv(tcg_flags);
3647

    
3648
    tcg_temp_free_i64(tcg_flags);
3649
}
3650

    
3651
/* C3.6.22 Floating point compare
3652
 *   31  30  29 28       24 23  22  21 20  16 15 14 13  10    9    5 4     0
3653
 * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
3654
 * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | op  | 1 0 0 0 |  Rn  |  op2  |
3655
 * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
3656
 */
3657
static void disas_fp_compare(DisasContext *s, uint32_t insn)
3658
{
3659
    unsigned int mos, type, rm, op, rn, opc, op2r;
3660

    
3661
    mos = extract32(insn, 29, 3);
3662
    type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3663
    rm = extract32(insn, 16, 5);
3664
    op = extract32(insn, 14, 2);
3665
    rn = extract32(insn, 5, 5);
3666
    opc = extract32(insn, 3, 2);
3667
    op2r = extract32(insn, 0, 3);
3668

    
3669
    if (mos || op || op2r || type > 1) {
3670
        unallocated_encoding(s);
3671
        return;
3672
    }
3673

    
3674
    handle_fp_compare(s, type, rn, rm, opc & 1, opc & 2);
3675
}
3676

    
3677
/* C3.6.23 Floating point conditional compare
3678
 *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5  4   3    0
3679
 * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
3680
 * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 0 1 |  Rn  | op | nzcv |
3681
 * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
3682
 */
3683
static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
3684
{
3685
    unsigned int mos, type, rm, cond, rn, op, nzcv;
3686
    TCGv_i64 tcg_flags;
3687
    int label_continue = -1;
3688

    
3689
    mos = extract32(insn, 29, 3);
3690
    type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3691
    rm = extract32(insn, 16, 5);
3692
    cond = extract32(insn, 12, 4);
3693
    rn = extract32(insn, 5, 5);
3694
    op = extract32(insn, 4, 1);
3695
    nzcv = extract32(insn, 0, 4);
3696

    
3697
    if (mos || type > 1) {
3698
        unallocated_encoding(s);
3699
        return;
3700
    }
3701

    
3702
    if (cond < 0x0e) { /* not always */
3703
        int label_match = gen_new_label();
3704
        label_continue = gen_new_label();
3705
        arm_gen_test_cc(cond, label_match);
3706
        /* nomatch: */
3707
        tcg_flags = tcg_const_i64(nzcv << 28);
3708
        gen_set_nzcv(tcg_flags);
3709
        tcg_temp_free_i64(tcg_flags);
3710
        tcg_gen_br(label_continue);
3711
        gen_set_label(label_match);
3712
    }
3713

    
3714
    handle_fp_compare(s, type, rn, rm, false, op);
3715

    
3716
    if (cond < 0x0e) {
3717
        gen_set_label(label_continue);
3718
    }
3719
}
3720

    
3721
/* copy src FP register to dst FP register; type specifies single or double */
3722
static void gen_mov_fp2fp(DisasContext *s, int type, int dst, int src)
3723
{
3724
    if (type) {
3725
        TCGv_i64 v = read_fp_dreg(s, src);
3726
        write_fp_dreg(s, dst, v);
3727
        tcg_temp_free_i64(v);
3728
    } else {
3729
        TCGv_i32 v = read_fp_sreg(s, src);
3730
        write_fp_sreg(s, dst, v);
3731
        tcg_temp_free_i32(v);
3732
    }
3733
}
3734

    
3735
/* C3.6.24 Floating point conditional select
3736
 *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5 4    0
3737
 * +---+---+---+-----------+------+---+------+------+-----+------+------+
3738
 * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 1 1 |  Rn  |  Rd  |
3739
 * +---+---+---+-----------+------+---+------+------+-----+------+------+
3740
 */
3741
static void disas_fp_csel(DisasContext *s, uint32_t insn)
3742
{
3743
    unsigned int mos, type, rm, cond, rn, rd;
3744
    int label_continue = -1;
3745

    
3746
    mos = extract32(insn, 29, 3);
3747
    type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3748
    rm = extract32(insn, 16, 5);
3749
    cond = extract32(insn, 12, 4);
3750
    rn = extract32(insn, 5, 5);
3751
    rd = extract32(insn, 0, 5);
3752

    
3753
    if (mos || type > 1) {
3754
        unallocated_encoding(s);
3755
        return;
3756
    }
3757

    
3758
    if (cond < 0x0e) { /* not always */
3759
        int label_match = gen_new_label();
3760
        label_continue = gen_new_label();
3761
        arm_gen_test_cc(cond, label_match);
3762
        /* nomatch: */
3763
        gen_mov_fp2fp(s, type, rd, rm);
3764
        tcg_gen_br(label_continue);
3765
        gen_set_label(label_match);
3766
    }
3767

    
3768
    gen_mov_fp2fp(s, type, rd, rn);
3769

    
3770
    if (cond < 0x0e) { /* continue */
3771
        gen_set_label(label_continue);
3772
    }
3773
}
3774

    
3775
/* C3.6.25 Floating-point data-processing (1 source) - single precision */
3776
static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
3777
{
3778
    TCGv_ptr fpst;
3779
    TCGv_i32 tcg_op;
3780
    TCGv_i32 tcg_res;
3781

    
3782
    fpst = get_fpstatus_ptr();
3783
    tcg_op = read_fp_sreg(s, rn);
3784
    tcg_res = tcg_temp_new_i32();
3785

    
3786
    switch (opcode) {
3787
    case 0x0: /* FMOV */
3788
        tcg_gen_mov_i32(tcg_res, tcg_op);
3789
        break;
3790
    case 0x1: /* FABS */
3791
        gen_helper_vfp_abss(tcg_res, tcg_op);
3792
        break;
3793
    case 0x2: /* FNEG */
3794
        gen_helper_vfp_negs(tcg_res, tcg_op);
3795
        break;
3796
    case 0x3: /* FSQRT */
3797
        gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
3798
        break;
3799
    case 0x8: /* FRINTN */
3800
    case 0x9: /* FRINTP */
3801
    case 0xa: /* FRINTM */
3802
    case 0xb: /* FRINTZ */
3803
    case 0xc: /* FRINTA */
3804
    {
3805
        TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
3806

    
3807
        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3808
        gen_helper_rints(tcg_res, tcg_op, fpst);
3809

    
3810
        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3811
        tcg_temp_free_i32(tcg_rmode);
3812
        break;
3813
    }
3814
    case 0xe: /* FRINTX */
3815
        gen_helper_rints_exact(tcg_res, tcg_op, fpst);
3816
        break;
3817
    case 0xf: /* FRINTI */
3818
        gen_helper_rints(tcg_res, tcg_op, fpst);
3819
        break;
3820
    default:
3821
        abort();
3822
    }
3823

    
3824
    write_fp_sreg(s, rd, tcg_res);
3825

    
3826
    tcg_temp_free_ptr(fpst);
3827
    tcg_temp_free_i32(tcg_op);
3828
    tcg_temp_free_i32(tcg_res);
3829
}
3830

    
3831
/* C3.6.25 Floating-point data-processing (1 source) - double precision */
3832
static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
3833
{
3834
    TCGv_ptr fpst;
3835
    TCGv_i64 tcg_op;
3836
    TCGv_i64 tcg_res;
3837

    
3838
    fpst = get_fpstatus_ptr();
3839
    tcg_op = read_fp_dreg(s, rn);
3840
    tcg_res = tcg_temp_new_i64();
3841

    
3842
    switch (opcode) {
3843
    case 0x0: /* FMOV */
3844
        tcg_gen_mov_i64(tcg_res, tcg_op);
3845
        break;
3846
    case 0x1: /* FABS */
3847
        gen_helper_vfp_absd(tcg_res, tcg_op);
3848
        break;
3849
    case 0x2: /* FNEG */
3850
        gen_helper_vfp_negd(tcg_res, tcg_op);
3851
        break;
3852
    case 0x3: /* FSQRT */
3853
        gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
3854
        break;
3855
    case 0x8: /* FRINTN */
3856
    case 0x9: /* FRINTP */
3857
    case 0xa: /* FRINTM */
3858
    case 0xb: /* FRINTZ */
3859
    case 0xc: /* FRINTA */
3860
    {
3861
        TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
3862

    
3863
        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3864
        gen_helper_rintd(tcg_res, tcg_op, fpst);
3865

    
3866
        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3867
        tcg_temp_free_i32(tcg_rmode);
3868
        break;
3869
    }
3870
    case 0xe: /* FRINTX */
3871
        gen_helper_rintd_exact(tcg_res, tcg_op, fpst);
3872
        break;
3873
    case 0xf: /* FRINTI */
3874
        gen_helper_rintd(tcg_res, tcg_op, fpst);
3875
        break;
3876
    default:
3877
        abort();
3878
    }
3879

    
3880
    write_fp_dreg(s, rd, tcg_res);
3881

    
3882
    tcg_temp_free_ptr(fpst);
3883
    tcg_temp_free_i64(tcg_op);
3884
    tcg_temp_free_i64(tcg_res);
3885
}
3886

    
3887
static void handle_fp_fcvt(DisasContext *s, int opcode,
3888
                           int rd, int rn, int dtype, int ntype)
3889
{
3890
    switch (ntype) {
3891
    case 0x0:
3892
    {
3893
        TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
3894
        if (dtype == 1) {
3895
            /* Single to double */
3896
            TCGv_i64 tcg_rd = tcg_temp_new_i64();
3897
            gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, cpu_env);
3898
            write_fp_dreg(s, rd, tcg_rd);
3899
            tcg_temp_free_i64(tcg_rd);
3900
        } else {
3901
            /* Single to half */
3902
            TCGv_i32 tcg_rd = tcg_temp_new_i32();
3903
            gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, cpu_env);
3904
            /* write_fp_sreg is OK here because top half of tcg_rd is zero */
3905
            write_fp_sreg(s, rd, tcg_rd);
3906
            tcg_temp_free_i32(tcg_rd);
3907
        }
3908
        tcg_temp_free_i32(tcg_rn);
3909
        break;
3910
    }
3911
    case 0x1:
3912
    {
3913
        TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
3914
        TCGv_i32 tcg_rd = tcg_temp_new_i32();
3915
        if (dtype == 0) {
3916
            /* Double to single */
3917
            gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
3918
        } else {
3919
            /* Double to half */
3920
            gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, cpu_env);
3921
            /* write_fp_sreg is OK here because top half of tcg_rd is zero */
3922
        }
3923
        write_fp_sreg(s, rd, tcg_rd);
3924
        tcg_temp_free_i32(tcg_rd);
3925
        tcg_temp_free_i64(tcg_rn);
3926
        break;
3927
    }
3928
    case 0x3:
3929
    {
3930
        TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
3931
        tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
3932
        if (dtype == 0) {
3933
            /* Half to single */
3934
            TCGv_i32 tcg_rd = tcg_temp_new_i32();
3935
            gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, cpu_env);
3936
            write_fp_sreg(s, rd, tcg_rd);
3937
            tcg_temp_free_i32(tcg_rd);
3938
        } else {
3939
            /* Half to double */
3940
            TCGv_i64 tcg_rd = tcg_temp_new_i64();
3941
            gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, cpu_env);
3942
            write_fp_dreg(s, rd, tcg_rd);
3943
            tcg_temp_free_i64(tcg_rd);
3944
        }
3945
        tcg_temp_free_i32(tcg_rn);
3946
        break;
3947
    }
3948
    default:
3949
        abort();
3950
    }
3951
}
3952

    
3953
/* C3.6.25 Floating point data-processing (1 source)
3954
 *   31  30  29 28       24 23  22  21 20    15 14       10 9    5 4    0
3955
 * +---+---+---+-----------+------+---+--------+-----------+------+------+
3956
 * | M | 0 | S | 1 1 1 1 0 | type | 1 | opcode | 1 0 0 0 0 |  Rn  |  Rd  |
3957
 * +---+---+---+-----------+------+---+--------+-----------+------+------+
3958
 */
3959
static void disas_fp_1src(DisasContext *s, uint32_t insn)
3960
{
3961
    int type = extract32(insn, 22, 2);
3962
    int opcode = extract32(insn, 15, 6);
3963
    int rn = extract32(insn, 5, 5);
3964
    int rd = extract32(insn, 0, 5);
3965

    
3966
    switch (opcode) {
3967
    case 0x4: case 0x5: case 0x7:
3968
    {
3969
        /* FCVT between half, single and double precision */
3970
        int dtype = extract32(opcode, 0, 2);
3971
        if (type == 2 || dtype == type) {
3972
            unallocated_encoding(s);
3973
            return;
3974
        }
3975
        handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
3976
        break;
3977
    }
3978
    case 0x0 ... 0x3:
3979
    case 0x8 ... 0xc:
3980
    case 0xe ... 0xf:
3981
        /* 32-to-32 and 64-to-64 ops */
3982
        switch (type) {
3983
        case 0:
3984
            handle_fp_1src_single(s, opcode, rd, rn);
3985
            break;
3986
        case 1:
3987
            handle_fp_1src_double(s, opcode, rd, rn);
3988
            break;
3989
        default:
3990
            unallocated_encoding(s);
3991
        }
3992
        break;
3993
    default:
3994
        unallocated_encoding(s);
3995
        break;
3996
    }
3997
}
3998

    
3999
/* C3.6.26 Floating-point data-processing (2 source) - single precision */
4000
static void handle_fp_2src_single(DisasContext *s, int opcode,
4001
                                  int rd, int rn, int rm)
4002
{
4003
    TCGv_i32 tcg_op1;
4004
    TCGv_i32 tcg_op2;
4005
    TCGv_i32 tcg_res;
4006
    TCGv_ptr fpst;
4007

    
4008
    tcg_res = tcg_temp_new_i32();
4009
    fpst = get_fpstatus_ptr();
4010
    tcg_op1 = read_fp_sreg(s, rn);
4011
    tcg_op2 = read_fp_sreg(s, rm);
4012

    
4013
    switch (opcode) {
4014
    case 0x0: /* FMUL */
4015
        gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
4016
        break;
4017
    case 0x1: /* FDIV */
4018
        gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
4019
        break;
4020
    case 0x2: /* FADD */
4021
        gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
4022
        break;
4023
    case 0x3: /* FSUB */
4024
        gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
4025
        break;
4026
    case 0x4: /* FMAX */
4027
        gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
4028
        break;
4029
    case 0x5: /* FMIN */
4030
        gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
4031
        break;
4032
    case 0x6: /* FMAXNM */
4033
        gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
4034
        break;
4035
    case 0x7: /* FMINNM */
4036
        gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
4037
        break;
4038
    case 0x8: /* FNMUL */
4039
        gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
4040
        gen_helper_vfp_negs(tcg_res, tcg_res);
4041
        break;
4042
    }
4043

    
4044
    write_fp_sreg(s, rd, tcg_res);
4045

    
4046
    tcg_temp_free_ptr(fpst);
4047
    tcg_temp_free_i32(tcg_op1);
4048
    tcg_temp_free_i32(tcg_op2);
4049
    tcg_temp_free_i32(tcg_res);
4050
}
4051

    
4052
/* C3.6.26 Floating-point data-processing (2 source) - double precision */
4053
static void handle_fp_2src_double(DisasContext *s, int opcode,
4054
                                  int rd, int rn, int rm)
4055
{
4056
    TCGv_i64 tcg_op1;
4057
    TCGv_i64 tcg_op2;
4058
    TCGv_i64 tcg_res;
4059
    TCGv_ptr fpst;
4060

    
4061
    tcg_res = tcg_temp_new_i64();
4062
    fpst = get_fpstatus_ptr();
4063
    tcg_op1 = read_fp_dreg(s, rn);
4064
    tcg_op2 = read_fp_dreg(s, rm);
4065

    
4066
    switch (opcode) {
4067
    case 0x0: /* FMUL */
4068
        gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
4069
        break;
4070
    case 0x1: /* FDIV */
4071
        gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
4072
        break;
4073
    case 0x2: /* FADD */
4074
        gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
4075
        break;
4076
    case 0x3: /* FSUB */
4077
        gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
4078
        break;
4079
    case 0x4: /* FMAX */
4080
        gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
4081
        break;
4082
    case 0x5: /* FMIN */
4083
        gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
4084
        break;
4085
    case 0x6: /* FMAXNM */
4086
        gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
4087
        break;
4088
    case 0x7: /* FMINNM */
4089
        gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
4090
        break;
4091
    case 0x8: /* FNMUL */
4092
        gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
4093
        gen_helper_vfp_negd(tcg_res, tcg_res);
4094
        break;
4095
    }
4096

    
4097
    write_fp_dreg(s, rd, tcg_res);
4098

    
4099
    tcg_temp_free_ptr(fpst);
4100
    tcg_temp_free_i64(tcg_op1);
4101
    tcg_temp_free_i64(tcg_op2);
4102
    tcg_temp_free_i64(tcg_res);
4103
}
4104

    
4105
/* C3.6.26 Floating point data-processing (2 source)
4106
 *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
4107
 * +---+---+---+-----------+------+---+------+--------+-----+------+------+
4108
 * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | opcode | 1 0 |  Rn  |  Rd  |
4109
 * +---+---+---+-----------+------+---+------+--------+-----+------+------+
4110
 */
4111
static void disas_fp_2src(DisasContext *s, uint32_t insn)
4112
{
4113
    int type = extract32(insn, 22, 2);
4114
    int rd = extract32(insn, 0, 5);
4115
    int rn = extract32(insn, 5, 5);
4116
    int rm = extract32(insn, 16, 5);
4117
    int opcode = extract32(insn, 12, 4);
4118

    
4119
    if (opcode > 8) {
4120
        unallocated_encoding(s);
4121
        return;
4122
    }
4123

    
4124
    switch (type) {
4125
    case 0:
4126
        handle_fp_2src_single(s, opcode, rd, rn, rm);
4127
        break;
4128
    case 1:
4129
        handle_fp_2src_double(s, opcode, rd, rn, rm);
4130
        break;
4131
    default:
4132
        unallocated_encoding(s);
4133
    }
4134
}
4135

    
4136
/* C3.6.27 Floating-point data-processing (3 source) - single precision */
4137
static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
4138
                                  int rd, int rn, int rm, int ra)
4139
{
4140
    TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
4141
    TCGv_i32 tcg_res = tcg_temp_new_i32();
4142
    TCGv_ptr fpst = get_fpstatus_ptr();
4143

    
4144
    tcg_op1 = read_fp_sreg(s, rn);
4145
    tcg_op2 = read_fp_sreg(s, rm);
4146
    tcg_op3 = read_fp_sreg(s, ra);
4147

    
4148
    /* These are fused multiply-add, and must be done as one
4149
     * floating point operation with no rounding between the
4150
     * multiplication and addition steps.
4151
     * NB that doing the negations here as separate steps is
4152
     * correct : an input NaN should come out with its sign bit
4153
     * flipped if it is a negated-input.
4154
     */
4155
    if (o1 == true) {
4156
        gen_helper_vfp_negs(tcg_op3, tcg_op3);
4157
    }
4158

    
4159
    if (o0 != o1) {
4160
        gen_helper_vfp_negs(tcg_op1, tcg_op1);
4161
    }
4162

    
4163
    gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
4164

    
4165
    write_fp_sreg(s, rd, tcg_res);
4166

    
4167
    tcg_temp_free_ptr(fpst);
4168
    tcg_temp_free_i32(tcg_op1);
4169
    tcg_temp_free_i32(tcg_op2);
4170
    tcg_temp_free_i32(tcg_op3);
4171
    tcg_temp_free_i32(tcg_res);
4172
}
4173

    
4174
/* C3.6.27 Floating-point data-processing (3 source) - double precision */
4175
static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
4176
                                  int rd, int rn, int rm, int ra)
4177
{
4178
    TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
4179
    TCGv_i64 tcg_res = tcg_temp_new_i64();
4180
    TCGv_ptr fpst = get_fpstatus_ptr();
4181

    
4182
    tcg_op1 = read_fp_dreg(s, rn);
4183
    tcg_op2 = read_fp_dreg(s, rm);
4184
    tcg_op3 = read_fp_dreg(s, ra);
4185

    
4186
    /* These are fused multiply-add, and must be done as one
4187
     * floating point operation with no rounding between the
4188
     * multiplication and addition steps.
4189
     * NB that doing the negations here as separate steps is
4190
     * correct : an input NaN should come out with its sign bit
4191
     * flipped if it is a negated-input.
4192
     */
4193
    if (o1 == true) {
4194
        gen_helper_vfp_negd(tcg_op3, tcg_op3);
4195
    }
4196

    
4197
    if (o0 != o1) {
4198
        gen_helper_vfp_negd(tcg_op1, tcg_op1);
4199
    }
4200

    
4201
    gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
4202

    
4203
    write_fp_dreg(s, rd, tcg_res);
4204

    
4205
    tcg_temp_free_ptr(fpst);
4206
    tcg_temp_free_i64(tcg_op1);
4207
    tcg_temp_free_i64(tcg_op2);
4208
    tcg_temp_free_i64(tcg_op3);
4209
    tcg_temp_free_i64(tcg_res);
4210
}
4211

    
4212
/* C3.6.27 Floating point data-processing (3 source)
4213
 *   31  30  29 28       24 23  22  21  20  16  15  14  10 9    5 4    0
4214
 * +---+---+---+-----------+------+----+------+----+------+------+------+
4215
 * | M | 0 | S | 1 1 1 1 1 | type | o1 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
4216
 * +---+---+---+-----------+------+----+------+----+------+------+------+
4217
 */
4218
static void disas_fp_3src(DisasContext *s, uint32_t insn)
4219
{
4220
    int type = extract32(insn, 22, 2);
4221
    int rd = extract32(insn, 0, 5);
4222
    int rn = extract32(insn, 5, 5);
4223
    int ra = extract32(insn, 10, 5);
4224
    int rm = extract32(insn, 16, 5);
4225
    bool o0 = extract32(insn, 15, 1);
4226
    bool o1 = extract32(insn, 21, 1);
4227

    
4228
    switch (type) {
4229
    case 0:
4230
        handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
4231
        break;
4232
    case 1:
4233
        handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
4234
        break;
4235
    default:
4236
        unallocated_encoding(s);
4237
    }
4238
}
4239

    
4240
/* C3.6.28 Floating point immediate
4241
 *   31  30  29 28       24 23  22  21 20        13 12   10 9    5 4    0
4242
 * +---+---+---+-----------+------+---+------------+-------+------+------+
4243
 * | M | 0 | S | 1 1 1 1 0 | type | 1 |    imm8    | 1 0 0 | imm5 |  Rd  |
4244
 * +---+---+---+-----------+------+---+------------+-------+------+------+
4245
 */
4246
static void disas_fp_imm(DisasContext *s, uint32_t insn)
4247
{
4248
    int rd = extract32(insn, 0, 5);
4249
    int imm8 = extract32(insn, 13, 8);
4250
    int is_double = extract32(insn, 22, 2);
4251
    uint64_t imm;
4252
    TCGv_i64 tcg_res;
4253

    
4254
    if (is_double > 1) {
4255
        unallocated_encoding(s);
4256
        return;
4257
    }
4258

    
4259
    /* The imm8 encodes the sign bit, enough bits to represent
4260
     * an exponent in the range 01....1xx to 10....0xx,
4261
     * and the most significant 4 bits of the mantissa; see
4262
     * VFPExpandImm() in the v8 ARM ARM.
4263
     */
4264
    if (is_double) {
4265
        imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
4266
            (extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
4267
            extract32(imm8, 0, 6);
4268
        imm <<= 48;
4269
    } else {
4270
        imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
4271
            (extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
4272
            (extract32(imm8, 0, 6) << 3);
4273
        imm <<= 16;
4274
    }
4275

    
4276
    tcg_res = tcg_const_i64(imm);
4277
    write_fp_dreg(s, rd, tcg_res);
4278
    tcg_temp_free_i64(tcg_res);
4279
}
4280

    
4281
/* Handle floating point <=> fixed point conversions. Note that we can
4282
 * also deal with fp <=> integer conversions as a special case (scale == 64)
4283
 * OPTME: consider handling that special case specially or at least skipping
4284
 * the call to scalbn in the helpers for zero shifts.
4285
 */
4286
static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
4287
                           bool itof, int rmode, int scale, int sf, int type)
4288
{
4289
    bool is_signed = !(opcode & 1);
4290
    bool is_double = type;
4291
    TCGv_ptr tcg_fpstatus;
4292
    TCGv_i32 tcg_shift;
4293

    
4294
    tcg_fpstatus = get_fpstatus_ptr();
4295

    
4296
    tcg_shift = tcg_const_i32(64 - scale);
4297

    
4298
    if (itof) {
4299
        TCGv_i64 tcg_int = cpu_reg(s, rn);
4300
        if (!sf) {
4301
            TCGv_i64 tcg_extend = new_tmp_a64(s);
4302

    
4303
            if (is_signed) {
4304
                tcg_gen_ext32s_i64(tcg_extend, tcg_int);
4305
            } else {
4306
                tcg_gen_ext32u_i64(tcg_extend, tcg_int);
4307
            }
4308

    
4309
            tcg_int = tcg_extend;
4310
        }
4311

    
4312
        if (is_double) {
4313
            TCGv_i64 tcg_double = tcg_temp_new_i64();
4314
            if (is_signed) {
4315
                gen_helper_vfp_sqtod(tcg_double, tcg_int,
4316
                                     tcg_shift, tcg_fpstatus);
4317
            } else {
4318
                gen_helper_vfp_uqtod(tcg_double, tcg_int,
4319
                                     tcg_shift, tcg_fpstatus);
4320
            }
4321
            write_fp_dreg(s, rd, tcg_double);
4322
            tcg_temp_free_i64(tcg_double);
4323
        } else {
4324
            TCGv_i32 tcg_single = tcg_temp_new_i32();
4325
            if (is_signed) {
4326
                gen_helper_vfp_sqtos(tcg_single, tcg_int,
4327
                                     tcg_shift, tcg_fpstatus);
4328
            } else {
4329
                gen_helper_vfp_uqtos(tcg_single, tcg_int,
4330
                                     tcg_shift, tcg_fpstatus);
4331
            }
4332
            write_fp_sreg(s, rd, tcg_single);
4333
            tcg_temp_free_i32(tcg_single);
4334
        }
4335
    } else {
4336
        TCGv_i64 tcg_int = cpu_reg(s, rd);
4337
        TCGv_i32 tcg_rmode;
4338

    
4339
        if (extract32(opcode, 2, 1)) {
4340
            /* There are too many rounding modes to all fit into rmode,
4341
             * so FCVTA[US] is a special case.
4342
             */
4343
            rmode = FPROUNDING_TIEAWAY;
4344
        }
4345

    
4346
        tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
4347

    
4348
        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4349

    
4350
        if (is_double) {
4351
            TCGv_i64 tcg_double = read_fp_dreg(s, rn);
4352
            if (is_signed) {
4353
                if (!sf) {
4354
                    gen_helper_vfp_tosld(tcg_int, tcg_double,
4355
                                         tcg_shift, tcg_fpstatus);
4356
                } else {
4357
                    gen_helper_vfp_tosqd(tcg_int, tcg_double,
4358
                                         tcg_shift, tcg_fpstatus);
4359
                }
4360
            } else {
4361
                if (!sf) {
4362
                    gen_helper_vfp_tould(tcg_int, tcg_double,
4363
                                         tcg_shift, tcg_fpstatus);
4364
                } else {
4365
                    gen_helper_vfp_touqd(tcg_int, tcg_double,
4366
                                         tcg_shift, tcg_fpstatus);
4367
                }
4368
            }
4369
            tcg_temp_free_i64(tcg_double);
4370
        } else {
4371
            TCGv_i32 tcg_single = read_fp_sreg(s, rn);
4372
            if (sf) {
4373
                if (is_signed) {
4374
                    gen_helper_vfp_tosqs(tcg_int, tcg_single,
4375
                                         tcg_shift, tcg_fpstatus);
4376
                } else {
4377
                    gen_helper_vfp_touqs(tcg_int, tcg_single,
4378
                                         tcg_shift, tcg_fpstatus);
4379
                }
4380
            } else {
4381
                TCGv_i32 tcg_dest = tcg_temp_new_i32();
4382
                if (is_signed) {
4383
                    gen_helper_vfp_tosls(tcg_dest, tcg_single,
4384
                                         tcg_shift, tcg_fpstatus);
4385
                } else {
4386
                    gen_helper_vfp_touls(tcg_dest, tcg_single,
4387
                                         tcg_shift, tcg_fpstatus);
4388
                }
4389
                tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
4390
                tcg_temp_free_i32(tcg_dest);
4391
            }
4392
            tcg_temp_free_i32(tcg_single);
4393
        }
4394

    
4395
        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4396
        tcg_temp_free_i32(tcg_rmode);
4397

    
4398
        if (!sf) {
4399
            tcg_gen_ext32u_i64(tcg_int, tcg_int);
4400
        }
4401
    }
4402

    
4403
    tcg_temp_free_ptr(tcg_fpstatus);
4404
    tcg_temp_free_i32(tcg_shift);
4405
}
4406

    
4407
/* C3.6.29 Floating point <-> fixed point conversions
4408
 *   31   30  29 28       24 23  22  21 20   19 18    16 15   10 9    5 4    0
4409
 * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
4410
 * | sf | 0 | S | 1 1 1 1 0 | type | 0 | rmode | opcode | scale |  Rn  |  Rd  |
4411
 * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
4412
 */
4413
static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
4414
{
4415
    int rd = extract32(insn, 0, 5);
4416
    int rn = extract32(insn, 5, 5);
4417
    int scale = extract32(insn, 10, 6);
4418
    int opcode = extract32(insn, 16, 3);
4419
    int rmode = extract32(insn, 19, 2);
4420
    int type = extract32(insn, 22, 2);
4421
    bool sbit = extract32(insn, 29, 1);
4422
    bool sf = extract32(insn, 31, 1);
4423
    bool itof;
4424

    
4425
    if (sbit || (type > 1)
4426
        || (!sf && scale < 32)) {
4427
        unallocated_encoding(s);
4428
        return;
4429
    }
4430

    
4431
    switch ((rmode << 3) | opcode) {
4432
    case 0x2: /* SCVTF */
4433
    case 0x3: /* UCVTF */
4434
        itof = true;
4435
        break;
4436
    case 0x18: /* FCVTZS */
4437
    case 0x19: /* FCVTZU */
4438
        itof = false;
4439
        break;
4440
    default:
4441
        unallocated_encoding(s);
4442
        return;
4443
    }
4444

    
4445
    handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
4446
}
4447

    
4448
static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
4449
{
4450
    /* FMOV: gpr to or from float, double, or top half of quad fp reg,
4451
     * without conversion.
4452
     */
4453

    
4454
    if (itof) {
4455
        TCGv_i64 tcg_rn = cpu_reg(s, rn);
4456

    
4457
        switch (type) {
4458
        case 0:
4459
        {
4460
            /* 32 bit */
4461
            TCGv_i64 tmp = tcg_temp_new_i64();
4462
            tcg_gen_ext32u_i64(tmp, tcg_rn);
4463
            tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(rd, MO_64));
4464
            tcg_gen_movi_i64(tmp, 0);
4465
            tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
4466
            tcg_temp_free_i64(tmp);
4467
            break;
4468
        }
4469
        case 1:
4470
        {
4471
            /* 64 bit */
4472
            TCGv_i64 tmp = tcg_const_i64(0);
4473
            tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(rd, MO_64));
4474
            tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
4475
            tcg_temp_free_i64(tmp);
4476
            break;
4477
        }
4478
        case 2:
4479
            /* 64 bit to top half. */
4480
            tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(rd));
4481
            break;
4482
        }
4483
    } else {
4484
        TCGv_i64 tcg_rd = cpu_reg(s, rd);
4485

    
4486
        switch (type) {
4487
        case 0:
4488
            /* 32 bit */
4489
            tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_32));
4490
            break;
4491
        case 1:
4492
            /* 64 bit */
4493
            tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_64));
4494
            break;
4495
        case 2:
4496
            /* 64 bits from top half */
4497
            tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(rn));
4498
            break;
4499
        }
4500
    }
4501
}
4502

    
4503
/* C3.6.30 Floating point <-> integer conversions
4504
 *   31   30  29 28       24 23  22  21 20   19 18 16 15         10 9  5 4  0
4505
 * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
4506
 * | sf | 0 | S | 1 1 1 1 0 | type | 1 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
4507
 * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
4508
 */
4509
static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
4510
{
4511
    int rd = extract32(insn, 0, 5);
4512
    int rn = extract32(insn, 5, 5);
4513
    int opcode = extract32(insn, 16, 3);
4514
    int rmode = extract32(insn, 19, 2);
4515
    int type = extract32(insn, 22, 2);
4516
    bool sbit = extract32(insn, 29, 1);
4517
    bool sf = extract32(insn, 31, 1);
4518

    
4519
    if (sbit) {
4520
        unallocated_encoding(s);
4521
        return;
4522
    }
4523

    
4524
    if (opcode > 5) {
4525
        /* FMOV */
4526
        bool itof = opcode & 1;
4527

    
4528
        if (rmode >= 2) {
4529
            unallocated_encoding(s);
4530
            return;
4531
        }
4532

    
4533
        switch (sf << 3 | type << 1 | rmode) {
4534
        case 0x0: /* 32 bit */
4535
        case 0xa: /* 64 bit */
4536
        case 0xd: /* 64 bit to top half of quad */
4537
            break;
4538
        default:
4539
            /* all other sf/type/rmode combinations are invalid */
4540
            unallocated_encoding(s);
4541
            break;
4542
        }
4543

    
4544
        handle_fmov(s, rd, rn, type, itof);
4545
    } else {
4546
        /* actual FP conversions */
4547
        bool itof = extract32(opcode, 1, 1);
4548

    
4549
        if (type > 1 || (rmode != 0 && opcode > 1)) {
4550
            unallocated_encoding(s);
4551
            return;
4552
        }
4553

    
4554
        handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
4555
    }
4556
}
4557

    
4558
/* FP-specific subcases of table C3-6 (SIMD and FP data processing)
4559
 *   31  30  29 28     25 24                          0
4560
 * +---+---+---+---------+-----------------------------+
4561
 * |   | 0 |   | 1 1 1 1 |                             |
4562
 * +---+---+---+---------+-----------------------------+
4563
 */
4564
static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
4565
{
4566
    if (extract32(insn, 24, 1)) {
4567
        /* Floating point data-processing (3 source) */
4568
        disas_fp_3src(s, insn);
4569
    } else if (extract32(insn, 21, 1) == 0) {
4570
        /* Floating point to fixed point conversions */
4571
        disas_fp_fixed_conv(s, insn);
4572
    } else {
4573
        switch (extract32(insn, 10, 2)) {
4574
        case 1:
4575
            /* Floating point conditional compare */
4576
            disas_fp_ccomp(s, insn);
4577
            break;
4578
        case 2:
4579
            /* Floating point data-processing (2 source) */
4580
            disas_fp_2src(s, insn);
4581
            break;
4582
        case 3:
4583
            /* Floating point conditional select */
4584
            disas_fp_csel(s, insn);
4585
            break;
4586
        case 0:
4587
            switch (ctz32(extract32(insn, 12, 4))) {
4588
            case 0: /* [15:12] == xxx1 */
4589
                /* Floating point immediate */
4590
                disas_fp_imm(s, insn);
4591
                break;
4592
            case 1: /* [15:12] == xx10 */
4593
                /* Floating point compare */
4594
                disas_fp_compare(s, insn);
4595
                break;
4596
            case 2: /* [15:12] == x100 */
4597
                /* Floating point data-processing (1 source) */
4598
                disas_fp_1src(s, insn);
4599
                break;
4600
            case 3: /* [15:12] == 1000 */
4601
                unallocated_encoding(s);
4602
                break;
4603
            default: /* [15:12] == 0000 */
4604
                /* Floating point <-> integer conversions */
4605
                disas_fp_int_conv(s, insn);
4606
                break;
4607
            }
4608
            break;
4609
        }
4610
    }
4611
}
4612

    
4613
static void disas_data_proc_simd(DisasContext *s, uint32_t insn)
4614
{
4615
    /* Note that this is called with all non-FP cases from
4616
     * table C3-6 so it must UNDEF for entries not specifically
4617
     * allocated to instructions in that table.
4618
     */
4619
    unsupported_encoding(s, insn);
4620
}
4621

    
4622
/* C3.6 Data processing - SIMD and floating point */
4623
static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
4624
{
4625
    if (extract32(insn, 28, 1) == 1 && extract32(insn, 30, 1) == 0) {
4626
        disas_data_proc_fp(s, insn);
4627
    } else {
4628
        /* SIMD, including crypto */
4629
        disas_data_proc_simd(s, insn);
4630
    }
4631
}
4632

    
4633
/* C3.1 A64 instruction index by encoding */
4634
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
4635
{
4636
    uint32_t insn;
4637

    
4638
    insn = arm_ldl_code(env, s->pc, s->bswap_code);
4639
    s->insn = insn;
4640
    s->pc += 4;
4641

    
4642
    switch (extract32(insn, 25, 4)) {
4643
    case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
4644
        unallocated_encoding(s);
4645
        break;
4646
    case 0x8: case 0x9: /* Data processing - immediate */
4647
        disas_data_proc_imm(s, insn);
4648
        break;
4649
    case 0xa: case 0xb: /* Branch, exception generation and system insns */
4650
        disas_b_exc_sys(s, insn);
4651
        break;
4652
    case 0x4:
4653
    case 0x6:
4654
    case 0xc:
4655
    case 0xe:      /* Loads and stores */
4656
        disas_ldst(s, insn);
4657
        break;
4658
    case 0x5:
4659
    case 0xd:      /* Data processing - register */
4660
        disas_data_proc_reg(s, insn);
4661
        break;
4662
    case 0x7:
4663
    case 0xf:      /* Data processing - SIMD and floating point */
4664
        disas_data_proc_simd_fp(s, insn);
4665
        break;
4666
    default:
4667
        assert(FALSE); /* all 15 cases should be handled above */
4668
        break;
4669
    }
4670

    
4671
    /* if we allocated any temporaries, free them here */
4672
    free_tmp_a64(s);
4673
}
4674

    
4675
void gen_intermediate_code_internal_a64(ARMCPU *cpu,
4676
                                        TranslationBlock *tb,
4677
                                        bool search_pc)
4678
{
4679
    CPUState *cs = CPU(cpu);
4680
    CPUARMState *env = &cpu->env;
4681
    DisasContext dc1, *dc = &dc1;
4682
    CPUBreakpoint *bp;
4683
    uint16_t *gen_opc_end;
4684
    int j, lj;
4685
    target_ulong pc_start;
4686
    target_ulong next_page_start;
4687
    int num_insns;
4688
    int max_insns;
4689

    
4690
    pc_start = tb->pc;
4691

    
4692
    dc->tb = tb;
4693

    
4694
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
4695

    
4696
    dc->is_jmp = DISAS_NEXT;
4697
    dc->pc = pc_start;
4698
    dc->singlestep_enabled = cs->singlestep_enabled;
4699
    dc->condjmp = 0;
4700

    
4701
    dc->aarch64 = 1;
4702
    dc->thumb = 0;
4703
    dc->bswap_code = 0;
4704
    dc->condexec_mask = 0;
4705
    dc->condexec_cond = 0;
4706
#if !defined(CONFIG_USER_ONLY)
4707
    dc->user = 0;
4708
#endif
4709
    dc->vfp_enabled = 0;
4710
    dc->vec_len = 0;
4711
    dc->vec_stride = 0;
4712
    dc->cp_regs = cpu->cp_regs;
4713
    dc->current_pl = arm_current_pl(env);
4714

    
4715
    init_tmp_a64_array(dc);
4716

    
4717
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
4718
    lj = -1;
4719
    num_insns = 0;
4720
    max_insns = tb->cflags & CF_COUNT_MASK;
4721
    if (max_insns == 0) {
4722
        max_insns = CF_COUNT_MASK;
4723
    }
4724

    
4725
    gen_tb_start();
4726

    
4727
    tcg_clear_temp_count();
4728

    
4729
    do {
4730
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
4731
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
4732
                if (bp->pc == dc->pc) {
4733
                    gen_exception_insn(dc, 0, EXCP_DEBUG);
4734
                    /* Advance PC so that clearing the breakpoint will
4735
                       invalidate this TB.  */
4736
                    dc->pc += 2;
4737
                    goto done_generating;
4738
                }
4739
            }
4740
        }
4741

    
4742
        if (search_pc) {
4743
            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
4744
            if (lj < j) {
4745
                lj++;
4746
                while (lj < j) {
4747
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
4748
                }
4749
            }
4750
            tcg_ctx.gen_opc_pc[lj] = dc->pc;
4751
            tcg_ctx.gen_opc_instr_start[lj] = 1;
4752
            tcg_ctx.gen_opc_icount[lj] = num_insns;
4753
        }
4754

    
4755
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
4756
            gen_io_start();
4757
        }
4758

    
4759
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
4760
            tcg_gen_debug_insn_start(dc->pc);
4761
        }
4762

    
4763
        disas_a64_insn(env, dc);
4764

    
4765
        if (tcg_check_temp_count()) {
4766
            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
4767
                    dc->pc);
4768
        }
4769

    
4770
        /* Translation stops when a conditional branch is encountered.
4771
         * Otherwise the subsequent code could get translated several times.
4772
         * Also stop translation when a page boundary is reached.  This
4773
         * ensures prefetch aborts occur at the right place.
4774
         */
4775
        num_insns++;
4776
    } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
4777
             !cs->singlestep_enabled &&
4778
             !singlestep &&
4779
             dc->pc < next_page_start &&
4780
             num_insns < max_insns);
4781

    
4782
    if (tb->cflags & CF_LAST_IO) {
4783
        gen_io_end();
4784
    }
4785

    
4786
    if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
4787
        /* Note that this means single stepping WFI doesn't halt the CPU.
4788
         * For conditional branch insns this is harmless unreachable code as
4789
         * gen_goto_tb() has already handled emitting the debug exception
4790
         * (and thus a tb-jump is not possible when singlestepping).
4791
         */
4792
        assert(dc->is_jmp != DISAS_TB_JUMP);
4793
        if (dc->is_jmp != DISAS_JUMP) {
4794
            gen_a64_set_pc_im(dc->pc);
4795
        }
4796
        gen_exception(EXCP_DEBUG);
4797
    } else {
4798
        switch (dc->is_jmp) {
4799
        case DISAS_NEXT:
4800
            gen_goto_tb(dc, 1, dc->pc);
4801
            break;
4802
        default:
4803
        case DISAS_UPDATE:
4804
            gen_a64_set_pc_im(dc->pc);
4805
            /* fall through */
4806
        case DISAS_JUMP:
4807
            /* indicate that the hash table must be used to find the next TB */
4808
            tcg_gen_exit_tb(0);
4809
            break;
4810
        case DISAS_TB_JUMP:
4811
        case DISAS_EXC:
4812
        case DISAS_SWI:
4813
            break;
4814
        case DISAS_WFI:
4815
            /* This is a special case because we don't want to just halt the CPU
4816
             * if trying to debug across a WFI.
4817
             */
4818
            gen_helper_wfi(cpu_env);
4819
            break;
4820
        }
4821
    }
4822

    
4823
done_generating:
4824
    gen_tb_end(tb, num_insns);
4825
    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
4826

    
4827
#ifdef DEBUG_DISAS
4828
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
4829
        qemu_log("----------------\n");
4830
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
4831
        log_target_disas(env, pc_start, dc->pc - pc_start,
4832
                         dc->thumb | (dc->bswap_code << 1));
4833
        qemu_log("\n");
4834
    }
4835
#endif
4836
    if (search_pc) {
4837
        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
4838
        lj++;
4839
        while (lj <= j) {
4840
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
4841
        }
4842
    } else {
4843
        tb->size = dc->pc - pc_start;
4844
        tb->icount = num_insns;
4845
    }
4846
}