1 /*******************************************************************************
3 * Copyright (c) 1993 Intel Corporation
5 * Intel hereby grants you permission to copy, modify, and distribute this
6 * software and its documentation. Intel grants this permission provided
7 * that the above copyright notice appears in all copies and that both the
8 * copyright notice and this permission notice appear in supporting
9 * documentation. In addition, Intel grants this permission provided that
10 * you prominently mark as "not part of the original" any modifications
11 * made to this software or documentation, and that the name of Intel
12 * Corporation not be used in advertising or publicity pertaining to
13 * distribution of the software or the documentation without specific,
14 * written prior permission.
16 * Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR
17 * IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY
18 * OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or
19 * representations regarding the use of, or the results of the use of,
20 * the software and documentation in terms of correctness, accuracy,
21 * reliability, currentness, or otherwise; and you rely on the software,
22 * documentation and results solely at your own risk.
24 * IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS,
25 * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES
26 * OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM
27 * PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER.
29 ******************************************************************************/
39 * (c) copyright 1988,1993 Intel Corp., all rights reserved
43 procedure strncmp (optimized assembler version for the CA)
45 result = strncmp (src1_addr, src2_addr, max_bytes)
47 compare the null terminated string pointed to by src1_addr to
48 the string space pointed to by src2_addr. Return 0 iff the strings
49 are equal, -1 if src1_addr is lexicly less than src2_addr, and 1
50 if it is lexicly greater. Do not compare more than max_bytes bytes.
52 Undefined behavior will occur if the end of either source string
53 (i.e. the terminating null byte) is in the last word of the program's
54 allocated memory space. This is so because, in several cases, strncmp
55 will fetch ahead one word. Disallowing the fetch ahead would impose
56 a severe performance penalty.
58 This program handles five cases:
60 1) both arguments start on a word boundary
61 2) neither are word aligned, but they are offset by the same amount
62 3) source1 is word aligned, source2 is not
63 4) source2 is word aligned, source1 is not
64 5) neither is word aligned, and they are offset by differing amounts
66 At the time of this writing, only g0 thru g7 and g14 are available
67 for use in this leafproc; other registers would have to be saved and
68 restored. These nine registers are sufficient to implement the routine.
69 The registers are used as follows:
71 g0 original src1 ptr; extracted word; return result
72 g1 src2 ptr; 0xff -- byte extraction mask
73 g2 maximum number of bytes to compare
89 #if __i960_BIG_ENDIAN__
103 .leafproc _strncmp, __strncmp
109 lda Lrett-(.+8)(ip),g14
113 notand g0,3,SRC1 # extract word addr of start of src1
114 lda (g14),g13 # preserve return address
115 cmpibge.f 0,g2,Lequal_exit # return equality if number of bytes to
116 /* compare is none. */
117 #if __i960_BIG_ENDIAN__
118 cmpo g0,SRC1 # check alignment of src1
120 ld (SRC1),LSW # fetch word with at least first byte of src1
121 notand g1,3,g3 # extract word addr of start of src2
122 ld 4(SRC1),MSW # fetch second word of src1
123 #if __i960_BIG_ENDIAN__
124 bne Lsrc1_unaligned # branch if src1 is unaligned
125 cmpo g3,g1 # check alignment of src2
126 ld (g3),SRC2 # fetch word with at least first byte of src2
127 shlo 3,g0,g14 # compute shift count for src1
128 subo g14,0,g14 # adjust shift count for big endian
129 lda 8(SRC1),SRC1 # advance src1 word addr
130 bne.f Lsrc2_unaligned # branch if src2 is NOT word aligned
132 /* src2 is word aligned */
136 Lwloop2: # word comparing loop
137 cmpo SRC2,g0 # compare src1 and src2 words
138 lda 0xff000000,g1 # byte extraction mask
139 mov MSW,LSW # move msw of src1 to lsw
140 ld (SRC1),MSW # pre-fetch next msw of src1
141 addo 4,SRC1,SRC1 # post-increment src1 addr
142 lda 4(g3),g3 # pre-increment src2 addr
143 bne.f Lcloop # branch if src1 and src2 unequal
144 scanbyte 0,g0 # check for null byte in src1 word
145 ld (g3),SRC2 # pre-fetch next word of src2
146 mov LSW,g0 # extract word of src1
147 subi 4,g2,g2 # decrement maximum byte count
148 bo.f Lequal_exit # branch if null byte encountered
149 cmpibl.t 0,g2,Lwloop2 # branch if max_bytes not reached yet
151 b Lequal_exit # strings were equal up through max_bytes
155 cmpo g3,g1 # check alignment of src2
156 ld (g3),SRC2 # fetch word with at least first byte of src2
157 shlo 3,g0,g14 # compute shift count for src1
158 #if __i960_BIG_ENDIAN__
159 subo g14,0,g14 # adjust shift count for big endian
161 eshro g14,g4,LSW # extract word of src1
162 lda 8(SRC1),SRC1 # advance src1 word addr
163 bne.f Lsrc2_unaligned # branch if src2 is NOT word aligned
165 /* at least src2 is word aligned */
169 Lwloop: # word comparing loop
170 cmpo SRC2,g0 # compare src1 and src2 words
171 #if __i960_BIG_ENDIAN__
172 lda 0xff000000,g1 # byte extraction mask
174 lda 0xff,g1 # byte extraction mask
176 mov MSW,LSW # move msw of src1 to lsw
177 ld (SRC1),MSW # pre-fetch next msw of src1
178 addo 4,SRC1,SRC1 # post-increment src1 addr
179 lda 4(g3),g3 # pre-increment src2 addr
180 bne.f Lcloop # branch if src1 and src2 unequal
181 scanbyte 0,g0 # check for null byte in src1 word
182 ld (g3),SRC2 # pre-fetch next word of src2
183 eshro g14,g4,g0 # extract word of src1
184 subi 4,g2,g2 # decrement maximum byte count
185 bo.f Lequal_exit # branch if null byte encountered
186 cmpibl.t 0,g2,Lwloop # branch if max_bytes not reached yet
188 b Lequal_exit # strings were equal up through max_bytes
190 Lcloop_setup: # setup for coming from Lsrc2_unaligned
191 mov LSW,g0 # restore extracted src1 word
192 #if __i960_BIG_ENDIAN__
193 lda 0xff000000,g1 # byte extraction mask
195 lda 0xff,g1 # byte extraction mask
198 Lcloop: # character comparing loop
199 and SRC2,g1,g3 # extract next char of src2
200 and g0,g1,LSW # extract next char of src1
201 cmpobne.f LSW,g3,.diff # check for equality
202 cmpo 0,LSW # check for null byte
203 #if __i960_BIG_ENDIAN__
204 shro 8,g1,g1 # shift mask for next byte
206 shlo 8,g1,g1 # shift mask for next byte
208 subi 1,g2,g2 # decrement character counter
209 bne.t Lcloop # branch if null not reached
211 /* words are equal up thru null byte */
214 mov 0,g14 # conform to register conventions
215 lda 0,g0 # return zero, indicating equality
225 cmpibge.f 0,g2,Lequal_exit # branch if difference is beyond max_bytes
227 bx (g13) # g0 = 1 (src1 > src2)
229 cmpibge.f 0,g2,Lequal_exit # branch if difference is beyond max_bytes
231 bx (g13) # g0 = -1 (src1 < src2)
234 notor g1,3,g14 # first step in computing new src1 ptr
235 ld 4(g3),SRC1 # fetch second word of src2
236 shlo 3,g1,MSW # compute shift count for src2
237 #if __i960_BIG_ENDIAN__
238 subo MSW,0,MSW # adjust shift count for big endian
240 eshro MSW,g6,SRC2 # extract word of src2
241 cmpo LSW,SRC2 # compare src1 and src2 words
242 lda 4(g3),g1 # set new src2 ptr
243 bne.f Lcloop_setup # first four bytes differ
244 scanbyte 0,LSW # check for null byte
245 subo g14,g0,g0 # second (final) step in computing new src1 ptr
246 addi g14,g2,g2 # compute new max_bytes too
247 lda (g13),g14 # prepare return pointer for Lrestart
248 bno.t Lrestart # if null byte not encountered, continue
249 /* with both string fetches shifted such that*/
250 /* src2 is now word aligned.*/
251 mov 0,g14 # conform to register conventions.
252 lda 0,g0 # return indicator of equality.