Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 1fddef4b

History | View | Annotate | Download (64.3 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
    struct TranslationBlock *tb;
36
} DisasContext;
37

    
38
#define DISAS_JUMP_NEXT 4
39

    
40
/* XXX: move that elsewhere */
41
static uint16_t *gen_opc_ptr;
42
static uint32_t *gen_opparam_ptr;
43
extern FILE *logfile;
44
extern int loglevel;
45

    
46
enum {
47
#define DEF(s, n, copy_size) INDEX_op_ ## s,
48
#include "opc.h"
49
#undef DEF
50
    NB_OPS,
51
};
52

    
53
#include "gen-op.h"
54

    
55
static GenOpFunc2 *gen_test_cc[14] = {
56
    gen_op_test_eq,
57
    gen_op_test_ne,
58
    gen_op_test_cs,
59
    gen_op_test_cc,
60
    gen_op_test_mi,
61
    gen_op_test_pl,
62
    gen_op_test_vs,
63
    gen_op_test_vc,
64
    gen_op_test_hi,
65
    gen_op_test_ls,
66
    gen_op_test_ge,
67
    gen_op_test_lt,
68
    gen_op_test_gt,
69
    gen_op_test_le,
70
};
71

    
72
const uint8_t table_logic_cc[16] = {
73
    1, /* and */
74
    1, /* xor */
75
    0, /* sub */
76
    0, /* rsb */
77
    0, /* add */
78
    0, /* adc */
79
    0, /* sbc */
80
    0, /* rsc */
81
    1, /* andl */
82
    1, /* xorl */
83
    0, /* cmp */
84
    0, /* cmn */
85
    1, /* orr */
86
    1, /* mov */
87
    1, /* bic */
88
    1, /* mvn */
89
};
90
    
91
static GenOpFunc1 *gen_shift_T1_im[4] = {
92
    gen_op_shll_T1_im,
93
    gen_op_shrl_T1_im,
94
    gen_op_sarl_T1_im,
95
    gen_op_rorl_T1_im,
96
};
97

    
98
static GenOpFunc *gen_shift_T1_0[4] = {
99
    NULL,
100
    gen_op_shrl_T1_0,
101
    gen_op_sarl_T1_0,
102
    gen_op_rrxl_T1,
103
};
104

    
105
static GenOpFunc1 *gen_shift_T2_im[4] = {
106
    gen_op_shll_T2_im,
107
    gen_op_shrl_T2_im,
108
    gen_op_sarl_T2_im,
109
    gen_op_rorl_T2_im,
110
};
111

    
112
static GenOpFunc *gen_shift_T2_0[4] = {
113
    NULL,
114
    gen_op_shrl_T2_0,
115
    gen_op_sarl_T2_0,
116
    gen_op_rrxl_T2,
117
};
118

    
119
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
120
    gen_op_shll_T1_im_cc,
121
    gen_op_shrl_T1_im_cc,
122
    gen_op_sarl_T1_im_cc,
123
    gen_op_rorl_T1_im_cc,
124
};
125

    
126
static GenOpFunc *gen_shift_T1_0_cc[4] = {
127
    NULL,
128
    gen_op_shrl_T1_0_cc,
129
    gen_op_sarl_T1_0_cc,
130
    gen_op_rrxl_T1_cc,
131
};
132

    
133
static GenOpFunc *gen_shift_T1_T0[4] = {
134
    gen_op_shll_T1_T0,
135
    gen_op_shrl_T1_T0,
136
    gen_op_sarl_T1_T0,
137
    gen_op_rorl_T1_T0,
138
};
139

    
140
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
141
    gen_op_shll_T1_T0_cc,
142
    gen_op_shrl_T1_T0_cc,
143
    gen_op_sarl_T1_T0_cc,
144
    gen_op_rorl_T1_T0_cc,
145
};
146

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

    
204
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
205
    {
206
        gen_op_movl_r0_T0,
207
        gen_op_movl_r1_T0,
208
        gen_op_movl_r2_T0,
209
        gen_op_movl_r3_T0,
210
        gen_op_movl_r4_T0,
211
        gen_op_movl_r5_T0,
212
        gen_op_movl_r6_T0,
213
        gen_op_movl_r7_T0,
214
        gen_op_movl_r8_T0,
215
        gen_op_movl_r9_T0,
216
        gen_op_movl_r10_T0,
217
        gen_op_movl_r11_T0,
218
        gen_op_movl_r12_T0,
219
        gen_op_movl_r13_T0,
220
        gen_op_movl_r14_T0,
221
        gen_op_movl_r15_T0,
222
    },
223
    {
224
        gen_op_movl_r0_T1,
225
        gen_op_movl_r1_T1,
226
        gen_op_movl_r2_T1,
227
        gen_op_movl_r3_T1,
228
        gen_op_movl_r4_T1,
229
        gen_op_movl_r5_T1,
230
        gen_op_movl_r6_T1,
231
        gen_op_movl_r7_T1,
232
        gen_op_movl_r8_T1,
233
        gen_op_movl_r9_T1,
234
        gen_op_movl_r10_T1,
235
        gen_op_movl_r11_T1,
236
        gen_op_movl_r12_T1,
237
        gen_op_movl_r13_T1,
238
        gen_op_movl_r14_T1,
239
        gen_op_movl_r15_T1,
240
    },
241
};
242

    
243
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
244
    gen_op_movl_T0_im,
245
    gen_op_movl_T1_im,
246
    gen_op_movl_T2_im,
247
};
248

    
249
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
250
    gen_op_shll_T0_im_thumb,
251
    gen_op_shrl_T0_im_thumb,
252
    gen_op_sarl_T0_im_thumb,
