[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 051/111] m68k: correct divs.w and divu.w
From: |
Bryce Lanham |
Subject: |
[Qemu-devel] [PATCH 051/111] m68k: correct divs.w and divu.w |
Date: |
Wed, 17 Aug 2011 15:46:56 -0500 |
From: Laurent Vivier <address@hidden>
- the source register to be divided is a 32bit,
so don't extend the 16bit value sign
- don't modify the destination operand on overflow
- don't modify N and Z flags on overflow
(documentation says "undefined" but real 68040 is
doing like this)
Signed-off-by: Laurent Vivier <address@hidden>
---
target-m68k/op_helper.c | 46 ++++++++++++++++++++++++++--------------------
target-m68k/translate.c | 26 +++++++++++++++++---------
2 files changed, 43 insertions(+), 29 deletions(-)
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index a6c8148..c270259 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -213,17 +213,20 @@ void HELPER(divu)(CPUState *env, uint32_t word)
/* Avoid using a PARAM1 of zero. This breaks dyngen because it uses
the address of a symbol, and gcc knows symbols can't have address
zero. */
- if (word && quot > 0xffff)
- flags |= CCF_V;
- if (quot == 0)
- flags |= CCF_Z;
- else if ((int32_t)quot < 0)
- flags |= CCF_N;
- /* Don't modify destination if overflow occured. */
- if ((flags & CCF_V) == 0) {
- env->div1 = quot;
- env->div2 = rem;
+ if (word && quot > 0xffff) {
+ /* real 68040 keep Z and N on overflow,
+ * whereas documentation says "undefined"
+ */
+ flags |= CCF_V | (env->cc_dest & (CCF_Z|CCF_N));
+ } else {
+ if (quot == 0)
+ flags |= CCF_Z;
+ else if ((int16_t)quot < 0)
+ flags |= CCF_N;
}
+
+ env->div1 = quot;
+ env->div2 = rem;
env->cc_dest = flags;
}
@@ -242,17 +245,20 @@ void HELPER(divs)(CPUState *env, uint32_t word)
quot = num / den;
rem = num % den;
flags = 0;
- if (word && quot != (int16_t)quot)
- flags |= CCF_V;
- if (quot == 0)
- flags |= CCF_Z;
- else if (quot < 0)
- flags |= CCF_N;
- /* Don't modify destination if overflow occured. */
- if ((flags & CCF_V) == 0) {
- env->div1 = quot;
- env->div2 = rem;
+ if (word && quot != (int16_t)quot) {
+ /* real 68040 keep Z and N on overflow,
+ * whereas documentation says "undefined"
+ */
+ flags |= CCF_V | (env->cc_dest & (CCF_Z|CCF_N));
+ } else {
+ if (quot == 0)
+ flags |= CCF_Z;
+ else if ((int16_t)quot < 0)
+ flags |= CCF_N;
}
+
+ env->div1 = quot;
+ env->div2 = rem;
env->cc_dest = flags;
}
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index f5e56bc..52da485 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -993,32 +993,40 @@ DISAS_INSN(mulw)
DISAS_INSN(divw)
{
- TCGv reg;
+ TCGv dest;
TCGv tmp;
TCGv src;
int sign;
+ int l1;
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 */
+
+ dest = DREG(insn, 9);
+ tcg_gen_mov_i32(QREG_DIV1, dest);
+
SRC_EA(src, OS_WORD, sign, NULL);
tcg_gen_mov_i32(QREG_DIV2, src);
+
+ /* div1 / div2 */
+
if (sign) {
gen_helper_divs(cpu_env, tcg_const_i32(1));
} else {
gen_helper_divu(cpu_env, tcg_const_i32(1));
}
+ s->cc_op = CC_OP_FLAGS;
+
+ l1 = gen_new_label();
+ gen_jmpcc(s, 9 /* V */, l1);
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);
- s->cc_op = CC_OP_FLAGS;
+ tcg_gen_or_i32(dest, tmp, src);
+ gen_set_label(l1);
}
DISAS_INSN(divl)
--
1.7.2.3
- [Qemu-devel] [PATCH 069/111] m68k: add fetox and flogn, (continued)
- [Qemu-devel] [PATCH 069/111] m68k: add fetox and flogn, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 048/111] m68k: correct shift side effect for roxrl and roxll, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 065/111] m68k: correct compute gen_bitfield_cc(), Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 049/111] m68k: asl/asr, clear C flag if shift count is 0, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 044/111] m68k: improve addx instructions Add (byte, word) opsize Add memory access, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 046/111] m68k: improve asl/asr evaluate correclty the missing V flag, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 023/111] m68k: add variable offset/width to bitfield_reg/bitfield_mem, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 081/111] m68k: correct fpcr update, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 063/111] m68k: some FPU debugging macros, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 066/111] m68k: add fgetexp, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 051/111] m68k: correct divs.w and divu.w,
Bryce Lanham <=
- [Qemu-devel] [PATCH 071/111] m68k: correct cmpa comparison datatype, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 061/111] m68k: remove useless file m68k-qreg.h, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 059/111] m68k: add m68030 definition, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 034/111] m68k: correct typo on f64_to_i32() return type., Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 052/111] m68k: correct flags with negl, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 038/111] m68k: add EA support for negx, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 056/111] m68k-linux-user: add '--enable-emulop', Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 080/111] m68k: add fcos instruction, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 064/111] m68k: more tests, Bryce Lanham, 2011/08/17
- [Qemu-devel] [PATCH 072/111] m68k: add flog10, Bryce Lanham, 2011/08/17