Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 3b46e624

History | View | Annotate | Download (112.1 kB)

1
/*
2
 *  ARM translation
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *  Copyright (c) 2005 CodeSourcery, LLC
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

    
32
#define ENABLE_ARCH_5J  0
33
#define ENABLE_ARCH_6   1
34
#define ENABLE_ARCH_6T2 1
35

    
36
#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
37

    
38
/* internal defines */
39
typedef struct DisasContext {
40
    target_ulong pc;
41
    int is_jmp;
42
    /* Nonzero if this instruction has been conditionally skipped.  */
43
    int condjmp;
44
    /* The label that will be jumped to when the instruction is skipped.  */
45
    int condlabel;
46
    struct TranslationBlock *tb;
47
    int singlestep_enabled;
48
    int thumb;
49
    int is_mem;
50
#if !defined(CONFIG_USER_ONLY)
51
    int user;
52
#endif
53
} DisasContext;
54

    
55
#if defined(CONFIG_USER_ONLY)
56
#define IS_USER(s) 1
57
#else
58
#define IS_USER(s) (s->user)
59
#endif
60

    
61
#define DISAS_JUMP_NEXT 4
62

    
63
#ifdef USE_DIRECT_JUMP
64
#define TBPARAM(x)
65
#else
66
#define TBPARAM(x) (long)(x)
67
#endif
68

    
69
/* XXX: move that elsewhere */
70
static uint16_t *gen_opc_ptr;
71
static uint32_t *gen_opparam_ptr;
72
extern FILE *logfile;
73
extern int loglevel;
74

    
75
enum {
76
#define DEF(s, n, copy_size) INDEX_op_ ## s,
77
#include "opc.h"
78
#undef DEF
79
    NB_OPS,
80
};
81

    
82
#include "gen-op.h"
83

    
84
static GenOpFunc1 *gen_test_cc[14] = {
85
    gen_op_test_eq,
86
    gen_op_test_ne,
87
    gen_op_test_cs,
88
    gen_op_test_cc,
89
    gen_op_test_mi,
90
    gen_op_test_pl,
91
    gen_op_test_vs,
92
    gen_op_test_vc,
93
    gen_op_test_hi,
94
    gen_op_test_ls,
95
    gen_op_test_ge,
96
    gen_op_test_lt,
97
    gen_op_test_gt,
98
    gen_op_test_le,
99
};
100

    
101
const uint8_t table_logic_cc[16] = {
102
    1, /* and */
103
    1, /* xor */
104
    0, /* sub */
105
    0, /* rsb */
106
    0, /* add */
107
    0, /* adc */
108
    0, /* sbc */
109
    0, /* rsc */
110
    1, /* andl */
111
    1, /* xorl */
112
    0, /* cmp */
113
    0, /* cmn */
114
    1, /* orr */
115
    1, /* mov */
116
    1, /* bic */
117
    1, /* mvn */
118
};
119

    
120
static GenOpFunc1 *gen_shift_T1_im[4] = {
121
    gen_op_shll_T1_im,
122
    gen_op_shrl_T1_im,
123
    gen_op_sarl_T1_im,
124
    gen_op_rorl_T1_im,
125
};
126

    
127
static GenOpFunc *gen_shift_T1_0[4] = {
128
    NULL,
129
    gen_op_shrl_T1_0,
130
    gen_op_sarl_T1_0,
131
    gen_op_rrxl_T1,
132
};
133

    
134
static GenOpFunc1 *gen_shift_T2_im[4] = {
135
    gen_op_shll_T2_im,
136
    gen_op_shrl_T2_im,
137
    gen_op_sarl_T2_im,
138
    gen_op_rorl_T2_im,
139
};
140

    
141
static GenOpFunc *gen_shift_T2_0[4] = {
142
    NULL,
143
    gen_op_shrl_T2_0,
144
    gen_op_sarl_T2_0,
145
    gen_op_rrxl_T2,
146
};
147

    
148
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
149
    gen_op_shll_T1_im_cc,
150
    gen_op_shrl_T1_im_cc,
151
    gen_op_sarl_T1_im_cc,
152
    gen_op_rorl_T1_im_cc,
153
};
154

    
155
static GenOpFunc *gen_shift_T1_0_cc[4] = {
156
    NULL,
157
    gen_op_shrl_T1_0_cc,
158
    gen_op_sarl_T1_0_cc,
159
    gen_op_rrxl_T1_cc,
160
};
161

    
162
static GenOpFunc *gen_shift_T1_T0[4] = {
163
    gen_op_shll_T1_T0,
164
    gen_op_shrl_T1_T0,
165
    gen_op_sarl_T1_T0,
166
    gen_op_rorl_T1_T0,
167
};
168

    
169
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
170
    gen_op_shll_T1_T0_cc,
171
    gen_op_shrl_T1_T0_cc,
172
    gen_op_sarl_T1_T0_cc,
173
    gen_op_rorl_T1_T0_cc,
174
};
175

    
176
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
177
    {
178
        gen_op_movl_T0_r0,
179
        gen_op_movl_T0_r1,
180
        gen_op_movl_T0_r2,
181
        gen_op_movl_T0_r3,
182
        gen_op_movl_T0_r4,
183
        gen_op_movl_T0_r5,
184
        gen_op_movl_T0_r6,
185
        gen_op_movl_T0_r7,
186
        gen_op_movl_T0_r8,
187
        gen_op_movl_T0_r9,
188
        gen_op_movl_T0_r10,
189
        gen_op_movl_T0_r11,
190
        gen_op_movl_T0_r12,
191
        gen_op_movl_T0_r13,
192
        gen_op_movl_T0_r14,
193
        gen_op_movl_T0_r15,
194
    },
195
    {
196
        gen_op_movl_T1_r0,
197
        gen_op_movl_T1_r1,
198
        gen_op_movl_T1_r2,
199
        gen_op_movl_T1_r3,
200
        gen_op_movl_T1_r4,
201
        gen_op_movl_T1_r5,
202
        gen_op_movl_T1_r6,
203
        gen_op_movl_T1_r7,
204
        gen_op_movl_T1_r8,
205
        gen_op_movl_T1_r9,
206
        gen_op_movl_T1_r10,
207
        gen_op_movl_T1_r11,
208
        gen_op_movl_T1_r12,
209
        gen_op_movl_T1_r13,
210
        gen_op_movl_T1_r14,
211
        gen_op_movl_T1_r15,
212
    },
213
    {
214
        gen_op_movl_T2_r0,
215
        gen_op_movl_T2_r1,
216
        gen_op_movl_T2_r2,
217
        gen_op_movl_T2_r3,
218
        gen_op_movl_T2_r4,
219
        gen_op_movl_T2_r5,
220
        gen_op_movl_T2_r6,
221
        gen_op_movl_T2_r7,
222
        gen_op_movl_T2_r8,
223
        gen_op_movl_T2_r9,
224
        gen_op_movl_T2_r10,
225
        gen_op_movl_T2_r11,
226
        gen_op_movl_T2_r12,
227
        gen_op_movl_T2_r13,
228
        gen_op_movl_T2_r14,
229
        gen_op_movl_T2_r15,
230
    },
231
};
232

    
233
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
234
    {
235
        gen_op_movl_r0_T0,
236
        gen_op_movl_r1_T0,
237
        gen_op_movl_r2_T0,
238
        gen_op_movl_r3_T0,
239
        gen_op_movl_r4_T0,
240
        gen_op_movl_r5_T0,
241
        gen_op_movl_r6_T0,
242
        gen_op_movl_r7_T0,
243
        gen_op_movl_r8_T0,
244
        gen_op_movl_r9_T0,
245
        gen_op_movl_r10_T0,
246
        gen_op_movl_r11_T0,
247
        gen_op_movl_r12_T0,
248
        gen_op_movl_r13_T0,
249
        gen_op_movl_r14_T0,
250
        gen_op_movl_r15_T0,
251
    },
252
    {
253
        gen_op_movl_r0_T1,
254
        gen_op_movl_r1_T1,
255
        gen_op_movl_r2_T1,
256
        gen_op_movl_r3_T1,
257
        gen_op_movl_r4_T1,
258
        gen_op_movl_r5_T1,
259
        gen_op_movl_r6_T1,
260
        gen_op_movl_r7_T1,
261
        gen_op_movl_r8_T1,
262
        gen_op_movl_r9_T1,
263
        gen_op_movl_r10_T1,
264
        gen_op_movl_r11_T1,
265
        gen_op_movl_r12_T1,
266
        gen_op_movl_r13_T1,
267
        gen_op_movl_r14_T1,
268
        gen_op_movl_r15_T1,
269
    },
270
};
271

    
272
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
273
    gen_op_movl_T0_im,
274
    gen_op_movl_T1_im,
275
    gen_op_movl_T2_im,
276
};
277

    
278
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
279
    gen_op_shll_T0_im_thumb,
280
    gen_op_shrl_T0_im_thumb,
281
    gen_op_sarl_T0_im_thumb,
282
};
283

    
284
static inline void gen_bx(DisasContext *s)
285
{
286
  s->is_jmp = DISAS_UPDATE;
287
  gen_op_bx_T0();
288
}
289

    
290

    
291
#if defined(CONFIG_USER_ONLY)
292
#define gen_ldst(name, s) gen_op_##name##_raw()
293
#else
294
#define gen_ldst(name, s) do { \
295
    s->is_mem = 1; \
296
    if (IS_USER(s)) \
297
        gen_op_##name##_user(); \
298
    else \
299
        gen_op_##name##_kernel(); \
300
    } while (0)
301
#endif
302

    
303
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
304
{
305
    int val;
306

    
307
    if (reg == 15) {
308
        /* normaly, since we updated PC, we need only to add one insn */
309
        if (s->thumb)
310
            val = (long)s->pc + 2;
311
        else
312
            val = (long)s->pc + 4;
313
        gen_op_movl_TN_im[t](val);
314
    } else {
315
        gen_op_movl_TN_reg[t][reg]();
316
    }
317
}
318

    
319
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
320
{
321
    gen_movl_TN_reg(s, reg, 0);
322
}
323

    
324
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
325
{
326
    gen_movl_TN_reg(s, reg, 1);
327
}
328

    
329
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
330
{
331
    gen_movl_TN_reg(s, reg, 2);
332
}
333

    
334
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
335
{
336
    gen_op_movl_reg_TN[t][reg]();
337
    if (reg == 15) {
338
        s->is_jmp = DISAS_JUMP;
339
    }
340
}
341

    
342
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
343
{
344
    gen_movl_reg_TN(s, reg, 0);
345
}
346

    
347
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
348
{
349
    gen_movl_reg_TN(s, reg, 1);
350
}
351

    
352
/* Force a TB lookup after an instruction that changes the CPU state.  */
353
static inline void gen_lookup_tb(DisasContext *s)
354
{
355
    gen_op_movl_T0_im(s->pc);
356
    gen_movl_reg_T0(s, 15);
357
    s->is_jmp = DISAS_UPDATE;
358
}
359

    
360
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
361
{
362
    int val, rm, shift, shiftop;
363

    
364
    if (!(insn & (1 << 25))) {
365
        /* immediate */
366
        val = insn & 0xfff;
367
        if (!(insn & (1 << 23)))
368
            val = -val;
369
        if (val != 0)
370
            gen_op_addl_T1_im(val);
371
    } else {
372
        /* shift/register */
373
        rm = (insn) & 0xf;
374
        shift = (insn >> 7) & 0x1f;
375
        gen_movl_T2_reg(s, rm);
376
        shiftop = (insn >> 5) & 3;
377
        if (shift != 0) {
378
            gen_shift_T2_im[shiftop](shift);
379
        } else if (shiftop != 0) {
380
            gen_shift_T2_0[shiftop]();
381
        }
382
        if (!(insn & (1 << 23)))
383
            gen_op_subl_T1_T2();
384
        else
385
            gen_op_addl_T1_T2();
386
    }
387
}
388

    
389
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
390
                                        int extra)
391
{
392
    int val, rm;
393

    
394
    if (insn & (1 << 22)) {
395
        /* immediate */
396
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
397
        if (!(insn & (1 << 23)))
398
            val = -val;
399
        val += extra;
400
        if (val != 0)
401
            gen_op_addl_T1_im(val);
402
    } else {
403
        /* register */
404
        if (extra)
405
            gen_op_addl_T1_im(extra);
406
        rm = (insn) & 0xf;
407
        gen_movl_T2_reg(s, rm);
408
        if (!(insn & (1 << 23)))
409
            gen_op_subl_T1_T2();
410
        else
411
            gen_op_addl_T1_T2();
412
    }
413
}
414

    
415
#define VFP_OP(name)                      \
416
static inline void gen_vfp_##name(int dp) \
417
{                                         \
418
    if (dp)                               \
419
        gen_op_vfp_##name##d();           \
420
    else                                  \
421
        gen_op_vfp_##name##s();           \
422
}
423

    
424
VFP_OP(add)
425
VFP_OP(sub)
426
VFP_OP(mul)
427
VFP_OP(div)
428
VFP_OP(neg)
429
VFP_OP(abs)
430
VFP_OP(sqrt)
431
VFP_OP(cmp)
432
VFP_OP(cmpe)
433
VFP_OP(F1_ld0)
434
VFP_OP(uito)
435
VFP_OP(sito)
436
VFP_OP(toui)
437
VFP_OP(touiz)
438
VFP_OP(tosi)
439
VFP_OP(tosiz)
440

    
441
#undef VFP_OP
442

    
443
static inline void gen_vfp_ld(DisasContext *s, int dp)
444
{
445
    if (dp)
446
        gen_ldst(vfp_ldd, s);
447
    else
448
        gen_ldst(vfp_lds, s);
449
}
450

    
451
static inline void gen_vfp_st(DisasContext *s, int dp)
452
{
453
    if (dp)
454
        gen_ldst(vfp_std, s);
455
    else
456
        gen_ldst(vfp_sts, s);
457
}
458

    
459
static inline long
460
vfp_reg_offset (int dp, int reg)
461
{
462
    if (dp)
463
        return offsetof(CPUARMState, vfp.regs[reg]);
464
    else if (reg & 1) {
465
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
466
          + offsetof(CPU_DoubleU, l.upper);
467
    } else {
468
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
469
          + offsetof(CPU_DoubleU, l.lower);
470
    }
471
}
472
static inline void gen_mov_F0_vreg(int dp, int reg)
473
{
474
    if (dp)
475
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
476
    else
477
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
478
}
479

    
480
static inline void gen_mov_F1_vreg(int dp, int reg)
481
{
482
    if (dp)
483
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
484
    else
485
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
486
}
487

    
488
static inline void gen_mov_vreg_F0(int dp, int reg)
489
{
490
    if (dp)
491
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
492
    else
493
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
494
}
495

    
496
#define ARM_CP_RW_BIT        (1 << 20)
497

    
498
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
499
{
500
    int rd;
501
    uint32_t offset;
502

    
503
    rd = (insn >> 16) & 0xf;
504
    gen_movl_T1_reg(s, rd);
505

    
506
    offset = (insn & 0xff) << ((insn >> 7) & 2);
507
    if (insn & (1 << 24)) {
508
        /* Pre indexed */
509
        if (insn & (1 << 23))
510
            gen_op_addl_T1_im(offset);
511
        else
512
            gen_op_addl_T1_im(-offset);
513

    
514
        if (insn & (1 << 21))
515
            gen_movl_reg_T1(s, rd);
516
    } else if (insn & (1 << 21)) {
517
        /* Post indexed */
518
        if (insn & (1 << 23))
519
            gen_op_movl_T0_im(offset);
520
        else
521
            gen_op_movl_T0_im(- offset);
522
        gen_op_addl_T0_T1();
523
        gen_movl_reg_T0(s, rd);
524
    } else if (!(insn & (1 << 23)))
525
        return 1;
526
    return 0;
527
}
528

    
529
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
530
{
531
    int rd = (insn >> 0) & 0xf;
532

    
533
    if (insn & (1 << 8))
534
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
535
            return 1;
536
        else
537
            gen_op_iwmmxt_movl_T0_wCx(rd);
538
    else
539
        gen_op_iwmmxt_movl_T0_T1_wRn(rd);
540

    
541
    gen_op_movl_T1_im(mask);
542
    gen_op_andl_T0_T1();
543
    return 0;
544
}
545

    
546
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
547
   (ie. an undefined instruction).  */
548
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
549
{
550
    int rd, wrd;
551
    int rdhi, rdlo, rd0, rd1, i;
552

    
553
    if ((insn & 0x0e000e00) == 0x0c000000) {
554
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
555
            wrd = insn & 0xf;
556
            rdlo = (insn >> 12) & 0xf;
557
            rdhi = (insn >> 16) & 0xf;
558
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
559
                gen_op_iwmmxt_movl_T0_T1_wRn(wrd);
560
                gen_movl_reg_T0(s, rdlo);
561
                gen_movl_reg_T1(s, rdhi);
562
            } else {                                        /* TMCRR */
563
                gen_movl_T0_reg(s, rdlo);
564
                gen_movl_T1_reg(s, rdhi);
565
                gen_op_iwmmxt_movl_wRn_T0_T1(wrd);
566
                gen_op_iwmmxt_set_mup();
567
            }
568
            return 0;
569
        }