253
};
254

    
255
static inline void gen_bx(DisasContext *s)
256
{
257
  s->is_jmp = DISAS_UPDATE;
258
  gen_op_bx_T0();
259
}
260

    
261
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
262
{
263
    int val;
264

    
265
    if (reg == 15) {
266
        /* normaly, since we updated PC, we need only to add 4 */
267
        val = (long)s->pc + 4;
268
        gen_op_movl_TN_im[t](val);
269
    } else {
270
        gen_op_movl_TN_reg[t][reg]();
271
    }
272
}
273

    
274
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
275
{
276
    gen_movl_TN_reg(s, reg, 0);
277
}
278

    
279
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
280
{
281
    gen_movl_TN_reg(s, reg, 1);
282
}
283

    
284
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
285
{
286
    gen_movl_TN_reg(s, reg, 2);
287
}
288

    
289
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
290
{
291
    gen_op_movl_reg_TN[t][reg]();
292
    if (reg == 15) {
293
        s->is_jmp = DISAS_JUMP;
294
    }
295
}
296

    
297
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
298
{
299
    gen_movl_reg_TN(s, reg, 0);
300
}
301

    
302
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
303
{
304
    gen_movl_reg_TN(s, reg, 1);
305
}
306

    
307
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
308
{
309
    int val, rm, shift, shiftop;
310

    
311
    if (!(insn & (1 << 25))) {
312
        /* immediate */
313
        val = insn & 0xfff;
314
        if (!(insn & (1 << 23)))
315
            val = -val;
316
        if (val != 0)
317
            gen_op_addl_T1_im(val);
318
    } else {
319
        /* shift/register */
320
        rm = (insn) & 0xf;
321
        shift = (insn >> 7) & 0x1f;
322
        gen_movl_T2_reg(s, rm);
323
        shiftop = (insn >> 5) & 3;
324
        if (shift != 0) {
325
            gen_shift_T2_im[shiftop](shift);
326
        } else if (shiftop != 0) {
327
            gen_shift_T2_0[shiftop]();
328
        }
329
        if (!(insn & (1 << 23)))
330
            gen_op_subl_T1_T2();
331
        else
332
            gen_op_addl_T1_T2();
333
    }
334
}
335

    
336
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
337
{
338
    int val, rm;
339
    
340
    if (insn & (1 << 22)) {
341
        /* immediate */
342
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
343
        if (!(insn & (1 << 23)))
344
            val = -val;
345
        if (val != 0)
346
            gen_op_addl_T1_im(val);
347
    } else {
348
        /* register */
349
        rm = (insn) & 0xf;
350
        gen_movl_T2_reg(s, rm);
351
        if (!(insn & (1 << 23)))
352
            gen_op_subl_T1_T2();
353
        else
354
            gen_op_addl_T1_T2();
355
    }
356
}
357

    
358
#define VFP_OP(name)                      \
359
static inline void gen_vfp_##name(int dp) \
360
{                                         \
361
    if (dp)                               \
362
        gen_op_vfp_##name##d();           \
363
    else                                  \
364
        gen_op_vfp_##name##s();           \
365
}
366

    
367
VFP_OP(add)
368
VFP_OP(sub)
369
VFP_OP(mul)
370
VFP_OP(div)
371
VFP_OP(neg)
372
VFP_OP(abs)
373
VFP_OP(sqrt)
374
VFP_OP(cmp)
375
VFP_OP(cmpe)
376
VFP_OP(F1_ld0)
377
VFP_OP(uito)
378
VFP_OP(sito)
379
VFP_OP(toui)
380
VFP_OP(touiz)
381
VFP_OP(tosi)
382
VFP_OP(tosiz)
383
VFP_OP(ld)
384
VFP_OP(st)
385

    
386
#undef VFP_OP
387

    
388
static inline long
389
vfp_reg_offset (int dp, int reg)
390
{
391
    if (dp)
392
        return offsetof(CPUARMState, vfp.regs[reg]);
393
    else if (reg & 1) {
394
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
395
          + offsetof(CPU_DoubleU, l.upper);
396
    } else {
397
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
398
          + offsetof(CPU_DoubleU, l.lower);
399
    }
400
}
401
static inline void gen_mov_F0_vreg(int dp, int reg)
402
{
403
    if (dp)
404
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
405
    else
406
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
407
}
408

    
409
static inline void gen_mov_F1_vreg(int dp, int reg)
410
{
411
    if (dp)
412
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
413
    else
414
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
415
}
416

    
417
static inline void gen_mov_vreg_F0(int dp, int reg)
418
{
419
    if (dp)
420
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
421
    else
422
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
423
}
424

    
425
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
426
   (ie. an undefined instruction).  */
427
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
428
{
429
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
430
    int dp, veclen;
431

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

    
532
                if (op == 15 && (rn == 15 || rn > 17)) {
533
                    /* Integer or single precision destination.  */
534
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
535
                } else {
536
                    if (insn & (1 << 22))
537
                        return 1;
538
                    rd = (insn >> 12) & 0xf;
539
                }
540

    
541
                if (op == 15 && (rn == 16 || rn == 17)) {
542
                    /* Integer source.  */
543
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
544
                } else {
545
                    if (insn & (1 << 5))
546
                        return 1;
547
                    rm = insn & 0xf;
548
                }
549
            } else {
550
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
551
                if (op == 15 && rn == 15) {
552
                    /* Double precision destination.  */
553
                    if (insn & (1 << 22))
554
                        return 1;
555
                    rd = (insn >> 12) & 0xf;
556
                } else
557
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
558
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
559
            }
560

    
561
            veclen = env->vfp.vec_len;
562
            if (op == 15 && rn > 3)
563
                veclen = 0;
564

    
565
            /* Shut up compiler warnings.  */
566
            delta_m = 0;
567
            delta_d = 0;
568
            bank_mask = 0;
569
            
570
            if (veclen > 0) {
571
                if (dp)
572
                    bank_mask = 0xc;
573
                else
574
                    bank_mask = 0x18;
575

    
576
                /* Figure out what type of vector operation this is.  */
577
                if ((rd & bank_mask) == 0) {
578
                    /* scalar */
579
                    veclen = 0;
580
                } else {
581
                    if (dp)
582
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
583
                    else
584
                        delta_d = env->vfp.vec_stride + 1;
585

    
586
                    if ((rm & bank_mask) == 0) {
587
                        /* mixed scalar/vector */
588
                        delta_m = 0;
589
                    } else {
590
                        /* vector */
591
                        delta_m = delta_d;
592
                    }
593
                }
594
            }
595

    
596
            /* Load the initial operands.  */
