From 1dbf2bef7934cee9829d875f11968d6ff1fee77f Mon Sep 17 00:00:00 2001 From: mengqinggang Date: Wed, 8 May 2024 10:06:15 +0800 Subject: LoongArch: Add support for TLS Descriptors This is mostly based on AArch64 and RISC-V implementation. Add R_LARCH_TLS_DESC32 and R_LARCH_TLS_DESC64 relocations. For _dl_tlsdesc_dynamic function slow path, temporarily save and restore all vector registers. --- sysdeps/loongarch/tst-gnu2-tls2.h | 377 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100644 sysdeps/loongarch/tst-gnu2-tls2.h (limited to 'sysdeps/loongarch/tst-gnu2-tls2.h') diff --git a/sysdeps/loongarch/tst-gnu2-tls2.h b/sysdeps/loongarch/tst-gnu2-tls2.h new file mode 100644 index 0000000000..8e4216785d --- /dev/null +++ b/sysdeps/loongarch/tst-gnu2-tls2.h @@ -0,0 +1,377 @@ +/* Test TLSDESC relocation. LoongArch64 version. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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 +#include +#include +#include + +/* The instruction between BEFORE_TLSDESC_CALL and _dl_tlsdesc_dynamic, + and the instruction between _dl_tlsdesc_dynamic and AFTER_TLSDESC_CALL, + may modified most of the general-purpose register. */ +#define SAVE_REGISTER(src) \ + asm volatile ("st.d $r3, %0" :"=m"(src) :); + +#ifdef __loongarch_soft_float + +#define BEFORE_TLSDESC_CALL() \ + uint64_t src; \ + SAVE_REGISTER (src); + +#define AFTER_TLSDESC_CALL() \ + uint64_t restore; \ + SAVE_REGISTER (restore); \ + if (src != restore) \ + abort (); + +#else /* hard float */ + +#define SAVE_REGISTER_FCC(src) \ + asm volatile ("movcf2gr $t0, $fcc0" ::: "$t0"); \ + asm volatile ("st.d $t0, %0" :"=m"(src[0]) :); \ + asm volatile ("movcf2gr $t0, $fcc1" ::: "$t0"); \ + asm volatile ("st.d $t0, %0" :"=m"(src[1]) :); \ + asm volatile ("movcf2gr $t0, $fcc2" ::: "$t0"); \ + asm volatile ("st.d $t0, %0" :"=m"(src[2]) :); \ + asm volatile ("movcf2gr $t0, $fcc3" ::: "$t0"); \ + asm volatile ("st.d $t0, %0" :"=m"(src[3]) :); \ + asm volatile ("movcf2gr $t0, $fcc4" ::: "$t0"); \ + asm volatile ("st.d $t0, %0" :"=m"(src[4]) :); \ + asm volatile ("movcf2gr $t0, $fcc5" ::: "$t0"); \ + asm volatile ("st.d $t0, %0" :"=m"(src[5]) :); \ + asm volatile ("movcf2gr $t0, $fcc6" ::: "$t0"); \ + asm volatile ("st.d $t0, %0" :"=m"(src[6]) :); \ + asm volatile ("movcf2gr $t0, $fcc7" ::: "$t0"); \ + asm volatile ("st.d $t0, %0" :"=m"(src[7]) :); + +#define LOAD_REGISTER_FCSR() \ + asm volatile ("li.d $t0, 0x01010101" ::: "$t0"); \ + asm volatile ("movgr2fcsr $fcsr0, $t0" :::); + +#define SAVE_REGISTER_FCSR() \ + asm volatile ("movfcsr2gr $t0, $fcsr0" ::: "$t0"); \ + asm volatile ("st.d $t0, %0" :"=m"(restore_fcsr) :); + +# define INIT_TLSDESC_CALL() \ + unsigned long hwcap = getauxval (AT_HWCAP); + +#define LOAD_REGISTER_FLOAT() \ + asm volatile ("fld.d $f0, %0" ::"m"(src_float[0]) :"$f0"); \ + asm volatile ("fld.d $f1, %0" ::"m"(src_float[1]) :"$f1"); \ + asm volatile ("fld.d $f2, %0" ::"m"(src_float[2]) :"$f2"); \ + asm volatile ("fld.d $f3, %0" ::"m"(src_float[3]) :"$f3"); \ + asm volatile ("fld.d $f4, %0" ::"m"(src_float[4]) :"$f4"); \ + asm volatile ("fld.d $f5, %0" ::"m"(src_float[5]) :"$f5"); \ + asm volatile ("fld.d $f6, %0" ::"m"(src_float[6]) :"$f6"); \ + asm volatile ("fld.d $f7, %0" ::"m"(src_float[7]) :"$f7"); \ + asm volatile ("fld.d $f8, %0" ::"m"(src_float[8]) :"$f8"); \ + asm volatile ("fld.d $f9, %0" ::"m"(src_float[9]) :"$f9"); \ + asm volatile ("fld.d $f10, %0" ::"m"(src_float[10]) :"$f10"); \ + asm volatile ("fld.d $f11, %0" ::"m"(src_float[11]) :"$f11"); \ + asm volatile ("fld.d $f12, %0" ::"m"(src_float[12]) :"$f12"); \ + asm volatile ("fld.d $f13, %0" ::"m"(src_float[13]) :"$f13"); \ + asm volatile ("fld.d $f14, %0" ::"m"(src_float[14]) :"$f14"); \ + asm volatile ("fld.d $f15, %0" ::"m"(src_float[15]) :"$f15"); \ + asm volatile ("fld.d $f16, %0" ::"m"(src_float[16]) :"$f16"); \ + asm volatile ("fld.d $f17, %0" ::"m"(src_float[17]) :"$f17"); \ + asm volatile ("fld.d $f18, %0" ::"m"(src_float[18]) :"$f18"); \ + asm volatile ("fld.d $f19, %0" ::"m"(src_float[19]) :"$f19"); \ + asm volatile ("fld.d $f20, %0" ::"m"(src_float[20]) :"$f20"); \ + asm volatile ("fld.d $f21, %0" ::"m"(src_float[21]) :"$f21"); \ + asm volatile ("fld.d $f22, %0" ::"m"(src_float[22]) :"$f22"); \ + asm volatile ("fld.d $f23, %0" ::"m"(src_float[23]) :"$f23"); \ + asm volatile ("fld.d $f24, %0" ::"m"(src_float[24]) :"$f24"); \ + asm volatile ("fld.d $f25, %0" ::"m"(src_float[25]) :"$f25"); \ + asm volatile ("fld.d $f26, %0" ::"m"(src_float[26]) :"$f26"); \ + asm volatile ("fld.d $f27, %0" ::"m"(src_float[27]) :"$f27"); \ + asm volatile ("fld.d $f28, %0" ::"m"(src_float[28]) :"$f28"); \ + asm volatile ("fld.d $f29, %0" ::"m"(src_float[29]) :"$f29"); \ + asm volatile ("fld.d $f30, %0" ::"m"(src_float[30]) :"$f30"); \ + asm volatile ("fld.d $f31, %0" ::"m"(src_float[31]) :"$f31"); + +#define SAVE_REGISTER_FLOAT() \ + asm volatile ("fst.d $f0, %0" :"=m"(restore_float[0]) :); \ + asm volatile ("fst.d $f1, %0" :"=m"(restore_float[1]) :); \ + asm volatile ("fst.d $f2, %0" :"=m"(restore_float[2]) :); \ + asm volatile ("fst.d $f3, %0" :"=m"(restore_float[3]) :); \ + asm volatile ("fst.d $f4, %0" :"=m"(restore_float[4]) :); \ + asm volatile ("fst.d $f5, %0" :"=m"(restore_float[5]) :); \ + asm volatile ("fst.d $f6, %0" :"=m"(restore_float[6]) :); \ + asm volatile ("fst.d $f7, %0" :"=m"(restore_float[7]) :); \ + asm volatile ("fst.d $f8, %0" :"=m"(restore_float[8]) :); \ + asm volatile ("fst.d $f9, %0" :"=m"(restore_float[9]) :); \ + asm volatile ("fst.d $f10, %0" :"=m"(restore_float[10]) :); \ + asm volatile ("fst.d $f11, %0" :"=m"(restore_float[11]) :); \ + asm volatile ("fst.d $f12, %0" :"=m"(restore_float[12]) :); \ + asm volatile ("fst.d $f13, %0" :"=m"(restore_float[13]) :); \ + asm volatile ("fst.d $f14, %0" :"=m"(restore_float[14]) :); \ + asm volatile ("fst.d $f15, %0" :"=m"(restore_float[15]) :); \ + asm volatile ("fst.d $f16, %0" :"=m"(restore_float[16]) :); \ + asm volatile ("fst.d $f17, %0" :"=m"(restore_float[17]) :); \ + asm volatile ("fst.d $f18, %0" :"=m"(restore_float[18]) :); \ + asm volatile ("fst.d $f19, %0" :"=m"(restore_float[19]) :); \ + asm volatile ("fst.d $f20, %0" :"=m"(restore_float[20]) :); \ + asm volatile ("fst.d $f21, %0" :"=m"(restore_float[21]) :); \ + asm volatile ("fst.d $f22, %0" :"=m"(restore_float[22]) :); \ + asm volatile ("fst.d $f23, %0" :"=m"(restore_float[23]) :); \ + asm volatile ("fst.d $f24, %0" :"=m"(restore_float[24]) :); \ + asm volatile ("fst.d $f25, %0" :"=m"(restore_float[25]) :); \ + asm volatile ("fst.d $f26, %0" :"=m"(restore_float[26]) :); \ + asm volatile ("fst.d $f27, %0" :"=m"(restore_float[27]) :); \ + asm volatile ("fst.d $f28, %0" :"=m"(restore_float[28]) :); \ + asm volatile ("fst.d $f29, %0" :"=m"(restore_float[29]) :); \ + asm volatile ("fst.d $f30, %0" :"=m"(restore_float[30]) :); \ + asm volatile ("fst.d $f31, %0" :"=m"(restore_float[31]) :); + +#ifdef HAVE_LOONGARCH_VEC_COM + #define LOAD_REGISTER_LSX() \ + /* Every byte in $vr0 is 1. */ \ + asm volatile ("vldi $vr0, 1" ::: "$vr0"); \ + asm volatile ("vldi $vr1, 2" ::: "$vr1"); \ + asm volatile ("vldi $vr2, 3" ::: "$vr2"); \ + asm volatile ("vldi $vr3, 4" ::: "$vr3"); \ + asm volatile ("vldi $vr4, 5" ::: "$vr4"); \ + asm volatile ("vldi $vr5, 6" ::: "$vr5"); \ + asm volatile ("vldi $vr6, 7" ::: "$vr6"); \ + asm volatile ("vldi $vr7, 8" ::: "$vr7"); \ + asm volatile ("vldi $vr8, 9" ::: "$vr8"); \ + asm volatile ("vldi $vr9, 10" ::: "$vr9"); \ + asm volatile ("vldi $vr10, 11" ::: "$vr10"); \ + asm volatile ("vldi $vr11, 12" ::: "$vr11"); \ + asm volatile ("vldi $vr12, 13" ::: "$vr12"); \ + asm volatile ("vldi $vr13, 14" ::: "$vr13"); \ + asm volatile ("vldi $vr14, 15" ::: "$vr14"); \ + asm volatile ("vldi $vr15, 16" ::: "$vr15"); \ + asm volatile ("vldi $vr16, 17" ::: "$vr16"); \ + asm volatile ("vldi $vr17, 18" ::: "$vr17"); \ + asm volatile ("vldi $vr18, 19" ::: "$vr18"); \ + asm volatile ("vldi $vr19, 20" ::: "$vr19"); \ + asm volatile ("vldi $vr20, 21" ::: "$vr20"); \ + asm volatile ("vldi $vr21, 22" ::: "$vr21"); \ + asm volatile ("vldi $vr22, 23" ::: "$vr22"); \ + asm volatile ("vldi $vr23, 24" ::: "$vr23"); \ + asm volatile ("vldi $vr24, 25" ::: "$vr24"); \ + asm volatile ("vldi $vr25, 26" ::: "$vr25"); \ + asm volatile ("vldi $vr26, 27" ::: "$vr26"); \ + asm volatile ("vldi $vr27, 28" ::: "$vr27"); \ + asm volatile ("vldi $vr28, 29" ::: "$vr28"); \ + asm volatile ("vldi $vr29, 30" ::: "$vr29"); \ + asm volatile ("vldi $vr30, 31" ::: "$vr30"); \ + asm volatile ("vldi $vr31, 32" ::: "$vr31"); +#else + #define LOAD_REGISTER_LSX() +#endif + +#ifdef HAVE_LOONGARCH_VEC_COM + #define SAVE_REGISTER_LSX() \ + int src_lsx[32][4]; \ + int restore_lsx[32][4]; \ + asm volatile ("vst $vr0, %0" :"=m"(restore_lsx[0]) :); \ + asm volatile ("vst $vr1, %0" :"=m"(restore_lsx[1]) :); \ + asm volatile ("vst $vr2, %0" :"=m"(restore_lsx[2]) :); \ + asm volatile ("vst $vr3, %0" :"=m"(restore_lsx[3]) :); \ + asm volatile ("vst $vr4, %0" :"=m"(restore_lsx[4]) :); \ + asm volatile ("vst $vr5, %0" :"=m"(restore_lsx[5]) :); \ + asm volatile ("vst $vr6, %0" :"=m"(restore_lsx[6]) :); \ + asm volatile ("vst $vr7, %0" :"=m"(restore_lsx[7]) :); \ + asm volatile ("vst $vr8, %0" :"=m"(restore_lsx[8]) :); \ + asm volatile ("vst $vr9, %0" :"=m"(restore_lsx[9]) :); \ + asm volatile ("vst $vr10, %0" :"=m"(restore_lsx[10]) :); \ + asm volatile ("vst $vr11, %0" :"=m"(restore_lsx[11]) :); \ + asm volatile ("vst $vr12, %0" :"=m"(restore_lsx[12]) :); \ + asm volatile ("vst $vr13, %0" :"=m"(restore_lsx[13]) :); \ + asm volatile ("vst $vr14, %0" :"=m"(restore_lsx[14]) :); \ + asm volatile ("vst $vr15, %0" :"=m"(restore_lsx[15]) :); \ + asm volatile ("vst $vr16, %0" :"=m"(restore_lsx[16]) :); \ + asm volatile ("vst $vr17, %0" :"=m"(restore_lsx[17]) :); \ + asm volatile ("vst $vr18, %0" :"=m"(restore_lsx[18]) :); \ + asm volatile ("vst $vr19, %0" :"=m"(restore_lsx[19]) :); \ + asm volatile ("vst $vr20, %0" :"=m"(restore_lsx[20]) :); \ + asm volatile ("vst $vr21, %0" :"=m"(restore_lsx[21]) :); \ + asm volatile ("vst $vr22, %0" :"=m"(restore_lsx[22]) :); \ + asm volatile ("vst $vr23, %0" :"=m"(restore_lsx[23]) :); \ + asm volatile ("vst $vr24, %0" :"=m"(restore_lsx[24]) :); \ + asm volatile ("vst $vr25, %0" :"=m"(restore_lsx[25]) :); \ + asm volatile ("vst $vr26, %0" :"=m"(restore_lsx[26]) :); \ + asm volatile ("vst $vr27, %0" :"=m"(restore_lsx[27]) :); \ + asm volatile ("vst $vr28, %0" :"=m"(restore_lsx[28]) :); \ + asm volatile ("vst $vr29, %0" :"=m"(restore_lsx[29]) :); \ + asm volatile ("vst $vr30, %0" :"=m"(restore_lsx[30]) :); \ + asm volatile ("vst $vr31, %0" :"=m"(restore_lsx[31]) :); \ + for (int i = 0; i < 32; i++) \ + for (int j = 0; j < 4; j++) \ + { \ + src_lsx[i][j] = 0x01010101 * (i + 1); \ + if (src_lsx[i][j] != restore_lsx[i][j]) \ + abort (); \ + } +#else + #define SAVE_REGISTER_LSX() +#endif + +#ifdef HAVE_LOONGARCH_VEC_COM + #define LOAD_REGISTER_LASX() \ + /* Every byte in $xr0 is 1. */ \ + asm volatile ("xvldi $xr0, 1" ::: "$xr0"); \ + asm volatile ("xvldi $xr1, 2" ::: "$xr1"); \ + asm volatile ("xvldi $xr2, 3" ::: "$xr2"); \ + asm volatile ("xvldi $xr3, 4" ::: "$xr3"); \ + asm volatile ("xvldi $xr4, 5" ::: "$xr4"); \ + asm volatile ("xvldi $xr5, 6" ::: "$xr5"); \ + asm volatile ("xvldi $xr6, 7" ::: "$xr6"); \ + asm volatile ("xvldi $xr7, 8" ::: "$xr7"); \ + asm volatile ("xvldi $xr8, 9" ::: "$xr8"); \ + asm volatile ("xvldi $xr9, 10" ::: "$xr9"); \ + asm volatile ("xvldi $xr10, 11" ::: "$xr10"); \ + asm volatile ("xvldi $xr11, 12" ::: "$xr11"); \ + asm volatile ("xvldi $xr12, 13" ::: "$xr12"); \ + asm volatile ("xvldi $xr13, 14" ::: "$xr13"); \ + asm volatile ("xvldi $xr14, 15" ::: "$xr14"); \ + asm volatile ("xvldi $xr15, 16" ::: "$xr15"); \ + asm volatile ("xvldi $xr16, 17" ::: "$xr16"); \ + asm volatile ("xvldi $xr17, 18" ::: "$xr17"); \ + asm volatile ("xvldi $xr18, 19" ::: "$xr18"); \ + asm volatile ("xvldi $xr19, 20" ::: "$xr19"); \ + asm volatile ("xvldi $xr20, 21" ::: "$xr20"); \ + asm volatile ("xvldi $xr21, 22" ::: "$xr21"); \ + asm volatile ("xvldi $xr22, 23" ::: "$xr22"); \ + asm volatile ("xvldi $xr23, 24" ::: "$xr23"); \ + asm volatile ("xvldi $xr24, 25" ::: "$xr24"); \ + asm volatile ("xvldi $xr25, 26" ::: "$xr25"); \ + asm volatile ("xvldi $xr26, 27" ::: "$xr26"); \ + asm volatile ("xvldi $xr27, 28" ::: "$xr27"); \ + asm volatile ("xvldi $xr28, 29" ::: "$xr28"); \ + asm volatile ("xvldi $xr29, 30" ::: "$xr29"); \ + asm volatile ("xvldi $xr30, 31" ::: "$xr30"); \ + asm volatile ("xvldi $xr31, 32" ::: "$xr31"); +#else + #define LOAD_REGISTER_LASX() +#endif + +#ifdef HAVE_LOONGARCH_VEC_COM + #define SAVE_REGISTER_LASX() \ + int src_lasx[32][8]; \ + int restore_lasx[32][8]; \ + asm volatile ("xvst $xr0, %0" :"=m"(restore_lasx[0]) :); \ + asm volatile ("xvst $xr1, %0" :"=m"(restore_lasx[1]) :); \ + asm volatile ("xvst $xr2, %0" :"=m"(restore_lasx[2]) :); \ + asm volatile ("xvst $xr3, %0" :"=m"(restore_lasx[3]) :); \ + asm volatile ("xvst $xr4, %0" :"=m"(restore_lasx[4]) :); \ + asm volatile ("xvst $xr5, %0" :"=m"(restore_lasx[5]) :); \ + asm volatile ("xvst $xr6, %0" :"=m"(restore_lasx[6]) :); \ + asm volatile ("xvst $xr7, %0" :"=m"(restore_lasx[7]) :); \ + asm volatile ("xvst $xr8, %0" :"=m"(restore_lasx[8]) :); \ + asm volatile ("xvst $xr9, %0" :"=m"(restore_lasx[9]) :); \ + asm volatile ("xvst $xr10, %0" :"=m"(restore_lasx[10]) :); \ + asm volatile ("xvst $xr11, %0" :"=m"(restore_lasx[11]) :); \ + asm volatile ("xvst $xr12, %0" :"=m"(restore_lasx[12]) :); \ + asm volatile ("xvst $xr13, %0" :"=m"(restore_lasx[13]) :); \ + asm volatile ("xvst $xr14, %0" :"=m"(restore_lasx[14]) :); \ + asm volatile ("xvst $xr15, %0" :"=m"(restore_lasx[15]) :); \ + asm volatile ("xvst $xr16, %0" :"=m"(restore_lasx[16]) :); \ + asm volatile ("xvst $xr17, %0" :"=m"(restore_lasx[17]) :); \ + asm volatile ("xvst $xr18, %0" :"=m"(restore_lasx[18]) :); \ + asm volatile ("xvst $xr19, %0" :"=m"(restore_lasx[19]) :); \ + asm volatile ("xvst $xr20, %0" :"=m"(restore_lasx[20]) :); \ + asm volatile ("xvst $xr21, %0" :"=m"(restore_lasx[21]) :); \ + asm volatile ("xvst $xr22, %0" :"=m"(restore_lasx[22]) :); \ + asm volatile ("xvst $xr23, %0" :"=m"(restore_lasx[23]) :); \ + asm volatile ("xvst $xr24, %0" :"=m"(restore_lasx[24]) :); \ + asm volatile ("xvst $xr25, %0" :"=m"(restore_lasx[25]) :); \ + asm volatile ("xvst $xr26, %0" :"=m"(restore_lasx[26]) :); \ + asm volatile ("xvst $xr27, %0" :"=m"(restore_lasx[27]) :); \ + asm volatile ("xvst $xr28, %0" :"=m"(restore_lasx[28]) :); \ + asm volatile ("xvst $xr29, %0" :"=m"(restore_lasx[29]) :); \ + asm volatile ("xvst $xr30, %0" :"=m"(restore_lasx[30]) :); \ + asm volatile ("xvst $xr31, %0" :"=m"(restore_lasx[31]) :); \ + for (int i = 0; i < 32; i++) \ + for (int j = 0; j < 8; j++) \ + { \ + src_lasx[i][j] = 0x01010101 * (i + 1); \ + if (src_lasx[i][j] != restore_lasx[i][j]) \ + abort (); \ + } +#else + #define SAVE_REGISTER_LASX() +#endif + +#define BEFORE_TLSDESC_CALL() \ + uint64_t src; \ + double src_float[32]; \ + uint64_t src_fcc[8]; \ + for (int i = 0; i < 32; i++) \ + src_float[i] = i + 1; \ + \ + SAVE_REGISTER (src); \ + LOAD_REGISTER_FCSR (); \ + SAVE_REGISTER_FCC(src_fcc) \ + \ + if (hwcap & HWCAP_LOONGARCH_LASX) \ + { \ + LOAD_REGISTER_LASX (); \ + } \ + else if (hwcap & HWCAP_LOONGARCH_LSX) \ + { \ + LOAD_REGISTER_LSX (); \ + } \ + else \ + { \ + LOAD_REGISTER_FLOAT (); \ + } + +#define AFTER_TLSDESC_CALL() \ + uint64_t restore; \ + uint64_t src_fcsr = 0x01010101; \ + uint64_t restore_fcsr; \ + uint64_t restore_fcc[8]; \ + SAVE_REGISTER (restore); \ + SAVE_REGISTER_FCSR (); \ + SAVE_REGISTER_FCC(restore_fcc) \ + \ + /* memcmp_lasx/strlen_lasx corrupts LSX/LASX registers, */ \ + /* compare LSX/LASX registers first. */ \ + if (hwcap & HWCAP_LOONGARCH_LASX) \ + { \ + SAVE_REGISTER_LASX (); \ + } \ + else if (hwcap & HWCAP_LOONGARCH_LSX) \ + { \ + SAVE_REGISTER_LSX (); \ + } \ + else \ + { \ + double restore_float[32]; \ + SAVE_REGISTER_FLOAT (); \ + \ + for (int i = 0; i < 32; i++) \ + if (src_float[i] != restore_float[i]) \ + abort (); \ + } \ + \ + if (src_fcsr != restore_fcsr) \ + abort (); \ + \ + if (memcmp (src_fcc, restore_fcc, sizeof (src_fcc)) != 0) \ + abort (); \ + \ + if (src != restore) \ + abort (); + +#endif /* #ifdef __loongarch_soft_float */ + +#include_next -- cgit 1.4.1