Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 0fa85d43

History | View | Annotate | Download (24.3 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 inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
249
{
250
    int val;
251

    
252
    if (reg == 15) {
253
        /* normaly, since we updated PC, we need only to add 4 */
254
        val = (long)s->pc + 4;
255
        gen_op_movl_TN_im[t](val);
256
    } else {
257
        gen_op_movl_TN_reg[t][reg]();
258
    }
259
}
260

    
261
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
262
{
263
    gen_movl_TN_reg(s, reg, 0);
264
}
265

    
266
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
267
{
268
    gen_movl_TN_reg(s, reg, 1);
269
}
270

    
271
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
272
{
273
    gen_movl_TN_reg(s, reg, 2);
274
}
275

    
276
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
277
{
278
    gen_op_movl_reg_TN[t][reg]();
279
    if (reg == 15) {
280
        s->is_jmp = DISAS_JUMP;
281
    }
282
}
283

    
284
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
285
{
286
    gen_movl_reg_TN(s, reg, 0);
287
}
288

    
289
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
290
{
291
    gen_movl_reg_TN(s, reg, 1);
292
}
293

    
294
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
295
{
296
    int val, rm, shift, shiftop;
297

    
298
    if (!(insn & (1 << 25))) {
299
        /* immediate */
300
        val = insn & 0xfff;
301
        if (!(insn & (1 << 23)))
302
            val = -val;
303
        if (val != 0)
304
            gen_op_addl_T1_im(val);
305
    } else {
306
        /* shift/register */
307
        rm = (insn) & 0xf;
308
        shift = (insn >> 7) & 0x1f;
309
        gen_movl_T2_reg(s, rm);
310
        shiftop = (insn >> 5) & 3;
311
        if (shift != 0) {
312
            gen_shift_T2_im[shiftop](shift);
313
        } else if (shiftop != 0) {
314
            gen_shift_T2_0[shiftop]();
315
        }
316
        if (!(insn & (1 << 23)))
317
            gen_op_subl_T1_T2();
318
        else
319
            gen_op_addl_T1_T2();
320
    }
321
}
322

    
323
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
324
{
325
    int val, rm;
326
    
327
    if (insn & (1 << 22)) {
328
        /* immediate */
329
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
330
        if (!(insn & (1 << 23)))
331
            val = -val;
332
        if (val != 0)
333
            gen_op_addl_T1_im(val);
334
    } else {
335
        /* register */
336
        rm = (insn) & 0xf;
337
        gen_movl_T2_reg(s, rm);
338
        if (!(insn & (1 << 23)))
339
            gen_op_subl_T1_T2();
340
        else
341
            gen_op_addl_T1_T2();
342
    }
343
}
344

    
345
static void disas_arm_insn(DisasContext *s)
346
{
347
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
348
    
349
    insn = ldl(s->pc);
350
    s->pc += 4;
351
    
352
    cond = insn >> 28;
353
    if (cond == 0xf)
354
        goto illegal_op;
355
    if (cond != 0xe) {
356
        /* if not always execute, we generate a conditional jump to
357
           next instruction */
358
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
359
        s->is_jmp = DISAS_JUMP_NEXT;
360
    }
361
    if (((insn & 0x0e000000) == 0 &&
362
         (insn & 0x00000090) != 0x90) ||
363
        ((insn & 0x0e000000) == (1 << 25))) {
364
        int set_cc, logic_cc, shiftop;
365
        
366
        op1 = (insn >> 21) & 0xf;
367
        set_cc = (insn >> 20) & 1;
368
        logic_cc = table_logic_cc[op1] & set_cc;
369

    
370
        /* data processing instruction */
371
        if (insn & (1 << 25)) {
372
            /* immediate operand */
373
            val = insn & 0xff;
374
            shift = ((insn >> 8) & 0xf) * 2;
375
            if (shift)
376
                val = (val >> shift) | (val << (32 - shift));
377
            gen_op_movl_T1_im(val);
378
            /* XXX: is CF modified ? */
379
        } else {
380
            /* register */
381
            rm = (insn) & 0xf;
382
            gen_movl_T1_reg(s, rm);
383
            shiftop = (insn >> 5) & 3;
384
            if (!(insn & (1 << 4))) {
385
                shift = (insn >> 7) & 0x1f;
386
                if (shift != 0) {
387
                    if (logic_cc) {
388
                        gen_shift_T1_im_cc[shiftop](shift);
389
                    } else {
390
                        gen_shift_T1_im[shiftop](shift);
391
                    }
392
                } else if (shiftop != 0) {
393
                    if (logic_cc) {
394
                        gen_shift_T1_0_cc[shiftop]();
395
                    } else {
396
                        gen_shift_T1_0[shiftop]();
397
                    }
398
                }
399
            } else {
400
                rs = (insn >> 8) & 0xf;
401
                gen_movl_T0_reg(s, rs);
402
                if (logic_cc) {
403
                    gen_shift_T1_T0_cc[shiftop]();
404
                } else {
405
                    gen_shift_T1_T0[shiftop]();
406
                }
407
            }
408
        }
409
        if (op1 != 0x0f && op1 != 0x0d) {
410
            rn = (insn >> 16) & 0xf;
411
            gen_movl_T0_reg(s, rn);
412
        }
413
        rd = (insn >> 12) & 0xf;
414
        switch(op1) {
415
        case 0x00:
416
            gen_op_andl_T0_T1();
417
            gen_movl_reg_T0(s, rd);
418
            if (logic_cc)
419
                gen_op_logic_T0_cc();
420
            break;
421
        case 0x01:
422
            gen_op_xorl_T0_T1();
423
            gen_movl_reg_T0(s, rd);
424
            if (logic_cc)
425
                gen_op_logic_T0_cc();
426
            break;
427
        case 0x02:
428
            if (set_cc)
429
                gen_op_subl_T0_T1_cc();
430
            else
431
                gen_op_subl_T0_T1();
432
            gen_movl_reg_T0(s, rd);
433
            break;
434
        case 0x03:
435
            if (set_cc)
436
                gen_op_rsbl_T0_T1_cc();
437
            else
438
                gen_op_rsbl_T0_T1();
439
            gen_movl_reg_T0(s, rd);
440
            break;
441
        case 0x04:
442
            if (set_cc)
443
                gen_op_addl_T0_T1_cc();
444
            else
445
                gen_op_addl_T0_T1();
446
            gen_movl_reg_T0(s, rd);
447
            break;
448
        case 0x05:
449
            if (set_cc)
450
                gen_op_adcl_T0_T1_cc();
451
            else
452
                gen_op_adcl_T0_T1();
453
            gen_movl_reg_T0(s, rd);
454
            break;
455
        case 0x06:
456
            if (set_cc)
457
                gen_op_sbcl_T0_T1_cc();
458
            else
459
                gen_op_sbcl_T0_T1();
460
            gen_movl_reg_T0(s, rd);
461
            break;
462
        case 0x07:
463
            if (set_cc)
464
                gen_op_rscl_T0_T1_cc();
465
            else
466
                gen_op_rscl_T0_T1();
467
            gen_movl_reg_T0(s, rd);
468
            break;
469
        case 0x08:
470
            if (set_cc) {
471
                gen_op_andl_T0_T1();
472
                gen_op_logic_T0_cc();
473
            }
474
            break;
475
        case 0x09:
476
            if (set_cc) {
477
                gen_op_xorl_T0_T1();
478
                gen_op_logic_T0_cc();
479
            }
480
            break;
481
        case 0x0a:
482
            if (set_cc) {
483
                gen_op_subl_T0_T1_cc();
484
            }
485
            break;
486
        case 0x0b:
487
            if (set_cc) {
488
                gen_op_addl_T0_T1_cc();
489
            }
490
            break;
491
        case 0x0c:
492
            gen_op_orl_T0_T1();
493
            gen_movl_reg_T0(s, rd);
494
            if (logic_cc)
495
                gen_op_logic_T0_cc();
496
            break;
497
        case 0x0d:
498
            gen_movl_reg_T1(s, rd);
499
            if (logic_cc)
500
                gen_op_logic_T1_cc();
501
            break;
502
        case 0x0e:
503
            gen_op_bicl_T0_T1();
504
            gen_movl_reg_T0(s, rd);
505
            if (logic_cc)
506
                gen_op_logic_T0_cc();
507
            break;
508
        default:
509
        case 0x0f:
510
            gen_op_notl_T1();
511
            gen_movl_reg_T1(s, rd);
512
            if (logic_cc)
513
                gen_op_logic_T1_cc();
514
            break;
515
        }
516
    } else {
517
        /* other instructions */
518
        op1 = (insn >> 24) & 0xf;
519
        switch(op1) {
520
        case 0x0:
521
        case 0x1:
522
            sh = (insn >> 5) & 3;
523
            if (sh == 0) {
524
                if (op1 == 0x0) {
525
                    rd = (insn >> 16) & 0xf;
526
                    rn = (insn >> 12) & 0xf;
527
                    rs = (insn >> 8) & 0xf;
528
                    rm = (insn) & 0xf;
529
                    if (!(insn & (1 << 23))) {
530
                        /* 32 bit mul */
531
                        gen_movl_T0_reg(s, rs);
532
                        gen_movl_T1_reg(s, rm);
533
                        gen_op_mul_T0_T1();
534
                        if (insn & (1 << 21)) {
535
                            gen_movl_T1_reg(s, rn);
536
                            gen_op_addl_T0_T1();
537
                        }
538
                        if (insn & (1 << 20)) 
539
                            gen_op_logic_T0_cc();
540
                        gen_movl_reg_T0(s, rd);
541
                    } else {
542
                        /* 64 bit mul */
543
                        gen_movl_T0_reg(s, rs);
544
                        gen_movl_T1_reg(s, rm);
545
                        if (insn & (1 << 22)) 
546
                            gen_op_imull_T0_T1();
547
                        else
548
                            gen_op_mull_T0_T1();
549
                        if (insn & (1 << 21)) 
550
                            gen_op_addq_T0_T1(rn, rd);
551
                        if (insn & (1 << 20)) 
552
                            gen_op_logicq_cc();
553
                        gen_movl_reg_T0(s, rn);
554
                        gen_movl_reg_T1(s, rd);
555
                    }
556
                } else {
557
                    /* SWP instruction */
558
                    rn = (insn >> 16) & 0xf;
559
                    rd = (insn >> 12) & 0xf;
560
                    rm = (insn) & 0xf;
561
                    
562
                    gen_movl_T0_reg(s, rm);
563
                    gen_movl_T1_reg(s, rn);
564
                    if (insn & (1 << 22)) {
565
                        gen_op_swpb_T0_T1();
566
                    } else {
567
                        gen_op_swpl_T0_T1();
568
                    }
569
                    gen_movl_reg_T0(s, rd);
570
                }
571
            } else {
572
                /* load/store half word */
573
                rn = (insn >> 16) & 0xf;
574
                rd = (insn >> 12) & 0xf;
575
                gen_movl_T1_reg(s, rn);
576
                if (insn & (1 << 24))
577
                    gen_add_datah_offset(s, insn);
578
                if (insn & (1 << 20)) {
579
                    /* load */
580
                    switch(sh) {
581
                    case 1:
582
                        gen_op_lduw_T0_T1();
583
                        break;
584
                    case 2:
585
                        gen_op_ldsb_T0_T1();
586
                        break;
587
                    default:
588
                    case 3:
589
                        gen_op_ldsw_T0_T1();
590
                        break;
591
                    }
592
                    gen_movl_reg_T0(s, rd);
593
                } else {
594
                    /* store */
595
                    gen_movl_T0_reg(s, rd);
596
                    gen_op_stw_T0_T1();
597
                }
598
                if (!(insn & (1 << 24))) {
599
                    gen_add_datah_offset(s, insn);
600
                    gen_movl_reg_T1(s, rn);
601
                } else if (insn & (1 << 21)) {
602
                    gen_movl_reg_T1(s, rn);
603
                }
604
            }
605
            break;
606
        case 0x4:
607
        case 0x5:
608
        case 0x6:
609
        case 0x7:
610
            /* load/store byte/word */
611
            rn = (insn >> 16) & 0xf;
612
            rd = (insn >> 12) & 0xf;
613
            gen_movl_T1_reg(s, rn);
614
            if (insn & (1 << 24))
615
                gen_add_data_offset(s, insn);
616
            if (insn & (1 << 20)) {
617
                /* load */
618
                if (insn & (1 << 22))
619
                    gen_op_ldub_T0_T1();
620
                else
621
                    gen_op_ldl_T0_T1();
622
                gen_movl_reg_T0(s, rd);
623
            } else {
624
                /* store */
625
                gen_movl_T0_reg(s, rd);
626
                if (insn & (1 << 22))
627
                    gen_op_stb_T0_T1();
628
                else
629
                    gen_op_stl_T0_T1();
630
            }
631
            if (!(insn & (1 << 24))) {
632
                gen_add_data_offset(s, insn);
633
                gen_movl_reg_T1(s, rn);
634
            } else if (insn & (1 << 21))
635
                gen_movl_reg_T1(s, rn); {
636
            }
637
            break;
638
        case 0x08:
639
        case 0x09:
640
            {
641
                int j, n;
642
                /* load/store multiple words */
643
                /* XXX: store correct base if write back */
644
                if (insn & (1 << 22))
645
                    goto illegal_op; /* only usable in supervisor mode */
646
                rn = (insn >> 16) & 0xf;
647
                gen_movl_T1_reg(s, rn);
648
                
649
                /* compute total size */
650
                n = 0;
651
                for(i=0;i<16;i++) {
652
                    if (insn & (1 << i))
653
                        n++;
654
                }
655
                /* XXX: test invalid n == 0 case ? */
656
                if (insn & (1 << 23)) {
657
                    if (insn & (1 << 24)) {
658
                        /* pre increment */
659
                        gen_op_addl_T1_im(4);
660
                    } else {
661
                        /* post increment */
662
                    }
663
                } else {
664
                    if (insn & (1 << 24)) {
665
                        /* pre decrement */
666
                        gen_op_addl_T1_im(-(n * 4));
667
                    } else {
668
                        /* post decrement */
669
                        if (n != 1)
670
                            gen_op_addl_T1_im(-((n - 1) * 4));
671
                    }
672
                }
673
                j = 0;
674
                for(i=0;i<16;i++) {
675
                    if (insn & (1 << i)) {
676
                        if (insn & (1 << 20)) {
677
                            /* load */
678
                            gen_op_ldl_T0_T1();
679
                            gen_movl_reg_T0(s, i);
680
                        } else {
681
                            /* store */
682
                            if (i == 15) {
683
                                /* special case: r15 = PC + 12 */
684
                                val = (long)s->pc + 8;
685
                                gen_op_movl_TN_im[0](val);
686
                            } else {
687
                                gen_movl_T0_reg(s, i);
688
                            }
689
                            gen_op_stl_T0_T1();
690
                        }
691
                        j++;
692
                        /* no need to add after the last transfer */
693
                        if (j != n)
694
                            gen_op_addl_T1_im(4);
695
                    }
696
                }
697
                if (insn & (1 << 21)) {
698
                    /* write back */
699
                    if (insn & (1 << 23)) {
700
                        if (insn & (1 << 24)) {
701
                            /* pre increment */
702
                        } else {
703
                            /* post increment */
704
                            gen_op_addl_T1_im(4);
705
                        }
706
                    } else {
707
                        if (insn & (1 << 24)) {
708
                            /* pre decrement */
709
                            if (n != 1)
710
                                gen_op_addl_T1_im(-((n - 1) * 4));
711
                        } else {
712
                            /* post decrement */
713
                            gen_op_addl_T1_im(-(n * 4));
714
                        }
715
                    }
716
                    gen_movl_reg_T1(s, rn);
717
                }
718
            }
719
            break;
720
        case 0xa:
721
        case 0xb:
722
            {
723
                int offset;
724
                
725
                /* branch (and link) */
726
                val = (int)s->pc;
727
                if (insn & (1 << 24)) {
728
                    gen_op_movl_T0_im(val);
729
                    gen_op_movl_reg_TN[0][14]();
730
                }
731
                offset = (((int)insn << 8) >> 8);
732
                val += (offset << 2) + 4;
733
                gen_op_jmp((long)s->tb, val);
734
                s->is_jmp = DISAS_TB_JUMP;
735
            }
736
            break;
737
        case 0xf:
738
            /* swi */
739
            gen_op_movl_T0_im((long)s->pc);
740
            gen_op_movl_reg_TN[0][15]();
741
            gen_op_swi();
742
            s->is_jmp = DISAS_JUMP;
743
            break;
744
        default:
745
        illegal_op:
746
            gen_op_movl_T0_im((long)s->pc - 4);
747
            gen_op_movl_reg_TN[0][15]();
748
            gen_op_undef_insn();
749
            s->is_jmp = DISAS_JUMP;
750
            break;
751
        }
752
    }
753
}
754

    
755
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
756
   basic block 'tb'. If search_pc is TRUE, also generate PC
757
   information for each intermediate instruction. */
758
static inline int gen_intermediate_code_internal(CPUState *env, 
759
                                                 TranslationBlock *tb, 
760
                                                 int search_pc)
761
{
762
    DisasContext dc1, *dc = &dc1;
763
    uint16_t *gen_opc_end;
764
    int j, lj;
765
    target_ulong pc_start;
766
    
767
    /* generate intermediate code */
768
    pc_start = tb->pc;
769
       
770
    dc->tb = tb;
771

    
772
    gen_opc_ptr = gen_opc_buf;
773
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
774
    gen_opparam_ptr = gen_opparam_buf;
775

    
776
    dc->is_jmp = DISAS_NEXT;
777
    dc->pc = pc_start;
778
    lj = -1;
779
    do {
780
        if (search_pc) {
781
            j = gen_opc_ptr - gen_opc_buf;
782
            if (lj < j) {
783
                lj++;
784
                while (lj < j)
785
                    gen_opc_instr_start[lj++] = 0;
786
            }
787
            gen_opc_pc[lj] = dc->pc;
788
            gen_opc_instr_start[lj] = 1;
789
        }
790
        disas_arm_insn(dc);
791
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
792
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
793
    switch(dc->is_jmp) {
794
    case DISAS_JUMP_NEXT:
795
    case DISAS_NEXT:
796
        gen_op_jmp((long)dc->tb, (long)dc->pc);
797
        break;
798
    default:
799
    case DISAS_JUMP:
800
        /* indicate that the hash table must be used to find the next TB */
801
        gen_op_movl_T0_0();
802
        gen_op_exit_tb();
803
        break;
804
    case DISAS_TB_JUMP:
805
        /* nothing more to generate */
806
        break;
807
    }
808
    *gen_opc_ptr = INDEX_op_end;
809

    
810
#ifdef DEBUG_DISAS
811
    if (loglevel & CPU_LOG_TB_IN_ASM) {
812
        fprintf(logfile, "----------------\n");
813
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
814
        target_disas(logfile, pc_start, dc->pc - pc_start, 0);
815
        fprintf(logfile, "\n");
816
        if (loglevel & (CPU_LOG_TB_OP)) {
817
            fprintf(logfile, "OP:\n");
818
            dump_ops(gen_opc_buf, gen_opparam_buf);
819
            fprintf(logfile, "\n");
820
        }
821
    }
822
#endif
823
    if (!search_pc)
824
        tb->size = dc->pc - pc_start;
825
    return 0;
826
}
827

    
828
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
829
{
830
    return gen_intermediate_code_internal(env, tb, 0);
831
}
832

    
833
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
834
{
835
    return gen_intermediate_code_internal(env, tb, 1);
836
}
837

    
838
CPUARMState *cpu_arm_init(void)
839
{
840
    CPUARMState *env;
841

    
842
    cpu_exec_init();
843

    
844
    env = malloc(sizeof(CPUARMState));
845
    if (!env)
846
        return NULL;
847
    memset(env, 0, sizeof(CPUARMState));
848
    cpu_single_env = env;
849
    return env;
850
}
851

    
852
void cpu_arm_close(CPUARMState *env)
853
{
854
    free(env);
855
}
856

    
857
void cpu_dump_state(CPUState *env, FILE *f, 
858
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
859
                    int flags)
860
{
861
    int i;
862

    
863
    for(i=0;i<16;i++) {
864
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
865
        if ((i % 4) == 3)
866
            cpu_fprintf(f, "\n");
867
        else
868
            cpu_fprintf(f, " ");
869
    }
870
    cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 
871
            env->cpsr, 
872
            env->cpsr & (1 << 31) ? 'N' : '-',
873
            env->cpsr & (1 << 30) ? 'Z' : '-',
874
            env->cpsr & (1 << 29) ? 'C' : '-',
875
            env->cpsr & (1 << 28) ? 'V' : '-');
876
}
877

    
878
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
879
{
880
    return addr;
881
}