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