+size_t
+strlen(const char *s)
+{
+ if (__builtin_constant_p(s))
+ return __builtin_strlen(s);
+ const char *p = s;
+ while (*p)
+ p++;
+ return p-s;
+}
+
+// Compare two areas of memory.
+int
+memcmp(const void *s1, const void *s2, size_t n)
+{
+ while (n) {
+ if (*(u8*)s1 != *(u8*)s2)
+ return *(u8*)s1 < *(u8*)s2 ? -1 : 1;
+ s1++;
+ s2++;
+ n--;
+ }
+ return 0;
+}
+
+// Compare two strings.
+int
+strcmp(const char *s1, const char *s2)
+{
+ for (;;) {
+ if (*s1 != *s2)
+ return *s1 < *s2 ? -1 : 1;
+ if (! *s1)
+ return 0;
+ s1++;
+ s2++;
+ }
+}
+
+inline void
+memset_far(u16 d_seg, void *d_far, u8 c, size_t len)
+{
+ SET_SEG(ES, d_seg);
+ asm volatile(
+ "rep stosb %%es:(%%di)"
+ : "+c"(len), "+D"(d_far)
+ : "a"(c)
+ : "cc", "memory");
+}
+
+inline void
+memset16_far(u16 d_seg, void *d_far, u16 c, size_t len)
+{
+ len /= 2;
+ SET_SEG(ES, d_seg);
+ asm volatile(
+ "rep stosw %%es:(%%di)"
+ : "+c"(len), "+D"(d_far)
+ : "a"(c)
+ : "cc", "memory");
+}
+