📄 translate.c.svn-base
字号:
case 4: /* Indirect predecrememnt. */ { int tmp; if (addrp && val > 0) { tmp = *addrp; } else { tmp = gen_lea(s, insn, opsize); if (tmp == -1) return -1; if (addrp) *addrp = tmp; } result = gen_ldst(s, opsize, tmp, val); /* ??? This is not exception safe. The instruction may still fault after this point. */ if (val > 0 || !addrp) { reg += QREG_A0; gen_op_mov32(reg, tmp); } } return result; case 5: /* Indirect displacement. */ case 6: /* Indirect index + displacement. */ return gen_ea_once(s, insn, opsize, val, addrp); case 7: /* Other */ switch (reg) { case 0: /* Absolute short. */ case 1: /* Absolute long. */ case 2: /* pc displacement */ case 3: /* pc index+displacement. */ return gen_ea_once(s, insn, opsize, val, addrp); case 4: /* Immediate. */ /* Sign extend values for consistency. */ switch (opsize) { case OS_BYTE: if (val) offset = ldsb_code(s->pc + 1); else offset = ldub_code(s->pc + 1); s->pc += 2; break; case OS_WORD: if (val) offset = ldsw_code(s->pc); else offset = lduw_code(s->pc); s->pc += 2; break; case OS_LONG: offset = read_im32(s); break; default: qemu_assert(0, "Bad immediate operand"); } return gen_im32(offset); default: return -1; } } /* Should never happen. */ return -1;}static void gen_logic_cc(DisasContext *s, int val){ gen_op_logic_cc(val); s->cc_op = CC_OP_LOGIC;}static void gen_jmpcc(DisasContext *s, int cond, int l1){ int tmp; gen_flush_flags(s); switch (cond) { case 0: /* T */ gen_op_jmp(l1); break; case 1: /* F */ break; case 2: /* HI (!C && !Z) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z)); gen_op_jmp_z32(tmp, l1); break; case 3: /* LS (C || Z) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z)); gen_op_jmp_nz32(tmp, l1); break; case 4: /* CC (!C) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C)); gen_op_jmp_z32(tmp, l1); break; case 5: /* CS (C) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C)); gen_op_jmp_nz32(tmp, l1); break; case 6: /* NE (!Z) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z)); gen_op_jmp_z32(tmp, l1); break; case 7: /* EQ (Z) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z)); gen_op_jmp_nz32(tmp, l1); break; case 8: /* VC (!V) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V)); gen_op_jmp_z32(tmp, l1); break; case 9: /* VS (V) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V)); gen_op_jmp_nz32(tmp, l1); break; case 10: /* PL (!N) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N)); gen_op_jmp_z32(tmp, l1); break; case 11: /* MI (N) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N)); gen_op_jmp_nz32(tmp, l1); break; case 12: /* GE (!(N ^ V)) */ tmp = gen_new_qreg(QMODE_I32); gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2)); gen_op_xor32(tmp, tmp, QREG_CC_DEST); gen_op_and32(tmp, tmp, gen_im32(CCF_V)); gen_op_jmp_z32(tmp, l1); break; case 13: /* LT (N ^ V) */ tmp = gen_new_qreg(QMODE_I32); gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2)); gen_op_xor32(tmp, tmp, QREG_CC_DEST); gen_op_and32(tmp, tmp, gen_im32(CCF_V)); gen_op_jmp_nz32(tmp, l1); break; case 14: /* GT (!(Z || (N ^ V))) */ { int l2; l2 = gen_new_label(); tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z)); gen_op_jmp_nz32(tmp, l2); tmp = gen_new_qreg(QMODE_I32); gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2)); gen_op_xor32(tmp, tmp, QREG_CC_DEST); gen_op_and32(tmp, tmp, gen_im32(CCF_V)); gen_op_jmp_nz32(tmp, l2); gen_op_jmp(l1); gen_set_label(l2); } break; case 15: /* LE (Z || (N ^ V)) */ tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z)); gen_op_jmp_nz32(tmp, l1); tmp = gen_new_qreg(QMODE_I32); gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2)); gen_op_xor32(tmp, tmp, QREG_CC_DEST); gen_op_and32(tmp, tmp, gen_im32(CCF_V)); gen_op_jmp_nz32(tmp, l1); break; default: /* Should ever happen. */ abort(); }}DISAS_INSN(scc){ int l1; int cond; int reg; l1 = gen_new_label(); cond = (insn >> 8) & 0xf; reg = DREG(insn, 0); gen_op_and32(reg, reg, gen_im32(0xffffff00)); gen_jmpcc(s, cond ^ 1, l1); gen_op_or32(reg, reg, gen_im32(0xff)); gen_set_label(l1);}/* Force a TB lookup after an instruction that changes the CPU state. */static void gen_lookup_tb(DisasContext *s){ gen_flush_cc_op(s); gen_op_mov32(QREG_PC, gen_im32(s->pc)); s->is_jmp = DISAS_UPDATE;}/* Generate a jump to to the address in qreg DEST. */static void gen_jmp(DisasContext *s, int dest){ gen_flush_cc_op(s); gen_op_mov32(QREG_PC, dest); s->is_jmp = DISAS_JUMP;}static void gen_exception(DisasContext *s, uint32_t where, int nr){ gen_flush_cc_op(s); gen_jmp(s, gen_im32(where)); gen_op_raise_exception(nr);}static inline void gen_addr_fault(DisasContext *s){ gen_exception(s, s->insn_pc, EXCP_ADDRESS);}#define SRC_EA(result, opsize, val, addrp) do { \ result = gen_ea(s, insn, opsize, val, addrp); \ if (result == -1) { \ gen_addr_fault(s); \ return; \ } \ } while (0)#define DEST_EA(insn, opsize, val, addrp) do { \ int ea_result = gen_ea(s, insn, opsize, val, addrp); \ if (ea_result == -1) { \ gen_addr_fault(s); \ return; \ } \ } while (0)/* Generate a jump to an immediate address. */static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest){ TranslationBlock *tb; tb = s->tb; if (__builtin_expect (s->singlestep_enabled, 0)) { gen_exception(s, dest, EXCP_DEBUG); } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) || (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { gen_op_goto_tb(0, n, (long)tb); gen_op_mov32(QREG_PC, gen_im32(dest)); gen_op_mov32(QREG_T0, gen_im32((long)tb + n)); gen_op_exit_tb(); } else { gen_jmp(s, gen_im32(dest)); gen_op_mov32(QREG_T0, gen_im32(0)); gen_op_exit_tb(); } s->is_jmp = DISAS_TB_JUMP;}DISAS_INSN(undef_mac){ gen_exception(s, s->pc - 2, EXCP_LINEA);}DISAS_INSN(undef_fpu){ gen_exception(s, s->pc - 2, EXCP_LINEF);}DISAS_INSN(undef){ gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED); cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x", insn, s->pc - 2);}DISAS_INSN(mulw){ int reg; int tmp; int src; int sign; sign = (insn & 0x100) != 0; reg = DREG(insn, 9); tmp = gen_new_qreg(QMODE_I32); if (sign) gen_op_ext16s32(tmp, reg); else gen_op_ext16u32(tmp, reg); SRC_EA(src, OS_WORD, sign ? -1 : 0, NULL); gen_op_mul32(tmp, tmp, src); gen_op_mov32(reg, tmp); /* Unlike m68k, coldfire always clears the overflow bit. */ gen_logic_cc(s, tmp);}DISAS_INSN(divw){ int reg; int tmp; int src; int sign; sign = (insn & 0x100) != 0; reg = DREG(insn, 9); if (sign) { gen_op_ext16s32(QREG_DIV1, reg); } else { gen_op_ext16u32(QREG_DIV1, reg); } SRC_EA(src, OS_WORD, sign ? -1 : 0, NULL); gen_op_mov32(QREG_DIV2, src); if (sign) { gen_op_divs(1); } else { gen_op_divu(1); } tmp = gen_new_qreg(QMODE_I32); src = gen_new_qreg(QMODE_I32); gen_op_ext16u32(tmp, QREG_DIV1); gen_op_shl32(src, QREG_DIV2, gen_im32(16)); gen_op_or32(reg, tmp, src); gen_op_flags_set(); s->cc_op = CC_OP_FLAGS;}DISAS_INSN(divl){ int num; int den; int reg; uint16_t ext; ext = lduw_code(s->pc); s->pc += 2; if (ext & 0x87f8) { gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); return; } num = DREG(ext, 12); reg = DREG(ext, 0); gen_op_mov32(QREG_DIV1, num); SRC_EA(den, OS_LONG, 0, NULL); gen_op_mov32(QREG_DIV2, den); if (ext & 0x0800) { gen_op_divs(2); } else { gen_op_divu(2); } if (num == reg) { /* div */ gen_op_mov32 (reg, QREG_DIV1); } else { /* rem */ gen_op_mov32 (reg, QREG_DIV2); } gen_op_flags_set(); s->cc_op = CC_OP_FLAGS;}DISAS_INSN(addsub){ int reg; int dest; int src; int tmp; int addr; int add; add = (insn & 0x4000) != 0; reg = DREG(insn, 9); dest = gen_new_qreg(QMODE_I32); if (insn & 0x100) { SRC_EA(tmp, OS_LONG, 0, &addr); src = reg; } else { tmp = reg; SRC_EA(src, OS_LONG, 0, NULL); } if (add) { gen_op_add32(dest, tmp, src); gen_op_update_xflag_lt(dest, src); s->cc_op = CC_OP_ADD; } else { gen_op_update_xflag_lt(tmp, src); gen_op_sub32(dest, tmp, src); s->cc_op = CC_OP_SUB; } gen_op_update_cc_add(dest, src); if (insn & 0x100) { DEST_EA(insn, OS_LONG, dest, &addr); } else { gen_op_mov32(reg, dest); }}/* Reverse the order of the bits in REG. */DISAS_INSN(bitrev){ int val; int tmp1; int tmp2; int reg; val = gen_new_qreg(QMODE_I32); tmp1 = gen_new_qreg(QMODE_I32); tmp2 = gen_new_qreg(QMODE_I32); reg = DREG(insn, 0); gen_op_mov32(val, reg); /* Reverse bits within each nibble. */ gen_op_shl32(tmp1, val, gen_im32(3)); gen_op_and32(tmp1, tmp1, gen_im32(0x88888888)); gen_op_shl32(tmp2, val, gen_im32(1)); gen_op_and32(tmp2, tmp2, gen_im32(0x44444444)); gen_op_or32(tmp1, tmp1, tmp2); gen_op_shr32(tmp2, val, gen_im32(1)); gen_op_and32(tmp2, tmp2, gen_im32(0x22222222)); gen_op_or32(tmp1, tmp1, tmp2); gen_op_shr32(tmp2, val, gen_im32(3)); gen_op_and32(tmp2, tmp2, gen_im32(0x11111111)); gen_op_or32(tmp1, tmp1, tmp2); /* Reverse nibbles withing bytes. */ gen_op_shl32(val, tmp1, gen_im32(4)); gen_op_and32(val, val, gen_im32(0xf0f0f0f0)); gen_op_shr32(tmp2, tmp1, gen_im32(4)); gen_op_and32(tmp2, tmp2, gen_im32(0x0f0f0f0f)); gen_op_or32(val, val, tmp2); /* Reverse bytes. */ gen_op_bswap32(reg, val); gen_op_mov32(reg, val);}DISAS_INSN(bitop_reg){ int opsize; int op; int src1; int src2; int tmp; int addr; int dest; if ((insn & 0x38) != 0) opsize = OS_BYTE; else opsize = OS_LONG; op = (insn >> 6) & 3; SRC_EA(src1, opsize, 0, op ? &addr: NULL); src2 = DREG(insn, 9); dest = gen_new_qreg(QMODE_I32); gen_flush_flags(s); tmp = gen_new_qreg(QMODE_I32); if (opsize == OS_BYTE) gen_op_and32(tmp, src2, gen_im32(7)); else gen_op_and32(tmp, src2, gen_im32(31)); src2 = tmp; tmp = gen_new_qreg(QMODE_I32); gen_op_shl32(tmp, gen_im32(1), src2); gen_op_btest(src1, tmp); switch (op) { case 1: /* bchg */ gen_op_xor32(dest, src1, tmp); break; case 2: /* bclr */ gen_op_not32(tmp, tmp); gen_op_and32(dest, src1, tmp); break; case 3: /* bset */ gen_op_or32(dest, src1, tmp); break; default: /* btst */ break; } if (op) DEST_EA(insn, opsize, dest, &addr);}DISAS_INSN(sats){ int reg; int tmp; int l1; reg = DREG(insn, 0); tmp = gen_new_qreg(QMODE_I32); gen_flush_flags(s); gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V)); l1 = gen_new_label(); gen_op_jmp_z32(tmp, l1); tmp = gen_new_qreg(QMODE_I32); gen_op_shr32(tmp, reg, gen_im32(31)); gen_op_xor32(tmp, tmp, gen_im32(0x80000000)); gen_op_mov32(reg, tmp); gen_set_label(l1); gen_logic_cc(s, tmp);}static void gen_push(DisasContext *s, int val){ int tmp; tmp = gen_new_qreg(QMODE_I32); gen_op_sub32(tmp, QREG_SP, gen_im32(4)); gen_store(s, OS_LONG, tmp, val); gen_op_mov32(QREG_SP, tmp);}DISAS_INSN(movem){ int addr; int i; uint16_t mask; int reg; int tmp; int is_load; mask = lduw_code(s->pc); s->pc += 2; tmp = gen_lea(s, insn, OS_LONG); if (tmp == -1) { gen_addr_fault(s); return; } addr = gen_new_qreg(QMODE_I32); gen_op_mov32(addr, tmp); is_load = ((insn & 0x0400) != 0); for (i = 0; i < 16; i++, mask >>= 1) { if (mask & 1) { if (i < 8) reg = DREG(i, 0); else reg = AREG(i, 0); if (is_load) { tmp = gen_load(s, OS_LONG, addr, 0); gen_op_mov32(reg, tmp); } else { gen_store(s, OS_LONG, addr, reg); } if (mask != 1) gen_op_add32(addr, addr, gen_im32(4)); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -