Statistics
| Branch: | Revision:

root / target-arm / translate.c @ afc7df11

History | View | Annotate | Download (44.8 kB)

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

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

    
30
/* internal defines */
31
typedef struct DisasContext {
32
    target_ulong pc;
33
    int is_jmp;
34
    struct TranslationBlock *tb;
35
} DisasContext;
36

    
37
#define DISAS_JUMP_NEXT 4
38

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

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

    
52
#include "gen-op.h"
53

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
357
static void disas_arm_insn(DisasContext *s)
358
{
359
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
360
    
361
    insn = ldl(s->pc);
362
    s->pc += 4;
363
    
364
    cond = insn >> 28;
365
    if (cond == 0xf){
366
        if ((insn & 0x0d70f000) == 0x0550f000)
367
            return; /* PLD */
368
        else if ((insn & 0x0e000000) == 0x0a000000) {
369
            /* branch link and change to thumb (blx <offset>) */
370
            int32_t offset;
371

    
372
            val = (uint32_t)s->pc;
373
            gen_op_movl_T0_im(val);
374
            gen_movl_reg_T0(s, 14);
375
            /* Sign-extend the 24-bit offset */
376
            offset = (((int32_t)insn) << 8) >> 8;
377
            /* offset * 4 + bit24 * 2 + (thumb bit) */
378
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
379
            /* pipeline offset */
380
            val += 4;
381
            gen_op_movl_T0_im(val);
382
            gen_bx(s);
383
            return;
384
        }
385
        goto illegal_op;
386
    }
387
    if (cond != 0xe) {
388
        /* if not always execute, we generate a conditional jump to
389
           next instruction */
390
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
391
        s->is_jmp = DISAS_JUMP_NEXT;
392
    }
393
    if ((insn & 0x0f900000) == 0x03000000) {
394
        if ((insn & 0x0ff0f000) != 0x0360f000)
395
            goto illegal_op;
396
        /* CPSR = immediate */
397
        val = insn & 0xff;
398
        shift = ((insn >> 8) & 0xf) * 2;
399
        if (shift)
400
            val = (val >> shift) | (val << (32 - shift));
401
        gen_op_movl_T0_im(val);
402
        if (insn & (1 << 19))
403
            gen_op_movl_psr_T0();
404
    } else if ((insn & 0x0f900000) == 0x01000000
405
               && (insn & 0x00000090) != 0x00000090) {
406
        /* miscellaneous instructions */
407
        op1 = (insn >> 21) & 3;
408
        sh = (insn >> 4) & 0xf;
409
        rm = insn & 0xf;
410
        switch (sh) {
411
        case 0x0: /* move program status register */
412
            if (op1 & 2) {
413
                /* SPSR not accessible in user mode */
414
                goto illegal_op;
415
            }
416
            if (op1 & 1) {
417
                /* CPSR = reg */
418
                gen_movl_T0_reg(s, rm);
419
                if (insn & (1 << 19))
420
                    gen_op_movl_psr_T0();
421
            } else {
422
                /* reg = CPSR */
423
                rd = (insn >> 12) & 0xf;
424
                gen_op_movl_T0_psr();
425
                gen_movl_reg_T0(s, rd);
426
            }
427
            break;
428
        case 0x1:
429
            if (op1 == 1) {
430
                /* branch/exchange thumb (bx).  */
431
                gen_movl_T0_reg(s, rm);
432
                gen_bx(s);
433
            } else if (op1 == 3) {
434
                /* clz */
435
                rd = (insn >> 12) & 0xf;
436
                gen_movl_T0_reg(s, rm);
437
                gen_op_clz_T0();
438
                gen_movl_reg_T0(s, rd);
439
            } else {
440
                goto illegal_op;
441
            }
442
            break;
443
        case 0x3:
444
            if (op1 != 1)
445
              goto illegal_op;
446

    
447
            /* branch link/exchange thumb (blx) */
448
            val = (uint32_t)s->pc;
449
            gen_op_movl_T0_im(val);
450
            gen_movl_reg_T0(s, 14);
451
            gen_movl_T0_reg(s, rm);
452
            gen_bx(s);
453
            break;
454
        case 0x5: /* saturating add/subtract */
455
            rd = (insn >> 12) & 0xf;
456
            rn = (insn >> 16) & 0xf;
457
            gen_movl_T0_reg(s, rn);
458
            if (op1 & 2) {
459
                gen_movl_T1_reg(s, rn);
460
                if (op1 & 1) 
461
                    gen_op_subl_T0_T1_saturate();
462
                else
463
                    gen_op_addl_T0_T1_saturate();
464
            }
465
            gen_movl_T1_reg(s, rm);
466
            if (op1 & 1)
467
                gen_op_subl_T0_T1_saturate();
468
            else
469
                gen_op_addl_T0_T1_saturate();
470
            gen_movl_reg_T0(s, rn);
471
            break;
472
        case 0x8: /* signed multiply */
473
        case 0xa:
474
        case 0xc:
475
        case 0xe:
476
            rs = (insn >> 8) & 0xf;
477
            rn = (insn >> 12) & 0xf;
478
            rd = (insn >> 16) & 0xf;
479
            if (op1 == 1) {
480
                /* (32 * 16) >> 16 */
481
                gen_movl_T0_reg(s, rm);
482
                gen_movl_T1_reg(s, rs);
483
                if (sh & 4)
484
                    gen_op_sarl_T1_im(16);
485
                else
486
                    gen_op_sxl_T1();
487
                gen_op_imulw_T0_T1();
488
                if ((sh & 2) == 0) {
489
                    gen_movl_T1_reg(s, rn);
490
                    gen_op_addl_T0_T1_setq();
491
                }
492
                gen_movl_reg_T0(s, rd);
493
            } else {
494
                /* 16 * 16 */
495
                gen_movl_T0_reg(s, rm);
496
                if (sh & 2)
497
                    gen_op_sarl_T0_im(16);
498
                else
499
                    gen_op_sxl_T0();
500
                gen_movl_T1_reg(s, rs);
501
                if (sh & 4)
502
                    gen_op_sarl_T1_im(16);
503
                else
504
                    gen_op_sxl_T1();
505
                if (op1 == 2) {
506
                    gen_op_imull_T0_T1();
507
                    gen_op_addq_T0_T1(rn, rd);
508
                    gen_movl_reg_T0(s, rn);
509
                    gen_movl_reg_T1(s, rd);
510
                } else {
511
                    gen_op_mul_T0_T1();
512
                    if (op1 == 0) {
513
                        gen_movl_T1_reg(s, rn);
514
                        gen_op_addl_T0_T1_setq();
515
                    }
516
                    gen_movl_reg_T0(s, rd);
517
                }
518
            }
519
            break;
520
        default:
521
            goto illegal_op;
522
        }
523
    } else if (((insn & 0x0e000000) == 0 &&
524
                (insn & 0x00000090) != 0x90) ||
525
               ((insn & 0x0e000000) == (1 << 25))) {
526
        int set_cc, logic_cc, shiftop;
527
        
528
        op1 = (insn >> 21) & 0xf;
529
        set_cc = (insn >> 20) & 1;
530
        logic_cc = table_logic_cc[op1] & set_cc;
531

    
532
        /* data processing instruction */
533
        if (insn & (1 << 25)) {
534
            /* immediate operand */
535
            val = insn & 0xff;
536
            shift = ((insn >> 8) & 0xf) * 2;
537
            if (shift)
538
                val = (val >> shift) | (val << (32 - shift));
539
            gen_op_movl_T1_im(val);
540
            if (logic_cc && shift)
541
                gen_op_mov_CF_T1();
542
        } else {
543
            /* register */
544
            rm = (insn) & 0xf;
545
            gen_movl_T1_reg(s, rm);
546
            shiftop = (insn >> 5) & 3;
547
            if (!(insn & (1 << 4))) {
548
                shift = (insn >> 7) & 0x1f;
549
                if (shift != 0) {
550
                    if (logic_cc) {
551
                        gen_shift_T1_im_cc[shiftop](shift);
552
                    } else {
553
                        gen_shift_T1_im[shiftop](shift);
554
                    }
555
                } else if (shiftop != 0) {
556
                    if (logic_cc) {
557
                        gen_shift_T1_0_cc[shiftop]();
558
                    } else {
559
                        gen_shift_T1_0[shiftop]();
560
                    }
561
                }
562
            } else {
563
                rs = (insn >> 8) & 0xf;
564
                gen_movl_T0_reg(s, rs);
565
                if (logic_cc) {
566
                    gen_shift_T1_T0_cc[shiftop]();
567
                } else {
568
                    gen_shift_T1_T0[shiftop]();
569
                }
570
            }
571
        }
572
        if (op1 != 0x0f && op1 != 0x0d) {
573
            rn = (insn >> 16) & 0xf;
574
            gen_movl_T0_reg(s, rn);
575
        }
576
        rd = (insn >> 12) & 0xf;
577
        switch(op1) {
578
        case 0x00:
579
            gen_op_andl_T0_T1();
580
            gen_movl_reg_T0(s, rd);
581
            if (logic_cc)
582
                gen_op_logic_T0_cc();
583
            break;
584
        case 0x01:
585
            gen_op_xorl_T0_T1();
586
            gen_movl_reg_T0(s, rd);
587
            if (logic_cc)
588
                gen_op_logic_T0_cc();
589
            break;
590
        case 0x02:
591
            if (set_cc)
592
                gen_op_subl_T0_T1_cc();
593
            else
594
                gen_op_subl_T0_T1();
595
            gen_movl_reg_T0(s, rd);
596
            break;
597
        case 0x03:
598
            if (set_cc)
599
                gen_op_rsbl_T0_T1_cc();
600
            else
601
                gen_op_rsbl_T0_T1();
602
            gen_movl_reg_T0(s, rd);
603
            break;
604
        case 0x04:
605
            if (set_cc)
606
                gen_op_addl_T0_T1_cc();
607
            else
608
                gen_op_addl_T0_T1();
609
            gen_movl_reg_T0(s, rd);
610
            break;
611
        case 0x05:
612
            if (set_cc)
613
                gen_op_adcl_T0_T1_cc();
614
            else
615
                gen_op_adcl_T0_T1();
616
            gen_movl_reg_T0(s, rd);
617
            break;
618
        case 0x06:
619
            if (set_cc)
620
                gen_op_sbcl_T0_T1_cc();
621
            else
622
                gen_op_sbcl_T0_T1();
623
            gen_movl_reg_T0(s, rd);
624
            break;
625
        case 0x07:
626
            if (set_cc)
627
                gen_op_rscl_T0_T1_cc();
628
            else
629
                gen_op_rscl_T0_T1();
630
            gen_movl_reg_T0(s, rd);
631
            break;
632
        case 0x08:
633
            if (set_cc) {
634
                gen_op_andl_T0_T1();
635
                gen_op_logic_T0_cc();
636
            }
637
            break;
638
        case 0x09:
639
            if (set_cc) {
640
                gen_op_xorl_T0_T1();
641
                gen_op_logic_T0_cc();
642
            }
643
            break;
644
        case 0x0a:
645
            if (set_cc) {
646
                gen_op_subl_T0_T1_cc();
647
            }
648
            break;
649
        case 0x0b:
650
            if (set_cc) {
651
                gen_op_addl_T0_T1_cc();
652
            }
653
            break;
654
        case 0x0c:
655
            gen_op_orl_T0_T1();
656
            gen_movl_reg_T0(s, rd);
657
            if (logic_cc)
658
                gen_op_logic_T0_cc();
659
            break;
660
        case 0x0d:
661
            gen_movl_reg_T1(s, rd);
662
            if (logic_cc)
663
                gen_op_logic_T1_cc();
664
            break;
665
        case 0x0e:
666
            gen_op_bicl_T0_T1();
667
            gen_movl_reg_T0(s, rd);
668
            if (logic_cc)
669
                gen_op_logic_T0_cc();
670
            break;
671
        default:
672
        case 0x0f:
673
            gen_op_notl_T1();
674
            gen_movl_reg_T1(s, rd);
675
            if (logic_cc)
676
                gen_op_logic_T1_cc();
677
            break;
678
        }
679
    } else {
680
        /* other instructions */
681
        op1 = (insn >> 24) & 0xf;
682
        switch(op1) {
683
        case 0x0:
684
        case 0x1:
685
            /* multiplies, extra load/stores */
686
            sh = (insn >> 5) & 3;
687
            if (sh == 0) {
688
                if (op1 == 0x0) {
689
                    rd = (insn >> 16) & 0xf;
690
                    rn = (insn >> 12) & 0xf;
691
                    rs = (insn >> 8) & 0xf;
692
                    rm = (insn) & 0xf;
693
                    if (((insn >> 22) & 3) == 0) {
694
                        /* 32 bit mul */
695
                        gen_movl_T0_reg(s, rs);
696
                        gen_movl_T1_reg(s, rm);
697
                        gen_op_mul_T0_T1();
698
                        if (insn & (1 << 21)) {
699
                            gen_movl_T1_reg(s, rn);
700
                            gen_op_addl_T0_T1();
701
                        }
702
                        if (insn & (1 << 20)) 
703
                            gen_op_logic_T0_cc();
704
                        gen_movl_reg_T0(s, rd);
705
                    } else {
706
                        /* 64 bit mul */
707
                        gen_movl_T0_reg(s, rs);
708
                        gen_movl_T1_reg(s, rm);
709
                        if (insn & (1 << 22)) 
710
                            gen_op_imull_T0_T1();
711
                        else
712
                            gen_op_mull_T0_T1();
713
                        if (insn & (1 << 21)) /* mult accumulate */
714
                            gen_op_addq_T0_T1(rn, rd);
715
                        if (!(insn & (1 << 23))) { /* double accumulate */
716
                            gen_op_addq_lo_T0_T1(rn);
717
                            gen_op_addq_lo_T0_T1(rd);
718
                        }
719
                        if (insn & (1 << 20)) 
720
                            gen_op_logicq_cc();
721
                        gen_movl_reg_T0(s, rn);
722
                        gen_movl_reg_T1(s, rd);
723
                    }
724
                } else {
725
                    rn = (insn >> 16) & 0xf;
726
                    rd = (insn >> 12) & 0xf;
727
                    if (insn & (1 << 23)) {
728
                        /* load/store exclusive */
729
                        goto illegal_op;
730
                    } else {
731
                        /* SWP instruction */
732
                        rm = (insn) & 0xf;
733
                        
734
                        gen_movl_T0_reg(s, rm);
735
                        gen_movl_T1_reg(s, rn);
736
                        if (insn & (1 << 22)) {
737
                            gen_op_swpb_T0_T1();
738
                        } else {
739
                            gen_op_swpl_T0_T1();
740
                        }
741
                        gen_movl_reg_T0(s, rd);
742
                    }
743
                }
744
            } else {
745
                /* Misc load/store */
746
                rn = (insn >> 16) & 0xf;
747
                rd = (insn >> 12) & 0xf;
748
                gen_movl_T1_reg(s, rn);
749
                if (insn & (1 << 24))
750
                    gen_add_datah_offset(s, insn);
751
                if (insn & (1 << 20)) {
752
                    /* load */
753
                    switch(sh) {
754
                    case 1:
755
                        gen_op_lduw_T0_T1();
756
                        break;
757
                    case 2:
758
                        gen_op_ldsb_T0_T1();
759
                        break;
760
                    default:
761
                    case 3:
762
                        gen_op_ldsw_T0_T1();
763
                        break;
764
                    }
765
                    gen_movl_reg_T0(s, rd);
766
                } else if (sh & 2) {
767
                    /* doubleword */
768
                    if (sh & 1) {
769
                        /* store */
770
                        gen_movl_T0_reg(s, rd);
771
                        gen_op_stl_T0_T1();
772
                        gen_op_addl_T1_im(4);
773
                        gen_movl_T0_reg(s, rd + 1);
774
                        gen_op_stl_T0_T1();
775
                        if ((insn & (1 << 24)) || (insn & (1 << 20)))
776
                            gen_op_addl_T1_im(-4);
777
                    } else {
778
                        /* load */
779
                        gen_op_ldl_T0_T1();
780
                        gen_movl_reg_T0(s, rd);
781
                        gen_op_addl_T1_im(4);
782
                        gen_op_ldl_T0_T1();
783
                        gen_movl_reg_T0(s, rd + 1);
784
                        if ((insn & (1 << 24)) || (insn & (1 << 20)))
785
                            gen_op_addl_T1_im(-4);
786
                    }
787
                } else {
788
                    /* store */
789
                    gen_movl_T0_reg(s, rd);
790
                    gen_op_stw_T0_T1();
791
                }
792
                if (!(insn & (1 << 24))) {
793
                    gen_add_datah_offset(s, insn);
794
                    gen_movl_reg_T1(s, rn);
795
                } else if (insn & (1 << 21)) {
796
                    gen_movl_reg_T1(s, rn);
797
                }
798
            }
799
            break;
800
        case 0x4:
801
        case 0x5:
802
        case 0x6:
803
        case 0x7:
804
            /* load/store byte/word */
805
            rn = (insn >> 16) & 0xf;
806
            rd = (insn >> 12) & 0xf;
807
            gen_movl_T1_reg(s, rn);
808
            if (insn & (1 << 24))
809
                gen_add_data_offset(s, insn);
810
            if (insn & (1 << 20)) {
811
                /* load */
812
                if (insn & (1 << 22))
813
                    gen_op_ldub_T0_T1();
814
                else
815
                    gen_op_ldl_T0_T1();
816
                if (rd == 15)
817
                    gen_bx(s);
818
                else
819
                    gen_movl_reg_T0(s, rd);
820
            } else {
821
                /* store */
822
                gen_movl_T0_reg(s, rd);
823
                if (insn & (1 << 22))
824
                    gen_op_stb_T0_T1();
825
                else
826
                    gen_op_stl_T0_T1();
827
            }
828
            if (!(insn & (1 << 24))) {
829
                gen_add_data_offset(s, insn);
830
                gen_movl_reg_T1(s, rn);
831
            } else if (insn & (1 << 21))
832
                gen_movl_reg_T1(s, rn); {
833
            }
834
            break;
835
        case 0x08:
836
        case 0x09:
837
            {
838
                int j, n;
839
                /* load/store multiple words */
840
                /* XXX: store correct base if write back */
841
                if (insn & (1 << 22))
842
                    goto illegal_op; /* only usable in supervisor mode */
843
                rn = (insn >> 16) & 0xf;
844
                gen_movl_T1_reg(s, rn);
845
                
846
                /* compute total size */
847
                n = 0;
848
                for(i=0;i<16;i++) {
849
                    if (insn & (1 << i))
850
                        n++;
851
                }
852
                /* XXX: test invalid n == 0 case ? */
853
                if (insn & (1 << 23)) {
854
                    if (insn & (1 << 24)) {
855
                        /* pre increment */
856
                        gen_op_addl_T1_im(4);
857
                    } else {
858
                        /* post increment */
859
                    }
860
                } else {
861
                    if (insn & (1 << 24)) {
862
                        /* pre decrement */
863
                        gen_op_addl_T1_im(-(n * 4));
864
                    } else {
865
                        /* post decrement */
866
                        if (n != 1)
867
                            gen_op_addl_T1_im(-((n - 1) * 4));
868
                    }
869
                }
870
                j = 0;
871
                for(i=0;i<16;i++) {
872
                    if (insn & (1 << i)) {
873
                        if (insn & (1 << 20)) {
874
                            /* load */
875
                            gen_op_ldl_T0_T1();
876
                            if (i == 15)
877
                                gen_bx(s);
878
                            else
879
                                gen_movl_reg_T0(s, i);
880
                        } else {
881
                            /* store */
882
                            if (i == 15) {
883
                                /* special case: r15 = PC + 12 */
884
                                val = (long)s->pc + 8;
885
                                gen_op_movl_TN_im[0](val);
886
                            } else {
887
                                gen_movl_T0_reg(s, i);
888
                            }
889
                            gen_op_stl_T0_T1();
890
                        }
891
                        j++;
892
                        /* no need to add after the last transfer */
893
                        if (j != n)
894
                            gen_op_addl_T1_im(4);
895
                    }
896
                }
897
                if (insn & (1 << 21)) {
898
                    /* write back */
899
                    if (insn & (1 << 23)) {
900
                        if (insn & (1 << 24)) {
901
                            /* pre increment */
902
                        } else {
903
                            /* post increment */
904
                            gen_op_addl_T1_im(4);
905
                        }
906
                    } else {
907
                        if (insn & (1 << 24)) {
908
                            /* pre decrement */
909
                            if (n != 1)
910
                                gen_op_addl_T1_im(-((n - 1) * 4));
911
                        } else {
912
                            /* post decrement */
913
                            gen_op_addl_T1_im(-(n * 4));
914
                        }
915
                    }
916
                    gen_movl_reg_T1(s, rn);
917
                }
918
            }
919
            break;
920
        case 0xa:
921
        case 0xb:
922
            {
923
                int32_t offset;
924
                
925
                /* branch (and link) */
926
                val = (int32_t)s->pc;
927
                if (insn & (1 << 24)) {
928
                    gen_op_movl_T0_im(val);
929
                    gen_op_movl_reg_TN[0][14]();
930
                }
931
                offset = (((int32_t)insn << 8) >> 8);
932
                val += (offset << 2) + 4;
933
                gen_op_jmp((long)s->tb, val);
934
                s->is_jmp = DISAS_TB_JUMP;
935
            }
936
            break;
937
        case 0xf:
938
            /* swi */
939
            gen_op_movl_T0_im((long)s->pc);
940
            gen_op_movl_reg_TN[0][15]();
941
            gen_op_swi();
942
            s->is_jmp = DISAS_JUMP;
943
            break;
944
        default:
945
        illegal_op:
946
            gen_op_movl_T0_im((long)s->pc - 4);
947
            gen_op_movl_reg_TN[0][15]();
948
            gen_op_undef_insn();
949
            s->is_jmp = DISAS_JUMP;
950
            break;
951
        }
952
    }
953
}
954

    
955
static void disas_thumb_insn(DisasContext *s)
956
{
957
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
958
    int32_t offset;
959
    int i;
960

    
961
    insn = lduw(s->pc);
962
    s->pc += 2;
963
    
964
    switch (insn >> 12) {
965
    case 0: case 1:
966
        rd = insn & 7;
967
        op = (insn >> 11) & 3;
968
        if (op == 3) {
969
            /* add/subtract */
970
            rn = (insn >> 3) & 7;
971
            gen_movl_T0_reg(s, rn);
972
            if (insn & (1 << 10)) {
973
                /* immediate */
974
                gen_op_movl_T1_im((insn >> 6) & 7);
975
            } else {
976
                /* reg */
977
                rm = (insn >> 6) & 7;
978
                gen_movl_T1_reg(s, rm);
979
            }
980
            if (insn & (1 << 9))
981
                gen_op_addl_T0_T1_cc();
982
            else
983
                gen_op_addl_T0_T1_cc();
984
            gen_movl_reg_T0(s, rd);
985
        } else {
986
            /* shift immediate */
987
            rm = (insn >> 3) & 7;
988
            shift = (insn >> 6) & 0x1f;
989
            gen_movl_T0_reg(s, rm);
990
            gen_shift_T0_im_thumb[op](shift);
991
            gen_movl_reg_T0(s, rd);
992
        }
993
        break;
994
    case 2: case 3:
995
        /* arithmetic large immediate */
996
        op = (insn >> 11) & 3;
997
        rd = (insn >> 8) & 0x7;
998
        if (op == 0) {
999
            gen_op_movl_T0_im(insn & 0xff);
1000
        } else {
1001
            gen_movl_T0_reg(s, rd);
1002
            gen_op_movl_T1_im(insn & 0xff);
1003
        }
1004
        switch (op) {
1005
        case 0: /* mov */
1006
            gen_op_logic_T0_cc();
1007
            break;
1008
        case 1: /* cmp */
1009
            gen_op_subl_T0_T1_cc();
1010
            break;
1011
        case 2: /* add */
1012
            gen_op_addl_T0_T1_cc();
1013
            break;
1014
        case 3: /* sub */
1015
            gen_op_subl_T0_T1_cc();
1016
            break;
1017
        }
1018
        if (op != 1)
1019
            gen_movl_reg_T0(s, rd);
1020
        break;
1021
    case 4:
1022
        if (insn & (1 << 11)) {
1023
            rd = (insn >> 8) & 7;
1024
            /* load pc-relative */
1025
            val = (insn & 0xff) * 4;
1026
            gen_op_movl_T1_im(val);
1027
            gen_movl_T2_reg(s, 15);
1028
            gen_op_addl_T1_T2();
1029
            gen_op_ldl_T0_T1();
1030
            gen_movl_reg_T0(s, rd);
1031
            break;
1032
        }
1033
        if (insn & (1 << 10)) {
1034
            /* data processing extended or blx */
1035
            rd = (insn & 7) | ((insn >> 4) & 8);
1036
            rm = (insn >> 3) & 0xf;
1037
            op = (insn >> 8) & 3;
1038
            switch (op) {
1039
            case 0: /* add */
1040
                gen_movl_T0_reg(s, rd);
1041
                gen_movl_T1_reg(s, rm);
1042
                gen_op_addl_T0_T1();
1043
                gen_movl_reg_T0(s, rd);
1044
                break;
1045
            case 1: /* cmp */
1046
                gen_movl_T0_reg(s, rd);
1047
                gen_movl_T1_reg(s, rm);
1048
                gen_op_subl_T0_T1_cc();
1049
                break;
1050
            case 2: /* mov/cpy */
1051
                gen_movl_T0_reg(s, rm);
1052
                gen_movl_reg_T0(s, rd);
1053
                break;
1054
            case 3:/* branch [and link] exchange thumb register */
1055
                if (insn & (1 << 7)) {
1056
                    val = (uint32_t)s->pc | 1;
1057
                    gen_op_movl_T1_im(val);
1058
                    gen_movl_reg_T1(s, 14);
1059
                }
1060
                gen_movl_T0_reg(s, rm);
1061
                gen_bx(s);
1062
                break;
1063
            }
1064
            break;
1065
        }
1066

    
1067
        /* data processing register */
1068
        rd = insn & 7;
1069
        rm = (insn >> 3) & 7;
1070
        op = (insn >> 6) & 0xf;
1071
        if (op == 2 || op == 3 || op == 4 || op == 7) {
1072
            /* the shift/rotate ops want the operands backwards */
1073
            val = rm;
1074
            rm = rd;
1075
            rd = val;
1076
            val = 1;
1077
        } else {
1078
            val = 0;
1079
        }
1080

    
1081
        if (op == 9) /* neg */
1082
            gen_op_movl_T0_im(0);
1083
        else if (op != 0xf) /* mvn doesn't read its first operand */
1084
            gen_movl_T0_reg(s, rd);
1085

    
1086
        gen_movl_T1_reg(s, rm);
1087
        switch (insn >> 6) {
1088
        case 0x0: /* and */
1089
            gen_op_andl_T0_T1();
1090
            gen_op_logic_T0_cc();
1091
            break;
1092
        case 0x1: /* eor */
1093
            gen_op_xorl_T0_T1();
1094
            gen_op_logic_T0_cc();
1095
            break;
1096
        case 0x2: /* lsl */
1097
            gen_op_shll_T1_T0_cc();
1098
            break;
1099
        case 0x3: /* lsr */
1100
            gen_op_shrl_T1_T0_cc();
1101
            break;
1102
        case 0x4: /* asr */
1103
            gen_op_sarl_T1_T0_cc();
1104
            break;
1105
        case 0x5: /* adc */
1106
            gen_op_adcl_T0_T1_cc();
1107
            break;
1108
        case 0x6: /* sbc */
1109
            gen_op_sbcl_T0_T1_cc();
1110
            break;
1111
        case 0x7: /* ror */
1112
            gen_op_rorl_T1_T0_cc();
1113
            break;
1114
        case 0x8: /* tst */
1115
            gen_op_andl_T0_T1();
1116
            gen_op_logic_T0_cc();
1117
            rd = 16;
1118
        case 0x9: /* neg */
1119
            gen_op_rsbl_T0_T1_cc();
1120
            break;
1121
        case 0xa: /* cmp */
1122
            gen_op_subl_T0_T1_cc();
1123
            rd = 16;
1124
            break;
1125
        case 0xb: /* cmn */
1126
            gen_op_addl_T0_T1_cc();
1127
            rd = 16;
1128
            break;
1129
        case 0xc: /* orr */
1130
            gen_op_orl_T0_T1();
1131
            gen_op_logic_T0_cc();
1132
            break;
1133
        case 0xd: /* mul */
1134
            gen_op_mull_T0_T1();
1135
            gen_op_logic_T0_cc();
1136
            break;
1137
        case 0xe: /* bic */
1138
            gen_op_bicl_T0_T1();
1139
            gen_op_logic_T0_cc();
1140
            break;
1141
        case 0xf: /* mvn */
1142
            gen_op_notl_T1();
1143
            gen_op_logic_T1_cc();
1144
            val = 1;
1145
            break;
1146
        }
1147
        if (rd != 16) {
1148
            if (val)
1149
                gen_movl_reg_T1(s, rd);
1150
            else
1151
                gen_movl_reg_T0(s, rd);
1152
        }
1153
        break;
1154

    
1155
    case 5:
1156
        /* load/store register offset.  */
1157
        rd = insn & 7;
1158
        rn = (insn >> 3) & 7;
1159
        rm = (insn >> 6) & 7;
1160
        op = (insn >> 9) & 7;
1161
        gen_movl_T1_reg(s, rn);
1162
        gen_movl_T2_reg(s, rm);
1163
        gen_op_addl_T1_T2();
1164

    
1165
        if (op < 3) /* store */
1166
            gen_movl_T0_reg(s, rd);
1167

    
1168
        switch (op) {
1169
        case 0: /* str */
1170
            gen_op_stl_T0_T1();
1171
            break;
1172
        case 1: /* strh */
1173
            gen_op_stw_T0_T1();
1174
            break;
1175
        case 2: /* strb */
1176
            gen_op_stb_T0_T1();
1177
            break;
1178
        case 3: /* ldrsb */
1179
            gen_op_ldsb_T0_T1();
1180
            break;
1181
        case 4: /* ldr */
1182
            gen_op_ldl_T0_T1();
1183
            break;
1184
        case 5: /* ldrh */
1185
            gen_op_ldsw_T0_T1();
1186
            break;
1187
        case 6: /* ldrb */
1188
            gen_op_ldub_T0_T1();
1189
            break;
1190
        case 7: /* ldrsh */
1191
            gen_op_ldsw_T0_T1();
1192
            break;
1193
        }
1194
        if (op >= 3) /* load */
1195
            gen_movl_reg_T0(s, rd);
1196
        break;
1197

    
1198
    case 6:
1199
        /* load/store word immediate offset */
1200
        rd = insn & 7;
1201
        rn = (insn >> 3) & 7;
1202
        gen_movl_T1_reg(s, rn);
1203
        val = (insn >> 4) & 0x7c;
1204
        gen_op_movl_T2_im(val);
1205
        gen_op_addl_T1_T2();
1206

    
1207
        if (insn & (1 << 11)) {
1208
            /* load */
1209
            gen_op_ldl_T0_T1();
1210
            gen_movl_reg_T0(s, rd);
1211
        } else {
1212
            /* store */
1213
            gen_movl_T0_reg(s, rd);
1214
            gen_op_stl_T0_T1();
1215
        }
1216
        break;
1217

    
1218
    case 7:
1219
        /* load/store byte immediate offset */
1220
        rd = insn & 7;
1221
        rn = (insn >> 3) & 7;
1222
        gen_movl_T1_reg(s, rn);
1223
        val = (insn >> 6) & 0x1f;
1224
        gen_op_movl_T2_im(val);
1225
        gen_op_addl_T1_T2();
1226

    
1227
        if (insn & (1 << 11)) {
1228
            /* load */
1229
            gen_op_ldub_T0_T1();
1230
            gen_movl_reg_T0(s, rd);
1231
        } else {
1232
            /* store */
1233
            gen_movl_T0_reg(s, rd);
1234
            gen_op_stb_T0_T1();
1235
        }
1236
        break;
1237

    
1238
    case 8:
1239
        /* load/store halfword immediate offset */
1240
        rd = insn & 7;
1241
        rn = (insn >> 3) & 7;
1242
        gen_movl_T1_reg(s, rn);
1243
        val = (insn >> 5) & 0x3e;
1244
        gen_op_movl_T2_im(val);
1245
        gen_op_addl_T1_T2();
1246

    
1247
        if (insn & (1 << 11)) {
1248
            /* load */
1249
            gen_op_lduw_T0_T1();
1250
            gen_movl_reg_T0(s, rd);
1251
        } else {
1252
            /* store */
1253
            gen_movl_T0_reg(s, rd);
1254
            gen_op_stw_T0_T1();
1255
        }
1256
        break;
1257

    
1258
    case 9:
1259
        /* load/store from stack */
1260
        rd = (insn >> 8) & 7;
1261
        gen_movl_T1_reg(s, 13);
1262
        val = (insn & 0xff) * 4;
1263
        gen_op_movl_T2_im(val);
1264
        gen_op_addl_T1_T2();
1265

    
1266
        if (insn & (1 << 11)) {
1267
            /* load */
1268
            gen_op_ldl_T0_T1();
1269
            gen_movl_reg_T0(s, rd);
1270
        } else {
1271
            /* store */
1272
            gen_movl_T0_reg(s, rd);
1273
            gen_op_stl_T0_T1();
1274
        }
1275
        break;
1276

    
1277
    case 10:
1278
        /* add to high reg */
1279
        rd = (insn >> 8) & 7;
1280
        if (insn & (1 << 11))
1281
            rm = 13; /* sp */
1282
        else
1283
            rm = 15; /* pc */
1284
        gen_movl_T0_reg(s, rm);
1285
        val = (insn & 0xff) * 4;
1286
        gen_op_movl_T1_im(val);
1287
        gen_op_addl_T0_T1();
1288
        gen_movl_reg_T0(s, rd);
1289
        break;
1290

    
1291
    case 11:
1292
        /* misc */
1293
        op = (insn >> 8) & 0xf;
1294
        switch (op) {
1295
        case 0:
1296
            /* adjust stack pointer */
1297
            gen_movl_T1_reg(s, 13);
1298
            val = (insn & 0x7f) * 4;
1299
            if (insn & (1 << 7))
1300
              val = -(int32_t)val;
1301
            gen_op_movl_T2_im(val);
1302
            gen_op_addl_T1_T2();
1303
            gen_movl_reg_T1(s, 13);
1304
            break;
1305

    
1306
        case 4: case 5: case 0xc: case 0xd:
1307
            /* push/pop */
1308
            gen_movl_T1_reg(s, 13);
1309
            if (insn & (1 << 11))
1310
                val = 4;
1311
            else
1312
                val = -4;
1313
            gen_op_movl_T2_im(val);
1314
            for (i = 0; i < 8; i++) {
1315
                if (insn & (1 << i)) {
1316
                    if (insn & (1 << 11)) {
1317
                        /* pop */
1318
                        gen_op_ldl_T0_T1();
1319
                        gen_movl_reg_T0(s, i);
1320
                    } else {
1321
                        /* push */
1322
                        gen_movl_T0_reg(s, i);
1323
                        gen_op_stl_T0_T1();
1324
                    }
1325
                    /* move to the next address */
1326
                    gen_op_addl_T1_T2();
1327
                }
1328
            }
1329
            if (insn & (1 << 8)) {
1330
                if (insn & (1 << 11)) {
1331
                    /* pop pc */
1332
                    gen_op_ldl_T0_T1();
1333
                    /* don't set the pc until the rest of the instruction
1334
                       has completed */
1335
                } else {
1336
                    /* push lr */
1337
                    gen_movl_T0_reg(s, 14);
1338
                    gen_op_stl_T0_T1();
1339
                }
1340
                gen_op_addl_T1_T2();
1341
            }
1342

    
1343
            /* write back the new stack pointer */
1344
            gen_movl_reg_T1(s, 13);
1345
            /* set the new PC value */
1346
            if ((insn & 0x0900) == 0x0900)
1347
                gen_bx(s);
1348
            break;
1349

    
1350
        default:
1351
            goto undef;
1352
        }
1353
        break;
1354

    
1355
    case 12:
1356
        /* load/store multiple */
1357
        rn = (insn >> 8) & 0x7;
1358
        gen_movl_T1_reg(s, rn);
1359
        gen_op_movl_T2_im(4);
1360
        val = 0;
1361
        for (i = 0; i < 8; i++) {
1362
            if (insn & (1 << i)) {
1363
                /* advance to the next address */
1364
                if (val)
1365
                    gen_op_addl_T1_T2();
1366
                else
1367
                    val = 1;
1368
                if (insn & (1 << 11)) {
1369
                    /* load */
1370
                    gen_op_ldl_T0_T1();
1371
                    gen_movl_reg_T0(s, i);
1372
                } else {
1373
                    /* store */
1374
                    gen_movl_T0_reg(s, i);
1375
                    gen_op_stl_T0_T1();
1376
                }
1377
            }
1378
        }
1379
        break;
1380

    
1381
    case 13:
1382
        /* conditional branch or swi */
1383
        cond = (insn >> 8) & 0xf;
1384
        if (cond == 0xe)
1385
            goto undef;
1386

    
1387
        if (cond == 0xf) {
1388
            /* swi */
1389
            gen_op_movl_T0_im((long)s->pc | 1);
1390
            /* Don't set r15.  */
1391
            gen_op_movl_reg_TN[0][15]();
1392
            gen_op_swi();
1393
            s->is_jmp = DISAS_JUMP;
1394
            break;
1395
        }
1396
        /* generate a conditional jump to next instruction */
1397
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1398
        s->is_jmp = DISAS_JUMP_NEXT;
1399
        gen_movl_T1_reg(s, 15);
1400

    
1401
        /* jump to the offset */
1402
        val = (uint32_t)s->pc;
1403
        offset = ((int32_t)insn << 24) >> 24;
1404
        val += (offset << 1) + 2;
1405
        gen_op_jmp((long)s->tb, val);
1406
        s->is_jmp = DISAS_TB_JUMP;
1407
        break;
1408

    
1409
    case 14:
1410
        /* unconditional branch */
1411
        if (insn & (1 << 11))
1412
            goto undef; /* Second half of a blx */
1413
        val = (uint32_t)s->pc;
1414
        offset = ((int32_t)insn << 21) >> 21;
1415
        val += (offset << 1) + 2;
1416
        gen_op_jmp((long)s->tb, val);
1417
        s->is_jmp = DISAS_TB_JUMP;
1418
        break;
1419

    
1420
    case 15:
1421
        /* branch and link [and switch to arm] */
1422
        offset = ((int32_t)insn << 21) >> 10;
1423
        insn = lduw(s->pc);
1424
        offset |= insn & 0x7ff;
1425

    
1426
        val = (uint32_t)s->pc + 2;
1427
        gen_op_movl_T1_im(val | 1);
1428
        gen_movl_reg_T1(s, 14);
1429
        
1430
        val += offset;
1431
        if (insn & (1 << 11)) {
1432
            /* bl */
1433
            gen_op_jmp((long)s->tb, val);
1434
            s->is_jmp = DISAS_TB_JUMP;
1435
        } else {
1436
            /* blx */
1437
            gen_op_movl_T0_im(val);
1438
            gen_bx(s);
1439
        }
1440
    }
1441
    return;
1442
undef:
1443
    gen_op_movl_T0_im((long)s->pc - 4);
1444
    gen_op_movl_reg_TN[0][15]();
1445
    gen_op_undef_insn();
1446
    s->is_jmp = DISAS_JUMP;
1447
}
1448

    
1449
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
1450
   basic block 'tb'. If search_pc is TRUE, also generate PC
1451
   information for each intermediate instruction. */
1452
static inline int gen_intermediate_code_internal(CPUState *env, 
1453
                                                 TranslationBlock *tb, 
1454
                                                 int search_pc)
1455
{
1456
    DisasContext dc1, *dc = &dc1;
1457
    uint16_t *gen_opc_end;
1458
    int j, lj;
1459
    target_ulong pc_start;
1460
    
1461
    /* generate intermediate code */
1462
    pc_start = tb->pc;
1463
       
1464
    dc->tb = tb;
1465

    
1466
    gen_opc_ptr = gen_opc_buf;
1467
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1468
    gen_opparam_ptr = gen_opparam_buf;
1469

    
1470
    dc->is_jmp = DISAS_NEXT;
1471
    dc->pc = pc_start;
1472
    lj = -1;
1473
    do {
1474
        if (search_pc) {
1475
            j = gen_opc_ptr - gen_opc_buf;
1476
            if (lj < j) {
1477
                lj++;
1478
                while (lj < j)
1479
                    gen_opc_instr_start[lj++] = 0;
1480
            }
1481
            gen_opc_pc[lj] = dc->pc;
1482
            gen_opc_instr_start[lj] = 1;
1483
        }
1484
        if (env->thumb)
1485
          disas_thumb_insn(dc);
1486
        else
1487
          disas_arm_insn(dc);
1488
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
1489
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
1490
    switch(dc->is_jmp) {
1491
    case DISAS_JUMP_NEXT:
1492
    case DISAS_NEXT:
1493
        gen_op_jmp((long)dc->tb, (long)dc->pc);
1494
        break;
1495
    default:
1496
    case DISAS_JUMP:
1497
    case DISAS_UPDATE:
1498
        /* indicate that the hash table must be used to find the next TB */
1499
        gen_op_movl_T0_0();
1500
        gen_op_exit_tb();
1501
        break;
1502
    case DISAS_TB_JUMP:
1503
        /* nothing more to generate */
1504
        break;
1505
    }
1506
    *gen_opc_ptr = INDEX_op_end;
1507

    
1508
#ifdef DEBUG_DISAS
1509
    if (loglevel & CPU_LOG_TB_IN_ASM) {
1510
        fprintf(logfile, "----------------\n");
1511
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1512
        target_disas(logfile, pc_start, dc->pc - pc_start, 0);
1513
        fprintf(logfile, "\n");
1514
        if (loglevel & (CPU_LOG_TB_OP)) {
1515
            fprintf(logfile, "OP:\n");
1516
            dump_ops(gen_opc_buf, gen_opparam_buf);
1517
            fprintf(logfile, "\n");
1518
        }
1519
    }
1520
#endif
1521
    if (!search_pc)
1522
        tb->size = dc->pc - pc_start;
1523
    return 0;
1524
}
1525

    
1526
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
1527
{
1528
    return gen_intermediate_code_internal(env, tb, 0);
1529
}
1530

    
1531
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
1532
{
1533
    return gen_intermediate_code_internal(env, tb, 1);
1534
}
1535

    
1536
CPUARMState *cpu_arm_init(void)
1537
{
1538
    CPUARMState *env;
1539

    
1540
    cpu_exec_init();
1541

    
1542
    env = malloc(sizeof(CPUARMState));
1543
    if (!env)
1544
        return NULL;
1545
    memset(env, 0, sizeof(CPUARMState));
1546
    cpu_single_env = env;
1547
    return env;
1548
}
1549

    
1550
void cpu_arm_close(CPUARMState *env)
1551
{
1552
    free(env);
1553
}
1554

    
1555
void cpu_dump_state(CPUState *env, FILE *f, 
1556
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1557
                    int flags)
1558
{
1559
    int i;
1560

    
1561
    for(i=0;i<16;i++) {
1562
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
1563
        if ((i % 4) == 3)
1564
            cpu_fprintf(f, "\n");
1565
        else
1566
            cpu_fprintf(f, " ");
1567
    }
1568
    cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 
1569
            env->cpsr, 
1570
            env->cpsr & (1 << 31) ? 'N' : '-',
1571
            env->cpsr & (1 << 30) ? 'Z' : '-',
1572
            env->cpsr & (1 << 29) ? 'C' : '-',
1573
            env->cpsr & (1 << 28) ? 'V' : '-');
1574
}
1575

    
1576
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1577
{
1578
    return addr;
1579
}
1580

    
1581
#if defined(CONFIG_USER_ONLY) 
1582

    
1583
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1584
                              int is_user, int is_softmmu)
1585
{
1586
    env->cp15_6 = address;
1587
    if (rw == 2) {
1588
        env->exception_index = EXCP_PREFETCH_ABORT;
1589
    } else {
1590
        env->exception_index = EXCP_DATA_ABORT;
1591
    }
1592
    return 1;
1593
}
1594

    
1595
#else
1596

    
1597
#error not implemented
1598

    
1599
#endif