xref: /optee_os/lib/libutils/isoc/newlib/memcmp.c (revision bc420748bfc44a9e09000a3966fc59e9e0219df4)
1 /*
2  * Copyright (c) 1994-2009  Red Hat, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from this
17  * software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33 FUNCTION
34 	<<memcmp>>---compare two memory areas
35 
36 INDEX
37 	memcmp
38 
39 ANSI_SYNOPSIS
40 	#include <string.h>
41 	int memcmp(const void *<[s1]>, const void *<[s2]>, size_t <[n]>);
42 
43 TRAD_SYNOPSIS
44 	#include <string.h>
45 	int memcmp(<[s1]>, <[s2]>, <[n]>)
46 	void *<[s1]>;
47 	void *<[s2]>;
48 	size_t <[n]>;
49 
50 DESCRIPTION
51 	This function compares not more than <[n]> characters of the
52 	object pointed to by <[s1]> with the object pointed to by <[s2]>.
53 
54 RETURNS
55 	The function returns an integer greater than, equal to or
56 	less than zero 	according to whether the object pointed to by
57 	<[s1]> is greater than, equal to or less than the object
58 	pointed to by <[s2]>.
59 
60 PORTABILITY
61 <<memcmp>> is ANSI C.
62 
63 <<memcmp>> requires no supporting OS subroutines.
64 
65 QUICKREF
66 	memcmp ansi pure
67 */
68 
69 #include "_ansi.h"
70 #include <string.h>
71 
72 /* Nonzero if either X or Y is not aligned on a "long" boundary.  */
73 #define UNALIGNED(X, Y) \
74 	(((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1)))
75 
76 /* How many bytes are copied each iteration of the word copy loop.  */
77 #define LBLOCKSIZE (sizeof(long))
78 
79 /* Threshhold for punting to the byte copier.  */
80 #define TOO_SMALL(LEN)  ((LEN) < LBLOCKSIZE)
81 
82 int
83 _DEFUN(memcmp, (m1, m2, n), _CONST _PTR m1 _AND _CONST _PTR m2 _AND size_t n)
84 {
85 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
86 	unsigned char *s1 = (unsigned char *)m1;
87 	unsigned char *s2 = (unsigned char *)m2;
88 
89 	while (n--) {
90 		if (*s1 != *s2)
91 			return *s1 - *s2;
92 		s1++;
93 		s2++;
94 	}
95 	return 0;
96 #else
97 	unsigned char *s1 = (unsigned char *)m1;
98 	unsigned char *s2 = (unsigned char *)m2;
99 	unsigned long *a1;
100 	unsigned long *a2;
101 
102 	/* If the size is too small, or either pointer is unaligned,
103 	   then we punt to the byte compare loop.  Hopefully this will
104 	   not turn up in inner loops.  */
105 	if (!TOO_SMALL(n) && !UNALIGNED(s1, s2)) {
106 		/*
107 		 * Otherwise, load and compare the blocks of memory one word at
108 		 * a time.
109 		 */
110 		a1 = (unsigned long *)s1;
111 		a2 = (unsigned long *)s2;
112 		while (n >= LBLOCKSIZE) {
113 			if (*a1 != *a2)
114 				break;
115 			a1++;
116 			a2++;
117 			n -= LBLOCKSIZE;
118 		}
119 
120 		/* check m mod LBLOCKSIZE remaining characters */
121 
122 		s1 = (unsigned char *)a1;
123 		s2 = (unsigned char *)a2;
124 	}
125 
126 	while (n--) {
127 		if (*s1 != *s2)
128 			return *s1 - *s2;
129 		s1++;
130 		s2++;
131 	}
132 
133 	return 0;
134 #endif /* not PREFER_SIZE_OVER_SPEED */
135 }
136