diff mbox

[046/111] m68k: improve asl/asr evaluate correclty the missing V flag

Message ID 1313614076-28878-47-git-send-email-blanham@gmail.com
State New
Headers show

Commit Message

Bryce Lanham Aug. 17, 2011, 8:46 p.m. UTC
From: Laurent Vivier <laurent@vivier.eu>

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    |   49 ++++++++++++++++++++++++++++++++++++++++++----
 target-m68k/helpers.h   |    3 ++
 target-m68k/translate.c |   36 ++++++++++++++++++++++++++++-----
 3 files changed, 77 insertions(+), 11 deletions(-)
diff mbox

Patch

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 8bf4920..bdfe9aa 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -327,8 +327,7 @@  void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
 
 #define SET_FLAGS_SHIFT(type) do { \
     SET_NZ(dest, type); \
-    if (src) \
-        flags |= CCF_C; \
+    flags |= src; \
     } while(0)
 
     flags = 0;
@@ -751,7 +750,7 @@  uint32_t HELPER(glue(glue(shl, bits),_cc))(CPUState *env, uint32_t val, uint32_t
         result = 0; \
         cf = 0; \
     } \
-    env->cc_src = cf; \
+    env->cc_src = cf ? CCF_C : 0; \
     if (shift) env->cc_x = (cf != 0); \
     env->cc_dest = result; \
     return result; \
@@ -780,7 +779,7 @@  uint32_t HELPER(glue(glue(shr, bits), _cc))(CPUState *env, uint32_t val, uint32_
         result = 0; \
         cf = 0; \
     } \
-    env->cc_src = cf; \
+    env->cc_src = cf ? CCF_C : 0; \
     if (shift) env->cc_x = (cf != 0); \
     env->cc_dest = result; \
     return result; \
@@ -790,6 +789,46 @@  HELPER_SHR(uint8_t, 8)
 HELPER_SHR(uint16_t, 16)
 HELPER_SHR(uint32_t, 32)
 
+#define HELPER_SAL(type, bits) \
+uint32_t HELPER(glue(glue(sal, bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t cf; \
+    uint32_t vf; \
+    uint32_t m; \
+    shift &= 63; \
+    if (shift == 0) { \
+        vf = 0; \
+    } else if (shift < bits) { \
+        m = ((1llu << (shift + 1)) - 1) << (bits - shift - 1); \
+        vf = (val & m) != m && (val & m) != 0; \
+    } else {\
+        m = (1llu << bits) - 1; \
+        vf = (val & m) != 0; \
+    }\
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = env->cc_src & CCF_C; \
+    } else if (shift < bits) { \
+        result = (type)val << shift; \
+        cf = ((type)val >> (bits - shift)) & 1; \
+    } else if (shift == bits) { \
+        result = 0; \
+        cf = val & 1; \
+    } else /* shift > bits */ { \
+        result = 0; \
+        cf = 0; \
+    } \
+    env->cc_src = (cf ? CCF_C : 0) | (vf ? CCF_V : 0); \
+    if (shift) env->cc_x = (cf != 0); \
+    env->cc_dest = result; \
+    return result; \
+}
+
+HELPER_SAL(int8_t, 8)
+HELPER_SAL(int16_t, 16)
+HELPER_SAL(int32_t, 32)
+
 #define HELPER_SAR(type, bits) \
 uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift)					\
 { \
@@ -806,7 +845,7 @@  uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t val, uint32_
         result = (type)val >> (bits - 1); \
         cf = (type)val >> (bits - 1); \
     } \
-    env->cc_src = cf; \
+    env->cc_src = cf ? CCF_C : 0; \
     if (shift) env->cc_x = (cf != 0); \
     env->cc_dest = result; \
     return result; \
diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
index 8f6d333..aa835eb 100644
--- a/target-m68k/helpers.h
+++ b/target-m68k/helpers.h
@@ -26,6 +26,9 @@  DEF_HELPER_3(shl32_cc, i32, env, i32, i32)
 DEF_HELPER_3(shr8_cc, i32, env, i32, i32)
 DEF_HELPER_3(shr16_cc, i32, env, i32, i32)
 DEF_HELPER_3(shr32_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal8_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal16_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal32_cc, i32, env, i32, i32)
 DEF_HELPER_3(sar8_cc, i32, env, i32, i32)
 DEF_HELPER_3(sar16_cc, i32, env, i32, i32)
 DEF_HELPER_3(sar32_cc, i32, env, i32, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index bc1cf04..37ee841 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2298,7 +2298,11 @@  DISAS_INSN(shift8_im)
     dest = tcg_temp_new_i32();
     /* No need to flush flags becuse we know we will set C flag.  */
     if (insn & 0x100) {
-        gen_helper_shl8_cc(dest, cpu_env, reg, shift);
+        if (insn & 8) {
+            gen_helper_shl8_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal8_cc(dest, cpu_env, reg, shift);
+        }
     } else {
         if (insn & 8) {
             gen_helper_shr8_cc(dest, cpu_env, reg, shift);
@@ -2326,7 +2330,11 @@  DISAS_INSN(shift16_im)
     dest = tcg_temp_new_i32();
     /* No need to flush flags becuse we know we will set C flag.  */
     if (insn & 0x100) {
-        gen_helper_shl16_cc(dest, cpu_env, reg, shift);
+        if (insn & 8) {
+            gen_helper_shl16_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal16_cc(dest, cpu_env, reg, shift);
+        }
     } else {
         if (insn & 8) {
             gen_helper_shr16_cc(dest, cpu_env, reg, shift);
@@ -2353,7 +2361,11 @@  DISAS_INSN(shift_im)
     shift = tcg_const_i32(tmp);
     /* No need to flush flags becuse we know we will set C flag.  */
     if (insn & 0x100) {
-        gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+        if (insn & 8) {
+            gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal32_cc(reg, cpu_env, reg, shift);
+        }
     } else {
         if (insn & 8) {
             gen_helper_shr32_cc(reg, cpu_env, reg, shift);
@@ -2379,7 +2391,11 @@  DISAS_INSN(shift8_reg)
     /* Shift by zero leaves C flag unmodified.   */
     gen_flush_flags(s);
     if (insn & 0x100) {
-        gen_helper_shl8_cc(dest, cpu_env, reg, tmp);
+        if (insn & 8) {
+            gen_helper_shl8_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sal8_cc(dest, cpu_env, reg, tmp);
+        }
     } else {
         if (insn & 8) {
             gen_helper_shr8_cc(dest, cpu_env, reg, tmp);
@@ -2406,7 +2422,11 @@  DISAS_INSN(shift16_reg)
     /* Shift by zero leaves C flag unmodified.   */
     gen_flush_flags(s);
     if (insn & 0x100) {
-        gen_helper_shl16_cc(dest, cpu_env, reg, tmp);
+        if (insn & 8) {
+            gen_helper_shl16_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sal16_cc(dest, cpu_env, reg, tmp);
+        }
     } else {
         if (insn & 8) {
             gen_helper_shr16_cc(dest, cpu_env, reg, tmp);
@@ -2428,7 +2448,11 @@  DISAS_INSN(shift_reg)
     /* Shift by zero leaves C flag unmodified.   */
     gen_flush_flags(s);
     if (insn & 0x100) {
-        gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+        if (insn & 8) {
+            gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal32_cc(reg, cpu_env, reg, shift);
+        }
     } else {
         if (insn & 8) {
             gen_helper_shr32_cc(reg, cpu_env, reg, shift);