| version 1.1, 2002/07/10 18:01:46 |
version 1.2, 2002/07/12 21:07:16 |
|
|
| |
/* string functions based on mmx instructions |
| |
*/ |
| #include <stdio.h> |
#include <stdio.h> |
| #include <stdlib.h> |
#include <stdlib.h> |
| #include <string.h> |
#include <string.h> |
| #include <unistd.h> |
#include <unistd.h> |
| static char *strcpymmx(void *dest, const void *src) |
#include "strmmx.h" |
| |
char *strcpymmx(void *dest, const void *src) |
| { |
{ |
| return (char *) memcpy(dest, src, strlen(src)); |
return (char *) memcpymmx(dest, src, strlen(src)); |
| } |
} |
| static char *strncpymmx(void *dest, const void *src, size_t n) |
char *strncpymmx(void *dest, const void *src, size_t n) |
| { |
{ |
| return (char *) memcpy(dest, src, n); |
return (char *) memcpymmx(dest, src, n); |
| } |
} |
| int align(const int n) |
int align(const int n) |
| { |
{ |
| return ((n >> 3) + (n % 8 != 0)) << 3; |
return ((n >> 3) + (n % 8 != 0)) << 3; |
| } |
} |
| |
|
| /* memcpy zalozena na instrukciach mmx */ |
void *memcpymmx(void *dest, const void *src, size_t n) |
| static void *memcpymmx(void *dest, const void *src, size_t n) |
|
| { |
{ |
| if ((n % 8) != 0) |
if ((n % 8) != 0) |
| n = align(n); /* zarovnat na delitela 8 */ |
n = align(n); |
| n /= 8; |
n /= 8; |
| __asm__ __volatile__("1:\n\t" |
__asm__ __volatile__("1:\n\t" |
| "movq (%%eax),%%mm0\n\t" |
"movq (%%eax),%%mm0\n\t" |
| "addl $8,%%eax\n\t" |
"movq %%mm0,(%%ebx)\n\t" |
| "movq %%mm0,(%%ebx)\n\t" |
"addl $8,%%eax\n\t" |
| "addl $8,%%ebx\n\t" |
"addl $8,%%ebx\n\t" |
| "loop 1b\n\t"::"a"(src), "b"(dest), "c"(n) |
"loop 1b\n\t"::"a"(src), "b"(dest), "c"(n) |
| :"memory"); |
:"memory"); |
| return dest; |
return dest; |
| } |
} |
| |
|
| static void *memsetmmx(void *s, int c, size_t n) |
void *memsetmmx(void *s, int c, size_t n) |
| { |
{ |
| char set[8]; |
char set[8]; |
| int i; |
int i; |
| printf("memset"); |
for (i = 0; i <= 7; i++) |
| for (i = 0; i <= 7; i++) |
set[i] = c; |
| set[i] = c; |
if ((n % 8) != 0) |
| if ((n % 8) != 0) |
n = align(n); |
| n = align(n); |
n /= 8; |
| n /= 8; |
__asm__ __volatile__("movq (%%ebx),%%mm0\n\t" |
| __asm__ __volatile__("movq (%%ebx),%%mm0\n\t" |
"1:\n\t" |
| "1:\n\t" |
"movq %%mm0,(%%eax)\n\t" |
| "movq %%mm0,(%%eax)\n\t" |
"addl $8,%%eax\n\t" |
| "addl $8,%%eax\n\t" |
"loop 1b\n\t"::"a"(s), "b"(&set), "c"(n) |
| "loop 1b\n\t"::"a"(s), "b"(&set), "c"(n) |
:"memory"); |
| :"memory"); |
return s; |
| return s; |
|
| } |
} |
| |
|
| /* funkcia vraci 0 alebo 1 ... inak nic */ |
/* function returns only 1 or 0 */ |
| static int memcmpmmx(const void *s1, const void *s2, size_t n) |
int memcmpmmx(const void *s1, const void *s2, size_t n) |
| { |
{ |
| if ((n % 8) != 0) |
if ((n % 8) != 0) |
| n = align(n); |
n = align(n); |
| n /= 8; |
n /= 8; |
| __asm__ __volatile__("1:\n\t" |
__asm__ __volatile__("1:\n\t" |
| "movq (%%eax),%%mm0\n\t" |
"movq (%%eax),%%mm0\n\t" |
| "addl $8,%%eax\n\t" |
"movq (%%ebx),%%mm1\n\t" |
| "movq (%%ebx),%%mm1\n\t" |
"addl $8,%%eax\n\t" |
| "addl $8,%%ebx\n\t" |
"addl $8,%%ebx\n\t" |
| "pcmpeqw %%mm0,%%mm1\n\t" |
"pcmpeqw %%mm0,%%mm1\n\t" |
| "movd %%mm1,%%edx\n\t" |
"movd %%mm1,%%edx\n\t" |
| "cmpl $0xFFFFFFFF,%%edx\n\t" |
"cmpl $0xFFFFFFFF,%%edx\n\t" |
| "jne 2f\n\t" |
"jne 2f\n\t" |
| "loop 1b\n\t" |
"loop 1b\n\t" |
| "jmp 3f\n\t" |
"jmp 3f\n\t" |
| "2:\n\t" |
"2:\n\t" |
| "movl $1,%%eax\n\t" |
"movl $1,%%eax\n\t" |
| "leave\n\t" |
"leave\n\t" |
| "ret\n\t" "3:\n\t"::"a"(s1), "b"(s1), "c"(n)); |
"ret\n\t" "3:\n\t"::"a"(s1), "b"(s1), "c"(n)); |
| return 0; |
return 0; |
| } |
} |
| |
|
| #ifdef TEST |
#if defined(SELF) || defined(SELFTEST) || defined(SELF_MMX) |
| /* testujeme memcpymmx */ |
/* testujeme memcpymmx */ |
| int main(int argc, char *argv[]) |
int main(int argc, char *argv[]) |
| { |
{ |
| char *pole1; |
char *pole1, *pole2; |
| char *pole2; |
int n, bsize; |
| int i, n, b; |
register int i; |
| if (argc == 1) { |
if (argc == 1) { |
| fprintf(stderr, "Use: %s buffersize memory\n", argv[0]); |
fprintf(stderr, "Use: %s buffersize memory\n", argv[0]); |
| exit(0); |
|
| } |
|
| b = atoi(argv[1]); |
|
| pole1 = (char *) malloc(b); |
|
| pole2 = (char *) malloc(b); |
|
| n = atoi(argv[2]) / b; |
|
| memsetmmx(pole1, 'A', b); |
|
| for (i = 0; i <= n; i++) |
|
| memcpymmx(pole2, pole1, b); |
|
| exit(0); |
exit(0); |
| |
} |
| |
bsize = atoi(argv[1]); |
| |
pole1 = (char *) malloc(bsize); |
| |
pole2 = (char *) malloc(bsize); |
| |
n = atoi(argv[2]) / atoi(bzize); |
| |
memsetmmx(pole1, 'A', bsize); |
| |
for (i = 0; i <= n; i++) |
| |
memcpymmx(pole2, pole1, bsize); |
| |
exit(0); |
| } |
} |
| #endif |
#endif |