597
            if (op == 15) {
598
                switch (rn) {
599
                case 16:
600
                case 17:
601
                    /* Integer source */
602
                    gen_mov_F0_vreg(0, rm);
603
                    break;
604
                case 8:
605
                case 9:
606
                    /* Compare */
607
                    gen_mov_F0_vreg(dp, rd);
608
                    gen_mov_F1_vreg(dp, rm);
609
                    break;
610
                case 10:
611
                case 11:
612
                    /* Compare with zero */
613
                    gen_mov_F0_vreg(dp, rd);
614
                    gen_vfp_F1_ld0(dp);
615
                    break;
616
                default:
617
                    /* One source operand.  */
618
                    gen_mov_F0_vreg(dp, rm);
619
                }
620
            } else {
621
                /* Two source operands.  */
622
                gen_mov_F0_vreg(dp, rn);
623
                gen_mov_F1_vreg(dp, rm);
624
            }
625

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

    
728
                /* Write back the result.  */
729
                if (op == 15 && (rn >= 8 && rn <= 11))
730
                    ; /* Comparison, do nothing.  */
731
                else if (op == 15 && rn > 17)
732
                    /* Integer result.  */
733
                    gen_mov_vreg_F0(0, rd);
734
                else if (op == 15 && rn == 15)
735
                    /* conversion */
736
                    gen_mov_vreg_F0(!dp, rd);
737
                else
738
                    gen_mov_vreg_F0(dp, rd);
739

    
740
                /* break out of the loop if we have finished  */
741
                if (veclen == 0)
742
                    break;
743

    
744
                if (op == 15 && delta_m == 0) {
745
                    /* single source one-many */
746
                    while (veclen--) {
747
                        rd = ((rd + delta_d) & (bank_mask - 1))
748
                             | (rd & bank_mask);
749
                        gen_mov_vreg_F0(dp, rd);
750
                    }
751
                    break;
752
                }
753
                /* Setup the next operands.  */
754
                veclen--;
755
                rd = ((rd + delta_d) & (bank_mask - 1))
756
                     | (rd & bank_mask);
757

    
758
                if (op == 15) {
759
                    /* One source operand.  */
760
                    rm = ((rm + delta_m) & (bank_mask - 1))
761
                         | (rm & bank_mask);
762
                    gen_mov_F0_vreg(dp, rm);
763
                } else {
764
                    /* Two source operands.  */
765
                    rn = ((rn + delta_d) & (bank_mask - 1))
766
                         | (rn & bank_mask);
767
                    gen_mov_F0_vreg(dp, rn);
768
                    if (delta_m) {
769
                        rm = ((rm + delta_m) & (bank_mask - 1))
770
                             | (rm & bank_mask);
771
                        gen_mov_F1_vreg(dp, rm);
772
                    }
773
                }
774
            }
775
        }
776
        break;
777
    case 0xc:
778
    case 0xd:
779
        if (dp && (insn & (1 << 22))) {
780
            /* two-register transfer */
781
            rn = (insn >> 16) & 0xf;
782
            rd = (insn >> 12) & 0xf;
783
            if (dp) {
784
                if (insn & (1 << 5))
785
                    return 1;
786
                rm = insn & 0xf;
787
            } else
788
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
789

    
790
            if (insn & (1 << 20)) {
791
                /* vfp->arm */
792
                if (dp) {
793
                    gen_mov_F0_vreg(1, rm);
794
                    gen_op_vfp_mrrd();
795
                    gen_movl_reg_T0(s, rd);
796
                    gen_movl_reg_T1(s, rn);
797
                } else {
798
                    gen_mov_F0_vreg(0, rm);
799
                    gen_op_vfp_mrs();
800
                    gen_movl_reg_T0(s, rn);
801
                    gen_mov_F0_vreg(0, rm + 1);
802
                    gen_op_vfp_mrs();
803
                    gen_movl_reg_T0(s, rd);
804
                }
805
            } else {
806
                /* arm->vfp */
807
                if (dp) {
808
                    gen_movl_T0_reg(s, rd);
809
                    gen_movl_T1_reg(s, rn);
810
                    gen_op_vfp_mdrr();
811
                    gen_mov_vreg_F0(1, rm);
812
                } else {
813
                    gen_movl_T0_reg(s, rn);
814
                    gen_op_vfp_msr();
815
                    gen_mov_vreg_F0(0, rm);
816
                    gen_movl_T0_reg(s, rd);
817
                    gen_op_vfp_msr();
818
                    gen_mov_vreg_F0(0, rm + 1);
819
                }
820
            }
821
        } else {
822
            /* Load/store */
823
            rn = (insn >> 16) & 0xf;
824
            if (dp)
825
                rd = (insn >> 12) & 0xf;
826
            else
827
                rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
828
            gen_movl_T1_reg(s, rn);
829
            if ((insn & 0x01200000) == 0x01000000) {
830
                /* Single load/store */
831
                offset = (insn & 0xff) << 2;
832
                if ((insn & (1 << 23)) == 0)
833
                    offset = -offset;
834
                gen_op_addl_T1_im(offset);
835
                if (insn & (1 << 20)) {
836
                    gen_vfp_ld(dp);
837
                    gen_mov_vreg_F0(dp, rd);
838
                } else {
839
                    gen_mov_F0_vreg(dp, rd);
840
                    gen_vfp_st(dp);
841
                }
842
            } else {
843
                /* load/store multiple */
844
                if (dp)
845
                    n = (insn >> 1) & 0x7f;
846
                else
847
                    n = insn & 0xff;
848

    
849
                if (insn & (1 << 24)) /* pre-decrement */
850
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
851

    
852
                if (dp)
853
                    offset = 8;
854
                else
855
                    offset = 4;
856
                for (i = 0; i < n; i++) {
857
                    if (insn & (1 << 20)) {
858
                        /* load */
859
                        gen_vfp_ld(dp);
860
                        gen_mov_vreg_F0(dp, rd + i);
861
                    } else {
862
                        /* store */
863
                        gen_mov_F0_vreg(dp, rd + i);
864
                        gen_vfp_st(dp);
865
                    }
866
                    gen_op_addl_T1_im(offset);
867
                }
868
                if (insn & (1 << 21)) {
869
                    /* writeback */
870
                    if (insn & (1 << 24))
871
                        offset = -offset * n;
872
                    else if (dp && (insn & 1))
873
                        offset = 4;
874
                    else
875
                        offset = 0;
876

    
877
                    if (offset != 0)
878
                        gen_op_addl_T1_im(offset);
879
                    gen_movl_reg_T1(s, rn);
880
                }
881
            }
882
        }
883
        break;
884
    default:
885
        /* Should never happen.  */
886
        return 1;
887
    }
