hurd: fix resolv/tst-resolv-res_init-skeleton.c build
[glibc.git] / sysdeps / s390 / multiarch / memccpy-vx.S
blobf60aecef770d459784b06b201b61630896b9954c
1 /* Vector optimized 32/64 bit S/390 version of memccpy.
2    Copyright (C) 2015-2017 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 /* void *memccpy (void * dest, const void *src, int c, size_t n)
27    Copies no more than n bytes from src to dest,
28    stopping when the character c is found
29    and returns pointer next to c in dest or null if c not found.
31    Register usage:
32    -r0=tmp
33    -r1=tmp
34    -r2=dest
35    -r3=src
36    -r4=c
37    -r5=n
38    -r6=current_len
39    -v16=part of s
40    -v17=index of found c
41    -v18=c replicated
42    -v19=part #2 of s
43    -v31=save area for r6
45 ENTRY(__memccpy_vx)
46         .machine "z13"
47         .machinemode "zarch_nohighgprs"
49 # if !defined __s390x__
50         llgfr   %r5,%r5
51 # endif /* !defined __s390x__ */
53         vlvgp   %v31,%r6,%r7    /* Save registers.  */
54         clgije  %r5,0,.Lnf_end  /* If len == 0 then exit.  */
56         vlbb    %v16,0(%r3),6   /* Load s until next 4k-byte boundary.  */
57         lcbb    %r0,0(%r3),6    /* Get bytes to 4k-byte boundary or 16.  */
58         llgfr   %r0,%r0         /* Convert 32bit to 64bit.  */
60         vlvgb   %v18,%r4,0      /* Generate vector which elements are all c.
61                                    if c > 255, c will be truncated.  */
62         vrepb   %v18,%v18,0
63         lghi    %r6,0           /* current_len = 0.  */
65         clgrjle %r5,%r0,.Lremaining_v16 /* If maxlen <= loaded-bytes
66                                            -> Process remaining.  */
68         vfeebs  %v17,%v16,%v18  /* Find c.  */
69         vlgvb   %r1,%v17,7      /* Load byte index of c.  */
70         clgrjl  %r1,%r0,.Lfound_v16 /* Found c is within loaded bytes.  */
72         /* Align s to 16 byte.  */
73         risbgn  %r1,%r3,60,128+63,0 /* %r3 = bits 60-63 of %r2 'and' 15.  */
74         lghi    %r6,15          /* current_len = 15.  */
75         slr     %r6,%r1         /* Compute highest index to 16byte boundary.  */
77         vstl    %v16,%r6,0(%r2) /* Store prcessed bytes */
78         ahi     %r6,1
80 .Lpreloop1:
81         /* Now we are 16byte aligned, so we can load
82            a full vreg without page fault.  */
83         vl      %v16,0(%r6,%r3) /* Load s.  */
84         clgijl  %r5,17,.Lremaining_v16  /* If n <= 16,
85                                            process remaining bytes.  */
86         lgr     %r7,%r5
87         slgfi   %r7,16          /* border_len = n - 16.  */
88         j       .Lloop1
90 .Lloop2:
91         vl      %v16,16(%r6,%r3)
92         vst     %v19,0(%r6,%r2)
93         aghi    %r6,16
95 .Lloop1:
96         clgrjhe %r6,%r7,.Lremaining_v16 /* If current_len >= border
97                                            then process remaining bytes.  */
98         vfeebs  %v17,%v16,%v18  /* Find c.  */
99         jl      .Lfound_v16     /* Jump away if c was found.  */
100         vl      %v19,16(%r6,%r3) /* Load next s part.  */
101         vst     %v16,0(%r6,%r2) /* Store previous part without c.  */
102         aghi    %r6,16
104         clgrjhe %r6,%r7,.Lremaining_v19
105         vfeebs  %v17,%v19,%v18
106         jl      .Lfound_v19
107         vl      %v16,16(%r6,%r3)
108         vst     %v19,0(%r6,%r2)
109         aghi    %r6,16
111         clgrjhe %r6,%r7,.Lremaining_v16
112         vfeebs  %v17,%v16,%v18
113         jl      .Lfound_v16
114         vl      %v19,16(%r6,%r3)
115         vst     %v16,0(%r6,%r2)
116         aghi    %r6,16
118         clgrjhe %r6,%r7,.Lremaining_v19
119         vfeebs  %v17,%v19,%v18
120         jo      .Lloop2
122 .Lfound_v19:
123         vlr     %v16,%v19
124 .Lfound_v16:
125         /* v16 contains c. Store remaining bytes to c. currlen hasnĀ“t
126            reached border, thus checking for maxlen is not needed! */
127         vlgvb   %r1,%v17,7      /* Load byte index of c.  */
128         la      %r2,0(%r6,%r2)  /* vstl has no support for index-register.  */
129 .Lfound_v16_store:
130         vstl    %v16,%r1,0(%r2) /* Copy bytes including c.  */
131         la      %r2,1(%r1,%r2)  /* Return pointer next to c in dest.  */
132         vlgvg   %r6,%v31,0
133         vlgvg   %r7,%v31,1
134         br      %r14
136 .Lremaining_v19:
137         vlr     %v16,%v19
138 .Lremaining_v16:
139         /* v16 contains the remaining bytes [1...16].
140            Check and store remaining bytes.  */
141         vfeebs  %v17,%v16,%v18
142         slgrk   %r7,%r5,%r6     /* Remaining bytes = maxlen - current_len.  */
143         aghi    %r7,-1          /* vstl needs highest index.  */
144         la      %r2,0(%r6,%r2)  /* vstl has no index register.  */
145         vlgvb   %r1,%v17,7      /* Load index of c or 16 if not found.  */
146         /* c in remaining bytes? -> Jump away (c-index <= max-index)  */
147         clrjle  %r1,%r7,.Lfound_v16_store
148         vstl    %v16,%r7,0(%r2) /* Store remaining bytes.  */
150 .Lnf_end:
151         vlgvg   %r6,%v31,0
152         vlgvg   %r7,%v31,1
153         lghi    %r2,0           /* Return null.  */
154         br      %r14
155 END(__memccpy_vx)
156 #endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */