OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [ia64/] [lib/] [clear_user.S] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * This routine clears to zero a linear memory buffer in user space.
3
 *
4
 * Inputs:
5
 *      in0:    address of buffer
6
 *      in1:    length of buffer in bytes
7
 * Outputs:
8
 *      r8:     number of bytes that didn't get cleared due to a fault
9
 *
10
 * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
11
 *      Stephane Eranian 
12
 */
13
 
14
#include 
15
 
16
//
17
// arguments
18
//
19
#define buf             r32
20
#define len             r33
21
 
22
//
23
// local registers
24
//
25
#define cnt             r16
26
#define buf2            r17
27
#define saved_lc        r18
28
#define saved_pfs       r19
29
#define tmp             r20
30
#define len2            r21
31
#define len3            r22
32
 
33
//
34
// Theory of operations:
35
//      - we check whether or not the buffer is small, i.e., less than 17
36
//        in which case we do the byte by byte loop.
37
//
38
//      - Otherwise we go progressively from 1 byte store to 8byte store in
39
//        the head part, the body is a 16byte store loop and we finish we the
40
//        tail for the last 15 bytes.
41
//        The good point about this breakdown is that the long buffer handling
42
//        contains only 2 branches.
43
//
44
//      The reason for not using shifting & masking for both the head and the
45
//      tail is to stay semantically correct. This routine is not supposed
46
//      to write bytes outside of the buffer. While most of the time this would
47
//      be ok, we can't tolerate a mistake. A classical example is the case
48
//      of multithreaded code were to the extra bytes touched is actually owned
49
//      by another thread which runs concurrently to ours. Another, less likely,
50
//      example is with device drivers where reading an I/O mapped location may
51
//      have side effects (same thing for writing).
52
//
53
 
54
GLOBAL_ENTRY(__do_clear_user)
55
        .prologue
56
        .save ar.pfs, saved_pfs
57
        alloc   saved_pfs=ar.pfs,2,0,0,0
58
        cmp.eq p6,p0=r0,len             // check for zero length
59
        .save ar.lc, saved_lc
60
        mov saved_lc=ar.lc              // preserve ar.lc (slow)
61
        .body
62
        ;;                              // avoid WAW on CFM
63
        adds tmp=-1,len                 // br.ctop is repeat/until
64
        mov ret0=len                    // return value is length at this point
65
(p6)    br.ret.spnt.many rp
66
        ;;
67
        cmp.lt p6,p0=16,len             // if len > 16 then long memset
68
        mov ar.lc=tmp                   // initialize lc for small count
69
(p6)    br.cond.dptk .long_do_clear
70
        ;;                              // WAR on ar.lc
71
        //
72
        // worst case 16 iterations, avg 8 iterations
73
        //
74
        // We could have played with the predicates to use the extra
75
        // M slot for 2 stores/iteration but the cost the initialization
76
        // the various counters compared to how long the loop is supposed
77
        // to last on average does not make this solution viable.
78
        //
79
1:
80
        EX( .Lexit1, st1 [buf]=r0,1 )
81
        adds len=-1,len                 // countdown length using len
82
        br.cloop.dptk 1b
83
        ;;                              // avoid RAW on ar.lc
84
        //
85
        // .Lexit4: comes from byte by byte loop
86
        //          len contains bytes left
87
.Lexit1:
88
        mov ret0=len                    // faster than using ar.lc
89
        mov ar.lc=saved_lc
90
        br.ret.sptk.many rp             // end of short clear_user
91
 
92
 
93
        //
94
        // At this point we know we have more than 16 bytes to copy
95
        // so we focus on alignment (no branches required)
96
        //
97
        // The use of len/len2 for countdown of the number of bytes left
98
        // instead of ret0 is due to the fact that the exception code
99
        // changes the values of r8.
100
        //
101
.long_do_clear:
102
        tbit.nz p6,p0=buf,0             // odd alignment (for long_do_clear)
103
        ;;
104
        EX( .Lexit3, (p6) st1 [buf]=r0,1 )      // 1-byte aligned
105
(p6)    adds len=-1,len;;               // sync because buf is modified
106
        tbit.nz p6,p0=buf,1
107
        ;;
108
        EX( .Lexit3, (p6) st2 [buf]=r0,2 )      // 2-byte aligned
