Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 173d6cfe

History | View | Annotate | Download (67.2 kB)

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

    
27
#include "cpu.h"
28
#include "exec-all.h"
29
#include "disas.h"
30

    
31
/* internal defines */
32
typedef struct DisasContext {
33
    target_ulong pc;
34
    int is_jmp;
35
    /* Nonzero if this instruction has been conditionally skipped.  */
36
    int condjmp;
37
    /* The label that will be jumped to when the instruction is skipped.  */
38
    int condlabel;
39
    struct TranslationBlock *tb;
40
    int singlestep_enabled;
41
    int thumb;
42
} DisasContext;
43

    
44
#define DISAS_JUMP_NEXT 4
45

    
46
#ifdef USE_DIRECT_JUMP
47
#define TBPARAM(x)
48
#else
49
#define TBPARAM(x) (long)(x)
50
#endif
51

    
52
/* XXX: move that elsewhere */
53
static uint16_t *gen_opc_ptr;
54
static uint32_t *gen_opparam_ptr;
55
extern FILE *logfile;
56
extern int loglevel;
57

    
58
enum {
59
#define DEF(s, n, copy_size) INDEX_op_ ## s,
60
#include "opc.h"
61
#undef DEF
62
    NB_OPS,
63
};
64

    
65
#include "gen-op.h"
66

    
67
static GenOpFunc1 *gen_test_cc[14] = {
68
    gen_op_test_eq,
69
    gen_op_test_ne,
70
    gen_op_test_cs,
71
    gen_op_test_cc,
72
    gen_op_test_mi,
73
    gen_op_test_pl,
74
    gen_op_test_vs,
75
    gen_op_test_vc,
76
    gen_op_test_hi,
77
    gen_op_test_ls,
78
    gen_op_test_ge,
79
    gen_op_test_lt,
80
    gen_op_test_gt,
81
    gen_op_test_le,
82
};
83

    
84
const uint8_t table_logic_cc[16] = {
85
    1, /* and */
86
    1, /* xor */
87
    0, /* sub */
88
    0, /* rsb */
89
    0, /* add */
90
    0, /* adc */
91
    0, /* sbc */
92
    0, /* rsc */
93
    1, /* andl */
94
    1, /* xorl */
95
    0, /* cmp */
96
    0, /* cmn */
97
    1, /* orr */
98
    1, /* mov */
99
    1, /* bic */
100
    1, /* mvn */
101
};
102
    
103
static GenOpFunc1 *gen_shift_T1_im[4] = {
104
    gen_op_shll_T1_im,
105
    gen_op_shrl_T1_im,
106
    gen_op_sarl_T1_im,
107
    gen_op_rorl_T1_im,
108
};
109

    
110
static GenOpFunc *gen_shift_T1_0[4] = {
111
    NULL,
112
    gen_op_shrl_T1_0,
113
    gen_op_sarl_T1_0,
114
    gen_op_rrxl_T1,
115
};
116

    
117
static GenOpFunc1 *gen_shift_T2_im[4] = {
118
    gen_op_shll_T2_im,
119
    gen_op_shrl_T2_im,
120
    gen_op_sarl_T2_im,
121
    gen_op_rorl_T2_im,
122
};
123

    
124
static GenOpFunc *gen_shift_T2_0[4] = {
125
    NULL,
126
    gen_op_shrl_T2_0,
127
    gen_op_sarl_T2_0,
128
    gen_op_rrxl_T2,
129
};
130

    
131
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
132
    gen_op_shll_T1_im_cc,
133
    gen_op_shrl_T1_im_cc,
134
    gen_op_sarl_T1_im_cc,
135
    gen_op_rorl_T1_im_cc,
136
};
137

    
138
static GenOpFunc *gen_shift_T1_0_cc[4] = {
139
    NULL,
140
    gen_op_shrl_T1_0_cc,
141
    gen_op_sarl_T1_0_cc,
142
    gen_op_rrxl_T1_cc,
143
};
144

    
145
static GenOpFunc *gen_shift_T1_T0[4] = {
146
    gen_op_shll_T1_T0,
147
    gen_op_shrl_T1_T0,
148
    gen_op_sarl_T1_T0,
149
    gen_op_rorl_T1_T0,
150
};
151

    
152
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
153
    gen_op_shll_T1_T0_cc,
154
    gen_op_shrl_T1_T0_cc,
155
    gen_op_sarl_T1_T0_cc,
156
    gen_op_rorl_T1_T0_cc,
157
};
158

    
159
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
160
    {
161
        gen_op_movl_T0_r0,
162
        gen_op_movl_T0_r1,
163
        gen_op_movl_T0_r2,
164
        gen_op_movl_T0_r3,
165
        gen_op_movl_T0_r4,
166
        gen_op_movl_T0_r5,
167
        gen_op_movl_T0_r6,
168
        gen_op_movl_T0_r7,
169
        gen_op_movl_T0_r8,
170
        gen_op_movl_T0_r9,
171
        gen_op_movl_T0_r10,
172
        gen_op_movl_T0_r11,
173
        gen_op_movl_T0_r12,
174
        gen_op_movl_T0_r13,
175
        gen_op_movl_T0_r14,
176
        gen_op_movl_T0_r15,
177
    },
178
    {
179
        gen_op_movl_T1_r0,
180
        gen_op_movl_T1_r1,
181
        gen_op_movl_T1_r2,
182
        gen_op_movl_T1_r3,
183
        gen_op_movl_T1_r4,
184
        gen_op_movl_T1_r5,
185
        gen_op_movl_T1_r6,
186
        gen_op_movl_T1_r7,
187
        gen_op_movl_T1_r8,
188
        gen_op_movl_T1_r9,
189
        gen_op_movl_T1_r10,
190
        gen_op_movl_T1_r11,
191
        gen_op_movl_T1_r12,
192
        gen_op_movl_T1_r13,
193
        gen_op_movl_T1_r14,
194
        gen_op_movl_T1_r15,
195
    },
196
    {
197
        gen_op_movl_T2_r0,
198
        gen_op_movl_T2_r1,
199
        gen_op_movl_T2_r2,
200
        gen_op_movl_T2_r3,
201
        gen_op_movl_T2_r4,
202
        gen_op_movl_T2_r5,
203
        gen_op_movl_T2_r6,
204
        gen_op_movl_T2_r7,
205
        gen_op_movl_T2_r8,
206
        gen_op_movl_T2_r9,
207
        gen_op_movl_T2_r10,
208
        gen_op_movl_T2_r11,
209
        gen_op_movl_T2_r12,
210
        gen_op_movl_T2_r13,
211
        gen_op_movl_T2_r14,
212
        gen_op_movl_T2_r15,
213
    },
214
};
215

    
216
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
217
    {
218
        gen_op_movl_r0_T0,
219
        gen_op_movl_r1_T0,
220
        gen_op_movl_r2_T0,
221
        gen_op_movl_r3_T0,
222
        gen_op_movl_r4_T0,
223
        gen_op_movl_r5_T0,
224
        gen_op_movl_r6_T0,
225
        gen_op_movl_r7_T0,
226
        gen_op_movl_r8_T0,
227
        gen_op_movl_r9_T0,
228
        gen_op_movl_r10_T0,
229
        gen_op_movl_r11_T0,
230
        gen_op_movl_r12_T0,
231
        gen_op_movl_r13_T0,
232
        gen_op_movl_r14_T0,
233
        gen_op_movl_r15_T0,
234
    },
235
    {
236
        gen_op_movl_r0_T1,
237
        gen_op_movl_r1_T1,
238
        gen_op_movl_r2_T1,
239
        gen_op_movl_r3_T1,
240
        gen_op_movl_r4_T1,
241
        gen_op_movl_r5_T1,
242
        gen_op_movl_r6_T1,
243
        gen_op_movl_r7_T1,
244
        gen_op_movl_r8_T1,
245
        gen_op_movl_r9_T1,
246
        gen_op_movl_r10_T1,
247
        gen_op_movl_r11_T1,
248
        gen_op_movl_r12_T1,
249
        gen_op_movl_r13_T1,
250
        gen_op_movl_r14_T1,
251
        gen_op_movl_r15_T1,
252
    },
253
};
254

    
255
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
256
    gen_op_movl_T0_im,
257
    gen_op_movl_T1_im,
258
    gen_op_movl_T2_im,
259
};
260

    
261
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
262
    gen_op_shll_T0_im_thumb,
263
    gen_op_shrl_T0_im_thumb,
264
    gen_op_sarl_T0_im_thumb,
