All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <laurent@vivier.eu>
To: qemu-devel@nongnu.org
Cc: schwab@linux-m68k.org, agraf@suse.de,
	Richard Henderson <rth@twiddle.net>,
	gerg@uclinux.org, Laurent Vivier <laurent@vivier.eu>
Subject: [Qemu-devel] [PATCH v2 2/3] target-m68k: Inline shifts
Date: Thu, 27 Oct 2016 23:43:28 +0200	[thread overview]
Message-ID: <1477604609-2206-3-git-send-email-laurent@vivier.eu> (raw)
In-Reply-To: <1477604609-2206-1-git-send-email-laurent@vivier.eu>

From: Richard Henderson <rth@twiddle.net>

Original patch from Richard Henderson <rth@twiddle.net>

Fix arithmetical/logical switch

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 target-m68k/helper.c    | 52 ---------------------------
 target-m68k/helper.h    |  3 --
 target-m68k/translate.c | 94 +++++++++++++++++++++++++++++++++++++------------
 3 files changed, 72 insertions(+), 77 deletions(-)

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 7aed9ff..f750d3d 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -284,58 +284,6 @@ void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
     m68k_switch_sp(env);
 }
 
-uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
-    uint64_t result;
-
-    shift &= 63;
-    result = (uint64_t)val << shift;
-
-    env->cc_c = (result >> 32) & 1;
-    env->cc_n = result;
-    env->cc_z = result;
-    env->cc_v = 0;
-    env->cc_x = shift ? env->cc_c : env->cc_x;
-
-    return result;
-}
-
-uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
-    uint64_t temp;
-    uint32_t result;
-
-    shift &= 63;
-    temp = (uint64_t)val << 32 >> shift;
-    result = temp >> 32;
-
-    env->cc_c = (temp >> 31) & 1;
-    env->cc_n = result;
-    env->cc_z = result;
-    env->cc_v = 0;
-    env->cc_x = shift ? env->cc_c : env->cc_x;
-
-    return result;
-}
-
-uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
-    uint64_t temp;
-    uint32_t result;
-
-    shift &= 63;
-    temp = (int64_t)val << 32 >> shift;
-    result = temp >> 32;
-
-    env->cc_c = (temp >> 31) & 1;
-    env->cc_n = result;
-    env->cc_z = result;
-    env->cc_v = result ^ val;
-    env->cc_x = shift ? env->cc_c : env->cc_x;
-
-    return result;
-}
-
 /* FPU helpers.  */
 uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
 {
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 2697e32..aae01f9 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -3,9 +3,6 @@ DEF_HELPER_1(ff1, i32, i32)
 DEF_HELPER_FLAGS_2(sats, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, i32)
-DEF_HELPER_3(shl_cc, i32, env, i32, i32)
-DEF_HELPER_3(shr_cc, i32, env, i32, i32)
-DEF_HELPER_3(sar_cc, i32, env, i32, i32)
 DEF_HELPER_2(set_sr, void, env, i32)
 DEF_HELPER_3(movec, void, env, i32, i32)
 
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 92e67eb..461d756 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2348,48 +2348,98 @@ DISAS_INSN(addx_mem)
     gen_store(s, opsize, addr_dest, QREG_CC_N);
 }
 
