162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * arch/alpha/lib/strncpy.S
462306a36Sopenharmony_ci * Contributed by Richard Henderson (rth@tamu.edu)
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copy no more than COUNT bytes of the null-terminated string from
762306a36Sopenharmony_ci * SRC to DST.  If SRC does not cover all of COUNT, the balance is
862306a36Sopenharmony_ci * zeroed.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Or, rather, if the kernel cared about that weird ANSI quirk.  This
1162306a36Sopenharmony_ci * version has cropped that bit o' nastiness as well as assuming that
1262306a36Sopenharmony_ci * __stxncpy is in range of a branch.
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci#include <linux/export.h>
1562306a36Sopenharmony_ci	.set noat
1662306a36Sopenharmony_ci	.set noreorder
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	.text
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	.align 4
2162306a36Sopenharmony_ci	.globl strncpy
2262306a36Sopenharmony_ci	.ent strncpy
2362306a36Sopenharmony_cistrncpy:
2462306a36Sopenharmony_ci	.frame $30, 0, $26
2562306a36Sopenharmony_ci	.prologue 0
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	mov	$16, $0		# set return value now
2862306a36Sopenharmony_ci	beq	$18, $zerolen
2962306a36Sopenharmony_ci	unop
3062306a36Sopenharmony_ci	bsr	$23, __stxncpy	# do the work of the copy
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	unop
3362306a36Sopenharmony_ci	bne	$18, $multiword	# do we have full words left?
3462306a36Sopenharmony_ci	subq	$24, 1, $3	# nope
3562306a36Sopenharmony_ci	subq	$27, 1, $4
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	or	$3, $24, $3	# clear the bits between the last
3862306a36Sopenharmony_ci	or	$4, $27, $4	# written byte and the last byte in COUNT
3962306a36Sopenharmony_ci	andnot	$3, $4, $4
4062306a36Sopenharmony_ci	zap	$1, $4, $1
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	stq_u	$1, 0($16)
4362306a36Sopenharmony_ci	ret
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	.align	4
4662306a36Sopenharmony_ci$multiword:
4762306a36Sopenharmony_ci	subq	$27, 1, $2	# clear the final bits in the prev word
4862306a36Sopenharmony_ci	or	$2, $27, $2
4962306a36Sopenharmony_ci	zapnot	$1, $2, $1
5062306a36Sopenharmony_ci	subq	$18, 1, $18
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	stq_u	$1, 0($16)
5362306a36Sopenharmony_ci	addq	$16, 8, $16
5462306a36Sopenharmony_ci	unop
5562306a36Sopenharmony_ci	beq	$18, 1f
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	nop
5862306a36Sopenharmony_ci	unop
5962306a36Sopenharmony_ci	nop
6062306a36Sopenharmony_ci	blbc	$18, 0f
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	stq_u	$31, 0($16)	# zero one word
6362306a36Sopenharmony_ci	subq	$18, 1, $18
6462306a36Sopenharmony_ci	addq	$16, 8, $16
6562306a36Sopenharmony_ci	beq	$18, 1f
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci0:	stq_u	$31, 0($16)	# zero two words
6862306a36Sopenharmony_ci	subq	$18, 2, $18
6962306a36Sopenharmony_ci	stq_u	$31, 8($16)
7062306a36Sopenharmony_ci	addq	$16, 16, $16
7162306a36Sopenharmony_ci	bne	$18, 0b
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci1:	ldq_u	$1, 0($16)	# clear the leading bits in the final word
7462306a36Sopenharmony_ci	subq	$24, 1, $2
7562306a36Sopenharmony_ci	or	$2, $24, $2
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	zap	$1, $2, $1
7862306a36Sopenharmony_ci	stq_u	$1, 0($16)
7962306a36Sopenharmony_ci$zerolen:
8062306a36Sopenharmony_ci	ret
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	.end	strncpy
8362306a36Sopenharmony_ci	EXPORT_SYMBOL(strncpy)
84