1*37c9f0a6Schristos/* $NetBSD: strlen.S,v 1.1 2005/12/20 19:28:50 christos Exp $ */ 2*37c9f0a6Schristos 3*37c9f0a6Schristos/* 4*37c9f0a6Schristos * Copyright 2002 Wasabi Systems, Inc. 5*37c9f0a6Schristos * All rights reserved. 6*37c9f0a6Schristos * 7*37c9f0a6Schristos * Written by Eduardo Horvath for Wasabi Systems, Inc. 8*37c9f0a6Schristos * 9*37c9f0a6Schristos * Redistribution and use in source and binary forms, with or without 10*37c9f0a6Schristos * modification, are permitted provided that the following conditions 11*37c9f0a6Schristos * are met: 12*37c9f0a6Schristos * 1. Redistributions of source code must retain the above copyright 13*37c9f0a6Schristos * notice, this list of conditions and the following disclaimer. 14*37c9f0a6Schristos * 2. Redistributions in binary form must reproduce the above copyright 15*37c9f0a6Schristos * notice, this list of conditions and the following disclaimer in the 16*37c9f0a6Schristos * documentation and/or other materials provided with the distribution. 17*37c9f0a6Schristos * 3. All advertising materials mentioning features or use of this software 18*37c9f0a6Schristos * must display the following acknowledgement: 19*37c9f0a6Schristos * This product includes software developed for the NetBSD Project by 20*37c9f0a6Schristos * Wasabi Systems, Inc. 21*37c9f0a6Schristos * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22*37c9f0a6Schristos * or promote products derived from this software without specific prior 23*37c9f0a6Schristos * written permission. 24*37c9f0a6Schristos * 25*37c9f0a6Schristos * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26*37c9f0a6Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27*37c9f0a6Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28*37c9f0a6Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29*37c9f0a6Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30*37c9f0a6Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31*37c9f0a6Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32*37c9f0a6Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33*37c9f0a6Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34*37c9f0a6Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35*37c9f0a6Schristos * POSSIBILITY OF SUCH DAMAGE. 36*37c9f0a6Schristos */ 37*37c9f0a6Schristos 38*37c9f0a6Schristos 39*37c9f0a6Schristos 40*37c9f0a6Schristos#include <machine/asm.h> 41*37c9f0a6Schristos#if defined(LIBC_SCCS) && !defined(lint) 42*37c9f0a6Schristos RCSID("$NetBSD: strlen.S,v 1.1 2005/12/20 19:28:50 christos Exp $") 43*37c9f0a6Schristos#endif /* LIBC_SCCS and not lint */ 44*37c9f0a6Schristos 45*37c9f0a6Schristos/* The algorithm here uses the following techniques: 46*37c9f0a6Schristos * 47*37c9f0a6Schristos * 1) Given a word 'x', we can test to see if it contains any 0 bytes 48*37c9f0a6Schristos * by subtracting 0x01010101, and seeing if any of the high bits of each 49*37c9f0a6Schristos * byte changed from 0 to 1. This works because the least significant 50*37c9f0a6Schristos * 0 byte must have had no incoming carry (otherwise it's not the least 51*37c9f0a6Schristos * significant), so it is 0x00 - 0x01 == 0xff. For all other 52*37c9f0a6Schristos * byte values, either they have the high bit set initially, or when 53*37c9f0a6Schristos * 1 is subtracted you get a value in the range 0x00-0x7f, none of which 54*37c9f0a6Schristos * have their high bit set. The expression here is 55*37c9f0a6Schristos * (x + 0xfefefeff) & ~(x | 0x7f7f7f7f), which gives 0x00000000 when 56*37c9f0a6Schristos * there were no 0x00 bytes in the word. 57*37c9f0a6Schristos * 58*37c9f0a6Schristos * 2) Now just hunt for the first byte that's 0x00 in 'x'. 59*37c9f0a6Schristos * 60*37c9f0a6Schristos * This is from the book 'The PowerPC Compiler Writer's Guide', 61*37c9f0a6Schristos * by Steve Hoxey, Faraydon Karim, Bill Hay and Hank Warren. 62*37c9f0a6Schristos */ 63*37c9f0a6Schristos 64*37c9f0a6SchristosENTRY(strlen) 65*37c9f0a6Schristos /* 66*37c9f0a6Schristos * Calculate address for and load the first xword. 67*37c9f0a6Schristos */ 68*37c9f0a6Schristos andn %o0, 0x7, %o1 69*37c9f0a6Schristos ldx [%o1], %g1 70*37c9f0a6Schristos 71*37c9f0a6Schristos /* 72*37c9f0a6Schristos * Now prepare some constants while the data arrives... 73*37c9f0a6Schristos */ 74*37c9f0a6Schristos sethi %hi(0xfefefefe), %o3 75*37c9f0a6Schristos sethi %hi(0x7f7f7f7f), %o2 76*37c9f0a6Schristos 77*37c9f0a6Schristos or %o3, %lo(0xfefefefe), %o3 78*37c9f0a6Schristos or %o2, %lo(0x7f7f7f7f), %o2 79*37c9f0a6Schristos 80*37c9f0a6Schristos sllx %o3, 32, %o5 81*37c9f0a6Schristos andcc %o0, 0x7, %g5 ! Hoisted from below to fill a slot 82*37c9f0a6Schristos 83*37c9f0a6Schristos sllx %o2, 32, %o4 84*37c9f0a6Schristos or %o3, %o5, %o3 85*37c9f0a6Schristos 86*37c9f0a6Schristos sll %g5, 3, %g5 ! Convert to bytes. hoisted 87*37c9f0a6Schristos or %o2, %o4, %o2 88*37c9f0a6Schristos 89*37c9f0a6Schristos inc %o3 90*37c9f0a6Schristos neg %g5 ! hoisted 91*37c9f0a6Schristos 92*37c9f0a6Schristos /* 93*37c9f0a6Schristos * Mask off the leading bits: 94*37c9f0a6Schristos * 95*37c9f0a6Schristos * if (ptr & 0x7) 96*37c9f0a6Schristos * mask = -1 << (64 - ((ptr & 0x7) << 3)); 97*37c9f0a6Schristos */ 98*37c9f0a6Schristos 99*37c9f0a6Schristos! andcc %o0, 0x7, %g5 ! Hoisted above 100*37c9f0a6Schristos bz,pt %icc, 0f 101*37c9f0a6Schristos 102*37c9f0a6Schristos 103*37c9f0a6Schristos! sll %g5, 3, %g5 ! Convert to bytes. Also hoisted 104*37c9f0a6Schristos 105*37c9f0a6Schristos! neg %g5 ! Hoisted 106*37c9f0a6Schristos 107*37c9f0a6Schristos add %g5, 64, %g5 108*37c9f0a6Schristos mov -1, %o4 109*37c9f0a6Schristos 110*37c9f0a6Schristos sllx %o4, %g5, %o4 111*37c9f0a6Schristos 112*37c9f0a6Schristos or %o4, %g1, %g1 ! Make leading bytes != 0 113*37c9f0a6Schristos 114*37c9f0a6Schristos0: 115*37c9f0a6Schristos or %g1, %o2, %o5 ! Do step 1 -- use or/andn instead of nor/and 116*37c9f0a6Schristos add %g1, %o3, %g5 117*37c9f0a6Schristos 118*37c9f0a6Schristos inc 8, %o1 ! Point to next word 119*37c9f0a6Schristos andncc %g5, %o5, %g0 120*37c9f0a6Schristos bz,a,pt %xcc, 0b 121*37c9f0a6Schristos ldx [%o1], %g1 122*37c9f0a6Schristos 123*37c9f0a6Schristos mov -1, %o4 124*37c9f0a6Schristos dec 8, %o1 125*37c9f0a6Schristos 126*37c9f0a6Schristos sllx %o4, 64-8, %o5 127*37c9f0a6Schristos 128*37c9f0a6Schristos btst %g1, %o5 ! Check high byte 129*37c9f0a6Schristos bz %xcc,0f 130*37c9f0a6Schristos srlx %o5, 8, %o5 131*37c9f0a6Schristos 132*37c9f0a6Schristos inc %o1 133*37c9f0a6Schristos btst %g1, %o5 ! Check 2nd byte 134*37c9f0a6Schristos bz %xcc,0f 135*37c9f0a6Schristos srlx %o5, 8, %o5 136*37c9f0a6Schristos 137*37c9f0a6Schristos inc %o1 138*37c9f0a6Schristos btst %g1, %o5 ! Check 3rd byte 139*37c9f0a6Schristos bz %xcc,0f 140*37c9f0a6Schristos srlx %o5, 8, %o5 141*37c9f0a6Schristos 142*37c9f0a6Schristos inc %o1 143*37c9f0a6Schristos btst %g1, %o5 ! Check 4th byte 144*37c9f0a6Schristos bz %xcc,0f 145*37c9f0a6Schristos srlx %o5, 8, %o5 146*37c9f0a6Schristos 147*37c9f0a6Schristos inc %o1 148*37c9f0a6Schristos btst %g1, %o5 ! Check 5th byte 149*37c9f0a6Schristos bz %xcc,0f 150*37c9f0a6Schristos srlx %o5, 8, %o5 151*37c9f0a6Schristos 152*37c9f0a6Schristos inc %o1 153*37c9f0a6Schristos btst %g1, %o5 ! Check 6th byte 154*37c9f0a6Schristos bz %xcc,0f 155*37c9f0a6Schristos srlx %o5, 8, %o5 156*37c9f0a6Schristos 157*37c9f0a6Schristos inc %o1 158*37c9f0a6Schristos btst %g1, %o5 ! Check 7th byte 159*37c9f0a6Schristos bz %xcc,0f 160*37c9f0a6Schristos nop 161*37c9f0a6Schristos 162*37c9f0a6Schristos inc %o1 163*37c9f0a6Schristos0: 164*37c9f0a6Schristos retl 165*37c9f0a6Schristos sub %o1, %o0, %o0 ! return length (ptr - (origptr+1)) 166