changed basic block exit generation
[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 #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-arm.h"
48 #undef DEF
49     NB_OPS,
50 };
51
52 #include "gen-op-arm.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(TranslationBlock *tb, int search_pc)
790 {
791     DisasContext dc1, *dc = &dc1;
792     uint16_t *gen_opc_end;
793     int j, lj;
794     uint8_t *pc_start;
795     
796     /* generate intermediate code */
797     pc_start = (uint8_t *)tb->pc;
798        
799     dc->tb = tb;
800
801     gen_opc_ptr = gen_opc_buf;
802     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
803     gen_opparam_ptr = gen_opparam_buf;
804
805     dc->is_jmp = DISAS_NEXT;
806     dc->pc = pc_start;
807     lj = -1;
808     do {
809         if (search_pc) {
810             j = gen_opc_ptr - gen_opc_buf;
811             if (lj < j) {
812                 lj++;
813                 while (lj < j)
814                     gen_opc_instr_start[lj++] = 0;
815             }
816             gen_opc_pc[lj] = (uint32_t)dc->pc;
817             gen_opc_instr_start[lj] = 1;
818         }
819         disas_arm_insn(dc);
820     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
821              (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
822     switch(dc->is_jmp) {
823     case DISAS_JUMP_NEXT:
824     case DISAS_NEXT:
825         gen_op_jmp((long)dc->tb, (long)dc->pc);
826         break;
827     default:
828     case DISAS_JUMP:
829         /* indicate that the hash table must be used to find the next TB */
830         gen_op_movl_T0_0();
831         gen_op_exit_tb();
832         break;
833     case DISAS_TB_JUMP:
834         /* nothing more to generate */
835         break;
836     }
837     *gen_opc_ptr = INDEX_op_end;
838
839 #ifdef DEBUG_DISAS
840     if (loglevel) {
841         fprintf(logfile, "----------------\n");
842         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
843         disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
844         fprintf(logfile, "\n");
845
846         fprintf(logfile, "OP:\n");
847         dump_ops(gen_opc_buf, gen_opparam_buf);
848         fprintf(logfile, "\n");
849     }
850 #endif
851     if (!search_pc)
852         tb->size = dc->pc - pc_start;
853     return 0;
854 }
855
856 int gen_intermediate_code(TranslationBlock *tb)
857 {
858     return gen_intermediate_code_internal(tb, 0);
859 }
860
861 int gen_intermediate_code_pc(TranslationBlock *tb)
862 {
863     return gen_intermediate_code_internal(tb, 1);
864 }
865
866 CPUARMState *cpu_arm_init(void)
867 {
868     CPUARMState *env;
869
870     cpu_exec_init();
871
872     env = malloc(sizeof(CPUARMState));
873     if (!env)
874         return NULL;
875     memset(env, 0, sizeof(CPUARMState));
876     return env;
877 }
878
879 void cpu_arm_close(CPUARMState *env)
880 {
881     free(env);
882 }
883
884 void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
885 {
886     int i;
887
888     for(i=0;i<16;i++) {
889         fprintf(f, "R%02d=%08x", i, env->regs[i]);
890         if ((i % 4) == 3)
891             fprintf(f, "\n");
892         else
893             fprintf(f, " ");
894     }
895     fprintf(f, "PSR=%08x %c%c%c%c\n", 
896             env->cpsr, 
897             env->cpsr & (1 << 31) ? 'N' : '-',
898             env->cpsr & (1 << 30) ? 'Z' : '-',
899             env->cpsr & (1 << 29) ? 'C' : '-',
900             env->cpsr & (1 << 28) ? 'V' : '-');
901 }