Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / alpha / alphaev6 / memset.S
blobf871561fda6ed4efba10645b26fffb421b41660e
1 /* Copyright (C) 2000-2014 Free Software Foundation, Inc.
2    Contributed by Richard Henderson (rth@tamu.edu)
3    EV6 optimized by Rick Gorton <rick.gorton@alpha-processor.com>.
4    This file is part of the GNU C Library.
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library.  If not, see
18    <http://www.gnu.org/licenses/>.  */
20 #include <sysdep.h>
22         .arch ev6
23         .set noat
24         .set noreorder
26 ENTRY(memset)
27 #ifdef PROF
28         ldgp    gp, 0(pv)
29         lda     AT, _mcount
30         jsr     AT, (AT), _mcount
31         .prologue 1
32 #else
33         .prologue 0
34 #endif
36         /*
37          * Serious stalling happens.  The only way to mitigate this is to
38          * undertake a major re-write to interleave the constant materialization
39          * with other parts of the fall-through code.  This is important, even
40          * though it makes maintenance tougher.
41          * Do this later.
42          */
43         and     $17, 255, $1    # E : 00000000000000ch
44         insbl   $17, 1, $2      # U : 000000000000ch00
45         mov     $16, $0         # E : return value
46         ble     $18, $end       # U : zero length requested?
48         addq    $18, $16, $6    # E : max address to write to
49         or      $1, $2, $17     # E : 000000000000chch
50         insbl   $1, 2, $3       # U : 0000000000ch0000
51         insbl   $1, 3, $4       # U : 00000000ch000000
53         or      $3, $4, $3      # E : 00000000chch0000
54         inswl   $17, 4, $5      # U : 0000chch00000000
55         xor     $16, $6, $1     # E : will complete write be within one quadword?
56         inswl   $17, 6, $2      # U : chch000000000000
58         or      $17, $3, $17    # E : 00000000chchchch
59         or      $2, $5, $2      # E : chchchch00000000
60         bic     $1, 7, $1       # E : fit within a single quadword?
61         and     $16, 7, $3      # E : Target addr misalignment
63         or      $17, $2, $17    # E : chchchchchchchch
64         beq     $1, $within_quad # U :
65         nop                     # E :
66         beq     $3, $aligned    # U : target is 0mod8
68         /*
69          * Target address is misaligned, and won't fit within a quadword.
70          */
71         ldq_u   $4, 0($16)      # L : Fetch first partial
72         mov     $16, $5         # E : Save the address
73         insql   $17, $16, $2    # U : Insert new bytes
74         subq    $3, 8, $3       # E : Invert (for addressing uses)
76         addq    $18, $3, $18    # E : $18 is new count ($3 is negative)
77         mskql   $4, $16, $4     # U : clear relevant parts of the quad
78         subq    $16, $3, $16    # E : $16 is new aligned destination
79         or      $2, $4, $1      # E : Final bytes
81         nop
82         stq_u   $1,0($5)        # L : Store result
83         nop
84         nop
86         .align 4
87 $aligned:
88         /*
89          * We are now guaranteed to be quad aligned, with at least
90          * one partial quad to write.
91          */
93         sra     $18, 3, $3      # U : Number of remaining quads to write
94         and     $18, 7, $18     # E : Number of trailing bytes to write
95         mov     $16, $5         # E : Save dest address
96         beq     $3, $no_quad    # U : tail stuff only
98         /*
99          * It's worth the effort to unroll this and use wh64 if possible.
100          * At this point, entry values are:
101          * $16  Current destination address
102          * $5   A copy of $16
103          * $6   The max quadword address to write to
104          * $18  Number trailer bytes
105          * $3   Number quads to write
106          */
108         and     $16, 0x3f, $2   # E : Forward work (only useful for unrolled loop)
109         subq    $3, 16, $4      # E : Only try to unroll if > 128 bytes
110         subq    $2, 0x40, $1    # E : bias counter (aligning stuff 0mod64)
111         blt     $4, $loop       # U :
113         /*
114          * We know we've got at least 16 quads, minimum of one trip
115          * through unrolled loop.  Do a quad at a time to get us 0mod64
116          * aligned.
117          */
119         nop                     # E :
120         nop                     # E :
121         nop                     # E :
122         beq     $1, $bigalign   # U :
124 $alignmod64:
125         stq     $17, 0($5)      # L :
126         subq    $3, 1, $3       # E : For consistency later
127         addq    $1, 8, $1       # E : Increment towards zero for alignment
128         addq    $5, 8, $4       # E : Initial wh64 address (filler instruction)
130         nop
131         nop
132         addq    $5, 8, $5       # E : Inc address
133         blt     $1, $alignmod64 # U :
135 $bigalign:
136         /*
137          * $3 - number quads left to go
138          * $5 - target address (aligned 0mod64)
139          * $17 - mask of stuff to store
140          * Scratch registers available: $7, $2, $4, $1
141          * We know that we'll be taking a minimum of one trip through.
142          * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
143          * Assumes the wh64 needs to be for 2 trips through the loop in the future.
144          * The wh64 is issued on for the starting destination address for trip +2
145          * through the loop, and if there are less than two trips left, the target
146          * address will be for the current trip.
147          */
149 $do_wh64:
150         wh64    ($4)            # L1 : memory subsystem write hint
151         subq    $3, 24, $2      # E : For determining future wh64 addresses
152         stq     $17, 0($5)      # L :
153         nop                     # E :
155         addq    $5, 128, $4     # E : speculative target of next wh64
156         stq     $17, 8($5)      # L :
157         stq     $17, 16($5)     # L :
158         addq    $5, 64, $7      # E : Fallback address for wh64 (== next trip addr)
160         stq     $17, 24($5)     # L :
161         stq     $17, 32($5)     # L :
162         cmovlt  $2, $7, $4      # E : Latency 2, extra mapping cycle
163         nop
165         stq     $17, 40($5)     # L :
166         stq     $17, 48($5)     # L :
167         subq    $3, 16, $2      # E : Repeat the loop at least once more?
168         nop
170         stq     $17, 56($5)     # L :
171         addq    $5, 64, $5      # E :
172         subq    $3, 8, $3       # E :
173         bge     $2, $do_wh64    # U :
175         nop
176         nop
177         nop
178         beq     $3, $no_quad    # U : Might have finished already
180         .align 4
181         /*
182          * Simple loop for trailing quadwords, or for small amounts
183          * of data (where we can't use an unrolled loop and wh64)
184          */
185 $loop:
186         stq     $17, 0($5)      # L :
187         subq    $3, 1, $3       # E : Decrement number quads left
188         addq    $5, 8, $5       # E : Inc address
189         bne     $3, $loop       # U : more?
191 $no_quad:
192         /*
193          * Write 0..7 trailing bytes.
194          */
195         nop                     # E :
196         beq     $18, $end       # U : All done?
197         ldq     $7, 0($5)       # L :
198         mskqh   $7, $6, $2      # U : Mask final quad
200         insqh   $17, $6, $4     # U : New bits
201         or      $2, $4, $1      # E : Put it all together
202         stq     $1, 0($5)       # L : And back to memory
203         ret     $31,($26),1     # L0 :
205 $within_quad:
206         ldq_u   $1, 0($16)      # L :
207         insql   $17, $16, $2    # U : New bits
208         mskql   $1, $16, $4     # U : Clear old
209         or      $2, $4, $2      # E : New result
211         mskql   $2, $6, $4      # U :
212         mskqh   $1, $6, $2      # U :
213         or      $2, $4, $1      # E :
214         stq_u   $1, 0($16)      # L :
216 $end:
217         nop
218         nop
219         nop
220         ret $31,($26),1         # L0 :
222         END(memset)
223 libc_hidden_builtin_def (memset)