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 #define ENABLE_ARCH_5J 0
32 #define ENABLE_ARCH_6 1
33 #define ENABLE_ARCH_6T2 1
35 #define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
37 /* internal defines */
38 typedef struct DisasContext {
41 /* Nonzero if this instruction has been conditionally skipped. */
43 /* The label that will be jumped to when the instruction is skipped. */
45 struct TranslationBlock *tb;
46 int singlestep_enabled;
48 #if !defined(CONFIG_USER_ONLY)
53 #if defined(CONFIG_USER_ONLY)
56 #define IS_USER(s) (s->user)
59 #define DISAS_JUMP_NEXT 4
61 #ifdef USE_DIRECT_JUMP
64 #define TBPARAM(x) (long)(x)
67 /* XXX: move that elsewhere */
68 static uint16_t *gen_opc_ptr;
69 static uint32_t *gen_opparam_ptr;
74 #define DEF(s, n, copy_size) INDEX_op_ ## s,
82 static GenOpFunc1 *gen_test_cc[14] = {
99 const uint8_t table_logic_cc[16] = {
118 static GenOpFunc1 *gen_shift_T1_im[4] = {
125 static GenOpFunc *gen_shift_T1_0[4] = {
132 static GenOpFunc1 *gen_shift_T2_im[4] = {
139 static GenOpFunc *gen_shift_T2_0[4] = {
146 static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
147 gen_op_shll_T1_im_cc,
148 gen_op_shrl_T1_im_cc,
149 gen_op_sarl_T1_im_cc,
150 gen_op_rorl_T1_im_cc,
153 static GenOpFunc *gen_shift_T1_0_cc[4] = {
160 static GenOpFunc *gen_shift_T1_T0[4] = {
167 static GenOpFunc *gen_shift_T1_T0_cc[4] = {
168 gen_op_shll_T1_T0_cc,
169 gen_op_shrl_T1_T0_cc,
170 gen_op_sarl_T1_T0_cc,
171 gen_op_rorl_T1_T0_cc,
174 static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
231 static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
270 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
276 static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
277 gen_op_shll_T0_im_thumb,
278 gen_op_shrl_T0_im_thumb,
279 gen_op_sarl_T0_im_thumb,
282 static inline void gen_bx(DisasContext *s)
284 s->is_jmp = DISAS_UPDATE;
289 #if defined(CONFIG_USER_ONLY)
290 #define gen_ldst(name, s) gen_op_##name##_raw()
292 #define gen_ldst(name, s) do { \
294 gen_op_##name##_user(); \
296 gen_op_##name##_kernel(); \
300 static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
305 /* normaly, since we updated PC, we need only to add one insn */
307 val = (long)s->pc + 2;
309 val = (long)s->pc + 4;
310 gen_op_movl_TN_im[t](val);
312 gen_op_movl_TN_reg[t][reg]();
316 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
318 gen_movl_TN_reg(s, reg, 0);
321 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
323 gen_movl_TN_reg(s, reg, 1);
326 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
328 gen_movl_TN_reg(s, reg, 2);
331 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
333 gen_op_movl_reg_TN[t][reg]();
335 s->is_jmp = DISAS_JUMP;
339 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
341 gen_movl_reg_TN(s, reg, 0);
344 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
346 gen_movl_reg_TN(s, reg, 1);
349 /* Force a TB lookup after an instruction that changes the CPU state. */
350 static inline void gen_lookup_tb(DisasContext *s)
352 gen_op_movl_T0_im(s->pc);
353 gen_movl_reg_T0(s, 15);
354 s->is_jmp = DISAS_UPDATE;
357 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
359 int val, rm, shift, shiftop;
361 if (!(insn & (1 << 25))) {
364 if (!(insn & (1 << 23)))
367 gen_op_addl_T1_im(val);
371 shift = (insn >> 7) & 0x1f;
372 gen_movl_T2_reg(s, rm);
373 shiftop = (insn >> 5) & 3;
375 gen_shift_T2_im[shiftop](shift);
376 } else if (shiftop != 0) {
377 gen_shift_T2_0[shiftop]();
379 if (!(insn & (1 << 23)))
386 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
390 if (insn & (1 << 22)) {
392 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
393 if (!(insn & (1 << 23)))
396 gen_op_addl_T1_im(val);
400 gen_movl_T2_reg(s, rm);
401 if (!(insn & (1 << 23)))
408 #define VFP_OP(name) \
409 static inline void gen_vfp_##name(int dp) \
412 gen_op_vfp_##name##d(); \
414 gen_op_vfp_##name##s(); \
436 static inline void gen_vfp_ld(DisasContext *s, int dp)
439 gen_ldst(vfp_ldd, s);
441 gen_ldst(vfp_lds, s);
444 static inline void gen_vfp_st(DisasContext *s, int dp)
447 gen_ldst(vfp_std, s);
449 gen_ldst(vfp_sts, s);
453 vfp_reg_offset (int dp, int reg)
456 return offsetof(CPUARMState, vfp.regs[reg]);
458 return offsetof(CPUARMState, vfp.regs[reg >> 1])
459 + offsetof(CPU_DoubleU, l.upper);
461 return offsetof(CPUARMState, vfp.regs[reg >> 1])
462 + offsetof(CPU_DoubleU, l.lower);
465 static inline void gen_mov_F0_vreg(int dp, int reg)
468 gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
470 gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
473 static inline void gen_mov_F1_vreg(int dp, int reg)
476 gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
478 gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
481 static inline void gen_mov_vreg_F0(int dp, int reg)
484 gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
486 gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
489 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
490 instruction is not defined. */
491 static int disas_cp15_insn(DisasContext *s, uint32_t insn)
495 /* ??? Some cp15 registers are accessible from userspace. */
499 if ((insn & 0x0fff0fff) == 0x0e070f90
500 || (insn & 0x0fff0fff) == 0x0e070f58) {
501 /* Wait for interrupt. */
502 gen_op_movl_T0_im((long)s->pc);
503 gen_op_movl_reg_TN[0][15]();
505 s->is_jmp = DISAS_JUMP;
508 rd = (insn >> 12) & 0xf;
509 if (insn & (1 << 20)) {
510 gen_op_movl_T0_cp15(insn);
511 /* If the destination register is r15 then sets condition codes. */
513 gen_movl_reg_T0(s, rd);
515 gen_movl_T0_reg(s, rd);
516 gen_op_movl_cp15_T0(insn);
522 /* Disassemble a VFP instruction. Returns nonzero if an error occured
523 (ie. an undefined instruction). */
524 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
526 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
529 if (!arm_feature(env, ARM_FEATURE_VFP))
532 if ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) == 0) {
533 /* VFP disabled. Only allow fmxr/fmrx to/from fpexc and fpsid. */
534 if ((insn & 0x0fe00fff) != 0x0ee00a10)
536 rn = (insn >> 16) & 0xf;
537 if (rn != 0 && rn != 8)
540 dp = ((insn & 0xf00) == 0xb00);
541 switch ((insn >> 24) & 0xf) {
543 if (insn & (1 << 4)) {
544 /* single register transfer */
545 if ((insn & 0x6f) != 0x00)
547 rd = (insn >> 12) & 0xf;
551 rn = (insn >> 16) & 0xf;
552 /* Get the existing value even for arm->vfp moves because
553 we only set half the register. */
554 gen_mov_F0_vreg(1, rn);
556 if (insn & (1 << 20)) {
558 if (insn & (1 << 21))
559 gen_movl_reg_T1(s, rd);
561 gen_movl_reg_T0(s, rd);
564 if (insn & (1 << 21))
565 gen_movl_T1_reg(s, rd);
567 gen_movl_T0_reg(s, rd);
569 gen_mov_vreg_F0(dp, rn);
572 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
573 if (insn & (1 << 20)) {
575 if (insn & (1 << 21)) {
576 /* system register */
582 case ARM_VFP_FPINST2:
583 gen_op_vfp_movl_T0_xreg(rn);
587 gen_op_vfp_movl_T0_fpscr_flags();
589 gen_op_vfp_movl_T0_fpscr();
595 gen_mov_F0_vreg(0, rn);
599 /* Set the 4 flag bits in the CPSR. */
600 gen_op_movl_cpsr_T0(0xf0000000);
602 gen_movl_reg_T0(s, rd);
605 gen_movl_T0_reg(s, rd);
606 if (insn & (1 << 21)) {
608 /* system register */
611 /* Writes are ignored. */
614 gen_op_vfp_movl_fpscr_T0();
618 gen_op_vfp_movl_xreg_T0(rn);
622 case ARM_VFP_FPINST2:
623 gen_op_vfp_movl_xreg_T0(rn);
630 gen_mov_vreg_F0(0, rn);
635 /* data processing */
636 /* The opcode is in bits 23, 21, 20 and 6. */
637 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
641 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
643 /* rn is register number */
646 rn = (insn >> 16) & 0xf;
649 if (op == 15 && (rn == 15 || rn > 17)) {
650 /* Integer or single precision destination. */
651 rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
653 if (insn & (1 << 22))
655 rd = (insn >> 12) & 0xf;
658 if (op == 15 && (rn == 16 || rn == 17)) {
659 /* Integer source. */
660 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
667 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
668 if (op == 15 && rn == 15) {
669 /* Double precision destination. */
670 if (insn & (1 << 22))
672 rd = (insn >> 12) & 0xf;
674 rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
675 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
678 veclen = env->vfp.vec_len;
679 if (op == 15 && rn > 3)
682 /* Shut up compiler warnings. */
693 /* Figure out what type of vector operation this is. */
694 if ((rd & bank_mask) == 0) {
699 delta_d = (env->vfp.vec_stride >> 1) + 1;
701 delta_d = env->vfp.vec_stride + 1;
703 if ((rm & bank_mask) == 0) {
704 /* mixed scalar/vector */
713 /* Load the initial operands. */
719 gen_mov_F0_vreg(0, rm);
724 gen_mov_F0_vreg(dp, rd);
725 gen_mov_F1_vreg(dp, rm);
729 /* Compare with zero */
730 gen_mov_F0_vreg(dp, rd);
734 /* One source operand. */
735 gen_mov_F0_vreg(dp, rm);
738 /* Two source operands. */
739 gen_mov_F0_vreg(dp, rn);
740 gen_mov_F1_vreg(dp, rm);
744 /* Perform the calculation. */
746 case 0: /* mac: fd + (fn * fm) */
748 gen_mov_F1_vreg(dp, rd);
751 case 1: /* nmac: fd - (fn * fm) */
754 gen_mov_F1_vreg(dp, rd);
757 case 2: /* msc: -fd + (fn * fm) */
759 gen_mov_F1_vreg(dp, rd);
762 case 3: /* nmsc: -fd - (fn * fm) */
764 gen_mov_F1_vreg(dp, rd);
768 case 4: /* mul: fn * fm */
771 case 5: /* nmul: -(fn * fm) */
775 case 6: /* add: fn + fm */
778 case 7: /* sub: fn - fm */
781 case 8: /* div: fn / fm */
784 case 15: /* extension space */
811 case 15: /* single<->double conversion */
826 case 25: /* ftouiz */
832 case 27: /* ftosiz */
835 default: /* undefined */
836 printf ("rn:%d\n", rn);
840 default: /* undefined */
841 printf ("op:%d\n", op);
845 /* Write back the result. */
846 if (op == 15 && (rn >= 8 && rn <= 11))
847 ; /* Comparison, do nothing. */
848 else if (op == 15 && rn > 17)
849 /* Integer result. */
850 gen_mov_vreg_F0(0, rd);
851 else if (op == 15 && rn == 15)
853 gen_mov_vreg_F0(!dp, rd);
855 gen_mov_vreg_F0(dp, rd);
857 /* break out of the loop if we have finished */
861 if (op == 15 && delta_m == 0) {
862 /* single source one-many */
864 rd = ((rd + delta_d) & (bank_mask - 1))
866 gen_mov_vreg_F0(dp, rd);
870 /* Setup the next operands. */
872 rd = ((rd + delta_d) & (bank_mask - 1))
876 /* One source operand. */
877 rm = ((rm + delta_m) & (bank_mask - 1))
879 gen_mov_F0_vreg(dp, rm);
881 /* Two source operands. */
882 rn = ((rn + delta_d) & (bank_mask - 1))
884 gen_mov_F0_vreg(dp, rn);
886 rm = ((rm + delta_m) & (bank_mask - 1))
888 gen_mov_F1_vreg(dp, rm);
896 if (dp && (insn & (1 << 22))) {
897 /* two-register transfer */
898 rn = (insn >> 16) & 0xf;
899 rd = (insn >> 12) & 0xf;
905 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
907 if (insn & (1 << 20)) {
910 gen_mov_F0_vreg(1, rm);
912 gen_movl_reg_T0(s, rd);
913 gen_movl_reg_T1(s, rn);
915 gen_mov_F0_vreg(0, rm);
917 gen_movl_reg_T0(s, rn);
918 gen_mov_F0_vreg(0, rm + 1);
920 gen_movl_reg_T0(s, rd);
925 gen_movl_T0_reg(s, rd);
926 gen_movl_T1_reg(s, rn);
928 gen_mov_vreg_F0(1, rm);
930 gen_movl_T0_reg(s, rn);
932 gen_mov_vreg_F0(0, rm);
933 gen_movl_T0_reg(s, rd);
935 gen_mov_vreg_F0(0, rm + 1);
940 rn = (insn >> 16) & 0xf;
942 rd = (insn >> 12) & 0xf;
944 rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
945 gen_movl_T1_reg(s, rn);
946 if ((insn & 0x01200000) == 0x01000000) {
947 /* Single load/store */
948 offset = (insn & 0xff) << 2;
949 if ((insn & (1 << 23)) == 0)
951 gen_op_addl_T1_im(offset);
952 if (insn & (1 << 20)) {
954 gen_mov_vreg_F0(dp, rd);
956 gen_mov_F0_vreg(dp, rd);
960 /* load/store multiple */
962 n = (insn >> 1) & 0x7f;
966 if (insn & (1 << 24)) /* pre-decrement */
967 gen_op_addl_T1_im(-((insn & 0xff) << 2));
973 for (i = 0; i < n; i++) {
974 if (insn & (1 << 20)) {
977 gen_mov_vreg_F0(dp, rd + i);
980 gen_mov_F0_vreg(dp, rd + i);
983 gen_op_addl_T1_im(offset);
985 if (insn & (1 << 21)) {
987 if (insn & (1 << 24))
988 offset = -offset * n;
989 else if (dp && (insn & 1))
995 gen_op_addl_T1_im(offset);
996 gen_movl_reg_T1(s, rn);
1002 /* Should never happen. */
1008 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
1010 TranslationBlock *tb;
1013 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1015 gen_op_goto_tb0(TBPARAM(tb));
1017 gen_op_goto_tb1(TBPARAM(tb));
1018 gen_op_movl_T0_im(dest);
1019 gen_op_movl_r15_T0();
1020 gen_op_movl_T0_im((long)tb + n);
1023 gen_op_movl_T0_im(dest);
1024 gen_op_movl_r15_T0();
1030 static inline void gen_jmp (DisasContext *s, uint32_t dest)
1032 if (__builtin_expect(s->singlestep_enabled, 0)) {
1033 /* An indirect jump so that we still trigger the debug exception. */
1036 gen_op_movl_T0_im(dest);
1039 gen_goto_tb(s, 0, dest);
1040 s->is_jmp = DISAS_TB_JUMP;
1044 static inline void gen_mulxy(int x, int y)
1047 gen_op_sarl_T0_im(16);
1051 gen_op_sarl_T1_im(16);
1057 /* Return the mask of PSR bits set by a MSR instruction. */
1058 static uint32_t msr_mask(DisasContext *s, int flags, int spsr) {
1062 if (flags & (1 << 0))
1064 if (flags & (1 << 1))
1066 if (flags & (1 << 2))
1068 if (flags & (1 << 3))
1070 /* Mask out undefined bits. */
1072 /* Mask out state bits. */
1074 mask &= ~0x01000020;
1075 /* Mask out privileged bits. */
1081 /* Returns nonzero if access to the PSR is not permitted. */
1082 static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
1085 /* ??? This is also undefined in system mode. */
1088 gen_op_movl_spsr_T0(mask);
1090 gen_op_movl_cpsr_T0(mask);
1096 static void gen_exception_return(DisasContext *s)
1098 gen_op_movl_reg_TN[0][15]();
1099 gen_op_movl_T0_spsr();
1100 gen_op_movl_cpsr_T0(0xffffffff);
1101 s->is_jmp = DISAS_UPDATE;
1104 static void disas_arm_insn(CPUState * env, DisasContext *s)
1106 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
1108 insn = ldl_code(s->pc);
1113 /* Unconditional instructions. */
1114 if ((insn & 0x0d70f000) == 0x0550f000)
1116 else if ((insn & 0x0e000000) == 0x0a000000) {
1117 /* branch link and change to thumb (blx <offset>) */
1120 val = (uint32_t)s->pc;
1121 gen_op_movl_T0_im(val);
1122 gen_movl_reg_T0(s, 14);
1123 /* Sign-extend the 24-bit offset */
1124 offset = (((int32_t)insn) << 8) >> 8;
1125 /* offset * 4 + bit24 * 2 + (thumb bit) */
1126 val += (offset << 2) | ((insn >> 23) & 2) | 1;
1127 /* pipeline offset */
1129 gen_op_movl_T0_im(val);
1132 } else if ((insn & 0x0fe00000) == 0x0c400000) {
1133 /* Coprocessor double register transfer. */
1134 } else if ((insn & 0x0f000010) == 0x0e000010) {
1135 /* Additional coprocessor register transfer. */
1136 } else if ((insn & 0x0ff10010) == 0x01000000) {
1137 /* cps (privileged) */
1138 } else if ((insn & 0x0ffffdff) == 0x01010000) {
1140 if (insn & (1 << 9)) {
1141 /* BE8 mode not implemented. */
1149 /* if not always execute, we generate a conditional jump to
1151 s->condlabel = gen_new_label();
1152 gen_test_cc[cond ^ 1](s->condlabel);
1154 //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1155 //s->is_jmp = DISAS_JUMP_NEXT;
1157 if ((insn & 0x0f900000) == 0x03000000) {
1158 if ((insn & 0x0fb0f000) != 0x0320f000)
1160 /* CPSR = immediate */
1162 shift = ((insn >> 8) & 0xf) * 2;
1164 val = (val >> shift) | (val << (32 - shift));
1165 gen_op_movl_T0_im(val);
1166 i = ((insn & (1 << 22)) != 0);
1167 if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i))
1169 } else if ((insn & 0x0f900000) == 0x01000000
1170 && (insn & 0x00000090) != 0x00000090) {
1171 /* miscellaneous instructions */
1172 op1 = (insn >> 21) & 3;
1173 sh = (insn >> 4) & 0xf;
1176 case 0x0: /* move program status register */
1179 gen_movl_T0_reg(s, rm);
1180 i = ((op1 & 2) != 0);
1181 if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i))
1185 rd = (insn >> 12) & 0xf;
1189 gen_op_movl_T0_spsr();
1191 gen_op_movl_T0_cpsr();
1193 gen_movl_reg_T0(s, rd);
1198 /* branch/exchange thumb (bx). */
1199 gen_movl_T0_reg(s, rm);
1201 } else if (op1 == 3) {
1203 rd = (insn >> 12) & 0xf;
1204 gen_movl_T0_reg(s, rm);
1206 gen_movl_reg_T0(s, rd);
1214 /* Trivial implementation equivalent to bx. */
1215 gen_movl_T0_reg(s, rm);
1225 /* branch link/exchange thumb (blx) */
1226 val = (uint32_t)s->pc;
1227 gen_op_movl_T0_im(val);
1228 gen_movl_reg_T0(s, 14);
1229 gen_movl_T0_reg(s, rm);
1232 case 0x5: /* saturating add/subtract */
1233 rd = (insn >> 12) & 0xf;
1234 rn = (insn >> 16) & 0xf;
1235 gen_movl_T0_reg(s, rm);
1236 gen_movl_T1_reg(s, rn);
1238 gen_op_double_T1_saturate();
1240 gen_op_subl_T0_T1_saturate();
1242 gen_op_addl_T0_T1_saturate();
1243 gen_movl_reg_T0(s, rd);
1246 gen_op_movl_T0_im((long)s->pc - 4);
1247 gen_op_movl_reg_TN[0][15]();
1249 s->is_jmp = DISAS_JUMP;
1251 case 0x8: /* signed multiply */
1255 rs = (insn >> 8) & 0xf;
1256 rn = (insn >> 12) & 0xf;
1257 rd = (insn >> 16) & 0xf;
1259 /* (32 * 16) >> 16 */
1260 gen_movl_T0_reg(s, rm);
1261 gen_movl_T1_reg(s, rs);
1263 gen_op_sarl_T1_im(16);
1266 gen_op_imulw_T0_T1();
1267 if ((sh & 2) == 0) {
1268 gen_movl_T1_reg(s, rn);
1269 gen_op_addl_T0_T1_setq();
1271 gen_movl_reg_T0(s, rd);
1274 gen_movl_T0_reg(s, rm);
1275 gen_movl_T1_reg(s, rs);
1276 gen_mulxy(sh & 2, sh & 4);
1278 gen_op_signbit_T1_T0();
1279 gen_op_addq_T0_T1(rn, rd);
1280 gen_movl_reg_T0(s, rn);
1281 gen_movl_reg_T1(s, rd);
1284 gen_movl_T1_reg(s, rn);
1285 gen_op_addl_T0_T1_setq();
1287 gen_movl_reg_T0(s, rd);
1294 } else if (((insn & 0x0e000000) == 0 &&
1295 (insn & 0x00000090) != 0x90) ||
1296 ((insn & 0x0e000000) == (1 << 25))) {
1297 int set_cc, logic_cc, shiftop;
1299 op1 = (insn >> 21) & 0xf;
1300 set_cc = (insn >> 20) & 1;
1301 logic_cc = table_logic_cc[op1] & set_cc;
1303 /* data processing instruction */
1304 if (insn & (1 << 25)) {
1305 /* immediate operand */
1307 shift = ((insn >> 8) & 0xf) * 2;
1309 val = (val >> shift) | (val << (32 - shift));
1310 gen_op_movl_T1_im(val);
1311 if (logic_cc && shift)
1316 gen_movl_T1_reg(s, rm);
1317 shiftop = (insn >> 5) & 3;
1318 if (!(insn & (1 << 4))) {
1319 shift = (insn >> 7) & 0x1f;
1322 gen_shift_T1_im_cc[shiftop](shift);
1324 gen_shift_T1_im[shiftop](shift);
1326 } else if (shiftop != 0) {
1328 gen_shift_T1_0_cc[shiftop]();
1330 gen_shift_T1_0[shiftop]();
1334 rs = (insn >> 8) & 0xf;
1335 gen_movl_T0_reg(s, rs);
1337 gen_shift_T1_T0_cc[shiftop]();
1339 gen_shift_T1_T0[shiftop]();
1343 if (op1 != 0x0f && op1 != 0x0d) {
1344 rn = (insn >> 16) & 0xf;
1345 gen_movl_T0_reg(s, rn);
1347 rd = (insn >> 12) & 0xf;
1350 gen_op_andl_T0_T1();
1351 gen_movl_reg_T0(s, rd);
1353 gen_op_logic_T0_cc();
1356 gen_op_xorl_T0_T1();
1357 gen_movl_reg_T0(s, rd);
1359 gen_op_logic_T0_cc();
1362 if (set_cc && rd == 15) {
1363 /* SUBS r15, ... is used for exception return. */
1366 gen_op_subl_T0_T1_cc();
1367 gen_exception_return(s);
1370 gen_op_subl_T0_T1_cc();
1372 gen_op_subl_T0_T1();
1373 gen_movl_reg_T0(s, rd);
1378 gen_op_rsbl_T0_T1_cc();
1380 gen_op_rsbl_T0_T1();
1381 gen_movl_reg_T0(s, rd);
1385 gen_op_addl_T0_T1_cc();
1387 gen_op_addl_T0_T1();
1388 gen_movl_reg_T0(s, rd);
1392 gen_op_adcl_T0_T1_cc();
1394 gen_op_adcl_T0_T1();
1395 gen_movl_reg_T0(s, rd);
1399 gen_op_sbcl_T0_T1_cc();
1401 gen_op_sbcl_T0_T1();
1402 gen_movl_reg_T0(s, rd);
1406 gen_op_rscl_T0_T1_cc();
1408 gen_op_rscl_T0_T1();
1409 gen_movl_reg_T0(s, rd);
1413 gen_op_andl_T0_T1();
1414 gen_op_logic_T0_cc();
1419 gen_op_xorl_T0_T1();
1420 gen_op_logic_T0_cc();
1425 gen_op_subl_T0_T1_cc();
1430 gen_op_addl_T0_T1_cc();
1435 gen_movl_reg_T0(s, rd);
1437 gen_op_logic_T0_cc();
1440 if (logic_cc && rd == 15) {
1441 /* MOVS r15, ... is used for exception return. */
1444 gen_op_movl_T0_T1();
1445 gen_exception_return(s);
1447 gen_movl_reg_T1(s, rd);
1449 gen_op_logic_T1_cc();
1453 gen_op_bicl_T0_T1();
1454 gen_movl_reg_T0(s, rd);
1456 gen_op_logic_T0_cc();
1461 gen_movl_reg_T1(s, rd);
1463 gen_op_logic_T1_cc();
1467 /* other instructions */
1468 op1 = (insn >> 24) & 0xf;
1472 /* multiplies, extra load/stores */
1473 sh = (insn >> 5) & 3;
1476 rd = (insn >> 16) & 0xf;
1477 rn = (insn >> 12) & 0xf;
1478 rs = (insn >> 8) & 0xf;
1480 if (((insn >> 22) & 3) == 0) {
1482 gen_movl_T0_reg(s, rs);
1483 gen_movl_T1_reg(s, rm);
1485 if (insn & (1 << 21)) {
1486 gen_movl_T1_reg(s, rn);
1487 gen_op_addl_T0_T1();
1489 if (insn & (1 << 20))
1490 gen_op_logic_T0_cc();
1491 gen_movl_reg_T0(s, rd);
1494 gen_movl_T0_reg(s, rs);
1495 gen_movl_T1_reg(s, rm);
1496 if (insn & (1 << 22))
1497 gen_op_imull_T0_T1();
1499 gen_op_mull_T0_T1();
1500 if (insn & (1 << 21)) /* mult accumulate */
1501 gen_op_addq_T0_T1(rn, rd);
1502 if (!(insn & (1 << 23))) { /* double accumulate */
1504 gen_op_addq_lo_T0_T1(rn);
1505 gen_op_addq_lo_T0_T1(rd);
1507 if (insn & (1 << 20))
1509 gen_movl_reg_T0(s, rn);
1510 gen_movl_reg_T1(s, rd);
1513 rn = (insn >> 16) & 0xf;
1514 rd = (insn >> 12) & 0xf;
1515 if (insn & (1 << 23)) {
1516 /* load/store exclusive */
1519 /* SWP instruction */
1522 gen_movl_T0_reg(s, rm);
1523 gen_movl_T1_reg(s, rn);
1524 if (insn & (1 << 22)) {
1529 gen_movl_reg_T0(s, rd);
1533 /* Misc load/store */
1534 rn = (insn >> 16) & 0xf;
1535 rd = (insn >> 12) & 0xf;
1536 gen_movl_T1_reg(s, rn);
1537 if (insn & (1 << 24))
1538 gen_add_datah_offset(s, insn);
1539 if (insn & (1 << 20)) {
1553 gen_movl_reg_T0(s, rd);
1554 } else if (sh & 2) {
1558 gen_movl_T0_reg(s, rd);
1560 gen_op_addl_T1_im(4);
1561 gen_movl_T0_reg(s, rd + 1);
1563 if ((insn & (1 << 24)) || (insn & (1 << 20)))
1564 gen_op_addl_T1_im(-4);
1568 gen_movl_reg_T0(s, rd);
1569 gen_op_addl_T1_im(4);
1571 gen_movl_reg_T0(s, rd + 1);
1572 if ((insn & (1 << 24)) || (insn & (1 << 20)))
1573 gen_op_addl_T1_im(-4);
1577 gen_movl_T0_reg(s, rd);
1580 if (!(insn & (1 << 24))) {
1581 gen_add_datah_offset(s, insn);
1582 gen_movl_reg_T1(s, rn);
1583 } else if (insn & (1 << 21)) {
1584 gen_movl_reg_T1(s, rn);
1592 /* Check for undefined extension instructions
1593 * per the ARM Bible IE:
1594 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
1596 sh = (0xf << 20) | (0xf << 4);
1597 if (op1 == 0x7 && ((insn & sh) == sh))
1601 /* load/store byte/word */
1602 rn = (insn >> 16) & 0xf;
1603 rd = (insn >> 12) & 0xf;
1604 gen_movl_T1_reg(s, rn);
1605 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
1606 if (insn & (1 << 24))
1607 gen_add_data_offset(s, insn);
1608 if (insn & (1 << 20)) {
1610 #if defined(CONFIG_USER_ONLY)
1611 if (insn & (1 << 22))
1616 if (insn & (1 << 22)) {
1620 gen_op_ldub_kernel();
1625 gen_op_ldl_kernel();
1631 gen_movl_reg_T0(s, rd);
1634 gen_movl_T0_reg(s, rd);
1635 #if defined(CONFIG_USER_ONLY)
1636 if (insn & (1 << 22))
1641 if (insn & (1 << 22)) {
1645 gen_op_stb_kernel();
1650 gen_op_stl_kernel();
1654 if (!(insn & (1 << 24))) {
1655 gen_add_data_offset(s, insn);
1656 gen_movl_reg_T1(s, rn);
1657 } else if (insn & (1 << 21))
1658 gen_movl_reg_T1(s, rn); {
1664 int j, n, user, loaded_base;
1665 /* load/store multiple words */
1666 /* XXX: store correct base if write back */
1668 if (insn & (1 << 22)) {
1670 goto illegal_op; /* only usable in supervisor mode */
1672 if ((insn & (1 << 15)) == 0)
1675 rn = (insn >> 16) & 0xf;
1676 gen_movl_T1_reg(s, rn);
1678 /* compute total size */
1682 if (insn & (1 << i))
1685 /* XXX: test invalid n == 0 case ? */
1686 if (insn & (1 << 23)) {
1687 if (insn & (1 << 24)) {
1689 gen_op_addl_T1_im(4);
1691 /* post increment */
1694 if (insn & (1 << 24)) {
1696 gen_op_addl_T1_im(-(n * 4));
1698 /* post decrement */
1700 gen_op_addl_T1_im(-((n - 1) * 4));
1705 if (insn & (1 << i)) {
1706 if (insn & (1 << 20)) {
1712 gen_op_movl_user_T0(i);
1713 } else if (i == rn) {
1714 gen_op_movl_T2_T0();
1717 gen_movl_reg_T0(s, i);
1722 /* special case: r15 = PC + 12 */
1723 val = (long)s->pc + 8;
1724 gen_op_movl_TN_im[0](val);
1726 gen_op_movl_T0_user(i);
1728 gen_movl_T0_reg(s, i);
1733 /* no need to add after the last transfer */
1735 gen_op_addl_T1_im(4);
1738 if (insn & (1 << 21)) {
1740 if (insn & (1 << 23)) {
1741 if (insn & (1 << 24)) {
1744 /* post increment */
1745 gen_op_addl_T1_im(4);
1748 if (insn & (1 << 24)) {
1751 gen_op_addl_T1_im(-((n - 1) * 4));
1753 /* post decrement */
1754 gen_op_addl_T1_im(-(n * 4));
1757 gen_movl_reg_T1(s, rn);
1760 gen_op_movl_T0_T2();
1761 gen_movl_reg_T0(s, rn);
1763 if ((insn & (1 << 22)) && !user) {
1764 /* Restore CPSR from SPSR. */
1765 gen_op_movl_T0_spsr();
1766 gen_op_movl_cpsr_T0(0xffffffff);
1767 s->is_jmp = DISAS_UPDATE;
1776 /* branch (and link) */
1777 val = (int32_t)s->pc;
1778 if (insn & (1 << 24)) {
1779 gen_op_movl_T0_im(val);
1780 gen_op_movl_reg_TN[0][14]();
1782 offset = (((int32_t)insn << 8) >> 8);
1783 val += (offset << 2) + 4;
1791 op1 = (insn >> 8) & 0xf;
1795 if (disas_vfp_insn (env, s, insn))
1799 if (disas_cp15_insn (s, insn))
1803 /* unknown coprocessor. */
1809 gen_op_movl_T0_im((long)s->pc);
1810 gen_op_movl_reg_TN[0][15]();
1812 s->is_jmp = DISAS_JUMP;
1816 gen_op_movl_T0_im((long)s->pc - 4);
1817 gen_op_movl_reg_TN[0][15]();
1818 gen_op_undef_insn();
1819 s->is_jmp = DISAS_JUMP;
1825 static void disas_thumb_insn(DisasContext *s)
1827 uint32_t val, insn, op, rm, rn, rd, shift, cond;
1831 insn = lduw_code(s->pc);
1834 switch (insn >> 12) {
1837 op = (insn >> 11) & 3;
1840 rn = (insn >> 3) & 7;
1841 gen_movl_T0_reg(s, rn);
1842 if (insn & (1 << 10)) {
1844 gen_op_movl_T1_im((insn >> 6) & 7);
1847 rm = (insn >> 6) & 7;
1848 gen_movl_T1_reg(s, rm);
1850 if (insn & (1 << 9))
1851 gen_op_subl_T0_T1_cc();
1853 gen_op_addl_T0_T1_cc();
1854 gen_movl_reg_T0(s, rd);
1856 /* shift immediate */
1857 rm = (insn >> 3) & 7;
1858 shift = (insn >> 6) & 0x1f;
1859 gen_movl_T0_reg(s, rm);
1860 gen_shift_T0_im_thumb[op](shift);
1861 gen_movl_reg_T0(s, rd);
1865 /* arithmetic large immediate */
1866 op = (insn >> 11) & 3;
1867 rd = (insn >> 8) & 0x7;
1869 gen_op_movl_T0_im(insn & 0xff);
1871 gen_movl_T0_reg(s, rd);
1872 gen_op_movl_T1_im(insn & 0xff);
1876 gen_op_logic_T0_cc();
1879 gen_op_subl_T0_T1_cc();
1882 gen_op_addl_T0_T1_cc();
1885 gen_op_subl_T0_T1_cc();
1889 gen_movl_reg_T0(s, rd);
1892 if (insn & (1 << 11)) {
1893 rd = (insn >> 8) & 7;
1894 /* load pc-relative. Bit 1 of PC is ignored. */
1895 val = s->pc + 2 + ((insn & 0xff) * 4);
1896 val &= ~(uint32_t)2;
1897 gen_op_movl_T1_im(val);
1899 gen_movl_reg_T0(s, rd);
1902 if (insn & (1 << 10)) {
1903 /* data processing extended or blx */
1904 rd = (insn & 7) | ((insn >> 4) & 8);
1905 rm = (insn >> 3) & 0xf;
1906 op = (insn >> 8) & 3;
1909 gen_movl_T0_reg(s, rd);
1910 gen_movl_T1_reg(s, rm);
1911 gen_op_addl_T0_T1();
1912 gen_movl_reg_T0(s, rd);
1915 gen_movl_T0_reg(s, rd);
1916 gen_movl_T1_reg(s, rm);
1917 gen_op_subl_T0_T1_cc();
1919 case 2: /* mov/cpy */
1920 gen_movl_T0_reg(s, rm);
1921 gen_movl_reg_T0(s, rd);
1923 case 3:/* branch [and link] exchange thumb register */
1924 if (insn & (1 << 7)) {
1925 val = (uint32_t)s->pc | 1;
1926 gen_op_movl_T1_im(val);
1927 gen_movl_reg_T1(s, 14);
1929 gen_movl_T0_reg(s, rm);
1936 /* data processing register */
1938 rm = (insn >> 3) & 7;
1939 op = (insn >> 6) & 0xf;
1940 if (op == 2 || op == 3 || op == 4 || op == 7) {
1941 /* the shift/rotate ops want the operands backwards */
1950 if (op == 9) /* neg */
1951 gen_op_movl_T0_im(0);
1952 else if (op != 0xf) /* mvn doesn't read its first operand */
1953 gen_movl_T0_reg(s, rd);
1955 gen_movl_T1_reg(s, rm);
1958 gen_op_andl_T0_T1();
1959 gen_op_logic_T0_cc();
1962 gen_op_xorl_T0_T1();
1963 gen_op_logic_T0_cc();
1966 gen_op_shll_T1_T0_cc();
1967 gen_op_logic_T1_cc();
1970 gen_op_shrl_T1_T0_cc();
1971 gen_op_logic_T1_cc();
1974 gen_op_sarl_T1_T0_cc();
1975 gen_op_logic_T1_cc();
1978 gen_op_adcl_T0_T1_cc();
1981 gen_op_sbcl_T0_T1_cc();
1984 gen_op_rorl_T1_T0_cc();
1985 gen_op_logic_T1_cc();
1988 gen_op_andl_T0_T1();
1989 gen_op_logic_T0_cc();
1993 gen_op_subl_T0_T1_cc();
1996 gen_op_subl_T0_T1_cc();
2000 gen_op_addl_T0_T1_cc();
2005 gen_op_logic_T0_cc();
2008 gen_op_mull_T0_T1();
2009 gen_op_logic_T0_cc();
2012 gen_op_bicl_T0_T1();
2013 gen_op_logic_T0_cc();
2017 gen_op_logic_T1_cc();
2024 gen_movl_reg_T1(s, rm);
2026 gen_movl_reg_T0(s, rd);
2031 /* load/store register offset. */
2033 rn = (insn >> 3) & 7;
2034 rm = (insn >> 6) & 7;
2035 op = (insn >> 9) & 7;
2036 gen_movl_T1_reg(s, rn);
2037 gen_movl_T2_reg(s, rm);
2038 gen_op_addl_T1_T2();
2040 if (op < 3) /* store */
2041 gen_movl_T0_reg(s, rd);
2069 if (op >= 3) /* load */
2070 gen_movl_reg_T0(s, rd);
2074 /* load/store word immediate offset */
2076 rn = (insn >> 3) & 7;
2077 gen_movl_T1_reg(s, rn);
2078 val = (insn >> 4) & 0x7c;
2079 gen_op_movl_T2_im(val);
2080 gen_op_addl_T1_T2();
2082 if (insn & (1 << 11)) {
2085 gen_movl_reg_T0(s, rd);
2088 gen_movl_T0_reg(s, rd);
2094 /* load/store byte immediate offset */
2096 rn = (insn >> 3) & 7;
2097 gen_movl_T1_reg(s, rn);
2098 val = (insn >> 6) & 0x1f;
2099 gen_op_movl_T2_im(val);
2100 gen_op_addl_T1_T2();
2102 if (insn & (1 << 11)) {
2105 gen_movl_reg_T0(s, rd);
2108 gen_movl_T0_reg(s, rd);
2114 /* load/store halfword immediate offset */
2116 rn = (insn >> 3) & 7;
2117 gen_movl_T1_reg(s, rn);
2118 val = (insn >> 5) & 0x3e;
2119 gen_op_movl_T2_im(val);
2120 gen_op_addl_T1_T2();
2122 if (insn & (1 << 11)) {
2125 gen_movl_reg_T0(s, rd);
2128 gen_movl_T0_reg(s, rd);
2134 /* load/store from stack */
2135 rd = (insn >> 8) & 7;
2136 gen_movl_T1_reg(s, 13);
2137 val = (insn & 0xff) * 4;
2138 gen_op_movl_T2_im(val);
2139 gen_op_addl_T1_T2();
2141 if (insn & (1 << 11)) {
2144 gen_movl_reg_T0(s, rd);
2147 gen_movl_T0_reg(s, rd);
2153 /* add to high reg */
2154 rd = (insn >> 8) & 7;
2155 if (insn & (1 << 11)) {
2157 gen_movl_T0_reg(s, 13);
2159 /* PC. bit 1 is ignored. */
2160 gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
2162 val = (insn & 0xff) * 4;
2163 gen_op_movl_T1_im(val);
2164 gen_op_addl_T0_T1();
2165 gen_movl_reg_T0(s, rd);
2170 op = (insn >> 8) & 0xf;
2173 /* adjust stack pointer */
2174 gen_movl_T1_reg(s, 13);
2175 val = (insn & 0x7f) * 4;
2176 if (insn & (1 << 7))
2177 val = -(int32_t)val;
2178 gen_op_movl_T2_im(val);
2179 gen_op_addl_T1_T2();
2180 gen_movl_reg_T1(s, 13);
2183 case 4: case 5: case 0xc: case 0xd:
2185 gen_movl_T1_reg(s, 13);
2186 if (insn & (1 << 8))
2190 for (i = 0; i < 8; i++) {
2191 if (insn & (1 << i))
2194 if ((insn & (1 << 11)) == 0) {
2195 gen_op_movl_T2_im(-offset);
2196 gen_op_addl_T1_T2();
2198 gen_op_movl_T2_im(4);
2199 for (i = 0; i < 8; i++) {
2200 if (insn & (1 << i)) {
2201 if (insn & (1 << 11)) {
2204 gen_movl_reg_T0(s, i);
2207 gen_movl_T0_reg(s, i);
2210 /* advance to the next address. */
2211 gen_op_addl_T1_T2();
2214 if (insn & (1 << 8)) {
2215 if (insn & (1 << 11)) {
2218 /* don't set the pc until the rest of the instruction
2222 gen_movl_T0_reg(s, 14);
2225 gen_op_addl_T1_T2();
2227 if ((insn & (1 << 11)) == 0) {
2228 gen_op_movl_T2_im(-offset);
2229 gen_op_addl_T1_T2();
2231 /* write back the new stack pointer */
2232 gen_movl_reg_T1(s, 13);
2233 /* set the new PC value */
2234 if ((insn & 0x0900) == 0x0900)
2238 case 0xe: /* bkpt */
2239 gen_op_movl_T0_im((long)s->pc - 2);
2240 gen_op_movl_reg_TN[0][15]();
2242 s->is_jmp = DISAS_JUMP;
2251 /* load/store multiple */
2252 rn = (insn >> 8) & 0x7;
2253 gen_movl_T1_reg(s, rn);
2254 gen_op_movl_T2_im(4);
2255 for (i = 0; i < 8; i++) {
2256 if (insn & (1 << i)) {
2257 if (insn & (1 << 11)) {
2260 gen_movl_reg_T0(s, i);
2263 gen_movl_T0_reg(s, i);
2266 /* advance to the next address */
2267 gen_op_addl_T1_T2();
2270 /* Base register writeback. */
2271 if ((insn & (1 << rn)) == 0)
2272 gen_movl_reg_T1(s, rn);
2276 /* conditional branch or swi */
2277 cond = (insn >> 8) & 0xf;
2283 gen_op_movl_T0_im((long)s->pc | 1);
2284 /* Don't set r15. */
2285 gen_op_movl_reg_TN[0][15]();
2287 s->is_jmp = DISAS_JUMP;
2290 /* generate a conditional jump to next instruction */
2291 s->condlabel = gen_new_label();
2292 gen_test_cc[cond ^ 1](s->condlabel);
2294 //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
2295 //s->is_jmp = DISAS_JUMP_NEXT;
2296 gen_movl_T1_reg(s, 15);
2298 /* jump to the offset */
2299 val = (uint32_t)s->pc + 2;
2300 offset = ((int32_t)insn << 24) >> 24;
2306 /* unconditional branch */
2307 if (insn & (1 << 11)) {
2308 /* Second half of blx. */
2309 offset = ((insn & 0x7ff) << 1);
2310 gen_movl_T0_reg(s, 14);
2311 gen_op_movl_T1_im(offset);
2312 gen_op_addl_T0_T1();
2313 gen_op_movl_T1_im(0xfffffffc);
2314 gen_op_andl_T0_T1();
2316 val = (uint32_t)s->pc;
2317 gen_op_movl_T1_im(val | 1);
2318 gen_movl_reg_T1(s, 14);
2322 val = (uint32_t)s->pc;
2323 offset = ((int32_t)insn << 21) >> 21;
2324 val += (offset << 1) + 2;
2329 /* branch and link [and switch to arm] */
2330 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
2331 /* Instruction spans a page boundary. Implement it as two
2332 16-bit instructions in case the second half causes an
2334 offset = ((int32_t)insn << 21) >> 9;
2335 val = s->pc + 2 + offset;
2336 gen_op_movl_T0_im(val);
2337 gen_movl_reg_T0(s, 14);
2340 if (insn & (1 << 11)) {
2341 /* Second half of bl. */
2342 offset = ((insn & 0x7ff) << 1) | 1;
2343 gen_movl_T0_reg(s, 14);
2344 gen_op_movl_T1_im(offset);
2345 gen_op_addl_T0_T1();
2347 val = (uint32_t)s->pc;
2348 gen_op_movl_T1_im(val | 1);
2349 gen_movl_reg_T1(s, 14);
2353 offset = ((int32_t)insn << 21) >> 10;
2354 insn = lduw_code(s->pc);
2355 offset |= insn & 0x7ff;
2357 val = (uint32_t)s->pc + 2;
2358 gen_op_movl_T1_im(val | 1);
2359 gen_movl_reg_T1(s, 14);
2362 if (insn & (1 << 12)) {
2367 val &= ~(uint32_t)2;
2368 gen_op_movl_T0_im(val);
2374 gen_op_movl_T0_im((long)s->pc - 2);
2375 gen_op_movl_reg_TN[0][15]();
2376 gen_op_undef_insn();
2377 s->is_jmp = DISAS_JUMP;
2380 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
2381 basic block 'tb'. If search_pc is TRUE, also generate PC
2382 information for each intermediate instruction. */
2383 static inline int gen_intermediate_code_internal(CPUState *env,
2384 TranslationBlock *tb,
2387 DisasContext dc1, *dc = &dc1;
2388 uint16_t *gen_opc_end;
2390 target_ulong pc_start;
2391 uint32_t next_page_start;
2393 /* generate intermediate code */
2398 gen_opc_ptr = gen_opc_buf;
2399 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2400 gen_opparam_ptr = gen_opparam_buf;
2402 dc->is_jmp = DISAS_NEXT;
2404 dc->singlestep_enabled = env->singlestep_enabled;
2406 dc->thumb = env->thumb;
2407 #if !defined(CONFIG_USER_ONLY)
2408 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
2410 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2414 if (env->nb_breakpoints > 0) {
2415 for(j = 0; j < env->nb_breakpoints; j++) {
2416 if (env->breakpoints[j] == dc->pc) {
2417 gen_op_movl_T0_im((long)dc->pc);
2418 gen_op_movl_reg_TN[0][15]();
2420 dc->is_jmp = DISAS_JUMP;
2426 j = gen_opc_ptr - gen_opc_buf;
2430 gen_opc_instr_start[lj++] = 0;
2432 gen_opc_pc[lj] = dc->pc;
2433 gen_opc_instr_start[lj] = 1;
2437 disas_thumb_insn(dc);
2439 disas_arm_insn(env, dc);
2441 if (dc->condjmp && !dc->is_jmp) {
2442 gen_set_label(dc->condlabel);
2445 /* Translation stops when a conditional branch is enoutered.
2446 * Otherwise the subsequent code could get translated several times.
2447 * Also stop translation when a page boundary is reached. This
2448 * ensures prefech aborts occur at the right place. */
2449 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2450 !env->singlestep_enabled &&
2451 dc->pc < next_page_start);
2452 /* At this stage dc->condjmp will only be set when the skipped
2453 * instruction was a conditional branch, and the PC has already been
2455 if (__builtin_expect(env->singlestep_enabled, 0)) {
2456 /* Make sure the pc is updated, and raise a debug exception. */
2459 gen_set_label(dc->condlabel);
2461 if (dc->condjmp || !dc->is_jmp) {
2462 gen_op_movl_T0_im((long)dc->pc);
2463 gen_op_movl_reg_TN[0][15]();
2468 switch(dc->is_jmp) {
2470 gen_goto_tb(dc, 1, dc->pc);
2475 /* indicate that the hash table must be used to find the next TB */
2480 /* nothing more to generate */
2484 gen_set_label(dc->condlabel);
2485 gen_goto_tb(dc, 1, dc->pc);
2489 *gen_opc_ptr = INDEX_op_end;
2492 if (loglevel & CPU_LOG_TB_IN_ASM) {
2493 fprintf(logfile, "----------------\n");
2494 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2495 target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
2496 fprintf(logfile, "\n");
2497 if (loglevel & (CPU_LOG_TB_OP)) {
2498 fprintf(logfile, "OP:\n");
2499 dump_ops(gen_opc_buf, gen_opparam_buf);
2500 fprintf(logfile, "\n");
2505 j = gen_opc_ptr - gen_opc_buf;
2508 gen_opc_instr_start[lj++] = 0;
2511 tb->size = dc->pc - pc_start;
2516 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2518 return gen_intermediate_code_internal(env, tb, 0);
2521 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2523 return gen_intermediate_code_internal(env, tb, 1);
2526 static const char *cpu_mode_names[16] = {
2527 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
2528 "???", "???", "???", "und", "???", "???", "???", "sys"
2530 void cpu_dump_state(CPUState *env, FILE *f,
2531 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2543 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2545 cpu_fprintf(f, "\n");
2547 cpu_fprintf(f, " ");
2549 psr = cpsr_read(env);
2550 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d %x\n",
2552 psr & (1 << 31) ? 'N' : '-',
2553 psr & (1 << 30) ? 'Z' : '-',
2554 psr & (1 << 29) ? 'C' : '-',
2555 psr & (1 << 28) ? 'V' : '-',
2556 psr & CPSR_T ? 'T' : 'A',
2557 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
2559 for (i = 0; i < 16; i++) {
2560 d.d = env->vfp.regs[i];
2563 cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
2564 i * 2, (int)s0.i, s0.s,
2565 i * 2 + 1, (int)s0.i, s0.s,
2566 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2569 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);