mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 01:33:56 -06:00
target-m68k: add 680x0 divu/divs variants
Update helper to set the throwing location in case of div-by-0. Cleanup divX.w and add quad word variants of divX.l. Signed-off-by: Laurent Vivier <laurent@vivier.eu> Reviewed-by: Richard Henderson <rth@twidle.net> [laurent: modified to clear Z on overflow, as found with risu]
This commit is contained in:
parent
8be95defd6
commit
0ccb9c1d81
6 changed files with 221 additions and 73 deletions
|
@ -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);
|
||||
}
|
||||
SRC_EA(env, src, OS_WORD, sign, NULL);
|
||||
tcg_gen_mov_i32(QREG_DIV2, src);
|
||||
if (sign) {
|
||||
gen_helper_divs(cpu_env, tcg_const_i32(1));
|
||||
} else {
|
||||
gen_helper_divu(cpu_env, tcg_const_i32(1));
|
||||
}
|
||||
|
||||
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);
|
||||
/* dest.l / src.w */
|
||||
|
||||
SRC_EA(env, src, OS_WORD, sign, NULL);
|
||||
destr = tcg_const_i32(REG(insn, 9));
|
||||
if (sign) {
|
||||
gen_helper_divsw(cpu_env, destr, src);
|
||||
} else {
|
||||
gen_helper_divuw(cpu_env, destr, 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));
|
||||
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 {
|
||||
gen_helper_divu(cpu_env, tcg_const_i32(0));
|
||||
}
|
||||
if ((ext & 7) == ((ext >> 12) & 7)) {
|
||||
/* div */
|
||||
tcg_gen_mov_i32 (reg, QREG_DIV1);
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue