xref: /openbmc/linux/arch/alpha/lib/copy_user.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds/*
31da177e4SLinus Torvalds * arch/alpha/lib/copy_user.S
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copy to/from user space, handling exceptions as we go..  This
61da177e4SLinus Torvalds * isn't exactly pretty.
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds * This is essentially the same as "memcpy()", but with a few twists.
91da177e4SLinus Torvalds * Notably, we have to make sure that $0 is always up-to-date and
101da177e4SLinus Torvalds * contains the right "bytes left to copy" value (and that it is updated
111da177e4SLinus Torvalds * only _after_ a successful copy). There is also some rather minor
121da177e4SLinus Torvalds * exception setup stuff..
131da177e4SLinus Torvalds */
141da177e4SLinus Torvalds
15*f3c78e94SMasahiro Yamada#include <linux/export.h>
1600fc0e0dSAl Viro
171da177e4SLinus Torvalds/* Allow an exception for an insn; exit if we get one.  */
181da177e4SLinus Torvalds#define EXI(x,y...)			\
191da177e4SLinus Torvalds	99: x,##y;			\
201da177e4SLinus Torvalds	.section __ex_table,"a";	\
211da177e4SLinus Torvalds	.long 99b - .;			\
221da177e4SLinus Torvalds	lda $31, $exitin-99b($31);	\
231da177e4SLinus Torvalds	.previous
241da177e4SLinus Torvalds
251da177e4SLinus Torvalds#define EXO(x,y...)			\
261da177e4SLinus Torvalds	99: x,##y;			\
271da177e4SLinus Torvalds	.section __ex_table,"a";	\
281da177e4SLinus Torvalds	.long 99b - .;			\
291da177e4SLinus Torvalds	lda $31, $exitout-99b($31);	\
301da177e4SLinus Torvalds	.previous
311da177e4SLinus Torvalds
321da177e4SLinus Torvalds	.set noat
331da177e4SLinus Torvalds	.align 4
341da177e4SLinus Torvalds	.globl __copy_user
351da177e4SLinus Torvalds	.ent __copy_user
361da177e4SLinus Torvalds__copy_user:
371da177e4SLinus Torvalds	.prologue 0
384606f68fSRichard Henderson	mov $18,$0
3985250231SAl Viro	and $16,7,$3
401da177e4SLinus Torvalds	beq $0,$35
411da177e4SLinus Torvalds	beq $3,$36
421da177e4SLinus Torvalds	subq $3,8,$3
431da177e4SLinus Torvalds	.align 4
441da177e4SLinus Torvalds$37:
4585250231SAl Viro	EXI( ldq_u $1,0($17) )
4685250231SAl Viro	EXO( ldq_u $2,0($16) )
4785250231SAl Viro	extbl $1,$17,$1
4885250231SAl Viro	mskbl $2,$16,$2
4985250231SAl Viro	insbl $1,$16,$1
501da177e4SLinus Torvalds	addq $3,1,$3
511da177e4SLinus Torvalds	bis $1,$2,$1
5285250231SAl Viro	EXO( stq_u $1,0($16) )
531da177e4SLinus Torvalds	subq $0,1,$0
5485250231SAl Viro	addq $16,1,$16
5585250231SAl Viro	addq $17,1,$17
561da177e4SLinus Torvalds	beq $0,$41
571da177e4SLinus Torvalds	bne $3,$37
581da177e4SLinus Torvalds$36:
5985250231SAl Viro	and $17,7,$1
601da177e4SLinus Torvalds	bic $0,7,$4
611da177e4SLinus Torvalds	beq $1,$43
621da177e4SLinus Torvalds	beq $4,$48
6385250231SAl Viro	EXI( ldq_u $3,0($17) )
641da177e4SLinus Torvalds	.align 4
651da177e4SLinus Torvalds$50:
6685250231SAl Viro	EXI( ldq_u $2,8($17) )
671da177e4SLinus Torvalds	subq $4,8,$4
6885250231SAl Viro	extql $3,$17,$3
6985250231SAl Viro	extqh $2,$17,$1
701da177e4SLinus Torvalds	bis $3,$1,$1
7185250231SAl Viro	EXO( stq $1,0($16) )
7285250231SAl Viro	addq $17,8,$17
731da177e4SLinus Torvalds	subq $0,8,$0
7485250231SAl Viro	addq $16,8,$16
751da177e4SLinus Torvalds	bis $2,$2,$3
761da177e4SLinus Torvalds	bne $4,$50
771da177e4SLinus Torvalds$48:
781da177e4SLinus Torvalds	beq $0,$41
791da177e4SLinus Torvalds	.align 4
801da177e4SLinus Torvalds$57:
8185250231SAl Viro	EXI( ldq_u $1,0($17) )
8285250231SAl Viro	EXO( ldq_u $2,0($16) )
8385250231SAl Viro	extbl $1,$17,$1
8485250231SAl Viro	mskbl $2,$16,$2
8585250231SAl Viro	insbl $1,$16,$1
861da177e4SLinus Torvalds	bis $1,$2,$1
8785250231SAl Viro	EXO( stq_u $1,0($16) )
881da177e4SLinus Torvalds	subq $0,1,$0
8985250231SAl Viro	addq $16,1,$16
9085250231SAl Viro	addq $17,1,$17
911da177e4SLinus Torvalds	bne $0,$57
921da177e4SLinus Torvalds	br $31,$41
931da177e4SLinus Torvalds	.align 4
941da177e4SLinus Torvalds$43:
951da177e4SLinus Torvalds	beq $4,$65
961da177e4SLinus Torvalds	.align 4
971da177e4SLinus Torvalds$66:
9885250231SAl Viro	EXI( ldq $1,0($17) )
991da177e4SLinus Torvalds	subq $4,8,$4
10085250231SAl Viro	EXO( stq $1,0($16) )
10185250231SAl Viro	addq $17,8,$17
1021da177e4SLinus Torvalds	subq $0,8,$0
10385250231SAl Viro	addq $16,8,$16
1041da177e4SLinus Torvalds	bne $4,$66
1051da177e4SLinus Torvalds$65:
1061da177e4SLinus Torvalds	beq $0,$41
10785250231SAl Viro	EXI( ldq $2,0($17) )
10885250231SAl Viro	EXO( ldq $1,0($16) )
1091da177e4SLinus Torvalds	mskql $2,$0,$2
1101da177e4SLinus Torvalds	mskqh $1,$0,$1
1111da177e4SLinus Torvalds	bis $2,$1,$2
11285250231SAl Viro	EXO( stq $2,0($16) )
1131da177e4SLinus Torvalds	bis $31,$31,$0
1141da177e4SLinus Torvalds$41:
1151da177e4SLinus Torvalds$35:
1161da177e4SLinus Torvalds$exitin:
117085354f9SAl Viro$exitout:
11885250231SAl Viro	ret $31,($26),1
1191da177e4SLinus Torvalds
1201da177e4SLinus Torvalds	.end __copy_user
12100fc0e0dSAl ViroEXPORT_SYMBOL(__copy_user)
122