570

    
571
        wrd = (insn >> 12) & 0xf;
572
        if (gen_iwmmxt_address(s, insn))
573
            return 1;
574
        if (insn & ARM_CP_RW_BIT) {
575
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
576
                gen_ldst(ldl, s);
577
                gen_op_iwmmxt_movl_wCx_T0(wrd);
578
            } else {
579
                if (insn & (1 << 8))
580
                    if (insn & (1 << 22))                /* WLDRD */
581
                        gen_ldst(iwmmxt_ldq, s);
582
                    else                                /* WLDRW wRd */
583
                        gen_ldst(iwmmxt_ldl, s);
584
                else
585
                    if (insn & (1 << 22))                /* WLDRH */
586
                        gen_ldst(iwmmxt_ldw, s);
587
                    else                                /* WLDRB */
588
                        gen_ldst(iwmmxt_ldb, s);
589
                gen_op_iwmmxt_movq_wRn_M0(wrd);
590
            }
591
        } else {
592
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
593
                gen_op_iwmmxt_movl_T0_wCx(wrd);
594
                gen_ldst(stl, s);
595
            } else {
596
                gen_op_iwmmxt_movq_M0_wRn(wrd);
597
                if (insn & (1 << 8))
598
                    if (insn & (1 << 22))                /* WSTRD */
599
                        gen_ldst(iwmmxt_stq, s);
600
                    else                                /* WSTRW wRd */
601
                        gen_ldst(iwmmxt_stl, s);
602
                else
603
                    if (insn & (1 << 22))                /* WSTRH */
604
                        gen_ldst(iwmmxt_ldw, s);
605
                    else                                /* WSTRB */
606
                        gen_ldst(iwmmxt_stb, s);
607
            }
608
        }
609
        return 0;
610
    }
611

    
612
    if ((insn & 0x0f000000) != 0x0e000000)
613
        return 1;
614

    
615
    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
616
    case 0x000:                                                /* WOR */
617
        wrd = (insn >> 12) & 0xf;
618
        rd0 = (insn >> 0) & 0xf;
619
        rd1 = (insn >> 16) & 0xf;
620
        gen_op_iwmmxt_movq_M0_wRn(rd0);
621
        gen_op_iwmmxt_orq_M0_wRn(rd1);
622
        gen_op_iwmmxt_setpsr_nz();
623
        gen_op_iwmmxt_movq_wRn_M0(wrd);
624
        gen_op_iwmmxt_set_mup();
625
        gen_op_iwmmxt_set_cup();
626
        break;
627
    case 0x011:                                                /* TMCR */
628
        if (insn & 0xf)
629
            return 1;
630
        rd = (insn >> 12) & 0xf;
631
        wrd = (insn >> 16) & 0xf;
632
        switch (wrd) {
633
        case ARM_IWMMXT_wCID:
634
        case ARM_IWMMXT_wCASF:
635
            break;
636
        case ARM_IWMMXT_wCon:
637
            gen_op_iwmmxt_set_cup();
638
            /* Fall through.  */
639
        case ARM_IWMMXT_wCSSF:
640
            gen_op_iwmmxt_movl_T0_wCx(wrd);
641
            gen_movl_T1_reg(s, rd);
642
            gen_op_bicl_T0_T1();
643
            gen_op_iwmmxt_movl_wCx_T0(wrd);
644
            break;
645
        case ARM_IWMMXT_wCGR0:
646
        case ARM_IWMMXT_wCGR1:
647
        case ARM_IWMMXT_wCGR2:
648
        case ARM_IWMMXT_wCGR3:
649
            gen_op_iwmmxt_set_cup();
650
            gen_movl_reg_T0(s, rd);
651
            gen_op_iwmmxt_movl_wCx_T0(wrd);
652
            break;
653
        default:
654
            return 1;
655
        }
656
        break;
657
    case 0x100:                                                /* WXOR */
658
        wrd = (insn >> 12) & 0xf;
659
        rd0 = (insn >> 0) & 0xf;
660
        rd1 = (insn >> 16) & 0xf;
661
        gen_op_iwmmxt_movq_M0_wRn(rd0);
662
        gen_op_iwmmxt_xorq_M0_wRn(rd1);
663
        gen_op_iwmmxt_setpsr_nz();
664
        gen_op_iwmmxt_movq_wRn_M0(wrd);
665
        gen_op_iwmmxt_set_mup();
666
        gen_op_iwmmxt_set_cup();
667
        break;
668
    case 0x111:                                                /* TMRC */
669
        if (insn & 0xf)
670
            return 1;
671
        rd = (insn >> 12) & 0xf;
672
        wrd = (insn >> 16) & 0xf;
673
        gen_op_iwmmxt_movl_T0_wCx(wrd);
674
        gen_movl_reg_T0(s, rd);
675
        break;
676
    case 0x300:                                                /* WANDN */
677
        wrd = (insn >> 12) & 0xf;
678
        rd0 = (insn >> 0) & 0xf;
679
        rd1 = (insn >> 16) & 0xf;
680
        gen_op_iwmmxt_movq_M0_wRn(rd0);
681
        gen_op_iwmmxt_negq_M0();
682
        gen_op_iwmmxt_andq_M0_wRn(rd1);
683
        gen_op_iwmmxt_setpsr_nz();
684
        gen_op_iwmmxt_movq_wRn_M0(wrd);
685
        gen_op_iwmmxt_set_mup();
686
        gen_op_iwmmxt_set_cup();
687
        break;
688
    case 0x200:                                                /* WAND */
689
        wrd = (insn >> 12) & 0xf;
690
        rd0 = (insn >> 0) & 0xf;
691
        rd1 = (insn >> 16) & 0xf;
692
        gen_op_iwmmxt_movq_M0_wRn(rd0);
693
        gen_op_iwmmxt_andq_M0_wRn(rd1);
694
        gen_op_iwmmxt_setpsr_nz();
695
        gen_op_iwmmxt_movq_wRn_M0(wrd);
696
        gen_op_iwmmxt_set_mup();
697
        gen_op_iwmmxt_set_cup();
698
        break;
699
    case 0x810: case 0xa10:                                /* WMADD */
700
        wrd = (insn >> 12) & 0xf;
701
        rd0 = (insn >> 0) & 0xf;
702
        rd1 = (insn >> 16) & 0xf;
703
        gen_op_iwmmxt_movq_M0_wRn(rd0);
704
        if (insn & (1 << 21))
705
            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
706
        else
707
            gen_op_iwmmxt_madduq_M0_wRn(rd1);
708
        gen_op_iwmmxt_movq_wRn_M0(wrd);
709
        gen_op_iwmmxt_set_mup();
710
        break;
711
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:        /* WUNPCKIL */
712
        wrd = (insn >> 12) & 0xf;
713
        rd0 = (insn >> 16) & 0xf;
714
        rd1 = (insn >> 0) & 0xf;
715
        gen_op_iwmmxt_movq_M0_wRn(rd0);
716
        switch ((insn >> 22) & 3) {
717
        case 0:
718
            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
719
            break;
720
        case 1:
721
            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
722
            break;
723
        case 2:
724
            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
725
            break;
726
        case 3:
727
            return 1;
728
        }
729
        gen_op_iwmmxt_movq_wRn_M0(wrd);
730
        gen_op_iwmmxt_set_mup();
731
        gen_op_iwmmxt_set_cup();
732
        break;
733
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:        /* WUNPCKIH */
734
        wrd = (insn >> 12) & 0xf;
735
        rd0 = (insn >> 16) & 0xf;
736
        rd1 = (insn >> 0) & 0xf;
737
        gen_op_iwmmxt_movq_M0_wRn(rd0);
738
        switch ((insn >> 22) & 3) {
739
        case 0:
740
            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
741
            break;
742
        case 1:
743
            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
744
            break;
745
        case 2:
746
            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
747
            break;
748
        case 3:
749
            return 1;
750
        }
751
        gen_op_iwmmxt_movq_wRn_M0(wrd);
752
        gen_op_iwmmxt_set_mup();
753
        gen_op_iwmmxt_set_cup();
754
        break;
755
    case 0x012: case 0x112: case 0x412: case 0x512:        /* WSAD */
756
        wrd = (insn >> 12) & 0xf;
757
        rd0 = (insn >> 16) & 0xf;
758
        rd1 = (insn >> 0) & 0xf;
759
        gen_op_iwmmxt_movq_M0_wRn(rd0);
760
        if (insn & (1 << 22))
761
            gen_op_iwmmxt_sadw_M0_wRn(rd1);
762
        else
763
            gen_op_iwmmxt_sadb_M0_wRn(rd1);
764
        if (!(insn & (1 << 20)))
765
            gen_op_iwmmxt_addl_M0_wRn(wrd);
766
        gen_op_iwmmxt_movq_wRn_M0(wrd);
767
        gen_op_iwmmxt_set_mup();
768
        break;
769
    case 0x010: case 0x110: case 0x210: case 0x310:        /* WMUL */
770
        wrd = (insn >> 12) & 0xf;
771
        rd0 = (insn >> 16) & 0xf;
772
        rd1 = (insn >> 0) & 0xf;
773
        gen_op_iwmmxt_movq_M0_wRn(rd0);
774
        if (insn & (1 << 21))
775
            gen_op_iwmmxt_mulsw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
776
        else
777
            gen_op_iwmmxt_muluw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
778
        gen_op_iwmmxt_movq_wRn_M0(wrd);
779
        gen_op_iwmmxt_set_mup();
780
        break;
781
    case 0x410: case 0x510: case 0x610: case 0x710:        /* WMAC */
782
        wrd = (insn >> 12) & 0xf;
783
        rd0 = (insn >> 16) & 0xf;
784
        rd1 = (insn >> 0) & 0xf;
785
        gen_op_iwmmxt_movq_M0_wRn(rd0);
786
        if (insn & (1 << 21))
787
            gen_op_iwmmxt_macsw_M0_wRn(rd1);
788
        else
789
            gen_op_iwmmxt_macuw_M0_wRn(rd1);
790
        if (!(insn & (1 << 20))) {
791
            if (insn & (1 << 21))
792
                gen_op_iwmmxt_addsq_M0_wRn(wrd);
793
            else
794
                gen_op_iwmmxt_adduq_M0_wRn(wrd);
795
        }
796
        gen_op_iwmmxt_movq_wRn_M0(wrd);
797
        gen_op_iwmmxt_set_mup();
798
        break;
799
    case 0x006: case 0x406: case 0x806: case 0xc06:        /* WCMPEQ */
800
        wrd = (insn >> 12) & 0xf;
801
        rd0 = (insn >> 16) & 0xf;
802
        rd1 = (insn >> 0) & 0xf;
803
        gen_op_iwmmxt_movq_M0_wRn(rd0);
804
        switch ((insn >> 22) & 3) {
805
        case 0:
806
            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
807
            break;
808
        case 1:
809
            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
810
            break;
811
        case 2:
812
            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
813
            break;
814
        case 3:
815
            return 1;
816
        }
817
        gen_op_iwmmxt_movq_wRn_M0(wrd);
818
        gen_op_iwmmxt_set_mup();
819
        gen_op_iwmmxt_set_cup();
820
        break;
821
    case 0x800: case 0x900: case 0xc00: case 0xd00:        /* WAVG2 */
822
        wrd = (insn >> 12) & 0xf;
823
        rd0 = (insn >> 16) & 0xf;
824
        rd1 = (insn >> 0) & 0xf;
825
        gen_op_iwmmxt_movq_M0_wRn(rd0);
826
        if (insn & (1 << 22))
827
            gen_op_iwmmxt_avgw_M0_wRn(rd1, (insn >> 20) & 1);
828
        else
829
            gen_op_iwmmxt_avgb_M0_wRn(rd1, (insn >> 20) & 1);
830
        gen_op_iwmmxt_movq_wRn_M0(wrd);
831
        gen_op_iwmmxt_set_mup();
832
        gen_op_iwmmxt_set_cup();
833
        break;
834
    case 0x802: case 0x902: case 0xa02: case 0xb02:        /* WALIGNR */
835
        wrd = (insn >> 12) & 0xf;
836
        rd0 = (insn >> 16) & 0xf;
837
        rd1 = (insn >> 0) & 0xf;
838
        gen_op_iwmmxt_movq_M0_wRn(rd0);
839
        gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
840
        gen_op_movl_T1_im(7);
841
        gen_op_andl_T0_T1();
842
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
843
        gen_op_iwmmxt_movq_wRn_M0(wrd);
844
        gen_op_iwmmxt_set_mup();
845
        break;
846
    case 0x601: case 0x605: case 0x609: case 0x60d:        /* TINSR */
847
        rd = (insn >> 12) & 0xf;
848
        wrd = (insn >> 16) & 0xf;
849
        gen_movl_T0_reg(s, rd);
850
        gen_op_iwmmxt_movq_M0_wRn(wrd);
851
        switch ((insn >> 6) & 3) {
852
        case 0:
853
            gen_op_movl_T1_im(0xff);
854
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
855
            break;
856
        case 1:
857
            gen_op_movl_T1_im(0xffff);
858
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
859
            break;
860
        case 2:
861
            gen_op_movl_T1_im(0xffffffff);
862
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
863
            break;
864
        case 3:
865
            return 1;
866
        }
867
        gen_op_iwmmxt_movq_wRn_M0(wrd);
868
        gen_op_iwmmxt_set_mup();
869
        break;
870
    case 0x107: case 0x507: case 0x907: case 0xd07:        /* TEXTRM */
871
        rd = (insn >> 12) & 0xf;
872
        wrd = (insn >> 16) & 0xf;
873
        if (rd == 15)
874
            return 1;
875
        gen_op_iwmmxt_movq_M0_wRn(wrd);
876
        switch ((insn >> 22) & 3) {
877
        case 0:
878
            if (insn & 8)
879
                gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
880
            else {
881
                gen_op_movl_T1_im(0xff);
882
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 7) << 3);
883
            }
884
            break;
885
        case 1:
886
            if (insn & 8)
887
                gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
888
            else {
889
                gen_op_movl_T1_im(0xffff);
890
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 3) << 4);
891
            }
892
            break;
893
        case 2:
894
            gen_op_movl_T1_im(0xffffffff);
895
            gen_op_iwmmxt_extru_T0_M0_T1((insn & 1) << 5);
896
            break;
897
        case 3:
898
            return 1;
899
        }
900
        gen_op_movl_reg_TN[0][rd]();
901
        break;
902
    case 0x117: case 0x517: case 0x917: case 0xd17:        /* TEXTRC */
903
        if ((insn & 0x000ff008) != 0x0003f000)
904
            return 1;
905
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
906
        switch ((insn >> 22) & 3) {
907
        case 0:
908
            gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
909
            break;
910
        case 1:
911
            gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
912
            break;
913
        case 2:
914
            gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
915
            break;
916
        case 3:
917
            return 1;
918
        }
919
        gen_op_shll_T1_im(28);
920
        gen_op_movl_T0_T1();
921
        gen_op_movl_cpsr_T0(0xf0000000);
922
        break;
923
    case 0x401: case 0x405: case 0x409: case 0x40d:        /* TBCST */
924
        rd = (insn >> 12) & 0xf;
925
        wrd = (insn >> 16) & 0xf;
926
        gen_movl_T0_reg(s, rd);
927
        switch ((insn >> 6) & 3) {
928
        case 0:
929
            gen_op_iwmmxt_bcstb_M0_T0();
930
            break;
931
        case 1:
932
            gen_op_iwmmxt_bcstw_M0_T0();
933
            break;
934
        case 2:
935
            gen_op_iwmmxt_bcstl_M0_T0();
936
            break;
937
        case 3:
938
            return 1;
939
        }
940
        gen_op_iwmmxt_movq_wRn_M0(wrd);
941
        gen_op_iwmmxt_set_mup();
942
        break;
943
    case 0x113: case 0x513: case 0x913: case 0xd13:        /* TANDC */
944
        if ((insn & 0x000ff00f) != 0x0003f000)
945
            return 1;
946
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
947
        switch ((insn >> 22) & 3) {
948
        case 0:
949
            for (i = 0; i < 7; i ++) {
950
                gen_op_shll_T1_im(4);
951
                gen_op_andl_T0_T1();
952
            }
953
            break;
954
        case 1:
955
            for (i = 0; i < 3; i ++) {
956
                gen_op_shll_T1_im(8);
957
                gen_op_andl_T0_T1();
958
            }
959
            break;
960
        case 2:
961
            gen_op_shll_T1_im(16);
962
            gen_op_andl_T0_T1();
963
            break;
964
        case 3:
965
            return 1;
966
        }
967
        gen_op_movl_cpsr_T0(0xf0000000);
968
        break;
969
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:        /* WACC */
970
        wrd = (insn >> 12) & 0xf;
971
        rd0 = (insn >> 16) & 0xf;
972
        gen_op_iwmmxt_movq_M0_wRn(rd0);
