Merge tag 'soc-ep93xx-dt-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-block.git] / arch / xtensa / lib / memset.S
... / ...
CommitLineData
1/*
2 * arch/xtensa/lib/memset.S
3 *
4 * ANSI C standard library function memset
5 * (Well, almost. .fixup code might return zero.)
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file "COPYING" in the main directory of
9 * this archive for more details.
10 *
11 * Copyright (C) 2002 Tensilica Inc.
12 */
13
14#include <linux/linkage.h>
15#include <asm/asmmacro.h>
16#include <asm/core.h>
17
18/*
19 * void *memset(void *dst, int c, size_t length)
20 *
21 * The algorithm is as follows:
22 * Create a word with c in all byte positions
23 * If the destination is aligned,
24 * do 16B chucks with a loop, and then finish up with
25 * 8B, 4B, 2B, and 1B stores conditional on the length.
26 * If destination is unaligned, align it by conditionally
27 * setting 1B and 2B and then go to aligned case.
28 * This code tries to use fall-through branches for the common
29 * case of an aligned destination (except for the branches to
30 * the alignment labels).
31 */
32
33.text
34ENTRY(__memset)
35WEAK(memset)
36
37 abi_entry_default
38 # a2/ dst, a3/ c, a4/ length
39 extui a3, a3, 0, 8 # mask to just 8 bits
40 slli a7, a3, 8 # duplicate character in all bytes of word
41 or a3, a3, a7 # ...
42 slli a7, a3, 16 # ...
43 or a3, a3, a7 # ...
44 mov a5, a2 # copy dst so that a2 is return value
45 movi a6, 3 # for alignment tests
46 bany a2, a6, .Ldstunaligned # if dst is unaligned
47.L0: # return here from .Ldstunaligned when dst is aligned
48 srli a7, a4, 4 # number of loop iterations with 16B
49 # per iteration
50 bnez a4, .Laligned
51 abi_ret_default
52
53/*
54 * Destination is word-aligned.
55 */
56 # set 16 bytes per iteration for word-aligned dst
57 .align 4 # 1 mod 4 alignment for LOOPNEZ
58 .byte 0 # (0 mod 4 alignment for LBEG)
59.Laligned:
60#if XCHAL_HAVE_LOOPS
61 loopnez a7, .Loop1done
62#else /* !XCHAL_HAVE_LOOPS */
63 beqz a7, .Loop1done
64 slli a6, a7, 4
65 add a6, a6, a5 # a6 = end of last 16B chunk
66#endif /* !XCHAL_HAVE_LOOPS */
67.Loop1:
68EX(10f) s32i a3, a5, 0
69EX(10f) s32i a3, a5, 4
70EX(10f) s32i a3, a5, 8
71EX(10f) s32i a3, a5, 12
72 addi a5, a5, 16
73#if !XCHAL_HAVE_LOOPS
74 blt a5, a6, .Loop1
75#endif /* !XCHAL_HAVE_LOOPS */
76.Loop1done:
77 bbci.l a4, 3, .L2
78 # set 8 bytes
79EX(10f) s32i a3, a5, 0
80EX(10f) s32i a3, a5, 4
81 addi a5, a5, 8
82.L2:
83 bbci.l a4, 2, .L3
84 # set 4 bytes
85EX(10f) s32i a3, a5, 0
86 addi a5, a5, 4
87.L3:
88 bbci.l a4, 1, .L4
89 # set 2 bytes
90EX(10f) s16i a3, a5, 0
91 addi a5, a5, 2
92.L4:
93 bbci.l a4, 0, .L5
94 # set 1 byte
95EX(10f) s8i a3, a5, 0
96.L5:
97.Lret1:
98 abi_ret_default
99
100/*
101 * Destination is unaligned
102 */
103
104.Ldstunaligned:
105 bltui a4, 8, .Lbyteset # do short copies byte by byte
106 bbci.l a5, 0, .L20 # branch if dst alignment half-aligned
107 # dst is only byte aligned
108 # set 1 byte
109EX(10f) s8i a3, a5, 0
110 addi a5, a5, 1
111 addi a4, a4, -1
112 # now retest if dst aligned
113 bbci.l a5, 1, .L0 # if now aligned, return to main algorithm
114.L20:
115 # dst half-aligned
116 # set 2 bytes
117EX(10f) s16i a3, a5, 0
118 addi a5, a5, 2
119 addi a4, a4, -2
120 j .L0 # dst is now aligned, return to main algorithm
121
122/*
123 * Byte by byte set
124 */
125 .align 4
126 .byte 0 # 1 mod 4 alignment for LOOPNEZ
127 # (0 mod 4 alignment for LBEG)
128.Lbyteset:
129#if XCHAL_HAVE_LOOPS
130 loopnez a4, .Lbytesetdone
131#else /* !XCHAL_HAVE_LOOPS */
132 beqz a4, .Lbytesetdone
133 add a6, a5, a4 # a6 = ending address
134#endif /* !XCHAL_HAVE_LOOPS */
135.Lbyteloop:
136EX(10f) s8i a3, a5, 0
137 addi a5, a5, 1
138#if !XCHAL_HAVE_LOOPS
139 blt a5, a6, .Lbyteloop
140#endif /* !XCHAL_HAVE_LOOPS */
141.Lbytesetdone:
142 abi_ret_default
143
144ENDPROC(__memset)
145EXPORT_SYMBOL(__memset)
146EXPORT_SYMBOL(memset)
147
148 .section .fixup, "ax"
149 .align 4
150
151/* We return zero if a failure occurred. */
152
15310:
154 movi a2, 0
155 abi_ret_default