File: [Platon] / libplaton / platon / str / strmmx.c (download)
Revision 1.13, Sat Apr 24 10:32:06 2010 UTC (13 years, 11 months ago) by nepto
Changes since 1.12: +28 -6 lines
Avoid MMX-related functions on Sparc
|
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <platon/str/strmmx.h>
/* Function for align string length to multiple of 8
*/
static int align(const int n)
{
return ((n >> 3) + (n % 8 != 0)) << 3;
}
char *PLATON_FUNC(strcpymmx)(void *dest, const void *src)
{
int len = strlen(src);
char *ret = PLATON_FUNC(memcpymmx)(dest, src, len);
ret[len] = '\0';
return ret;
}
char *PLATON_FUNC(strncpymmx)(void *dest, const void *src, size_t n)
{
char *ret = PLATON_FUNC(memcpymmx)(dest, src, n);
ret[n] = '\0';
return ret;
}
#if defined(__sparc__)
/* XXX: this should be done probably through macros, if possible */
void *PLATON_FUNC(memcpymmx)(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, n);
}
void *PLATON_FUNC(memsetmmx)(void *s, int c, size_t n)
{
return memset(s, c, n);
}
int PLATON_FUNC(memcmpmmx)(const void *s1, const void *s2, size_t n)
{
return memcmp(s1, s2, n);
}
#else
/* Function copy memory regions using MMX */
void *PLATON_FUNC(memcpymmx)(void *dest, const void *src, size_t n)
{
if ((n % 8) != 0)
n = align(n);
n = n >> 3;
__asm__ __volatile__("1:\n\t"
"movq (%%eax),%%mm0\n\t"
"movq %%mm0,(%%ebx)\n\t"
"addl $8,%%eax\n\t"
"addl $8,%%ebx\n\t"
"loop 1b\n\t"::"a"(src), "b"(dest), "c"(n)
:"memory");
return dest;
}
/* Function set every item of buffer to char 'c' using MMX */
void *PLATON_FUNC(memsetmmx)(void *s, int c, size_t n)
{
char set[8];
set[0] = set[1] = set[2] = set[3] = set[4] = set[5] = set[6] = set[7] = c;
if ((n % 8) != 0)
n = align(n);
n = n >> 3;
__asm__ __volatile__("movq (%%ebx),%%mm0\n\t"
"1:\n\t"
"movq %%mm0,(%%eax)\n\t"
"addl $8,%%eax\n\t"
"loop 1b\n\t"::"a"(s), "b"(&set), "c"(n)
:"memory");
return s;
}
/* Function compare two memory regions using MMX, returns 0 or 1 */
int PLATON_FUNC(memcmpmmx)(const void *s1, const void *s2, size_t n)
{
if ((n % 8) != 0)
n = align(n);
n = n >> 3;
__asm__ __volatile__("1:\n\t"
"movq (%%eax),%%mm0\n\t"
"movq (%%ebx),%%mm1\n\t"
"addl $8,%%eax\n\t"
"addl $8,%%ebx\n\t"
"pcmpeqw %%mm0,%%mm1\n\t"
"movd %%mm1,%%edx\n\t"
"cmpl $0xFFFFFFFF,%%edx\n\t"
"jne 2f\n\t"
"loop 1b\n\t"
"jmp 3f\n\t"
"2:\n\t"
"movl $1,%%eax\n\t"
"leave\n\t"
"ret\n\t" "3:\n\t"::"a"(s1), "b"(s1), "c"(n));
return 0;
}
#endif /* #if defined(__sparc__) */
#if defined(SELF) || defined(SELFTEST) || defined(SELF_MMX)
int main(int argc, char *argv[])
{
char *pole1, *pole2;
int n, bsize;
register int i;
if (argc < 3) {
fprintf(stderr, "Use: %s <buffersize> <memory>\n", argv[0]);
return 1;
}
bsize = atoi(argv[1]);
pole1 = (char *) malloc(bsize);
pole2 = (char *) malloc(bsize);
n = atoi(argv[2]) / bsize;
PLATON_FUNC(memsetmmx)(pole1, 'A', bsize);
for (i = 0; i <= n; i++)
PLATON_FUNC(memcpymmx)(pole2, pole1, bsize);
return 0;
}
#endif
Platon Group <platon@platon.org> http://platon.org/
|