0.7.1-alt1
[qemu] / qemu / target-arm / translate.c
1 /*
2  *  ARM translation
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *  Copyright (c) 2005 CodeSourcery, LLC
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
26
27 #include "cpu.h"
28 #include "exec-all.h"
29 #include "disas.h"
30
31 /* internal defines */
32 typedef struct DisasContext {
33     target_ulong pc;
34     int is_jmp;
35     /* Nonzero if this instruction has been conditionally skipped.  */
36     int condjmp;
37     /* The label that will be jumped to when the instruction is skipped.  */
38     int condlabel;
39     struct TranslationBlock *tb;
40     int singlestep_enabled;
41     int thumb;
42 } DisasContext;
43
44 #define DISAS_JUMP_NEXT 4
45
46 /* XXX: move that elsewhere */
47 static uint16_t *gen_opc_ptr;
48 static uint32_t *gen_opparam_ptr;
49 extern FILE *logfile;
50 extern int loglevel;
51
52 enum {
53 #define DEF(s, n, copy_size) INDEX_op_ ## s,
54 #include "opc.h"
55 #undef DEF
56     NB_OPS,
57 };
58
59 #include "gen-op.h"
60
61 static GenOpFunc1 *gen_test_cc[14] = {
62     gen_op_test_eq,
63     gen_op_test_ne,
64     gen_op_test_cs,
65     gen_op_test_cc,
66     gen_op_test_mi,
67     gen_op_test_pl,
68     gen_op_test_vs,
69     gen_op_test_vc,
70     gen_op_test_hi,
71     gen_op_test_ls,
72     gen_op_test_ge,
73     gen_op_test_lt,
74     gen_op_test_gt,
75     gen_op_test_le,
76 };
77
78 const uint8_t table_logic_cc[16] = {
79     1, /* and */
80     1, /* xor */
81     0, /* sub */
82     0, /* rsb */
83     0, /* add */
84     0, /* adc */
85     0, /* sbc */
86     0, /* rsc */
87     1, /* andl */
88     1, /* xorl */
89     0, /* cmp */
90     0, /* cmn */
91     1, /* orr */
92     1, /* mov */
93     1, /* bic */
94     1, /* mvn */
95 };
96     
97 static GenOpFunc1 *gen_shift_T1_im[4] = {
98     gen_op_shll_T1_im,
99     gen_op_shrl_T1_im,
100     gen_op_sarl_T1_im,
101     gen_op_rorl_T1_im,
102 };
103
104 static GenOpFunc *gen_shift_T1_0[4] = {
105     NULL,
106     gen_op_shrl_T1_0,
107     gen_op_sarl_T1_0,
108     gen_op_rrxl_T1,
109 };
110
111 static GenOpFunc1 *gen_shift_T2_im[4] = {
112     gen_op_shll_T2_im,
113     gen_op_shrl_T2_im,
114     gen_op_sarl_T2_im,
115     gen_op_rorl_T2_im,
116 };
117
118 static GenOpFunc *gen_shift_T2_0[4] = {
119     NULL,
120     gen_op_shrl_T2_0,
121     gen_op_sarl_T2_0,
122     gen_op_rrxl_T2,
123 };
124
125 static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
126     gen_op_shll_T1_im_cc,
127     gen_op_shrl_T1_im_cc,
128     gen_op_sarl_T1_im_cc,
129     gen_op_rorl_T1_im_cc,
130 };
131
132 static GenOpFunc *gen_shift_T1_0_cc[4] = {
133     NULL,
134     gen_op_shrl_T1_0_cc,
135     gen_op_sarl_T1_0_cc,
136     gen_op_rrxl_T1_cc,
137 };
138
139 static GenOpFunc *gen_shift_T1_T0[4] = {
140     gen_op_shll_T1_T0,
141     gen_op_shrl_T1_T0,
142     gen_op_sarl_T1_T0,
143     gen_op_rorl_T1_T0,
144 };
145
146 static GenOpFunc *gen_shift_T1_T0_cc[4] = {
147     gen_op_shll_T1_T0_cc,
148     gen_op_shrl_T1_T0_cc,
149     gen_op_sarl_T1_T0_cc,
150     gen_op_rorl_T1_T0_cc,
151 };
152
153 static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
154     {
155         gen_op_movl_T0_r0,
156         gen_op_movl_T0_r1,
157         gen_op_movl_T0_r2,
158         gen_op_movl_T0_r3,
159         gen_op_movl_T0_r4,
160         gen_op_movl_T0_r5,
161         gen_op_movl_T0_r6,
162         gen_op_movl_T0_r7,
163         gen_op_movl_T0_r8,
164         gen_op_movl_T0_r9,
165         gen_op_movl_T0_r10,
166         gen_op_movl_T0_r11,
167         gen_op_movl_T0_r12,
168         gen_op_movl_T0_r13,
169         gen_op_movl_T0_r14,
170         gen_op_movl_T0_r15,
171     },
172     {
173         gen_op_movl_T1_r0,
174         gen_op_movl_T1_r1,
175         gen_op_movl_T1_r2,
176         gen_op_movl_T1_r3,
177         gen_op_movl_T1_r4,
178         gen_op_movl_T1_r5,
179         gen_op_movl_T1_r6,
180         gen_op_movl_T1_r7,
181         gen_op_movl_T1_r8,
182         gen_op_movl_T1_r9,
183         gen_op_movl_T1_r10,
184         gen_op_movl_T1_r11,
185         gen_op_movl_T1_r12,
186         gen_op_movl_T1_r13,
187         gen_op_movl_T1_r14,
188         gen_op_movl_T1_r15,
189     },
190     {
191         gen_op_movl_T2_r0,
192         gen_op_movl_T2_r1,
193         gen_op_movl_T2_r2,
194         gen_op_movl_T2_r3,
195         gen_op_movl_T2_r4,
196         gen_op_movl_T2_r5,
197         gen_op_movl_T2_r6,
198         gen_op_movl_T2_r7,
199         gen_op_movl_T2_r8,
200         gen_op_movl_T2_r9,
201         gen_op_movl_T2_r10,
202         gen_op_movl_T2_r11,
203         gen_op_movl_T2_r12,
204         gen_op_movl_T2_r13,
205         gen_op_movl_T2_r14,
206         gen_op_movl_T2_r15,
207     },
208 };
209
210 static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
211     {
212         gen_op_movl_r0_T0,
213         gen_op_movl_r1_T0,
214         gen_op_movl_r2_T0,
215         gen_op_movl_r3_T0,
216         gen_op_movl_r4_T0,
217         gen_op_movl_r5_T0,
218         gen_op_movl_r6_T0,
219         gen_op_movl_r7_T0,
220         gen_op_movl_r8_T0,
221         gen_op_movl_r9_T0,
222         gen_op_movl_r10_T0,
223         gen_op_movl_r11_T0,
224         gen_op_movl_r12_T0,
225         gen_op_movl_r13_T0,
226         gen_op_movl_r14_T0,
227         gen_op_movl_r15_T0,
228     },
229     {
230         gen_op_movl_r0_T1,
231         gen_op_movl_r1_T1,
232         gen_op_movl_r2_T1,
233         gen_op_movl_r3_T1,
234         gen_op_movl_r4_T1,
235         gen_op_movl_r5_T1,
236         gen_op_movl_r6_T1,
237         gen_op_movl_r7_T1,
238         gen_op_movl_r8_T1,
239         gen_op_movl_r9_T1,
240         gen_op_movl_r10_T1,
241         gen_op_movl_r11_T1,
242         gen_op_movl_r12_T1,
243         gen_op_movl_r13_T1,
244         gen_op_movl_r14_T1,
245         gen_op_movl_r15_T1,
246     },
247 };
248
249 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
250     gen_op_movl_T0_im,
251     gen_op_movl_T1_im,
252     gen_op_movl_T2_im,
253 };
254
255 static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
256     gen_op_shll_T0_im_thumb,
257     gen_op_shrl_T0_im_thumb,
258     gen_op_sarl_T0_im_thumb,
259 };
260
261 static inline void gen_bx(DisasContext *s)
262 {
263   s->is_jmp = DISAS_UPDATE;
264   gen_op_bx_T0();
265 }
266
267 static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
268 {
269     int val;
270
271     if (reg == 15) {
272         /* normaly, since we updated PC, we need only to add one insn */
273         if (s->thumb)
274             val = (long)s->pc + 2;
275         else
276             val = (long)s->pc + 4;
277         gen_op_movl_TN_im[t](val);
278     } else {
279         gen_op_movl_TN_reg[t][reg]();
280     }
281 }
282
283 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
284 {
285     gen_movl_TN_reg(s, reg, 0);
286 }
287
288 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
289 {
290     gen_movl_TN_reg(s, reg, 1);
291 }
292
293 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
294 {
295     gen_movl_TN_reg(s, reg, 2);
296 }
297
298 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
299 {
300     gen_op_movl_reg_TN[t][reg]();
301     if (reg == 15) {
302         s->is_jmp = DISAS_JUMP;
303     }
304 }
305
306 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
307 {
308     gen_movl_reg_TN(s, reg, 0);
309 }
310
311 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
312 {
313     gen_movl_reg_TN(s, reg, 1);
314 }
315
316 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
317 {
318     int val, rm, shift, shiftop;
319
320     if (!(insn & (1 << 25))) {
321         /* immediate */
322         val = insn & 0xfff;
323         if (!(insn & (1 << 23)))
324             val = -val;
325         if (val != 0)
326             gen_op_addl_T1_im(val);
327     } else {
328         /* shift/register */
329         rm = (insn) & 0xf;
330         shift = (insn >> 7) & 0x1f;
331         gen_movl_T2_reg(s, rm);
332         shiftop = (insn >> 5) & 3;
333         if (shift != 0) {
334             gen_shift_T2_im[shiftop](shift);
335         } else if (shiftop != 0) {
336             gen_shift_T2_0[shiftop]();
337         }
338         if (!(insn & (1 << 23)))
339             gen_op_subl_T1_T2();
340         else
341             gen_op_addl_T1_T2();
342     }
343 }
344
345 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
346 {
347     int val, rm;
348     
349     if (insn & (1 << 22)) {
350         /* immediate */
351         val = (insn & 0xf) | ((insn >> 4) & 0xf0);
352         if (!(insn & (1 << 23)))
353             val = -val;
354         if (val != 0)
355             gen_op_addl_T1_im(val);
356     } else {
357         /* register */
358         rm = (insn) & 0xf;
359         gen_movl_T2_reg(s, rm);
360         if (!(insn & (1 << 23)))
361             gen_op_subl_T1_T2();
362         else
363             gen_op_addl_T1_T2();
364     }
365 }
366
367 #define VFP_OP(name)                      \
368 static inline void gen_vfp_##name(int dp) \
369 {                                         \
370     if (dp)                               \
371         gen_op_vfp_##name##d();           \
372     else                                  \
373         gen_op_vfp_##name##s();           \
374 }
375
376 VFP_OP(add)
377 VFP_OP(sub)
378 VFP_OP(mul)
379 VFP_OP(div)
380 VFP_OP(neg)
381 VFP_OP(abs)
382 VFP_OP(sqrt)
383 VFP_OP(cmp)
384 VFP_OP(cmpe)
385 VFP_OP(F1_ld0)
386 VFP_OP(uito)
387 VFP_OP(sito)
388 VFP_OP(toui)
389 VFP_OP(touiz)
390 VFP_OP(tosi)
391 VFP_OP(tosiz)
392 VFP_OP(ld)
393 VFP_OP(st)
394
395 #undef VFP_OP
396
397 static inline long
398 vfp_reg_offset (int dp, int reg)
399 {
400     if (dp)
401         return offsetof(CPUARMState, vfp.regs[reg]);
402     else if (reg & 1) {
403         return offsetof(CPUARMState, vfp.regs[reg >> 1])
404           + offsetof(CPU_DoubleU, l.upper);
405     } else {
406         return offsetof(CPUARMState, vfp.regs[reg >> 1])
407           + offsetof(CPU_DoubleU, l.lower);
408     }
409 }
410 static inline void gen_mov_F0_vreg(int dp, int reg)
411 {
412     if (dp)
413         gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
414     else
415         gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
416 }
417
418 static inline void gen_mov_F1_vreg(int dp, int reg)
419 {
420     if (dp)
421         gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
422     else
423         gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
424 }
425
426 static inline void gen_mov_vreg_F0(int dp, int reg)
427 {
428     if (dp)
429         gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
430     else
431         gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
432 }
433
434 /* Disassemble a VFP instruction.  Returns nonzero if an error occured
435    (ie. an undefined instruction).  */
436 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
437 {
438     uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
439     int dp, veclen;
440
441     dp = ((insn & 0xf00) == 0xb00);
442     switch ((insn >> 24) & 0xf) {
443     case 0xe:
444         if (insn & (1 << 4)) {
445             /* single register transfer */
446             if ((insn & 0x6f) != 0x00)
447                 return 1;
448             rd = (insn >> 12) & 0xf;
449             if (dp) {
450                 if (insn & 0x80)
451                     return 1;
452                 rn = (insn >> 16) & 0xf;
453                 /* Get the existing value even for arm->vfp moves because
454                    we only set half the register.  */
455                 gen_mov_F0_vreg(1, rn);
456                 gen_op_vfp_mrrd();
457                 if (insn & (1 << 20)) {
458                     /* vfp->arm */
459                     if (insn & (1 << 21))
460                         gen_movl_reg_T1(s, rd);
461                     else
462                         gen_movl_reg_T0(s, rd);
463                 } else {
464                     /* arm->vfp */
465                     if (insn & (1 << 21))
466                         gen_movl_T1_reg(s, rd);
467                     else
468                         gen_movl_T0_reg(s, rd);
469                     gen_op_vfp_mdrr();
470                     gen_mov_vreg_F0(dp, rn);
471                 }
472             } else {
473                 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
474                 if (insn & (1 << 20)) {
475                     /* vfp->arm */
476                     if (insn & (1 << 21)) {
477                         /* system register */
478                         switch (rn) {
479                         case 0: /* fpsid */
480                             n = 0x0091A0000;
481                             break;
482                         case 2: /* fpscr */
483                             if (rd == 15)
484                                 gen_op_vfp_movl_T0_fpscr_flags();
485                             else
486                                 gen_op_vfp_movl_T0_fpscr();
487                             break;
488                         default:
489                             return 1;
490                         }
491                     } else {
492                         gen_mov_F0_vreg(0, rn);
493                         gen_op_vfp_mrs();
494                     }
495                     if (rd == 15) {
496                         /* This will only set the 4 flag bits */
497                         gen_op_movl_psr_T0();
498                     } else
499                         gen_movl_reg_T0(s, rd);
500                 } else {
501                     /* arm->vfp */
502                     gen_movl_T0_reg(s, rd);
503                     if (insn & (1 << 21)) {
504                         /* system register */
505                         switch (rn) {
506                         case 0: /* fpsid */
507                             /* Writes are ignored.  */
508                             break;
509                         case 2: /* fpscr */
510                             gen_op_vfp_movl_fpscr_T0();
511                             /* This could change vector settings, so jump to
512                                the next instuction.  */
513                             gen_op_movl_T0_im(s->pc);
514                             gen_movl_reg_T0(s, 15);
515                             s->is_jmp = DISAS_UPDATE;
516                             break;
517                         default:
518                             return 1;
519                         }
520                     } else {
521                         gen_op_vfp_msr();
522                         gen_mov_vreg_F0(0, rn);
523                     }
524                 }
525             }
526         } else {
527             /* data processing */
528             /* The opcode is in bits 23, 21, 20 and 6.  */
529             op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
530             if (dp) {
531                 if (op == 15) {
532                     /* rn is opcode */
533                     rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
534                 } else {
535                     /* rn is register number */
536                     if (insn & (1 << 7))
537                         return 1;
538                     rn = (insn >> 16) & 0xf;
539                 }
540
541                 if (op == 15 && (rn == 15 || rn > 17)) {
542                     /* Integer or single precision destination.  */
543                     rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
544                 } else {
545                     if (insn & (1 << 22))
546                         return 1;
547                     rd = (insn >> 12) & 0xf;
548                 }
549
550                 if (op == 15 && (rn == 16 || rn == 17)) {
551                     /* Integer source.  */
552                     rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
553                 } else {
554                     if (insn & (1 << 5))
555                         return 1;
556                     rm = insn & 0xf;
557                 }
558             } else {
559                 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
560                 if (op == 15 && rn == 15) {
561                     /* Double precision destination.  */
562                     if (insn & (1 << 22))
563                         return 1;
564                     rd = (insn >> 12) & 0xf;
565                 } else
566                     rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
567                 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
568             }
569
570             veclen = env->vfp.vec_len;
571             if (op == 15 && rn > 3)
572                 veclen = 0;
573
574             /* Shut up compiler warnings.  */
575             delta_m = 0;
576             delta_d = 0;
577             bank_mask = 0;
578             
579             if (veclen > 0) {
580                 if (dp)
581                     bank_mask = 0xc;
582                 else
583                     bank_mask = 0x18;
584
585                 /* Figure out what type of vector operation this is.  */
586                 if ((rd & bank_mask) == 0) {
587                     /* scalar */
588                     veclen = 0;
589                 } else {
590                     if (dp)
591                         delta_d = (env->vfp.vec_stride >> 1) + 1;
592                     else
593                         delta_d = env->vfp.vec_stride + 1;
594
595                     if ((rm & bank_mask) == 0) {
596                         /* mixed scalar/vector */
597                         delta_m = 0;
598                     } else {
599                         /* vector */
600                         delta_m = delta_d;
601                     }
602                 }
603             }
604
605             /* Load the initial operands.  */
606             if (op == 15) {
607                 switch (rn) {
608                 case 16:
609                 case 17:
610                     /* Integer source */
611                     gen_mov_F0_vreg(0, rm);
612                     break;
613                 case 8:
614                 case 9:
615                     /* Compare */
616                     gen_mov_F0_vreg(dp, rd);
617                     gen_mov_F1_vreg(dp, rm);
618                     break;
619                 case 10:
620                 case 11:
621                     /* Compare with zero */
622                     gen_mov_F0_vreg(dp, rd);
623                     gen_vfp_F1_ld0(dp);
624                     break;
625                 default:
626                     /* One source operand.  */
627                     gen_mov_F0_vreg(dp, rm);
628                 }
629             } else {
630                 /* Two source operands.  */
631                 gen_mov_F0_vreg(dp, rn);
632                 gen_mov_F1_vreg(dp, rm);
633             }
634
635             for (;;) {
636                 /* Perform the calculation.  */
637                 switch (op) {
638                 case 0: /* mac: fd + (fn * fm) */
639                     gen_vfp_mul(dp);
640                     gen_mov_F1_vreg(dp, rd);
641                     gen_vfp_add(dp);
642                     break;
643                 case 1: /* nmac: fd - (fn * fm) */
644                     gen_vfp_mul(dp);
645                     gen_vfp_neg(dp);
646                     gen_mov_F1_vreg(dp, rd);
647                     gen_vfp_add(dp);
648                     break;
649                 case 2: /* msc: -fd + (fn * fm) */
650                     gen_vfp_mul(dp);
651                     gen_mov_F1_vreg(dp, rd);
652                     gen_vfp_sub(dp);
653                     break;
654                 case 3: /* nmsc: -fd - (fn * fm)  */
655                     gen_vfp_mul(dp);
656                     gen_mov_F1_vreg(dp, rd);
657                     gen_vfp_add(dp);
658                     gen_vfp_neg(dp);
659                     break;
660                 case 4: /* mul: fn * fm */
661                     gen_vfp_mul(dp);
662                     break;
663                 case 5: /* nmul: -(fn * fm) */
664                     gen_vfp_mul(dp);
665                     gen_vfp_neg(dp);
666                     break;
667                 case 6: /* add: fn + fm */
668                     gen_vfp_add(dp);
669                     break;
670                 case 7: /* sub: fn - fm */
671                     gen_vfp_sub(dp);
672                     break;
673                 case 8: /* div: fn / fm */
674                     gen_vfp_div(dp);
675                     break;
676                 case 15: /* extension space */
677                     switch (rn) {
678                     case 0: /* cpy */
679                         /* no-op */
680                         break;
681                     case 1: /* abs */
682                         gen_vfp_abs(dp);
683                         break;
684                     case 2: /* neg */
685                         gen_vfp_neg(dp);
686                         break;
687                     case 3: /* sqrt */
688                         gen_vfp_sqrt(dp);
689                         break;
690                     case 8: /* cmp */
691                         gen_vfp_cmp(dp);
692                         break;
693                     case 9: /* cmpe */
694                         gen_vfp_cmpe(dp);
695                         break;
696                     case 10: /* cmpz */
697                         gen_vfp_cmp(dp);
698                         break;
699                     case 11: /* cmpez */
700                         gen_vfp_F1_ld0(dp);
701                         gen_vfp_cmpe(dp);
702                         break;
703                     case 15: /* single<->double conversion */
704                         if (dp)
705                             gen_op_vfp_fcvtsd();
706                         else
707                             gen_op_vfp_fcvtds();
708                         break;
709                     case 16: /* fuito */
710                         gen_vfp_uito(dp);
711                         break;
712                     case 17: /* fsito */
713                         gen_vfp_sito(dp);
714                         break;
715                     case 24: /* ftoui */
716                         gen_vfp_toui(dp);
717                         break;
718                     case 25: /* ftouiz */
719                         gen_vfp_touiz(dp);
720                         break;
721                     case 26: /* ftosi */
722                         gen_vfp_tosi(dp);
723                         break;
724                     case 27: /* ftosiz */
725                         gen_vfp_tosiz(dp);
726                         break;
727                     default: /* undefined */
728                         printf ("rn:%d\n", rn);
729                         return 1;
730                     }
731                     break;
732                 default: /* undefined */
733                     printf ("op:%d\n", op);
734                     return 1;
735                 }
736
737                 /* Write back the result.  */
738                 if (op == 15 && (rn >= 8 && rn <= 11))
739                     ; /* Comparison, do nothing.  */
740                 else if (op == 15 && rn > 17)
741                     /* Integer result.  */
742                     gen_mov_vreg_F0(0, rd);
743                 else if (op == 15 && rn == 15)
744                     /* conversion */
745                     gen_mov_vreg_F0(!dp, rd);
746                 else
747                     gen_mov_vreg_F0(dp, rd);
748
749                 /* break out of the loop if we have finished  */
750                 if (veclen == 0)
751                     break;
752
753                 if (op == 15 && delta_m == 0) {
754                     /* single source one-many */
755                     while (veclen--) {
756                         rd = ((rd + delta_d) & (bank_mask - 1))
757                              | (rd & bank_mask);
758                         gen_mov_vreg_F0(dp, rd);
759                     }
760                     break;
761                 }
762                 /* Setup the next operands.  */
763                 veclen--;
764                 rd = ((rd + delta_d) & (bank_mask - 1))
765                      | (rd & bank_mask);
766
767                 if (op == 15) {
768                     /* One source operand.  */
769                     rm = ((rm + delta_m) & (bank_mask - 1))
770                          | (rm & bank_mask);
771                     gen_mov_F0_vreg(dp, rm);
772                 } else {
773                     /* Two source operands.  */
774                     rn = ((rn + delta_d) & (bank_mask - 1))
775                          | (rn & bank_mask);
776                     gen_mov_F0_vreg(dp, rn);
777                     if (delta_m) {
778                         rm = ((rm + delta_m) & (bank_mask - 1))
779                              | (rm & bank_mask);
780                         gen_mov_F1_vreg(dp, rm);
781                     }
782                 }
783             }
784         }
785         break;
786     case 0xc:
787     case 0xd:
788         if (dp && (insn & (1 << 22))) {
789             /* two-register transfer */
790             rn = (insn >> 16) & 0xf;
791             rd = (insn >> 12) & 0xf;
792             if (dp) {
793                 if (insn & (1 << 5))
794                     return 1;
795                 rm = insn & 0xf;
796             } else
797                 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
798
799             if (insn & (1 << 20)) {
800                 /* vfp->arm */
801                 if (dp) {
802                     gen_mov_F0_vreg(1, rm);
803                     gen_op_vfp_mrrd();
804                     gen_movl_reg_T0(s, rd);
805                     gen_movl_reg_T1(s, rn);
806                 } else {
807                     gen_mov_F0_vreg(0, rm);
808                     gen_op_vfp_mrs();
809                     gen_movl_reg_T0(s, rn);
810                     gen_mov_F0_vreg(0, rm + 1);
811                     gen_op_vfp_mrs();
812                     gen_movl_reg_T0(s, rd);
813                 }
814             } else {
815                 /* arm->vfp */
816                 if (dp) {
817                     gen_movl_T0_reg(s, rd);
818                     gen_movl_T1_reg(s, rn);
819                     gen_op_vfp_mdrr();
820                     gen_mov_vreg_F0(1, rm);
821                 } else {
822                     gen_movl_T0_reg(s, rn);
823                     gen_op_vfp_msr();
824                     gen_mov_vreg_F0(0, rm);
825                     gen_movl_T0_reg(s, rd);
826                     gen_op_vfp_msr();
827                     gen_mov_vreg_F0(0, rm + 1);
828                 }
829             }
830         } else {
831             /* Load/store */
832             rn = (insn >> 16) & 0xf;
833             if (dp)
834                 rd = (insn >> 12) & 0xf;
835             else
836                 rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
837             gen_movl_T1_reg(s, rn);
838             if ((insn & 0x01200000) == 0x01000000) {
839                 /* Single load/store */
840                 offset = (insn & 0xff) << 2;
841                 if ((insn & (1 << 23)) == 0)
842                     offset = -offset;
843                 gen_op_addl_T1_im(offset);
844                 if (insn & (1 << 20)) {
845                     gen_vfp_ld(dp);
846                     gen_mov_vreg_F0(dp, rd);
847                 } else {
848                     gen_mov_F0_vreg(dp, rd);
849                     gen_vfp_st(dp);
850                 }
851             } else {
852                 /* load/store multiple */
853                 if (dp)
854                     n = (insn >> 1) & 0x7f;
855                 else
856                     n = insn & 0xff;
857
858                 if (insn & (1 << 24)) /* pre-decrement */
859                     gen_op_addl_T1_im(-((insn & 0xff) << 2));
860
861                 if (dp)
862                     offset = 8;
863                 else
864                     offset = 4;
865                 for (i = 0; i < n; i++) {
866                     if (insn & (1 << 20)) {
867                         /* load */
868                         gen_vfp_ld(dp);
869                         gen_mov_vreg_F0(dp, rd + i);
870                     } else {
871                         /* store */
872                         gen_mov_F0_vreg(dp, rd + i);
873                         gen_vfp_st(dp);
874                     }
875                     gen_op_addl_T1_im(offset);
876                 }
877                 if (insn & (1 << 21)) {
878                     /* writeback */
879                     if (insn & (1 << 24))
880                         offset = -offset * n;
881                     else if (dp && (insn & 1))
882                         offset = 4;
883                     else
884                         offset = 0;
885
886                     if (offset != 0)
887                         gen_op_addl_T1_im(offset);
888                     gen_movl_reg_T1(s, rn);
889                 }
890             }
891         }
892         break;
893     default:
894         /* Should never happen.  */
895         return 1;
896     }
897     return 0;
898 }
899
900 static inline void gen_jmp (DisasContext *s, uint32_t dest)
901 {
902     if (__builtin_expect(s->singlestep_enabled, 0)) {
903         /* An indirect jump so that we still trigger the debug exception.  */
904         if (s->thumb)
905           dest |= 1;
906         gen_op_movl_T0_im(dest);
907         gen_bx(s);
908     } else {
909         gen_op_jmp0((long)s->tb, dest);
910         s->is_jmp = DISAS_TB_JUMP;
911     }
912 }
913
914 static void disas_arm_insn(CPUState * env, DisasContext *s)
915 {
916     unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
917     
918     insn = ldl(s->pc);
919     s->pc += 4;
920     
921     cond = insn >> 28;
922     if (cond == 0xf){
923         /* Unconditional instructions.  */
924         if ((insn & 0x0d70f000) == 0x0550f000)
925             return; /* PLD */
926         else if ((insn & 0x0e000000) == 0x0a000000) {
927             /* branch link and change to thumb (blx <offset>) */
928             int32_t offset;
929
930             val = (uint32_t)s->pc;
931             gen_op_movl_T0_im(val);
932             gen_movl_reg_T0(s, 14);
933             /* Sign-extend the 24-bit offset */
934             offset = (((int32_t)insn) << 8) >> 8;
935             /* offset * 4 + bit24 * 2 + (thumb bit) */
936             val += (offset << 2) | ((insn >> 23) & 2) | 1;
937             /* pipeline offset */
938             val += 4;
939             gen_op_movl_T0_im(val);
940             gen_bx(s);
941             return;
942         } else if ((insn & 0x0fe00000) == 0x0c400000) {
943             /* Coprocessor double register transfer.  */
944         } else if ((insn & 0x0f000010) == 0x0e000010) {
945             /* Additional coprocessor register transfer.  */
946         }
947         goto illegal_op;
948     }
949     if (cond != 0xe) {
950         /* if not always execute, we generate a conditional jump to
951            next instruction */
952         s->condlabel = gen_new_label();
953         gen_test_cc[cond ^ 1](s->condlabel);
954         s->condjmp = 1;
955         //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
956         //s->is_jmp = DISAS_JUMP_NEXT;
957     }
958     if ((insn & 0x0f900000) == 0x03000000) {
959         if ((insn & 0x0ff0f000) != 0x0360f000)
960             goto illegal_op;
961         /* CPSR = immediate */
962         val = insn & 0xff;
963         shift = ((insn >> 8) & 0xf) * 2;
964         if (shift)
965             val = (val >> shift) | (val << (32 - shift));
966         gen_op_movl_T0_im(val);
967         if (insn & (1 << 19))
968             gen_op_movl_psr_T0();
969     } else if ((insn & 0x0f900000) == 0x01000000
970                && (insn & 0x00000090) != 0x00000090) {
971         /* miscellaneous instructions */
972         op1 = (insn >> 21) & 3;
973         sh = (insn >> 4) & 0xf;
974         rm = insn & 0xf;
975         switch (sh) {
976         case 0x0: /* move program status register */
977             if (op1 & 2) {
978                 /* SPSR not accessible in user mode */
979                 goto illegal_op;
980             }
981             if (op1 & 1) {
982                 /* CPSR = reg */
983                 gen_movl_T0_reg(s, rm);
984                 if (insn & (1 << 19))
985                     gen_op_movl_psr_T0();
986             } else {
987                 /* reg = CPSR */
988                 rd = (insn >> 12) & 0xf;
989                 gen_op_movl_T0_psr();
990                 gen_movl_reg_T0(s, rd);
991             }
992             break;
993         case 0x1:
994             if (op1 == 1) {
995                 /* branch/exchange thumb (bx).  */
996                 gen_movl_T0_reg(s, rm);
997                 gen_bx(s);
998             } else if (op1 == 3) {
999                 /* clz */
1000                 rd = (insn >> 12) & 0xf;
1001                 gen_movl_T0_reg(s, rm);
1002                 gen_op_clz_T0();
1003                 gen_movl_reg_T0(s, rd);
1004             } else {
1005                 goto illegal_op;
1006             }
1007             break;
1008         case 0x3:
1009             if (op1 != 1)
1010               goto illegal_op;
1011
1012             /* branch link/exchange thumb (blx) */
1013             val = (uint32_t)s->pc;
1014             gen_op_movl_T0_im(val);
1015             gen_movl_reg_T0(s, 14);
1016             gen_movl_T0_reg(s, rm);
1017             gen_bx(s);
1018             break;
1019         case 0x5: /* saturating add/subtract */
1020             rd = (insn >> 12) & 0xf;
1021             rn = (insn >> 16) & 0xf;
1022             gen_movl_T0_reg(s, rm);
1023             gen_movl_T1_reg(s, rn);
1024             if (op1 & 2)
1025                 gen_op_double_T1_saturate();
1026             if (op1 & 1)
1027                 gen_op_subl_T0_T1_saturate();
1028             else
1029                 gen_op_addl_T0_T1_saturate();
1030             gen_movl_reg_T0(s, rd);
1031             break;
1032         case 0x8: /* signed multiply */
1033         case 0xa:
1034         case 0xc:
1035         case 0xe:
1036             rs = (insn >> 8) & 0xf;
1037             rn = (insn >> 12) & 0xf;
1038             rd = (insn >> 16) & 0xf;
1039             if (op1 == 1) {
1040                 /* (32 * 16) >> 16 */
1041                 gen_movl_T0_reg(s, rm);
1042                 gen_movl_T1_reg(s, rs);
1043                 if (sh & 4)
1044                     gen_op_sarl_T1_im(16);
1045                 else
1046                     gen_op_sxl_T1();
1047                 gen_op_imulw_T0_T1();
1048                 if ((sh & 2) == 0) {
1049                     gen_movl_T1_reg(s, rn);
1050                     gen_op_addl_T0_T1_setq();
1051                 }
1052                 gen_movl_reg_T0(s, rd);
1053             } else {
1054                 /* 16 * 16 */
1055                 gen_movl_T0_reg(s, rm);
1056                 if (sh & 2)
1057                     gen_op_sarl_T0_im(16);
1058                 else
1059                     gen_op_sxl_T0();
1060                 gen_movl_T1_reg(s, rs);
1061                 if (sh & 4)
1062                     gen_op_sarl_T1_im(16);
1063                 else
1064                     gen_op_sxl_T1();
1065                 if (op1 == 2) {
1066                     gen_op_imull_T0_T1();
1067                     gen_op_addq_T0_T1(rn, rd);
1068                     gen_movl_reg_T0(s, rn);
1069                     gen_movl_reg_T1(s, rd);
1070                 } else {
1071                     gen_op_mul_T0_T1();
1072                     if (op1 == 0) {
1073                         gen_movl_T1_reg(s, rn);
1074                         gen_op_addl_T0_T1_setq();
1075                     }
1076                     gen_movl_reg_T0(s, rd);
1077                 }
1078             }
1079             break;
1080         default:
1081             goto illegal_op;
1082         }
1083     } else if (((insn & 0x0e000000) == 0 &&
1084                 (insn & 0x00000090) != 0x90) ||
1085                ((insn & 0x0e000000) == (1 << 25))) {
1086         int set_cc, logic_cc, shiftop;
1087         
1088         op1 = (insn >> 21) & 0xf;
1089         set_cc = (insn >> 20) & 1;
1090         logic_cc = table_logic_cc[op1] & set_cc;
1091
1092         /* data processing instruction */
1093         if (insn & (1 << 25)) {
1094             /* immediate operand */
1095             val = insn & 0xff;
1096             shift = ((insn >> 8) & 0xf) * 2;
1097             if (shift)
1098                 val = (val >> shift) | (val << (32 - shift));
1099             gen_op_movl_T1_im(val);
1100             if (logic_cc && shift)
1101                 gen_op_mov_CF_T1();
1102         } else {
1103             /* register */
1104             rm = (insn) & 0xf;
1105             gen_movl_T1_reg(s, rm);
1106             shiftop = (insn >> 5) & 3;
1107             if (!(insn & (1 << 4))) {
1108                 shift = (insn >> 7) & 0x1f;
1109                 if (shift != 0) {
1110                     if (logic_cc) {
1111                         gen_shift_T1_im_cc[shiftop](shift);
1112                     } else {
1113                         gen_shift_T1_im[shiftop](shift);
1114                     }
1115                 } else if (shiftop != 0) {
1116                     if (logic_cc) {
1117                         gen_shift_T1_0_cc[shiftop]();
1118                     } else {
1119                         gen_shift_T1_0[shiftop]();
1120                     }
1121                 }
1122             } else {
1123                 rs = (insn >> 8) & 0xf;
1124                 gen_movl_T0_reg(s, rs);
1125                 if (logic_cc) {
1126                     gen_shift_T1_T0_cc[shiftop]();
1127                 } else {
1128                     gen_shift_T1_T0[shiftop]();
1129                 }
1130             }
1131         }
1132         if (op1 != 0x0f && op1 != 0x0d) {
1133             rn = (insn >> 16) & 0xf;
1134             gen_movl_T0_reg(s, rn);
1135         }
1136         rd = (insn >> 12) & 0xf;
1137         switch(op1) {
1138         case 0x00:
1139             gen_op_andl_T0_T1();
1140             gen_movl_reg_T0(s, rd);
1141             if (logic_cc)
1142                 gen_op_logic_T0_cc();
1143             break;
1144         case 0x01:
1145             gen_op_xorl_T0_T1();
1146             gen_movl_reg_T0(s, rd);
1147             if (logic_cc)
1148                 gen_op_logic_T0_cc();
1149             break;
1150         case 0x02:
1151             if (set_cc)
1152                 gen_op_subl_T0_T1_cc();
1153             else
1154                 gen_op_subl_T0_T1();
1155             gen_movl_reg_T0(s, rd);
1156             break;
1157         case 0x03:
1158             if (set_cc)
1159                 gen_op_rsbl_T0_T1_cc();
1160             else
1161                 gen_op_rsbl_T0_T1();
1162             gen_movl_reg_T0(s, rd);
1163             break;
1164         case 0x04:
1165             if (set_cc)
1166                 gen_op_addl_T0_T1_cc();
1167             else
1168                 gen_op_addl_T0_T1();
1169             gen_movl_reg_T0(s, rd);
1170             break;
1171         case 0x05:
1172             if (set_cc)
1173                 gen_op_adcl_T0_T1_cc();
1174             else
1175                 gen_op_adcl_T0_T1();
1176             gen_movl_reg_T0(s, rd);
1177             break;
1178         case 0x06:
1179             if (set_cc)
1180                 gen_op_sbcl_T0_T1_cc();
1181             else
1182                 gen_op_sbcl_T0_T1();
1183             gen_movl_reg_T0(s, rd);
1184             break;
1185         case 0x07:
1186             if (set_cc)
1187                 gen_op_rscl_T0_T1_cc();
1188             else
1189                 gen_op_rscl_T0_T1();
1190             gen_movl_reg_T0(s, rd);
1191             break;
1192         case 0x08:
1193             if (set_cc) {
1194                 gen_op_andl_T0_T1();
1195                 gen_op_logic_T0_cc();
1196             }
1197             break;
1198         case 0x09:
1199             if (set_cc) {
1200                 gen_op_xorl_T0_T1();
1201                 gen_op_logic_T0_cc();
1202             }
1203             break;
1204         case 0x0a:
1205             if (set_cc) {
1206                 gen_op_subl_T0_T1_cc();
1207             }
1208             break;
1209         case 0x0b:
1210             if (set_cc) {
1211                 gen_op_addl_T0_T1_cc();
1212             }
1213             break;
1214         case 0x0c:
1215             gen_op_orl_T0_T1();
1216             gen_movl_reg_T0(s, rd);
1217             if (logic_cc)
1218                 gen_op_logic_T0_cc();
1219             break;
1220         case 0x0d:
1221             gen_movl_reg_T1(s, rd);
1222             if (logic_cc)
1223                 gen_op_logic_T1_cc();
1224             break;
1225         case 0x0e:
1226             gen_op_bicl_T0_T1();
1227             gen_movl_reg_T0(s, rd);
1228             if (logic_cc)
1229                 gen_op_logic_T0_cc();
1230             break;
1231         default:
1232         case 0x0f:
1233             gen_op_notl_T1();
1234             gen_movl_reg_T1(s, rd);
1235             if (logic_cc)
1236                 gen_op_logic_T1_cc();
1237             break;
1238         }
1239     } else {
1240         /* other instructions */
1241         op1 = (insn >> 24) & 0xf;
1242         switch(op1) {
1243         case 0x0:
1244         case 0x1:
1245             /* multiplies, extra load/stores */
1246             sh = (insn >> 5) & 3;
1247             if (sh == 0) {
1248                 if (op1 == 0x0) {
1249                     rd = (insn >> 16) & 0xf;
1250                     rn = (insn >> 12) & 0xf;
1251                     rs = (insn >> 8) & 0xf;
1252                     rm = (insn) & 0xf;
1253                     if (((insn >> 22) & 3) == 0) {
1254                         /* 32 bit mul */
1255                         gen_movl_T0_reg(s, rs);
1256                         gen_movl_T1_reg(s, rm);
1257                         gen_op_mul_T0_T1();
1258                         if (insn & (1 << 21)) {
1259                             gen_movl_T1_reg(s, rn);
1260                             gen_op_addl_T0_T1();
1261                         }
1262                         if (insn & (1 << 20)) 
1263                             gen_op_logic_T0_cc();
1264                         gen_movl_reg_T0(s, rd);
1265                     } else {
1266                         /* 64 bit mul */
1267                         gen_movl_T0_reg(s, rs);
1268                         gen_movl_T1_reg(s, rm);
1269                         if (insn & (1 << 22)) 
1270                             gen_op_imull_T0_T1();
1271                         else
1272                             gen_op_mull_T0_T1();
1273                         if (insn & (1 << 21)) /* mult accumulate */
1274                             gen_op_addq_T0_T1(rn, rd);
1275                         if (!(insn & (1 << 23))) { /* double accumulate */
1276                             gen_op_addq_lo_T0_T1(rn);
1277                             gen_op_addq_lo_T0_T1(rd);
1278                         }
1279                         if (insn & (1 << 20)) 
1280                             gen_op_logicq_cc();
1281                         gen_movl_reg_T0(s, rn);
1282                         gen_movl_reg_T1(s, rd);
1283                     }
1284                 } else {
1285                     rn = (insn >> 16) & 0xf;
1286                     rd = (insn >> 12) & 0xf;
1287                     if (insn & (1 << 23)) {
1288                         /* load/store exclusive */
1289                         goto illegal_op;
1290                     } else {
1291                         /* SWP instruction */
1292                         rm = (insn) & 0xf;
1293                         
1294                         gen_movl_T0_reg(s, rm);
1295                         gen_movl_T1_reg(s, rn);
1296                         if (insn & (1 << 22)) {
1297                             gen_op_swpb_T0_T1();
1298                         } else {
1299                             gen_op_swpl_T0_T1();
1300                         }
1301                         gen_movl_reg_T0(s, rd);
1302                     }
1303                 }
1304             } else {
1305                 /* Misc load/store */
1306                 rn = (insn >> 16) & 0xf;
1307                 rd = (insn >> 12) & 0xf;
1308                 gen_movl_T1_reg(s, rn);
1309                 if (insn & (1 << 24))
1310                     gen_add_datah_offset(s, insn);
1311                 if (insn & (1 << 20)) {
1312                     /* load */
1313                     switch(sh) {
1314                     case 1:
1315                         gen_op_lduw_T0_T1();
1316                         break;
1317                     case 2:
1318                         gen_op_ldsb_T0_T1();
1319                         break;
1320                     default:
1321                     case 3:
1322                         gen_op_ldsw_T0_T1();
1323                         break;
1324                     }
1325                     gen_movl_reg_T0(s, rd);
1326                 } else if (sh & 2) {
1327                     /* doubleword */
1328                     if (sh & 1) {
1329                         /* store */
1330                         gen_movl_T0_reg(s, rd);
1331                         gen_op_stl_T0_T1();
1332                         gen_op_addl_T1_im(4);
1333                         gen_movl_T0_reg(s, rd + 1);
1334                         gen_op_stl_T0_T1();
1335                         if ((insn & (1 << 24)) || (insn & (1 << 20)))
1336                             gen_op_addl_T1_im(-4);
1337                     } else {
1338                         /* load */
1339                         gen_op_ldl_T0_T1();
1340                         gen_movl_reg_T0(s, rd);
1341                         gen_op_addl_T1_im(4);
1342                         gen_op_ldl_T0_T1();
1343                         gen_movl_reg_T0(s, rd + 1);
1344                         if ((insn & (1 << 24)) || (insn & (1 << 20)))
1345                             gen_op_addl_T1_im(-4);
1346                     }
1347                 } else {
1348                     /* store */
1349                     gen_movl_T0_reg(s, rd);
1350                     gen_op_stw_T0_T1();
1351                 }
1352                 if (!(insn & (1 << 24))) {
1353                     gen_add_datah_offset(s, insn);
1354                     gen_movl_reg_T1(s, rn);
1355                 } else if (insn & (1 << 21)) {
1356                     gen_movl_reg_T1(s, rn);
1357                 }
1358             }
1359             break;
1360         case 0x4:
1361         case 0x5:
1362         case 0x6:
1363         case 0x7:
1364             /* load/store byte/word */
1365             rn = (insn >> 16) & 0xf;
1366             rd = (insn >> 12) & 0xf;
1367             gen_movl_T1_reg(s, rn);
1368             if (insn & (1 << 24))
1369                 gen_add_data_offset(s, insn);
1370             if (insn & (1 << 20)) {
1371                 /* load */
1372                 if (insn & (1 << 22))
1373                     gen_op_ldub_T0_T1();
1374                 else
1375                     gen_op_ldl_T0_T1();
1376                 if (rd == 15)
1377                     gen_bx(s);
1378                 else
1379                     gen_movl_reg_T0(s, rd);
1380             } else {
1381                 /* store */
1382                 gen_movl_T0_reg(s, rd);
1383                 if (insn & (1 << 22))
1384                     gen_op_stb_T0_T1();
1385                 else
1386                     gen_op_stl_T0_T1();
1387             }
1388             if (!(insn & (1 << 24))) {
1389                 gen_add_data_offset(s, insn);
1390                 gen_movl_reg_T1(s, rn);
1391             } else if (insn & (1 << 21))
1392                 gen_movl_reg_T1(s, rn); {
1393             }
1394             break;
1395         case 0x08:
1396         case 0x09:
1397             {
1398                 int j, n;
1399                 /* load/store multiple words */
1400                 /* XXX: store correct base if write back */
1401                 if (insn & (1 << 22))
1402                     goto illegal_op; /* only usable in supervisor mode */
1403                 rn = (insn >> 16) & 0xf;
1404                 gen_movl_T1_reg(s, rn);
1405                 
1406                 /* compute total size */
1407                 n = 0;
1408                 for(i=0;i<16;i++) {
1409                     if (insn & (1 << i))
1410                         n++;
1411                 }
1412                 /* XXX: test invalid n == 0 case ? */
1413                 if (insn & (1 << 23)) {
1414                     if (insn & (1 << 24)) {
1415                         /* pre increment */
1416                         gen_op_addl_T1_im(4);
1417                     } else {
1418                         /* post increment */
1419                     }
1420                 } else {
1421                     if (insn & (1 << 24)) {
1422                         /* pre decrement */
1423                         gen_op_addl_T1_im(-(n * 4));
1424                     } else {
1425                         /* post decrement */
1426                         if (n != 1)
1427                             gen_op_addl_T1_im(-((n - 1) * 4));
1428                     }
1429                 }
1430                 j = 0;
1431                 for(i=0;i<16;i++) {
1432                     if (insn & (1 << i)) {
1433                         if (insn & (1 << 20)) {
1434                             /* load */
1435                             gen_op_ldl_T0_T1();
1436                             if (i == 15)
1437                                 gen_bx(s);
1438                             else
1439                                 gen_movl_reg_T0(s, i);
1440                         } else {
1441                             /* store */
1442                             if (i == 15) {
1443                                 /* special case: r15 = PC + 12 */
1444                                 val = (long)s->pc + 8;
1445                                 gen_op_movl_TN_im[0](val);
1446                             } else {
1447                                 gen_movl_T0_reg(s, i);
1448                             }
1449                             gen_op_stl_T0_T1();
1450                         }
1451                         j++;
1452                         /* no need to add after the last transfer */
1453                         if (j != n)
1454                             gen_op_addl_T1_im(4);
1455                     }
1456                 }
1457                 if (insn & (1 << 21)) {
1458                     /* write back */
1459                     if (insn & (1 << 23)) {
1460                         if (insn & (1 << 24)) {
1461                             /* pre increment */
1462                         } else {
1463                             /* post increment */
1464                             gen_op_addl_T1_im(4);
1465                         }
1466                     } else {
1467                         if (insn & (1 << 24)) {
1468                             /* pre decrement */
1469                             if (n != 1)
1470                                 gen_op_addl_T1_im(-((n - 1) * 4));
1471                         } else {
1472                             /* post decrement */
1473                             gen_op_addl_T1_im(-(n * 4));
1474                         }
1475                     }
1476                     gen_movl_reg_T1(s, rn);
1477                 }
1478             }
1479             break;
1480         case 0xa:
1481         case 0xb:
1482             {
1483                 int32_t offset;
1484                 
1485                 /* branch (and link) */
1486                 val = (int32_t)s->pc;
1487                 if (insn & (1 << 24)) {
1488                     gen_op_movl_T0_im(val);
1489                     gen_op_movl_reg_TN[0][14]();
1490                 }
1491                 offset = (((int32_t)insn << 8) >> 8);
1492                 val += (offset << 2) + 4;
1493                 gen_jmp(s, val);
1494             }
1495             break;
1496         case 0xc:
1497         case 0xd:
1498         case 0xe:
1499             /* Coprocessor.  */
1500             op1 = (insn >> 8) & 0xf;
1501             switch (op1) {
1502             case 10:
1503             case 11:
1504                 if (disas_vfp_insn (env, s, insn))
1505                     goto illegal_op;
1506                 break;
1507             default:
1508                 /* unknown coprocessor.  */
1509                 goto illegal_op;
1510             }
1511             break;
1512         case 0xf:
1513             /* swi */
1514             gen_op_movl_T0_im((long)s->pc);
1515             gen_op_movl_reg_TN[0][15]();
1516             gen_op_swi();
1517             s->is_jmp = DISAS_JUMP;
1518             break;
1519         default:
1520         illegal_op:
1521             gen_op_movl_T0_im((long)s->pc - 4);
1522             gen_op_movl_reg_TN[0][15]();
1523             gen_op_undef_insn();
1524             s->is_jmp = DISAS_JUMP;
1525             break;
1526         }
1527     }
1528 }
1529
1530 static void disas_thumb_insn(DisasContext *s)
1531 {
1532     uint32_t val, insn, op, rm, rn, rd, shift, cond;
1533     int32_t offset;
1534     int i;
1535
1536     insn = lduw(s->pc);
1537     s->pc += 2;
1538     
1539     switch (insn >> 12) {
1540     case 0: case 1:
1541         rd = insn & 7;
1542         op = (insn >> 11) & 3;
1543         if (op == 3) {
1544             /* add/subtract */
1545             rn = (insn >> 3) & 7;
1546             gen_movl_T0_reg(s, rn);
1547             if (insn & (1 << 10)) {
1548                 /* immediate */
1549                 gen_op_movl_T1_im((insn >> 6) & 7);
1550             } else {
1551                 /* reg */
1552                 rm = (insn >> 6) & 7;
1553                 gen_movl_T1_reg(s, rm);
1554             }
1555             if (insn & (1 << 9))
1556                 gen_op_subl_T0_T1_cc();
1557             else
1558                 gen_op_addl_T0_T1_cc();
1559             gen_movl_reg_T0(s, rd);
1560         } else {
1561             /* shift immediate */
1562             rm = (insn >> 3) & 7;
1563             shift = (insn >> 6) & 0x1f;
1564             gen_movl_T0_reg(s, rm);
1565             gen_shift_T0_im_thumb[op](shift);
1566             gen_movl_reg_T0(s, rd);
1567         }
1568         break;
1569     case 2: case 3:
1570         /* arithmetic large immediate */
1571         op = (insn >> 11) & 3;
1572         rd = (insn >> 8) & 0x7;
1573         if (op == 0) {
1574             gen_op_movl_T0_im(insn & 0xff);
1575         } else {
1576             gen_movl_T0_reg(s, rd);
1577             gen_op_movl_T1_im(insn & 0xff);
1578         }
1579         switch (op) {
1580         case 0: /* mov */
1581             gen_op_logic_T0_cc();
1582             break;
1583         case 1: /* cmp */
1584             gen_op_subl_T0_T1_cc();
1585             break;
1586         case 2: /* add */
1587             gen_op_addl_T0_T1_cc();
1588             break;
1589         case 3: /* sub */
1590             gen_op_subl_T0_T1_cc();
1591             break;
1592         }
1593         if (op != 1)
1594             gen_movl_reg_T0(s, rd);
1595         break;
1596     case 4:
1597         if (insn & (1 << 11)) {
1598             rd = (insn >> 8) & 7;
1599             /* load pc-relative.  Bit 1 of PC is ignored.  */
1600             val = s->pc + 2 + ((insn & 0xff) * 4);
1601             val &= ~(uint32_t)2;
1602             gen_op_movl_T1_im(val);
1603             gen_op_ldl_T0_T1();
1604             gen_movl_reg_T0(s, rd);
1605             break;
1606         }
1607         if (insn & (1 << 10)) {
1608             /* data processing extended or blx */
1609             rd = (insn & 7) | ((insn >> 4) & 8);
1610             rm = (insn >> 3) & 0xf;
1611             op = (insn >> 8) & 3;
1612             switch (op) {
1613             case 0: /* add */
1614                 gen_movl_T0_reg(s, rd);
1615                 gen_movl_T1_reg(s, rm);
1616                 gen_op_addl_T0_T1();
1617                 gen_movl_reg_T0(s, rd);
1618                 break;
1619             case 1: /* cmp */
1620                 gen_movl_T0_reg(s, rd);
1621                 gen_movl_T1_reg(s, rm);
1622                 gen_op_subl_T0_T1_cc();
1623                 break;
1624             case 2: /* mov/cpy */
1625                 gen_movl_T0_reg(s, rm);
1626                 gen_movl_reg_T0(s, rd);
1627                 break;
1628             case 3:/* branch [and link] exchange thumb register */
1629                 if (insn & (1 << 7)) {
1630                     val = (uint32_t)s->pc | 1;
1631                     gen_op_movl_T1_im(val);
1632                     gen_movl_reg_T1(s, 14);
1633                 }
1634                 gen_movl_T0_reg(s, rm);
1635                 gen_bx(s);
1636                 break;
1637             }
1638             break;
1639         }
1640
1641         /* data processing register */
1642         rd = insn & 7;
1643         rm = (insn >> 3) & 7;
1644         op = (insn >> 6) & 0xf;
1645         if (op == 2 || op == 3 || op == 4 || op == 7) {
1646             /* the shift/rotate ops want the operands backwards */
1647             val = rm;
1648             rm = rd;
1649             rd = val;
1650             val = 1;
1651         } else {
1652             val = 0;
1653         }
1654
1655         if (op == 9) /* neg */
1656             gen_op_movl_T0_im(0);
1657         else if (op != 0xf) /* mvn doesn't read its first operand */
1658             gen_movl_T0_reg(s, rd);
1659
1660         gen_movl_T1_reg(s, rm);
1661         switch (op) {
1662         case 0x0: /* and */
1663             gen_op_andl_T0_T1();
1664             gen_op_logic_T0_cc();
1665             break;
1666         case 0x1: /* eor */
1667             gen_op_xorl_T0_T1();
1668             gen_op_logic_T0_cc();
1669             break;
1670         case 0x2: /* lsl */
1671             gen_op_shll_T1_T0_cc();
1672             break;
1673         case 0x3: /* lsr */
1674             gen_op_shrl_T1_T0_cc();
1675             break;
1676         case 0x4: /* asr */
1677             gen_op_sarl_T1_T0_cc();
1678             break;
1679         case 0x5: /* adc */
1680             gen_op_adcl_T0_T1_cc();
1681             break;
1682         case 0x6: /* sbc */
1683             gen_op_sbcl_T0_T1_cc();
1684             break;
1685         case 0x7: /* ror */
1686             gen_op_rorl_T1_T0_cc();
1687             break;
1688         case 0x8: /* tst */
1689             gen_op_andl_T0_T1();
1690             gen_op_logic_T0_cc();
1691             rd = 16;
1692             break;
1693         case 0x9: /* neg */
1694             gen_op_subl_T0_T1_cc();
1695             break;
1696         case 0xa: /* cmp */
1697             gen_op_subl_T0_T1_cc();
1698             rd = 16;
1699             break;
1700         case 0xb: /* cmn */
1701             gen_op_addl_T0_T1_cc();
1702             rd = 16;
1703             break;
1704         case 0xc: /* orr */
1705             gen_op_orl_T0_T1();
1706             gen_op_logic_T0_cc();
1707             break;
1708         case 0xd: /* mul */
1709             gen_op_mull_T0_T1();
1710             gen_op_logic_T0_cc();
1711             break;
1712         case 0xe: /* bic */
1713             gen_op_bicl_T0_T1();
1714             gen_op_logic_T0_cc();
1715             break;
1716         case 0xf: /* mvn */
1717             gen_op_notl_T1();
1718             gen_op_logic_T1_cc();
1719             val = 1;
1720             rm = rd;
1721             break;
1722         }
1723         if (rd != 16) {
1724             if (val)
1725                 gen_movl_reg_T1(s, rm);
1726             else
1727                 gen_movl_reg_T0(s, rd);
1728         }
1729         break;
1730
1731     case 5:
1732         /* load/store register offset.  */
1733         rd = insn & 7;
1734         rn = (insn >> 3) & 7;
1735         rm = (insn >> 6) & 7;
1736         op = (insn >> 9) & 7;
1737         gen_movl_T1_reg(s, rn);
1738         gen_movl_T2_reg(s, rm);
1739         gen_op_addl_T1_T2();
1740
1741         if (op < 3) /* store */
1742             gen_movl_T0_reg(s, rd);
1743
1744         switch (op) {
1745         case 0: /* str */
1746             gen_op_stl_T0_T1();
1747             break;
1748         case 1: /* strh */
1749             gen_op_stw_T0_T1();
1750             break;
1751         case 2: /* strb */
1752             gen_op_stb_T0_T1();
1753             break;
1754         case 3: /* ldrsb */
1755             gen_op_ldsb_T0_T1();
1756             break;
1757         case 4: /* ldr */
1758             gen_op_ldl_T0_T1();
1759             break;
1760         case 5: /* ldrh */
1761             gen_op_lduw_T0_T1();
1762             break;
1763         case 6: /* ldrb */
1764             gen_op_ldub_T0_T1();
1765             break;
1766         case 7: /* ldrsh */
1767             gen_op_ldsw_T0_T1();
1768             break;
1769         }
1770         if (op >= 3) /* load */
1771             gen_movl_reg_T0(s, rd);
1772         break;
1773
1774     case 6:
1775         /* load/store word immediate offset */
1776         rd = insn & 7;
1777         rn = (insn >> 3) & 7;
1778         gen_movl_T1_reg(s, rn);
1779         val = (insn >> 4) & 0x7c;
1780         gen_op_movl_T2_im(val);
1781         gen_op_addl_T1_T2();
1782
1783         if (insn & (1 << 11)) {
1784             /* load */
1785             gen_op_ldl_T0_T1();
1786             gen_movl_reg_T0(s, rd);
1787         } else {
1788             /* store */
1789             gen_movl_T0_reg(s, rd);
1790             gen_op_stl_T0_T1();
1791         }
1792         break;
1793
1794     case 7:
1795         /* load/store byte immediate offset */
1796         rd = insn & 7;
1797         rn = (insn >> 3) & 7;
1798         gen_movl_T1_reg(s, rn);
1799         val = (insn >> 6) & 0x1f;
1800         gen_op_movl_T2_im(val);
1801         gen_op_addl_T1_T2();
1802
1803         if (insn & (1 << 11)) {
1804             /* load */
1805             gen_op_ldub_T0_T1();
1806             gen_movl_reg_T0(s, rd);
1807         } else {
1808             /* store */
1809             gen_movl_T0_reg(s, rd);
1810             gen_op_stb_T0_T1();
1811         }
1812         break;
1813
1814     case 8:
1815         /* load/store halfword immediate offset */
1816         rd = insn & 7;
1817         rn = (insn >> 3) & 7;
1818         gen_movl_T1_reg(s, rn);
1819         val = (insn >> 5) & 0x3e;
1820         gen_op_movl_T2_im(val);
1821         gen_op_addl_T1_T2();
1822
1823         if (insn & (1 << 11)) {
1824             /* load */
1825             gen_op_lduw_T0_T1();
1826             gen_movl_reg_T0(s, rd);
1827         } else {
1828             /* store */
1829             gen_movl_T0_reg(s, rd);
1830             gen_op_stw_T0_T1();
1831         }
1832         break;
1833
1834     case 9:
1835         /* load/store from stack */
1836         rd = (insn >> 8) & 7;
1837         gen_movl_T1_reg(s, 13);
1838         val = (insn & 0xff) * 4;
1839         gen_op_movl_T2_im(val);
1840         gen_op_addl_T1_T2();
1841
1842         if (insn & (1 << 11)) {
1843             /* load */
1844             gen_op_ldl_T0_T1();
1845             gen_movl_reg_T0(s, rd);
1846         } else {
1847             /* store */
1848             gen_movl_T0_reg(s, rd);
1849             gen_op_stl_T0_T1();
1850         }
1851         break;
1852
1853     case 10:
1854         /* add to high reg */
1855         rd = (insn >> 8) & 7;
1856         if (insn & (1 << 11)) {
1857             /* SP */
1858             gen_movl_T0_reg(s, 13);
1859         } else {
1860             /* PC. bit 1 is ignored.  */
1861             gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
1862         }
1863         val = (insn & 0xff) * 4;
1864         gen_op_movl_T1_im(val);
1865         gen_op_addl_T0_T1();
1866         gen_movl_reg_T0(s, rd);
1867         break;
1868
1869     case 11:
1870         /* misc */
1871         op = (insn >> 8) & 0xf;
1872         switch (op) {
1873         case 0:
1874             /* adjust stack pointer */
1875             gen_movl_T1_reg(s, 13);
1876             val = (insn & 0x7f) * 4;
1877             if (insn & (1 << 7))
1878               val = -(int32_t)val;
1879             gen_op_movl_T2_im(val);
1880             gen_op_addl_T1_T2();
1881             gen_movl_reg_T1(s, 13);
1882             break;
1883
1884         case 4: case 5: case 0xc: case 0xd:
1885             /* push/pop */
1886             gen_movl_T1_reg(s, 13);
1887             if (insn & (1 << 8))
1888                 offset = 4;
1889             else
1890                 offset = 0;
1891             for (i = 0; i < 8; i++) {
1892                 if (insn & (1 << i))
1893                     offset += 4;
1894             }
1895             if ((insn & (1 << 11)) == 0) {
1896                 gen_op_movl_T2_im(-offset);
1897                 gen_op_addl_T1_T2();
1898             }
1899             gen_op_movl_T2_im(4);
1900             for (i = 0; i < 8; i++) {
1901                 if (insn & (1 << i)) {
1902                     if (insn & (1 << 11)) {
1903                         /* pop */
1904                         gen_op_ldl_T0_T1();
1905                         gen_movl_reg_T0(s, i);
1906                     } else {
1907                         /* push */
1908                         gen_movl_T0_reg(s, i);
1909                         gen_op_stl_T0_T1();
1910                     }
1911                     /* advance to the next address.  */
1912                     gen_op_addl_T1_T2();
1913                 }
1914             }
1915             if (insn & (1 << 8)) {
1916                 if (insn & (1 << 11)) {
1917                     /* pop pc */
1918                     gen_op_ldl_T0_T1();
1919                     /* don't set the pc until the rest of the instruction
1920                        has completed */
1921                 } else {
1922                     /* push lr */
1923                     gen_movl_T0_reg(s, 14);
1924                     gen_op_stl_T0_T1();
1925                 }
1926                 gen_op_addl_T1_T2();
1927             }
1928             if ((insn & (1 << 11)) == 0) {
1929                 gen_op_movl_T2_im(-offset);
1930                 gen_op_addl_T1_T2();
1931             }
1932             /* write back the new stack pointer */
1933             gen_movl_reg_T1(s, 13);
1934             /* set the new PC value */
1935             if ((insn & 0x0900) == 0x0900)
1936                 gen_bx(s);
1937             break;
1938
1939         default:
1940             goto undef;
1941         }
1942         break;
1943
1944     case 12:
1945         /* load/store multiple */
1946         rn = (insn >> 8) & 0x7;
1947         gen_movl_T1_reg(s, rn);
1948         gen_op_movl_T2_im(4);
1949         for (i = 0; i < 8; i++) {
1950             if (insn & (1 << i)) {
1951                 if (insn & (1 << 11)) {
1952                     /* load */
1953                     gen_op_ldl_T0_T1();
1954                     gen_movl_reg_T0(s, i);
1955                 } else {
1956                     /* store */
1957                     gen_movl_T0_reg(s, i);
1958                     gen_op_stl_T0_T1();
1959                 }
1960                 /* advance to the next address */
1961                 gen_op_addl_T1_T2();
1962             }
1963         }
1964         /* Base register writeback.  */
1965         gen_movl_reg_T1(s, rn);
1966         break;
1967
1968     case 13:
1969         /* conditional branch or swi */
1970         cond = (insn >> 8) & 0xf;
1971         if (cond == 0xe)
1972             goto undef;
1973
1974         if (cond == 0xf) {
1975             /* swi */
1976             gen_op_movl_T0_im((long)s->pc | 1);
1977             /* Don't set r15.  */
1978             gen_op_movl_reg_TN[0][15]();
1979             gen_op_swi();
1980             s->is_jmp = DISAS_JUMP;
1981             break;
1982         }
1983         /* generate a conditional jump to next instruction */
1984         s->condlabel = gen_new_label();
1985         gen_test_cc[cond ^ 1](s->condlabel);
1986         s->condjmp = 1;
1987         //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1988         //s->is_jmp = DISAS_JUMP_NEXT;
1989         gen_movl_T1_reg(s, 15);
1990
1991         /* jump to the offset */
1992         val = (uint32_t)s->pc + 2;
1993         offset = ((int32_t)insn << 24) >> 24;
1994         val += offset << 1;
1995         gen_jmp(s, val);
1996         break;
1997
1998     case 14:
1999         /* unconditional branch */
2000         if (insn & (1 << 11))
2001             goto undef; /* Second half of a blx */
2002         val = (uint32_t)s->pc;
2003         offset = ((int32_t)insn << 21) >> 21;
2004         val += (offset << 1) + 2;
2005         gen_jmp(s, val);
2006         break;
2007
2008     case 15:
2009         /* branch and link [and switch to arm] */
2010         offset = ((int32_t)insn << 21) >> 10;
2011         insn = lduw(s->pc);
2012         offset |= insn & 0x7ff;
2013
2014         val = (uint32_t)s->pc + 2;
2015         gen_op_movl_T1_im(val | 1);
2016         gen_movl_reg_T1(s, 14);
2017         
2018         val += offset << 1;
2019         if (insn & (1 << 11)) {
2020             /* bl */
2021             gen_jmp(s, val);
2022         } else {
2023             /* blx */
2024             val &= ~(uint32_t)2;
2025             gen_op_movl_T0_im(val);
2026             gen_bx(s);
2027         }
2028     }
2029     return;
2030 undef:
2031     gen_op_movl_T0_im((long)s->pc - 2);
2032     gen_op_movl_reg_TN[0][15]();
2033     gen_op_undef_insn();
2034     s->is_jmp = DISAS_JUMP;
2035 }
2036
2037 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
2038    basic block 'tb'. If search_pc is TRUE, also generate PC
2039    information for each intermediate instruction. */
2040 static inline int gen_intermediate_code_internal(CPUState *env, 
2041                                                  TranslationBlock *tb, 
2042                                                  int search_pc)
2043 {
2044     DisasContext dc1, *dc = &dc1;
2045     uint16_t *gen_opc_end;
2046     int j, lj;
2047     target_ulong pc_start;
2048     
2049     /* generate intermediate code */
2050     pc_start = tb->pc;
2051        
2052     dc->tb = tb;
2053
2054     gen_opc_ptr = gen_opc_buf;
2055     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2056     gen_opparam_ptr = gen_opparam_buf;
2057
2058     dc->is_jmp = DISAS_NEXT;
2059     dc->pc = pc_start;
2060     dc->singlestep_enabled = env->singlestep_enabled;
2061     dc->condjmp = 0;
2062     dc->thumb = env->thumb;
2063     nb_gen_labels = 0;
2064     lj = -1;
2065     do {
2066         if (env->nb_breakpoints > 0) {
2067             for(j = 0; j < env->nb_breakpoints; j++) {
2068                 if (env->breakpoints[j] == dc->pc) {
2069                     gen_op_movl_T0_im((long)dc->pc);
2070                     gen_op_movl_reg_TN[0][15]();
2071                     gen_op_debug();
2072                     dc->is_jmp = DISAS_JUMP;
2073                     break;
2074                 }
2075             }
2076         }
2077         if (search_pc) {
2078             j = gen_opc_ptr - gen_opc_buf;
2079             if (lj < j) {
2080                 lj++;
2081                 while (lj < j)
2082                     gen_opc_instr_start[lj++] = 0;
2083             }
2084             gen_opc_pc[lj] = dc->pc;
2085             gen_opc_instr_start[lj] = 1;
2086         }
2087
2088         if (env->thumb)
2089           disas_thumb_insn(dc);
2090         else
2091           disas_arm_insn(env, dc);
2092
2093         if (dc->condjmp && !dc->is_jmp) {
2094             gen_set_label(dc->condlabel);
2095             dc->condjmp = 0;
2096         }
2097         /* Translation stops when a conditional branch is enoutered.
2098          * Otherwise the subsequent code could get translated several times.
2099          */
2100     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2101              !env->singlestep_enabled &&
2102              (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2103     /* It this stage dc->condjmp will only be set when the skipped
2104      * instruction was a conditional branch, and teh PC has already been
2105      * written.  */
2106     if (__builtin_expect(env->singlestep_enabled, 0)) {
2107         /* Make sure the pc is updated, and raise a debug exception.  */
2108         if (dc->condjmp) {
2109             gen_op_debug();
2110             gen_set_label(dc->condlabel);
2111         }
2112         if (dc->condjmp || !dc->is_jmp) {
2113             gen_op_movl_T0_im((long)dc->pc);
2114             gen_op_movl_reg_TN[0][15]();
2115             dc->condjmp = 0;
2116         }
2117         gen_op_debug();
2118     } else {
2119         switch(dc->is_jmp) {
2120         case DISAS_NEXT:
2121             gen_op_jmp1((long)dc->tb, (long)dc->pc);
2122             break;
2123         default:
2124         case DISAS_JUMP:
2125         case DISAS_UPDATE:
2126             /* indicate that the hash table must be used to find the next TB */
2127             gen_op_movl_T0_0();
2128             gen_op_exit_tb();
2129             break;
2130         case DISAS_TB_JUMP:
2131             /* nothing more to generate */
2132             break;
2133         }
2134         if (dc->condjmp) {
2135             gen_set_label(dc->condlabel);
2136             gen_op_jmp1((long)dc->tb, (long)dc->pc);
2137             dc->condjmp = 0;
2138         }
2139     }
2140     *gen_opc_ptr = INDEX_op_end;
2141
2142 #ifdef DEBUG_DISAS
2143     if (loglevel & CPU_LOG_TB_IN_ASM) {
2144         fprintf(logfile, "----------------\n");
2145         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2146         target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
2147         fprintf(logfile, "\n");
2148         if (loglevel & (CPU_LOG_TB_OP)) {
2149             fprintf(logfile, "OP:\n");
2150             dump_ops(gen_opc_buf, gen_opparam_buf);
2151             fprintf(logfile, "\n");
2152         }
2153     }
2154 #endif
2155     if (!search_pc)
2156         tb->size = dc->pc - pc_start;
2157     return 0;
2158 }
2159
2160 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2161 {
2162     return gen_intermediate_code_internal(env, tb, 0);
2163 }
2164
2165 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2166 {
2167     return gen_intermediate_code_internal(env, tb, 1);
2168 }
2169
2170 CPUARMState *cpu_arm_init(void)
2171 {
2172     CPUARMState *env;
2173
2174     cpu_exec_init();
2175
2176     env = malloc(sizeof(CPUARMState));
2177     if (!env)
2178         return NULL;
2179     memset(env, 0, sizeof(CPUARMState));
2180     cpu_single_env = env;
2181     return env;
2182 }
2183
2184 void cpu_arm_close(CPUARMState *env)
2185 {
2186     free(env);
2187 }
2188
2189 void cpu_dump_state(CPUState *env, FILE *f, 
2190                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2191                     int flags)
2192 {
2193     int i;
2194     union {
2195         uint32_t i;
2196         float s;
2197     } s0, s1;
2198     CPU_DoubleU d;
2199
2200     for(i=0;i<16;i++) {
2201         cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2202         if ((i % 4) == 3)
2203             cpu_fprintf(f, "\n");
2204         else
2205             cpu_fprintf(f, " ");
2206     }
2207     cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 
2208              env->cpsr, 
2209             env->cpsr & (1 << 31) ? 'N' : '-',
2210             env->cpsr & (1 << 30) ? 'Z' : '-',
2211             env->cpsr & (1 << 29) ? 'C' : '-',
2212             env->cpsr & (1 << 28) ? 'V' : '-');
2213
2214     for (i = 0; i < 16; i++) {
2215         d.d = env->vfp.regs[i];
2216         s0.i = d.l.lower;
2217         s1.i = d.l.upper;
2218         cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
2219                     i * 2, (int)s0.i, s0.s,
2220                     i * 2 + 1, (int)s0.i, s0.s,
2221                     i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2222                     d.d);
2223     }
2224     cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
2225 }
2226
2227 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2228 {
2229     return addr;
2230 }
2231
2232 #if defined(CONFIG_USER_ONLY) 
2233
2234 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
2235                               int is_user, int is_softmmu)
2236 {
2237     env->cp15_6 = address;
2238     if (rw == 2) {
2239         env->exception_index = EXCP_PREFETCH_ABORT;
2240     } else {
2241         env->exception_index = EXCP_DATA_ABORT;
2242     }
2243     return 1;
2244 }
2245
2246 #else
2247
2248 #error not implemented
2249
2250 #endif