2.9
[glibc/nacl-glibc.git] / sysdeps / alpha / alphaev6 / memset.S
blob3b3c4ba06137fd59781ca49f5913ee3c96a79315
1 /* Copyright (C) 2000, 2003 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, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
21 #include <sysdep.h>
23         .arch ev6
24         .set noat
25         .set noreorder
27 ENTRY(memset)
28 #ifdef PROF
29         ldgp    gp, 0(pv)
30         lda     AT, _mcount
31         jsr     AT, (AT), _mcount
32         .prologue 1
33 #else
34         .prologue 0
35 #endif
37         /*
38          * Serious stalling happens.  The only way to mitigate this is to
39          * undertake a major re-write to interleave the constant materialization
40          * with other parts of the fall-through code.  This is important, even
41          * though it makes maintenance tougher.
42          * Do this later.
43          */
44         and     $17, 255, $1    # E : 00000000000000ch
45         insbl   $17, 1, $2      # U : 000000000000ch00
46         mov     $16, $0         # E : return value
47         ble     $18, $end       # U : zero length requested?
49         addq    $18, $16, $6    # E : max address to write to
50         or      $1, $2, $17     # E : 000000000000chch
51         insbl   $1, 2, $3       # U : 0000000000ch0000
52         insbl   $1, 3, $4       # U : 00000000ch000000
54         or      $3, $4, $3      # E : 00000000chch0000
55         inswl   $17, 4, $5      # U : 0000chch00000000
56         xor     $16, $6, $1     # E : will complete write be within one quadword?
57         inswl   $17, 6, $2      # U : chch000000000000
59         or      $17, $3, $17    # E : 00000000chchchch
60         or      $2, $5, $2      # E : chchchch00000000
61         bic     $1, 7, $1       # E : fit within a single quadword?
62         and     $16, 7, $3      # E : Target addr misalignment
64         or      $17, $2, $17    # E : chchchchchchchch
65         beq     $1, $within_quad # U :
66         nop                     # E :
67         beq     $3, $aligned    # U : target is 0mod8
69         /*
70          * Target address is misaligned, and won't fit within a quadword.
71          */
72         ldq_u   $4, 0($16)      # L : Fetch first partial
73         mov     $16, $5         # E : Save the address
74         insql   $17, $16, $2    # U : Insert new bytes
75         subq    $3, 8, $3       # E : Invert (for addressing uses)
77         addq    $18, $3, $18    # E : $18 is new count ($3 is negative)
78         mskql   $4, $16, $4     # U : clear relevant parts of the quad
79         subq    $16, $3, $16    # E : $16 is new aligned destination
80         or      $2, $4, $1      # E : Final bytes
82         nop
83         stq_u   $1,0($5)        # L : Store result
84         nop
85         nop
87         .align 4
88 $aligned:
89         /*
90          * We are now guaranteed to be quad aligned, with at least
91          * one partial quad to write.
92          */
94         sra     $18, 3, $3      # U : Number of remaining quads to write
95         and     $18, 7, $18     # E : Number of trailing bytes to write
96         mov     $16, $5         # E : Save dest address
97         beq     $3, $no_quad    # U : tail stuff only
99         /*
100          * It's worth the effort to unroll this and use wh64 if possible.
101          * At this point, entry values are:
102          * $16  Current destination address
103          * $5   A copy of $16
104          * $6   The max quadword address to write to
105          * $18  Number trailer bytes
106          * $3   Number quads to write
107          */
109         and     $16, 0x3f, $2   # E : Forward work (only useful for unrolled loop)
110         subq    $3, 16, $4      # E : Only try to unroll if > 128 bytes
111         subq    $2, 0x40, $1    # E : bias counter (aligning stuff 0mod64)
112         blt     $4, $loop       # U :
114         /*
115          * We know we've got at least 16 quads, minimum of one trip
116          * through unrolled loop.  Do a quad at a time to get us 0mod64
117          * aligned.
118          */
120         nop                     # E :
121         nop                     # E :
122         nop                     # E :
123         beq     $1, $bigalign   # U :
125 $alignmod64:
126         stq     $17, 0($5)      # L :
127         subq    $3, 1, $3       # E : For consistency later
128         addq    $1, 8, $1       # E : Increment towards zero for alignment
129         addq    $5, 8, $4       # E : Initial wh64 address (filler instruction)
131         nop
132         nop
133         addq    $5, 8, $5       # E : Inc address
134         blt     $1, $alignmod64 # U :
136 $bigalign:
137         /*
138          * $3 - number quads left to go
139          * $5 - target address (aligned 0mod64)
140          * $17 - mask of stuff to store
141          * Scratch registers available: $7, $2, $4, $1
142          * We know that we'll be taking a minimum of one trip through.
143          * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
144          * Assumes the wh64 needs to be for 2 trips through the loop in the future.
145          * The wh64 is issued on for the starting destination address for trip +2
146          * through the loop, and if there are less than two trips left, the target
147          * address will be for the current trip.
148          */
150 $do_wh64:
151         wh64    ($4)            # L1 : memory subsystem write hint
152         subq    $3, 24, $2      # E : For determining future wh64 addresses
153         stq     $17, 0($5)      # L :
154         nop                     # E :
156         addq    $5, 128, $4     # E : speculative target of next wh64
157         stq     $17, 8($5)      # L :
158         stq     $17, 16($5)     # L :
159         addq    $5, 64, $7      # E : Fallback address for wh64 (== next trip addr)
161         stq     $17, 24($5)     # L :
162         stq     $17, 32($5)     # L :
163         cmovlt  $2, $7, $4      # E : Latency 2, extra mapping cycle
164         nop
166         stq     $17, 40($5)     # L :
167         stq     $17, 48($5)     # L :
168         subq    $3, 16, $2      # E : Repeat the loop at least once more?
169         nop
171         stq     $17, 56($5)     # L :
172         addq    $5, 64, $5      # E :
173         subq    $3, 8, $3       # E :
174         bge     $2, $do_wh64    # U :
176         nop
177         nop
178         nop
179         beq     $3, $no_quad    # U : Might have finished already
181         .align 4
182         /*
183          * Simple loop for trailing quadwords, or for small amounts
184          * of data (where we can't use an unrolled loop and wh64)
185          */
186 $loop:
187         stq     $17, 0($5)      # L :
188         subq    $3, 1, $3       # E : Decrement number quads left
189         addq    $5, 8, $5       # E : Inc address
190         bne     $3, $loop       # U : more?
192 $no_quad:
193         /*
194          * Write 0..7 trailing bytes.
195          */
196         nop                     # E :
197         beq     $18, $end       # U : All done?
198         ldq     $7, 0($5)       # L :
199         mskqh   $7, $6, $2      # U : Mask final quad
201         insqh   $17, $6, $4     # U : New bits
202         or      $2, $4, $1      # E : Put it all together
203         stq     $1, 0($5)       # L : And back to memory
204         ret     $31,($26),1     # L0 :
206 $within_quad:
207         ldq_u   $1, 0($16)      # L :
208         insql   $17, $16, $2    # U : New bits
209         mskql   $1, $16, $4     # U : Clear old
210         or      $2, $4, $2      # E : New result
212         mskql   $2, $6, $4      # U :
213         mskqh   $1, $6, $2      # U :
214         or      $2, $4, $1      # E :
215         stq_u   $1, 0($16)      # L :
217 $end:
218         nop
219         nop
220         nop
221         ret $31,($26),1         # L0 :
223         END(memset)
224 libc_hidden_builtin_def (memset)