973
        switch ((insn >> 22) & 3) {
974
        case 0:
975
            gen_op_iwmmxt_addcb_M0();
976
            break;
977
        case 1:
978
            gen_op_iwmmxt_addcw_M0();
979
            break;
980
        case 2:
981
            gen_op_iwmmxt_addcl_M0();
982
            break;
983
        case 3:
984
            return 1;
985
        }
986
        gen_op_iwmmxt_movq_wRn_M0(wrd);
987
        gen_op_iwmmxt_set_mup();
988
        break;
989
    case 0x115: case 0x515: case 0x915: case 0xd15:        /* TORC */
990
        if ((insn & 0x000ff00f) != 0x0003f000)
991
            return 1;
992
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
993
        switch ((insn >> 22) & 3) {
994
        case 0:
995
            for (i = 0; i < 7; i ++) {
996
                gen_op_shll_T1_im(4);
997
                gen_op_orl_T0_T1();
998
            }
999
            break;
1000
        case 1:
1001
            for (i = 0; i < 3; i ++) {
1002
                gen_op_shll_T1_im(8);
1003
                gen_op_orl_T0_T1();
1004
            }
1005
            break;
1006
        case 2:
1007
            gen_op_shll_T1_im(16);
1008
            gen_op_orl_T0_T1();
1009
            break;
1010
        case 3:
1011
            return 1;
1012
        }
1013
        gen_op_movl_T1_im(0xf0000000);
1014
        gen_op_andl_T0_T1();
1015
        gen_op_movl_cpsr_T0(0xf0000000);
1016
        break;
1017
    case 0x103: case 0x503: case 0x903: case 0xd03:        /* TMOVMSK */
1018
        rd = (insn >> 12) & 0xf;
1019
        rd0 = (insn >> 16) & 0xf;
1020
        if ((insn & 0xf) != 0)
1021
            return 1;
1022
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1023
        switch ((insn >> 22) & 3) {
1024
        case 0:
1025
            gen_op_iwmmxt_msbb_T0_M0();
1026
            break;
1027
        case 1:
1028
            gen_op_iwmmxt_msbw_T0_M0();
1029
            break;
1030
        case 2:
1031
            gen_op_iwmmxt_msbl_T0_M0();
1032
            break;
1033
        case 3:
1034
            return 1;
1035
        }
1036
        gen_movl_reg_T0(s, rd);
1037
        break;
1038
    case 0x106: case 0x306: case 0x506: case 0x706:        /* WCMPGT */
1039
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
1040
        wrd = (insn >> 12) & 0xf;
1041
        rd0 = (insn >> 16) & 0xf;
1042
        rd1 = (insn >> 0) & 0xf;
1043
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1044
        switch ((insn >> 22) & 3) {
1045
        case 0:
1046
            if (insn & (1 << 21))
1047
                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1048
            else
1049
                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1050
            break;
1051
        case 1:
1052
            if (insn & (1 << 21))
1053
                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1054
            else
1055
                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1056
            break;
1057
        case 2:
1058
            if (insn & (1 << 21))
1059
                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1060
            else
1061
                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1062
            break;
1063
        case 3:
1064
            return 1;
1065
        }
1066
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1067
        gen_op_iwmmxt_set_mup();
1068
        gen_op_iwmmxt_set_cup();
1069
        break;
1070
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:        /* WUNPCKEL */
1071
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1072
        wrd = (insn >> 12) & 0xf;
1073
        rd0 = (insn >> 16) & 0xf;
1074
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1075
        switch ((insn >> 22) & 3) {
1076
        case 0:
1077
            if (insn & (1 << 21))
1078
                gen_op_iwmmxt_unpacklsb_M0();
1079
            else
1080
                gen_op_iwmmxt_unpacklub_M0();
1081
            break;
1082
        case 1:
1083
            if (insn & (1 << 21))
1084
                gen_op_iwmmxt_unpacklsw_M0();
1085
            else
1086
                gen_op_iwmmxt_unpackluw_M0();
1087
            break;
1088
        case 2:
1089
            if (insn & (1 << 21))
1090
                gen_op_iwmmxt_unpacklsl_M0();
1091
            else
1092
                gen_op_iwmmxt_unpacklul_M0();
1093
            break;
1094
        case 3:
1095
            return 1;
1096
        }
1097
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1098
        gen_op_iwmmxt_set_mup();
1099
        gen_op_iwmmxt_set_cup();
1100
        break;
1101
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:        /* WUNPCKEH */
1102
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1103
        wrd = (insn >> 12) & 0xf;
1104
        rd0 = (insn >> 16) & 0xf;
1105
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1106
        switch ((insn >> 22) & 3) {
1107
        case 0:
1108
            if (insn & (1 << 21))
1109
                gen_op_iwmmxt_unpackhsb_M0();
1110
            else
1111
                gen_op_iwmmxt_unpackhub_M0();
1112
            break;
1113
        case 1:
1114
            if (insn & (1 << 21))
1115
                gen_op_iwmmxt_unpackhsw_M0();
1116
            else
1117
                gen_op_iwmmxt_unpackhuw_M0();
1118
            break;
1119
        case 2:
1120
            if (insn & (1 << 21))
1121
                gen_op_iwmmxt_unpackhsl_M0();
1122
            else
1123
                gen_op_iwmmxt_unpackhul_M0();
1124
            break;
1125
        case 3:
1126
            return 1;
1127
        }
1128
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1129
        gen_op_iwmmxt_set_mup();
1130
        gen_op_iwmmxt_set_cup();
1131
        break;
1132
    case 0x204: case 0x604: case 0xa04: case 0xe04:        /* WSRL */
1133
    case 0x214: case 0x614: case 0xa14: case 0xe14:
1134
        wrd = (insn >> 12) & 0xf;
1135
        rd0 = (insn >> 16) & 0xf;
1136
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1137
        if (gen_iwmmxt_shift(insn, 0xff))
1138
            return 1;
1139
        switch ((insn >> 22) & 3) {
1140
        case 0:
1141
            return 1;
1142
        case 1:
1143
            gen_op_iwmmxt_srlw_M0_T0();
1144
            break;
1145
        case 2:
1146
            gen_op_iwmmxt_srll_M0_T0();
1147
            break;
1148
        case 3:
1149
            gen_op_iwmmxt_srlq_M0_T0();
1150
            break;
1151
        }
1152
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1153
        gen_op_iwmmxt_set_mup();
1154
        gen_op_iwmmxt_set_cup();
1155
        break;
1156
    case 0x004: case 0x404: case 0x804: case 0xc04:        /* WSRA */
1157
    case 0x014: case 0x414: case 0x814: case 0xc14:
1158
        wrd = (insn >> 12) & 0xf;
1159
        rd0 = (insn >> 16) & 0xf;
1160
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1161
        if (gen_iwmmxt_shift(insn, 0xff))
1162
            return 1;
1163
        switch ((insn >> 22) & 3) {
1164
        case 0:
1165
            return 1;
1166
        case 1:
1167
            gen_op_iwmmxt_sraw_M0_T0();
1168
            break;
1169
        case 2:
1170
            gen_op_iwmmxt_sral_M0_T0();
1171
            break;
1172
        case 3:
1173
            gen_op_iwmmxt_sraq_M0_T0();
1174
            break;
1175
        }
1176
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1177
        gen_op_iwmmxt_set_mup();
1178
        gen_op_iwmmxt_set_cup();
1179
        break;
1180
    case 0x104: case 0x504: case 0x904: case 0xd04:        /* WSLL */
1181
    case 0x114: case 0x514: case 0x914: case 0xd14:
1182
        wrd = (insn >> 12) & 0xf;
1183
        rd0 = (insn >> 16) & 0xf;
1184
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1185
        if (gen_iwmmxt_shift(insn, 0xff))
1186
            return 1;
1187
        switch ((insn >> 22) & 3) {
1188
        case 0:
1189
            return 1;
1190
        case 1:
1191
            gen_op_iwmmxt_sllw_M0_T0();
1192
            break;
1193
        case 2:
1194
            gen_op_iwmmxt_slll_M0_T0();
1195
            break;
1196
        case 3:
1197
            gen_op_iwmmxt_sllq_M0_T0();
1198
            break;
1199
        }
1200
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1201
        gen_op_iwmmxt_set_mup();
1202
        gen_op_iwmmxt_set_cup();
1203
        break;
1204
    case 0x304: case 0x704: case 0xb04: case 0xf04:        /* WROR */
1205
    case 0x314: case 0x714: case 0xb14: case 0xf14:
1206
        wrd = (insn >> 12) & 0xf;
1207
        rd0 = (insn >> 16) & 0xf;
1208
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1209
        switch ((insn >> 22) & 3) {
1210
        case 0:
1211
            return 1;
1212
        case 1:
1213
            if (gen_iwmmxt_shift(insn, 0xf))
1214
                return 1;
1215
            gen_op_iwmmxt_rorw_M0_T0();
1216
            break;
1217
        case 2:
1218
            if (gen_iwmmxt_shift(insn, 0x1f))
1219
                return 1;
1220
            gen_op_iwmmxt_rorl_M0_T0();
1221
            break;
1222
        case 3:
1223
            if (gen_iwmmxt_shift(insn, 0x3f))
1224
                return 1;
1225
            gen_op_iwmmxt_rorq_M0_T0();
1226
            break;
1227
        }
1228
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1229
        gen_op_iwmmxt_set_mup();
1230
        gen_op_iwmmxt_set_cup();
1231
        break;
1232
    case 0x116: case 0x316: case 0x516: case 0x716:        /* WMIN */
1233
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
1234
        wrd = (insn >> 12) & 0xf;
1235
        rd0 = (insn >> 16) & 0xf;
1236
        rd1 = (insn >> 0) & 0xf;
1237
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1238
        switch ((insn >> 22) & 3) {
1239
        case 0:
1240
            if (insn & (1 << 21))
1241
                gen_op_iwmmxt_minsb_M0_wRn(rd1);
1242
            else
1243
                gen_op_iwmmxt_minub_M0_wRn(rd1);
1244
            break;
1245
        case 1:
1246
            if (insn & (1 << 21))
1247
                gen_op_iwmmxt_minsw_M0_wRn(rd1);
1248
            else
1249
                gen_op_iwmmxt_minuw_M0_wRn(rd1);
1250
            break;
1251
        case 2:
1252
            if (insn & (1 << 21))
1253
                gen_op_iwmmxt_minsl_M0_wRn(rd1);
1254
            else
1255
                gen_op_iwmmxt_minul_M0_wRn(rd1);
1256
            break;
1257
        case 3:
1258
            return 1;
1259
        }
1260
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1261
        gen_op_iwmmxt_set_mup();
1262
        break;
1263
    case 0x016: case 0x216: case 0x416: case 0x616:        /* WMAX */
1264
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
1265
        wrd = (insn >> 12) & 0xf;
1266
        rd0 = (insn >> 16) & 0xf;
1267
        rd1 = (insn >> 0) & 0xf;
1268
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1269
        switch ((insn >> 22) & 3) {
1270
        case 0:
1271
            if (insn & (1 << 21))
1272
                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
1273
            else
1274
                gen_op_iwmmxt_maxub_M0_wRn(rd1);
1275
            break;
1276
        case 1:
1277
            if (insn & (1 << 21))
1278
                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
1279
            else
1280
                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
1281
            break;
1282
        case 2:
1283
            if (insn & (1 << 21))
1284
                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
1285
            else
1286
                gen_op_iwmmxt_maxul_M0_wRn(rd1);
1287
            break;
1288
        case 3:
1289
            return 1;
1290
        }
1291
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1292
        gen_op_iwmmxt_set_mup();
1293
        break;
1294
    case 0x002: case 0x102: case 0x202: case 0x302:        /* WALIGNI */
1295
    case 0x402: case 0x502: case 0x602: case 0x702:
1296
        wrd = (insn >> 12) & 0xf;
1297
        rd0 = (insn >> 16) & 0xf;
1298
        rd1 = (insn >> 0) & 0xf;
1299
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1300
        gen_op_movl_T0_im((insn >> 20) & 3);
1301
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1302
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1303
        gen_op_iwmmxt_set_mup();
1304
        break;
1305
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:        /* WSUB */
1306
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
1307
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
1308
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
1309
        wrd = (insn >> 12) & 0xf;
1310
        rd0 = (insn >> 16) & 0xf;
1311
        rd1 = (insn >> 0) & 0xf;
1312
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1313
        switch ((insn >> 20) & 0xf) {
1314
        case 0x0:
1315
            gen_op_iwmmxt_subnb_M0_wRn(rd1);
1316
            break;
1317
        case 0x1:
1318
            gen_op_iwmmxt_subub_M0_wRn(rd1);
1319
            break;
1320
        case 0x3:
1321
            gen_op_iwmmxt_subsb_M0_wRn(rd1);
1322
            break;
1323
        case 0x4:
1324
            gen_op_iwmmxt_subnw_M0_wRn(rd1);
1325
            break;
1326
        case 0x5:
1327
            gen_op_iwmmxt_subuw_M0_wRn(rd1);
1328
            break;
1329
        case 0x7:
1330
            gen_op_iwmmxt_subsw_M0_wRn(rd1);
1331
            break;
1332
        case 0x8:
1333
            gen_op_iwmmxt_subnl_M0_wRn(rd1);
1334
            break;
1335
        case 0x9:
1336
            gen_op_iwmmxt_subul_M0_wRn(rd1);
1337
            break;
1338
        case 0xb:
1339
            gen_op_iwmmxt_subsl_M0_wRn(rd1);
1340
            break;
1341
        default:
1342
            return 1;
1343
        }
1344
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1345
        gen_op_iwmmxt_set_mup();
1346
        gen_op_iwmmxt_set_cup();
1347
        break;
1348
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:        /* WSHUFH */
1349
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
1350
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
1351
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
1352
        wrd = (insn >> 12) & 0xf;
1353
        rd0 = (insn >> 16) & 0xf;
1354
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1355
        gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
1356
        gen_op_iwmmxt_shufh_M0_T0();
1357
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1358
        gen_op_iwmmxt_set_mup();
1359
        gen_op_iwmmxt_set_cup();
1360
        break;
1361
    case 0x018: case 0x118: case 0x218: case 0x318:        /* WADD */
1362
    case 0x418: case 0x518: case 0x618: case 0x718:
1363
    case 0x818: case 0x918: case 0xa18: case 0xb18:
1364
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
1365
        wrd = (insn >> 12) & 0xf;
1366
        rd0 = (insn >> 16) & 0xf;
1367
        rd1 = (insn >> 0) & 0xf;
1368
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1369
        switch ((insn >> 20) & 0xf) {
1370
        case 0x0:
1371
            gen_op_iwmmxt_addnb_M0_wRn(rd1);
1372
            break;
1373
        case 0x1:
1374
            gen_op_iwmmxt_addub_M0_wRn(rd1);
1375
            break;
1376
        case 0x3:
1377
            gen_op_iwmmxt_addsb_M0_wRn(rd1);
1378
            break;
1379
        case 0x4:
1380
            gen_op_iwmmxt_addnw_M0_wRn(rd1);
1381
            break;
1382
        case 0x5:
1383
            gen_op_iwmmxt_adduw_M0_wRn(rd1);
1384
            break;
1385
        case 0x7:
1386
            gen_op_iwmmxt_addsw_M0_wRn(rd1);
1387
            break;
1388
        case 0x8:
1389
            gen_op_iwmmxt_addnl_M0_wRn(rd1);
1390
            break;
1391
        case 0x9:
1392
            gen_op_iwmmxt_addul_M0_wRn(rd1);
1393
            break;
1394
        case 0xb:
1395
            gen_op_iwmmxt_addsl_M0_wRn(rd1);
1396
            break;
1397
        default:
1398
            return 1;
1399
        }
1400
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1401
        gen_op_iwmmxt_set_mup();
1402
        gen_op_iwmmxt_set_cup();
1403
        break;
1404
    case 0x008: case 0x108: case 0x208: case 0x308:        /* WPACK */
1405
    case 0x408: case 0x508: case 0x608: case 0x708:
1406
    case 0x808: case 0x908: case 0xa08: case 0xb08:
1407
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
1408
        wrd = (insn >> 12) & 0xf;
1409
        rd0 = (insn >> 16) & 0xf;
1410
        rd1 = (insn >> 0) & 0xf;
1411
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1412
        if (!(insn & (1 << 20)))
1413
            return 1;
1414
        switch ((insn >> 22) & 3) {
1415
        case 0:
1416
            return 1;
1417
        case 1:
1418
            if (insn & (1 << 21))
1419
                gen_op_iwmmxt_packsw_M0_wRn(rd1);
1420
            else
1421
                gen_op_iwmmxt_packuw_M0_wRn(rd1);
1422
            break;
1423
        case 2:
1424
            if (insn & (1 << 21))
1425
                gen_op_iwmmxt_packsl_M0_wRn(rd1);
1426
            else
1427
                gen_op_iwmmxt_packul_M0_wRn(rd1);
1428
            break;
1429
        case 3:
1430
            if (insn & (1 << 21))
1431
                gen_op_iwmmxt_packsq_M0_wRn(rd1);
1432
            else
1433
                gen_op_iwmmxt_packuq_M0_wRn(rd1);
1434
            break;
1435
        }
1436
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1437
        gen_op_iwmmxt_set_mup();
1438
        gen_op_iwmmxt_set_cup();
1439
        break;
1440
    case 0x201: case 0x203: case 0x205: case 0x207:
1441
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
1442
    case 0x211: case 0x213: case 0x215: case 0x217:
1443
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
1444
        wrd = (insn >> 5) & 0xf;
1445
        rd0 = (insn >> 12) & 0xf;
1446
        rd1 = (insn >> 0) & 0xf;
1447
        if (rd0 == 0xf || rd1 == 0xf)
1448
            return 1;
1449
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1450
        switch ((insn >> 16) & 0xf) {
1451
        case 0x0:                                        /* TMIA */
1452
            gen_op_movl_TN_reg[0][rd0]();
1453
            gen_op_movl_TN_reg[1][rd1]();
1454
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
1455
            break;
1456
        case 0x8:                                        /* TMIAPH */
1457
            gen_op_movl_TN_reg[0][rd0]();
1458
            gen_op_movl_TN_reg[1][rd1]();
1459
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
1460
            break;
1461
        case 0xc: case 0xd: case 0xe: case 0xf:                /* TMIAxy */
1462
            gen_op_movl_TN_reg[1][rd0]();
1463
            if (insn & (1 << 16))
1464
                gen_op_shrl_T1_im(16);
1465
            gen_op_movl_T0_T1();
1466
            gen_op_movl_TN_reg[1][rd1]();
1467
            if (insn & (1 << 17))
1468
                gen_op_shrl_T1_im(16);
1469
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
1470
            break;
1471
        default:
1472
            return 1;
1473
        }
1474
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1475
        gen_op_iwmmxt_set_mup();
1476
        break;
1477
    default:
1478
        return 1;
1479
    }
1480

    
1481
    return 0;
1482
}
1483

    
1484
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
1485
   (ie. an undefined instruction).  */
1486
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1487
{
1488
    int acc, rd0, rd1, rdhi, rdlo;
1489

    
1490
    if ((insn & 0x0ff00f10) == 0x0e200010) {
1491
        /* Multiply with Internal Accumulate Format */
1492
        rd0 = (insn >> 12) & 0xf;
1493
        rd1 = insn & 0xf;
1494
        acc = (insn >> 5) & 7;
1495

    
1496
        if (acc != 0)
1497
            return 1;
1498

    
1499
        switch ((insn >> 16) & 0xf) {
1500
        case 0x0:                                        /* MIA */
1501
            gen_op_movl_TN_reg[0][rd0]();
1502
            gen_op_movl_TN_reg[1][rd1]();
1503
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
1504
            break;
1505
        case 0x8:                                        /* MIAPH */
1506
            gen_op_movl_TN_reg[0][rd0]();
1507
            gen_op_movl_TN_reg[1][rd1]();
1508
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
1509
            break;
1510
        case 0xc:                                        /* MIABB */
1511
        case 0xd:                                        /* MIABT */
1512
        case 0xe:                                        /* MIATB */
1513
        case 0xf:                                        /* MIATT */
1514
            gen_op_movl_TN_reg[1][rd0]();
1515
            if (insn & (1 << 16))
1516
                gen_op_shrl_T1_im(16);
1517
            gen_op_movl_T0_T1();
1518
            gen_op_movl_TN_reg[1][rd1]();
1519
            if (insn & (1 << 17))
1520
                gen_op_shrl_T1_im(16);
1521
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
1522
            break;
1523
        default:
1524
            return 1;
1525
        }
1526

    
1527
        gen_op_iwmmxt_movq_wRn_M0(acc);
1528
        return 0;
1529
    }
1530

    
1531
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
1532
        /* Internal Accumulator Access Format */
1533
        rdhi = (insn >> 16) & 0xf;
1534
        rdlo = (insn >> 12) & 0xf;
1535
        acc = insn & 7;
1536

    
1537
        if (acc != 0)
1538
            return 1;
1539

    
1540
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
1541
            gen_op_iwmmxt_movl_T0_T1_wRn(acc);
1542
            gen_op_movl_reg_TN[0][rdlo]();
1543
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
1544
            gen_op_andl_T0_T1();
1545
            gen_op_movl_reg_TN[0][rdhi]();
1546
        } else {                                        /* MAR */
1547
            gen_op_movl_TN_reg[0][rdlo]();
1548
            gen_op_movl_TN_reg[1][rdhi]();
1549
            gen_op_iwmmxt_movl_wRn_T0_T1(acc);
1550
        }
1551
        return 0;
1552
    }
1553

    
1554
    return 1;
1555
}
1556

    
1557
/* Disassemble system coprocessor instruction.  Return nonzero if
1558
   instruction is not defined.  */
1559
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1560
{
1561
    uint32_t rd = (insn >> 12) & 0xf;
1562
    uint32_t cp = (insn >> 8) & 0xf;
1563
    if (IS_USER(s)) {
1564
        return 1;
1565
    }
1566

    
1567
    if (insn & ARM_CP_RW_BIT) {
1568
        if (!env->cp[cp].cp_read)
1569
            return 1;
1570
        gen_op_movl_T0_im((uint32_t) s->pc);
1571
        gen_op_movl_reg_TN[0][15]();
1572
        gen_op_movl_T0_cp(insn);
1573
        gen_movl_reg_T0(s, rd);
1574
    } else {
1575
        if (!env->cp[cp].cp_write)
1576
            return 1;
1577
        gen_op_movl_T0_im((uint32_t) s->pc);
1578
        gen_op_movl_reg_TN[0][15]();
1579
        gen_movl_T0_reg(s, rd);
1580
        gen_op_movl_cp_T0(insn);
1581
    }
1582
    return 0;
1583
}
1584

    
1585
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
1586
   instruction is not defined.  */
1587
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
1588
{
1589
    uint32_t rd;
1590

    
1591
    /* ??? Some cp15 registers are accessible from userspace.  */
1592
    if (IS_USER(s)) {
1593
        return 1;
1594
    }
1595
    if ((insn & 0x0fff0fff) == 0x0e070f90
1596
        || (insn & 0x0fff0fff) == 0x0e070f58) {
1597
        /* Wait for interrupt.  */
1598
        gen_op_movl_T0_im((long)s->pc);
1599
        gen_op_movl_reg_TN[0][15]();
1600
        gen_op_wfi();
1601
        s->is_jmp = DISAS_JUMP;
1602
        return 0;
1603
    }
1604
    rd = (insn >> 12) & 0xf;
1605
    if (insn & ARM_CP_RW_BIT) {
1606
        gen_op_movl_T0_cp15(insn);
1607
        /* If the destination register is r15 then sets condition codes.  */
1608
        if (rd != 15)
1609
            gen_movl_reg_T0(s, rd);
1610
    } else {
1611
        gen_movl_T0_reg(s, rd);
1612
        gen_op_movl_cp15_T0(insn);
1613
        /* Normally we would always end the TB here, but Linux
1614
         * arch/arm/mach-pxa/sleep.S expects two instructions following
1615
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
1616
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
1617
                (insn & 0x0fff0fff) != 0x0e010f10)
1618
            gen_lookup_tb(s);
1619
    }
1620
    return 0;
1621
}
1622

    
1623
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
1624
   (ie. an undefined instruction).  */
1625
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
1626
{
1627
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
1628
    int dp, veclen;
1629

    
1630
    if (!arm_feature(env, ARM_FEATURE_VFP))
1631
        return 1;
1632

    
1633
    if ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) == 0) {
1634
        /* VFP disabled.  Only allow fmxr/fmrx to/from fpexc and fpsid.  */
1635
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
1636
            return 1;
1637
        rn = (insn >> 16) & 0xf;
1638
        if (rn != 0 && rn != 8)
1639
            return 1;
1640
    }
1641
    dp = ((insn & 0xf00) == 0xb00);
1642
    switch ((insn >> 24) & 0xf) {
1643
    case 0xe:
1644
        if (insn & (1 << 4)) {
1645
            /* single register transfer */
1646
            if ((insn & 0x6f) != 0x00)
1647
                return 1;
1648
            rd = (insn >> 12) & 0xf;
1649
            if (dp) {
1650
                if (insn & 0x80)
1651
                    return 1;
1652
                rn = (insn >> 16) & 0xf;
1653
                /* Get the existing value even for arm->vfp moves because
1654
                   we only set half the register.  */
1655
                gen_mov_F0_vreg(1, rn);
1656
                gen_op_vfp_mrrd();
1657
                if (insn & ARM_CP_RW_BIT) {
1658
                    /* vfp->arm */
1659
                    if (insn & (1 << 21))
1660
                        gen_movl_reg_T1(s, rd);
1661
                    else
1662
                        gen_movl_reg_T0(s, rd);
1663
                } else {
1664
                    /* arm->vfp */
1665
                    if (insn & (1 << 21))
1666
                        gen_movl_T1_reg(s, rd);
1667
                    else
1668
                        gen_movl_T0_reg(s, rd);
1669
                    gen_op_vfp_mdrr();
1670
                    gen_mov_vreg_F0(dp, rn);
1671
                }
1672
            } else {
1673
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
1674
                if (insn & ARM_CP_RW_BIT) {
1675
                    /* vfp->arm */
1676
                    if (insn & (1 << 21)) {
1677
                        /* system register */
1678
                        rn >>= 1;
1679
                        switch (rn) {
1680
                        case ARM_VFP_FPSID:
1681
                        case ARM_VFP_FPEXC:
1682
                        case ARM_VFP_FPINST:
1683
                        case ARM_VFP_FPINST2:
1684
                            gen_op_vfp_movl_T0_xreg(rn);
1685
                            break;
1686
                        case ARM_VFP_FPSCR:
1687
                            if (rd == 15)
1688
                                gen_op_vfp_movl_T0_fpscr_flags();
1689
                            else
1690
                                gen_op_vfp_movl_T0_fpscr();
1691
                            break;
1692
                        default:
1693
                            return 1;
1694
                        }
1695
                    } else {
1696
                        gen_mov_F0_vreg(0, rn);
1697
                        gen_op_vfp_mrs();
1698
                    }
1699
                    if (rd == 15) {
1700
                        /* Set the 4 flag bits in the CPSR.  */
1701
                        gen_op_movl_cpsr_T0(0xf0000000);
1702
                    } else
1703
                        gen_movl_reg_T0(s, rd);
1704
                } else {
1705
                    /* arm->vfp */
1706
                    gen_movl_T0_reg(s, rd);
1707
                    if (insn & (1 << 21)) {
1708
                        rn >>= 1;
1709
                        /* system register */
1710
                        switch (rn) {
1711
                        case ARM_VFP_FPSID:
1712
                            /* Writes are ignored.  */
1713
                            break;
1714
                        case ARM_VFP_FPSCR:
1715
                            gen_op_vfp_movl_fpscr_T0();
1716
                            gen_lookup_tb(s);
1717
                            break;
1718
                        case ARM_VFP_FPEXC:
1719
                            gen_op_vfp_movl_xreg_T0(rn);
1720
                            gen_lookup_tb(s);
1721
                            break;
1722
                        case ARM_VFP_FPINST:
1723
                        case ARM_VFP_FPINST2:
1724
                            gen_op_vfp_movl_xreg_T0(rn);
1725
                            break;
1726
                        default:
1727
                            return 1;
1728
                        }
1729
                    } else {
1730
                        gen_op_vfp_msr();
1731
                        gen_mov_vreg_F0(0, rn);
1732
                    }
1733
                }
1734
            }
1735
        } else {
1736
            /* data processing */
1737
            /* The opcode is in bits 23, 21, 20 and 6.  */
1738
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
1739
            if (dp) {
1740
                if (op == 15) {
1741
                    /* rn is opcode */
1742
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
1743
                } else {
1744
                    /* rn is register number */
1745
                    if (insn & (1 << 7))
1746
                        return 1;
1747
                    rn = (insn >> 16) & 0xf;
1748
                }
1749

    
1750
                if (op == 15 && (rn == 15 || rn > 17)) {
1751
                    /* Integer or single precision destination.  */
1752
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
1753
                } else {
1754
                    if (insn & (1 << 22))
1755
                        return 1;
1756
                    rd = (insn >> 12) & 0xf;
1757
                }
1758

    
1759
                if (op == 15 && (rn == 16 || rn == 17)) {
1760
                    /* Integer source.  */
1761
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
1762
                } else {
1763
                    if (insn & (1 << 5))
1764
                        return 1;
1765
                    rm = insn & 0xf;
1766
                }
1767
            } else {
1768
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
1769
                if (op == 15 && rn == 15) {
1770
                    /* Double precision destination.  */
1771
                    if (insn & (1 << 22))
1772
                        return 1;
1773
                    rd = (insn >> 12) & 0xf;
1774
                } else
1775
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
1776
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
1777
            }
1778

    
1779
            veclen = env->vfp.vec_len;
1780
            if (op == 15 && rn > 3)
1781
                veclen = 0;
1782

    
1783
            /* Shut up compiler warnings.  */
1784
            delta_m = 0;
1785
            delta_d = 0;
1786
            bank_mask = 0;
1787

    
1788
            if (veclen > 0) {
1789
                if (dp)
1790
                    bank_mask = 0xc;
1791
                else
1792
                    bank_mask = 0x18;
1793

    
1794
                /* Figure out what type of vector operation this is.  */
1795
                if ((rd & bank_mask) == 0) {
1796
                    /* scalar */
1797
                    veclen = 0;
1798
                } else {
1799
                    if (dp)
1800
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
1801
                    else
1802
                        delta_d = env->vfp.vec_stride + 1;
1803

    
1804
                    if ((rm & bank_mask) == 0) {
1805
                        /* mixed scalar/vector */
1806
                        delta_m = 0;
1807
                    } else {
1808
                        /* vector */
1809
                        delta_m = delta_d;
1810
                    }
1811
                }
1812
            }
1813

    
1814
            /* Load the initial operands.  */
1815
            if (op == 15) {
1816
                switch (rn) {
1817
                case 16:
1818
                case 17:
1819
                    /* Integer source */
1820
                    gen_mov_F0_vreg(0, rm);
1821
                    break;
1822
                case 8:
1823
                case 9:
1824
                    /* Compare */
1825
                    gen_mov_F0_vreg(dp, rd);
1826
                    gen_mov_F1_vreg(dp, rm);
1827
                    break;
1828
                case 10:
1829
                case 11:
1830
                    /* Compare with zero */
1831
                    gen_mov_F0_vreg(dp, rd);
1832
                    gen_vfp_F1_ld0(dp);
1833
                    break;
1834
                default:
1835
                    /* One source operand.  */
1836
                    gen_mov_F0_vreg(dp, rm);
1837
                }
1838
            } else {
1839
                /* Two source operands.  */
1840
                gen_mov_F0_vreg(dp, rn);
1841
                gen_mov_F1_vreg(dp, rm);
1842
            }
1843

    
1844
            for (;;) {
1845
                /* Perform the calculation.  */
1846
                switch (op) {
1847
                case 0: /* mac: fd + (fn * fm) */
1848
                    gen_vfp_mul(dp);
1849
                    gen_mov_F1_vreg(dp, rd);
1850
                    gen_vfp_add(dp);
1851
                    break;
1852
                case 1: /* nmac: fd - (fn * fm) */
1853
                    gen_vfp_mul(dp);
1854
                    gen_vfp_neg(dp);
1855
                    gen_mov_F1_vreg(dp, rd);
1856
                    gen_vfp_add(dp);
1857
                    break;
1858
                case 2: /* msc: -fd + (fn * fm) */
1859
                    gen_vfp_mul(dp);
1860
                    gen_mov_F1_vreg(dp, rd);
1861
                    gen_vfp_sub(dp);
1862
                    break;
1863
                case 3: /* nmsc: -fd - (fn * fm)  */
1864
                    gen_vfp_mul(dp);
1865
                    gen_mov_F1_vreg(dp, rd);
1866
                    gen_vfp_add(dp);
1867
                    gen_vfp_neg(dp);
1868
                    break;
1869
                case 4: /* mul: fn * fm */
1870
                    gen_vfp_mul(dp);
1871
                    break;
1872
                case 5: /* nmul: -(fn * fm) */
1873
                    gen_vfp_mul(dp);
1874
                    gen_vfp_neg(dp);
1875
                    break;
1876
                case 6: /* add: fn + fm */
1877
                    gen_vfp_add(dp);
1878
                    break;
1879
                case 7: /* sub: fn - fm */
1880
                    gen_vfp_sub(dp);
1881
                    break;
1882
                case 8: /* div: fn / fm */
1883
                    gen_vfp_div(dp);
1884
                    break;
1885
                case 15: /* extension space */
1886
                    switch (rn) {
1887
                    case 0: /* cpy */
1888
                        /* no-op */
1889
                        break;
1890
                    case 1: /* abs */
1891
                        gen_vfp_abs(dp);
1892
                        break;
1893
                    case 2: /* neg */
1894
                        gen_vfp_neg(dp);
1895
                        break;
1896
                    case 3: /* sqrt */
1897
                        gen_vfp_sqrt(dp);
1898
                        break;
1899
                    case 8: /* cmp */
1900
                        gen_vfp_cmp(dp);
1901
                        break;
1902
                    case 9: /* cmpe */
1903
                        gen_vfp_cmpe(dp);
1904
                        break;
1905
                    case 10: /* cmpz */
1906
                        gen_vfp_cmp(dp);
1907
                        break;
1908
                    case 11: /* cmpez */
1909
                        gen_vfp_F1_ld0(dp);
1910
                        gen_vfp_cmpe(dp);
1911
                        break;
1912
                    case 15: /* single<->double conversion */
1913
                        if (dp)
1914
                            gen_op_vfp_fcvtsd();
1915
                        else
1916
                            gen_op_vfp_fcvtds();
1917
                        break;
1918
                    case 16: /* fuito */
1919
                        gen_vfp_uito(dp);
1920
                        break;
1921
                    case 17: /* fsito */
1922
                        gen_vfp_sito(dp);
1923
                        break;
1924
                    case 24: /* ftoui */
1925
                        gen_vfp_toui(dp);
1926
                        break;
1927
                    case 25: /* ftouiz */
1928
                        gen_vfp_touiz(dp);
1929
                        break;
1930
                    case 26: /* ftosi */
1931
                        gen_vfp_tosi(dp);
1932
                        break;
1933
                    case 27: /* ftosiz */
1934
                        gen_vfp_tosiz(dp);
1935
                        break;
1936
                    default: /* undefined */
1937
                        printf ("rn:%d\n", rn);
1938
                        return 1;
1939
                    }
1940
                    break;
1941
                default: /* undefined */
1942
                    printf ("op:%d\n", op);
1943
                    return 1;
1944
                }
1945

    
1946
                /* Write back the result.  */
1947
                if (op == 15 && (rn >= 8 && rn <= 11))
1948
                    ; /* Comparison, do nothing.  */
1949
                else if (op == 15 && rn > 17)
1950
                    /* Integer result.  */
1951
                    gen_mov_vreg_F0(0, rd);
1952
                else if (op == 15 && rn == 15)
1953
                    /* conversion */
1954
                    gen_mov_vreg_F0(!dp, rd);
1955
                else
1956
                    gen_mov_vreg_F0(dp, rd);
1957

    
1958
                /* break out of the loop if we have finished  */
1959
                if (veclen == 0)
1960
                    break;
1961

    
1962
                if (op == 15 && delta_m == 0) {
1963
                    /* single source one-many */
1964
                    while (veclen--) {
1965
                        rd = ((rd + delta_d) & (bank_mask - 1))
1966
                             | (rd & bank_mask);
1967
                        gen_mov_vreg_F0(dp, rd);
1968
                    }
1969
                    break;
1970
                }
1971
                /* Setup the next operands.  */
1972
                veclen--;
1973
                rd = ((rd + delta_d) & (bank_mask - 1))
1974
                     | (rd & bank_mask);
1975

    
1976
                if (op == 15) {
1977
                    /* One source operand.  */
1978
                    rm = ((rm + delta_m) & (bank_mask - 1))
1979
                         | (rm & bank_mask);
1980
                    gen_mov_F0_vreg(dp, rm);
1981
                } else {
1982
                    /* Two source operands.  */
1983
                    rn = ((rn + delta_d) & (bank_mask - 1))
1984
                         | (rn & bank_mask);
1985
                    gen_mov_F0_vreg(dp, rn);
1986
                    if (delta_m) {
1987
                        rm = ((rm + delta_m) & (bank_mask - 1))
1988
                             | (rm & bank_mask);
1989
                        gen_mov_F1_vreg(dp, rm);
1990
                    }
1991
                }
1992
            }
1993
        }
1994
        break;
1995
    case 0xc:
1996
    case 0xd:
1997
        if (dp && (insn & (1 << 22))) {
1998
            /* two-register transfer */
1999
            rn = (insn >> 16) & 0xf;
2000
            rd = (insn >> 12) & 0xf;
2001
            if (dp) {
2002
                if (insn & (1 << 5))
2003
                    return 1;
2004
                rm = insn & 0xf;
2005
            } else
2006
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2007

    
2008
            if (insn & ARM_CP_RW_BIT) {
2009
                /* vfp->arm */
2010
                if (dp) {
2011
                    gen_mov_F0_vreg(1, rm);
2012
                    gen_op_vfp_mrrd();
2013
                    gen_movl_reg_T0(s, rd);
2014
                    gen_movl_reg_T1(s, rn);
2015
                } else {
2016
                    gen_mov_F0_vreg(0, rm);
2017
                    gen_op_vfp_mrs();
2018
                    gen_movl_reg_T0(s, rn);
2019
                    gen_mov_F0_vreg(0, rm + 1);
2020
                    gen_op_vfp_mrs();
2021
                    gen_movl_reg_T0(s, rd);
2022
                }
2023
            } else {
2024
                /* arm->vfp */
2025
                if (dp) {
2026
                    gen_movl_T0_reg(s, rd);
2027
                    gen_movl_T1_reg(s, rn);
2028
                    gen_op_vfp_mdrr();
2029
                    gen_mov_vreg_F0(1, rm);
2030
                } else {
2031
                    gen_movl_T0_reg(s, rn);
2032
                    gen_op_vfp_msr();
2033
                    gen_mov_vreg_F0(0, rm);
2034
                    gen_movl_T0_reg(s, rd);
2035
                    gen_op_vfp_msr();
2036
                    gen_mov_vreg_F0(0, rm + 1);
2037
                }
2038
            }
2039
        } else {
2040
            /* Load/store */
2041
            rn = (insn >> 16) & 0xf;
2042
            if (dp)
2043
                rd = (insn >> 12) & 0xf;
2044
            else
2045
                rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
2046
            gen_movl_T1_reg(s, rn);
2047
            if ((insn & 0x01200000) == 0x01000000) {
2048
                /* Single load/store */
2049
                offset = (insn & 0xff) << 2;
2050
                if ((insn & (1 << 23)) == 0)
2051
                    offset = -offset;
2052
                gen_op_addl_T1_im(offset);
2053
                if (insn & (1 << 20)) {
2054
                    gen_vfp_ld(s, dp);
2055
                    gen_mov_vreg_F0(dp, rd);
2056
                } else {
2057
                    gen_mov_F0_vreg(dp, rd);
2058
                    gen_vfp_st(s, dp);
2059
                }
2060
            } else {
2061
                /* load/store multiple */
2062
                if (dp)
2063
                    n = (insn >> 1) & 0x7f;
2064
                else
2065
                    n = insn & 0xff;
2066

    
2067
                if (insn & (1 << 24)) /* pre-decrement */
2068
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
2069

    
2070
                if (dp)
2071
                    offset = 8;
2072
                else
2073
                    offset = 4;
2074
                for (i = 0; i < n; i++) {
2075
                    if (insn & ARM_CP_RW_BIT) {
2076
                        /* load */
2077
                        gen_vfp_ld(s, dp);
2078
                        gen_mov_vreg_F0(dp, rd + i);
2079
                    } else {
2080
                        /* store */
2081
                        gen_mov_F0_vreg(dp, rd + i);
2082
                        gen_vfp_st(s, dp);
2083
                    }
2084
                    gen_op_addl_T1_im(offset);
2085
                }
2086
                if (insn & (1 << 21)) {
2087
                    /* writeback */
2088
                    if (insn & (1 << 24))
2089
                        offset = -offset * n;
2090
                    else if (dp && (insn & 1))
2091
                        offset = 4;
2092
                    else
2093
                        offset = 0;
2094

    
2095
                    if (offset != 0)
2096
                        gen_op_addl_T1_im(offset);
2097
                    gen_movl_reg_T1(s, rn);
2098
                }
2099
            }
2100
        }
2101
        break;
2102
    default:
2103
        /* Should never happen.  */
2104
        return 1;
2105
    }
2106
    return 0;
2107
}
2108

    
2109
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
2110
{
2111
    TranslationBlock *tb;
2112

    
2113
    tb = s->tb;
2114
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2115
        if (n == 0)
2116
            gen_op_goto_tb0(TBPARAM(tb));
2117
        else
2118
            gen_op_goto_tb1(TBPARAM(tb));
2119
        gen_op_movl_T0_im(dest);
2120
        gen_op_movl_r15_T0();
2121
        gen_op_movl_T0_im((long)tb + n);
2122
        gen_op_exit_tb();
2123
    } else {
2124
        gen_op_movl_T0_im(dest);
2125
        gen_op_movl_r15_T0();
2126
        gen_op_movl_T0_0();
2127
        gen_op_exit_tb();
2128
    }
2129
}
2130

    
2131
static inline void gen_jmp (DisasContext *s, uint32_t dest)
2132
{
2133
    if (__builtin_expect(s->singlestep_enabled, 0)) {
2134
        /* An indirect jump so that we still trigger the debug exception.  */
2135
        if (s->thumb)
2136
          dest |= 1;
2137
        gen_op_movl_T0_im(dest);
2138
        gen_bx(s);
2139
    } else {
2140
        gen_goto_tb(s, 0, dest);
2141
        s->is_jmp = DISAS_TB_JUMP;
2142
    }
2143
}
2144

    
2145
static inline void gen_mulxy(int x, int y)
2146
{
2147
    if (x)
2148
        gen_op_sarl_T0_im(16);
2149
    else
2150
        gen_op_sxth_T0();
2151
    if (y)
2152
        gen_op_sarl_T1_im(16);
2153
    else
2154
        gen_op_sxth_T1();
2155
    gen_op_mul_T0_T1();
2156
}
2157

    
2158
/* Return the mask of PSR bits set by a MSR instruction.  */
2159
static uint32_t msr_mask(DisasContext *s, int flags, int spsr) {
2160
    uint32_t mask;
2161

    
2162
    mask = 0;
2163
    if (flags & (1 << 0))
2164
        mask |= 0xff;
2165
    if (flags & (1 << 1))
2166
        mask |= 0xff00;
2167
    if (flags & (1 << 2))
2168
        mask |= 0xff0000;
2169
    if (flags & (1 << 3))
2170
        mask |= 0xff000000;
2171
    /* Mask out undefined bits.  */
2172
    mask &= 0xf90f03ff;
2173
    /* Mask out state bits.  */
2174
    if (!spsr)
2175
        mask &= ~0x01000020;
2176
    /* Mask out privileged bits.  */
2177
    if (IS_USER(s))
2178
        mask &= 0xf80f0200;
2179
    return mask;
2180
}
2181

    
2182
/* Returns nonzero if access to the PSR is not permitted.  */
2183
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
2184
{
2185
    if (spsr) {
2186
        /* ??? This is also undefined in system mode.  */
2187
        if (IS_USER(s))
2188
            return 1;
2189
        gen_op_movl_spsr_T0(mask);
2190
    } else {
2191
        gen_op_movl_cpsr_T0(mask);
2192
    }
2193
    gen_lookup_tb(s);
2194
    return 0;
2195
}
2196

    
2197
static void gen_exception_return(DisasContext *s)
2198
{
2199
    gen_op_movl_reg_TN[0][15]();
2200
    gen_op_movl_T0_spsr();
2201
    gen_op_movl_cpsr_T0(0xffffffff);
2202
    s->is_jmp = DISAS_UPDATE;
2203
}
2204

    
2205
static void disas_arm_insn(CPUState * env, DisasContext *s)
2206
{
2207
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
2208

    
2209
    insn = ldl_code(s->pc);
2210
    s->pc += 4;
2211

    
2212
    cond = insn >> 28;
2213
    if (cond == 0xf){
2214
        /* Unconditional instructions.  */
2215
        if ((insn & 0x0d70f000) == 0x0550f000)
2216
            return; /* PLD */
2217
        else if ((insn & 0x0e000000) == 0x0a000000) {
2218
            /* branch link and change to thumb (blx <offset>) */
2219
            int32_t offset;
2220

    
2221
            val = (uint32_t)s->pc;
2222
            gen_op_movl_T0_im(val);
2223
            gen_movl_reg_T0(s, 14);
2224
            /* Sign-extend the 24-bit offset */
2225
            offset = (((int32_t)insn) << 8) >> 8;
2226
            /* offset * 4 + bit24 * 2 + (thumb bit) */
2227
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
2228
            /* pipeline offset */
2229
            val += 4;
2230
            gen_op_movl_T0_im(val);
2231
            gen_bx(s);
2232
            return;
2233
        } else if ((insn & 0x0e000f00) == 0x0c000100) {
2234
            if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2235
                /* iWMMXt register transfer.  */
2236
                if (env->cp15.c15_cpar & (1 << 1))
2237
                    if (!disas_iwmmxt_insn(env, s, insn))
2238
                        return;
2239
            }
2240
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
2241
            /* Coprocessor double register transfer.  */
2242
        } else if ((insn & 0x0f000010) == 0x0e000010) {
2243
            /* Additional coprocessor register transfer.  */
2244
        } else if ((insn & 0x0ff10010) == 0x01000000) {
2245
            /* cps (privileged) */
2246
        } else if ((insn & 0x0ffffdff) == 0x01010000) {
2247
            /* setend */
2248
            if (insn & (1 << 9)) {
2249
                /* BE8 mode not implemented.  */
2250
                goto illegal_op;
2251
            }
2252
            return;
2253
        }
2254
        goto illegal_op;
2255
    }
2256
    if (cond != 0xe) {
2257
        /* if not always execute, we generate a conditional jump to
2258
           next instruction */
2259
        s->condlabel = gen_new_label();
2260
        gen_test_cc[cond ^ 1](s->condlabel);
2261
        s->condjmp = 1;
2262
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
2263
        //s->is_jmp = DISAS_JUMP_NEXT;
2264
    }
2265
    if ((insn & 0x0f900000) == 0x03000000) {
2266
        if ((insn & 0x0fb0f000) != 0x0320f000)
2267
            goto illegal_op;
2268
        /* CPSR = immediate */
2269
        val = insn & 0xff;
2270
        shift = ((insn >> 8) & 0xf) * 2;
2271
        if (shift)
2272
            val = (val >> shift) | (val << (32 - shift));
2273
        gen_op_movl_T0_im(val);
2274
        i = ((insn & (1 << 22)) != 0);
2275
        if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i))
2276
            goto illegal_op;
2277
    } else if ((insn & 0x0f900000) == 0x01000000
2278
               && (insn & 0x00000090) != 0x00000090) {
2279
        /* miscellaneous instructions */
2280
        op1 = (insn >> 21) & 3;
2281
        sh = (insn >> 4) & 0xf;
2282
        rm = insn & 0xf;
2283
        switch (sh) {
2284
        case 0x0: /* move program status register */
2285
            if (op1 & 1) {
2286
                /* PSR = reg */
2287
                gen_movl_T0_reg(s, rm);
2288
                i = ((op1 & 2) != 0);
2289
                if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i))
2290
                    goto illegal_op;
2291
            } else {
2292
                /* reg = PSR */
2293
                rd = (insn >> 12) & 0xf;
2294
                if (op1 & 2) {
2295
                    if (IS_USER(s))
2296
                        goto illegal_op;
2297
                    gen_op_movl_T0_spsr();
2298
                } else {
2299
                    gen_op_movl_T0_cpsr();
2300
                }
2301
                gen_movl_reg_T0(s, rd);
2302
            }
2303
            break;
2304
        case 0x1:
2305
            if (op1 == 1) {
2306
                /* branch/exchange thumb (bx).  */
2307
                gen_movl_T0_reg(s, rm);
2308
                gen_bx(s);
2309
            } else if (op1 == 3) {
2310
                /* clz */
2311
                rd = (insn >> 12) & 0xf;
2312
                gen_movl_T0_reg(s, rm);
2313
                gen_op_clz_T0();
2314
                gen_movl_reg_T0(s, rd);
2315
            } else {
2316
                goto illegal_op;
2317
            }
2318
            break;
2319
        case 0x2:
2320
            if (op1 == 1) {
2321
                ARCH(5J); /* bxj */
2322
                /* Trivial implementation equivalent to bx.  */
2323
                gen_movl_T0_reg(s, rm);
2324
                gen_bx(s);
2325
            } else {
2326
                goto illegal_op;
2327
            }
2328
            break;
2329
        case 0x3:
2330
            if (op1 != 1)
2331
              goto illegal_op;
2332

    
2333
            /* branch link/exchange thumb (blx) */
2334
            val = (uint32_t)s->pc;
2335
            gen_op_movl_T1_im(val);
2336
            gen_movl_T0_reg(s, rm);
2337
            gen_movl_reg_T1(s, 14);
2338
            gen_bx(s);
2339
            break;
2340
        case 0x5: /* saturating add/subtract */
2341
            rd = (insn >> 12) & 0xf;
2342
            rn = (insn >> 16) & 0xf;
2343
            gen_movl_T0_reg(s, rm);
