Linux Audio

Check our new training course

Loading...
v5.9
  1/*
  2 *  arch/xtensa/lib/strncpy_user.S
  3 *
  4 *  This file is subject to the terms and conditions of the GNU General
  5 *  Public License.  See the file "COPYING" in the main directory of
  6 *  this archive for more details.
  7 *
  8 *  Returns: -EFAULT if exception before terminator, N if the entire
  9 *  buffer filled, else strlen.
 10 *
 11 *  Copyright (C) 2002 Tensilica Inc.
 12 */
 13
 14#include <linux/errno.h>
 15#include <linux/linkage.h>
 16#include <asm/asmmacro.h>
 17#include <asm/core.h>
 18
 19/*
 20 * char *__strncpy_user(char *dst, const char *src, size_t len)
 21 */
 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# Register use
 36#   a0/ return address
 37#   a1/ stack pointer
 38#   a2/ return value
 39#   a3/ src
 40#   a4/ len
 41#   a5/ mask0
 42#   a6/ mask1
 43#   a7/ mask2
 44#   a8/ mask3
 45#   a9/ tmp
 46#   a10/ tmp
 47#   a11/ dst
 48#   a12/ tmp
 49
 50.text
 51ENTRY(__strncpy_user)
 52
 53	abi_entry_default
 54	# a2/ dst, a3/ src, a4/ len
 55	mov	a11, a2		# leave dst in return value register
 56	beqz	a4, .Lret	# if len is zero
 57	movi	a5, MASK0	# mask for byte 0
 58	movi	a6, MASK1	# mask for byte 1
 59	movi	a7, MASK2	# mask for byte 2
 60	movi	a8, MASK3	# mask for byte 3
 61	bbsi.l	a3, 0, .Lsrc1mod2 # if only  8-bit aligned
 62	bbsi.l	a3, 1, .Lsrc2mod4 # if only 16-bit aligned
 63.Lsrcaligned:	# return here when src is word-aligned
 64	srli	a12, a4, 2	# number of loop iterations with 4B per loop
 65	movi	a9, 3
 66	bnone	a11, a9, .Laligned
 67	j	.Ldstunaligned
 68
 69.Lsrc1mod2:	# src address is odd
 70EX(11f)	l8ui	a9, a3, 0		# get byte 0
 71	addi	a3, a3, 1		# advance src pointer
 72EX(10f)	s8i	a9, a11, 0		# store byte 0
 73	beqz	a9, .Lret		# if byte 0 is zero
 74	addi	a11, a11, 1		# advance dst pointer
 75	addi	a4, a4, -1		# decrement len
 76	beqz	a4, .Lret		# if len is zero
 77	bbci.l	a3, 1, .Lsrcaligned	# if src is now word-aligned
 78
 79.Lsrc2mod4:	# src address is 2 mod 4
 80EX(11f)	l8ui	a9, a3, 0		# get byte 0
 81	/* 1-cycle interlock */
 82EX(10f)	s8i	a9, a11, 0		# store byte 0
 83	beqz	a9, .Lret		# if byte 0 is zero
 84	addi	a11, a11, 1		# advance dst pointer
 85	addi	a4, a4, -1		# decrement len
 86	beqz	a4, .Lret		# if len is zero
 87EX(11f)	l8ui	a9, a3, 1		# get byte 0
 88	addi	a3, a3, 2		# advance src pointer
 89EX(10f)	s8i	a9, a11, 0		# store byte 0
 90	beqz	a9, .Lret		# if byte 0 is zero
 91	addi	a11, a11, 1		# advance dst pointer
 92	addi	a4, a4, -1		# decrement len
 93	bnez	a4, .Lsrcaligned	# if len is nonzero
 94.Lret:
 95	sub	a2, a11, a2		# compute strlen
 96	abi_ret_default
 97
 98/*
 99 * dst is word-aligned, src is word-aligned
100 */
101	.align	4		# 1 mod 4 alignment for LOOPNEZ
102	.byte	0		# (0 mod 4 alignment for LBEG)
103.Laligned:
104#if XCHAL_HAVE_LOOPS
105	loopnez	a12, .Loop1done
106#else
107	beqz	a12, .Loop1done
108	slli	a12, a12, 2
109	add	a12, a12, a11	# a12 = end of last 4B chunck
110#endif
111.Loop1:
112EX(11f)	l32i	a9, a3, 0		# get word from src
113	addi	a3, a3, 4		# advance src pointer
114	bnone	a9, a5, .Lz0		# if byte 0 is zero
115	bnone	a9, a6, .Lz1		# if byte 1 is zero
116	bnone	a9, a7, .Lz2		# if byte 2 is zero
117EX(10f)	s32i	a9, a11, 0		# store word to dst
118	bnone	a9, a8, .Lz3		# if byte 3 is zero
119	addi	a11, a11, 4		# advance dst pointer
120#if !XCHAL_HAVE_LOOPS
121	blt	a11, a12, .Loop1
122#endif
123
124.Loop1done:
125	bbci.l	a4, 1, .L100
126	# copy 2 bytes
127EX(11f)	l16ui	a9, a3, 0
128	addi	a3, a3, 2		# advance src pointer
129#ifdef __XTENSA_EB__
130	bnone	a9, a7, .Lz0		# if byte 2 is zero
131	bnone	a9, a8, .Lz1		# if byte 3 is zero
132#else
133	bnone	a9, a5, .Lz0		# if byte 0 is zero
134	bnone	a9, a6, .Lz1		# if byte 1 is zero
135#endif
136EX(10f)	s16i	a9, a11, 0
137	addi	a11, a11, 2		# advance dst pointer
138.L100:
139	bbci.l	a4, 0, .Lret
140EX(11f)	l8ui	a9, a3, 0
141	/* slot */
142EX(10f)	s8i	a9, a11, 0
143	beqz	a9, .Lret		# if byte is zero
144	addi	a11, a11, 1-3		# advance dst ptr 1, but also cancel
145					# the effect of adding 3 in .Lz3 code
146	/* fall thru to .Lz3 and "retw" */
147
148.Lz3:	# byte 3 is zero
149	addi	a11, a11, 3		# advance dst pointer
150	sub	a2, a11, a2		# compute strlen
151	abi_ret_default
152.Lz0:	# byte 0 is zero
153#ifdef __XTENSA_EB__
154	movi	a9, 0
155#endif /* __XTENSA_EB__ */
156EX(10f)	s8i	a9, a11, 0
157	sub	a2, a11, a2		# compute strlen
158	abi_ret_default
159.Lz1:	# byte 1 is zero
160#ifdef __XTENSA_EB__
161	extui   a9, a9, 16, 16
162#endif /* __XTENSA_EB__ */
163EX(10f)	s16i	a9, a11, 0
164	addi	a11, a11, 1		# advance dst pointer
165	sub	a2, a11, a2		# compute strlen
166	abi_ret_default
167.Lz2:	# byte 2 is zero
168#ifdef __XTENSA_EB__
169	extui   a9, a9, 16, 16
170#endif /* __XTENSA_EB__ */
171EX(10f)	s16i	a9, a11, 0
172	movi	a9, 0
173EX(10f)	s8i	a9, a11, 2
174	addi	a11, a11, 2		# advance dst pointer
175	sub	a2, a11, a2		# compute strlen
176	abi_ret_default
177
178	.align	4		# 1 mod 4 alignment for LOOPNEZ
179	.byte	0		# (0 mod 4 alignment for LBEG)
180.Ldstunaligned:
181/*
182 * for now just use byte copy loop
183 */
184#if XCHAL_HAVE_LOOPS
185	loopnez	a4, .Lunalignedend
186#else
187	beqz	a4, .Lunalignedend
188	add	a12, a11, a4		# a12 = ending address
189#endif /* XCHAL_HAVE_LOOPS */
190.Lnextbyte:
191EX(11f)	l8ui	a9, a3, 0
192	addi	a3, a3, 1
193EX(10f)	s8i	a9, a11, 0
194	beqz	a9, .Lunalignedend
195	addi	a11, a11, 1
196#if !XCHAL_HAVE_LOOPS
197	blt	a11, a12, .Lnextbyte
198#endif
199
200.Lunalignedend:
201	sub	a2, a11, a2		# compute strlen
202	abi_ret_default
203
204ENDPROC(__strncpy_user)
205
206	.section .fixup, "ax"
207	.align	4
208
209	/* For now, just return -EFAULT.  Future implementations might
210	 * like to clear remaining kernel space, like the fixup
211	 * implementation in memset().  Thus, we differentiate between
212	 * load/store fixups. */
213
21410:
21511:
216	movi	a2, -EFAULT
217	abi_ret_default
v6.2
  1/*
  2 *  arch/xtensa/lib/strncpy_user.S
  3 *
  4 *  This file is subject to the terms and conditions of the GNU General
  5 *  Public License.  See the file "COPYING" in the main directory of
  6 *  this archive for more details.
  7 *
  8 *  Returns: -EFAULT if exception before terminator, N if the entire
  9 *  buffer filled, else strlen.
 10 *
 11 *  Copyright (C) 2002 Tensilica Inc.
 12 */
 13
 14#include <linux/errno.h>
 15#include <linux/linkage.h>
 16#include <asm/asmmacro.h>
 17#include <asm/core.h>
 18
 19/*
 20 * char *__strncpy_user(char *dst, const char *src, size_t len)
 21 */
 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# Register use
 36#   a0/ return address
 37#   a1/ stack pointer
 38#   a2/ return value
 39#   a3/ src
 40#   a4/ len
 41#   a5/ mask0
 42#   a6/ mask1
 43#   a7/ mask2
 44#   a8/ mask3
 45#   a9/ tmp
 46#   a10/ tmp
 47#   a11/ dst
 
 48
 49.text
 50ENTRY(__strncpy_user)
 51
 52	abi_entry_default
 53	# a2/ dst, a3/ src, a4/ len
 54	mov	a11, a2		# leave dst in return value register
 55	beqz	a4, .Lret	# if len is zero
 56	movi	a5, MASK0	# mask for byte 0
 57	movi	a6, MASK1	# mask for byte 1
 58	movi	a7, MASK2	# mask for byte 2
 59	movi	a8, MASK3	# mask for byte 3
 60	bbsi.l	a3, 0, .Lsrc1mod2 # if only  8-bit aligned
 61	bbsi.l	a3, 1, .Lsrc2mod4 # if only 16-bit aligned
 62.Lsrcaligned:	# return here when src is word-aligned
 63	srli	a10, a4, 2	# number of loop iterations with 4B per loop
 64	movi	a9, 3
 65	bnone	a11, a9, .Laligned
 66	j	.Ldstunaligned
 67
 68.Lsrc1mod2:	# src address is odd
 69EX(11f)	l8ui	a9, a3, 0		# get byte 0
 70	addi	a3, a3, 1		# advance src pointer
 71EX(10f)	s8i	a9, a11, 0		# store byte 0
 72	beqz	a9, .Lret		# if byte 0 is zero
 73	addi	a11, a11, 1		# advance dst pointer
 74	addi	a4, a4, -1		# decrement len
 75	beqz	a4, .Lret		# if len is zero
 76	bbci.l	a3, 1, .Lsrcaligned	# if src is now word-aligned
 77
 78.Lsrc2mod4:	# src address is 2 mod 4
 79EX(11f)	l8ui	a9, a3, 0		# get byte 0
 80	/* 1-cycle interlock */
 81EX(10f)	s8i	a9, a11, 0		# store byte 0
 82	beqz	a9, .Lret		# if byte 0 is zero
 83	addi	a11, a11, 1		# advance dst pointer
 84	addi	a4, a4, -1		# decrement len
 85	beqz	a4, .Lret		# if len is zero
 86EX(11f)	l8ui	a9, a3, 1		# get byte 0
 87	addi	a3, a3, 2		# advance src pointer
 88EX(10f)	s8i	a9, a11, 0		# store byte 0
 89	beqz	a9, .Lret		# if byte 0 is zero
 90	addi	a11, a11, 1		# advance dst pointer
 91	addi	a4, a4, -1		# decrement len
 92	bnez	a4, .Lsrcaligned	# if len is nonzero
 93.Lret:
 94	sub	a2, a11, a2		# compute strlen
 95	abi_ret_default
 96
 97/*
 98 * dst is word-aligned, src is word-aligned
 99 */
100	.align	4		# 1 mod 4 alignment for LOOPNEZ
101	.byte	0		# (0 mod 4 alignment for LBEG)
102.Laligned:
103#if XCHAL_HAVE_LOOPS
104	loopnez	a10, .Loop1done
105#else
106	beqz	a10, .Loop1done
107	slli	a10, a10, 2
108	add	a10, a10, a11	# a10 = end of last 4B chunck
109#endif
110.Loop1:
111EX(11f)	l32i	a9, a3, 0		# get word from src
112	addi	a3, a3, 4		# advance src pointer
113	bnone	a9, a5, .Lz0		# if byte 0 is zero
114	bnone	a9, a6, .Lz1		# if byte 1 is zero
115	bnone	a9, a7, .Lz2		# if byte 2 is zero
116EX(10f)	s32i	a9, a11, 0		# store word to dst
117	bnone	a9, a8, .Lz3		# if byte 3 is zero
118	addi	a11, a11, 4		# advance dst pointer
119#if !XCHAL_HAVE_LOOPS
120	blt	a11, a10, .Loop1
121#endif
122
123.Loop1done:
124	bbci.l	a4, 1, .L100
125	# copy 2 bytes
126EX(11f)	l16ui	a9, a3, 0
127	addi	a3, a3, 2		# advance src pointer
128#ifdef __XTENSA_EB__
129	bnone	a9, a7, .Lz0		# if byte 2 is zero
130	bnone	a9, a8, .Lz1		# if byte 3 is zero
131#else
132	bnone	a9, a5, .Lz0		# if byte 0 is zero
133	bnone	a9, a6, .Lz1		# if byte 1 is zero
134#endif
135EX(10f)	s16i	a9, a11, 0
136	addi	a11, a11, 2		# advance dst pointer
137.L100:
138	bbci.l	a4, 0, .Lret
139EX(11f)	l8ui	a9, a3, 0
140	/* slot */
141EX(10f)	s8i	a9, a11, 0
142	beqz	a9, .Lret		# if byte is zero
143	addi	a11, a11, 1-3		# advance dst ptr 1, but also cancel
144					# the effect of adding 3 in .Lz3 code
145	/* fall thru to .Lz3 and "retw" */
146
147.Lz3:	# byte 3 is zero
148	addi	a11, a11, 3		# advance dst pointer
149	sub	a2, a11, a2		# compute strlen
150	abi_ret_default
151.Lz0:	# byte 0 is zero
152#ifdef __XTENSA_EB__
153	movi	a9, 0
154#endif /* __XTENSA_EB__ */
155EX(10f)	s8i	a9, a11, 0
156	sub	a2, a11, a2		# compute strlen
157	abi_ret_default
158.Lz1:	# byte 1 is zero
159#ifdef __XTENSA_EB__
160	extui   a9, a9, 16, 16
161#endif /* __XTENSA_EB__ */
162EX(10f)	s16i	a9, a11, 0
163	addi	a11, a11, 1		# advance dst pointer
164	sub	a2, a11, a2		# compute strlen
165	abi_ret_default
166.Lz2:	# byte 2 is zero
167#ifdef __XTENSA_EB__
168	extui   a9, a9, 16, 16
169#endif /* __XTENSA_EB__ */
170EX(10f)	s16i	a9, a11, 0
171	movi	a9, 0
172EX(10f)	s8i	a9, a11, 2
173	addi	a11, a11, 2		# advance dst pointer
174	sub	a2, a11, a2		# compute strlen
175	abi_ret_default
176
177	.align	4		# 1 mod 4 alignment for LOOPNEZ
178	.byte	0		# (0 mod 4 alignment for LBEG)
179.Ldstunaligned:
180/*
181 * for now just use byte copy loop
182 */
183#if XCHAL_HAVE_LOOPS
184	loopnez	a4, .Lunalignedend
185#else
186	beqz	a4, .Lunalignedend
187	add	a10, a11, a4		# a10 = ending address
188#endif /* XCHAL_HAVE_LOOPS */
189.Lnextbyte:
190EX(11f)	l8ui	a9, a3, 0
191	addi	a3, a3, 1
192EX(10f)	s8i	a9, a11, 0
193	beqz	a9, .Lunalignedend
194	addi	a11, a11, 1
195#if !XCHAL_HAVE_LOOPS
196	blt	a11, a10, .Lnextbyte
197#endif
198
199.Lunalignedend:
200	sub	a2, a11, a2		# compute strlen
201	abi_ret_default
202
203ENDPROC(__strncpy_user)
204
205	.section .fixup, "ax"
206	.align	4
207
208	/* For now, just return -EFAULT.  Future implementations might
209	 * like to clear remaining kernel space, like the fixup
210	 * implementation in memset().  Thus, we differentiate between
211	 * load/store fixups. */
212
21310:
21411:
215	movi	a2, -EFAULT
216	abi_ret_default