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 */
next 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).