2344
            gen_movl_T1_reg(s, rn);
2345
            if (op1 & 2)
2346
                gen_op_double_T1_saturate();
2347
            if (op1 & 1)
2348
                gen_op_subl_T0_T1_saturate();
2349
            else
2350
                gen_op_addl_T0_T1_saturate();
2351
            gen_movl_reg_T0(s, rd);
2352
            break;
2353
        case 7: /* bkpt */
2354
            gen_op_movl_T0_im((long)s->pc - 4);
2355
            gen_op_movl_reg_TN[0][15]();
2356
            gen_op_bkpt();
2357
            s->is_jmp = DISAS_JUMP;
2358
            break;
2359
        case 0x8: /* signed multiply */
2360
        case 0xa:
2361
        case 0xc:
2362
        case 0xe:
2363
            rs = (insn >> 8) & 0xf;
2364
            rn = (insn >> 12) & 0xf;
2365
            rd = (insn >> 16) & 0xf;
2366
            if (op1 == 1) {
2367
                /* (32 * 16) >> 16 */
2368
                gen_movl_T0_reg(s, rm);
2369
                gen_movl_T1_reg(s, rs);
2370
                if (sh & 4)
2371
                    gen_op_sarl_T1_im(16);
2372
                else
2373
                    gen_op_sxth_T1();
2374
                gen_op_imulw_T0_T1();
2375
                if ((sh & 2) == 0) {
2376
                    gen_movl_T1_reg(s, rn);
2377
                    gen_op_addl_T0_T1_setq();
2378
                }
2379
                gen_movl_reg_T0(s, rd);
2380
            } else {
2381
                /* 16 * 16 */
2382
                gen_movl_T0_reg(s, rm);
2383
                gen_movl_T1_reg(s, rs);
2384
                gen_mulxy(sh & 2, sh & 4);
2385
                if (op1 == 2) {
2386
                    gen_op_signbit_T1_T0();
2387
                    gen_op_addq_T0_T1(rn, rd);
2388
                    gen_movl_reg_T0(s, rn);
2389
                    gen_movl_reg_T1(s, rd);
2390
                } else {
2391
                    if (op1 == 0) {
2392
                        gen_movl_T1_reg(s, rn);
2393
                        gen_op_addl_T0_T1_setq();
2394
                    }
2395
                    gen_movl_reg_T0(s, rd);
2396
                }
2397
            }
2398
            break;
2399
        default:
2400
            goto illegal_op;
2401
        }
2402
    } else if (((insn & 0x0e000000) == 0 &&
2403
                (insn & 0x00000090) != 0x90) ||
2404
               ((insn & 0x0e000000) == (1 << 25))) {
2405
        int set_cc, logic_cc, shiftop;
2406

    
2407
        op1 = (insn >> 21) & 0xf;
2408
        set_cc = (insn >> 20) & 1;
2409
        logic_cc = table_logic_cc[op1] & set_cc;
2410

    
2411
        /* data processing instruction */
2412
        if (insn & (1 << 25)) {
2413
            /* immediate operand */
2414
            val = insn & 0xff;
2415
            shift = ((insn >> 8) & 0xf) * 2;
2416
            if (shift)
2417
                val = (val >> shift) | (val << (32 - shift));
2418
            gen_op_movl_T1_im(val);
2419
            if (logic_cc && shift)
2420
                gen_op_mov_CF_T1();
2421
        } else {
2422
            /* register */
2423
            rm = (insn) & 0xf;
2424
            gen_movl_T1_reg(s, rm);
2425
            shiftop = (insn >> 5) & 3;
2426
            if (!(insn & (1 << 4))) {
2427
                shift = (insn >> 7) & 0x1f;
2428
                if (shift != 0) {
2429
                    if (logic_cc) {
2430
                        gen_shift_T1_im_cc[shiftop](shift);
2431
                    } else {
2432
                        gen_shift_T1_im[shiftop](shift);
2433
                    }
2434
                } else if (shiftop != 0) {
2435
                    if (logic_cc) {
2436
                        gen_shift_T1_0_cc[shiftop]();
2437
                    } else {
2438
                        gen_shift_T1_0[shiftop]();
2439
                    }
2440
                }
2441
            } else {
2442
                rs = (insn >> 8) & 0xf;
2443
                gen_movl_T0_reg(s, rs);
2444
                if (logic_cc) {
2445
                    gen_shift_T1_T0_cc[shiftop]();
2446
                } else {
2447
                    gen_shift_T1_T0[shiftop]();
2448
                }
2449
            }
2450
        }
2451
        if (op1 != 0x0f && op1 != 0x0d) {
2452
            rn = (insn >> 16) & 0xf;
2453
            gen_movl_T0_reg(s, rn);
2454
        }
2455
        rd = (insn >> 12) & 0xf;
2456
        switch(op1) {
2457
        case 0x00:
2458
            gen_op_andl_T0_T1();
2459
            gen_movl_reg_T0(s, rd);
2460
            if (logic_cc)
2461
                gen_op_logic_T0_cc();
2462
            break;
2463
        case 0x01:
2464
            gen_op_xorl_T0_T1();
2465
            gen_movl_reg_T0(s, rd);
2466
            if (logic_cc)
2467
                gen_op_logic_T0_cc();
2468
            break;
2469
        case 0x02:
2470
            if (set_cc && rd == 15) {
2471
                /* SUBS r15, ... is used for exception return.  */
2472
                if (IS_USER(s))
2473
                    goto illegal_op;
2474
                gen_op_subl_T0_T1_cc();
2475
                gen_exception_return(s);
2476
            } else {
2477
                if (set_cc)
2478
                    gen_op_subl_T0_T1_cc();
2479
                else
2480
                    gen_op_subl_T0_T1();
2481
                gen_movl_reg_T0(s, rd);
2482
            }
2483
            break;
2484
        case 0x03:
2485
            if (set_cc)
2486
                gen_op_rsbl_T0_T1_cc();
2487
            else
2488
                gen_op_rsbl_T0_T1();
2489
            gen_movl_reg_T0(s, rd);
2490
            break;
2491
        case 0x04:
2492
            if (set_cc)
2493
                gen_op_addl_T0_T1_cc();
2494
            else
2495
                gen_op_addl_T0_T1();
2496
            gen_movl_reg_T0(s, rd);
2497
            break;
2498
        case 0x05:
2499
            if (set_cc)
2500
                gen_op_adcl_T0_T1_cc();
2501
            else
2502
                gen_op_adcl_T0_T1();
2503
            gen_movl_reg_T0(s, rd);
2504
            break;
2505
        case 0x06:
2506
            if (set_cc)
2507
                gen_op_sbcl_T0_T1_cc();
2508
            else
2509
                gen_op_sbcl_T0_T1();
2510
            gen_movl_reg_T0(s, rd);
2511
            break;
2512
        case 0x07:
2513
            if (set_cc)
2514
                gen_op_rscl_T0_T1_cc();
2515
            else
2516
                gen_op_rscl_T0_T1();
2517
            gen_movl_reg_T0(s, rd);
2518
            break;
2519
        case 0x08:
2520
            if (set_cc) {
2521
                gen_op_andl_T0_T1();
2522
                gen_op_logic_T0_cc();
2523
            }
2524
            break;
2525
        case 0x09:
2526
            if (set_cc) {
2527
                gen_op_xorl_T0_T1();
2528
                gen_op_logic_T0_cc();
2529
            }
2530
            break;
2531
        case 0x0a:
2532
            if (set_cc) {
2533
                gen_op_subl_T0_T1_cc();
2534
            }
2535
            break;
2536
        case 0x0b:
2537
            if (set_cc) {
2538
                gen_op_addl_T0_T1_cc();
2539
            }
2540
            break;
2541
        case 0x0c:
2542
            gen_op_orl_T0_T1();
2543
            gen_movl_reg_T0(s, rd);
2544
            if (logic_cc)
2545
                gen_op_logic_T0_cc();
2546
            break;
2547
        case 0x0d:
2548
            if (logic_cc && rd == 15) {
2549
                /* MOVS r15, ... is used for exception return.  */
2550
                if (IS_USER(s))
2551
                    goto illegal_op;
2552
                gen_op_movl_T0_T1();
2553
                gen_exception_return(s);
2554
            } else {
2555
                gen_movl_reg_T1(s, rd);
2556
                if (logic_cc)
2557
                    gen_op_logic_T1_cc();
2558
            }
2559
            break;
2560
        case 0x0e:
2561
            gen_op_bicl_T0_T1();
2562
            gen_movl_reg_T0(s, rd);
2563
            if (logic_cc)
2564
                gen_op_logic_T0_cc();
2565
            break;
2566
        default:
2567
        case 0x0f:
2568
            gen_op_notl_T1();
2569
            gen_movl_reg_T1(s, rd);
2570
            if (logic_cc)
2571
                gen_op_logic_T1_cc();
2572
            break;
2573
        }
2574
    } else {
2575
        /* other instructions */
2576
        op1 = (insn >> 24) & 0xf;
2577
        switch(op1) {
2578
        case 0x0:
2579
        case 0x1:
2580
            /* multiplies, extra load/stores */
2581
            sh = (insn >> 5) & 3;
2582
            if (sh == 0) {
2583
                if (op1 == 0x0) {
2584
                    rd = (insn >> 16) & 0xf;
2585
                    rn = (insn >> 12) & 0xf;
2586
                    rs = (insn >> 8) & 0xf;
2587
                    rm = (insn) & 0xf;
2588
                    if (((insn >> 22) & 3) == 0) {
2589
                        /* 32 bit mul */
2590
                        gen_movl_T0_reg(s, rs);
2591
                        gen_movl_T1_reg(s, rm);
2592
                        gen_op_mul_T0_T1();
2593
                        if (insn & (1 << 21)) {
2594
                            gen_movl_T1_reg(s, rn);
2595
                            gen_op_addl_T0_T1();
2596
                        }
2597
                        if (insn & (1 << 20))
2598
                            gen_op_logic_T0_cc();
2599
                        gen_movl_reg_T0(s, rd);
2600
                    } else {
2601
                        /* 64 bit mul */
2602
                        gen_movl_T0_reg(s, rs);
2603
                        gen_movl_T1_reg(s, rm);
2604
                        if (insn & (1 << 22))
2605
                            gen_op_imull_T0_T1();
2606
                        else
2607
                            gen_op_mull_T0_T1();
2608
                        if (insn & (1 << 21)) /* mult accumulate */
2609
                            gen_op_addq_T0_T1(rn, rd);
2610
                        if (!(insn & (1 << 23))) { /* double accumulate */
2611
                            ARCH(6);
2612
                            gen_op_addq_lo_T0_T1(rn);
2613
                            gen_op_addq_lo_T0_T1(rd);
2614
                        }
2615
                        if (insn & (1 << 20))
2616
                            gen_op_logicq_cc();
2617
                        gen_movl_reg_T0(s, rn);
2618
                        gen_movl_reg_T1(s, rd);
2619
                    }
2620
                } else {
2621
                    rn = (insn >> 16) & 0xf;
2622
                    rd = (insn >> 12) & 0xf;
2623
                    if (insn & (1 << 23)) {
2624
                        /* load/store exclusive */
2625
                        goto illegal_op;
2626
                    } else {
2627
                        /* SWP instruction */
2628
                        rm = (insn) & 0xf;
2629

    
2630
                        gen_movl_T0_reg(s, rm);
2631
                        gen_movl_T1_reg(s, rn);
2632
                        if (insn & (1 << 22)) {
2633
                            gen_ldst(swpb, s);
2634
                        } else {
2635
                            gen_ldst(swpl, s);
2636
                        }
2637
                        gen_movl_reg_T0(s, rd);
2638
                    }
2639
                }
2640
            } else {
2641
                int address_offset;
2642
                int load;
2643
                /* Misc load/store */
2644
                rn = (insn >> 16) & 0xf;
2645
                rd = (insn >> 12) & 0xf;
2646
                gen_movl_T1_reg(s, rn);
2647
                if (insn & (1 << 24))
2648
                    gen_add_datah_offset(s, insn, 0);
2649
                address_offset = 0;
2650
                if (insn & (1 << 20)) {
2651
                    /* load */
2652
                    switch(sh) {
2653
                    case 1:
2654
                        gen_ldst(lduw, s);
2655
                        break;
2656
                    case 2:
2657
                        gen_ldst(ldsb, s);
2658
                        break;
2659
                    default:
2660
                    case 3:
2661
                        gen_ldst(ldsw, s);
2662
                        break;
2663
                    }
2664
                    load = 1;
2665
                } else if (sh & 2) {
2666
                    /* doubleword */
2667
                    if (sh & 1) {
2668
                        /* store */
2669
                        gen_movl_T0_reg(s, rd);
2670
                        gen_ldst(stl, s);
2671
                        gen_op_addl_T1_im(4);
2672
                        gen_movl_T0_reg(s, rd + 1);
2673
                        gen_ldst(stl, s);
2674
                        load = 0;
2675
                    } else {
2676
                        /* load */
2677
                        gen_ldst(ldl, s);
2678
                        gen_movl_reg_T0(s, rd);
2679
                        gen_op_addl_T1_im(4);
2680
                        gen_ldst(ldl, s);
2681
                        rd++;
2682
                        load = 1;
2683
                    }
2684
                    address_offset = -4;
2685
                } else {
2686
                    /* store */
2687
                    gen_movl_T0_reg(s, rd);
2688
                    gen_ldst(stw, s);
2689
                    load = 0;
2690
                }
2691
                /* Perform base writeback before the loaded value to
2692
                   ensure correct behavior with overlapping index registers.
2693
                   ldrd with base writeback is is undefined if the
2694
                   destination and index registers overlap.  */
2695
                if (!(insn & (1 << 24))) {
2696
                    gen_add_datah_offset(s, insn, address_offset);
2697
                    gen_movl_reg_T1(s, rn);
2698
                } else if (insn & (1 << 21)) {
2699
                    if (address_offset)
2700
                        gen_op_addl_T1_im(address_offset);
2701
                    gen_movl_reg_T1(s, rn);
2702
                }
2703
                if (load) {
2704
                    /* Complete the load.  */
2705
                    gen_movl_reg_T0(s, rd);
2706
                }
2707
            }
2708
            break;
2709
        case 0x4:
2710
        case 0x5:
2711
        case 0x6:
2712
        case 0x7:
2713
            /* Check for undefined extension instructions
2714
             * per the ARM Bible IE:
2715
             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx
2716
             */
2717
            sh = (0xf << 20) | (0xf << 4);
2718
            if (op1 == 0x7 && ((insn & sh) == sh))
2719
            {
2720
                goto illegal_op;
2721
            }
2722
            /* load/store byte/word */
2723
            rn = (insn >> 16) & 0xf;
2724
            rd = (insn >> 12) & 0xf;
2725
            gen_movl_T1_reg(s, rn);
2726
            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
2727
            if (insn & (1 << 24))
2728
                gen_add_data_offset(s, insn);
2729
            if (insn & (1 << 20)) {
2730
                /* load */
2731
                s->is_mem = 1;
2732
#if defined(CONFIG_USER_ONLY)
2733
                if (insn & (1 << 22))
2734
                    gen_op_ldub_raw();
2735
                else
2736
                    gen_op_ldl_raw();
2737
#else
2738
                if (insn & (1 << 22)) {
2739
                    if (i)
2740
                        gen_op_ldub_user();
2741
                    else
2742
                        gen_op_ldub_kernel();
2743
                } else {
2744
                    if (i)
2745
                        gen_op_ldl_user();
2746
                    else
2747
                        gen_op_ldl_kernel();
2748
                }
2749
#endif
2750
            } else {
2751
                /* store */
2752
                gen_movl_T0_reg(s, rd);
2753
#if defined(CONFIG_USER_ONLY)
2754
                if (insn & (1 << 22))
2755
                    gen_op_stb_raw();
2756
                else
2757
                    gen_op_stl_raw();
2758
#else
2759
                if (insn & (1 << 22)) {
2760
                    if (i)
2761
                        gen_op_stb_user();
2762
                    else
2763
                        gen_op_stb_kernel();
2764
                } else {
2765
                    if (i)
2766
                        gen_op_stl_user();
2767
                    else
2768
                        gen_op_stl_kernel();
2769
                }
2770
#endif
2771
            }
2772
            if (!(insn & (1 << 24))) {
2773
                gen_add_data_offset(s, insn);
2774
                gen_movl_reg_T1(s, rn);
2775
            } else if (insn & (1 << 21))
2776
                gen_movl_reg_T1(s, rn); {
2777
            }
2778
            if (insn & (1 << 20)) {
2779
                /* Complete the load.  */
2780
                if (rd == 15)
2781
                    gen_bx(s);
2782
                else
2783
                    gen_movl_reg_T0(s, rd);
2784
            }
2785
            break;
2786
        case 0x08:
2787
        case 0x09:
2788
            {
2789
                int j, n, user, loaded_base;
2790
                /* load/store multiple words */
2791
                /* XXX: store correct base if write back */
2792
                user = 0;
2793
                if (insn & (1 << 22)) {
2794
                    if (IS_USER(s))
2795
                        goto illegal_op; /* only usable in supervisor mode */
2796

    
2797
                    if ((insn & (1 << 15)) == 0)
2798
                        user = 1;
2799
                }
2800
                rn = (insn >> 16) & 0xf;
2801
                gen_movl_T1_reg(s, rn);
2802

    
2803
                /* compute total size */
2804
                loaded_base = 0;
2805
                n = 0;
2806
                for(i=0;i<16;i++) {
2807
                    if (insn & (1 << i))
2808
                        n++;
2809
                }
2810
                /* XXX: test invalid n == 0 case ? */
2811
                if (insn & (1 << 23)) {
2812
                    if (insn & (1 << 24)) {
2813
                        /* pre increment */
2814
                        gen_op_addl_T1_im(4);
2815
                    } else {
2816
                        /* post increment */
2817
                    }
2818
                } else {
2819
                    if (insn & (1 << 24)) {
2820
                        /* pre decrement */
2821
                        gen_op_addl_T1_im(-(n * 4));
2822
                    } else {
2823
                        /* post decrement */
2824
                        if (n != 1)
2825
                            gen_op_addl_T1_im(-((n - 1) * 4));
2826
                    }
2827
                }
2828
                j = 0;
2829
                for(i=0;i<16;i++) {
2830
                    if (insn & (1 << i)) {
2831
                        if (insn & (1 << 20)) {
2832
                            /* load */
2833
                            gen_ldst(ldl, s);
2834
                            if (i == 15) {
2835
                                gen_bx(s);
2836
                            } else if (user) {
2837
                                gen_op_movl_user_T0(i);
2838
                            } else if (i == rn) {
2839
                                gen_op_movl_T2_T0();
2840
                                loaded_base = 1;
2841
                            } else {
2842
                                gen_movl_reg_T0(s, i);
2843
                            }
2844
                        } else {
2845
                            /* store */
2846
                            if (i == 15) {
2847
                                /* special case: r15 = PC + 8 */
2848
                                val = (long)s->pc + 4;
2849
                                gen_op_movl_TN_im[0](val);
2850
                            } else if (user) {
2851
                                gen_op_movl_T0_user(i);
2852
                            } else {
2853
                                gen_movl_T0_reg(s, i);
2854
                            }
2855
                            gen_ldst(stl, s);
2856
                        }
2857
                        j++;
2858
                        /* no need to add after the last transfer */
2859
                        if (j != n)
2860
                            gen_op_addl_T1_im(4);
2861
                    }
2862
                }
2863
                if (insn & (1 << 21)) {
2864
                    /* write back */
2865
                    if (insn & (1 << 23)) {
2866
                        if (insn & (1 << 24)) {
2867
                            /* pre increment */
2868
                        } else {
2869
                            /* post increment */
2870
                            gen_op_addl_T1_im(4);
2871
                        }
2872
                    } else {
2873
                        if (insn & (1 << 24)) {
2874
                            /* pre decrement */
2875
                            if (n != 1)
2876
                                gen_op_addl_T1_im(-((n - 1) * 4));
2877
                        } else {
2878
                            /* post decrement */
2879
                            gen_op_addl_T1_im(-(n * 4));
2880
                        }
2881
                    }
2882
                    gen_movl_reg_T1(s, rn);
2883
                }
2884
                if (loaded_base) {
2885
                    gen_op_movl_T0_T2();
2886
                    gen_movl_reg_T0(s, rn);
2887
                }
2888
                if ((insn & (1 << 22)) && !user) {
2889
                    /* Restore CPSR from SPSR.  */
2890
                    gen_op_movl_T0_spsr();
2891
                    gen_op_movl_cpsr_T0(0xffffffff);
2892
                    s->is_jmp = DISAS_UPDATE;
2893
                }
2894
            }
2895
            break;
2896
        case 0xa:
2897
        case 0xb:
2898
            {
2899
                int32_t offset;
2900

    
2901
                /* branch (and link) */
2902
                val = (int32_t)s->pc;
2903
                if (insn & (1 << 24)) {
2904
                    gen_op_movl_T0_im(val);
2905
                    gen_op_movl_reg_TN[0][14]();
2906
                }
2907
                offset = (((int32_t)insn << 8) >> 8);
2908
                val += (offset << 2) + 4;
2909
                gen_jmp(s, val);
2910
            }
2911
            break;
2912
        case 0xc:
2913
        case 0xd:
2914
        case 0xe:
2915
            /* Coprocessor.  */
2916
            op1 = (insn >> 8) & 0xf;
2917
            if (arm_feature(env, ARM_FEATURE_XSCALE) &&
2918
                    ((env->cp15.c15_cpar ^ 0x3fff) & (1 << op1)))
2919
                goto illegal_op;
2920
            switch (op1) {
2921
            case 0 ... 1:
2922
                if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2923
                    if (disas_iwmmxt_insn(env, s, insn))
2924
                        goto illegal_op;
2925
                } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
2926
                    if (disas_dsp_insn(env, s, insn))
2927
                        goto illegal_op;
2928
                } else
2929
                    goto illegal_op;
2930
                break;
2931
            case 2 ... 9:
2932
            case 12 ... 14:
2933
                if (disas_cp_insn (env, s, insn))
2934
                    goto illegal_op;
2935
                break;
2936
            case 10:
2937
            case 11:
2938
                if (disas_vfp_insn (env, s, insn))
2939
                    goto illegal_op;
2940
                break;
2941
            case 15:
2942
                if (disas_cp15_insn (env, s, insn))
2943
                    goto illegal_op;
2944
                break;
2945
            default:
2946
                /* unknown coprocessor.  */
2947
                goto illegal_op;
2948
            }
