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