All of lore.kernel.org
 help / color / mirror / Atom feed
From: "J. Mayer" <l_indien@magic.fr>
To: qemu-devel <qemu-devel@nongnu.org>
Subject: [Qemu-devel] Proposal for host-utils
Date: Sun, 28 Oct 2007 00:53:45 +0200	[thread overview]
Message-ID: <1193525625.16781.318.camel@rapid> (raw)

[-- Attachment #1: Type: text/plain, Size: 804 bytes --]

Following the previous discussions about host-utils implementations,
here's a patch with the following changes:
- move mulu64 and muls64 definitions from exec.h to host-utils.h, for
consistency
- include host-utils.h in more files to reflect this change
- make the optimized version of mulu64 / muls64 for amd64 hosts static
inline
- change clz64 to avoid 64 bits logical operations to optimize the 32
bits host case
- add ctz32, ctz64, cto32 and cto64, using the same method than ctlzxx /
cloxx implementations
- add ctpop8, ctpop16, ctpop32 and ctpop64, using the Sparc target
implementation method
  ctpop8 is used by the PowerPC target, I added ctpop16 for consistency
- change the Alpha and the PowerPC targets to use those helpers

Please comment.

-- 
J. Mayer <l_indien@magic.fr>
Never organized

[-- Attachment #2: host-utils.diff --]
[-- Type: text/x-patch, Size: 14689 bytes --]

Index: exec-all.h
===================================================================
RCS file: /sources/qemu/qemu/exec-all.h,v
retrieving revision 1.69
diff -u -d -d -p -r1.69 exec-all.h
--- exec-all.h	20 Oct 2007 19:45:43 -0000	1.69
+++ exec-all.h	27 Oct 2007 22:45:08 -0000
@@ -91,9 +91,6 @@ void optimize_flags_init(void);
 extern FILE *logfile;
 extern int loglevel;
 
-void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b);
-void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
-
 int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
 int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
 void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
Index: host-utils.c
===================================================================
RCS file: /sources/qemu/qemu/host-utils.c,v
retrieving revision 1.4
diff -u -d -d -p -r1.4 host-utils.c
--- host-utils.c	26 Oct 2007 22:35:01 -0000	1.4
+++ host-utils.c	27 Oct 2007 22:45:08 -0000
@@ -28,6 +28,7 @@
 //#define DEBUG_MULDIV
 
 /* Long integer helpers */
+#if !defined(__x86_64__)
 static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
 {
     *plow += a;
@@ -69,17 +70,10 @@ static void mul64 (uint64_t *plow, uint6
     *phigh += v;
 }
 
-
 /* Unsigned 64x64 -> 128 multiplication */
 void mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
 {
-#if defined(__x86_64__)
-    __asm__ ("mul %0\n\t"
-             : "=d" (*phigh), "=a" (*plow)
-             : "a" (a), "0" (b));
-#else
     mul64(plow, phigh, a, b);
-#endif
 #if defined(DEBUG_MULDIV)
     printf("mulu64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
            a, b, *phigh, *plow);
@@ -89,11 +83,6 @@ void mulu64 (uint64_t *plow, uint64_t *p
 /* Signed 64x64 -> 128 multiplication */
 void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
 {
-#if defined(__x86_64__)
-    __asm__ ("imul %0\n\t"
-             : "=d" (*phigh), "=a" (*plow)
-             : "a" (a), "0" (b));
-#else
     int sa, sb;
 
     sa = (a < 0);
@@ -106,9 +95,9 @@ void muls64 (uint64_t *plow, uint64_t *p
     if (sa ^ sb) {
         neg128(plow, phigh);
     }
-#endif
 #if defined(DEBUG_MULDIV)
     printf("muls64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
            a, b, *phigh, *plow);
 #endif
 }
+#endif /* !defined(__x86_64__) */
Index: host-utils.h
===================================================================
RCS file: /sources/qemu/qemu/host-utils.h,v
retrieving revision 1.1
diff -u -d -d -p -r1.1 host-utils.h
--- host-utils.h	27 Oct 2007 13:05:54 -0000	1.1
+++ host-utils.h	27 Oct 2007 22:45:08 -0000
@@ -23,6 +23,26 @@
  * THE SOFTWARE.
  */
 
+#if defined(__x86_64__)
+static always_inline void mulu64 (uint64_t *plow, uint64_t *phigh,
+                                  uint64_t a, uint64_t b)
+{
+    __asm__ ("mul %0\n\t"
+             : "=d" (*phigh), "=a" (*plow)
+             : "a" (a), "0" (b));
+}
+static always_inline void muls64 (uint64_t *plow, uint64_t *phigh,
+                                  int64_t a, int64_t b)
+{
+    __asm__ ("imul %0\n\t"
+             : "=d" (*phigh), "=a" (*plow)
+             : "a" (a), "0" (b));
+}
+#else
+void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b);
+void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
+#endif
+
 /* Note that some of those functions may end up calling libgcc functions,
    depending on the host machine. It is up to the target emulation to
    cope with that. */
@@ -68,37 +88,113 @@ static always_inline int clz64(uint64_t 
 {
     int cnt = 0;
 
-    if (!(val & 0xFFFFFFFF00000000ULL)) {
+    if (!(val >> 32)) {
         cnt += 32;
-        val <<= 32;
+    } else {
+        val >>= 32;
     }
-    if (!(val & 0xFFFF000000000000ULL)) {
+
+    return cnt + clz32(val);
+}
+
+static always_inline int clo64(uint64_t val)
+{
+    return clz64(~val);
+}
+
+static always_inline int ctz32 (uint32_t val)
+{
+    int cnt;
+
+    cnt = 0;
+    if (!(val & 0x0000FFFFUL)) {
         cnt += 16;
-        val <<= 16;
+        val >>= 16;
     }
-    if (!(val & 0xFF00000000000000ULL)) {
+    if (!(val & 0x000000FFUL)) {
         cnt += 8;
-        val <<= 8;
+        val >>= 8;
     }
-    if (!(val & 0xF000000000000000ULL)) {
+    if (!(val & 0x0000000FUL)) {
         cnt += 4;
-        val <<= 4;
+        val >>= 4;
     }
-    if (!(val & 0xC000000000000000ULL)) {
+    if (!(val & 0x00000003UL)) {
         cnt += 2;
-        val <<= 2;
+        val >>= 2;
     }
-    if (!(val & 0x8000000000000000ULL)) {
+    if (!(val & 0x00000001UL)) {
         cnt++;
-        val <<= 1;
+        val >>= 1;
     }
-    if (!(val & 0x8000000000000000ULL)) {
+    if (!(val & 0x00000001UL)) {
         cnt++;
     }
+
     return cnt;
 }
 
-static always_inline int clo64(uint64_t val)
+static always_inline int cto32 (uint32_t val)
 {
-    return clz64(~val);
+    return ctz32(~val);
+}
+
+static always_inline int ctz64 (uint64_t val)
+{
+    int cnt;
+
+    cnt = 0;
+    if (!((uint32_t)val)) {
+        cnt += 32;
+        val >>= 32;
+    }
+
+    return cnt + ctz32(val);
+}
+
+static always_inline int cto64 (uint64_t val)
+{
+    return ctz64(~val);
+}
+
+static always_inline int ctpop8 (uint8_t val)
+{
+    val = (val & 0x55) + ((val >> 1) & 0x55);
+    val = (val & 0x33) + ((val >> 2) & 0x33);
+    val = (val & 0x0f) + ((val >> 4) & 0x0f);
+
+    return val;
+}
+
+static always_inline int ctpop16 (uint16_t val)
+{
+    val = (val & 0x5555) + ((val >> 1) & 0x5555);
+    val = (val & 0x3333) + ((val >> 2) & 0x3333);
+    val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
+    val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
+
+    return val;
+}
+
+static always_inline int ctpop32 (uint32_t val)
+{
+    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
+    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
+    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
+    val = (val & 0x00ff00ff) + ((val >>  8) & 0x00ff00ff);
+    val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
+
+    return val;
+}
+
+static always_inline int ctpop64 (uint64_t val)
+{
+    val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
+    val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
+    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
+    val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) & 0x00ff00ff00ff00ffULL);
+    val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL);
+    val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
+
+    return val;
 }
Index: target-alpha/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-alpha/op.c,v
retrieving revision 1.4
diff -u -d -d -p -r1.4 op.c
--- target-alpha/op.c	25 Oct 2007 23:34:44 -0000	1.4
+++ target-alpha/op.c	27 Oct 2007 22:45:08 -0000
@@ -22,6 +22,7 @@
 
 #include "config.h"
 #include "exec.h"
+#include "host-utils.h"
 
 #include "op_helper.h"
 
Index: target-alpha/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-alpha/op_helper.c,v
retrieving revision 1.5
diff -u -d -d -p -r1.5 op_helper.c
--- target-alpha/op_helper.c	25 Oct 2007 23:34:44 -0000	1.5
+++ target-alpha/op_helper.c	27 Oct 2007 22:45:08 -0000
@@ -19,6 +19,7 @@
  */
 
 #include "exec.h"
+#include "host-utils.h"
 #include "softfloat.h"
 
 #include "op_helper.h"
@@ -211,87 +212,17 @@ void helper_mulqv ()
 
 void helper_ctpop (void)
 {
-    int n;
-
-    for (n = 0; T0 != 0; n++)
-        T0 = T0 ^ (T0 - 1);
-    T0 = n;
+    T0 = ctpop64(T0);
 }
 
 void helper_ctlz (void)
 {
-    uint32_t op32;
-    int n;
-
-    n = 0;
-    if (!(T0 & 0xFFFFFFFF00000000ULL)) {
-        n += 32;
-        T0 <<= 32;
-    }
-    /* Make it easier for 32 bits hosts */
-    op32 = T0 >> 32;
-    if (!(op32 & 0xFFFF0000UL)) {
-        n += 16;
-        op32 <<= 16;
-    }
-    if (!(op32 & 0xFF000000UL)) {
-        n += 8;
-        op32 <<= 8;
-    }
-    if (!(op32 & 0xF0000000UL)) {
-        n += 4;
-        op32 <<= 4;
-    }
-    if (!(op32 & 0xC0000000UL)) {
-        n += 2;
-        op32 <<= 2;
-    }
-    if (!(op32 & 0x80000000UL)) {
-        n++;
-        op32 <<= 1;
-    }
-    if (!(op32 & 0x80000000UL)) {
-        n++;
-    }
-    T0 = n;
+    T0 = clz64(T0);
 }
 
 void helper_cttz (void)
 {
-    uint32_t op32;
-    int n;
-
-    n = 0;
-    if (!(T0 & 0x00000000FFFFFFFFULL)) {
-        n += 32;
-        T0 >>= 32;
-    }
-    /* Make it easier for 32 bits hosts */
-    op32 = T0;
-    if (!(op32 & 0x0000FFFFUL)) {
-        n += 16;
-        op32 >>= 16;
-    }
-    if (!(op32 & 0x000000FFUL)) {
-        n += 8;
-        op32 >>= 8;
-    }
-    if (!(op32 & 0x0000000FUL)) {
-        n += 4;
-        op32 >>= 4;
-    }
-    if (!(op32 & 0x00000003UL)) {
-        n += 2;
-        op32 >>= 2;
-    }
-    if (!(op32 & 0x00000001UL)) {
-        n++;
-        op32 >>= 1;
-    }
-    if (!(op32 & 0x00000001UL)) {
-        n++;
-    }
-    T0 = n;
+    T0 = clz32(T0);
 }
 
 static inline uint64_t byte_zap (uint64_t op, uint8_t mskb)
Index: target-i386/helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-i386/helper.c,v
retrieving revision 1.91
diff -u -d -d -p -r1.91 helper.c
--- target-i386/helper.c	26 Oct 2007 22:35:02 -0000	1.91
+++ target-i386/helper.c	27 Oct 2007 22:45:09 -0000
@@ -18,6 +18,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include "exec.h"
+#include "host-utils.h"
 
 //#define DEBUG_PCALL
 
Index: target-ppc/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-ppc/op.c,v
retrieving revision 1.59
diff -u -d -d -p -r1.59 op.c
--- target-ppc/op.c	27 Oct 2007 17:54:30 -0000	1.59
+++ target-ppc/op.c	27 Oct 2007 22:45:09 -0000
@@ -22,6 +22,7 @@
 
 #include "config.h"
 #include "exec.h"
+#include "host-utils.h"
 #include "helper_regs.h"
 #include "op_helper.h"
 
@@ -1508,14 +1509,14 @@ void OPPROTO op_andi_T1_64 (void)
 /* count leading zero */
 void OPPROTO op_cntlzw (void)
 {
-    T0 = _do_cntlzw(T0);
+    do_cntlzw();
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_cntlzd (void)
 {
-    T0 = _do_cntlzd(T0);
+    do_cntlzd();
     RETURN();
 }
 #endif
Index: target-ppc/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-ppc/op_helper.c,v
retrieving revision 1.56
diff -u -d -d -p -r1.56 op_helper.c
--- target-ppc/op_helper.c	27 Oct 2007 17:59:46 -0000	1.56
+++ target-ppc/op_helper.c	27 Oct 2007 22:45:09 -0000
@@ -18,6 +18,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include "exec.h"
+#include "host-utils.h"
 
 #include "helper_regs.h"
 #include "op_helper.h"
@@ -381,6 +382,18 @@ void do_subfzeo_64 (void)
 }
 #endif
 
+void do_cntlzw (void)
+{
+    T0 = clz32(T0);
+}
+
+#if defined(TARGET_PPC64)
+void do_cntlzd (void)
+{
+    T0 = clz64(T0);
+}
+#endif
+
 /* shift right arithmetic helper */
 void do_sraw (void)
 {
@@ -438,16 +451,6 @@ void do_srad (void)
 }
 #endif
 
-static always_inline int popcnt (uint32_t val)
-{
-    int i;
-
-    for (i = 0; val != 0;)
-        val = val ^ (val - 1);
-
-    return i;
-}
-
 void do_popcntb (void)
 {
     uint32_t ret;
@@ -455,7 +458,7 @@ void do_popcntb (void)
 
     ret = 0;
     for (i = 0; i < 32; i += 8)
-        ret |= popcnt((T0 >> i) & 0xFF) << i;
+        ret |= ctpop8((T0 >> i) & 0xFF) << i;
     T0 = ret;
 }
 
@@ -467,7 +470,7 @@ void do_popcntb_64 (void)
 
     ret = 0;
     for (i = 0; i < 64; i += 8)
-        ret |= popcnt((T0 >> i) & 0xFF) << i;
+        ret |= ctpop8((T0 >> i) & 0xFF) << i;
     T0 = ret;
 }
 #endif
@@ -1925,14 +1928,14 @@ static always_inline uint32_t _do_eaddw 
 static always_inline int _do_ecntlsw (uint32_t val)
 {
     if (val & 0x80000000)
-        return _do_cntlzw(~val);
+        return clz32(~val);
     else
-        return _do_cntlzw(val);
+        return clz32(val);
 }
 
 static always_inline int _do_ecntlzw (uint32_t val)
 {
-    return _do_cntlzw(val);
+    return clz32(val);
 }
 
 static always_inline uint32_t _do_eneg (uint32_t val)
Index: target-ppc/op_helper.h
===================================================================
RCS file: /sources/qemu/qemu/target-ppc/op_helper.h,v
retrieving revision 1.24
diff -u -d -d -p -r1.24 op_helper.h
--- target-ppc/op_helper.h	27 Oct 2007 17:54:30 -0000	1.24
+++ target-ppc/op_helper.h	27 Oct 2007 22:45:09 -0000
@@ -75,6 +75,10 @@ void do_nego (void);
 void do_subfe (void);
 void do_subfmeo (void);
 void do_subfzeo (void);
+void do_cntlzw (void);
+#if defined(TARGET_PPC64)
+void do_cntlzd (void);
+#endif
 void do_sraw (void);
 #if defined(TARGET_PPC64)
 void do_adde_64 (void);
@@ -285,78 +289,6 @@ void do_evfsctsiz (void);
 void do_evfsctuiz (void);
 #endif /* defined(TARGET_PPCEMB) */
 
-/* Inlined helpers: used in micro-operation as well as helpers */
-/* Generic fixed-point helpers */
-static always_inline int _do_cntlzw (uint32_t val)
-{
-    int cnt = 0;
-    if (!(val & 0xFFFF0000UL)) {
-        cnt += 16;
-        val <<= 16;
-    }
-    if (!(val & 0xFF000000UL)) {
-        cnt += 8;
-        val <<= 8;
-    }
-    if (!(val & 0xF0000000UL)) {
-        cnt += 4;
-        val <<= 4;
-    }
-    if (!(val & 0xC0000000UL)) {
-        cnt += 2;
-        val <<= 2;
-    }
-    if (!(val & 0x80000000UL)) {
-        cnt++;
-        val <<= 1;
-    }
-    if (!(val & 0x80000000UL)) {
-        cnt++;
-    }
-    return cnt;
-}
-
-static always_inline int _do_cntlzd (uint64_t val)
-{
-    int cnt = 0;
-#if HOST_LONG_BITS == 64
-    if (!(val & 0xFFFFFFFF00000000ULL)) {
-        cnt += 32;
-        val <<= 32;
-    }
-    if (!(val & 0xFFFF000000000000ULL)) {
-        cnt += 16;
-        val <<= 16;
-    }
-    if (!(val & 0xFF00000000000000ULL)) {
-        cnt += 8;
-        val <<= 8;
-    }
-    if (!(val & 0xF000000000000000ULL)) {
-        cnt += 4;
-        val <<= 4;
-    }
-    if (!(val & 0xC000000000000000ULL)) {
-        cnt += 2;
-        val <<= 2;
-    }
-    if (!(val & 0x8000000000000000ULL)) {
-        cnt++;
-        val <<= 1;
-    }
-    if (!(val & 0x8000000000000000ULL)) {
-        cnt++;
-    }
-#else
-    /* Make it easier on 32 bits host machines */
-    if (!(val >> 32))
-        cnt = _do_cntlzw(val) + 32;
-    else
-        cnt = _do_cntlzw(val >> 32);
-#endif
-    return cnt;
-}
-
 #if defined(TARGET_PPCEMB)
 /* SPE extension */
 /* Single precision floating-point helpers */

             reply	other threads:[~2007-10-27 22:53 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-27 22:53 J. Mayer [this message]
2007-10-28 13:02 ` [Qemu-devel] Proposal for host-utils J. Mayer
2007-10-28 16:13   ` Thiemo Seufer

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=1193525625.16781.318.camel@rapid \
    --to=l_indien@magic.fr \
    --cc=qemu-devel@nongnu.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.