Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 1497c961

History | View | Annotate | Download (260.2 kB)

1
/*
2
 *  ARM translation
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *  Copyright (c) 2005-2007 CodeSourcery
6
 *  Copyright (c) 2007 OpenedHand, Ltd.
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 */
22
#include <stdarg.h>
23
#include <stdlib.h>
24
#include <stdio.h>
25
#include <string.h>
26
#include <inttypes.h>
27

    
28
#include "cpu.h"
29
#include "exec-all.h"
30
#include "disas.h"
31
#include "tcg-op.h"
32

    
33
#define GEN_HELPER 1
34
#include "helpers.h"
35

    
36
#define ENABLE_ARCH_5J    0
37
#define ENABLE_ARCH_6     arm_feature(env, ARM_FEATURE_V6)
38
#define ENABLE_ARCH_6K   arm_feature(env, ARM_FEATURE_V6K)
39
#define ENABLE_ARCH_6T2   arm_feature(env, ARM_FEATURE_THUMB2)
40
#define ENABLE_ARCH_7     arm_feature(env, ARM_FEATURE_V7)
41

    
42
#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
43

    
44
/* internal defines */
45
typedef struct DisasContext {
46
    target_ulong pc;
47
    int is_jmp;
48
    /* Nonzero if this instruction has been conditionally skipped.  */
49
    int condjmp;
50
    /* The label that will be jumped to when the instruction is skipped.  */
51
    int condlabel;
52
    /* Thumb-2 condtional execution bits.  */
53
    int condexec_mask;
54
    int condexec_cond;
55
    struct TranslationBlock *tb;
56
    int singlestep_enabled;
57
    int thumb;
58
    int is_mem;
59
#if !defined(CONFIG_USER_ONLY)
60
    int user;
61
#endif
62
} DisasContext;
63

    
64
#if defined(CONFIG_USER_ONLY)
65
#define IS_USER(s) 1
66
#else
67
#define IS_USER(s) (s->user)
68
#endif
69

    
70
/* These instructions trap after executing, so defer them until after the
71
   conditional executions state has been updated.  */
72
#define DISAS_WFI 4
73
#define DISAS_SWI 5
74

    
75
/* XXX: move that elsewhere */
76
extern FILE *logfile;
77
extern int loglevel;
78

    
79
static TCGv cpu_env;
80
/* FIXME:  These should be removed.  */
81
static TCGv cpu_T[3];
82

    
83
/* initialize TCG globals.  */
84
void arm_translate_init(void)
85
{
86
    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
87

    
88
    cpu_T[0] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG1, "T0");
89
    cpu_T[1] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG2, "T1");
90
    cpu_T[2] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG3, "T2");
91
}
92

    
93
/* The code generator doesn't like lots of temporaries, so maintain our own
94
   cache for reuse within a function.  */
95
#define MAX_TEMPS 8
96
static int num_temps;
97
static TCGv temps[MAX_TEMPS];
98

    
99
/* Allocate a temporary variable.  */
100
static TCGv new_tmp(void)
101
{
102
    TCGv tmp;
103
    if (num_temps == MAX_TEMPS)
104
        abort();
105

    
106
    if (GET_TCGV(temps[num_temps]))
107
      return temps[num_temps++];
108

    
109
    tmp = tcg_temp_new(TCG_TYPE_I32);
110
    temps[num_temps++] = tmp;
111
    return tmp;
112
}
113

    
114
/* Release a temporary variable.  */
115
static void dead_tmp(TCGv tmp)
116
{
117
    int i;
118
    num_temps--;
119
    i = num_temps;
120
    if (GET_TCGV(temps[i]) == GET_TCGV(tmp))
121
        return;
122

    
123
    /* Shuffle this temp to the last slot.  */
124
    while (GET_TCGV(temps[i]) != GET_TCGV(tmp))
125
        i--;
126
    while (i < num_temps) {
127
        temps[i] = temps[i + 1];
128
        i++;
129
    }
130
    temps[i] = tmp;
131
}
132

    
133
/* Set a variable to the value of a CPU register.  */
134
static void load_reg_var(DisasContext *s, TCGv var, int reg)
135
{
136
    if (reg == 15) {
137
        uint32_t addr;
138
        /* normaly, since we updated PC, we need only to add one insn */
139
        if (s->thumb)
140
            addr = (long)s->pc + 2;
141
        else
142
            addr = (long)s->pc + 4;
143
        tcg_gen_movi_i32(var, addr);
144
    } else {
145
        tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
146
    }
147
}
148

    
149
/* Create a new temporary and set it to the value of a CPU register.  */
150
static inline TCGv load_reg(DisasContext *s, int reg)
151
{
152
    TCGv tmp = new_tmp();
153
    load_reg_var(s, tmp, reg);
154
    return tmp;
155
}
156

    
157
/* Set a CPU register.  The source must be a temporary and will be
158
   marked as dead.  */
159
static void store_reg(DisasContext *s, int reg, TCGv var)
160
{
161
    if (reg == 15) {
162
        tcg_gen_andi_i32(var, var, ~1);
163
        s->is_jmp = DISAS_JUMP;
164
    }
165
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
166
    dead_tmp(var);
167
}
168

    
169

    
170
/* Basic operations.  */
171
#define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
172
#define gen_op_movl_T0_T2() tcg_gen_mov_i32(cpu_T[0], cpu_T[2])
173
#define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], cpu_T[0])
174
#define gen_op_movl_T1_T2() tcg_gen_mov_i32(cpu_T[1], cpu_T[2])
175
#define gen_op_movl_T2_T0() tcg_gen_mov_i32(cpu_T[2], cpu_T[0])
176
#define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
177
#define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
178
#define gen_op_movl_T2_im(im) tcg_gen_movi_i32(cpu_T[2], im)
179

    
180
#define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
181
#define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
182
#define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
183
#define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
184

    
185
#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
186
#define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
187
#define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
188
#define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
189
#define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
190
#define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
191
#define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
192

    
193
#define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im)
194
#define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
195
#define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
196
#define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im)
197
#define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im)
198

    
199
/* Value extensions.  */
200
#define gen_uxtb(var) tcg_gen_andi_i32(var, var, 0xff)
201
#define gen_uxth(var) tcg_gen_andi_i32(var, var, 0xffff)
202
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
203
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
204

    
205
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
206
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
207

    
208
#define gen_op_addl_T0_T1_setq() \
209
    gen_helper_add_setq(cpu_T[0], cpu_T[0], cpu_T[1])
210
#define gen_op_addl_T0_T1_saturate() \
211
    gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
212
#define gen_op_subl_T0_T1_saturate() \
213
    gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
214
#define gen_op_addl_T0_T1_usaturate() \
215
    gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
216
#define gen_op_subl_T0_T1_usaturate() \
217
    gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
218

    
219
/* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
220
    tmp = (t0 ^ t1) & 0x8000;
221
    t0 &= ~0x8000;
222
    t1 &= ~0x8000;
223
    t0 = (t0 + t1) ^ tmp;
224
 */
225

    
226
static void gen_add16(TCGv t0, TCGv t1)
227
{
228
    TCGv tmp = new_tmp();
229
    tcg_gen_xor_i32(tmp, t0, t1);
230
    tcg_gen_andi_i32(tmp, tmp, 0x8000);
231
    tcg_gen_andi_i32(t0, t0, ~0x8000);
232
    tcg_gen_andi_i32(t1, t1, ~0x8000);
233
    tcg_gen_add_i32(t0, t0, t1);
234
    tcg_gen_xor_i32(t0, t0, tmp);
235
    dead_tmp(tmp);
236
    dead_tmp(t1);
237
}
238

    
239
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
240

    
241
/* Set CF to the top bit of var.  */
242
static void gen_set_CF_bit31(TCGv var)
243
{
244
    TCGv tmp = new_tmp();
245
    tcg_gen_shri_i32(tmp, var, 31);
246
    gen_set_CF(var);
247
    dead_tmp(tmp);
248
}
249

    
250
/* Set N and Z flags from var.  */
251
static inline void gen_logic_CC(TCGv var)
252
{
253
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NZF));
254
}
255

    
256
/* T0 += T1 + CF.  */
257
static void gen_adc_T0_T1(void)
258
{
259
    TCGv tmp = new_tmp();
260
    gen_op_addl_T0_T1();
261
    tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
262
    tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
263
    dead_tmp(tmp);
264
}
265

    
266
/* FIXME:  Implement this natively.  */
267
static inline void tcg_gen_not_i32(TCGv t0, TCGv t1)
268
{
269
    tcg_gen_xori_i32(t0, t1, ~0);
270
}
271

    
272
/* T0 &= ~T1.  Clobbers T1.  */
273
/* FIXME: Implement bic natively.  */
274
static inline void gen_op_bicl_T0_T1(void)
275
{
276
    gen_op_notl_T1();
277
    gen_op_andl_T0_T1();
278
}
279

    
280
/* FIXME:  Implement this natively.  */
281
static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
282
{
283
    TCGv tmp;
284

    
285
    if (i == 0)
286
        return;
287

    
288
    tmp = new_tmp();
289
    tcg_gen_shri_i32(tmp, t1, i);
290
    tcg_gen_shli_i32(t1, t1, 32 - i);
291
    tcg_gen_or_i32(t0, t1, tmp);
292
    dead_tmp(tmp);
293
}
294

    
295
static void shifter_out_im(TCGv var, int shift)
296
{
297
    TCGv tmp = new_tmp();
298
    if (shift == 0) {
299
        tcg_gen_andi_i32(tmp, var, 1);
300
    } else {
301
        tcg_gen_shri_i32(tmp, var, shift);
302
        if (shift != 31);
303
            tcg_gen_andi_i32(tmp, tmp, 1);
304
    }
305
    gen_set_CF(tmp);
306
    dead_tmp(tmp);
307
}
308

    
309
/* Shift by immediate.  Includes special handling for shift == 0.  */
310
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
311
{
312
    switch (shiftop) {
313
    case 0: /* LSL */
314
        if (shift != 0) {
315
            if (flags)
316
                shifter_out_im(var, 32 - shift);
317
            tcg_gen_shli_i32(var, var, shift);
318
        }
319
        break;
320
    case 1: /* LSR */
321
        if (shift == 0) {
322
            if (flags) {
323
                tcg_gen_shri_i32(var, var, 31);
324
                gen_set_CF(var);
325
            }
326
            tcg_gen_movi_i32(var, 0);
327
        } else {
328
            if (flags)
329
                shifter_out_im(var, shift - 1);
330
            tcg_gen_shri_i32(var, var, shift);
331
        }
332
        break;
333
    case 2: /* ASR */
334
        if (shift == 0)
335
            shift = 32;
336
        if (flags)
337
            shifter_out_im(var, shift - 1);
338
        if (shift == 32)
339
          shift = 31;
340
        tcg_gen_sari_i32(var, var, shift);
341
        break;
342
    case 3: /* ROR/RRX */
343
        if (shift != 0) {
344
            if (flags)
345
                shifter_out_im(var, shift - 1);
346
            tcg_gen_rori_i32(var, var, shift); break;
347
        } else {
348
            TCGv tmp = new_tmp();
349
            tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
350
            if (flags)
351
                shifter_out_im(var, 0);
352
            tcg_gen_shri_i32(var, var, 1);
353
            tcg_gen_shli_i32(tmp, tmp, 31);
354
            tcg_gen_or_i32(var, var, tmp);
355
            dead_tmp(tmp);
356
        }
357
    }
358
};
359

    
360
#define PAS_OP(pfx) {  \
361
    gen_op_ ## pfx ## add16_T0_T1, \
362
    gen_op_ ## pfx ## addsubx_T0_T1, \
363
    gen_op_ ## pfx ## subaddx_T0_T1, \
364
    gen_op_ ## pfx ## sub16_T0_T1, \
365
    gen_op_ ## pfx ## add8_T0_T1, \
366
    NULL, \
367
    NULL, \
368
    gen_op_ ## pfx ## sub8_T0_T1 }
369

    
370
static GenOpFunc *gen_arm_parallel_addsub[8][8] = {
371
    {},
372
    PAS_OP(s),
373
    PAS_OP(q),
374
    PAS_OP(sh),
375
    {},
376
    PAS_OP(u),
377
    PAS_OP(uq),
378
    PAS_OP(uh),
379
};
380
#undef PAS_OP
381

    
382
/* For unknown reasons Arm and Thumb-2 use arbitrarily diffenet encodings.  */
383
#define PAS_OP(pfx) {  \
384
    gen_op_ ## pfx ## add8_T0_T1, \
385
    gen_op_ ## pfx ## add16_T0_T1, \
386
    gen_op_ ## pfx ## addsubx_T0_T1, \
387
    NULL, \
388
    gen_op_ ## pfx ## sub8_T0_T1, \
389
    gen_op_ ## pfx ## sub16_T0_T1, \
390
    gen_op_ ## pfx ## subaddx_T0_T1, \
391
    NULL }
392

    
393
static GenOpFunc *gen_thumb2_parallel_addsub[8][8] = {
394
    PAS_OP(s),
395
    PAS_OP(q),
396
    PAS_OP(sh),
397
    {},
398
    PAS_OP(u),
399
    PAS_OP(uq),
400
    PAS_OP(uh),
401
    {}
402
};
403
#undef PAS_OP
404

    
405
static GenOpFunc1 *gen_test_cc[14] = {
406
    gen_op_test_eq,
407
    gen_op_test_ne,
408
    gen_op_test_cs,
409
    gen_op_test_cc,
410
    gen_op_test_mi,
411
    gen_op_test_pl,
412
    gen_op_test_vs,
413
    gen_op_test_vc,
414
    gen_op_test_hi,
415
    gen_op_test_ls,
416
    gen_op_test_ge,
417
    gen_op_test_lt,
418
    gen_op_test_gt,
419
    gen_op_test_le,
420
};
421

    
422
const uint8_t table_logic_cc[16] = {
423
    1, /* and */
424
    1, /* xor */
425
    0, /* sub */
426
    0, /* rsb */
427
    0, /* add */
428
    0, /* adc */
429
    0, /* sbc */
430
    0, /* rsc */
431
    1, /* andl */
432
    1, /* xorl */
433
    0, /* cmp */
434
    0, /* cmn */
435
    1, /* orr */
436
    1, /* mov */
437
    1, /* bic */
438
    1, /* mvn */
439
};
440

    
441
static GenOpFunc *gen_shift_T1_T0[4] = {
442
    gen_op_shll_T1_T0,
443
    gen_op_shrl_T1_T0,
444
    gen_op_sarl_T1_T0,
445
    gen_op_rorl_T1_T0,
446
};
447

    
448
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
449
    gen_op_shll_T1_T0_cc,
450
    gen_op_shrl_T1_T0_cc,
451
    gen_op_sarl_T1_T0_cc,
452
    gen_op_rorl_T1_T0_cc,
453
};
454

    
455
/* Set PC and thumb state from T0.  Clobbers T0.  */
456
static inline void gen_bx(DisasContext *s)
457
{
458
    TCGv tmp;
459

    
460
    s->is_jmp = DISAS_UPDATE;
461
    tmp = new_tmp();
462
    tcg_gen_andi_i32(tmp, cpu_T[0], 1);
463
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
464
    dead_tmp(tmp);
465
    tcg_gen_andi_i32(cpu_T[0], cpu_T[0], ~1);
466
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
467
}
468

    
469
#if defined(CONFIG_USER_ONLY)
470
#define gen_ldst(name, s) gen_op_##name##_raw()
471
#else
472
#define gen_ldst(name, s) do { \
473
    s->is_mem = 1; \
474
    if (IS_USER(s)) \
475
        gen_op_##name##_user(); \
476
    else \
477
        gen_op_##name##_kernel(); \
478
    } while (0)
479
#endif
480

    
481
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
482
{
483
    load_reg_var(s, cpu_T[0], reg);
484
}
485

    
486
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
487
{
488
    load_reg_var(s, cpu_T[1], reg);
489
}
490

    
491
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
492
{
493
    load_reg_var(s, cpu_T[2], reg);
494
}
495

    
496
static inline void gen_set_pc_T0(void)
497
{
498
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
499
}
500

    
501
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
502
{
503
    TCGv tmp;
504
    if (reg == 15) {
505
        tmp = new_tmp();
506
        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
507
    } else {
508
        tmp = cpu_T[t];
509
    }
510
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
511
    if (reg == 15) {
512
        dead_tmp(tmp);
513
        s->is_jmp = DISAS_JUMP;
514
    }
515
}
516

    
517
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
518
{
519
    gen_movl_reg_TN(s, reg, 0);
520
}
521

    
522
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
523
{
524
    gen_movl_reg_TN(s, reg, 1);
525
}
526

    
527
/* Force a TB lookup after an instruction that changes the CPU state.  */
528
static inline void gen_lookup_tb(DisasContext *s)
529
{
530
    gen_op_movl_T0_im(s->pc);
531
    gen_movl_reg_T0(s, 15);
532
    s->is_jmp = DISAS_UPDATE;
533
}
534

    
535
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
536
{
537
    int val, rm, shift, shiftop;
538
    TCGv offset;
539

    
540
    if (!(insn & (1 << 25))) {
541
        /* immediate */
542
        val = insn & 0xfff;
543
        if (!(insn & (1 << 23)))
544
            val = -val;
545
        if (val != 0)
546
            gen_op_addl_T1_im(val);
547
    } else {
548
        /* shift/register */
549
        rm = (insn) & 0xf;
550
        shift = (insn >> 7) & 0x1f;
551
        shiftop = (insn >> 5) & 3;
552
        offset = load_reg(s, rm);
553
        gen_arm_shift_im(offset, shiftop, shift, 0);
554
        if (!(insn & (1 << 23)))
555
            tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
556
        else
557
            tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
558
        dead_tmp(offset);
559
    }
560
}
561

    
562
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
563
                                        int extra)
564
{
565
    int val, rm;
566
    TCGv offset;
567

    
568
    if (insn & (1 << 22)) {
569
        /* immediate */
570
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
571
        if (!(insn & (1 << 23)))
572
            val = -val;
573
        val += extra;
574
        if (val != 0)
575
            gen_op_addl_T1_im(val);
576
    } else {
577
        /* register */
578
        if (extra)
579
            gen_op_addl_T1_im(extra);
580
        rm = (insn) & 0xf;
581
        offset = load_reg(s, rm);
582
        if (!(insn & (1 << 23)))
583
            tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
584
        else
585
            tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
586
        dead_tmp(offset);
587
    }
588
}
589

    
590
#define VFP_OP(name)                      \
591
static inline void gen_vfp_##name(int dp) \
592
{                                         \
593
    if (dp)                               \
594
        gen_op_vfp_##name##d();           \
595
    else                                  \
596
        gen_op_vfp_##name##s();           \
597
}
598

    
599
#define VFP_OP1(name)                               \
600
static inline void gen_vfp_##name(int dp, int arg)  \
601
{                                                   \
602
    if (dp)                                         \
603
        gen_op_vfp_##name##d(arg);                  \
604
    else                                            \
605
        gen_op_vfp_##name##s(arg);                  \
606
}
607

    
608
VFP_OP(add)
609
VFP_OP(sub)
610
VFP_OP(mul)
611
VFP_OP(div)
612
VFP_OP(neg)
613
VFP_OP(abs)
614
VFP_OP(sqrt)
615
VFP_OP(cmp)
616
VFP_OP(cmpe)
617
VFP_OP(F1_ld0)
618
VFP_OP(uito)
619
VFP_OP(sito)
620
VFP_OP(toui)
621
VFP_OP(touiz)
622
VFP_OP(tosi)
623
VFP_OP(tosiz)
624
VFP_OP1(tosh)
625
VFP_OP1(tosl)
626
VFP_OP1(touh)
627
VFP_OP1(toul)
628
VFP_OP1(shto)
629
VFP_OP1(slto)
630
VFP_OP1(uhto)
631
VFP_OP1(ulto)
632

    
633
#undef VFP_OP
634

    
635
static inline void gen_vfp_fconst(int dp, uint32_t val)
636
{
637
    if (dp)
638
        gen_op_vfp_fconstd(val);
639
    else
640
        gen_op_vfp_fconsts(val);
641
}
642

    
643
static inline void gen_vfp_ld(DisasContext *s, int dp)
644
{
645
    if (dp)
646
        gen_ldst(vfp_ldd, s);
647
    else
648
        gen_ldst(vfp_lds, s);
649
}
650

    
651
static inline void gen_vfp_st(DisasContext *s, int dp)
652
{
653
    if (dp)
654
        gen_ldst(vfp_std, s);
655
    else
656
        gen_ldst(vfp_sts, s);
657
}
658

    
659
static inline long
660
vfp_reg_offset (int dp, int reg)
661
{
662
    if (dp)
663
        return offsetof(CPUARMState, vfp.regs[reg]);
664
    else if (reg & 1) {
665
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
666
          + offsetof(CPU_DoubleU, l.upper);
667
    } else {
668
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
669
          + offsetof(CPU_DoubleU, l.lower);
670
    }
671
}
672

    
673
/* Return the offset of a 32-bit piece of a NEON register.
674
   zero is the least significant end of the register.  */
675
static inline long
676
neon_reg_offset (int reg, int n)
677
{
678
    int sreg;
679
    sreg = reg * 2 + n;
680
    return vfp_reg_offset(0, sreg);
681
}
682

    
683
#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
684
#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
685

    
686
static inline void gen_mov_F0_vreg(int dp, int reg)
687
{
688
    if (dp)
689
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
690
    else
691
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
692
}
693

    
694
static inline void gen_mov_F1_vreg(int dp, int reg)
695
{
696
    if (dp)
697
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
698
    else
699
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
700
}
701

    
702
static inline void gen_mov_vreg_F0(int dp, int reg)
703
{
704
    if (dp)
705
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
706
    else
707
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
708
}
709

    
710
#define ARM_CP_RW_BIT        (1 << 20)
711

    
712
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
713
{
714
    int rd;
715
    uint32_t offset;
716

    
717
    rd = (insn >> 16) & 0xf;
718
    gen_movl_T1_reg(s, rd);
719

    
720
    offset = (insn & 0xff) << ((insn >> 7) & 2);
721
    if (insn & (1 << 24)) {
722
        /* Pre indexed */
723
        if (insn & (1 << 23))
724
            gen_op_addl_T1_im(offset);
725
        else
726
            gen_op_addl_T1_im(-offset);
727

    
728
        if (insn & (1 << 21))
729
            gen_movl_reg_T1(s, rd);
730
    } else if (insn & (1 << 21)) {
731
        /* Post indexed */
732
        if (insn & (1 << 23))
733
            gen_op_movl_T0_im(offset);
734
        else
735
            gen_op_movl_T0_im(- offset);
736
        gen_op_addl_T0_T1();
737
        gen_movl_reg_T0(s, rd);
738
    } else if (!(insn & (1 << 23)))
739
        return 1;
740
    return 0;
741
}
742

    
743
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
744
{
745
    int rd = (insn >> 0) & 0xf;
746

    
747
    if (insn & (1 << 8))
748
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
749
            return 1;
750
        else
751
            gen_op_iwmmxt_movl_T0_wCx(rd);
752
    else
753
        gen_op_iwmmxt_movl_T0_T1_wRn(rd);
754

    
755
    gen_op_movl_T1_im(mask);
756
    gen_op_andl_T0_T1();
757
    return 0;
758
}
759

    
760
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
761
   (ie. an undefined instruction).  */
762
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
763
{
764
    int rd, wrd;
765
    int rdhi, rdlo, rd0, rd1, i;
766

    
767
    if ((insn & 0x0e000e00) == 0x0c000000) {
768
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
769
            wrd = insn & 0xf;
770
            rdlo = (insn >> 12) & 0xf;
771
            rdhi = (insn >> 16) & 0xf;
772
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
773
                gen_op_iwmmxt_movl_T0_T1_wRn(wrd);
774
                gen_movl_reg_T0(s, rdlo);
775
                gen_movl_reg_T1(s, rdhi);
776
            } else {                                        /* TMCRR */
777
                gen_movl_T0_reg(s, rdlo);
778
                gen_movl_T1_reg(s, rdhi);
779
                gen_op_iwmmxt_movl_wRn_T0_T1(wrd);
780
                gen_op_iwmmxt_set_mup();
781
            }
782
            return 0;
783
        }
784

    
785
        wrd = (insn >> 12) & 0xf;
786
        if (gen_iwmmxt_address(s, insn))
787
            return 1;
788
        if (insn & ARM_CP_RW_BIT) {
789
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
790
                gen_ldst(ldl, s);
791
                gen_op_iwmmxt_movl_wCx_T0(wrd);
792
            } else {
793
                if (insn & (1 << 8))
794
                    if (insn & (1 << 22))                /* WLDRD */
795
                        gen_ldst(iwmmxt_ldq, s);
796
                    else                                /* WLDRW wRd */
797
                        gen_ldst(iwmmxt_ldl, s);
798
                else
799
                    if (insn & (1 << 22))                /* WLDRH */
800
                        gen_ldst(iwmmxt_ldw, s);
801
                    else                                /* WLDRB */
802
                        gen_ldst(iwmmxt_ldb, s);
803
                gen_op_iwmmxt_movq_wRn_M0(wrd);
804
            }
805
        } else {
806
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
807
                gen_op_iwmmxt_movl_T0_wCx(wrd);
808
                gen_ldst(stl, s);
809
            } else {
810
                gen_op_iwmmxt_movq_M0_wRn(wrd);
811
                if (insn & (1 << 8))
812
                    if (insn & (1 << 22))                /* WSTRD */
813
                        gen_ldst(iwmmxt_stq, s);
814
                    else                                /* WSTRW wRd */
815
                        gen_ldst(iwmmxt_stl, s);
816
                else
817
                    if (insn & (1 << 22))                /* WSTRH */
818
                        gen_ldst(iwmmxt_ldw, s);
819
                    else                                /* WSTRB */
820
                        gen_ldst(iwmmxt_stb, s);
821
            }
822
        }
823
        return 0;
824
    }
825

    
826
    if ((insn & 0x0f000000) != 0x0e000000)
827
        return 1;
828

    
829
    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
830
    case 0x000:                                                /* WOR */
831
        wrd = (insn >> 12) & 0xf;
832
        rd0 = (insn >> 0) & 0xf;
833
        rd1 = (insn >> 16) & 0xf;
834
        gen_op_iwmmxt_movq_M0_wRn(rd0);
835
        gen_op_iwmmxt_orq_M0_wRn(rd1);
836
        gen_op_iwmmxt_setpsr_nz();
837
        gen_op_iwmmxt_movq_wRn_M0(wrd);
838
        gen_op_iwmmxt_set_mup();
839
        gen_op_iwmmxt_set_cup();
840
        break;
841
    case 0x011:                                                /* TMCR */
842
        if (insn & 0xf)
843
            return 1;
844
        rd = (insn >> 12) & 0xf;
845
        wrd = (insn >> 16) & 0xf;
846
        switch (wrd) {
847
        case ARM_IWMMXT_wCID:
848
        case ARM_IWMMXT_wCASF:
849
            break;
850
        case ARM_IWMMXT_wCon:
851
            gen_op_iwmmxt_set_cup();
852
            /* Fall through.  */
853
        case ARM_IWMMXT_wCSSF:
854
            gen_op_iwmmxt_movl_T0_wCx(wrd);
855
            gen_movl_T1_reg(s, rd);
856
            gen_op_bicl_T0_T1();
857
            gen_op_iwmmxt_movl_wCx_T0(wrd);
858
            break;
859
        case ARM_IWMMXT_wCGR0:
860
        case ARM_IWMMXT_wCGR1:
861
        case ARM_IWMMXT_wCGR2:
862
        case ARM_IWMMXT_wCGR3:
863
            gen_op_iwmmxt_set_cup();
864
            gen_movl_reg_T0(s, rd);
865
            gen_op_iwmmxt_movl_wCx_T0(wrd);
866
            break;
867
        default:
868
            return 1;
869
        }
870
        break;
871
    case 0x100:                                                /* WXOR */
872
        wrd = (insn >> 12) & 0xf;
873
        rd0 = (insn >> 0) & 0xf;
874
        rd1 = (insn >> 16) & 0xf;
875
        gen_op_iwmmxt_movq_M0_wRn(rd0);
876
        gen_op_iwmmxt_xorq_M0_wRn(rd1);
877
        gen_op_iwmmxt_setpsr_nz();
878
        gen_op_iwmmxt_movq_wRn_M0(wrd);
879
        gen_op_iwmmxt_set_mup();
880
        gen_op_iwmmxt_set_cup();
881
        break;
882
    case 0x111:                                                /* TMRC */
883
        if (insn & 0xf)
884
            return 1;
885
        rd = (insn >> 12) & 0xf;
886
        wrd = (insn >> 16) & 0xf;
887
        gen_op_iwmmxt_movl_T0_wCx(wrd);
888
        gen_movl_reg_T0(s, rd);
889
        break;
890
    case 0x300:                                                /* WANDN */
891
        wrd = (insn >> 12) & 0xf;
892
        rd0 = (insn >> 0) & 0xf;
893
        rd1 = (insn >> 16) & 0xf;
894
        gen_op_iwmmxt_movq_M0_wRn(rd0);
895
        gen_op_iwmmxt_negq_M0();
896
        gen_op_iwmmxt_andq_M0_wRn(rd1);
897
        gen_op_iwmmxt_setpsr_nz();
898
        gen_op_iwmmxt_movq_wRn_M0(wrd);
899
        gen_op_iwmmxt_set_mup();
900
        gen_op_iwmmxt_set_cup();
901
        break;
902
    case 0x200:                                                /* WAND */
903
        wrd = (insn >> 12) & 0xf;
904
        rd0 = (insn >> 0) & 0xf;
905
        rd1 = (insn >> 16) & 0xf;
906
        gen_op_iwmmxt_movq_M0_wRn(rd0);
907
        gen_op_iwmmxt_andq_M0_wRn(rd1);
908
        gen_op_iwmmxt_setpsr_nz();
909
        gen_op_iwmmxt_movq_wRn_M0(wrd);
910
        gen_op_iwmmxt_set_mup();
911
        gen_op_iwmmxt_set_cup();
912
        break;
913
    case 0x810: case 0xa10:                                /* WMADD */
914
        wrd = (insn >> 12) & 0xf;
915
        rd0 = (insn >> 0) & 0xf;
916
        rd1 = (insn >> 16) & 0xf;
917
        gen_op_iwmmxt_movq_M0_wRn(rd0);
918
        if (insn & (1 << 21))
919
            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
920
        else
921
            gen_op_iwmmxt_madduq_M0_wRn(rd1);
922
        gen_op_iwmmxt_movq_wRn_M0(wrd);
923
        gen_op_iwmmxt_set_mup();
924
        break;
925
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:        /* WUNPCKIL */
926
        wrd = (insn >> 12) & 0xf;
927
        rd0 = (insn >> 16) & 0xf;
928
        rd1 = (insn >> 0) & 0xf;
929
        gen_op_iwmmxt_movq_M0_wRn(rd0);
930
        switch ((insn >> 22) & 3) {
931
        case 0:
932
            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
933
            break;
934
        case 1:
935
            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
936
            break;
937
        case 2:
938
            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
939
            break;
940
        case 3:
941
            return 1;
942
        }
943
        gen_op_iwmmxt_movq_wRn_M0(wrd);
944
        gen_op_iwmmxt_set_mup();
945
        gen_op_iwmmxt_set_cup();
946
        break;
947
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:        /* WUNPCKIH */
948
        wrd = (insn >> 12) & 0xf;
949
        rd0 = (insn >> 16) & 0xf;
950
        rd1 = (insn >> 0) & 0xf;
951
        gen_op_iwmmxt_movq_M0_wRn(rd0);
952
        switch ((insn >> 22) & 3) {
953
        case 0:
954
            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
955
            break;
956
        case 1:
957
            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
958
            break;
959
        case 2:
960
            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
961
            break;
962
        case 3:
963
            return 1;
964
        }
965
        gen_op_iwmmxt_movq_wRn_M0(wrd);
966
        gen_op_iwmmxt_set_mup();
967
        gen_op_iwmmxt_set_cup();
968
        break;
969
    case 0x012: case 0x112: case 0x412: case 0x512:        /* WSAD */
970
        wrd = (insn >> 12) & 0xf;
971
        rd0 = (insn >> 16) & 0xf;
972
        rd1 = (insn >> 0) & 0xf;
973
        gen_op_iwmmxt_movq_M0_wRn(rd0);
974
        if (insn & (1 << 22))
975
            gen_op_iwmmxt_sadw_M0_wRn(rd1);
976
        else
977
            gen_op_iwmmxt_sadb_M0_wRn(rd1);
978
        if (!(insn & (1 << 20)))
979
            gen_op_iwmmxt_addl_M0_wRn(wrd);
980
        gen_op_iwmmxt_movq_wRn_M0(wrd);
981
        gen_op_iwmmxt_set_mup();
982
        break;
983
    case 0x010: case 0x110: case 0x210: case 0x310:        /* WMUL */
984
        wrd = (insn >> 12) & 0xf;
985
        rd0 = (insn >> 16) & 0xf;
986
        rd1 = (insn >> 0) & 0xf;
987
        gen_op_iwmmxt_movq_M0_wRn(rd0);
988
        if (insn & (1 << 21))
989
            gen_op_iwmmxt_mulsw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
990
        else
991
            gen_op_iwmmxt_muluw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
992
        gen_op_iwmmxt_movq_wRn_M0(wrd);
993
        gen_op_iwmmxt_set_mup();
994
        break;
995
    case 0x410: case 0x510: case 0x610: case 0x710:        /* WMAC */
996
        wrd = (insn >> 12) & 0xf;
997
        rd0 = (insn >> 16) & 0xf;
998
        rd1 = (insn >> 0) & 0xf;
999
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1000
        if (insn & (1 << 21))
1001
            gen_op_iwmmxt_macsw_M0_wRn(rd1);
1002
        else
1003
            gen_op_iwmmxt_macuw_M0_wRn(rd1);
1004
        if (!(insn & (1 << 20))) {
1005
            if (insn & (1 << 21))
1006
                gen_op_iwmmxt_addsq_M0_wRn(wrd);
1007
            else
1008
                gen_op_iwmmxt_adduq_M0_wRn(wrd);
1009
        }
1010
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1011
        gen_op_iwmmxt_set_mup();
1012
        break;
1013
    case 0x006: case 0x406: case 0x806: case 0xc06:        /* WCMPEQ */
1014
        wrd = (insn >> 12) & 0xf;
1015
        rd0 = (insn >> 16) & 0xf;
1016
        rd1 = (insn >> 0) & 0xf;
1017
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1018
        switch ((insn >> 22) & 3) {
1019
        case 0:
1020
            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1021
            break;
1022
        case 1:
1023
            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1024
            break;
1025
        case 2:
1026
            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1027
            break;
1028
        case 3:
1029
            return 1;
1030
        }
1031
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1032
        gen_op_iwmmxt_set_mup();
1033
        gen_op_iwmmxt_set_cup();
1034
        break;
1035
    case 0x800: case 0x900: case 0xc00: case 0xd00:        /* WAVG2 */
1036
        wrd = (insn >> 12) & 0xf;
1037
        rd0 = (insn >> 16) & 0xf;
1038
        rd1 = (insn >> 0) & 0xf;
1039
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1040
        if (insn & (1 << 22))
1041
            gen_op_iwmmxt_avgw_M0_wRn(rd1, (insn >> 20) & 1);
1042
        else
1043
            gen_op_iwmmxt_avgb_M0_wRn(rd1, (insn >> 20) & 1);
1044
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1045
        gen_op_iwmmxt_set_mup();
1046
        gen_op_iwmmxt_set_cup();
1047
        break;
1048
    case 0x802: case 0x902: case 0xa02: case 0xb02:        /* WALIGNR */
1049
        wrd = (insn >> 12) & 0xf;
1050
        rd0 = (insn >> 16) & 0xf;
1051
        rd1 = (insn >> 0) & 0xf;
1052
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1053
        gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1054
        gen_op_movl_T1_im(7);
1055
        gen_op_andl_T0_T1();
1056
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1057
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1058
        gen_op_iwmmxt_set_mup();
