fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / newlib / libc / machine / hppa / strlen.S
blob301ead5c50b43fa1d3bdd5da93a3f364273eca46
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  */
16 /* HPUX_ID = "@(#) $Revision: 1.1 $" */
17 /* strlen(s): Return length of string s */
19 #define start   arg0
20 #define end     ret0
21 #define tmp1    arg1
22 #define tmp2    arg2
24 #include "DEFS.h"
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
78 $null_ptr:
79 EXIT(strlen)