fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / newlib / libc / machine / i960 / strcpy_ca.S
blobdbb944455a8c98347fde2b0a864fc91ad20cbf66
1 /*******************************************************************************
2  * 
3  * Copyright (c) 1993 Intel Corporation
4  * 
5  * Intel hereby grants you permission to copy, modify, and distribute this
6  * software and its documentation.  Intel grants this permission provided
7  * that the above copyright notice appears in all copies and that both the
8  * copyright notice and this permission notice appear in supporting
9  * documentation.  In addition, Intel grants this permission provided that
10  * you prominently mark as "not part of the original" any modifications
11  * made to this software or documentation, and that the name of Intel
12  * Corporation not be used in advertising or publicity pertaining to
13  * distribution of the software or the documentation without specific,
14  * written prior permission.
15  * 
16  * Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR
17  * IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY
18  * OR FITNESS FOR A PARTICULAR PURPOSE.  Intel makes no guarantee or
19  * representations regarding the use of, or the results of the use of,
20  * the software and documentation in terms of correctness, accuracy,
21  * reliability, currentness, or otherwise; and you rely on the software,
22  * documentation and results solely at your own risk.
23  *
24  * IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS,
25  * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES
26  * OF ANY KIND.  IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM
27  * PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER.
28  * 
29  ******************************************************************************/
31         .file "strcp_ca.s"
32 #ifdef  __PIC
33         .pic
34 #endif
35 #ifdef  __PID
36         .pid
37 #endif
39  * (c) copyright 1988,1993 Intel Corp., all rights reserved
40  */
43         procedure strcpy  (optimized assembler version for the CA)     
45         dest_addr = strcpy (dest_addr, src_addr)
47         copy the null terminated string pointed to by src_addr to 
48         the string space pointed to by dest_addr.  Return the original
49         dest_addr.
51         This routine will fail if the source and destination string
52         overlap (in particular, if the end of the source is overlapped
53         by the beginning of the destination).  The behavior is undefined.
54         This is acceptable according to the draft C standard.
56         Undefined behavior will also occur if the end of the source string
57         (i.e. the terminating null byte) is in the last word of the program's
58         allocated memory space.  This is so because, in several cases, strcpy
59         will fetch ahead one word.  Disallowing the fetch ahead would impose
60         a severe performance penalty.
62         This program handles five cases:
64         1) both arguments start on a word boundary
65         2) neither are word aligned, but they are offset by the same amount
66         3) source is word aligned, destination is not
67         4) destination is word aligned, source is not
68         5) neither is word aligned, and they are offset by differing amounts
70         At the time of this writing, only g0 thru g7 and g13 are available 
71         for use in this leafproc;  other registers would have to be saved and
72         restored.  These nine registers, plus tricky use of g14 are sufficient
73         to implement the routine.  The registers are used as follows:
75         g0  original dest ptr;  not modified, so that it may be returned.
76         g1  src ptr;  shift count
77         g2  dest ptr;  4 bytes of src
78         g3  src ptr (word aligned)
79         g4  dest ptr (word aligned)
80         g5  0xff  --  byte extraction mask
81         g6  lsw of double word for extraction of 4 bytes (little endian)
82             msw of double word for extraction of 4 bytes (big endian)
83         g7  msw of double word for extraction of 4 bytes (little endian)
84             lsw of double word for extraction of 4 bytes (big endian)
85         g13 return address
86         g14 byte extracted.  When reaches null byte, which is zero, we will
87             be in conformance with register conventions, and can return to
88             the caller with a clear conscience.
90         procedure strcat
92         dest_addr = strcat (dest_addr, src_addr)
94         Appends the string pointed to by src_addr to the string pointed
95         to by dest_addr.  The first character of the source string is
96         copied to the location initially occupied by the trailing null
97         byte of the destination string.  Thereafter, characters are copied
98         from the source to the destination up thru the null byte that
99         trails the source string.
102 #if __i960_BIG_ENDIAN__
103 #define MSW g6
104 #define LSW g7
105 #else
106 #define LSW g6
107 #define MSW g7
108 #endif
110         .globl  _strcpy, _strcat
111         .globl  __strcpy, __strcat
112         .leafproc       _strcpy, __strcpy
113         .leafproc       _strcat, __strcat
114         .align  2
115 _strcat:
116 #ifndef __PIC
117         lda     Lrett,g14
118 #else
119         lda     Lrett-(.+8)(ip),g14
120 #endif
121 __strcat:
122         notand  g0,3,g4         # extract word addr of start of dest
123         lda     (g14),g13       # preserve return address
124         and     g0,3,LSW        # extract byte offset of dest
125         ld      (g4),MSW        # fetch word containing at least first byte
126         shlo    3,LSW,g14       # get shift count for making mask for first word
127         subi    1,0,LSW         # mask initially all ones
128 #if __i960_BIG_ENDIAN__
129         shro    g14,LSW,LSW     # get mask for bytes needed from first word
130         lda     0xff000000,g5   # byte extraction mask
131 #else
132         shlo    g14,LSW,LSW     # get mask for bytes needed from first word
133         lda     0xff,g5         # byte extraction mask
134 #endif
135         notor   MSW,LSW,MSW     # set unneeded bytes to all ones
136 Lsearch_for_word_with_null:
137         scanbyte 0,MSW          # check for null byte
138         lda     4(g4),g4        # post-increment dest word pointer
139         mov     MSW,LSW         # keep a copy of current word
140         ld      (g4),MSW        # fetch next word of dest
141         bno.t   Lsearch_for_word_with_null      # branch if null not found yet
142         and     g5,LSW,g14      # extract byte
143         cmpo    0,g14           # branch if null is first byte of word
144         subo    4,g4,g4         # move dest word ptr back to word with null
145         notand  g1,3,g3         # extract word addr of start of src
146         lda     (g4),g2         # set dest byte ptr to 1st byte of word w/ null
147         be.f    Lcase_14
148 Lsearch_for_null:
149 #if __i960_BIG_ENDIAN__
150         shro    8,g5,g5         # move mask down to next byte
151 #else
152         shlo    8,g5,g5         # move mask up to next byte
153 #endif
154         lda     1(g2),g2        # move dest byte ptr to next byte
155         and     g5,LSW,g14      # extract byte
156         cmpobne.t 0,g14,Lsearch_for_null        # branch if null is not yet found
157         lda     0xff,g5         # byte extraction mask
158         b       Lcase_235.a
160         
161 _strcpy:
162 #ifndef __PIC
163         lda     Lrett,g14
164 #else
165         lda     Lrett-(.+8)(ip),g14
166 #endif
167 __strcpy:
168         notand  g0,3,g4         # extract word addr of start of dest
169         lda     (g14),g13       # preserve return address
170         cmpo    g0,g4           # check alignment of dest
171         lda     0xff,g5         # load mask for byte extraction
172         notand  g1,3,g3         # extract word addr of start of src
173         bne.f   Lcase_235       # branch if dest is NOT word aligned
175 Lcase_14:
176         cmpo    g3,g1           # check alignment of src
177         ld      (g3),LSW        # fetch word containing at least first byte
178         shlo    3,g1,g1         # compute shift count
179         lda     4(g3),g3        # advance src word addr
180 #if __i960_BIG_ENDIAN__
181         lda     0xff,g5         # byte extraction mask
182 #endif
183         bne.f   Lcase_4         # branch if src is NOT word aligned
185 Lcase_1:                                # src and dest are word aligned
186         subo    4,g4,g4         # store is pre-incrementing;  back up dest addr
187 Lcase_1_wloop:                  # word copying loop
188         scanbyte 0,LSW          # check for null byte in src word
189         lda     (LSW),g2        # keep a copy of the src word
190         addo    4,g4,g4         # pre-increment dest addr
191         ld      (g3),LSW        # pre-fetch next word of src
192         addo    4,g3,g3         # post-increment src addr
193         bo.f    Lcase_1_cloop   # branch if word contains null byte
194         st      g2,(g4)         # store word in dest string
195         b       Lcase_1_wloop
197 Lcase_3_cloop:
198 Lcase_1_cloop:                  # character copying loop
199 #if __i960_BIG_ENDIAN__
200         rotate  8,g2,g2         # move next byte into position for extraction
201         and     g5,g2,g14       # extract next char
202 #else
203         and     g5,g2,g14       # extract next char
204         shro    8,g2,g2         # move next byte into position for extraction
205 #endif
206         cmpo    0,g14           # check for null byte
207         stob    g14,(g4)        # store the byte in dest
208         lda     1(g4),g4        # post-increment dest byte addr
209         bne.t   Lcase_1_cloop   # branch if null not reached
211 Lexit_code:
212         bx      (g13)           # g0 = addr of dest;  g14 = 0
213 Lrett:
214         ret
216 Lcase_3:                                # src is word aligned; dest is not
217         addo    4,g4,g4         # move dest word ptr to first word boundary
218         mov     LSW,MSW         # make copy of first word of src
219         lda     0,g1            # initialize shift count to zero
221 Lcase_25:
222 Lcase_3_cloop_at_start:         # character copying loop for start of dest str
223 #if __i960_BIG_ENDIAN__
224         rotate  8,MSW,MSW       # move next byte into position for extraction
225         and     g5,MSW,g14      # extract next char
226 #else
227         and     g5,MSW,g14      # extract next char
228         shro    8,MSW,MSW       # move next byte into position for extraction
229 #endif
230         cmpo    0,g14           # check for null byte
231         stob    g14,(g2)        # store the byte in dest
232         lda     1(g2),g2        # post-increment dest ptr
233         be.f    Lexit_code      # branch if null byte reached
234         cmpo    g2,g4           # have we reached word boundary in dest?
235         lda     8(g1),g1        # augment the shift counter
236         bne.t   Lcase_3_cloop_at_start
238 Lcase_4:
239         ld      (g3),MSW        # fetch msw of operand for double shift
240 #if __i960_BIG_ENDIAN__
241         subo    g1,0,g1         # Adjust shift count for big endian.
242 #endif
244 Lcase_3_wloop:
245         eshro   g1,g6,g2        # extract 4 bytes of src
246         lda     4(g3),g3        # post-increment src word addr
247         scanbyte 0,g2           # check for null byte
248         lda     (MSW),LSW       # move msw to lsw
249         ld      (g3),MSW        # pre-fetch msw of operand for double shift
250         bo.f    Lcase_3_cloop   # branch if word contains null byte
251         st      g2,(g4)         # store 4 bytes to dest
252         addo    4,g4,g4         # post-increment dest ptr
253         b       Lcase_3_wloop
255 Lcase_235:
256         lda     (g0),g2         # copy dest ptr 
257 Lcase_235.a:
258         cmpo    g3,g1           # check alignment of src
259         ld      (g3),LSW        # fetch word containing at least first byte
260         and     3,g1,g14        # compute shift count
261         lda     4(g3),g3        # advance src word addr
262         shlo    3,g14,g1        
263         be.t    Lcase_3         # branch if dest is word aligned
264         or      g4,g14,g14      # is src earlier in word, later, or sync w/ dst
265         ld      (g3),MSW        # pre-fetch second half
266         cmpo    g2,g14          # < indicates first word of dest has more bytes
267         lda     4(g4),g4        # move dest word addr to first word boundary
268                                 /* than first word of source. */
269 #if __i960_BIG_ENDIAN__
270         subo    g1,0,g14        # Adjust shift count for big endian.
271         eshro   g14,g6,g14      # extract four bytes
272         bge.f   1f
273 #else
274         eshro   g1,g6,g14       # extract four bytes
275         bg.f    1f
276 #endif
277         mov     MSW,LSW
278         lda     4(g3),g3        # move src word addr to second word boundary
280         mov     g14,MSW
281         b       Lcase_25
283 /* end of strcpy */