1059
        break;
1060
    case 0x601: case 0x605: case 0x609: case 0x60d:        /* TINSR */
1061
        rd = (insn >> 12) & 0xf;
1062
        wrd = (insn >> 16) & 0xf;
1063
        gen_movl_T0_reg(s, rd);
1064
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1065
        switch ((insn >> 6) & 3) {
1066
        case 0:
1067
            gen_op_movl_T1_im(0xff);
1068
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1069
            break;
1070
        case 1:
1071
            gen_op_movl_T1_im(0xffff);
1072
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1073
            break;
1074
        case 2:
1075
            gen_op_movl_T1_im(0xffffffff);
1076
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1077
            break;
1078
        case 3:
1079
            return 1;
1080
        }
1081
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1082
        gen_op_iwmmxt_set_mup();
1083
        break;
1084
    case 0x107: case 0x507: case 0x907: case 0xd07:        /* TEXTRM */
1085
        rd = (insn >> 12) & 0xf;
1086
        wrd = (insn >> 16) & 0xf;
1087
        if (rd == 15)
1088
            return 1;
1089
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1090
        switch ((insn >> 22) & 3) {
1091
        case 0:
1092
            if (insn & 8)
1093
                gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1094
            else {
1095
                gen_op_movl_T1_im(0xff);
1096
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 7) << 3);
1097
            }
1098
            break;
1099
        case 1:
1100
            if (insn & 8)
1101
                gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1102
            else {
1103
                gen_op_movl_T1_im(0xffff);
1104
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 3) << 4);
1105
            }
1106
            break;
1107
        case 2:
1108
            gen_op_movl_T1_im(0xffffffff);
1109
            gen_op_iwmmxt_extru_T0_M0_T1((insn & 1) << 5);
1110
            break;
1111
        case 3:
1112
            return 1;
1113
        }
1114
        gen_movl_reg_T0(s, rd);
1115
        break;
1116
    case 0x117: case 0x517: case 0x917: case 0xd17:        /* TEXTRC */
1117
        if ((insn & 0x000ff008) != 0x0003f000)
1118
            return 1;
1119
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1120
        switch ((insn >> 22) & 3) {
1121
        case 0:
1122
            gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1123
            break;
1124
        case 1:
1125
            gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1126
            break;
1127
        case 2:
1128
            gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1129
            break;
1130
        case 3:
1131
            return 1;
1132
        }
1133
        gen_op_shll_T1_im(28);
1134
        gen_op_movl_T0_T1();
1135
        gen_op_movl_cpsr_T0(0xf0000000);
1136
        break;
1137
    case 0x401: case 0x405: case 0x409: case 0x40d:        /* TBCST */
1138
        rd = (insn >> 12) & 0xf;
1139
        wrd = (insn >> 16) & 0xf;
1140
        gen_movl_T0_reg(s, rd);
1141
        switch ((insn >> 6) & 3) {
1142
        case 0:
1143
            gen_op_iwmmxt_bcstb_M0_T0();
1144
            break;
1145
        case 1:
1146
            gen_op_iwmmxt_bcstw_M0_T0();
1147
            break;
1148
        case 2:
1149
            gen_op_iwmmxt_bcstl_M0_T0();
1150
            break;
1151
        case 3:
1152
            return 1;
1153
        }
1154
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1155
        gen_op_iwmmxt_set_mup();
1156
        break;
1157
    case 0x113: case 0x513: case 0x913: case 0xd13:        /* TANDC */
1158
        if ((insn & 0x000ff00f) != 0x0003f000)
1159
            return 1;
1160
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1161
        switch ((insn >> 22) & 3) {
1162
        case 0:
1163
            for (i = 0; i < 7; i ++) {
1164
                gen_op_shll_T1_im(4);
1165
                gen_op_andl_T0_T1();
1166
            }
1167
            break;
1168
        case 1:
1169
            for (i = 0; i < 3; i ++) {
1170
                gen_op_shll_T1_im(8);
1171
                gen_op_andl_T0_T1();
1172
            }
1173
            break;
1174
        case 2:
1175
            gen_op_shll_T1_im(16);
1176
            gen_op_andl_T0_T1();
1177
            break;
1178
        case 3:
1179
            return 1;
1180
        }
1181
        gen_op_movl_cpsr_T0(0xf0000000);
1182
        break;
1183
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:        /* WACC */
1184
        wrd = (insn >> 12) & 0xf;
1185
        rd0 = (insn >> 16) & 0xf;
1186
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1187
        switch ((insn >> 22) & 3) {
1188
        case 0:
1189
            gen_op_iwmmxt_addcb_M0();
1190
            break;
1191
        case 1:
1192
            gen_op_iwmmxt_addcw_M0();
1193
            break;
1194
        case 2:
1195
            gen_op_iwmmxt_addcl_M0();
1196
            break;
1197
        case 3:
1198
            return 1;
1199
        }
1200
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1201
        gen_op_iwmmxt_set_mup();
1202
        break;
1203
    case 0x115: case 0x515: case 0x915: case 0xd15:        /* TORC */
1204
        if ((insn & 0x000ff00f) != 0x0003f000)
1205
            return 1;
1206
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1207
        switch ((insn >> 22) & 3) {
1208
        case 0:
1209
            for (i = 0; i < 7; i ++) {
1210
                gen_op_shll_T1_im(4);
1211
                gen_op_orl_T0_T1();
1212
            }
1213
            break;
1214
        case 1:
1215
            for (i = 0; i < 3; i ++) {
1216
                gen_op_shll_T1_im(8);
1217
                gen_op_orl_T0_T1();
1218
            }
1219
            break;
1220
        case 2:
1221
            gen_op_shll_T1_im(16);
1222
            gen_op_orl_T0_T1();
1223
            break;
1224
        case 3:
1225
            return 1;
1226
        }
1227
        gen_op_movl_T1_im(0xf0000000);
1228
        gen_op_andl_T0_T1();
1229
        gen_op_movl_cpsr_T0(0xf0000000);
1230
        break;
1231
    case 0x103: case 0x503: case 0x903: case 0xd03:        /* TMOVMSK */
1232
        rd = (insn >> 12) & 0xf;
1233
        rd0 = (insn >> 16) & 0xf;
1234
        if ((insn & 0xf) != 0)
1235
            return 1;
1236
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1237
        switch ((insn >> 22) & 3) {
1238
        case 0:
1239
            gen_op_iwmmxt_msbb_T0_M0();
1240
            break;
1241
        case 1:
1242
            gen_op_iwmmxt_msbw_T0_M0();
1243
            break;
1244
        case 2:
1245
            gen_op_iwmmxt_msbl_T0_M0();
1246
            break;
1247
        case 3:
1248
            return 1;
1249
        }
1250
        gen_movl_reg_T0(s, rd);
1251
        break;
1252
    case 0x106: case 0x306: case 0x506: case 0x706:        /* WCMPGT */
1253
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
1254
        wrd = (insn >> 12) & 0xf;
1255
        rd0 = (insn >> 16) & 0xf;
1256
        rd1 = (insn >> 0) & 0xf;
1257
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1258
        switch ((insn >> 22) & 3) {
1259
        case 0:
1260
            if (insn & (1 << 21))
1261
                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1262
            else
1263
                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1264
            break;
1265
        case 1:
1266
            if (insn & (1 << 21))
1267
                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1268
            else
1269
                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1270
            break;
1271
        case 2:
1272
            if (insn & (1 << 21))
1273
                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1274
            else
1275
                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1276
            break;
1277
        case 3:
1278
            return 1;
1279
        }
1280
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1281
        gen_op_iwmmxt_set_mup();
1282
        gen_op_iwmmxt_set_cup();
1283
        break;
1284
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:        /* WUNPCKEL */
1285
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1286
        wrd = (insn >> 12) & 0xf;
1287
        rd0 = (insn >> 16) & 0xf;
1288
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1289
        switch ((insn >> 22) & 3) {
1290
        case 0:
1291
            if (insn & (1 << 21))
1292
                gen_op_iwmmxt_unpacklsb_M0();
1293
            else
1294
                gen_op_iwmmxt_unpacklub_M0();
1295
            break;
1296
        case 1:
1297
            if (insn & (1 << 21))
1298
                gen_op_iwmmxt_unpacklsw_M0();
1299
            else
1300
                gen_op_iwmmxt_unpackluw_M0();
1301
            break;
1302
        case 2:
1303
            if (insn & (1 << 21))
1304
                gen_op_iwmmxt_unpacklsl_M0();
1305
            else
1306
                gen_op_iwmmxt_unpacklul_M0();
1307
            break;
1308
        case 3:
1309
            return 1;
1310
        }
1311
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1312
        gen_op_iwmmxt_set_mup();
1313
        gen_op_iwmmxt_set_cup();
1314
        break;
1315
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:        /* WUNPCKEH */
1316
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1317
        wrd = (insn >> 12) & 0xf;
1318
        rd0 = (insn >> 16) & 0xf;
1319
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1320
        switch ((insn >> 22) & 3) {
1321
        case 0:
1322
            if (insn & (1 << 21))
1323
                gen_op_iwmmxt_unpackhsb_M0();
1324
            else
1325
                gen_op_iwmmxt_unpackhub_M0();
1326
            break;
1327
        case 1:
1328
            if (insn & (1 << 21))
1329
                gen_op_iwmmxt_unpackhsw_M0();
1330
            else
1331
                gen_op_iwmmxt_unpackhuw_M0();
1332
            break;
1333
        case 2:
1334
            if (insn & (1 << 21))
1335
                gen_op_iwmmxt_unpackhsl_M0();
1336
            else
1337
                gen_op_iwmmxt_unpackhul_M0();
1338
            break;
1339
        case 3:
1340
            return 1;
1341
        }
1342
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1343
        gen_op_iwmmxt_set_mup();
1344
        gen_op_iwmmxt_set_cup();
1345
        break;
1346
    case 0x204: case 0x604: case 0xa04: case 0xe04:        /* WSRL */
1347
    case 0x214: case 0x614: case 0xa14: case 0xe14:
1348
        wrd = (insn >> 12) & 0xf;
1349
        rd0 = (insn >> 16) & 0xf;
1350
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1351
        if (gen_iwmmxt_shift(insn, 0xff))
1352
            return 1;
1353
        switch ((insn >> 22) & 3) {
1354
        case 0:
1355
            return 1;
1356
        case 1:
1357
            gen_op_iwmmxt_srlw_M0_T0();
1358
            break;
1359
        case 2:
1360
            gen_op_iwmmxt_srll_M0_T0();
1361
            break;
1362
        case 3:
1363
            gen_op_iwmmxt_srlq_M0_T0();
1364
            break;
1365
        }
1366
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1367
        gen_op_iwmmxt_set_mup();
1368
        gen_op_iwmmxt_set_cup();
1369
        break;
1370
    case 0x004: case 0x404: case 0x804: case 0xc04:        /* WSRA */
1371
    case 0x014: case 0x414: case 0x814: case 0xc14:
1372
        wrd = (insn >> 12) & 0xf;
1373
        rd0 = (insn >> 16) & 0xf;
1374
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1375
        if (gen_iwmmxt_shift(insn, 0xff))
1376
            return 1;
1377
        switch ((insn >> 22) & 3) {
1378
        case 0:
1379
            return 1;
1380
        case 1:
1381
            gen_op_iwmmxt_sraw_M0_T0();
1382
            break;
1383
        case 2:
1384
            gen_op_iwmmxt_sral_M0_T0();
1385
            break;
1386
        case 3:
1387
            gen_op_iwmmxt_sraq_M0_T0();
1388
            break;
1389
        }
1390
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1391
        gen_op_iwmmxt_set_mup();
1392
        gen_op_iwmmxt_set_cup();
1393
        break;
1394
    case 0x104: case 0x504: case 0x904: case 0xd04:        /* WSLL */
1395
    case 0x114: case 0x514: case 0x914: case 0xd14:
1396
        wrd = (insn >> 12) & 0xf;
1397
        rd0 = (insn >> 16) & 0xf;
1398
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1399
        if (gen_iwmmxt_shift(insn, 0xff))
1400
            return 1;
1401
        switch ((insn >> 22) & 3) {
1402
        case 0:
1403
            return 1;
1404
        case 1:
1405
            gen_op_iwmmxt_sllw_M0_T0();
1406
            break;
1407
        case 2:
1408
            gen_op_iwmmxt_slll_M0_T0();
1409
            break;
1410
        case 3:
1411
            gen_op_iwmmxt_sllq_M0_T0();
1412
            break;
1413
        }
1414
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1415
        gen_op_iwmmxt_set_mup();
1416
        gen_op_iwmmxt_set_cup();
1417
        break;
1418
    case 0x304: case 0x704: case 0xb04: case 0xf04:        /* WROR */
1419
    case 0x314: case 0x714: case 0xb14: case 0xf14:
1420
        wrd = (insn >> 12) & 0xf;
1421
        rd0 = (insn >> 16) & 0xf;
1422
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1423
        switch ((insn >> 22) & 3) {
1424
        case 0:
1425
            return 1;
1426
        case 1:
1427
            if (gen_iwmmxt_shift(insn, 0xf))
1428
                return 1;
1429
            gen_op_iwmmxt_rorw_M0_T0();
1430
            break;
1431
        case 2:
1432
            if (gen_iwmmxt_shift(insn, 0x1f))
1433
                return 1;
1434
            gen_op_iwmmxt_rorl_M0_T0();
1435
            break;
1436
        case 3:
1437
            if (gen_iwmmxt_shift(insn, 0x3f))
1438
                return 1;
1439
            gen_op_iwmmxt_rorq_M0_T0();
1440
            break;
1441
        }
1442
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1443
        gen_op_iwmmxt_set_mup();
1444
        gen_op_iwmmxt_set_cup();
1445
        break;
1446
    case 0x116: case 0x316: case 0x516: case 0x716:        /* WMIN */
1447
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
1448
        wrd = (insn >> 12) & 0xf;
1449
        rd0 = (insn >> 16) & 0xf;
1450
        rd1 = (insn >> 0) & 0xf;
1451
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1452
        switch ((insn >> 22) & 3) {
1453
        case 0:
1454
            if (insn & (1 << 21))
1455
                gen_op_iwmmxt_minsb_M0_wRn(rd1);
1456
            else
1457
                gen_op_iwmmxt_minub_M0_wRn(rd1);
1458
            break;
1459
        case 1:
1460
            if (insn & (1 << 21))
1461
                gen_op_iwmmxt_minsw_M0_wRn(rd1);
1462
            else
1463
                gen_op_iwmmxt_minuw_M0_wRn(rd1);
1464
            break;
1465
        case 2:
1466
            if (insn & (1 << 21))
1467
                gen_op_iwmmxt_minsl_M0_wRn(rd1);
1468
            else
1469
                gen_op_iwmmxt_minul_M0_wRn(rd1);
1470
            break;
1471
        case 3:
1472
            return 1;
1473
        }
1474
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1475
        gen_op_iwmmxt_set_mup();
1476
        break;
1477
    case 0x016: case 0x216: case 0x416: case 0x616:        /* WMAX */
1478
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
1479
        wrd = (insn >> 12) & 0xf;
1480
        rd0 = (insn >> 16) & 0xf;
1481
        rd1 = (insn >> 0) & 0xf;
1482
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1483
        switch ((insn >> 22) & 3) {
1484
        case 0:
1485
            if (insn & (1 << 21))
1486
                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
1487
            else
1488
                gen_op_iwmmxt_maxub_M0_wRn(rd1);
1489
            break;
1490
        case 1:
1491
            if (insn & (1 << 21))
1492
                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
1493
            else
1494
                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
1495
            break;
1496
        case 2:
1497
            if (insn & (1 << 21))
1498
                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
1499
            else
1500
                gen_op_iwmmxt_maxul_M0_wRn(rd1);
1501
            break;
1502
        case 3:
1503
            return 1;
1504
        }
1505
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1506
        gen_op_iwmmxt_set_mup();
1507
        break;
1508
    case 0x002: case 0x102: case 0x202: case 0x302:        /* WALIGNI */
1509
    case 0x402: case 0x502: case 0x602: case 0x702:
1510
        wrd = (insn >> 12) & 0xf;
1511
        rd0 = (insn >> 16) & 0xf;
1512
        rd1 = (insn >> 0) & 0xf;
1513
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1514
        gen_op_movl_T0_im((insn >> 20) & 3);
1515
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1516
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1517
        gen_op_iwmmxt_set_mup();
1518
        break;
1519
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:        /* WSUB */
1520
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
1521
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
1522
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
1523
        wrd = (insn >> 12) & 0xf;
1524
        rd0 = (insn >> 16) & 0xf;
1525
        rd1 = (insn >> 0) & 0xf;
1526
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1527
        switch ((insn >> 20) & 0xf) {
1528
        case 0x0:
1529
            gen_op_iwmmxt_subnb_M0_wRn(rd1);
1530
            break;
1531
        case 0x1:
1532
            gen_op_iwmmxt_subub_M0_wRn(rd1);
1533
            break;
1534
        case 0x3:
1535
            gen_op_iwmmxt_subsb_M0_wRn(rd1);
1536
            break;
1537
        case 0x4:
1538
            gen_op_iwmmxt_subnw_M0_wRn(rd1);
1539
            break;
1540
        case 0x5:
1541
            gen_op_iwmmxt_subuw_M0_wRn(rd1);
1542
            break;
1543
        case 0x7:
1544
            gen_op_iwmmxt_subsw_M0_wRn(rd1);
1545
            break;
1546
        case 0x8:
1547
            gen_op_iwmmxt_subnl_M0_wRn(rd1);
1548
            break;
1549
        case 0x9:
1550
            gen_op_iwmmxt_subul_M0_wRn(rd1);
1551
            break;
1552
        case 0xb:
1553
            gen_op_iwmmxt_subsl_M0_wRn(rd1);
1554
            break;
1555
        default:
1556
            return 1;
1557
        }
1558
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1559
        gen_op_iwmmxt_set_mup();
1560
        gen_op_iwmmxt_set_cup();
1561
        break;
1562
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:        /* WSHUFH */
1563
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
1564
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
1565
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
1566
        wrd = (insn >> 12) & 0xf;
1567
        rd0 = (insn >> 16) & 0xf;
1568
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1569
        gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
1570
        gen_op_iwmmxt_shufh_M0_T0();
1571
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1572
        gen_op_iwmmxt_set_mup();
1573
        gen_op_iwmmxt_set_cup();
1574
        break;
1575
    case 0x018: case 0x118: case 0x218: case 0x318:        /* WADD */
1576
    case 0x418: case 0x518: case 0x618: case 0x718:
1577
    case 0x818: case 0x918: case 0xa18: case 0xb18:
1578
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
1579
        wrd = (insn >> 12) & 0xf;
1580
        rd0 = (insn >> 16) & 0xf;
1581
        rd1 = (insn >> 0) & 0xf;
1582
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1583
        switch ((insn >> 20) & 0xf) {
1584
        case 0x0:
1585
            gen_op_iwmmxt_addnb_M0_wRn(rd1);
1586
            break;
1587
        case 0x1:
1588
            gen_op_iwmmxt_addub_M0_wRn(rd1);
1589
            break;
1590
        case 0x3:
1591
            gen_op_iwmmxt_addsb_M0_wRn(rd1);
1592
            break;
1593
        case 0x4:
1594
            gen_op_iwmmxt_addnw_M0_wRn(rd1);
1595
            break;
1596
        case 0x5:
1597
            gen_op_iwmmxt_adduw_M0_wRn(rd1);
1598
            break;
1599
        case 0x7:
1600
            gen_op_iwmmxt_addsw_M0_wRn(rd1);
1601
            break;
1602
        case 0x8:
1603
            gen_op_iwmmxt_addnl_M0_wRn(rd1);
1604
            break;
1605
        case 0x9:
1606
            gen_op_iwmmxt_addul_M0_wRn(rd1);
1607
            break;
1608
        case 0xb:
1609
            gen_op_iwmmxt_addsl_M0_wRn(rd1);
1610
            break;
1611
        default:
1612
            return 1;
1613
        }
1614
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1615
        gen_op_iwmmxt_set_mup();
1616
        gen_op_iwmmxt_set_cup();
1617
        break;
1618
    case 0x008: case 0x108: case 0x208: case 0x308:        /* WPACK */
1619
    case 0x408: case 0x508: case 0x608: case 0x708:
1620
    case 0x808: case 0x908: case 0xa08: case 0xb08:
1621
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
1622
        wrd = (insn >> 12) & 0xf;
1623
        rd0 = (insn >> 16) & 0xf;
1624
        rd1 = (insn >> 0) & 0xf;
1625
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1626
        if (!(insn & (1 << 20)))
1627
            return 1;
1628
        switch ((insn >> 22) & 3) {
1629
        case 0:
1630
            return 1;
1631
        case 1:
1632
            if (insn & (1 << 21))
1633
                gen_op_iwmmxt_packsw_M0_wRn(rd1);
1634
            else
1635
                gen_op_iwmmxt_packuw_M0_wRn(rd1);
1636
            break;
1637
        case 2:
1638
            if (insn & (1 << 21))
1639
                gen_op_iwmmxt_packsl_M0_wRn(rd1);
1640
            else
1641
                gen_op_iwmmxt_packul_M0_wRn(rd1);
1642
            break;
1643
        case 3:
1644
            if (insn & (1 << 21))
1645
                gen_op_iwmmxt_packsq_M0_wRn(rd1);
1646
            else
1647
                gen_op_iwmmxt_packuq_M0_wRn(rd1);
1648
            break;
1649
        }
1650
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1651
        gen_op_iwmmxt_set_mup();
1652
        gen_op_iwmmxt_set_cup();
1653
        break;
1654
    case 0x201: case 0x203: case 0x205: case 0x207:
1655
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
1656
    case 0x211: case 0x213: case 0x215: case 0x217:
1657
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
1658
        wrd = (insn >> 5) & 0xf;
1659
        rd0 = (insn >> 12) & 0xf;
1660
        rd1 = (insn >> 0) & 0xf;
1661
        if (rd0 == 0xf || rd1 == 0xf)
1662
            return 1;
1663
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1664
        switch ((insn >> 16) & 0xf) {
1665
        case 0x0:                                        /* TMIA */
1666
            gen_movl_T0_reg(s, rd0);
1667
            gen_movl_T1_reg(s, rd1);
1668
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
1669
            break;
1670
        case 0x8:                                        /* TMIAPH */
1671
            gen_movl_T0_reg(s, rd0);
1672
            gen_movl_T1_reg(s, rd1);
1673
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
1674
            break;
1675
        case 0xc: case 0xd: case 0xe: case 0xf:                /* TMIAxy */
1676
            gen_movl_T1_reg(s, rd0);
1677
            if (insn & (1 << 16))
1678
                gen_op_shrl_T1_im(16);
1679
            gen_op_movl_T0_T1();
1680
            gen_movl_T1_reg(s, rd1);
1681
            if (insn & (1 << 17))
1682
                gen_op_shrl_T1_im(16);
1683
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
1684
            break;
1685
        default:
1686
            return 1;
1687
        }
1688
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1689
        gen_op_iwmmxt_set_mup();
1690
        break;
1691
    default:
1692
        return 1;
1693
    }
1694

    
1695
    return 0;
1696
}
1697

    
1698
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
1699
   (ie. an undefined instruction).  */
1700
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1701
{
1702
    int acc, rd0, rd1, rdhi, rdlo;
1703

    
1704
    if ((insn & 0x0ff00f10) == 0x0e200010) {
1705
        /* Multiply with Internal Accumulate Format */
1706
        rd0 = (insn >> 12) & 0xf;
1707
        rd1 = insn & 0xf;
1708
        acc = (insn >> 5) & 7;
1709

    
1710
        if (acc != 0)
1711
            return 1;
1712

    
1713
        switch ((insn >> 16) & 0xf) {
1714
        case 0x0:                                        /* MIA */
1715
            gen_movl_T0_reg(s, rd0);
1716
            gen_movl_T1_reg(s, rd1);
1717
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
1718
            break;
1719
        case 0x8:                                        /* MIAPH */
1720
            gen_movl_T0_reg(s, rd0);
1721
            gen_movl_T1_reg(s, rd1);
1722
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
1723
            break;
1724
        case 0xc:                                        /* MIABB */
1725
        case 0xd:                                        /* MIABT */
1726
        case 0xe:                                        /* MIATB */
1727
        case 0xf:                                        /* MIATT */
1728
            gen_movl_T1_reg(s, rd0);
1729
            if (insn & (1 << 16))
1730
                gen_op_shrl_T1_im(16);
1731
            gen_op_movl_T0_T1();
1732
            gen_movl_T1_reg(s, rd1);
1733
            if (insn & (1 << 17))
1734
                gen_op_shrl_T1_im(16);
1735
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
1736
            break;
1737
        default:
1738
            return 1;
1739
        }
1740

    
1741
        gen_op_iwmmxt_movq_wRn_M0(acc);
1742
        return 0;
1743
    }
1744

    
1745
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
1746
        /* Internal Accumulator Access Format */
1747
        rdhi = (insn >> 16) & 0xf;
1748
        rdlo = (insn >> 12) & 0xf;
1749
        acc = insn & 7;
1750

    
1751
        if (acc != 0)
1752
            return 1;
1753

    
1754
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
1755
            gen_op_iwmmxt_movl_T0_T1_wRn(acc);
1756
            gen_movl_reg_T0(s, rdlo);
1757
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
1758
            gen_op_andl_T0_T1();
1759
            gen_movl_reg_T0(s, rdhi);
1760
        } else {                                        /* MAR */
1761
            gen_movl_T0_reg(s, rdlo);
1762
            gen_movl_T1_reg(s, rdhi);
1763
            gen_op_iwmmxt_movl_wRn_T0_T1(acc);
1764
        }
1765
        return 0;
1766
    }
1767

    
1768
    return 1;
1769
}
1770

    
1771
/* Disassemble system coprocessor instruction.  Return nonzero if
1772
   instruction is not defined.  */
1773
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1774
{
1775
    uint32_t rd = (insn >> 12) & 0xf;
1776
    uint32_t cp = (insn >> 8) & 0xf;
1777
    if (IS_USER(s)) {
1778
        return 1;
1779
    }
1780

    
1781
    if (insn & ARM_CP_RW_BIT) {
1782
        if (!env->cp[cp].cp_read)
1783
            return 1;
1784
        gen_op_movl_T0_im((uint32_t) s->pc);
1785
        gen_set_pc_T0();
1786
        gen_op_movl_T0_cp(insn);
1787
        gen_movl_reg_T0(s, rd);
1788
    } else {
1789
        if (!env->cp[cp].cp_write)
1790
            return 1;
1791
        gen_op_movl_T0_im((uint32_t) s->pc);
1792
        gen_set_pc_T0();
1793
        gen_movl_T0_reg(s, rd);
1794
        gen_op_movl_cp_T0(insn);
1795
    }
1796
    return 0;
1797
}
1798

    
1799
static int cp15_user_ok(uint32_t insn)
1800
{
1801
    int cpn = (insn >> 16) & 0xf;
1802
    int cpm = insn & 0xf;
1803
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
1804

    
1805
    if (cpn == 13 && cpm == 0) {
1806
        /* TLS register.  */
1807
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
1808
            return 1;
1809
    }
1810
    if (cpn == 7) {
1811
        /* ISB, DSB, DMB.  */
1812
        if ((cpm == 5 && op == 4)
1813
                || (cpm == 10 && (op == 4 || op == 5)))
1814
            return 1;
1815
    }
1816
    return 0;
1817
}
1818

    
1819
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
1820
   instruction is not defined.  */
1821
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
1822
{
1823
    uint32_t rd;
1824

    
1825
    /* M profile cores use memory mapped registers instead of cp15.  */
1826
    if (arm_feature(env, ARM_FEATURE_M))
1827
        return 1;
1828

    
1829
    if ((insn & (1 << 25)) == 0) {
1830
        if (insn & (1 << 20)) {
1831
            /* mrrc */
1832
            return 1;
1833
        }
1834
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
1835
        return 0;
1836
    }
1837
    if ((insn & (1 << 4)) == 0) {
1838
        /* cdp */
1839
        return 1;
1840
    }
1841
    if (IS_USER(s) && !cp15_user_ok(insn)) {
1842
        return 1;
1843
    }
1844
    if ((insn & 0x0fff0fff) == 0x0e070f90
1845
        || (insn & 0x0fff0fff) == 0x0e070f58) {
1846
        /* Wait for interrupt.  */
1847
        gen_op_movl_T0_im((long)s->pc);
1848
        gen_set_pc_T0();
1849
        s->is_jmp = DISAS_WFI;
1850
        return 0;
1851
    }
1852
    rd = (insn >> 12) & 0xf;
1853
    if (insn & ARM_CP_RW_BIT) {
1854
        gen_op_movl_T0_cp15(insn);
1855
        /* If the destination register is r15 then sets condition codes.  */
1856
        if (rd != 15)
1857
            gen_movl_reg_T0(s, rd);
1858
    } else {
1859
        gen_movl_T0_reg(s, rd);
1860
        gen_op_movl_cp15_T0(insn);
1861
        /* Normally we would always end the TB here, but Linux
1862
         * arch/arm/mach-pxa/sleep.S expects two instructions following
1863
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
1864
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
1865
                (insn & 0x0fff0fff) != 0x0e010f10)
1866
            gen_lookup_tb(s);
1867
    }
1868
    return 0;
1869
}
1870

    
1871
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
1872
#define VFP_SREG(insn, bigbit, smallbit) \
1873
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
1874
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
1875
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
1876
        reg = (((insn) >> (bigbit)) & 0x0f) \
1877
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
1878
    } else { \
1879
        if (insn & (1 << (smallbit))) \
1880
            return 1; \
1881
        reg = ((insn) >> (bigbit)) & 0x0f; \
1882
    }} while (0)
1883

    
1884
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
1885
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
1886
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
1887
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
1888
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
1889
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
1890

    
1891
static inline int
1892
vfp_enabled(CPUState * env)
1893
{
1894
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
1895
}
1896

    
1897
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
1898
   (ie. an undefined instruction).  */
1899
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
1900
{
1901
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
1902
    int dp, veclen;
1903

    
1904
    if (!arm_feature(env, ARM_FEATURE_VFP))
1905
        return 1;
1906

    
1907
    if (!vfp_enabled(env)) {
1908
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
1909
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
1910
            return 1;
1911
        rn = (insn >> 16) & 0xf;
1912
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
1913
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
1914
            return 1;
1915
    }
1916
    dp = ((insn & 0xf00) == 0xb00);
1917
    switch ((insn >> 24) & 0xf) {
1918
    case 0xe:
1919
        if (insn & (1 << 4)) {
1920
            /* single register transfer */
1921
            rd = (insn >> 12) & 0xf;
1922
            if (dp) {
1923
                int size;
1924
                int pass;
1925

    
1926
                VFP_DREG_N(rn, insn);
1927
                if (insn & 0xf)
1928
                    return 1;
1929
                if (insn & 0x00c00060
1930
                    && !arm_feature(env, ARM_FEATURE_NEON))
1931
                    return 1;
1932

    
1933
                pass = (insn >> 21) & 1;
1934
                if (insn & (1 << 22)) {
1935
                    size = 0;
1936
                    offset = ((insn >> 5) & 3) * 8;
1937
                } else if (insn & (1 << 5)) {
1938
                    size = 1;
1939
                    offset = (insn & (1 << 6)) ? 16 : 0;
1940
                } else {
1941
                    size = 2;
1942
                    offset = 0;
1943
                }
1944
                if (insn & ARM_CP_RW_BIT) {
1945
                    /* vfp->arm */
1946
                    switch (size) {
1947
                    case 0:
1948
                        NEON_GET_REG(T1, rn, pass);
1949
                        if (offset)
1950
                            gen_op_shrl_T1_im(offset);
1951
                        if (insn & (1 << 23))
1952
                            gen_uxtb(cpu_T[1]);
1953
                        else
1954
                            gen_sxtb(cpu_T[1]);
1955
                        break;
1956
                    case 1:
1957
                        NEON_GET_REG(T1, rn, pass);
1958
                        if (insn & (1 << 23)) {
1959
                            if (offset) {
1960
                                gen_op_shrl_T1_im(16);
1961
                            } else {
1962
                                gen_uxth(cpu_T[1]);
1963
                            }
1964
                        } else {
1965
                            if (offset) {
1966
                                gen_op_sarl_T1_im(16);
1967
                            } else {
1968
                                gen_sxth(cpu_T[1]);
1969
                            }
1970
                        }
1971
                        break;
1972
                    case 2:
1973
                        NEON_GET_REG(T1, rn, pass);
1974
                        break;
1975
                    }
1976
                    gen_movl_reg_T1(s, rd);
1977
                } else {
1978
                    /* arm->vfp */
1979
                    gen_movl_T0_reg(s, rd);
1980
                    if (insn & (1 << 23)) {
1981
                        /* VDUP */
1982
                        if (size == 0) {
1983
                            gen_op_neon_dup_u8(0);
1984
                        } else if (size == 1) {
1985
                            gen_op_neon_dup_low16();
1986
                        }
1987
                        NEON_SET_REG(T0, rn, 0);
1988
                        NEON_SET_REG(T0, rn, 1);
1989
                    } else {
1990
                        /* VMOV */
1991
                        switch (size) {
1992
                        case 0:
1993
                            NEON_GET_REG(T2, rn, pass);
1994
                            gen_op_movl_T1_im(0xff);
1995
                            gen_op_andl_T0_T1();
1996
                            gen_op_neon_insert_elt(offset, ~(0xff << offset));
1997
                            NEON_SET_REG(T2, rn, pass);
1998
                            break;
1999
                        case 1:
2000
                            NEON_GET_REG(T2, rn, pass);
2001
                            gen_op_movl_T1_im(0xffff);
2002
                            gen_op_andl_T0_T1();
2003
                            bank_mask = offset ? 0xffff : 0xffff0000;
2004
                            gen_op_neon_insert_elt(offset, bank_mask);
2005
                            NEON_SET_REG(T2, rn, pass);
2006
                            break;
2007
                        case 2:
2008
                            NEON_SET_REG(T0, rn, pass);
2009
                            break;
2010
                        }
2011
                    }
2012
                }
2013
            } else { /* !dp */
2014
                if ((insn & 0x6f) != 0x00)
2015
                    return 1;
2016
                rn = VFP_SREG_N(insn);
2017
                if (insn & ARM_CP_RW_BIT) {
2018
                    /* vfp->arm */
2019
                    if (insn & (1 << 21)) {
2020
                        /* system register */
2021
                        rn >>= 1;
2022

    
2023
                        switch (rn) {
2024
                        case ARM_VFP_FPSID:
2025
                            /* VFP2 allows access for FSID from userspace.
2026
                               VFP3 restricts all id registers to privileged
2027
                               accesses.  */
2028
                            if (IS_USER(s)
2029
                                && arm_feature(env, ARM_FEATURE_VFP3))
2030
                                return 1;
2031
                            gen_op_vfp_movl_T0_xreg(rn);
2032
                            break;
2033
                        case ARM_VFP_FPEXC:
2034
                            if (IS_USER(s))
2035
                                return 1;
2036
                            gen_op_vfp_movl_T0_xreg(rn);
2037
                            break;
2038
                        case ARM_VFP_FPINST:
2039
                        case ARM_VFP_FPINST2:
2040
                            /* Not present in VFP3.  */
2041
                            if (IS_USER(s)
2042
                                || arm_feature(env, ARM_FEATURE_VFP3))
2043
                                return 1;
2044
                            gen_op_vfp_movl_T0_xreg(rn);
2045
                            break;
2046
                        case ARM_VFP_FPSCR:
2047
                            if (rd == 15)
2048
                                gen_op_vfp_movl_T0_fpscr_flags();
2049
                            else
2050
                                gen_op_vfp_movl_T0_fpscr();
2051
                            break;
2052
                        case ARM_VFP_MVFR0:
2053
                        case ARM_VFP_MVFR1:
2054
                            if (IS_USER(s)
2055
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2056
                                return 1;
2057
                            gen_op_vfp_movl_T0_xreg(rn);
2058
                            break;
2059
                        default:
2060
                            return 1;
2061
                        }
2062
                    } else {
2063
                        gen_mov_F0_vreg(0, rn);
2064
                        gen_op_vfp_mrs();
2065
                    }
2066
                    if (rd == 15) {
2067
                        /* Set the 4 flag bits in the CPSR.  */
2068
                        gen_op_movl_cpsr_T0(0xf0000000);
2069
                    } else
2070
                        gen_movl_reg_T0(s, rd);
2071
                } else {
2072
                    /* arm->vfp */
2073
                    gen_movl_T0_reg(s, rd);
2074
                    if (insn & (1 << 21)) {
2075
                        rn >>= 1;
2076
                        /* system register */
2077
                        switch (rn) {
2078
                        case ARM_VFP_FPSID:
2079
                        case ARM_VFP_MVFR0:
2080
                        case ARM_VFP_MVFR1:
2081
                            /* Writes are ignored.  */
2082
                            break;
2083
                        case ARM_VFP_FPSCR:
2084
                            gen_op_vfp_movl_fpscr_T0();
2085
                            gen_lookup_tb(s);
2086
                            break;
2087
                        case ARM_VFP_FPEXC:
2088
                            if (IS_USER(s))
2089
                                return 1;
2090
                            gen_op_vfp_movl_xreg_T0(rn);
2091
                            gen_lookup_tb(s);
2092
                            break;
2093
                        case ARM_VFP_FPINST:
2094
                        case ARM_VFP_FPINST2:
2095
                            gen_op_vfp_movl_xreg_T0(rn);
2096
                            break;
2097
                        default:
2098
                            return 1;
2099
                        }
2100
                    } else {
2101
                        gen_op_vfp_msr();
2102
                        gen_mov_vreg_F0(0, rn);
2103
                    }
2104
                }
2105
            }
2106
        } else {
2107
            /* data processing */
2108
            /* The opcode is in bits 23, 21, 20 and 6.  */
2109
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2110
            if (dp) {
2111
                if (op == 15) {
2112
                    /* rn is opcode */
2113
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2114
                } else {
2115
                    /* rn is register number */
2116
                    VFP_DREG_N(rn, insn);
2117
                }
2118

    
2119
                if (op == 15 && (rn == 15 || rn > 17)) {
2120
                    /* Integer or single precision destination.  */
2121
                    rd = VFP_SREG_D(insn);
2122
                } else {
2123
                    VFP_DREG_D(rd, insn);
2124
                }
2125

    
2126
                if (op == 15 && (rn == 16 || rn == 17)) {
2127
                    /* Integer source.  */
2128
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2129
                } else {
2130
                    VFP_DREG_M(rm, insn);
2131
                }
2132
            } else {
2133
                rn = VFP_SREG_N(insn);
2134
                if (op == 15 && rn == 15) {
2135
                    /* Double precision destination.  */
2136
                    VFP_DREG_D(rd, insn);
2137
                } else {
2138
                    rd = VFP_SREG_D(insn);
2139
                }
2140
                rm = VFP_SREG_M(insn);
2141
            }
2142

    
2143
            veclen = env->vfp.vec_len;
2144
            if (op == 15 && rn > 3)
2145
                veclen = 0;
2146

    
2147
            /* Shut up compiler warnings.  */
2148
            delta_m = 0;
2149
            delta_d = 0;
2150
            bank_mask = 0;
2151

    
2152
            if (veclen > 0) {
2153
                if (dp)
2154
                    bank_mask = 0xc;
2155
                else
2156
                    bank_mask = 0x18;
2157

    
2158
                /* Figure out what type of vector operation this is.  */
2159
                if ((rd & bank_mask) == 0) {
2160
                    /* scalar */
2161
                    veclen = 0;
2162
                } else {
2163
                    if (dp)
2164
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
2165
                    else
2166
                        delta_d = env->vfp.vec_stride + 1;
2167

    
2168
                    if ((rm & bank_mask) == 0) {
2169
                        /* mixed scalar/vector */
2170
                        delta_m = 0;
2171
                    } else {
2172
                        /* vector */
2173
                        delta_m = delta_d;
2174
                    }
2175
                }
2176
            }
2177

    
2178
            /* Load the initial operands.  */
2179
            if (op == 15) {
2180
                switch (rn) {
2181
                case 16:
2182
                case 17:
2183
                    /* Integer source */
2184
                    gen_mov_F0_vreg(0, rm);
2185
                    break;
2186
                case 8:
2187
                case 9:
2188
                    /* Compare */
2189
                    gen_mov_F0_vreg(dp, rd);
2190
                    gen_mov_F1_vreg(dp, rm);
2191
                    break;
2192
                case 10:
2193
                case 11:
2194
                    /* Compare with zero */
2195
                    gen_mov_F0_vreg(dp, rd);
2196
                    gen_vfp_F1_ld0(dp);
2197
                    break;
2198
                case 20:
2199
                case 21:
2200
                case 22:
2201
                case 23:
2202
                    /* Source and destination the same.  */
2203
                    gen_mov_F0_vreg(dp, rd);
2204
                    break;
2205
                default:
2206
                    /* One source operand.  */
2207
                    gen_mov_F0_vreg(dp, rm);
2208
                    break;
2209
                }
2210
            } else {
2211
                /* Two source operands.  */
2212
                gen_mov_F0_vreg(dp, rn);
2213
                gen_mov_F1_vreg(dp, rm);
2214
            }
2215

    
2216
            for (;;) {
2217
                /* Perform the calculation.  */
2218
                switch (op) {
2219
                case 0: /* mac: fd + (fn * fm) */
2220
                    gen_vfp_mul(dp);
2221
                    gen_mov_F1_vreg(dp, rd);
2222
                    gen_vfp_add(dp);
2223
                    break;
2224
                case 1: /* nmac: fd - (fn * fm) */
2225
                    gen_vfp_mul(dp);
2226
                    gen_vfp_neg(dp);
2227
                    gen_mov_F1_vreg(dp, rd);
2228
                    gen_vfp_add(dp);
2229
                    break;
2230
                case 2: /* msc: -fd + (fn * fm) */
2231
                    gen_vfp_mul(dp);
2232
                    gen_mov_F1_vreg(dp, rd);
2233
                    gen_vfp_sub(dp);
2234
                    break;
2235
                case 3: /* nmsc: -fd - (fn * fm)  */
2236
                    gen_vfp_mul(dp);
2237
                    gen_mov_F1_vreg(dp, rd);
2238
                    gen_vfp_add(dp);
2239
                    gen_vfp_neg(dp);
2240
                    break;
2241
                case 4: /* mul: fn * fm */
2242
                    gen_vfp_mul(dp);
2243
                    break;
2244
                case 5: /* nmul: -(fn * fm) */
2245
                    gen_vfp_mul(dp);
2246
                    gen_vfp_neg(dp);
2247
                    break;
2248
                case 6: /* add: fn + fm */
2249
                    gen_vfp_add(dp);
2250
                    break;
2251
                case 7: /* sub: fn - fm */
2252
                    gen_vfp_sub(dp);
2253
                    break;
2254
                case 8: /* div: fn / fm */
2255
                    gen_vfp_div(dp);
2256
                    break;
2257
                case 14: /* fconst */
2258
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
2259
                      return 1;
2260

    
2261
                    n = (insn << 12) & 0x80000000;
2262
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
2263
                    if (dp) {
2264
                        if (i & 0x40)
2265
                            i |= 0x3f80;
2266
                        else
2267
                            i |= 0x4000;
2268
                        n |= i << 16;
2269
                    } else {
2270
                        if (i & 0x40)
2271
                            i |= 0x780;
2272
                        else
2273
                            i |= 0x800;
2274
                        n |= i << 19;
2275
                    }
2276
                    gen_vfp_fconst(dp, n);
2277
                    break;
2278
                case 15: /* extension space */
2279
                    switch (rn) {
2280
                    case 0: /* cpy */
2281
                        /* no-op */
2282
                        break;
2283
                    case 1: /* abs */
2284
                        gen_vfp_abs(dp);
2285
                        break;
2286
                    case 2: /* neg */
2287
                        gen_vfp_neg(dp);
2288
                        break;
2289
                    case 3: /* sqrt */
2290
                        gen_vfp_sqrt(dp);
2291
                        break;
2292
                    case 8: /* cmp */
2293
                        gen_vfp_cmp(dp);
2294
                        break;
2295
                    case 9: /* cmpe */
2296
                        gen_vfp_cmpe(dp);
2297
                        break;
2298
                    case 10: /* cmpz */
2299
                        gen_vfp_cmp(dp);
2300
                        break;
2301
                    case 11: /* cmpez */
2302
                        gen_vfp_F1_ld0(dp);
2303
                        gen_vfp_cmpe(dp);
2304
                        break;
2305
                    case 15: /* single<->double conversion */
2306
                        if (dp)
2307
                            gen_op_vfp_fcvtsd();
2308
                        else
2309
                            gen_op_vfp_fcvtds();
2310
                        break;
2311
                    case 16: /* fuito */
2312
                        gen_vfp_uito(dp);
2313
                        break;
2314
                    case 17: /* fsito */
2315
                        gen_vfp_sito(dp);
2316
                        break;
2317
                    case 20: /* fshto */
2318
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2319
                          return 1;
2320
                        gen_vfp_shto(dp, rm);
2321
                        break;
2322
                    case 21: /* fslto */
2323
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2324
                          return 1;
2325
                        gen_vfp_slto(dp, rm);
2326
                        break;
2327
                    case 22: /* fuhto */
2328
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2329
                          return 1;
2330
                        gen_vfp_uhto(dp, rm);
2331
                        break;
2332
                    case 23: /* fulto */
2333
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2334
                          return 1;
2335
                        gen_vfp_ulto(dp, rm);
2336
                        break;
2337
                    case 24: /* ftoui */
2338
                        gen_vfp_toui(dp);
2339
                        break;
2340
                    case 25: /* ftouiz */
2341
                        gen_vfp_touiz(dp);
2342
                        break;
2343
                    case 26: /* ftosi */
2344
                        gen_vfp_tosi(dp);
2345
                        break;
2346
                    case 27: /* ftosiz */
2347
                        gen_vfp_tosiz(dp);
2348
                        break;
2349
                    case 28: /* ftosh */
2350
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2351
                          return 1;
2352
                        gen_vfp_tosh(dp, rm);
2353
                        break;
2354
                    case 29: /* ftosl */
2355
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2356
                          return 1;
2357
                        gen_vfp_tosl(dp, rm);
2358
                        break;
2359
                    case 30: /* ftouh */
2360
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2361
                          return 1;
2362
                        gen_vfp_touh(dp, rm);
2363
                        break;
2364
                    case 31: /* ftoul */
2365
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2366
                          return 1;
2367
                        gen_vfp_toul(dp, rm);
2368
                        break;
2369
                    default: /* undefined */
2370
                        printf ("rn:%d\n", rn);
2371
                        return 1;
2372
                    }
2373
                    break;
2374
                default: /* undefined */
2375
                    printf ("op:%d\n", op);
2376
                    return 1;
2377
                }
2378

    
2379
                /* Write back the result.  */
2380
                if (op == 15 && (rn >= 8 && rn <= 11))
2381
                    ; /* Comparison, do nothing.  */
2382
                else if (op == 15 && rn > 17)
2383
                    /* Integer result.  */
2384
                    gen_mov_vreg_F0(0, rd);
2385
                else if (op == 15 && rn == 15)
2386
                    /* conversion */
2387
                    gen_mov_vreg_F0(!dp, rd);
2388
                else
2389
                    gen_mov_vreg_F0(dp, rd);
2390

    
2391
                /* break out of the loop if we have finished  */
2392
                if (veclen == 0)
2393
                    break;
2394

    
2395
                if (op == 15 && delta_m == 0) {
2396
                    /* single source one-many */
2397
                    while (veclen--) {
2398
                        rd = ((rd + delta_d) & (bank_mask - 1))
2399
                             | (rd & bank_mask);
2400
                        gen_mov_vreg_F0(dp, rd);
2401
                    }
2402
                    break;
2403
                }
2404
                /* Setup the next operands.  */
2405
                veclen--;
2406
                rd = ((rd + delta_d) & (bank_mask - 1))
2407
                     | (rd & bank_mask);
2408

    
2409
                if (op == 15) {
2410
                    /* One source operand.  */
2411
                    rm = ((rm + delta_m) & (bank_mask - 1))
2412
                         | (rm & bank_mask);
2413
                    gen_mov_F0_vreg(dp, rm);
2414
                } else {
2415
                    /* Two source operands.  */
2416
                    rn = ((rn + delta_d) & (bank_mask - 1))
2417
                         | (rn & bank_mask);
2418
                    gen_mov_F0_vreg(dp, rn);
2419
                    if (delta_m) {
2420
                        rm = ((rm + delta_m) & (bank_mask - 1))
2421
                             | (rm & bank_mask);
2422
                        gen_mov_F1_vreg(dp, rm);
2423
                    }
2424
                }
2425
            }
2426
        }
2427
        break;
2428
    case 0xc:
2429
    case 0xd:
2430
        if (dp && (insn & 0x03e00000) == 0x00400000) {
2431
            /* two-register transfer */
2432
            rn = (insn >> 16) & 0xf;
2433
            rd = (insn >> 12) & 0xf;
2434
            if (dp) {
2435
                VFP_DREG_M(rm, insn);
2436
            } else {
2437
                rm = VFP_SREG_M(insn);
2438
            }
2439

    
2440
            if (insn & ARM_CP_RW_BIT) {
2441
                /* vfp->arm */
2442
                if (dp) {
2443
                    gen_mov_F0_vreg(1, rm);
2444
                    gen_op_vfp_mrrd();
2445
                    gen_movl_reg_T0(s, rd);
2446
                    gen_movl_reg_T1(s, rn);
2447
                } else {
2448
                    gen_mov_F0_vreg(0, rm);
2449
                    gen_op_vfp_mrs();
2450
                    gen_movl_reg_T0(s, rn);
2451
                    gen_mov_F0_vreg(0, rm + 1);
2452
                    gen_op_vfp_mrs();
2453
                    gen_movl_reg_T0(s, rd);
2454
                }
2455
            } else {
2456
                /* arm->vfp */
2457
                if (dp) {
2458
                    gen_movl_T0_reg(s, rd);
2459
                    gen_movl_T1_reg(s, rn);
2460
                    gen_op_vfp_mdrr();
2461
                    gen_mov_vreg_F0(1, rm);
2462
                } else {
2463
                    gen_movl_T0_reg(s, rn);
2464
                    gen_op_vfp_msr();
2465
                    gen_mov_vreg_F0(0, rm);
2466
                    gen_movl_T0_reg(s, rd);
2467
                    gen_op_vfp_msr();
2468
                    gen_mov_vreg_F0(0, rm + 1);
2469
                }
2470
            }
2471
        } else {
2472
            /* Load/store */
2473
            rn = (insn >> 16) & 0xf;
2474
            if (dp)
2475
                VFP_DREG_D(rd, insn);
2476
            else
2477
                rd = VFP_SREG_D(insn);
2478
            if (s->thumb && rn == 15) {
2479
                gen_op_movl_T1_im(s->pc & ~2);
2480
            } else {
2481
                gen_movl_T1_reg(s, rn);
2482
            }
2483
            if ((insn & 0x01200000) == 0x01000000) {
2484
                /* Single load/store */
2485
                offset = (insn & 0xff) << 2;
2486
                if ((insn & (1 << 23)) == 0)
2487
                    offset = -offset;
2488
                gen_op_addl_T1_im(offset);
2489
                if (insn & (1 << 20)) {
2490
                    gen_vfp_ld(s, dp);
2491
                    gen_mov_vreg_F0(dp, rd);
2492
                } else {
2493
                    gen_mov_F0_vreg(dp, rd);
2494
                    gen_vfp_st(s, dp);
2495
                }
2496
            } else {
2497
                /* load/store multiple */
2498
                if (dp)
2499
                    n = (insn >> 1) & 0x7f;
2500
                else
2501
                    n = insn & 0xff;
2502

    
2503
                if (insn & (1 << 24)) /* pre-decrement */
2504
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
2505

    
2506
                if (dp)
2507
                    offset = 8;
2508
                else
2509
                    offset = 4;
2510
                for (i = 0; i < n; i++) {
2511
                    if (insn & ARM_CP_RW_BIT) {
2512
                        /* load */
2513
                        gen_vfp_ld(s, dp);
2514
                        gen_mov_vreg_F0(dp, rd + i);
2515
                    } else {
2516
                        /* store */
2517
                        gen_mov_F0_vreg(dp, rd + i);
2518
                        gen_vfp_st(s, dp);
2519
                    }
2520
                    gen_op_addl_T1_im(offset);
2521
                }
2522
                if (insn & (1 << 21)) {
2523
                    /* writeback */
2524
                    if (insn & (1 << 24))
2525
                        offset = -offset * n;
2526
                    else if (dp && (insn & 1))
2527
                        offset = 4;
2528
                    else
2529
                        offset = 0;
2530

    
2531
                    if (offset != 0)
2532
                        gen_op_addl_T1_im(offset);
2533
                    gen_movl_reg_T1(s, rn);
2534
                }
2535
            }
2536
        }
2537
        break;
2538
    default:
2539
        /* Should never happen.  */
2540
        return 1;
2541
    }
2542
    return 0;
2543
}
2544

    
2545
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
2546
{
2547
    TranslationBlock *tb;
2548

    
2549
    tb = s->tb;
2550
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2551
        tcg_gen_goto_tb(n);
2552
        gen_op_movl_T0_im(dest);
2553
        gen_set_pc_T0();
2554
        tcg_gen_exit_tb((long)tb + n);
2555
    } else {
2556
        gen_op_movl_T0_im(dest);
2557
        gen_set_pc_T0();
2558
        tcg_gen_exit_tb(0);
2559
    }
2560
}
2561

    
2562
static inline void gen_jmp (DisasContext *s, uint32_t dest)
2563
{
2564
    if (__builtin_expect(s->singlestep_enabled, 0)) {
2565
        /* An indirect jump so that we still trigger the debug exception.  */
2566
        if (s->thumb)
2567
          dest |= 1;
2568
        gen_op_movl_T0_im(dest);
2569
        gen_bx(s);
2570
    } else {
2571
        gen_goto_tb(s, 0, dest);
2572
        s->is_jmp = DISAS_TB_JUMP;
2573
    }
2574
}
2575

    
2576
static inline void gen_mulxy(int x, int y)
2577
{
2578
    if (x)
2579
        tcg_gen_sari_i32(cpu_T[0], cpu_T[0], 16);
2580
    else
2581
        gen_sxth(cpu_T[0]);
2582
    if (y)
2583
        gen_op_sarl_T1_im(16);
2584
    else
2585
        gen_sxth(cpu_T[1]);
2586
    gen_op_mul_T0_T1();
2587
}
2588

    
2589
/* Return the mask of PSR bits set by a MSR instruction.  */
2590
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
2591
    uint32_t mask;
2592

    
2593
    mask = 0;
2594
    if (flags & (1 << 0))
2595
        mask |= 0xff;
2596
    if (flags & (1 << 1))
2597
        mask |= 0xff00;
2598
    if (flags & (1 << 2))
2599
        mask |= 0xff0000;
2600
    if (flags & (1 << 3))
2601
        mask |= 0xff000000;
2602

    
2603
    /* Mask out undefined bits.  */
2604
    mask &= ~CPSR_RESERVED;
2605
    if (!arm_feature(env, ARM_FEATURE_V6))
2606
        mask &= ~(CPSR_E | CPSR_GE);
2607
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
2608
        mask &= ~CPSR_IT;
2609
    /* Mask out execution state bits.  */
2610
    if (!spsr)
2611
        mask &= ~CPSR_EXEC;
2612
    /* Mask out privileged bits.  */
2613
    if (IS_USER(s))
2614
        mask &= CPSR_USER;
2615
    return mask;
2616
}
2617

    
2618
/* Returns nonzero if access to the PSR is not permitted.  */
2619
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
2620
{
2621
    if (spsr) {
2622
        /* ??? This is also undefined in system mode.  */
2623
        if (IS_USER(s))
2624
            return 1;
2625
        gen_op_movl_spsr_T0(mask);
2626
    } else {
2627
        gen_op_movl_cpsr_T0(mask);
2628
    }
2629
    gen_lookup_tb(s);
2630
    return 0;
2631
}
2632

    
2633
/* Generate an old-style exception return.  */
2634
static void gen_exception_return(DisasContext *s)
2635
{
2636
    gen_set_pc_T0();
2637
    gen_op_movl_T0_spsr();
2638
    gen_op_movl_cpsr_T0(0xffffffff);
2639
    s->is_jmp = DISAS_UPDATE;
2640
}
2641

    
2642
/* Generate a v6 exception return.  */
2643
static void gen_rfe(DisasContext *s)
2644
{
2645
    gen_op_movl_cpsr_T0(0xffffffff);
2646
    gen_op_movl_T0_T2();
2647
    gen_set_pc_T0();
2648
    s->is_jmp = DISAS_UPDATE;
2649
}
2650

    
2651
static inline void
2652
gen_set_condexec (DisasContext *s)
2653
{
2654
    if (s->condexec_mask) {
2655
        gen_op_set_condexec((s->condexec_cond << 4) | (s->condexec_mask >> 1));
2656
    }
2657
}
2658

    
2659
static void gen_nop_hint(DisasContext *s, int val)
2660
{
2661
    switch (val) {
2662
    case 3: /* wfi */
2663
        gen_op_movl_T0_im((long)s->pc);
2664
        gen_set_pc_T0();
2665
        s->is_jmp = DISAS_WFI;
2666
        break;
2667
    case 2: /* wfe */
2668
    case 4: /* sev */
2669
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
2670
    default: /* nop */
2671
        break;
2672
    }
2673
}
2674

    
2675
/* Neon shift by constant.  The actual ops are the same as used for variable
2676
   shifts.  [OP][U][SIZE]  */
2677
static GenOpFunc *gen_neon_shift_im[8][2][4] = {
2678
    { /* 0 */ /* VSHR */
2679
      {
2680
        gen_op_neon_shl_u8,
2681
        gen_op_neon_shl_u16,
2682
        gen_op_neon_shl_u32,
2683
        gen_op_neon_shl_u64
2684
      }, {
2685
        gen_op_neon_shl_s8,
2686
        gen_op_neon_shl_s16,
2687
        gen_op_neon_shl_s32,
2688
        gen_op_neon_shl_s64
2689
      }
2690
    }, { /* 1 */ /* VSRA */
2691
      {
2692
        gen_op_neon_shl_u8,
2693
        gen_op_neon_shl_u16,
2694
        gen_op_neon_shl_u32,
2695
        gen_op_neon_shl_u64
2696
      }, {
2697
        gen_op_neon_shl_s8,
2698
        gen_op_neon_shl_s16,
2699
        gen_op_neon_shl_s32,
2700
        gen_op_neon_shl_s64
2701
      }
2702
    }, { /* 2 */ /* VRSHR */
2703
      {
2704
        gen_op_neon_rshl_u8,
2705
        gen_op_neon_rshl_u16,
2706
        gen_op_neon_rshl_u32,
2707
        gen_op_neon_rshl_u64
2708
      }, {
2709
        gen_op_neon_rshl_s8,
2710
        gen_op_neon_rshl_s16,
2711
        gen_op_neon_rshl_s32,
2712
        gen_op_neon_rshl_s64
2713
      }
2714
    }, { /* 3 */ /* VRSRA */
2715
      {
2716
        gen_op_neon_rshl_u8,
2717
        gen_op_neon_rshl_u16,
2718
        gen_op_neon_rshl_u32,
2719
        gen_op_neon_rshl_u64
2720
      }, {
2721
        gen_op_neon_rshl_s8,
2722
        gen_op_neon_rshl_s16,
2723
        gen_op_neon_rshl_s32,
2724
        gen_op_neon_rshl_s64
2725
      }
2726
    }, { /* 4 */
2727
      {
2728
        NULL, NULL, NULL, NULL
2729
      }, { /* VSRI */
2730
        gen_op_neon_shl_u8,
2731
        gen_op_neon_shl_u16,
2732
        gen_op_neon_shl_u32,
2733
        gen_op_neon_shl_u64,
2734
      }
2735
    }, { /* 5 */
2736
      { /* VSHL */
2737
        gen_op_neon_shl_u8,
2738
        gen_op_neon_shl_u16,
2739
        gen_op_neon_shl_u32,
2740
        gen_op_neon_shl_u64,
2741
      }, { /* VSLI */
2742
        gen_op_neon_shl_u8,
2743
        gen_op_neon_shl_u16,
2744
        gen_op_neon_shl_u32,
2745
        gen_op_neon_shl_u64,
2746
      }
2747
    }, { /* 6 */ /* VQSHL */
2748
      {
2749
        gen_op_neon_qshl_u8,
2750
        gen_op_neon_qshl_u16,
2751
        gen_op_neon_qshl_u32,
2752
        gen_op_neon_qshl_u64
2753
      }, {
2754
        gen_op_neon_qshl_s8,
2755
        gen_op_neon_qshl_s16,
2756
        gen_op_neon_qshl_s32,
2757
        gen_op_neon_qshl_s64
2758
      }
2759
    }, { /* 7 */ /* VQSHLU */
2760
      {
2761
        gen_op_neon_qshl_u8,
2762
        gen_op_neon_qshl_u16,
2763
        gen_op_neon_qshl_u32,
2764
        gen_op_neon_qshl_u64
2765
      }, {
2766
        gen_op_neon_qshl_u8,
2767
        gen_op_neon_qshl_u16,
2768
        gen_op_neon_qshl_u32,
2769
        gen_op_neon_qshl_u64
2770
      }
2771
    }
2772
};
2773

    
2774
/* [R][U][size - 1] */
2775
static GenOpFunc *gen_neon_shift_im_narrow[2][2][3] = {
2776
    {
2777
      {
2778
        gen_op_neon_shl_u16,
2779
        gen_op_neon_shl_u32,
2780
        gen_op_neon_shl_u64
2781
      }, {
2782
        gen_op_neon_shl_s16,
2783
        gen_op_neon_shl_s32,
2784
        gen_op_neon_shl_s64
2785
      }
2786
    }, {
2787
      {
2788
        gen_op_neon_rshl_u16,
2789
        gen_op_neon_rshl_u32,
2790
        gen_op_neon_rshl_u64
2791
      }, {
2792
        gen_op_neon_rshl_s16,
2793
        gen_op_neon_rshl_s32,
2794
        gen_op_neon_rshl_s64
2795
      }
2796
    }
2797
};
2798

    
2799
static inline void
2800
gen_op_neon_narrow_u32 ()
2801
{
2802
    /* No-op.  */
2803
}
2804

    
2805
static GenOpFunc *gen_neon_narrow[3] = {
2806
    gen_op_neon_narrow_u8,
2807
    gen_op_neon_narrow_u16,
2808
    gen_op_neon_narrow_u32
2809
};
2810

    
2811
static GenOpFunc *gen_neon_narrow_satu[3] = {
2812
    gen_op_neon_narrow_sat_u8,
2813
    gen_op_neon_narrow_sat_u16,
2814
    gen_op_neon_narrow_sat_u32
2815
};
2816

    
2817
static GenOpFunc *gen_neon_narrow_sats[3] = {
2818
    gen_op_neon_narrow_sat_s8,
2819
    gen_op_neon_narrow_sat_s16,
2820
    gen_op_neon_narrow_sat_s32
2821
};
2822

    
2823
static inline int gen_neon_add(int size)
2824
{
2825
    switch (size) {
2826
    case 0: gen_op_neon_add_u8(); break;
2827
    case 1: gen_op_neon_add_u16(); break;
2828
    case 2: gen_op_addl_T0_T1(); break;
2829
    default: return 1;
2830
    }
2831
    return 0;
2832
}
2833

    
2834
/* 32-bit pairwise ops end up the same as the elementsise versions.  */
2835
#define gen_op_neon_pmax_s32  gen_op_neon_max_s32
2836
#define gen_op_neon_pmax_u32  gen_op_neon_max_u32
2837
#define gen_op_neon_pmin_s32  gen_op_neon_min_s32
2838
#define gen_op_neon_pmin_u32  gen_op_neon_min_u32
2839

    
2840
#define GEN_NEON_INTEGER_OP(name) do { \
2841
    switch ((size << 1) | u) { \
2842
    case 0: gen_op_neon_##name##_s8(); break; \
2843
    case 1: gen_op_neon_##name##_u8(); break; \
2844
    case 2: gen_op_neon_##name##_s16(); break; \
2845
    case 3: gen_op_neon_##name##_u16(); break; \
2846
    case 4: gen_op_neon_##name##_s32(); break; \
2847
    case 5: gen_op_neon_##name##_u32(); break; \
2848
    default: return 1; \
2849
    }} while (0)
2850

    
2851
static inline void
2852
gen_neon_movl_scratch_T0(int scratch)
2853
{
2854
  uint32_t offset;
2855

    
2856
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2857
  gen_op_neon_setreg_T0(offset);
2858
}
2859

    
2860
static inline void
2861
gen_neon_movl_scratch_T1(int scratch)
2862
{
2863
  uint32_t offset;
2864

    
2865
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2866
  gen_op_neon_setreg_T1(offset);
2867
}
2868

    
2869
static inline void
2870
gen_neon_movl_T0_scratch(int scratch)
2871
{
2872
  uint32_t offset;
2873

    
2874
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2875
  gen_op_neon_getreg_T0(offset);
2876
}
2877

    
2878
static inline void
2879
gen_neon_movl_T1_scratch(int scratch)
2880
{
2881
  uint32_t offset;
2882

    
2883
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2884
  gen_op_neon_getreg_T1(offset);
2885
}
2886

    
2887
static inline void gen_op_neon_widen_u32(void)
2888
{
2889
    gen_op_movl_T1_im(0);
2890
}
2891

    
2892
static inline void gen_neon_get_scalar(int size, int reg)
2893
{
2894
    if (size == 1) {
2895
        NEON_GET_REG(T0, reg >> 1, reg & 1);
2896
    } else {
2897
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
2898
        if (reg & 1)
2899
            gen_op_neon_dup_low16();
2900
        else
2901
            gen_op_neon_dup_high16();
2902
    }
2903
}
2904

    
2905
static void gen_neon_unzip(int reg, int q, int tmp, int size)
2906
{
2907
    int n;
2908

    
2909
    for (n = 0; n < q + 1; n += 2) {
2910
        NEON_GET_REG(T0, reg, n);
2911
        NEON_GET_REG(T0, reg, n + n);
2912
        switch (size) {
2913
        case 0: gen_op_neon_unzip_u8(); break;
2914
        case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same.  */
2915
        case 2: /* no-op */; break;
2916
        default: abort();
2917
        }
2918
        gen_neon_movl_scratch_T0(tmp + n);
2919
        gen_neon_movl_scratch_T1(tmp + n + 1);
2920
    }
2921
}
2922

    
2923
static struct {
2924
    int nregs;
2925
    int interleave;
2926
    int spacing;
2927
} neon_ls_element_type[11] = {
2928
    {4, 4, 1},
2929
    {4, 4, 2},
2930
    {4, 1, 1},
2931
    {4, 2, 1},
2932
    {3, 3, 1},
2933
    {3, 3, 2},
2934
    {3, 1, 1},
2935
    {1, 1, 1},
2936
    {2, 2, 1},
2937
    {2, 2, 2},
2938
    {2, 1, 1}
2939
};
2940

    
2941
/* Translate a NEON load/store element instruction.  Return nonzero if the
2942
   instruction is invalid.  */
2943
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
2944
{
2945
    int rd, rn, rm;
2946
    int op;
2947
    int nregs;
2948
    int interleave;
2949
    int stride;
2950
    int size;
2951
    int reg;
2952
    int pass;
2953
    int load;
2954
    int shift;
2955
    uint32_t mask;
2956
    int n;
2957

    
2958
    if (!vfp_enabled(env))
2959
      return 1;
2960
    VFP_DREG_D(rd, insn);
2961
    rn = (insn >> 16) & 0xf;
2962
    rm = insn & 0xf;
2963
    load = (insn & (1 << 21)) != 0;
2964
    if ((insn & (1 << 23)) == 0) {
2965
        /* Load store all elements.  */
2966
        op = (insn >> 8) & 0xf;
2967
        size = (insn >> 6) & 3;
2968
        if (op > 10 || size == 3)
2969
            return 1;
2970
        nregs = neon_ls_element_type[op].nregs;
2971
        interleave = neon_ls_element_type[op].interleave;
2972
        gen_movl_T1_reg(s, rn);
2973
        stride = (1 << size) * interleave;
2974
        for (reg = 0; reg < nregs; reg++) {
2975
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
2976
                gen_movl_T1_reg(s, rn);
2977
                gen_op_addl_T1_im((1 << size) * reg);
2978
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
2979
                gen_movl_T1_reg(s, rn);
2980
                gen_op_addl_T1_im(1 << size);
2981
            }
2982
            for (pass = 0; pass < 2; pass++) {
2983
                if (size == 2) {
2984
                    if (load) {
2985
                        gen_ldst(ldl, s);
2986
                        NEON_SET_REG(T0, rd, pass);
2987
                    } else {
2988
                        NEON_GET_REG(T0, rd, pass);
2989
                        gen_ldst(stl, s);
2990
                    }
2991
                    gen_op_addl_T1_im(stride);
2992
                } else if (size == 1) {
2993
                    if (load) {
2994
                        gen_ldst(lduw, s);
2995
                        gen_op_addl_T1_im(stride);
2996
                        gen_op_movl_T2_T0();
2997
                        gen_ldst(lduw, s);
2998
                        gen_op_addl_T1_im(stride);
2999
                        gen_op_neon_insert_elt(16, 0xffff);
3000
                        NEON_SET_REG(T2, rd, pass);
3001
                    } else {
3002
                        NEON_GET_REG(T2, rd, pass);
3003
                        gen_op_movl_T0_T2();
3004
                        gen_ldst(stw, s);
3005
                        gen_op_addl_T1_im(stride);
3006
                        gen_op_neon_extract_elt(16, 0xffff0000);
3007
                        gen_ldst(stw, s);
3008
                        gen_op_addl_T1_im(stride);
3009
                    }
3010
                } else /* size == 0 */ {
3011
                    if (load) {
3012
                        mask = 0xff;
3013
                        for (n = 0; n < 4; n++) {
3014
                            gen_ldst(ldub, s);
3015
                            gen_op_addl_T1_im(stride);
3016
                            if (n == 0) {
3017
                                gen_op_movl_T2_T0();
3018
                            } else {
3019
                                gen_op_neon_insert_elt(n * 8, ~mask);
3020
                            }
3021
                            mask <<= 8;
3022
                        }
3023
                        NEON_SET_REG(T2, rd, pass);
3024
                    } else {
3025
                        NEON_GET_REG(T2, rd, pass);
3026
                        mask = 0xff;
3027
                        for (n = 0; n < 4; n++) {
3028
                            if (n == 0) {
3029
                                gen_op_movl_T0_T2();
3030
                            } else {
3031
                                gen_op_neon_extract_elt(n * 8, mask);
3032
                            }
3033
                            gen_ldst(stb, s);
3034
                            gen_op_addl_T1_im(stride);
3035
                            mask <<= 8;
3036
                        }
3037
                    }
3038
                }
3039
            }
3040
            rd += neon_ls_element_type[op].spacing;
3041
        }
3042
        stride = nregs * 8;
3043
    } else {
3044
        size = (insn >> 10) & 3;
3045
        if (size == 3) {
3046
            /* Load single element to all lanes.  */
3047
            if (!load)
3048
                return 1;
3049
            size = (insn >> 6) & 3;
3050
            nregs = ((insn >> 8) & 3) + 1;
3051
            stride = (insn & (1 << 5)) ? 2 : 1;
3052
            gen_movl_T1_reg(s, rn);
3053
            for (reg = 0; reg < nregs; reg++) {
3054
                switch (size) {
3055
                case 0:
3056
                    gen_ldst(ldub, s);
3057
                    gen_op_neon_dup_u8(0);
3058
                    break;
3059
                case 1:
3060
                    gen_ldst(lduw, s);
3061
                    gen_op_neon_dup_low16();
3062
                    break;
3063
                case 2:
3064
                    gen_ldst(ldl, s);
3065
                    break;
3066
                case 3:
3067
                    return 1;
3068
                }
3069
                gen_op_addl_T1_im(1 << size);
3070
                NEON_SET_REG(T0, rd, 0);
3071
                NEON_SET_REG(T0, rd, 1);
3072
                rd += stride;
3073
            }
3074
            stride = (1 << size) * nregs;
3075
        } else {
3076
            /* Single element.  */
3077
            pass = (insn >> 7) & 1;
3078
            switch (size) {
3079
            case 0:
3080
                shift = ((insn >> 5) & 3) * 8;
3081
                mask = 0xff << shift;
3082
                stride = 1;
3083
                break;
3084
            case 1:
3085
                shift = ((insn >> 6) & 1) * 16;
3086
                mask = shift ? 0xffff0000 : 0xffff;
3087
                stride = (insn & (1 << 5)) ? 2 : 1;
3088
                break;
3089
            case 2:
3090
                shift = 0;
3091
                mask = 0xffffffff;
3092
                stride = (insn & (1 << 6)) ? 2 : 1;
3093
                break;
3094
            default:
3095
                abort();
3096
            }
3097
            nregs = ((insn >> 8) & 3) + 1;
3098
            gen_movl_T1_reg(s, rn);
3099
            for (reg = 0; reg < nregs; reg++) {
3100
                if (load) {
3101
                    if (size != 2) {
3102
                        NEON_GET_REG(T2, rd, pass);
3103
                    }
3104
                    switch (size) {
3105
                    case 0:
3106
                        gen_ldst(ldub, s);
3107
                        break;
3108
                    case 1:
3109
                        gen_ldst(lduw, s);
3110
                        break;
3111
                    case 2:
3112
                        gen_ldst(ldl, s);
3113
                        NEON_SET_REG(T0, rd, pass);
3114
                        break;
3115
                    }
3116
                    if (size != 2) {
3117
                        gen_op_neon_insert_elt(shift, ~mask);
3118
                        NEON_SET_REG(T0, rd, pass);
3119
                    }
3120
                } else { /* Store */
3121
                    if (size == 2) {
3122
                        NEON_GET_REG(T0, rd, pass);
3123
                    } else {
3124
                        NEON_GET_REG(T2, rd, pass);
3125
                        gen_op_neon_extract_elt(shift, mask);
3126
                    }
3127
                    switch (size) {
3128
                    case 0:
3129
                        gen_ldst(stb, s);
3130
                        break;
3131
                    case 1:
3132
                        gen_ldst(stw, s);
3133
                        break;
3134
                    case 2:
3135
                        gen_ldst(stl, s);
3136
                        break;
3137
                    }
3138
                }
3139
                rd += stride;
3140
                gen_op_addl_T1_im(1 << size);
3141
            }
3142
            stride = nregs * (1 << size);
3143
        }
3144
    }
3145
    if (rm != 15) {
3146
        TCGv base;
3147

    
3148
        base = load_reg(s, rn);
3149
        if (rm == 13) {
3150
            tcg_gen_addi_i32(base, base, stride);
3151
        } else {
3152
            TCGv index;
3153
            index = load_reg(s, rm);
3154
            tcg_gen_add_i32(base, base, index);
3155
            dead_tmp(index);
3156
        }
3157
        store_reg(s, rn, base);
3158
    }
3159
    return 0;
3160
}
3161

    
3162
/* Translate a NEON data processing instruction.  Return nonzero if the
3163
   instruction is invalid.
3164
   In general we process vectors in 32-bit chunks.  This means we can reuse
3165
   some of the scalar ops, and hopefully the code generated for 32-bit
3166
   hosts won't be too awful.  The downside is that the few 64-bit operations
3167
   (mainly shifts) get complicated.  */
3168

    
3169
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
3170
{
3171
    int op;
3172
    int q;
3173
    int rd, rn, rm;
3174
    int size;
3175
    int shift;
3176
    int pass;
3177
    int count;
3178
    int pairwise;
3179
    int u;
3180
    int n;
3181
    uint32_t imm;
3182

    
3183
    if (!vfp_enabled(env))
3184
      return 1;
3185
    q = (insn & (1 << 6)) != 0;
3186
    u = (insn >> 24) & 1;
3187
    VFP_DREG_D(rd, insn);
3188
    VFP_DREG_N(rn, insn);
3189
    VFP_DREG_M(rm, insn);
3190
    size = (insn >> 20) & 3;
3191
    if ((insn & (1 << 23)) == 0) {
3192
        /* Three register same length.  */
3193
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
3194
        if (size == 3 && (op == 1 || op == 5 || op == 16)) {
3195
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
3196
                NEON_GET_REG(T0, rm, pass * 2);
3197
                NEON_GET_REG(T1, rm, pass * 2 + 1);
3198
                gen_neon_movl_scratch_T0(0);
3199
                gen_neon_movl_scratch_T1(1);
3200
                NEON_GET_REG(T0, rn, pass * 2);
3201
                NEON_GET_REG(T1, rn, pass * 2 + 1);
3202
                switch (op) {
3203
                case 1: /* VQADD */
3204
                    if (u) {
3205
                        gen_op_neon_addl_saturate_u64();
3206
                    } else {
3207
                        gen_op_neon_addl_saturate_s64();
3208
                    }
3209
                    break;
3210
                case 5: /* VQSUB */
3211
                    if (u) {
3212
                        gen_op_neon_subl_saturate_u64();
3213
                    } else {
3214
                        gen_op_neon_subl_saturate_s64();
3215
                    }
3216
                    break;
3217
                case 16:
3218
                    if (u) {
3219
                        gen_op_neon_subl_u64();
3220
                    } else {
3221
                        gen_op_neon_addl_u64();
3222
                    }
3223
                    break;
3224
                default:
3225
                    abort();
3226
                }
3227
                NEON_SET_REG(T0, rd, pass * 2);
3228
                NEON_SET_REG(T1, rd, pass * 2 + 1);
3229
            }
3230
            return 0;
3231
        }
3232
        switch (op) {
3233
        case 8: /* VSHL */
3234
        case 9: /* VQSHL */
3235
        case 10: /* VRSHL */
3236
        case 11: /* VQSHL */
3237
            /* Shift operations have Rn and Rm reversed.  */
3238
            {
3239
                int tmp;
3240
                tmp = rn;
3241
                rn = rm;
3242
                rm = tmp;
3243
                pairwise = 0;
3244
            }
3245
            break;
3246
        case 20: /* VPMAX */
3247
        case 21: /* VPMIN */
3248
        case 23: /* VPADD */
3249
            pairwise = 1;
3250
            break;
3251
        case 26: /* VPADD (float) */
3252
            pairwise = (u && size < 2);
3253
            break;
3254
        case 30: /* VPMIN/VPMAX (float) */
3255
            pairwise = u;
3256
            break;
3257
        default:
3258
            pairwise = 0;
3259
            break;
3260
        }
3261
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
3262

    
3263
        if (pairwise) {
3264
            /* Pairwise.  */
3265
            if (q)
3266
                n = (pass & 1) * 2;
3267
            else
3268
                n = 0;
3269
            if (pass < q + 1) {
3270
                NEON_GET_REG(T0, rn, n);
3271
                NEON_GET_REG(T1, rn, n + 1);
3272
            } else {
3273
                NEON_GET_REG(T0, rm, n);
3274
                NEON_GET_REG(T1, rm, n + 1);
3275
            }
3276
        } else {
3277
            /* Elementwise.  */
3278
            NEON_GET_REG(T0, rn, pass);
3279
            NEON_GET_REG(T1, rm, pass);
3280
        }
3281
        switch (op) {
3282
        case 0: /* VHADD */
3283
            GEN_NEON_INTEGER_OP(hadd);
3284
            break;
3285
        case 1: /* VQADD */
3286
            switch (size << 1| u) {
3287
            case 0: gen_op_neon_qadd_s8(); break;
3288
            case 1: gen_op_neon_qadd_u8(); break;
3289
            case 2: gen_op_neon_qadd_s16(); break;
3290
            case 3: gen_op_neon_qadd_u16(); break;
3291
            case 4: gen_op_addl_T0_T1_saturate(); break;
3292
            case 5: gen_op_addl_T0_T1_usaturate(); break;
3293
            default: abort();
3294
            }
3295
            break;
3296
        case 2: /* VRHADD */
3297
            GEN_NEON_INTEGER_OP(rhadd);
3298
            break;
3299
        case 3: /* Logic ops.  */
3300
            switch ((u << 2) | size) {
3301
            case 0: /* VAND */
3302
                gen_op_andl_T0_T1();
3303
                break;
3304
            case 1: /* BIC */
3305
                gen_op_bicl_T0_T1();
3306
                break;
3307
            case 2: /* VORR */
3308
                gen_op_orl_T0_T1();
3309
                break;
3310
            case 3: /* VORN */
3311
                gen_op_notl_T1();
3312
                gen_op_orl_T0_T1();
3313
                break;
3314
            case 4: /* VEOR */
3315
                gen_op_xorl_T0_T1();
3316
                break;
3317
            case 5: /* VBSL */
3318
                NEON_GET_REG(T2, rd, pass);
3319
                gen_op_neon_bsl();
3320
                break;
3321
            case 6: /* VBIT */
3322
                NEON_GET_REG(T2, rd, pass);
3323
                gen_op_neon_bit();
3324
                break;
3325
            case 7: /* VBIF */
3326
                NEON_GET_REG(T2, rd, pass);
3327
                gen_op_neon_bif();
3328
                break;
3329
            }
3330
            break;
3331
        case 4: /* VHSUB */
3332
            GEN_NEON_INTEGER_OP(hsub);
3333
            break;
3334
        case 5: /* VQSUB */
3335
            switch ((size << 1) | u) {
3336
            case 0: gen_op_neon_qsub_s8(); break;
3337
            case 1: gen_op_neon_qsub_u8(); break;
3338
            case 2: gen_op_neon_qsub_s16(); break;
3339
            case 3: gen_op_neon_qsub_u16(); break;
3340
            case 4: gen_op_subl_T0_T1_saturate(); break;
3341
            case 5: gen_op_subl_T0_T1_usaturate(); break;
3342
            default: abort();
3343
            }
3344
            break;
3345
        case 6: /* VCGT */
3346
            GEN_NEON_INTEGER_OP(cgt);
3347
            break;
3348
        case 7: /* VCGE */
3349
            GEN_NEON_INTEGER_OP(cge);
3350
            break;
3351
        case 8: /* VSHL */
3352
            switch ((size << 1) | u) {
3353
            case 0: gen_op_neon_shl_s8(); break;
3354
            case 1: gen_op_neon_shl_u8(); break;
3355
            case 2: gen_op_neon_shl_s16(); break;
3356
            case 3: gen_op_neon_shl_u16(); break;
3357
            case 4: gen_op_neon_shl_s32(); break;
3358
            case 5: gen_op_neon_shl_u32(); break;
3359
#if 0
3360
            /* ??? Implementing these is tricky because the vector ops work
3361
               on 32-bit pieces.  */
3362
            case 6: gen_op_neon_shl_s64(); break;
3363
            case 7: gen_op_neon_shl_u64(); break;
3364
#else
3365
            case 6: case 7: cpu_abort(env, "VSHL.64 not implemented");
3366
#endif
3367
            }
3368
            break;
3369
        case 9: /* VQSHL */
3370
            switch ((size << 1) | u) {
3371
            case 0: gen_op_neon_qshl_s8(); break;
3372
            case 1: gen_op_neon_qshl_u8(); break;
3373
            case 2: gen_op_neon_qshl_s16(); break;
3374
            case 3: gen_op_neon_qshl_u16(); break;
3375
            case 4: gen_op_neon_qshl_s32(); break;
3376
            case 5: gen_op_neon_qshl_u32(); break;
3377
#if 0
3378
            /* ??? Implementing these is tricky because the vector ops work
3379
               on 32-bit pieces.  */
3380
            case 6: gen_op_neon_qshl_s64(); break;
3381
            case 7: gen_op_neon_qshl_u64(); break;
3382
#else
3383
            case 6: case 7: cpu_abort(env, "VQSHL.64 not implemented");
3384
#endif
3385
            }
3386
            break;
3387
        case 10: /* VRSHL */
3388
            switch ((size << 1) | u) {
3389
            case 0: gen_op_neon_rshl_s8(); break;
3390
            case 1: gen_op_neon_rshl_u8(); break;
3391
            case 2: gen_op_neon_rshl_s16(); break;
3392
            case 3: gen_op_neon_rshl_u16(); break;
3393
            case 4: gen_op_neon_rshl_s32(); break;
3394
            case 5: gen_op_neon_rshl_u32(); break;
3395
#if 0
3396
            /* ??? Implementing these is tricky because the vector ops work
3397
               on 32-bit pieces.  */
3398
            case 6: gen_op_neon_rshl_s64(); break;
3399
            case 7: gen_op_neon_rshl_u64(); break;
3400
#else
3401
            case 6: case 7: cpu_abort(env, "VRSHL.64 not implemented");
3402
#endif
3403
            }
3404
            break;
3405
        case 11: /* VQRSHL */
3406
            switch ((size << 1) | u) {
3407
            case 0: gen_op_neon_qrshl_s8(); break;
3408
            case 1: gen_op_neon_qrshl_u8(); break;
3409
            case 2: gen_op_neon_qrshl_s16(); break;
3410
            case 3: gen_op_neon_qrshl_u16(); break;
3411
            case 4: gen_op_neon_qrshl_s32(); break;
3412
            case 5: gen_op_neon_qrshl_u32(); break;
3413
#if 0
3414
            /* ??? Implementing these is tricky because the vector ops work
3415
               on 32-bit pieces.  */
3416
            case 6: gen_op_neon_qrshl_s64(); break;
3417
            case 7: gen_op_neon_qrshl_u64(); break;
3418
#else
3419
            case 6: case 7: cpu_abort(env, "VQRSHL.64 not implemented");
3420
#endif
3421
            }
3422
            break;
3423
        case 12: /* VMAX */
3424
            GEN_NEON_INTEGER_OP(max);
3425
            break;
3426
        case 13: /* VMIN */
3427
            GEN_NEON_INTEGER_OP(min);
3428
            break;
3429
        case 14: /* VABD */
3430
            GEN_NEON_INTEGER_OP(abd);
3431
            break;
3432
        case 15: /* VABA */
3433
            GEN_NEON_INTEGER_OP(abd);
3434
            NEON_GET_REG(T1, rd, pass);
3435
            gen_neon_add(size);
3436
            break;
3437
        case 16:
3438
            if (!u) { /* VADD */
3439
                if (gen_neon_add(size))
3440
                    return 1;
3441
            } else { /* VSUB */
3442
                switch (size) {
3443
                case 0: gen_op_neon_sub_u8(); break;
3444
                case 1: gen_op_neon_sub_u16(); break;
3445
                case 2: gen_op_subl_T0_T1(); break;
3446
                default: return 1;
3447
                }
3448
            }
3449
            break;
3450
        case 17:
3451
            if (!u) { /* VTST */
3452
                switch (size) {
3453
                case 0: gen_op_neon_tst_u8(); break;
3454
                case 1: gen_op_neon_tst_u16(); break;
3455
                case 2: gen_op_neon_tst_u32(); break;
3456
                default: return 1;
3457
                }
3458
            } else { /* VCEQ */
3459
                switch (size) {
3460
                case 0: gen_op_neon_ceq_u8(); break;
3461
                case 1: gen_op_neon_ceq_u16(); break;
3462
                case 2: gen_op_neon_ceq_u32(); break;
3463
                default: return 1;
3464
                }
3465
            }
3466
            break;
3467
        case 18: /* Multiply.  */
3468
            switch (size) {
3469
            case 0: gen_op_neon_mul_u8(); break;
3470
            case 1: gen_op_neon_mul_u16(); break;
3471
            case 2: gen_op_mul_T0_T1(); break;
3472
            default: return 1;
3473
            }
3474
            NEON_GET_REG(T1, rd, pass);
3475
            if (u) { /* VMLS */
3476
                switch (size) {
3477
                case 0: gen_op_neon_rsb_u8(); break;
3478
                case 1: gen_op_neon_rsb_u16(); break;
3479
                case 2: gen_op_rsbl_T0_T1(); break;
3480
                default: return 1;
3481
                }
3482
            } else { /* VMLA */
3483
                gen_neon_add(size);
3484
            }
3485
            break;
3486
        case 19: /* VMUL */
3487
            if (u) { /* polynomial */
3488
                gen_op_neon_mul_p8();
3489
            } else { /* Integer */
3490
                switch (size) {
3491
                case 0: gen_op_neon_mul_u8(); break;
3492
                case 1: gen_op_neon_mul_u16(); break;
3493
                case 2: gen_op_mul_T0_T1(); break;
3494
                default: return 1;
3495
                }
3496
            }
3497
            break;
3498
        case 20: /* VPMAX */
3499
            GEN_NEON_INTEGER_OP(pmax);
3500
            break;
3501
        case 21: /* VPMIN */
3502
            GEN_NEON_INTEGER_OP(pmin);
3503
            break;
3504
        case 22: /* Hultiply high.  */
3505
            if (!u) { /* VQDMULH */
3506
                switch (size) {
3507
                case 1: gen_op_neon_qdmulh_s16(); break;
3508
                case 2: gen_op_neon_qdmulh_s32(); break;
3509
                default: return 1;
3510
                }
3511
            } else { /* VQRDHMUL */
3512
                switch (size) {
3513
                case 1: gen_op_neon_qrdmulh_s16(); break;
3514
                case 2: gen_op_neon_qrdmulh_s32(); break;
3515
                default: return 1;
3516
                }
3517
            }
3518
            break;
3519
        case 23: /* VPADD */
3520
            if (u)
3521
                return 1;
3522
            switch (size) {
3523
            case 0: gen_op_neon_padd_u8(); break;
3524
            case 1: gen_op_neon_padd_u16(); break;
3525
            case 2: gen_op_addl_T0_T1(); break;
3526
            default: return 1;
3527
            }
3528
            break;
3529
        case 26: /* Floating point arithnetic.  */
3530
            switch ((u << 2) | size) {
3531
            case 0: /* VADD */
3532
                gen_op_neon_add_f32();
3533
                break;
3534
            case 2: /* VSUB */
3535
                gen_op_neon_sub_f32();
3536
                break;
3537
            case 4: /* VPADD */
3538
                gen_op_neon_add_f32();
3539
                break;
3540
            case 6: /* VABD */
3541
                gen_op_neon_abd_f32();
3542
                break;
3543
            default:
3544
                return 1;
3545
            }
3546
            break;
3547
        case 27: /* Float multiply.  */
3548
            gen_op_neon_mul_f32();
3549
            if (!u) {
3550
                NEON_GET_REG(T1, rd, pass);
3551
                if (size == 0) {
3552
                    gen_op_neon_add_f32();
3553
                } else {
3554
                    gen_op_neon_rsb_f32();
3555
                }
3556
            }
3557
            break;
3558
        case 28: /* Float compare.  */
3559
            if (!u) {
3560
                gen_op_neon_ceq_f32();
3561
            } else {
3562
                if (size == 0)
3563
                    gen_op_neon_cge_f32();
3564
                else
3565
                    gen_op_neon_cgt_f32();
3566
            }
3567
            break;
3568
        case 29: /* Float compare absolute.  */
3569
            if (!u)
3570
                return 1;
3571
            if (size == 0)
3572
                gen_op_neon_acge_f32();
3573
            else
3574
                gen_op_neon_acgt_f32();
3575
            break;
3576
        case 30: /* Float min/max.  */
3577
            if (size == 0)
3578
                gen_op_neon_max_f32();
3579
            else
3580
                gen_op_neon_min_f32();
3581
            break;
3582
        case 31:
3583
            if (size == 0)
3584
                gen_op_neon_recps_f32();
3585
            else
3586
                gen_op_neon_rsqrts_f32();
3587
            break;
3588
        default:
3589
            abort();
3590
        }
3591
        /* Save the result.  For elementwise operations we can put it
3592
           straight into the destination register.  For pairwise operations
3593
           we have to be careful to avoid clobbering the source operands.  */
3594
        if (pairwise && rd == rm) {
3595
            gen_neon_movl_scratch_T0(pass);
3596
        } else {
3597
            NEON_SET_REG(T0, rd, pass);
3598
        }
3599

    
3600
        } /* for pass */
3601
        if (pairwise && rd == rm) {
3602
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
3603
                gen_neon_movl_T0_scratch(pass);
3604
                NEON_SET_REG(T0, rd, pass);
3605
            }
3606
        }
3607
    } else if (insn & (1 << 4)) {
3608
        if ((insn & 0x00380080) != 0) {
3609
            /* Two registers and shift.  */
3610
            op = (insn >> 8) & 0xf;
3611
            if (insn & (1 << 7)) {
3612
                /* 64-bit shift.   */
3613
                size = 3;
3614
            } else {
3615
                size = 2;
3616
                while ((insn & (1 << (size + 19))) == 0)
3617
                    size--;
3618
            }
3619
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
3620
            /* To avoid excessive dumplication of ops we implement shift
3621
               by immediate using the variable shift operations.  */
3622
            if (op < 8) {
3623
                /* Shift by immediate:
3624
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
3625
                /* Right shifts are encoded as N - shift, where N is the
3626
                   element size in bits.  */
3627
                if (op <= 4)
3628
                    shift = shift - (1 << (size + 3));
3629
                else
3630
                    shift++;
3631
                if (size == 3) {
3632
                    count = q + 1;
3633
                } else {
3634
                    count = q ? 4: 2;
3635
                }
3636
                switch (size) {
3637
                case 0:
3638
                    imm = (uint8_t) shift;
3639
                    imm |= imm << 8;
3640
                    imm |= imm << 16;
3641
                    break;
3642
                case 1:
3643
                    imm = (uint16_t) shift;
3644
                    imm |= imm << 16;
3645
                    break;
3646
                case 2:
3647
                case 3:
3648
                    imm = shift;
3649
                    break;
3650
                default:
3651
                    abort();
3652
                }
3653

    
3654
                for (pass = 0; pass < count; pass++) {
3655
                    if (size < 3) {
3656
                        /* Operands in T0 and T1.  */
3657
                        gen_op_movl_T1_im(imm);
3658
                        NEON_GET_REG(T0, rm, pass);
3659
                    } else {
3660
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
3661
                        gen_op_movl_T0_im(imm);
3662
                        gen_neon_movl_scratch_T0(0);
3663
                        gen_op_movl_T0_im((int32_t)imm >> 31);
3664
                        gen_neon_movl_scratch_T0(1);
3665
                        NEON_GET_REG(T0, rm, pass * 2);
3666
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
3667
                    }
3668

    
3669
                    if (gen_neon_shift_im[op][u][size] == NULL)
3670
                        return 1;
3671
                    gen_neon_shift_im[op][u][size]();
3672

    
3673
                    if (op == 1 || op == 3) {
3674
                        /* Accumulate.  */
3675
                        if (size == 3) {
3676
                            gen_neon_movl_scratch_T0(0);
3677
                            gen_neon_movl_scratch_T1(1);
3678
                            NEON_GET_REG(T0, rd, pass * 2);
3679
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
3680
                            gen_op_neon_addl_u64();
3681
                        } else {
3682
                            NEON_GET_REG(T1, rd, pass);
3683
                            gen_neon_add(size);
3684
                        }
3685
                    } else if (op == 4 || (op == 5 && u)) {
3686
                        /* Insert */
3687
                        if (size == 3) {
3688
                            cpu_abort(env, "VS[LR]I.64 not implemented");
3689
                        }
3690
                        switch (size) {
3691
                        case 0:
3692
                            if (op == 4)
3693
                                imm = 0xff >> -shift;
3694
                            else
3695
                                imm = (uint8_t)(0xff << shift);
3696
                            imm |= imm << 8;
3697
                            imm |= imm << 16;
3698
                            break;
3699
                        case 1:
3700
                            if (op == 4)
3701
                                imm = 0xffff >> -shift;
3702
                            else
3703
                                imm = (uint16_t)(0xffff << shift);
3704
                            imm |= imm << 16;
3705
                            break;
3706
                        case 2:
3707
                            if (op == 4)
3708
                                imm = 0xffffffffu >> -shift;
3709
                            else
3710
                                imm = 0xffffffffu << shift;
3711
                            break;
3712
                        default:
3713
                            abort();
3714
                        }
3715
                        NEON_GET_REG(T1, rd, pass);
3716
                        gen_op_movl_T2_im(imm);
3717
                        gen_op_neon_bsl();
3718
                    }
3719
                    if (size == 3) {
3720
                        NEON_SET_REG(T0, rd, pass * 2);
3721
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
3722
                    } else {
3723
                        NEON_SET_REG(T0, rd, pass);
3724
                    }
3725
                } /* for pass */
3726
            } else if (op < 10) {
3727
                /* Shift by immedaiate and narrow:
3728
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
3729
                shift = shift - (1 << (size + 3));
3730
                size++;
3731
                if (size == 3) {
3732
                    count = q + 1;
3733
                } else {
3734
                    count = q ? 4: 2;
3735
                }
3736
                switch (size) {
3737
                case 1:
3738
                    imm = (uint16_t) shift;
3739
                    imm |= imm << 16;
3740
                    break;
3741
                case 2:
3742
                case 3:
3743
                    imm = shift;
3744
                    break;
3745
                default:
3746
                    abort();
3747
                }
3748

    
3749
                /* Processing MSB first means we need to do less shuffling at
3750
                   the end.  */
3751
                for (pass =  count - 1; pass >= 0; pass--) {
3752
                    /* Avoid clobbering the second operand before it has been
3753
                       written.  */
3754
                    n = pass;
3755
                    if (rd == rm)
3756
                        n ^= (count - 1);
3757
                    else
3758
                        n = pass;
3759

    
3760
                    if (size < 3) {
3761
                        /* Operands in T0 and T1.  */
3762
                        gen_op_movl_T1_im(imm);
3763
                        NEON_GET_REG(T0, rm, n);
3764
                    } else {
3765
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
3766
                        gen_op_movl_T0_im(imm);
3767
                        gen_neon_movl_scratch_T0(0);
3768
                        gen_op_movl_T0_im((int32_t)imm >> 31);
3769
                        gen_neon_movl_scratch_T0(1);
3770
                        NEON_GET_REG(T0, rm, n * 2);
3771
                        NEON_GET_REG(T0, rm, n * 2 + 1);
3772
                    }
3773

    
3774
                    gen_neon_shift_im_narrow[q][u][size - 1]();
3775

    
3776
                    if (size < 3 && (pass & 1) == 0) {
3777
                        gen_neon_movl_scratch_T0(0);
3778
                    } else {
3779
                        uint32_t offset;
3780

    
3781
                        if (size < 3)
3782
                            gen_neon_movl_T1_scratch(0);
3783

    
3784
                        if (op == 8 && !u) {
3785
                            gen_neon_narrow[size - 1]();
3786
                        } else {
3787
                            if (op == 8)
3788
                                gen_neon_narrow_sats[size - 2]();
3789
                            else
3790
                                gen_neon_narrow_satu[size - 1]();
3791
                        }
3792
                        if (size == 3)
3793
                            offset = neon_reg_offset(rd, n);
3794
                        else
3795
                            offset = neon_reg_offset(rd, n >> 1);
3796
                        gen_op_neon_setreg_T0(offset);
3797
                    }
3798
                } /* for pass */
3799
            } else if (op == 10) {
3800
                /* VSHLL */
3801
                if (q)
3802
                    return 1;
3803
                for (pass = 0; pass < 2; pass++) {
3804
                    /* Avoid clobbering the input operand.  */
3805
                    if (rd == rm)
3806
                        n = 1 - pass;
3807
                    else
3808
                        n = pass;
3809

    
3810
                    NEON_GET_REG(T0, rm, n);
3811
                    GEN_NEON_INTEGER_OP(widen);
3812
                    if (shift != 0) {
3813
                        /* The shift is less than the width of the source
3814
                           type, so in some cases we can just
3815
                           shift the whole register.  */
3816
                        if (size == 1 || (size == 0 && u)) {
3817
                            gen_op_shll_T0_im(shift);
3818
                            gen_op_shll_T1_im(shift);
3819
                        } else {
3820
                            switch (size) {
3821
                            case 0: gen_op_neon_shll_u16(shift); break;
3822
                            case 2: gen_op_neon_shll_u64(shift); break;
3823
                            default: abort();
3824
                            }
3825
                        }
3826
                    }
3827
                    NEON_SET_REG(T0, rd, n * 2);
3828
                    NEON_SET_REG(T1, rd, n * 2 + 1);
3829
                }
3830
            } else if (op == 15 || op == 16) {
3831
                /* VCVT fixed-point.  */
3832
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
3833
                    gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
3834
                    if (op & 1) {
3835
                        if (u)
3836
                            gen_op_vfp_ultos(shift);
3837
                        else
3838
                            gen_op_vfp_sltos(shift);
3839
                    } else {
3840
                        if (u)
3841
                            gen_op_vfp_touls(shift);
3842
                        else
3843
                            gen_op_vfp_tosls(shift);
3844
                    }
3845
                    gen_op_vfp_setreg_F0s(neon_reg_offset(rd, pass));
3846
                }
3847
            } else {
3848
                return 1;
3849
            }
3850
        } else { /* (insn & 0x00380080) == 0 */
3851
            int invert;
3852

    
3853
            op = (insn >> 8) & 0xf;
3854
            /* One register and immediate.  */
3855
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
3856
            invert = (insn & (1 << 5)) != 0;
3857
            switch (op) {
3858
            case 0: case 1:
3859
                /* no-op */
3860
                break;
3861
            case 2: case 3:
3862
                imm <<= 8;
3863
                break;
3864
            case 4: case 5:
3865
                imm <<= 16;
3866
                break;
3867
            case 6: case 7:
3868
                imm <<= 24;
3869
                break;
3870
            case 8: case 9:
3871
                imm |= imm << 16;
3872
                break;
3873
            case 10: case 11:
3874
                imm = (imm << 8) | (imm << 24);
3875
                break;
3876
            case 12:
3877
                imm = (imm < 8) | 0xff;
3878
                break;
3879
            case 13:
3880
                imm = (imm << 16) | 0xffff;
3881
                break;
3882
            case 14:
3883
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
3884
                if (invert)
3885
                    imm = ~imm;
3886
                break;
3887
            case 15:
3888
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
3889
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
3890
                break;
3891
            }
3892
            if (invert)
3893
                imm = ~imm;
3894

    
3895
            if (op != 14 || !invert)
3896
                gen_op_movl_T1_im(imm);
3897

    
3898
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
3899
                if (op & 1 && op < 12) {
3900
                    NEON_GET_REG(T0, rd, pass);
3901
                    if (invert) {
3902
                        /* The immediate value has already been inverted, so
3903
                           BIC becomes AND.  */
3904
                        gen_op_andl_T0_T1();
3905
                    } else {
3906
                        gen_op_orl_T0_T1();
3907
                    }
3908
                    NEON_SET_REG(T0, rd, pass);
3909
                } else {
3910
                    if (op == 14 && invert) {
3911
                        uint32_t tmp;
3912
                        tmp = 0;
3913
                        for (n = 0; n < 4; n++) {
3914
                            if (imm & (1 << (n + (pass & 1) * 4)))
3915
                                tmp |= 0xff << (n * 8);
3916
                        }
3917
                        gen_op_movl_T1_im(tmp);
3918
                    }
3919
                    /* VMOV, VMVN.  */
3920
                    NEON_SET_REG(T1, rd, pass);
3921
                }
3922
            }
3923
        }
3924
    } else { /* (insn & 0x00800010 == 0x00800010) */
3925
        if (size != 3) {
3926
            op = (insn >> 8) & 0xf;
3927
            if ((insn & (1 << 6)) == 0) {
3928
                /* Three registers of different lengths.  */
3929
                int src1_wide;
3930
                int src2_wide;
3931
                int prewiden;
3932
                /* prewiden, src1_wide, src2_wide */
3933
                static const int neon_3reg_wide[16][3] = {
3934
                    {1, 0, 0}, /* VADDL */
3935
                    {1, 1, 0}, /* VADDW */
3936
                    {1, 0, 0}, /* VSUBL */
3937
                    {1, 1, 0}, /* VSUBW */
3938
                    {0, 1, 1}, /* VADDHN */
3939
                    {0, 0, 0}, /* VABAL */
3940
                    {0, 1, 1}, /* VSUBHN */
3941
                    {0, 0, 0}, /* VABDL */
3942
                    {0, 0, 0}, /* VMLAL */
3943
                    {0, 0, 0}, /* VQDMLAL */
3944
                    {0, 0, 0}, /* VMLSL */
3945
                    {0, 0, 0}, /* VQDMLSL */
3946
                    {0, 0, 0}, /* Integer VMULL */
3947
                    {0, 0, 0}, /* VQDMULL */
3948
                    {0, 0, 0}  /* Polynomial VMULL */
3949
                };
3950

    
3951
                prewiden = neon_3reg_wide[op][0];
3952
                src1_wide = neon_3reg_wide[op][1];
3953
                src2_wide = neon_3reg_wide[op][2];
3954

    
3955
                /* Avoid overlapping operands.  Wide source operands are
3956
                   always aligned so will never overlap with wide
3957
                   destinations in problematic ways.  */
3958
                if (rd == rm) {
3959
                    NEON_GET_REG(T2, rm, 1);
3960
                } else if (rd == rn) {
3961
                    NEON_GET_REG(T2, rn, 1);
3962
                }
3963
                for (pass = 0; pass < 2; pass++) {
3964
                    /* Load the second operand into env->vfp.scratch.
3965
                       Also widen narrow operands.  */
3966
                    if (pass == 1 && rd == rm) {
3967
                        if (prewiden) {
3968
                            gen_op_movl_T0_T2();
3969
                        } else {
3970
                            gen_op_movl_T1_T2();
3971
                        }
3972
                    } else {
3973
                        if (src2_wide) {
3974
                            NEON_GET_REG(T0, rm, pass * 2);
3975
                            NEON_GET_REG(T1, rm, pass * 2 + 1);
3976
                        } else {
3977
                            if (prewiden) {
3978
                                NEON_GET_REG(T0, rm, pass);
3979
                            } else {
3980
                                NEON_GET_REG(T1, rm, pass);
3981
                            }
3982
                        }
3983
                    }
3984
                    if (prewiden && !src2_wide) {
3985
                        GEN_NEON_INTEGER_OP(widen);
3986
                    }
3987
                    if (prewiden || src2_wide) {
3988
                        gen_neon_movl_scratch_T0(0);
3989
                        gen_neon_movl_scratch_T1(1);
3990
                    }
3991

    
3992
                    /* Load the first operand.  */
3993
                    if (pass == 1 && rd == rn) {
3994
                        gen_op_movl_T0_T2();
3995
                    } else {
3996
                        if (src1_wide) {
3997
                            NEON_GET_REG(T0, rn, pass * 2);
3998
                            NEON_GET_REG(T1, rn, pass * 2 + 1);
3999
                        } else {
4000
                            NEON_GET_REG(T0, rn, pass);
4001
                        }
4002
                    }
4003
                    if (prewiden && !src1_wide) {
4004
                        GEN_NEON_INTEGER_OP(widen);
4005
                    }
4006
                    switch (op) {
4007
                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4008
                        switch (size) {
4009
                        case 0: gen_op_neon_addl_u16(); break;
4010
                        case 1: gen_op_neon_addl_u32(); break;
4011
                        case 2: gen_op_neon_addl_u64(); break;
4012
                        default: abort();
4013
                        }
4014
                        break;
4015
                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4016
                        switch (size) {
4017
                        case 0: gen_op_neon_subl_u16(); break;
4018
                        case 1: gen_op_neon_subl_u32(); break;
4019
                        case 2: gen_op_neon_subl_u64(); break;
4020
                        default: abort();
4021
                        }
4022
                        break;
4023
                    case 5: case 7: /* VABAL, VABDL */
4024
                        switch ((size << 1) | u) {
4025
                        case 0: gen_op_neon_abdl_s16(); break;
4026
                        case 1: gen_op_neon_abdl_u16(); break;
4027
                        case 2: gen_op_neon_abdl_s32(); break;
4028
                        case 3: gen_op_neon_abdl_u32(); break;
4029
                        case 4: gen_op_neon_abdl_s64(); break;
4030
                        case 5: gen_op_neon_abdl_u64(); break;
4031
                        default: abort();
4032
                        }
4033
                        break;
4034
                    case 8: case 9: case 10: case 11: case 12: case 13:
4035
                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4036
                        switch ((size << 1) | u) {
4037
                        case 0: gen_op_neon_mull_s8(); break;
4038
                        case 1: gen_op_neon_mull_u8(); break;
4039
                        case 2: gen_op_neon_mull_s16(); break;
4040
                        case 3: gen_op_neon_mull_u16(); break;
4041
                        case 4: gen_op_imull_T0_T1(); break;
4042
                        case 5: gen_op_mull_T0_T1(); break;
4043
                        default: abort();
4044
                        }
4045
                        break;
4046
                    case 14: /* Polynomial VMULL */
4047
                        cpu_abort(env, "Polynomial VMULL not implemented");
4048

    
4049
                    default: /* 15 is RESERVED.  */
4050
                        return 1;
4051
                    }
4052
                    if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4053
                        /* Accumulate.  */
4054
                        if (op == 10 || op == 11) {
4055
                            switch (size) {
4056
                            case 0: gen_op_neon_negl_u16(); break;
4057
                            case 1: gen_op_neon_negl_u32(); break;
4058
                            case 2: gen_op_neon_negl_u64(); break;
4059
                            default: abort();
4060
                            }
4061
                        }
4062

    
4063
                        gen_neon_movl_scratch_T0(0);
4064
                        gen_neon_movl_scratch_T1(1);
4065

    
4066
                        if (op != 13) {
4067
                            NEON_GET_REG(T0, rd, pass * 2);
4068
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4069
                        }
4070

    
4071
                        switch (op) {
4072
                        case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4073
                            switch (size) {
4074
                            case 0: gen_op_neon_addl_u16(); break;
4075
                            case 1: gen_op_neon_addl_u32(); break;
4076
                            case 2: gen_op_neon_addl_u64(); break;
4077
                            default: abort();
4078
                            }
4079
                            break;
4080
                        case 9: case 11: /* VQDMLAL, VQDMLSL */
4081
                            switch (size) {
4082
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4083
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4084
                            default: abort();
4085
                            }
4086
                            /* Fall through.  */
4087
                        case 13: /* VQDMULL */
4088
                            switch (size) {
4089
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4090
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4091
                            default: abort();
4092
                            }
4093
                            break;
4094
                        default:
4095
                            abort();
4096
                        }
4097
                        NEON_SET_REG(T0, rd, pass * 2);
4098
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4099
                    } else if (op == 4 || op == 6) {
4100
                        /* Narrowing operation.  */
4101
                        if (u) {
4102
                            switch (size) {
4103
                            case 0: gen_op_neon_narrow_high_u8(); break;
4104
                            case 1: gen_op_neon_narrow_high_u16(); break;
4105
                            case 2: gen_op_movl_T0_T1(); break;
4106
                            default: abort();
4107
                            }
4108
                        } else {
4109
                            switch (size) {
4110
                            case 0: gen_op_neon_narrow_high_round_u8(); break;
4111
                            case 1: gen_op_neon_narrow_high_round_u16(); break;
4112
                            case 2: gen_op_neon_narrow_high_round_u32(); break;
4113
                            default: abort();
4114
                            }
4115
                        }
4116
                        NEON_SET_REG(T0, rd, pass);
4117
                    } else {
4118
                        /* Write back the result.  */
4119
                        NEON_SET_REG(T0, rd, pass * 2);
4120
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4121
                    }
4122
                }
4123
            } else {
4124
                /* Two registers and a scalar.  */
4125
                switch (op) {
4126
                case 0: /* Integer VMLA scalar */
4127
                case 1: /* Float VMLA scalar */
4128
                case 4: /* Integer VMLS scalar */
4129
                case 5: /* Floating point VMLS scalar */
4130
                case 8: /* Integer VMUL scalar */
4131
                case 9: /* Floating point VMUL scalar */
4132
                case 12: /* VQDMULH scalar */
4133
                case 13: /* VQRDMULH scalar */
4134
                    gen_neon_get_scalar(size, rm);
4135
                    gen_op_movl_T2_T0();
4136
                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
4137
                        if (pass != 0)
4138
                            gen_op_movl_T0_T2();
4139
                        NEON_GET_REG(T1, rn, pass);
4140
                        if (op == 12) {
4141
                            if (size == 1) {
4142
                                gen_op_neon_qdmulh_s16();
4143
                            } else {
4144
                                gen_op_neon_qdmulh_s32();
4145
                            }
4146
                        } else if (op == 13) {
4147
                            if (size == 1) {
4148
                                gen_op_neon_qrdmulh_s16();
4149
                            } else {
4150
                                gen_op_neon_qrdmulh_s32();
4151
                            }
4152
                        } else if (op & 1) {
4153
                            gen_op_neon_mul_f32();
4154
                        } else {
4155
                            switch (size) {
4156
                            case 0: gen_op_neon_mul_u8(); break;
4157
                            case 1: gen_op_neon_mul_u16(); break;
4158
                            case 2: gen_op_mul_T0_T1(); break;
4159
                            default: return 1;
4160
                            }
4161
                        }
4162
                        if (op < 8) {
4163
                            /* Accumulate.  */
4164
                            NEON_GET_REG(T1, rd, pass);
4165
                            switch (op) {
4166
                            case 0:
4167
                                gen_neon_add(size);
4168
                                break;
4169
                            case 1:
4170
                                gen_op_neon_add_f32();
4171
                                break;
4172
                            case 4:
4173
                                switch (size) {
4174
                                case 0: gen_op_neon_rsb_u8(); break;
4175
                                case 1: gen_op_neon_rsb_u16(); break;
4176
                                case 2: gen_op_rsbl_T0_T1(); break;
4177
                                default: return 1;
4178
                                }
4179
                                break;
4180
                            case 5:
4181
                                gen_op_neon_rsb_f32();
4182
                                break;
4183
                            default:
4184
                                abort();
4185
                            }
4186
                        }
4187
                        NEON_SET_REG(T0, rd, pass);
4188
                    }
4189
                    break;
4190
                case 2: /* VMLAL sclar */
4191
                case 3: /* VQDMLAL scalar */
4192
                case 6: /* VMLSL scalar */
4193
                case 7: /* VQDMLSL scalar */
4194
                case 10: /* VMULL scalar */
4195
                case 11: /* VQDMULL scalar */
4196
                    if (rd == rn) {
4197
                        /* Save overlapping operands before they are
4198
                           clobbered.  */
4199
                        NEON_GET_REG(T0, rn, 1);
4200
                        gen_neon_movl_scratch_T0(2);
4201
                    }
4202
                    gen_neon_get_scalar(size, rm);
4203
                    gen_op_movl_T2_T0();
4204
                    for (pass = 0; pass < 2; pass++) {
4205
                        if (pass != 0) {
4206
                            gen_op_movl_T0_T2();
4207
                        }
4208
                        if (pass != 0 && rd == rn) {
4209
                            gen_neon_movl_T1_scratch(2);
4210
                        } else {
4211
                            NEON_GET_REG(T1, rn, pass);
4212
                        }
4213
                        switch ((size << 1) | u) {
4214
                        case 0: gen_op_neon_mull_s8(); break;
4215
                        case 1: gen_op_neon_mull_u8(); break;
4216
                        case 2: gen_op_neon_mull_s16(); break;
4217
                        case 3: gen_op_neon_mull_u16(); break;
4218
                        case 4: gen_op_imull_T0_T1(); break;
4219
                        case 5: gen_op_mull_T0_T1(); break;
4220
                        default: abort();
4221
                        }
4222
                        if (op == 6 || op == 7) {
4223
                            switch (size) {
4224
                            case 0: gen_op_neon_negl_u16(); break;
4225
                            case 1: gen_op_neon_negl_u32(); break;
4226
                            case 2: gen_op_neon_negl_u64(); break;
4227
                            default: abort();
4228
                            }
4229
                        }
4230
                        gen_neon_movl_scratch_T0(0);
4231
                        gen_neon_movl_scratch_T1(1);
4232
                        NEON_GET_REG(T0, rd, pass * 2);
4233
                        NEON_GET_REG(T1, rd, pass * 2 + 1);
4234
                        switch (op) {
4235
                        case 2: case 6:
4236
                            switch (size) {
4237
                            case 0: gen_op_neon_addl_u16(); break;
4238
                            case 1: gen_op_neon_addl_u32(); break;
4239
                            case 2: gen_op_neon_addl_u64(); break;
4240
                            default: abort();
4241
                            }
4242
                            break;
4243
                        case 3: case 7:
4244
                            switch (size) {
4245
                            case 1:
4246
                                gen_op_neon_addl_saturate_s32();
4247
                                gen_op_neon_addl_saturate_s32();
4248
                                break;
4249
                            case 2:
4250
                                gen_op_neon_addl_saturate_s64();
4251
                                gen_op_neon_addl_saturate_s64();
4252
                                break;
4253
                            default: abort();
4254
                            }
4255
                            break;
4256
                        case 10:
4257
                            /* no-op */
4258
                            break;
4259
                        case 11:
4260
                            switch (size) {
4261
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4262
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4263
                            default: abort();
4264
                            }
4265
                            break;
4266
                        default:
4267
                            abort();
4268
                        }
4269
                        NEON_SET_REG(T0, rd, pass * 2);
4270
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4271
                    }
4272
                    break;
4273
                default: /* 14 and 15 are RESERVED */
4274
                    return 1;
4275
                }
4276
            }
4277
        } else { /* size == 3 */
4278
            if (!u) {
4279
                /* Extract.  */
4280
                int reg;
4281
                imm = (insn >> 8) & 0xf;
4282
                reg = rn;
4283
                count = q ? 4 : 2;
4284
                n = imm >> 2;
4285
                NEON_GET_REG(T0, reg, n);
4286
                for (pass = 0; pass < count; pass++) {
4287
                    n++;
4288
                    if (n > count) {
4289
                        reg = rm;
4290
                        n -= count;
4291
                    }
4292
                    if (imm & 3) {
4293
                        NEON_GET_REG(T1, reg, n);
4294
                        gen_op_neon_extract((insn << 3) & 0x1f);
4295
                    }
4296
                    /* ??? This is broken if rd and rm overlap */
4297
                    NEON_SET_REG(T0, rd, pass);
4298
                    if (imm & 3) {
4299
                        gen_op_movl_T0_T1();
4300
                    } else {
4301
                        NEON_GET_REG(T0, reg, n);
4302
                    }
4303
                }
4304
            } else if ((insn & (1 << 11)) == 0) {
4305
                /* Two register misc.  */
4306
                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
4307
                size = (insn >> 18) & 3;
4308
                switch (op) {
4309
                case 0: /* VREV64 */
4310
                    if (size == 3)
4311
                        return 1;
4312
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4313
                        NEON_GET_REG(T0, rm, pass * 2);
4314
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4315
                        switch (size) {
4316
                        case 0: gen_op_rev_T0(); break;
4317
                        case 1: gen_op_revh_T0(); break;
4318
                        case 2: /* no-op */ break;
4319
                        default: abort();
4320
                        }
4321
                        NEON_SET_REG(T0, rd, pass * 2 + 1);
4322
                        if (size == 2) {
4323
                            NEON_SET_REG(T1, rd, pass * 2);
4324
                        } else {
4325
                            gen_op_movl_T0_T1();
4326
                            switch (size) {
4327
                            case 0: gen_op_rev_T0(); break;
4328
                            case 1: gen_op_revh_T0(); break;
4329
                            default: abort();
4330
                            }
4331
                            NEON_SET_REG(T0, rd, pass * 2);
4332
                        }
4333
                    }
4334
                    break;
4335
                case 4: case 5: /* VPADDL */
4336
                case 12: case 13: /* VPADAL */
4337
                    if (size < 2)
4338
                        goto elementwise;
4339
                    if (size == 3)
4340
                        return 1;
4341
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4342
                        NEON_GET_REG(T0, rm, pass * 2);
4343
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4344
                        if (op & 1)
4345
                            gen_op_neon_paddl_u32();
4346
                        else
4347
                            gen_op_neon_paddl_s32();
4348
                        if (op >= 12) {
4349
                            /* Accumulate.  */
4350
                            gen_neon_movl_scratch_T0(0);
4351
                            gen_neon_movl_scratch_T1(1);
4352

    
4353
                            NEON_GET_REG(T0, rd, pass * 2);
4354
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4355
                            gen_op_neon_addl_u64();
4356
                        }
4357
                        NEON_SET_REG(T0, rd, pass * 2);
4358
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4359
                    }
4360
                    break;
4361
                case 33: /* VTRN */
4362
                    if (size == 2) {
4363
                        for (n = 0; n < (q ? 4 : 2); n += 2) {
4364
                            NEON_GET_REG(T0, rm, n);
4365
                            NEON_GET_REG(T1, rd, n + 1);
4366
                            NEON_SET_REG(T1, rm, n);
4367
                            NEON_SET_REG(T0, rd, n + 1);
4368
                        }
4369
                    } else {
4370
                        goto elementwise;
4371
                    }
4372
                    break;
4373
                case 34: /* VUZP */
4374
                    /* Reg  Before       After
4375
                       Rd   A3 A2 A1 A0  B2 B0 A2 A0
4376
                       Rm   B3 B2 B1 B0  B3 B1 A3 A1
4377
                     */
4378
                    if (size == 3)
4379
                        return 1;
4380
                    gen_neon_unzip(rd, q, 0, size);
4381
                    gen_neon_unzip(rm, q, 4, size);
4382
                    if (q) {
4383
                        static int unzip_order_q[8] =
4384
                            {0, 2, 4, 6, 1, 3, 5, 7};
4385
                        for (n = 0; n < 8; n++) {
4386
                            int reg = (n < 4) ? rd : rm;
4387
                            gen_neon_movl_T0_scratch(unzip_order_q[n]);
4388
                            NEON_SET_REG(T0, reg, n % 4);
4389
                        }
4390
                    } else {
4391
                        static int unzip_order[4] =
4392
                            {0, 4, 1, 5};
4393
                        for (n = 0; n < 4; n++) {
4394
                            int reg = (n < 2) ? rd : rm;
4395
                            gen_neon_movl_T0_scratch(unzip_order[n]);
4396
                            NEON_SET_REG(T0, reg, n % 2);
4397
                        }
4398
                    }
4399
                    break;
4400
                case 35: /* VZIP */
4401
                    /* Reg  Before       After
4402
                       Rd   A3 A2 A1 A0  B1 A1 B0 A0
4403
                       Rm   B3 B2 B1 B0  B3 A3 B2 A2
4404
                     */
4405
                    if (size == 3)
4406
                        return 1;
4407
                    count = (q ? 4 : 2);
4408
                    for (n = 0; n < count; n++) {
4409
                        NEON_GET_REG(T0, rd, n);
4410
                        NEON_GET_REG(T1, rd, n);
4411
                        switch (size) {
4412
                        case 0: gen_op_neon_zip_u8(); break;
4413
                        case 1: gen_op_neon_zip_u16(); break;
4414
                        case 2: /* no-op */; break;
4415
                        default: abort();
4416
                        }
4417
                        gen_neon_movl_scratch_T0(n * 2);
4418
                        gen_neon_movl_scratch_T1(n * 2 + 1);
4419
                    }
4420
                    for (n = 0; n < count * 2; n++) {
4421
                        int reg = (n < count) ? rd : rm;
4422
                        gen_neon_movl_T0_scratch(n);
4423
                        NEON_SET_REG(T0, reg, n % count);
4424
                    }
4425
                    break;
4426
                case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
4427
                    for (pass = 0; pass < 2; pass++) {
4428
                        if (rd == rm + 1) {
4429
                            n = 1 - pass;
4430
                        } else {
4431
                            n = pass;
4432
                        }
4433
                        NEON_GET_REG(T0, rm, n * 2);
4434
                        NEON_GET_REG(T1, rm, n * 2 + 1);
4435
                        if (op == 36 && q == 0) {
4436
                            switch (size) {
4437
                            case 0: gen_op_neon_narrow_u8(); break;
4438
                            case 1: gen_op_neon_narrow_u16(); break;
4439
                            case 2: /* no-op */ break;
4440
                            default: return 1;
4441
                            }
4442
                        } else if (q) {
4443
                            switch (size) {
4444
                            case 0: gen_op_neon_narrow_sat_u8(); break;
4445
                            case 1: gen_op_neon_narrow_sat_u16(); break;
4446
                            case 2: gen_op_neon_narrow_sat_u32(); break;
4447
                            default: return 1;
4448
                            }
4449
                        } else {
4450
                            switch (size) {
4451
                            case 0: gen_op_neon_narrow_sat_s8(); break;
4452
                            case 1: gen_op_neon_narrow_sat_s16(); break;
4453
                            case 2: gen_op_neon_narrow_sat_s32(); break;
4454
                            default: return 1;
4455
                            }
4456
                        }
4457
                        NEON_SET_REG(T0, rd, n);
4458
                    }
4459
                    break;
4460
                case 38: /* VSHLL */
4461
                    if (q)
4462
                        return 1;
4463
                    if (rm == rd) {
4464
                        NEON_GET_REG(T2, rm, 1);
4465
                    }
4466
                    for (pass = 0; pass < 2; pass++) {
4467
                        if (pass == 1 && rm == rd) {
4468
                            gen_op_movl_T0_T2();
4469
                        } else {
4470
                            NEON_GET_REG(T0, rm, pass);
4471
                        }
4472
                        switch (size) {
4473
                        case 0: gen_op_neon_widen_high_u8(); break;
4474
                        case 1: gen_op_neon_widen_high_u16(); break;
4475
                        case 2:
4476
                            gen_op_movl_T1_T0();
4477
                            gen_op_movl_T0_im(0);
4478
                            break;
4479
                        default: return 1;
4480
                        }
4481
                        NEON_SET_REG(T0, rd, pass * 2);
4482
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4483
                    }
4484
                    break;
4485
                default:
4486
                elementwise:
4487
                    for (pass = 0; pass < (q ? 4 : 2); pass++) {
4488
                        if (op == 30 || op == 31 || op >= 58) {
4489
                            gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
4490
                        } else {
4491
                            NEON_GET_REG(T0, rm, pass);
4492
                        }
4493
                        switch (op) {
4494
                        case 1: /* VREV32 */
4495
                            switch (size) {
4496
                            case 0: gen_op_rev_T0(); break;
4497
                            case 1: gen_op_revh_T0(); break;
4498
                            default: return 1;
4499
                            }
4500
                            break;
4501
                        case 2: /* VREV16 */
4502
                            if (size != 0)
4503
                                return 1;
4504
                            gen_op_rev16_T0();
4505
                            break;
4506
                        case 4: case 5: /* VPADDL */
4507
                        case 12: case 13: /* VPADAL */
4508
                            switch ((size << 1) | (op & 1)) {
4509
                            case 0: gen_op_neon_paddl_s8(); break;
4510
                            case 1: gen_op_neon_paddl_u8(); break;
4511
                            case 2: gen_op_neon_paddl_s16(); break;
4512
                            case 3: gen_op_neon_paddl_u16(); break;
4513
                            default: abort();
4514
                            }
4515
                            if (op >= 12) {
4516
                                /* Accumulate */
4517
                                NEON_GET_REG(T1, rd, pass);
4518
                                switch (size) {
4519
                                case 0: gen_op_neon_add_u16(); break;
4520
                                case 1: gen_op_addl_T0_T1(); break;
4521
                                default: abort();
4522
                                }
4523
                            }
4524
                            break;
4525
                        case 8: /* CLS */
4526
                            switch (size) {
4527
                            case 0: gen_op_neon_cls_s8(); break;
4528
                            case 1: gen_op_neon_cls_s16(); break;
4529
                            case 2: gen_op_neon_cls_s32(); break;
4530
                            default: return 1;
4531
                            }
4532
                            break;
4533
                        case 9: /* CLZ */
4534
                            switch (size) {
4535
                            case 0: gen_op_neon_clz_u8(); break;
4536
                            case 1: gen_op_neon_clz_u16(); break;
4537
                            case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
4538
                            default: return 1;
4539
                            }
4540
                            break;
4541
                        case 10: /* CNT */
4542
                            if (size != 0)
4543
                                return 1;
4544
                            gen_op_neon_cnt_u8();
4545
                            break;
4546
                        case 11: /* VNOT */
4547
                            if (size != 0)
4548
                                return 1;
4549
                            gen_op_notl_T0();
4550
                            break;
4551
                        case 14: /* VQABS */
4552
                            switch (size) {
4553
                            case 0: gen_op_neon_qabs_s8(); break;
4554
                            case 1: gen_op_neon_qabs_s16(); break;
4555
                            case 2: gen_op_neon_qabs_s32(); break;
4556
                            default: return 1;
4557
                            }
4558
                            break;
4559
                        case 15: /* VQNEG */
4560
                            switch (size) {
4561
                            case 0: gen_op_neon_qneg_s8(); break;
4562
                            case 1: gen_op_neon_qneg_s16(); break;
4563
                            case 2: gen_op_neon_qneg_s32(); break;
4564
                            default: return 1;
4565
                            }
4566
                            break;
4567
                        case 16: case 19: /* VCGT #0, VCLE #0 */
4568
                            gen_op_movl_T1_im(0);
4569
                            switch(size) {
4570
                            case 0: gen_op_neon_cgt_s8(); break;
4571
                            case 1: gen_op_neon_cgt_s16(); break;
4572
                            case 2: gen_op_neon_cgt_s32(); break;
4573
                            default: return 1;
4574
                            }
4575
                            if (op == 19)
4576
                                gen_op_notl_T0();
4577
                            break;
4578
                        case 17: case 20: /* VCGE #0, VCLT #0 */
4579
                            gen_op_movl_T1_im(0);
4580
                            switch(size) {
4581
                            case 0: gen_op_neon_cge_s8(); break;
4582
                            case 1: gen_op_neon_cge_s16(); break;
4583
                            case 2: gen_op_neon_cge_s32(); break;
4584
                            default: return 1;
4585
                            }
4586
                            if (op == 20)
4587
                                gen_op_notl_T0();
4588
                            break;
4589
                        case 18: /* VCEQ #0 */
4590
                            gen_op_movl_T1_im(0);
4591
                            switch(size) {
4592
                            case 0: gen_op_neon_ceq_u8(); break;
4593
                            case 1: gen_op_neon_ceq_u16(); break;
4594
                            case 2: gen_op_neon_ceq_u32(); break;
4595
                            default: return 1;
4596
                            }
4597
                            break;
4598
                        case 22: /* VABS */
4599
                            switch(size) {
4600
                            case 0: gen_op_neon_abs_s8(); break;
4601
                            case 1: gen_op_neon_abs_s16(); break;
4602
                            case 2: gen_op_neon_abs_s32(); break;
4603
                            default: return 1;
4604
                            }
4605
                            break;
4606
                        case 23: /* VNEG */
4607
                            gen_op_movl_T1_im(0);
4608
                            switch(size) {
4609
                            case 0: gen_op_neon_rsb_u8(); break;
4610
                            case 1: gen_op_neon_rsb_u16(); break;
4611
                            case 2: gen_op_rsbl_T0_T1(); break;
4612
                            default: return 1;
4613
                            }
4614
                            break;
4615
                        case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
4616
                            gen_op_movl_T1_im(0);
4617
                            gen_op_neon_cgt_f32();
4618
                            if (op == 27)
4619
                                gen_op_notl_T0();
4620
                            break;
4621
                        case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
4622
                            gen_op_movl_T1_im(0);
4623
                            gen_op_neon_cge_f32();
4624
                            if (op == 28)
4625
                                gen_op_notl_T0();
4626
                            break;
4627
                        case 26: /* Float VCEQ #0 */
4628
                            gen_op_movl_T1_im(0);
4629
                            gen_op_neon_ceq_f32();
4630
                            break;
4631
                        case 30: /* Float VABS */
4632
                            gen_op_vfp_abss();
4633
                            break;
4634
                        case 31: /* Float VNEG */
4635
                            gen_op_vfp_negs();
4636
                            break;
4637
                        case 32: /* VSWP */
4638
                            NEON_GET_REG(T1, rd, pass);
4639
                            NEON_SET_REG(T1, rm, pass);
4640
                            break;
4641
                        case 33: /* VTRN */
4642
                            NEON_GET_REG(T1, rd, pass);
4643
                            switch (size) {
4644
                            case 0: gen_op_neon_trn_u8(); break;
4645
                            case 1: gen_op_neon_trn_u16(); break;
4646
                            case 2: abort();
4647
                            default: return 1;
4648
                            }
4649
                            NEON_SET_REG(T1, rm, pass);
4650
                            break;
4651
                        case 56: /* Integer VRECPE */
4652
                            gen_op_neon_recpe_u32();
4653
                            break;
4654
                        case 57: /* Integer VRSQRTE */
4655
                            gen_op_neon_rsqrte_u32();
4656
                            break;
4657
                        case 58: /* Float VRECPE */
4658
                            gen_op_neon_recpe_f32();
4659
                            break;
4660
                        case 59: /* Float VRSQRTE */
4661
                            gen_op_neon_rsqrte_f32();
4662
                            break;
4663
                        case 60: /* VCVT.F32.S32 */
4664
                            gen_op_vfp_tosizs();
4665
                            break;
4666
                        case 61: /* VCVT.F32.U32 */
4667
                            gen_op_vfp_touizs();
4668
                            break;
4669
                        case 62: /* VCVT.S32.F32 */
4670
                            gen_op_vfp_sitos();
4671
                            break;
4672
                        case 63: /* VCVT.U32.F32 */
4673
                            gen_op_vfp_uitos();
4674
                            break;
4675
                        default:
4676
                            /* Reserved: 21, 29, 39-56 */
4677
                            return 1;
4678
                        }
4679
                        if (op == 30 || op == 31 || op >= 58) {
4680
                            gen_op_vfp_setreg_F0s(neon_reg_offset(rm, pass));
4681
                        } else {
4682
                            NEON_SET_REG(T0, rd, pass);
4683
                        }
4684
                    }
4685
                    break;
4686
                }
4687
            } else if ((insn & (1 << 10)) == 0) {
4688
                /* VTBL, VTBX.  */
4689
                n = (insn >> 5) & 0x18;
4690
                NEON_GET_REG(T1, rm, 0);
4691
                if (insn & (1 << 6)) {
4692
                    NEON_GET_REG(T0, rd, 0);
4693
                } else {
4694
                    gen_op_movl_T0_im(0);
4695
                }
4696
                gen_op_neon_tbl(rn, n);
4697
                gen_op_movl_T2_T0();
4698
                NEON_GET_REG(T1, rm, 1);
4699
                if (insn & (1 << 6)) {
4700
                    NEON_GET_REG(T0, rd, 0);
4701
                } else {
4702
                    gen_op_movl_T0_im(0);
4703
                }
4704
                gen_op_neon_tbl(rn, n);
4705
                NEON_SET_REG(T2, rd, 0);
4706
                NEON_SET_REG(T0, rd, 1);
4707
            } else if ((insn & 0x380) == 0) {
4708
                /* VDUP */
4709
                if (insn & (1 << 19)) {
4710
                    NEON_SET_REG(T0, rm, 1);
4711
                } else {
4712
                    NEON_SET_REG(T0, rm, 0);
4713
                }
4714
                if (insn & (1 << 16)) {
4715
                    gen_op_neon_dup_u8(((insn >> 17) & 3) * 8);
4716
                } else if (insn & (1 << 17)) {
4717
                    if ((insn >> 18) & 1)
4718
                        gen_op_neon_dup_high16();
4719
                    else
4720
                        gen_op_neon_dup_low16();
4721
                }
4722
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4723
                    NEON_SET_REG(T0, rd, pass);
4724
                }
4725
            } else {
4726
                return 1;
4727
            }
4728
        }
4729
    }
4730
    return 0;
4731
}
4732

    
4733
static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
4734
{
4735
    int cpnum;
4736

    
4737
    cpnum = (insn >> 8) & 0xf;
4738
    if (arm_feature(env, ARM_FEATURE_XSCALE)
4739
            && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
4740
        return 1;
4741

    
4742
    switch (cpnum) {
4743
      case 0:
4744
      case 1:
4745
        if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
4746
            return disas_iwmmxt_insn(env, s, insn);
4747
        } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
4748
            return disas_dsp_insn(env, s, insn);
4749
        }
4750
        return 1;
4751
    case 10:
4752
    case 11:
4753
        return disas_vfp_insn (env, s, insn);
4754
    case 15:
4755
        return disas_cp15_insn (env, s, insn);
4756
    default:
4757
        /* Unknown coprocessor.  See if the board has hooked it.  */
4758
        return disas_cp_insn (env, s, insn);
4759
    }
4760
}
4761

    
4762
static void disas_arm_insn(CPUState * env, DisasContext *s)
4763
{
4764
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
4765
    TCGv tmp;
4766

    
4767
    insn = ldl_code(s->pc);
4768
    s->pc += 4;
4769

    
4770
    /* M variants do not implement ARM mode.  */
4771
    if (IS_M(env))
4772
        goto illegal_op;
4773
    cond = insn >> 28;
4774
    if (cond == 0xf){
4775
        /* Unconditional instructions.  */
4776
        if (((insn >> 25) & 7) == 1) {
4777
            /* NEON Data processing.  */
4778
            if (!arm_feature(env, ARM_FEATURE_NEON))
4779
                goto illegal_op;
4780

    
4781
            if (disas_neon_data_insn(env, s, insn))
4782
                goto illegal_op;
4783
            return;
4784
        }
4785
        if ((insn & 0x0f100000) == 0x04000000) {
4786
            /* NEON load/store.  */
4787
            if (!arm_feature(env, ARM_FEATURE_NEON))
4788
                goto illegal_op;
4789

    
4790
            if (disas_neon_ls_insn(env, s, insn))
4791
                goto illegal_op;
4792
            return;
4793
        }
4794
        if ((insn & 0x0d70f000) == 0x0550f000)
4795
            return; /* PLD */
4796
        else if ((insn & 0x0ffffdff) == 0x01010000) {
4797
            ARCH(6);
4798
            /* setend */
4799
            if (insn & (1 << 9)) {
4800
                /* BE8 mode not implemented.  */
4801
                goto illegal_op;
4802
            }
4803
            return;
4804
        } else if ((insn & 0x0fffff00) == 0x057ff000) {
4805
            switch ((insn >> 4) & 0xf) {
4806
            case 1: /* clrex */
4807
                ARCH(6K);
4808
                gen_op_clrex();
4809
                return;
4810
            case 4: /* dsb */
4811
            case 5: /* dmb */
4812
            case 6: /* isb */
4813
                ARCH(7);
4814
                /* We don't emulate caches so these are a no-op.  */
4815
                return;
4816
            default:
4817
                goto illegal_op;
4818
            }
4819
        } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
4820
            /* srs */
4821
            uint32_t offset;
4822
            if (IS_USER(s))
4823
                goto illegal_op;
4824
            ARCH(6);
4825
            op1 = (insn & 0x1f);
4826
            if (op1 == (env->uncached_cpsr & CPSR_M)) {
4827
                gen_movl_T1_reg(s, 13);
4828
            } else {
4829
                gen_op_movl_T1_r13_banked(op1);
4830
            }
4831
            i = (insn >> 23) & 3;
4832
            switch (i) {
4833
            case 0: offset = -4; break; /* DA */
4834
            case 1: offset = -8; break; /* DB */
4835
            case 2: offset = 0; break; /* IA */
4836
            case 3: offset = 4; break; /* IB */
4837
            default: abort();
4838
            }
4839
            if (offset)
4840
                gen_op_addl_T1_im(offset);
4841
            gen_movl_T0_reg(s, 14);
4842
            gen_ldst(stl, s);
4843
            gen_op_movl_T0_cpsr();
4844
            gen_op_addl_T1_im(4);
4845
            gen_ldst(stl, s);
4846
            if (insn & (1 << 21)) {
4847
                /* Base writeback.  */
4848
                switch (i) {
4849
                case 0: offset = -8; break;
4850
                case 1: offset = -4; break;
4851
                case 2: offset = 4; break;
4852
                case 3: offset = 0; break;
4853
                default: abort();
4854
                }
4855
                if (offset)
4856
                    gen_op_addl_T1_im(offset);
4857
                if (op1 == (env->uncached_cpsr & CPSR_M)) {
4858
                    gen_movl_reg_T1(s, 13);
4859
                } else {
4860
                    gen_op_movl_r13_T1_banked(op1);
4861
                }
4862
            }
4863
        } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
4864
            /* rfe */
4865
            uint32_t offset;
4866
            if (IS_USER(s))
4867
                goto illegal_op;
4868
            ARCH(6);
4869
            rn = (insn >> 16) & 0xf;
4870
            gen_movl_T1_reg(s, rn);
4871
            i = (insn >> 23) & 3;
4872
            switch (i) {
4873
            case 0: offset = 0; break; /* DA */
4874
            case 1: offset = -4; break; /* DB */
4875
            case 2: offset = 4; break; /* IA */
4876
            case 3: offset = 8; break; /* IB */
4877
            default: abort();
4878
            }
4879
            if (offset)
4880
                gen_op_addl_T1_im(offset);
4881
            /* Load CPSR into T2 and PC into T0.  */
4882
            gen_ldst(ldl, s);
4883
            gen_op_movl_T2_T0();
4884
            gen_op_addl_T1_im(-4);
4885
            gen_ldst(ldl, s);
4886
            if (insn & (1 << 21)) {
4887
                /* Base writeback.  */
4888
                switch (i) {
4889
                case 0: offset = -4; break;
4890
                case 1: offset = 0; break;
4891
                case 2: offset = 8; break;
4892
                case 3: offset = 4; break;
4893
                default: abort();
4894
                }
4895
                if (offset)
4896
                    gen_op_addl_T1_im(offset);
4897
                gen_movl_reg_T1(s, rn);
4898
            }
4899
            gen_rfe(s);
4900
        } else if ((insn & 0x0e000000) == 0x0a000000) {
4901
            /* branch link and change to thumb (blx <offset>) */
4902
            int32_t offset;
4903

    
4904
            val = (uint32_t)s->pc;
4905
            gen_op_movl_T0_im(val);
4906
            gen_movl_reg_T0(s, 14);
4907
            /* Sign-extend the 24-bit offset */
4908
            offset = (((int32_t)insn) << 8) >> 8;
4909
            /* offset * 4 + bit24 * 2 + (thumb bit) */
4910
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
4911
            /* pipeline offset */
4912
            val += 4;
4913
            gen_op_movl_T0_im(val);
4914
            gen_bx(s);
4915
            return;
4916
        } else if ((insn & 0x0e000f00) == 0x0c000100) {
4917
            if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
4918
                /* iWMMXt register transfer.  */
4919
                if (env->cp15.c15_cpar & (1 << 1))
4920
                    if (!disas_iwmmxt_insn(env, s, insn))
4921
                        return;
4922
            }
4923
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
4924
            /* Coprocessor double register transfer.  */
4925
        } else if ((insn & 0x0f000010) == 0x0e000010) {
4926
            /* Additional coprocessor register transfer.  */
4927
        } else if ((insn & 0x0ff10010) == 0x01000000) {
4928
            uint32_t mask;
4929
            uint32_t val;
4930
            /* cps (privileged) */
4931
            if (IS_USER(s))
4932
                return;
4933
            mask = val = 0;
4934
            if (insn & (1 << 19)) {
4935
                if (insn & (1 << 8))
4936
                    mask |= CPSR_A;
4937
                if (insn & (1 << 7))
4938
                    mask |= CPSR_I;
4939
                if (insn & (1 << 6))
4940
                    mask |= CPSR_F;
4941
                if (insn & (1 << 18))
4942
                    val |= mask;
4943
            }
4944
            if (insn & (1 << 14)) {
4945
                mask |= CPSR_M;
4946
                val |= (insn & 0x1f);
4947
            }
4948
            if (mask) {
4949
                gen_op_movl_T0_im(val);
4950
                gen_set_psr_T0(s, mask, 0);
4951
            }
4952
            return;
4953
        }
4954
        goto illegal_op;
4955
    }
4956
    if (cond != 0xe) {
4957
        /* if not always execute, we generate a conditional jump to
4958
           next instruction */
4959
        s->condlabel = gen_new_label();
4960
        gen_test_cc[cond ^ 1](s->condlabel);
4961
        s->condjmp = 1;
4962
    }
4963
    if ((insn & 0x0f900000) == 0x03000000) {
4964
        if ((insn & (1 << 21)) == 0) {
4965
            ARCH(6T2);
4966
            rd = (insn >> 12) & 0xf;
4967
            val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
4968
            if ((insn & (1 << 22)) == 0) {
4969
                /* MOVW */
4970
                gen_op_movl_T0_im(val);
4971
            } else {
4972
                /* MOVT */
4973
                gen_movl_T0_reg(s, rd);
4974
                gen_op_movl_T1_im(0xffff);
4975
                gen_op_andl_T0_T1();
4976
                gen_op_movl_T1_im(val << 16);
4977
                gen_op_orl_T0_T1();
4978
            }
4979
            gen_movl_reg_T0(s, rd);
4980
        } else {
4981
            if (((insn >> 12) & 0xf) != 0xf)
4982
                goto illegal_op;
4983
            if (((insn >> 16) & 0xf) == 0) {
4984
                gen_nop_hint(s, insn & 0xff);
4985
            } else {
4986
                /* CPSR = immediate */
4987
                val = insn & 0xff;
4988
                shift = ((insn >> 8) & 0xf) * 2;
4989
                if (shift)
4990
                    val = (val >> shift) | (val << (32 - shift));
4991
                gen_op_movl_T0_im(val);
4992
                i = ((insn & (1 << 22)) != 0);
4993
                if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
4994
                    goto illegal_op;
4995
            }
4996
        }
4997
    } else if ((insn & 0x0f900000) == 0x01000000
4998
               && (insn & 0x00000090) != 0x00000090) {
4999
        /* miscellaneous instructions */
5000
        op1 = (insn >> 21) & 3;
5001
        sh = (insn >> 4) & 0xf;
5002
        rm = insn & 0xf;
5003
        switch (sh) {
5004
        case 0x0: /* move program status register */
5005
            if (op1 & 1) {
5006
                /* PSR = reg */
5007
                gen_movl_T0_reg(s, rm);
5008
                i = ((op1 & 2) != 0);
5009
                if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5010
                    goto illegal_op;
5011
            } else {
5012
                /* reg = PSR */
5013
                rd = (insn >> 12) & 0xf;
5014
                if (op1 & 2) {
5015
                    if (IS_USER(s))
5016
                        goto illegal_op;
5017
                    gen_op_movl_T0_spsr();
5018
                } else {
5019
                    gen_op_movl_T0_cpsr();
5020
                }
5021
                gen_movl_reg_T0(s, rd);
5022
            }
5023
            break;
5024
        case 0x1:
5025
            if (op1 == 1) {
5026
                /* branch/exchange thumb (bx).  */
5027
                gen_movl_T0_reg(s, rm);
5028
                gen_bx(s);
5029
            } else if (op1 == 3) {
5030
                /* clz */
5031
                rd = (insn >> 12) & 0xf;
5032
                tmp = load_reg(s, rm);
5033
                gen_helper_clz(tmp, tmp);
5034
                store_reg(s, rd, tmp);
5035
            } else {
5036
                goto illegal_op;
5037
            }
5038
            break;
5039
        case 0x2:
5040
            if (op1 == 1) {
5041
                ARCH(5J); /* bxj */
5042
                /* Trivial implementation equivalent to bx.  */
5043
                gen_movl_T0_reg(s, rm);
5044
                gen_bx(s);
5045
            } else {
5046
                goto illegal_op;
5047
            }
5048
            break;
5049
        case 0x3:
5050
            if (op1 != 1)
5051
              goto illegal_op;
5052

    
5053
            /* branch link/exchange thumb (blx) */
5054
            val = (uint32_t)s->pc;
5055
            gen_op_movl_T1_im(val);
5056
            gen_movl_T0_reg(s, rm);
5057
            gen_movl_reg_T1(s, 14);
5058
            gen_bx(s);
5059
            break;
5060
        case 0x5: /* saturating add/subtract */
5061
            rd = (insn >> 12) & 0xf;
5062
            rn = (insn >> 16) & 0xf;
5063
            gen_movl_T0_reg(s, rm);
5064
            gen_movl_T1_reg(s, rn);
5065
            if (op1 & 2)
5066
                gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
5067
            if (op1 & 1)
5068
                gen_op_subl_T0_T1_saturate();
5069
            else
5070
                gen_op_addl_T0_T1_saturate();
5071
            gen_movl_reg_T0(s, rd);
5072
            break;
5073
        case 7: /* bkpt */
5074
            gen_set_condexec(s);
5075
            gen_op_movl_T0_im((long)s->pc - 4);
5076
            gen_set_pc_T0();
5077
            gen_op_bkpt();
5078
            s->is_jmp = DISAS_JUMP;
5079
            break;
5080
        case 0x8: /* signed multiply */
5081
        case 0xa:
5082
        case 0xc:
5083
        case 0xe:
5084
            rs = (insn >> 8) & 0xf;
5085
            rn = (insn >> 12) & 0xf;
5086
            rd = (insn >> 16) & 0xf;
5087
            if (op1 == 1) {
5088
                /* (32 * 16) >> 16 */
5089
                gen_movl_T0_reg(s, rm);
5090
                gen_movl_T1_reg(s, rs);
5091
                if (sh & 4)
5092
                    gen_op_sarl_T1_im(16);
5093
                else
5094
                    gen_sxth(cpu_T[1]);
5095
                gen_op_imulw_T0_T1();
5096
                if ((sh & 2) == 0) {
5097
                    gen_movl_T1_reg(s, rn);
5098
                    gen_op_addl_T0_T1_setq();
5099
                }
5100
                gen_movl_reg_T0(s, rd);
5101
            } else {
5102
                /* 16 * 16 */
5103
                gen_movl_T0_reg(s, rm);
5104
                gen_movl_T1_reg(s, rs);
5105
                gen_mulxy(sh & 2, sh & 4);
5106
                if (op1 == 2) {
5107
                    gen_op_signbit_T1_T0();
5108
                    gen_op_addq_T0_T1(rn, rd);
5109
                    gen_movl_reg_T0(s, rn);
5110
                    gen_movl_reg_T1(s, rd);
5111
                } else {
5112
                    if (op1 == 0) {
5113
                        gen_movl_T1_reg(s, rn);
5114
                        gen_op_addl_T0_T1_setq();
5115
                    }
5116
                    gen_movl_reg_T0(s, rd);
5117
                }
5118
            }
5119
            break;
5120
        default:
5121
            goto illegal_op;
5122
        }
5123
    } else if (((insn & 0x0e000000) == 0 &&
5124
                (insn & 0x00000090) != 0x90) ||
5125
               ((insn & 0x0e000000) == (1 << 25))) {
5126
        int set_cc, logic_cc, shiftop;
5127

    
5128
        op1 = (insn >> 21) & 0xf;
5129
        set_cc = (insn >> 20) & 1;
5130
        logic_cc = table_logic_cc[op1] & set_cc;
5131

    
5132
        /* data processing instruction */
5133
        if (insn & (1 << 25)) {
5134
            /* immediate operand */
5135
            val = insn & 0xff;
5136
            shift = ((insn >> 8) & 0xf) * 2;
5137
            if (shift)
5138
                val = (val >> shift) | (val << (32 - shift));
5139
            gen_op_movl_T1_im(val);
5140
            if (logic_cc && shift)
5141
                gen_set_CF_bit31(cpu_T[1]);
5142
        } else {
5143
            /* register */
5144
            rm = (insn) & 0xf;
5145
            gen_movl_T1_reg(s, rm);
5146
            shiftop = (insn >> 5) & 3;
5147
            if (!(insn & (1 << 4))) {
5148
                shift = (insn >> 7) & 0x1f;
5149
                gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
5150
            } else {
5151
                rs = (insn >> 8) & 0xf;
5152
                gen_movl_T0_reg(s, rs);
5153
                if (logic_cc) {
5154
                    gen_shift_T1_T0_cc[shiftop]();
5155
                } else {
5156
                    gen_shift_T1_T0[shiftop]();
5157
                }
5158
            }
5159
        }
5160
        if (op1 != 0x0f && op1 != 0x0d) {
5161
            rn = (insn >> 16) & 0xf;
5162
            gen_movl_T0_reg(s, rn);
5163
        }
5164
        rd = (insn >> 12) & 0xf;
5165
        switch(op1) {
5166
        case 0x00:
5167
            gen_op_andl_T0_T1();
5168
            gen_movl_reg_T0(s, rd);
5169
            if (logic_cc)
5170
                gen_op_logic_T0_cc();
5171
            break;
5172
        case 0x01:
5173
            gen_op_xorl_T0_T1();
5174
            gen_movl_reg_T0(s, rd);
5175
            if (logic_cc)
5176
                gen_op_logic_T0_cc();
5177
            break;
5178
        case 0x02:
5179
            if (set_cc && rd == 15) {
5180
                /* SUBS r15, ... is used for exception return.  */
5181
                if (IS_USER(s))
5182
                    goto illegal_op;
5183
                gen_op_subl_T0_T1_cc();
5184
                gen_exception_return(s);
5185
            } else {
5186
                if (set_cc)
5187
                    gen_op_subl_T0_T1_cc();
5188
                else
5189
                    gen_op_subl_T0_T1();
5190
                gen_movl_reg_T0(s, rd);
5191
            }
5192
            break;
5193
        case 0x03:
5194
            if (set_cc)
5195
                gen_op_rsbl_T0_T1_cc();
5196
            else
5197
                gen_op_rsbl_T0_T1();
5198
            gen_movl_reg_T0(s, rd);
5199
            break;
5200
        case 0x04:
5201
            if (set_cc)
5202
                gen_op_addl_T0_T1_cc();
5203
            else
5204
                gen_op_addl_T0_T1();
5205
            gen_movl_reg_T0(s, rd);
5206
            break;
5207
        case 0x05:
5208
            if (set_cc)
5209
                gen_op_adcl_T0_T1_cc();
5210
            else
5211
                gen_adc_T0_T1();
5212
            gen_movl_reg_T0(s, rd);
5213
            break;
5214
        case 0x06:
5215
            if (set_cc)
5216
                gen_op_sbcl_T0_T1_cc();
5217
            else
5218
                gen_op_sbcl_T0_T1();
5219
            gen_movl_reg_T0(s, rd);
5220
            break;
5221
        case 0x07:
5222
            if (set_cc)
5223
                gen_op_rscl_T0_T1_cc();
5224
            else
5225
                gen_op_rscl_T0_T1();
5226
            gen_movl_reg_T0(s, rd);
5227
            break;
5228
        case 0x08:
5229
            if (set_cc) {
5230
                gen_op_andl_T0_T1();
5231
                gen_op_logic_T0_cc();
5232
            }
5233
            break;
5234
        case 0x09:
5235
            if (set_cc) {
5236
                gen_op_xorl_T0_T1();
5237
                gen_op_logic_T0_cc();
5238
            }
5239
            break;
5240
        case 0x0a:
5241
            if (set_cc) {
5242
                gen_op_subl_T0_T1_cc();
5243
            }
5244
            break;
5245
        case 0x0b:
5246
            if (set_cc) {
5247
                gen_op_addl_T0_T1_cc();
5248
            }
5249
            break;
5250
        case 0x0c:
5251
            gen_op_orl_T0_T1();
5252
            gen_movl_reg_T0(s, rd);
5253
            if (logic_cc)
5254
                gen_op_logic_T0_cc();
5255
            break;
5256
        case 0x0d:
5257
            if (logic_cc && rd == 15) {
5258
                /* MOVS r15, ... is used for exception return.  */
5259
                if (IS_USER(s))
5260
                    goto illegal_op;
5261
                gen_op_movl_T0_T1();
5262
                gen_exception_return(s);
5263
            } else {
5264
                gen_movl_reg_T1(s, rd);
5265
                if (logic_cc)
5266
                    gen_op_logic_T1_cc();
5267
            }
5268
            break;
5269
        case 0x0e:
5270
            gen_op_bicl_T0_T1();
5271
            gen_movl_reg_T0(s, rd);
5272
            if (logic_cc)
5273
                gen_op_logic_T0_cc();
5274
            break;
5275
        default:
5276
        case 0x0f:
5277
            gen_op_notl_T1();
5278
            gen_movl_reg_T1(s, rd);
5279
            if (logic_cc)
5280
                gen_op_logic_T1_cc();
5281
            break;
5282
        }
5283
    } else {
5284
        /* other instructions */
5285
        op1 = (insn >> 24) & 0xf;
5286
        switch(op1) {
5287
        case 0x0:
5288
        case 0x1:
5289
            /* multiplies, extra load/stores */
5290
            sh = (insn >> 5) & 3;
5291
            if (sh == 0) {
5292
                if (op1 == 0x0) {
5293
                    rd = (insn >> 16) & 0xf;
5294
                    rn = (insn >> 12) & 0xf;
5295
                    rs = (insn >> 8) & 0xf;
5296
                    rm = (insn) & 0xf;
5297
                    op1 = (insn >> 20) & 0xf;
5298
                    switch (op1) {
5299
                    case 0: case 1: case 2: case 3: case 6:
5300
                        /* 32 bit mul */
5301
                        gen_movl_T0_reg(s, rs);
5302
                        gen_movl_T1_reg(s, rm);
5303
                        gen_op_mul_T0_T1();
5304
                        if (insn & (1 << 22)) {
5305
                            /* Subtract (mls) */
5306
                            ARCH(6T2);
5307
                            gen_movl_T1_reg(s, rn);
5308
                            gen_op_rsbl_T0_T1();
5309
                        } else if (insn & (1 << 21)) {
5310
                            /* Add */
5311
                            gen_movl_T1_reg(s, rn);
5312
                            gen_op_addl_T0_T1();
5313
                        }
5314
                        if (insn & (1 << 20))
5315
                            gen_op_logic_T0_cc();
5316
                        gen_movl_reg_T0(s, rd);
5317
                        break;
5318
                    default:
5319
                        /* 64 bit mul */
5320
                        gen_movl_T0_reg(s, rs);
5321
                        gen_movl_T1_reg(s, rm);
5322
                        if (insn & (1 << 22))
5323
                            gen_op_imull_T0_T1();
5324
                        else
5325
                            gen_op_mull_T0_T1();
5326
                        if (insn & (1 << 21)) /* mult accumulate */
5327
                            gen_op_addq_T0_T1(rn, rd);
5328
                        if (!(insn & (1 << 23))) { /* double accumulate */
5329
                            ARCH(6);
5330
                            gen_op_addq_lo_T0_T1(rn);
5331
                            gen_op_addq_lo_T0_T1(rd);
5332
                        }
5333
                        if (insn & (1 << 20))
5334
                            gen_op_logicq_cc();
5335
                        gen_movl_reg_T0(s, rn);
5336
                        gen_movl_reg_T1(s, rd);
5337
                        break;
5338
                    }
5339
                } else {
5340
                    rn = (insn >> 16) & 0xf;
5341
                    rd = (insn >> 12) & 0xf;
5342
                    if (insn & (1 << 23)) {
5343
                        /* load/store exclusive */
5344
                        gen_movl_T1_reg(s, rn);
5345
                        if (insn & (1 << 20)) {
5346
                            gen_ldst(ldlex, s);
5347
                        } else {
5348
                            rm = insn & 0xf;
5349
                            gen_movl_T0_reg(s, rm);
5350
                            gen_ldst(stlex, s);
5351
                        }
5352
                        gen_movl_reg_T0(s, rd);
5353
                    } else {
5354
                        /* SWP instruction */
5355
                        rm = (insn) & 0xf;
5356

    
5357
                        gen_movl_T0_reg(s, rm);
5358
                        gen_movl_T1_reg(s, rn);
5359
                        if (insn & (1 << 22)) {
5360
                            gen_ldst(swpb, s);
5361
                        } else {
5362
                            gen_ldst(swpl, s);
5363
                        }
5364
                        gen_movl_reg_T0(s, rd);
5365
                    }
5366
                }
5367
            } else {
5368
                int address_offset;
5369
                int load;
5370
                /* Misc load/store */
5371
                rn = (insn >> 16) & 0xf;
5372
                rd = (insn >> 12) & 0xf;
5373
                gen_movl_T1_reg(s, rn);
5374
                if (insn & (1 << 24))
5375
                    gen_add_datah_offset(s, insn, 0);
5376
                address_offset = 0;
5377
                if (insn & (1 << 20)) {
5378
                    /* load */
5379
                    switch(sh) {
5380
                    case 1:
5381
                        gen_ldst(lduw, s);
5382
                        break;
5383
                    case 2:
5384
                        gen_ldst(ldsb, s);
5385
                        break;
5386
                    default:
5387
                    case 3:
5388
                        gen_ldst(ldsw, s);
5389
                        break;
5390
                    }
5391
                    load = 1;
5392
                } else if (sh & 2) {
5393
                    /* doubleword */
5394
                    if (sh & 1) {
5395
                        /* store */
5396
                        gen_movl_T0_reg(s, rd);
5397
                        gen_ldst(stl, s);
5398
                        gen_op_addl_T1_im(4);
5399
                        gen_movl_T0_reg(s, rd + 1);
5400
                        gen_ldst(stl, s);
5401
                        load = 0;
5402
                    } else {
5403
                        /* load */
5404
                        gen_ldst(ldl, s);
5405
                        gen_movl_reg_T0(s, rd);
5406
                        gen_op_addl_T1_im(4);
5407
                        gen_ldst(ldl, s);
5408
                        rd++;
5409
                        load = 1;
5410
                    }
5411
                    address_offset = -4;
5412
                } else {
5413
                    /* store */
5414
                    gen_movl_T0_reg(s, rd);
5415
                    gen_ldst(stw, s);
5416
                    load = 0;
5417
                }
5418
                /* Perform base writeback before the loaded value to
5419
                   ensure correct behavior with overlapping index registers.
5420
                   ldrd with base writeback is is undefined if the
5421
                   destination and index registers overlap.  */
5422
                if (!(insn & (1 << 24))) {
5423
                    gen_add_datah_offset(s, insn, address_offset);
5424
                    gen_movl_reg_T1(s, rn);
5425
                } else if (insn & (1 << 21)) {
5426
                    if (address_offset)
5427
                        gen_op_addl_T1_im(address_offset);
5428
                    gen_movl_reg_T1(s, rn);
5429
                }
5430
                if (load) {
5431
                    /* Complete the load.  */
5432
                    gen_movl_reg_T0(s, rd);
5433
                }
5434
            }
5435
            break;
5436
        case 0x4:
5437
        case 0x5:
5438
            goto do_ldst;
5439
        case 0x6:
5440
        case 0x7:
5441
            if (insn & (1 << 4)) {
5442
                ARCH(6);
5443
                /* Armv6 Media instructions.  */
5444
                rm = insn & 0xf;
5445
                rn = (insn >> 16) & 0xf;
5446
                rd = (insn >> 12) & 0xf;
5447
                rs = (insn >> 8) & 0xf;
5448
                switch ((insn >> 23) & 3) {
5449
                case 0: /* Parallel add/subtract.  */
5450
                    op1 = (insn >> 20) & 7;
5451
                    gen_movl_T0_reg(s, rn);
5452
                    gen_movl_T1_reg(s, rm);
5453
                    sh = (insn >> 5) & 7;
5454
                    if ((op1 & 3) == 0 || sh == 5 || sh == 6)
5455
                        goto illegal_op;
5456
                    gen_arm_parallel_addsub[op1][sh]();
5457
                    gen_movl_reg_T0(s, rd);
5458
                    break;
5459
                case 1:
5460
                    if ((insn & 0x00700020) == 0) {
5461
                        /* Hafword pack.  */
5462
                        gen_movl_T0_reg(s, rn);
5463
                        gen_movl_T1_reg(s, rm);
5464
                        shift = (insn >> 7) & 0x1f;
5465
                        if (shift)
5466
                            gen_op_shll_T1_im(shift);
5467
                        if (insn & (1 << 6))
5468
                            gen_op_pkhtb_T0_T1();
5469
                        else
5470
                            gen_op_pkhbt_T0_T1();
5471
                        gen_movl_reg_T0(s, rd);
5472
                    } else if ((insn & 0x00200020) == 0x00200000) {
5473
                        /* [us]sat */
5474
                        gen_movl_T1_reg(s, rm);
5475
                        shift = (insn >> 7) & 0x1f;
5476
                        if (insn & (1 << 6)) {
5477
                            if (shift == 0)
5478
                                shift = 31;
5479
                            gen_op_sarl_T1_im(shift);
5480
                        } else {
5481
                            gen_op_shll_T1_im(shift);
5482
                        }
5483
                        sh = (insn >> 16) & 0x1f;
5484
                        if (sh != 0) {
5485
                            if (insn & (1 << 22))
5486
                                gen_op_usat_T1(sh);
5487
                            else
5488
                                gen_op_ssat_T1(sh);
5489
                        }
5490
                        gen_movl_T1_reg(s, rd);
5491
                    } else if ((insn & 0x00300fe0) == 0x00200f20) {
5492
                        /* [us]sat16 */
5493
                        gen_movl_T1_reg(s, rm);
5494
                        sh = (insn >> 16) & 0x1f;
5495
                        if (sh != 0) {
5496
                            if (insn & (1 << 22))
5497
                                gen_op_usat16_T1(sh);
5498
                            else
5499
                                gen_op_ssat16_T1(sh);
5500
                        }
5501
                        gen_movl_T1_reg(s, rd);
5502
                    } else if ((insn & 0x00700fe0) == 0x00000fa0) {
5503
                        /* Select bytes.  */
5504
                        gen_movl_T0_reg(s, rn);
5505
                        gen_movl_T1_reg(s, rm);
5506
                        gen_op_sel_T0_T1();
5507
                        gen_movl_reg_T0(s, rd);
5508
                    } else if ((insn & 0x000003e0) == 0x00000060) {
5509
                        gen_movl_T1_reg(s, rm);
5510
                        shift = (insn >> 10) & 3;
5511
                        /* ??? In many cases it's not neccessary to do a
5512
                           rotate, a shift is sufficient.  */
5513
                        if (shift != 0)
5514
                            gen_op_rorl_T1_im(shift * 8);
5515
                        op1 = (insn >> 20) & 7;
5516
                        switch (op1) {
5517
                        case 0: gen_sxtb16(cpu_T[1]); break;
5518
                        case 2: gen_sxtb(cpu_T[1]);   break;
5519
                        case 3: gen_sxth(cpu_T[1]);   break;
5520
                        case 4: gen_uxtb16(cpu_T[1]); break;
5521
                        case 6: gen_uxtb(cpu_T[1]);   break;
5522
                        case 7: gen_uxth(cpu_T[1]);   break;
5523
                        default: goto illegal_op;
5524
                        }
5525
                        if (rn != 15) {
5526
                            tmp = load_reg(s, rn);
5527
                            if ((op1 & 3) == 0) {
5528
                                gen_add16(cpu_T[1], tmp);
5529
                            } else {
5530
                                tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
5531
                                dead_tmp(tmp);
5532
                            }
5533
                        }
5534
                        gen_movl_reg_T1(s, rd);
5535
                    } else if ((insn & 0x003f0f60) == 0x003f0f20) {
5536
                        /* rev */
5537
                        gen_movl_T0_reg(s, rm);
5538
                        if (insn & (1 << 22)) {
5539
                            if (insn & (1 << 7)) {
5540
                                gen_op_revsh_T0();
5541
                            } else {
5542
                                ARCH(6T2);
5543
                                gen_op_rbit_T0();
5544
                            }
5545
                        } else {
5546
                            if (insn & (1 << 7))
5547
                                gen_op_rev16_T0();
5548
                            else
5549
                                gen_op_rev_T0();
5550
                        }
5551
                        gen_movl_reg_T0(s, rd);
5552
                    } else {
5553
                        goto illegal_op;
5554
                    }
5555
                    break;
5556
                case 2: /* Multiplies (Type 3).  */
5557
                    gen_movl_T0_reg(s, rm);
5558
                    gen_movl_T1_reg(s, rs);
5559
                    if (insn & (1 << 20)) {
5560
                        /* Signed multiply most significant [accumulate].  */
5561
                        gen_op_imull_T0_T1();
5562
                        if (insn & (1 << 5))
5563
                            gen_op_roundqd_T0_T1();
5564
                        else
5565
                            gen_op_movl_T0_T1();
5566
                        if (rn != 15) {
5567
                            gen_movl_T1_reg(s, rn);
5568
                            if (insn & (1 << 6)) {
5569
                                gen_op_addl_T0_T1();
5570
                            } else {
5571
                                gen_op_rsbl_T0_T1();
5572
                            }
5573
                        }
5574
                        gen_movl_reg_T0(s, rd);
5575
                    } else {
5576
                        if (insn & (1 << 5))
5577
                            gen_op_swap_half_T1();
5578
                        gen_op_mul_dual_T0_T1();
5579
                        if (insn & (1 << 22)) {
5580
                            if (insn & (1 << 6)) {
5581
                                /* smlald */
5582
                                gen_op_addq_T0_T1_dual(rn, rd);
5583
                            } else {
5584
                                /* smlsld */
5585
                                gen_op_subq_T0_T1_dual(rn, rd);
5586
                            }
5587
                        } else {
5588
                            /* This addition cannot overflow.  */
5589
                            if (insn & (1 << 6)) {
5590
                                /* sm[ul]sd */
5591
                                gen_op_subl_T0_T1();
5592
                            } else {
5593
                                /* sm[ul]ad */
5594
                                gen_op_addl_T0_T1();
5595
                            }
5596
                            if (rn != 15)
5597
                              {
5598
                                gen_movl_T1_reg(s, rn);
5599
                                gen_op_addl_T0_T1_setq();
5600
                              }
5601
                            gen_movl_reg_T0(s, rd);
5602
                        }
5603
                    }
5604
                    break;
5605
                case 3:
5606
                    op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
5607
                    switch (op1) {
5608
                    case 0: /* Unsigned sum of absolute differences.  */
5609
                            goto illegal_op;
5610
                        gen_movl_T0_reg(s, rm);
5611
                        gen_movl_T1_reg(s, rs);
5612
                        gen_op_usad8_T0_T1();
5613
                        if (rn != 15) {
5614
                            gen_movl_T1_reg(s, rn);
5615
                            gen_op_addl_T0_T1();
5616
                        }
5617
                        gen_movl_reg_T0(s, rd);
5618
                        break;
5619
                    case 0x20: case 0x24: case 0x28: case 0x2c:
5620
                        /* Bitfield insert/clear.  */
5621
                        ARCH(6T2);
5622
                        shift = (insn >> 7) & 0x1f;
5623
                        i = (insn >> 16) & 0x1f;
5624
                        i = i + 1 - shift;
5625
                        if (rm == 15) {
5626
                            gen_op_movl_T1_im(0);
5627
                        } else {
5628
                            gen_movl_T1_reg(s, rm);
5629
                        }
5630
                        if (i != 32) {
5631
                            gen_movl_T0_reg(s, rd);
5632
                            gen_op_bfi_T1_T0(shift, ((1u << i) - 1) << shift);
5633
                        }
5634
                        gen_movl_reg_T1(s, rd);
5635
                        break;
5636
                    case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
5637
                    case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
5638
                        gen_movl_T1_reg(s, rm);
5639
                        shift = (insn >> 7) & 0x1f;
5640
                        i = ((insn >> 16) & 0x1f) + 1;
5641
                        if (shift + i > 32)
5642
                            goto illegal_op;
5643
                        if (i < 32) {
5644
                            if (op1 & 0x20) {
5645
                                gen_op_ubfx_T1(shift, (1u << i) - 1);
5646
                            } else {
5647
                                gen_op_sbfx_T1(shift, i);
5648
                            }
5649
                        }
5650
                        gen_movl_reg_T1(s, rd);
5651
                        break;
5652
                    default:
5653
                        goto illegal_op;
5654
                    }
5655
                    break;
5656
                }
5657
                break;
5658
            }
5659
        do_ldst:
5660
            /* Check for undefined extension instructions
5661
             * per the ARM Bible IE:
5662
             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx
5663
             */
5664
            sh = (0xf << 20) | (0xf << 4);
5665
            if (op1 == 0x7 && ((insn & sh) == sh))
5666
            {
5667
                goto illegal_op;
5668
            }
5669
            /* load/store byte/word */
5670
            rn = (insn >> 16) & 0xf;
5671
            rd = (insn >> 12) & 0xf;
5672
            gen_movl_T1_reg(s, rn);
5673
            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
5674
            if (insn & (1 << 24))
5675
                gen_add_data_offset(s, insn);
5676
            if (insn & (1 << 20)) {
5677
                /* load */
5678
                s->is_mem = 1;
5679
#if defined(CONFIG_USER_ONLY)
5680
                if (insn & (1 << 22))
5681
                    gen_op_ldub_raw();
5682
                else
5683
                    gen_op_ldl_raw();
5684
#else
5685
                if (insn & (1 << 22)) {
5686
                    if (i)
5687
                        gen_op_ldub_user();
5688
                    else
5689
                        gen_op_ldub_kernel();
5690
                } else {
5691
                    if (i)
5692
                        gen_op_ldl_user();
5693
                    else
5694
                        gen_op_ldl_kernel();
5695
                }
5696
#endif
5697
            } else {
5698
                /* store */
5699
                gen_movl_T0_reg(s, rd);
5700
#if defined(CONFIG_USER_ONLY)
5701
                if (insn & (1 << 22))
5702
                    gen_op_stb_raw();
5703
                else
5704
                    gen_op_stl_raw();
5705
#else
5706
                if (insn & (1 << 22)) {
5707
                    if (i)
5708
                        gen_op_stb_user();
5709
                    else
5710
                        gen_op_stb_kernel();
5711
                } else {
5712
                    if (i)
5713
                        gen_op_stl_user();
5714
                    else
5715
                        gen_op_stl_kernel();
5716
                }
5717
#endif
5718
            }
5719
            if (!(insn & (1 << 24))) {
5720
                gen_add_data_offset(s, insn);
5721
                gen_movl_reg_T1(s, rn);
5722
            } else if (insn & (1 << 21))
5723
                gen_movl_reg_T1(s, rn); {
5724
            }
5725
            if (insn & (1 << 20)) {
5726
                /* Complete the load.  */
5727
                if (rd == 15)
5728
                    gen_bx(s);
5729
                else
5730
                    gen_movl_reg_T0(s, rd);
5731
            }
5732
            break;
5733
        case 0x08:
5734
        case 0x09:
5735
            {
5736
                int j, n, user, loaded_base;
5737
                /* load/store multiple words */
5738
                /* XXX: store correct base if write back */
5739
                user = 0;
5740
                if (insn & (1 << 22)) {
5741
                    if (IS_USER(s))
5742
                        goto illegal_op; /* only usable in supervisor mode */
5743

    
5744
                    if ((insn & (1 << 15)) == 0)
5745
                        user = 1;
5746
                }
5747
                rn = (insn >> 16) & 0xf;
5748
                gen_movl_T1_reg(s, rn);
5749

    
5750
                /* compute total size */
5751
                loaded_base = 0;
5752
                n = 0;
5753
                for(i=0;i<16;i++) {
5754
                    if (insn & (1 << i))
5755
                        n++;
5756
                }
5757
                /* XXX: test invalid n == 0 case ? */
5758
                if (insn & (1 << 23)) {
5759
                    if (insn & (1 << 24)) {
5760
                        /* pre increment */
5761
                        gen_op_addl_T1_im(4);
5762
                    } else {
5763
                        /* post increment */
5764
                    }
5765
                } else {
5766
                    if (insn & (1 << 24)) {
5767
                        /* pre decrement */
5768
                        gen_op_addl_T1_im(-(n * 4));
5769
                    } else {
5770
                        /* post decrement */
5771
                        if (n != 1)
5772
                            gen_op_addl_T1_im(-((n - 1) * 4));
5773
                    }
5774
                }
5775
                j = 0;
5776
                for(i=0;i<16;i++) {
5777
                    if (insn & (1 << i)) {
5778
                        if (insn & (1 << 20)) {
5779
                            /* load */
5780
                            gen_ldst(ldl, s);
5781
                            if (i == 15) {
5782
                                gen_bx(s);
5783
                            } else if (user) {
5784
                                gen_op_movl_user_T0(i);
5785
                            } else if (i == rn) {
5786
                                gen_op_movl_T2_T0();
5787
                                loaded_base = 1;
5788
                            } else {
5789
                                gen_movl_reg_T0(s, i);
5790
                            }
5791
                        } else {
5792
                            /* store */
5793
                            if (i == 15) {
5794
                                /* special case: r15 = PC + 8 */
5795
                                val = (long)s->pc + 4;
5796
                                gen_op_movl_T0_im(val);
5797
                            } else if (user) {
5798
                                gen_op_movl_T0_user(i);
5799
                            } else {
5800
                                gen_movl_T0_reg(s, i);
5801
                            }
5802
                            gen_ldst(stl, s);
5803
                        }
5804
                        j++;
5805
                        /* no need to add after the last transfer */
5806
                        if (j != n)
5807
                            gen_op_addl_T1_im(4);
5808
                    }
5809
                }
5810
                if (insn & (1 << 21)) {
5811
                    /* write back */
5812
                    if (insn & (1 << 23)) {
5813
                        if (insn & (1 << 24)) {
5814
                            /* pre increment */
5815
                        } else {
5816
                            /* post increment */
5817
                            gen_op_addl_T1_im(4);
5818
                        }
5819
                    } else {
5820
                        if (insn & (1 << 24)) {
5821
                            /* pre decrement */
5822
                            if (n != 1)
5823
                                gen_op_addl_T1_im(-((n - 1) * 4));
5824
                        } else {
5825
                            /* post decrement */
5826
                            gen_op_addl_T1_im(-(n * 4));
5827
                        }
5828
                    }
5829
                    gen_movl_reg_T1(s, rn);
5830
                }
5831
                if (loaded_base) {
5832
                    gen_op_movl_T0_T2();
5833
                    gen_movl_reg_T0(s, rn);
5834
                }
5835
                if ((insn & (1 << 22)) && !user) {
5836
                    /* Restore CPSR from SPSR.  */
5837
                    gen_op_movl_T0_spsr();
5838
                    gen_op_movl_cpsr_T0(0xffffffff);
5839
                    s->is_jmp = DISAS_UPDATE;
5840
                }
5841
            }
5842
            break;
5843
        case 0xa:
5844
        case 0xb:
5845
            {
5846
                int32_t offset;
5847

    
5848
                /* branch (and link) */
5849
                val = (int32_t)s->pc;
5850
                if (insn & (1 << 24)) {
5851
                    gen_op_movl_T0_im(val);
5852
                    gen_movl_reg_T0(s, 14);
5853
                }
5854
                offset = (((int32_t)insn << 8) >> 8);
5855
                val += (offset << 2) + 4;
5856
                gen_jmp(s, val);
5857
            }
5858
            break;
5859
        case 0xc:
5860
        case 0xd:
5861
        case 0xe:
5862
            /* Coprocessor.  */
5863
            if (disas_coproc_insn(env, s, insn))
5864
                goto illegal_op;
5865
            break;
5866
        case 0xf:
5867
            /* swi */
5868
            gen_op_movl_T0_im((long)s->pc);
5869
            gen_set_pc_T0();
5870
            s->is_jmp = DISAS_SWI;
5871
            break;
5872
        default:
5873
        illegal_op:
5874
            gen_set_condexec(s);
5875
            gen_op_movl_T0_im((long)s->pc - 4);
5876
            gen_set_pc_T0();
5877
            gen_op_undef_insn();
5878
            s->is_jmp = DISAS_JUMP;
5879
            break;
5880
        }
5881
    }
