#ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include /* 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 \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