S390: Ifunc resolver macro for vector instructions.
[glibc.git] / sysdeps / s390 / multiarch / ifunc-resolve.h
blobe9fd90e26bbae6e9175eada5bc2599b2c49e49fb
1 /* IFUNC resolver function for CPU specific functions.
2 32/64 bit S/390 version.
3 Copyright (C) 2015 Free Software Foundation, Inc.
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 Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the 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 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
20 #include <unistd.h>
21 #include <dl-procinfo.h>
23 #define S390_STFLE_BITS_Z10 34 /* General instructions extension */
24 #define S390_STFLE_BITS_Z196 45 /* Distinct operands, pop ... */
26 #define S390_IS_Z196(STFLE_BITS) \
27 ((STFLE_BITS & (1ULL << (63 - S390_STFLE_BITS_Z196))) != 0)
29 #define S390_IS_Z10(STFLE_BITS) \
30 ((STFLE_BITS & (1ULL << (63 - S390_STFLE_BITS_Z10))) != 0)
32 #define S390_STORE_STFLE(STFLE_BITS) \
33 /* We want just 1 double word to be returned. */ \
34 register unsigned long reg0 asm("0") = 0; \
36 asm volatile(".machine push" "\n\t" \
37 ".machine \"z9-109\"" "\n\t" \
38 ".machinemode \"zarch_nohighgprs\"\n\t" \
39 "stfle %0" "\n\t" \
40 ".machine pop" "\n" \
41 : "=QS" (STFLE_BITS), "+d" (reg0) \
42 : : "cc");
44 #define s390_libc_ifunc(FUNC) \
45 asm (".globl " #FUNC "\n\t" \
46 ".type " #FUNC ",@gnu_indirect_function\n\t" \
47 ".set " #FUNC ",__resolve_" #FUNC "\n\t" \
48 ".globl __GI_" #FUNC "\n\t" \
49 ".set __GI_" #FUNC "," #FUNC "\n"); \
51 /* Make the declarations of the optimized functions hidden in order
52 to prevent GOT slots being generated for them. */ \
53 extern void *__##FUNC##_z196 attribute_hidden; \
54 extern void *__##FUNC##_z10 attribute_hidden; \
55 extern void *__##FUNC##_default attribute_hidden; \
57 void *__resolve_##FUNC (unsigned long int dl_hwcap) \
58 { \
59 if ((dl_hwcap & HWCAP_S390_STFLE) \
60 && (dl_hwcap & HWCAP_S390_ZARCH) \
61 && (dl_hwcap & HWCAP_S390_HIGH_GPRS)) \
62 { \
63 unsigned long long stfle_bits; \
64 S390_STORE_STFLE (stfle_bits); \
66 if (S390_IS_Z196 (stfle_bits)) \
67 return &__##FUNC##_z196; \
68 else if (S390_IS_Z10 (stfle_bits)) \
69 return &__##FUNC##_z10; \
70 else \
71 return &__##FUNC##_default; \
72 } \
73 else \
74 return &__##FUNC##_default; \
77 #define s390_vx_libc_ifunc(FUNC) \
78 s390_vx_libc_ifunc2(FUNC, FUNC)
80 #define s390_vx_libc_ifunc2(RESOLVERFUNC, FUNC) \
81 /* Make the declarations of the optimized functions hidden in order
82 to prevent GOT slots being generated for them. */ \
83 extern __typeof (FUNC) RESOLVERFUNC##_vx attribute_hidden; \
84 extern __typeof (FUNC) RESOLVERFUNC##_c attribute_hidden; \
85 extern void *__resolve_##RESOLVERFUNC (unsigned long int) __asm__ (#FUNC); \
87 void *__resolve_##RESOLVERFUNC (unsigned long int dl_hwcap) \
88 { \
89 if (dl_hwcap & HWCAP_S390_VX) \
90 return &RESOLVERFUNC##_vx; \
91 else \
92 return &RESOLVERFUNC##_c; \
93 } \
94 __asm__ (".type " #FUNC ", %gnu_indirect_function");