888
    return 0;
889
}
890

    
891
static void disas_arm_insn(CPUState * env, DisasContext *s)
892
{
893
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
894
    
895
    insn = ldl(s->pc);
896
    s->pc += 4;
897
    
898
    cond = insn >> 28;
899
    if (cond == 0xf){
900
        /* Unconditional instructions.  */
901
        if ((insn & 0x0d70f000) == 0x0550f000)
902
            return; /* PLD */
903
        else if ((insn & 0x0e000000) == 0x0a000000) {
904
            /* branch link and change to thumb (blx <offset>) */
905
            int32_t offset;
906

    
907
            val = (uint32_t)s->pc;
908
            gen_op_movl_T0_im(val);
909
            gen_movl_reg_T0(s, 14);
910
            /* Sign-extend the 24-bit offset */
911
            offset = (((int32_t)insn) << 8) >> 8;
912
            /* offset * 4 + bit24 * 2 + (thumb bit) */
913
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
914
            /* pipeline offset */
915
            val += 4;
916
            gen_op_movl_T0_im(val);
917
            gen_bx(s);
918
            return;
919
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
920
            /* Coprocessor double register transfer.  */
921
        } else if ((insn & 0x0f000010) == 0x0e000010) {
922
            /* Additional coprocessor register transfer.  */
923
        }
924
        goto illegal_op;
925
    }
926
    if (cond != 0xe) {
927
        /* if not always execute, we generate a conditional jump to
928
           next instruction */
929
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
930
        s->is_jmp = DISAS_JUMP_NEXT;
931
    }
932
    if ((insn & 0x0f900000) == 0x03000000) {
933
        if ((insn & 0x0ff0f000) != 0x0360f000)
934
            goto illegal_op;
935
        /* CPSR = immediate */
936
        val = insn & 0xff;
937
        shift = ((insn >> 8) & 0xf) * 2;
938
        if (shift)
939
            val = (val >> shift) | (val << (32 - shift));
940
        gen_op_movl_T0_im(val);
941
        if (insn & (1 << 19))
942
            gen_op_movl_psr_T0();
943
    } else if ((insn & 0x0f900000) == 0x01000000
944
               && (insn & 0x00000090) != 0x00000090) {
945
        /* miscellaneous instructions */
946
        op1 = (insn >> 21) & 3;
947
        sh = (insn >> 4) & 0xf;
948
        rm = insn & 0xf;
949
        switch (sh) {
950
        case 0x0: /* move program status register */
951
            if (op1 & 2) {
952
                /* SPSR not accessible in user mode */
953
                goto illegal_op;
954
            }
955
            if (op1 & 1) {
956
                /* CPSR = reg */
957
                gen_movl_T0_reg(s, rm);
958
                if (insn & (1 << 19))
959
                    gen_op_movl_psr_T0();
960
            } else {
961
                /* reg = CPSR */
962
                rd = (insn >> 12) & 0xf;
963
                gen_op_movl_T0_psr();
964
                gen_movl_reg_T0(s, rd);
965
            }
966
            break;
967
        case 0x1:
968
            if (op1 == 1) {
969
                /* branch/exchange thumb (bx).  */
970
                gen_movl_T0_reg(s, rm);
971
                gen_bx(s);
972
            } else if (op1 == 3) {
973
                /* clz */
974
                rd = (insn >> 12) & 0xf;
975
                gen_movl_T0_reg(s, rm);
976
                gen_op_clz_T0();
977
                gen_movl_reg_T0(s, rd);
978
            } else {
979
                goto illegal_op;
980
            }
981
            break;
982
        case 0x3:
983
            if (op1 != 1)
984
              goto illegal_op;
985

    
986
            /* branch link/exchange thumb (blx) */
987
            val = (uint32_t)s->pc;
988
            gen_op_movl_T0_im(val);
989
            gen_movl_reg_T0(s, 14);
990
            gen_movl_T0_reg(s, rm);
991
            gen_bx(s);
992
            break;
993
        case 0x5: /* saturating add/subtract */
994
            rd = (insn >> 12) & 0xf;
995
            rn = (insn >> 16) & 0xf;
996
            gen_movl_T0_reg(s, rn);
997
            if (op1 & 2) {
998
                gen_movl_T1_reg(s, rn);
999
                if (op1 & 1) 
1000
                    gen_op_subl_T0_T1_saturate();
1001
                else
1002
                    gen_op_addl_T0_T1_saturate();
1003
            }
1004
            gen_movl_T1_reg(s, rm);
1005
            if (op1 & 1)
1006
                gen_op_subl_T0_T1_saturate();
1007
            else
1008
                gen_op_addl_T0_T1_saturate();
1009
            gen_movl_reg_T0(s, rn);
1010
            break;
1011
        case 0x8: /* signed multiply */
1012
        case 0xa:
1013
        case 0xc:
1014
        case 0xe:
1015
            rs = (insn >> 8) & 0xf;
1016
            rn = (insn >> 12) & 0xf;
1017
            rd = (insn >> 16) & 0xf;
1018
            if (op1 == 1) {
1019
                /* (32 * 16) >> 16 */
1020
                gen_movl_T0_reg(s, rm);
1021
                gen_movl_T1_reg(s, rs);
1022
                if (sh & 4)
1023
                    gen_op_sarl_T1_im(16);
1024
                else
1025
                    gen_op_sxl_T1();
1026
                gen_op_imulw_T0_T1();
1027
                if ((sh & 2) == 0) {
1028
                    gen_movl_T1_reg(s, rn);
1029
                    gen_op_addl_T0_T1_setq();
1030
                }
1031
                gen_movl_reg_T0(s, rd);
1032
            } else {
1033
                /* 16 * 16 */
1034
                gen_movl_T0_reg(s, rm);
1035
                if (sh & 2)
1036
                    gen_op_sarl_T0_im(16);
1037
                else
1038
                    gen_op_sxl_T0();
1039
                gen_movl_T1_reg(s, rs);
1040
                if (sh & 4)
1041
                    gen_op_sarl_T1_im(16);
1042
                else
1043
                    gen_op_sxl_T1();
1044
                if (op1 == 2) {
1045
                    gen_op_imull_T0_T1();
1046
                    gen_op_addq_T0_T1(rn, rd);
1047
                    gen_movl_reg_T0(s, rn);
1048
                    gen_movl_reg_T1(s, rd);
1049
                } else {
1050
                    gen_op_mul_T0_T1();
1051
                    if (op1 == 0) {
1052
                        gen_movl_T1_reg(s, rn);
1053
                        gen_op_addl_T0_T1_setq();
1054
                    }
1055
                    gen_movl_reg_T0(s, rd);
1056
                }
1057
            }
1058
            break;
1059
        default:
1060
            goto illegal_op;
1061
        }
1062
    } else if (((insn & 0x0e000000) == 0 &&
1063
                (insn & 0x00000090) != 0x90) ||
1064
               ((insn & 0x0e000000) == (1 << 25))) {
1065
        int set_cc, logic_cc, shiftop;
1066
        
1067
        op1 = (insn >> 21) & 0xf;
1068
        set_cc = (insn >> 20) & 1;
1069
        logic_cc = table_logic_cc[op1] & set_cc;
1070

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

    
1510
static void disas_thumb_insn(DisasContext *s)
1511
{
1512
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
1513
    int32_t offset;
1514
    int i;
1515

    
1516
    insn = lduw(s->pc);
1517
    s->pc += 2;
1518
    
1519
    switch (insn >> 12) {
1520
    case 0: case 1:
1521
        rd = insn & 7;
1522
        op = (insn >> 11) & 3;
1523
        if (op == 3) {
1524
            /* add/subtract */
1525
            rn = (insn >> 3) & 7;
1526
            gen_movl_T0_reg(s, rn);
1527
            if (insn & (1 << 10)) {
1528
                /* immediate */
1529
                gen_op_movl_T1_im((insn >> 6) & 7);
1530
            } else {
1531
                /* reg */
1532
                rm = (insn >> 6) & 7;
1533
                gen_movl_T1_reg(s, rm);
1534
            }
1535
            if (insn & (1 << 9))
1536
                gen_op_addl_T0_T1_cc();
1537
            else
1538
                gen_op_addl_T0_T1_cc();
1539
            gen_movl_reg_T0(s, rd);
1540
        } else {
1541
            /* shift immediate */
1542
            rm = (insn >> 3) & 7;
1543
            shift = (insn >> 6) & 0x1f;
1544
            gen_movl_T0_reg(s, rm);
1545
            gen_shift_T0_im_thumb[op](shift);
1546
            gen_movl_reg_T0(s, rd);
1547
        }
1548
        break;
1549
    case 2: case 3:
1550
        /* arithmetic large immediate */
1551
        op = (insn >> 11) & 3;
1552
        rd = (insn >> 8) & 0x7;
1553
        if (op == 0) {
1554
            gen_op_movl_T0_im(insn & 0xff);
1555
        } else {
1556
            gen_movl_T0_reg(s, rd);
1557
            gen_op_movl_T1_im(insn & 0xff);
1558
        }
1559
        switch (op) {
1560
        case 0: /* mov */
1561
            gen_op_logic_T0_cc();
1562
            break;
1563
        case 1: /* cmp */
1564
            gen_op_subl_T0_T1_cc();
1565
            break;
1566
        case 2: /* add */
1567
            gen_op_addl_T0_T1_cc();
1568
            break;
1569
        case 3: /* sub */
1570
            gen_op_subl_T0_T1_cc();
1571
            break;
1572
        }
1573
        if (op != 1)
1574
            gen_movl_reg_T0(s, rd);
1575
        break;
1576
    case 4:
1577
        if (insn & (1 << 11)) {
1578
            rd = (insn >> 8) & 7;
1579
            /* load pc-relative */
1580
            val = (insn & 0xff) * 4;
1581
            gen_op_movl_T1_im(val);
1582
            gen_movl_T2_reg(s, 15);
1583
            gen_op_addl_T1_T2();
1584
            gen_op_ldl_T0_T1();
1585
            gen_movl_reg_T0(s, rd);
1586
            break;
1587
        }
1588
        if (insn & (1 << 10)) {
1589
            /* data processing extended or blx */
1590
            rd = (insn & 7) | ((insn >> 4) & 8);
1591
            rm = (insn >> 3) & 0xf;
1592
            op = (insn >> 8) & 3;
1593
            switch (op) {
1594
            case 0: /* add */
1595
                gen_movl_T0_reg(s, rd);
1596
                gen_movl_T1_reg(s, rm);
1597
                gen_op_addl_T0_T1();
1598
                gen_movl_reg_T0(s, rd);
1599
                break;
1600
            case 1: /* cmp */
1601
                gen_movl_T0_reg(s, rd);
1602
                gen_movl_T1_reg(s, rm);
1603
                gen_op_subl_T0_T1_cc();
1604
                break;
1605
            case 2: /* mov/cpy */
1606
                gen_movl_T0_reg(s, rm);
1607
                gen_movl_reg_T0(s, rd);
1608
                break;
1609
            case 3:/* branch [and link] exchange thumb register */
1610
                if (insn & (1 << 7)) {
1611
                    val = (uint32_t)s->pc | 1;
1612
                    gen_op_movl_T1_im(val);
1613
                    gen_movl_reg_T1(s, 14);
1614
                }
1615
                gen_movl_T0_reg(s, rm);
1616
                gen_bx(s);
1617
                break;
1618
            }
1619
            break;
1620
        }
1621

    
1622
        /* data processing register */
1623
        rd = insn & 7;
1624
        rm = (insn >> 3) & 7;
1625
        op = (insn >> 6) & 0xf;
1626
        if (op == 2 || op == 3 || op == 4 || op == 7) {
1627
            /* the shift/rotate ops want the operands backwards */
1628
            val = rm;
1629
            rm = rd;
1630
            rd = val;
1631
            val = 1;
1632
        } else {
1633
            val = 0;
1634
        }
1635

    
1636
        if (op == 9) /* neg */
1637
            gen_op_movl_T0_im(0);
1638
        else if (op != 0xf) /* mvn doesn't read its first operand */
1639
            gen_movl_T0_reg(s, rd);
1640

    
1641
        gen_movl_T1_reg(s, rm);
1642
        switch (insn >> 6) {
1643
        case 0x0: /* and */
1644
            gen_op_andl_T0_T1();
1645
            gen_op_logic_T0_cc();
1646
            break;
1647
        case 0x1: /* eor */
1648
            gen_op_xorl_T0_T1();
1649
            gen_op_logic_T0_cc();
1650
            break;
1651
        case 0x2: /* lsl */
1652
            gen_op_shll_T1_T0_cc();
1653
            break;
1654
        case 0x3: /* lsr */
1655
            gen_op_shrl_T1_T0_cc();
1656
            break;
1657
        case 0x4: /* asr */
1658
            gen_op_sarl_T1_T0_cc();
1659
            break;
1660
        case 0x5: /* adc */
1661
            gen_op_adcl_T0_T1_cc();
1662
            break;
1663
        case 0x6: /* sbc */
1664
            gen_op_sbcl_T0_T1_cc();
1665
            break;
1666
        case 0x7: /* ror */
1667
            gen_op_rorl_T1_T0_cc();
1668
            break;
1669
        case 0x8: /* tst */
1670
            gen_op_andl_T0_T1();
1671
            gen_op_logic_T0_cc();
1672
            rd = 16;
1673
        case 0x9: /* neg */
1674
            gen_op_rsbl_T0_T1_cc();
1675
            break;
1676
        case 0xa: /* cmp */
1677
            gen_op_subl_T0_T1_cc();
1678
            rd = 16;
1679
            break;
1680
        case 0xb: /* cmn */
1681
            gen_op_addl_T0_T1_cc();
1682
            rd = 16;
1683
            break;
1684
        case 0xc: /* orr */
1685
            gen_op_orl_T0_T1();
1686
            gen_op_logic_T0_cc();
1687
            break;
1688
        case 0xd: /* mul */
1689
            gen_op_mull_T0_T1();
1690
            gen_op_logic_T0_cc();
1691
            break;
1692
        case 0xe: /* bic */
1693
            gen_op_bicl_T0_T1();
1694
            gen_op_logic_T0_cc();
1695
            break;
1696
        case 0xf: /* mvn */
1697
            gen_op_notl_T1();
1698
            gen_op_logic_T1_cc();
1699
            val = 1;
1700
            break;
1701
        }
1702
        if (rd != 16) {
1703
            if (val)
1704
                gen_movl_reg_T1(s, rd);
1705
            else
1706
                gen_movl_reg_T0(s, rd);
1707
        }
1708
        break;
1709

    
1710
    case 5:
1711
        /* load/store register offset.  */
1712
        rd = insn & 7;
1713
        rn = (insn >> 3) & 7;
1714
        rm = (insn >> 6) & 7;
1715
        op = (insn >> 9) & 7;
1716
        gen_movl_T1_reg(s, rn);
1717
        gen_movl_T2_reg(s, rm);
1718
        gen_op_addl_T1_T2();
1719

    
1720
        if (op < 3) /* store */
1721
            gen_movl_T0_reg(s, rd);
1722

    
1723
        switch (op) {
1724
        case 0: /* str */
1725
            gen_op_stl_T0_T1();
1726
            break;
1727
        case 1: /* strh */
1728
            gen_op_stw_T0_T1();
1729
            break;
1730
        case 2: /* strb */
1731
            gen_op_stb_T0_T1();
1732
            break;
1733
        case 3: /* ldrsb */
1734
            gen_op_ldsb_T0_T1();
1735
            break;
1736
        case 4: /* ldr */
1737
            gen_op_ldl_T0_T1();
1738
            break;
1739
        case 5: /* ldrh */
1740
            gen_op_ldsw_T0_T1();
1741
            break;
1742
        case 6: /* ldrb */
1743
            gen_op_ldub_T0_T1();
1744
            break;
1745
        case 7: /* ldrsh */
1746
            gen_op_ldsw_T0_T1();
1747
            break;
1748
        }
1749
        if (op >= 3) /* load */
1750
            gen_movl_reg_T0(s, rd);
1751
        break;
1752

    
1753
    case 6:
1754
        /* load/store word immediate offset */
1755
        rd = insn & 7;
1756
        rn = (insn >> 3) & 7;
1757
        gen_movl_T1_reg(s, rn);
1758
        val = (insn >> 4) & 0x7c;
1759
        gen_op_movl_T2_im(val);
1760
        gen_op_addl_T1_T2();
1761

    
1762
        if (insn & (1 << 11)) {
1763
            /* load */
1764
            gen_op_ldl_T0_T1();
1765
            gen_movl_reg_T0(s, rd);
1766
        } else {
1767
            /* store */
1768
            gen_movl_T0_reg(s, rd);
1769
            gen_op_stl_T0_T1();
1770
        }
1771
        break;
1772

    
1773
    case 7:
1774
        /* load/store byte immediate offset */
1775
        rd = insn & 7;
1776
        rn = (insn >> 3) & 7;
1777
        gen_movl_T1_reg(s, rn);
1778
        val = (insn >> 6) & 0x1f;
1779
        gen_op_movl_T2_im(val);
1780
        gen_op_addl_T1_T2();
1781

    
1782
        if (insn & (1 << 11)) {
1783
            /* load */
1784
            gen_op_ldub_T0_T1();
1785
            gen_movl_reg_T0(s, rd);
1786
        } else {
1787
            /* store */
1788
            gen_movl_T0_reg(s, rd);
1789
            gen_op_stb_T0_T1();
1790
        }
1791
        break;
1792

    
1793
    case 8:
1794
        /* load/store halfword immediate offset */
1795
        rd = insn & 7;
1796
        rn = (insn >> 3) & 7;
1797
        gen_movl_T1_reg(s, rn);
1798
        val = (insn >> 5) & 0x3e;
1799
        gen_op_movl_T2_im(val);
1800
        gen_op_addl_T1_T2();
1801

    
1802
        if (insn & (1 << 11)) {
1803
            /* load */
1804
            gen_op_lduw_T0_T1();
1805
            gen_movl_reg_T0(s, rd);
1806
        } else {
1807
            /* store */
1808
            gen_movl_T0_reg(s, rd);
1809
            gen_op_stw_T0_T1();
1810
        }
1811
        break;
1812

    
1813
    case 9:
1814
        /* load/store from stack */
1815
        rd = (insn >> 8) & 7;
1816
        gen_movl_T1_reg(s, 13);
1817
        val = (insn & 0xff) * 4;
1818
        gen_op_movl_T2_im(val);
1819
        gen_op_addl_T1_T2();
1820

    
1821
        if (insn & (1 << 11)) {
1822
            /* load */
1823
            gen_op_ldl_T0_T1();
1824
            gen_movl_reg_T0(s, rd);
1825
        } else {
1826
            /* store */
1827
            gen_movl_T0_reg(s, rd);
1828
            gen_op_stl_T0_T1();
1829
        }
1830
        break;
1831

    
1832
    case 10:
1833
        /* add to high reg */
1834
        rd = (insn >> 8) & 7;
1835
        if (insn & (1 << 11))
1836
            rm = 13; /* sp */
1837
        else
1838
            rm = 15; /* pc */
1839
        gen_movl_T0_reg(s, rm);
1840
        val = (insn & 0xff) * 4;
1841
        gen_op_movl_T1_im(val);
1842
        gen_op_addl_T0_T1();
1843
        gen_movl_reg_T0(s, rd);
1844
        break;
1845

    
1846
    case 11:
1847
        /* misc */
1848
        op = (insn >> 8) & 0xf;
1849
        switch (op) {
1850
        case 0:
1851
            /* adjust stack pointer */
1852
            gen_movl_T1_reg(s, 13);
1853
            val = (insn & 0x7f) * 4;
1854
            if (insn & (1 << 7))
1855
              val = -(int32_t)val;
1856
            gen_op_movl_T2_im(val);
1857
            gen_op_addl_T1_T2();
1858
            gen_movl_reg_T1(s, 13);
1859
            break;
1860

    
1861
        case 4: case 5: case 0xc: case 0xd:
1862
            /* push/pop */
1863
            gen_movl_T1_reg(s, 13);
1864
            if (insn & (1 << 11))
1865
                val = 4;
1866
            else
1867
                val = -4;
1868
            gen_op_movl_T2_im(val);
1869
            for (i = 0; i < 8; i++) {
1870
                if (insn & (1 << i)) {
1871
                    if (insn & (1 << 11)) {
1872
                        /* pop */
1873
                        gen_op_ldl_T0_T1();
1874
                        gen_movl_reg_T0(s, i);
1875
                    } else {
1876
                        /* push */
1877
                        gen_movl_T0_reg(s, i);
1878
                        gen_op_stl_T0_T1();
1879
                    }
1880
                    /* move to the next address */
1881
                    gen_op_addl_T1_T2();
1882
                }
1883
            }
1884
            if (insn & (1 << 8)) {
1885
                if (insn & (1 << 11)) {
1886
                    /* pop pc */
1887
                    gen_op_ldl_T0_T1();
1888
                    /* don't set the pc until the rest of the instruction
1889
                       has completed */
1890
                } else {
1891
                    /* push lr */
1892
                    gen_movl_T0_reg(s, 14);
1893
                    gen_op_stl_T0_T1();
1894
                }
1895
                gen_op_addl_T1_T2();
1896
            }
1897

    
1898
            /* write back the new stack pointer */
1899
            gen_movl_reg_T1(s, 13);
1900
            /* set the new PC value */
1901
            if ((insn & 0x0900) == 0x0900)
1902
                gen_bx(s);
1903
            break;
1904

    
1905
        default:
1906
            goto undef;
1907
        }
1908
        break;
1909

    
1910
    case 12:
1911
        /* load/store multiple */
1912
        rn = (insn >> 8) & 0x7;
1913
        gen_movl_T1_reg(s, rn);
1914
        gen_op_movl_T2_im(4);
1915
        val = 0;
1916
        for (i = 0; i < 8; i++) {
1917
            if (insn & (1 << i)) {
1918
                /* advance to the next address */
1919
                if (val)
1920
                    gen_op_addl_T1_T2();
1921
                else
1922
                    val = 1;
1923
                if (insn & (1 << 11)) {
1924
                    /* load */
1925
                    gen_op_ldl_T0_T1();
1926
                    gen_movl_reg_T0(s, i);
1927
                } else {
1928
                    /* store */
1929
                    gen_movl_T0_reg(s, i);
1930
                    gen_op_stl_T0_T1();
1931
                }
1932
            }
1933
        }
1934
        break;
1935

    
1936
    case 13:
1937
        /* conditional branch or swi */
1938
        cond = (insn >> 8) & 0xf;
1939
        if (cond == 0xe)
1940
            goto undef;
1941

    
1942
        if (cond == 0xf) {
1943
            /* swi */
1944
            gen_op_movl_T0_im((long)s->pc | 1);
1945
            /* Don't set r15.  */
1946
            gen_op_movl_reg_TN[0][15]();
1947
            gen_op_swi();
1948
            s->is_jmp = DISAS_JUMP;
1949
            break;
1950
        }
1951
        /* generate a conditional jump to next instruction */
1952
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1953
        s->is_jmp = DISAS_JUMP_NEXT;
1954
        gen_movl_T1_reg(s, 15);
1955

    
1956
        /* jump to the offset */
1957
        val = (uint32_t)s->pc;
1958
        offset = ((int32_t)insn << 24) >> 24;
1959
        val += (offset << 1) + 2;
1960
        gen_op_jmp((long)s->tb, val);
1961
        s->is_jmp = DISAS_TB_JUMP;
1962
        break;
1963

    
1964
    case 14:
1965
        /* unconditional branch */
1966
        if (insn & (1 << 11))
1967
            goto undef; /* Second half of a blx */
1968
        val = (uint32_t)s->pc;
1969
        offset = ((int32_t)insn << 21) >> 21;
1970
        val += (offset << 1) + 2;
1971
        gen_op_jmp((long)s->tb, val);
1972
        s->is_jmp = DISAS_TB_JUMP;
1973
        break;
1974

    
1975
    case 15:
1976
        /* branch and link [and switch to arm] */
1977
        offset = ((int32_t)insn << 21) >> 10;
1978
        insn = lduw(s->pc);
1979
        offset |= insn & 0x7ff;
1980

    
1981
        val = (uint32_t)s->pc + 2;
1982
        gen_op_movl_T1_im(val | 1);
1983
        gen_movl_reg_T1(s, 14);
1984
        
1985
        val += offset;
1986
        if (insn & (1 << 11)) {
1987
            /* bl */
1988
            gen_op_jmp((long)s->tb, val);
1989
            s->is_jmp = DISAS_TB_JUMP;
1990
        } else {
1991
            /* blx */
1992
            gen_op_movl_T0_im(val);
1993
            gen_bx(s);
1994
        }
1995
    }
1996
    return;
1997
undef:
1998
    gen_op_movl_T0_im((long)s->pc - 4);
1999
    gen_op_movl_reg_TN[0][15]();
2000
    gen_op_undef_insn();
2001
    s->is_jmp = DISAS_JUMP;
2002
}
2003

    
2004
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
2005
   basic block 'tb'. If search_pc is TRUE, also generate PC
2006
   information for each intermediate instruction. */
2007
static inline int gen_intermediate_code_internal(CPUState *env, 
2008
                                                 TranslationBlock *tb, 
2009
                                                 int search_pc)
2010
{
2011
    DisasContext dc1, *dc = &dc1;
2012
    uint16_t *gen_opc_end;
2013
    int j, lj;
2014
    target_ulong pc_start;
2015
    
2016
    /* generate intermediate code */
2017
    pc_start = tb->pc;
2018
       
2019
    dc->tb = tb;
2020

    
2021
    gen_opc_ptr = gen_opc_buf;
2022
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2023
    gen_opparam_ptr = gen_opparam_buf;
2024

    
2025
    dc->is_jmp = DISAS_NEXT;
2026
    dc->pc = pc_start;
2027
    lj = -1;
2028
    do {
2029
        if (env->nb_breakpoints > 0) {
2030
            for(j = 0; j < env->nb_breakpoints; j++) {
2031
                if (env->breakpoints[j] == dc->pc) {
2032
                    gen_op_movl_T0_im((long)dc->pc);
2033
                    gen_op_movl_reg_TN[0][15]();
2034
                    gen_op_debug();
2035
                    dc->is_jmp = DISAS_JUMP;
2036
                    break;
2037
                }
2038
            }
2039
        }
2040
        if (search_pc) {
2041
            j = gen_opc_ptr - gen_opc_buf;
2042
            if (lj < j) {
2043
                lj++;
2044
                while (lj < j)
2045
                    gen_opc_instr_start[lj++] = 0;
2046
            }
2047
            gen_opc_pc[lj] = dc->pc;
2048
            gen_opc_instr_start[lj] = 1;
2049
        }
2050
        if (env->thumb)
2051
          disas_thumb_insn(dc);
2052
        else
2053
          disas_arm_insn(env, dc);
2054
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2055
             !env->singlestep_enabled &&
2056
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2057
    switch(dc->is_jmp) {
2058
    case DISAS_JUMP_NEXT:
2059
    case DISAS_NEXT:
2060
        gen_op_jmp((long)dc->tb, (long)dc->pc);
2061
        break;
2062
    default:
2063
    case DISAS_JUMP:
2064
    case DISAS_UPDATE:
2065
        /* indicate that the hash table must be used to find the next TB */
2066
        gen_op_movl_T0_0();
2067
        gen_op_exit_tb();
2068
        break;
2069
    case DISAS_TB_JUMP:
2070
        /* nothing more to generate */
2071
        break;
2072
    }
2073
    *gen_opc_ptr = INDEX_op_end;
2074

    
2075
#ifdef DEBUG_DISAS
2076
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2077
        fprintf(logfile, "----------------\n");
2078
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2079
        target_disas(logfile, pc_start, dc->pc - pc_start, 0);
2080
        fprintf(logfile, "\n");
2081
        if (loglevel & (CPU_LOG_TB_OP)) {
2082
            fprintf(logfile, "OP:\n");
2083
            dump_ops(gen_opc_buf, gen_opparam_buf);
2084
            fprintf(logfile, "\n");
2085
        }
2086
    }
2087
#endif
2088
    if (!search_pc)
2089
        tb->size = dc->pc - pc_start;
2090
    return 0;
2091
}
2092

    
2093
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2094
{
2095
    return gen_intermediate_code_internal(env, tb, 0);
2096
}
2097

    
2098
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2099
{
2100
    return gen_intermediate_code_internal(env, tb, 1);
2101
}
2102

    
2103
CPUARMState *cpu_arm_init(void)
2104
{
2105
    CPUARMState *env;
2106

    
2107
    cpu_exec_init();
2108

    
2109
    env = malloc(sizeof(CPUARMState));
2110
    if (!env)
2111
        return NULL;
2112
    memset(env, 0, sizeof(CPUARMState));
2113
    cpu_single_env = env;
2114
    return env;
2115
}
2116

    
2117
void cpu_arm_close(CPUARMState *env)
2118
{
2119
    free(env);
2120
}
2121

    
2122
void cpu_dump_state(CPUState *env, FILE *f, 
2123
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2124
                    int flags)
2125
{
2126
    int i;
2127
    struct {
2128
        uint32_t i;
2129
        float s;
2130
    } s0, s1;
2131
    CPU_DoubleU d;
2132

    
2133
    for(i=0;i<16;i++) {
2134
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2135
        if ((i % 4) == 3)
2136
            cpu_fprintf(f, "\n");
2137
        else
2138
            cpu_fprintf(f, " ");
2139
    }
2140
    cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 
2141
             env->cpsr, 
2142
            env->cpsr & (1 << 31) ? 'N' : '-',
2143
            env->cpsr & (1 << 30) ? 'Z' : '-',
2144
            env->cpsr & (1 << 29) ? 'C' : '-',
2145
            env->cpsr & (1 << 28) ? 'V' : '-');
2146

    
2147
    for (i = 0; i < 16; i++) {
2148
        d.d = env->vfp.regs[i];
2149
        s0.i = d.l.lower;
2150
        s1.i = d.l.upper;
2151
        cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
2152
                    i * 2, (int)s0.i, s0.s,
2153
                    i * 2 + 1, (int)s0.i, s0.s,
2154
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2155
                    d.d);
2156
        cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
2157
    }
2158
}
2159

    
2160
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2161
{
2162
    return addr;
2163
}
2164

    
2165
#if defined(CONFIG_USER_ONLY) 
2166

    
2167
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
2168
                              int is_user, int is_softmmu)
2169
{
2170
    env->cp15_6 = address;
2171
    if (rw == 2) {
2172
        env->exception_index = EXCP_PREFETCH_ABORT;
2173
    } else {
2174
        env->exception_index = EXCP_DATA_ABORT;
2175
    }
2176
    return 1;
2177
}
2178

    
2179
#else
2180

    
2181
#error not implemented
2182

    
2183
#endif