// This is free and unencumbered software released into the public domain. // // Anyone is free to copy, modify, publish, use, compile, sell, or // distribute this software, either in source code form or as a compiled // binary, for any purpose, commercial or non-commercial, and by any // means. #include #include extern long time(); extern long insn(); #ifdef USE_MYSTDLIB extern char *malloc(); extern int printf(const char *format, ...); extern void *memcpy(void *dest, const void *src, long n); extern char *strcpy(char *dest, const char *src); extern int strcmp(const char *s1, const char *s2); char heap_memory[1024]; int heap_memory_used = 0; #endif long time() { int cycles; asm volatile ("rdcycle %0" : "=r"(cycles)); // printf("[time() -> %d]", cycles); return cycles; } long insn() { int insns; asm volatile ("rdinstret %0" : "=r"(insns)); // printf("[insn() -> %d]", insns); return insns; } #ifdef USE_MYSTDLIB char *malloc(int size) { char *p = heap_memory + heap_memory_used; // printf("[malloc(%d) -> %d (%d..%d)]", size, (int)p, heap_memory_used, heap_memory_used + size); heap_memory_used += size; if (heap_memory_used > 1024) asm volatile ("ebreak"); return p; } static void printf_c(int c) { *((volatile int*)0x10000000) = c; } static void printf_s(char *p) { while (*p) *((volatile int*)0x10000000) = *(p++); } static void printf_d(int val) { char buffer[32]; char *p = buffer; if (val < 0) { printf_c('-'); val = -val; } while (val || p == buffer) { *(p++) = '0' + val % 10; val = val / 10; } while (p != buffer) printf_c(*(--p)); } int printf(const char *format, ...) { int i; va_list ap; va_start(ap, format); for (i = 0; format[i]; i++) if (format[i] == '%') { while (format[++i]) { if (format[i] == 'c') { printf_c(va_arg(ap,int)); break; } if (format[i] == 's') { printf_s(va_arg(ap,char*)); break; } if (format[i] == 'd') { printf_d(va_arg(ap,int)); break; } } } else printf_c(format[i]); va_end(ap); } void *memcpy(void *aa, const void *bb, long n) { // printf("**MEMCPY**\n"); char *a = aa; const char *b = bb; while (n--) *(a++) = *(b++); return aa; } char *strcpy(char* dst, const char* src) { char *r = dst; while ((((uint32_t)dst | (uint32_t)src) & 3) != 0) { char c = *(src++); *(dst++) = c; if (!c) return r; } while (1) { uint32_t v = *(uint32_t*)src; if (__builtin_expect((((v) - 0x01010101UL) & ~(v) & 0x80808080UL), 0)) { dst[0] = v & 0xff; if ((v & 0xff) == 0) return r; v = v >> 8; dst[1] = v & 0xff; if ((v & 0xff) == 0) return r; v = v >> 8; dst[2] = v & 0xff; if ((v & 0xff) == 0) return r; v = v >> 8; dst[3] = v & 0xff; return r; } *(uint32_t*)dst = v; src += 4; dst += 4; } } int strcmp(const char *s1, const char *s2) { while ((((uint32_t)s1 | (uint32_t)s2) & 3) != 0) { char c1 = *(s1++); char c2 = *(s2++); if (c1 != c2) return c1 < c2 ? -1 : +1; else if (!c1) return 0; } while (1) { uint32_t v1 = *(uint32_t*)s1; uint32_t v2 = *(uint32_t*)s2; if (__builtin_expect(v1 != v2, 0)) { char c1, c2; c1 = v1 & 0xff, c2 = v2 & 0xff; if (c1 != c2) return c1 < c2 ? -1 : +1; if (!c1) return 0; v1 = v1 >> 8, v2 = v2 >> 8; c1 = v1 & 0xff, c2 = v2 & 0xff; if (c1 != c2) return c1 < c2 ? -1 : +1; if (!c1) return 0; v1 = v1 >> 8, v2 = v2 >> 8; c1 = v1 & 0xff, c2 = v2 & 0xff; if (c1 != c2) return c1 < c2 ? -1 : +1; if (!c1) return 0; v1 = v1 >> 8, v2 = v2 >> 8; c1 = v1 & 0xff, c2 = v2 & 0xff; if (c1 != c2) return c1 < c2 ? -1 : +1; return 0; } if (__builtin_expect((((v1) - 0x01010101UL) & ~(v1) & 0x80808080UL), 0)) return 0; s1 += 4; s2 += 4; } } #endif