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 * $FreeBSD$ 29 */ 30 31#include <machine/asm.h> 32__FBSDID("$FreeBSD$"); 33 34/* 35 * Note: this routine was written with kernel use in mind (read: no simd), 36 * it is only present in userspace as a temporary measure until something 37 * better gets imported. 38 */ 39 40#define ALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */ 41 42#ifdef BCMP 43ENTRY(bcmp) 44#else 45ENTRY(memcmp) 46#endif 47 xorl %eax,%eax 4810: 49 cmpq $16,%rdx 50 ja 101632f 51 52 cmpb $8,%dl 53 jg 100816f 54 55 cmpb $4,%dl 56 jg 100408f 57 58 cmpb $2,%dl 59 jge 100204f 60 61 cmpb $1,%dl 62 jl 100000f 63 movzbl (%rdi),%eax 64 movzbl (%rsi),%r8d 65 subl %r8d,%eax 66100000: 67 ret 68 69 ALIGN_TEXT 70100816: 71 movq (%rdi),%r8 72 movq (%rsi),%r9 73 cmpq %r8,%r9 74 jne 80f 75 movq -8(%rdi,%rdx),%r8 76 movq -8(%rsi,%rdx),%r9 77 cmpq %r8,%r9 78 jne 10081608f 79 ret 80 ALIGN_TEXT 81100408: 82 movl (%rdi),%r8d 83 movl (%rsi),%r9d 84 cmpl %r8d,%r9d 85 jne 80f 86 movl -4(%rdi,%rdx),%r8d 87 movl -4(%rsi,%rdx),%r9d 88 cmpl %r8d,%r9d 89 jne 10040804f 90 ret 91 ALIGN_TEXT 92100204: 93 movzwl (%rdi),%r8d 94 movzwl (%rsi),%r9d 95 cmpl %r8d,%r9d 96 jne 1f 97 movzwl -2(%rdi,%rdx),%r8d 98 movzwl -2(%rsi,%rdx),%r9d 99 cmpl %r8d,%r9d 100 jne 1f 101 ret 102 ALIGN_TEXT 103101632: 104 cmpq $32,%rdx 105 ja 103200f 106 movq (%rdi),%r8 107 movq (%rsi),%r9 108 cmpq %r8,%r9 109 jne 80f 110 movq 8(%rdi),%r8 111 movq 8(%rsi),%r9 112 cmpq %r8,%r9 113 jne 10163208f 114 movq -16(%rdi,%rdx),%r8 115 movq -16(%rsi,%rdx),%r9 116 cmpq %r8,%r9 117 jne 10163216f 118 movq -8(%rdi,%rdx),%r8 119 movq -8(%rsi,%rdx),%r9 120 cmpq %r8,%r9 121 jne 10163224f 122 ret 123 ALIGN_TEXT 124103200: 125 movq (%rdi),%r8 126 movq 8(%rdi),%r9 127 subq (%rsi),%r8 128 subq 8(%rsi),%r9 129 orq %r8,%r9 130 jnz 10320000f 131 132 movq 16(%rdi),%r8 133 movq 24(%rdi),%r9 134 subq 16(%rsi),%r8 135 subq 24(%rsi),%r9 136 orq %r8,%r9 137 jnz 10320016f 138 139 leaq 32(%rdi),%rdi 140 leaq 32(%rsi),%rsi 141 subq $32,%rdx 142 cmpq $32,%rdx 143 jae 103200b 144 cmpb $0,%dl 145 jne 10b 146 ret 147 148/* 149 * Mismatch was found. 150 */ 151#ifdef BCMP 152 ALIGN_TEXT 15310320016: 15410320000: 15510081608: 15610163224: 15710163216: 15810163208: 15910040804: 16080: 1611: 162 leal 1(%eax),%eax 163 ret 164END(bcmp) 165#else 166/* 167 * We need to compute the difference between strings. 168 * Start with narrowing the range down (16 -> 8 -> 4 bytes). 169 */ 170 ALIGN_TEXT 17110320016: 172 leaq 16(%rdi),%rdi 173 leaq 16(%rsi),%rsi 17410320000: 175 movq (%rdi),%r8 176 movq (%rsi),%r9 177 cmpq %r8,%r9 178 jne 80f 179 leaq 8(%rdi),%rdi 180 leaq 8(%rsi),%rsi 181 jmp 80f 182 ALIGN_TEXT 18310081608: 18410163224: 185 leaq -8(%rdi,%rdx),%rdi 186 leaq -8(%rsi,%rdx),%rsi 187 jmp 80f 188 ALIGN_TEXT 18910163216: 190 leaq -16(%rdi,%rdx),%rdi 191 leaq -16(%rsi,%rdx),%rsi 192 jmp 80f 193 ALIGN_TEXT 19410163208: 195 leaq 8(%rdi),%rdi 196 leaq 8(%rsi),%rsi 197 jmp 80f 198 ALIGN_TEXT 19910040804: 200 leaq -4(%rdi,%rdx),%rdi 201 leaq -4(%rsi,%rdx),%rsi 202 jmp 1f 203 204 ALIGN_TEXT 20580: 206 movl (%rdi),%r8d 207 movl (%rsi),%r9d 208 cmpl %r8d,%r9d 209 jne 1f 210 leaq 4(%rdi),%rdi 211 leaq 4(%rsi),%rsi 212 213/* 214 * We have up to 4 bytes to inspect. 215 */ 2161: 217 movzbl (%rdi),%eax 218 movzbl (%rsi),%r8d 219 cmpb %r8b,%al 220 jne 2f 221 222 movzbl 1(%rdi),%eax 223 movzbl 1(%rsi),%r8d 224 cmpb %r8b,%al 225 jne 2f 226 227 movzbl 2(%rdi),%eax 228 movzbl 2(%rsi),%r8d 229 cmpb %r8b,%al 230 jne 2f 231 232 movzbl 3(%rdi),%eax 233 movzbl 3(%rsi),%r8d 2342: 235 subl %r8d,%eax 236 ret 237END(memcmp) 238#endif 239 240 .section .note.GNU-stack,"",%progbits 241