diff options
Diffstat (limited to 'target/m68k/translate.c')
-rw-r--r-- | target/m68k/translate.c | 84 |
1 files changed, 47 insertions, 37 deletions
diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 6678b57b97..737009e0b5 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -1242,64 +1242,74 @@ DISAS_INSN(mulw) DISAS_INSN(divw) { - TCGv reg; - TCGv tmp; - TCGv src; int sign; + TCGv src; + TCGv destr; + + /* divX.w <EA>,Dn 32/16 -> 16r:16q */ sign = (insn & 0x100) != 0; - reg = DREG(insn, 9); - if (sign) { - tcg_gen_ext16s_i32(QREG_DIV1, reg); - } else { - tcg_gen_ext16u_i32(QREG_DIV1, reg); - } + + /* dest.l / src.w */ + SRC_EA(env, src, OS_WORD, sign, NULL); - tcg_gen_mov_i32(QREG_DIV2, src); + destr = tcg_const_i32(REG(insn, 9)); if (sign) { - gen_helper_divs(cpu_env, tcg_const_i32(1)); + gen_helper_divsw(cpu_env, destr, src); } else { - gen_helper_divu(cpu_env, tcg_const_i32(1)); + gen_helper_divuw(cpu_env, destr, src); } - - tmp = tcg_temp_new(); - src = tcg_temp_new(); - tcg_gen_ext16u_i32(tmp, QREG_DIV1); - tcg_gen_shli_i32(src, QREG_DIV2, 16); - tcg_gen_or_i32(reg, tmp, src); + tcg_temp_free(destr); set_cc_op(s, CC_OP_FLAGS); } DISAS_INSN(divl) { - TCGv num; - TCGv den; - TCGv reg; + TCGv num, reg, den; + int sign; uint16_t ext; ext = read_im16(env, s); - if (ext & 0x87f8) { - gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); + + sign = (ext & 0x0800) != 0; + + if (ext & 0x400) { + if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) { + gen_exception(s, s->insn_pc, EXCP_ILLEGAL); + return; + } + + /* divX.l <EA>, Dr:Dq 64/32 -> 32r:32q */ + + SRC_EA(env, den, OS_LONG, 0, NULL); + num = tcg_const_i32(REG(ext, 12)); + reg = tcg_const_i32(REG(ext, 0)); + if (sign) { + gen_helper_divsll(cpu_env, num, reg, den); + } else { + gen_helper_divull(cpu_env, num, reg, den); + } + tcg_temp_free(reg); + tcg_temp_free(num); + set_cc_op(s, CC_OP_FLAGS); return; } - num = DREG(ext, 12); - reg = DREG(ext, 0); - tcg_gen_mov_i32(QREG_DIV1, num); + + /* divX.l <EA>, Dq 32/32 -> 32q */ + /* divXl.l <EA>, Dr:Dq 32/32 -> 32r:32q */ + SRC_EA(env, den, OS_LONG, 0, NULL); - tcg_gen_mov_i32(QREG_DIV2, den); - if (ext & 0x0800) { - gen_helper_divs(cpu_env, tcg_const_i32(0)); - } else { - gen_helper_divu(cpu_env, tcg_const_i32(0)); - } - if ((ext & 7) == ((ext >> 12) & 7)) { - /* div */ - tcg_gen_mov_i32 (reg, QREG_DIV1); + num = tcg_const_i32(REG(ext, 12)); + reg = tcg_const_i32(REG(ext, 0)); + if (sign) { + gen_helper_divsl(cpu_env, num, reg, den); } else { - /* rem */ - tcg_gen_mov_i32 (reg, QREG_DIV2); + gen_helper_divul(cpu_env, num, reg, den); } + tcg_temp_free(reg); + tcg_temp_free(num); + set_cc_op(s, CC_OP_FLAGS); } |