/* This file is part of the GNU C Library. Copyright (C) 2012-2013 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ #include #ifdef __ASSEMBLER__ # ifdef SHARED # define SPARC_ASM_IFUNC_DFLT(name, dflt) \ ENTRY (__##name) \ .type __##name, @gnu_indirect_function; \ SETUP_PIC_REG_LEAF(o3, o5); \ sethi %gdop_hix22(dflt), %o1; \ xor %o1, %gdop_lox10(dflt), %o1; \ add %o3, %o1, %o1; \ retl; \ mov %o1, %o0; \ END (__##name) # define SPARC_ASM_IFUNC1(name, m1, f1, dflt) \ ENTRY (__##name) \ .type __##name, @gnu_indirect_function; \ SETUP_PIC_REG_LEAF(o3, o5); \ set m1, %o1; \ andcc %o0, %o1, %g0; \ be 9f; \ nop; \ sethi %gdop_hix22(f1), %o1; \ xor %o1, %gdop_lox10(f1), %o1; \ ba 10f; \ nop; \ 9: sethi %gdop_hix22(dflt), %o1; \ xor %o1, %gdop_lox10(dflt), %o1; \ 10: add %o3, %o1, %o1; \ retl; \ mov %o1, %o0; \ END (__##name) # define SPARC_ASM_IFUNC2(name, m1, f1, m2, f2, dflt) \ ENTRY (__##name) \ .type __##name, @gnu_indirect_function; \ SETUP_PIC_REG_LEAF(o3, o5); \ set m1, %o1; \ andcc %o0, %o1, %g0; \ be 8f; \ nop; \ sethi %gdop_hix22(f1), %o1; \ xor %o1, %gdop_lox10(f1), %o1; \ ba 10f; \ nop; \ 8: set m2, %o1; \ andcc %o0, %o1, %g0; \ be 9f; \ nop; \ sethi %gdop_hix22(f2), %o1; \ xor %o1, %gdop_lox10(f2), %o1; \ ba 10f; \ nop; \ 9: sethi %gdop_hix22(dflt), %o1; \ xor %o1, %gdop_lox10(dflt), %o1; \ 10: add %o3, %o1, %o1; \ retl; \ mov %o1, %o0; \ END (__##name) # else /* SHARED */ # ifdef __arch64__ # define SET(SYM, TMP, REG) setx SYM, TMP, REG # else # define SET(SYM, TMP, REG) set SYM, REG # endif # define SPARC_ASM_IFUNC_DFLT(name, dflt) \ ENTRY (__##name) \ .type __##name, @gnu_indirect_function; \ SET(dflt, %g1, %o1); \ retl; \ mov %o1, %o0; \ END (__##name) # define SPARC_ASM_IFUNC1(name, m1, f1, dflt) \ ENTRY (__##name) \ .type __##name, @gnu_indirect_function; \ set m1, %o1; \ andcc %o0, %o1, %g0; \ be 9f; \ nop; \ SET(f1, %g1, %o1); \ ba 10f; \ nop; \ 9: SET(dflt, %g1, %o1); \ 10: retl; \ mov %o1, %o0; \ END (__##name) # define SPARC_ASM_IFUNC2(name, m1, f1, m2, f2, dflt) \ ENTRY (__##name) \ .type __##name, @gnu_indirect_function; \ set m1, %o1; \ andcc %o0, %o1, %g0; \ be 8f; \ nop; \ SET(f1, %g1, %o1); \ ba 10f; \ nop; \ 8: set m2, %o1; \ andcc %o0, %o1, %g0; \ be 9f; \ nop; \ SET(f2, %g1, %o1); \ ba 10f; \ nop; \ 9: SET(dflt, %g1, %o1); \ 10: retl; \ mov %o1, %o0; \ END (__##name) # endif /* SHARED */ #define SPARC_ASM_VIS2_IFUNC(name) \ SPARC_ASM_IFUNC1(name, HWCAP_SPARC_VIS2, \ __##name##_vis2, __##name##_generic) # ifdef HAVE_AS_VIS3_SUPPORT #define SPARC_ASM_VIS3_IFUNC(name) \ SPARC_ASM_IFUNC1(name, HWCAP_SPARC_VIS3, \ __##name##_vis3, __##name##_generic) #define SPARC_ASM_VIS3_VIS2_IFUNC(name) \ SPARC_ASM_IFUNC2(name, HWCAP_SPARC_VIS3, \ __##name##_vis3, \ HWCAP_SPARC_VIS2, \ __##name##_vis2, __##name##_generic) # else /* HAVE_AS_VIS3_SUPPORT */ #define SPARC_ASM_VIS3_IFUNC(name) \ SPARC_ASM_IFUNC_DFLT(name, __##name##_generic) #define SPARC_ASM_VIS3_VIS2_IFUNC(name) \ SPARC_ASM_VIS2_IFUNC(name) # endif /* HAVE_AS_VIS3_SUPPORT */ #else /* __ASSEMBLER__ */ # define sparc_libm_ifunc(name, expr) \ extern void *name##_ifunc (int) __asm__ (#name); \ void *name##_ifunc (int hwcap) \ { \ __typeof (name) *res = expr; \ return res; \ } \ __asm__ (".type " #name ", %gnu_indirect_function"); # define sparc_libc_ifunc(name, expr) sparc_libm_ifunc (name, expr) #endif /* __ASSEMBLER__ */