Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 2c0262af

History | View | Annotate | Download (25.2 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
    uint8_t *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
typedef void (GenOpFunc)(void);
55
typedef void (GenOpFunc1)(long);
56
typedef void (GenOpFunc2)(long, long);
57
typedef void (GenOpFunc3)(long, long, long);
58

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

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

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

    
109
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
110
    gen_op_shll_T1_im_cc,
111
    gen_op_shrl_T1_im_cc,
112
    gen_op_sarl_T1_im_cc,
113
    gen_op_rorl_T1_im_cc,
114
};
115

    
116
static GenOpFunc *gen_shift_T1_T0[4] = {
117
    gen_op_shll_T1_T0,
118
    gen_op_shrl_T1_T0,
119
    gen_op_sarl_T1_T0,
120
    gen_op_rorl_T1_T0,
121
};
122

    
123
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
124
    gen_op_shll_T1_T0_cc,
125
    gen_op_shrl_T1_T0_cc,
126
    gen_op_sarl_T1_T0_cc,
127
    gen_op_rorl_T1_T0_cc,
128
};
129

    
130
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
131
    {
132
        gen_op_movl_T0_r0,
133
        gen_op_movl_T0_r1,
134
        gen_op_movl_T0_r2,
135
        gen_op_movl_T0_r3,
136
        gen_op_movl_T0_r4,
137
        gen_op_movl_T0_r5,
138
        gen_op_movl_T0_r6,
139
        gen_op_movl_T0_r7,
140
        gen_op_movl_T0_r8,
141
        gen_op_movl_T0_r9,
142
        gen_op_movl_T0_r10,
143
        gen_op_movl_T0_r11,
144
        gen_op_movl_T0_r12,
145
        gen_op_movl_T0_r13,
146
        gen_op_movl_T0_r14,
147
        gen_op_movl_T0_r15,
148
    },
149
    {
150
        gen_op_movl_T1_r0,
151
        gen_op_movl_T1_r1,
152
        gen_op_movl_T1_r2,
153
        gen_op_movl_T1_r3,
154
        gen_op_movl_T1_r4,
155
        gen_op_movl_T1_r5,
156
        gen_op_movl_T1_r6,
157
        gen_op_movl_T1_r7,
158
        gen_op_movl_T1_r8,
159
        gen_op_movl_T1_r9,
160
        gen_op_movl_T1_r10,
161
        gen_op_movl_T1_r11,
162
        gen_op_movl_T1_r12,
163
        gen_op_movl_T1_r13,
164
        gen_op_movl_T1_r14,
165
        gen_op_movl_T1_r15,
166
    },
167
    {
168
        gen_op_movl_T2_r0,
169
        gen_op_movl_T2_r1,
170
        gen_op_movl_T2_r2,
171
        gen_op_movl_T2_r3,
172
        gen_op_movl_T2_r4,
173
        gen_op_movl_T2_r5,
174
        gen_op_movl_T2_r6,
175
        gen_op_movl_T2_r7,
176
        gen_op_movl_T2_r8,
177
        gen_op_movl_T2_r9,
178
        gen_op_movl_T2_r10,
179
        gen_op_movl_T2_r11,
180
        gen_op_movl_T2_r12,
181
        gen_op_movl_T2_r13,
182
        gen_op_movl_T2_r14,
183
        gen_op_movl_T2_r15,
184
    },
185
};
186

    
187
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
188
    {
189
        gen_op_movl_r0_T0,
190
        gen_op_movl_r1_T0,
191
        gen_op_movl_r2_T0,
192
        gen_op_movl_r3_T0,
193
        gen_op_movl_r4_T0,
194
        gen_op_movl_r5_T0,
195
        gen_op_movl_r6_T0,
196
        gen_op_movl_r7_T0,
197
        gen_op_movl_r8_T0,
198
        gen_op_movl_r9_T0,
199
        gen_op_movl_r10_T0,
200
        gen_op_movl_r11_T0,
201
        gen_op_movl_r12_T0,
202
        gen_op_movl_r13_T0,
203
        gen_op_movl_r14_T0,
204
        gen_op_movl_r15_T0,
205
    },
206
    {
207
        gen_op_movl_r0_T1,
208
        gen_op_movl_r1_T1,
209
        gen_op_movl_r2_T1,
210
        gen_op_movl_r3_T1,
211
        gen_op_movl_r4_T1,
212
        gen_op_movl_r5_T1,
213
        gen_op_movl_r6_T1,
214
        gen_op_movl_r7_T1,
215
        gen_op_movl_r8_T1,
216
        gen_op_movl_r9_T1,
217
        gen_op_movl_r10_T1,
218
        gen_op_movl_r11_T1,
219
        gen_op_movl_r12_T1,
220
        gen_op_movl_r13_T1,
221
        gen_op_movl_r14_T1,
222
        gen_op_movl_r15_T1,
223
    },
224
};
225

    
226
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
227
    gen_op_movl_T0_im,
228
    gen_op_movl_T1_im,
229
    gen_op_movl_T2_im,
230
};
231

    
232
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
233
{
234
    int val;
235

    
236
    if (reg == 15) {
237
        /* normaly, since we updated PC, we need only to add 4 */
238
        val = (long)s->pc + 4;
239
        gen_op_movl_TN_im[t](val);
240
    } else {
241
        gen_op_movl_TN_reg[t][reg]();
242
    }
243
}
244

    
245
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
246
{
247
    gen_movl_TN_reg(s, reg, 0);
248
}
249

    
250
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
251
{
252
    gen_movl_TN_reg(s, reg, 1);
253
}
254

    
255
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
256
{
257
    gen_movl_TN_reg(s, reg, 2);
258
}
259

    
260
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
261
{
262
    gen_op_movl_reg_TN[t][reg]();
263
    if (reg == 15) {
264
        s->is_jmp = DISAS_JUMP;
265
    }
266
}
267

    
268
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
269
{
270
    gen_movl_reg_TN(s, reg, 0);
271
}
272

    
273
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
274
{
275
    gen_movl_reg_TN(s, reg, 1);
276
}
277

    
278
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
279
{
280
    int val, rm, shift;
281

    
282
    if (!(insn & (1 << 25))) {
283
        /* immediate */
284
        val = insn & 0xfff;
285
        if (!(insn & (1 << 23)))
286
            val = -val;
287
        gen_op_addl_T1_im(val);
288
    } else {
289
        /* shift/register */
290
        rm = (insn) & 0xf;
291
        shift = (insn >> 7) & 0x1f;
292
        gen_movl_T2_reg(s, rm);
293
        if (shift != 0) {
294
            gen_shift_T2_im[(insn >> 5) & 3](shift);
295
        }
296
        if (!(insn & (1 << 23)))
297
            gen_op_subl_T1_T2();
298
        else
299
            gen_op_addl_T1_T2();
300
    }
301
}
302

    
303
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
304
{
305
    int val, rm;
306
    
307
    if (insn & (1 << 22)) {
308
        /* immediate */
309
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
310
        if (!(insn & (1 << 23)))
311
            val = -val;
312
        gen_op_addl_T1_im(val);
313
    } else {
314
        /* register */
315
        rm = (insn) & 0xf;
316
        gen_movl_T2_reg(s, rm);
317
        if (!(insn & (1 << 23)))
318
            gen_op_subl_T1_T2();
319
        else
320
            gen_op_addl_T1_T2();
321
    }
322
}
323

    
324
static void disas_arm_insn(DisasContext *s)
325
{
326
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
327
    
328
    insn = ldl(s->pc);
329
    s->pc += 4;
330
    
331
    cond = insn >> 28;
332
    if (cond == 0xf)
333
        goto illegal_op;
334
    if (cond != 0xe) {
335
        /* if not always execute, we generate a conditional jump to
336
           next instruction */
337
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
338
        s->is_jmp = DISAS_JUMP_NEXT;
339
    }
340
    if (((insn & 0x0e000000) == 0 &&
341
         (insn & 0x00000090) != 0x90) ||
342
        ((insn & 0x0e000000) == (1 << 25))) {
343
        int set_cc, logic_cc, shiftop;
344
        
345
        op1 = (insn >> 21) & 0xf;
346
        set_cc = (insn >> 20) & 1;
347
        logic_cc = table_logic_cc[op1] & set_cc;
348

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

    
786
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
787
   basic block 'tb'. If search_pc is TRUE, also generate PC
788
   information for each intermediate instruction. */
789
static inline int gen_intermediate_code_internal(CPUState *env, 
790
                                                 TranslationBlock *tb, 
791
                                                 int search_pc)
792
{
793
    DisasContext dc1, *dc = &dc1;
794
    uint16_t *gen_opc_end;
795
    int j, lj;
796
    uint8_t *pc_start;
797
    
798
    /* generate intermediate code */
799
    pc_start = (uint8_t *)tb->pc;
800
       
801
    dc->tb = tb;
802

    
803
    gen_opc_ptr = gen_opc_buf;
804
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
805
    gen_opparam_ptr = gen_opparam_buf;
806

    
807
    dc->is_jmp = DISAS_NEXT;
808
    dc->pc = pc_start;
809
    lj = -1;
810
    do {
811
        if (search_pc) {
812
            j = gen_opc_ptr - gen_opc_buf;
813
            if (lj < j) {
814
                lj++;
815
                while (lj < j)
816
                    gen_opc_instr_start[lj++] = 0;
817
            }
818
            gen_opc_pc[lj] = (uint32_t)dc->pc;
819
            gen_opc_instr_start[lj] = 1;
820
        }
821
        disas_arm_insn(dc);
822
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
823
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
824
    switch(dc->is_jmp) {
825
    case DISAS_JUMP_NEXT:
826
    case DISAS_NEXT:
827
        gen_op_jmp((long)dc->tb, (long)dc->pc);
828
        break;
829
    default:
830
    case DISAS_JUMP:
831
        /* indicate that the hash table must be used to find the next TB */
832
        gen_op_movl_T0_0();
833
        gen_op_exit_tb();
834
        break;
835
    case DISAS_TB_JUMP:
836
        /* nothing more to generate */
837
        break;
838
    }
839
    *gen_opc_ptr = INDEX_op_end;
840

    
841
#ifdef DEBUG_DISAS
842
    if (loglevel) {
843
        fprintf(logfile, "----------------\n");
844
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
845
        disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
846
        fprintf(logfile, "\n");
847

    
848
        fprintf(logfile, "OP:\n");
849
        dump_ops(gen_opc_buf, gen_opparam_buf);
850
        fprintf(logfile, "\n");
851
    }
852
#endif
853
    if (!search_pc)
854
        tb->size = dc->pc - pc_start;
855
    return 0;
856
}
857

    
858
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
859
{
860
    return gen_intermediate_code_internal(env, tb, 0);
861
}
862

    
863
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
864
{
865
    return gen_intermediate_code_internal(env, tb, 1);
866
}
867

    
868
CPUARMState *cpu_arm_init(void)
869
{
870
    CPUARMState *env;
871

    
872
    cpu_exec_init();
873

    
874
    env = malloc(sizeof(CPUARMState));
875
    if (!env)
876
        return NULL;
877
    memset(env, 0, sizeof(CPUARMState));
878
    return env;
879
}
880

    
881
void cpu_arm_close(CPUARMState *env)
882
{
883
    free(env);
884
}
885

    
886
void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
887
{
888
    int i;
889

    
890
    for(i=0;i<16;i++) {
891
        fprintf(f, "R%02d=%08x", i, env->regs[i]);
892
        if ((i % 4) == 3)
893
            fprintf(f, "\n");
894
        else
895
            fprintf(f, " ");
896
    }
897
    fprintf(f, "PSR=%08x %c%c%c%c\n", 
898
            env->cpsr, 
899
            env->cpsr & (1 << 31) ? 'N' : '-',
900
            env->cpsr & (1 << 30) ? 'Z' : '-',
901
            env->cpsr & (1 << 29) ? 'C' : '-',
902
            env->cpsr & (1 << 28) ? 'V' : '-');
903
}