1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright (c) 1989,1998 by Sun Microsystems, Inc. 24 * All rights reserved. 25 * 26 * .seg "data" 27 * .asciz "@(#)strncmp.s 1.2 89/08/16" 28 */ 29 30.ident "%Z%%M% %I% %E% SMI" /* SunOS 4.1 1.4 */ 31 32 .file "strncmp.s" 33 34/* 35 * strncmp(s1, s2, n) 36 * 37 * Compare strings (at most n bytes): s1>s2: >0 s1==s2: 0 s1<s2: <0 38 * 39 * Fast assembler language version of the following C-program for strncmp 40 * which represents the `standard' for the C-library. 41 * 42 * int 43 * strncmp(const char *s1, const char *s2, size_t n) 44 * { 45 * n++; 46 * if (s1 == s2) 47 * return (0); 48 * while (--n != 0 && *s1 == *s2++) 49 * if (*s1++ == '\0') 50 * return (0); 51 * return ((n == 0) ? 0 : (*s1 - s2[-1])); 52 * } 53 */ 54 55#include <sys/asm_linkage.h> 56#include "synonyms.h" 57 58 ENTRY(strncmp) 59 save %sp, -SA(WINDOWSIZE), %sp 60 cmp %i2, 8 61 blu,a .cmp_bytes ! for small counts go do bytes 62 sub %i0, %i1, %i0 ! delay slot, get diff from s1 - s2 63 andcc %i0, 3, %g0 ! is s1 aligned 641: bz .iss2 ! if so go check s2 65 andcc %i1, 3, %i3 ! is s2 aligned 66 67 deccc %i2 ! --n >= 0 ? 68 bcs .doneq 69 nop ! delay slot 70 71 ldub [%i0], %i4 ! else cmp one byte 72 ldub [%i1], %i5 73 inc %i0 74 cmp %i4, %i5 75 bne .noteqb 76 inc %i1 77 tst %i4 ! terminating zero 78 bnz 1b 79 andcc %i0, 3, %g0 80 b,a .doneq 81 82.iss2: 83 set 0x7efefeff, %l6 84 set 0x81010100, %l7 85 sethi %hi(0xff000000), %l0 ! masks to test for terminating null 86 sethi %hi(0x00ff0000), %l1 87 srl %l1, 8, %l2 ! generate 0x0000ff00 mask 88 89 bz .w4cmp ! if s2 word aligned, compare words 90 cmp %i3, 2 ! check if s2 half aligned 91 be .w2cmp 92 cmp %i3, 1 ! check if aligned to 1 or 3 bytes 93.w3cmp: ldub [%i1], %i5 94 inc 1, %i1 95 be .w1cmp 96 sll %i5, 24, %i5 97 sub %i0, %i1, %i0 982: 99 deccc 4, %i2 ! n >= 4 ? 100 bgeu,a 3f 101 ld [%i1], %i3 ! delay slot 102 dec %i1 ! reset s2 103 inc %i0 ! reset s1 diff 104 b .cmp_bytes ! do a byte at a time if n < 4 105 inc 4, %i2 1063: 107 ld [%i0 + %i1], %i4 108 inc 4, %i1 109 srl %i3, 8, %l4 ! merge with the other half 110 or %l4, %i5, %i5 111 cmp %i4, %i5 112 be 1f 113 114 add %i4, %l6, %l3 115 b,a .noteq 1161: xor %l3, %i4, %l3 117 and %l3, %l7, %l3 118 cmp %l3, %l7 119 be,a 2b 120 sll %i3, 24, %i5 121 122 ! 123 ! For 7-bit characters, we know one of the bytes is zero, but for 124 ! 8-bit characters, the zero detection algorithm gives some false 125 ! triggers ... check every byte individually. 126 ! 127 andcc %i4, %l0, %g0 ! check if first byte was zero 128 bnz 1f 129 andcc %i4, %l1, %g0 ! check if second byte was zero 130 b,a .doneq 1311: bnz 1f 132 andcc %i4, %l2, %g0 ! check if third byte was zero 133 b,a .doneq 1341: bnz 1f 135 andcc %i4, 0xff, %g0 ! check if last byte is zero 136 b,a .doneq 1371: bnz 2b 138 sll %i3, 24, %i5 139 b,a .doneq 140 141.w1cmp: clr %l4 142 lduh [%i1], %l4 143 inc 2, %i1 144 sll %l4, 8, %l4 145 or %i5, %l4, %i5 146 147 sub %i0, %i1, %i0 1483: 149 deccc 4, %i2 ! n >= 4 ? 150 bgeu,a 4f 151 ld [%i1], %i3 ! delay slot 152 dec 3, %i1 ! reset s2 153 inc 3, %i0 ! reset s1 diff 154 b .cmp_bytes ! do a byte at a time if n < 4 155 inc 4, %i2 1564: 157 ld [%i0 + %i1], %i4 158 inc 4, %i1 159 srl %i3, 24, %l4 ! merge with the other half 160 or %l4, %i5, %i5 161 cmp %i4, %i5 162 be 1f 163 164 add %i4, %l6, %l3 165 b,a .noteq 1661: xor %l3, %i4, %l3 167 and %l3, %l7, %l3 168 cmp %l3, %l7 169 be,a 3b 170 sll %i3, 8, %i5 171 172 andcc %i4, %l0, %g0 ! check if first byte was zero 173 bnz 1f 174 andcc %i4, %l1, %g0 ! check if second byte was zero 175 b,a .doneq 1761: bnz 1f 177 andcc %i4, %l2, %g0 ! check if third byte was zero 178 b,a .doneq 1791: bnz 1f 180 andcc %i4, 0xff, %g0 ! check if last byte is zero 181 b,a .doneq 1821: bnz 3b 183 sll %i3, 8, %i5 184 b,a .doneq 185 186.w2cmp: 187 lduh [%i1], %i5 ! read a halfword to align s2 188 inc 2, %i1 189 sll %i5, 16, %i5 190 191 sub %i0, %i1, %i0 1924: 193 deccc 4, %i2 ! n >= 4 ? 194 bgeu,a 5f 195 ld [%i1], %i3 ! delay slot 196 dec 2, %i1 ! reset s2 197 inc 2, %i0 ! reset s1 diff 198 b .cmp_bytes ! do a byte at a time if n < 4 199 inc 4, %i2 ! delay slot 2005: 201 ld [%i1 + %i0], %i4 ! read a word from s2 202 inc 4, %i1 203 srl %i3, 16, %l4 ! merge with the other half 204 or %l4, %i5, %i5 205 cmp %i4, %i5 206 be 1f 207 208 add %i4, %l6, %l3 209 b,a .noteq 2101: xor %l3, %i4, %l3 ! are any bytes 0? 211 and %l3, %l7, %l3 212 cmp %l3, %l7 213 be,a 4b 214 sll %i3, 16, %i5 215 216 andcc %i4, %l0, %g0 ! check if first byte was zero 217 bnz 1f 218 andcc %i4, %l1, %g0 ! check if second byte was zero 219 b,a .doneq 2201: bnz 1f 221 andcc %i4, %l2, %g0 ! check if third byte was zero 222 b,a .doneq 2231: bnz 1f 224 andcc %i4, 0xff, %g0 ! check if last byte is zero 225 b,a .doneq 2261: bnz 4b 227 sll %i3, 16, %i5 228 b,a .doneq 229 230.w4cmp: sub %i0, %i1, %i0 231 ld [%i1], %i5 ! read a word from s1 2325: cmp %i2,0 233 be,a .doneq 234 nop 235 ld [%i1], %i5 ! read a word from s1 236 deccc 4, %i2 ! n >= 4 ? 237 bcs,a .cmp_bytes ! do a byte at a time if n < 4 238 inc 4, %i2 239 240 ld [%i1 + %i0], %i4 ! read a word from s2 241 cmp %i4, %i5 242 inc 4, %i1 243 be 1f 244 245 add %i4, %l6, %l3 246 b,a .noteq 2471: xor %l3, %i4, %l3 248 and %l3, %l7, %l3 249 cmp %l3, %l7 250 be,a 5b 251 nop 252 253 andcc %i4, %l0, %g0 ! check if first byte was zero 254 bnz 1f 255 andcc %i4, %l1, %g0 ! check if second byte was zero 256 b,a .doneq 2571: bnz 1f 258 andcc %i4, %l2, %g0 ! check if third byte was zero 259 b,a .doneq 2601: bnz 1f 261 andcc %i4, 0xff, %g0 ! check if last byte is zero 262 b,a .doneq 2631: bnz,a 5b 264 ld [%i1], %i5 265.doneq: ret 266 restore %g0, %g0, %o0 ! equal return zero 267 268.noteq: srl %i4, 24, %l4 269 srl %i5, 24, %l5 270 subcc %l4, %l5, %i0 271 bne 6f 272 andcc %l4, 0xff, %g0 273 bz .doneq 274 sll %i4, 8, %l4 275 sll %i5, 8, %l5 276 srl %l4, 24, %l4 277 srl %l5, 24, %l5 278 subcc %l4, %l5, %i0 279 bne 6f 280 andcc %l4, 0xff, %g0 281 bz .doneq 282 sll %i4, 16, %l4 283 sll %i5, 16, %l5 284 srl %l4, 24, %l4 285 srl %l5, 24, %l5 286 subcc %l4, %l5, %i0 287 bne 6f 288 andcc %l4, 0xff, %g0 289 bz .doneq 290 nop 291.noteqb: 292 and %i4, 0xff, %l4 293 and %i5, 0xff, %l5 294 subcc %l4, %l5, %i0 2956: ret 296 restore %i0, %g0, %o0 297 298 ! Do a byte by byte comparison, disregarding alignments 299.cmp_bytes: 300 deccc %i2 ! --n >= 0 ? 3011: 302 bcs .doneq 303 nop ! delay slot 304 ldub [%i1 + %i0], %i4 ! read a word from s1 305 ldub [%i1], %i5 ! read a word from s2 306 307 inc %i1 308 cmp %i4, %i5 309 bne .noteqb 310 tst %i4 ! terminating zero 311 bnz 1b 312 deccc %i2 ! --n >= 0 313 b,a .doneq 314 315 SET_SIZE(strncmp) 316