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 */