Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/amd64/string/timingsafe_memcmp.S
39486 views
1
/*-
2
* Copyright (c) 2023 The FreeBSD Foundation
3
*
4
* This software was developed by Robert Clausecker <[email protected]>
5
* under sponsorship from the FreeBSD Foundation.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ''AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE
27
*/
28
29
#include <machine/asm.h>
30
31
#define ALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */
32
33
/* int timingsafe_memcmp(const void *rdi, const void *rsi, size_t rdx) */
34
ENTRY(timingsafe_memcmp)
35
cmp $16, %rdx # at least 17 bytes to process?
36
ja .Lgt16
37
38
cmp $8, %edx # at least 9 bytes to process?
39
ja .L0916
40
41
cmp $4, %edx # at least 5 bytes to process?
42
ja .L0508
43
44
cmp $2, %edx # at least 3 bytes to process?
45
ja .L0304
46
47
test %edx, %edx # buffer empty?
48
jnz .L0102
49
50
xor %eax, %eax # empty buffer always matches
51
ret
52
53
.L0102: movzbl -1(%rdi, %rdx, 1), %eax # load 1--2 bytes from first buffer
54
movzbl -1(%rsi, %rdx, 1), %ecx
55
mov (%rdi), %ah # in big endian
56
mov (%rsi), %ch
57
sub %ecx, %eax
58
ret
59
60
.L0304: movzwl -2(%rdi, %rdx, 1), %ecx
61
movzwl -2(%rsi, %rdx, 1), %edx
62
movzwl (%rdi), %eax
63
movzwl (%rsi), %esi
64
bswap %ecx # convert to big endian
65
bswap %edx # dito for edx, (e)ax, and (e)si
66
rol $8, %ax # ROLW is used here so the upper two
67
rol $8, %si # bytes stay clear, allowing us to
68
sub %edx, %ecx # save a SBB compared to .L0508
69
sbb %esi, %eax
70
or %eax, %ecx # nonzero if not equal
71
setnz %al
72
ret
73
74
.L0508: mov -4(%rdi, %rdx, 1), %ecx
75
mov -4(%rsi, %rdx, 1), %edx
76
mov (%rdi), %edi
77
mov (%rsi), %esi
78
bswap %ecx # compare in big endian
79
bswap %edx
80
bswap %edi
81
bswap %esi
82
sub %edx, %ecx
83
sbb %esi, %edi
84
sbb %eax, %eax # -1 if less, 0 if greater or equal
85
or %edi, %ecx # nonzero if not equal
86
setnz %al # negative if <, 0 if =, 1 if >
87
ret
88
89
.L0916: mov -8(%rdi, %rdx, 1), %rcx
90
mov -8(%rsi, %rdx, 1), %rdx
91
mov (%rdi), %rdi
92
mov (%rsi), %rsi
93
bswap %rcx # compare in big endian
94
bswap %rdx
95
bswap %rdi
96
bswap %rsi
97
sub %rdx, %rcx
98
sbb %rsi, %rdi
99
sbb %eax, %eax # -1 if less, 0 if greater or equal
100
or %rdi, %rcx # nonzero if not equal
101
setnz %al # negative if <, 0 if =, 1 if >
102
ret
103
104
/* compare 17+ bytes */
105
.Lgt16: mov (%rdi), %r8 # process first 16 bytes
106
mov (%rsi), %r9
107
mov $32, %ecx
108
cmp %r8, %r9 # mismatch in head?
109
cmove 8(%rdi), %r8 # if not, try second pair
110
cmove 8(%rsi), %r9
111
cmp %rdx, %rcx
112
jae .Ltail
113
114
/* main loop processing 16 bytes per iteration */
115
ALIGN_TEXT
116
0: mov -16(%rdi, %rcx, 1), %r10
117
mov -16(%rsi, %rcx, 1), %r11
118
cmp %r10, %r11 # mismatch in first pair?
119
cmove -8(%rdi, %rcx, 1), %r10 # if not, try second pair
120
cmove -8(%rsi, %rcx, 1), %r11
121
cmp %r8, %r9 # was there a mismatch previously?
122
cmove %r10, %r8 # apply new pair if there was not
123
cmove %r11, %r9
124
add $16, %rcx
125
cmp %rdx, %rcx
126
jb 0b
127
128
.Ltail: mov -8(%rdi, %rdx, 1), %r10
129
mov -8(%rsi, %rdx, 1), %r11
130
cmp %r8, %r9
131
cmove -16(%rdi, %rdx, 1), %r8
132
cmove -16(%rsi, %rdx, 1), %r9
133
bswap %r10 # compare in big endian
134
bswap %r11
135
bswap %r8
136
bswap %r9
137
sub %r11, %r10
138
sbb %r9, %r8
139
sbb %eax, %eax # -1 if less, 0 if greater or equal
140
or %r10, %r8 # nonzero if not equal
141
setnz %al # negative if <, 0 if =, 1 if >
142
ret
143
END(timingsafe_memcmp)
144
145
.section .note.GNU-stack,"",%progbits
146
147