📄 translate.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);}/* 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);}/* 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 = gen_ea(s, insn, 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 = gen_ea(s, insn, 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(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); den = gen_ea(s, insn, 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) { tmp = gen_ea(s, insn, OS_LONG, 0, &addr); src = reg; } else { tmp = reg; src = gen_ea(s, insn, 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) { gen_ea(s, 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; src1 = gen_ea(s, insn, 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) gen_ea(s, 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(int val){ int tmp; tmp = gen_new_qreg(QMODE_I32); gen_op_sub32(tmp, QREG_SP, gen_im32(4)); gen_store(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(s->pc); s->pc += 2; tmp = gen_lea(s, insn, OS_LONG); 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(OS_LONG, addr, 0); gen_op_mov32(reg, tmp); } else { gen_store(OS_LONG, addr, reg); } if (mask != 1) gen_op_add32(addr, addr, gen_im32(4)); } }}DISAS_INSN(bitop_im){ int opsize; int op; int src1; uint32_t mask; int bitnum; int tmp; int addr; int dest; if ((insn & 0x38) != 0) opsize = OS_BYTE; else opsize = OS_LONG; op = (insn >> 6) & 3; bitnum = lduw(s->pc); s->pc += 2; if (bitnum & 0xff00) { disas_undef(s, insn); return; } src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL); gen_flush_flags(s); tmp = gen_new_qreg(QMODE_I32); if (opsize == OS_BYTE) bitnum &= 7; else bitnum &= 31; mask = 1 << bitnum; gen_op_btest(src1, gen_im32(mask)); if (op) dest = gen_new_qreg(QMODE_I32); else dest = -1; switch (op) { case 1: /* bchg */ gen_op_xor32(dest, src1, gen_im32(mask)); break; case 2: /* bclr */ gen_op_and32(dest, src1, gen_im32(~mask)); break; case 3: /* bset */ gen_op_or32(dest, src1, gen_im32(mask)); break; default: /* btst */ break; } if (op) gen_ea(s, insn, opsize, dest, &addr);}DISAS_INSN(arith_im){ int op; int src1; int dest; int src2; int addr; op = (insn >> 9) & 7; src1 = gen_ea(s, insn, OS_LONG, 0, (op == 6) ? NULL : &addr); src2 = gen_im32(read_im32(s)); dest = gen_new_qreg(QMODE_I32); switch (op) { case 0: /* ori */ gen_op_or32(dest, src1, src2); gen_logic_cc(s, dest); break; case 1: /* andi */ gen_op_and32(dest, src1, src2); gen_logic_cc(s, dest); break; case 2: /* subi */ gen_op_mov32(dest, src1); gen_op_update_xflag_lt(dest, src2); gen_op_sub32(dest, dest, src2); gen_op_update_cc_add(dest, src2); s->cc_op = CC_OP_SUB; break; case 3: /* addi */ gen_op_mov32(dest, src1); gen_op_add32(dest, dest, src2); gen_op_update_cc_add(dest, src2); gen_op_update_xflag_lt(dest, src2); s->cc_op = CC_OP_ADD; break; case 5: /* eori */ gen_op_xor32(dest, src1, src2); gen_logic_cc(s, dest); break; case 6: /* cmpi */ gen_op_mov32(dest, src1); gen_op_sub32(dest, dest, src2); gen_op_update_cc_add(dest, src2); s->cc_op = CC_OP_SUB; break; default: abort(); } if (op != 6) { gen_ea(s, insn, OS_LONG, dest, &addr); }}DISAS_INSN(byterev){ int reg;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -