update
[qemu] / translate-arm.c
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-arm.h"
27 #include "exec.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 /* XXX: move that elsewhere */
38 static uint16_t *gen_opc_ptr;
39 static uint32_t *gen_opparam_ptr;
40 extern FILE *logfile;
41 extern int loglevel;
42
43 enum {
44 #define DEF(s, n, copy_size) INDEX_op_ ## s,
45 #include "opc-arm.h"
46 #undef DEF
47     NB_OPS,
48 };
49
50 #include "gen-op-arm.h"
51
52 typedef void (GenOpFunc)(void);
53 typedef void (GenOpFunc1)(long);
54 typedef void (GenOpFunc2)(long, long);
55 typedef void (GenOpFunc3)(long, long, long);
56
57 static GenOpFunc2 *gen_test_cc[14] = {
58     gen_op_test_eq,
59     gen_op_test_ne,
60     gen_op_test_cs,
61     gen_op_test_cc,
62     gen_op_test_mi,
63     gen_op_test_pl,
64     gen_op_test_vs,
65     gen_op_test_vc,
66     gen_op_test_hi,
67     gen_op_test_ls,
68     gen_op_test_ge,
69     gen_op_test_lt,
70     gen_op_test_gt,
71     gen_op_test_le,
72 };
73
74 const uint8_t table_logic_cc[16] = {
75     1, /* and */
76     1, /* xor */
77     0, /* sub */
78     0, /* rsb */
79     0, /* add */
80     0, /* adc */
81     0, /* sbc */
82     0, /* rsc */
83     1, /* andl */
84     1, /* xorl */
85     0, /* cmp */
86     0, /* cmn */
87     1, /* orr */
88     1, /* mov */
89     1, /* bic */
90     1, /* mvn */
91 };
92     
93 static GenOpFunc1 *gen_shift_T1_im[4] = {
94     gen_op_shll_T1_im,
95     gen_op_shrl_T1_im,
96     gen_op_sarl_T1_im,
97     gen_op_rorl_T1_im,
98 };
99
100 static GenOpFunc1 *gen_shift_T2_im[4] = {
101     gen_op_shll_T2_im,
102     gen_op_shrl_T2_im,
103     gen_op_sarl_T2_im,
104     gen_op_rorl_T2_im,
105 };
106
107 static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
108     gen_op_shll_T1_im_cc,
109     gen_op_shrl_T1_im_cc,
110     gen_op_sarl_T1_im_cc,
111     gen_op_rorl_T1_im_cc,
112 };
113
114 static GenOpFunc *gen_shift_T1_T0[4] = {
115     gen_op_shll_T1_T0,
116     gen_op_shrl_T1_T0,
117     gen_op_sarl_T1_T0,
118     gen_op_rorl_T1_T0,
119 };
120
121 static GenOpFunc *gen_shift_T1_T0_cc[4] = {
122     gen_op_shll_T1_T0_cc,
123     gen_op_shrl_T1_T0_cc,
124     gen_op_sarl_T1_T0_cc,
125     gen_op_rorl_T1_T0_cc,
126 };
127
128 static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
129     {
130         gen_op_movl_T0_r0,
131         gen_op_movl_T0_r1,
132         gen_op_movl_T0_r2,
133         gen_op_movl_T0_r3,
134         gen_op_movl_T0_r4,
135         gen_op_movl_T0_r5,
136         gen_op_movl_T0_r6,
137         gen_op_movl_T0_r7,
138         gen_op_movl_T0_r8,
139         gen_op_movl_T0_r9,
140         gen_op_movl_T0_r10,
141         gen_op_movl_T0_r11,
142         gen_op_movl_T0_r12,
143         gen_op_movl_T0_r13,
144         gen_op_movl_T0_r14,
145         gen_op_movl_T0_r15,
146     },
147     {
148         gen_op_movl_T1_r0,
149         gen_op_movl_T1_r1,
150         gen_op_movl_T1_r2,
151         gen_op_movl_T1_r3,
152         gen_op_movl_T1_r4,
153         gen_op_movl_T1_r5,
154         gen_op_movl_T1_r6,
155         gen_op_movl_T1_r7,
156         gen_op_movl_T1_r8,
157         gen_op_movl_T1_r9,
158         gen_op_movl_T1_r10,
159         gen_op_movl_T1_r11,
160         gen_op_movl_T1_r12,
161         gen_op_movl_T1_r13,
162         gen_op_movl_T1_r14,
163         gen_op_movl_T1_r15,
164     },
165     {
166         gen_op_movl_T2_r0,
167         gen_op_movl_T2_r1,
168         gen_op_movl_T2_r2,
169         gen_op_movl_T2_r3,
170         gen_op_movl_T2_r4,
171         gen_op_movl_T2_r5,
172         gen_op_movl_T2_r6,
173         gen_op_movl_T2_r7,
174         gen_op_movl_T2_r8,
175         gen_op_movl_T2_r9,
176         gen_op_movl_T2_r10,
177         gen_op_movl_T2_r11,
178         gen_op_movl_T2_r12,
179         gen_op_movl_T2_r13,
180         gen_op_movl_T2_r14,
181         gen_op_movl_T2_r15,
182     },
183 };
184
185 static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
186     {
187         gen_op_movl_r0_T0,
188         gen_op_movl_r1_T0,
189         gen_op_movl_r2_T0,
190         gen_op_movl_r3_T0,
191         gen_op_movl_r4_T0,
192         gen_op_movl_r5_T0,
193         gen_op_movl_r6_T0,
194         gen_op_movl_r7_T0,
195         gen_op_movl_r8_T0,
196         gen_op_movl_r9_T0,
197         gen_op_movl_r10_T0,
198         gen_op_movl_r11_T0,
199         gen_op_movl_r12_T0,
200         gen_op_movl_r13_T0,
201         gen_op_movl_r14_T0,
202         gen_op_movl_r15_T0,
203     },
204     {
205         gen_op_movl_r0_T1,
206         gen_op_movl_r1_T1,
207         gen_op_movl_r2_T1,
208         gen_op_movl_r3_T1,
209         gen_op_movl_r4_T1,
210         gen_op_movl_r5_T1,
211         gen_op_movl_r6_T1,
212         gen_op_movl_r7_T1,
213         gen_op_movl_r8_T1,
214         gen_op_movl_r9_T1,
215         gen_op_movl_r10_T1,
216         gen_op_movl_r11_T1,
217         gen_op_movl_r12_T1,
218         gen_op_movl_r13_T1,
219         gen_op_movl_r14_T1,
220         gen_op_movl_r15_T1,
221     },
222 };
223
224 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
225     gen_op_movl_T0_im,
226     gen_op_movl_T1_im,
227     gen_op_movl_T2_im,
228 };
229
230 static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
231 {
232     int val;
233
234     if (reg == 15) {
235         /* normaly, since we updated PC, we need only to add 4 */
236         val = (long)s->pc + 4;
237         gen_op_movl_TN_im[t](val);
238     } else {
239         gen_op_movl_TN_reg[t][reg]();
240     }
241 }
242
243 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
244 {
245     gen_movl_TN_reg(s, reg, 0);
246 }
247
248 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
249 {
250     gen_movl_TN_reg(s, reg, 1);
251 }
252
253 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
254 {
255     gen_movl_TN_reg(s, reg, 2);
256 }
257
258 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
259 {
260     gen_op_movl_reg_TN[t][reg]();
261     if (reg == 15) {
262         s->is_jmp = DISAS_JUMP;
263     }
264 }
265
266 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
267 {
268     gen_movl_reg_TN(s, reg, 0);
269 }
270
271 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
272 {
273     gen_movl_reg_TN(s, reg, 1);
274 }
275
276 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
277 {
278     int val, rm, shift;
279
280     if (!(insn & (1 << 25))) {
281         /* immediate */
282         val = insn & 0xfff;
283         if (!(insn & (1 << 23)))
284             val = -val;
285         gen_op_addl_T1_im(val);
286     } else {
287         /* shift/register */
288         rm = (insn) & 0xf;
289         shift = (insn >> 7) & 0x1f;
290         gen_movl_T2_reg(s, rm);
291         if (shift != 0) {
292             gen_shift_T2_im[(insn >> 5) & 3](shift);
293         }
294         if (!(insn & (1 << 23)))
295             gen_op_subl_T1_T2();
296         else
297             gen_op_addl_T1_T2();
298     }
299 }
300
301 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
302 {
303     int val, rm;
304     
305     if (insn & (1 << 22)) {
306         /* immediate */
307         val = (insn & 0xf) | ((insn >> 4) & 0xf0);
308         if (!(insn & (1 << 23)))
309             val = -val;
310         gen_op_addl_T1_im(val);
311     } else {
312         /* register */
313         rm = (insn) & 0xf;
314         gen_movl_T2_reg(s, rm);
315         if (!(insn & (1 << 23)))
316             gen_op_subl_T1_T2();
317         else
318             gen_op_addl_T1_T2();
319     }
320 }
321
322 static void disas_arm_insn(DisasContext *s)
323 {
324     unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
325     
326     insn = ldl(s->pc);
327     s->pc += 4;
328     
329     cond = insn >> 28;
330     if (cond == 0xf)
331         goto illegal_op;
332     if (cond != 0xe) {
333         /* if not always execute, we generate a conditional jump to
334            next instruction */
335         gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
336         s->is_jmp = 1;
337     }
338     if ((insn & 0x0c000000) == 0 &&
339         (insn & 0x00000090) != 0x90) {
340         int set_cc, logic_cc, shiftop;
341         
342         op1 = (insn >> 21) & 0xf;
343         set_cc = (insn >> 20) & 1;
344         logic_cc = table_logic_cc[op1] & set_cc;
345
346         /* data processing instruction */
347         if (insn & (1 << 25)) {
348             /* immediate operand */
349             val = insn & 0xff;
350             shift = ((insn >> 8) & 0xf) * 2;
351             if (shift)
352                 val = (val >> shift) | (val << (32 - shift));
353             gen_op_movl_T1_im(val);
354             /* XXX: is CF modified ? */
355         } else {
356             /* register */
357             rm = (insn) & 0xf;
358             gen_movl_T1_reg(s, rm);
359             shiftop = (insn >> 5) & 3;
360             if (!(insn & (1 << 4))) {
361                 shift = (insn >> 7) & 0x1f;
362                 if (shift != 0) {
363                     if (logic_cc) {
364                         gen_shift_T1_im_cc[shiftop](shift);
365                     } else {
366                         gen_shift_T1_im[shiftop](shift);
367                     }
368                 }
369             } else {
370                 rs = (insn >> 16) & 0xf;
371                 gen_movl_T0_reg(s, rs);
372                 if (logic_cc) {
373                     gen_shift_T1_T0_cc[shiftop]();
374                 } else {
375                     gen_shift_T1_T0[shiftop]();
376                 }
377             }
378         }
379         if (op1 != 0x0f && op1 != 0x0d) {
380             rn = (insn >> 16) & 0xf;
381             gen_movl_T0_reg(s, rn);
382         }
383         rd = (insn >> 12) & 0xf;
384         switch(op1) {
385         case 0x00:
386             gen_op_andl_T0_T1();
387             gen_movl_reg_T0(s, rd);
388             break;
389         case 0x01:
390             gen_op_xorl_T0_T1();
391             gen_movl_reg_T0(s, rd);
392             break;
393         case 0x02:
394             if (set_cc)
395                 gen_op_subl_T0_T1_cc();
396             else
397                 gen_op_subl_T0_T1();
398             gen_movl_reg_T0(s, rd);
399             break;
400         case 0x03:
401             if (set_cc)
402                 gen_op_rsbl_T0_T1_cc();
403             else
404                 gen_op_rsbl_T0_T1();
405             gen_movl_reg_T0(s, rd);
406             break;
407         case 0x04:
408             if (set_cc)
409                 gen_op_addl_T0_T1_cc();
410             else
411                 gen_op_addl_T0_T1();
412             gen_movl_reg_T0(s, rd);
413             break;
414         case 0x05:
415             if (set_cc)
416                 gen_op_adcl_T0_T1_cc();
417             else
418                 gen_op_adcl_T0_T1();
419             gen_movl_reg_T0(s, rd);
420             break;
421         case 0x06:
422             if (set_cc)
423                 gen_op_sbcl_T0_T1_cc();
424             else
425                 gen_op_sbcl_T0_T1();
426             gen_movl_reg_T0(s, rd);
427             break;
428         case 0x07:
429             if (set_cc)
430                 gen_op_rscl_T0_T1_cc();
431             else
432                 gen_op_rscl_T0_T1();
433             gen_movl_reg_T0(s, rd);
434             break;
435         case 0x08:
436             if (set_cc) {
437                 gen_op_andl_T0_T1();
438             }
439             break;
440         case 0x09:
441             if (set_cc) {
442                 gen_op_xorl_T0_T1();
443             }
444             break;
445         case 0x0a:
446             if (set_cc) {
447                 gen_op_subl_T0_T1_cc();
448             }
449             break;
450         case 0x0b:
451             if (set_cc) {
452                 gen_op_addl_T0_T1_cc();
453             }
454             break;
455         case 0x0c:
456             gen_op_orl_T0_T1();
457             gen_movl_reg_T0(s, rd);
458             break;
459         case 0x0d:
460             gen_movl_reg_T1(s, rd);
461             break;
462         case 0x0e:
463             gen_op_bicl_T0_T1();
464             gen_movl_reg_T0(s, rd);
465             break;
466         default:
467         case 0x0f:
468             gen_op_notl_T1();
469             gen_movl_reg_T1(s, rd);
470             break;
471         }
472         if (logic_cc)
473             gen_op_logic_cc();
474     } else {
475         /* other instructions */
476         op1 = (insn >> 24) & 0xf;
477         switch(op1) {
478         case 0x0:
479         case 0x1:
480             sh = (insn >> 5) & 3;
481             if (sh == 0) {
482                 if (op1 == 0x0) {
483                     rd = (insn >> 16) & 0xf;
484                     rn = (insn >> 12) & 0xf;
485                     rs = (insn >> 8) & 0xf;
486                     rm = (insn) & 0xf;
487                     if (!(insn & (1 << 23))) {
488                         /* 32 bit mul */
489                         gen_movl_T0_reg(s, rs);
490                         gen_movl_T1_reg(s, rm);
491                         gen_op_mul_T0_T1();
492                         if (insn & (1 << 21)) {
493                             gen_movl_T1_reg(s, rn);
494                             gen_op_addl_T0_T1();
495                         }
496                         if (insn & (1 << 20)) 
497                             gen_op_logic_cc();
498                         gen_movl_reg_T0(s, rd);
499                     } else {
500                         /* 64 bit mul */
501                         gen_movl_T0_reg(s, rs);
502                         gen_movl_T1_reg(s, rm);
503                         if (insn & (1 << 22)) 
504                             gen_op_mull_T0_T1();
505                         else
506                             gen_op_imull_T0_T1();
507                         if (insn & (1 << 21)) 
508                             gen_op_addq_T0_T1(rn, rd);
509                         if (insn & (1 << 20)) 
510                             gen_op_logicq_cc();
511                         gen_movl_reg_T0(s, rn);
512                         gen_movl_reg_T1(s, rd);
513                     }
514                 } else {
515                     /* SWP instruction */
516                     rn = (insn >> 16) & 0xf;
517                     rd = (insn >> 12) & 0xf;
518                     rm = (insn) & 0xf;
519                     
520                     gen_movl_T0_reg(s, rm);
521                     gen_movl_T1_reg(s, rn);
522                     if (insn & (1 << 22)) {
523                         gen_op_swpb_T0_T1();
524                     } else {
525                         gen_op_swpl_T0_T1();
526                     }
527                     gen_movl_reg_T0(s, rd);
528                 }
529             } else {
530                 /* load/store half word */
531                 rn = (insn >> 16) & 0xf;
532                 rd = (insn >> 12) & 0xf;
533                 gen_movl_T1_reg(s, rn);
534                 if (insn & (1 << 25))
535                     gen_add_datah_offset(s, insn);
536                 if (insn & (1 << 20)) {
537                     /* load */
538                     switch(sh) {
539                     case 1:
540                         gen_op_lduw_T0_T1();
541                         break;
542                     case 2:
543                         gen_op_ldsb_T0_T1();
544                         break;
545                     default:
546                     case 3:
547                         gen_op_ldsw_T0_T1();
548                         break;
549                     }
550                 } else {
551                     /* store */
552                     gen_op_stw_T0_T1();
553                 }
554                 if (!(insn & (1 << 24)))
555                     gen_add_datah_offset(s, insn);
556                 if (insn & (1 << 21))
557                     gen_movl_reg_T1(s, rn);
558             }
559             break;
560         case 0x4:
561         case 0x5:
562         case 0x6:
563         case 0x7:
564             /* load/store byte/word */
565             rn = (insn >> 16) & 0xf;
566             rd = (insn >> 12) & 0xf;
567             gen_movl_T1_reg(s, rn);
568             if (insn & (1 << 24))
569                 gen_add_data_offset(s, insn);
570             if (insn & (1 << 20)) {
571                 /* load */
572                 if (insn & (1 << 22))
573                     gen_op_ldub_T0_T1();
574                 else
575                     gen_op_ldl_T0_T1();
576                 gen_movl_reg_T0(s, rd);
577             } else {
578                 /* store */
579                 gen_movl_T0_reg(s, rd);
580                 if (insn & (1 << 22))
581                     gen_op_stb_T0_T1();
582                 else
583                     gen_op_stl_T0_T1();
584             }
585             if (!(insn & (1 << 24)))
586                 gen_add_data_offset(s, insn);
587             if (insn & (1 << 21))
588                 gen_movl_reg_T1(s, rn);
589             break;
590         case 0x08:
591         case 0x09:
592             /* load/store multiple words */
593             if (insn & (1 << 22))
594                 goto illegal_op; /* only usable in supervisor mode */
595             rn = (insn >> 16) & 0xf;
596             gen_movl_T1_reg(s, rn);
597             val = 4;
598             if (!(insn & (1 << 23)))
599                 val = -val;
600             for(i=0;i<16;i++) {
601                 if (insn & (1 << i)) {
602                     if (insn & (1 << 24))
603                         gen_op_addl_T1_im(val);
604                     if (insn & (1 << 20)) {
605                         /* load */
606                         gen_op_ldl_T0_T1();
607                         gen_movl_reg_T0(s, i);
608                     } else {
609                         /* store */
610                         gen_movl_T0_reg(s, i);
611                         gen_op_stl_T0_T1();
612                     }
613                     if (!(insn & (1 << 24)))
614                         gen_op_addl_T1_im(val);
615                 }
616             }
617             if (insn & (1 << 21))
618                 gen_movl_reg_T1(s, rn);
619             break;
620         case 0xa:
621         case 0xb:
622             {
623                 int offset;
624                 
625                 /* branch (and link) */
626                 val = (int)s->pc;
627                 if (insn & (1 << 24)) {
628                     gen_op_movl_T0_im(val);
629                     gen_op_movl_reg_TN[0][14]();
630                 }
631                 offset = (((int)insn << 8) >> 8);
632                 val += (offset << 2) + 4;
633                 gen_op_jmp((long)s->tb, val);
634                 s->is_jmp = DISAS_TB_JUMP;
635             }
636             break;
637         case 0xf:
638             /* swi */
639             gen_op_movl_T0_im((long)s->pc);
640             gen_op_movl_reg_TN[0][15]();
641             gen_op_swi();
642             s->is_jmp = DISAS_JUMP;
643             break;
644         default:
645         illegal_op:
646             gen_op_movl_T0_im((long)s->pc - 4);
647             gen_op_movl_reg_TN[0][15]();
648             gen_op_undef_insn();
649             s->is_jmp = DISAS_JUMP;
650             break;
651         }
652     }
653 }
654
655 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
656    basic block 'tb'. If search_pc is TRUE, also generate PC
657    information for each intermediate instruction. */
658 static inline int gen_intermediate_code_internal(TranslationBlock *tb, int search_pc)
659 {
660     DisasContext dc1, *dc = &dc1;
661     uint16_t *gen_opc_end;
662     int j, lj;
663     uint8_t *pc_start;
664     
665     /* generate intermediate code */
666     pc_start = (uint8_t *)tb->pc;
667        
668     dc->tb = tb;
669
670     gen_opc_ptr = gen_opc_buf;
671     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
672     gen_opparam_ptr = gen_opparam_buf;
673
674     dc->is_jmp = DISAS_NEXT;
675     dc->pc = pc_start;
676     lj = -1;
677     do {
678         if (search_pc) {
679             j = gen_opc_ptr - gen_opc_buf;
680             if (lj < j) {
681                 lj++;
682                 while (lj < j)
683                     gen_opc_instr_start[lj++] = 0;
684                 gen_opc_pc[lj] = (uint32_t)dc->pc;
685                 gen_opc_instr_start[lj] = 1;
686             }
687         }
688         disas_arm_insn(dc);
689     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
690              (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
691     /* we must store the eflags state if it is not already done */
692     if (dc->is_jmp != DISAS_TB_JUMP && 
693         dc->is_jmp != DISAS_JUMP) {
694         gen_op_movl_T0_im((long)dc->pc - 4);
695         gen_op_movl_reg_TN[0][15]();
696     }
697     if (dc->is_jmp != DISAS_TB_JUMP) {
698         /* indicate that the hash table must be used to find the next TB */
699         gen_op_movl_T0_0();
700     }
701     *gen_opc_ptr = INDEX_op_end;
702
703 #ifdef DEBUG_DISAS
704     if (loglevel) {
705         fprintf(logfile, "----------------\n");
706         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
707         disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
708         fprintf(logfile, "\n");
709
710         fprintf(logfile, "OP:\n");
711         dump_ops(gen_opc_buf, gen_opparam_buf);
712         fprintf(logfile, "\n");
713     }
714 #endif
715     if (!search_pc)
716         tb->size = dc->pc - pc_start;
717     return 0;
718 }
719
720 int gen_intermediate_code(TranslationBlock *tb)
721 {
722     return gen_intermediate_code_internal(tb, 0);
723 }
724
725 int gen_intermediate_code_pc(TranslationBlock *tb)
726 {
727     return gen_intermediate_code_internal(tb, 1);
728 }
729
730 CPUARMState *cpu_arm_init(void)
731 {
732     CPUARMState *env;
733
734     cpu_exec_init();
735
736     env = malloc(sizeof(CPUARMState));
737     if (!env)
738         return NULL;
739     memset(env, 0, sizeof(CPUARMState));
740     return env;
741 }
742
743 void cpu_arm_close(CPUARMState *env)
744 {
745     free(env);
746 }
747
748 void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
749 {
750     int i;
751
752     for(i=0;i<16;i++) {
753         fprintf(f, "R%02d=%08x", i, env->regs[i]);
754         if ((i % 4) == 3)
755             fprintf(f, "\n");
756         else
757             fprintf(f, " ");
758     }
759     fprintf(f, "CPSR=%08x", env->cpsr);
760 }