xref: /openbmc/linux/arch/alpha/lib/clear_user.S (revision f3c78e94)
1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds/*
31da177e4SLinus Torvalds * arch/alpha/lib/clear_user.S
41da177e4SLinus Torvalds * Contributed by Richard Henderson <rth@tamu.edu>
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * Zero user space, handling exceptions as we go.
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds * We have to make sure that $0 is always up-to-date and contains the
91da177e4SLinus Torvalds * right "bytes left to zero" value (and that it is updated only _after_
101da177e4SLinus Torvalds * a successful copy).  There is also some rather minor exception setup
111da177e4SLinus Torvalds * stuff.
121da177e4SLinus Torvalds */
13*f3c78e94SMasahiro Yamada#include <linux/export.h>
141da177e4SLinus Torvalds
151da177e4SLinus Torvalds/* Allow an exception for an insn; exit if we get one.  */
161da177e4SLinus Torvalds#define EX(x,y...)			\
171da177e4SLinus Torvalds	99: x,##y;			\
181da177e4SLinus Torvalds	.section __ex_table,"a";	\
191da177e4SLinus Torvalds	.long 99b - .;			\
201da177e4SLinus Torvalds	lda $31, $exception-99b($31); 	\
211da177e4SLinus Torvalds	.previous
221da177e4SLinus Torvalds
231da177e4SLinus Torvalds	.set noat
241da177e4SLinus Torvalds	.set noreorder
251da177e4SLinus Torvalds	.align 4
261da177e4SLinus Torvalds
2785250231SAl Viro	.globl __clear_user
2885250231SAl Viro	.ent __clear_user
2985250231SAl Viro	.frame	$30, 0, $26
301da177e4SLinus Torvalds	.prologue 0
311da177e4SLinus Torvalds
321da177e4SLinus Torvalds$loop:
331da177e4SLinus Torvalds	and	$1, 3, $4	# e0    :
341da177e4SLinus Torvalds	beq	$4, 1f		# .. e1 :
351da177e4SLinus Torvalds
3685250231SAl Viro0:	EX( stq_u $31, 0($16) )	# e0    : zero one word
371da177e4SLinus Torvalds	subq	$0, 8, $0	# .. e1 :
381da177e4SLinus Torvalds	subq	$4, 1, $4	# e0    :
3985250231SAl Viro	addq	$16, 8, $16	# .. e1 :
401da177e4SLinus Torvalds	bne	$4, 0b		# e1    :
411da177e4SLinus Torvalds	unop			#       :
421da177e4SLinus Torvalds
431da177e4SLinus Torvalds1:	bic	$1, 3, $1	# e0    :
441da177e4SLinus Torvalds	beq	$1, $tail	# .. e1 :
451da177e4SLinus Torvalds
4685250231SAl Viro2:	EX( stq_u $31, 0($16) )	# e0    : zero four words
471da177e4SLinus Torvalds	subq	$0, 8, $0	# .. e1 :
4885250231SAl Viro	EX( stq_u $31, 8($16) )	# e0    :
491da177e4SLinus Torvalds	subq	$0, 8, $0	# .. e1 :
5085250231SAl Viro	EX( stq_u $31, 16($16) )	# e0    :
511da177e4SLinus Torvalds	subq	$0, 8, $0	# .. e1 :
5285250231SAl Viro	EX( stq_u $31, 24($16) )	# e0    :
531da177e4SLinus Torvalds	subq	$0, 8, $0	# .. e1 :
541da177e4SLinus Torvalds	subq	$1, 4, $1	# e0    :
5585250231SAl Viro	addq	$16, 32, $16	# .. e1 :
561da177e4SLinus Torvalds	bne	$1, 2b		# e1    :
571da177e4SLinus Torvalds
581da177e4SLinus Torvalds$tail:
591da177e4SLinus Torvalds	bne	$2, 1f		# e1    : is there a tail to do?
6085250231SAl Viro	ret	$31, ($26), 1	# .. e1 :
611da177e4SLinus Torvalds
6285250231SAl Viro1:	EX( ldq_u $5, 0($16) )	# e0    :
631da177e4SLinus Torvalds	clr	$0		# .. e1 :
641da177e4SLinus Torvalds	nop			# e1    :
651da177e4SLinus Torvalds	mskqh	$5, $0, $5	# e0    :
6685250231SAl Viro	EX( stq_u $5, 0($16) )	# e0    :
6785250231SAl Viro	ret	$31, ($26), 1	# .. e1 :
681da177e4SLinus Torvalds
6985250231SAl Viro__clear_user:
7085250231SAl Viro	and	$17, $17, $0
7185250231SAl Viro	and	$16, 7, $4	# e0    : find dest misalignment
721da177e4SLinus Torvalds	beq	$0, $zerolength # .. e1 :
731da177e4SLinus Torvalds	addq	$0, $4, $1	# e0    : bias counter
741da177e4SLinus Torvalds	and	$1, 7, $2	# e1    : number of bytes in tail
751da177e4SLinus Torvalds	srl	$1, 3, $1	# e0    :
761da177e4SLinus Torvalds	beq	$4, $loop	# .. e1 :
771da177e4SLinus Torvalds
7885250231SAl Viro	EX( ldq_u $5, 0($16) )	# e0    : load dst word to mask back in
791da177e4SLinus Torvalds	beq	$1, $oneword	# .. e1 : sub-word store?
801da177e4SLinus Torvalds
8185250231SAl Viro	mskql	$5, $16, $5	# e0    : take care of misaligned head
8285250231SAl Viro	addq	$16, 8, $16	# .. e1 :
8385250231SAl Viro	EX( stq_u $5, -8($16) )	# e0    :
841da177e4SLinus Torvalds	addq	$0, $4, $0	# .. e1 : bytes left -= 8 - misalignment
851da177e4SLinus Torvalds	subq	$1, 1, $1	# e0    :
861da177e4SLinus Torvalds	subq	$0, 8, $0	# .. e1 :
871da177e4SLinus Torvalds	br	$loop		# e1    :
881da177e4SLinus Torvalds	unop			#       :
891da177e4SLinus Torvalds
901da177e4SLinus Torvalds$oneword:
9185250231SAl Viro	mskql	$5, $16, $4	# e0    :
921da177e4SLinus Torvalds	mskqh	$5, $2, $5	# e0    :
931da177e4SLinus Torvalds	or	$5, $4, $5	# e1    :
9485250231SAl Viro	EX( stq_u $5, 0($16) )	# e0    :
951da177e4SLinus Torvalds	clr	$0		# .. e1 :
961da177e4SLinus Torvalds
971da177e4SLinus Torvalds$zerolength:
981da177e4SLinus Torvalds$exception:
9985250231SAl Viro	ret	$31, ($26), 1	# .. e1 :
1001da177e4SLinus Torvalds
10185250231SAl Viro	.end __clear_user
10285250231SAl Viro	EXPORT_SYMBOL(__clear_user)
103