update from main archive 961005
[glibc.git] / sysdeps / alpha / memset.S
blob55271f00ea51ae17e562bcf8a2e1bfc4bde112cf
1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2    Contributed by Richard Henderson (rth@tamu.edu)
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 Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 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 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB.  If
18 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19 Cambridge, MA 02139, USA.  */
21 /* Fill a block of memory with a character.  Optimized for the Alpha
22    architecture:
24    - memory accessed as aligned quadwords only
25    - destination memory not read unless needed for good cache behaviour
26    - basic blocks arranged to optimize branch prediction for full-quadword
27      aligned memory blocks.
28    - partial head and tail quadwords constructed with byte-mask instructions
30    This is generally scheduled for the EV5 (got to look out for my own
31    interests :-), but with EV4 needs in mind.  There *should* be no more
32    stalls for the EV4 than there are for the EV5.
36 #include <sysdep.h>
38         .set noat
39         .set noreorder
41         .text
43 /* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that
44    doesn't like putting the entry point for a procedure somewhere in the
45    middle of the procedure descriptor.  Work around this by putting the main
46    loop in its own procedure descriptor.  */
48         /* On entry to this basic block:
49            t3 == loop counter
50            t4 == bytes in partial final word
51            a0 == possibly misaligned destination pointer
52            a1 == replicated source character  */
54         .ent memset_loop
55         .align 3
56 memset_loop:
57         .frame sp, 0, ra, 0
58         .prologue 0
60         beq     t3, $tail
61         blbc    t3, 0f          # skip single store if count even
63         stq_u   a1, 0(a0)       # e0    : store one word
64         subq    t3, 1, t3       # .. e1 :
65         addq    a0, 8, a0       # e0    :
66         beq     t3, $tail       # .. e1 :
68 0:      stq_u   a1, 0(a0)       # e0    : store two words
69         subq    t3, 2, t3       # .. e1 :
70         stq_u   a1, 8(a0)       # e0    :
71         addq    a0, 16, a0      # .. e1 :
72         bne     t3, 0b          # e1    :
74 $tail:  bne     t4, 1f          # is there a tail to do?
75         ret                     # no
77         .align 3
78 1:      ldq_u   t0, 0(a0)       # e1    : yes, load original data
79         mskql   a1, t4, t1      # .. e0 :
80         mskqh   t0, t4, t0      # e0    :
81         or      t0, t1, t0      # e1 (stall)
82         stq_u   t0, 0(a0)       # e0    :
83         ret                     # .. e1 :
85         .end memset_loop
87 ENTRY(memset)
88         .prologue 0
90         zapnot  a1, 1, a1       # e0    : zero extend input character
91         mov     a0, v0          # .. e1 : move return value in place
92         sll     a1, 8, t0       # e0    : begin replicating the char
93         beq     a2, $done       # .. e1 : early exit for zero-length store
94         or      t0, a1, a1      # e0    :
95         and     a0, 7, t1       # .. e1 : dest misalignment
96         sll     a1, 16, t0      # e0    :
97         addq    a2, t1, a2      # .. e1 : add dest misalignment to count
98         or      t0, a1, a1      # e0    :
99         srl     a2, 3, t3       # .. e1 : loop = count >> 3
100         sll     a1, 32, t0      # e0    :
101         and     a2, 7, t4       # .. e1 : find number of bytes in tail
102         or      t0, a1, a1      # e0    : character replication done
104         beq     t1, memset_loop # .. e1 : aligned head, jump right in
106         ldq_u   t0, 0(a0)       # e1    : load original data to mask into
107         mskqh   a1, a0, t1      # .. e0 :
109         cmpult  a2, 8, t2       # e0    : is this a sub-word set?
110         bne     t2, $oneq       # .. e1 (zdb)
112         mskql   t0, a0, t0      # e0    : we span words.  finish this partial
113         subq    t3, 1, t3       # .. e1 :
114         addq    a0, 8, a0       # e0    :
115         or      t0, t1, t0      # .. e1 :
116         stq_u   t0, -8(a0)      # e0    :
117         br      memset_loop     # .. e1 :
119         .align 3
120 $oneq:
121         mskql   t1, a2, t1      # e0    : entire operation within one word
122         mskql   t0, a0, t2      # e0    :
123         mskqh   t0, a2, t3      # e0    :
124         or      t1, t2, t0      # .. e1 :
125         or      t0, t3, t0      # e1    :
126         stq_u   t0, 0(a0)       # e0 (stall)
128 $done:  ret
130         END(memset)