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