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