summaryrefslogtreecommitdiff
path: root/zap/src/memeq.c
blob: 7dce213ccdd41478be1dacecf05bbff8e2cddc82 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
	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 <zap/mem.h>

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#if 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) {
	unsigned char const *       lpos     = _lptr;
	unsigned char const *       rpos     = _rptr;
	unsigned char const * const afterbuf = lpos + _num;
	for (;lpos != afterbuf;++lpos,++rpos) {sus_likely (*lpos != *rpos) {return false;}}
	return true;
}
#endif