Add a fast version of bcmp which compares longwords at a time.

Submitted by: Peter Jeremy <jeremyp@gsmx07.alcatel.com.au>
This commit is contained in:
Doug Rabson 1999-06-19 16:30:28 +00:00
parent de4a801355
commit 13549ec01c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=48020

View File

@ -30,10 +30,16 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: bcmp.c,v 1.4 1997/02/22 09:39:51 peter Exp $
*/
#include <string.h>
#include <machine/endian.h>
typedef const void *cvp;
typedef const unsigned char *ustring;
typedef unsigned long ul;
typedef const unsigned long *culp;
/*
* bcmp -- vax cmpc3 instruction
@ -43,6 +49,91 @@ bcmp(b1, b2, length)
const void *b1, *b2;
register size_t length;
{
#if BYTE_ORDER == LITTLE_ENDIAN
/*
* The following code is endian specific. Changing it from
* little-endian to big-endian is fairly trivial, but making
* it do both is more difficult.
*
* Note that this code will reference the entire longword which
* includes the final byte to compare. I don't believe this is
* a problem since AFAIK, objects are not protected at smaller
* than longword boundaries.
*/
int shl, shr, len = length;
ustring p1 = b1, p2 = b2;
ul va, vb;
if (len == 0)
return (0);
/*
* align p1 to a longword boundary
*/
while ((long)p1 & (sizeof(long) - 1)) {
if (*p1++ != *p2++)
return (1);
if (--len <= 0)
return (0);
}
/*
* align p2 to longword boundary and calculate the shift required to
* align p1 and p2
*/
shr = (long)p2 & (sizeof(long) - 1);
if (shr != 0) {
p2 -= shr; /* p2 now longword aligned */
shr <<= 3; /* offset in bits */
shl = (sizeof(long) << 3) - shr;
va = *(culp)p2;
p2 += sizeof(long);
while ((len -= sizeof(long)) >= 0) {
vb = *(culp)p2;
p2 += sizeof(long);
if (*(culp)p1 != (va >> shr | vb << shl))
return (1);
p1 += sizeof(long);
va = vb;
}
/*
* At this point, len is between -sizeof(long) and -1,
* representing 0 .. sizeof(long)-1 bytes remaining.
*/
if (!(len += sizeof(long)))
return (0);
len <<= 3; /* remaining length in bits */
/*
* The following is similar to the `if' condition
* inside the above while loop. The ?: is necessary
* to avoid accessing the longword after the longword
* containing the last byte to be compared.
*/
return ((((va >> shr | ((shl < len) ? *(culp)p2 << shl : 0)) ^
*(culp)p1) & ((1L << len) - 1)) != 0);
} else {
/* p1 and p2 have common alignment so no shifting needed */
while ((len -= sizeof(long)) >= 0) {
if (*(culp)p1 != *(culp)p2)
return (1);
p1 += sizeof(long);
p2 += sizeof(long);
}
/*
* At this point, len is between -sizeof(long) and -1,
* representing 0 .. sizeof(long)-1 bytes remaining.
*/
if (!(len += sizeof(long)))
return (0);
return (((*(culp)p1 ^ *(culp)p2)
& ((1L << (len << 3)) - 1)) != 0);
}
#else
register char *p1, *p2;
if (length == 0)
@ -54,4 +145,5 @@ bcmp(b1, b2, length)
break;
while (--length);
return(length);
#endif
}