OSDN Git Service

Chris Zankel writes:
[uclinux-h8/uClibc.git] / libc / string / xtensa / strcpy.S
1 /* Optimized strcpy for Xtensa.
2    Copyright (C) 2001, 2007 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
18    Boston, MA 02110-1301, USA.  */
19
20 #include "../../sysdeps/linux/xtensa/sysdep.h"
21 #include <bits/xtensa-config.h>
22
23 #ifdef __XTENSA_EB__
24 #define MASK0 0xff000000
25 #define MASK1 0x00ff0000
26 #define MASK2 0x0000ff00
27 #define MASK3 0x000000ff
28 #else
29 #define MASK0 0x000000ff
30 #define MASK1 0x0000ff00
31 #define MASK2 0x00ff0000
32 #define MASK3 0xff000000
33 #endif
34
35         .text
36 ENTRY (strcpy)
37         /* a2 = dst, a3 = src */
38
39         mov     a10, a2         // leave dst in return value register
40         movi    a4, MASK0
41         movi    a5, MASK1
42         movi    a6, MASK2
43         movi    a7, MASK3
44         bbsi.l  a3, 0, .Lsrc1mod2
45         bbsi.l  a3, 1, .Lsrc2mod4
46 .Lsrcaligned:
47
48         /* Check if the destination is aligned.  */
49         movi    a8, 3
50         bnone   a10, a8, .Laligned
51
52         j       .Ldstunaligned
53
54 .Lsrc1mod2: // src address is odd
55         l8ui    a8, a3, 0       // get byte 0
56         addi    a3, a3, 1       // advance src pointer
57         s8i     a8, a10, 0      // store byte 0
58         beqz    a8, 1f          // if byte 0 is zero
59         addi    a10, a10, 1     // advance dst pointer
60         bbci.l  a3, 1, .Lsrcaligned // if src is now word-aligned
61
62 .Lsrc2mod4: // src address is 2 mod 4
63         l8ui    a8, a3, 0       // get byte 0
64         /* 1-cycle interlock */
65         s8i     a8, a10, 0      // store byte 0
66         beqz    a8, 1f          // if byte 0 is zero
67         l8ui    a8, a3, 1       // get byte 0
68         addi    a3, a3, 2       // advance src pointer
69         s8i     a8, a10, 1      // store byte 0
70         addi    a10, a10, 2     // advance dst pointer
71         bnez    a8, .Lsrcaligned
72 1:      retw
73
74
75 /* dst is word-aligned; src is word-aligned.  */
76
77         .align  4
78 #if XCHAL_HAVE_LOOPS
79         /* (2 mod 4) alignment for loop instruction */
80 .Laligned:
81         _movi.n a8, 0           // set up for the maximum loop count
82         loop    a8, .Lz3        // loop forever (almost anyway)
83         l32i    a8, a3, 0       // get word from src
84         addi    a3, a3, 4       // advance src pointer
85         bnone   a8, a4, .Lz0    // if byte 0 is zero
86         bnone   a8, a5, .Lz1    // if byte 1 is zero
87         bnone   a8, a6, .Lz2    // if byte 2 is zero
88         s32i    a8, a10, 0      // store word to dst
89         bnone   a8, a7, .Lz3    // if byte 3 is zero
90         addi    a10, a10, 4     // advance dst pointer
91
92 #else /* !XCHAL_HAVE_LOOPS */
93
94 1:      addi    a10, a10, 4     // advance dst pointer
95 .Laligned:
96         l32i    a8, a3, 0       // get word from src
97         addi    a3, a3, 4       // advance src pointer
98         bnone   a8, a4, .Lz0    // if byte 0 is zero
99         bnone   a8, a5, .Lz1    // if byte 1 is zero
100         bnone   a8, a6, .Lz2    // if byte 2 is zero
101         s32i    a8, a10, 0      // store word to dst
102         bany    a8, a7, 1b      // if byte 3 is zero
103 #endif /* !XCHAL_HAVE_LOOPS */
104
105 .Lz3:   /* Byte 3 is zero.  */
106         retw
107
108 .Lz0:   /* Byte 0 is zero.  */
109 #ifdef __XTENSA_EB__
110         movi    a8, 0
111 #endif
112         s8i     a8, a10, 0
113         retw
114
115 .Lz1:   /* Byte 1 is zero.  */
116 #ifdef __XTENSA_EB__
117         extui   a8, a8, 16, 16
118 #endif
119         s16i    a8, a10, 0
120         retw
121
122 .Lz2:   /* Byte 2 is zero.  */
123 #ifdef __XTENSA_EB__
124         extui   a8, a8, 16, 16
125 #endif
126         s16i    a8, a10, 0
127         movi    a8, 0
128         s8i     a8, a10, 2
129         retw
130
131         .align  4
132         /* (2 mod 4) alignment for loop instruction */
133 .Ldstunaligned:
134
135 #if XCHAL_HAVE_LOOPS
136         _movi.n a8, 0           // set up for the maximum loop count
137         loop    a8, 2f          // loop forever (almost anyway)
138 #endif
139 1:      l8ui    a8, a3, 0
140         addi    a3, a3, 1
141         s8i     a8, a10, 0
142         addi    a10, a10, 1
143 #if XCHAL_HAVE_LOOPS
144         beqz    a8, 2f
145 #else
146         bnez    a8, 1b
147 #endif
148 2:      retw
149
150 libc_hidden_def (strcpy)