summaryrefslogtreecommitdiff
path: root/zap/src/memeq.c
diff options
context:
space:
mode:
Diffstat (limited to 'zap/src/memeq.c')
-rw-r--r--zap/src/memeq.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/zap/src/memeq.c b/zap/src/memeq.c
new file mode 100644
index 0000000..f9717ad
--- /dev/null
+++ b/zap/src/memeq.c
@@ -0,0 +1,110 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#if defined(zap_priv_fastimpl)
+__asm__ (
+ ".global zap_memeq\n"
+
+ "zap_memeq:\n"
+ /*
+ void const * lptr
+ size_t num
+ void const * rptr
+ */
+#if defined(sus_arch_amd64)
+ /* rdi: Address of the current left element. */
+ /* rsi: Number of remaining elements. */
+ /* rdx: Address of the current right element. */
+ /* rax: Current left element. */
+ /* rcx: Current right element. */
+ ".wrdcmp:\n"
+ "cmpq $0x8,%rsi\n"
+ "jl .bytecmp\n"
+ "movq (%rdi),%rax\n"
+ "movq (%rdx),%rcx\n"
+ "cmpq %rax,%rcx\n"
+ "jne .neq\n"
+ "addq $0x8,%rdi\n"
+ "addq $0x8,%rdx\n"
+ "subq $0x8,%rsi\n"
+ "jmp .wrdcmp\n"
+ ".bytecmp:\n"
+ "testq %rsi,%rsi\n"
+ "jne .eq\n" /* If we have reached the final element, all previous elements have compared equal, and the memory sequences are equal. */
+ "movb (%rdi),%al\n"
+ "movb (%rdx),%cl\n"
+ "cmpb %al,%cl\n"
+ "jne .neq\n"
+ "incq %rdi\n"
+ "incq %rdx\n"
+ "decq %rsi\n"
+ "jmp .bytecmp\n"
+ ".eq:\n"
+ "movb $0x1,%al\n"
+ "ret\n"
+ ".neq:\n"
+ "movb $0x0,%al\n"
+ "ret\n"
+#elif defined(sus_arch_ia32)
+ /* eax: Address of the current left element. */
+ "movl 0x4(%esp),%eax\n"
+ /* ecx: Number of remaining elements. */
+ "movl 0x8(%esp),%ecx\n"
+ /* edx: Address of the current right element. */
+ "movl 0xC(%esp),%edx\n"
+ /* ebx: Current left element. */
+ "pushl %ebx\n"
+ /* ebx/esi: Current right element. */
+ "pushl %esi\n"
+ ".wrdcmp:\n"
+ "cmpl $0x4,%ecx\n"
+ "jl .bytecmp\n"
+ "movl (%eax),%ebx\n"
+ "movl (%edx),%esi\n"
+ "cmpl %ebx,%esi\n"
+ "jne .neq\n"
+ "addl $0x4,%eax\n"
+ "addl $0x4,%edx\n"
+ "subl $0x4,%ecx\n"
+ "jmp .wrdcmp\n"
+ ".bytecmp:\n"
+ "testl %ecx,%ecx\n"
+ "jne .eq\n" /* If we have reached the final element, all previous elements have compared equal, and the memory sequences are equal. */
+ "movb (%eax),%bl\n"
+ "movb (%edx),%bh\n"
+ "cmpb %bl,%bh\n"
+ "jne .neq\n"
+ "incl %eax\n"
+ "incl %edx\n"
+ "decl %ecx\n"
+ "jmp .bytecmp\n"
+ ".eq:\n"
+ "popl %ebx\n"
+ "popl %esi\n"
+ "movb $0x1,%al\n"
+ "ret\n"
+ ".neq:\n"
+ "popl %ebx\n"
+ "popl %esi\n"
+ "movb $0x0,%al\n"
+ "ret\n"
+#endif
+);
+#else
+bool zap_memeq(void const * const _lptr,size_t const _num,void const * const _rptr) {
+ uint_least8_t const * lpos = (uint_least8_t const *)_lptr;
+ uint_least8_t const * rpos = (uint_least8_t const *)_rptr;
+ uint_least8_t const * const afterbuf = lpos + _num;
+ for (;lpos != afterbuf;++lpos,++rpos) {sus_likely (*lpos != *rpos) {return false;}}
+ return true;
+}
+#endif