Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[cascardo/linux.git] / arch / alpha / lib / clear_user.S
1 /*
2  * arch/alpha/lib/clear_user.S
3  * Contributed by Richard Henderson <rth@tamu.edu>
4  *
5  * Zero user space, handling exceptions as we go.
6  *
7  * We have to make sure that $0 is always up-to-date and contains the
8  * right "bytes left to zero" value (and that it is updated only _after_
9  * a successful copy).  There is also some rather minor exception setup
10  * stuff.
11  *
12  * NOTE! This is not directly C-callable, because the calling semantics
13  * are different:
14  *
15  * Inputs:
16  *      length in $0
17  *      destination address in $6
18  *      exception pointer in $7
19  *      return address in $28 (exceptions expect it there)
20  *
21  * Outputs:
22  *      bytes left to copy in $0
23  *
24  * Clobbers:
25  *      $1,$2,$3,$4,$5,$6
26  */
27 #include <asm/export.h>
28
29 /* Allow an exception for an insn; exit if we get one.  */
30 #define EX(x,y...)                      \
31         99: x,##y;                      \
32         .section __ex_table,"a";        \
33         .long 99b - .;                  \
34         lda $31, $exception-99b($31);   \
35         .previous
36
37         .set noat
38         .set noreorder
39         .align 4
40
41         .globl __do_clear_user
42         .ent __do_clear_user
43         .frame  $30, 0, $28
44         .prologue 0
45
46 $loop:
47         and     $1, 3, $4       # e0    :
48         beq     $4, 1f          # .. e1 :
49
50 0:      EX( stq_u $31, 0($6) )  # e0    : zero one word
51         subq    $0, 8, $0       # .. e1 :
52         subq    $4, 1, $4       # e0    :
53         addq    $6, 8, $6       # .. e1 :
54         bne     $4, 0b          # e1    :
55         unop                    #       :
56
57 1:      bic     $1, 3, $1       # e0    :
58         beq     $1, $tail       # .. e1 :
59
60 2:      EX( stq_u $31, 0($6) )  # e0    : zero four words
61         subq    $0, 8, $0       # .. e1 :
62         EX( stq_u $31, 8($6) )  # e0    :
63         subq    $0, 8, $0       # .. e1 :
64         EX( stq_u $31, 16($6) ) # e0    :
65         subq    $0, 8, $0       # .. e1 :
66         EX( stq_u $31, 24($6) ) # e0    :
67         subq    $0, 8, $0       # .. e1 :
68         subq    $1, 4, $1       # e0    :
69         addq    $6, 32, $6      # .. e1 :
70         bne     $1, 2b          # e1    :
71
72 $tail:
73         bne     $2, 1f          # e1    : is there a tail to do?
74         ret     $31, ($28), 1   # .. e1 :
75
76 1:      EX( ldq_u $5, 0($6) )   # e0    :
77         clr     $0              # .. e1 :
78         nop                     # e1    :
79         mskqh   $5, $0, $5      # e0    :
80         EX( stq_u $5, 0($6) )   # e0    :
81         ret     $31, ($28), 1   # .. e1 :
82
83 __do_clear_user:
84         and     $6, 7, $4       # e0    : find dest misalignment
85         beq     $0, $zerolength # .. e1 :
86         addq    $0, $4, $1      # e0    : bias counter
87         and     $1, 7, $2       # e1    : number of bytes in tail
88         srl     $1, 3, $1       # e0    :
89         beq     $4, $loop       # .. e1 :
90
91         EX( ldq_u $5, 0($6) )   # e0    : load dst word to mask back in
92         beq     $1, $oneword    # .. e1 : sub-word store?
93
94         mskql   $5, $6, $5      # e0    : take care of misaligned head
95         addq    $6, 8, $6       # .. e1 :
96         EX( stq_u $5, -8($6) )  # e0    :
97         addq    $0, $4, $0      # .. e1 : bytes left -= 8 - misalignment
98         subq    $1, 1, $1       # e0    :
99         subq    $0, 8, $0       # .. e1 :
100         br      $loop           # e1    :
101         unop                    #       :
102
103 $oneword:
104         mskql   $5, $6, $4      # e0    :
105         mskqh   $5, $2, $5      # e0    :
106         or      $5, $4, $5      # e1    :
107         EX( stq_u $5, 0($6) )   # e0    :
108         clr     $0              # .. e1 :
109
110 $zerolength:
111 $exception:
112         ret     $31, ($28), 1   # .. e1 :
113
114         .end __do_clear_user
115         EXPORT_SYMBOL(__do_clear_user)