2949
            break;
2950
        case 0xf:
2951
            /* swi */
2952
            gen_op_movl_T0_im((long)s->pc);
2953
            gen_op_movl_reg_TN[0][15]();
2954
            gen_op_swi();
2955
            s->is_jmp = DISAS_JUMP;
2956
            break;
2957
        default:
2958
        illegal_op:
2959
            gen_op_movl_T0_im((long)s->pc - 4);
2960
            gen_op_movl_reg_TN[0][15]();
2961
            gen_op_undef_insn();
2962
            s->is_jmp = DISAS_JUMP;
2963
            break;
2964
        }
2965
    }
2966
}
2967

    
2968
static void disas_thumb_insn(DisasContext *s)
2969
{
2970
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
2971
    int32_t offset;
2972
    int i;
2973

    
2974
    insn = lduw_code(s->pc);
2975
    s->pc += 2;
2976

    
2977
    switch (insn >> 12) {
2978
    case 0: case 1:
2979
        rd = insn & 7;
2980
        op = (insn >> 11) & 3;
2981
        if (op == 3) {
2982
            /* add/subtract */
2983
            rn = (insn >> 3) & 7;
2984
            gen_movl_T0_reg(s, rn);
2985
            if (insn & (1 << 10)) {
2986
                /* immediate */
2987
                gen_op_movl_T1_im((insn >> 6) & 7);
2988
            } else {
2989
                /* reg */
2990
                rm = (insn >> 6) & 7;
2991
                gen_movl_T1_reg(s, rm);
2992
            }
2993
            if (insn & (1 << 9))
2994
                gen_op_subl_T0_T1_cc();
2995
            else
2996
                gen_op_addl_T0_T1_cc();
2997
            gen_movl_reg_T0(s, rd);
2998
        } else {
2999
            /* shift immediate */
3000
            rm = (insn >> 3) & 7;
3001
            shift = (insn >> 6) & 0x1f;
3002
            gen_movl_T0_reg(s, rm);
3003
            gen_shift_T0_im_thumb[op](shift);
3004
            gen_movl_reg_T0(s, rd);
3005
        }
3006
        break;
3007
    case 2: case 3:
3008
        /* arithmetic large immediate */
3009
        op = (insn >> 11) & 3;
3010
        rd = (insn >> 8) & 0x7;
3011
        if (op == 0) {
3012
            gen_op_movl_T0_im(insn & 0xff);
3013
        } else {
3014
            gen_movl_T0_reg(s, rd);
3015
            gen_op_movl_T1_im(insn & 0xff);
3016
        }
3017
        switch (op) {
3018
        case 0: /* mov */
3019
            gen_op_logic_T0_cc();
3020
            break;
3021
        case 1: /* cmp */
3022
            gen_op_subl_T0_T1_cc();
3023
            break;
3024
        case 2: /* add */
3025
            gen_op_addl_T0_T1_cc();
3026
            break;
3027
        case 3: /* sub */
3028
            gen_op_subl_T0_T1_cc();
3029
            break;
3030
        }
3031
        if (op != 1)
3032
            gen_movl_reg_T0(s, rd);
3033
        break;
3034
    case 4:
3035
        if (insn & (1 << 11)) {
3036
            rd = (insn >> 8) & 7;
3037
            /* load pc-relative.  Bit 1 of PC is ignored.  */
3038
            val = s->pc + 2 + ((insn & 0xff) * 4);
3039
            val &= ~(uint32_t)2;
3040
            gen_op_movl_T1_im(val);
3041
            gen_ldst(ldl, s);
3042
            gen_movl_reg_T0(s, rd);
3043
            break;
3044
        }
3045
        if (insn & (1 << 10)) {
3046
            /* data processing extended or blx */
3047
            rd = (insn & 7) | ((insn >> 4) & 8);
3048
            rm = (insn >> 3) & 0xf;
3049
            op = (insn >> 8) & 3;
3050
            switch (op) {
3051
            case 0: /* add */
3052
                gen_movl_T0_reg(s, rd);
3053
                gen_movl_T1_reg(s, rm);
3054
                gen_op_addl_T0_T1();
3055
                gen_movl_reg_T0(s, rd);
3056
                break;
3057
            case 1: /* cmp */
3058
                gen_movl_T0_reg(s, rd);
3059
                gen_movl_T1_reg(s, rm);
3060
                gen_op_subl_T0_T1_cc();
3061
                break;
3062
            case 2: /* mov/cpy */
3063
                gen_movl_T0_reg(s, rm);
3064
                gen_movl_reg_T0(s, rd);
3065
                break;
3066
            case 3:/* branch [and link] exchange thumb register */
3067
                if (insn & (1 << 7)) {
3068
                    val = (uint32_t)s->pc | 1;
3069
                    gen_op_movl_T1_im(val);
3070
                    gen_movl_reg_T1(s, 14);
3071
                }
3072
                gen_movl_T0_reg(s, rm);
3073
                gen_bx(s);
3074
                break;
3075
            }
3076
            break;
3077
        }
3078

    
3079
        /* data processing register */
3080
        rd = insn & 7;
3081
        rm = (insn >> 3) & 7;
3082
        op = (insn >> 6) & 0xf;
3083
        if (op == 2 || op == 3 || op == 4 || op == 7) {
3084
            /* the shift/rotate ops want the operands backwards */
3085
            val = rm;
3086
            rm = rd;
3087
            rd = val;
3088
            val = 1;
3089
        } else {
3090
            val = 0;
3091
        }
3092

    
3093
        if (op == 9) /* neg */
3094
            gen_op_movl_T0_im(0);
3095
        else if (op != 0xf) /* mvn doesn't read its first operand */
3096
            gen_movl_T0_reg(s, rd);
3097

    
3098
        gen_movl_T1_reg(s, rm);
3099
        switch (op) {
3100
        case 0x0: /* and */
3101
            gen_op_andl_T0_T1();
3102
            gen_op_logic_T0_cc();
3103
            break;
3104
        case 0x1: /* eor */
3105
            gen_op_xorl_T0_T1();
3106
            gen_op_logic_T0_cc();
3107
            break;
3108
        case 0x2: /* lsl */
3109
            gen_op_shll_T1_T0_cc();
3110
            gen_op_logic_T1_cc();
3111
            break;
3112
        case 0x3: /* lsr */
3113
            gen_op_shrl_T1_T0_cc();
3114
            gen_op_logic_T1_cc();
3115
            break;
3116
        case 0x4: /* asr */
3117
            gen_op_sarl_T1_T0_cc();
3118
            gen_op_logic_T1_cc();
3119
            break;
3120
        case 0x5: /* adc */
3121
            gen_op_adcl_T0_T1_cc();
3122
            break;
3123
        case 0x6: /* sbc */
3124
            gen_op_sbcl_T0_T1_cc();
3125
            break;
3126
        case 0x7: /* ror */
3127
            gen_op_rorl_T1_T0_cc();
3128
            gen_op_logic_T1_cc();
3129
            break;
3130
        case 0x8: /* tst */
3131
            gen_op_andl_T0_T1();
3132
            gen_op_logic_T0_cc();
3133
            rd = 16;
3134
            break;
3135
        case 0x9: /* neg */
3136
            gen_op_subl_T0_T1_cc();
3137
            break;
3138
        case 0xa: /* cmp */
3139
            gen_op_subl_T0_T1_cc();
3140
            rd = 16;
3141
            break;
3142
        case 0xb: /* cmn */
3143
            gen_op_addl_T0_T1_cc();
3144
            rd = 16;
3145
            break;
3146
        case 0xc: /* orr */
3147
            gen_op_orl_T0_T1();
3148
            gen_op_logic_T0_cc();
3149
            break;
3150
        case 0xd: /* mul */
3151
            gen_op_mull_T0_T1();
3152
            gen_op_logic_T0_cc();
3153
            break;
3154
        case 0xe: /* bic */
3155
            gen_op_bicl_T0_T1();
3156
            gen_op_logic_T0_cc();
3157
            break;
3158
        case 0xf: /* mvn */
3159
            gen_op_notl_T1();
3160
            gen_op_logic_T1_cc();
3161
            val = 1;
3162
            rm = rd;
3163
            break;
3164
        }
3165
        if (rd != 16) {
3166
            if (val)
3167
                gen_movl_reg_T1(s, rm);
3168
            else
3169
                gen_movl_reg_T0(s, rd);
3170
        }
3171
        break;
3172

    
3173
    case 5:
3174
        /* load/store register offset.  */
3175
        rd = insn & 7;
3176
        rn = (insn >> 3) & 7;
3177
        rm = (insn >> 6) & 7;
3178
        op = (insn >> 9) & 7;
3179
        gen_movl_T1_reg(s, rn);
3180
        gen_movl_T2_reg(s, rm);
3181
        gen_op_addl_T1_T2();
3182

    
3183
        if (op < 3) /* store */
3184
            gen_movl_T0_reg(s, rd);
3185

    
3186
        switch (op) {
3187
        case 0: /* str */
3188
            gen_ldst(stl, s);
3189
            break;
3190
        case 1: /* strh */
3191
            gen_ldst(stw, s);
3192
            break;
3193
        case 2: /* strb */
3194
            gen_ldst(stb, s);
3195
            break;
3196
        case 3: /* ldrsb */
3197
            gen_ldst(ldsb, s);
3198
            break;
3199
        case 4: /* ldr */
3200
            gen_ldst(ldl, s);
3201
            break;
3202
        case 5: /* ldrh */
3203
            gen_ldst(lduw, s);
3204
            break;
3205
        case 6: /* ldrb */
3206
            gen_ldst(ldub, s);
3207
            break;
3208
        case 7: /* ldrsh */
3209
            gen_ldst(ldsw, s);
3210
            break;
3211
        }
3212
        if (op >= 3) /* load */
3213
            gen_movl_reg_T0(s, rd);
3214
        break;
3215

    
3216
    case 6:
3217
        /* load/store word immediate offset */
3218
        rd = insn & 7;
3219
        rn = (insn >> 3) & 7;
3220
        gen_movl_T1_reg(s, rn);
3221
        val = (insn >> 4) & 0x7c;
3222
        gen_op_movl_T2_im(val);
3223
        gen_op_addl_T1_T2();
3224

    
3225
        if (insn & (1 << 11)) {
3226
            /* load */
3227
            gen_ldst(ldl, s);
3228
            gen_movl_reg_T0(s, rd);
3229
        } else {
3230
            /* store */
3231
            gen_movl_T0_reg(s, rd);
3232
            gen_ldst(stl, s);
3233
        }
3234
        break;
3235

    
3236
    case 7:
3237
        /* load/store byte immediate offset */
3238
        rd = insn & 7;
3239
        rn = (insn >> 3) & 7;
3240
        gen_movl_T1_reg(s, rn);
3241
        val = (insn >> 6) & 0x1f;
3242
        gen_op_movl_T2_im(val);
3243
        gen_op_addl_T1_T2();
3244

    
3245
        if (insn & (1 << 11)) {
3246
            /* load */
3247
            gen_ldst(ldub, s);
3248
            gen_movl_reg_T0(s, rd);
3249
        } else {
3250
            /* store */
3251
            gen_movl_T0_reg(s, rd);
3252
            gen_ldst(stb, s);
3253
        }
3254
        break;
3255

    
3256
    case 8:
3257
        /* load/store halfword immediate offset */
3258
        rd = insn & 7;
3259
        rn = (insn >> 3) & 7;
3260
        gen_movl_T1_reg(s, rn);
3261
        val = (insn >> 5) & 0x3e;
3262
        gen_op_movl_T2_im(val);
3263
        gen_op_addl_T1_T2();
3264

    
3265
        if (insn & (1 << 11)) {
3266
            /* load */
3267
            gen_ldst(lduw, s);
3268
            gen_movl_reg_T0(s, rd);
3269
        } else {
3270
            /* store */
3271
            gen_movl_T0_reg(s, rd);
3272
            gen_ldst(stw, s);
3273
        }
3274
        break;
3275

    
3276
    case 9:
3277
        /* load/store from stack */
3278
        rd = (insn >> 8) & 7;
3279
        gen_movl_T1_reg(s, 13);
3280
        val = (insn & 0xff) * 4;
3281
        gen_op_movl_T2_im(val);
3282
        gen_op_addl_T1_T2();
3283

    
3284
        if (insn & (1 << 11)) {
3285
            /* load */
3286
            gen_ldst(ldl, s);
3287
            gen_movl_reg_T0(s, rd);
3288
        } else {
3289
            /* store */
3290
            gen_movl_T0_reg(s, rd);
3291
            gen_ldst(stl, s);
3292
        }
3293
        break;
3294

    
3295
    case 10:
3296
        /* add to high reg */
3297
        rd = (insn >> 8) & 7;
3298
        if (insn & (1 << 11)) {
3299
            /* SP */
3300
            gen_movl_T0_reg(s, 13);
3301
        } else {
3302
            /* PC. bit 1 is ignored.  */
3303
            gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
3304
        }
3305
        val = (insn & 0xff) * 4;
3306
        gen_op_movl_T1_im(val);
3307
        gen_op_addl_T0_T1();
3308
        gen_movl_reg_T0(s, rd);
3309
        break;
3310

    
3311
    case 11:
3312
        /* misc */
3313
        op = (insn >> 8) & 0xf;
3314
        switch (op) {
3315
        case 0:
3316
            /* adjust stack pointer */
3317
            gen_movl_T1_reg(s, 13);
3318
            val = (insn & 0x7f) * 4;
3319
            if (insn & (1 << 7))
3320
              val = -(int32_t)val;
3321
            gen_op_movl_T2_im(val);
3322
            gen_op_addl_T1_T2();
3323
            gen_movl_reg_T1(s, 13);
3324
            break;
3325

    
3326
        case 4: case 5: case 0xc: case 0xd:
3327
            /* push/pop */
3328
            gen_movl_T1_reg(s, 13);
3329
            if (insn & (1 << 8))
3330
                offset = 4;
3331
            else
3332
                offset = 0;
3333
            for (i = 0; i < 8; i++) {
3334
                if (insn & (1 << i))
3335
                    offset += 4;
3336
            }
3337
            if ((insn & (1 << 11)) == 0) {
3338
                gen_op_movl_T2_im(-offset);
3339
                gen_op_addl_T1_T2();
3340
            }
3341
            gen_op_movl_T2_im(4);
3342
            for (i = 0; i < 8; i++) {
3343
                if (insn & (1 << i)) {
3344
                    if (insn & (1 << 11)) {
3345
                        /* pop */
3346
                        gen_ldst(ldl, s);
3347
                        gen_movl_reg_T0(s, i);
3348
                    } else {
3349
                        /* push */
3350
                        gen_movl_T0_reg(s, i);
3351
                        gen_ldst(stl, s);
3352
                    }
3353
                    /* advance to the next address.  */
3354
                    gen_op_addl_T1_T2();
3355
                }
3356
            }
3357
            if (insn & (1 << 8)) {
3358
                if (insn & (1 << 11)) {
3359
                    /* pop pc */
3360
                    gen_ldst(ldl, s);
3361
                    /* don't set the pc until the rest of the instruction
3362
                       has completed */
3363
                } else {
3364
                    /* push lr */
3365
                    gen_movl_T0_reg(s, 14);
3366
                    gen_ldst(stl, s);
3367
                }
3368
                gen_op_addl_T1_T2();
3369
            }
3370
            if ((insn & (1 << 11)) == 0) {
3371
                gen_op_movl_T2_im(-offset);
3372
                gen_op_addl_T1_T2();
3373
            }
3374
            /* write back the new stack pointer */
3375
            gen_movl_reg_T1(s, 13);
3376
            /* set the new PC value */
3377
            if ((insn & 0x0900) == 0x0900)
3378
                gen_bx(s);
3379
            break;
3380

    
3381
        case 0xe: /* bkpt */
3382
            gen_op_movl_T0_im((long)s->pc - 2);
3383
            gen_op_movl_reg_TN[0][15]();
3384
            gen_op_bkpt();
3385
            s->is_jmp = DISAS_JUMP;
3386
            break;
3387

    
3388
        default:
3389
            goto undef;
3390
        }
3391
        break;
3392

    
3393
    case 12:
3394
        /* load/store multiple */
3395
        rn = (insn >> 8) & 0x7;
3396
        gen_movl_T1_reg(s, rn);
3397
        gen_op_movl_T2_im(4);
3398
        for (i = 0; i < 8; i++) {
3399
            if (insn & (1 << i)) {
3400
                if (insn & (1 << 11)) {
3401
                    /* load */
3402
                    gen_ldst(ldl, s);
3403
                    gen_movl_reg_T0(s, i);
3404
                } else {
3405
                    /* store */
3406
                    gen_movl_T0_reg(s, i);
3407
                    gen_ldst(stl, s);
3408
                }
3409
                /* advance to the next address */
3410
                gen_op_addl_T1_T2();
3411
            }
3412
        }
3413
        /* Base register writeback.  */
3414
        if ((insn & (1 << rn)) == 0)
3415
            gen_movl_reg_T1(s, rn);
3416
        break;
3417

    
3418
    case 13:
3419
        /* conditional branch or swi */
3420
        cond = (insn >> 8) & 0xf;
3421
        if (cond == 0xe)
3422
            goto undef;
3423

    
3424
        if (cond == 0xf) {
3425
            /* swi */
3426
            gen_op_movl_T0_im((long)s->pc | 1);
3427
            /* Don't set r15.  */
3428
            gen_op_movl_reg_TN[0][15]();
3429
            gen_op_swi();
3430
            s->is_jmp = DISAS_JUMP;
3431
            break;
3432
        }
3433
        /* generate a conditional jump to next instruction */
3434
        s->condlabel = gen_new_label();
3435
        gen_test_cc[cond ^ 1](s->condlabel);
3436
        s->condjmp = 1;
3437
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
3438
        //s->is_jmp = DISAS_JUMP_NEXT;
3439
        gen_movl_T1_reg(s, 15);
3440

    
3441
        /* jump to the offset */
3442
        val = (uint32_t)s->pc + 2;
3443
        offset = ((int32_t)insn << 24) >> 24;
3444
        val += offset << 1;
3445
        gen_jmp(s, val);
3446
        break;
3447

    
3448
    case 14:
3449
        /* unconditional branch */
3450
        if (insn & (1 << 11)) {
3451
            /* Second half of blx.  */
3452
            offset = ((insn & 0x7ff) << 1);
3453
            gen_movl_T0_reg(s, 14);
3454
            gen_op_movl_T1_im(offset);
3455
            gen_op_addl_T0_T1();
3456
            gen_op_movl_T1_im(0xfffffffc);
3457
            gen_op_andl_T0_T1();
3458

    
3459
            val = (uint32_t)s->pc;
3460
            gen_op_movl_T1_im(val | 1);
3461
            gen_movl_reg_T1(s, 14);
3462
            gen_bx(s);
3463
            break;
3464
        }
3465
        val = (uint32_t)s->pc;
3466
        offset = ((int32_t)insn << 21) >> 21;
3467
        val += (offset << 1) + 2;
3468
        gen_jmp(s, val);
3469
        break;
3470

    
3471
    case 15:
3472
        /* branch and link [and switch to arm] */
3473
        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
3474
            /* Instruction spans a page boundary.  Implement it as two
3475
               16-bit instructions in case the second half causes an
3476
               prefetch abort.  */
3477
            offset = ((int32_t)insn << 21) >> 9;
3478
            val = s->pc + 2 + offset;
3479
            gen_op_movl_T0_im(val);
3480
            gen_movl_reg_T0(s, 14);
3481
            break;
3482
        }
3483
        if (insn & (1 << 11)) {
3484
            /* Second half of bl.  */
3485
            offset = ((insn & 0x7ff) << 1) | 1;
3486
            gen_movl_T0_reg(s, 14);
3487
            gen_op_movl_T1_im(offset);
3488
            gen_op_addl_T0_T1();
3489

    
3490
            val = (uint32_t)s->pc;
3491
            gen_op_movl_T1_im(val | 1);
3492
            gen_movl_reg_T1(s, 14);
3493
            gen_bx(s);
3494
            break;
3495
        }
3496
        offset = ((int32_t)insn << 21) >> 10;
3497
        insn = lduw_code(s->pc);
3498
        offset |= insn & 0x7ff;
3499

    
3500
        val = (uint32_t)s->pc + 2;
3501
        gen_op_movl_T1_im(val | 1);
3502
        gen_movl_reg_T1(s, 14);
3503

    
3504
        val += offset << 1;
3505
        if (insn & (1 << 12)) {
3506
            /* bl */
3507
            gen_jmp(s, val);
3508
        } else {
3509
            /* blx */
3510
            val &= ~(uint32_t)2;
3511
            gen_op_movl_T0_im(val);
3512
            gen_bx(s);
3513
        }
3514
    }
