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 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27.ident "%Z%%M% %I% %E% SMI" 28 29 .file "%M%" 30 31/* strcmp(s1, s2) 32 * 33 * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0 34 * 35 * Fast assembler language version of the following C-program for strcmp 36 * which represents the `standard' for the C-library. 37 * 38 * int 39 * strcmp(s1, s2) 40 * register const char *s1; 41 * register const char *s2; 42 * { 43 * 44 * if(s1 == s2) 45 * return(0); 46 * while(*s1 == *s2++) 47 * if(*s1++ == '\0') 48 * return(0); 49 * return(*s1 - s2[-1]); 50 * } 51 */ 52 53#include <sys/asm_linkage.h> 54#include "synonyms.h" 55 56 ! This strcmp implementation first determines whether s1 is aligned. 57 ! If it is not, it attempts to align it and then checks the 58 ! alignment of the destination string. If it is possible to 59 ! align s2, this also happens and then the compare begins. Otherwise, 60 ! a different compare for non-aligned strings is used. 61 ! In this case, we have multiple routines depending upon the 62 ! degree to which a string is mis-aligned. 63 64 ENTRY(strcmp) 65 66 .align 32 67 68 subcc %o0, %o1, %o2 ! s1 == s2 ? 69 bz .stringsequal1 ! yup, same string, done 70 sethi %hi(0x01010101), %o5 ! start loading Mycroft's magic2 71 andcc %o0, 3, %o3 ! s1 word-aligned ? 72 or %o5, %lo(0x01010101),%o5! finish loading Mycroft's magic2 73 bz .s1aligned ! yup 74 sll %o5, 7, %o4 ! load Mycroft's magic1 75 sub %o3, 4, %o3 ! number of bytes till aligned 76 77.aligns1: 78 ldub [%o1 + %o2], %o0 ! s1[] 79 ldub [%o1], %g1 ! s2[] 80 subcc %o0, %g1, %o0 ! s1[] != s2[] ? 81 bne .done ! yup, done 82 addcc %o0, %g1, %g0 ! s1[] == 0 ? 83 bz .done ! yup, done 84 inccc %o3 ! s1 aligned yet? 85 bnz .aligns1 ! nope, compare another pair of bytes 86 inc %o1 ! s1++, s2++ 87 88.s1aligned: 89 andcc %o1, 3, %o3 ! s2 word aligned ? 90 bz .word4 ! yup 91 cmp %o3, 2 ! s2 half-word aligned ? 92 be .word2 ! yup 93 cmp %o3, 3 ! s2 offset to dword == 3 ? 94 be,a .word3 ! yup 95 ldub [%o1], %o0 ! new lower word in s2 96 97.word1: 98 lduw [%o1 - 1], %o0 ! new lower word in s2 99 sethi %hi(0xff000000), %o3 ! mask for forcing byte 1 non-zero 100 sll %o0, 8, %g1 ! partial unaligned word from s2 101 or %o0, %o3, %o0 ! force byte 1 non-zero 102 103.cmp1: 104 andn %o4, %o0, %o3 ! ~word & 0x80808080 105 sub %o0, %o5, %o0 ! word - 0x01010101 106 andcc %o0, %o3, %g0 ! (word - 0x01010101) & ~word & 0x80808080 107 bz,a .doload1 ! no null byte in previous word from s2 108 lduw [%o1 + 3], %o0 ! load next aligned word from s2 109.doload1: 110 srl %o0, 24, %o3 ! byte 1 of new aligned word from s2 111 or %g1, %o3, %g1 ! merge to get unaligned word from s2 112 lduw [%o1 + %o2], %o3 ! word from s1 113 cmp %o3, %g1 ! *s1 != *s2 ? 114 bne .wordsdiffer ! yup, find the byte that is different 115 add %o1, 4, %o1 ! s1+=4, s2+=4 116 andn %o4, %o3, %g1 ! ~word & 0x80808080 117 sub %o3, %o5, %o3 ! word - 0x01010101 118 andcc %o3, %g1, %g0 ! (word - 0x01010101) & ~word & 0x80808080 119 bz .cmp1 ! no null-byte in s1 yet 120 sll %o0, 8, %g1 ! partial unaligned word from s2 121 122 ! words are equal but the end of s1 has been reached 123 ! this means the strings must be equal 124.stringsequal1: 125 retl ! return from leaf function 126 mov %g0, %o0 ! return 0, i.e. strings are equal 127 nop ! pad for optimal alignment of .cmp2 128 nop ! pad for optimal alignment of .cmp2 129 130.word2: 131 lduh [%o1], %o0 ! new lower word in s2 132 sethi %hi(0xffff0000), %o3 ! mask for forcing bytes 1,2 non-zero 133 sll %o0, 16, %g1 ! partial unaligned word from s2 134 or %o0, %o3, %o0 ! force bytes 1,2 non-zero 135 136.cmp2: 137 andn %o4, %o0, %o3 ! ~word & 0x80808080 138 sub %o0, %o5, %o0 ! word - 0x01010101 139 andcc %o0, %o3, %g0 ! (word - 0x01010101) & ~word & 0x80808080 140 bz,a .doload2 ! no null byte in previous word from s2 141 lduw [%o1 + 2], %o0 ! load next aligned word from s2 142.doload2: 143 srl %o0, 16, %o3 ! bytes 1,2 of new aligned word from s2 144 or %g1, %o3, %g1 ! merge to get unaligned word from s2 145 lduw [%o1 + %o2], %o3 ! word from s1 146 cmp %o3, %g1 ! *s1 != *s2 ? 147 bne .wordsdiffer ! yup, find the byte that is different 148 add %o1, 4, %o1 ! s1+=4, s2+=4 149 andn %o4, %o3, %g1 ! ~word & 0x80808080 150 sub %o3, %o5, %o3 ! word - 0x01010101 151 andcc %o3, %g1, %g0 ! (word - 0x01010101) & ~word & 0x80808080 152 bz .cmp2 ! no null-byte in s1 yet 153 sll %o0, 16, %g1 ! partial unaligned word from s2 154 155 ! words are equal but the end of s1 has been reached 156 ! this means the strings must be equal 157.stringsequal2: 158 retl ! return from leaf function 159 mov %g0, %o0 ! return 0, i.e. strings are equal 160 161.word3: 162 sll %o0, 24, %g1 ! partial unaligned word from s2 163 nop ! pad for optimal alignment of .cmp3 164.cmp3: 165 andcc %o0, 0xff, %g0 ! did previous word contain null-byte ? 166 bnz,a .doload3 ! nope, load next word from s2 167 lduw [%o1 + 1], %o0 ! load next aligned word from s2 168.doload3: 169 srl %o0, 8, %o3 ! bytes 1,2,3 from new aligned s2 word 170 or %g1, %o3, %g1 ! merge to get unaligned word from s2 171 lduw [%o1 + %o2], %o3 ! word from s1 172 cmp %o3, %g1 ! *s1 != *s2 ? 173 bne .wordsdiffer ! yup, find the byte that is different 174 add %o1, 4, %o1 ! s1+=4, s2+=4 175 andn %o4, %o3, %g1 ! ~word & 0x80808080 176 sub %o3, %o5, %o3 ! word - 0x01010101 177 andcc %o3, %g1, %g0 ! (word - 0x01010101) & ~word & 0x80808080 178 bz .cmp3 ! no null-byte in s1 yet 179 sll %o0, 24, %g1 ! partial unaligned word from s2 180 181 ! words are equal but the end of s1 has been reached 182 ! this means the strings must be equal 183.stringsequal3: 184 retl ! return from leaf function 185 mov %g0, %o0 ! return 0, i.e. strings are equal 186 187.word4: 188 lduw [%o1 + %o2], %o3 ! load word from s1 189 nop ! pad for optimal alignment of .cmp4 190 nop ! pad for optimal alignment of .cmp4 191 nop ! pad for optimal alignment of .cmp4 192 193.cmp4: 194 lduw [%o1], %g1 ! load word from s2 195 cmp %o3, %g1 ! *scr1 == *src2 ? 196 bne .wordsdiffer ! nope, find mismatching character 197 add %o1, 4, %o1 ! src1 += 4, src2 += 4 198 andn %o4, %o3, %o0 ! ~word & 0x80808080 199 sub %o3, %o5, %o3 ! word - 0x01010101 200 andcc %o3, %o0, %g0 ! (word - 0x01010101) & ~word & 0x80808080 201 bz,a .cmp4 ! no null-byte in s1 yet 202 lduw [%o1 + %o2], %o3 ! load word from s1 203 204 ! words are equal but the end of s1 has been reached 205 ! this means the strings must be equal 206.stringsequal4: 207 retl ! return from leaf function 208 mov %g0, %o0 ! return 0, i.e. strings are equal 209 210.wordsdiffer: 211 srl %g1, 24, %o2 ! first byte of mismatching word in s2 212 srl %o3, 24, %o1 ! first byte of mismatching word in s1 213 subcc %o1, %o2, %o0 ! *s1-*s2 214 bnz .done ! bytes differ, return difference 215 srl %g1, 16, %o2 ! second byte of mismatching word in s2 216 andcc %o1, 0xff, %o0 ! *s1 == 0 ? 217 bz .done ! yup 218 219 ! we know byte 1 is equal, so can compare bytes 1,2 as a group 220 221 srl %o3, 16, %o1 ! second byte of mismatching word in s1 222 subcc %o1, %o2, %o0 ! *s1-*s2 223 bnz .done ! bytes differ, return difference 224 srl %g1, 8, %o2 ! third byte of mismatching word in s2 225 andcc %o1, 0xff, %o0 ! *s1 == 0 ? 226 bz .done ! yup 227 228 ! we know bytes 1, 2 are equal, so can compare bytes 1,2,3 as a group 229 230 srl %o3, 8, %o1 ! third byte of mismatching word in s1 231 subcc %o1, %o2, %o0 ! *s1-*s2 232 bnz .done ! bytes differ, return difference 233 andcc %o1, 0xff, %g0 ! *s1 == 0 ? 234 bz .stringsequal1 ! yup 235 236 ! we know bytes 1,2,3 are equal, so can compare bytes 1,2,3,4 as group 237 238 subcc %o3, %g1, %o0 ! *s1-*s2 239 bz,a .done ! bytes differ, return difference 240 andcc %o3, 0xff, %o0 ! *s1 == 0 ? 241 242.done: 243 retl ! return from leaf routine 244 nop ! padding 245 246 247 SET_SIZE(strcmp) 248