265
};
266

    
267
static inline void gen_bx(DisasContext *s)
268
{
269
  s->is_jmp = DISAS_UPDATE;
270
  gen_op_bx_T0();
271
}
272

    
273
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
274
{
275
    int val;
276

    
277
    if (reg == 15) {
278
        /* normaly, since we updated PC, we need only to add one insn */
279
        if (s->thumb)
280
            val = (long)s->pc + 2;
281
        else
282
            val = (long)s->pc + 4;
283
        gen_op_movl_TN_im[t](val);
284
    } else {
285
        gen_op_movl_TN_reg[t][reg]();
286
    }
287
}
288

    
289
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
290
{
291
    gen_movl_TN_reg(s, reg, 0);
292
}
293

    
294
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
295
{
296
    gen_movl_TN_reg(s, reg, 1);
297
}
298

    
299
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
300
{
301
    gen_movl_TN_reg(s, reg, 2);
302
}
303

    
304
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
305
{
306
    gen_op_movl_reg_TN[t][reg]();
307
    if (reg == 15) {
308
        s->is_jmp = DISAS_JUMP;
309
    }
310
}
311

    
312
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
313
{
314
    gen_movl_reg_TN(s, reg, 0);
315
}
316

    
317
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
318
{
319
    gen_movl_reg_TN(s, reg, 1);
320
}
321

    
322
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
323
{
324
    int val, rm, shift, shiftop;
325

    
326
    if (!(insn & (1 << 25))) {
327
        /* immediate */
328
        val = insn & 0xfff;
329
        if (!(insn & (1 << 23)))
330
            val = -val;
331
        if (val != 0)
332
            gen_op_addl_T1_im(val);
333
    } else {
334
        /* shift/register */
335
        rm = (insn) & 0xf;
336
        shift = (insn >> 7) & 0x1f;
337
        gen_movl_T2_reg(s, rm);
338
        shiftop = (insn >> 5) & 3;
339
        if (shift != 0) {
340
            gen_shift_T2_im[shiftop](shift);
341
        } else if (shiftop != 0) {
342
            gen_shift_T2_0[shiftop]();
343
        }
344
        if (!(insn & (1 << 23)))
345
            gen_op_subl_T1_T2();
346
        else
347
            gen_op_addl_T1_T2();
348
    }
349
}
350

    
351
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
352
{
353
    int val, rm;
354
    
355
    if (insn & (1 << 22)) {
356
        /* immediate */
357
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
358
        if (!(insn & (1 << 23)))
359
            val = -val;
360
        if (val != 0)
361
            gen_op_addl_T1_im(val);
362
    } else {
363
        /* register */
364
        rm = (insn) & 0xf;
365
        gen_movl_T2_reg(s, rm);
366
        if (!(insn & (1 << 23)))
367
            gen_op_subl_T1_T2();
368
        else
369
            gen_op_addl_T1_T2();
370
    }
371
}
372

    
373
#define VFP_OP(name)                      \
374
static inline void gen_vfp_##name(int dp) \
375
{                                         \
376
    if (dp)                               \
377
        gen_op_vfp_##name##d();           \
378
    else                                  \
379
        gen_op_vfp_##name##s();           \
380
}
381

    
382
VFP_OP(add)
383
VFP_OP(sub)
384
VFP_OP(mul)
385
VFP_OP(div)
386
VFP_OP(neg)
387
VFP_OP(abs)
388
VFP_OP(sqrt)
389
VFP_OP(cmp)
390
VFP_OP(cmpe)
391
VFP_OP(F1_ld0)
392
VFP_OP(uito)
393
VFP_OP(sito)
394
VFP_OP(toui)
395
VFP_OP(touiz)
396
VFP_OP(tosi)
397
VFP_OP(tosiz)
398
VFP_OP(ld)
399
VFP_OP(st)
400

    
401
#undef VFP_OP
402

    
403
static inline long
404
vfp_reg_offset (int dp, int reg)
405
{
406
    if (dp)
407
        return offsetof(CPUARMState, vfp.regs[reg]);
408
    else if (reg & 1) {
409
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
410
          + offsetof(CPU_DoubleU, l.upper);
411
    } else {
412
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
413
          + offsetof(CPU_DoubleU, l.lower);
414
    }
415
}
416
static inline void gen_mov_F0_vreg(int dp, int reg)
417
{
418
    if (dp)
419
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
420
    else
421
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
422
}
423

    
424
static inline void gen_mov_F1_vreg(int dp, int reg)
425
{
426
    if (dp)
427
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
428
    else
429
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
430
}
431

    
432
static inline void gen_mov_vreg_F0(int dp, int reg)
433
{
434
    if (dp)
435
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
436
    else
437
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
438
}
439

    
440
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
441
   (ie. an undefined instruction).  */
