1/* 2 * (c) Copyright 1986 HEWLETT-PACKARD COMPANY 3 * 4 * To anyone who acknowledges that this file is provided "AS IS" 5 * without any express or implied warranty: 6 * permission to use, copy, modify, and distribute this file 7 * for any purpose is hereby granted without fee, provided that 8 * the above copyright notice and this notice appears in all 9 * copies, and that the name of Hewlett-Packard Company not be 10 * used in advertising or publicity pertaining to distribution 11 * of the software without specific, written prior permission. 12 * Hewlett-Packard Company makes no representations about the 13 * suitability of this software for any purpose. 14 */ 15 16/* HPUX_ID = "@(#) $Revision$" */ 17/* strlen(s): Return length of string s */ 18 19#include <picolibc.h> 20 21#define start arg0 22#define end ret0 23#define tmp1 arg1 24#define tmp2 arg2 25 26#include "DEFS.h" 27 28ENTRY(strlen) 29 movb,=,n start,end,$null_ptr 30 depi 0,31,2,end 31 comb,<> start,end,$not_aligned 32 ldws,ma 4(end),tmp1 33 comib,tr 0,0,$loop /* avoid INDIGO two register interlock */ 34 uxor,nbz 0,tmp1,0 35$not_aligned: 36 /* 37 ; Tricky code. The problem is that the value of of the word 38 ; including the start of the string has some garbage bytes that 39 ; may be 0. We don't want them to stop the string scan. So 40 ; we make those bytes non-zero (and any old non-zero value 41 ; will do). Notice that the end pointer has been rounded 42 ; down to a word boundary, and then incremented to the next 43 ; word by the time we get here. Therefore, (start-end) has 44 ; one of the values (-3, -2, or -1). Use uaddcm to do the 45 ; subtraction (instead of sub), and the result will be 46 ; (-4, -3, or -2). Multiply this by 8, and put into the 47 ; shift register (which truncates to the last 5 bits) and 48 ; the value will be (0, 8, or 16). Use this as a bit position, 49 ; and drop a mask down into tmp1. All the garbage bytes will 50 ; have at least 1 bit affected by the vdepi, so all the garbage 51 ; in this first word will be non-zero garbage. 52 */ 53 uaddcm start,end,tmp2 /* tmp2 <- { -4, -3, -2 } */ 54 sh3add tmp2,0,tmp2 /* tmp2 <- { -32, -24, -16 } */ 55 mtsar tmp2 /* sar <- { 0, 8, 16 } */ 56 vdepi -1,32,tmp1 57 uxor,nbz 0,tmp1,0 58$loop: 59 b,n $end_loop 60 ldws,ma 4(end),tmp1 61 comib,tr 0,0,$loop /* avoid INDIGO two register interlock */ 62 uxor,nbz 0,tmp1,0 63$end_loop: 64 /* adjust the end pointer to one past the end of the string */ 65 extru,<> tmp1,7,8,0 66 addib,tr,n -3,end,$out 67 extru,<> tmp1,15,8,0 68 addib,tr,n -2,end,$out 69 extru,<> tmp1,23,8,0 70 addi -1,end,end 71$out: 72 bv 0(rp) 73 /* 74 ; tricky code. the end pointer is just beyond the terminating 75 ; null byte, so the length is (end-start-1). use uaddcm 76 ; to do this in 1 instruction 77 */ 78 uaddcm end,start,ret0 79 80$null_ptr: 81EXIT(strlen) 82