diff --git a/port/android/guest/runtime/guest_string.c b/port/android/guest/runtime/guest_string.c new file mode 100644 index 00000000..2d6de7b8 --- /dev/null +++ b/port/android/guest/runtime/guest_string.c @@ -0,0 +1,37 @@ +/* +GUEST_STRING.C + +String functions faster than musl's generic C ones, which the guest takes +in their place (tools/android_build.py MUSL_EXCLUDE). The renderer's state +caches compare their keys with memcmp on every draw (the pixel shaders' +keys, the vertex constants, the uniforms), and musl's compares a byte at a +time. +*/ + +#include +#include +#include + +/* eight bytes at a time while they match (AArch64 loads them unaligned), +then the bytes that differ, or the tail. no_builtin: clang would turn the +loops back into a call to memcmp */ +__attribute__((no_builtin)) int memcmp(const void *left, const void *right, size_t size) +{ + const unsigned char *l = left, *r = right; + + for (; size >= 8; size -= 8, l += 8, r += 8) + { + uint64_t a, b; + + __builtin_memcpy(&a, l, 8); + __builtin_memcpy(&b, r, 8); + if (a != b) + break; + } + for (; size; size--, l++, r++) + { + if (*l != *r) + return *l - *r; + } + return 0; +} diff --git a/tools/android_build.py b/tools/android_build.py index 49d87847..fcce7c58 100644 --- a/tools/android_build.py +++ b/tools/android_build.py @@ -133,6 +133,8 @@ MUSL_EXCLUDE = { "env/__reset_tls.c", "malloc/oldmalloc", "thread/pthread_create.c", # unused, and its compiler barrier is an inline assembly statement "string/explicit_bzero.c", + # eight bytes at a time (guest_string.c) + "string/memcmp.c", } # game files that call variadic functions without a prototype in scope, which # only works under x86's calling convention (tools/android_abi_check.py)