3515
    return;
3516
undef:
3517
    gen_op_movl_T0_im((long)s->pc - 2);
3518
    gen_op_movl_reg_TN[0][15]();
3519
    gen_op_undef_insn();
3520
    s->is_jmp = DISAS_JUMP;
3521
}
3522

    
3523
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
3524
   basic block 'tb'. If search_pc is TRUE, also generate PC
3525
   information for each intermediate instruction. */
3526
static inline int gen_intermediate_code_internal(CPUState *env,
3527
                                                 TranslationBlock *tb,
3528
                                                 int search_pc)
3529
{
3530
    DisasContext dc1, *dc = &dc1;
3531
    uint16_t *gen_opc_end;
3532
    int j, lj;
3533
    target_ulong pc_start;
3534
    uint32_t next_page_start;
3535

    
3536
    /* generate intermediate code */
3537
    pc_start = tb->pc;
3538

    
3539
    dc->tb = tb;
3540

    
3541
    gen_opc_ptr = gen_opc_buf;
3542
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3543
    gen_opparam_ptr = gen_opparam_buf;
3544

    
3545
    dc->is_jmp = DISAS_NEXT;
3546
    dc->pc = pc_start;
3547
    dc->singlestep_enabled = env->singlestep_enabled;
3548
    dc->condjmp = 0;
3549
    dc->thumb = env->thumb;
3550
    dc->is_mem = 0;
3551
#if !defined(CONFIG_USER_ONLY)
3552
    dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
3553
#endif
3554
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
3555
    nb_gen_labels = 0;
3556
    lj = -1;
3557
    do {
3558
        if (env->nb_breakpoints > 0) {
3559
            for(j = 0; j < env->nb_breakpoints; j++) {
3560
                if (env->breakpoints[j] == dc->pc) {
3561
                    gen_op_movl_T0_im((long)dc->pc);
3562
                    gen_op_movl_reg_TN[0][15]();
3563
                    gen_op_debug();
3564
                    dc->is_jmp = DISAS_JUMP;
3565
                    break;
3566
                }
3567
            }
3568
        }
3569
        if (search_pc) {
3570
            j = gen_opc_ptr - gen_opc_buf;
3571
            if (lj < j) {
3572
                lj++;
3573
                while (lj < j)
3574
                    gen_opc_instr_start[lj++] = 0;
3575
            }
3576
            gen_opc_pc[lj] = dc->pc;
3577
            gen_opc_instr_start[lj] = 1;
3578
        }
3579

    
3580
        if (env->thumb)
3581
          disas_thumb_insn(dc);
3582
        else
3583
          disas_arm_insn(env, dc);
3584

    
3585
        if (dc->condjmp && !dc->is_jmp) {
3586
            gen_set_label(dc->condlabel);
3587
            dc->condjmp = 0;
3588
        }
3589
        /* Terminate the TB on memory ops if watchpoints are present.  */
3590
        /* FIXME: This should be replacd by the deterministic execution
3591
         * IRQ raising bits.  */
3592
        if (dc->is_mem && env->nb_watchpoints)
3593
            break;
3594

    
3595
        /* Translation stops when a conditional branch is enoutered.
3596
         * Otherwise the subsequent code could get translated several times.
3597
         * Also stop translation when a page boundary is reached.  This
3598
         * ensures prefech aborts occur at the right place.  */
3599
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3600
             !env->singlestep_enabled &&
3601
             dc->pc < next_page_start);
3602
    /* At this stage dc->condjmp will only be set when the skipped
3603
     * instruction was a conditional branch, and the PC has already been
3604
     * written.  */
3605
    if (__builtin_expect(env->singlestep_enabled, 0)) {
3606
        /* Make sure the pc is updated, and raise a debug exception.  */
3607
        if (dc->condjmp) {
3608
            gen_op_debug();
3609
            gen_set_label(dc->condlabel);
3610
        }
3611
        if (dc->condjmp || !dc->is_jmp) {
3612
            gen_op_movl_T0_im((long)dc->pc);
3613
            gen_op_movl_reg_TN[0][15]();
3614
            dc->condjmp = 0;
3615
        }
3616
        gen_op_debug();
3617
    } else {
3618
        switch(dc->is_jmp) {
3619
        case DISAS_NEXT:
3620
            gen_goto_tb(dc, 1, dc->pc);
3621
            break;
3622
        default:
3623
        case DISAS_JUMP:
3624
        case DISAS_UPDATE:
3625
            /* indicate that the hash table must be used to find the next TB */
3626
            gen_op_movl_T0_0();
3627
            gen_op_exit_tb();
3628
            break;
3629
        case DISAS_TB_JUMP:
3630
            /* nothing more to generate */
3631
            break;
3632
        }
3633
        if (dc->condjmp) {
3634
            gen_set_label(dc->condlabel);
3635
            gen_goto_tb(dc, 1, dc->pc);
3636
            dc->condjmp = 0;
3637
        }
3638
    }
3639
    *gen_opc_ptr = INDEX_op_end;
3640

    
3641
#ifdef DEBUG_DISAS
3642
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3643
        fprintf(logfile, "----------------\n");
3644
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3645
        target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
3646
        fprintf(logfile, "\n");
3647
        if (loglevel & (CPU_LOG_TB_OP)) {
3648
            fprintf(logfile, "OP:\n");
3649
            dump_ops(gen_opc_buf, gen_opparam_buf);
3650
            fprintf(logfile, "\n");
3651
        }
3652
    }
3653
#endif
3654
    if (search_pc) {
3655
        j = gen_opc_ptr - gen_opc_buf;
3656
        lj++;
3657
        while (lj <= j)
3658
            gen_opc_instr_start[lj++] = 0;
3659
    } else {
3660
        tb->size = dc->pc - pc_start;
3661
    }
3662
    return 0;
3663
}
3664

    
3665
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
3666
{
3667
    return gen_intermediate_code_internal(env, tb, 0);
3668
}
3669

    
3670
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
3671
{
3672
    return gen_intermediate_code_internal(env, tb, 1);
3673
}
3674

    
3675
static const char *cpu_mode_names[16] = {
3676
  "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
3677
  "???", "???", "???", "und", "???", "???", "???", "sys"
3678
};
3679
void cpu_dump_state(CPUState *env, FILE *f,
3680
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
3681
                    int flags)
3682
{
3683
    int i;
3684
    union {
3685
        uint32_t i;
3686
        float s;
3687
    } s0, s1;
3688
    CPU_DoubleU d;
3689
    /* ??? This assumes float64 and double have the same layout.
3690
       Oh well, it's only debug dumps.  */
3691
    union {
3692
        float64 f64;
3693
        double d;
3694
    } d0;
3695
    uint32_t psr;
3696

    
3697
    for(i=0;i<16;i++) {
3698
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
3699
        if ((i % 4) == 3)
3700
            cpu_fprintf(f, "\n");
3701
        else
3702
            cpu_fprintf(f, " ");
3703
    }
3704
    psr = cpsr_read(env);
3705
    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
3706
                psr,
3707
                psr & (1 << 31) ? 'N' : '-',
3708
                psr & (1 << 30) ? 'Z' : '-',
3709
                psr & (1 << 29) ? 'C' : '-',
3710
                psr & (1 << 28) ? 'V' : '-',
3711
                psr & CPSR_T ? 'T' : 'A',
3712
                cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
3713

    
3714
    for (i = 0; i < 16; i++) {
3715
        d.d = env->vfp.regs[i];
3716
        s0.i = d.l.lower;
3717
        s1.i = d.l.upper;
3718
        d0.f64 = d.d;
3719
        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
3720
                    i * 2, (int)s0.i, s0.s,
3721
                    i * 2 + 1, (int)s1.i, s1.s,
3722
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
3723
                    d0.d);
3724
    }
3725
    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
3726
}
3727