-/* TODO: This could be implemented without helper functions.  */
 DISAS_INSN(shift_im)
 {
-    TCGv reg;
-    int tmp;
-    TCGv shift;
+    TCGv reg = DREG(insn, 0);
+    int count = (insn >> 9) & 7;
+    int logical = insn & 8;
 
-    set_cc_op(s, CC_OP_FLAGS);
+    if (count == 0) {
+        count = 8;
+    }
 
-    reg = DREG(insn, 0);
-    tmp = (insn >> 9) & 7;
-    if (tmp == 0)
-        tmp = 8;
-    shift = tcg_const_i32(tmp);
-    /* No need to flush flags becuse we know we will set C flag.  */
     if (insn & 0x100) {
-        gen_helper_shl_cc(reg, cpu_env, reg, shift);
+        tcg_gen_shri_i32(QREG_CC_C, reg, 31 - count);
+        tcg_gen_shli_i32(QREG_CC_N, reg, count);
     } else {
-        if (insn & 8) {
-            gen_helper_shr_cc(reg, cpu_env, reg, shift);
+        tcg_gen_shri_i32(QREG_CC_C, reg, count - 1);
+        if (logical) {
+            tcg_gen_shri_i32(QREG_CC_N, reg, count);
         } else {
-            gen_helper_sar_cc(reg, cpu_env, reg, shift);
+            tcg_gen_sari_i32(QREG_CC_N, reg, count);
         }
     }
+    tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
+    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+    tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
+
+    /* Note that ColdFire always clears V, while M68000 sets it for
+       a change in the sign bit.  */
+    if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
+        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg);
+    } else {
+        tcg_gen_movi_i32(QREG_CC_V, 0);
+    }
+
+    tcg_gen_mov_i32(reg, QREG_CC_N);
+    set_cc_op(s, CC_OP_FLAGS);
 }
 
 DISAS_INSN(shift_reg)
 {
-    TCGv reg;
-    TCGv shift;
+    TCGv reg, s32;
+    TCGv_i64 t64, s64;
+    int logical = insn & 8;
 
     reg = DREG(insn, 0);
-    shift = DREG(insn, 9);
+    t64 = tcg_temp_new_i64();
+    s64 = tcg_temp_new_i64();
+    s32 = tcg_temp_new();
+
+    /* Note that m68k truncates the shift count modulo 64, not 32.
+       In addition, a 64-bit shift makes it easy to find "the last
+       bit shifted out", for the carry flag.  */
+    tcg_gen_andi_i32(s32, DREG(insn, 9), 63);
+    tcg_gen_extu_i32_i64(s64, s32);
+
+    /* Non-arithmetic shift clears V.  Use it as a source zero here.  */
+    tcg_gen_movi_i32(QREG_CC_V, 0);
+
     if (insn & 0x100) {
-        gen_helper_shl_cc(reg, cpu_env, reg, shift);
+        tcg_gen_extu_i32_i64(t64, reg);
+        tcg_gen_shl_i64(t64, t64, s64);
+        tcg_temp_free_i64(s64);
+        tcg_gen_extr_i64_i32(QREG_CC_N, QREG_CC_C, t64);
+        tcg_temp_free_i64(t64);
+        tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
     } else {
-        if (insn & 8) {
-            gen_helper_shr_cc(reg, cpu_env, reg, shift);
+        tcg_gen_extu_i32_i64(t64, reg);
+        tcg_gen_shli_i64(t64, t64, 32);
+        if (logical) {
+            tcg_gen_shr_i64(t64, t64, s64);
         } else {
-            gen_helper_sar_cc(reg, cpu_env, reg, shift);
+            tcg_gen_sar_i64(t64, t64, s64);
         }
+        tcg_temp_free_i64(s64);
+        tcg_gen_extr_i64_i32(QREG_CC_C, QREG_CC_N, t64);
+        tcg_temp_free_i64(t64);
+        tcg_gen_shri_i32(QREG_CC_C, QREG_CC_C, 31);
     }
+    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+
+    /* Note that X = C, but only if the shift count was non-zero.  */
+    tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
+                        QREG_CC_C, QREG_CC_X);
+    tcg_temp_free(s32);
+
+    /* Note that ColdFire always clears V (which we have done above),
+       while M68000 sets it for a change in the sign bit.  */
+    if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
+        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg);
+    }
+
+    /* Write back the result.  */
+    tcg_gen_mov_i32(reg, QREG_CC_N);
     set_cc_op(s, CC_OP_FLAGS);
 }
 
-- 
2.7.4

  parent reply	other threads:[~2016-10-27 21:43 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-27 21:43 [Qemu-devel] [PATCH v2 0/3] 680x0 instruction set, part 2 Laurent Vivier
2016-10-27 21:43 ` [Qemu-devel] [PATCH v2 1/3] target-m68k: add cmpm Laurent Vivier
2016-11-01 17:48   ` Richard Henderson
2016-11-01 19:58     ` Laurent Vivier
2016-10-27 21:43 ` Laurent Vivier [this message]
2016-10-27 21:43 ` [Qemu-devel] [PATCH v2 3/3] target-m68k: shift ops manage word and byte operands Laurent Vivier
2016-10-28 17:42   ` Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1477604609-2206-3-git-send-email-laurent@vivier.eu \
    --to=laurent@vivier.eu \
    --cc=agraf@suse.de \
    --cc=gerg@uclinux.org \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    --cc=schwab@linux-m68k.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.