📄 translate.c.svn-base
字号:
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_code(s->pc); s->pc += 2; if (bitnum & 0xff00) { disas_undef(s, insn); return; } SRC_EA(src1, 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) DEST_EA(insn, opsize, dest, &addr);}DISAS_INSN(arith_im){ int op; int src1; int dest; int src2; int addr; op = (insn >> 9) & 7; SRC_EA(src1, 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) { DEST_EA(insn, OS_LONG, dest, &addr); }}DISAS_INSN(byterev){ int reg; reg = DREG(insn, 0); gen_op_bswap32(reg, reg);}DISAS_INSN(move){ int src; int dest; int op; int opsize; switch (insn >> 12) { case 1: /* move.b */ opsize = OS_BYTE; break; case 2: /* move.l */ opsize = OS_LONG; break; case 3: /* move.w */ opsize = OS_WORD; break; default: abort(); } SRC_EA(src, opsize, -1, NULL); op = (insn >> 6) & 7; if (op == 1) { /* movea */ /* The value will already have been sign extended. */ dest = AREG(insn, 9); gen_op_mov32(dest, src); } else { /* normal move */ uint16_t dest_ea; dest_ea = ((insn >> 9) & 7) | (op << 3); DEST_EA(dest_ea, opsize, src, NULL); /* This will be correct because loads sign extend. */ gen_logic_cc(s, src); }}DISAS_INSN(negx){ int reg; int dest; int tmp; gen_flush_flags(s); reg = DREG(insn, 0); dest = gen_new_qreg(QMODE_I32); gen_op_mov32 (dest, gen_im32(0)); gen_op_subx_cc(dest, reg); /* !Z is sticky. */ tmp = gen_new_qreg(QMODE_I32); gen_op_mov32 (tmp, QREG_CC_DEST); gen_op_update_cc_add(dest, reg); gen_op_mov32(reg, dest); s->cc_op = CC_OP_DYNAMIC; gen_flush_flags(s); gen_op_or32(tmp, tmp, gen_im32(~CCF_Z)); gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp); s->cc_op = CC_OP_FLAGS;}DISAS_INSN(lea){ int reg; int tmp; reg = AREG(insn, 9); tmp = gen_lea(s, insn, OS_LONG); if (tmp == -1) { gen_addr_fault(s); return; } gen_op_mov32(reg, tmp);}DISAS_INSN(clr){ int opsize; switch ((insn >> 6) & 3) { case 0: /* clr.b */ opsize = OS_BYTE; break; case 1: /* clr.w */ opsize = OS_WORD; break; case 2: /* clr.l */ opsize = OS_LONG; break; default: abort(); } DEST_EA(insn, opsize, gen_im32(0), NULL); gen_logic_cc(s, gen_im32(0));}static int gen_get_ccr(DisasContext *s){ int dest; gen_flush_flags(s); dest = gen_new_qreg(QMODE_I32); gen_op_get_xflag(dest); gen_op_shl32(dest, dest, gen_im32(4)); gen_op_or32(dest, dest, QREG_CC_DEST); return dest;}DISAS_INSN(move_from_ccr){ int reg; int ccr; ccr = gen_get_ccr(s); reg = DREG(insn, 0); gen_partset_reg(OS_WORD, reg, ccr);}DISAS_INSN(neg){ int reg; int src1; reg = DREG(insn, 0); src1 = gen_new_qreg(QMODE_I32); gen_op_mov32(src1, reg); gen_op_neg32(reg, src1); s->cc_op = CC_OP_SUB; gen_op_update_cc_add(reg, src1); gen_op_update_xflag_lt(gen_im32(0), src1); s->cc_op = CC_OP_SUB;}static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only){ gen_op_logic_cc(gen_im32(val & 0xf)); gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4)); if (!ccr_only) { gen_op_set_sr(gen_im32(val & 0xff00)); }}static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only){ int src1; int reg; s->cc_op = CC_OP_FLAGS; if ((insn & 0x38) == 0) { src1 = gen_new_qreg(QMODE_I32); reg = DREG(insn, 0); gen_op_and32(src1, reg, gen_im32(0xf)); gen_op_logic_cc(src1); gen_op_shr32(src1, reg, gen_im32(4)); gen_op_and32(src1, src1, gen_im32(1)); gen_op_update_xflag_tst(src1); if (!ccr_only) { gen_op_set_sr(reg); } } else if ((insn & 0x3f) == 0x3c) { uint16_t val; val = lduw_code(s->pc); s->pc += 2; gen_set_sr_im(s, val, ccr_only); } else disas_undef(s, insn);}DISAS_INSN(move_to_ccr){ gen_set_sr(s, insn, 1);}DISAS_INSN(not){ int reg; reg = DREG(insn, 0); gen_op_not32(reg, reg); gen_logic_cc(s, reg);}DISAS_INSN(swap){ int dest; int src1; int src2; int reg; dest = gen_new_qreg(QMODE_I32); src1 = gen_new_qreg(QMODE_I32); src2 = gen_new_qreg(QMODE_I32); reg = DREG(insn, 0); gen_op_shl32(src1, reg, gen_im32(16)); gen_op_shr32(src2, reg, gen_im32(16)); gen_op_or32(dest, src1, src2); gen_op_mov32(reg, dest); gen_logic_cc(s, dest);}DISAS_INSN(pea){ int tmp; tmp = gen_lea(s, insn, OS_LONG); if (tmp == -1) { gen_addr_fault(s); return; } gen_push(s, tmp);}DISAS_INSN(ext){ int reg; int op; int tmp; reg = DREG(insn, 0); op = (insn >> 6) & 7; tmp = gen_new_qreg(QMODE_I32); if (op == 3) gen_op_ext16s32(tmp, reg); else gen_op_ext8s32(tmp, reg); if (op == 2) gen_partset_reg(OS_WORD, reg, tmp); else gen_op_mov32(reg, tmp); gen_logic_cc(s, tmp);}DISAS_INSN(tst){ int opsize; int tmp; switch ((insn >> 6) & 3) { case 0: /* tst.b */ opsize = OS_BYTE; break; case 1: /* tst.w */ opsize = OS_WORD; break; case 2: /* tst.l */ opsize = OS_LONG; break; default: abort(); } SRC_EA(tmp, opsize, -1, NULL); gen_logic_cc(s, tmp);}DISAS_INSN(pulse){ /* Implemented as a NOP. */}DISAS_INSN(illegal){ gen_exception(s, s->pc - 2, EXCP_ILLEGAL);}/* ??? This should be atomic. */DISAS_INSN(tas){ int dest; int src1; int addr; dest = gen_new_qreg(QMODE_I32); SRC_EA(src1, OS_BYTE, -1, &addr); gen_logic_cc(s, src1); gen_op_or32(dest, src1, gen_im32(0x80)); DEST_EA(insn, OS_BYTE, dest, &addr);}DISAS_INSN(mull){ uint16_t ext; int reg; int src1; int dest; /* The upper 32 bits of the product are discarded, so muls.l and mulu.l are functionally equivalent. */ ext = lduw_code(s->pc); s->pc += 2; if (ext & 0x87ff) { gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); return; } reg = DREG(ext, 12); SRC_EA(src1, OS_LONG, 0, NULL); dest = gen_new_qreg(QMODE_I32); gen_op_mul32(dest, src1, reg); gen_op_mov32(reg, dest); /* Unlike m68k, coldfire always clears the overflow bit. */ gen_logic_cc(s, dest);}DISAS_INSN(link){ int16_t offset; int reg; int tmp; offset = ldsw_code(s->pc); s->pc += 2; reg = AREG(insn, 0); tmp = gen_new_qreg(QMODE_I32); gen_op_sub32(tmp, QREG_SP, gen_im32(4)); gen_store(s, OS_LONG, tmp, reg); if (reg != QREG_SP) gen_op_mov32(reg, tmp); gen_op_add32(QREG_SP, tmp, gen_im32(offset));}DISAS_INSN(unlk){ int src; int reg; int tmp; src = gen_new_qreg(QMODE_I32); reg = AREG(insn, 0); gen_op_mov32(src, reg); tmp = gen_load(s, OS_LONG, src, 0); gen_op_mov32(reg, tmp); gen_op_add32(QREG_SP, src, gen_im32(4));}DISAS_INSN(nop){}DISAS_INSN(rts){ int tmp; tmp = gen_load(s, OS_LONG, QREG_SP, 0); gen_op_add32(QREG_SP, QREG_SP, gen_im32(4)); gen_jmp(s, tmp);}DISAS_INSN(jump){ int tmp; /* Load the target address first to ensure correct exception behavior. */ tmp = gen_lea(s, insn, OS_LONG); if (tmp == -1) { gen_addr_fault(s); return; } if ((insn & 0x40) == 0) { /* jsr */ gen_push(s, gen_im32(s->pc)); } gen_jmp(s, tmp);}DISAS_INSN(addsubq){ int src1; int src2; int dest; int val; int addr; SRC_EA(src1, OS_LONG, 0, &addr); val = (insn >> 9) & 7; if (val == 0) val = 8; src2 = gen_im32(val); dest = gen_new_qreg(QMODE_I32); gen_op_mov32(dest, src1); if ((insn & 0x38) == 0x08) { /* Don't update condition codes if the destination is an address register. */ if (insn & 0x0100) { gen_op_sub32(dest, dest, src2); } else { gen_op_add32(dest, dest, src2); } } else { if (insn & 0x0100) { gen_op_update_xflag_lt(dest, src2); gen_op_sub32(dest, dest, src2); s->cc_op = CC_OP_SUB; } else { gen_op_add32(dest, dest, src2); gen_op_update_xflag_lt(dest, src2); s->cc_op = CC_OP_ADD; } gen_op_update_cc_add(dest, src2); } DEST_EA(insn, OS_LONG, dest, &addr);}DISAS_INSN(tpf){ switch (insn & 7) { case 2: /* One extension word. */ s->pc += 2; break; case 3: /* Two extension words. */ s->pc += 4; break; case 4: /* No extension words. */ break; default: disas_undef(s, insn); }}DISAS_INSN(branch){ int32_t offset; uint32_t base; int op; int l1; base = s->pc; op = (insn >> 8) & 0xf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -