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 strcmp (optimized assembler version for the CA)
45 result = strcmp (src1_addr, src2_addr)
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.
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, strcmp
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; return result
72 g1 src2 ptr; 0xff -- byte extraction mask
89 #if __i960_BIG_ENDIAN__
103 .leafproc _strcmp, __strcmp
109 lda Lrett-(.+8)(ip),g14
114 notand g0,3,g2 # extract word addr of start of src1
115 lda (g14),g13 # preserve return address
116 #if __i960_BIG_ENDIAN__
117 cmpo g0,g2 # check alignment of src1
119 ld (g2),LSW # fetch word with at least first byte of src1
120 notand g1,3,g3 # extract word addr of start of src2
121 ld 4(g2),MSW # fetch second word of src1
122 #if __i960_BIG_ENDIAN__
123 bne Lsrc1_unaligned # branch if src1 is unaligned
124 cmpo g3,g1 # check alignment of src2
125 ld (g3),SRC2 # fetch word with at least first byte of src2
126 mov LSW,SRC1 # extract word of src1
127 lda 8(g2),g2 # advance src1 word addr
128 bne.f Lsrc2_unaligned # branch if src2 is NOT word aligned
130 /* src2 is word aligned */
132 Lwloop2: # word comparing loop
133 cmpo SRC2,SRC1 # compare src1 and src2 words
134 lda 0xff000000,g1 # byte extraction mask
135 mov MSW,LSW # move msw of src1 to lsw
136 ld (g2),MSW # pre-fetch next msw of src1
137 addo 4,g2,g2 # post-increment src1 addr
138 lda 4(g3),g3 # pre-increment src2 addr
139 bne.f Lcloop # branch if src1 and src2 unequal
140 scanbyte 0,SRC1 # check for null byte in src1 word
141 ld (g3),SRC2 # pre-fetch next word of src2
142 mov LSW,SRC1 # extract word of src1
143 lda 0,g0 # prepare to return zero, indicating equality
144 bno.t Lwloop2 # branch if null byte not encountered
146 /* words were equal and contained null byte */
148 mov 0,g14 # conform to register conventions
154 cmpo g3,g1 # check alignment of src2
155 ld (g3),SRC2 # fetch word with at least first byte of src2
156 shlo 3,g0,g14 # compute shift count for src1
157 #if __i960_BIG_ENDIAN__
158 subo g14,0,g14 # 32 - shift count for big endian.
160 eshro g14,g4,SRC1 # extract word of src1
161 lda 8(g2),g2 # advance src1 word addr
162 bne.f Lsrc2_unaligned # branch if src2 is NOT word aligned
164 /* at least src2 is word aligned */
166 Lwloop: # word comparing loop
167 cmpo SRC2,SRC1 # compare src1 and src2 words
168 #if __i960_BIG_ENDIAN__
169 lda 0xff000000,g1 # byte extraction mask
171 lda 0xff,g1 # byte extraction mask
173 mov MSW,LSW # move msw of src1 to lsw
174 ld (g2),MSW # pre-fetch next msw of src1
175 addo 4,g2,g2 # post-increment src1 addr
176 lda 4(g3),g3 # pre-increment src2 addr
177 bne.f Lcloop # branch if src1 and src2 unequal
178 scanbyte 0,SRC1 # check for null byte in src1 word
179 ld (g3),SRC2 # pre-fetch next word of src2
180 eshro g14,g4,SRC1 # extract word of src1
181 lda 0,g0 # prepare to return zero, indicating equality
182 bno.t Lwloop # branch if null byte not encountered
184 /* words were equal and contained null byte */
186 mov 0,g14 # conform to register conventions
189 Lcloop_setup: # setup for coming from Lsrc2_unaligned
190 mov LSW,SRC1 # restore extracted src1 word
191 #if __i960_BIG_ENDIAN__
192 lda 0xff000000,g1 # byte extraction mask
194 lda 0xff,g1 # byte extraction mask
197 Lcloop: # character comparing loop
198 and SRC2,g1,g3 # extract next char of src2
199 and SRC1,g1,g0 # extract next char of src1
200 cmpobne.f g0,g3,.diff # check for equality
201 cmpo 0,g0 # check for null byte
202 #if __i960_BIG_ENDIAN__
203 shro 8,g1,g1 # shift mask for next byte
205 shlo 8,g1,g1 # shift mask for next byte
207 bne.t Lcloop # branch if null not reached
209 /* words are equal up thru null byte */
212 bx (g13) # g0 = 0 (src1 == src2)
221 bx (g13) # g0 = 1 (src1 > src2)
224 bx (g13) # g0 = -1 (src1 < src2)
227 mov SRC1,LSW # retain src1 extracted word
228 ld 4(g3),SRC1 # fetch second word of src2
229 shlo 3,g1,MSW # compute shift count for src2
230 #if __i960_BIG_ENDIAN__
231 subo MSW,0,MSW # 32 - shift count for big endian.
233 eshro MSW,g6,SRC2 # extract word of src2
234 cmpo LSW,SRC2 # compare src1 and src2 words
235 notor g1,3,MSW # first step in computing new src1 ptr
236 lda 4(g3),g1 # set new src2 ptr
237 bne.f Lcloop_setup # first four bytes differ
238 scanbyte 0,LSW # check for null byte
239 lda (g13),g14 # prepare return pointer for Lrestart
240 subo MSW,g0,g0 # second (final) step in computing new src1 ptr
241 bno.t Lrestart # if null byte not encountered, continue
242 /* with both string fetches shifted such that */
243 /* src2 is now word aligned. */
244 mov 0,g14 # conform to register conventions.
245 lda 0,g0 # return indicator of equality.