10Sstevel@tonic-gate/* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 56812Sraf * Common Development and Distribution License (the "License"). 66812Sraf * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 216812Sraf 220Sstevel@tonic-gate/* 236812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 27*7298SMark.J.Nelson@Sun.COM .file "strlen.s" 280Sstevel@tonic-gate 290Sstevel@tonic-gate/* 300Sstevel@tonic-gate * strlen(s) 310Sstevel@tonic-gate * 320Sstevel@tonic-gate * Given string s, return length (not including the terminating null). 330Sstevel@tonic-gate * 340Sstevel@tonic-gate * Fast assembler language version of the following C-program strlen 350Sstevel@tonic-gate * which represents the `standard' for the C-library. 360Sstevel@tonic-gate * 370Sstevel@tonic-gate * size_t 380Sstevel@tonic-gate * strlen(s) 390Sstevel@tonic-gate * register const char *s; 400Sstevel@tonic-gate * { 410Sstevel@tonic-gate * register const char *s0 = s + 1; 420Sstevel@tonic-gate * 430Sstevel@tonic-gate * while (*s++ != '\0') 440Sstevel@tonic-gate * ; 450Sstevel@tonic-gate * return (s - s0); 460Sstevel@tonic-gate * } 470Sstevel@tonic-gate */ 480Sstevel@tonic-gate 490Sstevel@tonic-gate#include <sys/asm_linkage.h> 500Sstevel@tonic-gate 510Sstevel@tonic-gate ! The object of strlen is to, as quickly as possible, find the 520Sstevel@tonic-gate ! null byte. To this end, we attempt to get our string aligned 530Sstevel@tonic-gate ! and then blast across it using Alan Mycroft's algorithm for 540Sstevel@tonic-gate ! finding null bytes. If we are not aligned, the string is 550Sstevel@tonic-gate ! checked a byte at a time until it is. Once this occurs, 560Sstevel@tonic-gate ! we can proceed word-wise across it. Once a word with a 570Sstevel@tonic-gate ! zero byte has been found, we then check the word a byte 580Sstevel@tonic-gate ! at a time until we've located the zero byte, and return 590Sstevel@tonic-gate ! the proper length. 600Sstevel@tonic-gate 610Sstevel@tonic-gate .align 32 620Sstevel@tonic-gate ENTRY(strlen) 630Sstevel@tonic-gate andcc %o0, 3, %o4 ! is src word aligned 640Sstevel@tonic-gate bz,pt %icc, .nowalgnd 650Sstevel@tonic-gate mov %o0, %o2 660Sstevel@tonic-gate 670Sstevel@tonic-gate cmp %o4, 2 ! is src half-word aligned 680Sstevel@tonic-gate be,a,pn %icc, .s2algn 690Sstevel@tonic-gate lduh [%o2], %o1 700Sstevel@tonic-gate 710Sstevel@tonic-gate ldub [%o2], %o1 720Sstevel@tonic-gate tst %o1 ! byte zero? 730Sstevel@tonic-gate bz,pn %icc, .done 740Sstevel@tonic-gate cmp %o4, 3 ! src is byte aligned 750Sstevel@tonic-gate 760Sstevel@tonic-gate be,pn %icc, .nowalgnd 770Sstevel@tonic-gate inc 1, %o2 780Sstevel@tonic-gate 790Sstevel@tonic-gate lduh [%o2], %o1 800Sstevel@tonic-gate 810Sstevel@tonic-gate.s2algn: 820Sstevel@tonic-gate srl %o1, 8, %o4 830Sstevel@tonic-gate tst %o4 840Sstevel@tonic-gate bz,pn %icc, .done 850Sstevel@tonic-gate andcc %o1, 0xff, %g0 860Sstevel@tonic-gate 870Sstevel@tonic-gate bz,pn %icc, .done 880Sstevel@tonic-gate inc 1, %o2 890Sstevel@tonic-gate 900Sstevel@tonic-gate inc 1, %o2 910Sstevel@tonic-gate 920Sstevel@tonic-gate.nowalgnd: 930Sstevel@tonic-gate ld [%o2], %o1 940Sstevel@tonic-gate sethi %hi(0x01010101), %o4 950Sstevel@tonic-gate sethi %hi(0x80808080), %o5 960Sstevel@tonic-gate or %o4, %lo(0x01010101), %o4 970Sstevel@tonic-gate or %o5, %lo(0x80808080), %o5 980Sstevel@tonic-gate 990Sstevel@tonic-gate andn %o5, %o1, %o3 1000Sstevel@tonic-gate sub %o1, %o4, %g1 1010Sstevel@tonic-gate andcc %o3, %g1, %g0 1020Sstevel@tonic-gate bnz,a,pn %icc, .nullfound 1030Sstevel@tonic-gate sethi %hi(0xff000000), %o4 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate ld [%o2+4], %o1 1060Sstevel@tonic-gate inc 4, %o2 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate.loop: ! this should be aligned to 32 1090Sstevel@tonic-gate inc 4, %o2 1100Sstevel@tonic-gate andn %o5, %o1, %o3 ! %o5 = ~word & 0x80808080 1110Sstevel@tonic-gate sub %o1, %o4, %g1 ! %g1 = word - 0x01010101 1120Sstevel@tonic-gate andcc %o3, %g1, %g0 1130Sstevel@tonic-gate bz,a,pt %icc, .loop 1140Sstevel@tonic-gate ld [%o2], %o1 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate dec 4, %o2 1170Sstevel@tonic-gate sethi %hi(0xff000000), %o4 1180Sstevel@tonic-gate.nullfound: 1190Sstevel@tonic-gate andcc %o1, %o4, %g0 1200Sstevel@tonic-gate bz,pn %icc, .done ! first byte zero 1210Sstevel@tonic-gate srl %o4, 8, %o4 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate andcc %o1, %o4, %g0 1240Sstevel@tonic-gate bz,pn %icc, .done ! second byte zero 1250Sstevel@tonic-gate inc 1, %o2 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate srl %o4, 8, %o4 1280Sstevel@tonic-gate andcc %o1, %o4, %g0 1290Sstevel@tonic-gate bz,pn %icc, .done ! thrid byte zero 1300Sstevel@tonic-gate inc 1, %o2 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate inc 1, %o2 ! fourth byte zero 1330Sstevel@tonic-gate.done: 1340Sstevel@tonic-gate retl 1350Sstevel@tonic-gate sub %o2, %o0, %o0 1360Sstevel@tonic-gate SET_SIZE(strlen) 1370Sstevel@tonic-gate 138