orphan
[debian/elilo] / ia64 / memset.S
1 /*
2  *  Copyright (C) 1999-2003 Hewlett-Packard Co.
3  *      Contributed by Stephane Eranian <eranian@hpl.hp.com>
4  *
5  * This file is part of the ELILO, the EFI Linux boot loader.
6  *
7  *  ELILO is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2, or (at your option)
10  *  any later version.
11  *
12  *  ELILO is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with ELILO; see the file COPYING.  If not, write to the Free
19  *  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20  *  02111-1307, USA.
21  *
22  * Please check out the elilo.txt for complete documentation on how
23  * to use this program.
24  *
25  * This code is derived from the Linux/ia64 source code.
26  */
27
28 /*
29  *
30  * Optimized version of the standard memset() function
31  *
32  * Return: none
33  *
34  * Inputs:
35  *      in0:    address of buffer
36  *      in1:    byte value to use for storing
37  *      in2:    length of the buffer
38  *
39  */
40
41 // arguments
42 //
43 #define buf             r32
44 #define val             r33
45 #define len             r34
46
47 //
48 // local registers
49 //
50 #define saved_pfs       r14
51 #define cnt             r18
52 #define buf2            r19
53 #define saved_lc        r20
54 #define tmp             r21
55         .text
56         .global Memset
57         .proc Memset
58 Memset:
59         .prologue
60         .save ar.pfs, saved_pfs
61         alloc saved_pfs=ar.pfs,3,0,0,0  // cnt is sink here
62         cmp.eq p8,p0=r0,len     // check for zero length
63         .save ar.lc, saved_lc
64         mov saved_lc=ar.lc      // preserve ar.lc (slow)
65         ;;
66
67         .body
68
69         adds tmp=-1,len         // br.ctop is repeat/until
70         tbit.nz p6,p0=buf,0     // odd alignment
71 (p8)    br.ret.spnt.few rp
72
73         cmp.lt p7,p0=16,len     // if len > 16 then long memset
74         mux1 val=val,@brcst     // prepare value
75 (p7)    br.cond.dptk.few long_memset
76         ;;
77         mov ar.lc=tmp           // initialize lc for small count
78         ;;                      // avoid RAW and WAW on ar.lc
79 1:                              // worst case 15 cyles, avg 8 cycles
80         st1 [buf]=val,1
81         br.cloop.dptk.few 1b
82         ;;                              // avoid RAW on ar.lc
83         mov ar.lc=saved_lc
84         mov ar.pfs=saved_pfs
85         br.ret.sptk.few rp      // end of short memset
86
87         // at this point we know we have more than 16 bytes to copy
88         // so we focus on alignment
89 long_memset:
90 (p6)    st1 [buf]=val,1         // 1-byte aligned
91 (p6)    adds len=-1,len;;       // sync because buf is modified
92         tbit.nz p6,p0=buf,1
93         ;;
94 (p6)    st2 [buf]=val,2         // 2-byte aligned
95 (p6)    adds len=-2,len;;
96         tbit.nz p6,p0=buf,2
97         ;;
98 (p6)    st4 [buf]=val,4         // 4-byte aligned
99 (p6)    adds len=-4,len;;
100         tbit.nz p6,p0=buf,3
101         ;;
102 (p6)    st8 [buf]=val,8         // 8-byte aligned
103 (p6)    adds len=-8,len;;
104         shr.u cnt=len,4         // number of 128-bit (2x64bit) words
105         ;;
106         cmp.eq p6,p0=r0,cnt
107         adds tmp=-1,cnt
108 (p6)    br.cond.dpnt.few .dotail // we have less than 16 bytes left
109         ;;
110         adds buf2=8,buf         // setup second base pointer
111         mov ar.lc=tmp
112         ;;
113 2:                              // 16bytes/iteration
114         st8 [buf]=val,16
115         st8 [buf2]=val,16
116         br.cloop.dptk.few 2b
117         ;;
118 .dotail:                        // tail correction based on len only
119         tbit.nz p6,p0=len,3
120         ;;
121 (p6)    st8 [buf]=val,8         // at least 8 bytes
122         tbit.nz p6,p0=len,2
123         ;;
124 (p6)    st4 [buf]=val,4         // at least 4 bytes
125         tbit.nz p6,p0=len,1
126         ;;
127 (p6)    st2 [buf]=val,2         // at least 2 bytes
128         tbit.nz p6,p0=len,0
129         mov ar.lc=saved_lc
130         ;;
131 (p6)    st1 [buf]=val           // only 1 byte left
132         br.ret.dptk.few rp
133         .endp Memset