qse/ase/cmn/mem.c

255 lines
4.5 KiB
C
Raw Normal View History

/*
2008-04-25 22:59:00 +00:00
* $Id: mem.c 171 2008-04-25 04:59:00Z baconevi $
*
* {License}
*/
#include <ase/cmn/mem.h>
2008-04-25 07:08:14 +00:00
#if defined(__SPU__)
#include <spu_intrinsics.h>
2008-04-25 22:50:34 +00:00
#define SPU_VUC_SIZE ASE_SIZEOF(vector unsigned char)
2008-04-25 07:08:14 +00:00
#endif
/*#define IS_UNALIGNED(ptr) (((ase_size_t)ptr)%ASE_SIZEOF(ase_size_t))*/
#define IS_UNALIGNED(ptr) (((ase_size_t)ptr)&(ASE_SIZEOF(ase_size_t)-1))
2007-12-25 21:25:45 +00:00
#define IS_ALIGNED(ptr) (!IS_UNALIGNED(ptr))
2007-12-25 21:37:48 +00:00
#define IS_EITHER_UNALIGNED(ptr1,ptr2) \
2008-04-25 07:08:14 +00:00
(((ase_size_t)ptr1|(ase_size_t)ptr2)&(ASE_SIZEOF(ase_size_t)-1))
2007-12-25 21:37:48 +00:00
#define IS_BOTH_ALIGNED(ptr1,ptr2) (!IS_EITHER_UNALIGNED(ptr1,ptr2))
void* ase_memcpy (void* dst, const void* src, ase_size_t n)
{
2008-04-25 06:19:44 +00:00
#if defined(ASE_BUILD_FOR_SIZE)
2008-04-25 22:50:34 +00:00
2008-04-25 06:19:44 +00:00
ase_byte_t* d = (ase_byte_t*)dst;
ase_byte_t* s = (ase_byte_t*)src;
while (n-- > 0) *d++ = *s++;
return dst;
2008-04-25 22:50:34 +00:00
#elif defined(__SPU__)
ase_byte_t* d;
ase_byte_t* s;
2008-04-25 22:59:00 +00:00
if (n >= SPU_VUC_SIZE &&
2008-04-25 22:50:34 +00:00
(((ase_size_t)dst) & (SPU_VUC_SIZE-1)) == 0 &&
(((ase_size_t)src) & (SPU_VUC_SIZE-1)) == 0)
{
vector unsigned char* du = (vector unsigned char*)dst;
vector unsigned char* su = (vector unsigned char*)src;
do
{
*du++ = *su++;
n -= SPU_VUC_SIZE;
}
while (n >= SPU_VUC_SIZE);
d = (ase_byte_t*)du;
s = (ase_byte_t*)su;
}
else
{
d = (ase_byte_t*)dst;
s = (ase_byte_t*)src;
}
while (n-- > 0) *d++ = *s++;
return dst;
2008-04-25 06:19:44 +00:00
#else
2008-04-25 22:50:34 +00:00
2008-04-25 06:19:44 +00:00
ase_byte_t* d;
ase_byte_t* s;
2007-12-25 21:25:45 +00:00
2008-04-25 07:21:17 +00:00
if (n >= ASE_SIZEOF(ase_size_t) && IS_BOTH_ALIGNED(dst,src))
2007-12-25 21:25:45 +00:00
{
2008-04-25 07:21:17 +00:00
ase_size_t* du = (ase_size_t*)dst;
ase_size_t* su = (ase_size_t*)src;
2008-04-25 07:34:17 +00:00
do
2007-12-25 21:25:45 +00:00
{
2008-04-25 06:19:44 +00:00
*du++ = *su++;
2008-04-25 07:21:17 +00:00
n -= ASE_SIZEOF(ase_size_t);
2007-12-25 21:25:45 +00:00
}
2008-04-25 07:34:17 +00:00
while (n >= ASE_SIZEOF(ase_size_t));
2007-12-25 21:25:45 +00:00
2008-04-25 06:19:44 +00:00
d = (ase_byte_t*)du;
s = (ase_byte_t*)su;
2007-12-25 21:25:45 +00:00
}
2008-04-25 06:19:44 +00:00
else
{
2008-04-25 06:19:44 +00:00
d = (ase_byte_t*)dst;
s = (ase_byte_t*)src;
}
2008-04-25 06:19:44 +00:00
while (n-- > 0) *d++ = *s++;
return dst;
2008-04-25 22:50:34 +00:00
2008-04-25 06:19:44 +00:00
#endif
}
void* ase_memset (void* dst, int val, ase_size_t n)
{
2008-04-25 06:19:44 +00:00
#if defined(ASE_BUILD_FOR_SIZE)
2008-04-25 07:08:14 +00:00
2008-04-25 06:19:44 +00:00
ase_byte_t* d = (ase_byte_t*)dst;
while (n-- > 0) *d++ = (ase_byte_t)val;
return dst;
2008-04-25 07:08:14 +00:00
2008-04-25 06:19:44 +00:00
#elif defined(__SPU__)
2008-04-25 07:08:14 +00:00
2008-04-25 08:25:47 +00:00
ase_byte_t* d;
2008-04-25 07:08:14 +00:00
ase_size_t rem;
2008-04-25 08:25:47 +00:00
if (n <= 0) return dst;
d = (ase_byte_t*)dst;
2008-04-25 07:08:14 +00:00
/* spu SIMD instructions require 16-byte alignment */
2008-04-25 22:50:34 +00:00
rem = ((ase_size_t)dst) & (SPU_VUC_SIZE-1);
2008-04-25 07:08:14 +00:00
if (rem > 0)
{
2008-04-25 22:27:37 +00:00
/* handle leading unaligned part */
2008-04-25 07:21:17 +00:00
do { *d++ = (ase_byte_t)val; }
2008-04-25 22:50:34 +00:00
while (n-- > 0 && ++rem < SPU_VUC_SIZE);
2008-04-25 07:08:14 +00:00
}
/* do the vector copy */
2008-04-25 22:50:34 +00:00
if (n >= SPU_VUC_SIZE)
2008-04-25 07:08:14 +00:00
{
2008-04-25 07:40:41 +00:00
/* a vector of 16 unsigned char cells */
vector unsigned char v16;
/* a pointer to such a vector */
vector unsigned char* vd = (vector unsigned char*)d;
2008-04-25 07:08:14 +00:00
2008-04-25 07:40:41 +00:00
/* fills all 16 unsigned char cells with the same value
* no need to use shift and bitwise-or owing to splats */
v16 = spu_splats((ase_byte_t)val);
do
{
*vd++ = v16;
2008-04-25 22:50:34 +00:00
n -= SPU_VUC_SIZE;
2008-04-25 07:40:41 +00:00
}
2008-04-25 22:50:34 +00:00
while (n >= SPU_VUC_SIZE);
2008-04-25 07:40:41 +00:00
d = (ase_byte_t*)vd;
2008-04-25 06:19:44 +00:00
}
2008-04-25 22:27:37 +00:00
/* handle the trailing part */
2008-04-25 07:40:41 +00:00
while (n-- > 0) *d++ = (ase_byte_t)val;
2008-04-25 07:08:14 +00:00
return dst;
2008-04-25 06:19:44 +00:00
#else
2008-04-25 07:08:14 +00:00
2008-04-25 08:25:47 +00:00
ase_byte_t* d;
2008-04-25 07:21:17 +00:00
ase_size_t rem;
2008-04-25 08:25:47 +00:00
if (n <= 0) return dst;
d = (ase_byte_t*)dst;
2008-04-25 07:21:17 +00:00
rem = IS_UNALIGNED(dst);
if (rem > 0)
{
2008-04-25 07:34:17 +00:00
do { *d++ = (ase_byte_t)val; }
while (n-- > 0 && ++rem < ASE_SIZEOF(ase_size_t));
2008-04-25 07:21:17 +00:00
}
if (n >= ASE_SIZEOF(ase_size_t))
{
2008-04-25 07:34:17 +00:00
ase_size_t* u = (ase_size_t*)d;
2008-04-25 07:21:17 +00:00
ase_size_t uv = 0;
2008-04-25 06:19:44 +00:00
int i;
if (val != 0)
{
2008-04-25 07:21:17 +00:00
for (i = 0; i < ASE_SIZEOF(ase_size_t); i++)
2008-04-25 06:19:44 +00:00
uv = (uv << 8) | (ase_byte_t)val;
}
2008-04-25 07:34:17 +00:00
ASE_ASSERT (IS_ALIGNED(u));
do
2008-04-25 06:19:44 +00:00
{
*u++ = uv;
2008-04-25 07:21:17 +00:00
n -= ASE_SIZEOF(ase_size_t);
2008-04-25 06:19:44 +00:00
}
2008-04-25 07:34:17 +00:00
while (n >= ASE_SIZEOF(ase_size_t));
2008-04-25 06:19:44 +00:00
d = (ase_byte_t*)u;
}
2008-04-25 06:19:44 +00:00
while (n-- > 0) *d++ = (ase_byte_t)val;
return dst;
2008-04-25 07:08:14 +00:00
2008-04-25 06:19:44 +00:00
#endif
}
int ase_memcmp (const void* s1, const void* s2, ase_size_t n)
{
2008-04-25 06:19:44 +00:00
#if defined(ASE_BUILD_FOR_SIZE)
2007-12-29 06:39:01 +00:00
/*
const void* e;
if (n == 0) return 0;
e = (const ase_byte_t*)s1 + n - 1;
while (s1 < e && *(ase_byte_t*)s1 == *(ase_byte_t*)s2)
{
s1 = (ase_byte_t*)s1 + 1;
s2 = (ase_byte_t*)s2 + 1;
}
return *((ase_byte_t*)s1) - *((ase_byte_t*)s2);
2007-12-29 06:39:01 +00:00
*/
2008-04-25 06:19:44 +00:00
const ase_byte_t* b1 = (const ase_byte_t*)s1;
const ase_byte_t* b2 = (const ase_byte_t*)s2;
while (n-- > 0)
{
if (*b1 != *b2) return *b1 - *b2;
b1++; b2++;
}
return 0;
#else
const ase_byte_t* b1;
const ase_byte_t* b2;
2008-04-25 07:21:17 +00:00
if (n >= ASE_SIZEOF(ase_size_t) && IS_BOTH_ALIGNED(s1,s2))
2008-04-25 06:19:44 +00:00
{
2008-04-25 07:21:17 +00:00
const ase_size_t* u1 = (const ase_size_t*)s1;
const ase_size_t* u2 = (const ase_size_t*)s2;
2008-04-25 06:19:44 +00:00
2008-04-25 07:34:17 +00:00
do
2008-04-25 06:19:44 +00:00
{
2008-04-25 06:33:26 +00:00
if (*u1 != *u2) break;
2008-04-25 06:19:44 +00:00
u1++; u2++;
2008-04-25 07:21:17 +00:00
n -= ASE_SIZEOF(ase_size_t);
2008-04-25 06:19:44 +00:00
}
2008-04-25 07:34:17 +00:00
while (n >= ASE_SIZEOF(ase_size_t));
2008-04-25 06:33:26 +00:00
b1 = (const ase_byte_t*)u1;
b2 = (const ase_byte_t*)u2;
2008-04-25 06:19:44 +00:00
}
else
{
b1 = (const ase_byte_t*)s1;
b2 = (const ase_byte_t*)s2;
}
2007-12-29 06:39:01 +00:00
2008-04-25 06:19:44 +00:00
while (n-- > 0)
2007-12-29 06:39:01 +00:00
{
2008-04-25 06:19:44 +00:00
if (*b1 != *b2) return *b1 - *b2;
b1++; b2++;
2007-12-29 06:39:01 +00:00
}
return 0;
2008-04-25 06:19:44 +00:00
#endif
}