1139815Simp/*-
21541Srgrimes * Copyright (c) 1987, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 4. Neither the name of the University nor the names of its contributors
141541Srgrimes *    may be used to endorse or promote products derived from this software
151541Srgrimes *    without specific prior written permission.
161541Srgrimes *
171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271541Srgrimes * SUCH DAMAGE.
281541Srgrimes */
291541Srgrimes
30116189Sobrien#include <sys/cdefs.h>
31116189Sobrien__FBSDID("$FreeBSD$");
32116189Sobrien
33102281Sjhb#include <sys/libkern.h>
3448020Sdfr#include <machine/endian.h>
351541Srgrimes
3648020Sdfrtypedef	const void	*cvp;
3748020Sdfrtypedef	const unsigned char	*ustring;
3848020Sdfrtypedef unsigned long	ul;
3948020Sdfrtypedef const unsigned long	*culp;
4048020Sdfr
411541Srgrimes/*
421541Srgrimes * bcmp -- vax cmpc3 instruction
431541Srgrimes */
441541Srgrimesint
451541Srgrimesbcmp(b1, b2, length)
461541Srgrimes	const void *b1, *b2;
471541Srgrimes	register size_t length;
481541Srgrimes{
4948020Sdfr#if BYTE_ORDER == LITTLE_ENDIAN
5048020Sdfr	/*
5148020Sdfr	 * The following code is endian specific.  Changing it from
5248020Sdfr	 * little-endian to big-endian is fairly trivial, but making
5348020Sdfr	 * it do both is more difficult.
5448020Sdfr	 *
5548020Sdfr	 * Note that this code will reference the entire longword which
5648020Sdfr	 * includes the final byte to compare.  I don't believe this is
5748020Sdfr	 * a problem since AFAIK, objects are not protected at smaller
5848020Sdfr	 * than longword boundaries.
5948020Sdfr	 */
6048020Sdfr	int	shl, shr, len = length;
6148020Sdfr	ustring	p1 = b1, p2 = b2;
6248020Sdfr	ul	va, vb;
6348020Sdfr
6448020Sdfr	if (len == 0)
6548020Sdfr		return (0);
6648020Sdfr
6748020Sdfr	/*
6848020Sdfr	 * align p1 to a longword boundary
6948020Sdfr	 */
7048020Sdfr	while ((long)p1 & (sizeof(long) - 1)) {
7148020Sdfr		if (*p1++ != *p2++)
7248020Sdfr			return (1);
7348020Sdfr		if (--len <= 0)
7448020Sdfr			return (0);
7548020Sdfr	}
7648020Sdfr
7748020Sdfr	/*
7848020Sdfr	 * align p2 to longword boundary and calculate the shift required to
7948020Sdfr	 * align p1 and p2
8048020Sdfr	 */
8148020Sdfr	shr = (long)p2 & (sizeof(long) - 1);
8248020Sdfr	if (shr != 0) {
8348020Sdfr		p2 -= shr;			/* p2 now longword aligned */
8448020Sdfr		shr <<= 3;			/* offset in bits */
8548020Sdfr		shl = (sizeof(long) << 3) - shr;
8648020Sdfr
8748020Sdfr		va = *(culp)p2;
8848020Sdfr		p2 += sizeof(long);
8948020Sdfr
9048020Sdfr		while ((len -= sizeof(long)) >= 0) {
9148020Sdfr			vb = *(culp)p2;
9248020Sdfr			p2 += sizeof(long);
9348020Sdfr			if (*(culp)p1 != (va >> shr | vb << shl))
9448020Sdfr				return (1);
9548020Sdfr			p1 += sizeof(long);
9648020Sdfr			va = vb;
9748020Sdfr		}
9848020Sdfr		/*
9948020Sdfr		 * At this point, len is between -sizeof(long) and -1,
10048020Sdfr		 * representing 0 .. sizeof(long)-1 bytes remaining.
10148020Sdfr		 */
10248020Sdfr		if (!(len += sizeof(long)))
10348020Sdfr			return (0);
10448020Sdfr
10548020Sdfr		len <<= 3;		/* remaining length in bits */
10648020Sdfr		/*
10748020Sdfr		 * The following is similar to the `if' condition
10848020Sdfr		 * inside the above while loop.  The ?: is necessary
10948020Sdfr		 * to avoid accessing the longword after the longword
11048020Sdfr		 * containing the last byte to be compared.
11148020Sdfr		 */
11248020Sdfr		return ((((va >> shr | ((shl < len) ? *(culp)p2 << shl : 0)) ^
11348020Sdfr		    *(culp)p1) & ((1L << len) - 1)) != 0);
11448020Sdfr	} else {
11548020Sdfr		/* p1 and p2 have common alignment so no shifting needed */
11648020Sdfr		while ((len -= sizeof(long)) >= 0) {
11748020Sdfr			if (*(culp)p1 != *(culp)p2)
11848020Sdfr				return (1);
11948020Sdfr			p1 += sizeof(long);
12048020Sdfr			p2 += sizeof(long);
12148020Sdfr		}
12248020Sdfr
12348020Sdfr		/*
12448020Sdfr		 * At this point, len is between -sizeof(long) and -1,
12548020Sdfr		 * representing 0 .. sizeof(long)-1 bytes remaining.
12648020Sdfr		 */
12748020Sdfr		if (!(len += sizeof(long)))
12848020Sdfr			return (0);
12948020Sdfr
13048020Sdfr		return (((*(culp)p1 ^ *(culp)p2)
13148020Sdfr			 & ((1L << (len << 3)) - 1)) != 0);
13248020Sdfr	}
13348020Sdfr#else
134125725Sgrehan	const char *p1, *p2;
1351541Srgrimes
1361541Srgrimes	if (length == 0)
1371541Srgrimes		return(0);
138125725Sgrehan	p1 = b1;
139125725Sgrehan	p2 = b2;
1401541Srgrimes	do
1411541Srgrimes		if (*p1++ != *p2++)
1421541Srgrimes			break;
1431541Srgrimes	while (--length);
1441541Srgrimes	return(length);
14548020Sdfr#endif
1461541Srgrimes}
147