📄 translate.c
字号:
} break; } /* Setup the next operands. */ veclen--; rd = ((rd + delta_d) & (bank_mask - 1)) | (rd & bank_mask); if (op == 15) { /* One source operand. */ rm = ((rm + delta_m) & (bank_mask - 1)) | (rm & bank_mask); gen_mov_F0_vreg(dp, rm); } else { /* Two source operands. */ rn = ((rn + delta_d) & (bank_mask - 1)) | (rn & bank_mask); gen_mov_F0_vreg(dp, rn); if (delta_m) { rm = ((rm + delta_m) & (bank_mask - 1)) | (rm & bank_mask); gen_mov_F1_vreg(dp, rm); } } } } break; case 0xc: case 0xd: if (dp && (insn & (1 << 22))) { /* two-register transfer */ rn = (insn >> 16) & 0xf; rd = (insn >> 12) & 0xf; if (dp) { if (insn & (1 << 5)) return 1; rm = insn & 0xf; } else rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1); if (insn & (1 << 20)) { /* vfp->arm */ if (dp) { gen_mov_F0_vreg(1, rm); gen_op_vfp_mrrd(); gen_movl_reg_T0(s, rd); gen_movl_reg_T1(s, rn); } else { gen_mov_F0_vreg(0, rm); gen_op_vfp_mrs(); gen_movl_reg_T0(s, rn); gen_mov_F0_vreg(0, rm + 1); gen_op_vfp_mrs(); gen_movl_reg_T0(s, rd); } } else { /* arm->vfp */ if (dp) { gen_movl_T0_reg(s, rd); gen_movl_T1_reg(s, rn); gen_op_vfp_mdrr(); gen_mov_vreg_F0(1, rm); } else { gen_movl_T0_reg(s, rn); gen_op_vfp_msr(); gen_mov_vreg_F0(0, rm); gen_movl_T0_reg(s, rd); gen_op_vfp_msr(); gen_mov_vreg_F0(0, rm + 1); } } } else { /* Load/store */ rn = (insn >> 16) & 0xf; if (dp) rd = (insn >> 12) & 0xf; else rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1); gen_movl_T1_reg(s, rn); if ((insn & 0x01200000) == 0x01000000) { /* Single load/store */ offset = (insn & 0xff) << 2; if ((insn & (1 << 23)) == 0) offset = -offset; gen_op_addl_T1_im(offset); if (insn & (1 << 20)) { gen_vfp_ld(s, dp); gen_mov_vreg_F0(dp, rd); } else { gen_mov_F0_vreg(dp, rd); gen_vfp_st(s, dp); } } else { /* load/store multiple */ if (dp) n = (insn >> 1) & 0x7f; else n = insn & 0xff; if (insn & (1 << 24)) /* pre-decrement */ gen_op_addl_T1_im(-((insn & 0xff) << 2)); if (dp) offset = 8; else offset = 4; for (i = 0; i < n; i++) { if (insn & (1 << 20)) { /* load */ gen_vfp_ld(s, dp); gen_mov_vreg_F0(dp, rd + i); } else { /* store */ gen_mov_F0_vreg(dp, rd + i); gen_vfp_st(s, dp); } gen_op_addl_T1_im(offset); } if (insn & (1 << 21)) { /* writeback */ if (insn & (1 << 24)) offset = -offset * n; else if (dp && (insn & 1)) offset = 4; else offset = 0; if (offset != 0) gen_op_addl_T1_im(offset); gen_movl_reg_T1(s, rn); } } } break; default: /* Should never happen. */ return 1; } return 0;}static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest){ TranslationBlock *tb; tb = s->tb; if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { if (n == 0) gen_op_goto_tb0(TBPARAM(tb)); else gen_op_goto_tb1(TBPARAM(tb)); gen_op_movl_T0_im(dest); gen_op_movl_r15_T0(); gen_op_movl_T0_im((long)tb + n); gen_op_exit_tb(); } else { gen_op_movl_T0_im(dest); gen_op_movl_r15_T0(); gen_op_movl_T0_0(); gen_op_exit_tb(); }}static inline void gen_jmp (DisasContext *s, uint32_t dest){ if (__builtin_expect(s->singlestep_enabled, 0)) { /* An indirect jump so that we still trigger the debug exception. */ if (s->thumb) dest |= 1; gen_op_movl_T0_im(dest); gen_bx(s); } else { gen_goto_tb(s, 0, dest); s->is_jmp = DISAS_TB_JUMP; }}static inline void gen_mulxy(int x, int y){ if (x) gen_op_sarl_T0_im(16); else gen_op_sxth_T0(); if (y) gen_op_sarl_T1_im(16); else gen_op_sxth_T1(); gen_op_mul_T0_T1();}/* Return the mask of PSR bits set by a MSR instruction. */static uint32_t msr_mask(DisasContext *s, int flags, int spsr) { uint32_t mask; mask = 0; if (flags & (1 << 0)) mask |= 0xff; if (flags & (1 << 1)) mask |= 0xff00; if (flags & (1 << 2)) mask |= 0xff0000; if (flags & (1 << 3)) mask |= 0xff000000; /* Mask out undefined bits. */ mask &= 0xf90f03ff; /* Mask out state bits. */ if (!spsr) mask &= ~0x01000020; /* Mask out privileged bits. */ if (IS_USER(s)) mask &= 0xf80f0200; return mask;}/* Returns nonzero if access to the PSR is not permitted. */static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr){ if (spsr) { /* ??? This is also undefined in system mode. */ if (IS_USER(s)) return 1; gen_op_movl_spsr_T0(mask); } else { gen_op_movl_cpsr_T0(mask); } gen_lookup_tb(s); return 0;}static void gen_exception_return(DisasContext *s){ gen_op_movl_reg_TN[0][15](); gen_op_movl_T0_spsr(); gen_op_movl_cpsr_T0(0xffffffff); s->is_jmp = DISAS_UPDATE;}static void disas_arm_insn(CPUState * env, DisasContext *s){ unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; insn = ldl_code(s->pc); s->pc += 4; cond = insn >> 28; if (cond == 0xf){ /* Unconditional instructions. */ if ((insn & 0x0d70f000) == 0x0550f000) return; /* PLD */ else if ((insn & 0x0e000000) == 0x0a000000) { /* branch link and change to thumb (blx <offset>) */ int32_t offset; val = (uint32_t)s->pc; gen_op_movl_T0_im(val); gen_movl_reg_T0(s, 14); /* Sign-extend the 24-bit offset */ offset = (((int32_t)insn) << 8) >> 8; /* offset * 4 + bit24 * 2 + (thumb bit) */ val += (offset << 2) | ((insn >> 23) & 2) | 1; /* pipeline offset */ val += 4; gen_op_movl_T0_im(val); gen_bx(s); return; } else if ((insn & 0x0fe00000) == 0x0c400000) { /* Coprocessor double register transfer. */ } else if ((insn & 0x0f000010) == 0x0e000010) { /* Additional coprocessor register transfer. */ } else if ((insn & 0x0ff10010) == 0x01000000) { /* cps (privileged) */ } else if ((insn & 0x0ffffdff) == 0x01010000) { /* setend */ if (insn & (1 << 9)) { /* BE8 mode not implemented. */ goto illegal_op; } return; } goto illegal_op; } if (cond != 0xe) { /* if not always execute, we generate a conditional jump to next instruction */ s->condlabel = gen_new_label(); gen_test_cc[cond ^ 1](s->condlabel); s->condjmp = 1; //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); //s->is_jmp = DISAS_JUMP_NEXT; } if ((insn & 0x0f900000) == 0x03000000) { if ((insn & 0x0fb0f000) != 0x0320f000) goto illegal_op; /* CPSR = immediate */ val = insn & 0xff; shift = ((insn >> 8) & 0xf) * 2; if (shift) val = (val >> shift) | (val << (32 - shift)); gen_op_movl_T0_im(val); i = ((insn & (1 << 22)) != 0); if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i)) goto illegal_op; } else if ((insn & 0x0f900000) == 0x01000000 && (insn & 0x00000090) != 0x00000090) { /* miscellaneous instructions */ op1 = (insn >> 21) & 3; sh = (insn >> 4) & 0xf; rm = insn & 0xf; switch (sh) { case 0x0: /* move program status register */ if (op1 & 1) { /* PSR = reg */ gen_movl_T0_reg(s, rm); i = ((op1 & 2) != 0); if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i)) goto illegal_op; } else { /* reg = PSR */ rd = (insn >> 12) & 0xf; if (op1 & 2) { if (IS_USER(s)) goto illegal_op; gen_op_movl_T0_spsr(); } else { gen_op_movl_T0_cpsr(); } gen_movl_reg_T0(s, rd); } break; case 0x1: if (op1 == 1) { /* branch/exchange thumb (bx). */ gen_movl_T0_reg(s, rm); gen_bx(s); } else if (op1 == 3) { /* clz */ rd = (insn >> 12) & 0xf; gen_movl_T0_reg(s, rm); gen_op_clz_T0(); gen_movl_reg_T0(s, rd); } else { goto illegal_op; } break; case 0x2: if (op1 == 1) { ARCH(5J); /* bxj */ /* Trivial implementation equivalent to bx. */ gen_movl_T0_reg(s, rm); gen_bx(s); } else { goto illegal_op; } break; case 0x3: if (op1 != 1) goto illegal_op; /* branch link/exchange thumb (blx) */ val = (uint32_t)s->pc; gen_op_movl_T0_im(val); gen_movl_reg_T0(s, 14); gen_movl_T0_reg(s, rm); gen_bx(s); break; case 0x5: /* saturating add/subtract */ rd = (insn >> 12) & 0xf; rn = (insn >> 16) & 0xf; gen_movl_T0_reg(s, rm); gen_movl_T1_reg(s, rn); if (op1 & 2) gen_op_double_T1_saturate(); if (op1 & 1) gen_op_subl_T0_T1_saturate(); else gen_op_addl_T0_T1_saturate(); gen_movl_reg_T0(s, rd); break; case 7: /* bkpt */ gen_op_movl_T0_im((long)s->pc - 4); gen_op_movl_reg_TN[0][15](); gen_op_bkpt(); s->is_jmp = DISAS_JUMP; break; case 0x8: /* signed multiply */ case 0xa: case 0xc: case 0xe: rs = (insn >> 8) & 0xf; rn = (insn >> 12) & 0xf; rd = (insn >> 16) & 0xf; if (op1 == 1) { /* (32 * 16) >> 16 */ gen_movl_T0_reg(s, rm); gen_movl_T1_reg(s, rs); if (sh & 4) gen_op_sarl_T1_im(16); else gen_op_sxth_T1(); gen_op_imulw_T0_T1(); if ((sh & 2) == 0) { gen_movl_T1_reg(s, rn); gen_op_addl_T0_T1_setq(); } gen_movl_reg_T0(s, rd); } else { /* 16 * 16 */ gen_movl_T0_reg(s, rm); gen_movl_T1_reg(s, rs); gen_mulxy(sh & 2, sh & 4); if (op1 == 2) { gen_op_signbit_T1_T0(); gen_op_addq_T0_T1(rn, rd); gen_movl_reg_T0(s, rn); gen_movl_reg_T1(s, rd); } else { if (op1 == 0) { gen_movl_T1_reg(s, rn); gen_op_addl_T0_T1_setq(); } gen_movl_reg_T0(s, rd); } } break; default: goto illegal_op; } } else if (((insn & 0x0e000000) == 0 && (insn & 0x00000090) != 0x90) || ((insn & 0x0e000000) == (1 << 25))) { int set_cc, logic_cc, shiftop; op1 = (insn >> 21) & 0xf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -