aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-user/m68k/cpu_loop.c2
-rw-r--r--target/m68k/helper.h12
-rw-r--r--target/m68k/op_helper.c48
-rw-r--r--target/m68k/translate.c33
4 files changed, 52 insertions, 43 deletions
diff --git a/linux-user/m68k/cpu_loop.c b/linux-user/m68k/cpu_loop.c
index e24d17e..6598bce 100644
--- a/linux-user/m68k/cpu_loop.c
+++ b/linux-user/m68k/cpu_loop.c
@@ -50,7 +50,7 @@ void cpu_loop(CPUM68KState *env)
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->mmu.ar);
break;
case EXCP_DIV0:
- force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc);
+ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->mmu.ar);
break;
case EXCP_TRAP0:
{
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 0a6b414..f016c4c 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -1,12 +1,12 @@
DEF_HELPER_1(bitrev, i32, i32)
DEF_HELPER_1(ff1, i32, i32)
DEF_HELPER_FLAGS_2(sats, TCG_CALL_NO_RWG_SE, i32, i32, i32)
-DEF_HELPER_3(divuw, void, env, int, i32)
-DEF_HELPER_3(divsw, void, env, int, s32)
-DEF_HELPER_4(divul, void, env, int, int, i32)
-DEF_HELPER_4(divsl, void, env, int, int, s32)
-DEF_HELPER_4(divull, void, env, int, int, i32)
-DEF_HELPER_4(divsll, void, env, int, int, s32)
+DEF_HELPER_4(divuw, void, env, int, i32, int)
+DEF_HELPER_4(divsw, void, env, int, s32, int)
+DEF_HELPER_5(divul, void, env, int, int, i32, int)
+DEF_HELPER_5(divsl, void, env, int, int, s32, int)
+DEF_HELPER_5(divull, void, env, int, int, i32, int)
+DEF_HELPER_5(divsll, void, env, int, int, s32, int)
DEF_HELPER_2(set_sr, void, env, i32)
DEF_HELPER_3(cf_movec_to, void, env, i32, i32)
DEF_HELPER_3(m68k_movec_to, void, env, i32, i32)
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index 750d655..729ee0e 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -396,7 +396,6 @@ static void m68k_interrupt_all(CPUM68KState *env, int is_hw)
break;
case EXCP_ILLEGAL:
- case EXCP_DIV0:
case EXCP_TRAPCC:
case EXCP_TRACE:
/* FIXME: addr is not only env->pc */
@@ -404,6 +403,7 @@ static void m68k_interrupt_all(CPUM68KState *env, int is_hw)
break;
case EXCP_CHK:
+ case EXCP_DIV0:
do_stack_frame(env, &sp, 2, oldsr, env->mmu.ar, env->pc);
break;
@@ -574,18 +574,19 @@ raise_exception_format2(CPUM68KState *env, int tt, int ilen, uintptr_t raddr)
cpu_loop_exit(cs);
}
-void HELPER(divuw)(CPUM68KState *env, int destr, uint32_t den)
+void HELPER(divuw)(CPUM68KState *env, int destr, uint32_t den, int ilen)
{
uint32_t num = env->dregs[destr];
uint32_t quot, rem;
+ env->cc_c = 0; /* always cleared, even if div0 */
+
if (den == 0) {
- raise_exception_ra(env, EXCP_DIV0, GETPC());
+ raise_exception_format2(env, EXCP_DIV0, ilen, GETPC());
}
quot = num / den;
rem = num % den;
- env->cc_c = 0; /* always cleared, even if overflow */
if (quot > 0xffff) {
env->cc_v = -1;
/*
@@ -601,18 +602,19 @@ void HELPER(divuw)(CPUM68KState *env, int destr, uint32_t den)
env->cc_v = 0;
}
-void HELPER(divsw)(CPUM68KState *env, int destr, int32_t den)
+void HELPER(divsw)(CPUM68KState *env, int destr, int32_t den, int ilen)
{
int32_t num = env->dregs[destr];
uint32_t quot, rem;
+ env->cc_c = 0; /* always cleared, even if overflow/div0 */
+
if (den == 0) {
- raise_exception_ra(env, EXCP_DIV0, GETPC());
+ raise_exception_format2(env, EXCP_DIV0, ilen, GETPC());
}
quot = num / den;
rem = num % den;
- env->cc_c = 0; /* always cleared, even if overflow */
if (quot != (int16_t)quot) {
env->cc_v = -1;
/* nothing else is modified */
@@ -629,18 +631,20 @@ void HELPER(divsw)(CPUM68KState *env, int destr, int32_t den)
env->cc_v = 0;
}
-void HELPER(divul)(CPUM68KState *env, int numr, int regr, uint32_t den)
+void HELPER(divul)(CPUM68KState *env, int numr, int regr,
+ uint32_t den, int ilen)
{
uint32_t num = env->dregs[numr];
uint32_t quot, rem;
+ env->cc_c = 0; /* always cleared, even if div0 */
+
if (den == 0) {
- raise_exception_ra(env, EXCP_DIV0, GETPC());
+ raise_exception_format2(env, EXCP_DIV0, ilen, GETPC());
}
quot = num / den;
rem = num % den;
- env->cc_c = 0;
env->cc_z = quot;
env->cc_n = quot;
env->cc_v = 0;
@@ -657,18 +661,20 @@ void HELPER(divul)(CPUM68KState *env, int numr, int regr, uint32_t den)
}
}
-void HELPER(divsl)(CPUM68KState *env, int numr, int regr, int32_t den)
+void HELPER(divsl)(CPUM68KState *env, int numr, int regr,
+ int32_t den, int ilen)
{
int32_t num = env->dregs[numr];
int32_t quot, rem;
+ env->cc_c = 0; /* always cleared, even if overflow/div0 */
+
if (den == 0) {
- raise_exception_ra(env, EXCP_DIV0, GETPC());
+ raise_exception_format2(env, EXCP_DIV0, ilen, GETPC());
}
quot = num / den;
rem = num % den;
- env->cc_c = 0;
env->cc_z = quot;
env->cc_n = quot;
env->cc_v = 0;
@@ -685,19 +691,21 @@ void HELPER(divsl)(CPUM68KState *env, int numr, int regr, int32_t den)
}
}
-void HELPER(divull)(CPUM68KState *env, int numr, int regr, uint32_t den)
+void HELPER(divull)(CPUM68KState *env, int numr, int regr,
+ uint32_t den, int ilen)
{
uint64_t num = deposit64(env->dregs[numr], 32, 32, env->dregs[regr]);
uint64_t quot;
uint32_t rem;
+ env->cc_c = 0; /* always cleared, even if overflow/div0 */
+
if (den == 0) {
- raise_exception_ra(env, EXCP_DIV0, GETPC());
+ raise_exception_format2(env, EXCP_DIV0, ilen, GETPC());
}
quot = num / den;
rem = num % den;
- env->cc_c = 0; /* always cleared, even if overflow */
if (quot > 0xffffffffULL) {
env->cc_v = -1;
/*
@@ -720,19 +728,21 @@ void HELPER(divull)(CPUM68KState *env, int numr, int regr, uint32_t den)
env->dregs[numr] = quot;
}
-void HELPER(divsll)(CPUM68KState *env, int numr, int regr, int32_t den)
+void HELPER(divsll)(CPUM68KState *env, int numr, int regr,
+ int32_t den, int ilen)
{
int64_t num = deposit64(env->dregs[numr], 32, 32, env->dregs[regr]);
int64_t quot;
int32_t rem;
+ env->cc_c = 0; /* always cleared, even if overflow/div0 */
+
if (den == 0) {
- raise_exception_ra(env, EXCP_DIV0, GETPC());
+ raise_exception_format2(env, EXCP_DIV0, ilen, GETPC());
}
quot = num / den;
rem = num % den;
- env->cc_c = 0; /* always cleared, even if overflow */
if (quot != (int32_t)quot) {
env->cc_v = -1;
/*
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 22e5379..6075f49 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -1601,6 +1601,7 @@ DISAS_INSN(divw)
int sign;
TCGv src;
TCGv destr;
+ TCGv ilen;
/* divX.w <EA>,Dn 32/16 -> 16r:16q */
@@ -1609,20 +1610,20 @@ DISAS_INSN(divw)
/* dest.l / src.w */
SRC_EA(env, src, OS_WORD, sign, NULL);
- destr = tcg_const_i32(REG(insn, 9));
+ destr = tcg_constant_i32(REG(insn, 9));
+ ilen = tcg_constant_i32(s->pc - s->base.pc_next);
if (sign) {
- gen_helper_divsw(cpu_env, destr, src);
+ gen_helper_divsw(cpu_env, destr, src, ilen);
} else {
- gen_helper_divuw(cpu_env, destr, src);
+ gen_helper_divuw(cpu_env, destr, src, ilen);
}
- tcg_temp_free(destr);
set_cc_op(s, CC_OP_FLAGS);
}
DISAS_INSN(divl)
{
- TCGv num, reg, den;
+ TCGv num, reg, den, ilen;
int sign;
uint16_t ext;
@@ -1639,15 +1640,14 @@ DISAS_INSN(divl)
/* 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));
+ num = tcg_constant_i32(REG(ext, 12));
+ reg = tcg_constant_i32(REG(ext, 0));
+ ilen = tcg_constant_i32(s->pc - s->base.pc_next);
if (sign) {
- gen_helper_divsll(cpu_env, num, reg, den);
+ gen_helper_divsll(cpu_env, num, reg, den, ilen);
} else {
- gen_helper_divull(cpu_env, num, reg, den);
+ gen_helper_divull(cpu_env, num, reg, den, ilen);
}
- tcg_temp_free(reg);
- tcg_temp_free(num);
set_cc_op(s, CC_OP_FLAGS);
return;
}
@@ -1656,15 +1656,14 @@ DISAS_INSN(divl)
/* divXl.l <EA>, Dr:Dq 32/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));
+ num = tcg_constant_i32(REG(ext, 12));
+ reg = tcg_constant_i32(REG(ext, 0));
+ ilen = tcg_constant_i32(s->pc - s->base.pc_next);
if (sign) {
- gen_helper_divsl(cpu_env, num, reg, den);
+ gen_helper_divsl(cpu_env, num, reg, den, ilen);
} else {
- gen_helper_divul(cpu_env, num, reg, den);
+ gen_helper_divul(cpu_env, num, reg, den, ilen);
}
- tcg_temp_free(reg);
- tcg_temp_free(num);
set_cc_op(s, CC_OP_FLAGS);
}