1/*- 2 * Copyright (c) 2018 The FreeBSD Foundation 3 * 4 * This software was developed by Mateusz Guzik <mjg@FreeBSD.org> 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 * Note: this routine was written with kernel use in mind (read: no simd), 32 * it is only present in userspace as a temporary measure until something 33 * better gets imported. 34 */ 35 36#define ALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */ 37 38#ifdef BCMP 39ENTRY(bcmp) 40#else 41ENTRY(memcmp) 42#endif 43 xorl %eax,%eax 4410: 45 cmpq $16,%rdx 46 ja 101632f 47 48 cmpb $8,%dl 49 jg 100816f 50 51 cmpb $4,%dl 52 jg 100408f 53 54 cmpb $2,%dl 55 jge 100204f 56 57 cmpb $1,%dl 58 jl 100000f 59 movzbl (%rdi),%eax 60 movzbl (%rsi),%r8d 61 subl %r8d,%eax 62100000: 63 ret 64 65 ALIGN_TEXT 66100816: 67 movq (%rdi),%r8 68 movq (%rsi),%r9 69 cmpq %r8,%r9 70 jne 80f 71 movq -8(%rdi,%rdx),%r8 72 movq -8(%rsi,%rdx),%r9 73 cmpq %r8,%r9 74 jne 10081608f 75 ret 76 ALIGN_TEXT 77100408: 78 movl (%rdi),%r8d 79 movl (%rsi),%r9d 80 cmpl %r8d,%r9d 81 jne 80f 82 movl -4(%rdi,%rdx),%r8d 83 movl -4(%rsi,%rdx),%r9d 84 cmpl %r8d,%r9d 85 jne 10040804f 86 ret 87 ALIGN_TEXT 88100204: 89 movzwl (%rdi),%r8d 90 movzwl (%rsi),%r9d 91 cmpl %r8d,%r9d 92 jne 1f 93 movzwl -2(%rdi,%rdx),%r8d 94 movzwl -2(%rsi,%rdx),%r9d 95 cmpl %r8d,%r9d 96 jne 1f 97 ret 98 ALIGN_TEXT 99101632: 100 cmpq $32,%rdx 101 ja 103200f 102 movq (%rdi),%r8 103 movq (%rsi),%r9 104 cmpq %r8,%r9 105 jne 80f 106 movq 8(%rdi),%r8 107 movq 8(%rsi),%r9 108 cmpq %r8,%r9 109 jne 10163208f 110 movq -16(%rdi,%rdx),%r8 111 movq -16(%rsi,%rdx),%r9 112 cmpq %r8,%r9 113 jne 10163216f 114 movq -8(%rdi,%rdx),%r8 115 movq -8(%rsi,%rdx),%r9 116 cmpq %r8,%r9 117 jne 10163224f 118 ret 119 ALIGN_TEXT 120103200: 121 movq (%rdi),%r8 122 movq 8(%rdi),%r9 123 subq (%rsi),%r8 124 subq 8(%rsi),%r9 125 orq %r8,%r9 126 jnz 10320000f 127 128 movq 16(%rdi),%r8 129 movq 24(%rdi),%r9 130 subq 16(%rsi),%r8 131 subq 24(%rsi),%r9 132 orq %r8,%r9 133 jnz 10320016f 134 135 leaq 32(%rdi),%rdi 136 leaq 32(%rsi),%rsi 137 subq $32,%rdx 138 cmpq $32,%rdx 139 jae 103200b 140 cmpb $0,%dl 141 jne 10b 142 ret 143 144/* 145 * Mismatch was found. 146 */ 147#ifdef BCMP 148 ALIGN_TEXT 14910320016: 15010320000: 15110081608: 15210163224: 15310163216: 15410163208: 15510040804: 15680: 1571: 158 leal 1(%eax),%eax 159 ret 160END(bcmp) 161#else 162/* 163 * We need to compute the difference between strings. 164 * Start with narrowing the range down (16 -> 8 -> 4 bytes). 165 */ 166 ALIGN_TEXT 16710320016: 168 leaq 16(%rdi),%rdi 169 leaq 16(%rsi),%rsi 17010320000: 171 movq (%rdi),%r8 172 movq (%rsi),%r9 173 cmpq %r8,%r9 174 jne 80f 175 leaq 8(%rdi),%rdi 176 leaq 8(%rsi),%rsi 177 jmp 80f 178 ALIGN_TEXT 17910081608: 18010163224: 181 leaq -8(%rdi,%rdx),%rdi 182 leaq -8(%rsi,%rdx),%rsi 183 jmp 80f 184 ALIGN_TEXT 18510163216: 186 leaq -16(%rdi,%rdx),%rdi 187 leaq -16(%rsi,%rdx),%rsi 188 jmp 80f 189 ALIGN_TEXT 19010163208: 191 leaq 8(%rdi),%rdi 192 leaq 8(%rsi),%rsi 193 jmp 80f 194 ALIGN_TEXT 19510040804: 196 leaq -4(%rdi,%rdx),%rdi 197 leaq -4(%rsi,%rdx),%rsi 198 jmp 1f 199 200 ALIGN_TEXT 20180: 202 movl (%rdi),%r8d 203 movl (%rsi),%r9d 204 cmpl %r8d,%r9d 205 jne 1f 206 leaq 4(%rdi),%rdi 207 leaq 4(%rsi),%rsi 208 209/* 210 * We have up to 4 bytes to inspect. 211 */ 2121: 213 movzbl (%rdi),%eax 214 movzbl (%rsi),%r8d 215 cmpb %r8b,%al 216 jne 2f 217 218 movzbl 1(%rdi),%eax 219 movzbl 1(%rsi),%r8d 220 cmpb %r8b,%al 221 jne 2f 222 223 movzbl 2(%rdi),%eax 224 movzbl 2(%rsi),%r8d 225 cmpb %r8b,%al 226 jne 2f 227 228 movzbl 3(%rdi),%eax 229 movzbl 3(%rsi),%r8d 2302: 231 subl %r8d,%eax 232 ret 233END(memcmp) 234#endif 235 236 .section .note.GNU-stack,"",%progbits 237