4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005 CodeSourcery, LLC
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.
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.
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
31 /* internal defines */
32 typedef struct DisasContext
{
35 /* Nonzero if this instruction has been conditionally skipped. */
37 /* The label that will be jumped to when the instruction is skipped. */
39 struct TranslationBlock
*tb
;
40 int singlestep_enabled
;
44 #define DISAS_JUMP_NEXT 4
46 /* XXX: move that elsewhere */
47 static uint16_t *gen_opc_ptr
;
48 static uint32_t *gen_opparam_ptr
;
53 #define DEF(s, n, copy_size) INDEX_op_ ## s,
61 static GenOpFunc1
*gen_test_cc
[14] = {
78 const uint8_t table_logic_cc
[16] = {
97 static GenOpFunc1
*gen_shift_T1_im
[4] = {
104 static GenOpFunc
*gen_shift_T1_0
[4] = {
111 static GenOpFunc1
*gen_shift_T2_im
[4] = {
118 static GenOpFunc
*gen_shift_T2_0
[4] = {
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
,
132 static GenOpFunc
*gen_shift_T1_0_cc
[4] = {
139 static GenOpFunc
*gen_shift_T1_T0
[4] = {
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
,
153 static GenOpFunc
*gen_op_movl_TN_reg
[3][16] = {
210 static GenOpFunc
*gen_op_movl_reg_TN
[2][16] = {
249 static GenOpFunc1
*gen_op_movl_TN_im
[3] = {
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
,
261 static inline void gen_bx(DisasContext
*s
)
263 s
->is_jmp
= DISAS_UPDATE
;
267 static inline void gen_movl_TN_reg(DisasContext
*s
, int reg
, int t
)
272 /* normaly, since we updated PC, we need only to add one insn */
274 val
= (long)s
->pc
+ 2;
276 val
= (long)s
->pc
+ 4;
277 gen_op_movl_TN_im
[t
](val
);
279 gen_op_movl_TN_reg
[t
][reg
]();
283 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
285 gen_movl_TN_reg(s
, reg
, 0);
288 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
290 gen_movl_TN_reg(s
, reg
, 1);
293 static inline void gen_movl_T2_reg(DisasContext
*s
, int reg
)
295 gen_movl_TN_reg(s
, reg
, 2);
298 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
300 gen_op_movl_reg_TN
[t
][reg
]();
302 s
->is_jmp
= DISAS_JUMP
;
306 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
308 gen_movl_reg_TN(s
, reg
, 0);
311 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
313 gen_movl_reg_TN(s
, reg
, 1);
316 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
)
318 int val
, rm
, shift
, shiftop
;
320 if (!(insn
& (1 << 25))) {
323 if (!(insn
& (1 << 23)))
326 gen_op_addl_T1_im(val
);
330 shift
= (insn
>> 7) & 0x1f;
331 gen_movl_T2_reg(s
, rm
);
332 shiftop
= (insn
>> 5) & 3;
334 gen_shift_T2_im
[shiftop
](shift
);
335 } else if (shiftop
!= 0) {
336 gen_shift_T2_0
[shiftop
]();
338 if (!(insn
& (1 << 23)))
345 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
)
349 if (insn
& (1 << 22)) {
351 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
352 if (!(insn
& (1 << 23)))
355 gen_op_addl_T1_im(val
);
359 gen_movl_T2_reg(s
, rm
);
360 if (!(insn
& (1 << 23)))
367 #define VFP_OP(name) \
368 static inline void gen_vfp_##name(int dp) \
371 gen_op_vfp_##name##d(); \
373 gen_op_vfp_##name##s(); \
398 vfp_reg_offset (int dp
, int reg
)
401 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
403 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
404 + offsetof(CPU_DoubleU
, l
.upper
);
406 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
407 + offsetof(CPU_DoubleU
, l
.lower
);
410 static inline void gen_mov_F0_vreg(int dp
, int reg
)
413 gen_op_vfp_getreg_F0d(vfp_reg_offset(dp
, reg
));
415 gen_op_vfp_getreg_F0s(vfp_reg_offset(dp
, reg
));
418 static inline void gen_mov_F1_vreg(int dp
, int reg
)
421 gen_op_vfp_getreg_F1d(vfp_reg_offset(dp
, reg
));
423 gen_op_vfp_getreg_F1s(vfp_reg_offset(dp
, reg
));
426 static inline void gen_mov_vreg_F0(int dp
, int reg
)
429 gen_op_vfp_setreg_F0d(vfp_reg_offset(dp
, reg
));
431 gen_op_vfp_setreg_F0s(vfp_reg_offset(dp
, reg
));
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
)
438 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
441 dp
= ((insn
& 0xf00) == 0xb00);
442 switch ((insn
>> 24) & 0xf) {
444 if (insn
& (1 << 4)) {
445 /* single register transfer */
446 if ((insn
& 0x6f) != 0x00)
448 rd
= (insn
>> 12) & 0xf;
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
);
457 if (insn
& (1 << 20)) {
459 if (insn
& (1 << 21))
460 gen_movl_reg_T1(s
, rd
);
462 gen_movl_reg_T0(s
, rd
);
465 if (insn
& (1 << 21))
466 gen_movl_T1_reg(s
, rd
);
468 gen_movl_T0_reg(s
, rd
);
470 gen_mov_vreg_F0(dp
, rn
);
473 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
474 if (insn
& (1 << 20)) {
476 if (insn
& (1 << 21)) {
477 /* system register */
484 gen_op_vfp_movl_T0_fpscr_flags();
486 gen_op_vfp_movl_T0_fpscr();
492 gen_mov_F0_vreg(0, rn
);
496 /* This will only set the 4 flag bits */
497 gen_op_movl_psr_T0();
499 gen_movl_reg_T0(s
, rd
);
502 gen_movl_T0_reg(s
, rd
);
503 if (insn
& (1 << 21)) {
504 /* system register */
507 /* Writes are ignored. */
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
;
522 gen_mov_vreg_F0(0, rn
);
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);
533 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
535 /* rn is register number */
538 rn
= (insn
>> 16) & 0xf;
541 if (op
== 15 && (rn
== 15 || rn
> 17)) {
542 /* Integer or single precision destination. */
543 rd
= ((insn
>> 11) & 0x1e) | ((insn
>> 22) & 1);
545 if (insn
& (1 << 22))
547 rd
= (insn
>> 12) & 0xf;
550 if (op
== 15 && (rn
== 16 || rn
== 17)) {
551 /* Integer source. */
552 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
559 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
560 if (op
== 15 && rn
== 15) {
561 /* Double precision destination. */
562 if (insn
& (1 << 22))
564 rd
= (insn
>> 12) & 0xf;
566 rd
= ((insn
>> 11) & 0x1e) | ((insn
>> 22) & 1);
567 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
570 veclen
= env
->vfp
.vec_len
;
571 if (op
== 15 && rn
> 3)
574 /* Shut up compiler warnings. */
585 /* Figure out what type of vector operation this is. */
586 if ((rd
& bank_mask
) == 0) {
591 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
593 delta_d
= env
->vfp
.vec_stride
+ 1;
595 if ((rm
& bank_mask
) == 0) {
596 /* mixed scalar/vector */
605 /* Load the initial operands. */
611 gen_mov_F0_vreg(0, rm
);
616 gen_mov_F0_vreg(dp
, rd
);
617 gen_mov_F1_vreg(dp
, rm
);
621 /* Compare with zero */
622 gen_mov_F0_vreg(dp
, rd
);
626 /* One source operand. */
627 gen_mov_F0_vreg(dp
, rm
);
630 /* Two source operands. */
631 gen_mov_F0_vreg(dp
, rn
);
632 gen_mov_F1_vreg(dp
, rm
);
636 /* Perform the calculation. */
638 case 0: /* mac: fd + (fn * fm) */
640 gen_mov_F1_vreg(dp
, rd
);
643 case 1: /* nmac: fd - (fn * fm) */
646 gen_mov_F1_vreg(dp
, rd
);
649 case 2: /* msc: -fd + (fn * fm) */
651 gen_mov_F1_vreg(dp
, rd
);
654 case 3: /* nmsc: -fd - (fn * fm) */
656 gen_mov_F1_vreg(dp
, rd
);
660 case 4: /* mul: fn * fm */
663 case 5: /* nmul: -(fn * fm) */
667 case 6: /* add: fn + fm */
670 case 7: /* sub: fn - fm */
673 case 8: /* div: fn / fm */
676 case 15: /* extension space */
703 case 15: /* single<->double conversion */
718 case 25: /* ftouiz */
724 case 27: /* ftosiz */
727 default: /* undefined */
728 printf ("rn:%d\n", rn
);
732 default: /* undefined */
733 printf ("op:%d\n", op
);
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)
745 gen_mov_vreg_F0(!dp
, rd
);
747 gen_mov_vreg_F0(dp
, rd
);
749 /* break out of the loop if we have finished */
753 if (op
== 15 && delta_m
== 0) {
754 /* single source one-many */
756 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
758 gen_mov_vreg_F0(dp
, rd
);
762 /* Setup the next operands. */
764 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
768 /* One source operand. */
769 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
771 gen_mov_F0_vreg(dp
, rm
);
773 /* Two source operands. */
774 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
776 gen_mov_F0_vreg(dp
, rn
);
778 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
780 gen_mov_F1_vreg(dp
, rm
);
788 if (dp
&& (insn
& (1 << 22))) {
789 /* two-register transfer */
790 rn
= (insn
>> 16) & 0xf;
791 rd
= (insn
>> 12) & 0xf;
797 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
799 if (insn
& (1 << 20)) {
802 gen_mov_F0_vreg(1, rm
);
804 gen_movl_reg_T0(s
, rd
);
805 gen_movl_reg_T1(s
, rn
);
807 gen_mov_F0_vreg(0, rm
);
809 gen_movl_reg_T0(s
, rn
);
810 gen_mov_F0_vreg(0, rm
+ 1);
812 gen_movl_reg_T0(s
, rd
);
817 gen_movl_T0_reg(s
, rd
);
818 gen_movl_T1_reg(s
, rn
);
820 gen_mov_vreg_F0(1, rm
);
822 gen_movl_T0_reg(s
, rn
);
824 gen_mov_vreg_F0(0, rm
);
825 gen_movl_T0_reg(s
, rd
);
827 gen_mov_vreg_F0(0, rm
+ 1);
832 rn
= (insn
>> 16) & 0xf;
834 rd
= (insn
>> 12) & 0xf;
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)
843 gen_op_addl_T1_im(offset
);
844 if (insn
& (1 << 20)) {
846 gen_mov_vreg_F0(dp
, rd
);
848 gen_mov_F0_vreg(dp
, rd
);
852 /* load/store multiple */
854 n
= (insn
>> 1) & 0x7f;
858 if (insn
& (1 << 24)) /* pre-decrement */
859 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
865 for (i
= 0; i
< n
; i
++) {
866 if (insn
& (1 << 20)) {
869 gen_mov_vreg_F0(dp
, rd
+ i
);
872 gen_mov_F0_vreg(dp
, rd
+ i
);
875 gen_op_addl_T1_im(offset
);
877 if (insn
& (1 << 21)) {
879 if (insn
& (1 << 24))
880 offset
= -offset
* n
;
881 else if (dp
&& (insn
& 1))
887 gen_op_addl_T1_im(offset
);
888 gen_movl_reg_T1(s
, rn
);
894 /* Should never happen. */
900 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
902 if (__builtin_expect(s
->singlestep_enabled
, 0)) {
903 /* An indirect jump so that we still trigger the debug exception. */
906 gen_op_movl_T0_im(dest
);
909 gen_op_jmp0((long)s
->tb
, dest
);
910 s
->is_jmp
= DISAS_TB_JUMP
;
914 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
916 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
923 /* Unconditional instructions. */
924 if ((insn
& 0x0d70f000) == 0x0550f000)
926 else if ((insn
& 0x0e000000) == 0x0a000000) {
927 /* branch link and change to thumb (blx <offset>) */
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 */
939 gen_op_movl_T0_im(val
);
942 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
943 /* Coprocessor double register transfer. */
944 } else if ((insn
& 0x0f000010) == 0x0e000010) {
945 /* Additional coprocessor register transfer. */
950 /* if not always execute, we generate a conditional jump to
952 s
->condlabel
= gen_new_label();
953 gen_test_cc
[cond
^ 1](s
->condlabel
);
955 //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
956 //s->is_jmp = DISAS_JUMP_NEXT;
958 if ((insn
& 0x0f900000) == 0x03000000) {
959 if ((insn
& 0x0ff0f000) != 0x0360f000)
961 /* CPSR = immediate */
963 shift
= ((insn
>> 8) & 0xf) * 2;
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;
976 case 0x0: /* move program status register */
978 /* SPSR not accessible in user mode */
983 gen_movl_T0_reg(s
, rm
);
984 if (insn
& (1 << 19))
985 gen_op_movl_psr_T0();
988 rd
= (insn
>> 12) & 0xf;
989 gen_op_movl_T0_psr();
990 gen_movl_reg_T0(s
, rd
);
995 /* branch/exchange thumb (bx). */
996 gen_movl_T0_reg(s
, rm
);
998 } else if (op1
== 3) {
1000 rd
= (insn
>> 12) & 0xf;
1001 gen_movl_T0_reg(s
, rm
);
1003 gen_movl_reg_T0(s
, rd
);
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
);
1019 case 0x5: /* saturating add/subtract */
1020 rd
= (insn
>> 12) & 0xf;
1021 rn
= (insn
>> 16) & 0xf;
1022 gen_movl_T0_reg(s
, rn
);
1024 gen_movl_T1_reg(s
, rn
);
1026 gen_op_subl_T0_T1_saturate();
1028 gen_op_addl_T0_T1_saturate();
1030 gen_movl_T1_reg(s
, rm
);
1032 gen_op_subl_T0_T1_saturate();
1034 gen_op_addl_T0_T1_saturate();
1035 gen_movl_reg_T0(s
, rn
);
1037 case 0x8: /* signed multiply */
1041 rs
= (insn
>> 8) & 0xf;
1042 rn
= (insn
>> 12) & 0xf;
1043 rd
= (insn
>> 16) & 0xf;
1045 /* (32 * 16) >> 16 */
1046 gen_movl_T0_reg(s
, rm
);
1047 gen_movl_T1_reg(s
, rs
);
1049 gen_op_sarl_T1_im(16);
1052 gen_op_imulw_T0_T1();
1053 if ((sh
& 2) == 0) {
1054 gen_movl_T1_reg(s
, rn
);
1055 gen_op_addl_T0_T1_setq();
1057 gen_movl_reg_T0(s
, rd
);
1060 gen_movl_T0_reg(s
, rm
);
1062 gen_op_sarl_T0_im(16);
1065 gen_movl_T1_reg(s
, rs
);
1067 gen_op_sarl_T1_im(16);
1071 gen_op_imull_T0_T1();
1072 gen_op_addq_T0_T1(rn
, rd
);
1073 gen_movl_reg_T0(s
, rn
);
1074 gen_movl_reg_T1(s
, rd
);
1078 gen_movl_T1_reg(s
, rn
);
1079 gen_op_addl_T0_T1_setq();
1081 gen_movl_reg_T0(s
, rd
);
1088 } else if (((insn
& 0x0e000000) == 0 &&
1089 (insn
& 0x00000090) != 0x90) ||
1090 ((insn
& 0x0e000000) == (1 << 25))) {
1091 int set_cc
, logic_cc
, shiftop
;
1093 op1
= (insn
>> 21) & 0xf;
1094 set_cc
= (insn
>> 20) & 1;
1095 logic_cc
= table_logic_cc
[op1
] & set_cc
;
1097 /* data processing instruction */
1098 if (insn
& (1 << 25)) {
1099 /* immediate operand */
1101 shift
= ((insn
>> 8) & 0xf) * 2;
1103 val
= (val
>> shift
) | (val
<< (32 - shift
));
1104 gen_op_movl_T1_im(val
);
1105 if (logic_cc
&& shift
)
1110 gen_movl_T1_reg(s
, rm
);
1111 shiftop
= (insn
>> 5) & 3;
1112 if (!(insn
& (1 << 4))) {
1113 shift
= (insn
>> 7) & 0x1f;
1116 gen_shift_T1_im_cc
[shiftop
](shift
);
1118 gen_shift_T1_im
[shiftop
](shift
);
1120 } else if (shiftop
!= 0) {
1122 gen_shift_T1_0_cc
[shiftop
]();
1124 gen_shift_T1_0
[shiftop
]();
1128 rs
= (insn
>> 8) & 0xf;
1129 gen_movl_T0_reg(s
, rs
);
1131 gen_shift_T1_T0_cc
[shiftop
]();
1133 gen_shift_T1_T0
[shiftop
]();
1137 if (op1
!= 0x0f && op1
!= 0x0d) {
1138 rn
= (insn
>> 16) & 0xf;
1139 gen_movl_T0_reg(s
, rn
);
1141 rd
= (insn
>> 12) & 0xf;
1144 gen_op_andl_T0_T1();
1145 gen_movl_reg_T0(s
, rd
);
1147 gen_op_logic_T0_cc();
1150 gen_op_xorl_T0_T1();
1151 gen_movl_reg_T0(s
, rd
);
1153 gen_op_logic_T0_cc();
1157 gen_op_subl_T0_T1_cc();
1159 gen_op_subl_T0_T1();
1160 gen_movl_reg_T0(s
, rd
);
1164 gen_op_rsbl_T0_T1_cc();
1166 gen_op_rsbl_T0_T1();
1167 gen_movl_reg_T0(s
, rd
);
1171 gen_op_addl_T0_T1_cc();
1173 gen_op_addl_T0_T1();
1174 gen_movl_reg_T0(s
, rd
);
1178 gen_op_adcl_T0_T1_cc();
1180 gen_op_adcl_T0_T1();
1181 gen_movl_reg_T0(s
, rd
);
1185 gen_op_sbcl_T0_T1_cc();
1187 gen_op_sbcl_T0_T1();
1188 gen_movl_reg_T0(s
, rd
);
1192 gen_op_rscl_T0_T1_cc();
1194 gen_op_rscl_T0_T1();
1195 gen_movl_reg_T0(s
, rd
);
1199 gen_op_andl_T0_T1();
1200 gen_op_logic_T0_cc();
1205 gen_op_xorl_T0_T1();
1206 gen_op_logic_T0_cc();
1211 gen_op_subl_T0_T1_cc();
1216 gen_op_addl_T0_T1_cc();
1221 gen_movl_reg_T0(s
, rd
);
1223 gen_op_logic_T0_cc();
1226 gen_movl_reg_T1(s
, rd
);
1228 gen_op_logic_T1_cc();
1231 gen_op_bicl_T0_T1();
1232 gen_movl_reg_T0(s
, rd
);
1234 gen_op_logic_T0_cc();
1239 gen_movl_reg_T1(s
, rd
);
1241 gen_op_logic_T1_cc();
1245 /* other instructions */
1246 op1
= (insn
>> 24) & 0xf;
1250 /* multiplies, extra load/stores */
1251 sh
= (insn
>> 5) & 3;
1254 rd
= (insn
>> 16) & 0xf;
1255 rn
= (insn
>> 12) & 0xf;
1256 rs
= (insn
>> 8) & 0xf;
1258 if (((insn
>> 22) & 3) == 0) {
1260 gen_movl_T0_reg(s
, rs
);
1261 gen_movl_T1_reg(s
, rm
);
1263 if (insn
& (1 << 21)) {
1264 gen_movl_T1_reg(s
, rn
);
1265 gen_op_addl_T0_T1();
1267 if (insn
& (1 << 20))
1268 gen_op_logic_T0_cc();
1269 gen_movl_reg_T0(s
, rd
);
1272 gen_movl_T0_reg(s
, rs
);
1273 gen_movl_T1_reg(s
, rm
);
1274 if (insn
& (1 << 22))
1275 gen_op_imull_T0_T1();
1277 gen_op_mull_T0_T1();
1278 if (insn
& (1 << 21)) /* mult accumulate */
1279 gen_op_addq_T0_T1(rn
, rd
);
1280 if (!(insn
& (1 << 23))) { /* double accumulate */
1281 gen_op_addq_lo_T0_T1(rn
);
1282 gen_op_addq_lo_T0_T1(rd
);
1284 if (insn
& (1 << 20))
1286 gen_movl_reg_T0(s
, rn
);
1287 gen_movl_reg_T1(s
, rd
);
1290 rn
= (insn
>> 16) & 0xf;
1291 rd
= (insn
>> 12) & 0xf;
1292 if (insn
& (1 << 23)) {
1293 /* load/store exclusive */
1296 /* SWP instruction */
1299 gen_movl_T0_reg(s
, rm
);
1300 gen_movl_T1_reg(s
, rn
);
1301 if (insn
& (1 << 22)) {
1302 gen_op_swpb_T0_T1();
1304 gen_op_swpl_T0_T1();
1306 gen_movl_reg_T0(s
, rd
);
1310 /* Misc load/store */
1311 rn
= (insn
>> 16) & 0xf;
1312 rd
= (insn
>> 12) & 0xf;
1313 gen_movl_T1_reg(s
, rn
);
1314 if (insn
& (1 << 24))
1315 gen_add_datah_offset(s
, insn
);
1316 if (insn
& (1 << 20)) {
1320 gen_op_lduw_T0_T1();
1323 gen_op_ldsb_T0_T1();
1327 gen_op_ldsw_T0_T1();
1330 gen_movl_reg_T0(s
, rd
);
1331 } else if (sh
& 2) {
1335 gen_movl_T0_reg(s
, rd
);
1337 gen_op_addl_T1_im(4);
1338 gen_movl_T0_reg(s
, rd
+ 1);
1340 if ((insn
& (1 << 24)) || (insn
& (1 << 20)))
1341 gen_op_addl_T1_im(-4);
1345 gen_movl_reg_T0(s
, rd
);
1346 gen_op_addl_T1_im(4);
1348 gen_movl_reg_T0(s
, rd
+ 1);
1349 if ((insn
& (1 << 24)) || (insn
& (1 << 20)))
1350 gen_op_addl_T1_im(-4);
1354 gen_movl_T0_reg(s
, rd
);
1357 if (!(insn
& (1 << 24))) {
1358 gen_add_datah_offset(s
, insn
);
1359 gen_movl_reg_T1(s
, rn
);
1360 } else if (insn
& (1 << 21)) {
1361 gen_movl_reg_T1(s
, rn
);
1369 /* load/store byte/word */
1370 rn
= (insn
>> 16) & 0xf;
1371 rd
= (insn
>> 12) & 0xf;
1372 gen_movl_T1_reg(s
, rn
);
1373 if (insn
& (1 << 24))
1374 gen_add_data_offset(s
, insn
);
1375 if (insn
& (1 << 20)) {
1377 if (insn
& (1 << 22))
1378 gen_op_ldub_T0_T1();
1384 gen_movl_reg_T0(s
, rd
);
1387 gen_movl_T0_reg(s
, rd
);
1388 if (insn
& (1 << 22))
1393 if (!(insn
& (1 << 24))) {
1394 gen_add_data_offset(s
, insn
);
1395 gen_movl_reg_T1(s
, rn
);
1396 } else if (insn
& (1 << 21))
1397 gen_movl_reg_T1(s
, rn
); {
1404 /* load/store multiple words */
1405 /* XXX: store correct base if write back */
1406 if (insn
& (1 << 22))
1407 goto illegal_op
; /* only usable in supervisor mode */
1408 rn
= (insn
>> 16) & 0xf;
1409 gen_movl_T1_reg(s
, rn
);
1411 /* compute total size */
1414 if (insn
& (1 << i
))
1417 /* XXX: test invalid n == 0 case ? */
1418 if (insn
& (1 << 23)) {
1419 if (insn
& (1 << 24)) {
1421 gen_op_addl_T1_im(4);
1423 /* post increment */
1426 if (insn
& (1 << 24)) {
1428 gen_op_addl_T1_im(-(n
* 4));
1430 /* post decrement */
1432 gen_op_addl_T1_im(-((n
- 1) * 4));
1437 if (insn
& (1 << i
)) {
1438 if (insn
& (1 << 20)) {
1444 gen_movl_reg_T0(s
, i
);
1448 /* special case: r15 = PC + 12 */
1449 val
= (long)s
->pc
+ 8;
1450 gen_op_movl_TN_im
[0](val
);
1452 gen_movl_T0_reg(s
, i
);
1457 /* no need to add after the last transfer */
1459 gen_op_addl_T1_im(4);
1462 if (insn
& (1 << 21)) {
1464 if (insn
& (1 << 23)) {
1465 if (insn
& (1 << 24)) {
1468 /* post increment */
1469 gen_op_addl_T1_im(4);
1472 if (insn
& (1 << 24)) {
1475 gen_op_addl_T1_im(-((n
- 1) * 4));
1477 /* post decrement */
1478 gen_op_addl_T1_im(-(n
* 4));
1481 gen_movl_reg_T1(s
, rn
);
1490 /* branch (and link) */
1491 val
= (int32_t)s
->pc
;
1492 if (insn
& (1 << 24)) {
1493 gen_op_movl_T0_im(val
);
1494 gen_op_movl_reg_TN
[0][14]();
1496 offset
= (((int32_t)insn
<< 8) >> 8);
1497 val
+= (offset
<< 2) + 4;
1505 op1
= (insn
>> 8) & 0xf;
1509 if (disas_vfp_insn (env
, s
, insn
))
1513 /* unknown coprocessor. */
1519 gen_op_movl_T0_im((long)s
->pc
);
1520 gen_op_movl_reg_TN
[0][15]();
1522 s
->is_jmp
= DISAS_JUMP
;
1526 gen_op_movl_T0_im((long)s
->pc
- 4);
1527 gen_op_movl_reg_TN
[0][15]();
1528 gen_op_undef_insn();
1529 s
->is_jmp
= DISAS_JUMP
;
1535 static void disas_thumb_insn(DisasContext
*s
)
1537 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
1544 switch (insn
>> 12) {
1547 op
= (insn
>> 11) & 3;
1550 rn
= (insn
>> 3) & 7;
1551 gen_movl_T0_reg(s
, rn
);
1552 if (insn
& (1 << 10)) {
1554 gen_op_movl_T1_im((insn
>> 6) & 7);
1557 rm
= (insn
>> 6) & 7;
1558 gen_movl_T1_reg(s
, rm
);
1560 if (insn
& (1 << 9))
1561 gen_op_subl_T0_T1_cc();
1563 gen_op_addl_T0_T1_cc();
1564 gen_movl_reg_T0(s
, rd
);
1566 /* shift immediate */
1567 rm
= (insn
>> 3) & 7;
1568 shift
= (insn
>> 6) & 0x1f;
1569 gen_movl_T0_reg(s
, rm
);
1570 gen_shift_T0_im_thumb
[op
](shift
);
1571 gen_movl_reg_T0(s
, rd
);
1575 /* arithmetic large immediate */
1576 op
= (insn
>> 11) & 3;
1577 rd
= (insn
>> 8) & 0x7;
1579 gen_op_movl_T0_im(insn
& 0xff);
1581 gen_movl_T0_reg(s
, rd
);
1582 gen_op_movl_T1_im(insn
& 0xff);
1586 gen_op_logic_T0_cc();
1589 gen_op_subl_T0_T1_cc();
1592 gen_op_addl_T0_T1_cc();
1595 gen_op_subl_T0_T1_cc();
1599 gen_movl_reg_T0(s
, rd
);
1602 if (insn
& (1 << 11)) {
1603 rd
= (insn
>> 8) & 7;
1604 /* load pc-relative. Bit 1 of PC is ignored. */
1605 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
1606 val
&= ~(uint32_t)2;
1607 gen_op_movl_T1_im(val
);
1609 gen_movl_reg_T0(s
, rd
);
1612 if (insn
& (1 << 10)) {
1613 /* data processing extended or blx */
1614 rd
= (insn
& 7) | ((insn
>> 4) & 8);
1615 rm
= (insn
>> 3) & 0xf;
1616 op
= (insn
>> 8) & 3;
1619 gen_movl_T0_reg(s
, rd
);
1620 gen_movl_T1_reg(s
, rm
);
1621 gen_op_addl_T0_T1();
1622 gen_movl_reg_T0(s
, rd
);
1625 gen_movl_T0_reg(s
, rd
);
1626 gen_movl_T1_reg(s
, rm
);
1627 gen_op_subl_T0_T1_cc();
1629 case 2: /* mov/cpy */
1630 gen_movl_T0_reg(s
, rm
);
1631 gen_movl_reg_T0(s
, rd
);
1633 case 3:/* branch [and link] exchange thumb register */
1634 if (insn
& (1 << 7)) {
1635 val
= (uint32_t)s
->pc
| 1;
1636 gen_op_movl_T1_im(val
);
1637 gen_movl_reg_T1(s
, 14);
1639 gen_movl_T0_reg(s
, rm
);
1646 /* data processing register */
1648 rm
= (insn
>> 3) & 7;
1649 op
= (insn
>> 6) & 0xf;
1650 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
1651 /* the shift/rotate ops want the operands backwards */
1660 if (op
== 9) /* neg */
1661 gen_op_movl_T0_im(0);
1662 else if (op
!= 0xf) /* mvn doesn't read its first operand */
1663 gen_movl_T0_reg(s
, rd
);
1665 gen_movl_T1_reg(s
, rm
);
1668 gen_op_andl_T0_T1();
1669 gen_op_logic_T0_cc();
1672 gen_op_xorl_T0_T1();
1673 gen_op_logic_T0_cc();
1676 gen_op_shll_T1_T0_cc();
1679 gen_op_shrl_T1_T0_cc();
1682 gen_op_sarl_T1_T0_cc();
1685 gen_op_adcl_T0_T1_cc();
1688 gen_op_sbcl_T0_T1_cc();
1691 gen_op_rorl_T1_T0_cc();
1694 gen_op_andl_T0_T1();
1695 gen_op_logic_T0_cc();
1699 gen_op_subl_T0_T1_cc();
1702 gen_op_subl_T0_T1_cc();
1706 gen_op_addl_T0_T1_cc();
1711 gen_op_logic_T0_cc();
1714 gen_op_mull_T0_T1();
1715 gen_op_logic_T0_cc();
1718 gen_op_bicl_T0_T1();
1719 gen_op_logic_T0_cc();
1723 gen_op_logic_T1_cc();
1730 gen_movl_reg_T1(s
, rm
);
1732 gen_movl_reg_T0(s
, rd
);
1737 /* load/store register offset. */
1739 rn
= (insn
>> 3) & 7;
1740 rm
= (insn
>> 6) & 7;
1741 op
= (insn
>> 9) & 7;
1742 gen_movl_T1_reg(s
, rn
);
1743 gen_movl_T2_reg(s
, rm
);
1744 gen_op_addl_T1_T2();
1746 if (op
< 3) /* store */
1747 gen_movl_T0_reg(s
, rd
);
1760 gen_op_ldsb_T0_T1();
1766 gen_op_lduw_T0_T1();
1769 gen_op_ldub_T0_T1();
1772 gen_op_ldsw_T0_T1();
1775 if (op
>= 3) /* load */
1776 gen_movl_reg_T0(s
, rd
);
1780 /* load/store word immediate offset */
1782 rn
= (insn
>> 3) & 7;
1783 gen_movl_T1_reg(s
, rn
);
1784 val
= (insn
>> 4) & 0x7c;
1785 gen_op_movl_T2_im(val
);
1786 gen_op_addl_T1_T2();
1788 if (insn
& (1 << 11)) {
1791 gen_movl_reg_T0(s
, rd
);
1794 gen_movl_T0_reg(s
, rd
);
1800 /* load/store byte immediate offset */
1802 rn
= (insn
>> 3) & 7;
1803 gen_movl_T1_reg(s
, rn
);
1804 val
= (insn
>> 6) & 0x1f;
1805 gen_op_movl_T2_im(val
);
1806 gen_op_addl_T1_T2();
1808 if (insn
& (1 << 11)) {
1810 gen_op_ldub_T0_T1();
1811 gen_movl_reg_T0(s
, rd
);
1814 gen_movl_T0_reg(s
, rd
);
1820 /* load/store halfword immediate offset */
1822 rn
= (insn
>> 3) & 7;
1823 gen_movl_T1_reg(s
, rn
);
1824 val
= (insn
>> 5) & 0x3e;
1825 gen_op_movl_T2_im(val
);
1826 gen_op_addl_T1_T2();
1828 if (insn
& (1 << 11)) {
1830 gen_op_lduw_T0_T1();
1831 gen_movl_reg_T0(s
, rd
);
1834 gen_movl_T0_reg(s
, rd
);
1840 /* load/store from stack */
1841 rd
= (insn
>> 8) & 7;
1842 gen_movl_T1_reg(s
, 13);
1843 val
= (insn
& 0xff) * 4;
1844 gen_op_movl_T2_im(val
);
1845 gen_op_addl_T1_T2();
1847 if (insn
& (1 << 11)) {
1850 gen_movl_reg_T0(s
, rd
);
1853 gen_movl_T0_reg(s
, rd
);
1859 /* add to high reg */
1860 rd
= (insn
>> 8) & 7;
1861 if (insn
& (1 << 11)) {
1863 gen_movl_T0_reg(s
, 13);
1865 /* PC. bit 1 is ignored. */
1866 gen_op_movl_T0_im((s
->pc
+ 2) & ~(uint32_t)2);
1868 val
= (insn
& 0xff) * 4;
1869 gen_op_movl_T1_im(val
);
1870 gen_op_addl_T0_T1();
1871 gen_movl_reg_T0(s
, rd
);
1876 op
= (insn
>> 8) & 0xf;
1879 /* adjust stack pointer */
1880 gen_movl_T1_reg(s
, 13);
1881 val
= (insn
& 0x7f) * 4;
1882 if (insn
& (1 << 7))
1883 val
= -(int32_t)val
;
1884 gen_op_movl_T2_im(val
);
1885 gen_op_addl_T1_T2();
1886 gen_movl_reg_T1(s
, 13);
1889 case 4: case 5: case 0xc: case 0xd:
1891 gen_movl_T1_reg(s
, 13);
1892 if (insn
& (1 << 8))
1896 for (i
= 0; i
< 8; i
++) {
1897 if (insn
& (1 << i
))
1900 if ((insn
& (1 << 11)) == 0) {
1901 gen_op_movl_T2_im(-offset
);
1902 gen_op_addl_T1_T2();
1904 gen_op_movl_T2_im(4);
1905 for (i
= 0; i
< 8; i
++) {
1906 if (insn
& (1 << i
)) {
1907 if (insn
& (1 << 11)) {
1910 gen_movl_reg_T0(s
, i
);
1913 gen_movl_T0_reg(s
, i
);
1916 /* advance to the next address. */
1917 gen_op_addl_T1_T2();
1920 if (insn
& (1 << 8)) {
1921 if (insn
& (1 << 11)) {
1924 /* don't set the pc until the rest of the instruction
1928 gen_movl_T0_reg(s
, 14);
1931 gen_op_addl_T1_T2();
1933 if ((insn
& (1 << 11)) == 0) {
1934 gen_op_movl_T2_im(-offset
);
1935 gen_op_addl_T1_T2();
1937 /* write back the new stack pointer */
1938 gen_movl_reg_T1(s
, 13);
1939 /* set the new PC value */
1940 if ((insn
& 0x0900) == 0x0900)
1950 /* load/store multiple */
1951 rn
= (insn
>> 8) & 0x7;
1952 gen_movl_T1_reg(s
, rn
);
1953 gen_op_movl_T2_im(4);
1954 for (i
= 0; i
< 8; i
++) {
1955 if (insn
& (1 << i
)) {
1956 if (insn
& (1 << 11)) {
1959 gen_movl_reg_T0(s
, i
);
1962 gen_movl_T0_reg(s
, i
);
1965 /* advance to the next address */
1966 gen_op_addl_T1_T2();
1969 /* Base register writeback. */
1970 gen_movl_reg_T1(s
, rn
);
1974 /* conditional branch or swi */
1975 cond
= (insn
>> 8) & 0xf;
1981 gen_op_movl_T0_im((long)s
->pc
| 1);
1982 /* Don't set r15. */
1983 gen_op_movl_reg_TN
[0][15]();
1985 s
->is_jmp
= DISAS_JUMP
;
1988 /* generate a conditional jump to next instruction */
1989 s
->condlabel
= gen_new_label();
1990 gen_test_cc
[cond
^ 1](s
->condlabel
);
1992 //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1993 //s->is_jmp = DISAS_JUMP_NEXT;
1994 gen_movl_T1_reg(s
, 15);
1996 /* jump to the offset */
1997 val
= (uint32_t)s
->pc
+ 2;
1998 offset
= ((int32_t)insn
<< 24) >> 24;
2004 /* unconditional branch */
2005 if (insn
& (1 << 11))
2006 goto undef
; /* Second half of a blx */
2007 val
= (uint32_t)s
->pc
;
2008 offset
= ((int32_t)insn
<< 21) >> 21;
2009 val
+= (offset
<< 1) + 2;
2014 /* branch and link [and switch to arm] */
2015 offset
= ((int32_t)insn
<< 21) >> 10;
2017 offset
|= insn
& 0x7ff;
2019 val
= (uint32_t)s
->pc
+ 2;
2020 gen_op_movl_T1_im(val
| 1);
2021 gen_movl_reg_T1(s
, 14);
2024 if (insn
& (1 << 11)) {
2029 val
&= ~(uint32_t)2;
2030 gen_op_movl_T0_im(val
);
2036 gen_op_movl_T0_im((long)s
->pc
- 2);
2037 gen_op_movl_reg_TN
[0][15]();
2038 gen_op_undef_insn();
2039 s
->is_jmp
= DISAS_JUMP
;
2042 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
2043 basic block 'tb'. If search_pc is TRUE, also generate PC
2044 information for each intermediate instruction. */
2045 static inline int gen_intermediate_code_internal(CPUState
*env
,
2046 TranslationBlock
*tb
,
2049 DisasContext dc1
, *dc
= &dc1
;
2050 uint16_t *gen_opc_end
;
2052 target_ulong pc_start
;
2054 /* generate intermediate code */
2059 gen_opc_ptr
= gen_opc_buf
;
2060 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
2061 gen_opparam_ptr
= gen_opparam_buf
;
2063 dc
->is_jmp
= DISAS_NEXT
;
2065 dc
->singlestep_enabled
= env
->singlestep_enabled
;
2067 dc
->thumb
= env
->thumb
;
2071 if (env
->nb_breakpoints
> 0) {
2072 for(j
= 0; j
< env
->nb_breakpoints
; j
++) {
2073 if (env
->breakpoints
[j
] == dc
->pc
) {
2074 gen_op_movl_T0_im((long)dc
->pc
);
2075 gen_op_movl_reg_TN
[0][15]();
2077 dc
->is_jmp
= DISAS_JUMP
;
2083 j
= gen_opc_ptr
- gen_opc_buf
;
2087 gen_opc_instr_start
[lj
++] = 0;
2089 gen_opc_pc
[lj
] = dc
->pc
;
2090 gen_opc_instr_start
[lj
] = 1;
2094 disas_thumb_insn(dc
);
2096 disas_arm_insn(env
, dc
);
2098 if (dc
->condjmp
&& !dc
->is_jmp
) {
2099 gen_set_label(dc
->condlabel
);
2102 /* Translation stops when a conditional branch is enoutered.
2103 * Otherwise the subsequent code could get translated several times.
2105 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
2106 !env
->singlestep_enabled
&&
2107 (dc
->pc
- pc_start
) < (TARGET_PAGE_SIZE
- 32));
2108 /* It this stage dc->condjmp will only be set when the skipped
2109 * instruction was a conditional branch, and teh PC has already been
2111 if (__builtin_expect(env
->singlestep_enabled
, 0)) {
2112 /* Make sure the pc is updated, and raise a debug exception. */
2115 gen_set_label(dc
->condlabel
);
2117 if (dc
->condjmp
|| !dc
->is_jmp
) {
2118 gen_op_movl_T0_im((long)dc
->pc
);
2119 gen_op_movl_reg_TN
[0][15]();
2124 switch(dc
->is_jmp
) {
2126 gen_op_jmp1((long)dc
->tb
, (long)dc
->pc
);
2131 /* indicate that the hash table must be used to find the next TB */
2136 /* nothing more to generate */
2140 gen_set_label(dc
->condlabel
);
2141 gen_op_jmp1((long)dc
->tb
, (long)dc
->pc
);
2145 *gen_opc_ptr
= INDEX_op_end
;
2148 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
2149 fprintf(logfile
, "----------------\n");
2150 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
2151 target_disas(logfile
, pc_start
, dc
->pc
- pc_start
, env
->thumb
);
2152 fprintf(logfile
, "\n");
2153 if (loglevel
& (CPU_LOG_TB_OP
)) {
2154 fprintf(logfile
, "OP:\n");
2155 dump_ops(gen_opc_buf
, gen_opparam_buf
);
2156 fprintf(logfile
, "\n");
2161 tb
->size
= dc
->pc
- pc_start
;
2165 int gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
2167 return gen_intermediate_code_internal(env
, tb
, 0);
2170 int gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
2172 return gen_intermediate_code_internal(env
, tb
, 1);
2175 CPUARMState
*cpu_arm_init(void)
2181 env
= malloc(sizeof(CPUARMState
));
2184 memset(env
, 0, sizeof(CPUARMState
));
2185 cpu_single_env
= env
;
2189 void cpu_arm_close(CPUARMState
*env
)
2194 void cpu_dump_state(CPUState
*env
, FILE *f
,
2195 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
2206 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
2208 cpu_fprintf(f
, "\n");
2210 cpu_fprintf(f
, " ");
2212 cpu_fprintf(f
, "PSR=%08x %c%c%c%c\n",
2214 env
->cpsr
& (1 << 31) ? 'N' : '-',
2215 env
->cpsr
& (1 << 30) ? 'Z' : '-',
2216 env
->cpsr
& (1 << 29) ? 'C' : '-',
2217 env
->cpsr
& (1 << 28) ? 'V' : '-');
2219 for (i
= 0; i
< 16; i
++) {
2220 d
.d
= env
->vfp
.regs
[i
];
2223 cpu_fprintf(f
, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
2224 i
* 2, (int)s0
.i
, s0
.s
,
2225 i
* 2 + 1, (int)s0
.i
, s0
.s
,
2226 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
2229 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.fpscr
);
2232 target_ulong
cpu_get_phys_page_debug(CPUState
*env
, target_ulong addr
)
2237 #if defined(CONFIG_USER_ONLY)
2239 int cpu_arm_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
2240 int is_user
, int is_softmmu
)
2242 env
->cp15_6
= address
;
2244 env
->exception_index
= EXCP_PREFETCH_ABORT
;
2246 env
->exception_index
= EXCP_DATA_ABORT
;
2253 #error not implemented