Floppy disk emulation (Jocelyn Mayer)
[qemu] / target-arm / translate.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.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 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 GenOpFunc1 *gen_shift_T2_im[4] = {
98     gen_op_shll_T2_im,
99     gen_op_shrl_T2_im,
100     gen_op_sarl_T2_im,
101     gen_op_rorl_T2_im,
102 };
103
104 static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
105     gen_op_shll_T1_im_cc,
106     gen_op_shrl_T1_im_cc,
107     gen_op_sarl_T1_im_cc,
108     gen_op_rorl_T1_im_cc,
109 };
110
111 static GenOpFunc *gen_shift_T1_T0[4] = {
112     gen_op_shll_T1_T0,
113     gen_op_shrl_T1_T0,
114     gen_op_sarl_T1_T0,
115     gen_op_rorl_T1_T0,
116 };
117
118 static GenOpFunc *gen_shift_T1_T0_cc[4] = {
119     gen_op_shll_T1_T0_cc,
120     gen_op_shrl_T1_T0_cc,
121     gen_op_sarl_T1_T0_cc,
122     gen_op_rorl_T1_T0_cc,
123 };
124
125 static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
126     {
127         gen_op_movl_T0_r0,
128         gen_op_movl_T0_r1,
129         gen_op_movl_T0_r2,
130         gen_op_movl_T0_r3,
131         gen_op_movl_T0_r4,
132         gen_op_movl_T0_r5,
133         gen_op_movl_T0_r6,
134         gen_op_movl_T0_r7,
135         gen_op_movl_T0_r8,
136         gen_op_movl_T0_r9,
137         gen_op_movl_T0_r10,
138         gen_op_movl_T0_r11,
139         gen_op_movl_T0_r12,
140         gen_op_movl_T0_r13,
141         gen_op_movl_T0_r14,
142         gen_op_movl_T0_r15,
143     },
144     {
145         gen_op_movl_T1_r0,
146         gen_op_movl_T1_r1,
147         gen_op_movl_T1_r2,
148         gen_op_movl_T1_r3,
149         gen_op_movl_T1_r4,
150         gen_op_movl_T1_r5,
151         gen_op_movl_T1_r6,
152         gen_op_movl_T1_r7,
153         gen_op_movl_T1_r8,
154         gen_op_movl_T1_r9,
155         gen_op_movl_T1_r10,
156         gen_op_movl_T1_r11,
157         gen_op_movl_T1_r12,
158         gen_op_movl_T1_r13,
159         gen_op_movl_T1_r14,
160         gen_op_movl_T1_r15,
161     },
162     {
163         gen_op_movl_T2_r0,
164         gen_op_movl_T2_r1,
165         gen_op_movl_T2_r2,
166         gen_op_movl_T2_r3,
167         gen_op_movl_T2_r4,
168         gen_op_movl_T2_r5,
169         gen_op_movl_T2_r6,
170         gen_op_movl_T2_r7,
171         gen_op_movl_T2_r8,
172         gen_op_movl_T2_r9,
173         gen_op_movl_T2_r10,
174         gen_op_movl_T2_r11,
175         gen_op_movl_T2_r12,
176         gen_op_movl_T2_r13,
177         gen_op_movl_T2_r14,
178         gen_op_movl_T2_r15,
179     },
180 };
181
182 static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
183     {
184         gen_op_movl_r0_T0,
185         gen_op_movl_r1_T0,
186         gen_op_movl_r2_T0,
187         gen_op_movl_r3_T0,
188         gen_op_movl_r4_T0,
189         gen_op_movl_r5_T0,
190         gen_op_movl_r6_T0,
191         gen_op_movl_r7_T0,
192         gen_op_movl_r8_T0,
193         gen_op_movl_r9_T0,
194         gen_op_movl_r10_T0,
195         gen_op_movl_r11_T0,
196         gen_op_movl_r12_T0,
197         gen_op_movl_r13_T0,
198         gen_op_movl_r14_T0,
199         gen_op_movl_r15_T0,
200     },
201     {
202         gen_op_movl_r0_T1,
203         gen_op_movl_r1_T1,
204         gen_op_movl_r2_T1,
205         gen_op_movl_r3_T1,
206         gen_op_movl_r4_T1,
207         gen_op_movl_r5_T1,
208         gen_op_movl_r6_T1,
209         gen_op_movl_r7_T1,
210         gen_op_movl_r8_T1,
211         gen_op_movl_r9_T1,
212         gen_op_movl_r10_T1,
213         gen_op_movl_r11_T1,
214         gen_op_movl_r12_T1,
215         gen_op_movl_r13_T1,
216         gen_op_movl_r14_T1,
217         gen_op_movl_r15_T1,
218     },
219 };
220
221 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
222     gen_op_movl_T0_im,
223     gen_op_movl_T1_im,
224     gen_op_movl_T2_im,
225 };
226
227 static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
228 {
229     int val;
230
231     if (reg == 15) {
232         /* normaly, since we updated PC, we need only to add 4 */
233         val = (long)s->pc + 4;
234         gen_op_movl_TN_im[t](val);
235     } else {
236         gen_op_movl_TN_reg[t][reg]();
237     }
238 }
239
240 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
241 {
242     gen_movl_TN_reg(s, reg, 0);
243 }
244
245 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
246 {
247     gen_movl_TN_reg(s, reg, 1);
248 }
249
250 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
251 {
252     gen_movl_TN_reg(s, reg, 2);
253 }
254
255 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
256 {
257     gen_op_movl_reg_TN[t][reg]();
258     if (reg == 15) {
259         s->is_jmp = DISAS_JUMP;
260     }
261 }
262
263 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
264 {
265     gen_movl_reg_TN(s, reg, 0);
266 }
267
268 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
269 {
270     gen_movl_reg_TN(s, reg, 1);
271 }
272
273 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
274 {
275     int val, rm, shift;
276
277     if (!(insn & (1 << 25))) {
278         /* immediate */
279         val = insn & 0xfff;
280         if (!(insn & (1 << 23)))
281             val = -val;
282         gen_op_addl_T1_im(val);
283     } else {
284         /* shift/register */
285         rm = (insn) & 0xf;
286         shift = (insn >> 7) & 0x1f;
287         gen_movl_T2_reg(s, rm);
288         if (shift != 0) {
289             gen_shift_T2_im[(insn >> 5) & 3](shift);
290         }
291         if (!(insn & (1 << 23)))
292             gen_op_subl_T1_T2();
293         else
294             gen_op_addl_T1_T2();
295     }
296 }
297
298 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
299 {
300     int val, rm;
301     
302     if (insn & (1 << 22)) {
303         /* immediate */
304         val = (insn & 0xf) | ((insn >> 4) & 0xf0);
305         if (!(insn & (1 << 23)))
306             val = -val;
307         gen_op_addl_T1_im(val);
308     } else {
309         /* register */
310         rm = (insn) & 0xf;
311         gen_movl_T2_reg(s, rm);
312         if (!(insn & (1 << 23)))
313             gen_op_subl_T1_T2();
314         else
315             gen_op_addl_T1_T2();
316     }
317 }
318
319 static void disas_arm_insn(DisasContext *s)
320 {
321     unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
322     
323     insn = ldl(s->pc);
324     s->pc += 4;
325     
326     cond = insn >> 28;
327     if (cond == 0xf)
328         goto illegal_op;
329     if (cond != 0xe) {
330         /* if not always execute, we generate a conditional jump to
331            next instruction */
332         gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
333         s->is_jmp = DISAS_JUMP_NEXT;
334     }
335     if (((insn & 0x0e000000) == 0 &&
336          (insn & 0x00000090) != 0x90) ||
337         ((insn & 0x0e000000) == (1 << 25))) {
338         int set_cc, logic_cc, shiftop;
339         
340         op1 = (insn >> 21) & 0xf;
341         set_cc = (insn >> 20) & 1;
342         logic_cc = table_logic_cc[op1] & set_cc;
343
344         /* data processing instruction */
345         if (insn & (1 << 25)) {
346             /* immediate operand */
347             val = insn & 0xff;
348             shift = ((insn >> 8) & 0xf) * 2;
349             if (shift)
350                 val = (val >> shift) | (val << (32 - shift));
351             gen_op_movl_T1_im(val);
352             /* XXX: is CF modified ? */
353         } else {
354             /* register */
355             rm = (insn) & 0xf;
356             gen_movl_T1_reg(s, rm);
357             shiftop = (insn >> 5) & 3;
358             if (!(insn & (1 << 4))) {
359                 shift = (insn >> 7) & 0x1f;
360                 if (shift != 0) {
361                     if (logic_cc) {
362                         gen_shift_T1_im_cc[shiftop](shift);
363                     } else {
364                         gen_shift_T1_im[shiftop](shift);
365                     }
366                 }
367             } else {
368                 rs = (insn >> 8) & 0xf;
369                 gen_movl_T0_reg(s, rs);
370                 if (logic_cc) {
371                     gen_shift_T1_T0_cc[shiftop]();
372                 } else {
373                     gen_shift_T1_T0[shiftop]();
374                 }
375             }
376         }
377         if (op1 != 0x0f && op1 != 0x0d) {
378             rn = (insn >> 16) & 0xf;
379             gen_movl_T0_reg(s, rn);
380         }
381         rd = (insn >> 12) & 0xf;
382         switch(op1) {
383         case 0x00:
384             gen_op_andl_T0_T1();
385             gen_movl_reg_T0(s, rd);
386             if (logic_cc)
387                 gen_op_logic_T0_cc();
388             break;
389         case 0x01:
390             gen_op_xorl_T0_T1();
391             gen_movl_reg_T0(s, rd);
392             if (logic_cc)
393                 gen_op_logic_T0_cc();
394             break;
395         case 0x02:
396             if (set_cc)
397                 gen_op_subl_T0_T1_cc();
398             else
399                 gen_op_subl_T0_T1();
400             gen_movl_reg_T0(s, rd);
401             break;
402         case 0x03:
403             if (set_cc)
404                 gen_op_rsbl_T0_T1_cc();
405             else
406                 gen_op_rsbl_T0_T1();
407             gen_movl_reg_T0(s, rd);
408             break;
409         case 0x04:
410             if (set_cc)
411                 gen_op_addl_T0_T1_cc();
412             else
413                 gen_op_addl_T0_T1();
414             gen_movl_reg_T0(s, rd);
415             break;
416         case 0x05:
417             if (set_cc)
418                 gen_op_adcl_T0_T1_cc();
419             else
420                 gen_op_adcl_T0_T1();
421             gen_movl_reg_T0(s, rd);
422             break;
423         case 0x06:
424             if (set_cc)
425                 gen_op_sbcl_T0_T1_cc();
426             else
427                 gen_op_sbcl_T0_T1();
428             gen_movl_reg_T0(s, rd);
429             break;
430         case 0x07:
431             if (set_cc)
432                 gen_op_rscl_T0_T1_cc();
433             else
434                 gen_op_rscl_T0_T1();
435             gen_movl_reg_T0(s, rd);
436             break;
437         case 0x08:
438             if (set_cc) {
439                 gen_op_andl_T0_T1();
440                 gen_op_logic_T0_cc();
441             }
442             break;
443         case 0x09:
444             if (set_cc) {
445                 gen_op_xorl_T0_T1();
446                 gen_op_logic_T0_cc();
447             }
448             break;
449         case 0x0a:
450             if (set_cc) {
451                 gen_op_subl_T0_T1_cc();
452             }
453             break;
454         case 0x0b:
455             if (set_cc) {
456                 gen_op_addl_T0_T1_cc();
457             }
458             break;
459         case 0x0c:
460             gen_op_orl_T0_T1();
461             gen_movl_reg_T0(s, rd);
462             if (logic_cc)
463                 gen_op_logic_T0_cc();
464             break;
465         case 0x0d:
466             gen_movl_reg_T1(s, rd);
467             if (logic_cc)
468                 gen_op_logic_T1_cc();
469             break;
470         case 0x0e:
471             gen_op_bicl_T0_T1();
472             gen_movl_reg_T0(s, rd);
473             if (logic_cc)
474                 gen_op_logic_T0_cc();
475             break;
476         default:
477         case 0x0f:
478             gen_op_notl_T1();
479             gen_movl_reg_T1(s, rd);
480             if (logic_cc)
481                 gen_op_logic_T1_cc();
482             break;
483         }
484     } else {
485         /* other instructions */
486         op1 = (insn >> 24) & 0xf;
487         switch(op1) {
488         case 0x0:
489         case 0x1:
490             sh = (insn >> 5) & 3;
491             if (sh == 0) {
492                 if (op1 == 0x0) {
493                     rd = (insn >> 16) & 0xf;
494                     rn = (insn >> 12) & 0xf;
495                     rs = (insn >> 8) & 0xf;
496                     rm = (insn) & 0xf;
497                     if (!(insn & (1 << 23))) {
498                         /* 32 bit mul */
499                         gen_movl_T0_reg(s, rs);
500                         gen_movl_T1_reg(s, rm);
501                         gen_op_mul_T0_T1();
502                         if (insn & (1 << 21)) {
503                             gen_movl_T1_reg(s, rn);
504                             gen_op_addl_T0_T1();
505                         }
506                         if (insn & (1 << 20)) 
507                             gen_op_logic_T0_cc();
508                         gen_movl_reg_T0(s, rd);
509                     } else {
510                         /* 64 bit mul */
511                         gen_movl_T0_reg(s, rs);
512                         gen_movl_T1_reg(s, rm);
513                         if (insn & (1 << 22)) 
514                             gen_op_imull_T0_T1();
515                         else
516                             gen_op_mull_T0_T1();
517                         if (insn & (1 << 21)) 
518                             gen_op_addq_T0_T1(rn, rd);
519                         if (insn & (1 << 20)) 
520                             gen_op_logicq_cc();
521                         gen_movl_reg_T0(s, rn);
522                         gen_movl_reg_T1(s, rd);
523                     }
524                 } else {
525                     /* SWP instruction */
526                     rn = (insn >> 16) & 0xf;
527                     rd = (insn >> 12) & 0xf;
528                     rm = (insn) & 0xf;
529                     
530                     gen_movl_T0_reg(s, rm);
531                     gen_movl_T1_reg(s, rn);
532                     if (insn & (1 << 22)) {
533                         gen_op_swpb_T0_T1();
534                     } else {
535                         gen_op_swpl_T0_T1();
536                     }
537                     gen_movl_reg_T0(s, rd);
538                 }
539             } else {
540                 /* load/store half word */
541                 rn = (insn >> 16) & 0xf;
542                 rd = (insn >> 12) & 0xf;
543                 gen_movl_T1_reg(s, rn);
544                 gen_add_datah_offset(s, insn);
545                 if (insn & (1 << 20)) {
546                     /* load */
547                     switch(sh) {
548                     case 1:
549                         gen_op_lduw_T0_T1();
550                         break;
551                     case 2:
552                         gen_op_ldsb_T0_T1();
553                         break;
554                     default:
555                     case 3:
556                         gen_op_ldsw_T0_T1();
557                         break;
558                     }
559                     gen_movl_reg_T0(s, rd);
560                 } else {
561                     /* store */
562                     gen_movl_T0_reg(s, rd);
563                     gen_op_stw_T0_T1();
564                 }
565                 if (!(insn & (1 << 24))) {
566                     gen_add_datah_offset(s, insn);
567                     gen_movl_reg_T1(s, rn);
568                 } else if (insn & (1 << 21)) {
569                     gen_movl_reg_T1(s, rn);
570                 }
571             }
572             break;
573         case 0x4:
574         case 0x5:
575         case 0x6:
576         case 0x7:
577             /* load/store byte/word */
578             rn = (insn >> 16) & 0xf;
579             rd = (insn >> 12) & 0xf;
580             gen_movl_T1_reg(s, rn);
581             if (insn & (1 << 24))
582                 gen_add_data_offset(s, insn);
583             if (insn & (1 << 20)) {
584                 /* load */
585                 if (insn & (1 << 22))
586                     gen_op_ldub_T0_T1();
587                 else
588                     gen_op_ldl_T0_T1();
589                 gen_movl_reg_T0(s, rd);
590             } else {
591                 /* store */
592                 gen_movl_T0_reg(s, rd);
593                 if (insn & (1 << 22))
594                     gen_op_stb_T0_T1();
595                 else
596                     gen_op_stl_T0_T1();
597             }
598             if (!(insn & (1 << 24))) {
599                 gen_add_data_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             break;
605         case 0x08:
606         case 0x09:
607             {
608                 int j, n;
609                 /* load/store multiple words */
610                 /* XXX: store correct base if write back */
611                 if (insn & (1 << 22))
612                     goto illegal_op; /* only usable in supervisor mode */
613                 rn = (insn >> 16) & 0xf;
614                 gen_movl_T1_reg(s, rn);
615                 
616                 /* compute total size */
617                 n = 0;
618                 for(i=0;i<16;i++) {
619                     if (insn & (1 << i))
620                         n++;
621                 }
622                 /* XXX: test invalid n == 0 case ? */
623                 if (insn & (1 << 23)) {
624                     if (insn & (1 << 24)) {
625                         /* pre increment */
626                         gen_op_addl_T1_im(4);
627                     } else {
628                         /* post increment */
629                     }
630                 } else {
631                     if (insn & (1 << 24)) {
632                         /* pre decrement */
633                         gen_op_addl_T1_im(-(n * 4));
634                     } else {
635                         /* post decrement */
636                         if (n != 1)
637                             gen_op_addl_T1_im(-((n - 1) * 4));
638                     }
639                 }
640                 j = 0;
641                 for(i=0;i<16;i++) {
642                     if (insn & (1 << i)) {
643                         if (insn & (1 << 20)) {
644                             /* load */
645                             gen_op_ldl_T0_T1();
646                             gen_movl_reg_T0(s, i);
647                         } else {
648                             /* store */
649                             if (i == 15) {
650                                 /* special case: r15 = PC + 12 */
651                                 val = (long)s->pc + 8;
652                                 gen_op_movl_TN_im[0](val);
653                             } else {
654                                 gen_movl_T0_reg(s, i);
655                             }
656                             gen_op_stl_T0_T1();
657                         }
658                         j++;
659                         /* no need to add after the last transfer */
660                         if (j != n)
661                             gen_op_addl_T1_im(4);
662                     }
663                 }
664                 if (insn & (1 << 21)) {
665                     /* write back */
666                     if (insn & (1 << 23)) {
667                         if (insn & (1 << 24)) {
668                             /* pre increment */
669                         } else {
670                             /* post increment */
671                             gen_op_addl_T1_im(4);
672                         }
673                     } else {
674                         if (insn & (1 << 24)) {
675                             /* pre decrement */
676                             if (n != 1)
677                                 gen_op_addl_T1_im(-((n - 1) * 4));
678                         } else {
679                             /* post decrement */
680                             gen_op_addl_T1_im(-(n * 4));
681                         }
682                     }
683                     gen_movl_reg_T1(s, rn);
684                 }
685             }
686             break;
687         case 0xa:
688         case 0xb:
689             {
690                 int offset;
691                 
692                 /* branch (and link) */
693                 val = (int)s->pc;
694                 if (insn & (1 << 24)) {
695                     gen_op_movl_T0_im(val);
696                     gen_op_movl_reg_TN[0][14]();
697                 }
698                 offset = (((int)insn << 8) >> 8);
699                 val += (offset << 2) + 4;
700                 gen_op_jmp((long)s->tb, val);
701                 s->is_jmp = DISAS_TB_JUMP;
702             }
703             break;
704         case 0xf:
705             /* swi */
706             gen_op_movl_T0_im((long)s->pc);
707             gen_op_movl_reg_TN[0][15]();
708             gen_op_swi();
709             s->is_jmp = DISAS_JUMP;
710             break;
711         case 0xc:
712         case 0xd:
713             rd = (insn >> 12) & 0x7;
714             rn = (insn >> 16) & 0xf;
715             gen_movl_T1_reg(s, rn);
716             val = (insn) & 0xff;
717             if (!(insn & (1 << 23)))
718                 val = -val;
719             switch((insn >> 8) & 0xf) {
720             case 0x1:
721                 /* load/store */
722                 if ((insn & (1 << 24)))
723                     gen_op_addl_T1_im(val);
724                 /* XXX: do it */
725                 if (!(insn & (1 << 24)))
726                     gen_op_addl_T1_im(val);
727                 if (insn & (1 << 21))
728                     gen_movl_reg_T1(s, rn);
729                 break;
730             case 0x2:
731                 {
732                     int n, i;
733                     /* load store multiple */
734                     if ((insn & (1 << 24)))
735                         gen_op_addl_T1_im(val);
736                     switch(insn & 0x00408000) {
737                     case 0x00008000: n = 1; break;
738                     case 0x00400000: n = 2; break;
739                     case 0x00408000: n = 3; break;
740                     default: n = 4; break;
741                     }
742                     for(i = 0;i < n; i++) {
743                         /* XXX: do it */
744                     }
745                     if (!(insn & (1 << 24)))
746                         gen_op_addl_T1_im(val);
747                     if (insn & (1 << 21))
748                         gen_movl_reg_T1(s, rn);
749                 }
750                 break;
751             default:
752                 goto illegal_op;
753             }
754             break;
755         case 0x0e:
756             /* float ops */
757             /* XXX: do it */
758             switch((insn >> 20) & 0xf) {
759             case 0x2: /* wfs */
760                 break;
761             case 0x3: /* rfs */
762                 break;
763             case 0x4: /* wfc */
764                 break;
765             case 0x5: /* rfc */
766                 break;
767             default:
768                 goto illegal_op;
769             }
770             break;
771         default:
772         illegal_op:
773             gen_op_movl_T0_im((long)s->pc - 4);
774             gen_op_movl_reg_TN[0][15]();
775             gen_op_undef_insn();
776             s->is_jmp = DISAS_JUMP;
777             break;
778         }
779     }
780 }
781
782 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
783    basic block 'tb'. If search_pc is TRUE, also generate PC
784    information for each intermediate instruction. */
785 static inline int gen_intermediate_code_internal(CPUState *env, 
786                                                  TranslationBlock *tb, 
787                                                  int search_pc)
788 {
789     DisasContext dc1, *dc = &dc1;
790     uint16_t *gen_opc_end;
791     int j, lj;
792     uint8_t *pc_start;
793     
794     /* generate intermediate code */
795     pc_start = (uint8_t *)tb->pc;
796        
797     dc->tb = tb;
798
799     gen_opc_ptr = gen_opc_buf;
800     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
801     gen_opparam_ptr = gen_opparam_buf;
802
803     dc->is_jmp = DISAS_NEXT;
804     dc->pc = pc_start;
805     lj = -1;
806     do {
807         if (search_pc) {
808             j = gen_opc_ptr - gen_opc_buf;
809             if (lj < j) {
810                 lj++;
811                 while (lj < j)
812                     gen_opc_instr_start[lj++] = 0;
813             }
814             gen_opc_pc[lj] = (uint32_t)dc->pc;
815             gen_opc_instr_start[lj] = 1;
816         }
817         disas_arm_insn(dc);
818     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
819              (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
820     switch(dc->is_jmp) {
821     case DISAS_JUMP_NEXT:
822     case DISAS_NEXT:
823         gen_op_jmp((long)dc->tb, (long)dc->pc);
824         break;
825     default:
826     case DISAS_JUMP:
827         /* indicate that the hash table must be used to find the next TB */
828         gen_op_movl_T0_0();
829         gen_op_exit_tb();
830         break;
831     case DISAS_TB_JUMP:
832         /* nothing more to generate */
833         break;
834     }
835     *gen_opc_ptr = INDEX_op_end;
836
837 #ifdef DEBUG_DISAS
838     if (loglevel) {
839         fprintf(logfile, "----------------\n");
840         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
841         disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
842         fprintf(logfile, "\n");
843
844         fprintf(logfile, "OP:\n");
845         dump_ops(gen_opc_buf, gen_opparam_buf);
846         fprintf(logfile, "\n");
847     }
848 #endif
849     if (!search_pc)
850         tb->size = dc->pc - pc_start;
851     return 0;
852 }
853
854 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
855 {
856     return gen_intermediate_code_internal(env, tb, 0);
857 }
858
859 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
860 {
861     return gen_intermediate_code_internal(env, tb, 1);
862 }
863
864 CPUARMState *cpu_arm_init(void)
865 {
866     CPUARMState *env;
867
868     cpu_exec_init();
869
870     env = malloc(sizeof(CPUARMState));
871     if (!env)
872         return NULL;
873     memset(env, 0, sizeof(CPUARMState));
874     return env;
875 }
876
877 void cpu_arm_close(CPUARMState *env)
878 {
879     free(env);
880 }
881
882 void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
883 {
884     int i;
885
886     for(i=0;i<16;i++) {
887         fprintf(f, "R%02d=%08x", i, env->regs[i]);
888         if ((i % 4) == 3)
889             fprintf(f, "\n");
890         else
891             fprintf(f, " ");
892     }
893     fprintf(f, "PSR=%08x %c%c%c%c\n", 
894             env->cpsr, 
895             env->cpsr & (1 << 31) ? 'N' : '-',
896             env->cpsr & (1 << 30) ? 'Z' : '-',
897             env->cpsr & (1 << 29) ? 'C' : '-',
898             env->cpsr & (1 << 28) ? 'V' : '-');
899 }