109
(p6)    adds len=-2,len;;
110
        tbit.nz p6,p0=buf,2
111
        ;;
112
        EX( .Lexit3, (p6) st4 [buf]=r0,4 )      // 4-byte aligned
113
(p6)    adds len=-4,len;;
114
        tbit.nz p6,p0=buf,3
115
        ;;
116
        EX( .Lexit3, (p6) st8 [buf]=r0,8 )      // 8-byte aligned
117
(p6)    adds len=-8,len;;
118
        shr.u cnt=len,4         // number of 128-bit (2x64bit) words
119
        ;;
120
        cmp.eq p6,p0=r0,cnt
121
        adds tmp=-1,cnt
122
(p6)    br.cond.dpnt .dotail            // we have less than 16 bytes left
123
        ;;
124
        adds buf2=8,buf                 // setup second base pointer
125
        mov ar.lc=tmp
126
        ;;
127
 
128
        //
129
        // 16bytes/iteration core loop
130
        //
131
        // The second store can never generate a fault because
132
        // we come into the loop only when we are 16-byte aligned.
133
        // This means that if we cross a page then it will always be
134
        // in the first store and never in the second.
135
        //
136
        //
137
        // We need to keep track of the remaining length. A possible (optimistic)
138
        // way would be to use ar.lc and derive how many byte were left by
139
        // doing : left= 16*ar.lc + 16.  this would avoid the addition at
140
        // every iteration.
141
        // However we need to keep the synchronization point. A template
142
        // M;;MB does not exist and thus we can keep the addition at no
143
        // extra cycle cost (use a nop slot anyway). It also simplifies the
144
        // (unlikely)  error recovery code
145
        //
146
 
147
2:      EX(.Lexit3, st8 [buf]=r0,16 )
148
        ;;                              // needed to get len correct when error
149
        st8 [buf2]=r0,16
150
        adds len=-16,len
151
        br.cloop.dptk 2b
152
        ;;
153
        mov ar.lc=saved_lc
154
        //
155
        // tail correction based on len only
156
        //
157
        // We alternate the use of len3,len2 to allow parallelism and correct
158
        // error handling. We also reuse p6/p7 to return correct value.
159
        // The addition of len2/len3 does not cost anything more compared to
160
        // the regular memset as we had empty slots.
161
        //
162
.dotail:
163
        mov len2=len                    // for parallelization of error handling
164
        mov len3=len
165
        tbit.nz p6,p0=len,3
166
        ;;
167
        EX( .Lexit2, (p6) st8 [buf]=r0,8 )      // at least 8 bytes
168
(p6)    adds len3=-8,len2
169
        tbit.nz p7,p6=len,2
170
        ;;
171
        EX( .Lexit2, (p7) st4 [buf]=r0,4 )      // at least 4 bytes
172
(p7)    adds len2=-4,len3
173
        tbit.nz p6,p7=len,1
174
        ;;
175
        EX( .Lexit2, (p6) st2 [buf]=r0,2 )      // at least 2 bytes
176
(p6)    adds len3=-2,len2
177
        tbit.nz p7,p6=len,0
178
        ;;
179
        EX( .Lexit2, (p7) st1 [buf]=r0 )        // only 1 byte left
180
        mov ret0=r0                             // success
181
        br.ret.sptk.many rp                     // end of most likely path
182
 
183
        //
184
        // Outlined error handling code
185
        //
186
 
187
        //
188
        // .Lexit3: comes from core loop, need restore pr/lc
189
        //          len contains bytes left
190
        //
191
        //
192
        // .Lexit2:
193
        //      if p6 -> coming from st8 or st2 : len2 contains what's left
194
        //      if p7 -> coming from st4 or st1 : len3 contains what's left
195
        // We must restore lc/pr even though might not have been used.
196
.Lexit2:
197
        .pred.rel "mutex", p6, p7
198
(p6)    mov len=len2
199
(p7)    mov len=len3
200
        ;;
201
        //
202
        // .Lexit4: comes from head, need not restore pr/lc
203
        //          len contains bytes left
204
        //
205
.Lexit3:
206
        mov ret0=len
207
        mov ar.lc=saved_lc
208
        br.ret.sptk.many rp
209
END(__do_clear_user)

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.