Make Alpha and PowerPC targets use shared helpers

for clz, clo, ctz, cto and ctpop.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3466 c046a42c-6fe2-441c-8c8c-71466251a162
master
j_mayer 2007-10-28 12:54:53 +00:00
parent b9ef45ffa8
commit 603fcccece
4 changed files with 29 additions and 162 deletions

View File

@ -19,6 +19,7 @@
*/ */
#include "exec.h" #include "exec.h"
#include "host-utils.h"
#include "softfloat.h" #include "softfloat.h"
#include "op_helper.h" #include "op_helper.h"
@ -211,87 +212,17 @@ void helper_mulqv ()
void helper_ctpop (void) void helper_ctpop (void)
{ {
int n; T0 = ctpop64(T0);
for (n = 0; T0 != 0; n++)
T0 = T0 ^ (T0 - 1);
T0 = n;
} }
void helper_ctlz (void) void helper_ctlz (void)
{ {
uint32_t op32; T0 = clz64(T0);
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;
} }
void helper_cttz (void) void helper_cttz (void)
{ {
uint32_t op32; T0 = ctz64(T0);
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;
} }
static always_inline uint64_t byte_zap (uint64_t op, uint8_t mskb) static always_inline uint64_t byte_zap (uint64_t op, uint8_t mskb)

View File

@ -22,6 +22,7 @@
#include "config.h" #include "config.h"
#include "exec.h" #include "exec.h"
#include "host-utils.h"
#include "helper_regs.h" #include "helper_regs.h"
#include "op_helper.h" #include "op_helper.h"
@ -1508,14 +1509,14 @@ void OPPROTO op_andi_T1_64 (void)
/* count leading zero */ /* count leading zero */
void OPPROTO op_cntlzw (void) void OPPROTO op_cntlzw (void)
{ {
T0 = _do_cntlzw(T0); do_cntlzw();
RETURN(); RETURN();
} }
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
void OPPROTO op_cntlzd (void) void OPPROTO op_cntlzd (void)
{ {
T0 = _do_cntlzd(T0); do_cntlzd();
RETURN(); RETURN();
} }
#endif #endif

View File

@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "exec.h" #include "exec.h"
#include "host-utils.h"
#include "helper_regs.h" #include "helper_regs.h"
#include "op_helper.h" #include "op_helper.h"
@ -381,6 +382,18 @@ void do_subfzeo_64 (void)
} }
#endif #endif
void do_cntlzw (void)
{
T0 = clz32(T0);
}
#if defined(TARGET_PPC64)
void do_cntlzd (void)
{
T0 = clz64(T0);
}
#endif
/* shift right arithmetic helper */ /* shift right arithmetic helper */
void do_sraw (void) void do_sraw (void)
{ {
@ -438,16 +451,6 @@ void do_srad (void)
} }
#endif #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) void do_popcntb (void)
{ {
uint32_t ret; uint32_t ret;
@ -455,7 +458,7 @@ void do_popcntb (void)
ret = 0; ret = 0;
for (i = 0; i < 32; i += 8) for (i = 0; i < 32; i += 8)
ret |= popcnt((T0 >> i) & 0xFF) << i; ret |= ctpop8((T0 >> i) & 0xFF) << i;
T0 = ret; T0 = ret;
} }
@ -467,7 +470,7 @@ void do_popcntb_64 (void)
ret = 0; ret = 0;
for (i = 0; i < 64; i += 8) for (i = 0; i < 64; i += 8)
ret |= popcnt((T0 >> i) & 0xFF) << i; ret |= ctpop8((T0 >> i) & 0xFF) << i;
T0 = ret; T0 = ret;
} }
#endif #endif
@ -1924,14 +1927,14 @@ static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
static always_inline int _do_ecntlsw (uint32_t val) static always_inline int _do_ecntlsw (uint32_t val)
{ {
if (val & 0x80000000) if (val & 0x80000000)
return _do_cntlzw(~val); return clz32(~val);
else else
return _do_cntlzw(val); return clz32(val);
} }
static always_inline int _do_ecntlzw (uint32_t 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) static always_inline uint32_t _do_eneg (uint32_t val)

View File

@ -75,6 +75,10 @@ void do_nego (void);
void do_subfe (void); void do_subfe (void);
void do_subfmeo (void); void do_subfmeo (void);
void do_subfzeo (void); void do_subfzeo (void);
void do_cntlzw (void);
#if defined(TARGET_PPC64)
void do_cntlzd (void);
#endif
void do_sraw (void); void do_sraw (void);
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
void do_adde_64 (void); void do_adde_64 (void);
@ -285,78 +289,6 @@ void do_evfsctsiz (void);
void do_evfsctuiz (void); void do_evfsctuiz (void);
#endif /* defined(TARGET_PPCEMB) */ #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) #if defined(TARGET_PPCEMB)
/* SPE extension */ /* SPE extension */
/* Single precision floating-point helpers */ /* Single precision floating-point helpers */