1 |
39 |
lampret |
/*
|
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 |
56 |
joel |
/* HPUX_ID = "@(#) $Revision: 1.1.1.2 $" */
|
17 |
39 |
lampret |
/* strlen(s): Return length of string s */
|
18 |
|
|
|
19 |
|
|
#define start arg0
|
20 |
|
|
#define end ret0
|
21 |
|
|
#define tmp1 arg1
|
22 |
|
|
#define tmp2 arg2
|
23 |
|
|
|
24 |
|
|
#include "DEFS.h"
|
25 |
|
|
|
26 |
|
|
ENTRY(strlen)
|
27 |
|
|
movb,=,n start,end,$null_ptr
|
28 |
|
|
depi 0,31,2,end
|
29 |
|
|
comb,<> start,end,$not_aligned
|
30 |
|
|
ldws,ma 4(end),tmp1
|
31 |
|
|
comib,tr 0,0,$loop /* avoid INDIGO two register interlock */
|
32 |
|
|
uxor,nbz 0,tmp1,0
|
33 |
|
|
$not_aligned:
|
34 |
|
|
/*
|
35 |
|
|
; Tricky code. The problem is that the value of of the word
|
36 |
|
|
; including the start of the string has some garbage bytes that
|
37 |
|
|
; may be 0. We don't want them to stop the string scan. So
|
38 |
|
|
; we make those bytes non-zero (and any old non-zero value
|
39 |
|
|
; will do). Notice that the end pointer has been rounded
|
40 |
|
|
; down to a word boundary, and then incremented to the next
|
41 |
|
|
; word by the time we get here. Therefore, (start-end) has
|
42 |
|
|
; one of the values (-3, -2, or -1). Use uaddcm to do the
|
43 |
|
|
; subtraction (instead of sub), and the result will be
|
44 |
|
|
; (-4, -3, or -2). Multiply this by 8, and put into the
|
45 |
|
|
; shift register (which truncates to the last 5 bits) and
|
46 |
|
|
; the value will be (0, 8, or 16). Use this as a bit position,
|
47 |
|
|
; and drop a mask down into tmp1. All the garbage bytes will
|
48 |
|
|
; have at least 1 bit affected by the vdepi, so all the garbage
|
49 |
|
|
; in this first word will be non-zero garbage.
|
50 |
|
|
*/
|
51 |
|
|
uaddcm start,end,tmp2 /* tmp2 <- { -4, -3, -2 } */
|
52 |
|
|
sh3add tmp2,0,tmp2 /* tmp2 <- { -32, -24, -16 } */
|
53 |
|
|
mtsar tmp2 /* sar <- { 0, 8, 16 } */
|
54 |
|
|
vdepi -1,32,tmp1
|
55 |
|
|
uxor,nbz 0,tmp1,0
|
56 |
|
|
$loop:
|
57 |
|
|
b,n $end_loop
|
58 |
|
|
ldws,ma 4(end),tmp1
|
59 |
|
|
comib,tr 0,0,$loop /* avoid INDIGO two register interlock */
|
60 |
|
|
uxor,nbz 0,tmp1,0
|
61 |
|
|
$end_loop:
|
62 |
|
|
/* adjust the end pointer to one past the end of the string */
|
63 |
|
|
extru,<> tmp1,7,8,0
|
64 |
|
|
addib,tr,n -3,end,$out
|
65 |
|
|
extru,<> tmp1,15,8,0
|
66 |
|
|
addib,tr,n -2,end,$out
|
67 |
|
|
extru,<> tmp1,23,8,0
|
68 |
|
|
addi -1,end,end
|
69 |
|
|
$out:
|
70 |
|
|
bv 0(rp)
|
71 |
|
|
/*
|
72 |
|
|
; tricky code. the end pointer is just beyond the terminating
|
73 |
|
|
; null byte, so the length is (end-start-1). use uaddcm
|
74 |
|
|
; to do this in 1 instruction
|
75 |
|
|
*/
|
76 |
|
|
uaddcm end,start,ret0
|
77 |
|
|
|
78 |
|
|
$null_ptr:
|
79 |
|
|
EXIT(strlen)
|