S390: Optimize wmemset.
[glibc.git] / sysdeps / s390 / multiarch / wmemset-vx.S
blob22bddcd3a3b91c8b0bac3e0d4c7ccd376fe08ca3
1 /* Vector Optimized 32/64 bit S/390 version of wmemset.
2    Copyright (C) 2015 Free Software Foundation, Inc.
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, see
17    <http://www.gnu.org/licenses/>.  */
19 #if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
21 # include "sysdep.h"
22 # include "asm-syntax.h"
24         .text
26 /* wchar_t *wmemset(wchar_t *dest, wchar_t wc, size_t n)
27    Fill an array of wide-characters with a constant wide character
28    and returns dest.
30    Register usage:
31    -r0=tmp
32    -r1=tmp
33    -r2=dest or current-pointer
34    -r3=wc
35    -r4=n
36    -r5=tmp
37    -v16=replicated wc
38    -v17,v18,v19=copy of v16 for vstm
39    -v31=saved dest for return
41 ENTRY(__wmemset_vx)
42         .machine "z13"
43         .machinemode "zarch_nohighgprs"
45 # if !defined __s390x__
46         llgfr   %r4,%r4
47 # endif /* !defined __s390x__ */
49         vlvgg   %v31,%r2,0      /* Save destination pointer for return.  */
50         clgije  %r4,0,.Lend
52         vlvgf   %v16,%r3,0      /* Generate vector with wchar_t wc.  */
53         vrepf   %v16,%v16,0
55         /* Check range of maxlen and convert to byte-count.  */
56 # ifdef __s390x__
57         tmhh    %r4,49152       /* Test bit 0 or 1 of maxlen.  */
58         lghi    %r5,-4          /* Max byte-count is 18446744073709551612.  */
59 # else
60         tmlh    %r4,49152       /* Test bit 0 or 1 of maxlen.  */
61         llilf   %r5,4294967292  /* Max byte-count is 4294967292.  */
62 # endif /* !__s390x__ */
63         sllg    %r4,%r4,2       /* Convert character-count to byte-count.  */
64         locgrne %r4,%r5         /* Use max byte-count, if bit 0/1 was one.  */
66         /* Align dest to 16 byte.  */
67         risbg   %r0,%r2,60,128+63,0 /* Test if s is aligned and
68                                        %r3 = bits 60-63 'and' 15.  */
69         je      .Lpreloop       /* If s is aligned, loop aligned.  */
70         tmll    %r2,3           /* Test if s is 4-byte aligned?  */
71         jne     .Lfallback      /* And use common-code variant if not.  */
72         lghi    %r1,16
73         slr     %r1,%r0         /* Compute byte count to load (16-x).  */
74         clgr    %r1,%r4
75         locgrh  %r1,%r4         /* min (byte count, n)  */
76         aghik   %r5,%r1,-1      /* vstl needs highest index.  */
77         vstl    %v16,%r5,0(%r2) /* Store remaining bytes.  */
78         clgrje  %r1,%r4,.Lend   /* Return if n bytes where set.  */
79         slgr    %r4,%r1         /* Compute remaining byte count.  */
80         la      %r2,0(%r1,%r2)
82 .Lpreloop:
83         /* Now we are 16-byte aligned.  */
84         clgijl  %r4,17,.Lremaining
85         srlg    %r1,%r4,8       /* Split into 256byte blocks */
86         clgije  %r1,0,.Lpreloop64
87         vlr     %v17,%v16
88         vlr     %v18,%v16
89         vlr     %v19,%v16
91 .Lloop256:
92         vstm    %v16,%v19,0(%r2)
93         vstm    %v16,%v19,64(%r2)
94         vstm    %v16,%v19,128(%r2)
95         vstm    %v16,%v19,192(%r2)
96         la      %r2,256(%r2)
97         brctg   %r1,.Lloop256   /* Loop until all blocks are processed.  */
99         llgfr   %r4,%r4
100         nilf    %r4,255         /* Get remaining bytes */
101         je      .Lend           /* Skip store remaining bytes if zero.  */
103 .Lpreloop64:
104         clgijl  %r4,17,.Lremaining
105         clgijl  %r4,33,.Lpreloop16
106         srlg    %r1,%r4,5       /* Split into 32byte blocks */
108 .Lloop32:
109         vst     %v16,0(%r2)
110         vst     %v16,16(%r2)
111         la      %r2,32(%r2)
112         brctg   %r1,.Lloop32    /* Loop until all blocks are processed.  */
114         llgfr   %r4,%r4
115         nilf    %r4,31          /* Get remaining bytes */
116         je      .Lend           /* Skip store remaining bytes if zero.  */
118 .Lpreloop16:
119         clgijl  %r4,17,.Lremaining
120         srlg    %r1,%r4,4       /* Split into 16byte blocks */
122 .Lloop16:
123         vst     %v16,0(%r2)
124         la      %r2,16(%r2)
125         brctg   %r1,.Lloop16    /* Loop until all blocks are processed.  */
127         llgfr   %r4,%r4
128         nilf    %r4,15          /* Get remaining bytes */
129         je      .Lend           /* Skip store remaining bytes if zero.  */
131 .Lremaining:
132         aghi    %r4,-1          /* vstl needs highest index.  */
133         vstl    %v16,%r4,0(%r2)
135 .Lend:
136         vlgvg   %r2,%v31,0      /* Load saved dest for return value.  */
137         br      %r14
138 .Lfallback:
139         srlg    %r4,%r4,2       /* Convert byte-count to character-count.  */
140         jg      __wmemset_c
141 END(__wmemset_vx)
142 #endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */