Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 5e3f878a

History | View | Annotate | Download (283.3 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
static TCGv cpu_F0s, cpu_F1s, cpu_F0d, cpu_F1d;
83

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

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

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

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

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

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

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

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

    
134
static inline TCGv load_cpu_offset(int offset)
135
{
136
    TCGv tmp = new_tmp();
137
    tcg_gen_ld_i32(tmp, cpu_env, offset);
138
    return tmp;
139
}
140

    
141
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
142

    
143
static inline void store_cpu_offset(TCGv var, int offset)
144
{
145
    tcg_gen_st_i32(var, cpu_env, offset);
146
    dead_tmp(var);
147
}
148

    
149
#define store_cpu_field(var, name) \
150
    store_cpu_offset(var, offsetof(CPUState, name))
151

    
152
/* Set a variable to the value of a CPU register.  */
153
static void load_reg_var(DisasContext *s, TCGv var, int reg)
154
{
155
    if (reg == 15) {
156
        uint32_t addr;
157
        /* normaly, since we updated PC, we need only to add one insn */
158
        if (s->thumb)
159
            addr = (long)s->pc + 2;
160
        else
161
            addr = (long)s->pc + 4;
162
        tcg_gen_movi_i32(var, addr);
163
    } else {
164
        tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
165
    }
166
}
167

    
168
/* Create a new temporary and set it to the value of a CPU register.  */
169
static inline TCGv load_reg(DisasContext *s, int reg)
170
{
171
    TCGv tmp = new_tmp();
172
    load_reg_var(s, tmp, reg);
173
    return tmp;
174
}
175

    
176
/* Set a CPU register.  The source must be a temporary and will be
177
   marked as dead.  */
178
static void store_reg(DisasContext *s, int reg, TCGv var)
179
{
180
    if (reg == 15) {
181
        tcg_gen_andi_i32(var, var, ~1);
182
        s->is_jmp = DISAS_JUMP;
183
    }
184
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
185
    dead_tmp(var);
186
}
187

    
188

    
189
/* Basic operations.  */
190
#define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
191
#define gen_op_movl_T0_T2() tcg_gen_mov_i32(cpu_T[0], cpu_T[2])
192
#define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], cpu_T[0])
193
#define gen_op_movl_T1_T2() tcg_gen_mov_i32(cpu_T[1], cpu_T[2])
194
#define gen_op_movl_T2_T0() tcg_gen_mov_i32(cpu_T[2], cpu_T[0])
195
#define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
196
#define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
197
#define gen_op_movl_T2_im(im) tcg_gen_movi_i32(cpu_T[2], im)
198

    
199
#define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
200
#define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
201
#define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
202
#define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
203

    
204
#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
205
#define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
206
#define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
207
#define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
208
#define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
209
#define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
210
#define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
211

    
212
#define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im)
213
#define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
214
#define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
215
#define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im)
216
#define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im)
217

    
218
/* Value extensions.  */
219
#define gen_uxtb(var) tcg_gen_andi_i32(var, var, 0xff)
220
#define gen_uxth(var) tcg_gen_andi_i32(var, var, 0xffff)
221
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
222
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
223

    
224
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
225
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
226

    
227
#define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
228

    
229
#define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
230
/* Set NZCV flags from the high 4 bits of var.  */
231
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
232

    
233
static void gen_exception(int excp)
234
{
235
    TCGv tmp = new_tmp();
236
    tcg_gen_movi_i32(tmp, excp);
237
    gen_helper_exception(tmp);
238
    dead_tmp(tmp);
239
}
240

    
241
static void gen_smul_dual(TCGv a, TCGv b)
242
{
243
    TCGv tmp1 = new_tmp();
244
    TCGv tmp2 = new_tmp();
245
    tcg_gen_ext8s_i32(tmp1, a);
246
    tcg_gen_ext8s_i32(tmp2, b);
247
    tcg_gen_mul_i32(tmp1, tmp1, tmp2);
248
    dead_tmp(tmp2);
249
    tcg_gen_sari_i32(a, a, 16);
250
    tcg_gen_sari_i32(b, b, 16);
251
    tcg_gen_mul_i32(b, b, a);
252
    tcg_gen_mov_i32(a, tmp1);
253
    dead_tmp(tmp1);
254
}
255

    
256
/* Byteswap each halfword.  */
257
static void gen_rev16(TCGv var)
258
{
259
    TCGv tmp = new_tmp();
260
    tcg_gen_shri_i32(tmp, var, 8);
261
    tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
262
    tcg_gen_shli_i32(var, var, 8);
263
    tcg_gen_andi_i32(var, var, 0xff00ff00);
264
    tcg_gen_or_i32(var, var, tmp);
265
    dead_tmp(tmp);
266
}
267

    
268
/* Byteswap low halfword and sign extend.  */
269
static void gen_revsh(TCGv var)
270
{
271
    TCGv tmp = new_tmp();
272
    tcg_gen_shri_i32(tmp, var, 8);
273
    tcg_gen_andi_i32(tmp, tmp, 0x00ff);
274
    tcg_gen_shli_i32(var, var, 8);
275
    tcg_gen_ext8s_i32(var, var);
276
    tcg_gen_or_i32(var, var, tmp);
277
    dead_tmp(tmp);
278
}
279

    
280
/* Unsigned bitfield extract.  */
281
static void gen_ubfx(TCGv var, int shift, uint32_t mask)
282
{
283
    if (shift)
284
        tcg_gen_shri_i32(var, var, shift);
285
    tcg_gen_andi_i32(var, var, mask);
286
}
287

    
288
/* Signed bitfield extract.  */
289
static void gen_sbfx(TCGv var, int shift, int width)
290
{
291
    uint32_t signbit;
292

    
293
    if (shift)
294
        tcg_gen_sari_i32(var, var, shift);
295
    if (shift + width < 32) {
296
        signbit = 1u << (width - 1);
297
        tcg_gen_andi_i32(var, var, (1u << width) - 1);
298
        tcg_gen_xori_i32(var, var, signbit);
299
        tcg_gen_subi_i32(var, var, signbit);
300
    }
301
}
302

    
303
/* Bitfield insertion.  Insert val into base.  Clobbers base and val.  */
304
static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
305
{
306
    tcg_gen_shli_i32(val, val, shift);
307
    tcg_gen_andi_i32(val, val, mask);
308
    tcg_gen_andi_i32(base, base, ~mask);
309
    tcg_gen_or_i32(dest, base, val);
310
}
311

    
312
/* Round the top 32 bits of a 64-bit value.  */
313
static void gen_roundqd(TCGv a, TCGv b)
314
{
315
    tcg_gen_shri_i32(a, a, 31);
316
    tcg_gen_add_i32(a, a, b);
317
}
318

    
319
/* FIXME: Most targets have native widening multiplication.
320
   It would be good to use that instead of a full wide multiply.  */
321
/* 32x32->64 multiply.  Marks inputs as dead.  */
322
static TCGv gen_mulu_i64_i32(TCGv a, TCGv b)
323
{
324
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
325
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
326

    
327
    tcg_gen_extu_i32_i64(tmp1, a);
328
    dead_tmp(a);
329
    tcg_gen_extu_i32_i64(tmp2, b);
330
    dead_tmp(b);
331
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
332
    return tmp1;
333
}
334

    
335
static TCGv gen_muls_i64_i32(TCGv a, TCGv b)
336
{
337
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
338
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
339

    
340
    tcg_gen_ext_i32_i64(tmp1, a);
341
    dead_tmp(a);
342
    tcg_gen_ext_i32_i64(tmp2, b);
343
    dead_tmp(b);
344
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
345
    return tmp1;
346
}
347

    
348
/* Unsigned 32x32->64 multiply.  */
349
static void gen_op_mull_T0_T1(void)
350
{
351
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
352
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
353

    
354
    tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
355
    tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
356
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
357
    tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
358
    tcg_gen_shri_i64(tmp1, tmp1, 32);
359
    tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
360
}
361

    
362
/* Signed 32x32->64 multiply.  */
363
static void gen_imull(TCGv a, TCGv b)
364
{
365
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
366
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
367

    
368
    tcg_gen_ext_i32_i64(tmp1, a);
369
    tcg_gen_ext_i32_i64(tmp2, b);
370
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
371
    tcg_gen_trunc_i64_i32(a, tmp1);
372
    tcg_gen_shri_i64(tmp1, tmp1, 32);
373
    tcg_gen_trunc_i64_i32(b, tmp1);
374
}
375
#define gen_op_imull_T0_T1() gen_imull(cpu_T[0], cpu_T[1])
376

    
377
/* Swap low and high halfwords.  */
378
static void gen_swap_half(TCGv var)
379
{
380
    TCGv tmp = new_tmp();
381
    tcg_gen_shri_i32(tmp, var, 16);
382
    tcg_gen_shli_i32(var, var, 16);
383
    tcg_gen_or_i32(var, var, tmp);
384
    dead_tmp(tmp);
385
}
386

    
387
/* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
388
    tmp = (t0 ^ t1) & 0x8000;
389
    t0 &= ~0x8000;
390
    t1 &= ~0x8000;
391
    t0 = (t0 + t1) ^ tmp;
392
 */
393

    
394
static void gen_add16(TCGv t0, TCGv t1)
395
{
396
    TCGv tmp = new_tmp();
397
    tcg_gen_xor_i32(tmp, t0, t1);
398
    tcg_gen_andi_i32(tmp, tmp, 0x8000);
399
    tcg_gen_andi_i32(t0, t0, ~0x8000);
400
    tcg_gen_andi_i32(t1, t1, ~0x8000);
401
    tcg_gen_add_i32(t0, t0, t1);
402
    tcg_gen_xor_i32(t0, t0, tmp);
403
    dead_tmp(tmp);
404
    dead_tmp(t1);
405
}
406

    
407
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
408

    
409
/* Set CF to the top bit of var.  */
410
static void gen_set_CF_bit31(TCGv var)
411
{
412
    TCGv tmp = new_tmp();
413
    tcg_gen_shri_i32(tmp, var, 31);
414
    gen_set_CF(var);
415
    dead_tmp(tmp);
416
}
417

    
418
/* Set N and Z flags from var.  */
419
static inline void gen_logic_CC(TCGv var)
420
{
421
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NZF));
422
}
423

    
424
/* T0 += T1 + CF.  */
425
static void gen_adc_T0_T1(void)
426
{
427
    TCGv tmp;
428
    gen_op_addl_T0_T1();
429
    tmp = load_cpu_field(CF);
430
    tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
431
    dead_tmp(tmp);
432
}
433

    
434
/* dest = T0 - T1 + CF - 1.  */
435
static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
436
{
437
    TCGv tmp;
438
    tcg_gen_sub_i32(dest, t0, t1);
439
    tmp = load_cpu_field(CF);
440
    tcg_gen_add_i32(dest, dest, tmp);
441
    tcg_gen_subi_i32(dest, dest, 1);
442
    dead_tmp(tmp);
443
}
444

    
445
#define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
446
#define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
447

    
448
/* FIXME:  Implement this natively.  */
449
static inline void tcg_gen_not_i32(TCGv t0, TCGv t1)
450
{
451
    tcg_gen_xori_i32(t0, t1, ~0);
452
}
453

    
454
/* T0 &= ~T1.  Clobbers T1.  */
455
/* FIXME: Implement bic natively.  */
456
static inline void gen_op_bicl_T0_T1(void)
457
{
458
    gen_op_notl_T1();
459
    gen_op_andl_T0_T1();
460
}
461

    
462
/* FIXME:  Implement this natively.  */
463
static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
464
{
465
    TCGv tmp;
466

    
467
    if (i == 0)
468
        return;
469

    
470
    tmp = new_tmp();
471
    tcg_gen_shri_i32(tmp, t1, i);
472
    tcg_gen_shli_i32(t1, t1, 32 - i);
473
    tcg_gen_or_i32(t0, t1, tmp);
474
    dead_tmp(tmp);
475
}
476

    
477
static void shifter_out_im(TCGv var, int shift)
478
{
479
    TCGv tmp = new_tmp();
480
    if (shift == 0) {
481
        tcg_gen_andi_i32(tmp, var, 1);
482
    } else {
483
        tcg_gen_shri_i32(tmp, var, shift);
484
        if (shift != 31);
485
            tcg_gen_andi_i32(tmp, tmp, 1);
486
    }
487
    gen_set_CF(tmp);
488
    dead_tmp(tmp);
489
}
490

    
491
/* Shift by immediate.  Includes special handling for shift == 0.  */
492
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
493
{
494
    switch (shiftop) {
495
    case 0: /* LSL */
496
        if (shift != 0) {
497
            if (flags)
498
                shifter_out_im(var, 32 - shift);
499
            tcg_gen_shli_i32(var, var, shift);
500
        }
501
        break;
502
    case 1: /* LSR */
503
        if (shift == 0) {
504
            if (flags) {
505
                tcg_gen_shri_i32(var, var, 31);
506
                gen_set_CF(var);
507
            }
508
            tcg_gen_movi_i32(var, 0);
509
        } else {
510
            if (flags)
511
                shifter_out_im(var, shift - 1);
512
            tcg_gen_shri_i32(var, var, shift);
513
        }
514
        break;
515
    case 2: /* ASR */
516
        if (shift == 0)
517
            shift = 32;
518
        if (flags)
519
            shifter_out_im(var, shift - 1);
520
        if (shift == 32)
521
          shift = 31;
522
        tcg_gen_sari_i32(var, var, shift);
523
        break;
524
    case 3: /* ROR/RRX */
525
        if (shift != 0) {
526
            if (flags)
527
                shifter_out_im(var, shift - 1);
528
            tcg_gen_rori_i32(var, var, shift); break;
529
        } else {
530
            TCGv tmp = load_cpu_field(CF);
531
            if (flags)
532
                shifter_out_im(var, 0);
533
            tcg_gen_shri_i32(var, var, 1);
534
            tcg_gen_shli_i32(tmp, tmp, 31);
535
            tcg_gen_or_i32(var, var, tmp);
536
            dead_tmp(tmp);
537
        }
538
    }
539
};
540

    
541
#define PAS_OP(pfx) \
542
    switch (op2) {  \
543
    case 0: gen_pas_helper(glue(pfx,add16)); break; \
544
    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
545
    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
546
    case 3: gen_pas_helper(glue(pfx,sub16)); break; \
547
    case 4: gen_pas_helper(glue(pfx,add8)); break; \
548
    case 7: gen_pas_helper(glue(pfx,sub8)); break; \
549
    }
550
static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
551
{
552
    TCGv tmp;
553

    
554
    switch (op1) {
555
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
556
    case 1:
557
        tmp = tcg_temp_new(TCG_TYPE_PTR);
558
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
559
        PAS_OP(s)
560
        break;
561
    case 5:
562
        tmp = tcg_temp_new(TCG_TYPE_PTR);
563
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
564
        PAS_OP(u)
565
        break;
566
#undef gen_pas_helper
567
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
568
    case 2:
569
        PAS_OP(q);
570
        break;
571
    case 3:
572
        PAS_OP(sh);
573
        break;
574
    case 6:
575
        PAS_OP(uq);
576
        break;
577
    case 7:
578
        PAS_OP(uh);
579
        break;
580
#undef gen_pas_helper
581
    }
582
}
583
#undef PAS_OP
584

    
585
/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
586
#define PAS_OP(pfx) \
587
    switch (op2) {  \
588
    case 0: gen_pas_helper(glue(pfx,add8)); break; \
589
    case 1: gen_pas_helper(glue(pfx,add16)); break; \
590
    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
591
    case 4: gen_pas_helper(glue(pfx,sub8)); break; \
592
    case 5: gen_pas_helper(glue(pfx,sub16)); break; \
593
    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
594
    }
595
static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
596
{
597
    TCGv tmp;
598

    
599
    switch (op1) {
600
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
601
    case 0:
602
        tmp = tcg_temp_new(TCG_TYPE_PTR);
603
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
604
        PAS_OP(s)
605
        break;
606
    case 4:
607
        tmp = tcg_temp_new(TCG_TYPE_PTR);
608
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
609
        PAS_OP(u)
610
        break;
611
#undef gen_pas_helper
612
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
613
    case 1:
614
        PAS_OP(q);
615
        break;
616
    case 2:
617
        PAS_OP(sh);
618
        break;
619
    case 5:
620
        PAS_OP(uq);
621
        break;
622
    case 6:
623
        PAS_OP(uh);
624
        break;
625
#undef gen_pas_helper
626
    }
627
}
628
#undef PAS_OP
629

    
630
static void gen_test_cc(int cc, int label)
631
{
632
    TCGv tmp;
633
    TCGv tmp2;
634
    TCGv zero;
635
    int inv;
636

    
637
    zero = tcg_const_i32(0);
638
    switch (cc) {
639
    case 0: /* eq: Z */
640
        tmp = load_cpu_field(NZF);
641
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
642
        break;
643
    case 1: /* ne: !Z */
644
        tmp = load_cpu_field(NZF);
645
        tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
646
        break;
647
    case 2: /* cs: C */
648
        tmp = load_cpu_field(CF);
649
        tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
650
        break;
651
    case 3: /* cc: !C */
652
        tmp = load_cpu_field(CF);
653
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
654
        break;
655
    case 4: /* mi: N */
656
        tmp = load_cpu_field(NZF);
657
        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
658
        break;
659
    case 5: /* pl: !N */
660
        tmp = load_cpu_field(NZF);
661
        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
662
        break;
663
    case 6: /* vs: V */
664
        tmp = load_cpu_field(VF);
665
        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
666
        break;
667
    case 7: /* vc: !V */
668
        tmp = load_cpu_field(VF);
669
        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
670
        break;
671
    case 8: /* hi: C && !Z */
672
        inv = gen_new_label();
673
        tmp = load_cpu_field(CF);
674
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);
675
        dead_tmp(tmp);
676
        tmp = load_cpu_field(NZF);
677
        tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
678
        gen_set_label(inv);
679
        break;
680
    case 9: /* ls: !C || Z */
681
        tmp = load_cpu_field(CF);
682
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
683
        dead_tmp(tmp);
684
        tmp = load_cpu_field(NZF);
685
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
686
        break;
687
    case 10: /* ge: N == V -> N ^ V == 0 */
688
        tmp = load_cpu_field(VF);
689
        tmp2 = load_cpu_field(NZF);
690
        tcg_gen_xor_i32(tmp, tmp, tmp2);
691
        dead_tmp(tmp2);
692
        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
693
        break;
694
    case 11: /* lt: N != V -> N ^ V != 0 */
695
        tmp = load_cpu_field(VF);
696
        tmp2 = load_cpu_field(NZF);
697
        tcg_gen_xor_i32(tmp, tmp, tmp2);
698
        dead_tmp(tmp2);
699
        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
700
        break;
701
    case 12: /* gt: !Z && N == V */
702
        inv = gen_new_label();
703
        tmp = load_cpu_field(NZF);
704
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);
705
        dead_tmp(tmp);
706
        tmp = load_cpu_field(VF);
707
        tmp2 = load_cpu_field(NZF);
708
        tcg_gen_xor_i32(tmp, tmp, tmp2);
709
        dead_tmp(tmp2);
710
        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
711
        gen_set_label(inv);
712
        break;
713
    case 13: /* le: Z || N != V */
714
        tmp = load_cpu_field(NZF);
715
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
716
        dead_tmp(tmp);
717
        tmp = load_cpu_field(VF);
718
        tmp2 = load_cpu_field(NZF);
719
        tcg_gen_xor_i32(tmp, tmp, tmp2);
720
        dead_tmp(tmp2);
721
        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
722
        break;
723
    default:
724
        fprintf(stderr, "Bad condition code 0x%x\n", cc);
725
        abort();
726
    }
727
    dead_tmp(tmp);
728
}
729

    
730
const uint8_t table_logic_cc[16] = {
731
    1, /* and */
732
    1, /* xor */
733
    0, /* sub */
734
    0, /* rsb */
735
    0, /* add */
736
    0, /* adc */
737
    0, /* sbc */
738
    0, /* rsc */
739
    1, /* andl */
740
    1, /* xorl */
741
    0, /* cmp */
742
    0, /* cmn */
743
    1, /* orr */
744
    1, /* mov */
745
    1, /* bic */
746
    1, /* mvn */
747
};
748

    
749
static GenOpFunc *gen_shift_T1_T0[4] = {
750
    gen_op_shll_T1_T0,
751
    gen_op_shrl_T1_T0,
752
    gen_op_sarl_T1_T0,
753
    gen_op_rorl_T1_T0,
754
};
755

    
756
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
757
    gen_op_shll_T1_T0_cc,
758
    gen_op_shrl_T1_T0_cc,
759
    gen_op_sarl_T1_T0_cc,
760
    gen_op_rorl_T1_T0_cc,
761
};
762

    
763
/* Set PC and Thumb state from an immediate address.  */
764
static inline void gen_bx_im(DisasContext *s, uint32_t addr)
765
{
766
    TCGv tmp;
767

    
768
    s->is_jmp = DISAS_UPDATE;
769
    tmp = new_tmp();
770
    if (s->thumb != (addr & 1)) {
771
        tcg_gen_movi_i32(tmp, addr & 1);
772
        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
773
    }
774
    tcg_gen_movi_i32(tmp, addr & ~1);
775
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));
776
    dead_tmp(tmp);
777
}
778

    
779
/* Set PC and Thumb state from var.  var is marked as dead.  */
780
static inline void gen_bx(DisasContext *s, TCGv var)
781
{
782
    TCGv tmp;
783

    
784
    s->is_jmp = DISAS_UPDATE;
785
    tmp = new_tmp();
786
    tcg_gen_andi_i32(tmp, var, 1);
787
    store_cpu_field(tmp, thumb);
788
    tcg_gen_andi_i32(var, var, ~1);
789
    store_cpu_field(var, regs[15]);
790
}
791

    
792
/* TODO: This should be removed.  Use gen_bx instead.  */
793
static inline void gen_bx_T0(DisasContext *s)
794
{
795
    TCGv tmp = new_tmp();
796
    tcg_gen_mov_i32(tmp, cpu_T[0]);
797
    gen_bx(s, tmp);
798
}
799

    
800
#if defined(CONFIG_USER_ONLY)
801
#define gen_ldst(name, s) gen_op_##name##_raw()
802
#else
803
#define gen_ldst(name, s) do { \
804
    s->is_mem = 1; \
805
    if (IS_USER(s)) \
806
        gen_op_##name##_user(); \
807
    else \
808
        gen_op_##name##_kernel(); \
809
    } while (0)
810
#endif
811
static inline TCGv gen_ld8s(TCGv addr, int index)
812
{
813
    TCGv tmp = new_tmp();
814
    tcg_gen_qemu_ld8s(tmp, addr, index);
815
    return tmp;
816
}
817
static inline TCGv gen_ld8u(TCGv addr, int index)
818
{
819
    TCGv tmp = new_tmp();
820
    tcg_gen_qemu_ld8u(tmp, addr, index);
821
    return tmp;
822
}
823
static inline TCGv gen_ld16s(TCGv addr, int index)
824
{
825
    TCGv tmp = new_tmp();
826
    tcg_gen_qemu_ld16s(tmp, addr, index);
827
    return tmp;
828
}
829
static inline TCGv gen_ld16u(TCGv addr, int index)
830
{
831
    TCGv tmp = new_tmp();
832
    tcg_gen_qemu_ld16u(tmp, addr, index);
833
    return tmp;
834
}
835
static inline TCGv gen_ld32(TCGv addr, int index)
836
{
837
    TCGv tmp = new_tmp();
838
    tcg_gen_qemu_ld32u(tmp, addr, index);
839
    return tmp;
840
}
841
static inline void gen_st8(TCGv val, TCGv addr, int index)
842
{
843
    tcg_gen_qemu_st8(val, addr, index);
844
    dead_tmp(val);
845
}
846
static inline void gen_st16(TCGv val, TCGv addr, int index)
847
{
848
    tcg_gen_qemu_st16(val, addr, index);
849
    dead_tmp(val);
850
}
851
static inline void gen_st32(TCGv val, TCGv addr, int index)
852
{
853
    tcg_gen_qemu_st32(val, addr, index);
854
    dead_tmp(val);
855
}
856

    
857
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
858
{
859
    load_reg_var(s, cpu_T[0], reg);
860
}
861

    
862
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
863
{
864
    load_reg_var(s, cpu_T[1], reg);
865
}
866

    
867
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
868
{
869
    load_reg_var(s, cpu_T[2], reg);
870
}
871

    
872
static inline void gen_set_pc_im(uint32_t val)
873
{
874
    TCGv tmp = new_tmp();
875
    tcg_gen_movi_i32(tmp, val);
876
    store_cpu_field(tmp, regs[15]);
877
}
878

    
879
static inline void gen_set_pc_T0(void)
880
{
881
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
882
}
883

    
884
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
885
{
886
    TCGv tmp;
887
    if (reg == 15) {
888
        tmp = new_tmp();
889
        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
890
    } else {
891
        tmp = cpu_T[t];
892
    }
893
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
894
    if (reg == 15) {
895
        dead_tmp(tmp);
896
        s->is_jmp = DISAS_JUMP;
897
    }
898
}
899

    
900
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
901
{
902
    gen_movl_reg_TN(s, reg, 0);
903
}
904

    
905
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
906
{
907
    gen_movl_reg_TN(s, reg, 1);
908
}
909

    
910
/* Force a TB lookup after an instruction that changes the CPU state.  */
911
static inline void gen_lookup_tb(DisasContext *s)
912
{
913
    gen_op_movl_T0_im(s->pc);
914
    gen_movl_reg_T0(s, 15);
915
    s->is_jmp = DISAS_UPDATE;
916
}
917

    
918
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
919
                                       TCGv var)
920
{
921
    int val, rm, shift, shiftop;
922
    TCGv offset;
923

    
924
    if (!(insn & (1 << 25))) {
925
        /* immediate */
926
        val = insn & 0xfff;
927
        if (!(insn & (1 << 23)))
928
            val = -val;
929
        if (val != 0)
930
            tcg_gen_addi_i32(var, var, val);
931
    } else {
932
        /* shift/register */
933
        rm = (insn) & 0xf;
934
        shift = (insn >> 7) & 0x1f;
935
        shiftop = (insn >> 5) & 3;
936
        offset = load_reg(s, rm);
937
        gen_arm_shift_im(offset, shiftop, shift, 0);
938
        if (!(insn & (1 << 23)))
939
            tcg_gen_sub_i32(var, var, offset);
940
        else
941
            tcg_gen_add_i32(var, var, offset);
942
        dead_tmp(offset);
943
    }
944
}
945

    
946
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
947
                                        int extra, TCGv var)
948
{
949
    int val, rm;
950
    TCGv offset;
951

    
952
    if (insn & (1 << 22)) {
953
        /* immediate */
954
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
955
        if (!(insn & (1 << 23)))
956
            val = -val;
957
        val += extra;
958
        if (val != 0)
959
            tcg_gen_addi_i32(var, var, val);
960
    } else {
961
        /* register */
962
        if (extra)
963
            tcg_gen_addi_i32(var, var, extra);
964
        rm = (insn) & 0xf;
965
        offset = load_reg(s, rm);
966
        if (!(insn & (1 << 23)))
967
            tcg_gen_sub_i32(var, var, offset);
968
        else
969
            tcg_gen_add_i32(var, var, offset);
970
        dead_tmp(offset);
971
    }
972
}
973

    
974
#define VFP_OP2(name)                                                 \
975
static inline void gen_vfp_##name(int dp)                             \
976
{                                                                     \
977
    if (dp)                                                           \
978
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
979
    else                                                              \
980
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
981
}
982

    
983
#define VFP_OP1i(name)                               \
984
static inline void gen_vfp_##name(int dp, int arg)  \
985
{                                                   \
986
    if (dp)                                         \
987
        gen_op_vfp_##name##d(arg);                  \
988
    else                                            \
989
        gen_op_vfp_##name##s(arg);                  \
990
}
991

    
992
VFP_OP2(add)
993
VFP_OP2(sub)
994
VFP_OP2(mul)
995
VFP_OP2(div)
996

    
997
#undef VFP_OP2
998

    
999
static inline void gen_vfp_abs(int dp)
1000
{
1001
    if (dp)
1002
        gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1003
    else
1004
        gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1005
}
1006

    
1007
static inline void gen_vfp_neg(int dp)
1008
{
1009
    if (dp)
1010
        gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1011
    else
1012
        gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1013
}
1014

    
1015
static inline void gen_vfp_sqrt(int dp)
1016
{
1017
    if (dp)
1018
        gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1019
    else
1020
        gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1021
}
1022

    
1023
static inline void gen_vfp_cmp(int dp)
1024
{
1025
    if (dp)
1026
        gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1027
    else
1028
        gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1029
}
1030

    
1031
static inline void gen_vfp_cmpe(int dp)
1032
{
1033
    if (dp)
1034
        gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1035
    else
1036
        gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1037
}
1038

    
1039
static inline void gen_vfp_F1_ld0(int dp)
1040
{
1041
    if (dp)
1042
        tcg_gen_movi_i64(cpu_F0d, 0);
1043
    else
1044
        tcg_gen_movi_i32(cpu_F0s, 0);
1045
}
1046

    
1047
static inline void gen_vfp_uito(int dp)
1048
{
1049
    if (dp)
1050
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1051
    else
1052
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1053
}
1054

    
1055
static inline void gen_vfp_sito(int dp)
1056
{
1057
    if (dp)
1058
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1059
    else
1060
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1061
}
1062

    
1063
static inline void gen_vfp_toui(int dp)
1064
{
1065
    if (dp)
1066
        gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1067
    else
1068
        gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1069
}
1070

    
1071
static inline void gen_vfp_touiz(int dp)
1072
{
1073
    if (dp)
1074
        gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1075
    else
1076
        gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1077
}
1078

    
1079
static inline void gen_vfp_tosi(int dp)
1080
{
1081
    if (dp)
1082
        gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1083
    else
1084
        gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1085
}
1086

    
1087
static inline void gen_vfp_tosiz(int dp)
1088
{
1089
    if (dp)
1090
        gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1091
    else
1092
        gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1093
}
1094

    
1095
#define VFP_GEN_FIX(name) \
1096
static inline void gen_vfp_##name(int dp, int shift) \
1097
{ \
1098
    if (dp) \
1099
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1100
    else \
1101
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1102
}
1103
VFP_GEN_FIX(tosh)
1104
VFP_GEN_FIX(tosl)
1105
VFP_GEN_FIX(touh)
1106
VFP_GEN_FIX(toul)
1107
VFP_GEN_FIX(shto)
1108
VFP_GEN_FIX(slto)
1109
VFP_GEN_FIX(uhto)
1110
VFP_GEN_FIX(ulto)
1111
#undef VFP_GEN_FIX
1112

    
1113
static inline void gen_vfp_ld(DisasContext *s, int dp)
1114
{
1115
    if (dp)
1116
        tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1117
    else
1118
        tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1119
}
1120

    
1121
static inline void gen_vfp_st(DisasContext *s, int dp)
1122
{
1123
    if (dp)
1124
        tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1125
    else
1126
        tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1127
}
1128

    
1129
static inline long
1130
vfp_reg_offset (int dp, int reg)
1131
{
1132
    if (dp)
1133
        return offsetof(CPUARMState, vfp.regs[reg]);
1134
    else if (reg & 1) {
1135
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1136
          + offsetof(CPU_DoubleU, l.upper);
1137
    } else {
1138
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1139
          + offsetof(CPU_DoubleU, l.lower);
1140
    }
1141
}
1142

    
1143
/* Return the offset of a 32-bit piece of a NEON register.
1144
   zero is the least significant end of the register.  */
1145
static inline long
1146
neon_reg_offset (int reg, int n)
1147
{
1148
    int sreg;
1149
    sreg = reg * 2 + n;
1150
    return vfp_reg_offset(0, sreg);
1151
}
1152

    
1153
#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
1154
#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
1155

    
1156
#define tcg_gen_ld_f32 tcg_gen_ld_i32
1157
#define tcg_gen_ld_f64 tcg_gen_ld_i64
1158
#define tcg_gen_st_f32 tcg_gen_st_i32
1159
#define tcg_gen_st_f64 tcg_gen_st_i64
1160

    
1161
static inline void gen_mov_F0_vreg(int dp, int reg)
1162
{
1163
    if (dp)
1164
        tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1165
    else
1166
        tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1167
}
1168

    
1169
static inline void gen_mov_F1_vreg(int dp, int reg)
1170
{
1171
    if (dp)
1172
        tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1173
    else
1174
        tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1175
}
1176

    
1177
static inline void gen_mov_vreg_F0(int dp, int reg)
1178
{
1179
    if (dp)
1180
        tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1181
    else
1182
        tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1183
}
1184

    
1185
#define ARM_CP_RW_BIT        (1 << 20)
1186

    
1187
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1188
{
1189
    int rd;
1190
    uint32_t offset;
1191

    
1192
    rd = (insn >> 16) & 0xf;
1193
    gen_movl_T1_reg(s, rd);
1194

    
1195
    offset = (insn & 0xff) << ((insn >> 7) & 2);
1196
    if (insn & (1 << 24)) {
1197
        /* Pre indexed */
1198
        if (insn & (1 << 23))
1199
            gen_op_addl_T1_im(offset);
1200
        else
1201
            gen_op_addl_T1_im(-offset);
1202

    
1203
        if (insn & (1 << 21))
1204
            gen_movl_reg_T1(s, rd);
1205
    } else if (insn & (1 << 21)) {
1206
        /* Post indexed */
1207
        if (insn & (1 << 23))
1208
            gen_op_movl_T0_im(offset);
1209
        else
1210
            gen_op_movl_T0_im(- offset);
1211
        gen_op_addl_T0_T1();
1212
        gen_movl_reg_T0(s, rd);
1213
    } else if (!(insn & (1 << 23)))
1214
        return 1;
1215
    return 0;
1216
}
1217

    
1218
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1219
{
1220
    int rd = (insn >> 0) & 0xf;
1221

    
1222
    if (insn & (1 << 8))
1223
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1224
            return 1;
1225
        else
1226
            gen_op_iwmmxt_movl_T0_wCx(rd);
1227
    else
1228
        gen_op_iwmmxt_movl_T0_T1_wRn(rd);
1229

    
1230
    gen_op_movl_T1_im(mask);
1231
    gen_op_andl_T0_T1();
1232
    return 0;
1233
}
1234

    
1235
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
1236
   (ie. an undefined instruction).  */
1237
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1238
{
1239
    int rd, wrd;
1240
    int rdhi, rdlo, rd0, rd1, i;
1241
    TCGv tmp;
1242

    
1243
    if ((insn & 0x0e000e00) == 0x0c000000) {
1244
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
1245
            wrd = insn & 0xf;
1246
            rdlo = (insn >> 12) & 0xf;
1247
            rdhi = (insn >> 16) & 0xf;
1248
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
1249
                gen_op_iwmmxt_movl_T0_T1_wRn(wrd);
1250
                gen_movl_reg_T0(s, rdlo);
1251
                gen_movl_reg_T1(s, rdhi);
1252
            } else {                                        /* TMCRR */
1253
                gen_movl_T0_reg(s, rdlo);
1254
                gen_movl_T1_reg(s, rdhi);
1255
                gen_op_iwmmxt_movl_wRn_T0_T1(wrd);
1256
                gen_op_iwmmxt_set_mup();
1257
            }
1258
            return 0;
1259
        }
1260

    
1261
        wrd = (insn >> 12) & 0xf;
1262
        if (gen_iwmmxt_address(s, insn))
1263
            return 1;
1264
        if (insn & ARM_CP_RW_BIT) {
1265
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
1266
                tmp = gen_ld32(cpu_T[1], IS_USER(s));
1267
                tcg_gen_mov_i32(cpu_T[0], tmp);
1268
                dead_tmp(tmp);
1269
                gen_op_iwmmxt_movl_wCx_T0(wrd);
1270
            } else {
1271
                if (insn & (1 << 8))
1272
                    if (insn & (1 << 22))                /* WLDRD */
1273
                        gen_ldst(iwmmxt_ldq, s);
1274
                    else                                /* WLDRW wRd */
1275
                        gen_ldst(iwmmxt_ldl, s);
1276
                else
1277
                    if (insn & (1 << 22))                /* WLDRH */
1278
                        gen_ldst(iwmmxt_ldw, s);
1279
                    else                                /* WLDRB */
1280
                        gen_ldst(iwmmxt_ldb, s);
1281
                gen_op_iwmmxt_movq_wRn_M0(wrd);
1282
            }
1283
        } else {
1284
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
1285
                gen_op_iwmmxt_movl_T0_wCx(wrd);
1286
                tmp = new_tmp();
1287
                tcg_gen_mov_i32(tmp, cpu_T[0]);
1288
                gen_st32(tmp, cpu_T[1], IS_USER(s));
1289
            } else {
1290
                gen_op_iwmmxt_movq_M0_wRn(wrd);
1291
                if (insn & (1 << 8))
1292
                    if (insn & (1 << 22))                /* WSTRD */
1293
                        gen_ldst(iwmmxt_stq, s);
1294
                    else                                /* WSTRW wRd */
1295
                        gen_ldst(iwmmxt_stl, s);
1296
                else
1297
                    if (insn & (1 << 22))                /* WSTRH */
1298
                        gen_ldst(iwmmxt_ldw, s);
1299
                    else                                /* WSTRB */
1300
                        gen_ldst(iwmmxt_stb, s);
1301
            }
1302
        }
1303
        return 0;
1304
    }
1305

    
1306
    if ((insn & 0x0f000000) != 0x0e000000)
1307
        return 1;
1308

    
1309
    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1310
    case 0x000:                                                /* WOR */
1311
        wrd = (insn >> 12) & 0xf;
1312
        rd0 = (insn >> 0) & 0xf;
1313
        rd1 = (insn >> 16) & 0xf;
1314
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1315
        gen_op_iwmmxt_orq_M0_wRn(rd1);
1316
        gen_op_iwmmxt_setpsr_nz();
1317
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1318
        gen_op_iwmmxt_set_mup();
1319
        gen_op_iwmmxt_set_cup();
1320
        break;
1321
    case 0x011:                                                /* TMCR */
1322
        if (insn & 0xf)
1323
            return 1;
1324
        rd = (insn >> 12) & 0xf;
1325
        wrd = (insn >> 16) & 0xf;
1326
        switch (wrd) {
1327
        case ARM_IWMMXT_wCID:
1328
        case ARM_IWMMXT_wCASF:
1329
            break;
1330
        case ARM_IWMMXT_wCon:
1331
            gen_op_iwmmxt_set_cup();
1332
            /* Fall through.  */
1333
        case ARM_IWMMXT_wCSSF:
1334
            gen_op_iwmmxt_movl_T0_wCx(wrd);
1335
            gen_movl_T1_reg(s, rd);
1336
            gen_op_bicl_T0_T1();
1337
            gen_op_iwmmxt_movl_wCx_T0(wrd);
1338
            break;
1339
        case ARM_IWMMXT_wCGR0:
1340
        case ARM_IWMMXT_wCGR1:
1341
        case ARM_IWMMXT_wCGR2:
1342
        case ARM_IWMMXT_wCGR3:
1343
            gen_op_iwmmxt_set_cup();
1344
            gen_movl_reg_T0(s, rd);
1345
            gen_op_iwmmxt_movl_wCx_T0(wrd);
1346
            break;
1347
        default:
1348
            return 1;
1349
        }
1350
        break;
1351
    case 0x100:                                                /* WXOR */
1352
        wrd = (insn >> 12) & 0xf;
1353
        rd0 = (insn >> 0) & 0xf;
1354
        rd1 = (insn >> 16) & 0xf;
1355
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1356
        gen_op_iwmmxt_xorq_M0_wRn(rd1);
1357
        gen_op_iwmmxt_setpsr_nz();
1358
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1359
        gen_op_iwmmxt_set_mup();
1360
        gen_op_iwmmxt_set_cup();
1361
        break;
1362
    case 0x111:                                                /* TMRC */
1363
        if (insn & 0xf)
1364
            return 1;
1365
        rd = (insn >> 12) & 0xf;
1366
        wrd = (insn >> 16) & 0xf;
1367
        gen_op_iwmmxt_movl_T0_wCx(wrd);
1368
        gen_movl_reg_T0(s, rd);
1369
        break;
1370
    case 0x300:                                                /* WANDN */
1371
        wrd = (insn >> 12) & 0xf;
1372
        rd0 = (insn >> 0) & 0xf;
1373
        rd1 = (insn >> 16) & 0xf;
1374
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1375
        gen_op_iwmmxt_negq_M0();
1376
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1377
        gen_op_iwmmxt_setpsr_nz();
1378
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1379
        gen_op_iwmmxt_set_mup();
1380
        gen_op_iwmmxt_set_cup();
1381
        break;
1382
    case 0x200:                                                /* WAND */
1383
        wrd = (insn >> 12) & 0xf;
1384
        rd0 = (insn >> 0) & 0xf;
1385
        rd1 = (insn >> 16) & 0xf;
1386
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1387
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1388
        gen_op_iwmmxt_setpsr_nz();
1389
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1390
        gen_op_iwmmxt_set_mup();
1391
        gen_op_iwmmxt_set_cup();
1392
        break;
1393
    case 0x810: case 0xa10:                                /* WMADD */
1394
        wrd = (insn >> 12) & 0xf;
1395
        rd0 = (insn >> 0) & 0xf;
1396
        rd1 = (insn >> 16) & 0xf;
1397
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1398
        if (insn & (1 << 21))
1399
            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1400
        else
1401
            gen_op_iwmmxt_madduq_M0_wRn(rd1);
1402
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1403
        gen_op_iwmmxt_set_mup();
1404
        break;
1405
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:        /* WUNPCKIL */
1406
        wrd = (insn >> 12) & 0xf;
1407
        rd0 = (insn >> 16) & 0xf;
1408
        rd1 = (insn >> 0) & 0xf;
1409
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1410
        switch ((insn >> 22) & 3) {
1411
        case 0:
1412
            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1413
            break;
1414
        case 1:
1415
            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1416
            break;
1417
        case 2:
1418
            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1419
            break;
1420
        case 3:
1421
            return 1;
1422
        }
1423
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1424
        gen_op_iwmmxt_set_mup();
1425
        gen_op_iwmmxt_set_cup();
1426
        break;
1427
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:        /* WUNPCKIH */
1428
        wrd = (insn >> 12) & 0xf;
1429
        rd0 = (insn >> 16) & 0xf;
1430
        rd1 = (insn >> 0) & 0xf;
1431
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1432
        switch ((insn >> 22) & 3) {
1433
        case 0:
1434
            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1435
            break;
1436
        case 1:
1437
            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1438
            break;
1439
        case 2:
1440
            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1441
            break;
1442
        case 3:
1443
            return 1;
1444
        }
1445
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1446
        gen_op_iwmmxt_set_mup();
1447
        gen_op_iwmmxt_set_cup();
1448
        break;
1449
    case 0x012: case 0x112: case 0x412: case 0x512:        /* WSAD */
1450
        wrd = (insn >> 12) & 0xf;
1451
        rd0 = (insn >> 16) & 0xf;
1452
        rd1 = (insn >> 0) & 0xf;
1453
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1454
        if (insn & (1 << 22))
1455
            gen_op_iwmmxt_sadw_M0_wRn(rd1);
1456
        else
1457
            gen_op_iwmmxt_sadb_M0_wRn(rd1);
1458
        if (!(insn & (1 << 20)))
1459
            gen_op_iwmmxt_addl_M0_wRn(wrd);
1460
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1461
        gen_op_iwmmxt_set_mup();
1462
        break;
1463
    case 0x010: case 0x110: case 0x210: case 0x310:        /* WMUL */
1464
        wrd = (insn >> 12) & 0xf;
1465
        rd0 = (insn >> 16) & 0xf;
1466
        rd1 = (insn >> 0) & 0xf;
1467
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1468
        if (insn & (1 << 21))
1469
            gen_op_iwmmxt_mulsw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
1470
        else
1471
            gen_op_iwmmxt_muluw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
1472
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1473
        gen_op_iwmmxt_set_mup();
1474
        break;
1475
    case 0x410: case 0x510: case 0x610: case 0x710:        /* WMAC */
1476
        wrd = (insn >> 12) & 0xf;
1477
        rd0 = (insn >> 16) & 0xf;
1478
        rd1 = (insn >> 0) & 0xf;
1479
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1480
        if (insn & (1 << 21))
1481
            gen_op_iwmmxt_macsw_M0_wRn(rd1);
1482
        else
1483
            gen_op_iwmmxt_macuw_M0_wRn(rd1);
1484
        if (!(insn & (1 << 20))) {
1485
            if (insn & (1 << 21))
1486
                gen_op_iwmmxt_addsq_M0_wRn(wrd);
1487
            else
1488
                gen_op_iwmmxt_adduq_M0_wRn(wrd);
1489
        }
1490
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1491
        gen_op_iwmmxt_set_mup();
1492
        break;
1493
    case 0x006: case 0x406: case 0x806: case 0xc06:        /* WCMPEQ */
1494
        wrd = (insn >> 12) & 0xf;
1495
        rd0 = (insn >> 16) & 0xf;
1496
        rd1 = (insn >> 0) & 0xf;
1497
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1498
        switch ((insn >> 22) & 3) {
1499
        case 0:
1500
            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1501
            break;
1502
        case 1:
1503
            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1504
            break;
1505
        case 2:
1506
            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1507
            break;
1508
        case 3:
1509
            return 1;
1510
        }
1511
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1512
        gen_op_iwmmxt_set_mup();
1513
        gen_op_iwmmxt_set_cup();
1514
        break;
1515
    case 0x800: case 0x900: case 0xc00: case 0xd00:        /* WAVG2 */
1516
        wrd = (insn >> 12) & 0xf;
1517
        rd0 = (insn >> 16) & 0xf;
1518
        rd1 = (insn >> 0) & 0xf;
1519
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1520
        if (insn & (1 << 22))
1521
            gen_op_iwmmxt_avgw_M0_wRn(rd1, (insn >> 20) & 1);
1522
        else
1523
            gen_op_iwmmxt_avgb_M0_wRn(rd1, (insn >> 20) & 1);
1524
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1525
        gen_op_iwmmxt_set_mup();
1526
        gen_op_iwmmxt_set_cup();
1527
        break;
1528
    case 0x802: case 0x902: case 0xa02: case 0xb02:        /* WALIGNR */
1529
        wrd = (insn >> 12) & 0xf;
1530
        rd0 = (insn >> 16) & 0xf;
1531
        rd1 = (insn >> 0) & 0xf;
1532
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1533
        gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1534
        gen_op_movl_T1_im(7);
1535
        gen_op_andl_T0_T1();
1536
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1537
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1538
        gen_op_iwmmxt_set_mup();
1539
        break;
1540
    case 0x601: case 0x605: case 0x609: case 0x60d:        /* TINSR */
1541
        rd = (insn >> 12) & 0xf;
1542
        wrd = (insn >> 16) & 0xf;
1543
        gen_movl_T0_reg(s, rd);
1544
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1545
        switch ((insn >> 6) & 3) {
1546
        case 0:
1547
            gen_op_movl_T1_im(0xff);
1548
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1549
            break;
1550
        case 1:
1551
            gen_op_movl_T1_im(0xffff);
1552
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1553
            break;
1554
        case 2:
1555
            gen_op_movl_T1_im(0xffffffff);
1556
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1557
            break;
1558
        case 3:
1559
            return 1;
1560
        }
1561
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1562
        gen_op_iwmmxt_set_mup();
1563
        break;
1564
    case 0x107: case 0x507: case 0x907: case 0xd07:        /* TEXTRM */
1565
        rd = (insn >> 12) & 0xf;
1566
        wrd = (insn >> 16) & 0xf;
1567
        if (rd == 15)
1568
            return 1;
1569
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1570
        switch ((insn >> 22) & 3) {
1571
        case 0:
1572
            if (insn & 8)
1573
                gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1574
            else {
1575
                gen_op_movl_T1_im(0xff);
1576
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 7) << 3);
1577
            }
1578
            break;
1579
        case 1:
1580
            if (insn & 8)
1581
                gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1582
            else {
1583
                gen_op_movl_T1_im(0xffff);
1584
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 3) << 4);
1585
            }
1586
            break;
1587
        case 2:
1588
            gen_op_movl_T1_im(0xffffffff);
1589
            gen_op_iwmmxt_extru_T0_M0_T1((insn & 1) << 5);
1590
            break;
1591
        case 3:
1592
            return 1;
1593
        }
1594
        gen_movl_reg_T0(s, rd);
1595
        break;
1596
    case 0x117: case 0x517: case 0x917: case 0xd17:        /* TEXTRC */
1597
        if ((insn & 0x000ff008) != 0x0003f000)
1598
            return 1;
1599
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1600
        switch ((insn >> 22) & 3) {
1601
        case 0:
1602
            gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1603
            break;
1604
        case 1:
1605
            gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1606
            break;
1607
        case 2:
1608
            gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1609
            break;
1610
        case 3:
1611
            return 1;
1612
        }
1613
        gen_op_shll_T1_im(28);
1614
        gen_set_nzcv(cpu_T[1]);
1615
        break;
1616
    case 0x401: case 0x405: case 0x409: case 0x40d:        /* TBCST */
1617
        rd = (insn >> 12) & 0xf;
1618
        wrd = (insn >> 16) & 0xf;
1619
        gen_movl_T0_reg(s, rd);
1620
        switch ((insn >> 6) & 3) {
1621
        case 0:
1622
            gen_op_iwmmxt_bcstb_M0_T0();
1623
            break;
1624
        case 1:
1625
            gen_op_iwmmxt_bcstw_M0_T0();
1626
            break;
1627
        case 2:
1628
            gen_op_iwmmxt_bcstl_M0_T0();
1629
            break;
1630
        case 3:
1631
            return 1;
1632
        }
1633
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1634
        gen_op_iwmmxt_set_mup();
1635
        break;
1636
    case 0x113: case 0x513: case 0x913: case 0xd13:        /* TANDC */
1637
        if ((insn & 0x000ff00f) != 0x0003f000)
1638
            return 1;
1639
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1640
        switch ((insn >> 22) & 3) {
1641
        case 0:
1642
            for (i = 0; i < 7; i ++) {
1643
                gen_op_shll_T1_im(4);
1644
                gen_op_andl_T0_T1();
1645
            }
1646
            break;
1647
        case 1:
1648
            for (i = 0; i < 3; i ++) {
1649
                gen_op_shll_T1_im(8);
1650
                gen_op_andl_T0_T1();
1651
            }
1652
            break;
1653
        case 2:
1654
            gen_op_shll_T1_im(16);
1655
            gen_op_andl_T0_T1();
1656
            break;
1657
        case 3:
1658
            return 1;
1659
        }
1660
        gen_set_nzcv(cpu_T[0]);
1661
        break;
1662
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:        /* WACC */
1663
        wrd = (insn >> 12) & 0xf;
1664
        rd0 = (insn >> 16) & 0xf;
1665
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1666
        switch ((insn >> 22) & 3) {
1667
        case 0:
1668
            gen_op_iwmmxt_addcb_M0();
1669
            break;
1670
        case 1:
1671
            gen_op_iwmmxt_addcw_M0();
1672
            break;
1673
        case 2:
1674
            gen_op_iwmmxt_addcl_M0();
1675
            break;
1676
        case 3:
1677
            return 1;
1678
        }
1679
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1680
        gen_op_iwmmxt_set_mup();
1681
        break;
1682
    case 0x115: case 0x515: case 0x915: case 0xd15:        /* TORC */
1683
        if ((insn & 0x000ff00f) != 0x0003f000)
1684
            return 1;
1685
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1686
        switch ((insn >> 22) & 3) {
1687
        case 0:
1688
            for (i = 0; i < 7; i ++) {
1689
                gen_op_shll_T1_im(4);
1690
                gen_op_orl_T0_T1();
1691
            }
1692
            break;
1693
        case 1:
1694
            for (i = 0; i < 3; i ++) {
1695
                gen_op_shll_T1_im(8);
1696
                gen_op_orl_T0_T1();
1697
            }
1698
            break;
1699
        case 2:
1700
            gen_op_shll_T1_im(16);
1701
            gen_op_orl_T0_T1();
1702
            break;
1703
        case 3:
1704
            return 1;
1705
        }
1706
        gen_set_nzcv(cpu_T[0]);
1707
        break;
1708
    case 0x103: case 0x503: case 0x903: case 0xd03:        /* TMOVMSK */
1709
        rd = (insn >> 12) & 0xf;
1710
        rd0 = (insn >> 16) & 0xf;
1711
        if ((insn & 0xf) != 0)
1712
            return 1;
1713
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1714
        switch ((insn >> 22) & 3) {
1715
        case 0:
1716
            gen_op_iwmmxt_msbb_T0_M0();
1717
            break;
1718
        case 1:
1719
            gen_op_iwmmxt_msbw_T0_M0();
1720
            break;
1721
        case 2:
1722
            gen_op_iwmmxt_msbl_T0_M0();
1723
            break;
1724
        case 3:
1725
            return 1;
1726
        }
1727
        gen_movl_reg_T0(s, rd);
1728
        break;
1729
    case 0x106: case 0x306: case 0x506: case 0x706:        /* WCMPGT */
1730
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
1731
        wrd = (insn >> 12) & 0xf;
1732
        rd0 = (insn >> 16) & 0xf;
1733
        rd1 = (insn >> 0) & 0xf;
1734
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1735
        switch ((insn >> 22) & 3) {
1736
        case 0:
1737
            if (insn & (1 << 21))
1738
                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1739
            else
1740
                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1741
            break;
1742
        case 1:
1743
            if (insn & (1 << 21))
1744
                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1745
            else
1746
                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1747
            break;
1748
        case 2:
1749
            if (insn & (1 << 21))
1750
                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1751
            else
1752
                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1753
            break;
1754
        case 3:
1755
            return 1;
1756
        }
1757
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1758
        gen_op_iwmmxt_set_mup();
1759
        gen_op_iwmmxt_set_cup();
1760
        break;
1761
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:        /* WUNPCKEL */
1762
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1763
        wrd = (insn >> 12) & 0xf;
1764
        rd0 = (insn >> 16) & 0xf;
1765
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1766
        switch ((insn >> 22) & 3) {
1767
        case 0:
1768
            if (insn & (1 << 21))
1769
                gen_op_iwmmxt_unpacklsb_M0();
1770
            else
1771
                gen_op_iwmmxt_unpacklub_M0();
1772
            break;
1773
        case 1:
1774
            if (insn & (1 << 21))
1775
                gen_op_iwmmxt_unpacklsw_M0();
1776
            else
1777
                gen_op_iwmmxt_unpackluw_M0();
1778
            break;
1779
        case 2:
1780
            if (insn & (1 << 21))
1781
                gen_op_iwmmxt_unpacklsl_M0();
1782
            else
1783
                gen_op_iwmmxt_unpacklul_M0();
1784
            break;
1785
        case 3:
1786
            return 1;
1787
        }
1788
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1789
        gen_op_iwmmxt_set_mup();
1790
        gen_op_iwmmxt_set_cup();
1791
        break;
1792
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:        /* WUNPCKEH */
1793
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1794
        wrd = (insn >> 12) & 0xf;
1795
        rd0 = (insn >> 16) & 0xf;
1796
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1797
        switch ((insn >> 22) & 3) {
1798
        case 0:
1799
            if (insn & (1 << 21))
1800
                gen_op_iwmmxt_unpackhsb_M0();
1801
            else
1802
                gen_op_iwmmxt_unpackhub_M0();
1803
            break;
1804
        case 1:
1805
            if (insn & (1 << 21))
1806
                gen_op_iwmmxt_unpackhsw_M0();
1807
            else
1808
                gen_op_iwmmxt_unpackhuw_M0();
1809
            break;
1810
        case 2:
1811
            if (insn & (1 << 21))
1812
                gen_op_iwmmxt_unpackhsl_M0();
1813
            else
1814
                gen_op_iwmmxt_unpackhul_M0();
1815
            break;
1816
        case 3:
1817
            return 1;
1818
        }
1819
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1820
        gen_op_iwmmxt_set_mup();
1821
        gen_op_iwmmxt_set_cup();
1822
        break;
1823
    case 0x204: case 0x604: case 0xa04: case 0xe04:        /* WSRL */
1824
    case 0x214: case 0x614: case 0xa14: case 0xe14:
1825
        wrd = (insn >> 12) & 0xf;
1826
        rd0 = (insn >> 16) & 0xf;
1827
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1828
        if (gen_iwmmxt_shift(insn, 0xff))
1829
            return 1;
1830
        switch ((insn >> 22) & 3) {
1831
        case 0:
1832
            return 1;
1833
        case 1:
1834
            gen_op_iwmmxt_srlw_M0_T0();
1835
            break;
1836
        case 2:
1837
            gen_op_iwmmxt_srll_M0_T0();
1838
            break;
1839
        case 3:
1840
            gen_op_iwmmxt_srlq_M0_T0();
1841
            break;
1842
        }
1843
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1844
        gen_op_iwmmxt_set_mup();
1845
        gen_op_iwmmxt_set_cup();
1846
        break;
1847
    case 0x004: case 0x404: case 0x804: case 0xc04:        /* WSRA */
1848
    case 0x014: case 0x414: case 0x814: case 0xc14:
1849
        wrd = (insn >> 12) & 0xf;
1850
        rd0 = (insn >> 16) & 0xf;
1851
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1852
        if (gen_iwmmxt_shift(insn, 0xff))
1853
            return 1;
1854
        switch ((insn >> 22) & 3) {
1855
        case 0:
1856
            return 1;
1857
        case 1:
1858
            gen_op_iwmmxt_sraw_M0_T0();
1859
            break;
1860
        case 2:
1861
            gen_op_iwmmxt_sral_M0_T0();
1862
            break;
1863
        case 3:
1864
            gen_op_iwmmxt_sraq_M0_T0();
1865
            break;
1866
        }
1867
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1868
        gen_op_iwmmxt_set_mup();
1869
        gen_op_iwmmxt_set_cup();
1870
        break;
1871
    case 0x104: case 0x504: case 0x904: case 0xd04:        /* WSLL */
1872
    case 0x114: case 0x514: case 0x914: case 0xd14:
1873
        wrd = (insn >> 12) & 0xf;
1874
        rd0 = (insn >> 16) & 0xf;
1875
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1876
        if (gen_iwmmxt_shift(insn, 0xff))
1877
            return 1;
1878
        switch ((insn >> 22) & 3) {
1879
        case 0:
1880
            return 1;
1881
        case 1:
1882
            gen_op_iwmmxt_sllw_M0_T0();
1883
            break;
1884
        case 2:
1885
            gen_op_iwmmxt_slll_M0_T0();
1886
            break;
1887
        case 3:
1888
            gen_op_iwmmxt_sllq_M0_T0();
1889
            break;
1890
        }
1891
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1892
        gen_op_iwmmxt_set_mup();
1893
        gen_op_iwmmxt_set_cup();
1894
        break;
1895
    case 0x304: case 0x704: case 0xb04: case 0xf04:        /* WROR */
1896
    case 0x314: case 0x714: case 0xb14: case 0xf14:
1897
        wrd = (insn >> 12) & 0xf;
1898
        rd0 = (insn >> 16) & 0xf;
1899
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1900
        switch ((insn >> 22) & 3) {
1901
        case 0:
1902
            return 1;
1903
        case 1:
1904
            if (gen_iwmmxt_shift(insn, 0xf))
1905
                return 1;
1906
            gen_op_iwmmxt_rorw_M0_T0();
1907
            break;
1908
        case 2:
1909
            if (gen_iwmmxt_shift(insn, 0x1f))
1910
                return 1;
1911
            gen_op_iwmmxt_rorl_M0_T0();
1912
            break;
1913
        case 3:
1914
            if (gen_iwmmxt_shift(insn, 0x3f))
1915
                return 1;
1916
            gen_op_iwmmxt_rorq_M0_T0();
1917
            break;
1918
        }
1919
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1920
        gen_op_iwmmxt_set_mup();
1921
        gen_op_iwmmxt_set_cup();
1922
        break;
1923
    case 0x116: case 0x316: case 0x516: case 0x716:        /* WMIN */
1924
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
1925
        wrd = (insn >> 12) & 0xf;
1926
        rd0 = (insn >> 16) & 0xf;
1927
        rd1 = (insn >> 0) & 0xf;
1928
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1929
        switch ((insn >> 22) & 3) {
1930
        case 0:
1931
            if (insn & (1 << 21))
1932
                gen_op_iwmmxt_minsb_M0_wRn(rd1);
1933
            else
1934
                gen_op_iwmmxt_minub_M0_wRn(rd1);
1935
            break;
1936
        case 1:
1937
            if (insn & (1 << 21))
1938
                gen_op_iwmmxt_minsw_M0_wRn(rd1);
1939
            else
1940
                gen_op_iwmmxt_minuw_M0_wRn(rd1);
1941
            break;
1942
        case 2:
1943
            if (insn & (1 << 21))
1944
                gen_op_iwmmxt_minsl_M0_wRn(rd1);
1945
            else
1946
                gen_op_iwmmxt_minul_M0_wRn(rd1);
1947
            break;
1948
        case 3:
1949
            return 1;
1950
        }
1951
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1952
        gen_op_iwmmxt_set_mup();
1953
        break;
1954
    case 0x016: case 0x216: case 0x416: case 0x616:        /* WMAX */
1955
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
1956
        wrd = (insn >> 12) & 0xf;
1957
        rd0 = (insn >> 16) & 0xf;
1958
        rd1 = (insn >> 0) & 0xf;
1959
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1960
        switch ((insn >> 22) & 3) {
1961
        case 0:
1962
            if (insn & (1 << 21))
1963
                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
1964
            else
1965
                gen_op_iwmmxt_maxub_M0_wRn(rd1);
1966
            break;
1967
        case 1:
1968
            if (insn & (1 << 21))
1969
                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
1970
            else
1971
                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
1972
            break;
1973
        case 2:
1974
            if (insn & (1 << 21))
1975
                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
1976
            else
1977
                gen_op_iwmmxt_maxul_M0_wRn(rd1);
1978
            break;
1979
        case 3:
1980
            return 1;
1981
        }
1982
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1983
        gen_op_iwmmxt_set_mup();
1984
        break;
1985
    case 0x002: case 0x102: case 0x202: case 0x302:        /* WALIGNI */
1986
    case 0x402: case 0x502: case 0x602: case 0x702:
1987
        wrd = (insn >> 12) & 0xf;
1988
        rd0 = (insn >> 16) & 0xf;
1989
        rd1 = (insn >> 0) & 0xf;
1990
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1991
        gen_op_movl_T0_im((insn >> 20) & 3);
1992
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1993
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1994
        gen_op_iwmmxt_set_mup();
1995
        break;
1996
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:        /* WSUB */
1997
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
1998
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
1999
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2000
        wrd = (insn >> 12) & 0xf;
2001
        rd0 = (insn >> 16) & 0xf;
2002
        rd1 = (insn >> 0) & 0xf;
2003
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2004
        switch ((insn >> 20) & 0xf) {
2005
        case 0x0:
2006
            gen_op_iwmmxt_subnb_M0_wRn(rd1);
2007
            break;
2008
        case 0x1:
2009
            gen_op_iwmmxt_subub_M0_wRn(rd1);
2010
            break;
2011
        case 0x3:
2012
            gen_op_iwmmxt_subsb_M0_wRn(rd1);
2013
            break;
2014
        case 0x4:
2015
            gen_op_iwmmxt_subnw_M0_wRn(rd1);
2016
            break;
2017
        case 0x5:
2018
            gen_op_iwmmxt_subuw_M0_wRn(rd1);
2019
            break;
2020
        case 0x7:
2021
            gen_op_iwmmxt_subsw_M0_wRn(rd1);
2022
            break;
2023
        case 0x8:
2024
            gen_op_iwmmxt_subnl_M0_wRn(rd1);
2025
            break;
2026
        case 0x9:
2027
            gen_op_iwmmxt_subul_M0_wRn(rd1);
2028
            break;
2029
        case 0xb:
2030
            gen_op_iwmmxt_subsl_M0_wRn(rd1);
2031
            break;
2032
        default:
2033
            return 1;
2034
        }
2035
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2036
        gen_op_iwmmxt_set_mup();
2037
        gen_op_iwmmxt_set_cup();
2038
        break;
2039
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:        /* WSHUFH */
2040
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2041
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2042
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2043
        wrd = (insn >> 12) & 0xf;
2044
        rd0 = (insn >> 16) & 0xf;
2045
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2046
        gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2047
        gen_op_iwmmxt_shufh_M0_T0();
2048
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2049
        gen_op_iwmmxt_set_mup();
2050
        gen_op_iwmmxt_set_cup();
2051
        break;
2052
    case 0x018: case 0x118: case 0x218: case 0x318:        /* WADD */
2053
    case 0x418: case 0x518: case 0x618: case 0x718:
2054
    case 0x818: case 0x918: case 0xa18: case 0xb18:
2055
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2056
        wrd = (insn >> 12) & 0xf;
2057
        rd0 = (insn >> 16) & 0xf;
2058
        rd1 = (insn >> 0) & 0xf;
2059
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2060
        switch ((insn >> 20) & 0xf) {
2061
        case 0x0:
2062
            gen_op_iwmmxt_addnb_M0_wRn(rd1);
2063
            break;
2064
        case 0x1:
2065
            gen_op_iwmmxt_addub_M0_wRn(rd1);
2066
            break;
2067
        case 0x3:
2068
            gen_op_iwmmxt_addsb_M0_wRn(rd1);
2069
            break;
2070
        case 0x4:
2071
            gen_op_iwmmxt_addnw_M0_wRn(rd1);
2072
            break;
2073
        case 0x5:
2074
            gen_op_iwmmxt_adduw_M0_wRn(rd1);
2075
            break;
2076
        case 0x7:
2077
            gen_op_iwmmxt_addsw_M0_wRn(rd1);
2078
            break;
2079
        case 0x8:
2080
            gen_op_iwmmxt_addnl_M0_wRn(rd1);
2081
            break;
2082
        case 0x9:
2083
            gen_op_iwmmxt_addul_M0_wRn(rd1);
2084
            break;
2085
        case 0xb:
2086
            gen_op_iwmmxt_addsl_M0_wRn(rd1);
2087
            break;
2088
        default:
2089
            return 1;
2090
        }
2091
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2092
        gen_op_iwmmxt_set_mup();
2093
        gen_op_iwmmxt_set_cup();
2094
        break;
2095
    case 0x008: case 0x108: case 0x208: case 0x308:        /* WPACK */
2096
    case 0x408: case 0x508: case 0x608: case 0x708:
2097
    case 0x808: case 0x908: case 0xa08: case 0xb08:
2098
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2099
        wrd = (insn >> 12) & 0xf;
2100
        rd0 = (insn >> 16) & 0xf;
2101
        rd1 = (insn >> 0) & 0xf;
2102
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2103
        if (!(insn & (1 << 20)))
2104
            return 1;
2105
        switch ((insn >> 22) & 3) {
2106
        case 0:
2107
            return 1;
2108
        case 1:
2109
            if (insn & (1 << 21))
2110
                gen_op_iwmmxt_packsw_M0_wRn(rd1);
2111
            else
2112
                gen_op_iwmmxt_packuw_M0_wRn(rd1);
2113
            break;
2114
        case 2:
2115
            if (insn & (1 << 21))
2116
                gen_op_iwmmxt_packsl_M0_wRn(rd1);
2117
            else
2118
                gen_op_iwmmxt_packul_M0_wRn(rd1);
2119
            break;
2120
        case 3:
2121
            if (insn & (1 << 21))
2122
                gen_op_iwmmxt_packsq_M0_wRn(rd1);
2123
            else
2124
                gen_op_iwmmxt_packuq_M0_wRn(rd1);
2125
            break;
2126
        }
2127
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2128
        gen_op_iwmmxt_set_mup();
2129
        gen_op_iwmmxt_set_cup();
2130
        break;
2131
    case 0x201: case 0x203: case 0x205: case 0x207:
2132
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
2133
    case 0x211: case 0x213: case 0x215: case 0x217:
2134
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
2135
        wrd = (insn >> 5) & 0xf;
2136
        rd0 = (insn >> 12) & 0xf;
2137
        rd1 = (insn >> 0) & 0xf;
2138
        if (rd0 == 0xf || rd1 == 0xf)
2139
            return 1;
2140
        gen_op_iwmmxt_movq_M0_wRn(wrd);
2141
        switch ((insn >> 16) & 0xf) {
2142
        case 0x0:                                        /* TMIA */
2143
            gen_movl_T0_reg(s, rd0);
2144
            gen_movl_T1_reg(s, rd1);
2145
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
2146
            break;
2147
        case 0x8:                                        /* TMIAPH */
2148
            gen_movl_T0_reg(s, rd0);
2149
            gen_movl_T1_reg(s, rd1);
2150
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
2151
            break;
2152
        case 0xc: case 0xd: case 0xe: case 0xf:                /* TMIAxy */
2153
            gen_movl_T1_reg(s, rd0);
2154
            if (insn & (1 << 16))
2155
                gen_op_shrl_T1_im(16);
2156
            gen_op_movl_T0_T1();
2157
            gen_movl_T1_reg(s, rd1);
2158
            if (insn & (1 << 17))
2159
                gen_op_shrl_T1_im(16);
2160
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
2161
            break;
2162
        default:
2163
            return 1;
2164
        }
2165
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2166
        gen_op_iwmmxt_set_mup();
2167
        break;
2168
    default:
2169
        return 1;
2170
    }
2171

    
2172
    return 0;
2173
}
2174

    
2175
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
2176
   (ie. an undefined instruction).  */
2177
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2178
{
2179
    int acc, rd0, rd1, rdhi, rdlo;
2180

    
2181
    if ((insn & 0x0ff00f10) == 0x0e200010) {
2182
        /* Multiply with Internal Accumulate Format */
2183
        rd0 = (insn >> 12) & 0xf;
2184
        rd1 = insn & 0xf;
2185
        acc = (insn >> 5) & 7;
2186

    
2187
        if (acc != 0)
2188
            return 1;
2189

    
2190
        switch ((insn >> 16) & 0xf) {
2191
        case 0x0:                                        /* MIA */
2192
            gen_movl_T0_reg(s, rd0);
2193
            gen_movl_T1_reg(s, rd1);
2194
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
2195
            break;
2196
        case 0x8:                                        /* MIAPH */
2197
            gen_movl_T0_reg(s, rd0);
2198
            gen_movl_T1_reg(s, rd1);
2199
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
2200
            break;
2201
        case 0xc:                                        /* MIABB */
2202
        case 0xd:                                        /* MIABT */
2203
        case 0xe:                                        /* MIATB */
2204
        case 0xf:                                        /* MIATT */
2205
            gen_movl_T1_reg(s, rd0);
2206
            if (insn & (1 << 16))
2207
                gen_op_shrl_T1_im(16);
2208
            gen_op_movl_T0_T1();
2209
            gen_movl_T1_reg(s, rd1);
2210
            if (insn & (1 << 17))
2211
                gen_op_shrl_T1_im(16);
2212
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
2213
            break;
2214
        default:
2215
            return 1;
2216
        }
2217

    
2218
        gen_op_iwmmxt_movq_wRn_M0(acc);
2219
        return 0;
2220
    }
2221

    
2222
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
2223
        /* Internal Accumulator Access Format */
2224
        rdhi = (insn >> 16) & 0xf;
2225
        rdlo = (insn >> 12) & 0xf;
2226
        acc = insn & 7;
2227

    
2228
        if (acc != 0)
2229
            return 1;
2230

    
2231
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
2232
            gen_op_iwmmxt_movl_T0_T1_wRn(acc);
2233
            gen_movl_reg_T0(s, rdlo);
2234
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2235
            gen_op_andl_T0_T1();
2236
            gen_movl_reg_T0(s, rdhi);
2237
        } else {                                        /* MAR */
2238
            gen_movl_T0_reg(s, rdlo);
2239
            gen_movl_T1_reg(s, rdhi);
2240
            gen_op_iwmmxt_movl_wRn_T0_T1(acc);
2241
        }
2242
        return 0;
2243
    }
2244

    
2245
    return 1;
2246
}
2247

    
2248
/* Disassemble system coprocessor instruction.  Return nonzero if
2249
   instruction is not defined.  */
2250
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2251
{
2252
    uint32_t rd = (insn >> 12) & 0xf;
2253
    uint32_t cp = (insn >> 8) & 0xf;
2254
    if (IS_USER(s)) {
2255
        return 1;
2256
    }
2257

    
2258
    if (insn & ARM_CP_RW_BIT) {
2259
        if (!env->cp[cp].cp_read)
2260
            return 1;
2261
        gen_op_movl_T0_im((uint32_t) s->pc);
2262
        gen_set_pc_T0();
2263
        gen_op_movl_T0_cp(insn);
2264
        gen_movl_reg_T0(s, rd);
2265
    } else {
2266
        if (!env->cp[cp].cp_write)
2267
            return 1;
2268
        gen_op_movl_T0_im((uint32_t) s->pc);
2269
        gen_set_pc_T0();
2270
        gen_movl_T0_reg(s, rd);
2271
        gen_op_movl_cp_T0(insn);
2272
    }
2273
    return 0;
2274
}
2275

    
2276
static int cp15_user_ok(uint32_t insn)
2277
{
2278
    int cpn = (insn >> 16) & 0xf;
2279
    int cpm = insn & 0xf;
2280
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2281

    
2282
    if (cpn == 13 && cpm == 0) {
2283
        /* TLS register.  */
2284
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2285
            return 1;
2286
    }
2287
    if (cpn == 7) {
2288
        /* ISB, DSB, DMB.  */
2289
        if ((cpm == 5 && op == 4)
2290
                || (cpm == 10 && (op == 4 || op == 5)))
2291
            return 1;
2292
    }
2293
    return 0;
2294
}
2295

    
2296
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
2297
   instruction is not defined.  */
2298
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2299
{
2300
    uint32_t rd;
2301

    
2302
    /* M profile cores use memory mapped registers instead of cp15.  */
2303
    if (arm_feature(env, ARM_FEATURE_M))
2304
        return 1;
2305

    
2306
    if ((insn & (1 << 25)) == 0) {
2307
        if (insn & (1 << 20)) {
2308
            /* mrrc */
2309
            return 1;
2310
        }
2311
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
2312
        return 0;
2313
    }
2314
    if ((insn & (1 << 4)) == 0) {
2315
        /* cdp */
2316
        return 1;
2317
    }
2318
    if (IS_USER(s) && !cp15_user_ok(insn)) {
2319
        return 1;
2320
    }
2321
    if ((insn & 0x0fff0fff) == 0x0e070f90
2322
        || (insn & 0x0fff0fff) == 0x0e070f58) {
2323
        /* Wait for interrupt.  */
2324
        gen_op_movl_T0_im((long)s->pc);
2325
        gen_set_pc_T0();
2326
        s->is_jmp = DISAS_WFI;
2327
        return 0;
2328
    }
2329
    rd = (insn >> 12) & 0xf;
2330
    if (insn & ARM_CP_RW_BIT) {
2331
        gen_op_movl_T0_cp15(insn);
2332
        /* If the destination register is r15 then sets condition codes.  */
2333
        if (rd != 15)
2334
            gen_movl_reg_T0(s, rd);
2335
    } else {
2336
        gen_movl_T0_reg(s, rd);
2337
        gen_op_movl_cp15_T0(insn);
2338
        /* Normally we would always end the TB here, but Linux
2339
         * arch/arm/mach-pxa/sleep.S expects two instructions following
2340
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
2341
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2342
                (insn & 0x0fff0fff) != 0x0e010f10)
2343
            gen_lookup_tb(s);
2344
    }
2345
    return 0;
2346
}
2347

    
2348
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2349
#define VFP_SREG(insn, bigbit, smallbit) \
2350
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2351
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2352
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2353
        reg = (((insn) >> (bigbit)) & 0x0f) \
2354
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
2355
    } else { \
2356
        if (insn & (1 << (smallbit))) \
2357
            return 1; \
2358
        reg = ((insn) >> (bigbit)) & 0x0f; \
2359
    }} while (0)
2360

    
2361
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2362
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2363
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
2364
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
2365
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2366
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2367

    
2368
/* Move between integer and VFP cores.  */
2369
static TCGv gen_vfp_mrs(void)
2370
{
2371
    TCGv tmp = new_tmp();
2372
    tcg_gen_mov_i32(tmp, cpu_F0s);
2373
    return tmp;
2374
}
2375

    
2376
static void gen_vfp_msr(TCGv tmp)
2377
{
2378
    tcg_gen_mov_i32(cpu_F0s, tmp);
2379
    dead_tmp(tmp);
2380
}
2381

    
2382
static inline int
2383
vfp_enabled(CPUState * env)
2384
{
2385
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2386
}
2387

    
2388
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
2389
   (ie. an undefined instruction).  */
2390
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2391
{
2392
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2393
    int dp, veclen;
2394
    TCGv tmp;
2395

    
2396
    if (!arm_feature(env, ARM_FEATURE_VFP))
2397
        return 1;
2398

    
2399
    if (!vfp_enabled(env)) {
2400
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2401
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
2402
            return 1;
2403
        rn = (insn >> 16) & 0xf;
2404
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2405
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2406
            return 1;
2407
    }
2408
    dp = ((insn & 0xf00) == 0xb00);
2409
    switch ((insn >> 24) & 0xf) {
2410
    case 0xe:
2411
        if (insn & (1 << 4)) {
2412
            /* single register transfer */
2413
            rd = (insn >> 12) & 0xf;
2414
            if (dp) {
2415
                int size;
2416
                int pass;
2417

    
2418
                VFP_DREG_N(rn, insn);
2419
                if (insn & 0xf)
2420
                    return 1;
2421
                if (insn & 0x00c00060
2422
                    && !arm_feature(env, ARM_FEATURE_NEON))
2423
                    return 1;
2424

    
2425
                pass = (insn >> 21) & 1;
2426
                if (insn & (1 << 22)) {
2427
                    size = 0;
2428
                    offset = ((insn >> 5) & 3) * 8;
2429
                } else if (insn & (1 << 5)) {
2430
                    size = 1;
2431
                    offset = (insn & (1 << 6)) ? 16 : 0;
2432
                } else {
2433
                    size = 2;
2434
                    offset = 0;
2435
                }
2436
                if (insn & ARM_CP_RW_BIT) {
2437
                    /* vfp->arm */
2438
                    switch (size) {
2439
                    case 0:
2440
                        NEON_GET_REG(T1, rn, pass);
2441
                        if (offset)
2442
                            gen_op_shrl_T1_im(offset);
2443
                        if (insn & (1 << 23))
2444
                            gen_uxtb(cpu_T[1]);
2445
                        else
2446
                            gen_sxtb(cpu_T[1]);
2447
                        break;
2448
                    case 1:
2449
                        NEON_GET_REG(T1, rn, pass);
2450
                        if (insn & (1 << 23)) {
2451
                            if (offset) {
2452
                                gen_op_shrl_T1_im(16);
2453
                            } else {
2454
                                gen_uxth(cpu_T[1]);
2455
                            }
2456
                        } else {
2457
                            if (offset) {
2458
                                gen_op_sarl_T1_im(16);
2459
                            } else {
2460
                                gen_sxth(cpu_T[1]);
2461
                            }
2462
                        }
2463
                        break;
2464
                    case 2:
2465
                        NEON_GET_REG(T1, rn, pass);
2466
                        break;
2467
                    }
2468
                    gen_movl_reg_T1(s, rd);
2469
                } else {
2470
                    /* arm->vfp */
2471
                    gen_movl_T0_reg(s, rd);
2472
                    if (insn & (1 << 23)) {
2473
                        /* VDUP */
2474
                        if (size == 0) {
2475
                            gen_op_neon_dup_u8(0);
2476
                        } else if (size == 1) {
2477
                            gen_op_neon_dup_low16();
2478
                        }
2479
                        NEON_SET_REG(T0, rn, 0);
2480
                        NEON_SET_REG(T0, rn, 1);
2481
                    } else {
2482
                        /* VMOV */
2483
                        switch (size) {
2484
                        case 0:
2485
                            NEON_GET_REG(T2, rn, pass);
2486
                            gen_op_movl_T1_im(0xff);
2487
                            gen_op_andl_T0_T1();
2488
                            gen_op_neon_insert_elt(offset, ~(0xff << offset));
2489
                            NEON_SET_REG(T2, rn, pass);
2490
                            break;
2491
                        case 1:
2492
                            NEON_GET_REG(T2, rn, pass);
2493
                            gen_op_movl_T1_im(0xffff);
2494
                            gen_op_andl_T0_T1();
2495
                            bank_mask = offset ? 0xffff : 0xffff0000;
2496
                            gen_op_neon_insert_elt(offset, bank_mask);
2497
                            NEON_SET_REG(T2, rn, pass);
2498
                            break;
2499
                        case 2:
2500
                            NEON_SET_REG(T0, rn, pass);
2501
                            break;
2502
                        }
2503
                    }
2504
                }
2505
            } else { /* !dp */
2506
                if ((insn & 0x6f) != 0x00)
2507
                    return 1;
2508
                rn = VFP_SREG_N(insn);
2509
                if (insn & ARM_CP_RW_BIT) {
2510
                    /* vfp->arm */
2511
                    if (insn & (1 << 21)) {
2512
                        /* system register */
2513
                        rn >>= 1;
2514

    
2515
                        switch (rn) {
2516
                        case ARM_VFP_FPSID:
2517
                            /* VFP2 allows access to FSID from userspace.
2518
                               VFP3 restricts all id registers to privileged
2519
                               accesses.  */
2520
                            if (IS_USER(s)
2521
                                && arm_feature(env, ARM_FEATURE_VFP3))
2522
                                return 1;
2523
                            tmp = load_cpu_field(vfp.xregs[rn]);
2524
                            break;
2525
                        case ARM_VFP_FPEXC:
2526
                            if (IS_USER(s))
2527
                                return 1;
2528
                            tmp = load_cpu_field(vfp.xregs[rn]);
2529
                            break;
2530
                        case ARM_VFP_FPINST:
2531
                        case ARM_VFP_FPINST2:
2532
                            /* Not present in VFP3.  */
2533
                            if (IS_USER(s)
2534
                                || arm_feature(env, ARM_FEATURE_VFP3))
2535
                                return 1;
2536
                            tmp = load_cpu_field(vfp.xregs[rn]);
2537
                            break;
2538
                        case ARM_VFP_FPSCR:
2539
                            if (rd == 15) {
2540
                                tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2541
                                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2542
                            } else {
2543
                                tmp = new_tmp();
2544
                                gen_helper_vfp_get_fpscr(tmp, cpu_env);
2545
                            }
2546
                            break;
2547
                        case ARM_VFP_MVFR0:
2548
                        case ARM_VFP_MVFR1:
2549
                            if (IS_USER(s)
2550
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2551
                                return 1;
2552
                            tmp = load_cpu_field(vfp.xregs[rn]);
2553
                            break;
2554
                        default:
2555
                            return 1;
2556
                        }
2557
                    } else {
2558
                        gen_mov_F0_vreg(0, rn);
2559
                        tmp = gen_vfp_mrs();
2560
                    }
2561
                    if (rd == 15) {
2562
                        /* Set the 4 flag bits in the CPSR.  */
2563
                        gen_set_nzcv(tmp);
2564
                        dead_tmp(tmp);
2565
                    } else {
2566
                        store_reg(s, rd, tmp);
2567
                    }
2568
                } else {
2569
                    /* arm->vfp */
2570
                    tmp = load_reg(s, rd);
2571
                    if (insn & (1 << 21)) {
2572
                        rn >>= 1;
2573
                        /* system register */
2574
                        switch (rn) {
2575
                        case ARM_VFP_FPSID:
2576
                        case ARM_VFP_MVFR0:
2577
                        case ARM_VFP_MVFR1:
2578
                            /* Writes are ignored.  */
2579
                            break;
2580
                        case ARM_VFP_FPSCR:
2581
                            gen_helper_vfp_set_fpscr(cpu_env, tmp);
2582
                            dead_tmp(tmp);
2583
                            gen_lookup_tb(s);
2584
                            break;
2585
                        case ARM_VFP_FPEXC:
2586
                            if (IS_USER(s))
2587
                                return 1;
2588
                            store_cpu_field(tmp, vfp.xregs[rn]);
2589
                            gen_lookup_tb(s);
2590
                            break;
2591
                        case ARM_VFP_FPINST:
2592
                        case ARM_VFP_FPINST2:
2593
                            store_cpu_field(tmp, vfp.xregs[rn]);
2594
                            break;
2595
                        default:
2596
                            return 1;
2597
                        }
2598
                    } else {
2599
                        gen_vfp_msr(tmp);
2600
                        gen_mov_vreg_F0(0, rn);
2601
                    }
2602
                }
2603
            }
2604
        } else {
2605
            /* data processing */
2606
            /* The opcode is in bits 23, 21, 20 and 6.  */
2607
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2608
            if (dp) {
2609
                if (op == 15) {
2610
                    /* rn is opcode */
2611
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2612
                } else {
2613
                    /* rn is register number */
2614
                    VFP_DREG_N(rn, insn);
2615
                }
2616

    
2617
                if (op == 15 && (rn == 15 || rn > 17)) {
2618
                    /* Integer or single precision destination.  */
2619
                    rd = VFP_SREG_D(insn);
2620
                } else {
2621
                    VFP_DREG_D(rd, insn);
2622
                }
2623

    
2624
                if (op == 15 && (rn == 16 || rn == 17)) {
2625
                    /* Integer source.  */
2626
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2627
                } else {
2628
                    VFP_DREG_M(rm, insn);
2629
                }
2630
            } else {
2631
                rn = VFP_SREG_N(insn);
2632
                if (op == 15 && rn == 15) {
2633
                    /* Double precision destination.  */
2634
                    VFP_DREG_D(rd, insn);
2635
                } else {
2636
                    rd = VFP_SREG_D(insn);
2637
                }
2638
                rm = VFP_SREG_M(insn);
2639
            }
2640

    
2641
            veclen = env->vfp.vec_len;
2642
            if (op == 15 && rn > 3)
2643
                veclen = 0;
2644

    
2645
            /* Shut up compiler warnings.  */
2646
            delta_m = 0;
2647
            delta_d = 0;
2648
            bank_mask = 0;
2649

    
2650
            if (veclen > 0) {
2651
                if (dp)
2652
                    bank_mask = 0xc;
2653
                else
2654
                    bank_mask = 0x18;
2655

    
2656
                /* Figure out what type of vector operation this is.  */
2657
                if ((rd & bank_mask) == 0) {
2658
                    /* scalar */
2659
                    veclen = 0;
2660
                } else {
2661
                    if (dp)
2662
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
2663
                    else
2664
                        delta_d = env->vfp.vec_stride + 1;
2665

    
2666
                    if ((rm & bank_mask) == 0) {
2667
                        /* mixed scalar/vector */
2668
                        delta_m = 0;
2669
                    } else {
2670
                        /* vector */
2671
                        delta_m = delta_d;
2672
                    }
2673
                }
2674
            }
2675

    
2676
            /* Load the initial operands.  */
2677
            if (op == 15) {
2678
                switch (rn) {
2679
                case 16:
2680
                case 17:
2681
                    /* Integer source */
2682
                    gen_mov_F0_vreg(0, rm);
2683
                    break;
2684
                case 8:
2685
                case 9:
2686
                    /* Compare */
2687
                    gen_mov_F0_vreg(dp, rd);
2688
                    gen_mov_F1_vreg(dp, rm);
2689
                    break;
2690
                case 10:
2691
                case 11:
2692
                    /* Compare with zero */
2693
                    gen_mov_F0_vreg(dp, rd);
2694
                    gen_vfp_F1_ld0(dp);
2695
                    break;
2696
                case 20:
2697
                case 21:
2698
                case 22:
2699
                case 23:
2700
                    /* Source and destination the same.  */
2701
                    gen_mov_F0_vreg(dp, rd);
2702
                    break;
2703
                default:
2704
                    /* One source operand.  */
2705
                    gen_mov_F0_vreg(dp, rm);
2706
                    break;
2707
                }
2708
            } else {
2709
                /* Two source operands.  */
2710
                gen_mov_F0_vreg(dp, rn);
2711
                gen_mov_F1_vreg(dp, rm);
2712
            }
2713

    
2714
            for (;;) {
2715
                /* Perform the calculation.  */
2716
                switch (op) {
2717
                case 0: /* mac: fd + (fn * fm) */
2718
                    gen_vfp_mul(dp);
2719
                    gen_mov_F1_vreg(dp, rd);
2720
                    gen_vfp_add(dp);
2721
                    break;
2722
                case 1: /* nmac: fd - (fn * fm) */
2723
                    gen_vfp_mul(dp);
2724
                    gen_vfp_neg(dp);
2725
                    gen_mov_F1_vreg(dp, rd);
2726
                    gen_vfp_add(dp);
2727
                    break;
2728
                case 2: /* msc: -fd + (fn * fm) */
2729
                    gen_vfp_mul(dp);
2730
                    gen_mov_F1_vreg(dp, rd);
2731
                    gen_vfp_sub(dp);
2732
                    break;
2733
                case 3: /* nmsc: -fd - (fn * fm)  */
2734
                    gen_vfp_mul(dp);
2735
                    gen_mov_F1_vreg(dp, rd);
2736
                    gen_vfp_add(dp);
2737
                    gen_vfp_neg(dp);
2738
                    break;
2739
                case 4: /* mul: fn * fm */
2740
                    gen_vfp_mul(dp);
2741
                    break;
2742
                case 5: /* nmul: -(fn * fm) */
2743
                    gen_vfp_mul(dp);
2744
                    gen_vfp_neg(dp);
2745
                    break;
2746
                case 6: /* add: fn + fm */
2747
                    gen_vfp_add(dp);
2748
                    break;
2749
                case 7: /* sub: fn - fm */
2750
                    gen_vfp_sub(dp);
2751
                    break;
2752
                case 8: /* div: fn / fm */
2753
                    gen_vfp_div(dp);
2754
                    break;
2755
                case 14: /* fconst */
2756
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
2757
                      return 1;
2758

    
2759
                    n = (insn << 12) & 0x80000000;
2760
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
2761
                    if (dp) {
2762
                        if (i & 0x40)
2763
                            i |= 0x3f80;
2764
                        else
2765
                            i |= 0x4000;
2766
                        n |= i << 16;
2767
                        tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
2768
                    } else {
2769
                        if (i & 0x40)
2770
                            i |= 0x780;
2771
                        else
2772
                            i |= 0x800;
2773
                        n |= i << 19;
2774
                        tcg_gen_movi_i32(cpu_F0d, ((uint64_t)n) << 32);
2775
                    }
2776
                    break;
2777
                case 15: /* extension space */
2778
                    switch (rn) {
2779
                    case 0: /* cpy */
2780
                        /* no-op */
2781
                        break;
2782
                    case 1: /* abs */
2783
                        gen_vfp_abs(dp);
2784
                        break;
2785
                    case 2: /* neg */
2786
                        gen_vfp_neg(dp);
2787
                        break;
2788
                    case 3: /* sqrt */
2789
                        gen_vfp_sqrt(dp);
2790
                        break;
2791
                    case 8: /* cmp */
2792
                        gen_vfp_cmp(dp);
2793
                        break;
2794
                    case 9: /* cmpe */
2795
                        gen_vfp_cmpe(dp);
2796
                        break;
2797
                    case 10: /* cmpz */
2798
                        gen_vfp_cmp(dp);
2799
                        break;
2800
                    case 11: /* cmpez */
2801
                        gen_vfp_F1_ld0(dp);
2802
                        gen_vfp_cmpe(dp);
2803
                        break;
2804
                    case 15: /* single<->double conversion */
2805
                        if (dp)
2806
                            gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
2807
                        else
2808
                            gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
2809
                        break;
2810
                    case 16: /* fuito */
2811
                        gen_vfp_uito(dp);
2812
                        break;
2813
                    case 17: /* fsito */
2814
                        gen_vfp_sito(dp);
2815
                        break;
2816
                    case 20: /* fshto */
2817
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2818
                          return 1;
2819
                        gen_vfp_shto(dp, rm);
2820
                        break;
2821
                    case 21: /* fslto */
2822
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2823
                          return 1;
2824
                        gen_vfp_slto(dp, rm);
2825
                        break;
2826
                    case 22: /* fuhto */
2827
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2828
                          return 1;
2829
                        gen_vfp_uhto(dp, rm);
2830
                        break;
2831
                    case 23: /* fulto */
2832
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2833
                          return 1;
2834
                        gen_vfp_ulto(dp, rm);
2835
                        break;
2836
                    case 24: /* ftoui */
2837
                        gen_vfp_toui(dp);
2838
                        break;
2839
                    case 25: /* ftouiz */
2840
                        gen_vfp_touiz(dp);
2841
                        break;
2842
                    case 26: /* ftosi */
2843
                        gen_vfp_tosi(dp);
2844
                        break;
2845
                    case 27: /* ftosiz */
2846
                        gen_vfp_tosiz(dp);
2847
                        break;
2848
                    case 28: /* ftosh */
2849
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2850
                          return 1;
2851
                        gen_vfp_tosh(dp, rm);
2852
                        break;
2853
                    case 29: /* ftosl */
2854
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2855
                          return 1;
2856
                        gen_vfp_tosl(dp, rm);
2857
                        break;
2858
                    case 30: /* ftouh */
2859
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2860
                          return 1;
2861
                        gen_vfp_touh(dp, rm);
2862
                        break;
2863
                    case 31: /* ftoul */
2864
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2865
                          return 1;
2866
                        gen_vfp_toul(dp, rm);
2867
                        break;
2868
                    default: /* undefined */
2869
                        printf ("rn:%d\n", rn);
2870
                        return 1;
2871
                    }
2872
                    break;
2873
                default: /* undefined */
2874
                    printf ("op:%d\n", op);
2875
                    return 1;
2876
                }
2877

    
2878
                /* Write back the result.  */
2879
                if (op == 15 && (rn >= 8 && rn <= 11))
2880
                    ; /* Comparison, do nothing.  */
2881
                else if (op == 15 && rn > 17)
2882
                    /* Integer result.  */
2883
                    gen_mov_vreg_F0(0, rd);
2884
                else if (op == 15 && rn == 15)
2885
                    /* conversion */
2886
                    gen_mov_vreg_F0(!dp, rd);
2887
                else
2888
                    gen_mov_vreg_F0(dp, rd);
2889

    
2890
                /* break out of the loop if we have finished  */
2891
                if (veclen == 0)
2892
                    break;
2893

    
2894
                if (op == 15 && delta_m == 0) {
2895
                    /* single source one-many */
2896
                    while (veclen--) {
2897
                        rd = ((rd + delta_d) & (bank_mask - 1))
2898
                             | (rd & bank_mask);
2899
                        gen_mov_vreg_F0(dp, rd);
2900
                    }
2901
                    break;
2902
                }
2903
                /* Setup the next operands.  */
2904
                veclen--;
2905
                rd = ((rd + delta_d) & (bank_mask - 1))
2906
                     | (rd & bank_mask);
2907

    
2908
                if (op == 15) {
2909
                    /* One source operand.  */
2910
                    rm = ((rm + delta_m) & (bank_mask - 1))
2911
                         | (rm & bank_mask);
2912
                    gen_mov_F0_vreg(dp, rm);
2913
                } else {
2914
                    /* Two source operands.  */
2915
                    rn = ((rn + delta_d) & (bank_mask - 1))
2916
                         | (rn & bank_mask);
2917
                    gen_mov_F0_vreg(dp, rn);
2918
                    if (delta_m) {
2919
                        rm = ((rm + delta_m) & (bank_mask - 1))
2920
                             | (rm & bank_mask);
2921
                        gen_mov_F1_vreg(dp, rm);
2922
                    }
2923
                }
2924
            }
2925
        }
2926
        break;
2927
    case 0xc:
2928
    case 0xd:
2929
        if (dp && (insn & 0x03e00000) == 0x00400000) {
2930
            /* two-register transfer */
2931
            rn = (insn >> 16) & 0xf;
2932
            rd = (insn >> 12) & 0xf;
2933
            if (dp) {
2934
                VFP_DREG_M(rm, insn);
2935
            } else {
2936
                rm = VFP_SREG_M(insn);
2937
            }
2938

    
2939
            if (insn & ARM_CP_RW_BIT) {
2940
                /* vfp->arm */
2941
                if (dp) {
2942
                    gen_mov_F0_vreg(0, rm * 2);
2943
                    tmp = gen_vfp_mrs();
2944
                    store_reg(s, rd, tmp);
2945
                    gen_mov_F0_vreg(0, rm * 2 + 1);
2946
                    tmp = gen_vfp_mrs();
2947
                    store_reg(s, rn, tmp);
2948
                } else {
2949
                    gen_mov_F0_vreg(0, rm);
2950
                    tmp = gen_vfp_mrs();
2951
                    store_reg(s, rn, tmp);
2952
                    gen_mov_F0_vreg(0, rm + 1);
2953
                    tmp = gen_vfp_mrs();
2954
                    store_reg(s, rd, tmp);
2955
                }
2956
            } else {
2957
                /* arm->vfp */
2958
                if (dp) {
2959
                    tmp = load_reg(s, rd);
2960
                    gen_vfp_msr(tmp);
2961
                    gen_mov_vreg_F0(0, rm * 2);
2962
                    tmp = load_reg(s, rn);
2963
                    gen_vfp_msr(tmp);
2964
                    gen_mov_vreg_F0(0, rm * 2 + 1);
2965
                } else {
2966
                    tmp = load_reg(s, rn);
2967
                    gen_vfp_msr(tmp);
2968
                    gen_mov_vreg_F0(0, rm);
2969
                    tmp = load_reg(s, rd);
2970
                    gen_vfp_msr(tmp);
2971
                    gen_mov_vreg_F0(0, rm + 1);
2972
                }
2973
            }
2974
        } else {
2975
            /* Load/store */
2976
            rn = (insn >> 16) & 0xf;
2977
            if (dp)
2978
                VFP_DREG_D(rd, insn);
2979
            else
2980
                rd = VFP_SREG_D(insn);
2981
            if (s->thumb && rn == 15) {
2982
                gen_op_movl_T1_im(s->pc & ~2);
2983
            } else {
2984
                gen_movl_T1_reg(s, rn);
2985
            }
2986
            if ((insn & 0x01200000) == 0x01000000) {
2987
                /* Single load/store */
2988
                offset = (insn & 0xff) << 2;
2989
                if ((insn & (1 << 23)) == 0)
2990
                    offset = -offset;
2991
                gen_op_addl_T1_im(offset);
2992
                if (insn & (1 << 20)) {
2993
                    gen_vfp_ld(s, dp);
2994
                    gen_mov_vreg_F0(dp, rd);
2995
                } else {
2996
                    gen_mov_F0_vreg(dp, rd);
2997
                    gen_vfp_st(s, dp);
2998
                }
2999
            } else {
3000
                /* load/store multiple */
3001
                if (dp)
3002
                    n = (insn >> 1) & 0x7f;
3003
                else
3004
                    n = insn & 0xff;
3005

    
3006
                if (insn & (1 << 24)) /* pre-decrement */
3007
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
3008

    
3009
                if (dp)
3010
                    offset = 8;
3011
                else
3012
                    offset = 4;
3013
                for (i = 0; i < n; i++) {
3014
                    if (insn & ARM_CP_RW_BIT) {
3015
                        /* load */
3016
                        gen_vfp_ld(s, dp);
3017
                        gen_mov_vreg_F0(dp, rd + i);
3018
                    } else {
3019
                        /* store */
3020
                        gen_mov_F0_vreg(dp, rd + i);
3021
                        gen_vfp_st(s, dp);
3022
                    }
3023
                    gen_op_addl_T1_im(offset);
3024
                }
3025
                if (insn & (1 << 21)) {
3026
                    /* writeback */
3027
                    if (insn & (1 << 24))
3028
                        offset = -offset * n;
3029
                    else if (dp && (insn & 1))
3030
                        offset = 4;
3031
                    else
3032
                        offset = 0;
3033

    
3034
                    if (offset != 0)
3035
                        gen_op_addl_T1_im(offset);
3036
                    gen_movl_reg_T1(s, rn);
3037
                }
3038
            }
3039
        }
3040
        break;
3041
    default:
3042
        /* Should never happen.  */
3043
        return 1;
3044
    }
3045
    return 0;
3046
}
3047

    
3048
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3049
{
3050
    TranslationBlock *tb;
3051

    
3052
    tb = s->tb;
3053
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3054
        tcg_gen_goto_tb(n);
3055
        gen_op_movl_T0_im(dest);
3056
        gen_set_pc_T0();
3057
        tcg_gen_exit_tb((long)tb + n);
3058
    } else {
3059
        gen_op_movl_T0_im(dest);
3060
        gen_set_pc_T0();
3061
        tcg_gen_exit_tb(0);
3062
    }
3063
}
3064

    
3065
static inline void gen_jmp (DisasContext *s, uint32_t dest)
3066
{
3067
    if (__builtin_expect(s->singlestep_enabled, 0)) {
3068
        /* An indirect jump so that we still trigger the debug exception.  */
3069
        if (s->thumb)
3070
            dest |= 1;
3071
        gen_bx_im(s, dest);
3072
    } else {
3073
        gen_goto_tb(s, 0, dest);
3074
        s->is_jmp = DISAS_TB_JUMP;
3075
    }
3076
}
3077

    
3078
static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3079
{
3080
    if (x)
3081
        tcg_gen_sari_i32(t0, t0, 16);
3082
    else
3083
        gen_sxth(t0);
3084
    if (y)
3085
        tcg_gen_sari_i32(t1, t1, 16);
3086
    else
3087
        gen_sxth(t1);
3088
    tcg_gen_mul_i32(t0, t0, t1);
3089
}
3090

    
3091
/* Return the mask of PSR bits set by a MSR instruction.  */
3092
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3093
    uint32_t mask;
3094

    
3095
    mask = 0;
3096
    if (flags & (1 << 0))
3097
        mask |= 0xff;
3098
    if (flags & (1 << 1))
3099
        mask |= 0xff00;
3100
    if (flags & (1 << 2))
3101
        mask |= 0xff0000;
3102
    if (flags & (1 << 3))
3103
        mask |= 0xff000000;
3104

    
3105
    /* Mask out undefined bits.  */
3106
    mask &= ~CPSR_RESERVED;
3107
    if (!arm_feature(env, ARM_FEATURE_V6))
3108
        mask &= ~(CPSR_E | CPSR_GE);
3109
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
3110
        mask &= ~CPSR_IT;
3111
    /* Mask out execution state bits.  */
3112
    if (!spsr)
3113
        mask &= ~CPSR_EXEC;
3114
    /* Mask out privileged bits.  */
3115
    if (IS_USER(s))
3116
        mask &= CPSR_USER;
3117
    return mask;
3118
}
3119

    
3120
/* Returns nonzero if access to the PSR is not permitted.  */
3121
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
3122
{
3123
    TCGv tmp;
3124
    if (spsr) {
3125
        /* ??? This is also undefined in system mode.  */
3126
        if (IS_USER(s))
3127
            return 1;
3128

    
3129
        tmp = load_cpu_field(spsr);
3130
        tcg_gen_andi_i32(tmp, tmp, ~mask);
3131
        tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
3132
        tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
3133
        store_cpu_field(tmp, spsr);
3134
    } else {
3135
        gen_set_cpsr(cpu_T[0], mask);
3136
    }
3137
    gen_lookup_tb(s);
3138
    return 0;
3139
}
3140

    
3141
/* Generate an old-style exception return.  */
3142
static void gen_exception_return(DisasContext *s)
3143
{
3144
    TCGv tmp;
3145
    gen_set_pc_T0();
3146
    tmp = load_cpu_field(spsr);
3147
    gen_set_cpsr(tmp, 0xffffffff);
3148
    dead_tmp(tmp);
3149
    s->is_jmp = DISAS_UPDATE;
3150
}
3151

    
3152
/* Generate a v6 exception return.  Marks both values as dead.  */
3153
static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3154
{
3155
    gen_set_cpsr(cpsr, 0xffffffff);
3156
    dead_tmp(cpsr);
3157
    store_reg(s, 15, pc);
3158
    s->is_jmp = DISAS_UPDATE;
3159
}
3160

    
3161
static inline void
3162
gen_set_condexec (DisasContext *s)
3163
{
3164
    if (s->condexec_mask) {
3165
        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3166
        TCGv tmp = new_tmp();
3167
        tcg_gen_movi_i32(tmp, val);
3168
        store_cpu_field(tmp, condexec_bits);
3169
    }
3170
}
3171

    
3172
static void gen_nop_hint(DisasContext *s, int val)
3173
{
3174
    switch (val) {
3175
    case 3: /* wfi */
3176
        gen_op_movl_T0_im((long)s->pc);
3177
        gen_set_pc_T0();
3178
        s->is_jmp = DISAS_WFI;
3179
        break;
3180
    case 2: /* wfe */
3181
    case 4: /* sev */
3182
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
3183
    default: /* nop */
3184
        break;
3185
    }
3186
}
3187

    
3188
/* Neon shift by constant.  The actual ops are the same as used for variable
3189
   shifts.  [OP][U][SIZE]  */
3190
static GenOpFunc *gen_neon_shift_im[8][2][4] = {
3191
    { /* 0 */ /* VSHR */
3192
      {
3193
        gen_op_neon_shl_u8,
3194
        gen_op_neon_shl_u16,
3195
        gen_op_neon_shl_u32,
3196
        gen_op_neon_shl_u64
3197
      }, {
3198
        gen_op_neon_shl_s8,
3199
        gen_op_neon_shl_s16,
3200
        gen_op_neon_shl_s32,
3201
        gen_op_neon_shl_s64
3202
      }
3203
    }, { /* 1 */ /* VSRA */
3204
      {
3205
        gen_op_neon_shl_u8,
3206
        gen_op_neon_shl_u16,
3207
        gen_op_neon_shl_u32,
3208
        gen_op_neon_shl_u64
3209
      }, {
3210
        gen_op_neon_shl_s8,
3211
        gen_op_neon_shl_s16,
3212
        gen_op_neon_shl_s32,
3213
        gen_op_neon_shl_s64
3214
      }
3215
    }, { /* 2 */ /* VRSHR */
3216
      {
3217
        gen_op_neon_rshl_u8,
3218
        gen_op_neon_rshl_u16,
3219
        gen_op_neon_rshl_u32,
3220
        gen_op_neon_rshl_u64
3221
      }, {
3222
        gen_op_neon_rshl_s8,
3223
        gen_op_neon_rshl_s16,
3224
        gen_op_neon_rshl_s32,
3225
        gen_op_neon_rshl_s64
3226
      }
3227
    }, { /* 3 */ /* VRSRA */
3228
      {
3229
        gen_op_neon_rshl_u8,
3230
        gen_op_neon_rshl_u16,
3231
        gen_op_neon_rshl_u32,
3232
        gen_op_neon_rshl_u64
3233
      }, {
3234
        gen_op_neon_rshl_s8,
3235
        gen_op_neon_rshl_s16,
3236
        gen_op_neon_rshl_s32,
3237
        gen_op_neon_rshl_s64
3238
      }
3239
    }, { /* 4 */
3240
      {
3241
        NULL, NULL, NULL, NULL
3242
      }, { /* VSRI */
3243
        gen_op_neon_shl_u8,
3244
        gen_op_neon_shl_u16,
3245
        gen_op_neon_shl_u32,
3246
        gen_op_neon_shl_u64,
3247
      }
3248
    }, { /* 5 */
3249
      { /* VSHL */
3250
        gen_op_neon_shl_u8,
3251
        gen_op_neon_shl_u16,
3252
        gen_op_neon_shl_u32,
3253
        gen_op_neon_shl_u64,
3254
      }, { /* VSLI */
3255
        gen_op_neon_shl_u8,
3256
        gen_op_neon_shl_u16,
3257
        gen_op_neon_shl_u32,
3258
        gen_op_neon_shl_u64,
3259
      }
3260
    }, { /* 6 */ /* VQSHL */
3261
      {
3262
        gen_op_neon_qshl_u8,
3263
        gen_op_neon_qshl_u16,
3264
        gen_op_neon_qshl_u32,
3265
        gen_op_neon_qshl_u64
3266
      }, {
3267
        gen_op_neon_qshl_s8,
3268
        gen_op_neon_qshl_s16,
3269
        gen_op_neon_qshl_s32,
3270
        gen_op_neon_qshl_s64
3271
      }
3272
    }, { /* 7 */ /* VQSHLU */
3273
      {
3274
        gen_op_neon_qshl_u8,
3275
        gen_op_neon_qshl_u16,
3276
        gen_op_neon_qshl_u32,
3277
        gen_op_neon_qshl_u64
3278
      }, {
3279
        gen_op_neon_qshl_u8,
3280
        gen_op_neon_qshl_u16,
3281
        gen_op_neon_qshl_u32,
3282
        gen_op_neon_qshl_u64
3283
      }
3284
    }
3285
};
3286

    
3287
/* [R][U][size - 1] */
3288
static GenOpFunc *gen_neon_shift_im_narrow[2][2][3] = {
3289
    {
3290
      {
3291
        gen_op_neon_shl_u16,
3292
        gen_op_neon_shl_u32,
3293
        gen_op_neon_shl_u64
3294
      }, {
3295
        gen_op_neon_shl_s16,
3296
        gen_op_neon_shl_s32,
3297
        gen_op_neon_shl_s64
3298
      }
3299
    }, {
3300
      {
3301
        gen_op_neon_rshl_u16,
3302
        gen_op_neon_rshl_u32,
3303
        gen_op_neon_rshl_u64
3304
      }, {
3305
        gen_op_neon_rshl_s16,
3306
        gen_op_neon_rshl_s32,
3307
        gen_op_neon_rshl_s64
3308
      }
3309
    }
3310
};
3311

    
3312
static inline void
3313
gen_op_neon_narrow_u32 ()
3314
{
3315
    /* No-op.  */
3316
}
3317

    
3318
static GenOpFunc *gen_neon_narrow[3] = {
3319
    gen_op_neon_narrow_u8,
3320
    gen_op_neon_narrow_u16,
3321
    gen_op_neon_narrow_u32
3322
};
3323

    
3324
static GenOpFunc *gen_neon_narrow_satu[3] = {
3325
    gen_op_neon_narrow_sat_u8,
3326
    gen_op_neon_narrow_sat_u16,
3327
    gen_op_neon_narrow_sat_u32
3328
};
3329

    
3330
static GenOpFunc *gen_neon_narrow_sats[3] = {
3331
    gen_op_neon_narrow_sat_s8,
3332
    gen_op_neon_narrow_sat_s16,
3333
    gen_op_neon_narrow_sat_s32
3334
};
3335

    
3336
static inline int gen_neon_add(int size)
3337
{
3338
    switch (size) {
3339
    case 0: gen_op_neon_add_u8(); break;
3340
    case 1: gen_op_neon_add_u16(); break;
3341
    case 2: gen_op_addl_T0_T1(); break;
3342
    default: return 1;
3343
    }
3344
    return 0;
3345
}
3346

    
3347
/* 32-bit pairwise ops end up the same as the elementsise versions.  */
3348
#define gen_op_neon_pmax_s32  gen_op_neon_max_s32
3349
#define gen_op_neon_pmax_u32  gen_op_neon_max_u32
3350
#define gen_op_neon_pmin_s32  gen_op_neon_min_s32
3351
#define gen_op_neon_pmin_u32  gen_op_neon_min_u32
3352

    
3353
#define GEN_NEON_INTEGER_OP(name) do { \
3354
    switch ((size << 1) | u) { \
3355
    case 0: gen_op_neon_##name##_s8(); break; \
3356
    case 1: gen_op_neon_##name##_u8(); break; \
3357
    case 2: gen_op_neon_##name##_s16(); break; \
3358
    case 3: gen_op_neon_##name##_u16(); break; \
3359
    case 4: gen_op_neon_##name##_s32(); break; \
3360
    case 5: gen_op_neon_##name##_u32(); break; \
3361
    default: return 1; \
3362
    }} while (0)
3363

    
3364
static inline void
3365
gen_neon_movl_scratch_T0(int scratch)
3366
{
3367
  uint32_t offset;
3368

    
3369
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3370
  gen_op_neon_setreg_T0(offset);
3371
}
3372

    
3373
static inline void
3374
gen_neon_movl_scratch_T1(int scratch)
3375
{
3376
  uint32_t offset;
3377

    
3378
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3379
  gen_op_neon_setreg_T1(offset);
3380
}
3381

    
3382
static inline void
3383
gen_neon_movl_T0_scratch(int scratch)
3384
{
3385
  uint32_t offset;
3386

    
3387
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3388
  gen_op_neon_getreg_T0(offset);
3389
}
3390

    
3391
static inline void
3392
gen_neon_movl_T1_scratch(int scratch)
3393
{
3394
  uint32_t offset;
3395

    
3396
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3397
  gen_op_neon_getreg_T1(offset);
3398
}
3399

    
3400
static inline void gen_op_neon_widen_u32(void)
3401
{
3402
    gen_op_movl_T1_im(0);
3403
}
3404

    
3405
static inline void gen_neon_get_scalar(int size, int reg)
3406
{
3407
    if (size == 1) {
3408
        NEON_GET_REG(T0, reg >> 1, reg & 1);
3409
    } else {
3410
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3411
        if (reg & 1)
3412
            gen_op_neon_dup_low16();
3413
        else
3414
            gen_op_neon_dup_high16();
3415
    }
3416
}
3417

    
3418
static void gen_neon_unzip(int reg, int q, int tmp, int size)
3419
{
3420
    int n;
3421

    
3422
    for (n = 0; n < q + 1; n += 2) {
3423
        NEON_GET_REG(T0, reg, n);
3424
        NEON_GET_REG(T0, reg, n + n);
3425
        switch (size) {
3426
        case 0: gen_op_neon_unzip_u8(); break;
3427
        case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same.  */
3428
        case 2: /* no-op */; break;
3429
        default: abort();
3430
        }
3431
        gen_neon_movl_scratch_T0(tmp + n);
3432
        gen_neon_movl_scratch_T1(tmp + n + 1);
3433
    }
3434
}
3435

    
3436
static struct {
3437
    int nregs;
3438
    int interleave;
3439
    int spacing;
3440
} neon_ls_element_type[11] = {
3441
    {4, 4, 1},
3442
    {4, 4, 2},
3443
    {4, 1, 1},
3444
    {4, 2, 1},
3445
    {3, 3, 1},
3446
    {3, 3, 2},
3447
    {3, 1, 1},
3448
    {1, 1, 1},
3449
    {2, 2, 1},
3450
    {2, 2, 2},
3451
    {2, 1, 1}
3452
};
3453

    
3454
/* Translate a NEON load/store element instruction.  Return nonzero if the
3455
   instruction is invalid.  */
3456
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3457
{
3458
    int rd, rn, rm;
3459
    int op;
3460
    int nregs;
3461
    int interleave;
3462
    int stride;
3463
    int size;
3464
    int reg;
3465
    int pass;
3466
    int load;
3467
    int shift;
3468
    uint32_t mask;
3469
    int n;
3470
    TCGv tmp;
3471

    
3472
    if (!vfp_enabled(env))
3473
      return 1;
3474
    VFP_DREG_D(rd, insn);
3475
    rn = (insn >> 16) & 0xf;
3476
    rm = insn & 0xf;
3477
    load = (insn & (1 << 21)) != 0;
3478
    if ((insn & (1 << 23)) == 0) {
3479
        /* Load store all elements.  */
3480
        op = (insn >> 8) & 0xf;
3481
        size = (insn >> 6) & 3;
3482
        if (op > 10 || size == 3)
3483
            return 1;
3484
        nregs = neon_ls_element_type[op].nregs;
3485
        interleave = neon_ls_element_type[op].interleave;
3486
        gen_movl_T1_reg(s, rn);
3487
        stride = (1 << size) * interleave;
3488
        for (reg = 0; reg < nregs; reg++) {
3489
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3490
                gen_movl_T1_reg(s, rn);
3491
                gen_op_addl_T1_im((1 << size) * reg);
3492
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
3493
                gen_movl_T1_reg(s, rn);
3494
                gen_op_addl_T1_im(1 << size);
3495
            }
3496
            for (pass = 0; pass < 2; pass++) {
3497
                if (size == 2) {
3498
                    if (load) {
3499
                        tmp = gen_ld32(cpu_T[1], IS_USER(s));
3500
                        tcg_gen_mov_i32(cpu_T[0], tmp);
3501
                        dead_tmp(tmp);
3502
                        NEON_SET_REG(T0, rd, pass);
3503
                    } else {
3504
                        NEON_GET_REG(T0, rd, pass);
3505
                        tmp = new_tmp();
3506
                        tcg_gen_mov_i32(tmp, cpu_T[0]);
3507
                        gen_st32(tmp, cpu_T[1], IS_USER(s));
3508
                    }
3509
                    gen_op_addl_T1_im(stride);
3510
                } else if (size == 1) {
3511
                    if (load) {
3512
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3513
                        tcg_gen_mov_i32(cpu_T[0], tmp);
3514
                        dead_tmp(tmp);
3515
                        gen_op_addl_T1_im(stride);
3516
                        gen_op_movl_T2_T0();
3517
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3518
                        tcg_gen_mov_i32(cpu_T[0], tmp);
3519
                        dead_tmp(tmp);
3520
                        gen_op_addl_T1_im(stride);
3521
                        gen_op_neon_insert_elt(16, 0xffff);
3522
                        NEON_SET_REG(T2, rd, pass);
3523
                    } else {
3524
                        NEON_GET_REG(T2, rd, pass);
3525
                        gen_op_movl_T0_T2();
3526
                        tmp = new_tmp();
3527
                        tcg_gen_mov_i32(tmp, cpu_T[0]);
3528
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3529
                        gen_op_addl_T1_im(stride);
3530
                        gen_op_neon_extract_elt(16, 0xffff0000);
3531
                        tmp = new_tmp();
3532
                        tcg_gen_mov_i32(tmp, cpu_T[0]);
3533
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3534
                        gen_op_addl_T1_im(stride);
3535
                    }
3536
                } else /* size == 0 */ {
3537
                    if (load) {
3538
                        mask = 0xff;
3539
                        for (n = 0; n < 4; n++) {
3540
                            tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3541
                            tcg_gen_mov_i32(cpu_T[0], tmp);
3542
                            dead_tmp(tmp);
3543
                            gen_op_addl_T1_im(stride);
3544
                            if (n == 0) {
3545
                                gen_op_movl_T2_T0();
3546
                            } else {
3547
                                gen_op_neon_insert_elt(n * 8, ~mask);
3548
                            }
3549
                            mask <<= 8;
3550
                        }
3551
                        NEON_SET_REG(T2, rd, pass);
3552
                    } else {
3553
                        NEON_GET_REG(T2, rd, pass);
3554
                        mask = 0xff;
3555
                        for (n = 0; n < 4; n++) {
3556
                            if (n == 0) {
3557
                                gen_op_movl_T0_T2();
3558
                            } else {
3559
                                gen_op_neon_extract_elt(n * 8, mask);
3560
                            }
3561
                            tmp = new_tmp();
3562
                            tcg_gen_mov_i32(tmp, cpu_T[0]);
3563
                            gen_st8(tmp, cpu_T[1], IS_USER(s));
3564
                            gen_op_addl_T1_im(stride);
3565
                            mask <<= 8;
3566
                        }
3567
                    }
3568
                }
3569
            }
3570
            rd += neon_ls_element_type[op].spacing;
3571
        }
3572
        stride = nregs * 8;
3573
    } else {
3574
        size = (insn >> 10) & 3;
3575
        if (size == 3) {
3576
            /* Load single element to all lanes.  */
3577
            if (!load)
3578
                return 1;
3579
            size = (insn >> 6) & 3;
3580
            nregs = ((insn >> 8) & 3) + 1;
3581
            stride = (insn & (1 << 5)) ? 2 : 1;
3582
            gen_movl_T1_reg(s, rn);
3583
            for (reg = 0; reg < nregs; reg++) {
3584
                switch (size) {
3585
                case 0:
3586
                    tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3587
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3588
                    dead_tmp(tmp);
3589
                    gen_op_neon_dup_u8(0);
3590
                    break;
3591
                case 1:
3592
                    tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3593
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3594
                    dead_tmp(tmp);
3595
                    gen_op_neon_dup_low16();
3596
                    break;
3597
                case 2:
3598
                    tmp = gen_ld32(cpu_T[0], IS_USER(s));
3599
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3600
                    dead_tmp(tmp);
3601
                    break;
3602
                case 3:
3603
                    return 1;
3604
                }
3605
                gen_op_addl_T1_im(1 << size);
3606
                NEON_SET_REG(T0, rd, 0);
3607
                NEON_SET_REG(T0, rd, 1);
3608
                rd += stride;
3609
            }
3610
            stride = (1 << size) * nregs;
3611
        } else {
3612
            /* Single element.  */
3613
            pass = (insn >> 7) & 1;
3614
            switch (size) {
3615
            case 0:
3616
                shift = ((insn >> 5) & 3) * 8;
3617
                mask = 0xff << shift;
3618
                stride = 1;
3619
                break;
3620
            case 1:
3621
                shift = ((insn >> 6) & 1) * 16;
3622
                mask = shift ? 0xffff0000 : 0xffff;
3623
                stride = (insn & (1 << 5)) ? 2 : 1;
3624
                break;
3625
            case 2:
3626
                shift = 0;
3627
                mask = 0xffffffff;
3628
                stride = (insn & (1 << 6)) ? 2 : 1;
3629
                break;
3630
            default:
3631
                abort();
3632
            }
3633
            nregs = ((insn >> 8) & 3) + 1;
3634
            gen_movl_T1_reg(s, rn);
3635
            for (reg = 0; reg < nregs; reg++) {
3636
                if (load) {
3637
                    if (size != 2) {
3638
                        NEON_GET_REG(T2, rd, pass);
3639
                    }
3640
                    switch (size) {
3641
                    case 0:
3642
                        tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3643
                        break;
3644
                    case 1:
3645
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3646
                        break;
3647
                    case 2:
3648
                        tmp = gen_ld32(cpu_T[1], IS_USER(s));
3649
                        break;
3650
                    }
3651
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3652
                    dead_tmp(tmp);
3653
                    if (size != 2) {
3654
                        gen_op_neon_insert_elt(shift, ~mask);
3655
                        NEON_SET_REG(T0, rd, pass);
3656
                    } else {
3657
                        NEON_SET_REG(T0, rd, pass);
3658
                    }
3659
                } else { /* Store */
3660
                    if (size == 2) {
3661
                        NEON_GET_REG(T0, rd, pass);
3662
                    } else {
3663
                        NEON_GET_REG(T2, rd, pass);
3664
                        gen_op_neon_extract_elt(shift, mask);
3665
                    }
3666
                    tmp = new_tmp();
3667
                    tcg_gen_mov_i32(tmp, cpu_T[0]);
3668
                    switch (size) {
3669
                    case 0:
3670
                        gen_st8(tmp, cpu_T[1], IS_USER(s));
3671
                        break;
3672
                    case 1:
3673
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3674
                        break;
3675
                    case 2:
3676
                        gen_st32(tmp, cpu_T[1], IS_USER(s));
3677
                        break;
3678
                    }
3679
                }
3680
                rd += stride;
3681
                gen_op_addl_T1_im(1 << size);
3682
            }
3683
            stride = nregs * (1 << size);
3684
        }
3685
    }
3686
    if (rm != 15) {
3687
        TCGv base;
3688

    
3689
        base = load_reg(s, rn);
3690
        if (rm == 13) {
3691
            tcg_gen_addi_i32(base, base, stride);
3692
        } else {
3693
            TCGv index;
3694
            index = load_reg(s, rm);
3695
            tcg_gen_add_i32(base, base, index);
3696
            dead_tmp(index);
3697
        }
3698
        store_reg(s, rn, base);
3699
    }
3700
    return 0;
3701
}
3702

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

    
3710
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
3711
{
3712
    int op;
3713
    int q;
3714
    int rd, rn, rm;
3715
    int size;
3716
    int shift;
3717
    int pass;
3718
    int count;
3719
    int pairwise;
3720
    int u;
3721
    int n;
3722
    uint32_t imm;
3723

    
3724
    if (!vfp_enabled(env))
3725
      return 1;
3726
    q = (insn & (1 << 6)) != 0;
3727
    u = (insn >> 24) & 1;
3728
    VFP_DREG_D(rd, insn);
3729
    VFP_DREG_N(rn, insn);
3730
    VFP_DREG_M(rm, insn);
3731
    size = (insn >> 20) & 3;
3732
    if ((insn & (1 << 23)) == 0) {
3733
        /* Three register same length.  */
3734
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
3735
        if (size == 3 && (op == 1 || op == 5 || op == 16)) {
3736
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
3737
                NEON_GET_REG(T0, rm, pass * 2);
3738
                NEON_GET_REG(T1, rm, pass * 2 + 1);
3739
                gen_neon_movl_scratch_T0(0);
3740
                gen_neon_movl_scratch_T1(1);
3741
                NEON_GET_REG(T0, rn, pass * 2);
3742
                NEON_GET_REG(T1, rn, pass * 2 + 1);
3743
                switch (op) {
3744
                case 1: /* VQADD */
3745
                    if (u) {
3746
                        gen_op_neon_addl_saturate_u64();
3747
                    } else {
3748
                        gen_op_neon_addl_saturate_s64();
3749
                    }
3750
                    break;
3751
                case 5: /* VQSUB */
3752
                    if (u) {
3753
                        gen_op_neon_subl_saturate_u64();
3754
                    } else {
3755
                        gen_op_neon_subl_saturate_s64();
3756
                    }
3757
                    break;
3758
                case 16:
3759
                    if (u) {
3760
                        gen_op_neon_subl_u64();
3761
                    } else {
3762
                        gen_op_neon_addl_u64();
3763
                    }
3764
                    break;
3765
                default:
3766
                    abort();
3767
                }
3768
                NEON_SET_REG(T0, rd, pass * 2);
3769
                NEON_SET_REG(T1, rd, pass * 2 + 1);
3770
            }
3771
            return 0;
3772
        }
3773
        switch (op) {
3774
        case 8: /* VSHL */
3775
        case 9: /* VQSHL */
3776
        case 10: /* VRSHL */
3777
        case 11: /* VQSHL */
3778
            /* Shift operations have Rn and Rm reversed.  */
3779
            {
3780
                int tmp;
3781
                tmp = rn;
3782
                rn = rm;
3783
                rm = tmp;
3784
                pairwise = 0;
3785
            }
3786
            break;
3787
        case 20: /* VPMAX */
3788
        case 21: /* VPMIN */
3789
        case 23: /* VPADD */
3790
            pairwise = 1;
3791
            break;
3792
        case 26: /* VPADD (float) */
3793
            pairwise = (u && size < 2);
3794
            break;
3795
        case 30: /* VPMIN/VPMAX (float) */
3796
            pairwise = u;
3797
            break;
3798
        default:
3799
            pairwise = 0;
3800
            break;
3801
        }
3802
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
3803

    
3804
        if (pairwise) {
3805
            /* Pairwise.  */
3806
            if (q)
3807
                n = (pass & 1) * 2;
3808
            else
3809
                n = 0;
3810
            if (pass < q + 1) {
3811
                NEON_GET_REG(T0, rn, n);
3812
                NEON_GET_REG(T1, rn, n + 1);
3813
            } else {
3814
                NEON_GET_REG(T0, rm, n);
3815
                NEON_GET_REG(T1, rm, n + 1);
3816
            }
3817
        } else {
3818
            /* Elementwise.  */
3819
            NEON_GET_REG(T0, rn, pass);
3820
            NEON_GET_REG(T1, rm, pass);
3821
        }
3822
        switch (op) {
3823
        case 0: /* VHADD */
3824
            GEN_NEON_INTEGER_OP(hadd);
3825
            break;
3826
        case 1: /* VQADD */
3827
            switch (size << 1| u) {
3828
            case 0: gen_op_neon_qadd_s8(); break;
3829
            case 1: gen_op_neon_qadd_u8(); break;
3830
            case 2: gen_op_neon_qadd_s16(); break;
3831
            case 3: gen_op_neon_qadd_u16(); break;
3832
            case 4:
3833
                gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1]);
3834
                break;
3835
            case 5:
3836
                gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1]);
3837
                break;
3838
            default: abort();
3839
            }
3840
            break;
3841
        case 2: /* VRHADD */
3842
            GEN_NEON_INTEGER_OP(rhadd);
3843
            break;
3844
        case 3: /* Logic ops.  */
3845
            switch ((u << 2) | size) {
3846
            case 0: /* VAND */
3847
                gen_op_andl_T0_T1();
3848
                break;
3849
            case 1: /* BIC */
3850
                gen_op_bicl_T0_T1();
3851
                break;
3852
            case 2: /* VORR */
3853
                gen_op_orl_T0_T1();
3854
                break;
3855
            case 3: /* VORN */
3856
                gen_op_notl_T1();
3857
                gen_op_orl_T0_T1();
3858
                break;
3859
            case 4: /* VEOR */
3860
                gen_op_xorl_T0_T1();
3861
                break;
3862
            case 5: /* VBSL */
3863
                NEON_GET_REG(T2, rd, pass);
3864
                gen_op_neon_bsl();
3865
                break;
3866
            case 6: /* VBIT */
3867
                NEON_GET_REG(T2, rd, pass);
3868
                gen_op_neon_bit();
3869
                break;
3870
            case 7: /* VBIF */
3871
                NEON_GET_REG(T2, rd, pass);
3872
                gen_op_neon_bif();
3873
                break;
3874
            }
3875
            break;
3876
        case 4: /* VHSUB */
3877
            GEN_NEON_INTEGER_OP(hsub);
3878
            break;
3879
        case 5: /* VQSUB */
3880
            switch ((size << 1) | u) {
3881
            case 0: gen_op_neon_qsub_s8(); break;
3882
            case 1: gen_op_neon_qsub_u8(); break;
3883
            case 2: gen_op_neon_qsub_s16(); break;
3884
            case 3: gen_op_neon_qsub_u16(); break;
3885
            case 4:
3886
                gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1]);
3887
                break;
3888
            case 5:
3889
                gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1]);
3890
                break;
3891
            default: abort();
3892
            }
3893
            break;
3894
        case 6: /* VCGT */
3895
            GEN_NEON_INTEGER_OP(cgt);
3896
            break;
3897
        case 7: /* VCGE */
3898
            GEN_NEON_INTEGER_OP(cge);
3899
            break;
3900
        case 8: /* VSHL */
3901
            switch ((size << 1) | u) {
3902
            case 0: gen_op_neon_shl_s8(); break;
3903
            case 1: gen_op_neon_shl_u8(); break;
3904
            case 2: gen_op_neon_shl_s16(); break;
3905
            case 3: gen_op_neon_shl_u16(); break;
3906
            case 4: gen_op_neon_shl_s32(); break;
3907
            case 5: gen_op_neon_shl_u32(); break;
3908
#if 0
3909
            /* ??? Implementing these is tricky because the vector ops work
3910
               on 32-bit pieces.  */
3911
            case 6: gen_op_neon_shl_s64(); break;
3912
            case 7: gen_op_neon_shl_u64(); break;
3913
#else
3914
            case 6: case 7: cpu_abort(env, "VSHL.64 not implemented");
3915
#endif
3916
            }
3917
            break;
3918
        case 9: /* VQSHL */
3919
            switch ((size << 1) | u) {
3920
            case 0: gen_op_neon_qshl_s8(); break;
3921
            case 1: gen_op_neon_qshl_u8(); break;
3922
            case 2: gen_op_neon_qshl_s16(); break;
3923
            case 3: gen_op_neon_qshl_u16(); break;
3924
            case 4: gen_op_neon_qshl_s32(); break;
3925
            case 5: gen_op_neon_qshl_u32(); break;
3926
#if 0
3927
            /* ??? Implementing these is tricky because the vector ops work
3928
               on 32-bit pieces.  */
3929
            case 6: gen_op_neon_qshl_s64(); break;
3930
            case 7: gen_op_neon_qshl_u64(); break;
3931
#else
3932
            case 6: case 7: cpu_abort(env, "VQSHL.64 not implemented");
3933
#endif
3934
            }
3935
            break;
3936
        case 10: /* VRSHL */
3937
            switch ((size << 1) | u) {
3938
            case 0: gen_op_neon_rshl_s8(); break;
3939
            case 1: gen_op_neon_rshl_u8(); break;
3940
            case 2: gen_op_neon_rshl_s16(); break;
3941
            case 3: gen_op_neon_rshl_u16(); break;
3942
            case 4: gen_op_neon_rshl_s32(); break;
3943
            case 5: gen_op_neon_rshl_u32(); break;
3944
#if 0
3945
            /* ??? Implementing these is tricky because the vector ops work
3946
               on 32-bit pieces.  */
3947
            case 6: gen_op_neon_rshl_s64(); break;
3948
            case 7: gen_op_neon_rshl_u64(); break;
3949
#else
3950
            case 6: case 7: cpu_abort(env, "VRSHL.64 not implemented");
3951
#endif
3952
            }
3953
            break;
3954
        case 11: /* VQRSHL */
3955
            switch ((size << 1) | u) {
3956
            case 0: gen_op_neon_qrshl_s8(); break;
3957
            case 1: gen_op_neon_qrshl_u8(); break;
3958
            case 2: gen_op_neon_qrshl_s16(); break;
3959
            case 3: gen_op_neon_qrshl_u16(); break;
3960
            case 4: gen_op_neon_qrshl_s32(); break;
3961
            case 5: gen_op_neon_qrshl_u32(); break;
3962
#if 0
3963
            /* ??? Implementing these is tricky because the vector ops work
3964
               on 32-bit pieces.  */
3965
            case 6: gen_op_neon_qrshl_s64(); break;
3966
            case 7: gen_op_neon_qrshl_u64(); break;
3967
#else
3968
            case 6: case 7: cpu_abort(env, "VQRSHL.64 not implemented");
3969
#endif
3970
            }
3971
            break;
3972
        case 12: /* VMAX */
3973
            GEN_NEON_INTEGER_OP(max);
3974
            break;
3975
        case 13: /* VMIN */
3976
            GEN_NEON_INTEGER_OP(min);
3977
            break;
3978
        case 14: /* VABD */
3979
            GEN_NEON_INTEGER_OP(abd);
3980
            break;
3981
        case 15: /* VABA */
3982
            GEN_NEON_INTEGER_OP(abd);
3983
            NEON_GET_REG(T1, rd, pass);
3984
            gen_neon_add(size);
3985
            break;
3986
        case 16:
3987
            if (!u) { /* VADD */
3988
                if (gen_neon_add(size))
3989
                    return 1;
3990
            } else { /* VSUB */
3991
                switch (size) {
3992
                case 0: gen_op_neon_sub_u8(); break;
3993
                case 1: gen_op_neon_sub_u16(); break;
3994
                case 2: gen_op_subl_T0_T1(); break;
3995
                default: return 1;
3996
                }
3997
            }
3998
            break;
3999
        case 17:
4000
            if (!u) { /* VTST */
4001
                switch (size) {
4002
                case 0: gen_op_neon_tst_u8(); break;
4003
                case 1: gen_op_neon_tst_u16(); break;
4004
                case 2: gen_op_neon_tst_u32(); break;
4005
                default: return 1;
4006
                }
4007
            } else { /* VCEQ */
4008
                switch (size) {
4009
                case 0: gen_op_neon_ceq_u8(); break;
4010
                case 1: gen_op_neon_ceq_u16(); break;
4011
                case 2: gen_op_neon_ceq_u32(); break;
4012
                default: return 1;
4013
                }
4014
            }
4015
            break;
4016
        case 18: /* Multiply.  */
4017
            switch (size) {
4018
            case 0: gen_op_neon_mul_u8(); break;
4019
            case 1: gen_op_neon_mul_u16(); break;
4020
            case 2: gen_op_mul_T0_T1(); break;
4021
            default: return 1;
4022
            }
4023
            NEON_GET_REG(T1, rd, pass);
4024
            if (u) { /* VMLS */
4025
                switch (size) {
4026
                case 0: gen_op_neon_rsb_u8(); break;
4027
                case 1: gen_op_neon_rsb_u16(); break;
4028
                case 2: gen_op_rsbl_T0_T1(); break;
4029
                default: return 1;
4030
                }
4031
            } else { /* VMLA */
4032
                gen_neon_add(size);
4033
            }
4034
            break;
4035
        case 19: /* VMUL */
4036
            if (u) { /* polynomial */
4037
                gen_op_neon_mul_p8();
4038
            } else { /* Integer */
4039
                switch (size) {
4040
                case 0: gen_op_neon_mul_u8(); break;
4041
                case 1: gen_op_neon_mul_u16(); break;
4042
                case 2: gen_op_mul_T0_T1(); break;
4043
                default: return 1;
4044
                }
4045
            }
4046
            break;
4047
        case 20: /* VPMAX */
4048
            GEN_NEON_INTEGER_OP(pmax);
4049
            break;
4050
        case 21: /* VPMIN */
4051
            GEN_NEON_INTEGER_OP(pmin);
4052
            break;
4053
        case 22: /* Hultiply high.  */
4054
            if (!u) { /* VQDMULH */
4055
                switch (size) {
4056
                case 1: gen_op_neon_qdmulh_s16(); break;
4057
                case 2: gen_op_neon_qdmulh_s32(); break;
4058
                default: return 1;
4059
                }
4060
            } else { /* VQRDHMUL */
4061
                switch (size) {
4062
                case 1: gen_op_neon_qrdmulh_s16(); break;
4063
                case 2: gen_op_neon_qrdmulh_s32(); break;
4064
                default: return 1;
4065
                }
4066
            }
4067
            break;
4068
        case 23: /* VPADD */
4069
            if (u)
4070
                return 1;
4071
            switch (size) {
4072
            case 0: gen_op_neon_padd_u8(); break;
4073
            case 1: gen_op_neon_padd_u16(); break;
4074
            case 2: gen_op_addl_T0_T1(); break;
4075
            default: return 1;
4076
            }
4077
            break;
4078
        case 26: /* Floating point arithnetic.  */
4079
            switch ((u << 2) | size) {
4080
            case 0: /* VADD */
4081
                gen_op_neon_add_f32();
4082
                break;
4083
            case 2: /* VSUB */
4084
                gen_op_neon_sub_f32();
4085
                break;
4086
            case 4: /* VPADD */
4087
                gen_op_neon_add_f32();
4088
                break;
4089
            case 6: /* VABD */
4090
                gen_op_neon_abd_f32();
4091
                break;
4092
            default:
4093
                return 1;
4094
            }
4095
            break;
4096
        case 27: /* Float multiply.  */
4097
            gen_op_neon_mul_f32();
4098
            if (!u) {
4099
                NEON_GET_REG(T1, rd, pass);
4100
                if (size == 0) {
4101
                    gen_op_neon_add_f32();
4102
                } else {
4103
                    gen_op_neon_rsb_f32();
4104
                }
4105
            }
4106
            break;
4107
        case 28: /* Float compare.  */
4108
            if (!u) {
4109
                gen_op_neon_ceq_f32();
4110
            } else {
4111
                if (size == 0)
4112
                    gen_op_neon_cge_f32();
4113
                else
4114
                    gen_op_neon_cgt_f32();
4115
            }
4116
            break;
4117
        case 29: /* Float compare absolute.  */
4118
            if (!u)
4119
                return 1;
4120
            if (size == 0)
4121
                gen_op_neon_acge_f32();
4122
            else
4123
                gen_op_neon_acgt_f32();
4124
            break;
4125
        case 30: /* Float min/max.  */
4126
            if (size == 0)
4127
                gen_op_neon_max_f32();
4128
            else
4129
                gen_op_neon_min_f32();
4130
            break;
4131
        case 31:
4132
            if (size == 0)
4133
                gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4134
            else
4135
                gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4136
            break;
4137
        default:
4138
            abort();
4139
        }
4140
        /* Save the result.  For elementwise operations we can put it
4141
           straight into the destination register.  For pairwise operations
4142
           we have to be careful to avoid clobbering the source operands.  */
4143
        if (pairwise && rd == rm) {
4144
            gen_neon_movl_scratch_T0(pass);
4145
        } else {
4146
            NEON_SET_REG(T0, rd, pass);
4147
        }
4148

    
4149
        } /* for pass */
4150
        if (pairwise && rd == rm) {
4151
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4152
                gen_neon_movl_T0_scratch(pass);
4153
                NEON_SET_REG(T0, rd, pass);
4154
            }
4155
        }
4156
    } else if (insn & (1 << 4)) {
4157
        if ((insn & 0x00380080) != 0) {
4158
            /* Two registers and shift.  */
4159
            op = (insn >> 8) & 0xf;
4160
            if (insn & (1 << 7)) {
4161
                /* 64-bit shift.   */
4162
                size = 3;
4163
            } else {
4164
                size = 2;
4165
                while ((insn & (1 << (size + 19))) == 0)
4166
                    size--;
4167
            }
4168
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4169
            /* To avoid excessive dumplication of ops we implement shift
4170
               by immediate using the variable shift operations.  */
4171
            if (op < 8) {
4172
                /* Shift by immediate:
4173
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
4174
                /* Right shifts are encoded as N - shift, where N is the
4175
                   element size in bits.  */
4176
                if (op <= 4)
4177
                    shift = shift - (1 << (size + 3));
4178
                else
4179
                    shift++;
4180
                if (size == 3) {
4181
                    count = q + 1;
4182
                } else {
4183
                    count = q ? 4: 2;
4184
                }
4185
                switch (size) {
4186
                case 0:
4187
                    imm = (uint8_t) shift;
4188
                    imm |= imm << 8;
4189
                    imm |= imm << 16;
4190
                    break;
4191
                case 1:
4192
                    imm = (uint16_t) shift;
4193
                    imm |= imm << 16;
4194
                    break;
4195
                case 2:
4196
                case 3:
4197
                    imm = shift;
4198
                    break;
4199
                default:
4200
                    abort();
4201
                }
4202

    
4203
                for (pass = 0; pass < count; pass++) {
4204
                    if (size < 3) {
4205
                        /* Operands in T0 and T1.  */
4206
                        gen_op_movl_T1_im(imm);
4207
                        NEON_GET_REG(T0, rm, pass);
4208
                    } else {
4209
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
4210
                        gen_op_movl_T0_im(imm);
4211
                        gen_neon_movl_scratch_T0(0);
4212
                        gen_op_movl_T0_im((int32_t)imm >> 31);
4213
                        gen_neon_movl_scratch_T0(1);
4214
                        NEON_GET_REG(T0, rm, pass * 2);
4215
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4216
                    }
4217

    
4218
                    if (gen_neon_shift_im[op][u][size] == NULL)
4219
                        return 1;
4220
                    gen_neon_shift_im[op][u][size]();
4221

    
4222
                    if (op == 1 || op == 3) {
4223
                        /* Accumulate.  */
4224
                        if (size == 3) {
4225
                            gen_neon_movl_scratch_T0(0);
4226
                            gen_neon_movl_scratch_T1(1);
4227
                            NEON_GET_REG(T0, rd, pass * 2);
4228
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4229
                            gen_op_neon_addl_u64();
4230
                        } else {
4231
                            NEON_GET_REG(T1, rd, pass);
4232
                            gen_neon_add(size);
4233
                        }
4234
                    } else if (op == 4 || (op == 5 && u)) {
4235
                        /* Insert */
4236
                        if (size == 3) {
4237
                            cpu_abort(env, "VS[LR]I.64 not implemented");
4238
                        }
4239
                        switch (size) {
4240
                        case 0:
4241
                            if (op == 4)
4242
                                imm = 0xff >> -shift;
4243
                            else
4244
                                imm = (uint8_t)(0xff << shift);
4245
                            imm |= imm << 8;
4246
                            imm |= imm << 16;
4247
                            break;
4248
                        case 1:
4249
                            if (op == 4)
4250
                                imm = 0xffff >> -shift;
4251
                            else
4252
                                imm = (uint16_t)(0xffff << shift);
4253
                            imm |= imm << 16;
4254
                            break;
4255
                        case 2:
4256
                            if (op == 4)
4257
                                imm = 0xffffffffu >> -shift;
4258
                            else
4259
                                imm = 0xffffffffu << shift;
4260
                            break;
4261
                        default:
4262
                            abort();
4263
                        }
4264
                        NEON_GET_REG(T1, rd, pass);
4265
                        gen_op_movl_T2_im(imm);
4266
                        gen_op_neon_bsl();
4267
                    }
4268
                    if (size == 3) {
4269
                        NEON_SET_REG(T0, rd, pass * 2);
4270
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4271
                    } else {
4272
                        NEON_SET_REG(T0, rd, pass);
4273
                    }
4274
                } /* for pass */
4275
            } else if (op < 10) {
4276
                /* Shift by immedaiate and narrow:
4277
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
4278
                shift = shift - (1 << (size + 3));
4279
                size++;
4280
                if (size == 3) {
4281
                    count = q + 1;
4282
                } else {
4283
                    count = q ? 4: 2;
4284
                }
4285
                switch (size) {
4286
                case 1:
4287
                    imm = (uint16_t) shift;
4288
                    imm |= imm << 16;
4289
                    break;
4290
                case 2:
4291
                case 3:
4292
                    imm = shift;
4293
                    break;
4294
                default:
4295
                    abort();
4296
                }
4297

    
4298
                /* Processing MSB first means we need to do less shuffling at
4299
                   the end.  */
4300
                for (pass =  count - 1; pass >= 0; pass--) {
4301
                    /* Avoid clobbering the second operand before it has been
4302
                       written.  */
4303
                    n = pass;
4304
                    if (rd == rm)
4305
                        n ^= (count - 1);
4306
                    else
4307
                        n = pass;
4308

    
4309
                    if (size < 3) {
4310
                        /* Operands in T0 and T1.  */
4311
                        gen_op_movl_T1_im(imm);
4312
                        NEON_GET_REG(T0, rm, n);
4313
                    } else {
4314
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
4315
                        gen_op_movl_T0_im(imm);
4316
                        gen_neon_movl_scratch_T0(0);
4317
                        gen_op_movl_T0_im((int32_t)imm >> 31);
4318
                        gen_neon_movl_scratch_T0(1);
4319
                        NEON_GET_REG(T0, rm, n * 2);
4320
                        NEON_GET_REG(T0, rm, n * 2 + 1);
4321
                    }
4322

    
4323
                    gen_neon_shift_im_narrow[q][u][size - 1]();
4324

    
4325
                    if (size < 3 && (pass & 1) == 0) {
4326
                        gen_neon_movl_scratch_T0(0);
4327
                    } else {
4328
                        uint32_t offset;
4329

    
4330
                        if (size < 3)
4331
                            gen_neon_movl_T1_scratch(0);
4332

    
4333
                        if (op == 8 && !u) {
4334
                            gen_neon_narrow[size - 1]();
4335
                        } else {
4336
                            if (op == 8)
4337
                                gen_neon_narrow_sats[size - 2]();
4338
                            else
4339
                                gen_neon_narrow_satu[size - 1]();
4340
                        }
4341
                        if (size == 3)
4342
                            offset = neon_reg_offset(rd, n);
4343
                        else
4344
                            offset = neon_reg_offset(rd, n >> 1);
4345
                        gen_op_neon_setreg_T0(offset);
4346
                    }
4347
                } /* for pass */
4348
            } else if (op == 10) {
4349
                /* VSHLL */
4350
                if (q)
4351
                    return 1;
4352
                for (pass = 0; pass < 2; pass++) {
4353
                    /* Avoid clobbering the input operand.  */
4354
                    if (rd == rm)
4355
                        n = 1 - pass;
4356
                    else
4357
                        n = pass;
4358

    
4359
                    NEON_GET_REG(T0, rm, n);
4360
                    GEN_NEON_INTEGER_OP(widen);
4361
                    if (shift != 0) {
4362
                        /* The shift is less than the width of the source
4363
                           type, so in some cases we can just
4364
                           shift the whole register.  */
4365
                        if (size == 1 || (size == 0 && u)) {
4366
                            gen_op_shll_T0_im(shift);
4367
                            gen_op_shll_T1_im(shift);
4368
                        } else {
4369
                            switch (size) {
4370
                            case 0: gen_op_neon_shll_u16(shift); break;
4371
                            case 2: gen_op_neon_shll_u64(shift); break;
4372
                            default: abort();
4373
                            }
4374
                        }
4375
                    }
4376
                    NEON_SET_REG(T0, rd, n * 2);
4377
                    NEON_SET_REG(T1, rd, n * 2 + 1);
4378
                }
4379
            } else if (op == 15 || op == 16) {
4380
                /* VCVT fixed-point.  */
4381
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4382
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4383
                    if (op & 1) {
4384
                        if (u)
4385
                            gen_vfp_ulto(0, shift);
4386
                        else
4387
                            gen_vfp_slto(0, shift);
4388
                    } else {
4389
                        if (u)
4390
                            gen_vfp_toul(0, shift);
4391
                        else
4392
                            gen_vfp_tosl(0, shift);
4393
                    }
4394
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4395
                }
4396
            } else {
4397
                return 1;
4398
            }
4399
        } else { /* (insn & 0x00380080) == 0 */
4400
            int invert;
4401

    
4402
            op = (insn >> 8) & 0xf;
4403
            /* One register and immediate.  */
4404
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4405
            invert = (insn & (1 << 5)) != 0;
4406
            switch (op) {
4407
            case 0: case 1:
4408
                /* no-op */
4409
                break;
4410
            case 2: case 3:
4411
                imm <<= 8;
4412
                break;
4413
            case 4: case 5:
4414
                imm <<= 16;
4415
                break;
4416
            case 6: case 7:
4417
                imm <<= 24;
4418
                break;
4419
            case 8: case 9:
4420
                imm |= imm << 16;
4421
                break;
4422
            case 10: case 11:
4423
                imm = (imm << 8) | (imm << 24);
4424
                break;
4425
            case 12:
4426
                imm = (imm < 8) | 0xff;
4427
                break;
4428
            case 13:
4429
                imm = (imm << 16) | 0xffff;
4430
                break;
4431
            case 14:
4432
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
4433
                if (invert)
4434
                    imm = ~imm;
4435
                break;
4436
            case 15:
4437
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4438
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4439
                break;
4440
            }
4441
            if (invert)
4442
                imm = ~imm;
4443

    
4444
            if (op != 14 || !invert)
4445
                gen_op_movl_T1_im(imm);
4446

    
4447
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4448
                if (op & 1 && op < 12) {
4449
                    NEON_GET_REG(T0, rd, pass);
4450
                    if (invert) {
4451
                        /* The immediate value has already been inverted, so
4452
                           BIC becomes AND.  */
4453
                        gen_op_andl_T0_T1();
4454
                    } else {
4455
                        gen_op_orl_T0_T1();
4456
                    }
4457
                    NEON_SET_REG(T0, rd, pass);
4458
                } else {
4459
                    if (op == 14 && invert) {
4460
                        uint32_t tmp;
4461
                        tmp = 0;
4462
                        for (n = 0; n < 4; n++) {
4463
                            if (imm & (1 << (n + (pass & 1) * 4)))
4464
                                tmp |= 0xff << (n * 8);
4465
                        }
4466
                        gen_op_movl_T1_im(tmp);
4467
                    }
4468
                    /* VMOV, VMVN.  */
4469
                    NEON_SET_REG(T1, rd, pass);
4470
                }
4471
            }
4472
        }
4473
    } else { /* (insn & 0x00800010 == 0x00800010) */
4474
        if (size != 3) {
4475
            op = (insn >> 8) & 0xf;
4476
            if ((insn & (1 << 6)) == 0) {
4477
                /* Three registers of different lengths.  */
4478
                int src1_wide;
4479
                int src2_wide;
4480
                int prewiden;
4481
                /* prewiden, src1_wide, src2_wide */
4482
                static const int neon_3reg_wide[16][3] = {
4483
                    {1, 0, 0}, /* VADDL */
4484
                    {1, 1, 0}, /* VADDW */
4485
                    {1, 0, 0}, /* VSUBL */
4486
                    {1, 1, 0}, /* VSUBW */
4487
                    {0, 1, 1}, /* VADDHN */
4488
                    {0, 0, 0}, /* VABAL */
4489
                    {0, 1, 1}, /* VSUBHN */
4490
                    {0, 0, 0}, /* VABDL */
4491
                    {0, 0, 0}, /* VMLAL */
4492
                    {0, 0, 0}, /* VQDMLAL */
4493
                    {0, 0, 0}, /* VMLSL */
4494
                    {0, 0, 0}, /* VQDMLSL */
4495
                    {0, 0, 0}, /* Integer VMULL */
4496
                    {0, 0, 0}, /* VQDMULL */
4497
                    {0, 0, 0}  /* Polynomial VMULL */
4498
                };
4499

    
4500
                prewiden = neon_3reg_wide[op][0];
4501
                src1_wide = neon_3reg_wide[op][1];
4502
                src2_wide = neon_3reg_wide[op][2];
4503

    
4504
                /* Avoid overlapping operands.  Wide source operands are
4505
                   always aligned so will never overlap with wide
4506
                   destinations in problematic ways.  */
4507
                if (rd == rm) {
4508
                    NEON_GET_REG(T2, rm, 1);
4509
                } else if (rd == rn) {
4510
                    NEON_GET_REG(T2, rn, 1);
4511
                }
4512
                for (pass = 0; pass < 2; pass++) {
4513
                    /* Load the second operand into env->vfp.scratch.
4514
                       Also widen narrow operands.  */
4515
                    if (pass == 1 && rd == rm) {
4516
                        if (prewiden) {
4517
                            gen_op_movl_T0_T2();
4518
                        } else {
4519
                            gen_op_movl_T1_T2();
4520
                        }
4521
                    } else {
4522
                        if (src2_wide) {
4523
                            NEON_GET_REG(T0, rm, pass * 2);
4524
                            NEON_GET_REG(T1, rm, pass * 2 + 1);
4525
                        } else {
4526
                            if (prewiden) {
4527
                                NEON_GET_REG(T0, rm, pass);
4528
                            } else {
4529
                                NEON_GET_REG(T1, rm, pass);
4530
                            }
4531
                        }
4532
                    }
4533
                    if (prewiden && !src2_wide) {
4534
                        GEN_NEON_INTEGER_OP(widen);
4535
                    }
4536
                    if (prewiden || src2_wide) {
4537
                        gen_neon_movl_scratch_T0(0);
4538
                        gen_neon_movl_scratch_T1(1);
4539
                    }
4540

    
4541
                    /* Load the first operand.  */
4542
                    if (pass == 1 && rd == rn) {
4543
                        gen_op_movl_T0_T2();
4544
                    } else {
4545
                        if (src1_wide) {
4546
                            NEON_GET_REG(T0, rn, pass * 2);
4547
                            NEON_GET_REG(T1, rn, pass * 2 + 1);
4548
                        } else {
4549
                            NEON_GET_REG(T0, rn, pass);
4550
                        }
4551
                    }
4552
                    if (prewiden && !src1_wide) {
4553
                        GEN_NEON_INTEGER_OP(widen);
4554
                    }
4555
                    switch (op) {
4556
                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4557
                        switch (size) {
4558
                        case 0: gen_op_neon_addl_u16(); break;
4559
                        case 1: gen_op_neon_addl_u32(); break;
4560
                        case 2: gen_op_neon_addl_u64(); break;
4561
                        default: abort();
4562
                        }
4563
                        break;
4564
                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4565
                        switch (size) {
4566
                        case 0: gen_op_neon_subl_u16(); break;
4567
                        case 1: gen_op_neon_subl_u32(); break;
4568
                        case 2: gen_op_neon_subl_u64(); break;
4569
                        default: abort();
4570
                        }
4571
                        break;
4572
                    case 5: case 7: /* VABAL, VABDL */
4573
                        switch ((size << 1) | u) {
4574
                        case 0: gen_op_neon_abdl_s16(); break;
4575
                        case 1: gen_op_neon_abdl_u16(); break;
4576
                        case 2: gen_op_neon_abdl_s32(); break;
4577
                        case 3: gen_op_neon_abdl_u32(); break;
4578
                        case 4: gen_op_neon_abdl_s64(); break;
4579
                        case 5: gen_op_neon_abdl_u64(); break;
4580
                        default: abort();
4581
                        }
4582
                        break;
4583
                    case 8: case 9: case 10: case 11: case 12: case 13:
4584
                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4585
                        switch ((size << 1) | u) {
4586
                        case 0: gen_op_neon_mull_s8(); break;
4587
                        case 1: gen_op_neon_mull_u8(); break;
4588
                        case 2: gen_op_neon_mull_s16(); break;
4589
                        case 3: gen_op_neon_mull_u16(); break;
4590
                        case 4: gen_op_imull_T0_T1(); break;
4591
                        case 5: gen_op_mull_T0_T1(); break;
4592
                        default: abort();
4593
                        }
4594
                        break;
4595
                    case 14: /* Polynomial VMULL */
4596
                        cpu_abort(env, "Polynomial VMULL not implemented");
4597

    
4598
                    default: /* 15 is RESERVED.  */
4599
                        return 1;
4600
                    }
4601
                    if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4602
                        /* Accumulate.  */
4603
                        if (op == 10 || op == 11) {
4604
                            switch (size) {
4605
                            case 0: gen_op_neon_negl_u16(); break;
4606
                            case 1: gen_op_neon_negl_u32(); break;
4607
                            case 2: gen_op_neon_negl_u64(); break;
4608
                            default: abort();
4609
                            }
4610
                        }
4611

    
4612
                        gen_neon_movl_scratch_T0(0);
4613
                        gen_neon_movl_scratch_T1(1);
4614

    
4615
                        if (op != 13) {
4616
                            NEON_GET_REG(T0, rd, pass * 2);
4617
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4618
                        }
4619

    
4620
                        switch (op) {
4621
                        case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4622
                            switch (size) {
4623
                            case 0: gen_op_neon_addl_u16(); break;
4624
                            case 1: gen_op_neon_addl_u32(); break;
4625
                            case 2: gen_op_neon_addl_u64(); break;
4626
                            default: abort();
4627
                            }
4628
                            break;
4629
                        case 9: case 11: /* VQDMLAL, VQDMLSL */
4630
                            switch (size) {
4631
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4632
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4633
                            default: abort();
4634
                            }
4635
                            /* Fall through.  */
4636
                        case 13: /* VQDMULL */
4637
                            switch (size) {
4638
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4639
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4640
                            default: abort();
4641
                            }
4642
                            break;
4643
                        default:
4644
                            abort();
4645
                        }
4646
                        NEON_SET_REG(T0, rd, pass * 2);
4647
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4648
                    } else if (op == 4 || op == 6) {
4649
                        /* Narrowing operation.  */
4650
                        if (u) {
4651
                            switch (size) {
4652
                            case 0: gen_op_neon_narrow_high_u8(); break;
4653
                            case 1: gen_op_neon_narrow_high_u16(); break;
4654
                            case 2: gen_op_movl_T0_T1(); break;
4655
                            default: abort();
4656
                            }
4657
                        } else {
4658
                            switch (size) {
4659
                            case 0: gen_op_neon_narrow_high_round_u8(); break;
4660
                            case 1: gen_op_neon_narrow_high_round_u16(); break;
4661
                            case 2: gen_op_neon_narrow_high_round_u32(); break;
4662
                            default: abort();
4663
                            }
4664
                        }
4665
                        NEON_SET_REG(T0, rd, pass);
4666
                    } else {
4667
                        /* Write back the result.  */
4668
                        NEON_SET_REG(T0, rd, pass * 2);
4669
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4670
                    }
4671
                }
4672
            } else {
4673
                /* Two registers and a scalar.  */
4674
                switch (op) {
4675
                case 0: /* Integer VMLA scalar */
4676
                case 1: /* Float VMLA scalar */
4677
                case 4: /* Integer VMLS scalar */
4678
                case 5: /* Floating point VMLS scalar */
4679
                case 8: /* Integer VMUL scalar */
4680
                case 9: /* Floating point VMUL scalar */
4681
                case 12: /* VQDMULH scalar */
4682
                case 13: /* VQRDMULH scalar */
4683
                    gen_neon_get_scalar(size, rm);
4684
                    gen_op_movl_T2_T0();
4685
                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
4686
                        if (pass != 0)
4687
                            gen_op_movl_T0_T2();
4688
                        NEON_GET_REG(T1, rn, pass);
4689
                        if (op == 12) {
4690
                            if (size == 1) {
4691
                                gen_op_neon_qdmulh_s16();
4692
                            } else {
4693
                                gen_op_neon_qdmulh_s32();
4694
                            }
4695
                        } else if (op == 13) {
4696
                            if (size == 1) {
4697
                                gen_op_neon_qrdmulh_s16();
4698
                            } else {
4699
                                gen_op_neon_qrdmulh_s32();
4700
                            }
4701
                        } else if (op & 1) {
4702
                            gen_op_neon_mul_f32();
4703
                        } else {
4704
                            switch (size) {
4705
                            case 0: gen_op_neon_mul_u8(); break;
4706
                            case 1: gen_op_neon_mul_u16(); break;
4707
                            case 2: gen_op_mul_T0_T1(); break;
4708
                            default: return 1;
4709
                            }
4710
                        }
4711
                        if (op < 8) {
4712
                            /* Accumulate.  */
4713
                            NEON_GET_REG(T1, rd, pass);
4714
                            switch (op) {
4715
                            case 0:
4716
                                gen_neon_add(size);
4717
                                break;
4718
                            case 1:
4719
                                gen_op_neon_add_f32();
4720
                                break;
4721
                            case 4:
4722
                                switch (size) {
4723
                                case 0: gen_op_neon_rsb_u8(); break;
4724
                                case 1: gen_op_neon_rsb_u16(); break;
4725
                                case 2: gen_op_rsbl_T0_T1(); break;
4726
                                default: return 1;
4727
                                }
4728
                                break;
4729
                            case 5:
4730
                                gen_op_neon_rsb_f32();
4731
                                break;
4732
                            default:
4733
                                abort();
4734
                            }
4735
                        }
4736
                        NEON_SET_REG(T0, rd, pass);
4737
                    }
4738
                    break;
4739
                case 2: /* VMLAL sclar */
4740
                case 3: /* VQDMLAL scalar */
4741
                case 6: /* VMLSL scalar */
4742
                case 7: /* VQDMLSL scalar */
4743
                case 10: /* VMULL scalar */
4744
                case 11: /* VQDMULL scalar */
4745
                    if (rd == rn) {
4746
                        /* Save overlapping operands before they are
4747
                           clobbered.  */
4748
                        NEON_GET_REG(T0, rn, 1);
4749
                        gen_neon_movl_scratch_T0(2);
4750
                    }
4751
                    gen_neon_get_scalar(size, rm);
4752
                    gen_op_movl_T2_T0();
4753
                    for (pass = 0; pass < 2; pass++) {
4754
                        if (pass != 0) {
4755
                            gen_op_movl_T0_T2();
4756
                        }
4757
                        if (pass != 0 && rd == rn) {
4758
                            gen_neon_movl_T1_scratch(2);
4759
                        } else {
4760
                            NEON_GET_REG(T1, rn, pass);
4761
                        }
4762
                        switch ((size << 1) | u) {
4763
                        case 0: gen_op_neon_mull_s8(); break;
4764
                        case 1: gen_op_neon_mull_u8(); break;
4765
                        case 2: gen_op_neon_mull_s16(); break;
4766
                        case 3: gen_op_neon_mull_u16(); break;
4767
                        case 4: gen_op_imull_T0_T1(); break;
4768
                        case 5: gen_op_mull_T0_T1(); break;
4769
                        default: abort();
4770
                        }
4771
                        if (op == 6 || op == 7) {
4772
                            switch (size) {
4773
                            case 0: gen_op_neon_negl_u16(); break;
4774
                            case 1: gen_op_neon_negl_u32(); break;
4775
                            case 2: gen_op_neon_negl_u64(); break;
4776
                            default: abort();
4777
                            }
4778
                        }
4779
                        gen_neon_movl_scratch_T0(0);
4780
                        gen_neon_movl_scratch_T1(1);
4781
                        NEON_GET_REG(T0, rd, pass * 2);
4782
                        NEON_GET_REG(T1, rd, pass * 2 + 1);
4783
                        switch (op) {
4784
                        case 2: case 6:
4785
                            switch (size) {
4786
                            case 0: gen_op_neon_addl_u16(); break;
4787
                            case 1: gen_op_neon_addl_u32(); break;
4788
                            case 2: gen_op_neon_addl_u64(); break;
4789
                            default: abort();
4790
                            }
4791
                            break;
4792
                        case 3: case 7:
4793
                            switch (size) {
4794
                            case 1:
4795
                                gen_op_neon_addl_saturate_s32();
4796
                                gen_op_neon_addl_saturate_s32();
4797
                                break;
4798
                            case 2:
4799
                                gen_op_neon_addl_saturate_s64();
4800
                                gen_op_neon_addl_saturate_s64();
4801
                                break;
4802
                            default: abort();
4803
                            }
4804
                            break;
4805
                        case 10:
4806
                            /* no-op */
4807
                            break;
4808
                        case 11:
4809
                            switch (size) {
4810
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4811
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4812
                            default: abort();
4813
                            }
4814
                            break;
4815
                        default:
4816
                            abort();
4817
                        }
4818
                        NEON_SET_REG(T0, rd, pass * 2);
4819
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4820
                    }
4821
                    break;
4822
                default: /* 14 and 15 are RESERVED */
4823
                    return 1;
4824
                }
4825
            }
4826
        } else { /* size == 3 */
4827
            if (!u) {
4828
                /* Extract.  */
4829
                int reg;
4830
                imm = (insn >> 8) & 0xf;
4831
                reg = rn;
4832
                count = q ? 4 : 2;
4833
                n = imm >> 2;
4834
                NEON_GET_REG(T0, reg, n);
4835
                for (pass = 0; pass < count; pass++) {
4836
                    n++;
4837
                    if (n > count) {
4838
                        reg = rm;
4839
                        n -= count;
4840
                    }
4841
                    if (imm & 3) {
4842
                        NEON_GET_REG(T1, reg, n);
4843
                        gen_op_neon_extract((insn << 3) & 0x1f);
4844
                    }
4845
                    /* ??? This is broken if rd and rm overlap */
4846
                    NEON_SET_REG(T0, rd, pass);
4847
                    if (imm & 3) {
4848
                        gen_op_movl_T0_T1();
4849
                    } else {
4850
                        NEON_GET_REG(T0, reg, n);
4851
                    }
4852
                }
4853
            } else if ((insn & (1 << 11)) == 0) {
4854
                /* Two register misc.  */
4855
                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
4856
                size = (insn >> 18) & 3;
4857
                switch (op) {
4858
                case 0: /* VREV64 */
4859
                    if (size == 3)
4860
                        return 1;
4861
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4862
                        NEON_GET_REG(T0, rm, pass * 2);
4863
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4864
                        switch (size) {
4865
                        case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
4866
                        case 1: gen_swap_half(cpu_T[0]); break;
4867
                        case 2: /* no-op */ break;
4868
                        default: abort();
4869
                        }
4870
                        NEON_SET_REG(T0, rd, pass * 2 + 1);
4871
                        if (size == 2) {
4872
                            NEON_SET_REG(T1, rd, pass * 2);
4873
                        } else {
4874
                            gen_op_movl_T0_T1();
4875
                            switch (size) {
4876
                            case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
4877
                            case 1: gen_swap_half(cpu_T[0]); break;
4878
                            default: abort();
4879
                            }
4880
                            NEON_SET_REG(T0, rd, pass * 2);
4881
                        }
4882
                    }
4883
                    break;
4884
                case 4: case 5: /* VPADDL */
4885
                case 12: case 13: /* VPADAL */
4886
                    if (size < 2)
4887
                        goto elementwise;
4888
                    if (size == 3)
4889
                        return 1;
4890
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4891
                        NEON_GET_REG(T0, rm, pass * 2);
4892
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4893
                        if (op & 1)
4894
                            gen_op_neon_paddl_u32();
4895
                        else
4896
                            gen_op_neon_paddl_s32();
4897
                        if (op >= 12) {
4898
                            /* Accumulate.  */
4899
                            gen_neon_movl_scratch_T0(0);
4900
                            gen_neon_movl_scratch_T1(1);
4901

    
4902
                            NEON_GET_REG(T0, rd, pass * 2);
4903
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4904
                            gen_op_neon_addl_u64();
4905
                        }
4906
                        NEON_SET_REG(T0, rd, pass * 2);
4907
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4908
                    }
4909
                    break;
4910
                case 33: /* VTRN */
4911
                    if (size == 2) {
4912
                        for (n = 0; n < (q ? 4 : 2); n += 2) {
4913
                            NEON_GET_REG(T0, rm, n);
4914
                            NEON_GET_REG(T1, rd, n + 1);
4915
                            NEON_SET_REG(T1, rm, n);
4916
                            NEON_SET_REG(T0, rd, n + 1);
4917
                        }
4918
                    } else {
4919
                        goto elementwise;
4920
                    }
4921
                    break;
4922
                case 34: /* VUZP */
4923
                    /* Reg  Before       After
4924
                       Rd   A3 A2 A1 A0  B2 B0 A2 A0
4925
                       Rm   B3 B2 B1 B0  B3 B1 A3 A1
4926
                     */
4927
                    if (size == 3)
4928
                        return 1;
4929
                    gen_neon_unzip(rd, q, 0, size);
4930
                    gen_neon_unzip(rm, q, 4, size);
4931
                    if (q) {
4932
                        static int unzip_order_q[8] =
4933
                            {0, 2, 4, 6, 1, 3, 5, 7};
4934
                        for (n = 0; n < 8; n++) {
4935
                            int reg = (n < 4) ? rd : rm;
4936
                            gen_neon_movl_T0_scratch(unzip_order_q[n]);
4937
                            NEON_SET_REG(T0, reg, n % 4);
4938
                        }
4939
                    } else {
4940
                        static int unzip_order[4] =
4941
                            {0, 4, 1, 5};
4942
                        for (n = 0; n < 4; n++) {
4943
                            int reg = (n < 2) ? rd : rm;
4944
                            gen_neon_movl_T0_scratch(unzip_order[n]);
4945
                            NEON_SET_REG(T0, reg, n % 2);
4946
                        }
4947
                    }
4948
                    break;
4949
                case 35: /* VZIP */
4950
                    /* Reg  Before       After
4951
                       Rd   A3 A2 A1 A0  B1 A1 B0 A0
4952
                       Rm   B3 B2 B1 B0  B3 A3 B2 A2
4953
                     */
4954
                    if (size == 3)
4955
                        return 1;
4956
                    count = (q ? 4 : 2);
4957
                    for (n = 0; n < count; n++) {
4958
                        NEON_GET_REG(T0, rd, n);
4959
                        NEON_GET_REG(T1, rd, n);
4960
                        switch (size) {
4961
                        case 0: gen_op_neon_zip_u8(); break;
4962
                        case 1: gen_op_neon_zip_u16(); break;
4963
                        case 2: /* no-op */; break;
4964
                        default: abort();
4965
                        }
4966
                        gen_neon_movl_scratch_T0(n * 2);
4967
                        gen_neon_movl_scratch_T1(n * 2 + 1);
4968
                    }
4969
                    for (n = 0; n < count * 2; n++) {
4970
                        int reg = (n < count) ? rd : rm;
4971
                        gen_neon_movl_T0_scratch(n);
4972
                        NEON_SET_REG(T0, reg, n % count);
4973
                    }
4974
                    break;
4975
                case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
4976
                    for (pass = 0; pass < 2; pass++) {
4977
                        if (rd == rm + 1) {
4978
                            n = 1 - pass;
4979
                        } else {
4980
                            n = pass;
4981
                        }
4982
                        NEON_GET_REG(T0, rm, n * 2);
4983
                        NEON_GET_REG(T1, rm, n * 2 + 1);
4984
                        if (op == 36 && q == 0) {
4985
                            switch (size) {
4986
                            case 0: gen_op_neon_narrow_u8(); break;
4987
                            case 1: gen_op_neon_narrow_u16(); break;
4988
                            case 2: /* no-op */ break;
4989
                            default: return 1;
4990
                            }
4991
                        } else if (q) {
4992
                            switch (size) {
4993
                            case 0: gen_op_neon_narrow_sat_u8(); break;
4994
                            case 1: gen_op_neon_narrow_sat_u16(); break;
4995
                            case 2: gen_op_neon_narrow_sat_u32(); break;
4996
                            default: return 1;
4997
                            }
4998
                        } else {
4999
                            switch (size) {
5000
                            case 0: gen_op_neon_narrow_sat_s8(); break;
5001
                            case 1: gen_op_neon_narrow_sat_s16(); break;
5002
                            case 2: gen_op_neon_narrow_sat_s32(); break;
5003
                            default: return 1;
5004
                            }
5005
                        }
5006
                        NEON_SET_REG(T0, rd, n);
5007
                    }
5008
                    break;
5009
                case 38: /* VSHLL */
5010
                    if (q)
5011
                        return 1;
5012
                    if (rm == rd) {
5013
                        NEON_GET_REG(T2, rm, 1);
5014
                    }
5015
                    for (pass = 0; pass < 2; pass++) {
5016
                        if (pass == 1 && rm == rd) {
5017
                            gen_op_movl_T0_T2();
5018
                        } else {
5019
                            NEON_GET_REG(T0, rm, pass);
5020
                        }
5021
                        switch (size) {
5022
                        case 0: gen_op_neon_widen_high_u8(); break;
5023
                        case 1: gen_op_neon_widen_high_u16(); break;
5024
                        case 2:
5025
                            gen_op_movl_T1_T0();
5026
                            gen_op_movl_T0_im(0);
5027
                            break;
5028
                        default: return 1;
5029
                        }
5030
                        NEON_SET_REG(T0, rd, pass * 2);
5031
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
5032
                    }
5033
                    break;
5034
                default:
5035
                elementwise:
5036
                    for (pass = 0; pass < (q ? 4 : 2); pass++) {
5037
                        if (op == 30 || op == 31 || op >= 58) {
5038
                            tcg_gen_ld_f32(cpu_F0s, cpu_env,
5039
                                           neon_reg_offset(rm, pass));
5040
                        } else {
5041
                            NEON_GET_REG(T0, rm, pass);
5042
                        }
5043
                        switch (op) {
5044
                        case 1: /* VREV32 */
5045
                            switch (size) {
5046
                            case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
5047
                            case 1: gen_swap_half(cpu_T[0]); break;
5048
                            default: return 1;
5049
                            }
5050
                            break;
5051
                        case 2: /* VREV16 */
5052
                            if (size != 0)
5053
                                return 1;
5054
                            gen_rev16(cpu_T[0]);
5055
                            break;
5056
                        case 4: case 5: /* VPADDL */
5057
                        case 12: case 13: /* VPADAL */
5058
                            switch ((size << 1) | (op & 1)) {
5059
                            case 0: gen_op_neon_paddl_s8(); break;
5060
                            case 1: gen_op_neon_paddl_u8(); break;
5061
                            case 2: gen_op_neon_paddl_s16(); break;
5062
                            case 3: gen_op_neon_paddl_u16(); break;
5063
                            default: abort();
5064
                            }
5065
                            if (op >= 12) {
5066
                                /* Accumulate */
5067
                                NEON_GET_REG(T1, rd, pass);
5068
                                switch (size) {
5069
                                case 0: gen_op_neon_add_u16(); break;
5070
                                case 1: gen_op_addl_T0_T1(); break;
5071
                                default: abort();
5072
                                }
5073
                            }
5074
                            break;
5075
                        case 8: /* CLS */
5076
                            switch (size) {
5077
                            case 0: gen_op_neon_cls_s8(); break;
5078
                            case 1: gen_op_neon_cls_s16(); break;
5079
                            case 2: gen_op_neon_cls_s32(); break;
5080
                            default: return 1;
5081
                            }
5082
                            break;
5083
                        case 9: /* CLZ */
5084
                            switch (size) {
5085
                            case 0: gen_op_neon_clz_u8(); break;
5086
                            case 1: gen_op_neon_clz_u16(); break;
5087
                            case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
5088
                            default: return 1;
5089
                            }
5090
                            break;
5091
                        case 10: /* CNT */
5092
                            if (size != 0)
5093
                                return 1;
5094
                            gen_op_neon_cnt_u8();
5095
                            break;
5096
                        case 11: /* VNOT */
5097
                            if (size != 0)
5098
                                return 1;
5099
                            gen_op_notl_T0();
5100
                            break;
5101
                        case 14: /* VQABS */
5102
                            switch (size) {
5103
                            case 0: gen_op_neon_qabs_s8(); break;
5104
                            case 1: gen_op_neon_qabs_s16(); break;
5105
                            case 2: gen_op_neon_qabs_s32(); break;
5106
                            default: return 1;
5107
                            }
5108
                            break;
5109
                        case 15: /* VQNEG */
5110
                            switch (size) {
5111
                            case 0: gen_op_neon_qneg_s8(); break;
5112
                            case 1: gen_op_neon_qneg_s16(); break;
5113
                            case 2: gen_op_neon_qneg_s32(); break;
5114
                            default: return 1;
5115
                            }
5116
                            break;
5117
                        case 16: case 19: /* VCGT #0, VCLE #0 */
5118
                            gen_op_movl_T1_im(0);
5119
                            switch(size) {
5120
                            case 0: gen_op_neon_cgt_s8(); break;
5121
                            case 1: gen_op_neon_cgt_s16(); break;
5122
                            case 2: gen_op_neon_cgt_s32(); break;
5123
                            default: return 1;
5124
                            }
5125
                            if (op == 19)
5126
                                gen_op_notl_T0();
5127
                            break;
5128
                        case 17: case 20: /* VCGE #0, VCLT #0 */
5129
                            gen_op_movl_T1_im(0);
5130
                            switch(size) {
5131
                            case 0: gen_op_neon_cge_s8(); break;
5132
                            case 1: gen_op_neon_cge_s16(); break;
5133
                            case 2: gen_op_neon_cge_s32(); break;
5134
                            default: return 1;
5135
                            }
5136
                            if (op == 20)
5137
                                gen_op_notl_T0();
5138
                            break;
5139
                        case 18: /* VCEQ #0 */
5140
                            gen_op_movl_T1_im(0);
5141
                            switch(size) {
5142
                            case 0: gen_op_neon_ceq_u8(); break;
5143
                            case 1: gen_op_neon_ceq_u16(); break;
5144
                            case 2: gen_op_neon_ceq_u32(); break;
5145
                            default: return 1;
5146
                            }
5147
                            break;
5148
                        case 22: /* VABS */
5149
                            switch(size) {
5150
                            case 0: gen_op_neon_abs_s8(); break;
5151
                            case 1: gen_op_neon_abs_s16(); break;
5152
                            case 2: gen_op_neon_abs_s32(); break;
5153
                            default: return 1;
5154
                            }
5155
                            break;
5156
                        case 23: /* VNEG */
5157
                            gen_op_movl_T1_im(0);
5158
                            switch(size) {
5159
                            case 0: gen_op_neon_rsb_u8(); break;
5160
                            case 1: gen_op_neon_rsb_u16(); break;
5161
                            case 2: gen_op_rsbl_T0_T1(); break;
5162
                            default: return 1;
5163
                            }
5164
                            break;
5165
                        case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5166
                            gen_op_movl_T1_im(0);
5167
                            gen_op_neon_cgt_f32();
5168
                            if (op == 27)
5169
                                gen_op_notl_T0();
5170
                            break;
5171
                        case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5172
                            gen_op_movl_T1_im(0);
5173
                            gen_op_neon_cge_f32();
5174
                            if (op == 28)
5175
                                gen_op_notl_T0();
5176
                            break;
5177
                        case 26: /* Float VCEQ #0 */
5178
                            gen_op_movl_T1_im(0);
5179
                            gen_op_neon_ceq_f32();
5180
                            break;
5181
                        case 30: /* Float VABS */
5182
                            gen_vfp_abs(0);
5183
                            break;
5184
                        case 31: /* Float VNEG */
5185
                            gen_vfp_neg(0);
5186
                            break;
5187
                        case 32: /* VSWP */
5188
                            NEON_GET_REG(T1, rd, pass);
5189
                            NEON_SET_REG(T1, rm, pass);
5190
                            break;
5191
                        case 33: /* VTRN */
5192
                            NEON_GET_REG(T1, rd, pass);
5193
                            switch (size) {
5194
                            case 0: gen_op_neon_trn_u8(); break;
5195
                            case 1: gen_op_neon_trn_u16(); break;
5196
                            case 2: abort();
5197
                            default: return 1;
5198
                            }
5199
                            NEON_SET_REG(T1, rm, pass);
5200
                            break;
5201
                        case 56: /* Integer VRECPE */
5202
                            gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env);
5203
                            break;
5204
                        case 57: /* Integer VRSQRTE */
5205
                            gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env);
5206
                            break;
5207
                        case 58: /* Float VRECPE */
5208
                            gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5209
                            break;
5210
                        case 59: /* Float VRSQRTE */
5211
                            gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5212
                            break;
5213
                        case 60: /* VCVT.F32.S32 */
5214
                            gen_vfp_tosiz(0);
5215
                            break;
5216
                        case 61: /* VCVT.F32.U32 */
5217
                            gen_vfp_touiz(0);
5218
                            break;
5219
                        case 62: /* VCVT.S32.F32 */
5220
                            gen_vfp_sito(0);
5221
                            break;
5222
                        case 63: /* VCVT.U32.F32 */
5223
                            gen_vfp_uito(0);
5224
                            break;
5225
                        default:
5226
                            /* Reserved: 21, 29, 39-56 */
5227
                            return 1;
5228
                        }
5229
                        if (op == 30 || op == 31 || op >= 58) {
5230
                            tcg_gen_st_f32(cpu_F0s, cpu_env,
5231
                                           neon_reg_offset(rd, pass));
5232
                        } else {
5233
                            NEON_SET_REG(T0, rd, pass);
5234
                        }
5235
                    }
5236
                    break;
5237
                }
5238
            } else if ((insn & (1 << 10)) == 0) {
5239
                /* VTBL, VTBX.  */
5240
                n = (insn >> 5) & 0x18;
5241
                NEON_GET_REG(T1, rm, 0);
5242
                if (insn & (1 << 6)) {
5243
                    NEON_GET_REG(T0, rd, 0);
5244
                } else {
5245
                    gen_op_movl_T0_im(0);
5246
                }
5247
                gen_op_neon_tbl(rn, n);
5248
                gen_op_movl_T2_T0();
5249
                NEON_GET_REG(T1, rm, 1);
5250
                if (insn & (1 << 6)) {
5251
                    NEON_GET_REG(T0, rd, 0);
5252
                } else {
5253
                    gen_op_movl_T0_im(0);
5254
                }
5255
                gen_op_neon_tbl(rn, n);
5256
                NEON_SET_REG(T2, rd, 0);
5257
                NEON_SET_REG(T0, rd, 1);
5258
            } else if ((insn & 0x380) == 0) {
5259
                /* VDUP */
5260
                if (insn & (1 << 19)) {
5261
                    NEON_SET_REG(T0, rm, 1);
5262
                } else {
5263
                    NEON_SET_REG(T0, rm, 0);
5264
                }
5265
                if (insn & (1 << 16)) {
5266
                    gen_op_neon_dup_u8(((insn >> 17) & 3) * 8);
5267
                } else if (insn & (1 << 17)) {
5268
                    if ((insn >> 18) & 1)
5269
                        gen_op_neon_dup_high16();
5270
                    else
5271
                        gen_op_neon_dup_low16();
5272
                }
5273
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
5274
                    NEON_SET_REG(T0, rd, pass);
5275
                }
5276
            } else {
5277
                return 1;
5278
            }
5279
        }
5280
    }
5281
    return 0;
5282
}
5283

    
5284
static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5285
{
5286
    int cpnum;
5287

    
5288
    cpnum = (insn >> 8) & 0xf;
5289
    if (arm_feature(env, ARM_FEATURE_XSCALE)
5290
            && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5291
        return 1;
5292

    
5293
    switch (cpnum) {
5294
      case 0:
5295
      case 1:
5296
        if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5297
            return disas_iwmmxt_insn(env, s, insn);
5298
        } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5299
            return disas_dsp_insn(env, s, insn);
5300
        }
5301
        return 1;
5302
    case 10:
5303
    case 11:
5304
        return disas_vfp_insn (env, s, insn);
5305
    case 15:
5306
        return disas_cp15_insn (env, s, insn);
5307
    default:
5308
        /* Unknown coprocessor.  See if the board has hooked it.  */
5309
        return disas_cp_insn (env, s, insn);
5310
    }
5311
}
5312

    
5313

    
5314
/* Store a 64-bit value to a register pair.  Clobbers val.  */
5315
static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv val)
5316
{
5317
    TCGv tmp;
5318
    tmp = new_tmp();
5319
    tcg_gen_trunc_i64_i32(tmp, val);
5320
    store_reg(s, rlow, tmp);
5321
    tmp = new_tmp();
5322
    tcg_gen_shri_i64(val, val, 32);
5323
    tcg_gen_trunc_i64_i32(tmp, val);
5324
    store_reg(s, rhigh, tmp);
5325
}
5326

    
5327
/* load a 32-bit value from a register and perform a 64-bit accumulate.  */
5328
static void gen_addq_lo(DisasContext *s, TCGv val, int rlow)
5329
{
5330
    TCGv tmp;
5331
    TCGv tmp2;
5332

    
5333
    /* Load 64-bit value rd:rn.  */
5334
    tmp = tcg_temp_new(TCG_TYPE_I64);
5335
    tmp2 = load_reg(s, rlow);
5336
    tcg_gen_extu_i32_i64(tmp, tmp2);
5337
    dead_tmp(tmp2);
5338
    tcg_gen_add_i64(val, val, tmp);
5339
}
5340

    
5341
/* load and add a 64-bit value from a register pair.  */
5342
static void gen_addq(DisasContext *s, TCGv val, int rlow, int rhigh)
5343
{
5344
    TCGv tmp;
5345
    TCGv tmp2;
5346

    
5347
    /* Load 64-bit value rd:rn.  */
5348
    tmp = tcg_temp_new(TCG_TYPE_I64);
5349
    tmp2 = load_reg(s, rhigh);
5350
    tcg_gen_extu_i32_i64(tmp, tmp2);
5351
    dead_tmp(tmp2);
5352
    tcg_gen_shli_i64(tmp, tmp, 32);
5353
    tcg_gen_add_i64(val, val, tmp);
5354

    
5355
    tmp2 = load_reg(s, rlow);
5356
    tcg_gen_extu_i32_i64(tmp, tmp2);
5357
    dead_tmp(tmp2);
5358
    tcg_gen_add_i64(val, val, tmp);
5359
}
5360

    
5361
/* Set N and Z flags from a 64-bit value.  */
5362
static void gen_logicq_cc(TCGv val)
5363
{
5364
    TCGv tmp = new_tmp();
5365
    gen_helper_logicq_cc(tmp, val);
5366
    store_cpu_field(tmp, NZF);
5367
}
5368

    
5369
static void disas_arm_insn(CPUState * env, DisasContext *s)
5370
{
5371
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5372
    TCGv tmp;
5373
    TCGv tmp2;
5374
    TCGv tmp3;
5375
    TCGv addr;
5376

    
5377
    insn = ldl_code(s->pc);
5378
    s->pc += 4;
5379

    
5380
    /* M variants do not implement ARM mode.  */
5381
    if (IS_M(env))
5382
        goto illegal_op;
5383
    cond = insn >> 28;
5384
    if (cond == 0xf){
5385
        /* Unconditional instructions.  */
5386
        if (((insn >> 25) & 7) == 1) {
5387
            /* NEON Data processing.  */
5388
            if (!arm_feature(env, ARM_FEATURE_NEON))
5389
                goto illegal_op;
5390

    
5391
            if (disas_neon_data_insn(env, s, insn))
5392
                goto illegal_op;
5393
            return;
5394
        }
5395
        if ((insn & 0x0f100000) == 0x04000000) {
5396
            /* NEON load/store.  */
5397
            if (!arm_feature(env, ARM_FEATURE_NEON))
5398
                goto illegal_op;
5399

    
5400
            if (disas_neon_ls_insn(env, s, insn))
5401
                goto illegal_op;
5402
            return;
5403
        }
5404
        if ((insn & 0x0d70f000) == 0x0550f000)
5405
            return; /* PLD */
5406
        else if ((insn & 0x0ffffdff) == 0x01010000) {
5407
            ARCH(6);
5408
            /* setend */
5409
            if (insn & (1 << 9)) {
5410
                /* BE8 mode not implemented.  */
5411
                goto illegal_op;
5412
            }
5413
            return;
5414
        } else if ((insn & 0x0fffff00) == 0x057ff000) {
5415
            switch ((insn >> 4) & 0xf) {
5416
            case 1: /* clrex */
5417
                ARCH(6K);
5418
                gen_op_clrex();
5419
                return;
5420
            case 4: /* dsb */
5421
            case 5: /* dmb */
5422
            case 6: /* isb */
5423
                ARCH(7);
5424
                /* We don't emulate caches so these are a no-op.  */
5425
                return;
5426
            default:
5427
                goto illegal_op;
5428
            }
5429
        } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5430
            /* srs */
5431
            uint32_t offset;
5432
            if (IS_USER(s))
5433
                goto illegal_op;
5434
            ARCH(6);
5435
            op1 = (insn & 0x1f);
5436
            if (op1 == (env->uncached_cpsr & CPSR_M)) {
5437
                addr = load_reg(s, 13);
5438
            } else {
5439
                addr = new_tmp();
5440
                gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5441
            }
5442
            i = (insn >> 23) & 3;
5443
            switch (i) {
5444
            case 0: offset = -4; break; /* DA */
5445
            case 1: offset = -8; break; /* DB */
5446
            case 2: offset = 0; break; /* IA */
5447
            case 3: offset = 4; break; /* IB */
5448
            default: abort();
5449
            }
5450
            if (offset)
5451
                tcg_gen_addi_i32(addr, addr, offset);
5452
            tmp = load_reg(s, 14);
5453
            gen_st32(tmp, addr, 0);
5454
            tmp = new_tmp();
5455
            gen_helper_cpsr_read(tmp);
5456
            tcg_gen_addi_i32(addr, addr, 4);
5457
            gen_st32(tmp, addr, 0);
5458
            if (insn & (1 << 21)) {
5459
                /* Base writeback.  */
5460
                switch (i) {
5461
                case 0: offset = -8; break;
5462
                case 1: offset = -4; break;
5463
                case 2: offset = 4; break;
5464
                case 3: offset = 0; break;
5465
                default: abort();
5466
                }
5467
                if (offset)
5468
                    tcg_gen_addi_i32(addr, tmp, offset);
5469
                if (op1 == (env->uncached_cpsr & CPSR_M)) {
5470
                    gen_movl_reg_T1(s, 13);
5471
                } else {
5472
                    gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]);
5473
                }
5474
            } else {
5475
                dead_tmp(addr);
5476
            }
5477
        } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5478
            /* rfe */
5479
            uint32_t offset;
5480
            if (IS_USER(s))
5481
                goto illegal_op;
5482
            ARCH(6);
5483
            rn = (insn >> 16) & 0xf;
5484
            addr = load_reg(s, rn);
5485
            i = (insn >> 23) & 3;
5486
            switch (i) {
5487
            case 0: offset = -4; break; /* DA */
5488
            case 1: offset = -8; break; /* DB */
5489
            case 2: offset = 0; break; /* IA */
5490
            case 3: offset = 4; break; /* IB */
5491
            default: abort();
5492
            }
5493
            if (offset)
5494
                tcg_gen_addi_i32(addr, addr, offset);
5495
            /* Load PC into tmp and CPSR into tmp2.  */
5496
            tmp = gen_ld32(addr, 0);
5497
            tcg_gen_addi_i32(addr, addr, 4);
5498
            tmp2 = gen_ld32(addr, 0);
5499
            if (insn & (1 << 21)) {
5500
                /* Base writeback.  */
5501
                switch (i) {
5502
                case 0: offset = -8; break;
5503
                case 1: offset = -4; break;
5504
                case 2: offset = 4; break;
5505
                case 3: offset = 0; break;
5506
                default: abort();
5507
                }
5508
                if (offset)
5509
                    tcg_gen_addi_i32(addr, addr, offset);
5510
                store_reg(s, rn, addr);
5511
            } else {
5512
                dead_tmp(addr);
5513
            }
5514
            gen_rfe(s, tmp, tmp2);
5515
        } else if ((insn & 0x0e000000) == 0x0a000000) {
5516
            /* branch link and change to thumb (blx <offset>) */
5517
            int32_t offset;
5518

    
5519
            val = (uint32_t)s->pc;
5520
            tmp = new_tmp();
5521
            tcg_gen_movi_i32(tmp, val);
5522
            store_reg(s, 14, tmp);
5523
            /* Sign-extend the 24-bit offset */
5524
            offset = (((int32_t)insn) << 8) >> 8;
5525
            /* offset * 4 + bit24 * 2 + (thumb bit) */
5526
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
5527
            /* pipeline offset */
5528
            val += 4;
5529
            gen_bx_im(s, val);
5530
            return;
5531
        } else if ((insn & 0x0e000f00) == 0x0c000100) {
5532
            if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5533
                /* iWMMXt register transfer.  */
5534
                if (env->cp15.c15_cpar & (1 << 1))
5535
                    if (!disas_iwmmxt_insn(env, s, insn))
5536
                        return;
5537
            }
5538
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
5539
            /* Coprocessor double register transfer.  */
5540
        } else if ((insn & 0x0f000010) == 0x0e000010) {
5541
            /* Additional coprocessor register transfer.  */
5542
        } else if ((insn & 0x0ff10010) == 0x01000000) {
5543
            uint32_t mask;
5544
            uint32_t val;
5545
            /* cps (privileged) */
5546
            if (IS_USER(s))
5547
                return;
5548
            mask = val = 0;
5549
            if (insn & (1 << 19)) {
5550
                if (insn & (1 << 8))
5551
                    mask |= CPSR_A;
5552
                if (insn & (1 << 7))
5553
                    mask |= CPSR_I;
5554
                if (insn & (1 << 6))
5555
                    mask |= CPSR_F;
5556
                if (insn & (1 << 18))
5557
                    val |= mask;
5558
            }
5559
            if (insn & (1 << 14)) {
5560
                mask |= CPSR_M;
5561
                val |= (insn & 0x1f);
5562
            }
5563
            if (mask) {
5564
                gen_op_movl_T0_im(val);
5565
                gen_set_psr_T0(s, mask, 0);
5566
            }
5567
            return;
5568
        }
5569
        goto illegal_op;
5570
    }
5571
    if (cond != 0xe) {
5572
        /* if not always execute, we generate a conditional jump to
5573
           next instruction */
5574
        s->condlabel = gen_new_label();
5575
        gen_test_cc(cond ^ 1, s->condlabel);
5576
        s->condjmp = 1;
5577
    }
5578
    if ((insn & 0x0f900000) == 0x03000000) {
5579
        if ((insn & (1 << 21)) == 0) {
5580
            ARCH(6T2);
5581
            rd = (insn >> 12) & 0xf;
5582
            val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5583
            if ((insn & (1 << 22)) == 0) {
5584
                /* MOVW */
5585
                tmp = new_tmp();
5586
                tcg_gen_movi_i32(tmp, val);
5587
            } else {
5588
                /* MOVT */
5589
                tmp = load_reg(s, rd);
5590
                tcg_gen_andi_i32(tmp, tmp, 0xffff);
5591
                tcg_gen_ori_i32(tmp, tmp, val << 16);
5592
            }
5593
            store_reg(s, rd, tmp);
5594
        } else {
5595
            if (((insn >> 12) & 0xf) != 0xf)
5596
                goto illegal_op;
5597
            if (((insn >> 16) & 0xf) == 0) {
5598
                gen_nop_hint(s, insn & 0xff);
5599
            } else {
5600
                /* CPSR = immediate */
5601
                val = insn & 0xff;
5602
                shift = ((insn >> 8) & 0xf) * 2;
5603
                if (shift)
5604
                    val = (val >> shift) | (val << (32 - shift));
5605
                gen_op_movl_T0_im(val);
5606
                i = ((insn & (1 << 22)) != 0);
5607
                if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5608
                    goto illegal_op;
5609
            }
5610
        }
5611
    } else if ((insn & 0x0f900000) == 0x01000000
5612
               && (insn & 0x00000090) != 0x00000090) {
5613
        /* miscellaneous instructions */
5614
        op1 = (insn >> 21) & 3;
5615
        sh = (insn >> 4) & 0xf;
5616
        rm = insn & 0xf;
5617
        switch (sh) {
5618
        case 0x0: /* move program status register */
5619
            if (op1 & 1) {
5620
                /* PSR = reg */
5621
                gen_movl_T0_reg(s, rm);
5622
                i = ((op1 & 2) != 0);
5623
                if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5624
                    goto illegal_op;
5625
            } else {
5626
                /* reg = PSR */
5627
                rd = (insn >> 12) & 0xf;
5628
                if (op1 & 2) {
5629
                    if (IS_USER(s))
5630
                        goto illegal_op;
5631
                    tmp = load_cpu_field(spsr);
5632
                } else {
5633
                    tmp = new_tmp();
5634
                    gen_helper_cpsr_read(tmp);
5635
                }
5636
                store_reg(s, rd, tmp);
5637
            }
5638
            break;
5639
        case 0x1:
5640
            if (op1 == 1) {
5641
                /* branch/exchange thumb (bx).  */
5642
                tmp = load_reg(s, rm);
5643
                gen_bx(s, tmp);
5644
            } else if (op1 == 3) {
5645
                /* clz */
5646
                rd = (insn >> 12) & 0xf;
5647
                tmp = load_reg(s, rm);
5648
                gen_helper_clz(tmp, tmp);
5649
                store_reg(s, rd, tmp);
5650
            } else {
5651
                goto illegal_op;
5652
            }
5653
            break;
5654
        case 0x2:
5655
            if (op1 == 1) {
5656
                ARCH(5J); /* bxj */
5657
                /* Trivial implementation equivalent to bx.  */
5658
                tmp = load_reg(s, rm);
5659
                gen_bx(s, tmp);
5660
            } else {
5661
                goto illegal_op;
5662
            }
5663
            break;
5664
        case 0x3:
5665
            if (op1 != 1)
5666
              goto illegal_op;
5667

    
5668
            /* branch link/exchange thumb (blx) */
5669
            tmp = load_reg(s, rm);
5670
            tmp2 = new_tmp();
5671
            tcg_gen_movi_i32(tmp2, s->pc);
5672
            store_reg(s, 14, tmp2);
5673
            gen_bx(s, tmp);
5674
            break;
5675
        case 0x5: /* saturating add/subtract */
5676
            rd = (insn >> 12) & 0xf;
5677
            rn = (insn >> 16) & 0xf;
5678
            tmp = load_reg(s, rn);
5679
            tmp2 = load_reg(s, rn);
5680
            if (op1 & 2)
5681
                gen_helper_double_saturate(tmp2, tmp2);
5682
            if (op1 & 1)
5683
                gen_helper_sub_saturate(tmp, tmp, tmp2);
5684
            else
5685
                gen_helper_add_saturate(tmp, tmp, tmp2);
5686
            dead_tmp(tmp2);
5687
            store_reg(s, rd, tmp);
5688
            break;
5689
        case 7: /* bkpt */
5690
            gen_set_condexec(s);
5691
            gen_set_pc_im(s->pc - 4);
5692
            gen_exception(EXCP_BKPT);
5693
            s->is_jmp = DISAS_JUMP;
5694
            break;
5695
        case 0x8: /* signed multiply */
5696
        case 0xa:
5697
        case 0xc:
5698
        case 0xe:
5699
            rs = (insn >> 8) & 0xf;
5700
            rn = (insn >> 12) & 0xf;
5701
            rd = (insn >> 16) & 0xf;
5702
            if (op1 == 1) {
5703
                /* (32 * 16) >> 16 */
5704
                tmp = load_reg(s, rm);
5705
                tmp2 = load_reg(s, rs);
5706
                if (sh & 4)
5707
                    tcg_gen_sari_i32(tmp2, tmp2, 16);
5708
                else
5709
                    gen_sxth(tmp2);
5710
                tmp2 = gen_muls_i64_i32(tmp, tmp2);
5711
                tcg_gen_shri_i64(tmp2, tmp2, 16);
5712
                tmp = new_tmp();
5713
                tcg_gen_trunc_i64_i32(tmp, tmp2);
5714
                if ((sh & 2) == 0) {
5715
                    tmp2 = load_reg(s, rn);
5716
                    gen_helper_add_setq(tmp, tmp, tmp2);
5717
                    dead_tmp(tmp2);
5718
                }
5719
                store_reg(s, rd, tmp);
5720
            } else {
5721
                /* 16 * 16 */
5722
                tmp = load_reg(s, rm);
5723
                tmp2 = load_reg(s, rs);
5724
                gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
5725
                dead_tmp(tmp2);
5726
                if (op1 == 2) {
5727
                    tmp = tcg_temp_new(TCG_TYPE_I64);
5728
                    tcg_gen_ext_i32_i64(tmp, cpu_T[0]);
5729
                    gen_addq(s, tmp, rn, rd);
5730
                    gen_storeq_reg(s, rn, rd, tmp);
5731
                } else {
5732
                    if (op1 == 0) {
5733
                        tmp2 = load_reg(s, rn);
5734
                        gen_helper_add_setq(tmp, tmp, tmp2);
5735
                        dead_tmp(tmp2);
5736
                    }
5737
                    store_reg(s, rd, tmp);
5738
                }
5739
            }
5740
            break;
5741
        default:
5742
            goto illegal_op;
5743
        }
5744
    } else if (((insn & 0x0e000000) == 0 &&
5745
                (insn & 0x00000090) != 0x90) ||
5746
               ((insn & 0x0e000000) == (1 << 25))) {
5747
        int set_cc, logic_cc, shiftop;
5748

    
5749
        op1 = (insn >> 21) & 0xf;
5750
        set_cc = (insn >> 20) & 1;
5751
        logic_cc = table_logic_cc[op1] & set_cc;
5752

    
5753
        /* data processing instruction */
5754
        if (insn & (1 << 25)) {
5755
            /* immediate operand */
5756
            val = insn & 0xff;
5757
            shift = ((insn >> 8) & 0xf) * 2;
5758
            if (shift)
5759
                val = (val >> shift) | (val << (32 - shift));
5760
            gen_op_movl_T1_im(val);
5761
            if (logic_cc && shift)
5762
                gen_set_CF_bit31(cpu_T[1]);
5763
        } else {
5764
            /* register */
5765
            rm = (insn) & 0xf;
5766
            gen_movl_T1_reg(s, rm);
5767
            shiftop = (insn >> 5) & 3;
5768
            if (!(insn & (1 << 4))) {
5769
                shift = (insn >> 7) & 0x1f;
5770
                gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
5771
            } else {
5772
                rs = (insn >> 8) & 0xf;
5773
                gen_movl_T0_reg(s, rs);
5774
                if (logic_cc) {
5775
                    gen_shift_T1_T0_cc[shiftop]();
5776
                } else {
5777
                    gen_shift_T1_T0[shiftop]();
5778
                }
5779
            }
5780
        }
5781
        if (op1 != 0x0f && op1 != 0x0d) {
5782
            rn = (insn >> 16) & 0xf;
5783
            gen_movl_T0_reg(s, rn);
5784
        }
5785
        rd = (insn >> 12) & 0xf;
5786
        switch(op1) {
5787
        case 0x00:
5788
            gen_op_andl_T0_T1();
5789
            gen_movl_reg_T0(s, rd);
5790
            if (logic_cc)
5791
                gen_op_logic_T0_cc();
5792
            break;
5793
        case 0x01:
5794
            gen_op_xorl_T0_T1();
5795
            gen_movl_reg_T0(s, rd);
5796
            if (logic_cc)
5797
                gen_op_logic_T0_cc();
5798
            break;
5799
        case 0x02:
5800
            if (set_cc && rd == 15) {
5801
                /* SUBS r15, ... is used for exception return.  */
5802
                if (IS_USER(s))
5803
                    goto illegal_op;
5804
                gen_op_subl_T0_T1_cc();
5805
                gen_exception_return(s);
5806
            } else {
5807
                if (set_cc)
5808
                    gen_op_subl_T0_T1_cc();
5809
                else
5810
                    gen_op_subl_T0_T1();
5811
                gen_movl_reg_T0(s, rd);
5812
            }
5813
            break;
5814
        case 0x03:
5815
            if (set_cc)
5816
                gen_op_rsbl_T0_T1_cc();
5817
            else
5818
                gen_op_rsbl_T0_T1();
5819
            gen_movl_reg_T0(s, rd);
5820
            break;
5821
        case 0x04:
5822
            if (set_cc)
5823
                gen_op_addl_T0_T1_cc();
5824
            else
5825
                gen_op_addl_T0_T1();
5826
            gen_movl_reg_T0(s, rd);
5827
            break;
5828
        case 0x05:
5829
            if (set_cc)
5830
                gen_op_adcl_T0_T1_cc();
5831
            else
5832
                gen_adc_T0_T1();
5833
            gen_movl_reg_T0(s, rd);
5834
            break;
5835
        case 0x06:
5836
            if (set_cc)
5837
                gen_op_sbcl_T0_T1_cc();
5838
            else
5839
                gen_sbc_T0_T1();
5840
            gen_movl_reg_T0(s, rd);
5841
            break;
5842
        case 0x07:
5843
            if (set_cc)
5844
                gen_op_rscl_T0_T1_cc();
5845
            else
5846
                gen_rsc_T0_T1();
5847
            gen_movl_reg_T0(s, rd);
5848
            break;
5849
        case 0x08:
5850
            if (set_cc) {
5851
                gen_op_andl_T0_T1();
5852
                gen_op_logic_T0_cc();
5853
            }
5854
            break;
5855
        case 0x09:
5856
            if (set_cc) {
5857
                gen_op_xorl_T0_T1();
5858
                gen_op_logic_T0_cc();
5859
            }
5860
            break;
5861
        case 0x0a:
5862
            if (set_cc) {
5863
                gen_op_subl_T0_T1_cc();
5864
            }
5865
            break;
5866
        case 0x0b:
5867
            if (set_cc) {
5868
                gen_op_addl_T0_T1_cc();
5869
            }
5870
            break;
5871
        case 0x0c:
5872
            gen_op_orl_T0_T1();
5873
            gen_movl_reg_T0(s, rd);
5874
            if (logic_cc)
5875
                gen_op_logic_T0_cc();
5876
            break;
5877
        case 0x0d:
5878
            if (logic_cc && rd == 15) {
5879
                /* MOVS r15, ... is used for exception return.  */
5880
                if (IS_USER(s))
5881
                    goto illegal_op;
5882
                gen_op_movl_T0_T1();
5883
                gen_exception_return(s);
5884
            } else {
5885
                gen_movl_reg_T1(s, rd);
5886
                if (logic_cc)
5887
                    gen_op_logic_T1_cc();
5888
            }
5889
            break;
5890
        case 0x0e:
5891
            gen_op_bicl_T0_T1();
5892
            gen_movl_reg_T0(s, rd);
5893
            if (logic_cc)
5894
                gen_op_logic_T0_cc();
5895
            break;
5896
        default:
5897
        case 0x0f:
5898
            gen_op_notl_T1();
5899
            gen_movl_reg_T1(s, rd);
5900
            if (logic_cc)
5901
                gen_op_logic_T1_cc();
5902
            break;
5903
        }
5904
    } else {
5905
        /* other instructions */
5906
        op1 = (insn >> 24) & 0xf;
5907
        switch(op1) {
5908
        case 0x0:
5909
        case 0x1:
5910
            /* multiplies, extra load/stores */
5911
            sh = (insn >> 5) & 3;
5912
            if (sh == 0) {
5913
                if (op1 == 0x0) {
5914
                    rd = (insn >> 16) & 0xf;
5915
                    rn = (insn >> 12) & 0xf;
5916
                    rs = (insn >> 8) & 0xf;
5917
                    rm = (insn) & 0xf;
5918
                    op1 = (insn >> 20) & 0xf;
5919
                    switch (op1) {
5920
                    case 0: case 1: case 2: case 3: case 6:
5921
                        /* 32 bit mul */
5922
                        tmp = load_reg(s, rs);
5923
                        tmp2 = load_reg(s, rm);
5924
                        tcg_gen_mul_i32(tmp, tmp, tmp2);
5925
                        dead_tmp(tmp2);
5926
                        if (insn & (1 << 22)) {
5927
                            /* Subtract (mls) */
5928
                            ARCH(6T2);
5929
                            tmp2 = load_reg(s, rn);
5930
                            tcg_gen_sub_i32(tmp, tmp2, tmp);
5931
                            dead_tmp(tmp2);
5932
                        } else if (insn & (1 << 21)) {
5933
                            /* Add */
5934
                            tmp2 = load_reg(s, rn);
5935
                            tcg_gen_add_i32(tmp, tmp, tmp2);
5936
                            dead_tmp(tmp2);
5937
                        }
5938
                        if (insn & (1 << 20))
5939
                            gen_logic_CC(tmp);
5940
                        store_reg(s, rd, tmp);
5941
                        break;
5942
                    default:
5943
                        /* 64 bit mul */
5944
                        tmp = load_reg(s, rs);
5945
                        tmp2 = load_reg(s, rm);
5946
                        if (insn & (1 << 22))
5947
                            tmp = gen_muls_i64_i32(tmp, tmp2);
5948
                        else
5949
                            tmp = gen_mulu_i64_i32(tmp, tmp2);
5950
                        if (insn & (1 << 21)) /* mult accumulate */
5951
                            gen_addq(s, tmp, rn, rd);
5952
                        if (!(insn & (1 << 23))) { /* double accumulate */
5953
                            ARCH(6);
5954
                            gen_addq_lo(s, tmp, rn);
5955
                            gen_addq_lo(s, tmp, rd);
5956
                        }
5957
                        if (insn & (1 << 20))
5958
                            gen_logicq_cc(tmp);
5959
                        gen_storeq_reg(s, rn, rd, tmp);
5960
                        break;
5961
                    }
5962
                } else {
5963
                    rn = (insn >> 16) & 0xf;
5964
                    rd = (insn >> 12) & 0xf;
5965
                    if (insn & (1 << 23)) {
5966
                        /* load/store exclusive */
5967
                        gen_movl_T1_reg(s, rn);
5968
                        if (insn & (1 << 20)) {
5969
                            gen_ldst(ldlex, s);
5970
                        } else {
5971
                            rm = insn & 0xf;
5972
                            gen_movl_T0_reg(s, rm);
5973
                            gen_ldst(stlex, s);
5974
                        }
5975
                        gen_movl_reg_T0(s, rd);
5976
                    } else {
5977
                        /* SWP instruction */
5978
                        rm = (insn) & 0xf;
5979

    
5980
                        gen_movl_T0_reg(s, rm);
5981
                        gen_movl_T1_reg(s, rn);
5982
                        if (insn & (1 << 22)) {
5983
                            gen_ldst(swpb, s);
5984
                        } else {
5985
                            gen_ldst(swpl, s);
5986
                        }
5987
                        gen_movl_reg_T0(s, rd);
5988
                    }
5989
                }
5990
            } else {
5991
                int address_offset;
5992
                int load;
5993
                /* Misc load/store */
5994
                rn = (insn >> 16) & 0xf;
5995
                rd = (insn >> 12) & 0xf;
5996
                addr = load_reg(s, rn);
5997
                if (insn & (1 << 24))
5998
                    gen_add_datah_offset(s, insn, 0, addr);
5999
                address_offset = 0;
6000
                if (insn & (1 << 20)) {
6001
                    /* load */
6002
                    switch(sh) {
6003
                    case 1:
6004
                        tmp = gen_ld16u(addr, IS_USER(s));
6005
                        break;
6006
                    case 2:
6007
                        tmp = gen_ld8s(addr, IS_USER(s));
6008
                        break;
6009
                    default:
6010
                    case 3:
6011
                        tmp = gen_ld16s(addr, IS_USER(s));
6012
                        break;
6013
                    }
6014
                    load = 1;
6015
                } else if (sh & 2) {
6016
                    /* doubleword */
6017
                    if (sh & 1) {
6018
                        /* store */
6019
                        tmp = load_reg(s, rd);
6020
                        gen_st32(tmp, addr, IS_USER(s));
6021
                        tcg_gen_addi_i32(addr, addr, 4);
6022
                        tmp = load_reg(s, rd + 1);
6023
                        gen_st32(tmp, addr, IS_USER(s));
6024
                        load = 0;
6025
                    } else {
6026
                        /* load */
6027
                        tmp = gen_ld32(addr, IS_USER(s));
6028
                        store_reg(s, rd, tmp);
6029
                        tcg_gen_addi_i32(addr, addr, 4);
6030
                        tmp = gen_ld32(addr, IS_USER(s));
6031
                        rd++;
6032
                        load = 1;
6033
                    }
6034
                    address_offset = -4;
6035
                } else {
6036
                    /* store */
6037
                    tmp = load_reg(s, rd);
6038
                    gen_st16(tmp, addr, IS_USER(s));
6039
                    load = 0;
6040
                }
6041
                /* Perform base writeback before the loaded value to
6042
                   ensure correct behavior with overlapping index registers.
6043
                   ldrd with base writeback is is undefined if the
6044
                   destination and index registers overlap.  */
6045
                if (!(insn & (1 << 24))) {
6046
                    gen_add_datah_offset(s, insn, address_offset, addr);
6047
                    store_reg(s, rn, addr);
6048
                } else if (insn & (1 << 21)) {
6049
                    if (address_offset)
6050
                        tcg_gen_addi_i32(addr, addr, address_offset);
6051
                    store_reg(s, rn, addr);
6052
                } else {
6053
                    dead_tmp(addr);
6054
                }
6055
                if (load) {
6056
                    /* Complete the load.  */
6057
                    store_reg(s, rd, tmp);
6058
                }
6059
            }
6060
            break;
6061
        case 0x4:
6062
        case 0x5:
6063
            goto do_ldst;
6064
        case 0x6:
6065
        case 0x7:
6066
            if (insn & (1 << 4)) {
6067
                ARCH(6);
6068
                /* Armv6 Media instructions.  */
6069
                rm = insn & 0xf;
6070
                rn = (insn >> 16) & 0xf;
6071
                rd = (insn >> 12) & 0xf;
6072
                rs = (insn >> 8) & 0xf;
6073
                switch ((insn >> 23) & 3) {
6074
                case 0: /* Parallel add/subtract.  */
6075
                    op1 = (insn >> 20) & 7;
6076
                    tmp = load_reg(s, rn);
6077
                    tmp2 = load_reg(s, rm);
6078
                    sh = (insn >> 5) & 7;
6079
                    if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6080
                        goto illegal_op;
6081
                    gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6082
                    dead_tmp(tmp2);
6083
                    store_reg(s, rd, tmp);
6084
                    break;
6085
                case 1:
6086
                    if ((insn & 0x00700020) == 0) {
6087
                        /* Hafword pack.  */
6088
                        tmp = load_reg(s, rn);
6089
                        tmp2 = load_reg(s, rm);
6090
                        shift = (insn >> 7) & 0x1f;
6091
                        if (shift)
6092
                            tcg_gen_shli_i32(tmp2, tmp2, shift);
6093
                        if (insn & (1 << 6)) {
6094
                            /* pkhtb */
6095
                            tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6096
                            tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
6097
                        } else {
6098
                            /* pkhbt */
6099
                            tcg_gen_andi_i32(tmp, tmp, 0xffff);
6100
                            tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6101
                        }
6102
                        tcg_gen_or_i32(tmp, tmp, tmp2);
6103
                        store_reg(s, rd, tmp);
6104
                    } else if ((insn & 0x00200020) == 0x00200000) {
6105
                        /* [us]sat */
6106
                        tmp = load_reg(s, rm);
6107
                        shift = (insn >> 7) & 0x1f;
6108
                        if (insn & (1 << 6)) {
6109
                            if (shift == 0)
6110
                                shift = 31;
6111
                            tcg_gen_sari_i32(tmp, tmp, shift);
6112
                        } else {
6113
                            tcg_gen_shli_i32(tmp, tmp, shift);
6114
                        }
6115
                        sh = (insn >> 16) & 0x1f;
6116
                        if (sh != 0) {
6117
                            if (insn & (1 << 22))
6118
                                gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6119
                            else
6120
                                gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6121
                        }
6122
                        store_reg(s, rd, tmp);
6123
                    } else if ((insn & 0x00300fe0) == 0x00200f20) {
6124
                        /* [us]sat16 */
6125
                        tmp = load_reg(s, rm);
6126
                        sh = (insn >> 16) & 0x1f;
6127
                        if (sh != 0) {
6128
                            if (insn & (1 << 22))
6129
                                gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6130
                            else
6131
                                gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6132
                        }
6133
                        store_reg(s, rd, tmp);
6134
                    } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6135
                        /* Select bytes.  */
6136
                        tmp = load_reg(s, rn);
6137
                        tmp2 = load_reg(s, rm);
6138
                        tmp3 = new_tmp();
6139
                        tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6140
                        gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6141
                        dead_tmp(tmp3);
6142
                        dead_tmp(tmp2);
6143
                        store_reg(s, rd, tmp);
6144
                    } else if ((insn & 0x000003e0) == 0x00000060) {
6145
                        tmp = load_reg(s, rm);
6146
                        shift = (insn >> 10) & 3;
6147
                        /* ??? In many cases it's not neccessary to do a
6148
                           rotate, a shift is sufficient.  */
6149
                        if (shift != 0)
6150
                            tcg_gen_rori_i32(tmp, tmp, shift * 8);
6151
                        op1 = (insn >> 20) & 7;
6152
                        switch (op1) {
6153
                        case 0: gen_sxtb16(tmp);  break;
6154
                        case 2: gen_sxtb(tmp);    break;
6155
                        case 3: gen_sxth(tmp);    break;
6156
                        case 4: gen_uxtb16(tmp);  break;
6157
                        case 6: gen_uxtb(tmp);    break;
6158
                        case 7: gen_uxth(tmp);    break;
6159
                        default: goto illegal_op;
6160
                        }
6161
                        if (rn != 15) {
6162
                            tmp2 = load_reg(s, rn);
6163
                            if ((op1 & 3) == 0) {
6164
                                gen_add16(tmp, tmp2);
6165
                            } else {
6166
                                tcg_gen_add_i32(tmp, tmp, tmp2);
6167
                                dead_tmp(tmp2);
6168
                            }
6169
                        }
6170
                        store_reg(s, rd, tmp2);
6171
                    } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6172
                        /* rev */
6173
                        tmp = load_reg(s, rm);
6174
                        if (insn & (1 << 22)) {
6175
                            if (insn & (1 << 7)) {
6176
                                gen_revsh(tmp);
6177
                            } else {
6178
                                ARCH(6T2);
6179
                                gen_helper_rbit(tmp, tmp);
6180
                            }
6181
                        } else {
6182
                            if (insn & (1 << 7))
6183
                                gen_rev16(tmp);
6184
                            else
6185
                                tcg_gen_bswap_i32(tmp, tmp);
6186
                        }
6187
                        store_reg(s, rd, tmp);
6188
                    } else {
6189
                        goto illegal_op;
6190
                    }
6191
                    break;
6192
                case 2: /* Multiplies (Type 3).  */
6193
                    tmp = load_reg(s, rm);
6194
                    tmp2 = load_reg(s, rs);
6195
                    if (insn & (1 << 20)) {
6196
                        /* Signed multiply most significant [accumulate].  */
6197
                        tmp2 = gen_muls_i64_i32(tmp, tmp2);
6198
                        if (insn & (1 << 5))
6199
                            tcg_gen_addi_i64(tmp2, tmp2, 0x80000000u);
6200
                        tcg_gen_shri_i64(tmp2, tmp2, 32);
6201
                        tmp = new_tmp();
6202
                        tcg_gen_trunc_i64_i32(tmp, tmp2);
6203
                        if (rn != 15) {
6204
                            tmp2 = load_reg(s, rn);
6205
                            if (insn & (1 << 6)) {
6206
                                tcg_gen_sub_i32(tmp, tmp, tmp2);
6207
                            } else {
6208
                                tcg_gen_add_i32(tmp, tmp, tmp2);
6209
                            }
6210
                            dead_tmp(tmp2);
6211
                        }
6212
                        store_reg(s, rd, tmp);
6213
                    } else {
6214
                        if (insn & (1 << 5))
6215
                            gen_swap_half(tmp2);
6216
                        gen_smul_dual(tmp, tmp2);
6217
                        /* This addition cannot overflow.  */
6218
                        if (insn & (1 << 6)) {
6219
                            tcg_gen_sub_i32(tmp, tmp, tmp2);
6220
                        } else {
6221
                            tcg_gen_add_i32(tmp, tmp, tmp2);
6222
                        }
6223
                        dead_tmp(tmp2);
6224
                        if (insn & (1 << 22)) {
6225
                            /* smlald, smlsld */
6226
                            tmp2 = tcg_temp_new(TCG_TYPE_I64);
6227
                            tcg_gen_ext_i32_i64(tmp2, tmp);
6228
                            dead_tmp(tmp);
6229
                            gen_addq(s, tmp2, rn, rd);
6230
                            gen_storeq_reg(s, rn, rd, tmp2);
6231
                        } else {
6232
                            /* smuad, smusd, smlad, smlsd */
6233
                            if (rn != 15)
6234
                              {
6235
                                tmp2 = load_reg(s, rn);
6236
                                gen_helper_add_setq(tmp, tmp, tmp2);
6237
                                dead_tmp(tmp2);
6238
                              }
6239
                            store_reg(s, rd, tmp);
6240
                        }
6241
                    }
6242
                    break;
6243
                case 3:
6244
                    op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6245
                    switch (op1) {
6246
                    case 0: /* Unsigned sum of absolute differences.  */
6247
                        ARCH(6);
6248
                        tmp = load_reg(s, rm);
6249
                        tmp2 = load_reg(s, rs);
6250
                        gen_helper_usad8(tmp, tmp, tmp2);
6251
                        dead_tmp(tmp2);
6252
                        if (rn != 15) {
6253
                            tmp2 = load_reg(s, rn);
6254
                            tcg_gen_add_i32(tmp, tmp, tmp2);
6255
                            dead_tmp(tmp2);
6256
                        }
6257
                        store_reg(s, rd, tmp);
6258
                        break;
6259
                    case 0x20: case 0x24: case 0x28: case 0x2c:
6260
                        /* Bitfield insert/clear.  */
6261
                        ARCH(6T2);
6262
                        shift = (insn >> 7) & 0x1f;
6263
                        i = (insn >> 16) & 0x1f;
6264
                        i = i + 1 - shift;
6265
                        if (rm == 15) {
6266
                            tmp = new_tmp();
6267
                            tcg_gen_movi_i32(tmp, 0);
6268
                        } else {
6269
                            tmp = load_reg(s, rm);
6270
                        }
6271
                        if (i != 32) {
6272
                            tmp2 = load_reg(s, rd);
6273
                            gen_bfi(tmp, tmp2, tmp,
6274
                                    shift, ((1u << i) - 1) << shift);
6275
                            dead_tmp(tmp2);
6276
                        }
6277
                        store_reg(s, rd, tmp);
6278
                        break;
6279
                    case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6280
                    case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6281
                        tmp = load_reg(s, rm);
6282
                        shift = (insn >> 7) & 0x1f;
6283
                        i = ((insn >> 16) & 0x1f) + 1;
6284
                        if (shift + i > 32)
6285
                            goto illegal_op;
6286
                        if (i < 32) {
6287
                            if (op1 & 0x20) {
6288
                                gen_ubfx(tmp, shift, (1u << i) - 1);
6289
                            } else {
6290
                                gen_sbfx(tmp, shift, i);
6291
                            }
6292
                        }
6293
                        store_reg(s, rd, tmp);
6294
                        break;
6295
                    default:
6296
                        goto illegal_op;
6297
                    }
6298
                    break;
6299
                }
6300
                break;
6301
            }
6302
        do_ldst:
6303
            /* Check for undefined extension instructions
6304
             * per the ARM Bible IE:
6305
             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx
6306
             */
6307
            sh = (0xf << 20) | (0xf << 4);
6308
            if (op1 == 0x7 && ((insn & sh) == sh))
6309
            {
6310
                goto illegal_op;
6311
            }
6312
            /* load/store byte/word */
6313
            rn = (insn >> 16) & 0xf;
6314
            rd = (insn >> 12) & 0xf;
6315
            tmp2 = load_reg(s, rn);
6316
            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6317
            if (insn & (1 << 24))
6318
                gen_add_data_offset(s, insn, tmp2);
6319
            if (insn & (1 << 20)) {
6320
                /* load */
6321
                s->is_mem = 1;
6322
                if (insn & (1 << 22)) {
6323
                    tmp = gen_ld8u(tmp2, i);
6324
                } else {
6325
                    tmp = gen_ld32(tmp2, i);
6326
                }
6327
            } else {
6328
                /* store */
6329
                tmp = load_reg(s, rd);
6330
                if (insn & (1 << 22))
6331
                    gen_st8(tmp, tmp2, i);
6332
                else
6333
                    gen_st32(tmp, tmp2, i);
6334
            }
6335
            if (!(insn & (1 << 24))) {
6336
                gen_add_data_offset(s, insn, tmp2);
6337
                store_reg(s, rn, tmp2);
6338
            } else if (insn & (1 << 21)) {
6339
                store_reg(s, rn, tmp2);
6340
            } else {
6341
                dead_tmp(tmp2);
6342
            }
6343
            if (insn & (1 << 20)) {
6344
                /* Complete the load.  */
6345
                if (rd == 15)
6346
                    gen_bx(s, tmp);
6347
                else
6348
                    store_reg(s, rd, tmp);
6349
            }
6350
            break;
6351
        case 0x08:
6352
        case 0x09:
6353
            {
6354
                int j, n, user, loaded_base;
6355
                TCGv loaded_var;
6356
                /* load/store multiple words */
6357
                /* XXX: store correct base if write back */
6358
                user = 0;
6359
                if (insn & (1 << 22)) {
6360
                    if (IS_USER(s))
6361
                        goto illegal_op; /* only usable in supervisor mode */
6362

    
6363
                    if ((insn & (1 << 15)) == 0)
6364
                        user = 1;
6365
                }
6366
                rn = (insn >> 16) & 0xf;
6367
                addr = load_reg(s, rn);
6368

    
6369
                /* compute total size */
6370
                loaded_base = 0;
6371
                n = 0;
6372
                for(i=0;i<16;i++) {
6373
                    if (insn & (1 << i))
6374
                        n++;
6375
                }
6376
                /* XXX: test invalid n == 0 case ? */
6377
                if (insn & (1 << 23)) {
6378
                    if (insn & (1 << 24)) {
6379
                        /* pre increment */
6380
                        tcg_gen_addi_i32(addr, addr, 4);
6381
                    } else {
6382
                        /* post increment */
6383
                    }
6384
                } else {
6385
                    if (insn & (1 << 24)) {
6386
                        /* pre decrement */
6387
                        tcg_gen_addi_i32(addr, addr, -(n * 4));
6388
                    } else {
6389
                        /* post decrement */
6390
                        if (n != 1)
6391
                        tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6392
                    }
6393
                }
6394
                j = 0;
6395
                for(i=0;i<16;i++) {
6396
                    if (insn & (1 << i)) {
6397
                        if (insn & (1 << 20)) {
6398
                            /* load */
6399
                            tmp = gen_ld32(addr, IS_USER(s));
6400
                            if (i == 15) {
6401
                                gen_bx(s, tmp);
6402
                            } else if (user) {
6403
                                gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6404
                                dead_tmp(tmp);
6405
                            } else if (i == rn) {
6406
                                loaded_var = tmp;
6407
                                loaded_base = 1;
6408
                            } else {
6409
                                store_reg(s, i, tmp);
6410
                            }
6411
                        } else {
6412
                            /* store */
6413
                            if (i == 15) {
6414
                                /* special case: r15 = PC + 8 */
6415
                                val = (long)s->pc + 4;
6416
                                tmp = new_tmp();
6417
                                tcg_gen_movi_i32(tmp, val);
6418
                            } else if (user) {
6419
                                tmp = new_tmp();
6420
                                gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6421
                            } else {
6422
                                tmp = load_reg(s, i);
6423
                            }
6424
                            gen_st32(tmp, addr, IS_USER(s));
6425
                        }
6426
                        j++;
6427
                        /* no need to add after the last transfer */
6428
                        if (j != n)
6429
                            tcg_gen_addi_i32(addr, addr, 4);
6430
                    }
6431
                }
6432
                if (insn & (1 << 21)) {
6433
                    /* write back */
6434
                    if (insn & (1 << 23)) {
6435
                        if (insn & (1 << 24)) {
6436
                            /* pre increment */
6437
                        } else {
6438
                            /* post increment */
6439
                            tcg_gen_addi_i32(addr, addr, 4);
6440
                        }
6441
                    } else {
6442
                        if (insn & (1 << 24)) {
6443
                            /* pre decrement */
6444
                            if (n != 1)
6445
                                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6446
                        } else {
6447
                            /* post decrement */
6448
                            tcg_gen_addi_i32(addr, addr, -(n * 4));
6449
                        }
6450
                    }
6451
                    store_reg(s, rn, addr);
6452
                } else {
6453
                    dead_tmp(addr);
6454
                }
6455
                if (loaded_base) {
6456
                    store_reg(s, rn, loaded_var);
6457
                }
6458
                if ((insn & (1 << 22)) && !user) {
6459
                    /* Restore CPSR from SPSR.  */
6460
                    tmp = load_cpu_field(spsr);
6461
                    gen_set_cpsr(tmp, 0xffffffff);
6462
                    dead_tmp(tmp);
6463
                    s->is_jmp = DISAS_UPDATE;
6464
                }
6465
            }
6466
            break;
6467
        case 0xa:
6468
        case 0xb:
6469
            {
6470
                int32_t offset;
6471

    
6472
                /* branch (and link) */
6473
                val = (int32_t)s->pc;
6474
                if (insn & (1 << 24)) {
6475
                    tmp = new_tmp();
6476
                    tcg_gen_movi_i32(tmp, val);
6477
                    store_reg(s, 14, tmp);
6478
                }
6479
                offset = (((int32_t)insn << 8) >> 8);
6480
                val += (offset << 2) + 4;
6481
                gen_jmp(s, val);
6482
            }
6483
            break;
6484
        case 0xc:
6485
        case 0xd:
6486
        case 0xe:
6487
            /* Coprocessor.  */
6488
            if (disas_coproc_insn(env, s, insn))
6489
                goto illegal_op;
6490
            break;
6491
        case 0xf:
6492
            /* swi */
6493
            gen_set_pc_im(s->pc);
6494
            s->is_jmp = DISAS_SWI;
6495
            break;
6496
        default:
6497
        illegal_op:
6498
            gen_set_condexec(s);
6499
            gen_set_pc_im(s->pc - 4);
6500
            gen_exception(EXCP_UDEF);
6501
            s->is_jmp = DISAS_JUMP;
6502
            break;
6503
        }
6504
    }
6505
}
6506

    
6507
/* Return true if this is a Thumb-2 logical op.  */
6508
static int
6509
thumb2_logic_op(int op)
6510
{
6511
    return (op < 8);
6512
}
6513

    
6514
/* Generate code for a Thumb-2 data processing operation.  If CONDS is nonzero
6515
   then set condition code flags based on the result of the operation.
6516
   If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6517
   to the high bit of T1.
6518
   Returns zero if the opcode is valid.  */
6519

    
6520
static int
6521
gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
6522
{
6523
    int logic_cc;
6524

    
6525
    logic_cc = 0;
6526
    switch (op) {
6527
    case 0: /* and */
6528
        gen_op_andl_T0_T1();
6529
        logic_cc = conds;
6530
        break;
6531
    case 1: /* bic */
6532
        gen_op_bicl_T0_T1();
6533
        logic_cc = conds;
6534
        break;
6535
    case 2: /* orr */
6536
        gen_op_orl_T0_T1();
6537
        logic_cc = conds;
6538
        break;
6539
    case 3: /* orn */
6540
        gen_op_notl_T1();
6541
        gen_op_orl_T0_T1();
6542
        logic_cc = conds;
6543
        break;
6544
    case 4: /* eor */
6545
        gen_op_xorl_T0_T1();
6546
        logic_cc = conds;
6547
        break;
6548
    case 8: /* add */
6549
        if (conds)
6550
            gen_op_addl_T0_T1_cc();
6551
        else
6552
            gen_op_addl_T0_T1();
6553
        break;
6554
    case 10: /* adc */
6555
        if (conds)
6556
            gen_op_adcl_T0_T1_cc();
6557
        else
6558
            gen_adc_T0_T1();
6559
        break;
6560
    case 11: /* sbc */
6561
        if (conds)
6562
            gen_op_sbcl_T0_T1_cc();
6563
        else
6564
            gen_sbc_T0_T1();
6565
        break;
6566
    case 13: /* sub */
6567
        if (conds)
6568
            gen_op_subl_T0_T1_cc();
6569
        else
6570
            gen_op_subl_T0_T1();
6571
        break;
6572
    case 14: /* rsb */
6573
        if (conds)
6574
            gen_op_rsbl_T0_T1_cc();
6575
        else
6576
            gen_op_rsbl_T0_T1();
6577
        break;
6578
    default: /* 5, 6, 7, 9, 12, 15. */
6579
        return 1;
6580
    }
6581
    if (logic_cc) {
6582
        gen_op_logic_T0_cc();
6583
        if (shifter_out)
6584
            gen_set_CF_bit31(cpu_T[1]);
6585
    }
6586
    return 0;
6587
}
6588

    
6589
/* Translate a 32-bit thumb instruction.  Returns nonzero if the instruction
6590
   is not legal.  */
6591
static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
6592
{
6593
    uint32_t insn, imm, shift, offset;
6594
    uint32_t rd, rn, rm, rs;
6595
    TCGv tmp;
6596
    TCGv tmp2;
6597
    TCGv tmp3;
6598
    TCGv addr;
6599
    int op;
6600
    int shiftop;
6601
    int conds;
6602
    int logic_cc;
6603

    
6604
    if (!(arm_feature(env, ARM_FEATURE_THUMB2)
6605
          || arm_feature (env, ARM_FEATURE_M))) {
6606
        /* Thumb-1 cores may need to tread bl and blx as a pair of
6607
           16-bit instructions to get correct prefetch abort behavior.  */
6608
        insn = insn_hw1;
6609
        if ((insn & (1 << 12)) == 0) {
6610
            /* Second half of blx.  */
6611
            offset = ((insn & 0x7ff) << 1);
6612
            tmp = load_reg(s, 14);
6613
            tcg_gen_addi_i32(tmp, tmp, offset);
6614
            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
6615

    
6616
            tmp2 = new_tmp();
6617
            tcg_gen_movi_i32(tmp2, s->pc | 1);
6618
            store_reg(s, 14, tmp2);
6619
            gen_bx(s, tmp);
6620
            return 0;
6621
        }
6622
        if (insn & (1 << 11)) {
6623
            /* Second half of bl.  */
6624
            offset = ((insn & 0x7ff) << 1) | 1;
6625
            tmp = load_reg(s, 14);
6626
            tcg_gen_addi_i32(tmp, tmp, 14);
6627

    
6628
            tmp2 = new_tmp();
6629
            tcg_gen_movi_i32(tmp2, s->pc | 1);
6630
            store_reg(s, 14, tmp2);
6631
            gen_bx(s, tmp);
6632
            return 0;
6633
        }
6634
        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
6635
            /* Instruction spans a page boundary.  Implement it as two
6636
               16-bit instructions in case the second half causes an
6637
               prefetch abort.  */
6638
            offset = ((int32_t)insn << 21) >> 9;
6639
            gen_op_movl_T0_im(s->pc + 2 + offset);
6640
            gen_movl_reg_T0(s, 14);
6641
            return 0;
6642
        }
6643
        /* Fall through to 32-bit decode.  */
6644
    }
6645

    
6646
    insn = lduw_code(s->pc);
6647
    s->pc += 2;
6648
    insn |= (uint32_t)insn_hw1 << 16;
6649

    
6650
    if ((insn & 0xf800e800) != 0xf000e800) {
6651
        ARCH(6T2);
6652
    }
6653

    
6654
    rn = (insn >> 16) & 0xf;
6655
    rs = (insn >> 12) & 0xf;
6656
    rd = (insn >> 8) & 0xf;
6657
    rm = insn & 0xf;
6658
    switch ((insn >> 25) & 0xf) {
6659
    case 0: case 1: case 2: case 3:
6660
        /* 16-bit instructions.  Should never happen.  */
6661
        abort();
6662
    case 4:
6663
        if (insn & (1 << 22)) {
6664
            /* Other load/store, table branch.  */
6665
            if (insn & 0x01200000) {
6666
                /* Load/store doubleword.  */
6667
                if (rn == 15) {
6668
                    addr = new_tmp();
6669
                    tcg_gen_movi_i32(addr, s->pc & ~3);
6670
                } else {
6671
                    addr = load_reg(s, rn);
6672
                }
6673
                offset = (insn & 0xff) * 4;
6674
                if ((insn & (1 << 23)) == 0)
6675
                    offset = -offset;
6676
                if (insn & (1 << 24)) {
6677
                    tcg_gen_addi_i32(addr, addr, offset);
6678
                    offset = 0;
6679
                }
6680
                if (insn & (1 << 20)) {
6681
                    /* ldrd */
6682
                    tmp = gen_ld32(addr, IS_USER(s));
6683
                    store_reg(s, rs, tmp);
6684
                    tcg_gen_addi_i32(addr, addr, 4);
6685
                    tmp = gen_ld32(addr, IS_USER(s));
6686
                    store_reg(s, rd, tmp);
6687
                } else {
6688
                    /* strd */
6689
                    tmp = load_reg(s, rs);
6690
                    gen_st32(tmp, addr, IS_USER(s));
6691
                    tcg_gen_addi_i32(addr, addr, 4);
6692
                    tmp = load_reg(s, rd);
6693
                    gen_st32(tmp, addr, IS_USER(s));
6694
                }
6695
                if (insn & (1 << 21)) {
6696
                    /* Base writeback.  */
6697
                    if (rn == 15)
6698
                        goto illegal_op;
6699
                    tcg_gen_addi_i32(addr, addr, offset - 4);
6700
                    store_reg(s, rn, addr);
6701
                } else {
6702
                    dead_tmp(addr);
6703
                }
6704
            } else if ((insn & (1 << 23)) == 0) {
6705
                /* Load/store exclusive word.  */
6706
                gen_movl_T0_reg(s, rd);
6707
                gen_movl_T1_reg(s, rn);
6708
                if (insn & (1 << 20)) {
6709
                    gen_ldst(ldlex, s);
6710
                } else {
6711
                    gen_ldst(stlex, s);
6712
                }
6713
                gen_movl_reg_T0(s, rd);
6714
            } else if ((insn & (1 << 6)) == 0) {
6715
                /* Table Branch.  */
6716
                if (rn == 15) {
6717
                    addr = new_tmp();
6718
                    tcg_gen_movi_i32(addr, s->pc);
6719
                } else {
6720
                    addr = load_reg(s, rn);
6721
                }
6722
                tmp = load_reg(s, rm);
6723
                tcg_gen_add_i32(addr, addr, tmp);
6724
                if (insn & (1 << 4)) {
6725
                    /* tbh */
6726
                    tcg_gen_add_i32(addr, addr, tmp);
6727
                    dead_tmp(tmp);
6728
                    tmp = gen_ld16u(addr, IS_USER(s));
6729
                } else { /* tbb */
6730
                    dead_tmp(tmp);
6731
                    tmp = gen_ld8u(addr, IS_USER(s));
6732
                }
6733
                dead_tmp(addr);
6734
                tcg_gen_shli_i32(tmp, tmp, 1);
6735
                tcg_gen_addi_i32(tmp, tmp, s->pc);
6736
                store_reg(s, 15, tmp);
6737
            } else {
6738
                /* Load/store exclusive byte/halfword/doubleword.  */
6739
                op = (insn >> 4) & 0x3;
6740
                gen_movl_T1_reg(s, rn);
6741
                if (insn & (1 << 20)) {
6742
                    switch (op) {
6743
                    case 0:
6744
                        gen_ldst(ldbex, s);
6745
                        break;
6746
                    case 1:
6747
                        gen_ldst(ldwex, s);
6748
                        break;
6749
                    case 3:
6750
                        gen_ldst(ldqex, s);
6751
                        gen_movl_reg_T1(s, rd);
6752
                        break;
6753
                    default:
6754
                        goto illegal_op;
6755
                    }
6756
                    gen_movl_reg_T0(s, rs);
6757
                } else {
6758
                    gen_movl_T0_reg(s, rs);
6759
                    switch (op) {
6760
                    case 0:
6761
                        gen_ldst(stbex, s);
6762
                        break;
6763
                    case 1:
6764
                        gen_ldst(stwex, s);
6765
                        break;
6766
                    case 3:
6767
                        gen_movl_T2_reg(s, rd);
6768
                        gen_ldst(stqex, s);
6769
                        break;
6770
                    default:
6771
                        goto illegal_op;
6772
                    }
6773
                    gen_movl_reg_T0(s, rm);
6774
                }
6775
            }
6776
        } else {
6777
            /* Load/store multiple, RFE, SRS.  */
6778
            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
6779
                /* Not available in user mode.  */
6780
                if (IS_USER(s))
6781
                    goto illegal_op;
6782
                if (insn & (1 << 20)) {
6783
                    /* rfe */
6784
                    addr = load_reg(s, rn);
6785
                    if ((insn & (1 << 24)) == 0)
6786
                        tcg_gen_addi_i32(addr, addr, -8);
6787
                    /* Load PC into tmp and CPSR into tmp2.  */
6788
                    tmp = gen_ld32(addr, 0);
6789
                    tcg_gen_addi_i32(addr, addr, 4);
6790
                    tmp2 = gen_ld32(addr, 0);
6791
                    if (insn & (1 << 21)) {
6792
                        /* Base writeback.  */
6793
                        if (insn & (1 << 24)) {
6794
                            tcg_gen_addi_i32(addr, addr, 4);
6795
                        } else {
6796
                            tcg_gen_addi_i32(addr, addr, -4);
6797
                        }
6798
                        store_reg(s, rn, addr);
6799
                    } else {
6800
                        dead_tmp(addr);
6801
                    }
6802
                    gen_rfe(s, tmp, tmp2);
6803
                } else {
6804
                    /* srs */
6805
                    op = (insn & 0x1f);
6806
                    if (op == (env->uncached_cpsr & CPSR_M)) {
6807
                        addr = load_reg(s, 13);
6808
                    } else {
6809
                        addr = new_tmp();
6810
                        gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
6811
                    }
6812
                    if ((insn & (1 << 24)) == 0) {
6813
                        tcg_gen_addi_i32(addr, addr, -8);
6814
                    }
6815
                    tmp = load_reg(s, 14);
6816
                    gen_st32(tmp, addr, 0);
6817
                    tcg_gen_addi_i32(addr, addr, 4);
6818
                    tmp = new_tmp();
6819
                    gen_helper_cpsr_read(tmp);
6820
                    gen_st32(tmp, addr, 0);
6821
                    if (insn & (1 << 21)) {
6822
                        if ((insn & (1 << 24)) == 0) {
6823
                            tcg_gen_addi_i32(addr, addr, -4);
6824
                        } else {
6825
                            tcg_gen_addi_i32(addr, addr, 4);
6826
                        }
6827
                        if (op == (env->uncached_cpsr & CPSR_M)) {
6828
                            store_reg(s, 13, addr);
6829
                        } else {
6830
                            gen_helper_set_r13_banked(cpu_env,
6831
                                tcg_const_i32(op), addr);
6832
                        }
6833
                    } else {
6834
                        dead_tmp(addr);
6835
                    }
6836
                }
6837
            } else {
6838
                int i;
6839
                /* Load/store multiple.  */
6840
                addr = load_reg(s, rn);
6841
                offset = 0;
6842
                for (i = 0; i < 16; i++) {
6843
                    if (insn & (1 << i))
6844
                        offset += 4;
6845
                }
6846
                if (insn & (1 << 24)) {
6847
                    tcg_gen_addi_i32(addr, addr, -offset);
6848
                }
6849

    
6850
                for (i = 0; i < 16; i++) {
6851
                    if ((insn & (1 << i)) == 0)
6852
                        continue;
6853
                    if (insn & (1 << 20)) {
6854
                        /* Load.  */
6855
                        tmp = gen_ld32(addr, IS_USER(s));
6856
                        if (i == 15) {
6857
                            gen_bx(s, tmp);
6858
                        } else {
6859
                            store_reg(s, i, tmp);
6860
                        }
6861
                    } else {
6862
                        /* Store.  */
6863
                        tmp = load_reg(s, i);
6864
                        gen_st32(tmp, addr, IS_USER(s));
6865
                    }
6866
                    tcg_gen_addi_i32(addr, addr, 4);
6867
                }
6868
                if (insn & (1 << 21)) {
6869
                    /* Base register writeback.  */
6870
                    if (insn & (1 << 24)) {
6871
                        tcg_gen_addi_i32(addr, addr, -offset);
6872
                    }
6873
                    /* Fault if writeback register is in register list.  */
6874
                    if (insn & (1 << rn))
6875
                        goto illegal_op;
6876
                    store_reg(s, rn, addr);
6877
                } else {
6878
                    dead_tmp(addr);
6879
                }
6880
            }
6881
        }
6882
        break;
6883
    case 5: /* Data processing register constant shift.  */
6884
        if (rn == 15)
6885
            gen_op_movl_T0_im(0);
6886
        else
6887
            gen_movl_T0_reg(s, rn);
6888
        gen_movl_T1_reg(s, rm);
6889
        op = (insn >> 21) & 0xf;
6890
        shiftop = (insn >> 4) & 3;
6891
        shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6892
        conds = (insn & (1 << 20)) != 0;
6893
        logic_cc = (conds && thumb2_logic_op(op));
6894
        gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
6895
        if (gen_thumb2_data_op(s, op, conds, 0))
6896
            goto illegal_op;
6897
        if (rd != 15)
6898
            gen_movl_reg_T0(s, rd);
6899
        break;
6900
    case 13: /* Misc data processing.  */
6901
        op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
6902
        if (op < 4 && (insn & 0xf000) != 0xf000)
6903
            goto illegal_op;
6904
        switch (op) {
6905
        case 0: /* Register controlled shift.  */
6906
            gen_movl_T0_reg(s, rm);
6907
            gen_movl_T1_reg(s, rn);
6908
            if ((insn & 0x70) != 0)
6909
                goto illegal_op;
6910
            op = (insn >> 21) & 3;
6911
            if (insn & (1 << 20)) {
6912
                gen_shift_T1_T0_cc[op]();
6913
                gen_op_logic_T1_cc();
6914
            } else {
6915
                gen_shift_T1_T0[op]();
6916
            }
6917
            gen_movl_reg_T1(s, rd);
6918
            break;
6919
        case 1: /* Sign/zero extend.  */
6920
            tmp = load_reg(s, rm);
6921
            shift = (insn >> 4) & 3;
6922
            /* ??? In many cases it's not neccessary to do a
6923
               rotate, a shift is sufficient.  */
6924
            if (shift != 0)
6925
                tcg_gen_rori_i32(tmp, tmp, shift * 8);
6926
            op = (insn >> 20) & 7;
6927
            switch (op) {
6928
            case 0: gen_sxth(tmp);   break;
6929
            case 1: gen_uxth(tmp);   break;
6930
            case 2: gen_sxtb16(tmp); break;
6931
            case 3: gen_uxtb16(tmp); break;
6932
            case 4: gen_sxtb(tmp);   break;
6933
            case 5: gen_uxtb(tmp);   break;
6934
            default: goto illegal_op;
6935
            }
6936
            if (rn != 15) {
6937
                tmp2 = load_reg(s, rn);
6938
                if ((op >> 1) == 1) {
6939
                    gen_add16(tmp, tmp2);
6940
                } else {
6941
                    tcg_gen_add_i32(tmp, tmp, tmp2);
6942
                    dead_tmp(tmp2);
6943
                }
6944
            }
6945
            store_reg(s, rd, tmp);
6946
            break;
6947
        case 2: /* SIMD add/subtract.  */
6948
            op = (insn >> 20) & 7;
6949
            shift = (insn >> 4) & 7;
6950
            if ((op & 3) == 3 || (shift & 3) == 3)
6951
                goto illegal_op;
6952
            tmp = load_reg(s, rn);
6953
            tmp2 = load_reg(s, rm);
6954
            gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
6955
            dead_tmp(tmp2);
6956
            store_reg(s, rd, tmp);
6957
            break;
6958
        case 3: /* Other data processing.  */
6959
            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
6960
            if (op < 4) {
6961
                /* Saturating add/subtract.  */
6962
                tmp = load_reg(s, rn);
6963
                tmp2 = load_reg(s, rm);
6964
                if (op & 2)
6965
                    gen_helper_double_saturate(tmp, tmp);
6966
                if (op & 1)
6967
                    gen_helper_sub_saturate(tmp, tmp2, tmp);
6968
                else
6969
                    gen_helper_add_saturate(tmp, tmp, tmp2);
6970
                dead_tmp(tmp2);
6971
            } else {
6972
                tmp = load_reg(s, rn);
6973
                switch (op) {
6974
                case 0x0a: /* rbit */
6975
                    gen_helper_rbit(tmp, tmp);
6976
                    break;
6977
                case 0x08: /* rev */
6978
                    tcg_gen_bswap_i32(tmp, tmp);
6979
                    break;
6980
                case 0x09: /* rev16 */
6981
                    gen_rev16(tmp);
6982
                    break;
6983
                case 0x0b: /* revsh */
6984
                    gen_revsh(tmp);
6985
                    break;
6986
                case 0x10: /* sel */
6987
                    tmp2 = load_reg(s, rm);
6988
                    tmp3 = new_tmp();
6989
                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6990
                    gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6991
                    dead_tmp(tmp3);
6992
                    dead_tmp(tmp2);
6993
                    break;
6994
                case 0x18: /* clz */
6995
                    gen_helper_clz(tmp, tmp);
6996
                    break;
6997
                default:
6998
                    goto illegal_op;
6999
                }
7000
            }
7001
            store_reg(s, rd, tmp);
7002
            break;
7003
        case 4: case 5: /* 32-bit multiply.  Sum of absolute differences.  */
7004
            op = (insn >> 4) & 0xf;
7005
            tmp = load_reg(s, rn);
7006
            tmp2 = load_reg(s, rm);
7007
            switch ((insn >> 20) & 7) {
7008
            case 0: /* 32 x 32 -> 32 */
7009
                tcg_gen_mul_i32(tmp, tmp, tmp2);
7010
                dead_tmp(tmp2);
7011
                if (rs != 15) {
7012
                    tmp2 = load_reg(s, rs);
7013
                    if (op)
7014
                        tcg_gen_sub_i32(tmp, tmp2, tmp);
7015
                    else
7016
                        tcg_gen_add_i32(tmp, tmp, tmp2);
7017
                    dead_tmp(tmp2);
7018
                }
7019
                break;
7020
            case 1: /* 16 x 16 -> 32 */
7021
                gen_mulxy(tmp, tmp2, op & 2, op & 1);
7022
                dead_tmp(tmp2);
7023
                if (rs != 15) {
7024
                    tmp2 = load_reg(s, rs);
7025
                    gen_helper_add_setq(tmp, tmp, tmp2);
7026
                    dead_tmp(tmp2);
7027
                }
7028
                break;
7029
            case 2: /* Dual multiply add.  */
7030
            case 4: /* Dual multiply subtract.  */
7031
                if (op)
7032
                    gen_swap_half(tmp2);
7033
                gen_smul_dual(tmp, tmp2);
7034
                /* This addition cannot overflow.  */
7035
                if (insn & (1 << 22)) {
7036
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
7037
                } else {
7038
                    tcg_gen_add_i32(tmp, tmp, tmp2);
7039
                }
7040
                dead_tmp(tmp2);
7041
                if (rs != 15)
7042
                  {
7043
                    tmp2 = load_reg(s, rs);
7044
                    gen_helper_add_setq(tmp, tmp, tmp2);
7045
                    dead_tmp(tmp2);
7046
                  }
7047
                break;
7048
            case 3: /* 32 * 16 -> 32msb */
7049
                if (op)
7050
                    tcg_gen_sari_i32(tmp2, tmp2, 16);
7051
                else
7052
                    gen_sxth(tmp2);
7053
                tmp2 = gen_muls_i64_i32(tmp, tmp2);
7054
                tcg_gen_shri_i64(tmp2, tmp2, 16);
7055
                tmp = new_tmp();
7056
                tcg_gen_trunc_i64_i32(tmp, tmp2);
7057
                if (rs != 15)
7058
                  {
7059
                    tmp2 = load_reg(s, rs);
7060
                    gen_helper_add_setq(tmp, tmp, tmp2);
7061
                    dead_tmp(tmp2);
7062
                  }
7063
                break;
7064
            case 5: case 6: /* 32 * 32 -> 32msb */
7065
                gen_imull(tmp, tmp2);
7066
                if (insn & (1 << 5)) {
7067
                    gen_roundqd(tmp, tmp2);
7068
                    dead_tmp(tmp2);
7069
                } else {
7070
                    dead_tmp(tmp);
7071
                    tmp = tmp2;
7072
                }
7073
                if (rs != 15) {
7074
                    tmp2 = load_reg(s, rs);
7075
                    if (insn & (1 << 21)) {
7076
                        tcg_gen_add_i32(tmp, tmp, tmp2);
7077
                    } else {
7078
                        tcg_gen_sub_i32(tmp, tmp2, tmp);
7079
                    }
7080
                    dead_tmp(tmp2);
7081
                }
7082
                break;
7083
            case 7: /* Unsigned sum of absolute differences.  */
7084
                gen_helper_usad8(tmp, tmp, tmp2);
7085
                dead_tmp(tmp2);
7086
                if (rs != 15) {
7087
                    tmp2 = load_reg(s, rs);
7088
                    tcg_gen_add_i32(tmp, tmp, tmp2);
7089
                    dead_tmp(tmp2);
7090
                }
7091
                break;
7092
            }
7093
            store_reg(s, rd, tmp);
7094
            break;
7095
        case 6: case 7: /* 64-bit multiply, Divide.  */
7096
            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7097
            tmp = load_reg(s, rn);
7098
            tmp2 = load_reg(s, rm);
7099
            if ((op & 0x50) == 0x10) {
7100
                /* sdiv, udiv */
7101
                if (!arm_feature(env, ARM_FEATURE_DIV))
7102
                    goto illegal_op;
7103
                if (op & 0x20)
7104
                    gen_helper_udiv(tmp, tmp, tmp2);
7105
                else
7106
                    gen_helper_sdiv(tmp, tmp, tmp2);
7107
                dead_tmp(tmp2);
7108
                store_reg(s, rd, tmp);
7109
            } else if ((op & 0xe) == 0xc) {
7110
                /* Dual multiply accumulate long.  */
7111
                if (op & 1)
7112
                    gen_swap_half(tmp2);
7113
                gen_smul_dual(tmp, tmp2);
7114
                if (op & 0x10) {
7115
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
7116
                } else {
7117
                    tcg_gen_add_i32(tmp, tmp, tmp2);
7118
                }
7119
                dead_tmp(tmp2);
7120
                tmp2 = tcg_temp_new(TCG_TYPE_I64);
7121
                gen_addq(s, tmp, rs, rd);
7122
                gen_storeq_reg(s, rs, rd, tmp);
7123
            } else {
7124
                if (op & 0x20) {
7125
                    /* Unsigned 64-bit multiply  */
7126
                    tmp = gen_mulu_i64_i32(tmp, tmp2);
7127
                } else {
7128
                    if (op & 8) {
7129
                        /* smlalxy */
7130
                        gen_mulxy(tmp, tmp2, op & 2, op & 1);
7131
                        dead_tmp(tmp2);
7132
                        tmp2 = tcg_temp_new(TCG_TYPE_I64);
7133
                        tcg_gen_ext_i32_i64(tmp2, tmp);
7134
                        dead_tmp(tmp);
7135
                        tmp = tmp2;
7136
                    } else {
7137
                        /* Signed 64-bit multiply  */
7138
                        tmp = gen_muls_i64_i32(tmp, tmp2);
7139
                    }
7140
                }
7141
                if (op & 4) {
7142
                    /* umaal */
7143
                    gen_addq_lo(s, tmp, rs);
7144
                    gen_addq_lo(s, tmp, rd);
7145
                } else if (op & 0x40) {
7146
                    /* 64-bit accumulate.  */
7147
                    gen_addq(s, tmp, rs, rd);
7148
                }
7149
                gen_storeq_reg(s, rs, rd, tmp);
7150
            }
7151
            break;
7152
        }
7153
        break;
7154
    case 6: case 7: case 14: case 15:
7155
        /* Coprocessor.  */
7156
        if (((insn >> 24) & 3) == 3) {
7157
            /* Translate into the equivalent ARM encoding.  */
7158
            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7159
            if (disas_neon_data_insn(env, s, insn))
7160
                goto illegal_op;
7161
        } else {
7162
            if (insn & (1 << 28))
7163
                goto illegal_op;
7164
            if (disas_coproc_insn (env, s, insn))
7165
                goto illegal_op;
7166
        }
7167
        break;
7168
    case 8: case 9: case 10: case 11:
7169
        if (insn & (1 << 15)) {
7170
            /* Branches, misc control.  */
7171
            if (insn & 0x5000) {
7172
                /* Unconditional branch.  */
7173
                /* signextend(hw1[10:0]) -> offset[:12].  */
7174
                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7175
                /* hw1[10:0] -> offset[11:1].  */
7176
                offset |= (insn & 0x7ff) << 1;
7177
                /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7178
                   offset[24:22] already have the same value because of the
7179
                   sign extension above.  */
7180
                offset ^= ((~insn) & (1 << 13)) << 10;
7181
                offset ^= ((~insn) & (1 << 11)) << 11;
7182

    
7183
                if (insn & (1 << 14)) {
7184
                    /* Branch and link.  */
7185
                    gen_op_movl_T1_im(s->pc | 1);
7186
                    gen_movl_reg_T1(s, 14);
7187
                }
7188

    
7189
                offset += s->pc;
7190
                if (insn & (1 << 12)) {
7191
                    /* b/bl */
7192
                    gen_jmp(s, offset);
7193
                } else {
7194
                    /* blx */
7195
                    offset &= ~(uint32_t)2;
7196
                    gen_bx_im(s, offset);
7197
                }
7198
            } else if (((insn >> 23) & 7) == 7) {
7199
                /* Misc control */
7200
                if (insn & (1 << 13))
7201
                    goto illegal_op;
7202

    
7203
                if (insn & (1 << 26)) {
7204
                    /* Secure monitor call (v6Z) */
7205
                    goto illegal_op; /* not implemented.  */
7206
                } else {
7207
                    op = (insn >> 20) & 7;
7208
                    switch (op) {
7209
                    case 0: /* msr cpsr.  */
7210
                        if (IS_M(env)) {
7211
                            gen_op_v7m_msr_T0(insn & 0xff);
7212
                            gen_movl_reg_T0(s, rn);
7213
                            gen_lookup_tb(s);
7214
                            break;
7215
                        }
7216
                        /* fall through */
7217
                    case 1: /* msr spsr.  */
7218
                        if (IS_M(env))
7219
                            goto illegal_op;
7220
                        gen_movl_T0_reg(s, rn);
7221
                        if (gen_set_psr_T0(s,
7222
                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7223
                              op == 1))
7224
                            goto illegal_op;
7225
                        break;
7226
                    case 2: /* cps, nop-hint.  */
7227
                        if (((insn >> 8) & 7) == 0) {
7228
                            gen_nop_hint(s, insn & 0xff);
7229
                        }
7230
                        /* Implemented as NOP in user mode.  */
7231
                        if (IS_USER(s))
7232
                            break;
7233
                        offset = 0;
7234
                        imm = 0;
7235
                        if (insn & (1 << 10)) {
7236
                            if (insn & (1 << 7))
7237
                                offset |= CPSR_A;
7238
                            if (insn & (1 << 6))
7239
                                offset |= CPSR_I;
7240
                            if (insn & (1 << 5))
7241
                                offset |= CPSR_F;
7242
                            if (insn & (1 << 9))
7243
                                imm = CPSR_A | CPSR_I | CPSR_F;
7244
                        }
7245
                        if (insn & (1 << 8)) {
7246
                            offset |= 0x1f;
7247
                            imm |= (insn & 0x1f);
7248
                        }
7249
                        if (offset) {
7250
                            gen_op_movl_T0_im(imm);
7251
                            gen_set_psr_T0(s, offset, 0);
7252
                        }
7253
                        break;
7254
                    case 3: /* Special control operations.  */
7255
                        op = (insn >> 4) & 0xf;
7256
                        switch (op) {
7257
                        case 2: /* clrex */
7258
                            gen_op_clrex();
7259
                            break;
7260
                        case 4: /* dsb */
7261
                        case 5: /* dmb */
7262
                        case 6: /* isb */
7263
                            /* These execute as NOPs.  */
7264
                            ARCH(7);
7265
                            break;
7266
                        default:
7267
                            goto illegal_op;
7268
                        }
7269
                        break;
7270
                    case 4: /* bxj */
7271
                        /* Trivial implementation equivalent to bx.  */
7272
                        tmp = load_reg(s, rn);
7273
                        gen_bx(s, tmp);
7274
                        break;
7275
                    case 5: /* Exception return.  */
7276
                        /* Unpredictable in user mode.  */
7277
                        goto illegal_op;
7278
                    case 6: /* mrs cpsr.  */
7279
                        if (IS_M(env)) {
7280
                            gen_op_v7m_mrs_T0(insn & 0xff);
7281
                        } else {
7282
                            gen_helper_cpsr_read(cpu_T[0]);
7283
                        }
7284
                        gen_movl_reg_T0(s, rd);
7285
                        break;
7286
                    case 7: /* mrs spsr.  */
7287
                        /* Not accessible in user mode.  */
7288
                        if (IS_USER(s) || IS_M(env))
7289
                            goto illegal_op;
7290
                        tmp = load_cpu_field(spsr);
7291
                        store_reg(s, rd, tmp);
7292
                        break;
7293
                    }
7294
                }
7295
            } else {
7296
                /* Conditional branch.  */
7297
                op = (insn >> 22) & 0xf;
7298
                /* Generate a conditional jump to next instruction.  */
7299
                s->condlabel = gen_new_label();
7300
                gen_test_cc(op ^ 1, s->condlabel);
7301
                s->condjmp = 1;
7302

    
7303
                /* offset[11:1] = insn[10:0] */
7304
                offset = (insn & 0x7ff) << 1;
7305
                /* offset[17:12] = insn[21:16].  */
7306
                offset |= (insn & 0x003f0000) >> 4;
7307
                /* offset[31:20] = insn[26].  */
7308
                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7309
                /* offset[18] = insn[13].  */
7310
                offset |= (insn & (1 << 13)) << 5;
7311
                /* offset[19] = insn[11].  */
7312
                offset |= (insn & (1 << 11)) << 8;
7313

    
7314
                /* jump to the offset */
7315
                gen_jmp(s, s->pc + offset);
7316
            }
7317
        } else {
7318
            /* Data processing immediate.  */
7319
            if (insn & (1 << 25)) {
7320
                if (insn & (1 << 24)) {
7321
                    if (insn & (1 << 20))
7322
                        goto illegal_op;
7323
                    /* Bitfield/Saturate.  */
7324
                    op = (insn >> 21) & 7;
7325
                    imm = insn & 0x1f;
7326
                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7327
                    if (rn == 15) {
7328
                        tmp = new_tmp();
7329
                        tcg_gen_movi_i32(tmp, 0);
7330
                    } else {
7331
                        tmp = load_reg(s, rn);
7332
                    }
7333
                    switch (op) {
7334
                    case 2: /* Signed bitfield extract.  */
7335
                        imm++;
7336
                        if (shift + imm > 32)
7337
                            goto illegal_op;
7338
                        if (imm < 32)
7339
                            gen_sbfx(tmp, shift, imm);
7340
                        break;
7341
                    case 6: /* Unsigned bitfield extract.  */
7342
                        imm++;
7343
                        if (shift + imm > 32)
7344
                            goto illegal_op;
7345
                        if (imm < 32)
7346
                            gen_ubfx(tmp, shift, (1u << imm) - 1);
7347
                        break;
7348
                    case 3: /* Bitfield insert/clear.  */
7349
                        if (imm < shift)
7350
                            goto illegal_op;
7351
                        imm = imm + 1 - shift;
7352
                        if (imm != 32) {
7353
                            tmp2 = load_reg(s, rd);
7354
                            gen_bfi(tmp, tmp2, tmp,
7355
                                    shift, ((1u << imm) - 1) << shift);
7356
                            dead_tmp(tmp2);
7357
                        }
7358
                        break;
7359
                    case 7:
7360
                        goto illegal_op;
7361
                    default: /* Saturate.  */
7362
                        if (shift) {
7363
                            if (op & 1)
7364
                                tcg_gen_sari_i32(tmp, tmp, shift);
7365
                            else
7366
                                tcg_gen_shli_i32(tmp, tmp, shift);
7367
                        }
7368
                        tmp2 = tcg_const_i32(imm);
7369
                        if (op & 4) {
7370
                            /* Unsigned.  */
7371
                            if ((op & 1) && shift == 0)
7372
                                gen_helper_usat16(tmp, tmp, tmp2);
7373
                            else
7374
                                gen_helper_usat(tmp, tmp, tmp2);
7375
                        } else {
7376
                            /* Signed.  */
7377
                            if ((op & 1) && shift == 0)
7378
                                gen_helper_ssat16(tmp, tmp, tmp2);
7379
                            else
7380
                                gen_helper_ssat(tmp, tmp, tmp2);
7381
                        }
7382
                        break;
7383
                    }
7384
                    store_reg(s, rd, tmp);
7385
                } else {
7386
                    imm = ((insn & 0x04000000) >> 15)
7387
                          | ((insn & 0x7000) >> 4) | (insn & 0xff);
7388
                    if (insn & (1 << 22)) {
7389
                        /* 16-bit immediate.  */
7390
                        imm |= (insn >> 4) & 0xf000;
7391
                        if (insn & (1 << 23)) {
7392
                            /* movt */
7393
                            tmp = load_reg(s, rd);
7394
                            tcg_gen_andi_i32(tmp, tmp, 0xffff);
7395
                            tcg_gen_ori_i32(tmp, tmp, imm << 16);
7396
                        } else {
7397
                            /* movw */
7398
                            tmp = new_tmp();
7399
                            tcg_gen_movi_i32(tmp, imm);
7400
                        }
7401
                    } else {
7402
                        /* Add/sub 12-bit immediate.  */
7403
                        if (rn == 15) {
7404
                            offset = s->pc & ~(uint32_t)3;
7405
                            if (insn & (1 << 23))
7406
                                offset -= imm;
7407
                            else
7408
                                offset += imm;
7409
                            tmp = new_tmp();
7410
                            tcg_gen_movi_i32(tmp, offset);
7411
                        } else {
7412
                            tmp = load_reg(s, rn);
7413
                            if (insn & (1 << 23))
7414
                                tcg_gen_subi_i32(tmp, tmp, imm);
7415
                            else
7416
                                tcg_gen_addi_i32(tmp, tmp, imm);
7417
                        }
7418
                    }
7419
                    store_reg(s, rd, tmp);
7420
                }
7421
            } else {
7422
                int shifter_out = 0;
7423
                /* modified 12-bit immediate.  */
7424
                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7425
                imm = (insn & 0xff);
7426
                switch (shift) {
7427
                case 0: /* XY */
7428
                    /* Nothing to do.  */
7429
                    break;
7430
                case 1: /* 00XY00XY */
7431
                    imm |= imm << 16;
7432
                    break;
7433
                case 2: /* XY00XY00 */
7434
                    imm |= imm << 16;
7435
                    imm <<= 8;
7436
                    break;
7437
                case 3: /* XYXYXYXY */
7438
                    imm |= imm << 16;
7439
                    imm |= imm << 8;
7440
                    break;
7441
                default: /* Rotated constant.  */
7442
                    shift = (shift << 1) | (imm >> 7);
7443
                    imm |= 0x80;
7444
                    imm = imm << (32 - shift);
7445
                    shifter_out = 1;
7446
                    break;
7447
                }
7448
                gen_op_movl_T1_im(imm);
7449
                rn = (insn >> 16) & 0xf;
7450
                if (rn == 15)
7451
                    gen_op_movl_T0_im(0);
7452
                else
7453
                    gen_movl_T0_reg(s, rn);
7454
                op = (insn >> 21) & 0xf;
7455
                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7456
                                       shifter_out))
