diff --git a/gold/aarch64-reloc-property.cc b/gold/aarch64-reloc-property.cc index bf521d7..971419d 100644 --- a/gold/aarch64-reloc-property.cc +++ b/gold/aarch64-reloc-property.cc @@ -59,17 +59,50 @@ template<> bool rvalue_checkup<0, 0>(int64_t) { return true; } +namespace +{ + template -uint64_t -rvalue_bit_select(uint64_t x) +class Rvalue_bit_select_impl { - if (U == 63) return x >> L; - return (x & (((uint64_t)1 << (U+1)) - 1)) >> L; -} +public: + static uint64_t + calc(uint64_t x) + { + return (x & (((uint64_t)1 << (U+1)) - 1)) >> L; + } +}; + +template +class Rvalue_bit_select_impl +{ +public: + static uint64_t + calc(uint64_t x) + { + return x >> L; + } +}; template<> +class Rvalue_bit_select_impl<0, 0> +{ +public: + static uint64_t + calc(uint64_t x) + { + return x; + } +}; + +} // End anonymous namespace. + +template uint64_t -rvalue_bit_select<0, 0>(uint64_t x) { return x; } +rvalue_bit_select(uint64_t x) +{ + return Rvalue_bit_select_impl::calc(x); +} AArch64_reloc_property::AArch64_reloc_property( unsigned int code, diff --git a/gold/aarch64-reloc.def b/gold/aarch64-reloc.def index f33929b..1c482b1 100644 --- a/gold/aarch64-reloc.def +++ b/gold/aarch64-reloc.def @@ -40,6 +40,20 @@ ARD(PREL32 , STATIC , DATA , Y, -1, 31,32 ARD(PREL16 , STATIC , DATA , Y, -1, 15,16 , 0,0 , Symbol::RELATIVE_REF , DATA ) // Above is from Table 4-6, Data relocations, 257-262. +ARD(MOVW_UABS_G0 , STATIC , AARCH64 , Y, 0, 0,16 , 0,15 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G0_NC , STATIC , AARCH64 , Y, 0, 0,0 , 0,15 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G1 , STATIC , AARCH64 , Y, 0, 0,32 , 16,31 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G1_NC , STATIC , AARCH64 , Y, 0, 0,0 , 16,31 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G2 , STATIC , AARCH64 , Y, 0, 0,48 , 32,47 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G2_NC , STATIC , AARCH64 , Y, 0, 0,0 , 32,47 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_UABS_G3 , STATIC , AARCH64 , Y, 0, 0,0 , 48,63 , Symbol::ABSOLUTE_REF , MOVW ) +// Above is from Table 4-7, Group relocations to create a 16-, 32-, 48-, or 64-bit unsigned data value or address inline. + +ARD(MOVW_SABS_G0 , STATIC , AARCH64 , Y, 0, 16,16 , 0,15 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_SABS_G1 , STATIC , AARCH64 , Y, 0, 32,32 , 16,31 , Symbol::ABSOLUTE_REF , MOVW ) +ARD(MOVW_SABS_G2 , STATIC , AARCH64 , Y, 0, 48,48 , 32,47 , Symbol::ABSOLUTE_REF , MOVW ) +// Above is from Table 4-8, Group relocations to create a 16, 32, 48, or 64 bit signed data or offset value inline. + ARD(LD_PREL_LO19 , STATIC , AARCH64 , Y, -1, 20,20 , 2,20 , Symbol::RELATIVE_REF , LDST ) ARD(ADR_PREL_LO21 , STATIC , AARCH64 , Y, -1, 20,20 , 0,20 , Symbol::RELATIVE_REF , ADR ) ARD(ADR_PREL_PG_HI21 , STATIC , AARCH64 , Y, -1, 32,32 , 12,32 , Symbol::RELATIVE_REF , ADRP ) diff --git a/gold/aarch64.cc b/gold/aarch64.cc index 75e4177..58a063c 100644 --- a/gold/aarch64.cc +++ b/gold/aarch64.cc @@ -6023,6 +6023,23 @@ Target_aarch64::Scan::local( } break; + case elfcpp::R_AARCH64_MOVW_UABS_G0: // 263 + case elfcpp::R_AARCH64_MOVW_UABS_G0_NC: // 264 + case elfcpp::R_AARCH64_MOVW_UABS_G1: // 265 + case elfcpp::R_AARCH64_MOVW_UABS_G1_NC: // 266 + case elfcpp::R_AARCH64_MOVW_UABS_G2: // 267 + case elfcpp::R_AARCH64_MOVW_UABS_G2_NC: // 268 + case elfcpp::R_AARCH64_MOVW_UABS_G3: // 269 + case elfcpp::R_AARCH64_MOVW_SABS_G0: // 270 + case elfcpp::R_AARCH64_MOVW_SABS_G1: // 271 + case elfcpp::R_AARCH64_MOVW_SABS_G2: // 272 + if (parameters->options().output_is_position_independent()) + { + gold_error(_("%s: unsupported reloc %u in pos independent link."), + object->name().c_str(), r_type); + } + break; + case elfcpp::R_AARCH64_LD_PREL_LO19: // 273 case elfcpp::R_AARCH64_ADR_PREL_LO21: // 274 case elfcpp::R_AARCH64_ADR_PREL_PG_HI21: // 275 @@ -6299,6 +6316,23 @@ Target_aarch64::Scan::global( } break; + case elfcpp::R_AARCH64_MOVW_UABS_G0: // 263 + case elfcpp::R_AARCH64_MOVW_UABS_G0_NC: // 264 + case elfcpp::R_AARCH64_MOVW_UABS_G1: // 265 + case elfcpp::R_AARCH64_MOVW_UABS_G1_NC: // 266 + case elfcpp::R_AARCH64_MOVW_UABS_G2: // 267 + case elfcpp::R_AARCH64_MOVW_UABS_G2_NC: // 268 + case elfcpp::R_AARCH64_MOVW_UABS_G3: // 269 + case elfcpp::R_AARCH64_MOVW_SABS_G0: // 270 + case elfcpp::R_AARCH64_MOVW_SABS_G1: // 271 + case elfcpp::R_AARCH64_MOVW_SABS_G2: // 272 + if (parameters->options().output_is_position_independent()) + { + gold_error(_("%s: unsupported reloc %u in pos independent link."), + object->name().c_str(), r_type); + } + break; + case elfcpp::R_AARCH64_LD_PREL_LO19: // 273 case elfcpp::R_AARCH64_ADR_PREL_LO21: // 274 case elfcpp::R_AARCH64_ADR_PREL_PG_HI21: // 275 @@ -6981,6 +7015,23 @@ Target_aarch64::Relocate::relocate( view, object, psymval, addend, address, reloc_property); break; + case elfcpp::R_AARCH64_MOVW_UABS_G0: + case elfcpp::R_AARCH64_MOVW_UABS_G0_NC: + case elfcpp::R_AARCH64_MOVW_UABS_G1: + case elfcpp::R_AARCH64_MOVW_UABS_G1_NC: + case elfcpp::R_AARCH64_MOVW_UABS_G2: + case elfcpp::R_AARCH64_MOVW_UABS_G2_NC: + case elfcpp::R_AARCH64_MOVW_UABS_G3: + reloc_status = Reloc::template rela_general<64>( + view, object, psymval, addend, reloc_property); + break; + case elfcpp::R_AARCH64_MOVW_SABS_G0: + case elfcpp::R_AARCH64_MOVW_SABS_G1: + case elfcpp::R_AARCH64_MOVW_SABS_G2: + reloc_status = Reloc::movnz(view, psymval->value(object, addend), + reloc_property); + break; + case elfcpp::R_AARCH64_LD_PREL_LO19: reloc_status = Reloc::template pcrela_general<32>( view, object, psymval, addend, address, reloc_property); diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 01cae9f..8a72f76 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -3472,6 +3472,23 @@ MOSTLYCLEANFILES += arm_farcall_thumb_arm arm_farcall_thumb_arm_5t endif DEFAULT_TARGET_ARM +if DEFAULT_TARGET_AARCH64 + +check_SCRIPTS += aarch64_relocs.sh +check_DATA += aarch64_relocs.stdout +aarch64_globals.o: aarch64_globals.s + $(TEST_AS) -o $@ $< +aarch64_relocs.o: aarch64_relocs.s + $(TEST_AS) -o $@ $< +aarch64_relocs: aarch64_relocs.o aarch64_globals.o ../ld-new + ../ld-new -o $@ aarch64_relocs.o aarch64_globals.o -e0 --emit-relocs +aarch64_relocs.stdout: aarch64_relocs + $(TEST_OBJDUMP) -dr $< > $@ + +MOSTLYCLEANFILES += aarch64_relocs + +endif DEFAULT_TARGET_AARCH64 + if DEFAULT_TARGET_S390 check_SCRIPTS += split_s390.sh diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 3771f79..da73903 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -882,8 +882,11 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_thumb_6m \ @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_arm \ @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_arm_5t -@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_89 = split_s390.sh -@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_90 = split_s390_z1.stdout split_s390_z2.stdout split_s390_z3.stdout \ +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_89 = aarch64_relocs.sh +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_90 = aarch64_relocs.stdout +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_91 = aarch64_relocs +@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_92 = split_s390.sh +@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_93 = split_s390_z1.stdout split_s390_z2.stdout split_s390_z3.stdout \ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390_z4.stdout split_s390_n1.stdout split_s390_n2.stdout \ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390_a1.stdout split_s390_a2.stdout split_s390_z1_ns.stdout \ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390_z2_ns.stdout split_s390_z3_ns.stdout split_s390_z4_ns.stdout \ @@ -895,7 +898,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390x_z4_ns.stdout split_s390x_n1_ns.stdout \ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390x_n2_ns.stdout split_s390x_r.stdout -@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_91 = split_s390_z1 split_s390_z2 split_s390_z3 \ +@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_94 = split_s390_z1 split_s390_z2 split_s390_z3 \ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390_z4 split_s390_n1 split_s390_n2 split_s390_a1 \ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390_a2 split_s390_z1_ns split_s390_z2_ns split_s390_z3_ns \ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390_z4_ns split_s390_n1_ns split_s390_n2_ns split_s390_r \ @@ -904,10 +907,10 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390x_z1_ns split_s390x_z2_ns split_s390x_z3_ns \ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_s390x_z4_ns split_s390x_n1_ns split_s390x_n2_ns split_s390x_r -@DEFAULT_TARGET_X86_64_TRUE@am__append_92 = *.dwo *.dwp -@DEFAULT_TARGET_X86_64_TRUE@am__append_93 = dwp_test_1.sh \ +@DEFAULT_TARGET_X86_64_TRUE@am__append_95 = *.dwo *.dwp +@DEFAULT_TARGET_X86_64_TRUE@am__append_96 = dwp_test_1.sh \ @DEFAULT_TARGET_X86_64_TRUE@ dwp_test_2.sh -@DEFAULT_TARGET_X86_64_TRUE@am__append_94 = dwp_test_1.stdout \ +@DEFAULT_TARGET_X86_64_TRUE@am__append_97 = dwp_test_1.stdout \ @DEFAULT_TARGET_X86_64_TRUE@ dwp_test_2.stdout subdir = testsuite DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am @@ -2616,7 +2619,7 @@ MOSTLYCLEANFILES = *.so *.syms *.stdout $(am__append_4) \ $(am__append_68) $(am__append_71) $(am__append_73) \ $(am__append_76) $(am__append_79) $(am__append_82) \ $(am__append_85) $(am__append_88) $(am__append_91) \ - $(am__append_92) + $(am__append_94) $(am__append_95) # We will add to these later, for each individual test. Note # that we add each test under check_SCRIPTS or check_PROGRAMS; @@ -2626,13 +2629,15 @@ check_SCRIPTS = $(am__append_2) $(am__append_21) $(am__append_27) \ $(am__append_43) $(am__append_47) $(am__append_50) \ $(am__append_66) $(am__append_69) $(am__append_74) \ $(am__append_77) $(am__append_80) $(am__append_83) \ - $(am__append_86) $(am__append_89) $(am__append_93) + $(am__append_86) $(am__append_89) $(am__append_92) \ + $(am__append_96) check_DATA = $(am__append_3) $(am__append_22) $(am__append_28) \ $(am__append_31) $(am__append_37) $(am__append_40) \ $(am__append_44) $(am__append_48) $(am__append_51) \ $(am__append_67) $(am__append_70) $(am__append_75) \ $(am__append_78) $(am__append_81) $(am__append_84) \ - $(am__append_87) $(am__append_90) $(am__append_94) + $(am__append_87) $(am__append_90) $(am__append_93) \ + $(am__append_97) BUILT_SOURCES = $(am__append_34) TESTS = $(check_SCRIPTS) $(check_PROGRAMS) @@ -4697,6 +4702,8 @@ arm_farcall_thumb_thumb.sh.log: arm_farcall_thumb_thumb.sh @p='arm_farcall_thumb_thumb.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) arm_farcall_thumb_arm.sh.log: arm_farcall_thumb_arm.sh @p='arm_farcall_thumb_arm.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) +aarch64_relocs.sh.log: aarch64_relocs.sh + @p='aarch64_relocs.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) split_s390.sh.log: split_s390.sh @p='split_s390.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) dwp_test_1.sh.log: dwp_test_1.sh @@ -7067,6 +7074,14 @@ uninstall-am: @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@arm_farcall_thumb_arm_5t.o: arm_farcall_thumb_arm.s @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -march=armv5t -o $@ $< +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@aarch64_globals.o: aarch64_globals.s +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@aarch64_relocs.o: aarch64_relocs.s +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@aarch64_relocs: aarch64_relocs.o aarch64_globals.o ../ld-new +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new -o $@ aarch64_relocs.o aarch64_globals.o -e0 --emit-relocs +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@aarch64_relocs.stdout: aarch64_relocs +@DEFAULT_TARGET_AARCH64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -dr $< > $@ @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_1_z1.o: split_s390_1_z1.s @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -m31 -o $@ $< @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_1_z2.o: split_s390_1_z2.s diff --git a/gold/testsuite/aarch64_globals.s b/gold/testsuite/aarch64_globals.s new file mode 100644 index 0000000..f6a1897 --- /dev/null +++ b/gold/testsuite/aarch64_globals.s @@ -0,0 +1,11 @@ +.global abs_0x1234 +abs_0x1234=0x1234 + +.global abs_0x11000 +abs_0x11000=0x11000 + +.global abs_0x45000 +abs_0x45000=0x45000 + +.global abs_0x3600010000 +abs_0x3600010000=0x3600010000 diff --git a/gold/testsuite/aarch64_relocs.s b/gold/testsuite/aarch64_relocs.s new file mode 100644 index 0000000..0aa3d68 --- /dev/null +++ b/gold/testsuite/aarch64_relocs.s @@ -0,0 +1,45 @@ +.text + +test_R_AARCH64_MOVW_UABS_G0: + movz x4, :abs_g0:abs_0x1234 + movz x4, :abs_g0:abs_0x1234 + 4 + +test_R_AARCH64_MOVW_UABS_G0_NC: + movz x4, :abs_g0_nc:abs_0x1234 + movz x4, :abs_g0_nc:abs_0x1234 + 0x45000 + +test_R_AARCH64_MOVW_UABS_G1: + movz x4, :abs_g1:abs_0x1234 - 4 + movz x4, :abs_g1:abs_0x11000 + movz x4, :abs_g1:abs_0x45000 + 0x20010 + +test_R_AARCH64_MOVW_UABS_G1_NC: + movz x4, :abs_g1_nc:abs_0x1234 - 4 + movz x4, :abs_g1_nc:abs_0x11000 + movz x4, :abs_g1_nc:abs_0x45000 + 0x100020010 + +test_R_AARCH64_MOVW_UABS_G2: + movz x4, :abs_g2:abs_0x45000 + 0x20010 + movz x4, :abs_g2:abs_0x3600010000 + 0x100020010 + +test_R_AARCH64_MOVW_UABS_G2_NC: + movz x4, :abs_g2_nc:abs_0x45000 + 0x20010 + movz x4, :abs_g2_nc:abs_0x3600010000 + 0x3000100020010 + +test_R_AARCH64_MOVW_UABS_G3: + movz x4, :abs_g3:abs_0x3600010000 + 0x100020010 + movz x4, :abs_g3:abs_0x3600010000 + 0x3000100020010 + +test_R_AARCH64_MOVW_SABS_G0: + movz x4, :abs_g0_s:abs_0x1234 + 4 + movz x4, :abs_g0_s:abs_0x1234 - 0x2345 + +test_R_AARCH64_MOVW_SABS_G1: + movz x4, :abs_g1_s:abs_0x1234 - 0x2345 + movz x4, :abs_g1_s:abs_0x45000 + 0x20010 + movz x4, :abs_g1_s:abs_0x45000 - 0x56000 + +test_R_AARCH64_MOVW_SABS_G2: + movz x4, :abs_g2_s:abs_0x45000 + 0x20010 + movz x4, :abs_g2_s:abs_0x3600010000 + 0x100020010 + movz x4, :abs_g2_s:abs_0x3600010000 - 0x4400010000 diff --git a/gold/testsuite/aarch64_relocs.sh b/gold/testsuite/aarch64_relocs.sh new file mode 100755 index 0000000..f23c58f --- /dev/null +++ b/gold/testsuite/aarch64_relocs.sh @@ -0,0 +1,110 @@ +#!/bin/sh + +# aarch64_relocs.sh -- test AArch64 relocations. + +# Copyright (C) 2016 Free Software Foundation, Inc. +# Written by Igor Kudrin + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +check() +{ + file=$1 + lbl=$2 + line=$3 + pattern=$4 + + found=`grep "<$lbl>:" $file` + if test -z "$found"; then + echo "Label $lbl not found." + exit 1 + fi + + match_pattern=`grep "<$lbl>:" -A$line $file | tail -n 1 | grep -e "$pattern"` + if test -z "$match_pattern"; then + echo "Expected pattern did not found in line $line after label $lbl:" + echo " $pattern" + echo "" + echo "Extract:" + grep "<$lbl>:" -A$line $file + echo "" + echo "Actual output below:" + cat "$file" + exit 1 + fi +} + +check "aarch64_relocs.stdout" "test_R_AARCH64_MOVW_UABS_G0" 1 "\