fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / newlib / libc / machine / hppa / strcat.S
blob8424a4fb0ca0df053c2d6c0b73c22c966420e0f0
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 $   */
18  * strcat(s1, s2)
19  *
20  * Concatenate s2 on the end of s1.  S1's space must be large enough.
21  * Return s1.
22  */
23 #include "DEFS.h"
25 #define d_addr  r26
26 #define s_addr  r25
27 #define tmp6    r24
28 #define tmp1    r19
29 #define tmp2    r20
30 #define tmp3    r21
31 #define tmp4    r22
32 #define tmp5    arg3
33 #define save    r1
36 ENTRY(strcat)
38         comb,=          r0,s_addr,done  /* quit if s2=NULL */
39         copy      d_addr,ret0          /* The return value is the value of d_addr. DELAY SLOT*/
41 /* First look for end of s1 (d_addr) */
43         extru       d_addr,31,2,tmp1   /* Extract the low two bits of the dest address. */
44         combt,=         tmp1,r0,dont_mask
45         dep             0,31,2,d_addr   /*set word alignment */
46         ldwm            4(d_addr),tmp2
47         sh3add          tmp1,r0,save    /* build mask based on tmp1 */
48         mtctl           save,11
49         zvdepi          -2,32,save
50         or              save,tmp2,tmp2
51         uxor,nbz        tmp2,r0,save
52 search:
53         b,n             found_end       /* nullified under uxor conditions above and below */
54 dont_mask:
55         ldwm            4(d_addr),tmp2
56         comib,tr        r0,r0,search
57         uxor,nbz        tmp2,r0,save
59 found_end:                              /* at this point d_addr points to word */
60         extru,<>        save,7,8,r0     /* following word with null */
61         addib,tr,n      -4,d_addr,begin_copy    /*set d_addr to end of s1 */
62         extru,<>        save,15,8,r0
63         addib,tr,n      -3,d_addr,begin_copy
64         extru,<>        save,23,8,r0
65         addi            -1,d_addr,d_addr
66         addi            -1,d_addr,d_addr
69 begin_copy:
71         extru       s_addr,31,2,tmp1   /* Extract the low two bits of the source address. */
72         extru       d_addr,31,2,tmp6   /* Extract the low two bits of the destination address. */
73         sub,=       tmp6,tmp1,tmp3     /* Compute the shift quantity and don't branch if tmp6=tmp1. */
74         b           not_aligned        /* Not_aligned says that shifts Will be needed. */
75         dep         0,31,2,s_addr      /* Compute the word address of the source.  DELAY SLOT. */
76 /* aligned */
78         combt,=         tmp6,r0,skip_mask
79         ldwm            4(0,s_addr),tmp1   /* tmp1 = *s_addr   s_addr += 4 (DELAY SLOT) */
80         sh3add          tmp6,r0,save
81         mtctl           save,r11
82         zvdepi          -2,32,save
83         or              save,tmp1,tmp1
84         uxor,nbz        tmp1,r0,save
85         b,n             first_null      /* special case: null in first word */
86         b,n             skip_mask2
88 chunks:
89         b,n             null_found      /* delay slot for uxor below */
91 skip_mask2:
92         stbys,b,m       tmp1,4(d_addr)
93         ldwm            4(s_addr),tmp1
94 skip_mask:
95         comib,tr        0,0,chunks
96         uxor,nbz        tmp1,r0,save
98 /* Begin non_aligned code.  */
100 not_aligned:
101         sh3add,>=       tmp3,r0,tmp4        /* compute the shift amt.and skip load if tmp6 > tmp1. */
102         ldwm            4(0,s_addr),tmp1    /* load up the first word from the source. tmp1 = *s_addr++ */
103         ldwm            4(0,s_addr),tmp2    /* get either first or second word from source.  */
104         combt,=         tmp6,r0,chunk2      /* don't mask if whole word is valid */
105         mtctl           tmp4,11             /* load the shift count into cr11 = shift count register. */
106         vshd            tmp1,tmp2,tmp3      /* position data !  (delay slot) */
107         sh3add          tmp6,r0,save        /* setup r1 */
108         mtctl           save,r11            /* set-up cr11 for mask */
109         zvdepi          -2,32,save
110         or              save, tmp3, tmp3
111         uxor,nbz        tmp3,r0,save
112         b,n             first_null2
113         b               did_mask
114         mtctl           tmp4,11            /* re-load the shift count into cr11 */
116 chunk2:
117         vshd            tmp1,tmp2,tmp3
118         uxor,nbz        tmp3, r0, save
119         b,n             null_found
120 did_mask:
121         stbys,b,m       tmp3,4(0,d_addr)    /* store !  */
123         ldwm            4(0,s_addr),tmp1    /* get next word !  */
124         vshd            tmp2,tmp1,tmp3      /* position data !  */
125         uxor,nbz        tmp3, r0, save
126         b,n             null_found
127         stwm            tmp3,4(d_addr)
128         comib,tr        0,0,chunk2
129         ldwm            4(s_addr),tmp2
132 null_found:                             /* adjust d_addr and store final word */
134         extru,<>        save,7,8,r0
135         addib,tr,n      1,d_addr,store_final
136         extru,<>        save,15,8,r0
137         addib,tr,n      2,d_addr,store_final
138         extru,<>        save,23,8,r0
139         addib,tr        3,d_addr,store_final2
140         bv              0(r2)
141         stw             save,0(d_addr)
143 store_final:
144         bv              0(r2)
145 store_final2:
146         stbys,e         save,0(d_addr)  /* delay slot */
148 first_null:                     /* null found in first word of aligned (wrt d_addr) */
149         addi            -4,s_addr,s_addr
150         ldbx            tmp6(s_addr),tmp4
151         add             tmp6,s_addr,s_addr
152         comib,=         0,tmp4,done
153         stbs,ma         tmp4,1(d_addr)
154         ldbs            1(s_addr),tmp4
155         comib,=         0,tmp4,done
156         stbs,ma         tmp4,1(d_addr)
157         bv              0(r2)           /* done */
158         stbs            0,0(d_addr)
160 first_null2:    /* null found in first word of non-aligned (wrt d_addr) */
161         addibt,=        -1,tmp6,check3  /* check last 3 bytes of word */
162         extru           save,15,8,tmp4
163         addibt,=,n      -1,tmp6,check2  /* check last 2 bytes */
164         bv              0(r2)
165         stbys,b         save, 0(d_addr)
167 check3:
168         combt,=         tmp4,r0,done
169         stbs,ma         tmp4,1(d_addr)
170 check2:
171         extru,<>        save,23,8,tmp4
172         bv              0(r2)
173         stbs,ma         tmp4,1(d_addr)
174         bv              0(r2)
175         stbs            r0,0(d_addr)
177 done:
178 EXIT(strcat)