📄 translate.c
字号:
case 1: /* cmp.w */ opsize = OS_WORD; s->cc_op = CC_OP_CMPW; break; case 2: /* cmp.l */ opsize = OS_LONG; s->cc_op = CC_OP_SUB; break; default: abort(); } src = gen_ea(s, insn, opsize, -1, NULL); reg = DREG(insn, 9); dest = gen_new_qreg(QMODE_I32); gen_op_sub32(dest, reg, src); gen_op_update_cc_add(dest, src);}DISAS_INSN(cmpa){ int opsize; int src; int reg; int dest; if (insn & 0x100) { opsize = OS_LONG; } else { opsize = OS_WORD; } src = gen_ea(s, insn, opsize, -1, NULL); reg = AREG(insn, 9); dest = gen_new_qreg(QMODE_I32); gen_op_sub32(dest, reg, src); gen_op_update_cc_add(dest, src); s->cc_op = CC_OP_SUB;}DISAS_INSN(eor){ int src; int reg; int dest; int addr; src = gen_ea(s, insn, OS_LONG, 0, &addr); reg = DREG(insn, 9); dest = gen_new_qreg(QMODE_I32); gen_op_xor32(dest, src, reg); gen_logic_cc(s, dest); gen_ea(s, insn, OS_LONG, dest, &addr);}DISAS_INSN(and){ int src; int reg; int dest; int addr; reg = DREG(insn, 9); dest = gen_new_qreg(QMODE_I32); if (insn & 0x100) { src = gen_ea(s, insn, OS_LONG, 0, &addr); gen_op_and32(dest, src, reg); gen_ea(s, insn, OS_LONG, dest, &addr); } else { src = gen_ea(s, insn, OS_LONG, 0, NULL); gen_op_and32(dest, src, reg); gen_op_mov32(reg, dest); } gen_logic_cc(s, dest);}DISAS_INSN(adda){ int src; int reg; src = gen_ea(s, insn, OS_LONG, 0, NULL); reg = AREG(insn, 9); gen_op_add32(reg, reg, src);}DISAS_INSN(addx){ int reg; int src; int dest; int tmp; gen_flush_flags(s); reg = DREG(insn, 9); src = DREG(insn, 0); dest = gen_new_qreg(QMODE_I32); gen_op_mov32 (dest, reg); gen_op_addx_cc(dest, src); /* !Z is sticky. */ tmp = gen_new_qreg(QMODE_I32); gen_op_mov32 (tmp, QREG_CC_DEST); gen_op_update_cc_add(dest, src); 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(shift_im){ int reg; int tmp; reg = DREG(insn, 0); tmp = (insn >> 9) & 7; if (tmp == 0) tmp = 8; if (insn & 0x100) { gen_op_shl_im_cc(reg, tmp); s->cc_op = CC_OP_SHL; } else { if (insn & 8) { gen_op_shr_im_cc(reg, tmp); s->cc_op = CC_OP_SHR; } else { gen_op_sar_im_cc(reg, tmp); s->cc_op = CC_OP_SAR; } }}DISAS_INSN(shift_reg){ int reg; int src; int tmp; reg = DREG(insn, 0); src = DREG(insn, 9); tmp = gen_new_qreg(QMODE_I32); gen_op_and32(tmp, src, gen_im32(63)); if (insn & 0x100) { gen_op_shl_cc(reg, tmp); s->cc_op = CC_OP_SHL; } else { if (insn & 8) { gen_op_shr_cc(reg, tmp); s->cc_op = CC_OP_SHR; } else { gen_op_sar_cc(reg, tmp); s->cc_op = CC_OP_SAR; } }}DISAS_INSN(ff1){ cpu_abort(NULL, "Unimplemented insn: ff1");}DISAS_INSN(strldsr){ uint16_t ext; uint32_t addr; addr = s->pc - 2; ext = lduw(s->pc); s->pc += 2; if (ext != 0x46FC) gen_exception(s, addr, EXCP_UNSUPPORTED); else gen_exception(s, addr, EXCP_PRIVILEGE);}DISAS_INSN(move_from_sr){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(move_to_sr){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(move_from_usp){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(move_to_usp){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(halt){ gen_exception(s, s->pc, EXCP_HLT);}DISAS_INSN(stop){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(rte){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(movec){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(intouch){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(cpushl){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(wddata){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(wdebug){ gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);}DISAS_INSN(trap){ gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));}/* ??? FP exceptions are not implemented. Most exceptions are deferred until immediately before the next FP instruction is executed. */DISAS_INSN(fpu){ uint16_t ext; int opmode; int src; int dest; int res; int round; int opsize; ext = lduw(s->pc); s->pc += 2; opmode = ext & 0x7f; switch ((ext >> 13) & 7) { case 0: case 2: break; case 1: goto undef; case 3: /* fmove out */ src = FREG(ext, 7); /* fmove */ /* ??? TODO: Proper behavior on overflow. */ switch ((ext >> 10) & 7) { case 0: opsize = OS_LONG; res = gen_new_qreg(QMODE_I32); gen_op_f64_to_i32(res, src); break; case 1: opsize = OS_SINGLE; res = gen_new_qreg(QMODE_F32); gen_op_f64_to_f32(res, src); break; case 4: opsize = OS_WORD; res = gen_new_qreg(QMODE_I32); gen_op_f64_to_i32(res, src); break; case 5: opsize = OS_DOUBLE; res = src; break; case 6: opsize = OS_BYTE; res = gen_new_qreg(QMODE_I32); gen_op_f64_to_i32(res, src); break; default: goto undef; } gen_ea(s, insn, opsize, res, NULL); return; case 4: /* fmove to control register. */ switch ((ext >> 10) & 7) { case 4: /* FPCR */ /* Not implemented. Ignore writes. */ break; case 1: /* FPIAR */ case 2: /* FPSR */ default: cpu_abort(NULL, "Unimplemented: fmove to control %d", (ext >> 10) & 7); } break; case 5: /* fmove from control register. */ switch ((ext >> 10) & 7) { case 4: /* FPCR */ /* Not implemented. Always return zero. */ res = gen_im32(0); break; case 1: /* FPIAR */ case 2: /* FPSR */ default: cpu_abort(NULL, "Unimplemented: fmove from control %d", (ext >> 10) & 7); goto undef; } gen_ea(s, insn, OS_LONG, res, NULL); break; case 6: /* fmovem */ case 7: { int addr; uint16_t mask; if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0) goto undef; src = gen_lea(s, insn, OS_LONG); addr = gen_new_qreg(QMODE_I32); gen_op_mov32(addr, src); mask = 0x80; dest = QREG_F0; while (mask) { if (ext & mask) { if (ext & (1 << 13)) { /* store */ gen_op_stf64(addr, dest); } else { /* load */ gen_op_ldf64(dest, addr); } if (ext & (mask - 1)) gen_op_add32(addr, addr, gen_im32(8)); } mask >>= 1; dest++; } } return; } if (ext & (1 << 14)) { int tmp; /* Source effective address. */ switch ((ext >> 10) & 7) { case 0: opsize = OS_LONG; break; case 1: opsize = OS_SINGLE; break; case 4: opsize = OS_WORD; break; case 5: opsize = OS_DOUBLE; break; case 6: opsize = OS_BYTE; break; default: goto undef; } tmp = gen_ea(s, insn, opsize, -1, NULL); if (opsize == OS_DOUBLE) { src = tmp; } else { src = gen_new_qreg(QMODE_F64); switch (opsize) { case OS_LONG: case OS_WORD: case OS_BYTE: gen_op_i32_to_f64(src, tmp); break; case OS_SINGLE: gen_op_f32_to_f64(src, tmp); break; } } } else { /* Source register. */ src = FREG(ext, 10); } dest = FREG(ext, 7); res = gen_new_qreg(QMODE_F64); if (opmode != 0x3a) gen_op_movf64(res, dest); round = 1; switch (opmode) { case 0: case 0x40: case 0x44: /* fmove */ gen_op_movf64(res, src); break; case 1: /* fint */ gen_op_iround_f64(res, src); round = 0; break; case 3: /* fintrz */ gen_op_itrunc_f64(res, src); round = 0; break; case 4: case 0x41: case 0x45: /* fsqrt */ gen_op_sqrtf64(res, src); break; case 0x18: case 0x58: case 0x5c: /* fabs */ gen_op_absf64(res, src); break; case 0x1a: case 0x5a: case 0x5e: /* fneg */ gen_op_chsf64(res, src); break; case 0x20: case 0x60: case 0x64: /* fdiv */ gen_op_divf64(res, res, src); break; case 0x22: case 0x62: case 0x66: /* fadd */ gen_op_addf64(res, res, src); break; case 0x23: case 0x63: case 0x67: /* fmul */ gen_op_mulf64(res, res, src); break; case 0x28: case 0x68: case 0x6c: /* fsub */ gen_op_subf64(res, res, src); break; case 0x38: /* fcmp */ gen_op_sub_cmpf64(res, res, src); dest = 0; round = 0; break; case 0x3a: /* ftst */ gen_op_movf64(res, src); dest = 0; round = 0; break; default: goto undef; } if (round) { if (opmode & 0x40) { if ((opmode & 0x4) != 0) round = 0; } else if ((s->fpcr & M68K_FPCR_PREC) == 0) { round = 0; } } if (round) { int tmp; tmp = gen_new_qreg(QMODE_F32); gen_op_f64_to_f32(tmp, res); gen_op_f32_to_f64(res, tmp); } gen_op_fp_result(res); if (dest) { gen_op_movf64(dest, res); } return;undef: s->pc -= 2; disas_undef_fpu(s, insn);}DISAS_INSN(fbcc){ uint32_t offset; uint32_t addr; int flag; int zero; int l1; addr = s->pc; offset = ldsw(s->pc); s->pc += 2; if (insn & (1 << 6)) { offset = (offset << 16) | lduw(s->pc); s->pc += 2; } l1 = gen_new_label(); /* TODO: Raise BSUN exception. */ flag = gen_new_qreg(QMODE_I32); zero = gen_new_qreg(QMODE_F64); gen_op_zerof64(zero); gen_op_compare_quietf64(flag, QREG_FP_RESULT, zero); /* Jump to l1 if condition is true. */ switch (insn & 0xf) { case 0: /* f */ break; case 1: /* eq (=0) */ gen_op_jmp_z32(flag, l1); break; case 2: /* ogt (=1) */ gen_op_sub32(flag, flag, gen_im32(1)); gen_op_jmp_z32(flag, l1); break; case 3: /* oge (=0 or =1) */ gen_op_jmp_z32(flag, l1); gen_op_sub32(flag, flag, gen_im32(1)); gen_op_jmp_z32(flag, l1); break; case 4: /* olt (=-1) */ gen_op_jmp_s32(flag, l1); break; case 5: /* ole (=-1 or =0) */ gen_op_jmp_s32(flag, l1); gen_op_jmp_z32(flag, l1); break; case 6: /* ogl (=-1 or =1) */ gen_op_jmp_s32(flag, l1); gen_op_sub32(flag, flag, gen_im32(1)); gen_op_jmp_z32(flag, l1); break; case 7: /* or (=2) */ gen_op_sub32(flag, flag, gen_im32(2)); gen_op_jmp_z32(flag, l1); break; case 8: /* un (<2) */ gen_op_sub32(flag, flag, gen_im32(2)); gen_op_jmp_s32(flag, l1); break; case 9: /* ueq (=0 or =2) */ gen_op_jmp_z32(flag, l1); gen_op_sub32(flag, flag, gen_im32(2)); gen_op_jmp_z32(flag, l1); break; case 10: /* ugt (>0) */ /* ??? Add jmp_gtu. */ gen_op_sub32(flag, flag, gen_im32(1)); gen_op_jmp_ns32(flag, l1); break; case 11: /* uge (>=0) */ gen_op_jmp_ns32(flag, l1); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -