[NDS32] Support Linux target for nds32.
gcc/ * config.gcc (nds32*): Use nds32-linux.opt and nds32-elf.opt. (nds32le-*-*, nds32be-*-*): Integrate checking process. (nds32*-*-*): Add glibc and uclibc conditions. * common/config/nds32/nds32-common.c (nds32_except_unwind_info): New. (TARGET_EXCEPT_UNWIND_INFO): Define. * config/nds32/elf.h: New file. * config/nds32/linux.h: New file. * config/nds32/nds32-elf.opt: New file. * config/nds32/nds32-linux.opt: New file. * config/nds32/nds32-fp-as-gp.c (pass_nds32_fp_as_gp::gate): Consider TARGET_LINUX_ABI. * config/nds32/nds32.c (nds32_conditional_register_usage): Consider TARGET_LINUX_ABI. (nds32_asm_file_end): Ditto. (nds32_print_operand): Ditto. (nds32_insert_attributes): Ditto. (nds32_init_libfuncs): New function. (TARGET_HAVE_TLS): Define. (TARGET_INIT_LIBFUNCS): Define. * config/nds32/nds32.h (TARGET_DEFAULT_RELAX): Apply different relax spec content. (TARGET_ELF): Apply different mcmodel setting. (LINK_SPEC, LIB_SPEC, STARTFILE_SPEC, ENDFILE_SPEC): The content has been migrated into elf.h and linux.h files. * config/nds32/nds32.md (add_pc): Consider TARGET_LINUX_ABI. * config/nds32/nds32.opt (mvh): Consider TARGET_LINUX_ABI. (mcmodel): The content has been migrated into nds32-elf.opt and nds32-linux.opt files. * config/nds32/t-elf: New file. * config/nds32/t-linux: New file. libgcc/ * config.host (nds32*-linux*): New. * config/nds32/linux-atomic.c: New file. * config/nds32/linux-unwind.h: New file. Co-Authored-By: Kito Cheng <kito.cheng@gmail.com> Co-Authored-By: Monk Chiang <sh.chiang04@gmail.com> From-SVN: r261116
This commit is contained in:
parent
2140297cb3
commit
cf3cd43d5a
|
@ -1,3 +1,37 @@
|
||||||
|
2018-06-02 Chung-Ju Wu <jasonwucj@gmail.com>
|
||||||
|
Kito Cheng <kito.cheng@gmail.com>
|
||||||
|
|
||||||
|
* config.gcc (nds32*): Use nds32-linux.opt and nds32-elf.opt.
|
||||||
|
(nds32le-*-*, nds32be-*-*): Integrate checking process.
|
||||||
|
(nds32*-*-*): Add glibc and uclibc conditions.
|
||||||
|
* common/config/nds32/nds32-common.c (nds32_except_unwind_info): New.
|
||||||
|
(TARGET_EXCEPT_UNWIND_INFO): Define.
|
||||||
|
* config/nds32/elf.h: New file.
|
||||||
|
* config/nds32/linux.h: New file.
|
||||||
|
* config/nds32/nds32-elf.opt: New file.
|
||||||
|
* config/nds32/nds32-linux.opt: New file.
|
||||||
|
* config/nds32/nds32-fp-as-gp.c
|
||||||
|
(pass_nds32_fp_as_gp::gate): Consider TARGET_LINUX_ABI.
|
||||||
|
* config/nds32/nds32.c (nds32_conditional_register_usage): Consider
|
||||||
|
TARGET_LINUX_ABI.
|
||||||
|
(nds32_asm_file_end): Ditto.
|
||||||
|
(nds32_print_operand): Ditto.
|
||||||
|
(nds32_insert_attributes): Ditto.
|
||||||
|
(nds32_init_libfuncs): New function.
|
||||||
|
(TARGET_HAVE_TLS): Define.
|
||||||
|
(TARGET_INIT_LIBFUNCS): Define.
|
||||||
|
* config/nds32/nds32.h (TARGET_DEFAULT_RELAX): Apply different relax
|
||||||
|
spec content.
|
||||||
|
(TARGET_ELF): Apply different mcmodel setting.
|
||||||
|
(LINK_SPEC, LIB_SPEC, STARTFILE_SPEC, ENDFILE_SPEC): The content has
|
||||||
|
been migrated into elf.h and linux.h files.
|
||||||
|
* config/nds32/nds32.md (add_pc): Consider TARGET_LINUX_ABI.
|
||||||
|
* config/nds32/nds32.opt (mvh): Consider TARGET_LINUX_ABI.
|
||||||
|
(mcmodel): The content has been migrated into nds32-elf.opt and
|
||||||
|
nds32-linux.opt files.
|
||||||
|
* config/nds32/t-elf: New file.
|
||||||
|
* config/nds32/t-linux: New file.
|
||||||
|
|
||||||
2018-06-02 Chung-Ju Wu <jasonwucj@gmail.com>
|
2018-06-02 Chung-Ju Wu <jasonwucj@gmail.com>
|
||||||
Shiva Chen <shiva0217@gmail.com>
|
Shiva Chen <shiva0217@gmail.com>
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,19 @@ static const struct default_options nds32_option_optimization_table[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/* Implement TARGET_EXCEPT_UNWIND_INFO. */
|
||||||
|
static enum unwind_info_type
|
||||||
|
nds32_except_unwind_info (struct gcc_options *opts ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
if (TARGET_LINUX_ABI)
|
||||||
|
return UI_DWARF2;
|
||||||
|
|
||||||
|
return UI_SJLJ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
/* Run-time Target Specification. */
|
/* Run-time Target Specification. */
|
||||||
|
|
||||||
|
@ -127,7 +140,7 @@ static const struct default_options nds32_option_optimization_table[] =
|
||||||
/* Defining the Output Assembler Language. */
|
/* Defining the Output Assembler Language. */
|
||||||
|
|
||||||
#undef TARGET_EXCEPT_UNWIND_INFO
|
#undef TARGET_EXCEPT_UNWIND_INFO
|
||||||
#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info
|
#define TARGET_EXCEPT_UNWIND_INFO nds32_except_unwind_info
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
|
@ -448,6 +448,16 @@ mips*-*-*)
|
||||||
nds32*)
|
nds32*)
|
||||||
cpu_type=nds32
|
cpu_type=nds32
|
||||||
extra_headers="nds32_intrinsic.h"
|
extra_headers="nds32_intrinsic.h"
|
||||||
|
case ${target} in
|
||||||
|
nds32*-*-linux*)
|
||||||
|
extra_options="${extra_options} nds32/nds32-linux.opt"
|
||||||
|
;;
|
||||||
|
nds32*-*-elf*)
|
||||||
|
extra_options="${extra_options} nds32/nds32-elf.opt"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
extra_objs="nds32-cost.o nds32-intrinsic.o nds32-isr.o nds32-md-auxiliary.o nds32-pipelines-auxiliary.o nds32-predicates.o nds32-memory-manipulation.o nds32-fp-as-gp.o nds32-relax-opt.o nds32-utils.o"
|
extra_objs="nds32-cost.o nds32-intrinsic.o nds32-isr.o nds32-md-auxiliary.o nds32-pipelines-auxiliary.o nds32-predicates.o nds32-memory-manipulation.o nds32-fp-as-gp.o nds32-relax-opt.o nds32-utils.o"
|
||||||
;;
|
;;
|
||||||
nios2-*-*)
|
nios2-*-*)
|
||||||
|
@ -2335,18 +2345,32 @@ msp430*-*-*)
|
||||||
tmake_file="${tmake_file} msp430/t-msp430"
|
tmake_file="${tmake_file} msp430/t-msp430"
|
||||||
extra_gcc_objs="driver-msp430.o"
|
extra_gcc_objs="driver-msp430.o"
|
||||||
;;
|
;;
|
||||||
nds32le-*-*)
|
nds32*-*-*)
|
||||||
target_cpu_default="0"
|
target_cpu_default="0"
|
||||||
tm_defines="${tm_defines}"
|
tm_defines="${tm_defines}"
|
||||||
tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} nds32/nds32_intrinsic.h"
|
case ${target} in
|
||||||
tmake_file="nds32/t-nds32 nds32/t-mlibs"
|
nds32le*-*-*)
|
||||||
;;
|
;;
|
||||||
nds32be-*-*)
|
nds32be-*-*)
|
||||||
target_cpu_default="0|MASK_BIG_ENDIAN"
|
target_cpu_default="${target_cpu_default}|MASK_BIG_ENDIAN"
|
||||||
tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
|
tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
|
||||||
tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} nds32/nds32_intrinsic.h"
|
;;
|
||||||
tmake_file="nds32/t-nds32 nds32/t-mlibs"
|
esac
|
||||||
|
case ${target} in
|
||||||
|
nds32*-*-elf*)
|
||||||
|
tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} nds32/elf.h nds32/nds32_intrinsic.h"
|
||||||
|
tmake_file="nds32/t-nds32 nds32/t-elf"
|
||||||
|
;;
|
||||||
|
nds32*-*-linux*)
|
||||||
|
tm_file="dbxelf.h elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h nds32/linux.h nds32/nds32_intrinsic.h"
|
||||||
|
tmake_file="${tmake_file} nds32/t-nds32 nds32/t-linux"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Handle --enable-default-relax setting.
|
||||||
|
if test x${enable_default_relax} = xyes; then
|
||||||
|
tm_defines="${tm_defines} TARGET_DEFAULT_RELAX=1"
|
||||||
|
fi
|
||||||
# Handle --with-ext-dsp
|
# Handle --with-ext-dsp
|
||||||
if test x${with_ext_dsp} = xyes; then
|
if test x${with_ext_dsp} = xyes; then
|
||||||
tm_defines="${tm_defines} TARGET_DEFAULT_EXT_DSP=1"
|
tm_defines="${tm_defines} TARGET_DEFAULT_EXT_DSP=1"
|
||||||
|
@ -4383,15 +4407,30 @@ case "${target}" in
|
||||||
"")
|
"")
|
||||||
# the default library is newlib
|
# the default library is newlib
|
||||||
with_nds32_lib=newlib
|
with_nds32_lib=newlib
|
||||||
|
tm_defines="${tm_defines} TARGET_DEFAULT_CTOR_DTOR=1"
|
||||||
;;
|
;;
|
||||||
newlib)
|
newlib)
|
||||||
# OK
|
# OK
|
||||||
|
tm_defines="${tm_defines} TARGET_DEFAULT_CTOR_DTOR=1"
|
||||||
;;
|
;;
|
||||||
mculib)
|
mculib)
|
||||||
# OK
|
# OK
|
||||||
|
# for the arch=v3f or arch=v3s under mculib toolchain,
|
||||||
|
# we would like to set -fno-math-errno as default
|
||||||
|
case "${with_arch}" in
|
||||||
|
v3f | v3s)
|
||||||
|
tm_defines="${tm_defines} TARGET_DEFAULT_NO_MATH_ERRNO=1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
glibc)
|
||||||
|
# OK
|
||||||
|
tm_defines="${tm_defines} TARGET_DEFAULT_TLSDESC_TRAMPOLINE=1"
|
||||||
|
;;
|
||||||
|
uclibc)
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Cannot accept --with-nds32-lib=$with_nds32_lib, available values are: newlib mculib" 1>&2
|
echo "Cannot accept --with-nds32-lib=$with_nds32_lib, available values are: newlib mculib glibc uclibc" 1>&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/* Definitions of target machine of Andes NDS32 cpu for GNU compiler
|
||||||
|
Copyright (C) 2012-2014 Free Software Foundation, Inc.
|
||||||
|
Contributed by Andes Technology Corporation.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC 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, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
GCC 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 GCC; see the file COPYING3. If not see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
#define TARGET_LINUX_ABI 0
|
||||||
|
|
||||||
|
/* In the configure stage we may use options --enable-default-relax,
|
||||||
|
--enable-Os-default-ifc and --enable-Os-default-ex9. They effect
|
||||||
|
the default spec of passing --relax, --mifc, and --mex9 to linker.
|
||||||
|
We use NDS32_RELAX_SPEC, NDS32_IFC_SPEC, and NDS32_EX9_SPEC
|
||||||
|
so that we can customize them conveniently. */
|
||||||
|
#define LINK_SPEC \
|
||||||
|
" %{G*}" \
|
||||||
|
" %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
|
||||||
|
" %{shared:-shared}" \
|
||||||
|
NDS32_RELAX_SPEC
|
||||||
|
|
||||||
|
#define LIB_SPEC \
|
||||||
|
" -lc -lgloss"
|
||||||
|
|
||||||
|
#define LIBGCC_SPEC \
|
||||||
|
" -lgcc"
|
||||||
|
|
||||||
|
/* The option -mno-ctor-dtor can disable constructor/destructor feature
|
||||||
|
by applying different crt stuff. In the convention, crt0.o is the
|
||||||
|
startup file without constructor/destructor;
|
||||||
|
crt1.o, crti.o, crtbegin.o, crtend.o, and crtn.o are the
|
||||||
|
startup files with constructor/destructor.
|
||||||
|
Note that crt0.o, crt1.o, crti.o, and crtn.o are provided
|
||||||
|
by newlib/mculib/glibc/ublic, while crtbegin.o and crtend.o are
|
||||||
|
currently provided by GCC for nds32 target.
|
||||||
|
|
||||||
|
For nds32 target so far:
|
||||||
|
If -mno-ctor-dtor, we are going to link
|
||||||
|
"crt0.o [user objects]".
|
||||||
|
If -mctor-dtor, we are going to link
|
||||||
|
"crt1.o crtbegin1.o [user objects] crtend1.o".
|
||||||
|
|
||||||
|
Note that the TARGET_DEFAULT_CTOR_DTOR would effect the
|
||||||
|
default behavior. Check gcc/config.gcc for more information. */
|
||||||
|
#ifdef TARGET_DEFAULT_CTOR_DTOR
|
||||||
|
#define STARTFILE_SPEC \
|
||||||
|
" %{!mno-ctor-dtor:crt1.o%s;:crt0.o%s}" \
|
||||||
|
" %{!mno-ctor-dtor:crtbegin1.o%s}" \
|
||||||
|
" %{mcrt-arg:crtarg.o%s}"
|
||||||
|
#define ENDFILE_SPEC \
|
||||||
|
" %{!mno-ctor-dtor:crtend1.o%s}"
|
||||||
|
#else
|
||||||
|
#define STARTFILE_SPEC \
|
||||||
|
" %{mctor-dtor|coverage:crt1.o%s;:crt0.o%s}" \
|
||||||
|
" %{mctor-dtor|coverage:crtbegin1.o%s}" \
|
||||||
|
" %{mcrt-arg:crtarg.o%s}"
|
||||||
|
#define ENDFILE_SPEC \
|
||||||
|
" %{mctor-dtor|coverage:crtend1.o%s}"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STARTFILE_CXX_SPEC \
|
||||||
|
" %{!mno-ctor-dtor:crt1.o%s;:crt0.o%s}" \
|
||||||
|
" %{!mno-ctor-dtor:crtbegin1.o%s}" \
|
||||||
|
" %{mcrt-arg:crtarg.o%s}"
|
||||||
|
#define ENDFILE_CXX_SPEC \
|
||||||
|
" %{!mno-ctor-dtor:crtend1.o%s}"
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* Definitions of target machine of Andes NDS32 cpu for GNU compiler
|
||||||
|
Copyright (C) 2012-2014 Free Software Foundation, Inc.
|
||||||
|
Contributed by Andes Technology Corporation.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC 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, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
GCC 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 GCC; see the file COPYING3. If not see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
#define TARGET_LINUX_ABI 1
|
||||||
|
|
||||||
|
#undef SIZE_TYPE
|
||||||
|
#define SIZE_TYPE "unsigned int"
|
||||||
|
|
||||||
|
#undef PTRDIFF_TYPE
|
||||||
|
#define PTRDIFF_TYPE "int"
|
||||||
|
|
||||||
|
#ifdef TARGET_DEFAULT_TLSDESC_TRAMPOLINE
|
||||||
|
#define NDS32_TLSDESC_TRAMPOLINE_SPEC \
|
||||||
|
" %{!mno-tlsdesc-trampoline:--mtlsdesc-trampoline}"
|
||||||
|
#else
|
||||||
|
#define NDS32_TLSDESC_TRAMPOLINE_SPEC ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TARGET_OS_CPP_BUILTINS() \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
GNU_USER_TARGET_OS_CPP_BUILTINS(); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
|
||||||
|
|
||||||
|
/* In the configure stage we may use options --enable-default-relax,
|
||||||
|
--enable-Os-default-ifc and --enable-Os-default-ex9. They effect
|
||||||
|
the default spec of passing --relax, --mifc, and --mex9 to linker.
|
||||||
|
We use NDS32_RELAX_SPEC, NDS32_IFC_SPEC, and NDS32_EX9_SPEC
|
||||||
|
so that we can customize them conveniently. */
|
||||||
|
#define LINK_SPEC \
|
||||||
|
" %{G*}" \
|
||||||
|
" %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
|
||||||
|
" %{shared:-shared} \
|
||||||
|
%{!shared: \
|
||||||
|
%{!static: \
|
||||||
|
%{rdynamic:-export-dynamic} \
|
||||||
|
-dynamic-linker " GNU_USER_DYNAMIC_LINKER "} \
|
||||||
|
%{static:-static}}" \
|
||||||
|
NDS32_RELAX_SPEC \
|
||||||
|
NDS32_TLSDESC_TRAMPOLINE_SPEC
|
||||||
|
|
||||||
|
#define LINK_PIE_SPEC "%{pie:%{!fno-pie:%{!fno-PIE:%{!static:-pie}}}} "
|
||||||
|
|
||||||
|
#define CPP_SPEC "%{pthread:-D_REENTRANT}"
|
||||||
|
|
||||||
|
/* The SYNC operations are implemented as library functions, not
|
||||||
|
INSN patterns. As a result, the HAVE defines for the patterns are
|
||||||
|
not defined. We need to define them to generate the corresponding
|
||||||
|
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_* and __GCC_ATOMIC_*_LOCK_FREE
|
||||||
|
defines.
|
||||||
|
Ref: https://sourceware.org/ml/libc-alpha/2014-09/msg00322.html */
|
||||||
|
#define HAVE_sync_compare_and_swapqi 1
|
||||||
|
#define HAVE_sync_compare_and_swaphi 1
|
||||||
|
#define HAVE_sync_compare_and_swapsi 1
|
|
@ -0,0 +1,16 @@
|
||||||
|
mcmodel=
|
||||||
|
Target RejectNegative Joined Enum(nds32_cmodel_type) Var(nds32_cmodel_option) Init(CMODEL_MEDIUM)
|
||||||
|
Specify the address generation strategy for code model.
|
||||||
|
|
||||||
|
Enum
|
||||||
|
Name(nds32_cmodel_type) Type(enum nds32_cmodel_type)
|
||||||
|
Known cmodel types (for use with the -mcmodel= option):
|
||||||
|
|
||||||
|
EnumValue
|
||||||
|
Enum(nds32_cmodel_type) String(small) Value(CMODEL_SMALL)
|
||||||
|
|
||||||
|
EnumValue
|
||||||
|
Enum(nds32_cmodel_type) String(medium) Value(CMODEL_MEDIUM)
|
||||||
|
|
||||||
|
EnumValue
|
||||||
|
Enum(nds32_cmodel_type) String(large) Value(CMODEL_LARGE)
|
|
@ -265,7 +265,8 @@ public:
|
||||||
/* opt_pass methods: */
|
/* opt_pass methods: */
|
||||||
bool gate (function *)
|
bool gate (function *)
|
||||||
{
|
{
|
||||||
return TARGET_16_BIT
|
return !TARGET_LINUX_ABI
|
||||||
|
&& TARGET_16_BIT
|
||||||
&& optimize_size;
|
&& optimize_size;
|
||||||
}
|
}
|
||||||
unsigned int execute (function *) { return nds32_fp_as_gp (); }
|
unsigned int execute (function *) { return nds32_fp_as_gp (); }
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
mcmodel=
|
||||||
|
Target RejectNegative Joined Enum(nds32_cmodel_type) Var(nds32_cmodel_option) Init(CMODEL_LARGE)
|
||||||
|
Specify the address generation strategy for code model.
|
||||||
|
|
||||||
|
Enum
|
||||||
|
Name(nds32_cmodel_type) Type(enum nds32_cmodel_type)
|
||||||
|
Known cmodel types (for use with the -mcmodel= option):
|
||||||
|
|
||||||
|
EnumValue
|
||||||
|
Enum(nds32_cmodel_type) String(small) Value(CMODEL_SMALL)
|
||||||
|
|
||||||
|
EnumValue
|
||||||
|
Enum(nds32_cmodel_type) String(medium) Value(CMODEL_MEDIUM)
|
||||||
|
|
||||||
|
EnumValue
|
||||||
|
Enum(nds32_cmodel_type) String(large) Value(CMODEL_LARGE)
|
|
@ -1698,6 +1698,9 @@ nds32_conditional_register_usage (void)
|
||||||
{
|
{
|
||||||
int regno;
|
int regno;
|
||||||
|
|
||||||
|
if (TARGET_LINUX_ABI)
|
||||||
|
fixed_regs[TP_REGNUM] = 1;
|
||||||
|
|
||||||
if (TARGET_HARD_FLOAT)
|
if (TARGET_HARD_FLOAT)
|
||||||
{
|
{
|
||||||
for (regno = NDS32_FIRST_FPR_REGNUM;
|
for (regno = NDS32_FIRST_FPR_REGNUM;
|
||||||
|
@ -3120,21 +3123,30 @@ nds32_asm_file_start (void)
|
||||||
fprintf (asm_out_file, "\t! This asm file is generated by compiler\n");
|
fprintf (asm_out_file, "\t! This asm file is generated by compiler\n");
|
||||||
fprintf (asm_out_file, "\t.flag\tverbatim\n");
|
fprintf (asm_out_file, "\t.flag\tverbatim\n");
|
||||||
|
|
||||||
if (TARGET_ICT_MODEL_LARGE)
|
/* Insert directive for linker to distinguish object's ict flag. */
|
||||||
fprintf (asm_out_file, "\t.ict_model\tlarge\n");
|
if (!TARGET_LINUX_ABI)
|
||||||
else
|
{
|
||||||
fprintf (asm_out_file, "\t.ict_model\tsmall\n");
|
if (TARGET_ICT_MODEL_LARGE)
|
||||||
/* Give assembler the size of each vector for interrupt handler. */
|
fprintf (asm_out_file, "\t.ict_model\tlarge\n");
|
||||||
fprintf (asm_out_file, "\t! This vector size directive is required "
|
else
|
||||||
"for checking inconsistency on interrupt handler\n");
|
fprintf (asm_out_file, "\t.ict_model\tsmall\n");
|
||||||
fprintf (asm_out_file, "\t.vec_size\t%d\n", nds32_isr_vector_size);
|
}
|
||||||
|
|
||||||
|
/* We need to provide the size of each vector for interrupt handler
|
||||||
|
under elf toolchain. */
|
||||||
|
if (!TARGET_LINUX_ABI)
|
||||||
|
{
|
||||||
|
fprintf (asm_out_file, "\t! This vector size directive is required "
|
||||||
|
"for checking inconsistency on interrupt handler\n");
|
||||||
|
fprintf (asm_out_file, "\t.vec_size\t%d\n", nds32_isr_vector_size);
|
||||||
|
}
|
||||||
|
|
||||||
/* If user enables '-mforce-fp-as-gp' or compiles programs with -Os,
|
/* If user enables '-mforce-fp-as-gp' or compiles programs with -Os,
|
||||||
the compiler may produce 'la $fp,_FP_BASE_' instruction
|
the compiler may produce 'la $fp,_FP_BASE_' instruction
|
||||||
at prologue for fp-as-gp optimization.
|
at prologue for fp-as-gp optimization.
|
||||||
We should emit weak reference of _FP_BASE_ to avoid undefined reference
|
We should emit weak reference of _FP_BASE_ to avoid undefined reference
|
||||||
in case user does not pass '--relax' option to linker. */
|
in case user does not pass '--relax' option to linker. */
|
||||||
if (TARGET_FORCE_FP_AS_GP || optimize_size)
|
if (!TARGET_LINUX_ABI && (TARGET_FORCE_FP_AS_GP || optimize_size))
|
||||||
{
|
{
|
||||||
fprintf (asm_out_file, "\t! This weak reference is required to do "
|
fprintf (asm_out_file, "\t! This weak reference is required to do "
|
||||||
"fp-as-gp link time optimization\n");
|
"fp-as-gp link time optimization\n");
|
||||||
|
@ -3270,6 +3282,11 @@ nds32_asm_file_end (void)
|
||||||
{
|
{
|
||||||
nds32_asm_file_end_for_isr ();
|
nds32_asm_file_end_for_isr ();
|
||||||
|
|
||||||
|
/* The NDS32 Linux stack is mapped non-executable by default, so add a
|
||||||
|
.note.GNU-stack section. */
|
||||||
|
if (TARGET_LINUX_ABI)
|
||||||
|
file_end_indicate_exec_stack ();
|
||||||
|
|
||||||
fprintf (asm_out_file, "\t! ------------------------------------\n");
|
fprintf (asm_out_file, "\t! ------------------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3497,7 +3514,7 @@ nds32_print_operand (FILE *stream, rtx x, int code)
|
||||||
case SYMBOL_REF:
|
case SYMBOL_REF:
|
||||||
output_addr_const (stream, x);
|
output_addr_const (stream, x);
|
||||||
|
|
||||||
if (nds32_indirect_call_referenced_p (x))
|
if (!TARGET_LINUX_ABI && nds32_indirect_call_referenced_p (x))
|
||||||
fprintf (stream, "@ICT");
|
fprintf (stream, "@ICT");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -3912,6 +3929,9 @@ nds32_insert_attributes (tree decl, tree *attributes)
|
||||||
{
|
{
|
||||||
tree new_attrs = *attributes;
|
tree new_attrs = *attributes;
|
||||||
|
|
||||||
|
if (TARGET_LINUX_ABI)
|
||||||
|
error("cannot use indirect_call attribute under linux toolchain");
|
||||||
|
|
||||||
if (lookup_attribute ("noinline", new_attrs) == NULL)
|
if (lookup_attribute ("noinline", new_attrs) == NULL)
|
||||||
new_attrs = tree_cons (get_identifier ("noinline"), NULL, new_attrs);
|
new_attrs = tree_cons (get_identifier ("noinline"), NULL, new_attrs);
|
||||||
if (lookup_attribute ("noclone", new_attrs) == NULL)
|
if (lookup_attribute ("noclone", new_attrs) == NULL)
|
||||||
|
@ -4166,6 +4186,13 @@ nds32_expand_builtin (tree exp,
|
||||||
return nds32_expand_builtin_impl (exp, target, subtarget, mode, ignore);
|
return nds32_expand_builtin_impl (exp, target, subtarget, mode, ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implement TARGET_INIT_LIBFUNCS. */
|
||||||
|
static void
|
||||||
|
nds32_init_libfuncs (void)
|
||||||
|
{
|
||||||
|
if (TARGET_LINUX_ABI)
|
||||||
|
init_sync_libfuncs (UNITS_PER_WORD);
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
@ -5758,6 +5785,9 @@ nds32_use_blocks_for_constant_p (machine_mode mode,
|
||||||
|
|
||||||
/* Emulating TLS. */
|
/* Emulating TLS. */
|
||||||
|
|
||||||
|
#undef TARGET_HAVE_TLS
|
||||||
|
#define TARGET_HAVE_TLS TARGET_LINUX_ABI
|
||||||
|
|
||||||
|
|
||||||
/* Defining coprocessor specifics for MIPS targets. */
|
/* Defining coprocessor specifics for MIPS targets. */
|
||||||
|
|
||||||
|
@ -5785,6 +5815,8 @@ nds32_use_blocks_for_constant_p (machine_mode mode,
|
||||||
#undef TARGET_EXPAND_BUILTIN
|
#undef TARGET_EXPAND_BUILTIN
|
||||||
#define TARGET_EXPAND_BUILTIN nds32_expand_builtin
|
#define TARGET_EXPAND_BUILTIN nds32_expand_builtin
|
||||||
|
|
||||||
|
#undef TARGET_INIT_LIBFUNCS
|
||||||
|
#define TARGET_INIT_LIBFUNCS nds32_init_libfuncs
|
||||||
|
|
||||||
#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
|
#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
|
||||||
#define TARGET_USE_BLOCKS_FOR_CONSTANT_P nds32_use_blocks_for_constant_p
|
#define TARGET_USE_BLOCKS_FOR_CONSTANT_P nds32_use_blocks_for_constant_p
|
||||||
|
|
|
@ -922,6 +922,14 @@ enum nds32_builtins
|
||||||
|
|
||||||
#define TARGET_CONFIG_FPU_DEFAULT NDS32_CONFIG_FPU_2
|
#define TARGET_CONFIG_FPU_DEFAULT NDS32_CONFIG_FPU_2
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
#ifdef TARGET_DEFAULT_RELAX
|
||||||
|
# define NDS32_RELAX_SPEC " %{!mno-relax:--relax}"
|
||||||
|
#else
|
||||||
|
# define NDS32_RELAX_SPEC " %{mrelax:--relax}"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef TARGET_DEFAULT_EXT_DSP
|
#ifdef TARGET_DEFAULT_EXT_DSP
|
||||||
# define NDS32_EXT_DSP_SPEC " %{!mno-ext-dsp:-mext-dsp}"
|
# define NDS32_EXT_DSP_SPEC " %{!mno-ext-dsp:-mext-dsp}"
|
||||||
#else
|
#else
|
||||||
|
@ -963,34 +971,6 @@ enum nds32_builtins
|
||||||
" %{mext-dsp:-mdsp-ext}" \
|
" %{mext-dsp:-mdsp-ext}" \
|
||||||
" %{O|O1|O2|O3|Ofast:-O1;:-Os}"
|
" %{O|O1|O2|O3|Ofast:-O1;:-Os}"
|
||||||
|
|
||||||
/* If user issues -mrelax, we need to pass '--relax' to linker. */
|
|
||||||
#define LINK_SPEC \
|
|
||||||
" %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
|
|
||||||
" %{mrelax:--relax}"
|
|
||||||
|
|
||||||
#define LIB_SPEC \
|
|
||||||
" -lc -lgloss"
|
|
||||||
|
|
||||||
/* The option -mno-ctor-dtor can disable constructor/destructor feature
|
|
||||||
by applying different crt stuff. In the convention, crt0.o is the
|
|
||||||
startup file without constructor/destructor;
|
|
||||||
crt1.o, crti.o, crtbegin.o, crtend.o, and crtn.o are the
|
|
||||||
startup files with constructor/destructor.
|
|
||||||
Note that crt0.o, crt1.o, crti.o, and crtn.o are provided
|
|
||||||
by newlib/mculib/glibc/ublic, while crtbegin.o and crtend.o are
|
|
||||||
currently provided by GCC for nds32 target.
|
|
||||||
|
|
||||||
For nds32 target so far:
|
|
||||||
If -mno-ctor-dtor, we are going to link
|
|
||||||
"crt0.o [user objects]".
|
|
||||||
If general cases, we are going to link
|
|
||||||
"crt1.o crtbegin1.o [user objects] crtend1.o". */
|
|
||||||
#define STARTFILE_SPEC \
|
|
||||||
" %{!mno-ctor-dtor:crt1.o%s;:crt0.o%s}" \
|
|
||||||
" %{!mno-ctor-dtor:crtbegin1.o%s}"
|
|
||||||
#define ENDFILE_SPEC \
|
|
||||||
" %{!mno-ctor-dtor:crtend1.o%s}"
|
|
||||||
|
|
||||||
/* The TARGET_BIG_ENDIAN_DEFAULT is defined if we
|
/* The TARGET_BIG_ENDIAN_DEFAULT is defined if we
|
||||||
configure gcc with --target=nds32be-* setting.
|
configure gcc with --target=nds32be-* setting.
|
||||||
Check gcc/config.gcc for more information. */
|
Check gcc/config.gcc for more information. */
|
||||||
|
@ -1000,9 +980,11 @@ enum nds32_builtins
|
||||||
# define NDS32_ENDIAN_DEFAULT "mlittle-endian"
|
# define NDS32_ENDIAN_DEFAULT "mlittle-endian"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Currently we only have elf toolchain,
|
#if TARGET_ELF
|
||||||
where -mcmodel=medium is always the default. */
|
# define NDS32_CMODEL_DEFAULT "mcmodel=medium"
|
||||||
#define NDS32_CMODEL_DEFAULT "mcmodel=medium"
|
#else
|
||||||
|
# define NDS32_CMODEL_DEFAULT "mcmodel=large"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MULTILIB_DEFAULTS \
|
#define MULTILIB_DEFAULTS \
|
||||||
{ NDS32_ENDIAN_DEFAULT, NDS32_CMODEL_DEFAULT }
|
{ NDS32_ENDIAN_DEFAULT, NDS32_CMODEL_DEFAULT }
|
||||||
|
|
|
@ -2221,7 +2221,7 @@
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||||
(plus:SI (match_operand:SI 1 "register_operand" "0")
|
(plus:SI (match_operand:SI 1 "register_operand" "0")
|
||||||
(pc)))]
|
(pc)))]
|
||||||
"flag_pic"
|
"TARGET_LINUX_ABI || flag_pic"
|
||||||
"add5.pc\t%0"
|
"add5.pc\t%0"
|
||||||
[(set_attr "type" "alu")
|
[(set_attr "type" "alu")
|
||||||
(set_attr "length" "4")]
|
(set_attr "length" "4")]
|
||||||
|
|
|
@ -151,7 +151,7 @@ Target Report Mask(RELAX_HINT)
|
||||||
Insert relax hint for linker to do relaxation.
|
Insert relax hint for linker to do relaxation.
|
||||||
|
|
||||||
mvh
|
mvh
|
||||||
Target Report Mask(VH)
|
Target Report Mask(VH) Condition(!TARGET_LINUX_ABI)
|
||||||
Enable Virtual Hosting support.
|
Enable Virtual Hosting support.
|
||||||
|
|
||||||
misr-vector-size=
|
misr-vector-size=
|
||||||
|
@ -185,23 +185,6 @@ Enum(nds32_arch_type) String(v3f) Value(ARCH_V3F)
|
||||||
EnumValue
|
EnumValue
|
||||||
Enum(nds32_arch_type) String(v3s) Value(ARCH_V3S)
|
Enum(nds32_arch_type) String(v3s) Value(ARCH_V3S)
|
||||||
|
|
||||||
mcmodel=
|
|
||||||
Target RejectNegative Joined Enum(nds32_cmodel_type) Var(nds32_cmodel_option) Init(CMODEL_LARGE)
|
|
||||||
Specify the address generation strategy for code model.
|
|
||||||
|
|
||||||
Enum
|
|
||||||
Name(nds32_cmodel_type) Type(enum nds32_cmodel_type)
|
|
||||||
Known cmodel types (for use with the -mcmodel= option):
|
|
||||||
|
|
||||||
EnumValue
|
|
||||||
Enum(nds32_cmodel_type) String(small) Value(CMODEL_SMALL)
|
|
||||||
|
|
||||||
EnumValue
|
|
||||||
Enum(nds32_cmodel_type) String(medium) Value(CMODEL_MEDIUM)
|
|
||||||
|
|
||||||
EnumValue
|
|
||||||
Enum(nds32_cmodel_type) String(large) Value(CMODEL_LARGE)
|
|
||||||
|
|
||||||
mcpu=
|
mcpu=
|
||||||
Target RejectNegative Joined Enum(nds32_cpu_type) Var(nds32_cpu_option) Init(CPU_N9)
|
Target RejectNegative Joined Enum(nds32_cpu_type) Var(nds32_cpu_option) Init(CPU_N9)
|
||||||
Specify the cpu for pipeline model.
|
Specify the cpu for pipeline model.
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
# The multilib settings of Andes NDS32 cpu for GNU compiler
|
||||||
|
# Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
||||||
|
# Contributed by Andes Technology Corporation.
|
||||||
|
#
|
||||||
|
# This file is part of GCC.
|
||||||
|
#
|
||||||
|
# GCC 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, or (at your
|
||||||
|
# option) any later version.
|
||||||
|
#
|
||||||
|
# GCC 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 GCC; see the file COPYING3. If not see
|
||||||
|
# <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# We also define a macro MULTILIB_DEFAULTS in nds32.h that tells the
|
||||||
|
# driver program which options are defaults for this target and thus
|
||||||
|
# do not need to be handled specially.
|
||||||
|
MULTILIB_OPTIONS += mcmodel=small/mcmodel=medium/mcmodel=large mvh
|
||||||
|
|
||||||
|
ifneq ($(filter graywolf,$(TM_MULTILIB_CONFIG)),)
|
||||||
|
MULTILIB_OPTIONS += mcpu=graywolf
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(filter dsp,$(TM_MULTILIB_CONFIG)),)
|
||||||
|
MULTILIB_OPTIONS += mext-dsp
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(filter zol,$(TM_MULTILIB_CONFIG)),)
|
||||||
|
MULTILIB_OPTIONS += mext-zol
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(filter v3m+,$(TM_MULTILIB_CONFIG)),)
|
||||||
|
MULTILIB_OPTIONS += march=v3m+
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
|
@ -0,0 +1,26 @@
|
||||||
|
# The multilib settings of Andes NDS32 cpu for GNU compiler
|
||||||
|
# Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
||||||
|
# Contributed by Andes Technology Corporation.
|
||||||
|
#
|
||||||
|
# This file is part of GCC.
|
||||||
|
#
|
||||||
|
# GCC 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, or (at your
|
||||||
|
# option) any later version.
|
||||||
|
#
|
||||||
|
# GCC 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 GCC; see the file COPYING3. If not see
|
||||||
|
# <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# We also define a macro MULTILIB_DEFAULTS in nds32.h that tells the
|
||||||
|
# driver program which options are defaults for this target and thus
|
||||||
|
# do not need to be handled specially.
|
||||||
|
MULTILIB_OPTIONS +=
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
|
@ -1,3 +1,10 @@
|
||||||
|
2018-06-02 Chung-Ju Wu <jasonwucj@gmail.com>
|
||||||
|
Monk Chiang <sh.chiang04@gmail.com>
|
||||||
|
|
||||||
|
* config.host (nds32*-linux*): New.
|
||||||
|
* config/nds32/linux-atomic.c: New file.
|
||||||
|
* config/nds32/linux-unwind.h: New file.
|
||||||
|
|
||||||
2018-05-31 Uros Bizjak <ubizjak@gmail.com>
|
2018-05-31 Uros Bizjak <ubizjak@gmail.com>
|
||||||
|
|
||||||
PR target/85591
|
PR target/85591
|
||||||
|
|
|
@ -979,6 +979,23 @@ msp430*-*-elf)
|
||||||
tmake_file="$tm_file t-crtstuff t-fdpbit msp430/t-msp430"
|
tmake_file="$tm_file t-crtstuff t-fdpbit msp430/t-msp430"
|
||||||
extra_parts="$extra_parts libmul_none.a libmul_16.a libmul_32.a libmul_f5.a"
|
extra_parts="$extra_parts libmul_none.a libmul_16.a libmul_32.a libmul_f5.a"
|
||||||
;;
|
;;
|
||||||
|
nds32*-linux*)
|
||||||
|
# Basic makefile fragment and extra_parts for crt stuff.
|
||||||
|
# We also append c-isr library implementation.
|
||||||
|
tmake_file="${tmake_file} t-slibgcc-libgcc"
|
||||||
|
tmake_file="${tmake_file} nds32/t-nds32-glibc nds32/t-crtstuff t-softfp-sfdf t-softfp"
|
||||||
|
# The header file of defining MD_FALLBACK_FRAME_STATE_FOR.
|
||||||
|
md_unwind_header=nds32/linux-unwind.h
|
||||||
|
# Append library definition makefile fragment according to --with-nds32-lib=X setting.
|
||||||
|
case "${with_nds32_lib}" in
|
||||||
|
"" | glibc | uclibc )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Cannot accept --with-nds32-lib=$with_nds32_lib, available values are: glibc uclibc" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
nds32*-elf*)
|
nds32*-elf*)
|
||||||
# Basic makefile fragment and extra_parts for crt stuff.
|
# Basic makefile fragment and extra_parts for crt stuff.
|
||||||
# We also append c-isr library implementation.
|
# We also append c-isr library implementation.
|
||||||
|
|
|
@ -0,0 +1,282 @@
|
||||||
|
/* Linux-specific atomic operations for NDS32 Linux.
|
||||||
|
Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file 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, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This file 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.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* We implement byte, short and int versions of each atomic operation
|
||||||
|
using the kernel helper defined below. There is no support for
|
||||||
|
64-bit operations yet. */
|
||||||
|
|
||||||
|
/* This function copy form NDS32 Linux-kernal. */
|
||||||
|
static inline int
|
||||||
|
__kernel_cmpxchg (int oldval, int newval, int *mem)
|
||||||
|
{
|
||||||
|
int temp1, temp2, temp3, offset;
|
||||||
|
|
||||||
|
asm volatile ("msync\tall\n"
|
||||||
|
"movi\t%0, #0\n"
|
||||||
|
"1:\n"
|
||||||
|
"\tllw\t%1, [%4+%0]\n"
|
||||||
|
"\tsub\t%3, %1, %6\n"
|
||||||
|
"\tcmovz\t%2, %5, %3\n"
|
||||||
|
"\tcmovn\t%2, %1, %3\n"
|
||||||
|
"\tscw\t%2, [%4+%0]\n"
|
||||||
|
"\tbeqz\t%2, 1b\n"
|
||||||
|
: "=&r" (offset), "=&r" (temp3), "=&r" (temp2), "=&r" (temp1)
|
||||||
|
: "r" (mem), "r" (newval), "r" (oldval) : "memory");
|
||||||
|
|
||||||
|
return temp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HIDDEN __attribute__ ((visibility ("hidden")))
|
||||||
|
|
||||||
|
#ifdef __NDS32_EL__
|
||||||
|
#define INVERT_MASK_1 0
|
||||||
|
#define INVERT_MASK_2 0
|
||||||
|
#else
|
||||||
|
#define INVERT_MASK_1 24
|
||||||
|
#define INVERT_MASK_2 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MASK_1 0xffu
|
||||||
|
#define MASK_2 0xffffu
|
||||||
|
|
||||||
|
#define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP) \
|
||||||
|
int HIDDEN \
|
||||||
|
__sync_fetch_and_##OP##_4 (int *ptr, int val) \
|
||||||
|
{ \
|
||||||
|
int failure, tmp; \
|
||||||
|
\
|
||||||
|
do { \
|
||||||
|
tmp = __atomic_load_n (ptr, __ATOMIC_SEQ_CST); \
|
||||||
|
failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \
|
||||||
|
} while (failure != 0); \
|
||||||
|
\
|
||||||
|
return tmp; \
|
||||||
|
}
|
||||||
|
|
||||||
|
FETCH_AND_OP_WORD (add, , +)
|
||||||
|
FETCH_AND_OP_WORD (sub, , -)
|
||||||
|
FETCH_AND_OP_WORD (or, , |)
|
||||||
|
FETCH_AND_OP_WORD (and, , &)
|
||||||
|
FETCH_AND_OP_WORD (xor, , ^)
|
||||||
|
FETCH_AND_OP_WORD (nand, ~, &)
|
||||||
|
|
||||||
|
#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH
|
||||||
|
#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH
|
||||||
|
|
||||||
|
/* Implement both __sync_<op>_and_fetch and __sync_fetch_and_<op> for
|
||||||
|
subword-sized quantities. */
|
||||||
|
|
||||||
|
#define SUBWORD_SYNC_OP(OP, PFX_OP, INF_OP, TYPE, WIDTH, RETURN) \
|
||||||
|
TYPE HIDDEN \
|
||||||
|
NAME##_##RETURN (OP, WIDTH) (TYPE *ptr, TYPE val) \
|
||||||
|
{ \
|
||||||
|
int *wordptr = (int *) ((unsigned long) ptr & ~3); \
|
||||||
|
unsigned int mask, shift, oldval, newval; \
|
||||||
|
int failure; \
|
||||||
|
\
|
||||||
|
shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
|
||||||
|
mask = MASK_##WIDTH << shift; \
|
||||||
|
\
|
||||||
|
do { \
|
||||||
|
oldval = __atomic_load_n (wordptr, __ATOMIC_SEQ_CST); \
|
||||||
|
newval = ((PFX_OP (((oldval & mask) >> shift) \
|
||||||
|
INF_OP (unsigned int) val)) << shift) & mask; \
|
||||||
|
newval |= oldval & ~mask; \
|
||||||
|
failure = __kernel_cmpxchg (oldval, newval, wordptr); \
|
||||||
|
} while (failure != 0); \
|
||||||
|
\
|
||||||
|
return (RETURN & mask) >> shift; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SUBWORD_SYNC_OP (add, , +, unsigned short, 2, oldval)
|
||||||
|
SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, oldval)
|
||||||
|
SUBWORD_SYNC_OP (or, , |, unsigned short, 2, oldval)
|
||||||
|
SUBWORD_SYNC_OP (and, , &, unsigned short, 2, oldval)
|
||||||
|
SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, oldval)
|
||||||
|
SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, oldval)
|
||||||
|
|
||||||
|
SUBWORD_SYNC_OP (add, , +, unsigned char, 1, oldval)
|
||||||
|
SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, oldval)
|
||||||
|
SUBWORD_SYNC_OP (or, , |, unsigned char, 1, oldval)
|
||||||
|
SUBWORD_SYNC_OP (and, , &, unsigned char, 1, oldval)
|
||||||
|
SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, oldval)
|
||||||
|
SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, oldval)
|
||||||
|
|
||||||
|
#define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP) \
|
||||||
|
int HIDDEN \
|
||||||
|
__sync_##OP##_and_fetch_4 (int *ptr, int val) \
|
||||||
|
{ \
|
||||||
|
int tmp, failure; \
|
||||||
|
\
|
||||||
|
do { \
|
||||||
|
tmp = __atomic_load_n (ptr, __ATOMIC_SEQ_CST); \
|
||||||
|
failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \
|
||||||
|
} while (failure != 0); \
|
||||||
|
\
|
||||||
|
return PFX_OP (tmp INF_OP val); \
|
||||||
|
}
|
||||||
|
|
||||||
|
OP_AND_FETCH_WORD (add, , +)
|
||||||
|
OP_AND_FETCH_WORD (sub, , -)
|
||||||
|
OP_AND_FETCH_WORD (or, , |)
|
||||||
|
OP_AND_FETCH_WORD (and, , &)
|
||||||
|
OP_AND_FETCH_WORD (xor, , ^)
|
||||||
|
OP_AND_FETCH_WORD (nand, ~, &)
|
||||||
|
|
||||||
|
SUBWORD_SYNC_OP (add, , +, unsigned short, 2, newval)
|
||||||
|
SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, newval)
|
||||||
|
SUBWORD_SYNC_OP (or, , |, unsigned short, 2, newval)
|
||||||
|
SUBWORD_SYNC_OP (and, , &, unsigned short, 2, newval)
|
||||||
|
SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, newval)
|
||||||
|
SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, newval)
|
||||||
|
|
||||||
|
SUBWORD_SYNC_OP (add, , +, unsigned char, 1, newval)
|
||||||
|
SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, newval)
|
||||||
|
SUBWORD_SYNC_OP (or, , |, unsigned char, 1, newval)
|
||||||
|
SUBWORD_SYNC_OP (and, , &, unsigned char, 1, newval)
|
||||||
|
SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, newval)
|
||||||
|
SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, newval)
|
||||||
|
|
||||||
|
int HIDDEN
|
||||||
|
__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval)
|
||||||
|
{
|
||||||
|
int actual_oldval, fail;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
actual_oldval = __atomic_load_n (ptr, __ATOMIC_SEQ_CST);
|
||||||
|
|
||||||
|
if (oldval != actual_oldval)
|
||||||
|
return actual_oldval;
|
||||||
|
|
||||||
|
fail = __kernel_cmpxchg (actual_oldval, newval, ptr);
|
||||||
|
|
||||||
|
if (!fail)
|
||||||
|
return oldval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SUBWORD_VAL_CAS(TYPE, WIDTH) \
|
||||||
|
TYPE HIDDEN \
|
||||||
|
__sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \
|
||||||
|
TYPE newval) \
|
||||||
|
{ \
|
||||||
|
int *wordptr = (int *)((unsigned long) ptr & ~3), fail; \
|
||||||
|
unsigned int mask, shift, actual_oldval, actual_newval; \
|
||||||
|
\
|
||||||
|
shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
|
||||||
|
mask = MASK_##WIDTH << shift; \
|
||||||
|
\
|
||||||
|
while (1) \
|
||||||
|
{ \
|
||||||
|
actual_oldval = __atomic_load_n (wordptr, __ATOMIC_SEQ_CST); \
|
||||||
|
\
|
||||||
|
if (((actual_oldval & mask) >> shift) != (unsigned int) oldval) \
|
||||||
|
return (actual_oldval & mask) >> shift; \
|
||||||
|
\
|
||||||
|
actual_newval = (actual_oldval & ~mask) \
|
||||||
|
| (((unsigned int) newval << shift) & mask); \
|
||||||
|
\
|
||||||
|
fail = __kernel_cmpxchg (actual_oldval, actual_newval, \
|
||||||
|
wordptr); \
|
||||||
|
\
|
||||||
|
if (!fail) \
|
||||||
|
return oldval; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBWORD_VAL_CAS (unsigned short, 2)
|
||||||
|
SUBWORD_VAL_CAS (unsigned char, 1)
|
||||||
|
|
||||||
|
typedef unsigned char bool;
|
||||||
|
|
||||||
|
bool HIDDEN
|
||||||
|
__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval)
|
||||||
|
{
|
||||||
|
int failure = __kernel_cmpxchg (oldval, newval, ptr);
|
||||||
|
return (failure == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SUBWORD_BOOL_CAS(TYPE, WIDTH) \
|
||||||
|
bool HIDDEN \
|
||||||
|
__sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \
|
||||||
|
TYPE newval) \
|
||||||
|
{ \
|
||||||
|
TYPE actual_oldval \
|
||||||
|
= __sync_val_compare_and_swap_##WIDTH (ptr, oldval, newval); \
|
||||||
|
return (oldval == actual_oldval); \
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBWORD_BOOL_CAS (unsigned short, 2)
|
||||||
|
SUBWORD_BOOL_CAS (unsigned char, 1)
|
||||||
|
|
||||||
|
int HIDDEN
|
||||||
|
__sync_lock_test_and_set_4 (int *ptr, int val)
|
||||||
|
{
|
||||||
|
int failure, oldval;
|
||||||
|
|
||||||
|
do {
|
||||||
|
oldval = __atomic_load_n (ptr, __ATOMIC_SEQ_CST);
|
||||||
|
failure = __kernel_cmpxchg (oldval, val, ptr);
|
||||||
|
} while (failure != 0);
|
||||||
|
|
||||||
|
return oldval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SUBWORD_TEST_AND_SET(TYPE, WIDTH) \
|
||||||
|
TYPE HIDDEN \
|
||||||
|
__sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val) \
|
||||||
|
{ \
|
||||||
|
int failure; \
|
||||||
|
unsigned int oldval, newval, shift, mask; \
|
||||||
|
int *wordptr = (int *) ((unsigned long) ptr & ~3); \
|
||||||
|
\
|
||||||
|
shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
|
||||||
|
mask = MASK_##WIDTH << shift; \
|
||||||
|
\
|
||||||
|
do { \
|
||||||
|
oldval = __atomic_load_n (wordptr, __ATOMIC_SEQ_CST); \
|
||||||
|
newval = (oldval & ~mask) \
|
||||||
|
| (((unsigned int) val << shift) & mask); \
|
||||||
|
failure = __kernel_cmpxchg (oldval, newval, wordptr); \
|
||||||
|
} while (failure != 0); \
|
||||||
|
\
|
||||||
|
return (oldval & mask) >> shift; \
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBWORD_TEST_AND_SET (unsigned short, 2)
|
||||||
|
SUBWORD_TEST_AND_SET (unsigned char, 1)
|
||||||
|
|
||||||
|
#define SYNC_LOCK_RELEASE(TYPE, WIDTH) \
|
||||||
|
void HIDDEN \
|
||||||
|
__sync_lock_release_##WIDTH (TYPE *ptr) \
|
||||||
|
{ \
|
||||||
|
/* All writes before this point must be seen before we release \
|
||||||
|
the lock itself. */ \
|
||||||
|
__builtin_nds32_msync_all (); \
|
||||||
|
*ptr = 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
SYNC_LOCK_RELEASE (int, 4)
|
||||||
|
SYNC_LOCK_RELEASE (short, 2)
|
||||||
|
SYNC_LOCK_RELEASE (char, 1)
|
|
@ -0,0 +1,156 @@
|
||||||
|
/* DWARF2 EH unwinding support for NDS32 Linux signal frame.
|
||||||
|
Copyright (C) 2014-2015 Free Software Foundation, Inc.
|
||||||
|
Contributed by Andes Technology Corporation.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC 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, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
GCC 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.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef inhibit_libc
|
||||||
|
|
||||||
|
/* Do code reading to identify a signal frame, and set the frame
|
||||||
|
state data appropriately. See unwind-dw2.c for the structs.
|
||||||
|
The corresponding bits in the Linux kernel are in
|
||||||
|
arch/nds32/kernel/signal.c. */
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <asm/unistd.h>
|
||||||
|
|
||||||
|
/* Exactly the same layout as the kernel structures, unique names. */
|
||||||
|
|
||||||
|
/* arch/nds32/kernel/signal.c */
|
||||||
|
struct _sigframe {
|
||||||
|
struct ucontext uc;
|
||||||
|
unsigned long retcode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _rt_sigframe {
|
||||||
|
siginfo_t info;
|
||||||
|
struct _sigframe sig;
|
||||||
|
};
|
||||||
|
#define SIGRETURN 0xeb0e0a64
|
||||||
|
#define RT_SIGRETURN 0xab150a64
|
||||||
|
|
||||||
|
#define MD_FALLBACK_FRAME_STATE_FOR nds32_fallback_frame_state
|
||||||
|
|
||||||
|
/* This function is supposed to be invoked by uw_frame_state_for()
|
||||||
|
when there is no unwind data available.
|
||||||
|
|
||||||
|
Generally, given the _Unwind_Context CONTEXT for a stack frame,
|
||||||
|
we need to look up its caller and decode information into FS.
|
||||||
|
However, if the exception handling happens within a signal handler,
|
||||||
|
the return address of signal handler is a special module, which
|
||||||
|
contains signal return syscall and has no FDE in the .eh_frame section.
|
||||||
|
We need to implement MD_FALLBACK_FRAME_STATE_FOR so that we can
|
||||||
|
unwind through signal frames. */
|
||||||
|
static _Unwind_Reason_Code
|
||||||
|
nds32_fallback_frame_state (struct _Unwind_Context *context,
|
||||||
|
_Unwind_FrameState *fs)
|
||||||
|
{
|
||||||
|
u_int32_t *pc = (u_int32_t *) context->ra;
|
||||||
|
struct sigcontext *sc_;
|
||||||
|
_Unwind_Ptr new_cfa;
|
||||||
|
|
||||||
|
#ifdef __NDS32_EB__
|
||||||
|
#error "Signal handler is not supported for force unwind."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((_Unwind_Ptr) pc & 3)
|
||||||
|
return _URC_END_OF_STACK;
|
||||||
|
|
||||||
|
/* Check if we are going through a signal handler.
|
||||||
|
See arch/nds32/kernel/signal.c implementation.
|
||||||
|
SWI_SYS_SIGRETURN -> (0xeb0e0a64)
|
||||||
|
SWI_SYS_RT_SIGRETURN -> (0xab150a64)
|
||||||
|
FIXME: Currently we only handle little endian (EL) case. */
|
||||||
|
if (pc[0] == SIGRETURN)
|
||||||
|
{
|
||||||
|
/* Using '_sigfame' memory address to locate kernal's sigcontext.
|
||||||
|
The sigcontext structures in arch/nds32/include/asm/sigcontext.h. */
|
||||||
|
struct _sigframe *rt_;
|
||||||
|
rt_ = context->cfa;
|
||||||
|
sc_ = &rt_->uc.uc_mcontext;
|
||||||
|
}
|
||||||
|
else if (pc[0] == RT_SIGRETURN)
|
||||||
|
{
|
||||||
|
/* Using '_sigfame' memory address to locate kernal's sigcontext. */
|
||||||
|
struct _rt_sigframe *rt_;
|
||||||
|
rt_ = context->cfa;
|
||||||
|
sc_ = &rt_->sig.uc.uc_mcontext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return _URC_END_OF_STACK;
|
||||||
|
|
||||||
|
/* Update cfa from sigcontext. */
|
||||||
|
new_cfa = (_Unwind_Ptr) sc_;
|
||||||
|
fs->regs.cfa_how = CFA_REG_OFFSET;
|
||||||
|
fs->regs.cfa_reg = STACK_POINTER_REGNUM;
|
||||||
|
fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
|
||||||
|
|
||||||
|
#define NDS32_PUT_FS_REG(NUM, NAME) \
|
||||||
|
(fs->regs.reg[NUM].how = REG_SAVED_OFFSET, \
|
||||||
|
fs->regs.reg[NUM].loc.offset = (_Unwind_Ptr) &(sc_->NAME) - new_cfa)
|
||||||
|
|
||||||
|
/* Restore all registers value. */
|
||||||
|
NDS32_PUT_FS_REG (0, nds32_r0);
|
||||||
|
NDS32_PUT_FS_REG (1, nds32_r1);
|
||||||
|
NDS32_PUT_FS_REG (2, nds32_r2);
|
||||||
|
NDS32_PUT_FS_REG (3, nds32_r3);
|
||||||
|
NDS32_PUT_FS_REG (4, nds32_r4);
|
||||||
|
NDS32_PUT_FS_REG (5, nds32_r5);
|
||||||
|
NDS32_PUT_FS_REG (6, nds32_r6);
|
||||||
|
NDS32_PUT_FS_REG (7, nds32_r7);
|
||||||
|
NDS32_PUT_FS_REG (8, nds32_r8);
|
||||||
|
NDS32_PUT_FS_REG (9, nds32_r9);
|
||||||
|
NDS32_PUT_FS_REG (10, nds32_r10);
|
||||||
|
NDS32_PUT_FS_REG (11, nds32_r11);
|
||||||
|
NDS32_PUT_FS_REG (12, nds32_r12);
|
||||||
|
NDS32_PUT_FS_REG (13, nds32_r13);
|
||||||
|
NDS32_PUT_FS_REG (14, nds32_r14);
|
||||||
|
NDS32_PUT_FS_REG (15, nds32_r15);
|
||||||
|
NDS32_PUT_FS_REG (16, nds32_r16);
|
||||||
|
NDS32_PUT_FS_REG (17, nds32_r17);
|
||||||
|
NDS32_PUT_FS_REG (18, nds32_r18);
|
||||||
|
NDS32_PUT_FS_REG (19, nds32_r19);
|
||||||
|
NDS32_PUT_FS_REG (20, nds32_r20);
|
||||||
|
NDS32_PUT_FS_REG (21, nds32_r21);
|
||||||
|
NDS32_PUT_FS_REG (22, nds32_r22);
|
||||||
|
NDS32_PUT_FS_REG (23, nds32_r23);
|
||||||
|
NDS32_PUT_FS_REG (24, nds32_r24);
|
||||||
|
NDS32_PUT_FS_REG (25, nds32_r25);
|
||||||
|
|
||||||
|
NDS32_PUT_FS_REG (28, nds32_fp);
|
||||||
|
NDS32_PUT_FS_REG (29, nds32_gp);
|
||||||
|
NDS32_PUT_FS_REG (30, nds32_lp);
|
||||||
|
NDS32_PUT_FS_REG (31, nds32_sp);
|
||||||
|
|
||||||
|
/* Restore PC, point to trigger signal instruction. */
|
||||||
|
NDS32_PUT_FS_REG (32, nds32_ipc);
|
||||||
|
|
||||||
|
#undef NDS32_PUT_FS_REG
|
||||||
|
|
||||||
|
/* The retaddr is PC, use PC to find FDE. */
|
||||||
|
fs->retaddr_column = 32;
|
||||||
|
fs->signal_frame = 1;
|
||||||
|
|
||||||
|
return _URC_NO_REASON;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue