.
[glibc/history.git] / sysdeps / alpha / memset.S
blobe34af2b314060fe2b57e1e73e42c1ff87c9625bc
1 /* Copyright (C) 1996, 1997, 2003 Free Software Foundation, Inc.
2    Contributed by Richard Henderson (rth@tamu.edu)
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 /* Fill a block of memory with a character.  Optimized for the Alpha
21    architecture:
23    - memory accessed as aligned quadwords only
24    - destination memory not read unless needed for good cache behaviour
25    - basic blocks arranged to optimize branch prediction for full-quadword
26      aligned memory blocks.
27    - partial head and tail quadwords constructed with byte-mask instructions
29    This is generally scheduled for the EV5 (got to look out for my own
30    interests :-), but with EV4 needs in mind.  There *should* be no more
31    stalls for the EV4 than there are for the EV5.
35 #include <sysdep.h>
37         .set noat
38         .set noreorder
40         .text
42 /* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that
43    doesn't like putting the entry point for a procedure somewhere in the
44    middle of the procedure descriptor.  Work around this by putting the main
45    loop in its own procedure descriptor.  */
47         /* On entry to this basic block:
48            t3 == loop counter
49            t4 == bytes in partial final word
50            a0 == possibly misaligned destination pointer
51            a1 == replicated source character  */
53         .ent memset_loop
54         .align 3
55 memset_loop:
56         .frame sp, 0, ra, 0
57         .prologue 0
59         beq     t3, $tail
60         blbc    t3, 0f          # skip single store if count even
62         stq_u   a1, 0(a0)       # e0    : store one word
63         subq    t3, 1, t3       # .. e1 :
64         addq    a0, 8, a0       # e0    :
65         beq     t3, $tail       # .. e1 :
67 0:      stq_u   a1, 0(a0)       # e0    : store two words
68         subq    t3, 2, t3       # .. e1 :
69         stq_u   a1, 8(a0)       # e0    :
70         addq    a0, 16, a0      # .. e1 :
71         bne     t3, 0b          # e1    :
73 $tail:  bne     t4, 1f          # is there a tail to do?
74         ret                     # no
76         .align 3
77 1:      ldq_u   t0, 0(a0)       # e1    : yes, load original data
78         mskql   a1, t4, t1      # .. e0 :
79         mskqh   t0, t4, t0      # e0    :
80         or      t0, t1, t0      # e1 (stall)
81         stq_u   t0, 0(a0)       # e0    :
82         ret                     # .. e1 :
84         .end memset_loop
86 ENTRY(memset)
87 #ifdef PROF
88         ldgp    gp, 0(pv)
89         lda     AT, _mcount
90         jsr     AT, (AT), _mcount
91         .prologue 1
92 #else
93         .prologue 0
94 #endif
96         zapnot  a1, 1, a1       # e0    : zero extend input character
97         mov     a0, v0          # .. e1 : move return value in place
98         sll     a1, 8, t0       # e0    : begin replicating the char
99         beq     a2, $done       # .. e1 : early exit for zero-length store
100         or      t0, a1, a1      # e0    :
101         and     a0, 7, t1       # .. e1 : dest misalignment
102         sll     a1, 16, t0      # e0    :
103         addq    a2, t1, a2      # .. e1 : add dest misalignment to count
104         or      t0, a1, a1      # e0    :
105         srl     a2, 3, t3       # .. e1 : loop = count >> 3
106         sll     a1, 32, t0      # e0    :
107         and     a2, 7, t4       # .. e1 : find number of bytes in tail
108         or      t0, a1, a1      # e0    : character replication done
110         beq     t1, memset_loop # .. e1 : aligned head, jump right in
112         ldq_u   t0, 0(a0)       # e1    : load original data to mask into
113         mskqh   a1, a0, t1      # .. e0 :
115         cmpult  a2, 8, t2       # e0    : is this a sub-word set?
116         bne     t2, $oneq       # .. e1 (zdb)
118         mskql   t0, a0, t0      # e0    : we span words.  finish this partial
119         subq    t3, 1, t3       # .. e1 :
120         addq    a0, 8, a0       # e0    :
121         or      t0, t1, t0      # .. e1 :
122         stq_u   t0, -8(a0)      # e0    :
123         br      memset_loop     # .. e1 :
125         .align 3
126 $oneq:
127         mskql   t1, a2, t1      # e0    : entire operation within one word
128         mskql   t0, a0, t2      # e0    :
129         mskqh   t0, a2, t3      # e0    :
130         or      t1, t2, t0      # .. e1 :
131         or      t0, t3, t0      # e1    :
132         stq_u   t0, 0(a0)       # e0 (stall)
134 $done:  ret
136         END(memset)
137 libc_hidden_builtin_def (memset)