162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/alpha/lib/clear_user.S 462306a36Sopenharmony_ci * Contributed by Richard Henderson <rth@tamu.edu> 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Zero user space, handling exceptions as we go. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * We have to make sure that $0 is always up-to-date and contains the 962306a36Sopenharmony_ci * right "bytes left to zero" value (and that it is updated only _after_ 1062306a36Sopenharmony_ci * a successful copy). There is also some rather minor exception setup 1162306a36Sopenharmony_ci * stuff. 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci#include <linux/export.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* Allow an exception for an insn; exit if we get one. */ 1662306a36Sopenharmony_ci#define EX(x,y...) \ 1762306a36Sopenharmony_ci 99: x,##y; \ 1862306a36Sopenharmony_ci .section __ex_table,"a"; \ 1962306a36Sopenharmony_ci .long 99b - .; \ 2062306a36Sopenharmony_ci lda $31, $exception-99b($31); \ 2162306a36Sopenharmony_ci .previous 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci .set noat 2462306a36Sopenharmony_ci .set noreorder 2562306a36Sopenharmony_ci .align 4 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci .globl __clear_user 2862306a36Sopenharmony_ci .ent __clear_user 2962306a36Sopenharmony_ci .frame $30, 0, $26 3062306a36Sopenharmony_ci .prologue 0 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci$loop: 3362306a36Sopenharmony_ci and $1, 3, $4 # e0 : 3462306a36Sopenharmony_ci beq $4, 1f # .. e1 : 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci0: EX( stq_u $31, 0($16) ) # e0 : zero one word 3762306a36Sopenharmony_ci subq $0, 8, $0 # .. e1 : 3862306a36Sopenharmony_ci subq $4, 1, $4 # e0 : 3962306a36Sopenharmony_ci addq $16, 8, $16 # .. e1 : 4062306a36Sopenharmony_ci bne $4, 0b # e1 : 4162306a36Sopenharmony_ci unop # : 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci1: bic $1, 3, $1 # e0 : 4462306a36Sopenharmony_ci beq $1, $tail # .. e1 : 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci2: EX( stq_u $31, 0($16) ) # e0 : zero four words 4762306a36Sopenharmony_ci subq $0, 8, $0 # .. e1 : 4862306a36Sopenharmony_ci EX( stq_u $31, 8($16) ) # e0 : 4962306a36Sopenharmony_ci subq $0, 8, $0 # .. e1 : 5062306a36Sopenharmony_ci EX( stq_u $31, 16($16) ) # e0 : 5162306a36Sopenharmony_ci subq $0, 8, $0 # .. e1 : 5262306a36Sopenharmony_ci EX( stq_u $31, 24($16) ) # e0 : 5362306a36Sopenharmony_ci subq $0, 8, $0 # .. e1 : 5462306a36Sopenharmony_ci subq $1, 4, $1 # e0 : 5562306a36Sopenharmony_ci addq $16, 32, $16 # .. e1 : 5662306a36Sopenharmony_ci bne $1, 2b # e1 : 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci$tail: 5962306a36Sopenharmony_ci bne $2, 1f # e1 : is there a tail to do? 6062306a36Sopenharmony_ci ret $31, ($26), 1 # .. e1 : 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci1: EX( ldq_u $5, 0($16) ) # e0 : 6362306a36Sopenharmony_ci clr $0 # .. e1 : 6462306a36Sopenharmony_ci nop # e1 : 6562306a36Sopenharmony_ci mskqh $5, $0, $5 # e0 : 6662306a36Sopenharmony_ci EX( stq_u $5, 0($16) ) # e0 : 6762306a36Sopenharmony_ci ret $31, ($26), 1 # .. e1 : 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci__clear_user: 7062306a36Sopenharmony_ci and $17, $17, $0 7162306a36Sopenharmony_ci and $16, 7, $4 # e0 : find dest misalignment 7262306a36Sopenharmony_ci beq $0, $zerolength # .. e1 : 7362306a36Sopenharmony_ci addq $0, $4, $1 # e0 : bias counter 7462306a36Sopenharmony_ci and $1, 7, $2 # e1 : number of bytes in tail 7562306a36Sopenharmony_ci srl $1, 3, $1 # e0 : 7662306a36Sopenharmony_ci beq $4, $loop # .. e1 : 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci EX( ldq_u $5, 0($16) ) # e0 : load dst word to mask back in 7962306a36Sopenharmony_ci beq $1, $oneword # .. e1 : sub-word store? 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci mskql $5, $16, $5 # e0 : take care of misaligned head 8262306a36Sopenharmony_ci addq $16, 8, $16 # .. e1 : 8362306a36Sopenharmony_ci EX( stq_u $5, -8($16) ) # e0 : 8462306a36Sopenharmony_ci addq $0, $4, $0 # .. e1 : bytes left -= 8 - misalignment 8562306a36Sopenharmony_ci subq $1, 1, $1 # e0 : 8662306a36Sopenharmony_ci subq $0, 8, $0 # .. e1 : 8762306a36Sopenharmony_ci br $loop # e1 : 8862306a36Sopenharmony_ci unop # : 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci$oneword: 9162306a36Sopenharmony_ci mskql $5, $16, $4 # e0 : 9262306a36Sopenharmony_ci mskqh $5, $2, $5 # e0 : 9362306a36Sopenharmony_ci or $5, $4, $5 # e1 : 9462306a36Sopenharmony_ci EX( stq_u $5, 0($16) ) # e0 : 9562306a36Sopenharmony_ci clr $0 # .. e1 : 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci$zerolength: 9862306a36Sopenharmony_ci$exception: 9962306a36Sopenharmony_ci ret $31, ($26), 1 # .. e1 : 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci .end __clear_user 10262306a36Sopenharmony_ci EXPORT_SYMBOL(__clear_user) 103