442
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
443
{
444
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
445
    int dp, veclen;
446

    
447
    dp = ((insn & 0xf00) == 0xb00);
448
    switch ((insn >> 24) & 0xf) {
449
    case 0xe:
450
        if (insn & (1 << 4)) {
451
            /* single register transfer */
452
            if ((insn & 0x6f) != 0x00)
453
                return 1;
454
            rd = (insn >> 12) & 0xf;
455
            if (dp) {
456
                if (insn & 0x80)
457
                    return 1;
458
                rn = (insn >> 16) & 0xf;
459
                /* Get the existing value even for arm->vfp moves because
460
                   we only set half the register.  */
461
                gen_mov_F0_vreg(1, rn);
462
                gen_op_vfp_mrrd();
463
                if (insn & (1 << 20)) {
464
                    /* vfp->arm */
465
                    if (insn & (1 << 21))
466
                        gen_movl_reg_T1(s, rd);
467
                    else
468
                        gen_movl_reg_T0(s, rd);
469
                } else {
470
                    /* arm->vfp */
471
                    if (insn & (1 << 21))
472
                        gen_movl_T1_reg(s, rd);
473
                    else
474
                        gen_movl_T0_reg(s, rd);
475
                    gen_op_vfp_mdrr();
476
                    gen_mov_vreg_F0(dp, rn);
477
                }
478
            } else {
479
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
480
                if (insn & (1 << 20)) {
481
                    /* vfp->arm */
482
                    if (insn & (1 << 21)) {
483
                        /* system register */
484
                        switch (rn) {
485
                        case 0: /* fpsid */
486
                            n = 0x0091A0000;
487
                            break;
488
                        case 2: /* fpscr */
489
                            if (rd == 15)
490
                                gen_op_vfp_movl_T0_fpscr_flags();
491
                            else
492
                                gen_op_vfp_movl_T0_fpscr();
493
                            break;
494
                        default:
495
                            return 1;
496
                        }
497
                    } else {
498
                        gen_mov_F0_vreg(0, rn);
499
                        gen_op_vfp_mrs();
500
                    }
501
                    if (rd == 15) {
502
                        /* This will only set the 4 flag bits */
503
                        gen_op_movl_psr_T0();
504
                    } else
505
                        gen_movl_reg_T0(s, rd);
506
                } else {
507
                    /* arm->vfp */
508
                    gen_movl_T0_reg(s, rd);
509
                    if (insn & (1 << 21)) {
510
                        /* system register */
511
                        switch (rn) {
512
                        case 0: /* fpsid */
513
                            /* Writes are ignored.  */
514
                            break;
515
                        case 2: /* fpscr */
516
                            gen_op_vfp_movl_fpscr_T0();
517
                            /* This could change vector settings, so jump to
518
                               the next instuction.  */
519
                            gen_op_movl_T0_im(s->pc);
520
                            gen_movl_reg_T0(s, 15);
521
                            s->is_jmp = DISAS_UPDATE;
522
                            break;
523
                        default:
524
                            return 1;
525
                        }
526
                    } else {
527
                        gen_op_vfp_msr();
528
                        gen_mov_vreg_F0(0, rn);
529
                    }
530
                }
531
            }
532
        } else {
533
            /* data processing */
534
            /* The opcode is in bits 23, 21, 20 and 6.  */
535
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
536
            if (dp) {
537
                if (op == 15) {
538
                    /* rn is opcode */
539
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
540
                } else {
541
                    /* rn is register number */
542
                    if (insn & (1 << 7))
543
                        return 1;
544
                    rn = (insn >> 16) & 0xf;
545
                }
546

    
547
                if (op == 15 && (rn == 15 || rn > 17)) {
548
                    /* Integer or single precision destination.  */
549
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
550
                } else {
551
                    if (insn & (1 << 22))
552
                        return 1;
553
                    rd = (insn >> 12) & 0xf;
554
                }
555

    
556
                if (op == 15 && (rn == 16 || rn == 17)) {
557
                    /* Integer source.  */
558
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
559
                } else {
560
                    if (insn & (1 << 5))
561
                        return 1;
562
                    rm = insn & 0xf;
563
                }
564
            } else {
565
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
566
                if (op == 15 && rn == 15) {
567
                    /* Double precision destination.  */
568
                    if (insn & (1 << 22))
569
                        return 1;
570
                    rd = (insn >> 12) & 0xf;
571
                } else
572
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
573
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
574
            }
575

    
576
            veclen = env->vfp.vec_len;
577
            if (op == 15 && rn > 3)
578
                veclen = 0;
579

    
580
            /* Shut up compiler warnings.  */
581
            delta_m = 0;
582
            delta_d = 0;
583
            bank_mask = 0;
584
            
585
            if (veclen > 0) {
586
                if (dp)
587
                    bank_mask = 0xc;
588
                else
589
                    bank_mask = 0x18;
590

    
591
                /* Figure out what type of vector operation this is.  */
592
                if ((rd & bank_mask) == 0) {
593
                    /* scalar */
594
                    veclen = 0;
595
                } else {
596
                    if (dp)
597
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
598
                    else
599
                        delta_d = env->vfp.vec_stride + 1;
600

    
601
                    if ((rm & bank_mask) == 0) {
602
                        /* mixed scalar/vector */
603
                        delta_m = 0;
604
                    } else {
605
                        /* vector */
606
                        delta_m = delta_d;
607
                    }
608
                }
609
            }
610

    
611
            /* Load the initial operands.  */
612
            if (op == 15) {
613
                switch (rn) {
614
                case 16:
615
                case 17:
616
                    /* Integer source */
617
                    gen_mov_F0_vreg(0, rm);
618
                    break;
619
                case 8:
620
                case 9:
621
                    /* Compare */
622
                    gen_mov_F0_vreg(dp, rd);
623
                    gen_mov_F1_vreg(dp, rm);
624
                    break;
625
                case 10:
626
                case 11:
627
                    /* Compare with zero */
628
                    gen_mov_F0_vreg(dp, rd);
629
                    gen_vfp_F1_ld0(dp);
630
                    break;
631
                default:
632
                    /* One source operand.  */
633
                    gen_mov_F0_vreg(dp, rm);
634
                }
635
            } else {
636
                /* Two source operands.  */
637
                gen_mov_F0_vreg(dp, rn);
638
                gen_mov_F1_vreg(dp, rm);
639
            }
640

    
641
            for (;;) {
642
                /* Perform the calculation.  */
643
                switch (op) {
644
                case 0: /* mac: fd + (fn * fm) */
645
                    gen_vfp_mul(dp);
646
                    gen_mov_F1_vreg(dp, rd);
647
                    gen_vfp_add(dp);
648
                    break;
649
                case 1: /* nmac: fd - (fn * fm) */
650
                    gen_vfp_mul(dp);
651
                    gen_vfp_neg(dp);
652
                    gen_mov_F1_vreg(dp, rd);
653
                    gen_vfp_add(dp);
654
                    break;
655
                case 2: /* msc: -fd + (fn * fm) */
656
                    gen_vfp_mul(dp);
657
                    gen_mov_F1_vreg(dp, rd);
658
                    gen_vfp_sub(dp);
659
                    break;
660
                case 3: /* nmsc: -fd - (fn * fm)  */
661
                    gen_vfp_mul(dp);
662
                    gen_mov_F1_vreg(dp, rd);
663
                    gen_vfp_add(dp);
664
                    gen_vfp_neg(dp);
665
                    break;
666
                case 4: /* mul: fn * fm */
667
                    gen_vfp_mul(dp);
668
                    break;
669
                case 5: /* nmul: -(fn * fm) */
670
                    gen_vfp_mul(dp);
671
                    gen_vfp_neg(dp);
672
                    break;
673
                case 6: /* add: fn + fm */
674
                    gen_vfp_add(dp);
675
                    break;
676
                case 7: /* sub: fn - fm */
677
                    gen_vfp_sub(dp);
678
                    break;
679
                case 8: /* div: fn / fm */
680
                    gen_vfp_div(dp);
681
                    break;
682
                case 15: /* extension space */
683
                    switch (rn) {
684
                    case 0: /* cpy */
685
                        /* no-op */
686
                        break;
687
                    case 1: /* abs */
688
                        gen_vfp_abs(dp);
689
                        break;
690
                    case 2: /* neg */
691
                        gen_vfp_neg(dp);
692
                        break;
693
                    case 3: /* sqrt */
694
                        gen_vfp_sqrt(dp);
695
                        break;
696
                    case 8: /* cmp */
697
                        gen_vfp_cmp(dp);
698
                        break;
699
                    case 9: /* cmpe */
700
                        gen_vfp_cmpe(dp);
701
                        break;
702
                    case 10: /* cmpz */
703
                        gen_vfp_cmp(dp);
704
                        break;
705
                    case 11: /* cmpez */
706
                        gen_vfp_F1_ld0(dp);
707
                        gen_vfp_cmpe(dp);
708
                        break;
709
                    case 15: /* single<->double conversion */
710
                        if (dp)
711
                            gen_op_vfp_fcvtsd();
712
                        else
713
                            gen_op_vfp_fcvtds();
714
                        break;
715
                    case 16: /* fuito */
716
                        gen_vfp_uito(dp);
717
                        break;
718
                    case 17: /* fsito */
719
                        gen_vfp_sito(dp);
720
                        break;
721
                    case 24: /* ftoui */
722
                        gen_vfp_toui(dp);
723
                        break;
724
                    case 25: /* ftouiz */
725
                        gen_vfp_touiz(dp);
726
                        break;
727
                    case 26: /* ftosi */
728
                        gen_vfp_tosi(dp);
729
                        break;
730
                    case 27: /* ftosiz */
731
                        gen_vfp_tosiz(dp);
732
                        break;
733
                    default: /* undefined */
734
                        printf ("rn:%d\n", rn);
735
                        return 1;
736
                    }
737
                    break;
738
                default: /* undefined */
739
                    printf ("op:%d\n", op);
740
                    return 1;
741
                }
742

    
743
                /* Write back the result.  */
744
                if (op == 15 && (rn >= 8 && rn <= 11))
745
                    ; /* Comparison, do nothing.  */
746
                else if (op == 15 && rn > 17)
747
                    /* Integer result.  */
748
                    gen_mov_vreg_F0(0, rd);
749
                else if (op == 15 && rn == 15)
750
                    /* conversion */
751
                    gen_mov_vreg_F0(!dp, rd);
752
                else
753
                    gen_mov_vreg_F0(dp, rd);
754

    
755
                /* break out of the loop if we have finished  */
756
                if (veclen == 0)
757
                    break;
758

    
759
                if (op == 15 && delta_m == 0) {
760
                    /* single source one-many */
761
                    while (veclen--) {
762
                        rd = ((rd + delta_d) & (bank_mask - 1))
763
                             | (rd & bank_mask);
764
                        gen_mov_vreg_F0(dp, rd);
765
                    }
766
                    break;
767
                }
768
                /* Setup the next operands.  */
769
                veclen--;
770
                rd = ((rd + delta_d) & (bank_mask - 1))
771
                     | (rd & bank_mask);
772

    
773
                if (op == 15) {
774
                    /* One source operand.  */
775
                    rm = ((rm + delta_m) & (bank_mask - 1))
776
                         | (rm & bank_mask);
777
                    gen_mov_F0_vreg(dp, rm);
778
                } else {
779
                    /* Two source operands.  */
780
                    rn = ((rn + delta_d) & (bank_mask - 1))
781
                         | (rn & bank_mask);
782
                    gen_mov_F0_vreg(dp, rn);
783
                    if (delta_m) {
784
                        rm = ((rm + delta_m) & (bank_mask - 1))
785
                             | (rm & bank_mask);
786
                        gen_mov_F1_vreg(dp, rm);
787
                    }
788
                }
789
            }
790
        }
791
        break;
792
    case 0xc:
793
    case 0xd:
794
        if (dp && (insn & (1 << 22))) {
795
            /* two-register transfer */
796
            rn = (insn >> 16) & 0xf;
797
            rd = (insn >> 12) & 0xf;
798
            if (dp) {
799
                if (insn & (1 << 5))
800
                    return 1;
801
                rm = insn & 0xf;
802
            } else
803
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
804

    
805
            if (insn & (1 << 20)) {
806
                /* vfp->arm */
807
                if (dp) {
808
                    gen_mov_F0_vreg(1, rm);
809
                    gen_op_vfp_mrrd();
810
                    gen_movl_reg_T0(s, rd);
811
                    gen_movl_reg_T1(s, rn);
812
                } else {
813
                    gen_mov_F0_vreg(0, rm);
814
                    gen_op_vfp_mrs();
815
                    gen_movl_reg_T0(s, rn);
816
                    gen_mov_F0_vreg(0, rm + 1);
817
                    gen_op_vfp_mrs();
818
                    gen_movl_reg_T0(s, rd);
819
                }
820
            } else {
821
                /* arm->vfp */
822
                if (dp) {
823
                    gen_movl_T0_reg(s, rd);
824
                    gen_movl_T1_reg(s, rn);
825
                    gen_op_vfp_mdrr();
826
                    gen_mov_vreg_F0(1, rm);
827
                } else {
828
                    gen_movl_T0_reg(s, rn);
829
                    gen_op_vfp_msr();
830
                    gen_mov_vreg_F0(0, rm);
831
                    gen_movl_T0_reg(s, rd);
832
                    gen_op_vfp_msr();
833
                    gen_mov_vreg_F0(0, rm + 1);
834
                }
835
            }
836
        } else {
837
            /* Load/store */
838
            rn = (insn >> 16) & 0xf;
839
            if (dp)
840
                rd = (insn >> 12) & 0xf;
841
            else
842
                rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
843
            gen_movl_T1_reg(s, rn);
844
            if ((insn & 0x01200000) == 0x01000000) {
845
                /* Single load/store */
846
                offset = (insn & 0xff) << 2;
847
                if ((insn & (1 << 23)) == 0)
848
                    offset = -offset;
849
                gen_op_addl_T1_im(offset);
850
                if (insn & (1 << 20)) {
851
                    gen_vfp_ld(dp);
852
                    gen_mov_vreg_F0(dp, rd);
853
                } else {
854
                    gen_mov_F0_vreg(dp, rd);
855
                    gen_vfp_st(dp);
856
                }
857
            } else {
858
                /* load/store multiple */
859
                if (dp)
860
                    n = (insn >> 1) & 0x7f;
861
                else
862
                    n = insn & 0xff;
863

    
864
                if (insn & (1 << 24)) /* pre-decrement */
865
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
866

    
867
                if (dp)
868
                    offset = 8;
869
                else
870
                    offset = 4;
871
                for (i = 0; i < n; i++) {
872
                    if (insn & (1 << 20)) {
873
                        /* load */
874
                        gen_vfp_ld(dp);
875
                        gen_mov_vreg_F0(dp, rd + i);
876
                    } else {
877
                        /* store */
878
                        gen_mov_F0_vreg(dp, rd + i);
879
                        gen_vfp_st(dp);
880
                    }
881
                    gen_op_addl_T1_im(offset);
882
                }
883
                if (insn & (1 << 21)) {
884
                    /* writeback */
885
                    if (insn & (1 << 24))
886
                        offset = -offset * n;
887
                    else if (dp && (insn & 1))
888
                        offset = 4;
889
                    else
890
                        offset = 0;
891

    
892
                    if (offset != 0)
893
                        gen_op_addl_T1_im(offset);
894
                    gen_movl_reg_T1(s, rn);
895
                }
896
            }
897
        }
898
        break;
899
    default:
900
        /* Should never happen.  */
901
        return 1;
902
    }
903
    return 0;
904
}
905

    
906
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
907
{
908
    TranslationBlock *tb;
909

    
910
    tb = s->tb;
911
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
912
        if (n == 0)
913
            gen_op_goto_tb0(TBPARAM(tb));
914
        else
915
            gen_op_goto_tb1(TBPARAM(tb));
916
        gen_op_movl_T0_im(dest);
917
        gen_op_movl_r15_T0();
918
        gen_op_movl_T0_im((long)tb + n);
919
        gen_op_exit_tb();
920
    } else {
921
        gen_op_movl_T0_im(dest);
922
        gen_op_movl_r15_T0();
923
        gen_op_movl_T0_0();
924
        gen_op_exit_tb();
925
    }