5882
}
5883

    
5884
/* Return true if this is a Thumb-2 logical op.  */
5885
static int
5886
thumb2_logic_op(int op)
5887
{
5888
    return (op < 8);
5889
}
5890

    
5891
/* Generate code for a Thumb-2 data processing operation.  If CONDS is nonzero
5892
   then set condition code flags based on the result of the operation.
5893
   If SHIFTER_OUT is nonzero then set the carry flag for logical operations
5894
   to the high bit of T1.
5895
   Returns zero if the opcode is valid.  */
5896

    
5897
static int
5898
gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
5899
{
5900
    int logic_cc;
5901

    
5902
    logic_cc = 0;
5903
    switch (op) {
5904
    case 0: /* and */
5905
        gen_op_andl_T0_T1();
5906
        logic_cc = conds;
5907
        break;
5908
    case 1: /* bic */
5909
        gen_op_bicl_T0_T1();
5910
        logic_cc = conds;
5911
        break;
5912
    case 2: /* orr */
5913
        gen_op_orl_T0_T1();
5914
        logic_cc = conds;
5915
        break;
5916
    case 3: /* orn */
5917
        gen_op_notl_T1();
5918
        gen_op_orl_T0_T1();
5919
        logic_cc = conds;
5920
        break;
5921
    case 4: /* eor */
5922
        gen_op_xorl_T0_T1();
5923
        logic_cc = conds;
5924
        break;
5925
    case 8: /* add */
5926
        if (conds)
5927
            gen_op_addl_T0_T1_cc();
5928
        else
5929
            gen_op_addl_T0_T1();
5930
        break;
5931
    case 10: /* adc */
5932
        if (conds)
5933
            gen_op_adcl_T0_T1_cc();
5934
        else
5935
            gen_adc_T0_T1();
5936
        break;
5937
    case 11: /* sbc */
5938
        if (conds)
5939
            gen_op_sbcl_T0_T1_cc();
5940
        else
5941
            gen_op_sbcl_T0_T1();
5942
        break;
5943
    case 13: /* sub */
5944
        if (conds)
5945
            gen_op_subl_T0_T1_cc();
5946
        else
5947
            gen_op_subl_T0_T1();
5948
        break;
5949
    case 14: /* rsb */
5950
        if (conds)
5951
            gen_op_rsbl_T0_T1_cc();
5952
        else
5953
            gen_op_rsbl_T0_T1();
5954
        break;
5955
    default: /* 5, 6, 7, 9, 12, 15. */
5956
        return 1;
5957
    }
5958
    if (logic_cc) {
5959
        gen_op_logic_T0_cc();
5960
        if (shifter_out)
5961
            gen_set_CF_bit31(cpu_T[1]);
5962
    }
5963
    return 0;
5964
}
5965

    
5966
/* Translate a 32-bit thumb instruction.  Returns nonzero if the instruction
5967
   is not legal.  */
5968
static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
5969
{
5970
    uint32_t insn, imm, shift, offset, addr;
5971
    uint32_t rd, rn, rm, rs;
5972
    TCGv tmp;
5973
    int op;
5974
    int shiftop;
5975
    int conds;
5976
    int logic_cc;
5977

    
5978
    if (!(arm_feature(env, ARM_FEATURE_THUMB2)
5979
          || arm_feature (env, ARM_FEATURE_M))) {
5980
        /* Thumb-1 cores may need to tread bl and blx as a pair of
5981
           16-bit instructions to get correct prefetch abort behavior.  */
5982
        insn = insn_hw1;
5983
        if ((insn & (1 << 12)) == 0) {
5984
            /* Second half of blx.  */
5985
            offset = ((insn & 0x7ff) << 1);
5986
            gen_movl_T0_reg(s, 14);
5987
            gen_op_movl_T1_im(offset);
5988
            gen_op_addl_T0_T1();
5989
            gen_op_movl_T1_im(0xfffffffc);
5990
            gen_op_andl_T0_T1();
5991

    
5992
            addr = (uint32_t)s->pc;
5993
            gen_op_movl_T1_im(addr | 1);
5994
            gen_movl_reg_T1(s, 14);
5995
            gen_bx(s);
5996
            return 0;
5997
        }
5998
        if (insn & (1 << 11)) {
5999
            /* Second half of bl.  */
6000
            offset = ((insn & 0x7ff) << 1) | 1;
6001
            gen_movl_T0_reg(s, 14);
6002
            gen_op_movl_T1_im(offset);
6003
            gen_op_addl_T0_T1();
6004

    
6005
            addr = (uint32_t)s->pc;
6006
            gen_op_movl_T1_im(addr | 1);
6007
            gen_movl_reg_T1(s, 14);
6008
            gen_bx(s);
6009
            return 0;
6010
        }
6011
        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
6012
            /* Instruction spans a page boundary.  Implement it as two
6013
               16-bit instructions in case the second half causes an
6014
               prefetch abort.  */
6015
            offset = ((int32_t)insn << 21) >> 9;
6016
            addr = s->pc + 2 + offset;
6017
            gen_op_movl_T0_im(addr);
6018
            gen_movl_reg_T0(s, 14);
6019
            return 0;
6020
        }
6021
        /* Fall through to 32-bit decode.  */
6022
    }
6023

    
6024
    insn = lduw_code(s->pc);
6025
    s->pc += 2;
6026
    insn |= (uint32_t)insn_hw1 << 16;
6027

    
6028
    if ((insn & 0xf800e800) != 0xf000e800) {
6029
        ARCH(6T2);
6030
    }
6031

    
6032
    rn = (insn >> 16) & 0xf;
6033
    rs = (insn >> 12) & 0xf;
6034
    rd = (insn >> 8) & 0xf;
6035
    rm = insn & 0xf;
6036
    switch ((insn >> 25) & 0xf) {
6037
    case 0: case 1: case 2: case 3:
6038
        /* 16-bit instructions.  Should never happen.  */
6039
        abort();
6040
    case 4:
6041
        if (insn & (1 << 22)) {
6042
            /* Other load/store, table branch.  */
6043
            if (insn & 0x01200000) {
6044
                /* Load/store doubleword.  */
6045
                if (rn == 15) {
6046
                    gen_op_movl_T1_im(s->pc & ~3);
6047
                } else {
6048
                    gen_movl_T1_reg(s, rn);
6049
                }
6050
                offset = (insn & 0xff) * 4;
6051
                if ((insn & (1 << 23)) == 0)
6052
                    offset = -offset;
6053
                if (insn & (1 << 24)) {
6054
                    gen_op_addl_T1_im(offset);
6055
                    offset = 0;
6056
                }
6057
                if (insn & (1 << 20)) {
6058
                    /* ldrd */
6059
                    gen_ldst(ldl, s);
6060
                    gen_movl_reg_T0(s, rs);
6061
                    gen_op_addl_T1_im(4);
6062
                    gen_ldst(ldl, s);
6063
                    gen_movl_reg_T0(s, rd);
6064
                } else {
6065
                    /* strd */
6066
                    gen_movl_T0_reg(s, rs);
6067
                    gen_ldst(stl, s);
6068
                    gen_op_addl_T1_im(4);
6069
                    gen_movl_T0_reg(s, rd);
6070
                    gen_ldst(stl, s);
6071
                }
6072
                if (insn & (1 << 21)) {
6073
                    /* Base writeback.  */
6074
                    if (rn == 15)
6075
                        goto illegal_op;
6076
                    gen_op_addl_T1_im(offset - 4);
6077
                    gen_movl_reg_T1(s, rn);
6078
                }
6079
            } else if ((insn & (1 << 23)) == 0) {
6080
                /* Load/store exclusive word.  */
6081
                gen_movl_T0_reg(s, rd);
6082
                gen_movl_T1_reg(s, rn);
6083
                if (insn & (1 << 20)) {
6084
                    gen_ldst(ldlex, s);
6085
                } else {
6086
                    gen_ldst(stlex, s);
6087
                }
6088
                gen_movl_reg_T0(s, rd);
6089
            } else if ((insn & (1 << 6)) == 0) {
6090
                /* Table Branch.  */
6091
                if (rn == 15) {
6092
                    gen_op_movl_T1_im(s->pc);
6093
                } else {
6094
                    gen_movl_T1_reg(s, rn);
6095
                }
6096
                tmp = load_reg(s, rm);
6097
                tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6098
                if (insn & (1 << 4)) {
6099
                    /* tbh */
6100
                    tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6101
                    dead_tmp(tmp);
6102
                    gen_ldst(lduw, s);
6103
                } else { /* tbb */
6104
                    dead_tmp(tmp);
6105
                    gen_ldst(ldub, s);
6106
                }
6107
                gen_op_jmp_T0_im(s->pc);
6108
                s->is_jmp = DISAS_JUMP;
6109
            } else {
6110
                /* Load/store exclusive byte/halfword/doubleword.  */
6111
                op = (insn >> 4) & 0x3;
6112
                gen_movl_T1_reg(s, rn);
6113
                if (insn & (1 << 20)) {
6114
                    switch (op) {
6115
                    case 0:
6116
                        gen_ldst(ldbex, s);
6117
                        break;
6118
                    case 1:
6119
                        gen_ldst(ldwex, s);
6120
                        break;
6121
                    case 3:
6122
                        gen_ldst(ldqex, s);
6123
                        gen_movl_reg_T1(s, rd);
6124
                        break;
6125
                    default:
6126
                        goto illegal_op;
6127
                    }
6128
                    gen_movl_reg_T0(s, rs);
6129
                } else {
6130
                    gen_movl_T0_reg(s, rs);
6131
                    switch (op) {
6132
                    case 0:
6133
                        gen_ldst(stbex, s);
6134
                        break;
6135
                    case 1:
6136
                        gen_ldst(stwex, s);
6137
                        break;
6138
                    case 3:
6139
                        gen_movl_T2_reg(s, rd);
6140
                        gen_ldst(stqex, s);
6141
                        break;
6142
                    default:
6143
                        goto illegal_op;
6144
                    }
6145
                    gen_movl_reg_T0(s, rm);
6146
                }
6147
            }
6148
        } else {
6149
            /* Load/store multiple, RFE, SRS.  */
6150
            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
6151
                /* Not available in user mode.  */
6152
                if (!IS_USER(s))
6153
                    goto illegal_op;
6154
                if (insn & (1 << 20)) {
6155
                    /* rfe */
6156
                    gen_movl_T1_reg(s, rn);
6157
                    if (insn & (1 << 24)) {
6158
                        gen_op_addl_T1_im(4);
6159
                    } else {
6160
                        gen_op_addl_T1_im(-4);
6161
                    }
6162
                    /* Load CPSR into T2 and PC into T0.  */
6163
                    gen_ldst(ldl, s);
6164
                    gen_op_movl_T2_T0();
6165
                    gen_op_addl_T1_im(-4);
6166
                    gen_ldst(ldl, s);
6167
                    if (insn & (1 << 21)) {
6168
                        /* Base writeback.  */
6169
                        if (insn & (1 << 24))
6170
                            gen_op_addl_T1_im(8);
6171
                        gen_movl_reg_T1(s, rn);
6172
                    }
6173
                    gen_rfe(s);
6174
                } else {
6175
                    /* srs */
6176
                    op = (insn & 0x1f);
6177
                    if (op == (env->uncached_cpsr & CPSR_M)) {
6178
                        gen_movl_T1_reg(s, 13);
6179
                    } else {
6180
                        gen_op_movl_T1_r13_banked(op);
6181
                    }
6182
                    if ((insn & (1 << 24)) == 0) {
6183
                        gen_op_addl_T1_im(-8);
6184
                    }
6185
                    gen_movl_T0_reg(s, 14);
6186
                    gen_ldst(stl, s);
6187
                    gen_op_movl_T0_cpsr();
6188
                    gen_op_addl_T1_im(4);
6189
                    gen_ldst(stl, s);
6190
                    if (insn & (1 << 21)) {
6191
                        if ((insn & (1 << 24)) == 0) {
6192
                            gen_op_addl_T1_im(-4);
6193
                        } else {
6194
                            gen_op_addl_T1_im(4);
6195
                        }
6196
                        if (op == (env->uncached_cpsr & CPSR_M)) {
6197
                            gen_movl_reg_T1(s, 13);
6198
                        } else {
6199
                            gen_op_movl_r13_T1_banked(op);
6200
                        }
6201
                    }
6202
                }
6203
            } else {
6204
                int i;
6205
                /* Load/store multiple.  */
6206
                gen_movl_T1_reg(s, rn);
6207
                offset = 0;
6208
                for (i = 0; i < 16; i++) {
6209
                    if (insn & (1 << i))
6210
                        offset += 4;
6211
                }
6212
                if (insn & (1 << 24)) {
6213
                    gen_op_addl_T1_im(-offset);
6214
                }
6215

    
6216
                for (i = 0; i < 16; i++) {
6217
                    if ((insn & (1 << i)) == 0)
6218
                        continue;
6219
                    if (insn & (1 << 20)) {
6220
                        /* Load.  */
6221
                        gen_ldst(ldl, s);
6222
                        if (i == 15) {
6223
                            gen_bx(s);
6224
                        } else {
6225
                            gen_movl_reg_T0(s, i);
6226
                        }
6227
                    } else {
6228
                        /* Store.  */
6229
                        gen_movl_T0_reg(s, i);
6230
                        gen_ldst(stl, s);
6231
                    }
6232
                    gen_op_addl_T1_im(4);
6233
                }
6234
                if (insn & (1 << 21)) {
6235
                    /* Base register writeback.  */
6236
                    if (insn & (1 << 24)) {
6237
                        gen_op_addl_T1_im(-offset);
6238
                    }
6239
                    /* Fault if writeback register is in register list.  */
6240
                    if (insn & (1 << rn))
6241
                        goto illegal_op;
6242
                    gen_movl_reg_T1(s, rn);
6243
                }
6244
            }
6245
        }
6246
        break;
6247
    case 5: /* Data processing register constant shift.  */
6248
        if (rn == 15)
6249
            gen_op_movl_T0_im(0);
6250
        else
6251
            gen_movl_T0_reg(s, rn);
6252
        gen_movl_T1_reg(s, rm);
6253
        op = (insn >> 21) & 0xf;
6254
        shiftop = (insn >> 4) & 3;
6255
        shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6256
        conds = (insn & (1 << 20)) != 0;
6257
        logic_cc = (conds && thumb2_logic_op(op));
6258
        gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
6259
        if (gen_thumb2_data_op(s, op, conds, 0))
6260
            goto illegal_op;
6261
        if (rd != 15)
6262
            gen_movl_reg_T0(s, rd);
6263
        break;
6264
    case 13: /* Misc data processing.  */
6265
        op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
6266
        if (op < 4 && (insn & 0xf000) != 0xf000)
6267
            goto illegal_op;
6268
        switch (op) {
6269
        case 0: /* Register controlled shift.  */
6270
            gen_movl_T0_reg(s, rm);
6271
            gen_movl_T1_reg(s, rn);
6272
            if ((insn & 0x70) != 0)
6273
                goto illegal_op;
6274
            op = (insn >> 21) & 3;
6275
            if (insn & (1 << 20)) {
6276
                gen_shift_T1_T0_cc[op]();
6277
                gen_op_logic_T1_cc();
6278
            } else {
6279
                gen_shift_T1_T0[op]();
6280
            }
6281
            gen_movl_reg_T1(s, rd);
6282
            break;
6283
        case 1: /* Sign/zero extend.  */
6284
            gen_movl_T1_reg(s, rm);
6285
            shift = (insn >> 4) & 3;
6286
            /* ??? In many cases it's not neccessary to do a
6287
               rotate, a shift is sufficient.  */
6288
            if (shift != 0)
6289
                gen_op_rorl_T1_im(shift * 8);
6290
            op = (insn >> 20) & 7;
6291
            switch (op) {
6292
            case 0: gen_sxth(cpu_T[1]);   break;
6293
            case 1: gen_uxth(cpu_T[1]);   break;
6294
            case 2: gen_sxtb16(cpu_T[1]); break;
6295
            case 3: gen_uxtb16(cpu_T[1]); break;
6296
            case 4: gen_sxtb(cpu_T[1]);   break;
6297
            case 5: gen_uxtb(cpu_T[1]);   break;
6298
            default: goto illegal_op;
6299
            }
6300
            if (rn != 15) {
6301
                tmp = load_reg(s, rn);
6302
                if ((op >> 1) == 1) {
6303
                    gen_add16(cpu_T[1], tmp);
6304
                } else {
6305
                    tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6306
                    dead_tmp(tmp);
6307
                }
6308
            }
6309
            gen_movl_reg_T1(s, rd);
6310
            break;
6311
        case 2: /* SIMD add/subtract.  */
6312
            op = (insn >> 20) & 7;
6313
            shift = (insn >> 4) & 7;
6314
            if ((op & 3) == 3 || (shift & 3) == 3)
6315
                goto illegal_op;
6316
            gen_movl_T0_reg(s, rn);
6317
            gen_movl_T1_reg(s, rm);
6318
            gen_thumb2_parallel_addsub[op][shift]();
6319
            gen_movl_reg_T0(s, rd);
6320
            break;
6321
        case 3: /* Other data processing.  */
6322
            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
6323
            if (op < 4) {
6324
                /* Saturating add/subtract.  */
6325
                gen_movl_T0_reg(s, rm);
6326
                gen_movl_T1_reg(s, rn);
6327
                if (op & 2)
6328
                    gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
6329
                if (op & 1)
6330
                    gen_op_subl_T0_T1_saturate();
6331
                else
6332
                    gen_op_addl_T0_T1_saturate();
6333
            } else {
6334
                gen_movl_T0_reg(s, rn);
6335
                switch (op) {
6336
                case 0x0a: /* rbit */
6337
                    gen_op_rbit_T0();
6338
                    break;
6339
                case 0x08: /* rev */
6340
                    gen_op_rev_T0();
6341
                    break;
6342
                case 0x09: /* rev16 */
6343
                    gen_op_rev16_T0();
6344
                    break;
6345
                case 0x0b: /* revsh */
6346
                    gen_op_revsh_T0();
6347
                    break;
6348
                case 0x10: /* sel */
6349
                    gen_movl_T1_reg(s, rm);
6350
                    gen_op_sel_T0_T1();
6351
                    break;
6352
                case 0x18: /* clz */
6353
                    gen_helper_clz(cpu_T[0], cpu_T[0]);
6354
                    break;
6355
                default:
6356
                    goto illegal_op;
6357
                }
6358
            }
6359
            gen_movl_reg_T0(s, rd);
6360
            break;
6361
        case 4: case 5: /* 32-bit multiply.  Sum of absolute differences.  */
6362
            op = (insn >> 4) & 0xf;
6363
            gen_movl_T0_reg(s, rn);
6364
            gen_movl_T1_reg(s, rm);
6365
            switch ((insn >> 20) & 7) {
6366
            case 0: /* 32 x 32 -> 32 */
6367
                gen_op_mul_T0_T1();
6368
                if (rs != 15) {
6369
                    gen_movl_T1_reg(s, rs);
6370
                    if (op)
6371
                        gen_op_rsbl_T0_T1();
6372
                    else
6373
                        gen_op_addl_T0_T1();
6374
                }
6375
                gen_movl_reg_T0(s, rd);
6376
                break;
6377
            case 1: /* 16 x 16 -> 32 */
6378
                gen_mulxy(op & 2, op & 1);
6379
                if (rs != 15) {
6380
                    gen_movl_T1_reg(s, rs);
6381
                    gen_op_addl_T0_T1_setq();
6382
                }
6383
                gen_movl_reg_T0(s, rd);
6384
                break;
6385
            case 2: /* Dual multiply add.  */
6386
            case 4: /* Dual multiply subtract.  */
6387
                if (op)
6388
                    gen_op_swap_half_T1();
6389
                gen_op_mul_dual_T0_T1();
6390
                /* This addition cannot overflow.  */
6391
                if (insn & (1 << 22)) {
6392
                    gen_op_subl_T0_T1();
6393
                } else {
6394
                    gen_op_addl_T0_T1();
6395
                }
6396
                if (rs != 15)
6397
                  {
6398
                    gen_movl_T1_reg(s, rs);
6399
                    gen_op_addl_T0_T1_setq();
6400
                  }
6401
                gen_movl_reg_T0(s, rd);
6402
                break;
6403
            case 3: /* 32 * 16 -> 32msb */
6404
                if (op)
6405
                    gen_op_sarl_T1_im(16);
6406
                else
6407
                    gen_sxth(cpu_T[1]);
6408
                gen_op_imulw_T0_T1();
6409
                if (rs != 15)
6410
                  {
6411
                    gen_movl_T1_reg(s, rs);
6412
                    gen_op_addl_T0_T1_setq();
6413
                  }
6414
                gen_movl_reg_T0(s, rd);
6415
                break;
6416
            case 5: case 6: /* 32 * 32 -> 32msb */
6417
                gen_op_imull_T0_T1();
6418
                if (insn & (1 << 5))
6419
                    gen_op_roundqd_T0_T1();
6420
                else
6421
                    gen_op_movl_T0_T1();
6422
                if (rs != 15) {
6423
                    gen_movl_T1_reg(s, rs);
6424
                    if (insn & (1 << 21)) {
6425
                        gen_op_addl_T0_T1();
6426
                    } else {
6427
                        gen_op_rsbl_T0_T1();
6428
                    }
6429
                }
6430
                gen_movl_reg_T0(s, rd);
6431
                break;
6432
            case 7: /* Unsigned sum of absolute differences.  */
6433
                gen_op_usad8_T0_T1();
6434
                if (rs != 15) {
6435
                    gen_movl_T1_reg(s, rs);
6436
                    gen_op_addl_T0_T1();
6437
                }
6438
                gen_movl_reg_T0(s, rd);
6439
                break;
6440
            }
6441
            break;
6442
        case 6: case 7: /* 64-bit multiply, Divide.  */
6443
            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
6444
            gen_movl_T0_reg(s, rn);
6445
            gen_movl_T1_reg(s, rm);
6446
            if ((op & 0x50) == 0x10) {
6447
                /* sdiv, udiv */
6448
                if (!arm_feature(env, ARM_FEATURE_DIV))
6449
                    goto illegal_op;
6450
                if (op & 0x20)
6451
                    gen_op_udivl_T0_T1();
6452
                else
6453
                    gen_op_sdivl_T0_T1();
6454
                gen_movl_reg_T0(s, rd);
6455
            } else if ((op & 0xe) == 0xc) {
6456
                /* Dual multiply accumulate long.  */
6457
                if (op & 1)
6458
                    gen_op_swap_half_T1();
6459
                gen_op_mul_dual_T0_T1();
6460
                if (op & 0x10) {
6461
                    gen_op_subl_T0_T1();
6462
                } else {
6463
                    gen_op_addl_T0_T1();
6464
                }
6465
                gen_op_signbit_T1_T0();
6466
                gen_op_addq_T0_T1(rs, rd);
6467
                gen_movl_reg_T0(s, rs);
6468
                gen_movl_reg_T1(s, rd);
6469
            } else {
6470
                if (op & 0x20) {
6471
                    /* Unsigned 64-bit multiply  */
6472
                    gen_op_mull_T0_T1();
6473
                } else {
6474
                    if (op & 8) {
6475
                        /* smlalxy */
6476
                        gen_mulxy(op & 2, op & 1);
6477
                        gen_op_signbit_T1_T0();
6478
                    } else {
6479
                        /* Signed 64-bit multiply  */
6480
                        gen_op_imull_T0_T1();
6481
                    }
6482
                }
6483
                if (op & 4) {
6484
                    /* umaal */
6485
                    gen_op_addq_lo_T0_T1(rs);
6486
                    gen_op_addq_lo_T0_T1(rd);
6487
                } else if (op & 0x40) {
6488
                    /* 64-bit accumulate.  */
6489
                    gen_op_addq_T0_T1(rs, rd);
6490
                }
6491
                gen_movl_reg_T0(s, rs);
6492
                gen_movl_reg_T1(s, rd);
6493
            }
6494
            break;
6495
        }
6496
        break;
6497
    case 6: case 7: case 14: case 15:
6498
        /* Coprocessor.  */
6499
        if (((insn >> 24) & 3) == 3) {
6500
            /* Translate into the equivalent ARM encoding.  */
6501
            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
6502
            if (disas_neon_data_insn(env, s, insn))
6503
                goto illegal_op;
6504
        } else {
6505
            if (insn & (1 << 28))
6506
                goto illegal_op;
6507
            if (disas_coproc_insn (env, s, insn))
6508
                goto illegal_op;
6509
        }
6510
        break;
6511
    case 8: case 9: case 10: case 11:
6512
        if (insn & (1 << 15)) {
6513
            /* Branches, misc control.  */
6514
            if (insn & 0x5000) {
6515
                /* Unconditional branch.  */
6516
                /* signextend(hw1[10:0]) -> offset[:12].  */
6517
                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
6518
                /* hw1[10:0] -> offset[11:1].  */
6519
                offset |= (insn & 0x7ff) << 1;
6520
                /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
6521
                   offset[24:22] already have the same value because of the
6522
                   sign extension above.  */
6523
                offset ^= ((~insn) & (1 << 13)) << 10;
6524
                offset ^= ((~insn) & (1 << 11)) << 11;
6525

    
6526
                addr = s->pc;
6527
                if (insn & (1 << 14)) {
6528
                    /* Branch and link.  */
6529
                    gen_op_movl_T1_im(addr | 1);
6530
                    gen_movl_reg_T1(s, 14);
6531
                }
6532

    
6533
                addr += offset;
6534
                if (insn & (1 << 12)) {
6535
                    /* b/bl */
6536
                    gen_jmp(s, addr);
6537
                } else {
6538
                    /* blx */
6539
                    addr &= ~(uint32_t)2;
6540
                    gen_op_movl_T0_im(addr);
6541
                    gen_bx(s);
6542
                }
6543
            } else if (((insn >> 23) & 7) == 7) {
6544
                /* Misc control */
6545
                if (insn & (1 << 13))
6546
                    goto illegal_op;
6547

    
6548
                if (insn & (1 << 26)) {
6549
                    /* Secure monitor call (v6Z) */
6550
                    goto illegal_op; /* not implemented.  */
6551
                } else {
6552
                    op = (insn >> 20) & 7;
6553
                    switch (op) {
6554
                    case 0: /* msr cpsr.  */
6555
                        if (IS_M(env)) {
6556
                            gen_op_v7m_msr_T0(insn & 0xff);
6557
                            gen_movl_reg_T0(s, rn);
6558
                            gen_lookup_tb(s);
6559
                            break;
6560
                        }
6561
                        /* fall through */
6562
                    case 1: /* msr spsr.  */
6563
                        if (IS_M(env))
6564
                            goto illegal_op;
6565
                        gen_movl_T0_reg(s, rn);
6566
                        if (gen_set_psr_T0(s,
6567
                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
6568
                              op == 1))
6569
                            goto illegal_op;
6570
                        break;
6571
                    case 2: /* cps, nop-hint.  */
6572
                        if (((insn >> 8) & 7) == 0) {
6573
                            gen_nop_hint(s, insn & 0xff);
6574
                        }
6575
                        /* Implemented as NOP in user mode.  */
6576
                        if (IS_USER(s))
6577
                            break;
6578
                        offset = 0;
6579
                        imm = 0;
6580
                        if (insn & (1 << 10)) {
6581
                            if (insn & (1 << 7))
6582
                                offset |= CPSR_A;
6583
                            if (insn & (1 << 6))
6584
                                offset |= CPSR_I;
6585
                            if (insn & (1 << 5))
6586
                                offset |= CPSR_F;
6587
                            if (insn & (1 << 9))
6588
                                imm = CPSR_A | CPSR_I | CPSR_F;
6589
                        }
6590
                        if (insn & (1 << 8)) {
6591
                            offset |= 0x1f;
6592
                            imm |= (insn & 0x1f);
6593
                        }
6594
                        if (offset) {
6595
                            gen_op_movl_T0_im(imm);
6596
                            gen_set_psr_T0(s, offset, 0);
6597
                        }
6598
                        break;
6599
                    case 3: /* Special control operations.  */
6600
                        op = (insn >> 4) & 0xf;
6601
                        switch (op) {
6602
                        case 2: /* clrex */
6603
                            gen_op_clrex();
6604
                            break;
6605
                        case 4: /* dsb */
6606
                        case 5: /* dmb */
6607
                        case 6: /* isb */
6608
                            /* These execute as NOPs.  */
6609
                            ARCH(7);
6610
                            break;
6611
                        default:
6612
                            goto illegal_op;
6613
                        }
6614
                        break;
6615
                    case 4: /* bxj */
6616
                        /* Trivial implementation equivalent to bx.  */
6617
                        gen_movl_T0_reg(s, rn);
6618
                        gen_bx(s);
6619
                        break;
6620
                    case 5: /* Exception return.  */
6621
                        /* Unpredictable in user mode.  */
6622
                        goto illegal_op;
6623
                    case 6: /* mrs cpsr.  */
6624
                        if (IS_M(env)) {
6625
                            gen_op_v7m_mrs_T0(insn & 0xff);
6626
                        } else {
6627
                            gen_op_movl_T0_cpsr();
6628
                        }
6629
                        gen_movl_reg_T0(s, rd);
6630
                        break;
6631
                    case 7: /* mrs spsr.  */
6632
                        /* Not accessible in user mode.  */
6633
                        if (IS_USER(s) || IS_M(env))
6634
                            goto illegal_op;
6635
                        gen_op_movl_T0_spsr();
6636
                        gen_movl_reg_T0(s, rd);
6637
                        break;
6638
                    }
6639
                }
6640
            } else {
6641
                /* Conditional branch.  */
6642
                op = (insn >> 22) & 0xf;
6643
                /* Generate a conditional jump to next instruction.  */
6644
                s->condlabel = gen_new_label();
6645
                gen_test_cc[op ^ 1](s->condlabel);
6646
                s->condjmp = 1;
6647

    
6648
                /* offset[11:1] = insn[10:0] */
6649
                offset = (insn & 0x7ff) << 1;
6650
                /* offset[17:12] = insn[21:16].  */
6651
                offset |= (insn & 0x003f0000) >> 4;
6652
                /* offset[31:20] = insn[26].  */
6653
                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
6654
                /* offset[18] = insn[13].  */
6655
                offset |= (insn & (1 << 13)) << 5;
6656
                /* offset[19] = insn[11].  */
6657
                offset |= (insn & (1 << 11)) << 8;
6658

    
6659
                /* jump to the offset */
6660
                addr = s->pc + offset;
6661
                gen_jmp(s, addr);
6662
            }
6663
        } else {
6664
            /* Data processing immediate.  */
6665
            if (insn & (1 << 25)) {
6666
                if (insn & (1 << 24)) {
6667
                    if (insn & (1 << 20))
6668
                        goto illegal_op;
6669
                    /* Bitfield/Saturate.  */
6670
                    op = (insn >> 21) & 7;
6671
                    imm = insn & 0x1f;
6672
                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6673
                    if (rn == 15)
6674
                        gen_op_movl_T1_im(0);
6675
                    else
6676
                        gen_movl_T1_reg(s, rn);
6677
                    switch (op) {
6678
                    case 2: /* Signed bitfield extract.  */
6679
                        imm++;
6680
                        if (shift + imm > 32)
6681
                            goto illegal_op;
6682
                        if (imm < 32)
6683
                            gen_op_sbfx_T1(shift, imm);
6684
                        break;
6685
                    case 6: /* Unsigned bitfield extract.  */
6686
                        imm++;
6687
                        if (shift + imm > 32)
6688
                            goto illegal_op;
6689
                        if (imm < 32)
6690
                            gen_op_ubfx_T1(shift, (1u << imm) - 1);
6691
                        break;
6692
                    case 3: /* Bitfield insert/clear.  */
6693
                        if (imm < shift)
6694
                            goto illegal_op;
6695
                        imm = imm + 1 - shift;
6696
                        if (imm != 32) {
6697
                            gen_movl_T0_reg(s, rd);
6698
                            gen_op_bfi_T1_T0(shift, ((1u << imm) - 1) << shift);
6699
                        }
6700
                        break;
6701
                    case 7:
6702
                        goto illegal_op;
6703
                    default: /* Saturate.  */
6704
                        gen_movl_T1_reg(s, rn);
6705
                        if (shift) {
6706
                            if (op & 1)
6707
                                gen_op_sarl_T1_im(shift);
6708
                            else
6709
                                gen_op_shll_T1_im(shift);
6710
                        }
6711
                        if (op & 4) {
6712
                            /* Unsigned.  */
6713
                            gen_op_ssat_T1(imm);
6714
                            if ((op & 1) && shift == 0)
6715
                                gen_op_usat16_T1(imm);
6716
                            else
6717
                                gen_op_usat_T1(imm);
6718
                        } else {
6719
                            /* Signed.  */
6720
                            gen_op_ssat_T1(imm);
6721
                            if ((op & 1) && shift == 0)
6722
                                gen_op_ssat16_T1(imm);
6723
                            else
6724
                                gen_op_ssat_T1(imm);
6725
                        }
6726
                        break;
6727
                    }
6728
                    gen_movl_reg_T1(s, rd);
6729
                } else {
6730
                    imm = ((insn & 0x04000000) >> 15)
6731
                          | ((insn & 0x7000) >> 4) | (insn & 0xff);
6732
                    if (insn & (1 << 22)) {
6733
                        /* 16-bit immediate.  */
6734
                        imm |= (insn >> 4) & 0xf000;
6735
                        if (insn & (1 << 23)) {
6736
                            /* movt */
6737
                            gen_movl_T0_reg(s, rd);
6738
                            gen_op_movtop_T0_im(imm << 16);
6739
                        } else {
6740
                            /* movw */
6741
                            gen_op_movl_T0_im(imm);
6742
                        }
6743
                    } else {
6744
                        /* Add/sub 12-bit immediate.  */
6745
                        if (rn == 15) {
6746
                            addr = s->pc & ~(uint32_t)3;
6747
                            if (insn & (1 << 23))
6748
                                addr -= imm;
6749
                            else
6750
                                addr += imm;
6751
                            gen_op_movl_T0_im(addr);
6752
                        } else {
6753
                            gen_movl_T0_reg(s, rn);
6754
                            gen_op_movl_T1_im(imm);
6755
                            if (insn & (1 << 23))
6756
                                gen_op_subl_T0_T1();
6757
                            else
6758
                                gen_op_addl_T0_T1();
6759
                        }
6760
                    }
6761
                    gen_movl_reg_T0(s, rd);
6762
                }
6763
            } else {
6764
                int shifter_out = 0;
6765
                /* modified 12-bit immediate.  */
6766
                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
6767
                imm = (insn & 0xff);
6768
                switch (shift) {
6769
                case 0: /* XY */
6770
                    /* Nothing to do.  */
6771
                    break;
6772
                case 1: /* 00XY00XY */
6773
                    imm |= imm << 16;
6774
                    break;
6775
                case 2: /* XY00XY00 */
6776
                    imm |= imm << 16;
6777
                    imm <<= 8;
6778
                    break;
6779
                case 3: /* XYXYXYXY */
6780
                    imm |= imm << 16;
6781
                    imm |= imm << 8;
6782
                    break;
6783
                default: /* Rotated constant.  */
6784
                    shift = (shift << 1) | (imm >> 7);
6785
                    imm |= 0x80;
6786
                    imm = imm << (32 - shift);
6787
                    shifter_out = 1;
6788
                    break;
6789
                }
6790
                gen_op_movl_T1_im(imm);
6791
                rn = (insn >> 16) & 0xf;
6792
                if (rn == 15)
6793
                    gen_op_movl_T0_im(0);
6794
                else
6795
                    gen_movl_T0_reg(s, rn);
6796
                op = (insn >> 21) & 0xf;
6797
                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
6798
                                       shifter_out))
6799
                    goto illegal_op;
6800
                rd = (insn >> 8) & 0xf;
6801
                if (rd != 15) {
6802
                    gen_movl_reg_T0(s, rd);
6803
                }
6804
            }
6805
        }
6806
        break;
6807
    case 12: /* Load/store single data item.  */