7457
                    goto illegal_op;
7458
                rd = (insn >> 8) & 0xf;
7459
                if (rd != 15) {
7460
                    gen_movl_reg_T0(s, rd);
7461
                }
7462
            }
7463
        }
7464
        break;
7465
    case 12: /* Load/store single data item.  */
7466
        {
7467
        int postinc = 0;
7468
        int writeback = 0;
7469
        int user;
7470
        if ((insn & 0x01100000) == 0x01000000) {
7471
            if (disas_neon_ls_insn(env, s, insn))
7472
                goto illegal_op;
7473
            break;
7474
        }
7475
        user = IS_USER(s);
7476
        if (rn == 15) {
7477
            addr = new_tmp();
7478
            /* PC relative.  */
7479
            /* s->pc has already been incremented by 4.  */
7480
            imm = s->pc & 0xfffffffc;
7481
            if (insn & (1 << 23))
7482
                imm += insn & 0xfff;
7483
            else
7484
                imm -= insn & 0xfff;
7485
            tcg_gen_movi_i32(addr, imm);
7486
        } else {
7487
            addr = load_reg(s, rn);
7488
            if (insn & (1 << 23)) {
7489
                /* Positive offset.  */
7490
                imm = insn & 0xfff;
7491
                tcg_gen_addi_i32(addr, addr, imm);
7492
            } else {
7493
                op = (insn >> 8) & 7;
7494
                imm = insn & 0xff;
7495
                switch (op) {
7496
                case 0: case 8: /* Shifted Register.  */
7497
                    shift = (insn >> 4) & 0xf;
7498
                    if (shift > 3)
7499
                        goto illegal_op;
7500
                    tmp = load_reg(s, rm);
7501
                    if (shift)
7502
                        tcg_gen_shli_i32(tmp, tmp, shift);
7503
                    tcg_gen_add_i32(addr, addr, tmp);
7504
                    dead_tmp(tmp);
7505
                    break;
7506
                case 4: /* Negative offset.  */
7507
                    tcg_gen_addi_i32(addr, addr, -imm);
7508
                    break;
7509
                case 6: /* User privilege.  */
7510
                    tcg_gen_addi_i32(addr, addr, imm);
7511
                    user = 1;
7512
                    break;
7513
                case 1: /* Post-decrement.  */
7514
                    imm = -imm;
7515
                    /* Fall through.  */
7516
                case 3: /* Post-increment.  */
7517
                    postinc = 1;
7518
                    writeback = 1;
7519
                    break;
7520
                case 5: /* Pre-decrement.  */
7521
                    imm = -imm;
7522
                    /* Fall through.  */
7523
                case 7: /* Pre-increment.  */
7524
                    tcg_gen_addi_i32(addr, addr, imm);
7525
                    writeback = 1;
7526
                    break;
7527
                default:
7528
                    goto illegal_op;
7529
                }
7530
            }
7531
        }
7532
        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
7533
        if (insn & (1 << 20)) {
7534
            /* Load.  */
7535
            if (rs == 15 && op != 2) {
7536
                if (op & 2)
7537
                    goto illegal_op;
7538
                /* Memory hint.  Implemented as NOP.  */
7539
            } else {
7540
                switch (op) {
7541
                case 0: tmp = gen_ld8u(addr, user); break;
7542
                case 4: tmp = gen_ld8s(addr, user); break;
7543
                case 1: tmp = gen_ld16u(addr, user); break;
7544
                case 5: tmp = gen_ld16s(addr, user); break;
7545
                case 2: tmp = gen_ld32(addr, user); break;
7546
                default: goto illegal_op;
7547
                }
7548
                if (rs == 15) {
7549
                    gen_bx(s, tmp);
7550
                } else {
7551
                    store_reg(s, rs, tmp);
7552
                }
7553
            }
7554
        } else {
7555
            /* Store.  */
7556
            if (rs == 15)
7557
                goto illegal_op;
7558
            tmp = load_reg(s, rs);
7559
            switch (op) {
7560
            case 0: gen_st8(tmp, addr, user); break;
7561
            case 1: gen_st16(tmp, addr, user); break;
7562
            case 2: gen_st32(tmp, addr, user); break;
7563
            default: goto illegal_op;
7564
            }
7565
        }
7566
        if (postinc)
7567
            tcg_gen_addi_i32(addr, addr, imm);
7568
        if (writeback) {
7569
            store_reg(s, rn, addr);
7570
        } else {
7571
            dead_tmp(addr);
7572
        }
7573
        }
7574
        break;
7575
    default:
7576
        goto illegal_op;
7577
    }
7578
    return 0;
7579
illegal_op:
7580
    return 1;
7581
}
7582

    
7583
static void disas_thumb_insn(CPUState *env, DisasContext *s)
7584
{
7585
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
7586
    int32_t offset;
7587
    int i;
7588
    TCGv tmp;
7589
    TCGv tmp2;
7590
    TCGv addr;
7591

    
7592
    if (s->condexec_mask) {
7593
        cond = s->condexec_cond;
7594
        s->condlabel = gen_new_label();
7595
        gen_test_cc(cond ^ 1, s->condlabel);
7596
        s->condjmp = 1;
7597
    }
7598

    
7599
    insn = lduw_code(s->pc);
7600
    s->pc += 2;
7601

    
7602
    switch (insn >> 12) {
7603
    case 0: case 1:
7604
        rd = insn & 7;
7605
        op = (insn >> 11) & 3;
7606
        if (op == 3) {
7607
            /* add/subtract */
7608
            rn = (insn >> 3) & 7;
7609
            gen_movl_T0_reg(s, rn);
7610
            if (insn & (1 << 10)) {
7611
                /* immediate */
7612
                gen_op_movl_T1_im((insn >> 6) & 7);
7613
            } else {
7614
                /* reg */
7615
                rm = (insn >> 6) & 7;
7616
                gen_movl_T1_reg(s, rm);
7617
            }
7618
            if (insn & (1 << 9)) {
7619
                if (s->condexec_mask)
7620
                    gen_op_subl_T0_T1();
7621
                else
7622
                    gen_op_subl_T0_T1_cc();
7623
            } else {
7624
                if (s->condexec_mask)
7625
                    gen_op_addl_T0_T1();
7626
                else
7627
                    gen_op_addl_T0_T1_cc();
7628
            }
7629
            gen_movl_reg_T0(s, rd);
7630
        } else {
7631
            /* shift immediate */
7632
            rm = (insn >> 3) & 7;
7633
            shift = (insn >> 6) & 0x1f;
7634
            tmp = load_reg(s, rm);
7635
            gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
7636
            if (!s->condexec_mask)
7637
                gen_logic_CC(tmp);
7638
            store_reg(s, rd, tmp);
7639
        }
7640
        break;
7641
    case 2: case 3:
7642
        /* arithmetic large immediate */
7643
        op = (insn >> 11) & 3;
7644
        rd = (insn >> 8) & 0x7;
7645
        if (op == 0) {
7646
            gen_op_movl_T0_im(insn & 0xff);
7647
        } else {
7648
            gen_movl_T0_reg(s, rd);
7649
            gen_op_movl_T1_im(insn & 0xff);
7650
        }
7651
        switch (op) {
7652
        case 0: /* mov */
7653
            if (!s->condexec_mask)
7654
                gen_op_logic_T0_cc();
7655
            break;
7656
        case 1: /* cmp */
7657
            gen_op_subl_T0_T1_cc();
7658
            break;
7659
        case 2: /* add */
7660
            if (s->condexec_mask)
7661
                gen_op_addl_T0_T1();
7662
            else
7663
                gen_op_addl_T0_T1_cc();
7664
            break;
7665
        case 3: /* sub */
7666
            if (s->condexec_mask)
7667
                gen_op_subl_T0_T1();
7668
            else
7669
                gen_op_subl_T0_T1_cc();
7670
            break;
7671
        }
7672
        if (op != 1)
7673
            gen_movl_reg_T0(s, rd);
7674
        break;
7675
    case 4:
7676
        if (insn & (1 << 11)) {
7677
            rd = (insn >> 8) & 7;
7678
            /* load pc-relative.  Bit 1 of PC is ignored.  */
7679
            val = s->pc + 2 + ((insn & 0xff) * 4);
7680
            val &= ~(uint32_t)2;
7681
            addr = new_tmp();
7682
            tcg_gen_movi_i32(addr, val);
7683
            tmp = gen_ld32(addr, IS_USER(s));
7684
            dead_tmp(addr);
7685
            store_reg(s, rd, tmp);
7686
            break;
7687
        }
7688
        if (insn & (1 << 10)) {
7689
            /* data processing extended or blx */
7690
            rd = (insn & 7) | ((insn >> 4) & 8);
7691
            rm = (insn >> 3) & 0xf;
7692
            op = (insn >> 8) & 3;
7693
            switch (op) {
7694
            case 0: /* add */
7695
                gen_movl_T0_reg(s, rd);
7696
                gen_movl_T1_reg(s, rm);
7697
                gen_op_addl_T0_T1();
7698
                gen_movl_reg_T0(s, rd);
7699
                break;
7700
            case 1: /* cmp */
7701
                gen_movl_T0_reg(s, rd);
7702
                gen_movl_T1_reg(s, rm);
7703
                gen_op_subl_T0_T1_cc();
7704
                break;
7705
            case 2: /* mov/cpy */
7706
                gen_movl_T0_reg(s, rm);
7707
                gen_movl_reg_T0(s, rd);
7708
                break;
7709
            case 3:/* branch [and link] exchange thumb register */
7710
                tmp = load_reg(s, rm);
7711
                if (insn & (1 << 7)) {
7712
                    val = (uint32_t)s->pc | 1;
7713
                    tmp2 = new_tmp();
7714
                    tcg_gen_movi_i32(tmp2, val);
7715
                    store_reg(s, 14, tmp2);
7716
                }
7717
                gen_bx(s, tmp);
7718
                break;
7719
            }
7720
            break;
7721
        }
7722

    
7723
        /* data processing register */
7724
        rd = insn & 7;
7725
        rm = (insn >> 3) & 7;
7726
        op = (insn >> 6) & 0xf;
7727
        if (op == 2 || op == 3 || op == 4 || op == 7) {
7728
            /* the shift/rotate ops want the operands backwards */
7729
            val = rm;
7730
            rm = rd;
7731
            rd = val;
7732
            val = 1;
7733
        } else {
7734
            val = 0;
7735
        }
7736

    
7737
        if (op == 9) /* neg */
7738
            gen_op_movl_T0_im(0);
7739
        else if (op != 0xf) /* mvn doesn't read its first operand */
7740
            gen_movl_T0_reg(s, rd);
7741

    
7742
        gen_movl_T1_reg(s, rm);
7743
        switch (op) {
7744
        case 0x0: /* and */
7745
            gen_op_andl_T0_T1();
7746
            if (!s->condexec_mask)
7747
                gen_op_logic_T0_cc();
7748
            break;
7749
        case 0x1: /* eor */
7750
            gen_op_xorl_T0_T1();
7751
            if (!s->condexec_mask)
7752
                gen_op_logic_T0_cc();
7753
            break;
7754
        case 0x2: /* lsl */
7755
            if (s->condexec_mask) {
7756
                gen_op_shll_T1_T0();
7757
            } else {
7758
                gen_op_shll_T1_T0_cc();
7759
                gen_op_logic_T1_cc();
7760
            }
7761
            break;
7762
        case 0x3: /* lsr */
7763
            if (s->condexec_mask) {
7764
                gen_op_shrl_T1_T0();
7765
            } else {
7766
                gen_op_shrl_T1_T0_cc();
7767
                gen_op_logic_T1_cc();
7768
            }
7769
            break;
7770
        case 0x4: /* asr */
7771
            if (s->condexec_mask) {
7772
                gen_op_sarl_T1_T0();
7773
            } else {
7774
                gen_op_sarl_T1_T0_cc();
7775
                gen_op_logic_T1_cc();
7776
            }
7777
            break;
7778
        case 0x5: /* adc */
7779
            if (s->condexec_mask)
7780
                gen_adc_T0_T1();
7781
            else
7782
                gen_op_adcl_T0_T1_cc();
7783
            break;
7784
        case 0x6: /* sbc */
7785
            if (s->condexec_mask)
7786
                gen_sbc_T0_T1();
7787
            else
7788
                gen_op_sbcl_T0_T1_cc();
7789
            break;
7790
        case 0x7: /* ror */
7791
            if (s->condexec_mask) {
7792
                gen_op_rorl_T1_T0();
7793
            } else {
7794
                gen_op_rorl_T1_T0_cc();
7795
                gen_op_logic_T1_cc();
7796
            }
7797
            break;
7798
        case 0x8: /* tst */
7799
            gen_op_andl_T0_T1();
7800
            gen_op_logic_T0_cc();
7801
            rd = 16;
7802
            break;
7803
        case 0x9: /* neg */
7804
            if (s->condexec_mask)
7805
                gen_op_subl_T0_T1();
7806
            else
7807
                gen_op_subl_T0_T1_cc();
7808
            break;
7809
        case 0xa: /* cmp */
7810
            gen_op_subl_T0_T1_cc();
7811
            rd = 16;
7812
            break;
7813
        case 0xb: /* cmn */
7814
            gen_op_addl_T0_T1_cc();
7815
            rd = 16;
7816
            break;
7817
        case 0xc: /* orr */
7818
            gen_op_orl_T0_T1();
7819
            if (!s->condexec_mask)
7820
                gen_op_logic_T0_cc();
7821
            break;
7822
        case 0xd: /* mul */
7823
            gen_op_mull_T0_T1();
7824
            if (!s->condexec_mask)
7825
                gen_op_logic_T0_cc();
7826
            break;
7827
        case 0xe: /* bic */
7828
            gen_op_bicl_T0_T1();
7829
            if (!s->condexec_mask)
7830
                gen_op_logic_T0_cc();
7831
            break;
7832
        case 0xf: /* mvn */
7833
            gen_op_notl_T1();
7834
            if (!s->condexec_mask)
7835
                gen_op_logic_T1_cc();
7836
            val = 1;
7837
            rm = rd;
7838
            break;
7839
        }
7840
        if (rd != 16) {
7841
            if (val)
7842
                gen_movl_reg_T1(s, rm);
7843
            else
7844
                gen_movl_reg_T0(s, rd);
7845
        }
7846
        break;
7847

    
7848
    case 5:
7849
        /* load/store register offset.  */
7850
        rd = insn & 7;
7851
        rn = (insn >> 3) & 7;
7852
        rm = (insn >> 6) & 7;
7853
        op = (insn >> 9) & 7;
7854
        addr = load_reg(s, rn);
7855
        tmp = load_reg(s, rm);
7856
        tcg_gen_add_i32(addr, addr, tmp);
7857
        dead_tmp(tmp);
7858

    
7859
        if (op < 3) /* store */
7860
            tmp = load_reg(s, rd);
7861

    
7862
        switch (op) {
7863
        case 0: /* str */
7864
            gen_st32(tmp, addr, IS_USER(s));
7865
            break;
7866
        case 1: /* strh */
7867
            gen_st16(tmp, addr, IS_USER(s));
7868
            break;
7869
        case 2: /* strb */
7870
            gen_st8(tmp, addr, IS_USER(s));
7871
            break;
7872
        case 3: /* ldrsb */
7873
            tmp = gen_ld8s(addr, IS_USER(s));
7874
            break;
7875
        case 4: /* ldr */
7876
            tmp = gen_ld32(addr, IS_USER(s));
7877
            break;
7878
        case 5: /* ldrh */
7879
            tmp = gen_ld16u(addr, IS_USER(s));
7880
            break;
7881
        case 6: /* ldrb */
7882
            tmp = gen_ld8u(addr, IS_USER(s));
7883
            break;
7884
        case 7: /* ldrsh */
7885
            tmp = gen_ld16s(addr, IS_USER(s));
7886
            break;
7887
        }
7888
        if (op >= 3) /* load */
7889
            store_reg(s, rd, tmp);
7890
        dead_tmp(addr);
7891
        break;
7892

    
7893
    case 6:
7894
        /* load/store word immediate offset */
7895
        rd = insn & 7;
7896
        rn = (insn >> 3) & 7;
7897
        addr = load_reg(s, rn);
7898
        val = (insn >> 4) & 0x7c;
7899
        tcg_gen_addi_i32(addr, addr, val);
7900

    
7901
        if (insn & (1 << 11)) {
7902
            /* load */
7903
            tmp = gen_ld32(addr, IS_USER(s));
7904
            store_reg(s, rd, tmp);
7905
        } else {
7906
            /* store */
7907
            tmp = load_reg(s, rd);
7908
            gen_st32(tmp, addr, IS_USER(s));
7909
        }
7910
        dead_tmp(addr);
7911
        break;
7912

    
7913
    case 7:
7914
        /* load/store byte immediate offset */
7915
        rd = insn & 7;
7916
        rn = (insn >> 3) & 7;
7917
        addr = load_reg(s, rn);
7918
        val = (insn >> 6) & 0x1f;
7919
        tcg_gen_addi_i32(addr, addr, val);
7920

    
7921
        if (insn & (1 << 11)) {
7922
            /* load */
7923
            tmp = gen_ld8u(addr, IS_USER(s));
7924
            store_reg(s, rd, tmp);
7925
        } else {
7926
            /* store */
7927
            tmp = load_reg(s, rd);
7928
            gen_st8(tmp, addr, IS_USER(s));
7929
        }
7930
        dead_tmp(addr);
7931
        break;
7932

    
7933
    case 8:
7934
        /* load/store halfword immediate offset */
7935
        rd = insn & 7;
7936
        rn = (insn >> 3) & 7;
7937
        addr = load_reg(s, rn);
7938
        val = (insn >> 5) & 0x3e;
7939
        tcg_gen_addi_i32(addr, addr, val);
7940

    
7941
        if (insn & (1 << 11)) {
7942
            /* load */
7943
            tmp = gen_ld16u(addr, IS_USER(s));
7944
            store_reg(s, rd, tmp);
7945
        } else {
7946
            /* store */
7947
            tmp = load_reg(s, rd);
7948
            gen_st16(tmp, addr, IS_USER(s));
7949
        }
7950
        dead_tmp(addr);
7951
        break;
7952

    
7953
    case 9:
7954
        /* load/store from stack */
7955
        rd = (insn >> 8) & 7;
7956
        addr = load_reg(s, 13);
7957
        val = (insn & 0xff) * 4;
7958
        tcg_gen_addi_i32(addr, addr, val);
7959

    
7960
        if (insn & (1 << 11)) {
7961
            /* load */
7962
            tmp = gen_ld32(addr, IS_USER(s));
7963
            store_reg(s, rd, tmp);
7964
        } else {
7965
            /* store */
7966
            tmp = load_reg(s, rd);
7967
            gen_st32(tmp, addr, IS_USER(s));
7968
        }
7969
        dead_tmp(addr);
7970
        break;
7971

    
7972
    case 10:
7973
        /* add to high reg */
7974
        rd = (insn >> 8) & 7;
7975
        if (insn & (1 << 11)) {
7976
            /* SP */
7977
            tmp = load_reg(s, 13);
7978
        } else {
7979
            /* PC. bit 1 is ignored.  */
7980
            tmp = new_tmp();
7981
            tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
7982
        }
7983
        val = (insn & 0xff) * 4;
7984
        tcg_gen_addi_i32(tmp, tmp, val);
7985
        store_reg(s, rd, tmp);
7986
        break;
7987

    
7988
    case 11:
7989
        /* misc */
7990
        op = (insn >> 8) & 0xf;
7991
        switch (op) {
7992
        case 0:
7993
            /* adjust stack pointer */
7994
            tmp = load_reg(s, 13);
7995
            val = (insn & 0x7f) * 4;
7996
            if (insn & (1 << 7))
7997
              val = -(int32_t)val;
7998
            tcg_gen_addi_i32(tmp, tmp, val);
7999
            store_reg(s, 13, tmp);
8000
            break;
8001

    
8002
        case 2: /* sign/zero extend.  */
8003
            ARCH(6);
8004
            rd = insn & 7;
8005
            rm = (insn >> 3) & 7;
8006
            tmp = load_reg(s, rm);
8007
            switch ((insn >> 6) & 3) {
8008
            case 0: gen_sxth(tmp); break;
8009
            case 1: gen_sxtb(tmp); break;
8010
            case 2: gen_uxth(tmp); break;
8011
            case 3: gen_uxtb(tmp); break;
8012
            }
8013
            store_reg(s, rd, tmp);
8014
            break;
8015
        case 4: case 5: case 0xc: case 0xd:
8016
            /* push/pop */
8017
            addr = load_reg(s, 13);
8018
            if (insn & (1 << 8))
8019
                offset = 4;
8020
            else
8021
                offset = 0;
8022
            for (i = 0; i < 8; i++) {
8023
                if (insn & (1 << i))
8024
                    offset += 4;
8025
            }
8026
            if ((insn & (1 << 11)) == 0) {
8027
                tcg_gen_addi_i32(addr, addr, -offset);
8028
            }
8029
            for (i = 0; i < 8; i++) {
8030
                if (insn & (1 << i)) {
8031
                    if (insn & (1 << 11)) {
8032
                        /* pop */
8033
                        tmp = gen_ld32(addr, IS_USER(s));
8034
                        store_reg(s, i, tmp);
8035
                    } else {
8036
                        /* push */
8037
                        tmp = load_reg(s, i);
8038
                        gen_st32(tmp, addr, IS_USER(s));
8039
                    }
8040
                    /* advance to the next address.  */
8041
                    tcg_gen_addi_i32(addr, addr, 4);
8042
                }
8043
            }
8044
            if (insn & (1 << 8)) {
8045
                if (insn & (1 << 11)) {
8046
                    /* pop pc */
8047
                    tmp = gen_ld32(addr, IS_USER(s));
8048
                    /* don't set the pc until the rest of the instruction
8049
                       has completed */
8050
                } else {
8051
                    /* push lr */
8052
                    tmp = load_reg(s, 14);
8053
                    gen_st32(tmp, addr, IS_USER(s));
8054
                }
8055
                tcg_gen_addi_i32(addr, addr, 4);
8056
            }
8057
            if ((insn & (1 << 11)) == 0) {
8058
                tcg_gen_addi_i32(addr, addr, -offset);
8059
            }
8060
            /* write back the new stack pointer */
8061
            store_reg(s, 13, addr);
8062
            /* set the new PC value */
8063
            if ((insn & 0x0900) == 0x0900)
8064
                gen_bx(s, tmp);
8065
            break;
8066

    
8067
        case 1: case 3: case 9: case 11: /* czb */
8068
            rm = insn & 7;
8069
            tmp = load_reg(s, rm);
8070
            tmp2 = tcg_const_i32(0);
8071
            s->condlabel = gen_new_label();
8072
            s->condjmp = 1;
8073
            if (insn & (1 << 11))
8074
                tcg_gen_brcond_i32(TCG_COND_EQ, tmp, tmp2, s->condlabel);
8075
            else
8076
                tcg_gen_brcond_i32(TCG_COND_NE, tmp, tmp2, s->condlabel);
8077
            dead_tmp(tmp);
8078
            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8079
            val = (uint32_t)s->pc + 2;
8080
            val += offset;
8081
            gen_jmp(s, val);
8082
            break;
8083

    
8084
        case 15: /* IT, nop-hint.  */
8085
            if ((insn & 0xf) == 0) {
8086
                gen_nop_hint(s, (insn >> 4) & 0xf);
8087
                break;
8088
            }
8089
            /* If Then.  */
8090
            s->condexec_cond = (insn >> 4) & 0xe;
8091
            s->condexec_mask = insn & 0x1f;
8092
            /* No actual code generated for this insn, just setup state.  */
8093
            break;
8094

    
8095
        case 0xe: /* bkpt */
8096
            gen_set_condexec(s);
8097
            gen_set_pc_im(s->pc - 2);
8098
            gen_exception(EXCP_BKPT);
8099
            s->is_jmp = DISAS_JUMP;
8100
            break;
8101

    
8102
        case 0xa: /* rev */
8103
            ARCH(6);
8104
            rn = (insn >> 3) & 0x7;
8105
            rd = insn & 0x7;
8106
            tmp = load_reg(s, rn);
8107
            switch ((insn >> 6) & 3) {
8108
            case 0: tcg_gen_bswap_i32(tmp, tmp); break;
8109
            case 1: gen_rev16(tmp); break;
8110
            case 3: gen_revsh(tmp); break;
8111
            default: goto illegal_op;
8112
            }
8113
            store_reg(s, rd, tmp);
8114
            break;
8115

    
8116
        case 6: /* cps */
8117
            ARCH(6);
8118
            if (IS_USER(s))
8119
                break;
8120
            if (IS_M(env)) {
8121
                val = (insn & (1 << 4)) != 0;
8122
                gen_op_movl_T0_im(val);
8123
                /* PRIMASK */
8124
                if (insn & 1)
8125
                    gen_op_v7m_msr_T0(16);
8126
                /* FAULTMASK */
8127
                if (insn & 2)
8128
                    gen_op_v7m_msr_T0(17);
8129

    
8130
                gen_lookup_tb(s);
8131
            } else {
8132
                if (insn & (1 << 4))
8133
                    shift = CPSR_A | CPSR_I | CPSR_F;
8134
                else
8135
                    shift = 0;
8136

    
8137
                val = ((insn & 7) << 6) & shift;
8138
                gen_op_movl_T0_im(val);
8139
                gen_set_psr_T0(s, shift, 0);
8140
            }
8141
            break;
8142

    
8143
        default:
8144
            goto undef;
8145
        }
8146
        break;
8147

    
8148
    case 12:
8149
        /* load/store multiple */
8150
        rn = (insn >> 8) & 0x7;
8151
        addr = load_reg(s, rn);
8152
        for (i = 0; i < 8; i++) {
8153
            if (insn & (1 << i)) {
8154
                if (insn & (1 << 11)) {
8155
                    /* load */
8156
                    tmp = gen_ld32(addr, IS_USER(s));
8157
                    store_reg(s, i, tmp);
8158
                } else {
8159
                    /* store */
8160
                    tmp = load_reg(s, i);
8161
                    gen_st32(tmp, addr, IS_USER(s));
8162
                }
8163
                /* advance to the next address */
8164
                tcg_gen_addi_i32(addr, addr, 4);
8165
            }
8166
        }
8167
        /* Base register writeback.  */
8168
        if ((insn & (1 << rn)) == 0) {
8169
            store_reg(s, rn, addr);
8170
        } else {
8171
            dead_tmp(addr);
8172
        }
8173
        break;
8174

    
8175
    case 13:
8176
        /* conditional branch or swi */
8177
        cond = (insn >> 8) & 0xf;
8178
        if (cond == 0xe)
8179
            goto undef;
8180

    
8181
        if (cond == 0xf) {
8182
            /* swi */
8183
            gen_set_condexec(s);
8184
            gen_set_pc_im(s->pc | 1);
8185
            s->is_jmp = DISAS_SWI;
8186
            break;
8187
        }
8188
        /* generate a conditional jump to next instruction */
8189
        s->condlabel = gen_new_label();
8190
        gen_test_cc(cond ^ 1, s->condlabel);
8191
        s->condjmp = 1;
8192
        gen_movl_T1_reg(s, 15);
8193

    
8194
        /* jump to the offset */
8195
        val = (uint32_t)s->pc + 2;
8196
        offset = ((int32_t)insn << 24) >> 24;
8197
        val += offset << 1;
8198
        gen_jmp(s, val);
8199
        break;
8200

    
8201
    case 14:
8202
        if (insn & (1 << 11)) {
8203
            if (disas_thumb2_insn(env, s, insn))
8204
              goto undef32;
8205
            break;
8206
        }
8207
        /* unconditional branch */
8208
        val = (uint32_t)s->pc;
8209
        offset = ((int32_t)insn << 21) >> 21;
8210
        val += (offset << 1) + 2;
8211
        gen_jmp(s, val);
8212
        break;
8213

    
8214
    case 15:
8215
        if (disas_thumb2_insn(env, s, insn))
8216
          goto undef32;
8217
        break;
8218
    }
8219
    return;
8220
undef32:
8221
    gen_set_condexec(s);
8222
    gen_set_pc_im(s->pc - 4);
8223
    gen_exception(EXCP_UDEF);
8224
    s->is_jmp = DISAS_JUMP;
8225
    return;
8226
illegal_op:
8227
undef:
8228
    gen_set_condexec(s);
8229
    gen_set_pc_im(s->pc - 2);
8230
    gen_exception(EXCP_UDEF);
8231
    s->is_jmp = DISAS_JUMP;
8232
}
8233

    
8234
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8235
   basic block 'tb'. If search_pc is TRUE, also generate PC
8236
   information for each intermediate instruction. */
8237
static inline int gen_intermediate_code_internal(CPUState *env,
8238
                                                 TranslationBlock *tb,
8239
                                                 int search_pc)
8240
{
8241
    DisasContext dc1, *dc = &dc1;
8242
    uint16_t *gen_opc_end;
8243
    int j, lj;
8244
    target_ulong pc_start;
8245
    uint32_t next_page_start;
8246

    
8247
    /* generate intermediate code */
8248
    num_temps = 0;
8249
    memset(temps, 0, sizeof(temps));
8250

    
8251
    pc_start = tb->pc;
8252

    
8253
    dc->tb = tb;
8254

    
8255
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8256

    
8257
    dc->is_jmp = DISAS_NEXT;
8258
    dc->pc = pc_start;
8259
    dc->singlestep_enabled = env->singlestep_enabled;
8260
    dc->condjmp = 0;
8261
    dc->thumb = env->thumb;
8262
    dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8263
    dc->condexec_cond = env->condexec_bits >> 4;
8264
    dc->is_mem = 0;
8265
#if !defined(CONFIG_USER_ONLY)
8266
    if (IS_M(env)) {
8267
        dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8268
    } else {
8269
        dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8270
    }
8271
#endif
8272
    cpu_F0s = tcg_temp_new(TCG_TYPE_I32);
8273
    cpu_F1s = tcg_temp_new(TCG_TYPE_I32);
8274
    cpu_F0d = tcg_temp_new(TCG_TYPE_I64);
8275
    cpu_F1d = tcg_temp_new(TCG_TYPE_I64);
8276
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8277
    lj = -1;
8278
    /* Reset the conditional execution bits immediately. This avoids
8279
       complications trying to do it at the end of the block.  */
8280
    if (env->condexec_bits)
8281
      {
8282
        TCGv tmp = new_tmp();
8283
        tcg_gen_movi_i32(tmp, 0);
8284
        store_cpu_field(tmp, condexec_bits);
8285
      }
8286
    do {
8287
#ifndef CONFIG_USER_ONLY
8288
        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8289
            /* We always get here via a jump, so know we are not in a
8290
               conditional execution block.  */
8291
            gen_exception(EXCP_EXCEPTION_EXIT);
8292
        }
8293
#endif
8294

    
8295
        if (env->nb_breakpoints > 0) {
8296
            for(j = 0; j < env->nb_breakpoints; j++) {
8297
                if (env->breakpoints[j] == dc->pc) {
8298
                    gen_set_condexec(dc);
8299
                    gen_set_pc_im(dc->pc);
8300
                    gen_exception(EXCP_DEBUG);
8301
                    dc->is_jmp = DISAS_JUMP;
8302
                    /* Advance PC so that clearing the breakpoint will
8303
                       invalidate this TB.  */
8304
                    dc->pc += 2;
8305
                    goto done_generating;
8306
                    break;
8307
                }
8308
            }
8309
        }
8310
        if (search_pc) {
8311
            j = gen_opc_ptr - gen_opc_buf;
8312
            if (lj < j) {
8313
                lj++;
8314
                while (lj < j)
8315
                    gen_opc_instr_start[lj++] = 0;
8316
            }
8317
            gen_opc_pc[lj] = dc->pc;
8318
            gen_opc_instr_start[lj] = 1;
8319
        }
8320

    
8321
        if (env->thumb) {
8322
            disas_thumb_insn(env, dc);
8323
            if (dc->condexec_mask) {
8324
                dc->condexec_cond = (dc->condexec_cond & 0xe)
8325
                                   | ((dc->condexec_mask >> 4) & 1);
8326
                dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8327
                if (dc->condexec_mask == 0) {
8328
                    dc->condexec_cond = 0;
8329
                }
8330
            }
8331
        } else {
8332
            disas_arm_insn(env, dc);
8333
        }
8334
        if (num_temps) {
8335
            fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8336
            num_temps = 0;
8337
        }
8338

    
8339
        if (dc->condjmp && !dc->is_jmp) {
8340
            gen_set_label(dc->condlabel);
8341
            dc->condjmp = 0;
8342
        }
8343
        /* Terminate the TB on memory ops if watchpoints are present.  */
8344
        /* FIXME: This should be replacd by the deterministic execution
8345
         * IRQ raising bits.  */
8346
        if (dc->is_mem && env->nb_watchpoints)
8347
            break;
8348

    
8349
        /* Translation stops when a conditional branch is enoutered.
8350
         * Otherwise the subsequent code could get translated several times.
8351
         * Also stop translation when a page boundary is reached.  This
8352
         * ensures prefech aborts occur at the right place.  */
8353
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8354
             !env->singlestep_enabled &&
8355
             dc->pc < next_page_start);
8356

    
8357
    /* At this stage dc->condjmp will only be set when the skipped
8358
       instruction was a conditional branch or trap, and the PC has
8359
       already been written.  */
8360
    if (__builtin_expect(env->singlestep_enabled, 0)) {
8361
        /* Make sure the pc is updated, and raise a debug exception.  */
8362
        if (dc->condjmp) {
8363
            gen_set_condexec(dc);
8364
            if (dc->is_jmp == DISAS_SWI) {
8365
                gen_exception(EXCP_SWI);
8366
            } else {
8367
                gen_exception(EXCP_DEBUG);
8368
            }
8369
            gen_set_label(dc->condlabel);
8370
        }
8371
        if (dc->condjmp || !dc->is_jmp) {
8372
            gen_set_pc_im(dc->pc);
8373
            dc->condjmp = 0;
8374
        }
8375
        gen_set_condexec(dc);
8376
        if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8377
            gen_exception(EXCP_SWI);
8378
        } else {
8379
            /* FIXME: Single stepping a WFI insn will not halt
8380
               the CPU.  */
8381
            gen_exception(EXCP_DEBUG);
8382
        }
8383
    } else {
8384
        /* While branches must always occur at the end of an IT block,
8385
           there are a few other things that can cause us to terminate
8386
           the TB in the middel of an IT block:
8387
            - Exception generating instructions (bkpt, swi, undefined).
8388
            - Page boundaries.
8389
            - Hardware watchpoints.
8390
           Hardware breakpoints have already been handled and skip this code.
8391
         */
8392
        gen_set_condexec(dc);
8393
        switch(dc->is_jmp) {
8394
        case DISAS_NEXT:
8395
            gen_goto_tb(dc, 1, dc->pc);
8396
            break;
8397
        default:
8398
        case DISAS_JUMP:
8399
        case DISAS_UPDATE:
8400
            /* indicate that the hash table must be used to find the next TB */
8401
            tcg_gen_exit_tb(0);
8402
            break;
8403
        case DISAS_TB_JUMP:
8404
            /* nothing more to generate */
8405
            break;
8406
        case DISAS_WFI:
8407
            gen_helper_wfi();
8408
            break;
8409
        case DISAS_SWI:
8410
            gen_exception(EXCP_SWI);
8411
            break;
8412
        }
8413
        if (dc->condjmp) {
8414
            gen_set_label(dc->condlabel);
8415
            gen_set_condexec(dc);
8416
            gen_goto_tb(dc, 1, dc->pc);
8417
            dc->condjmp = 0;
8418
        }
8419
    }
8420
done_generating:
8421
    *gen_opc_ptr = INDEX_op_end;
8422

    
8423
#ifdef DEBUG_DISAS
8424
    if (loglevel & CPU_LOG_TB_IN_ASM) {
8425
        fprintf(logfile, "----------------\n");
8426
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
8427
        target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
8428
        fprintf(logfile, "\n");
8429
    }
8430
#endif
8431
    if (search_pc) {
8432
        j = gen_opc_ptr - gen_opc_buf;
8433
        lj++;
8434
        while (lj <= j)
8435
            gen_opc_instr_start[lj++] = 0;
8436
    } else {
8437
        tb->size = dc->pc - pc_start;
8438
    }
8439
    return 0;
8440
}
8441

    
8442
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
8443
{
8444
    return gen_intermediate_code_internal(env, tb, 0);
8445
}
8446

    
8447
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
8448
{
8449
    return gen_intermediate_code_internal(env, tb, 1);
8450
}
8451

    
8452
static const char *cpu_mode_names[16] = {
8453
  "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8454
  "???", "???", "???", "und", "???", "???", "???", "sys"
8455
};
8456

    
8457
void cpu_dump_state(CPUState *env, FILE *f,
8458
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8459
                    int flags)
8460
{
8461
    int i;
8462
    union {
8463
        uint32_t i;
8464
        float s;
8465
    } s0, s1;
8466
    CPU_DoubleU d;
8467
    /* ??? This assumes float64 and double have the same layout.
8468
       Oh well, it's only debug dumps.  */
8469
    union {
8470
        float64 f64;
8471
        double d;
8472
    } d0;
8473
    uint32_t psr;
8474

    
8475
    for(i=0;i<16;i++) {
8476
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
8477
        if ((i % 4) == 3)
8478
            cpu_fprintf(f, "\n");
8479
        else
8480
            cpu_fprintf(f, " ");
8481
    }
8482
    psr = cpsr_read(env);
8483
    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
8484
                psr,
8485
                psr & (1 << 31) ? 'N' : '-',
8486
                psr & (1 << 30) ? 'Z' : '-',
8487
                psr & (1 << 29) ? 'C' : '-',
8488
                psr & (1 << 28) ? 'V' : '-',
8489
                psr & CPSR_T ? 'T' : 'A',
8490
                cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
8491

    
8492
#if 0
8493
    for (i = 0; i < 16; i++) {
8494
        d.d = env->vfp.regs[i];
8495
        s0.i = d.l.lower;
8496
        s1.i = d.l.upper;
8497
        d0.f64 = d.d;
8498
        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8499
                    i * 2, (int)s0.i, s0.s,
8500
                    i * 2 + 1, (int)s1.i, s1.s,
8501
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
8502
                    d0.d);
8503
    }
8504
    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
8505
#endif
8506
}
8507