926
}
927

    
928
static inline void gen_jmp (DisasContext *s, uint32_t dest)
929
{
930
    if (__builtin_expect(s->singlestep_enabled, 0)) {
931
        /* An indirect jump so that we still trigger the debug exception.  */
932
        if (s->thumb)
933
          dest |= 1;
934
        gen_op_movl_T0_im(dest);
935
        gen_bx(s);
936
    } else {
937
        gen_goto_tb(s, 0, dest);
938
        s->is_jmp = DISAS_TB_JUMP;
939
    }
940
}
941

    
942
static void disas_arm_insn(CPUState * env, DisasContext *s)
943
{
944
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
945
    
946
    insn = ldl(s->pc);
947
    s->pc += 4;
948
    
949
    cond = insn >> 28;
950
    if (cond == 0xf){
951
        /* Unconditional instructions.  */
952
        if ((insn & 0x0d70f000) == 0x0550f000)
953
            return; /* PLD */
954
        else if ((insn & 0x0e000000) == 0x0a000000) {
955
            /* branch link and change to thumb (blx <offset>) */
956
            int32_t offset;
957

    
958
            val = (uint32_t)s->pc;
959
            gen_op_movl_T0_im(val);
960
            gen_movl_reg_T0(s, 14);
961
            /* Sign-extend the 24-bit offset */
962
            offset = (((int32_t)insn) << 8) >> 8;
963
            /* offset * 4 + bit24 * 2 + (thumb bit) */
964
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
965
            /* pipeline offset */
966
            val += 4;
967
            gen_op_movl_T0_im(val);
968
            gen_bx(s);
969
            return;
970
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
971
            /* Coprocessor double register transfer.  */
972
        } else if ((insn & 0x0f000010) == 0x0e000010) {
973
            /* Additional coprocessor register transfer.  */
974
        }
975
        goto illegal_op;
976
    }
977
    if (cond != 0xe) {
978
        /* if not always execute, we generate a conditional jump to
979
           next instruction */
980
        s->condlabel = gen_new_label();
981
        gen_test_cc[cond ^ 1](s->condlabel);
982
        s->condjmp = 1;
983
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
984
        //s->is_jmp = DISAS_JUMP_NEXT;
985
    }
986
    if ((insn & 0x0f900000) == 0x03000000) {
987
        if ((insn & 0x0ff0f000) != 0x0360f000)
988
            goto illegal_op;
989
        /* CPSR = immediate */
990
        val = insn & 0xff;
991
        shift = ((insn >> 8) & 0xf) * 2;
992
        if (shift)
993
            val = (val >> shift) | (val << (32 - shift));
994
        gen_op_movl_T0_im(val);
995
        if (insn & (1 << 19))
996
            gen_op_movl_psr_T0();
997
    } else if ((insn & 0x0f900000) == 0x01000000
998
               && (insn & 0x00000090) != 0x00000090) {
999
        /* miscellaneous instructions */
1000
        op1 = (insn >> 21) & 3;
1001
        sh = (insn >> 4) & 0xf;
1002
        rm = insn & 0xf;
1003
        switch (sh) {
1004
        case 0x0: /* move program status register */
1005
            if (op1 & 2) {
1006
                /* SPSR not accessible in user mode */
1007
                goto illegal_op;
1008
            }
1009
            if (op1 & 1) {
1010
                /* CPSR = reg */
1011
                gen_movl_T0_reg(s, rm);
1012
                if (insn & (1 << 19))
1013
                    gen_op_movl_psr_T0();
1014
            } else {
1015
                /* reg = CPSR */
1016
                rd = (insn >> 12) & 0xf;
1017
                gen_op_movl_T0_psr();
1018
                gen_movl_reg_T0(s, rd);
1019
            }
1020
            break;
1021
        case 0x1:
1022
            if (op1 == 1) {
1023
                /* branch/exchange thumb (bx).  */
1024
                gen_movl_T0_reg(s, rm);
1025
                gen_bx(s);
1026
            } else if (op1 == 3) {
1027
                /* clz */
1028
                rd = (insn >> 12) & 0xf;
1029
                gen_movl_T0_reg(s, rm);
1030
                gen_op_clz_T0();
1031
                gen_movl_reg_T0(s, rd);
1032
            } else {
1033
                goto illegal_op;
1034
            }
1035
            break;
1036
        case 0x3:
1037
            if (op1 != 1)
1038
              goto illegal_op;
1039

    
1040
            /* branch link/exchange thumb (blx) */
1041
            val = (uint32_t)s->pc;
1042
            gen_op_movl_T0_im(val);
1043
            gen_movl_reg_T0(s, 14);
1044
            gen_movl_T0_reg(s, rm);
1045
            gen_bx(s);
1046
            break;
1047
        case 0x5: /* saturating add/subtract */
1048
            rd = (insn >> 12) & 0xf;
1049
            rn = (insn >> 16) & 0xf;
1050
            gen_movl_T0_reg(s, rm);
1051
            gen_movl_T1_reg(s, rn);
1052
            if (op1 & 2)
1053
                gen_op_double_T1_saturate();
1054
            if (op1 & 1)
1055
                gen_op_subl_T0_T1_saturate();
1056
            else
1057
                gen_op_addl_T0_T1_saturate();
1058
            gen_movl_reg_T0(s, rd);
1059
            break;
1060
        case 0x8: /* signed multiply */
1061
        case 0xa:
1062
        case 0xc:
1063
        case 0xe:
1064
            rs = (insn >> 8) & 0xf;
1065
            rn = (insn >> 12) & 0xf;
1066
            rd = (insn >> 16) & 0xf;
1067
            if (op1 == 1) {
1068
                /* (32 * 16) >> 16 */
1069
                gen_movl_T0_reg(s, rm);
1070
                gen_movl_T1_reg(s, rs);
1071
                if (sh & 4)
1072
                    gen_op_sarl_T1_im(16);
1073
                else
1074
                    gen_op_sxl_T1();
1075
                gen_op_imulw_T0_T1();
1076
                if ((sh & 2) == 0) {
1077
                    gen_movl_T1_reg(s, rn);
1078
                    gen_op_addl_T0_T1_setq();
1079
                }
1080
                gen_movl_reg_T0(s, rd);
1081
            } else {
1082
                /* 16 * 16 */
1083
                gen_movl_T0_reg(s, rm);
1084
                if (sh & 2)
1085
                    gen_op_sarl_T0_im(16);
1086
                else
1087
                    gen_op_sxl_T0();
1088
                gen_movl_T1_reg(s, rs);
1089
                if (sh & 4)
1090
                    gen_op_sarl_T1_im(16);
1091
                else
1092
                    gen_op_sxl_T1();
1093
                if (op1 == 2) {
1094
                    gen_op_imull_T0_T1();
1095
                    gen_op_addq_T0_T1(rn, rd);
1096
                    gen_movl_reg_T0(s, rn);
1097
                    gen_movl_reg_T1(s, rd);
1098
                } else {
1099
                    gen_op_mul_T0_T1();
1100
                    if (op1 == 0) {
1101
                        gen_movl_T1_reg(s, rn);
1102
                        gen_op_addl_T0_T1_setq();
1103
                    }
1104
                    gen_movl_reg_T0(s, rd);
1105
                }
1106
            }
1107
            break;
1108
        default:
1109
            goto illegal_op;
1110
        }
1111
    } else if (((insn & 0x0e000000) == 0 &&
1112
                (insn & 0x00000090) != 0x90) ||
1113
               ((insn & 0x0e000000) == (1 << 25))) {
1114
        int set_cc, logic_cc, shiftop;
1115
        
1116
        op1 = (insn >> 21) & 0xf;
1117
        set_cc = (insn >> 20) & 1;
1118
        logic_cc = table_logic_cc[op1] & set_cc;
1119

    
1120
        /* data processing instruction */
1121
        if (insn & (1 << 25)) {
1122
            /* immediate operand */
1123
            val = insn & 0xff;
1124
            shift = ((insn >> 8) & 0xf) * 2;
1125
            if (shift)
1126
                val = (val >> shift) | (val << (32 - shift));
1127
            gen_op_movl_T1_im(val);
1128
            if (logic_cc && shift)
1129
                gen_op_mov_CF_T1();
1130
        } else {
1131
            /* register */
1132
            rm = (insn) & 0xf;
1133
            gen_movl_T1_reg(s, rm);
1134
            shiftop = (insn >> 5) & 3;
1135
            if (!(insn & (1 << 4))) {
1136
                shift = (insn >> 7) & 0x1f;
1137
                if (shift != 0) {
1138
                    if (logic_cc) {
1139
                        gen_shift_T1_im_cc[shiftop](shift);
1140
                    } else {
1141
                        gen_shift_T1_im[shiftop](shift);
1142
                    }
1143
                } else if (shiftop != 0) {
1144
                    if (logic_cc) {
1145
                        gen_shift_T1_0_cc[shiftop]();
1146
                    } else {
1147
                        gen_shift_T1_0[shiftop]();
1148
                    }
1149
                }
1150
            } else {
1151
                rs = (insn >> 8) & 0xf;
1152
                gen_movl_T0_reg(s, rs);
1153
                if (logic_cc) {
1154
                    gen_shift_T1_T0_cc[shiftop]();
1155
                } else {
1156
                    gen_shift_T1_T0[shiftop]();
1157
                }
1158
            }
1159
        }
1160
        if (op1 != 0x0f && op1 != 0x0d) {
1161
            rn = (insn >> 16) & 0xf;
1162
            gen_movl_T0_reg(s, rn);
1163
        }
1164
        rd = (insn >> 12) & 0xf;
1165
        switch(op1) {
1166
        case 0x00:
1167
            gen_op_andl_T0_T1();
1168
            gen_movl_reg_T0(s, rd);
1169
            if (logic_cc)
1170
                gen_op_logic_T0_cc();
1171
            break;
1172
        case 0x01:
1173
            gen_op_xorl_T0_T1();
1174
            gen_movl_reg_T0(s, rd);
1175
            if (logic_cc)
1176
                gen_op_logic_T0_cc();
1177
            break;
1178
        case 0x02:
1179
            if (set_cc)
1180
                gen_op_subl_T0_T1_cc();
1181
            else
1182
                gen_op_subl_T0_T1();
1183
            gen_movl_reg_T0(s, rd);
1184
            break;
1185
        case 0x03:
1186
            if (set_cc)
1187
                gen_op_rsbl_T0_T1_cc();
1188
            else
1189
                gen_op_rsbl_T0_T1();
1190
            gen_movl_reg_T0(s, rd);
1191
            break;
1192
        case 0x04:
1193
            if (set_cc)
1194
                gen_op_addl_T0_T1_cc();
1195
            else
1196
                gen_op_addl_T0_T1();
1197
            gen_movl_reg_T0(s, rd);
1198
            break;
1199
        case 0x05:
1200
            if (set_cc)
1201
                gen_op_adcl_T0_T1_cc();
1202
            else
1203
                gen_op_adcl_T0_T1();
1204
            gen_movl_reg_T0(s, rd);
1205
            break;
1206
        case 0x06:
1207
            if (set_cc)
1208
                gen_op_sbcl_T0_T1_cc();
1209
            else
1210
                gen_op_sbcl_T0_T1();
1211
            gen_movl_reg_T0(s, rd);
1212
            break;
1213
        case 0x07:
1214
            if (set_cc)
1215
                gen_op_rscl_T0_T1_cc();
1216
            else
1217
                gen_op_rscl_T0_T1();
1218
            gen_movl_reg_T0(s, rd);
1219
            break;
1220
        case 0x08:
1221
            if (set_cc) {
1222
                gen_op_andl_T0_T1();
1223
                gen_op_logic_T0_cc();
1224
            }
1225
            break;
1226
        case 0x09:
1227
            if (set_cc) {
1228
                gen_op_xorl_T0_T1();
1229
                gen_op_logic_T0_cc();
1230
            }
1231
            break;
1232
        case 0x0a:
1233
            if (set_cc) {
1234
                gen_op_subl_T0_T1_cc();
1235
            }
1236
            break;
1237
        case 0x0b:
1238
            if (set_cc) {
1239
                gen_op_addl_T0_T1_cc();
1240
            }
1241
            break;
1242
        case 0x0c:
1243
            gen_op_orl_T0_T1();
1244
            gen_movl_reg_T0(s, rd);
1245
            if (logic_cc)
1246
                gen_op_logic_T0_cc();
1247
            break;
1248
        case 0x0d:
1249
            gen_movl_reg_T1(s, rd);
1250
            if (logic_cc)
1251
                gen_op_logic_T1_cc();
1252
            break;
1253
        case 0x0e:
1254
            gen_op_bicl_T0_T1();
1255
            gen_movl_reg_T0(s, rd);
1256
            if (logic_cc)
1257
                gen_op_logic_T0_cc();
1258
            break;
1259
        default:
1260
        case 0x0f:
1261
            gen_op_notl_T1();
1262
            gen_movl_reg_T1(s, rd);
1263
            if (logic_cc)
1264
                gen_op_logic_T1_cc();
1265
            break;
1266
        }
1267
    } else {
1268
        /* other instructions */
1269
        op1 = (insn >> 24) & 0xf;
1270
        switch(op1) {
1271
        case 0x0:
1272
        case 0x1:
1273
            /* multiplies, extra load/stores */
1274
            sh = (insn >> 5) & 3;
1275
            if (sh == 0) {
1276
                if (op1 == 0x0) {
1277
                    rd = (insn >> 16) & 0xf;
1278
                    rn = (insn >> 12) & 0xf;
1279
                    rs = (insn >> 8) & 0xf;
1280
                    rm = (insn) & 0xf;
1281
                    if (((insn >> 22) & 3) == 0) {
1282
                        /* 32 bit mul */
1283
                        gen_movl_T0_reg(s, rs);
1284
                        gen_movl_T1_reg(s, rm);
1285
                        gen_op_mul_T0_T1();
1286
                        if (insn & (1 << 21)) {
1287
                            gen_movl_T1_reg(s, rn);
1288
                            gen_op_addl_T0_T1();
1289
                        }
1290
                        if (insn & (1 << 20)) 
1291
                            gen_op_logic_T0_cc();
1292
                        gen_movl_reg_T0(s, rd);
1293
                    } else {
1294
                        /* 64 bit mul */
1295
                        gen_movl_T0_reg(s, rs);
1296
                        gen_movl_T1_reg(s, rm);
1297
                        if (insn & (1 << 22)) 
1298
                            gen_op_imull_T0_T1();
1299
                        else
1300
                            gen_op_mull_T0_T1();
1301
                        if (insn & (1 << 21)) /* mult accumulate */
1302
                            gen_op_addq_T0_T1(rn, rd);
1303
                        if (!(insn & (1 << 23))) { /* double accumulate */
1304
                            gen_op_addq_lo_T0_T1(rn);
1305
                            gen_op_addq_lo_T0_T1(rd);
1306
                        }
1307
                        if (insn & (1 << 20)) 
1308
                            gen_op_logicq_cc();
1309
                        gen_movl_reg_T0(s, rn);
1310
                        gen_movl_reg_T1(s, rd);
1311
                    }
1312
                } else {
1313
                    rn = (insn >> 16) & 0xf;
1314
                    rd = (insn >> 12) & 0xf;
1315
                    if (insn & (1 << 23)) {
1316
                        /* load/store exclusive */
1317
                        goto illegal_op;
1318
                    } else {
1319
                        /* SWP instruction */
1320
                        rm = (insn) & 0xf;
1321
                        
1322
                        gen_movl_T0_reg(s, rm);
1323
                        gen_movl_T1_reg(s, rn);
1324
                        if (insn & (1 << 22)) {
1325
                            gen_op_swpb_T0_T1();
1326
                        } else {
1327
                            gen_op_swpl_T0_T1();
1328
                        }
1329
                        gen_movl_reg_T0(s, rd);
1330
                    }
1331
                }
1332
            } else {
1333
                /* Misc load/store */
1334
                rn = (insn >> 16) & 0xf;
1335
                rd = (insn >> 12) & 0xf;
1336
                gen_movl_T1_reg(s, rn);
1337
                if (insn & (1 << 24))
1338
                    gen_add_datah_offset(s, insn);
1339
                if (insn & (1 << 20)) {
1340
                    /* load */
1341
                    switch(sh) {
1342
                    case 1:
1343
                        gen_op_lduw_T0_T1();
1344
                        break;
1345
                    case 2:
1346
                        gen_op_ldsb_T0_T1();
1347
                        break;
1348
                    default:
1349
                    case 3:
1350
                        gen_op_ldsw_T0_T1();
1351
                        break;
1352
                    }
1353
                    gen_movl_reg_T0(s, rd);
1354
                } else if (sh & 2) {
1355
                    /* doubleword */
1356
                    if (sh & 1) {
1357
                        /* store */
1358
                        gen_movl_T0_reg(s, rd);
1359
                        gen_op_stl_T0_T1();
1360
                        gen_op_addl_T1_im(4);
1361
                        gen_movl_T0_reg(s, rd + 1);
1362
                        gen_op_stl_T0_T1();
1363
                        if ((insn & (1 << 24)) || (insn & (1 << 20)))
1364
                            gen_op_addl_T1_im(-4);
1365
                    } else {
1366
                        /* load */
1367
                        gen_op_ldl_T0_T1();
1368
                        gen_movl_reg_T0(s, rd);
1369
                        gen_op_addl_T1_im(4);
1370
                        gen_op_ldl_T0_T1();
1371
                        gen_movl_reg_T0(s, rd + 1);
1372
                        if ((insn & (1 << 24)) || (insn & (1 << 20)))
1373
                            gen_op_addl_T1_im(-4);
1374
                    }
1375
                } else {
1376
                    /* store */
1377
                    gen_movl_T0_reg(s, rd);
1378
                    gen_op_stw_T0_T1();
1379
                }
1380
                if (!(insn & (1 << 24))) {
1381
                    gen_add_datah_offset(s, insn);
1382
                    gen_movl_reg_T1(s, rn);
1383
                } else if (insn & (1 << 21)) {
1384
                    gen_movl_reg_T1(s, rn);
1385
                }
1386
            }
1387
            break;
1388
        case 0x4:
1389
        case 0x5:
1390
        case 0x6:
1391
        case 0x7:
1392
            /* load/store byte/word */
1393
            rn = (insn >> 16) & 0xf;
1394
            rd = (insn >> 12) & 0xf;
1395
            gen_movl_T1_reg(s, rn);
1396
            if (insn & (1 << 24))
1397
                gen_add_data_offset(s, insn);
1398
            if (insn & (1 << 20)) {
1399
                /* load */
1400
                if (insn & (1 << 22))
1401
                    gen_op_ldub_T0_T1();
1402
                else
1403
                    gen_op_ldl_T0_T1();
1404
                if (rd == 15)
1405
                    gen_bx(s);
1406
                else
1407
                    gen_movl_reg_T0(s, rd);
1408
            } else {
1409
                /* store */
1410
                gen_movl_T0_reg(s, rd);
1411
                if (insn & (1 << 22))
1412
                    gen_op_stb_T0_T1();
1413
                else
1414
                    gen_op_stl_T0_T1();
1415
            }
1416
            if (!(insn & (1 << 24))) {
1417
                gen_add_data_offset(s, insn);
1418
                gen_movl_reg_T1(s, rn);
1419
            } else if (insn & (1 << 21))
1420
                gen_movl_reg_T1(s, rn); {
1421
            }
1422
            break;
1423
        case 0x08:
1424
        case 0x09:
1425
            {
1426
                int j, n;
1427
                /* load/store multiple words */
1428
                /* XXX: store correct base if write back */
1429
                if (insn & (1 << 22))
1430
                    goto illegal_op; /* only usable in supervisor mode */
1431
                rn = (insn >> 16) & 0xf;
1432
                gen_movl_T1_reg(s, rn);
1433
                
1434
                /* compute total size */
1435
                n = 0;
1436
                for(i=0;i<16;i++) {
1437
                    if (insn & (1 << i))
1438
                        n++;
1439
                }
1440
                /* XXX: test invalid n == 0 case ? */
1441
                if (insn & (1 << 23)) {
1442
                    if (insn & (1 << 24)) {
1443
                        /* pre increment */
1444
                        gen_op_addl_T1_im(4);
1445
                    } else {
1446
                        /* post increment */
1447
                    }
1448
                } else {
1449
                    if (insn & (1 << 24)) {
1450
                        /* pre decrement */
1451
                        gen_op_addl_T1_im(-(n * 4));
1452
                    } else {
1453
                        /* post decrement */
1454
                        if (n != 1)
1455
                            gen_op_addl_T1_im(-((n - 1) * 4));
1456
                    }
1457
                }
1458
                j = 0;
1459
                for(i=0;i<16;i++) {
1460
                    if (insn & (1 << i)) {
1461
                        if (insn & (1 << 20)) {
1462
                            /* load */
1463
                            gen_op_ldl_T0_T1();
1464
                            if (i == 15)
1465
                                gen_bx(s);
1466
                            else
1467
                                gen_movl_reg_T0(s, i);
1468
                        } else {
1469
                            /* store */
1470
                            if (i == 15) {
1471
                                /* special case: r15 = PC + 12 */
1472
                                val = (long)s->pc + 8;
1473
                                gen_op_movl_TN_im[0](val);
1474
                            } else {
1475
                                gen_movl_T0_reg(s, i);
1476
                            }
1477
                            gen_op_stl_T0_T1();
1478
                        }
1479
                        j++;
1480
                        /* no need to add after the last transfer */
1481
                        if (j != n)
1482
                            gen_op_addl_T1_im(4);
1483
                    }
1484
                }
1485
                if (insn & (1 << 21)) {
1486
                    /* write back */
1487
                    if (insn & (1 << 23)) {
1488
                        if (insn & (1 << 24)) {
1489
                            /* pre increment */
1490
                        } else {
1491
                            /* post increment */
1492
                            gen_op_addl_T1_im(4);
1493
                        }
1494
                    } else {
1495
                        if (insn & (1 << 24)) {
1496
                            /* pre decrement */
1497
                            if (n != 1)
1498
                                gen_op_addl_T1_im(-((n - 1) * 4));
1499
                        } else {
1500
                            /* post decrement */
1501
                            gen_op_addl_T1_im(-(n * 4));
1502
                        }
1503
                    }
1504
                    gen_movl_reg_T1(s, rn);
1505
                }
1506
            }
1507
            break;
1508
        case 0xa:
1509
        case 0xb:
1510
            {
1511
                int32_t offset;
1512
                
1513
                /* branch (and link) */
1514
                val = (int32_t)s->pc;
1515
                if (insn & (1 << 24)) {
1516
                    gen_op_movl_T0_im(val);
1517
                    gen_op_movl_reg_TN[0][14]();
1518
                }
1519
                offset = (((int32_t)insn << 8) >> 8);
1520
                val += (offset << 2) + 4;
1521
                gen_jmp(s, val);
1522
            }
1523
            break;
1524
        case 0xc:
1525
        case 0xd:
1526
        case 0xe:
1527
            /* Coprocessor.  */
1528
            op1 = (insn >> 8) & 0xf;
1529
            switch (op1) {
1530
            case 10:
1531
            case 11:
1532
                if (disas_vfp_insn (env, s, insn))
1533
                    goto illegal_op;
1534
                break;
1535
            default:
1536
                /* unknown coprocessor.  */
1537
                goto illegal_op;
1538
            }
1539
            break;
1540
        case 0xf:
1541
            /* swi */
1542
            gen_op_movl_T0_im((long)s->pc);
1543
            gen_op_movl_reg_TN[0][15]();
1544
            gen_op_swi();
1545
            s->is_jmp = DISAS_JUMP;
1546
            break;
1547
        default:
1548
        illegal_op:
1549
            gen_op_movl_T0_im((long)s->pc - 4);
1550
            gen_op_movl_reg_TN[0][15]();
1551
            gen_op_undef_insn();
1552
            s->is_jmp = DISAS_JUMP;
1553
            break;
1554
        }
1555
    }
1556
}
1557

    
1558
static void disas_thumb_insn(DisasContext *s)
1559
{
1560
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
1561
    int32_t offset;
1562
    int i;
1563

    
1564
    insn = lduw(s->pc);
1565
    s->pc += 2;
1566
    
1567
    switch (insn >> 12) {
1568
    case 0: case 1:
1569
        rd = insn & 7;
1570
        op = (insn >> 11) & 3;
1571
        if (op == 3) {
1572
            /* add/subtract */
1573
            rn = (insn >> 3) & 7;
1574
            gen_movl_T0_reg(s, rn);
1575
            if (insn & (1 << 10)) {
1576
                /* immediate */
1577
                gen_op_movl_T1_im((insn >> 6) & 7);
1578
            } else {
1579
                /* reg */
1580
                rm = (insn >> 6) & 7;
1581
                gen_movl_T1_reg(s, rm);
1582
            }
1583
            if (insn & (1 << 9))
1584
                gen_op_subl_T0_T1_cc();
1585
            else
1586
                gen_op_addl_T0_T1_cc();
1587
            gen_movl_reg_T0(s, rd);
1588
        } else {
1589
            /* shift immediate */
1590
            rm = (insn >> 3) & 7;
1591
            shift = (insn >> 6) & 0x1f;
1592
            gen_movl_T0_reg(s, rm);
1593
            gen_shift_T0_im_thumb[op](shift);
1594
            gen_movl_reg_T0(s, rd);
1595
        }
1596
        break;
1597
    case 2: case 3:
1598
        /* arithmetic large immediate */
1599
        op = (insn >> 11) & 3;
1600
        rd = (insn >> 8) & 0x7;
1601
        if (op == 0) {
1602
            gen_op_movl_T0_im(insn & 0xff);
1603
        } else {
1604
            gen_movl_T0_reg(s, rd);
1605
            gen_op_movl_T1_im(insn & 0xff);
1606
        }
1607
        switch (op) {
1608
        case 0: /* mov */
1609
            gen_op_logic_T0_cc();
1610
            break;
1611
        case 1: /* cmp */
1612
            gen_op_subl_T0_T1_cc();
1613
            break;
1614
        case 2: /* add */
1615
            gen_op_addl_T0_T1_cc();
1616
            break;
1617
        case 3: /* sub */
1618
            gen_op_subl_T0_T1_cc();
1619
            break;
1620
        }
1621
        if (op != 1)
1622
            gen_movl_reg_T0(s, rd);
1623
        break;
1624
    case 4:
1625
        if (insn & (1 << 11)) {
1626
            rd = (insn >> 8) & 7;
1627
            /* load pc-relative.  Bit 1 of PC is ignored.  */
1628
            val = s->pc + 2 + ((insn & 0xff) * 4);
1629
            val &= ~(uint32_t)2;
1630
            gen_op_movl_T1_im(val);
1631
            gen_op_ldl_T0_T1();
1632
            gen_movl_reg_T0(s, rd);
1633
            break;
1634
        }
1635
        if (insn & (1 << 10)) {
1636
            /* data processing extended or blx */
1637
            rd = (insn & 7) | ((insn >> 4) & 8);
1638
            rm = (insn >> 3) & 0xf;
1639
            op = (insn >> 8) & 3;
1640
            switch (op) {
1641
            case 0: /* add */
1642
                gen_movl_T0_reg(s, rd);
1643
                gen_movl_T1_reg(s, rm);
1644
                gen_op_addl_T0_T1();
1645
                gen_movl_reg_T0(s, rd);
1646
                break;
1647
            case 1: /* cmp */
1648
                gen_movl_T0_reg(s, rd);
1649
                gen_movl_T1_reg(s, rm);
1650
                gen_op_subl_T0_T1_cc();
1651
                break;
1652
            case 2: /* mov/cpy */
1653
                gen_movl_T0_reg(s, rm);
1654
                gen_movl_reg_T0(s, rd);
1655
                break;
1656
            case 3:/* branch [and link] exchange thumb register */
1657
                if (insn & (1 << 7)) {
1658
                    val = (uint32_t)s->pc | 1;
1659
                    gen_op_movl_T1_im(val);
1660
                    gen_movl_reg_T1(s, 14);
1661
                }
1662
                gen_movl_T0_reg(s, rm);
1663
                gen_bx(s);
1664
                break;
1665
            }
1666
            break;
1667
        }
1668

    
1669
        /* data processing register */
1670
        rd = insn & 7;
1671
        rm = (insn >> 3) & 7;
1672
        op = (insn >> 6) & 0xf;
1673
        if (op == 2 || op == 3 || op == 4 || op == 7) {
1674
            /* the shift/rotate ops want the operands backwards */
1675
            val = rm;
1676
            rm = rd;
1677
            rd = val;
1678
            val = 1;
1679
        } else {
1680
            val = 0;
1681
        }
1682

    
1683
        if (op == 9) /* neg */
1684
            gen_op_movl_T0_im(0);
1685
        else if (op != 0xf) /* mvn doesn't read its first operand */
1686
            gen_movl_T0_reg(s, rd);
1687

    
1688
        gen_movl_T1_reg(s, rm);
1689
        switch (op) {
1690
        case 0x0: /* and */
1691
            gen_op_andl_T0_T1();
1692
            gen_op_logic_T0_cc();
1693
            break;
1694
        case 0x1: /* eor */
1695
            gen_op_xorl_T0_T1();
1696
            gen_op_logic_T0_cc();
1697
            break;
1698
        case 0x2: /* lsl */
1699
            gen_op_shll_T1_T0_cc();
1700
            break;
1701
        case 0x3: /* lsr */
1702
            gen_op_shrl_T1_T0_cc();
1703
            break;
1704
        case 0x4: /* asr */
1705
            gen_op_sarl_T1_T0_cc();
1706
            break;
1707
        case 0x5: /* adc */
1708
            gen_op_adcl_T0_T1_cc();
1709
            break;
1710
        case 0x6: /* sbc */
1711
            gen_op_sbcl_T0_T1_cc();
1712
            break;
1713
        case 0x7: /* ror */
1714
            gen_op_rorl_T1_T0_cc();
1715
            break;
1716
        case 0x8: /* tst */
1717
            gen_op_andl_T0_T1();
1718
            gen_op_logic_T0_cc();
1719
            rd = 16;
1720
            break;
1721
        case 0x9: /* neg */
1722
            gen_op_subl_T0_T1_cc();
1723
            break;
1724
        case 0xa: /* cmp */
1725
            gen_op_subl_T0_T1_cc();
1726
            rd = 16;
1727
            break;
1728
        case 0xb: /* cmn */
1729
            gen_op_addl_T0_T1_cc();
1730
            rd = 16;
1731
            break;
1732
        case 0xc: /* orr */
1733
            gen_op_orl_T0_T1();
1734
            gen_op_logic_T0_cc();
1735
            break;
1736
        case 0xd: /* mul */
1737
            gen_op_mull_T0_T1();
1738
            gen_op_logic_T0_cc();
1739
            break;
1740
        case 0xe: /* bic */
1741
            gen_op_bicl_T0_T1();
1742
            gen_op_logic_T0_cc();
1743
            break;
1744
        case 0xf: /* mvn */
1745
            gen_op_notl_T1();
1746
            gen_op_logic_T1_cc();
1747
            val = 1;
1748
            rm = rd;
1749
            break;
1750
        }
1751
        if (rd != 16) {
1752
            if (val)
1753
                gen_movl_reg_T1(s, rm);
1754
            else
1755
                gen_movl_reg_T0(s, rd);
1756
        }
1757
        break;
1758

    
1759
    case 5:
1760
        /* load/store register offset.  */
1761
        rd = insn & 7;
1762
        rn = (insn >> 3) & 7;
1763
        rm = (insn >> 6) & 7;
1764
        op = (insn >> 9) & 7;
1765
        gen_movl_T1_reg(s, rn);
1766
        gen_movl_T2_reg(s, rm);
1767
        gen_op_addl_T1_T2();
1768

    
1769
        if (op < 3) /* store */
1770
            gen_movl_T0_reg(s, rd);
1771

    
1772
        switch (op) {
1773
        case 0: /* str */
1774
            gen_op_stl_T0_T1();
1775
            break;
1776
        case 1: /* strh */
1777
            gen_op_stw_T0_T1();
1778
            break;
1779
        case 2: /* strb */
1780
            gen_op_stb_T0_T1();
1781
            break;
1782
        case 3: /* ldrsb */
1783
            gen_op_ldsb_T0_T1();
1784
            break;
1785
        case 4: /* ldr */
1786
            gen_op_ldl_T0_T1();
1787
            break;
1788
        case 5: /* ldrh */
1789
            gen_op_lduw_T0_T1();
1790
            break;
1791
        case 6: /* ldrb */
1792
            gen_op_ldub_T0_T1();
1793
            break;
1794
        case 7: /* ldrsh */
1795
            gen_op_ldsw_T0_T1();
1796
            break;
1797
        }
1798
        if (op >= 3) /* load */
1799
            gen_movl_reg_T0(s, rd);
1800
        break;
1801

    
1802
    case 6:
1803
        /* load/store word immediate offset */
1804
        rd = insn & 7;
1805
        rn = (insn >> 3) & 7;
1806
        gen_movl_T1_reg(s, rn);
1807
        val = (insn >> 4) & 0x7c;
1808
        gen_op_movl_T2_im(val);
1809
        gen_op_addl_T1_T2();
1810

    
1811
        if (insn & (1 << 11)) {
1812
            /* load */
1813
            gen_op_ldl_T0_T1();
1814
            gen_movl_reg_T0(s, rd);
1815
        } else {
1816
            /* store */
1817
            gen_movl_T0_reg(s, rd);
1818
            gen_op_stl_T0_T1();
1819
        }
1820
        break;
1821

    
1822
    case 7:
1823
        /* load/store byte immediate offset */
1824
        rd = insn & 7;
1825
        rn = (insn >> 3) & 7;
1826
        gen_movl_T1_reg(s, rn);
1827
        val = (insn >> 6) & 0x1f;
1828
        gen_op_movl_T2_im(val);
1829
        gen_op_addl_T1_T2();
1830

    
1831
        if (insn & (1 << 11)) {
1832
            /* load */
1833
            gen_op_ldub_T0_T1();
1834
            gen_movl_reg_T0(s, rd);
1835
        } else {
1836
            /* store */
1837
            gen_movl_T0_reg(s, rd);
1838
            gen_op_stb_T0_T1();
1839
        }
1840
        break;
1841

    
1842
    case 8:
1843
        /* load/store halfword immediate offset */
1844
        rd = insn & 7;
1845
        rn = (insn >> 3) & 7;
1846
        gen_movl_T1_reg(s, rn);
1847
        val = (insn >> 5) & 0x3e;
1848
        gen_op_movl_T2_im(val);
1849
        gen_op_addl_T1_T2();
1850

    
1851
        if (insn & (1 << 11)) {
1852
            /* load */
1853
            gen_op_lduw_T0_T1();
1854
            gen_movl_reg_T0(s, rd);
1855
        } else {
1856
            /* store */
1857
            gen_movl_T0_reg(s, rd);
1858
            gen_op_stw_T0_T1();
1859
        }
1860
        break;
1861

    
1862
    case 9:
1863
        /* load/store from stack */
1864
        rd = (insn >> 8) & 7;
1865
        gen_movl_T1_reg(s, 13);
1866
        val = (insn & 0xff) * 4;
1867
        gen_op_movl_T2_im(val);
1868
        gen_op_addl_T1_T2();
1869

    
1870
        if (insn & (1 << 11)) {
1871
            /* load */
1872
            gen_op_ldl_T0_T1();
1873
            gen_movl_reg_T0(s, rd);
1874
        } else {
1875
            /* store */
1876
            gen_movl_T0_reg(s, rd);
1877
            gen_op_stl_T0_T1();
1878
        }
1879
        break;
1880

    
1881
    case 10:
1882
        /* add to high reg */
1883
        rd = (insn >> 8) & 7;
1884
        if (insn & (1 << 11)) {
1885
            /* SP */
1886
            gen_movl_T0_reg(s, 13);
1887
        } else {
1888
            /* PC. bit 1 is ignored.  */
1889
            gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
1890
        }
1891
        val = (insn & 0xff) * 4;
1892
        gen_op_movl_T1_im(val);
1893
        gen_op_addl_T0_T1();
1894
        gen_movl_reg_T0(s, rd);
1895
        break;
1896

    
1897
    case 11:
1898
        /* misc */
1899
        op = (insn >> 8) & 0xf;
1900
        switch (op) {
1901
        case 0:
1902
            /* adjust stack pointer */
1903
            gen_movl_T1_reg(s, 13);
1904
            val = (insn & 0x7f) * 4;
1905
            if (insn & (1 << 7))
1906
              val = -(int32_t)val;
1907
            gen_op_movl_T2_im(val);
1908
            gen_op_addl_T1_T2();
1909
            gen_movl_reg_T1(s, 13);
1910
            break;
1911

    
1912
        case 4: case 5: case 0xc: case 0xd:
1913
            /* push/pop */
1914
            gen_movl_T1_reg(s, 13);
1915
            if (insn & (1 << 8))
1916
                offset = 4;
1917
            else
1918
                offset = 0;
1919
            for (i = 0; i < 8; i++) {
1920
                if (insn & (1 << i))
1921
                    offset += 4;
1922
            }
1923
            if ((insn & (1 << 11)) == 0) {
1924
                gen_op_movl_T2_im(-offset);
1925
                gen_op_addl_T1_T2();
1926
            }
1927
            gen_op_movl_T2_im(4);
1928
            for (i = 0; i < 8; i++) {
1929
                if (insn & (1 << i)) {
1930
                    if (insn & (1 << 11)) {
1931
                        /* pop */
1932
                        gen_op_ldl_T0_T1();
1933
                        gen_movl_reg_T0(s, i);
1934
                    } else {
1935
                        /* push */
1936
                        gen_movl_T0_reg(s, i);
1937
                        gen_op_stl_T0_T1();
1938
                    }
1939
                    /* advance to the next address.  */
1940
                    gen_op_addl_T1_T2();
1941
                }
1942
            }
1943
            if (insn & (1 << 8)) {
1944
                if (insn & (1 << 11)) {
1945
                    /* pop pc */
1946
                    gen_op_ldl_T0_T1();
1947
                    /* don't set the pc until the rest of the instruction
1948
                       has completed */
1949
                } else {
1950
                    /* push lr */
1951
                    gen_movl_T0_reg(s, 14);
1952
                    gen_op_stl_T0_T1();
1953
                }
1954
                gen_op_addl_T1_T2();
1955
            }
1956
            if ((insn & (1 << 11)) == 0) {
1957
                gen_op_movl_T2_im(-offset);
1958
                gen_op_addl_T1_T2();
1959
            }
1960
            /* write back the new stack pointer */
1961
            gen_movl_reg_T1(s, 13);
1962
            /* set the new PC value */
1963
            if ((insn & 0x0900) == 0x0900)
1964
                gen_bx(s);
1965
            break;
1966

    
1967
        default:
1968
            goto undef;
1969
        }
1970
        break;
1971

    
1972
    case 12:
1973
        /* load/store multiple */
1974
        rn = (insn >> 8) & 0x7;
1975
        gen_movl_T1_reg(s, rn);
1976
        gen_op_movl_T2_im(4);
1977
        for (i = 0; i < 8; i++) {
1978
            if (insn & (1 << i)) {
1979
                if (insn & (1 << 11)) {
1980
                    /* load */
1981
                    gen_op_ldl_T0_T1();
1982
                    gen_movl_reg_T0(s, i);
1983
                } else {
1984
                    /* store */
1985
                    gen_movl_T0_reg(s, i);
1986
                    gen_op_stl_T0_T1();
1987
                }
1988
                /* advance to the next address */
1989
                gen_op_addl_T1_T2();
1990
            }
1991
        }
1992
        /* Base register writeback.  */
1993
        gen_movl_reg_T1(s, rn);
1994
        break;
1995

    
1996
    case 13:
1997
        /* conditional branch or swi */
1998
        cond = (insn >> 8) & 0xf;
1999
        if (cond == 0xe)
2000
            goto undef;
2001

    
2002
        if (cond == 0xf) {
2003
            /* swi */
2004
            gen_op_movl_T0_im((long)s->pc | 1);
2005
            /* Don't set r15.  */
2006
            gen_op_movl_reg_TN[0][15]();
2007
            gen_op_swi();
2008
            s->is_jmp = DISAS_JUMP;
2009
            break;
2010
        }
2011
        /* generate a conditional jump to next instruction */
2012
        s->condlabel = gen_new_label();
2013
        gen_test_cc[cond ^ 1](s->condlabel);
2014
        s->condjmp = 1;
2015
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
2016
        //s->is_jmp = DISAS_JUMP_NEXT;
2017
        gen_movl_T1_reg(s, 15);
2018

    
2019
        /* jump to the offset */
2020
        val = (uint32_t)s->pc + 2;
2021
        offset = ((int32_t)insn << 24) >> 24;
2022
        val += offset << 1;
2023
        gen_jmp(s, val);
2024
        break;
2025

    
2026
    case 14:
2027
        /* unconditional branch */
2028
        if (insn & (1 << 11))
2029
            goto undef; /* Second half of a blx */
2030
        val = (uint32_t)s->pc;
2031
        offset = ((int32_t)insn << 21) >> 21;
2032
        val += (offset << 1) + 2;
2033
        gen_jmp(s, val);
2034
        break;
2035

    
2036
    case 15:
2037
        /* branch and link [and switch to arm] */
2038
        offset = ((int32_t)insn << 21) >> 10;
2039
        insn = lduw(s->pc);
2040
        offset |= insn & 0x7ff;
2041

    
2042
        val = (uint32_t)s->pc + 2;
2043
        gen_op_movl_T1_im(val | 1);
2044
        gen_movl_reg_T1(s, 14);
2045
        
2046
        val += offset << 1;
2047
        if (insn & (1 << 12)) {
2048
            /* bl */
2049
            gen_jmp(s, val);
2050
        } else {
2051
            /* blx */
2052
            val &= ~(uint32_t)2;
2053
            gen_op_movl_T0_im(val);
2054
            gen_bx(s);
2055
        }
2056
    }
2057
    return;
2058
undef:
2059
    gen_op_movl_T0_im((long)s->pc - 2);
2060
    gen_op_movl_reg_TN[0][15]();
2061
    gen_op_undef_insn();
2062
    s->is_jmp = DISAS_JUMP;
2063
}
2064

    
2065
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
2066
   basic block 'tb'. If search_pc is TRUE, also generate PC
2067
   information for each intermediate instruction. */
2068
static inline int gen_intermediate_code_internal(CPUState *env, 
2069
                                                 TranslationBlock *tb, 
2070
                                                 int search_pc)
2071
{
2072
    DisasContext dc1, *dc = &dc1;
2073
    uint16_t *gen_opc_end;
2074
    int j, lj;
2075
    target_ulong pc_start;
2076
    
2077
    /* generate intermediate code */
2078
    pc_start = tb->pc;
2079
       
2080
    dc->tb = tb;
2081

    
2082
    gen_opc_ptr = gen_opc_buf;
2083
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2084
    gen_opparam_ptr = gen_opparam_buf;
2085

    
2086
    dc->is_jmp = DISAS_NEXT;
2087
    dc->pc = pc_start;
2088
    dc->singlestep_enabled = env->singlestep_enabled;
2089
    dc->condjmp = 0;
2090
    dc->thumb = env->thumb;
2091
    nb_gen_labels = 0;
2092
    lj = -1;
2093
    do {
2094
        if (env->nb_breakpoints > 0) {
2095
            for(j = 0; j < env->nb_breakpoints; j++) {
2096
                if (env->breakpoints[j] == dc->pc) {
2097
                    gen_op_movl_T0_im((long)dc->pc);
2098
                    gen_op_movl_reg_TN[0][15]();
2099
                    gen_op_debug();
2100
                    dc->is_jmp = DISAS_JUMP;
2101
                    break;
2102
                }
2103
            }
2104
        }
2105
        if (search_pc) {
2106
            j = gen_opc_ptr - gen_opc_buf;
2107
            if (lj < j) {
2108
                lj++;
2109
                while (lj < j)
2110
                    gen_opc_instr_start[lj++] = 0;
2111
            }
2112
            gen_opc_pc[lj] = dc->pc;
2113
            gen_opc_instr_start[lj] = 1;
2114
        }
2115

    
2116
        if (env->thumb)
2117
          disas_thumb_insn(dc);
2118
        else
2119
          disas_arm_insn(env, dc);
2120

    
2121
        if (dc->condjmp && !dc->is_jmp) {
2122
            gen_set_label(dc->condlabel);
2123
            dc->condjmp = 0;
2124
        }
2125
        /* Translation stops when a conditional branch is enoutered.
2126
         * Otherwise the subsequent code could get translated several times.
2127
         */
2128
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2129
             !env->singlestep_enabled &&
2130
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2131
    /* It this stage dc->condjmp will only be set when the skipped
2132
     * instruction was a conditional branch, and teh PC has already been
2133
     * written.  */
2134
    if (__builtin_expect(env->singlestep_enabled, 0)) {
2135
        /* Make sure the pc is updated, and raise a debug exception.  */
2136
        if (dc->condjmp) {
2137
            gen_op_debug();
2138
            gen_set_label(dc->condlabel);
2139
        }
2140
        if (dc->condjmp || !dc->is_jmp) {
2141
            gen_op_movl_T0_im((long)dc->pc);
2142
            gen_op_movl_reg_TN[0][15]();
2143
            dc->condjmp = 0;
2144
        }
2145
        gen_op_debug();
2146
    } else {
2147
        switch(dc->is_jmp) {
2148
        case DISAS_NEXT:
2149
            gen_goto_tb(dc, 1, dc->pc);
2150
            break;
2151
        default:
2152
        case DISAS_JUMP:
2153
        case DISAS_UPDATE:
2154
            /* indicate that the hash table must be used to find the next TB */
2155
            gen_op_movl_T0_0();
2156
            gen_op_exit_tb();
2157
            break;
2158
        case DISAS_TB_JUMP:
2159
            /* nothing more to generate */
2160
            break;
2161
        }
2162
        if (dc->condjmp) {
2163
            gen_set_label(dc->condlabel);
2164
            gen_goto_tb(dc, 1, dc->pc);
2165
            dc->condjmp = 0;
2166
        }
2167
    }
2168
    *gen_opc_ptr = INDEX_op_end;
2169

    
2170
#ifdef DEBUG_DISAS
2171
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2172
        fprintf(logfile, "----------------\n");
2173
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2174
        target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
2175
        fprintf(logfile, "\n");
2176
        if (loglevel & (CPU_LOG_TB_OP)) {
2177
            fprintf(logfile, "OP:\n");
2178
            dump_ops(gen_opc_buf, gen_opparam_buf);
2179
            fprintf(logfile, "\n");
2180
        }
2181
    }
2182
#endif
2183
    if (!search_pc)
2184
        tb->size = dc->pc - pc_start;
2185
    return 0;
2186
}
2187

    
2188
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2189
{
2190
    return gen_intermediate_code_internal(env, tb, 0);
2191
}
2192

    
2193
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2194
{
2195
    return gen_intermediate_code_internal(env, tb, 1);
2196
}
2197

    
2198
CPUARMState *cpu_arm_init(void)
2199
{
2200
    CPUARMState *env;
2201

    
2202
    env = qemu_mallocz(sizeof(CPUARMState));
2203
    if (!env)
2204
        return NULL;
2205
    cpu_exec_init(env);
2206
    return env;
2207
}
2208

    
2209
void cpu_arm_close(CPUARMState *env)
2210
{
2211
    free(env);
2212
}
2213

    
2214
void cpu_dump_state(CPUState *env, FILE *f, 
2215
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2216
                    int flags)
