18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/alpha/lib/copy_user.S 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copy to/from user space, handling exceptions as we go.. This 68c2ecf20Sopenharmony_ci * isn't exactly pretty. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This is essentially the same as "memcpy()", but with a few twists. 98c2ecf20Sopenharmony_ci * Notably, we have to make sure that $0 is always up-to-date and 108c2ecf20Sopenharmony_ci * contains the right "bytes left to copy" value (and that it is updated 118c2ecf20Sopenharmony_ci * only _after_ a successful copy). There is also some rather minor 128c2ecf20Sopenharmony_ci * exception setup stuff.. 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <asm/export.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* Allow an exception for an insn; exit if we get one. */ 188c2ecf20Sopenharmony_ci#define EXI(x,y...) \ 198c2ecf20Sopenharmony_ci 99: x,##y; \ 208c2ecf20Sopenharmony_ci .section __ex_table,"a"; \ 218c2ecf20Sopenharmony_ci .long 99b - .; \ 228c2ecf20Sopenharmony_ci lda $31, $exitin-99b($31); \ 238c2ecf20Sopenharmony_ci .previous 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define EXO(x,y...) \ 268c2ecf20Sopenharmony_ci 99: x,##y; \ 278c2ecf20Sopenharmony_ci .section __ex_table,"a"; \ 288c2ecf20Sopenharmony_ci .long 99b - .; \ 298c2ecf20Sopenharmony_ci lda $31, $exitout-99b($31); \ 308c2ecf20Sopenharmony_ci .previous 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci .set noat 338c2ecf20Sopenharmony_ci .align 4 348c2ecf20Sopenharmony_ci .globl __copy_user 358c2ecf20Sopenharmony_ci .ent __copy_user 368c2ecf20Sopenharmony_ci__copy_user: 378c2ecf20Sopenharmony_ci .prologue 0 388c2ecf20Sopenharmony_ci mov $18,$0 398c2ecf20Sopenharmony_ci and $16,7,$3 408c2ecf20Sopenharmony_ci beq $0,$35 418c2ecf20Sopenharmony_ci beq $3,$36 428c2ecf20Sopenharmony_ci subq $3,8,$3 438c2ecf20Sopenharmony_ci .align 4 448c2ecf20Sopenharmony_ci$37: 458c2ecf20Sopenharmony_ci EXI( ldq_u $1,0($17) ) 468c2ecf20Sopenharmony_ci EXO( ldq_u $2,0($16) ) 478c2ecf20Sopenharmony_ci extbl $1,$17,$1 488c2ecf20Sopenharmony_ci mskbl $2,$16,$2 498c2ecf20Sopenharmony_ci insbl $1,$16,$1 508c2ecf20Sopenharmony_ci addq $3,1,$3 518c2ecf20Sopenharmony_ci bis $1,$2,$1 528c2ecf20Sopenharmony_ci EXO( stq_u $1,0($16) ) 538c2ecf20Sopenharmony_ci subq $0,1,$0 548c2ecf20Sopenharmony_ci addq $16,1,$16 558c2ecf20Sopenharmony_ci addq $17,1,$17 568c2ecf20Sopenharmony_ci beq $0,$41 578c2ecf20Sopenharmony_ci bne $3,$37 588c2ecf20Sopenharmony_ci$36: 598c2ecf20Sopenharmony_ci and $17,7,$1 608c2ecf20Sopenharmony_ci bic $0,7,$4 618c2ecf20Sopenharmony_ci beq $1,$43 628c2ecf20Sopenharmony_ci beq $4,$48 638c2ecf20Sopenharmony_ci EXI( ldq_u $3,0($17) ) 648c2ecf20Sopenharmony_ci .align 4 658c2ecf20Sopenharmony_ci$50: 668c2ecf20Sopenharmony_ci EXI( ldq_u $2,8($17) ) 678c2ecf20Sopenharmony_ci subq $4,8,$4 688c2ecf20Sopenharmony_ci extql $3,$17,$3 698c2ecf20Sopenharmony_ci extqh $2,$17,$1 708c2ecf20Sopenharmony_ci bis $3,$1,$1 718c2ecf20Sopenharmony_ci EXO( stq $1,0($16) ) 728c2ecf20Sopenharmony_ci addq $17,8,$17 738c2ecf20Sopenharmony_ci subq $0,8,$0 748c2ecf20Sopenharmony_ci addq $16,8,$16 758c2ecf20Sopenharmony_ci bis $2,$2,$3 768c2ecf20Sopenharmony_ci bne $4,$50 778c2ecf20Sopenharmony_ci$48: 788c2ecf20Sopenharmony_ci beq $0,$41 798c2ecf20Sopenharmony_ci .align 4 808c2ecf20Sopenharmony_ci$57: 818c2ecf20Sopenharmony_ci EXI( ldq_u $1,0($17) ) 828c2ecf20Sopenharmony_ci EXO( ldq_u $2,0($16) ) 838c2ecf20Sopenharmony_ci extbl $1,$17,$1 848c2ecf20Sopenharmony_ci mskbl $2,$16,$2 858c2ecf20Sopenharmony_ci insbl $1,$16,$1 868c2ecf20Sopenharmony_ci bis $1,$2,$1 878c2ecf20Sopenharmony_ci EXO( stq_u $1,0($16) ) 888c2ecf20Sopenharmony_ci subq $0,1,$0 898c2ecf20Sopenharmony_ci addq $16,1,$16 908c2ecf20Sopenharmony_ci addq $17,1,$17 918c2ecf20Sopenharmony_ci bne $0,$57 928c2ecf20Sopenharmony_ci br $31,$41 938c2ecf20Sopenharmony_ci .align 4 948c2ecf20Sopenharmony_ci$43: 958c2ecf20Sopenharmony_ci beq $4,$65 968c2ecf20Sopenharmony_ci .align 4 978c2ecf20Sopenharmony_ci$66: 988c2ecf20Sopenharmony_ci EXI( ldq $1,0($17) ) 998c2ecf20Sopenharmony_ci subq $4,8,$4 1008c2ecf20Sopenharmony_ci EXO( stq $1,0($16) ) 1018c2ecf20Sopenharmony_ci addq $17,8,$17 1028c2ecf20Sopenharmony_ci subq $0,8,$0 1038c2ecf20Sopenharmony_ci addq $16,8,$16 1048c2ecf20Sopenharmony_ci bne $4,$66 1058c2ecf20Sopenharmony_ci$65: 1068c2ecf20Sopenharmony_ci beq $0,$41 1078c2ecf20Sopenharmony_ci EXI( ldq $2,0($17) ) 1088c2ecf20Sopenharmony_ci EXO( ldq $1,0($16) ) 1098c2ecf20Sopenharmony_ci mskql $2,$0,$2 1108c2ecf20Sopenharmony_ci mskqh $1,$0,$1 1118c2ecf20Sopenharmony_ci bis $2,$1,$2 1128c2ecf20Sopenharmony_ci EXO( stq $2,0($16) ) 1138c2ecf20Sopenharmony_ci bis $31,$31,$0 1148c2ecf20Sopenharmony_ci$41: 1158c2ecf20Sopenharmony_ci$35: 1168c2ecf20Sopenharmony_ci$exitin: 1178c2ecf20Sopenharmony_ci$exitout: 1188c2ecf20Sopenharmony_ci ret $31,($26),1 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci .end __copy_user 1218c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__copy_user) 122