18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * arch/alpha/lib/clear_user.S
48c2ecf20Sopenharmony_ci * Contributed by Richard Henderson <rth@tamu.edu>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Zero user space, handling exceptions as we go.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * We have to make sure that $0 is always up-to-date and contains the
98c2ecf20Sopenharmony_ci * right "bytes left to zero" value (and that it is updated only _after_
108c2ecf20Sopenharmony_ci * a successful copy).  There is also some rather minor exception setup
118c2ecf20Sopenharmony_ci * stuff.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci#include <asm/export.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/* Allow an exception for an insn; exit if we get one.  */
168c2ecf20Sopenharmony_ci#define EX(x,y...)			\
178c2ecf20Sopenharmony_ci	99: x,##y;			\
188c2ecf20Sopenharmony_ci	.section __ex_table,"a";	\
198c2ecf20Sopenharmony_ci	.long 99b - .;			\
208c2ecf20Sopenharmony_ci	lda $31, $exception-99b($31); 	\
218c2ecf20Sopenharmony_ci	.previous
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	.set noat
248c2ecf20Sopenharmony_ci	.set noreorder
258c2ecf20Sopenharmony_ci	.align 4
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	.globl __clear_user
288c2ecf20Sopenharmony_ci	.ent __clear_user
298c2ecf20Sopenharmony_ci	.frame	$30, 0, $26
308c2ecf20Sopenharmony_ci	.prologue 0
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci$loop:
338c2ecf20Sopenharmony_ci	and	$1, 3, $4	# e0    :
348c2ecf20Sopenharmony_ci	beq	$4, 1f		# .. e1 :
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci0:	EX( stq_u $31, 0($16) )	# e0    : zero one word
378c2ecf20Sopenharmony_ci	subq	$0, 8, $0	# .. e1 :
388c2ecf20Sopenharmony_ci	subq	$4, 1, $4	# e0    :
398c2ecf20Sopenharmony_ci	addq	$16, 8, $16	# .. e1 :
408c2ecf20Sopenharmony_ci	bne	$4, 0b		# e1    :
418c2ecf20Sopenharmony_ci	unop			#       :
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci1:	bic	$1, 3, $1	# e0    :
448c2ecf20Sopenharmony_ci	beq	$1, $tail	# .. e1 :
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci2:	EX( stq_u $31, 0($16) )	# e0    : zero four words
478c2ecf20Sopenharmony_ci	subq	$0, 8, $0	# .. e1 :
488c2ecf20Sopenharmony_ci	EX( stq_u $31, 8($16) )	# e0    :
498c2ecf20Sopenharmony_ci	subq	$0, 8, $0	# .. e1 :
508c2ecf20Sopenharmony_ci	EX( stq_u $31, 16($16) )	# e0    :
518c2ecf20Sopenharmony_ci	subq	$0, 8, $0	# .. e1 :
528c2ecf20Sopenharmony_ci	EX( stq_u $31, 24($16) )	# e0    :
538c2ecf20Sopenharmony_ci	subq	$0, 8, $0	# .. e1 :
548c2ecf20Sopenharmony_ci	subq	$1, 4, $1	# e0    :
558c2ecf20Sopenharmony_ci	addq	$16, 32, $16	# .. e1 :
568c2ecf20Sopenharmony_ci	bne	$1, 2b		# e1    :
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci$tail:
598c2ecf20Sopenharmony_ci	bne	$2, 1f		# e1    : is there a tail to do?
608c2ecf20Sopenharmony_ci	ret	$31, ($26), 1	# .. e1 :
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci1:	EX( ldq_u $5, 0($16) )	# e0    :
638c2ecf20Sopenharmony_ci	clr	$0		# .. e1 :
648c2ecf20Sopenharmony_ci	nop			# e1    :
658c2ecf20Sopenharmony_ci	mskqh	$5, $0, $5	# e0    :
668c2ecf20Sopenharmony_ci	EX( stq_u $5, 0($16) )	# e0    :
678c2ecf20Sopenharmony_ci	ret	$31, ($26), 1	# .. e1 :
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci__clear_user:
708c2ecf20Sopenharmony_ci	and	$17, $17, $0
718c2ecf20Sopenharmony_ci	and	$16, 7, $4	# e0    : find dest misalignment
728c2ecf20Sopenharmony_ci	beq	$0, $zerolength # .. e1 :
738c2ecf20Sopenharmony_ci	addq	$0, $4, $1	# e0    : bias counter
748c2ecf20Sopenharmony_ci	and	$1, 7, $2	# e1    : number of bytes in tail
758c2ecf20Sopenharmony_ci	srl	$1, 3, $1	# e0    :
768c2ecf20Sopenharmony_ci	beq	$4, $loop	# .. e1 :
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	EX( ldq_u $5, 0($16) )	# e0    : load dst word to mask back in
798c2ecf20Sopenharmony_ci	beq	$1, $oneword	# .. e1 : sub-word store?
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	mskql	$5, $16, $5	# e0    : take care of misaligned head
828c2ecf20Sopenharmony_ci	addq	$16, 8, $16	# .. e1 :
838c2ecf20Sopenharmony_ci	EX( stq_u $5, -8($16) )	# e0    :
848c2ecf20Sopenharmony_ci	addq	$0, $4, $0	# .. e1 : bytes left -= 8 - misalignment
858c2ecf20Sopenharmony_ci	subq	$1, 1, $1	# e0    :
868c2ecf20Sopenharmony_ci	subq	$0, 8, $0	# .. e1 :
878c2ecf20Sopenharmony_ci	br	$loop		# e1    :
888c2ecf20Sopenharmony_ci	unop			#       :
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci$oneword:
918c2ecf20Sopenharmony_ci	mskql	$5, $16, $4	# e0    :
928c2ecf20Sopenharmony_ci	mskqh	$5, $2, $5	# e0    :
938c2ecf20Sopenharmony_ci	or	$5, $4, $5	# e1    :
948c2ecf20Sopenharmony_ci	EX( stq_u $5, 0($16) )	# e0    :
958c2ecf20Sopenharmony_ci	clr	$0		# .. e1 :
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci$zerolength:
988c2ecf20Sopenharmony_ci$exception:
998c2ecf20Sopenharmony_ci	ret	$31, ($26), 1	# .. e1 :
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	.end __clear_user
1028c2ecf20Sopenharmony_ci	EXPORT_SYMBOL(__clear_user)
103