2217
{
2218
    int i;
2219
    union {
2220
        uint32_t i;
2221
        float s;
2222
    } s0, s1;
2223
    CPU_DoubleU d;
2224

    
2225
    for(i=0;i<16;i++) {
2226
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2227
        if ((i % 4) == 3)
2228
            cpu_fprintf(f, "\n");
2229
        else
2230
            cpu_fprintf(f, " ");
2231
    }
2232
    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c\n", 
2233
             env->cpsr, 
2234
            env->cpsr & (1 << 31) ? 'N' : '-',
2235
            env->cpsr & (1 << 30) ? 'Z' : '-',
2236
            env->cpsr & (1 << 29) ? 'C' : '-',
2237
            env->cpsr & (1 << 28) ? 'V' : '-',
2238
            env->thumb ? 'T' : 'A');
2239

    
2240
    for (i = 0; i < 16; i++) {
2241
        d.d = env->vfp.regs[i];
2242
        s0.i = d.l.lower;
2243
        s1.i = d.l.upper;
2244
        cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
2245
                    i * 2, (int)s0.i, s0.s,
2246
                    i * 2 + 1, (int)s0.i, s0.s,
2247
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2248
                    d.d);
2249
    }
2250
    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
2251
}
2252

    
2253
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2254
{
2255
    return addr;
2256
}
2257

    
2258
#if defined(CONFIG_USER_ONLY) 
2259

    
2260
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
2261
                              int is_user, int is_softmmu)
2262
{
2263
    env->cp15_6 = address;
2264
    if (rw == 2) {
2265
        env->exception_index = EXCP_PREFETCH_ABORT;
2266
    } else {
2267
        env->exception_index = EXCP_DATA_ABORT;
2268
    }
2269
    return 1;
2270
}
2271

    
2272
#else
2273

    
2274
#error not implemented
2275

    
2276
#endif