// Basic string routines. Not hardware optimized, but not shabby.
-#ifdef __SHARC__
-#pragma nosharc
-#endif
-
+#include <stdio.h>
#include <string.h>
#include <ros/memlayout.h>
#include <assert.h>
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')
return 0;
}
+// Return a pointer to the last occurrence of 'c' in 's',
+// or a null pointer if the string has no 'c'.
+char *
+strrchr(const char *s, char c)
+{
+ char *lastc = NULL;
+ for (; *s; s++)
+ if (*s == c){
+ lastc = (char*)s;
+ }
+ return lastc;
+}
+
void *
memchr(void* mem, int chr, int len)
{
return (char *) s;
}
-// n must be a multiple of 16 and v must be uint32_t-aligned
+// memset aligned words.
static inline void *
-memset16(uint32_t *COUNT(n/sizeof(uint32_t)) _v, uint32_t c, size_t n)
+memsetw(long* _v, long c, size_t n)
{
- uint32_t *start, *end;
- uint32_t *BND(_v, end) v;
+ long *start, *end, *v;
start = _v;
- end = _v + n/sizeof(uint32_t);
+ end = _v + n/sizeof(long);
v = _v;
- c = c | c<<8 | c<<16 | c<<24;
-
- if(n >= 64 && ((uintptr_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)
+ c = c & 0xff;
+ c = c | c<<8;
+ c = c | c<<16;
+ #if NUM_ADDR_BITS == 64
+ c = c | c<<32;
+ #elif NUM_ADDR_BITS != 32
+ # error
+ #endif
+
+ while(v < end - (8-1))
{
v[3] = v[2] = v[1] = v[0] = c;
v += 4;
+ 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;
- }
+ while(v < end)
+ *v++ = c;
- return dststart;
+ return start;
}
-void *
-pagecopy(void* d, void* s)
-{
- static_assert(PGSIZE % 64 == 0);
- for(int i = 0; i < PGSIZE; i += 64)
- {
- *((uint64_t*)(d+i+0)) = *((uint64_t*)(s+i+0));
- *((uint64_t*)(d+i+8)) = *((uint64_t*)(s+i+8));
- *((uint64_t*)(d+i+16)) = *((uint64_t*)(s+i+16));
- *((uint64_t*)(d+i+24)) = *((uint64_t*)(s+i+24));
- *((uint64_t*)(d+i+32)) = *((uint64_t*)(s+i+32));
- *((uint64_t*)(d+i+40)) = *((uint64_t*)(s+i+40));
- *((uint64_t*)(d+i+48)) = *((uint64_t*)(s+i+48));
- *((uint64_t*)(d+i+56)) = *((uint64_t*)(s+i+56));
- }
- return d;
-}
+// copy aligned words.
+// unroll 9 ways to get multiple misses in flight
+#define memcpyw(type, _dst, _src, n) \
+ do { \
+ type* restrict src = (type*)(_src); \
+ type* restrict dst = (type*)(_dst); \
+ type* srcend = src + (n)/sizeof(type); \
+ type* dstend = dst + (n)/sizeof(type); \
+ while (dst < dstend - (9-1)) { \
+ dst[0] = src[0]; \
+ dst[1] = src[1]; \
+ dst[2] = src[2]; \
+ dst[3] = src[3]; \
+ dst[4] = src[4]; \
+ dst[5] = src[5]; \
+ dst[6] = src[6]; \
+ dst[7] = src[7]; \
+ dst[8] = src[8]; \
+ src += 9; \
+ dst += 9; \
+ } \
+ while(dst < dstend) \
+ *dst++ = *src++; \
+ } while(0)
void *
-memset(void *COUNT(_n) v, int c, size_t _n)
+memset(void *v, int c, size_t _n)
{
- char *BND(v,v+_n) p;
+ char *p;
size_t n0;
size_t n = _n;
p = v;
- while (n > 0 && ((uintptr_t)p & 7))
+ while (n > 0 && ((uintptr_t)p & (sizeof(long)-1)))
{
*p++ = c;
n--;
}
- if(n >= 16 && ((uintptr_t)p & 3) == 0)
+ if (n >= sizeof(long))
{
- n0 = (n/16)*16;
- memset16((uint32_t*COUNT(n0/sizeof(uint32_t)))p,c,n0);
+ n0 = n / sizeof(long) * sizeof(long);
+ memsetw((long*)p, c, n0);
n -= n0;
p += n0;
}
}
void *
-(DMEMCPY(1,2,3) memcpy)(void *COUNT(_n) dst, const void *COUNT(_n) src, size_t _n)
+memcpy(void* dst, const void* src, size_t _n)
{
- const char *BND(src,src+_n) s;
- char *BND(dst,dst+_n) d;
- size_t n0;
+ const char* s;
+ char* d;
+ size_t n0 = 0;
size_t n = _n;
+ int align = sizeof(long)-1;
s = src;
d = dst;
- if(n >= 16 && ((uintptr_t)src & 3) == 0 && ((uintptr_t)dst & 3) == 0)
+ if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(long)-1)) == 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;
+ n0 = n / sizeof(long) * sizeof(long);
+ memcpyw(long, d, s, n0);
+ }
+ else if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(int)-1)) == 0)
+ {
+ n0 = n / sizeof(int) * sizeof(int);
+ memcpyw(int, d, s, n0);
}
+ else if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(short)-1)) == 0)
+ {
+ n0 = n / sizeof(short) * sizeof(short);
+ memcpyw(short, d, s, n0);
+ }
+
+ n -= n0;
+ s += n0;
+ d += n0;
while (n-- > 0)
*d++ = *s++;
}
void *
-memmove(void *COUNT(_n) dst, const void *COUNT(_n) src, size_t _n)
+memmove(void *dst, const void *src, size_t _n)
{
- const char *BND(src,src+_n) s;
- char *BND(dst,dst+_n) d;
+#ifdef CONFIG_X86
+ bcopy(src, dst, _n);
+ return dst;
+#else
+ const char *s;
+ char *d;
size_t n = _n;
s = src;
*d++ = *s++;
return dst;
+#endif
}
int
-memcmp(const void *COUNT(n) v1, const void *COUNT(n) v2, size_t n)
+memcmp(const void *v1, const void *v2, size_t n)
{
- const uint8_t *BND(v1,v1+n) s1 = (const uint8_t *) v1;
- const uint8_t *BND(v2,v2+n) s2 = (const uint8_t *) v2;
+ const uint8_t *s1 = (const uint8_t *) v1;
+ const uint8_t *s2 = (const uint8_t *) v2;
while (n-- > 0) {
if (*s1 != *s2)
}
void *
-memfind(const void *COUNT(n) _s, int c, size_t n)
+memfind(const void *_s, int c, size_t n)
{
- const void *SNT ends = (const char *) _s + n;
- const void *BND(_s,_s + n) s = _s;
+ const void *ends = (const char *) _s + n;
+ const void *s = _s;
for (; s < ends; s++)
if (*(const unsigned char *) s == (unsigned char) c)
break;
- return (void *BND(_s,_s+n)) s;
+ return (void *)s;
}
long
return (neg ? -val : val);
}
-int
-atoi(const char* s)
+unsigned long
+strtoul(const char *s, char **endptr, int base)
+{
+ int neg = 0;
+ unsigned long val = 0;
+
+ // gobble initial whitespace
+ while (*s == ' ' || *s == '\t')
+ s++;
+
+ // plus/minus sign
+ if (*s == '+')
+ s++;
+ else if (*s == '-')
+ s++, neg = 1;
+
+ // hex or octal base prefix
+ if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x'))
+ s += 2, base = 16;
+ else if (base == 0 && s[0] == '0')
+ s++, base = 8;
+ else if (base == 0)
+ base = 10;
+
+ // digits
+ while (1) {
+ int dig;
+
+ if (*s >= '0' && *s <= '9')
+ dig = *s - '0';
+ else if (*s >= 'a' && *s <= 'z')
+ dig = *s - 'a' + 10;
+ else if (*s >= 'A' && *s <= 'Z')
+ dig = *s - 'A' + 10;
+ else
+ break;
+ if (dig >= base)
+ break;
+ s++, val = (val * base) + dig;
+ // we don't properly detect overflow!
+ }
+
+ if (endptr)
+ *endptr = (char *) s;
+ return (neg ? -val : val);
+}
+
+int atoi(const char *s)
{
+ if (!s)
+ return 0;
+ if (s[0] == '0' && s[1] == 'x')
+ warn("atoi() used on a hex string!");
// no overflow detection
return (int)strtol(s,NULL,10);
}
+
+int sigchecksum(void *address, int length)
+{
+ uint8_t *p, sum;
+
+ sum = 0;
+ for (p = address; length-- > 0; p++)
+ sum += *p;
+
+ return sum;
+}
+
+void *sigscan(uint8_t *address, int length, char *signature)
+{
+ uint8_t *e, *p;
+ int siglength;
+
+ e = address + length;
+ siglength = strlen(signature);
+ for (p = address; p + siglength < e; p += 16) {
+ if (memcmp(p, signature, siglength))
+ continue;
+ return p;
+ }
+
+ return NULL;
+}