#include "global.h" #include #define LBLOCKSIZE (sizeof(long)) // Nonzero if (long)X contains a NULL byte. #define CONTAINSNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) // Nonzero if X is not aligned on a "long" boundary. #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) void *memcpy(void *dst0, const void *src0, size_t len0) { char *dst = dst0; const char *src = src0; long *aligned_dst; const long *aligned_src; unsigned int len = len0; // If the size is small, or either src or dst is unaligned, // then go to the byte copy loop. This should be rare. if(len >= 16 && !(UNALIGNED(src) | UNALIGNED(dst))) { aligned_dst = (long *)dst; aligned_src = (long *)src; // Copy 4X long words at a time if possible. while(len >= 16) { *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; len -= 16; } // Copy one long word at a time if possible while(len >= 4) { *aligned_dst++ = *aligned_src++; len -= 4; } dst = (char *)aligned_dst; src = (char *)aligned_src; } // Pick up any remaining bytes with a byte copier. while(len--) *dst++ = *src++; return dst0; } void *memset(void *m, int c, size_t n) { char *s = (char *)m; int count, i; unsigned long buffer; unsigned long *aligned_addr; unsigned char *unaligned_addr; // If the size is small or m is unaligned, // then go to the byte copy loop. This should be rare. if(n >= LBLOCKSIZE && !UNALIGNED(m)) { // We know that n is large and m is word-aligned. aligned_addr = (unsigned long *)m; // Store C into each char sized location in buffer so that // we can set large blocks quickly. c &= 0xFF; if(LBLOCKSIZE == 4) { buffer = (c << 8) | c; buffer |= (buffer << 16); } else { buffer = 0; for(i = 0; i < LBLOCKSIZE; i++) buffer = (buffer << 8) | c; } while(n >= LBLOCKSIZE * 4) { *aligned_addr++ = buffer; *aligned_addr++ = buffer; *aligned_addr++ = buffer; *aligned_addr++ = buffer; n -= LBLOCKSIZE * 4; } while(n >= LBLOCKSIZE) { *aligned_addr++ = buffer; n -= LBLOCKSIZE; } s = (char *)aligned_addr; } // Pick up the remainder with a bytewise loop. while(n--) *s++ = (char)c; return m; } int strcmp(const char *s1, const char *s2) { unsigned long *a1; unsigned long *a2; // If s1 or s2 are unaligned, then skip this and compare bytes. if(!(UNALIGNED(s1) | UNALIGNED(s2))) { // Compare them a word at a time. a1 = (unsigned long *)s1; a2 = (unsigned long *)s2; while(*a1 == *a2) { // If *a1 == *a2, and we find a null in *a1, // then the strings must be equal, so return zero. if(CONTAINSNULL(*a1)) return 0; a1++; a2++; } s1 = (char *)a1; s2 = (char *)a2; } // Check the remaining few bytes. while(*s1 != '\0' && *s1 == *s2) { s1++; s2++; } return (*(unsigned char *) s1) - (*(unsigned char *) s2); } char* strcpy(char *dst0, const char *src0) { char *dst = dst0; const char *src = src0; unsigned long *a1; const unsigned long *a2; // If SRC or DEST is unaligned, then copy bytes. if(!(UNALIGNED(src) | UNALIGNED(dst))) { // SRC and DEST are both "long int" aligned, try to do "long int" // sized copies. a1 = (unsigned long *)dst; a2 = (unsigned long *)src; while(!CONTAINSNULL(*a2)) { *a1++ = *a2++; } dst = (char *)a1; src = (char *)a2; } // Copy the remaining few bytes. while(*dst++ = *src++); return dst0; }