diff mbox

[for-2.5,12/30] m68k: Manage divw overflow

Message ID 1439151229-27747-13-git-send-email-laurent@vivier.eu
State New
Headers show

Commit Message

Laurent Vivier Aug. 9, 2015, 8:13 p.m. UTC
"Overflow may be detected and set before the instruction completes.
If the instruction detects an overflow, it sets the overflow condition
code, and the operands are unaffected."

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/translate.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

Comments

Richard Henderson Aug. 12, 2015, 6:03 a.m. UTC | #1
On 08/09/2015 01:13 PM, Laurent Vivier wrote:
> "Overflow may be detected and set before the instruction completes.
> If the instruction detects an overflow, it sets the overflow condition
> code, and the operands are unaffected."

May also implies may not.  I presume this is important for matching hardware? 
Is there some program you know of that depends on this?

> +    /* dest.l / src.w */
> +
> +    dest = DREG(insn, 9);
> +    tcg_gen_mov_i32(QREG_DIV1, dest);
> +
>       SRC_EA(env, 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));
>       }
>
> +    set_cc_op(s, 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);
> -    set_cc_op(s, CC_OP_FLAGS);
> +    tcg_gen_or_i32(dest, tmp, src);
> +    gen_set_label(l1);

All that said, it's possible to implement this branch inside the helper via 
exception.  Or simply return the inputs to effect no change.


r~
diff mbox

Patch

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 8a3d315..370a2f0 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1034,32 +1034,40 @@  DISAS_INSN(mulw)
 
 DISAS_INSN(divw)
 {
-    TCGv reg;
+    TCGv dest;
     TCGv tmp;
     TCGv src;
     int sign;
+    TCGLabel *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(env, 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));
     }
 
+    set_cc_op(s, 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);
-    set_cc_op(s, CC_OP_FLAGS);
+    tcg_gen_or_i32(dest, tmp, src);
+    gen_set_label(l1);
 }
 
 DISAS_INSN(divl)