162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/alpha/lib/copy_user.S 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copy to/from user space, handling exceptions as we go.. This 662306a36Sopenharmony_ci * isn't exactly pretty. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This is essentially the same as "memcpy()", but with a few twists. 962306a36Sopenharmony_ci * Notably, we have to make sure that $0 is always up-to-date and 1062306a36Sopenharmony_ci * contains the right "bytes left to copy" value (and that it is updated 1162306a36Sopenharmony_ci * only _after_ a successful copy). There is also some rather minor 1262306a36Sopenharmony_ci * exception setup stuff.. 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/export.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* Allow an exception for an insn; exit if we get one. */ 1862306a36Sopenharmony_ci#define EXI(x,y...) \ 1962306a36Sopenharmony_ci 99: x,##y; \ 2062306a36Sopenharmony_ci .section __ex_table,"a"; \ 2162306a36Sopenharmony_ci .long 99b - .; \ 2262306a36Sopenharmony_ci lda $31, $exitin-99b($31); \ 2362306a36Sopenharmony_ci .previous 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define EXO(x,y...) \ 2662306a36Sopenharmony_ci 99: x,##y; \ 2762306a36Sopenharmony_ci .section __ex_table,"a"; \ 2862306a36Sopenharmony_ci .long 99b - .; \ 2962306a36Sopenharmony_ci lda $31, $exitout-99b($31); \ 3062306a36Sopenharmony_ci .previous 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci .set noat 3362306a36Sopenharmony_ci .align 4 3462306a36Sopenharmony_ci .globl __copy_user 3562306a36Sopenharmony_ci .ent __copy_user 3662306a36Sopenharmony_ci__copy_user: 3762306a36Sopenharmony_ci .prologue 0 3862306a36Sopenharmony_ci mov $18,$0 3962306a36Sopenharmony_ci and $16,7,$3 4062306a36Sopenharmony_ci beq $0,$35 4162306a36Sopenharmony_ci beq $3,$36 4262306a36Sopenharmony_ci subq $3,8,$3 4362306a36Sopenharmony_ci .align 4 4462306a36Sopenharmony_ci$37: 4562306a36Sopenharmony_ci EXI( ldq_u $1,0($17) ) 4662306a36Sopenharmony_ci EXO( ldq_u $2,0($16) ) 4762306a36Sopenharmony_ci extbl $1,$17,$1 4862306a36Sopenharmony_ci mskbl $2,$16,$2 4962306a36Sopenharmony_ci insbl $1,$16,$1 5062306a36Sopenharmony_ci addq $3,1,$3 5162306a36Sopenharmony_ci bis $1,$2,$1 5262306a36Sopenharmony_ci EXO( stq_u $1,0($16) ) 5362306a36Sopenharmony_ci subq $0,1,$0 5462306a36Sopenharmony_ci addq $16,1,$16 5562306a36Sopenharmony_ci addq $17,1,$17 5662306a36Sopenharmony_ci beq $0,$41 5762306a36Sopenharmony_ci bne $3,$37 5862306a36Sopenharmony_ci$36: 5962306a36Sopenharmony_ci and $17,7,$1 6062306a36Sopenharmony_ci bic $0,7,$4 6162306a36Sopenharmony_ci beq $1,$43 6262306a36Sopenharmony_ci beq $4,$48 6362306a36Sopenharmony_ci EXI( ldq_u $3,0($17) ) 6462306a36Sopenharmony_ci .align 4 6562306a36Sopenharmony_ci$50: 6662306a36Sopenharmony_ci EXI( ldq_u $2,8($17) ) 6762306a36Sopenharmony_ci subq $4,8,$4 6862306a36Sopenharmony_ci extql $3,$17,$3 6962306a36Sopenharmony_ci extqh $2,$17,$1 7062306a36Sopenharmony_ci bis $3,$1,$1 7162306a36Sopenharmony_ci EXO( stq $1,0($16) ) 7262306a36Sopenharmony_ci addq $17,8,$17 7362306a36Sopenharmony_ci subq $0,8,$0 7462306a36Sopenharmony_ci addq $16,8,$16 7562306a36Sopenharmony_ci bis $2,$2,$3 7662306a36Sopenharmony_ci bne $4,$50 7762306a36Sopenharmony_ci$48: 7862306a36Sopenharmony_ci beq $0,$41 7962306a36Sopenharmony_ci .align 4 8062306a36Sopenharmony_ci$57: 8162306a36Sopenharmony_ci EXI( ldq_u $1,0($17) ) 8262306a36Sopenharmony_ci EXO( ldq_u $2,0($16) ) 8362306a36Sopenharmony_ci extbl $1,$17,$1 8462306a36Sopenharmony_ci mskbl $2,$16,$2 8562306a36Sopenharmony_ci insbl $1,$16,$1 8662306a36Sopenharmony_ci bis $1,$2,$1 8762306a36Sopenharmony_ci EXO( stq_u $1,0($16) ) 8862306a36Sopenharmony_ci subq $0,1,$0 8962306a36Sopenharmony_ci addq $16,1,$16 9062306a36Sopenharmony_ci addq $17,1,$17 9162306a36Sopenharmony_ci bne $0,$57 9262306a36Sopenharmony_ci br $31,$41 9362306a36Sopenharmony_ci .align 4 9462306a36Sopenharmony_ci$43: 9562306a36Sopenharmony_ci beq $4,$65 9662306a36Sopenharmony_ci .align 4 9762306a36Sopenharmony_ci$66: 9862306a36Sopenharmony_ci EXI( ldq $1,0($17) ) 9962306a36Sopenharmony_ci subq $4,8,$4 10062306a36Sopenharmony_ci EXO( stq $1,0($16) ) 10162306a36Sopenharmony_ci addq $17,8,$17 10262306a36Sopenharmony_ci subq $0,8,$0 10362306a36Sopenharmony_ci addq $16,8,$16 10462306a36Sopenharmony_ci bne $4,$66 10562306a36Sopenharmony_ci$65: 10662306a36Sopenharmony_ci beq $0,$41 10762306a36Sopenharmony_ci EXI( ldq $2,0($17) ) 10862306a36Sopenharmony_ci EXO( ldq $1,0($16) ) 10962306a36Sopenharmony_ci mskql $2,$0,$2 11062306a36Sopenharmony_ci mskqh $1,$0,$1 11162306a36Sopenharmony_ci bis $2,$1,$2 11262306a36Sopenharmony_ci EXO( stq $2,0($16) ) 11362306a36Sopenharmony_ci bis $31,$31,$0 11462306a36Sopenharmony_ci$41: 11562306a36Sopenharmony_ci$35: 11662306a36Sopenharmony_ci$exitin: 11762306a36Sopenharmony_ci$exitout: 11862306a36Sopenharmony_ci ret $31,($26),1 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci .end __copy_user 12162306a36Sopenharmony_ciEXPORT_SYMBOL(__copy_user) 122