/*
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__ (
".globl 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