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 | #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) |
---|