OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / libc / string / xtensa / memset.S
1 /* Optimized memset 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, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <sysdep.h>
20 #include <bits/xtensa-config.h>
21
22 /* Do not use .literal_position in the ENTRY macro.  */
23 #undef LITERAL_POSITION
24 #define LITERAL_POSITION
25
26 /* void *memset (void *dst, int c, size_t length)
27
28    The algorithm is as follows:
29
30    Create a word with c in all byte positions.
31
32    If the destination is aligned, set 16B chunks with a loop, and then
33    finish up with 8B, 4B, 2B, and 1B stores conditional on the length.
34
35    If the destination is unaligned, align it by conditionally
36    setting 1B and/or 2B and then go to aligned case.
37
38    This code tries to use fall-through branches for the common
39    case of an aligned destination (except for the branches to
40    the alignment labels).  */
41
42
43 /* Byte-by-byte set.  */
44
45         .text
46         .align  4
47         .literal_position
48 __memset_aux:
49
50         /* Skip a byte to get 1 mod 4 alignment for LOOPNEZ
51            (0 mod 4 alignment for LBEG).  */
52         .byte   0
53
54 .Lbyteset:
55 #if XCHAL_HAVE_LOOPS
56         loopnez a4, 2f
57 #else
58         beqz    a4, 2f
59         add     a6, a5, a4      /* a6 = ending address */
60 #endif
61 1:      s8i     a3, a5, 0
62         addi    a5, a5, 1
63 #if !XCHAL_HAVE_LOOPS
64         blt     a5, a6, 1b
65 #endif
66 2:      retw
67
68
69 /* Destination is unaligned.  */
70
71         .align  4
72
73 .Ldst1mod2: /* dst is only byte aligned */
74
75         /* Do short sizes byte-by-byte.  */
76         bltui   a4, 8, .Lbyteset
77
78         /* Set 1 byte.  */
79         s8i     a3, a5, 0
80         addi    a5, a5, 1
81         addi    a4, a4, -1
82
83         /* Now retest if dst is aligned.  */
84         _bbci.l a5, 1, .Ldstaligned
85
86 .Ldst2mod4: /* dst has 16-bit alignment */
87
88         /* Do short sizes byte-by-byte.  */
89         bltui   a4, 8, .Lbyteset
90
91         /* Set 2 bytes.  */
92         s16i    a3, a5, 0
93         addi    a5, a5, 2
94         addi    a4, a4, -2
95
96         /* dst is now aligned; return to main algorithm */
97         j       .Ldstaligned
98
99
100 ENTRY (memset)
101         /* a2 = dst, a3 = c, a4 = length */
102
103         /* Duplicate character into all bytes of word.  */
104         extui   a3, a3, 0, 8
105         slli    a7, a3, 8
106         or      a3, a3, a7
107         slli    a7, a3, 16
108         or      a3, a3, a7
109
110         mov     a5, a2          /* copy dst so that a2 is return value */
111
112         /* Check if dst is unaligned.  */
113         _bbsi.l a2, 0, .Ldst1mod2
114         _bbsi.l a2, 1, .Ldst2mod4
115 .Ldstaligned:
116
117         /* Get number of loop iterations with 16B per iteration.  */
118         srli    a7, a4, 4
119
120         /* Destination is word-aligned.  */
121 #if XCHAL_HAVE_LOOPS
122         loopnez a7, 2f
123 #else
124         beqz    a7, 2f
125         slli    a6, a7, 4
126         add     a6, a6, a5      /* a6 = end of last 16B chunk */
127 #endif
128         /* Set 16 bytes per iteration.  */
129 1:      s32i    a3, a5, 0
130         s32i    a3, a5, 4
131         s32i    a3, a5, 8
132         s32i    a3, a5, 12
133         addi    a5, a5, 16
134 #if !XCHAL_HAVE_LOOPS
135         blt     a5, a6, 1b
136 #endif
137
138         /* Set any leftover pieces smaller than 16B.  */
139 2:      bbci.l  a4, 3, 3f
140
141         /* Set 8 bytes.  */
142         s32i    a3, a5, 0
143         s32i    a3, a5, 4
144         addi    a5, a5, 8
145
146 3:      bbci.l  a4, 2, 4f
147
148         /* Set 4 bytes.  */
149         s32i    a3, a5, 0
150         addi    a5, a5, 4
151
152 4:      bbci.l  a4, 1, 5f
153
154         /* Set 2 bytes.  */
155         s16i    a3, a5, 0
156         addi    a5, a5, 2
157
158 5:      bbci.l  a4, 0, 6f
159
160         /* Set 1 byte.  */
161         s8i     a3, a5, 0
162 6:      retw
163
164 libc_hidden_def (memset)