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