Sped up memset
[akaros.git] / kern / src / string.c
index 06622a9..ba7ab14 100644 (file)
@@ -1,7 +1,7 @@
 // Basic string routines.  Not hardware optimized, but not shabby.
 
-#ifdef __DEPUTY__
-#pragma nodeputy
+#ifdef __SHARC__
+#pragma nosharc
 #endif
 
 #include <string.h>
@@ -26,6 +26,7 @@ strnlen(const char *s, size_t size)
        return n;
 }
 
+/* zra: These aren't being used, and they are dangerous, so I'm rm'ing them
 char *
 strcpy(char *dst, const char *src)
 {
@@ -33,17 +34,26 @@ strcpy(char *dst, const char *src)
 
        ret = dst;
        while ((*dst++ = *src++) != '\0')
-               /* do nothing */;
+               ;
        return ret;
 }
 
 char *
+strcat(char *dst, const char *src)
+{
+       strcpy(dst+strlen(dst),src);
+       return dst;
+}
+*/
+
+char *
 strncpy(char *dst, const char *src, size_t size) {
        size_t i;
        char *ret;
 
        ret = dst;
        for (i = 0; i < size; i++) {
+               // TODO: ivy bitches about this
                *dst++ = *src;
                // If strlen(src) < size, null-pad 'dst' out to 'size' chars
                if (*src != '\0')
@@ -107,29 +117,125 @@ strfind(const char *s, char c)
        return (char *) s;
 }
 
+// n must be a multiple of 16 and v must be uint32_t-aligned
+static inline void *
+memset16(uint32_t *COUNT(n/sizeof(uint32_t)) _v, uint32_t c, size_t n)
+{
+       uint32_t *start, *end;
+       uint32_t *BND(_v, end) v;
+
+       start = _v;
+       end = _v + n/sizeof(uint32_t);
+       v = _v;
+       c = c | c<<8 | c<<16 | c<<24;
+
+       if(n >= 64 && ((intptr_t)v) % 8 == 0)
+       {
+               uint64_t* v64 = (uint64_t*)v;
+               uint64_t c64 = c | ((uint64_t)c)<<32;
+               while(v64 < (uint64_t*)end-7)
+               {
+                       v64[3] = v64[2] = v64[1] = v64[0] = c64;
+                       v64[7] = v64[6] = v64[5] = v64[4] = c64;
+                       v64 += 8;
+               }
+               v = (uint32_t*)v64;
+       }
+
+       while(v < end)
+       {
+               v[3] = v[2] = v[1] = v[0] = c;
+               v += 4;
+       }
+
+       return start;
+}
+
+// n must be a multiple of 16 and v must be 4-byte aligned.
+// as allowed by ISO, behavior undefined if dst/src overlap
+static inline void *
+memcpy16(uint32_t *COUNT(n/sizeof(uint32_t)) _dst,
+         const uint32_t *COUNT(n/sizeof(uint32_t)) _src, size_t n)
+{
+       uint32_t *dststart, *SNT dstend, *SNT srcend;
+       uint32_t *BND(_dst,dstend) dst;
+       const uint32_t *BND(_src,srcend) src;
+
+       dststart = _dst;
+       dstend = (uint32_t *SNT)(_dst + n/sizeof(uint32_t));
+       srcend = (uint32_t *SNT)(_src + n/sizeof(uint32_t));
+       dst = _dst;
+       src = _src;
+
+       while(dst < dstend && src < srcend)
+       {
+               dst[0] = src[0];
+               dst[1] = src[1];
+               dst[2] = src[2];
+               dst[3] = src[3];
+
+               src += 4;
+               dst += 4;
+       }
+
+       return dststart;
+}
 
 void *
-memset(void *v, int c, size_t n)
+memset(void *COUNT(_n) v, int c, size_t _n)
 {
-       char *p;
-       int m;
+       char *BND(v,v+_n) p;
+       size_t n0;
+       size_t n = _n;
+
+       if (n == 0) return NULL; // zra: complain here?
 
        p = v;
-       m = n;
-       while (--m >= 0)
+
+    while (n > 0 && ((uintptr_t)p & 7))
+       {
                *p++ = c;
+               n--;
+       }
+
+       if(n >= 16 && ((uintptr_t)p & 3) == 0)
+       {
+               n0 = (n/16)*16;
+               memset16((uint32_t*COUNT(n0/sizeof(uint32_t)))p,c,n0);
+               n -= n0;
+               p += n0;
+       }
+
+       while (n > 0)
+       {
+               *p++ = c;
+               n--;
+       }
 
        return v;
 }
 
 void *
-memcpy(void *dst, const void *src, size_t n)
+(DMEMCPY(1,2,3) memcpy)(void *COUNT(_n) dst, const void *COUNT(_n) src, size_t _n)
 {
-       const char *s;
-       char *d;
+       const char *BND(src,src+_n) s;
+       char *BND(dst,dst+_n) d;
+       size_t n0;
+       size_t n = _n;
 
        s = src;
        d = dst;
+
+       if(n >= 16 && ((uintptr_t)src  & 3) == 0 && ((uintptr_t)dst & 3) == 0)
+       {
+               n0 = (n/16)*16;
+               memcpy16((uint32_t*COUNT(n0/sizeof(uint32_t)))dst,
+                 (const uint32_t*COUNT(n0/sizeof(uint32_t)))src,n0);
+               n -= n0;
+               s += n0;
+               d += n0;
+       }
+
        while (n-- > 0)
                *d++ = *s++;
 
@@ -137,10 +243,11 @@ memcpy(void *dst, const void *src, size_t n)
 }
 
 void *
-memmove(void *dst, const void *src, size_t n)
+memmove(void *COUNT(_n) dst, const void *COUNT(_n) src, size_t _n)
 {
-       const char *s;
-       char *d;
+       const char *BND(src,src+_n) s;
+       char *BND(dst,dst+_n) d;
+       size_t n = _n;
        
        s = src;
        d = dst;
@@ -157,10 +264,10 @@ memmove(void *dst, const void *src, size_t n)
 }
 
 int
-memcmp(const void *v1, const void *v2, size_t n)
+memcmp(const void *COUNT(n) v1, const void *COUNT(n) v2, size_t n)
 {
-       const uint8_t *s1 = (const uint8_t *) v1;
-       const uint8_t *s2 = (const uint8_t *) v2;
+       const uint8_t *BND(v1,v1+n) s1 = (const uint8_t *) v1;
+       const uint8_t *BND(v2,v2+n) s2 = (const uint8_t *) v2;
 
        while (n-- > 0) {
                if (*s1 != *s2)
@@ -172,13 +279,14 @@ memcmp(const void *v1, const void *v2, size_t n)
 }
 
 void *
-memfind(const void *s, int c, size_t n)
+memfind(const void *COUNT(n) _s, int c, size_t n)
 {
-       const void *ends = (const char *) s + n;
+       const void *SNT ends = (const char *) _s + n;
+       const void *BND(_s,_s + n) s = _s;
        for (; s < ends; s++)
                if (*(const unsigned char *) s == (unsigned char) c)
                        break;
-       return (void *) s;
+       return (void *BND(_s,_s+n)) s;
 }
 
 long
@@ -228,3 +336,9 @@ strtol(const char *s, char **endptr, int base)
        return (neg ? -val : val);
 }
 
+int
+atoi(const char* s)
+{
+       // no overflow detection
+       return (int)strtol(s,NULL,10);
+}