source: trunk/libs/newlib/src/newlib/libc/machine/i960/strcpy_ca.S @ 690

Last change on this file since 690 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 9.7 KB
Line 
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 ******************************************************************************/
30
31        .file "strcp_ca.s"
32#ifdef  __PIC
33        .pic
34#endif
35#ifdef  __PID
36        .pid
37#endif
38/*
39 * (c) copyright 1988,1993 Intel Corp., all rights reserved
40 */
41
42/*
43        procedure strcpy  (optimized assembler version for the CA)     
44
45        dest_addr = strcpy (dest_addr, src_addr)
46
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.
50
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.
55
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.
61
62        This program handles five cases:
63
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
69
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:
74
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.
89
90        procedure strcat
91
92        dest_addr = strcat (dest_addr, src_addr)
93
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.
100*/
101
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
109
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
136Lsearch_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
148Lsearch_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
159
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
174
175Lcase_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
184
185Lcase_1:                                # src and dest are word aligned
186        subo    4,g4,g4         # store is pre-incrementing;  back up dest addr
187Lcase_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
196
197Lcase_3_cloop:
198Lcase_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
210
211Lexit_code:
212        bx      (g13)           # g0 = addr of dest;  g14 = 0
213Lrett:
214        ret
215
216Lcase_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
220
221Lcase_25:
222Lcase_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
237
238Lcase_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
243
244Lcase_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
254
255Lcase_235:
256        lda     (g0),g2         # copy dest ptr
257Lcase_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
2791:
280        mov     g14,MSW
281        b       Lcase_25
282
283/* end of strcpy */
284
Note: See TracBrowser for help on using the repository browser.