6808
        {
6809
        int postinc = 0;
6810
        int writeback = 0;
6811
        if ((insn & 0x01100000) == 0x01000000) {
6812
            if (disas_neon_ls_insn(env, s, insn))
6813
                goto illegal_op;
6814
            break;
6815
        }
6816
        if (rn == 15) {
6817
            /* PC relative.  */
6818
            /* s->pc has already been incremented by 4.  */
6819
            imm = s->pc & 0xfffffffc;
6820
            if (insn & (1 << 23))
6821
                imm += insn & 0xfff;
6822
            else
6823
                imm -= insn & 0xfff;
6824
            gen_op_movl_T1_im(imm);
6825
        } else {
6826
            gen_movl_T1_reg(s, rn);
6827
            if (insn & (1 << 23)) {
6828
                /* Positive offset.  */
6829
                imm = insn & 0xfff;
6830
                gen_op_addl_T1_im(imm);
6831
            } else {
6832
                op = (insn >> 8) & 7;
6833
                imm = insn & 0xff;
6834
                switch (op) {
6835
                case 0: case 8: /* Shifted Register.  */
6836
                    shift = (insn >> 4) & 0xf;
6837
                    if (shift > 3)
6838
                        goto illegal_op;
6839
                    tmp = load_reg(s, rm);
6840
                    if (shift)
6841
                        tcg_gen_shli_i32(tmp, tmp, shift);
6842
                    tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6843
                    dead_tmp(tmp);
6844
                    break;
6845
                case 4: /* Negative offset.  */
6846
                    gen_op_addl_T1_im(-imm);
6847
                    break;
6848
                case 6: /* User privilege.  */
6849
                    gen_op_addl_T1_im(imm);
6850
                    break;
6851
                case 1: /* Post-decrement.  */
6852
                    imm = -imm;
6853
                    /* Fall through.  */
6854
                case 3: /* Post-increment.  */
6855
                    postinc = 1;
6856
                    writeback = 1;
6857
                    break;
6858
                case 5: /* Pre-decrement.  */
6859
                    imm = -imm;
6860
                    /* Fall through.  */
6861
                case 7: /* Pre-increment.  */
6862
                    gen_op_addl_T1_im(imm);
6863
                    writeback = 1;
6864
                    break;
6865
                default:
6866
                    goto illegal_op;
6867
                }
6868
            }
6869
        }
6870
        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
6871
        if (insn & (1 << 20)) {
6872
            /* Load.  */
6873
            if (rs == 15 && op != 2) {
6874
                if (op & 2)
6875
                    goto illegal_op;
6876
                /* Memory hint.  Implemented as NOP.  */
6877
            } else {
6878
                switch (op) {
6879
                case 0: gen_ldst(ldub, s); break;
6880
                case 4: gen_ldst(ldsb, s); break;
6881
                case 1: gen_ldst(lduw, s); break;
6882
                case 5: gen_ldst(ldsw, s); break;
6883
                case 2: gen_ldst(ldl, s); break;
6884
                default: goto illegal_op;
6885
                }
6886
                if (rs == 15) {
6887
                    gen_bx(s);
6888
                } else {
6889
                    gen_movl_reg_T0(s, rs);
6890
                }
6891
            }
6892
        } else {
6893
            /* Store.  */
6894
            if (rs == 15)
6895
                goto illegal_op;
6896
            gen_movl_T0_reg(s, rs);
6897
            switch (op) {
6898
            case 0: gen_ldst(stb, s); break;
6899
            case 1: gen_ldst(stw, s); break;
6900
            case 2: gen_ldst(stl, s); break;
6901
            default: goto illegal_op;
6902
            }
6903
        }
6904
        if (postinc)
6905
            gen_op_addl_T1_im(imm);
6906
        if (writeback)
6907
            gen_movl_reg_T1(s, rn);
6908
        }
6909
        break;
6910
    default:
6911
        goto illegal_op;
6912
    }
6913
    return 0;
6914
illegal_op:
6915
    return 1;
6916
}
6917

    
6918
static void disas_thumb_insn(CPUState *env, DisasContext *s)
6919
{
6920
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
6921
    int32_t offset;
6922
    int i;
6923
    TCGv tmp;
6924

    
6925
    if (s->condexec_mask) {
6926
        cond = s->condexec_cond;
6927
        s->condlabel = gen_new_label();
6928
        gen_test_cc[cond ^ 1](s->condlabel);
6929
        s->condjmp = 1;
6930
    }
6931

    
6932
    insn = lduw_code(s->pc);
6933
    s->pc += 2;
6934

    
6935
    switch (insn >> 12) {
6936
    case 0: case 1:
6937
        rd = insn & 7;
6938
        op = (insn >> 11) & 3;
6939
        if (op == 3) {
6940
            /* add/subtract */
6941
            rn = (insn >> 3) & 7;
6942
            gen_movl_T0_reg(s, rn);
6943
            if (insn & (1 << 10)) {
6944
                /* immediate */
6945
                gen_op_movl_T1_im((insn >> 6) & 7);
6946
            } else {
6947
                /* reg */
6948
                rm = (insn >> 6) & 7;
6949
                gen_movl_T1_reg(s, rm);
6950
            }
6951
            if (insn & (1 << 9)) {
6952
                if (s->condexec_mask)
6953
                    gen_op_subl_T0_T1();
6954
                else
6955
                    gen_op_subl_T0_T1_cc();
6956
            } else {
6957
                if (s->condexec_mask)
6958
                    gen_op_addl_T0_T1();
6959
                else
6960
                    gen_op_addl_T0_T1_cc();
6961
            }
6962
            gen_movl_reg_T0(s, rd);
6963
        } else {
6964
            /* shift immediate */
6965
            rm = (insn >> 3) & 7;
6966
            shift = (insn >> 6) & 0x1f;
6967
            tmp = load_reg(s, rm);
6968
            gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
6969
            if (!s->condexec_mask)
6970
                gen_logic_CC(tmp);
6971
            store_reg(s, rd, tmp);
6972
        }
6973
        break;
6974
    case 2: case 3:
6975
        /* arithmetic large immediate */
6976
        op = (insn >> 11) & 3;
6977
        rd = (insn >> 8) & 0x7;
6978
        if (op == 0) {
6979
            gen_op_movl_T0_im(insn & 0xff);
6980
        } else {
6981
            gen_movl_T0_reg(s, rd);
6982
            gen_op_movl_T1_im(insn & 0xff);
6983
        }
6984
        switch (op) {
6985
        case 0: /* mov */
6986
            if (!s->condexec_mask)
6987
                gen_op_logic_T0_cc();
6988
            break;
6989
        case 1: /* cmp */
6990
            gen_op_subl_T0_T1_cc();
6991
            break;
6992
        case 2: /* add */
6993
            if (s->condexec_mask)
6994
                gen_op_addl_T0_T1();
6995
            else
6996
                gen_op_addl_T0_T1_cc();
6997
            break;
6998
        case 3: /* sub */
6999
            if (s->condexec_mask)
7000
                gen_op_subl_T0_T1();
7001
            else
7002
                gen_op_subl_T0_T1_cc();
7003
            break;
7004
        }
7005
        if (op != 1)
7006
            gen_movl_reg_T0(s, rd);
7007
        break;
7008
    case 4:
7009
        if (insn & (1 << 11)) {
7010
            rd = (insn >> 8) & 7;
7011
            /* load pc-relative.  Bit 1 of PC is ignored.  */
7012
            val = s->pc + 2 + ((insn & 0xff) * 4);
7013
            val &= ~(uint32_t)2;
7014
            gen_op_movl_T1_im(val);
7015
            gen_ldst(ldl, s);
7016
            gen_movl_reg_T0(s, rd);
7017
            break;
7018
        }
7019
        if (insn & (1 << 10)) {
7020
            /* data processing extended or blx */
7021
            rd = (insn & 7) | ((insn >> 4) & 8);
7022
            rm = (insn >> 3) & 0xf;
7023
            op = (insn >> 8) & 3;
7024
            switch (op) {
7025
            case 0: /* add */
7026
                gen_movl_T0_reg(s, rd);
7027
                gen_movl_T1_reg(s, rm);
7028
                gen_op_addl_T0_T1();
7029
                gen_movl_reg_T0(s, rd);
7030
                break;
7031
            case 1: /* cmp */
7032
                gen_movl_T0_reg(s, rd);
7033
                gen_movl_T1_reg(s, rm);
7034
                gen_op_subl_T0_T1_cc();
7035
                break;
7036
            case 2: /* mov/cpy */
7037
                gen_movl_T0_reg(s, rm);
7038
                gen_movl_reg_T0(s, rd);
7039
                break;
7040
            case 3:/* branch [and link] exchange thumb register */
7041
                if (insn & (1 << 7)) {
7042
                    val = (uint32_t)s->pc | 1;
7043
                    gen_op_movl_T1_im(val);
7044
                    gen_movl_reg_T1(s, 14);
7045
                }
7046
                gen_movl_T0_reg(s, rm);
7047
                gen_bx(s);
7048
                break;
7049
            }
7050
            break;
7051
        }
7052

    
7053
        /* data processing register */
7054
        rd = insn & 7;
7055
        rm = (insn >> 3) & 7;
7056
        op = (insn >> 6) & 0xf;
7057
        if (op == 2 || op == 3 || op == 4 || op == 7) {
7058
            /* the shift/rotate ops want the operands backwards */
7059
            val = rm;
7060
            rm = rd;
7061
            rd = val;
7062
            val = 1;
7063
        } else {
7064
            val = 0;
7065
        }
7066

    
7067
        if (op == 9) /* neg */
7068
            gen_op_movl_T0_im(0);
7069
        else if (op != 0xf) /* mvn doesn't read its first operand */
7070
            gen_movl_T0_reg(s, rd);
7071

    
7072
        gen_movl_T1_reg(s, rm);
7073
        switch (op) {
7074
        case 0x0: /* and */
7075
            gen_op_andl_T0_T1();
7076
            if (!s->condexec_mask)
7077
                gen_op_logic_T0_cc();
7078
            break;
7079
        case 0x1: /* eor */
7080
            gen_op_xorl_T0_T1();
7081
            if (!s->condexec_mask)
7082
                gen_op_logic_T0_cc();
7083
            break;
7084
        case 0x2: /* lsl */
7085
            if (s->condexec_mask) {
7086
                gen_op_shll_T1_T0();
7087
            } else {
7088
                gen_op_shll_T1_T0_cc();
7089
                gen_op_logic_T1_cc();
7090
            }
7091
            break;
7092
        case 0x3: /* lsr */
7093
            if (s->condexec_mask) {
7094
                gen_op_shrl_T1_T0();
7095
            } else {
7096
                gen_op_shrl_T1_T0_cc();
7097
                gen_op_logic_T1_cc();
7098
            }
7099
            break;
7100
        case 0x4: /* asr */
7101
            if (s->condexec_mask) {
7102
                gen_op_sarl_T1_T0();
7103
            } else {
7104
                gen_op_sarl_T1_T0_cc();
7105
                gen_op_logic_T1_cc();
7106
            }
7107
            break;
7108
        case 0x5: /* adc */
7109
            if (s->condexec_mask)
7110
                gen_adc_T0_T1();
7111
            else
7112
                gen_op_adcl_T0_T1_cc();
7113
            break;
7114
        case 0x6: /* sbc */
7115
            if (s->condexec_mask)
7116
                gen_op_sbcl_T0_T1();
7117
            else
7118
                gen_op_sbcl_T0_T1_cc();
7119
            break;
7120
        case 0x7: /* ror */
7121
            if (s->condexec_mask) {
7122
                gen_op_rorl_T1_T0();
7123
            } else {
7124
                gen_op_rorl_T1_T0_cc();
7125
                gen_op_logic_T1_cc();
7126
            }
7127
            break;
7128
        case 0x8: /* tst */
7129
            gen_op_andl_T0_T1();
7130
            gen_op_logic_T0_cc();
7131
            rd = 16;
7132
            break;
7133
        case 0x9: /* neg */
7134
            if (s->condexec_mask)
7135
                gen_op_subl_T0_T1();
7136
            else
7137
                gen_op_subl_T0_T1_cc();
7138
            break;
7139
        case 0xa: /* cmp */
7140
            gen_op_subl_T0_T1_cc();
7141
            rd = 16;
7142
            break;
7143
        case 0xb: /* cmn */
7144
            gen_op_addl_T0_T1_cc();
7145
            rd = 16;
7146
            break;
7147
        case 0xc: /* orr */
7148
            gen_op_orl_T0_T1();
7149
            if (!s->condexec_mask)
7150
                gen_op_logic_T0_cc();
7151
            break;
7152
        case 0xd: /* mul */
7153
            gen_op_mull_T0_T1();
7154
            if (!s->condexec_mask)
7155
                gen_op_logic_T0_cc();
7156
            break;
7157
        case 0xe: /* bic */
7158
            gen_op_bicl_T0_T1();
7159
            if (!s->condexec_mask)
7160
                gen_op_logic_T0_cc();
7161
            break;
7162
        case 0xf: /* mvn */
7163
            gen_op_notl_T1();
7164
            if (!s->condexec_mask)
7165
                gen_op_logic_T1_cc();
7166
            val = 1;
7167
            rm = rd;
7168
            break;
7169
        }
7170
        if (rd != 16) {
7171
            if (val)
7172
                gen_movl_reg_T1(s, rm);
7173
            else
7174
                gen_movl_reg_T0(s, rd);
7175
        }
7176
        break;
7177

    
7178
    case 5:
7179
        /* load/store register offset.  */
7180
        rd = insn & 7;
7181
        rn = (insn >> 3) & 7;
7182
        rm = (insn >> 6) & 7;
7183
        op = (insn >> 9) & 7;
7184
        gen_movl_T1_reg(s, rn);
7185
        tmp = load_reg(s, rm);
7186
        tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
7187
        dead_tmp(tmp);
7188

    
7189
        if (op < 3) /* store */
7190
            gen_movl_T0_reg(s, rd);
7191

    
7192
        switch (op) {
7193
        case 0: /* str */
7194
            gen_ldst(stl, s);
7195
            break;
7196
        case 1: /* strh */
7197
            gen_ldst(stw, s);
7198
            break;
7199
        case 2: /* strb */
7200
            gen_ldst(stb, s);
7201
            break;
7202
        case 3: /* ldrsb */
7203
            gen_ldst(ldsb, s);
7204
            break;
7205
        case 4: /* ldr */
7206
            gen_ldst(ldl, s);
7207
            break;
7208
        case 5: /* ldrh */
7209
            gen_ldst(lduw, s);
7210
            break;
7211
        case 6: /* ldrb */
7212
            gen_ldst(ldub, s);
7213
            break;
7214
        case 7: /* ldrsh */
7215
            gen_ldst(ldsw, s);
7216
            break;
7217
        }
7218
        if (op >= 3) /* load */
7219
            gen_movl_reg_T0(s, rd);
7220
        break;
7221

    
7222
    case 6:
7223
        /* load/store word immediate offset */
7224
        rd = insn & 7;
7225
        rn = (insn >> 3) & 7;
7226
        gen_movl_T1_reg(s, rn);
7227
        val = (insn >> 4) & 0x7c;
7228
        tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
7229

    
7230
        if (insn & (1 << 11)) {
7231
            /* load */
7232
            gen_ldst(ldl, s);
7233
            gen_movl_reg_T0(s, rd);
7234
        } else {
7235
            /* store */
7236
            gen_movl_T0_reg(s, rd);
7237
            gen_ldst(stl, s);
7238
        }
7239
        break;
7240

    
7241
    case 7:
7242
        /* load/store byte immediate offset */
7243
        rd = insn & 7;
7244
        rn = (insn >> 3) & 7;
7245
        gen_movl_T1_reg(s, rn);
7246
        val = (insn >> 6) & 0x1f;
7247
        tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
7248

    
7249
        if (insn & (1 << 11)) {
7250
            /* load */
7251
            gen_ldst(ldub, s);
7252
            gen_movl_reg_T0(s, rd);
7253
        } else {
7254
            /* store */
7255
            gen_movl_T0_reg(s, rd);
7256
            gen_ldst(stb, s);
7257
        }
7258
        break;
7259

    
7260
    case 8:
7261
        /* load/store halfword immediate offset */
7262
        rd = insn & 7;
7263
        rn = (insn >> 3) & 7;
7264
        gen_movl_T1_reg(s, rn);
7265
        val = (insn >> 5) & 0x3e;
7266
        tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
7267

    
7268
        if (insn & (1 << 11)) {
7269
            /* load */
7270
            gen_ldst(lduw, s);
7271
            gen_movl_reg_T0(s, rd);
7272
        } else {
7273
            /* store */
7274
            gen_movl_T0_reg(s, rd);
7275
            gen_ldst(stw, s);
7276
        }
7277
        break;
7278

    
7279
    case 9:
7280
        /* load/store from stack */
7281
        rd = (insn >> 8) & 7;
7282
        gen_movl_T1_reg(s, 13);
7283
        val = (insn & 0xff) * 4;
7284
        tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
7285

    
7286
        if (insn & (1 << 11)) {
7287
            /* load */
7288
            gen_ldst(ldl, s);
7289
            gen_movl_reg_T0(s, rd);
7290
        } else {
7291
            /* store */
7292
            gen_movl_T0_reg(s, rd);
7293
            gen_ldst(stl, s);
7294
        }
7295
        break;
7296

    
7297
    case 10:
7298
        /* add to high reg */
7299
        rd = (insn >> 8) & 7;
7300
        if (insn & (1 << 11)) {
7301
            /* SP */
7302
            gen_movl_T0_reg(s, 13);
7303
        } else {
7304
            /* PC. bit 1 is ignored.  */
7305
            gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
7306
        }
7307
        val = (insn & 0xff) * 4;
7308
        gen_op_movl_T1_im(val);
7309
        gen_op_addl_T0_T1();
7310
        gen_movl_reg_T0(s, rd);
7311
        break;
7312

    
7313
    case 11:
7314
        /* misc */
7315
        op = (insn >> 8) & 0xf;
7316
        switch (op) {
7317
        case 0:
7318
            /* adjust stack pointer */
7319
            tmp = load_reg(s, 13);
7320
            val = (insn & 0x7f) * 4;
7321
            if (insn & (1 << 7))
7322
              val = -(int32_t)val;
7323
            tcg_gen_addi_i32(tmp, tmp, val);
7324
            store_reg(s, 13, tmp);
7325
            break;
7326

    
7327
        case 2: /* sign/zero extend.  */
7328
            ARCH(6);
7329
            rd = insn & 7;
7330
            rm = (insn >> 3) & 7;
7331
            gen_movl_T1_reg(s, rm);
7332
            switch ((insn >> 6) & 3) {
7333
            case 0: gen_sxth(cpu_T[1]); break;
7334
            case 1: gen_sxtb(cpu_T[1]); break;
7335
            case 2: gen_uxth(cpu_T[1]); break;
7336
            case 3: gen_uxtb(cpu_T[1]); break;
7337
            }
7338
            gen_movl_reg_T1(s, rd);
7339
            break;
7340
        case 4: case 5: case 0xc: case 0xd:
7341
            /* push/pop */
7342
            gen_movl_T1_reg(s, 13);
7343
            if (insn & (1 << 8))
7344
                offset = 4;
7345
            else
7346
                offset = 0;
7347
            for (i = 0; i < 8; i++) {
7348
                if (insn & (1 << i))
7349
                    offset += 4;
7350
            }
7351
            if ((insn & (1 << 11)) == 0) {
7352
                gen_op_addl_T1_im(-offset);
7353
            }
7354
            for (i = 0; i < 8; i++) {
7355
                if (insn & (1 << i)) {
7356
                    if (insn & (1 << 11)) {
7357
                        /* pop */
7358
                        gen_ldst(ldl, s);
7359
                        gen_movl_reg_T0(s, i);
7360
                    } else {
7361
                        /* push */
7362
                        gen_movl_T0_reg(s, i);
7363
                        gen_ldst(stl, s);
7364
                    }
7365
                    /* advance to the next address.  */
7366
                    gen_op_addl_T1_im(4);
7367
                }
7368
            }
7369
            if (insn & (1 << 8)) {
7370
                if (insn & (1 << 11)) {
7371
                    /* pop pc */
7372
                    gen_ldst(ldl, s);
7373
                    /* don't set the pc until the rest of the instruction
7374
                       has completed */
7375
                } else {
7376
                    /* push lr */
7377
                    gen_movl_T0_reg(s, 14);
7378
                    gen_ldst(stl, s);
7379
                }
7380
                gen_op_addl_T1_im(4);
7381
            }
7382
            if ((insn & (1 << 11)) == 0) {
7383
                gen_op_addl_T1_im(-offset);
7384
            }
7385
            /* write back the new stack pointer */
7386
            gen_movl_reg_T1(s, 13);
7387
            /* set the new PC value */
7388
            if ((insn & 0x0900) == 0x0900)
7389
                gen_bx(s);
7390
            break;
7391

    
7392
        case 1: case 3: case 9: case 11: /* czb */
7393
            rm = insn & 7;
7394
            gen_movl_T0_reg(s, rm);
7395
            s->condlabel = gen_new_label();
7396
            s->condjmp = 1;
7397
            if (insn & (1 << 11))
7398
                gen_op_testn_T0(s->condlabel);
7399
            else
7400
                gen_op_test_T0(s->condlabel);
7401

    
7402
            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
7403
            val = (uint32_t)s->pc + 2;
7404
            val += offset;
7405
            gen_jmp(s, val);
7406
            break;
7407

    
7408
        case 15: /* IT, nop-hint.  */
7409
            if ((insn & 0xf) == 0) {
7410
                gen_nop_hint(s, (insn >> 4) & 0xf);
7411
                break;
7412
            }
7413
            /* If Then.  */
7414
            s->condexec_cond = (insn >> 4) & 0xe;
7415
            s->condexec_mask = insn & 0x1f;
7416
            /* No actual code generated for this insn, just setup state.  */
7417
            break;
7418

    
7419
        case 0xe: /* bkpt */
7420
            gen_set_condexec(s);
7421
            gen_op_movl_T0_im((long)s->pc - 2);
7422
            gen_set_pc_T0();
7423
            gen_op_bkpt();
7424
            s->is_jmp = DISAS_JUMP;
7425
            break;
7426

    
7427
        case 0xa: /* rev */
7428
            ARCH(6);
7429
            rn = (insn >> 3) & 0x7;
7430
            rd = insn & 0x7;
7431
            gen_movl_T0_reg(s, rn);
7432
            switch ((insn >> 6) & 3) {
7433
            case 0: gen_op_rev_T0(); break;
7434
            case 1: gen_op_rev16_T0(); break;
7435
            case 3: gen_op_revsh_T0(); break;
7436
            default: goto illegal_op;
7437
            }
7438
            gen_movl_reg_T0(s, rd);
7439
            break;
7440

    
7441
        case 6: /* cps */
7442
            ARCH(6);
7443
            if (IS_USER(s))
7444
                break;
7445
            if (IS_M(env)) {
7446
                val = (insn & (1 << 4)) != 0;
7447
                gen_op_movl_T0_im(val);
7448
                /* PRIMASK */
7449
                if (insn & 1)
7450
                    gen_op_v7m_msr_T0(16);
7451
                /* FAULTMASK */
7452
                if (insn & 2)
7453
                    gen_op_v7m_msr_T0(17);
7454

    
7455
                gen_lookup_tb(s);
7456
            } else {
7457
                if (insn & (1 << 4))
7458
                    shift = CPSR_A | CPSR_I | CPSR_F;
7459
                else
7460
                    shift = 0;
7461

    
7462
                val = ((insn & 7) << 6) & shift;
7463
                gen_op_movl_T0_im(val);
7464
                gen_set_psr_T0(s, shift, 0);
7465
            }
7466
            break;
7467

    
7468
        default:
7469
            goto undef;
7470
        }
7471
        break;
7472

    
7473
    case 12:
7474
        /* load/store multiple */
7475
        rn = (insn >> 8) & 0x7;
7476
        gen_movl_T1_reg(s, rn);
7477
        for (i = 0; i < 8; i++) {
7478
            if (insn & (1 << i)) {
7479
                if (insn & (1 << 11)) {
7480
                    /* load */
7481
                    gen_ldst(ldl, s);
7482
                    gen_movl_reg_T0(s, i);
7483
                } else {
7484
                    /* store */
7485
                    gen_movl_T0_reg(s, i);
7486
                    gen_ldst(stl, s);
7487
                }
7488
                /* advance to the next address */
7489
                gen_op_addl_T1_im(4);
7490
            }
7491
        }
7492
        /* Base register writeback.  */
7493
        if ((insn & (1 << rn)) == 0)
7494
            gen_movl_reg_T1(s, rn);
7495
        break;
7496

    
7497
    case 13:
7498
        /* conditional branch or swi */
7499
        cond = (insn >> 8) & 0xf;
7500
        if (cond == 0xe)
7501
            goto undef;
7502

    
7503
        if (cond == 0xf) {
7504
            /* swi */
7505
            gen_set_condexec(s);
7506
            gen_op_movl_T0_im((long)s->pc | 1);
7507
            /* Don't set r15.  */
7508
            gen_set_pc_T0();
7509
            s->is_jmp = DISAS_SWI;
7510
            break;
7511
        }
7512
        /* generate a conditional jump to next instruction */
7513
        s->condlabel = gen_new_label();
7514
        gen_test_cc[cond ^ 1](s->condlabel);
7515
        s->condjmp = 1;
7516
        gen_movl_T1_reg(s, 15);
7517

    
7518
        /* jump to the offset */
7519
        val = (uint32_t)s->pc + 2;
7520
        offset = ((int32_t)insn << 24) >> 24;
7521
        val += offset << 1;
7522
        gen_jmp(s, val);
7523
        break;
7524

    
7525
    case 14:
7526
        if (insn & (1 << 11)) {
7527
            if (disas_thumb2_insn(env, s, insn))
7528
              goto undef32;
7529
            break;
7530
        }
7531
        /* unconditional branch */
7532
        val = (uint32_t)s->pc;
7533
        offset = ((int32_t)insn << 21) >> 21;
7534
        val += (offset << 1) + 2;
7535
        gen_jmp(s, val);
7536
        break;
7537

    
7538
    case 15:
7539
        if (disas_thumb2_insn(env, s, insn))
7540
          goto undef32;
7541
        break;
7542
    }
7543
    return;
7544
undef32:
7545
    gen_set_condexec(s);
7546
    gen_op_movl_T0_im((long)s->pc - 4);
7547
    gen_set_pc_T0();
7548
    gen_op_undef_insn();
7549
    s->is_jmp = DISAS_JUMP;
7550
    return;
7551
illegal_op:
7552
undef:
7553
    gen_set_condexec(s);
7554
    gen_op_movl_T0_im((long)s->pc - 2);
7555
    gen_set_pc_T0();
7556
    gen_op_undef_insn();
7557
    s->is_jmp = DISAS_JUMP;
7558
}
7559

    
7560
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7561
   basic block 'tb'. If search_pc is TRUE, also generate PC
7562
   information for each intermediate instruction. */
7563
static inline int gen_intermediate_code_internal(CPUState *env,
7564
                                                 TranslationBlock *tb,
7565
                                                 int search_pc)
7566
{
7567
    DisasContext dc1, *dc = &dc1;
7568
    uint16_t *gen_opc_end;
7569
    int j, lj;
7570
    target_ulong pc_start;
7571
    uint32_t next_page_start;
7572

    
7573
    /* generate intermediate code */
7574
    num_temps = 0;
7575
    memset(temps, 0, sizeof(temps));
7576

    
7577
    pc_start = tb->pc;
7578

    
7579
    dc->tb = tb;
7580

    
7581
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7582

    
7583
    dc->is_jmp = DISAS_NEXT;
7584
    dc->pc = pc_start;
7585
    dc->singlestep_enabled = env->singlestep_enabled;
7586
    dc->condjmp = 0;
7587
    dc->thumb = env->thumb;
7588
    dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
7589
    dc->condexec_cond = env->condexec_bits >> 4;
7590
    dc->is_mem = 0;
7591
#if !defined(CONFIG_USER_ONLY)
7592
    if (IS_M(env)) {
7593
        dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
7594
    } else {
7595
        dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
7596
    }
7597
#endif
7598
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
7599
    lj = -1;
7600
    /* Reset the conditional execution bits immediately. This avoids
7601
       complications trying to do it at the end of the block.  */
7602
    if (env->condexec_bits)
7603
      gen_op_set_condexec(0);
7604
    do {
7605
#ifndef CONFIG_USER_ONLY
7606
        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
7607
            /* We always get here via a jump, so know we are not in a
7608
               conditional execution block.  */
7609
            gen_op_exception_exit();
7610
        }
7611
#endif
7612

    
7613
        if (env->nb_breakpoints > 0) {
7614
            for(j = 0; j < env->nb_breakpoints; j++) {
7615
                if (env->breakpoints[j] == dc->pc) {
7616
                    gen_set_condexec(dc);
7617
                    gen_op_movl_T0_im((long)dc->pc);
7618
                    gen_set_pc_T0();
7619
                    gen_op_debug();
7620
                    dc->is_jmp = DISAS_JUMP;
7621
                    /* Advance PC so that clearing the breakpoint will
7622
                       invalidate this TB.  */
7623
                    dc->pc += 2;
7624
                    goto done_generating;
7625
                    break;
7626
                }
7627
            }
7628
        }
7629
        if (search_pc) {
7630
            j = gen_opc_ptr - gen_opc_buf;
7631
            if (lj < j) {
7632
                lj++;
7633
                while (lj < j)
7634
                    gen_opc_instr_start[lj++] = 0;
7635
            }
7636
            gen_opc_pc[lj] = dc->pc;
7637
            gen_opc_instr_start[lj] = 1;
7638
        }
7639

    
7640
        if (env->thumb) {
7641
            disas_thumb_insn(env, dc);
7642
            if (dc->condexec_mask) {
7643
                dc->condexec_cond = (dc->condexec_cond & 0xe)
7644
                                   | ((dc->condexec_mask >> 4) & 1);
7645
                dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
7646
                if (dc->condexec_mask == 0) {
7647
                    dc->condexec_cond = 0;
7648
                }
7649
            }
7650
        } else {
7651
            disas_arm_insn(env, dc);
7652
        }
7653
        if (num_temps) {
7654
            fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
7655
            num_temps = 0;
7656
        }
7657

    
7658
        if (dc->condjmp && !dc->is_jmp) {
7659
            gen_set_label(dc->condlabel);
7660
            dc->condjmp = 0;
7661
        }
7662
        /* Terminate the TB on memory ops if watchpoints are present.  */
7663
        /* FIXME: This should be replacd by the deterministic execution
7664
         * IRQ raising bits.  */
7665
        if (dc->is_mem && env->nb_watchpoints)
7666
            break;
7667

    
7668
        /* Translation stops when a conditional branch is enoutered.
7669
         * Otherwise the subsequent code could get translated several times.
7670
         * Also stop translation when a page boundary is reached.  This
7671
         * ensures prefech aborts occur at the right place.  */
7672
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
7673
             !env->singlestep_enabled &&
7674
             dc->pc < next_page_start);
7675

    
7676
    /* At this stage dc->condjmp will only be set when the skipped
7677
       instruction was a conditional branch or trap, and the PC has
7678
       already been written.  */
7679
    if (__builtin_expect(env->singlestep_enabled, 0)) {
7680
        /* Make sure the pc is updated, and raise a debug exception.  */
7681
        if (dc->condjmp) {
7682
            gen_set_condexec(dc);
7683
            if (dc->is_jmp == DISAS_SWI) {
7684
                gen_op_swi();
7685
            } else {
7686
                gen_op_debug();
7687
            }
7688
            gen_set_label(dc->condlabel);
7689
        }
7690
        if (dc->condjmp || !dc->is_jmp) {
7691
            gen_op_movl_T0_im((long)dc->pc);
7692
            gen_set_pc_T0();
7693
            dc->condjmp = 0;
7694
        }
7695
        gen_set_condexec(dc);
7696
        if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
7697
            gen_op_swi();
7698
        } else {
7699
            /* FIXME: Single stepping a WFI insn will not halt
7700
               the CPU.  */
7701
            gen_op_debug();
7702
        }
7703
    } else {
7704
        /* While branches must always occur at the end of an IT block,
7705
           there are a few other things that can cause us to terminate
7706
           the TB in the middel of an IT block:
7707
            - Exception generating instructions (bkpt, swi, undefined).
7708
            - Page boundaries.
7709
            - Hardware watchpoints.
7710
           Hardware breakpoints have already been handled and skip this code.
7711
         */
7712
        gen_set_condexec(dc);
7713
        switch(dc->is_jmp) {
7714
        case DISAS_NEXT:
7715
            gen_goto_tb(dc, 1, dc->pc);
7716
            break;
7717
        default:
7718
        case DISAS_JUMP:
7719
        case DISAS_UPDATE:
7720
            /* indicate that the hash table must be used to find the next TB */
7721
            tcg_gen_exit_tb(0);
7722
            break;
7723
        case DISAS_TB_JUMP:
7724
            /* nothing more to generate */
7725
            break;
7726
        case DISAS_WFI:
7727
            gen_op_wfi();
7728
            break;
7729
        case DISAS_SWI:
7730
            gen_op_swi();
7731
            break;
7732
        }
7733
        if (dc->condjmp) {
7734
            gen_set_label(dc->condlabel);
7735
            gen_set_condexec(dc);
7736
            gen_goto_tb(dc, 1, dc->pc);
7737
            dc->condjmp = 0;
7738
        }
7739
    }
7740
done_generating:
7741
    *gen_opc_ptr = INDEX_op_end;
7742

    
7743
#ifdef DEBUG_DISAS
7744
    if (loglevel & CPU_LOG_TB_IN_ASM) {
7745
        fprintf(logfile, "----------------\n");
7746
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
7747
        target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
7748
        fprintf(logfile, "\n");
7749
    }
7750
#endif
7751
    if (search_pc) {
7752
        j = gen_opc_ptr - gen_opc_buf;
7753
        lj++;
7754
        while (lj <= j)
7755
            gen_opc_instr_start[lj++] = 0;
7756
    } else {
7757
        tb->size = dc->pc - pc_start;
7758
    }
7759
    return 0;
7760
}
7761

    
7762
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
7763
{
7764
    return gen_intermediate_code_internal(env, tb, 0);
7765
}
7766

    
7767
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
7768
{
7769
    return gen_intermediate_code_internal(env, tb, 1);
7770
}
7771

    
7772
static const char *cpu_mode_names[16] = {
7773
  "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
7774
  "???", "???", "???", "und", "???", "???", "???", "sys"
7775
};
7776

    
7777
void cpu_dump_state(CPUState *env, FILE *f,
7778
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7779
                    int flags)
7780
{
7781
    int i;
7782
    union {
7783
        uint32_t i;
7784
        float s;
7785
    } s0, s1;
7786
    CPU_DoubleU d;
7787
    /* ??? This assumes float64 and double have the same layout.
7788
       Oh well, it's only debug dumps.  */
7789
    union {
7790
        float64 f64;
7791
        double d;
7792
    } d0;
7793
    uint32_t psr;
7794

    
7795
    for(i=0;i<16;i++) {
7796
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
7797
        if ((i % 4) == 3)
7798
            cpu_fprintf(f, "\n");
7799
        else
7800
            cpu_fprintf(f, " ");
7801
    }
7802
    psr = cpsr_read(env);
7803
    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
7804
                psr,
7805
                psr & (1 << 31) ? 'N' : '-',
7806
                psr & (1 << 30) ? 'Z' : '-',
7807
                psr & (1 << 29) ? 'C' : '-',
7808
                psr & (1 << 28) ? 'V' : '-',
7809
                psr & CPSR_T ? 'T' : 'A',
7810
                cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
7811

    
7812
    for (i = 0; i < 16; i++) {
7813
        d.d = env->vfp.regs[i];
7814
        s0.i = d.l.lower;
7815
        s1.i = d.l.upper;
7816
        d0.f64 = d.d;
7817
        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
7818
                    i * 2, (int)s0.i, s0.s,
7819
                    i * 2 + 1, (int)s1.i, s1.s,
7820
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
7821
                    d0.d);
7822
    }
7823
    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
7824
}
7825