From b8c107c7b8a7b620e446dfd4ae74dac1bb4a5def Mon Sep 17 00:00:00 2001 From: Patrick Georgi Date: Fri, 25 Jan 2019 15:51:28 +0100 Subject: util/crossgcc: Update to binutils 2.31.1 and gcc 8.2 Change-Id: Icf7c6bdd4021bf84cc295c819f93838248e0f4c7 Signed-off-by: Patrick Georgi Reviewed-on: https://review.coreboot.org/c/31089 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes --- util/crossgcc/buildgcc | 4 +- .../crossgcc/patches/binutils-2.30_mips-gold.patch | 11 - util/crossgcc/patches/binutils-2.30_nds32.patch | 25740 ------------------- .../patches/binutils-2.30_no-bfd-doc.patch | 12 - .../patches/binutils-2.31.1_mips-gold.patch | 11 + .../patches/binutils-2.31.1_no-bfd-doc.patch | 12 + .../patches/gcc-8.1.0_ada-musl_workaround.patch | 120 - util/crossgcc/patches/gcc-8.1.0_armv6s-m.patch | 64 - util/crossgcc/patches/gcc-8.1.0_bsd.patch | 12 - util/crossgcc/patches/gcc-8.1.0_gnat.patch | 11 - util/crossgcc/patches/gcc-8.1.0_libgcc.patch | 60 - util/crossgcc/patches/gcc-8.1.0_nds32_ite.patch | 21164 --------------- .../patches/gcc-8.2.0_ada-musl_workaround.patch | 120 + util/crossgcc/patches/gcc-8.2.0_gnat.patch | 11 + util/crossgcc/patches/gcc-8.2.0_libgcc.patch | 60 + util/crossgcc/patches/gcc-8.2.0_nds32_ite.patch | 21019 +++++++++++++++ util/crossgcc/sum/binutils-2.30.tar.xz.cksum | 1 - util/crossgcc/sum/binutils-2.31.1.tar.xz.cksum | 1 + util/crossgcc/sum/gcc-8.1.0.tar.xz.cksum | 1 - util/crossgcc/sum/gcc-8.2.0.tar.xz.cksum | 1 + 20 files changed, 21237 insertions(+), 47198 deletions(-) delete mode 100644 util/crossgcc/patches/binutils-2.30_mips-gold.patch delete mode 100644 util/crossgcc/patches/binutils-2.30_nds32.patch delete mode 100644 util/crossgcc/patches/binutils-2.30_no-bfd-doc.patch create mode 100644 util/crossgcc/patches/binutils-2.31.1_mips-gold.patch create mode 100644 util/crossgcc/patches/binutils-2.31.1_no-bfd-doc.patch delete mode 100644 util/crossgcc/patches/gcc-8.1.0_ada-musl_workaround.patch delete mode 100644 util/crossgcc/patches/gcc-8.1.0_armv6s-m.patch delete mode 100644 util/crossgcc/patches/gcc-8.1.0_bsd.patch delete mode 100644 util/crossgcc/patches/gcc-8.1.0_gnat.patch delete mode 100644 util/crossgcc/patches/gcc-8.1.0_libgcc.patch delete mode 100644 util/crossgcc/patches/gcc-8.1.0_nds32_ite.patch create mode 100644 util/crossgcc/patches/gcc-8.2.0_ada-musl_workaround.patch create mode 100644 util/crossgcc/patches/gcc-8.2.0_gnat.patch create mode 100644 util/crossgcc/patches/gcc-8.2.0_libgcc.patch create mode 100644 util/crossgcc/patches/gcc-8.2.0_nds32_ite.patch delete mode 100644 util/crossgcc/sum/binutils-2.30.tar.xz.cksum create mode 100644 util/crossgcc/sum/binutils-2.31.1.tar.xz.cksum delete mode 100644 util/crossgcc/sum/gcc-8.1.0.tar.xz.cksum create mode 100644 util/crossgcc/sum/gcc-8.2.0.tar.xz.cksum (limited to 'util') diff --git a/util/crossgcc/buildgcc b/util/crossgcc/buildgcc index 4b5a718a8e..707fdea445 100755 --- a/util/crossgcc/buildgcc +++ b/util/crossgcc/buildgcc @@ -50,9 +50,9 @@ THREADS=1 GMP_VERSION=6.1.2 MPFR_VERSION=4.0.1 MPC_VERSION=1.1.0 -GCC_VERSION=8.1.0 +GCC_VERSION=8.2.0 GCC_AUTOCONF_VERSION=2.69 -BINUTILS_VERSION=2.30 +BINUTILS_VERSION=2.31.1 GDB_VERSION=8.2.1 IASL_VERSION=20190108 PYTHON_VERSION=3.7.2 diff --git a/util/crossgcc/patches/binutils-2.30_mips-gold.patch b/util/crossgcc/patches/binutils-2.30_mips-gold.patch deleted file mode 100644 index d9a40210ff..0000000000 --- a/util/crossgcc/patches/binutils-2.30_mips-gold.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -urN binutils-2.27.orig/gold/configure.tgt binutils-2.27/gold/configure.tgt ---- binutils-2.27.orig/gold/configure.tgt 2016-08-03 15:36:53.000000000 +0800 -+++ binutils-2.27/gold/configure.tgt 2016-10-29 19:28:56.140587026 +0800 -@@ -157,6 +157,7 @@ - targ_obj=mips - targ_machine=EM_MIPS_RS3_LE - targ_size=32 -+ targ_extra_size=64 - targ_big_endian=false - targ_extra_big_endian=true - ;; diff --git a/util/crossgcc/patches/binutils-2.30_nds32.patch b/util/crossgcc/patches/binutils-2.30_nds32.patch deleted file mode 100644 index 9608265ad2..0000000000 --- a/util/crossgcc/patches/binutils-2.30_nds32.patch +++ /dev/null @@ -1,25740 +0,0 @@ -diff --git binutils-2.30/bfd/bfd-in2.h binutils-2.30-nds32/bfd/bfd-in2.h -index f4b3720b4b..49ac0a3a18 100644 ---- binutils-2.30/bfd/bfd-in2.h -+++ binutils-2.30-nds32/bfd/bfd-in2.h -@@ -4137,6 +4137,9 @@ and shift left by 1 for use in lhi.gp, shi.gp... */ - and shift left by 0 for use in lbi.gp, sbi.gp... */ - BFD_RELOC_NDS32_SDA19S0, - -+/* This is a 24-bit reloc for security check sum. */ -+ BFD_RELOC_NDS32_SECURITY_16, -+ - /* for PIC */ - BFD_RELOC_NDS32_GOT20, - BFD_RELOC_NDS32_9_PLTREL, -@@ -4248,18 +4251,43 @@ This is a 5 bit absolute address. */ - - /* For TLS. */ - BFD_RELOC_NDS32_TPOFF, -+ BFD_RELOC_NDS32_GOTTPOFF, - BFD_RELOC_NDS32_TLS_LE_HI20, - BFD_RELOC_NDS32_TLS_LE_LO12, -- BFD_RELOC_NDS32_TLS_LE_ADD, -- BFD_RELOC_NDS32_TLS_LE_LS, -- BFD_RELOC_NDS32_GOTTPOFF, -- BFD_RELOC_NDS32_TLS_IE_HI20, -- BFD_RELOC_NDS32_TLS_IE_LO12S2, -- BFD_RELOC_NDS32_TLS_TPOFF, - BFD_RELOC_NDS32_TLS_LE_20, - BFD_RELOC_NDS32_TLS_LE_15S0, - BFD_RELOC_NDS32_TLS_LE_15S1, - BFD_RELOC_NDS32_TLS_LE_15S2, -+ BFD_RELOC_NDS32_TLS_LE_ADD, -+ BFD_RELOC_NDS32_TLS_LE_LS, -+ BFD_RELOC_NDS32_TLS_IE_HI20, -+ BFD_RELOC_NDS32_TLS_IE_LO12, -+ BFD_RELOC_NDS32_TLS_IE_LO12S2, -+ BFD_RELOC_NDS32_TLS_IEGP_HI20, -+ BFD_RELOC_NDS32_TLS_IEGP_LO12, -+ BFD_RELOC_NDS32_TLS_IEGP_LO12S2, -+ BFD_RELOC_NDS32_TLS_IEGP_LW, -+ BFD_RELOC_NDS32_TLS_DESC, -+ BFD_RELOC_NDS32_TLS_DESC_HI20, -+ BFD_RELOC_NDS32_TLS_DESC_LO12, -+ BFD_RELOC_NDS32_TLS_DESC_20, -+ BFD_RELOC_NDS32_TLS_DESC_SDA17S2, -+ BFD_RELOC_NDS32_TLS_DESC_ADD, -+ BFD_RELOC_NDS32_TLS_DESC_FUNC, -+ BFD_RELOC_NDS32_TLS_DESC_CALL, -+ BFD_RELOC_NDS32_TLS_DESC_MEM, -+ BFD_RELOC_NDS32_REMOVE, -+ BFD_RELOC_NDS32_GROUP, -+ -+/* Jump-patch table relative relocations. */ -+ BFD_RELOC_NDS32_ICT, -+ BFD_RELOC_NDS32_ICT_HI20, -+ BFD_RELOC_NDS32_ICT_LO12, -+ BFD_RELOC_NDS32_ICT_25PC, -+ BFD_RELOC_NDS32_ICT_LO12S2, -+ -+/* For bug 12566. */ -+ BFD_RELOC_NDS32_LSI, - - /* This is a 9-bit reloc */ - BFD_RELOC_V850_9_PCREL, -diff --git binutils-2.30/bfd/config.bfd binutils-2.30-nds32/bfd/config.bfd -index f04a993f06..9aa2fc63a8 100644 ---- binutils-2.30/bfd/config.bfd -+++ binutils-2.30-nds32/bfd/config.bfd -@@ -1260,11 +1260,13 @@ case "${targ}" in - nds32*le-*-linux*) - targ_defvec=nds32_elf32_linux_le_vec - targ_selvecs=nds32_elf32_linux_be_vec -+ targ_cflags=-DNDS32_LINUX_TOOLCHAIN - ;; - - nds32*be-*-linux*) - targ_defvec=nds32_elf32_linux_be_vec - targ_selvecs=nds32_elf32_linux_le_vec -+ targ_cflags=-DNDS32_LINUX_TOOLCHAIN - ;; - - nds32*le-*-*) -diff --git binutils-2.30/bfd/elf32-nds32.c binutils-2.30-nds32/bfd/elf32-nds32.c -index 5ceb0a0b26..06be7a24bd 100644 ---- binutils-2.30/bfd/elf32-nds32.c -+++ binutils-2.30-nds32/bfd/elf32-nds32.c -@@ -20,6 +20,8 @@ - 02110-1301, USA. */ - - -+#pragma GCC diagnostic ignored "-Wstack-usage=" -+ - #include "sysdep.h" - #include "bfd.h" - #include "bfd_stdint.h" -@@ -33,6 +35,7 @@ - #include "elf32-nds32.h" - #include "opcode/cgen.h" - #include "../opcodes/nds32-opc.h" -+#include - - /* Relocation HOWTO functions. */ - static bfd_reloc_status_type nds32_elf_ignore_reloc -@@ -56,36 +59,72 @@ static bfd_reloc_status_type nds32_elf_sda15_reloc - static bfd_reloc_status_type nds32_elf_do_9_pcrel_reloc - (bfd *, reloc_howto_type *, asection *, bfd_byte *, bfd_vma, - asection *, bfd_vma, bfd_vma); -+static void nds32_elf_relocate_hi20 -+ (bfd *, int, Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_byte *, bfd_vma); -+static reloc_howto_type *bfd_elf32_bfd_reloc_type_table_lookup -+ (enum elf_nds32_reloc_type); -+static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup -+ (bfd *, bfd_reloc_code_real_type); -+ -+/* Target hooks. */ -+static void nds32_info_to_howto_rel -+ (bfd *, arelent *, Elf_Internal_Rela *); -+static void nds32_info_to_howto -+ (bfd *, arelent *, Elf_Internal_Rela *); -+static bfd_boolean nds32_elf_add_symbol_hook -+ (bfd *, struct bfd_link_info *, Elf_Internal_Sym *, const char **, -+ flagword *, asection **, bfd_vma *); -+static bfd_boolean nds32_elf_relocate_section -+ (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, -+ Elf_Internal_Rela *, Elf_Internal_Sym *, asection **); -+static bfd_boolean nds32_elf_object_p (bfd *); -+static void nds32_elf_final_write_processing (bfd *, bfd_boolean); -+static bfd_boolean nds32_elf_set_private_flags (bfd *, flagword); -+static bfd_boolean nds32_elf_merge_private_bfd_data (bfd *, struct bfd_link_info *); -+static bfd_boolean nds32_elf_print_private_bfd_data (bfd *, void *); -+static bfd_boolean nds32_elf_check_relocs -+ (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *); -+static asection *nds32_elf_gc_mark_hook -+ (asection *, struct bfd_link_info *, Elf_Internal_Rela *, -+ struct elf_link_hash_entry *, Elf_Internal_Sym *); -+static bfd_boolean nds32_elf_adjust_dynamic_symbol -+ (struct bfd_link_info *, struct elf_link_hash_entry *); -+static bfd_boolean nds32_elf_size_dynamic_sections -+ (bfd *, struct bfd_link_info *); -+static bfd_boolean nds32_elf_create_dynamic_sections -+ (bfd *, struct bfd_link_info *); -+static bfd_boolean nds32_elf_finish_dynamic_sections -+ (bfd *, struct bfd_link_info *info); -+static bfd_boolean nds32_elf_finish_dynamic_symbol -+ (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, -+ Elf_Internal_Sym *); -+static bfd_boolean nds32_elf_mkobject (bfd *); - - /* Nds32 helper functions. */ -+static bfd_reloc_status_type nds32_elf_final_sda_base -+ (bfd *, struct bfd_link_info *, bfd_vma *, bfd_boolean); -+static bfd_boolean allocate_dynrelocs (struct elf_link_hash_entry *, void *); -+static bfd_boolean readonly_dynrelocs (struct elf_link_hash_entry *, void *); -+static Elf_Internal_Rela *find_relocs_at_address -+ (Elf_Internal_Rela *, Elf_Internal_Rela *, -+ Elf_Internal_Rela *, enum elf_nds32_reloc_type); - static bfd_vma calculate_memory_address --(bfd *, Elf_Internal_Rela *, Elf_Internal_Sym *, Elf_Internal_Shdr *); -+ (bfd *, Elf_Internal_Rela *, Elf_Internal_Sym *, Elf_Internal_Shdr *); - static int nds32_get_section_contents (bfd *, asection *, - bfd_byte **, bfd_boolean); --static bfd_boolean nds32_elf_ex9_build_hash_table --(bfd *, asection *, struct bfd_link_info *); --static bfd_boolean nds32_elf_ex9_itb_base (struct bfd_link_info *); --static void nds32_elf_ex9_import_table (struct bfd_link_info *); --static void nds32_elf_ex9_finish (struct bfd_link_info *); --static void nds32_elf_ex9_reloc_jmp (struct bfd_link_info *); --static void nds32_elf_get_insn_with_reg -- (Elf_Internal_Rela *, uint32_t, uint32_t *); - static int nds32_get_local_syms (bfd *, asection *ATTRIBUTE_UNUSED, - Elf_Internal_Sym **); --static bfd_boolean nds32_elf_ex9_replace_instruction -- (struct bfd_link_info *, bfd *, asection *); --static bfd_boolean nds32_elf_ifc_calc (struct bfd_link_info *, bfd *, -- asection *); --static bfd_boolean nds32_elf_ifc_finish (struct bfd_link_info *); --static bfd_boolean nds32_elf_ifc_replace (struct bfd_link_info *); --static bfd_boolean nds32_elf_ifc_reloc (void); --static bfd_boolean nds32_relax_fp_as_gp -- (struct bfd_link_info *link_info, bfd *abfd, asection *sec, -- Elf_Internal_Rela *internal_relocs, Elf_Internal_Rela *irelend, -- Elf_Internal_Sym *isymbuf); -+static bfd_boolean nds32_relax_fp_as_gp -+ (struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *, -+ Elf_Internal_Rela *, Elf_Internal_Sym *); - static bfd_boolean nds32_fag_remove_unused_fpbase -- (bfd *abfd, asection *sec, Elf_Internal_Rela *internal_relocs, -- Elf_Internal_Rela *irelend); -+ (bfd *, asection *, Elf_Internal_Rela *, Elf_Internal_Rela *); -+static bfd_byte *nds32_elf_get_relocated_section_contents -+ (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, -+ bfd_boolean, asymbol **); -+static void nds32_elf_ict_hash_init (void); -+static void nds32_elf_ict_relocate (bfd *, struct bfd_link_info *); -+static asection* nds32_elf_get_target_section (struct bfd_link_info *, char *); - - enum - { -@@ -95,13 +134,24 @@ enum - MACH_V3M = bfd_mach_n1h_v3m - }; - -+/* If ABI is set by the option --mabi, without -+ checking the ABI compatible. */ -+static char *output_abi; -+ - #define MIN(a, b) ((a) > (b) ? (b) : (a)) - #define MAX(a, b) ((a) > (b) ? (a) : (b)) - -+/* True if insn is 4byte. */ -+#define INSN_32BIT(insn) ((((insn) & 0x80000000) == 0 ? (TRUE) : (FALSE))) -+ - /* The name of the dynamic interpreter. This is put in the .interp - section. */ - #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" - -+#define NDS32_GUARD_SEC_P(flags) ((flags) & SEC_ALLOC \ -+ && (flags) & SEC_LOAD \ -+ && (flags) & SEC_READONLY) -+ - /* The nop opcode we use. */ - #define NDS32_NOP32 0x40000009 - #define NDS32_NOP16 0x9200 -@@ -113,32 +163,32 @@ enum - /* The first entry in a procedure linkage table are reserved, - and the initial contents are unimportant (we zero them out). - Subsequent entries look like this. */ --#define PLT0_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(.got+4) */ --#define PLT0_ENTRY_WORD1 0x58f78000 /* ori r15, r25, LO12(.got+4) */ --#define PLT0_ENTRY_WORD2 0x05178000 /* lwi r17, [r15+0] */ --#define PLT0_ENTRY_WORD3 0x04f78001 /* lwi r15, [r15+4] */ --#define PLT0_ENTRY_WORD4 0x4a003c00 /* jr r15 */ -+#define PLT0_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(.got+4) */ -+#define PLT0_ENTRY_WORD1 0x58f78000 /* ori r15, r25, LO12(.got+4) */ -+#define PLT0_ENTRY_WORD2 0x05178000 /* lwi r17, [r15+0] */ -+#define PLT0_ENTRY_WORD3 0x04f78001 /* lwi r15, [r15+4] */ -+#define PLT0_ENTRY_WORD4 0x4a003c00 /* jr r15 */ - - /* $ta is change to $r15 (from $r25). */ - #define PLT0_PIC_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(got[1]@GOT) */ --#define PLT0_PIC_ENTRY_WORD1 0x58f78000 /* ori r15, r15, LO12(got[1]@GOT) */ --#define PLT0_PIC_ENTRY_WORD2 0x40f7f400 /* add r15, gp, r15 */ --#define PLT0_PIC_ENTRY_WORD3 0x05178000 /* lwi r17, [r15+0] */ --#define PLT0_PIC_ENTRY_WORD4 0x04f78001 /* lwi r15, [r15+4] */ --#define PLT0_PIC_ENTRY_WORD5 0x4a003c00 /* jr r15 */ -- --#define PLT_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(&got[n+3]) */ --#define PLT_ENTRY_WORD1 0x04f78000 /* lwi r15, r15, LO12(&got[n+3]) */ --#define PLT_ENTRY_WORD2 0x4a003c00 /* jr r15 */ --#define PLT_ENTRY_WORD3 0x45000000 /* movi r16, sizeof(RELA) * n */ --#define PLT_ENTRY_WORD4 0x48000000 /* j .plt0. */ -- --#define PLT_PIC_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(got[n+3]@GOT) */ --#define PLT_PIC_ENTRY_WORD1 0x58f78000 /* ori r15, r15, LO12(got[n+3]@GOT) */ --#define PLT_PIC_ENTRY_WORD2 0x38febc02 /* lw r15, [gp+r15] */ --#define PLT_PIC_ENTRY_WORD3 0x4a003c00 /* jr r15 */ --#define PLT_PIC_ENTRY_WORD4 0x45000000 /* movi r16, sizeof(RELA) * n */ --#define PLT_PIC_ENTRY_WORD5 0x48000000 /* j .plt0 */ -+#define PLT0_PIC_ENTRY_WORD1 0x58f78000 /* ori r15, r15, LO12(got[1]@GOT) */ -+#define PLT0_PIC_ENTRY_WORD2 0x40f7f400 /* add r15, gp, r15 */ -+#define PLT0_PIC_ENTRY_WORD3 0x05178000 /* lwi r17, [r15+0] */ -+#define PLT0_PIC_ENTRY_WORD4 0x04f78001 /* lwi r15, [r15+4] */ -+#define PLT0_PIC_ENTRY_WORD5 0x4a003c00 /* jr r15 */ -+ -+#define PLT_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(&got[n+3]) */ -+#define PLT_ENTRY_WORD1 0x04f78000 /* lwi r15, r15, LO12(&got[n+3]) */ -+#define PLT_ENTRY_WORD2 0x4a003c00 /* jr r15 */ -+#define PLT_ENTRY_WORD3 0x45000000 /* movi r16, sizeof(RELA) * n */ -+#define PLT_ENTRY_WORD4 0x48000000 /* j .plt0 */ -+ -+#define PLT_PIC_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(got[n+3]@GOT) */ -+#define PLT_PIC_ENTRY_WORD1 0x58f78000 /* ori r15, r15, LO12(got[n+3]@GOT) */ -+#define PLT_PIC_ENTRY_WORD2 0x38febc02 /* lw r15, [gp+r15] */ -+#define PLT_PIC_ENTRY_WORD3 0x4a003c00 /* jr r15 */ -+#define PLT_PIC_ENTRY_WORD4 0x45000000 /* movi r16, sizeof(RELA) * n */ -+#define PLT_PIC_ENTRY_WORD5 0x48000000 /* j .plt0 */ - - /* These are macros used to get the relocation accurate value. */ - #define ACCURATE_8BIT_S1 (0x100) -@@ -160,10 +210,11 @@ enum - #define CONSERVATIVE_19BIT (0x40000 - 0x1000) - #define CONSERVATIVE_20BIT (0x80000 - 0x1000) - -+#define NDS32_ICT_SECTION ".nds32.ict" -+ - /* Size of small data/bss sections, used to calculate SDA_BASE. */ - static long got_size = 0; - static int is_SDA_BASE_set = 0; --static int is_ITB_BASE_set = 0; - - /* Convert ELF-VER in eflags to string for debugging purpose. */ - static const char *const nds32_elfver_strtab[] = -@@ -192,37 +243,108 @@ struct elf_nds32_pcrel_relocs_copied - bfd_size_type count; - }; - -+/* The sh linker needs to keep track of the number of relocs that it -+ decides to copy as dynamic relocs in check_relocs for each symbol. -+ This is so that it can later discard them if they are found to be -+ unnecessary. We store the information in a field extending the -+ regular ELF linker hash table. */ -+ -+struct elf_nds32_dyn_relocs -+{ -+ struct elf_nds32_dyn_relocs *next; -+ -+ /* The input section of the reloc. */ -+ asection *sec; -+ -+ /* Total number of relocs copied for the input section. */ -+ bfd_size_type count; -+ -+ /* Number of pc-relative relocs copied for the input section. */ -+ bfd_size_type pc_count; -+}; -+ - /* Nds32 ELF linker hash entry. */ - -+enum elf_nds32_tls_type -+{ -+ GOT_UNKNOWN = (0), -+ GOT_NORMAL = (1 << 0), -+ GOT_TLS_LE = (1 << 1), -+ GOT_TLS_IE = (1 << 2), -+ GOT_TLS_IEGP = (1 << 3), -+ GOT_TLS_LD = (1 << 4), -+ GOT_TLS_GD = (1 << 5), -+ GOT_TLS_DESC = (1 << 6), -+}; -+ - struct elf_nds32_link_hash_entry - { - struct elf_link_hash_entry root; - - /* Track dynamic relocs copied for this symbol. */ -- struct elf_dyn_relocs *dyn_relocs; -+ struct elf_nds32_dyn_relocs *dyn_relocs; - - /* For checking relocation type. */ --#define GOT_UNKNOWN 0 --#define GOT_NORMAL 1 --#define GOT_TLS_IE 2 -- unsigned int tls_type; -+ enum elf_nds32_tls_type tls_type; -+ -+ int offset_to_gp; -+ -+ /* For saving function attribute indirect_call and entry address. */ -+ bfd_boolean indirect_call; - }; - - /* Get the nds32 ELF linker hash table from a link_info structure. */ - - #define FP_BASE_NAME "_FP_BASE_" - static int check_start_export_sym = 0; --static size_t ex9_relax_size = 0; /* Save ex9 predicted reducing size. */ -+/* File for exporting indirect call table. */ -+static FILE *ict_file = NULL; -+/* Save object ict model. */ -+static unsigned int ict_model = 0; -+/* True if _INDIRECT_CALL_TABLE_BASE_ is defined. */ -+static bfd_boolean ignore_indirect_call = FALSE; -+/* Be used to set ifc bit in elf header. */ -+static bfd_boolean ifc_flag = FALSE; -+ -+/* Rom-patch symbol hash table. */ -+struct elf_nds32_ict_hash_entry -+{ -+ struct bfd_hash_entry root; -+ struct elf_link_hash_entry *h; -+ unsigned int order; -+}; -+ -+/* Rom-patch hash table. */ -+static struct bfd_hash_table indirect_call_table; - - /* The offset for executable tls relaxation. */ - #define TP_OFFSET 0x0 - -+typedef struct -+{ -+ int min_id; -+ int max_id; -+ int count; -+ int bias; -+ int init; -+} elf32_nds32_relax_group_t; -+ - struct elf_nds32_obj_tdata - { - struct elf_obj_tdata root; - - /* tls_type for each local got entry. */ - char *local_got_tls_type; -+ -+ unsigned int hdr_size; -+ -+ /* GOTPLT entries for TLS descriptors. */ -+ bfd_vma *local_tlsdesc_gotent; -+ -+ int* offset_to_gp; -+ -+ /* for R_NDS32_RELAX_GROUP handling. */ -+ elf32_nds32_relax_group_t relax_group; - }; - - #define elf_nds32_tdata(bfd) \ -@@ -231,6 +353,12 @@ struct elf_nds32_obj_tdata - #define elf32_nds32_local_got_tls_type(bfd) \ - (elf_nds32_tdata (bfd)->local_got_tls_type) - -+#define elf32_nds32_local_gp_offset(bfd) \ -+ (elf_nds32_tdata (bfd)->offset_to_gp) -+ -+#define elf32_nds32_relax_group_ptr(bfd) \ -+ &(elf_nds32_tdata (bfd)->relax_group) -+ - #define elf32_nds32_hash_entry(ent) ((struct elf_nds32_link_hash_entry *)(ent)) - - static bfd_boolean -@@ -240,68 +368,75 @@ nds32_elf_mkobject (bfd *abfd) - NDS32_ELF_DATA); - } - -+ - /* Relocations used for relocation. */ --static reloc_howto_type nds32_elf_howto_table[] = --{ -+/* NOTE! -+ the index order must be the same with elf_nds32_reloc_type in -+ include/elf/nds32.h -+ */ -+#define HOWTO2(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ -+ [C] = HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) -+ -+static reloc_howto_type nds32_elf_howto_table[] = { - /* This reloc does nothing. */ -- HOWTO (R_NDS32_NONE, /* type */ -- 0, /* rightshift */ -- 3, /* size (0 = byte, 1 = short, 2 = long) */ -- 0, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_NONE", /* name */ -- FALSE, /* partial_inplace */ -- 0, /* src_mask */ -- 0, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_NONE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_NONE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* A 16 bit absolute relocation. */ -- HOWTO (R_NDS32_16, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- nds32_elf_generic_reloc, /* special_function */ -- "R_NDS32_16", /* name */ -- FALSE, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ nds32_elf_generic_reloc,/* special_function */ -+ "R_NDS32_16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* A 32 bit absolute relocation. */ -- HOWTO (R_NDS32_32, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- nds32_elf_generic_reloc, /* special_function */ -- "R_NDS32_32", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_32, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ nds32_elf_generic_reloc,/* special_function */ -+ "R_NDS32_32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* A 20 bit address. */ -- HOWTO (R_NDS32_20, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_unsigned, /* complain_on_overflow */ -- nds32_elf_generic_reloc, /* special_function */ -- "R_NDS32_20", /* name */ -- FALSE, /* partial_inplace */ -- 0xfffff, /* src_mask */ -- 0xfffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_20, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_unsigned,/* complain_on_overflow */ -+ nds32_elf_generic_reloc,/* special_function */ -+ "R_NDS32_20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* An PC Relative 9-bit relocation, shifted by 2. - This reloc is complicated because relocations are relative to pc & -4. -@@ -311,1910 +446,2264 @@ static reloc_howto_type nds32_elf_howto_table[] = - Branch relaxing in the assembler can store the addend in the insn, - and if bfd_install_relocation gets called the addend may get added - again. */ -- HOWTO (R_NDS32_9_PCREL, /* type */ -- 1, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 8, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- nds32_elf_9_pcrel_reloc, /* special_function */ -- "R_NDS32_9_PCREL", /* name */ -- FALSE, /* partial_inplace */ -- 0xff, /* src_mask */ -- 0xff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_9_PCREL, /* type */ -+ 1, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 8, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ nds32_elf_9_pcrel_reloc,/* special_function */ -+ "R_NDS32_9_PCREL", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xff, /* src_mask */ -+ 0xff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* A relative 15 bit relocation, right shifted by 1. */ -- HOWTO (R_NDS32_15_PCREL, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 14, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_15_PCREL", /* name */ -- FALSE, /* partial_inplace */ -- 0x3fff, /* src_mask */ -- 0x3fff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_15_PCREL, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 14, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_15_PCREL", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x3fff, /* src_mask */ -+ 0x3fff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* A relative 17 bit relocation, right shifted by 1. */ -- HOWTO (R_NDS32_17_PCREL, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_17_PCREL", /* name */ -- FALSE, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_17_PCREL, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_17_PCREL", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* A relative 25 bit relocation, right shifted by 1. */ - /* ??? It's not clear whether this should have partial_inplace set or not. - Branch relaxing in the assembler can store the addend in the insn, - and if bfd_install_relocation gets called the addend may get added - again. */ -- HOWTO (R_NDS32_25_PCREL, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 24, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_25_PCREL", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffff, /* src_mask */ -- 0xffffff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_25_PCREL, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 24, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_25_PCREL", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffff, /* src_mask */ -+ 0xffffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* High 20 bits of address when lower 12 is or'd in. */ -- HOWTO (R_NDS32_HI20, /* type */ -- 12, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_hi20_reloc, /* special_function */ -- "R_NDS32_HI20", /* name */ -- FALSE, /* partial_inplace */ -- 0x000fffff, /* src_mask */ -- 0x000fffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_HI20, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_hi20_reloc, /* special_function */ -+ "R_NDS32_HI20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Lower 12 bits of address. */ -- HOWTO (R_NDS32_LO12S3, /* type */ -- 3, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 9, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_lo12_reloc, /* special_function */ -- "R_NDS32_LO12S3", /* name */ -- FALSE, /* partial_inplace */ -- 0x000001ff, /* src_mask */ -- 0x000001ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S3, /* type */ -+ 3, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 9, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_lo12_reloc, /* special_function */ -+ "R_NDS32_LO12S3", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000001ff, /* src_mask */ -+ 0x000001ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Lower 12 bits of address. */ -- HOWTO (R_NDS32_LO12S2, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 10, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_lo12_reloc, /* special_function */ -- "R_NDS32_LO12S2", /* name */ -- FALSE, /* partial_inplace */ -- 0x000003ff, /* src_mask */ -- 0x000003ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S2, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 10, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_lo12_reloc, /* special_function */ -+ "R_NDS32_LO12S2", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000003ff, /* src_mask */ -+ 0x000003ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Lower 12 bits of address. */ -- HOWTO (R_NDS32_LO12S1, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 11, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_lo12_reloc, /* special_function */ -- "R_NDS32_LO12S1", /* name */ -- FALSE, /* partial_inplace */ -- 0x000007ff, /* src_mask */ -- 0x000007ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S1, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 11, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_lo12_reloc, /* special_function */ -+ "R_NDS32_LO12S1", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000007ff, /* src_mask */ -+ 0x000007ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Lower 12 bits of address. */ -- HOWTO (R_NDS32_LO12S0, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_lo12_reloc, /* special_function */ -- "R_NDS32_LO12S0", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S0, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_lo12_reloc, /* special_function */ -+ "R_NDS32_LO12S0", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Small data area 15 bits offset. */ -- HOWTO (R_NDS32_SDA15S3, /* type */ -- 3, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- nds32_elf_sda15_reloc, /* special_function */ -- "R_NDS32_SDA15S3", /* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA15S3, /* type */ -+ 3, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ nds32_elf_sda15_reloc, /* special_function */ -+ "R_NDS32_SDA15S3", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Small data area 15 bits offset. */ -- HOWTO (R_NDS32_SDA15S2, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- nds32_elf_sda15_reloc, /* special_function */ -- "R_NDS32_SDA15S2", /* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA15S2, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ nds32_elf_sda15_reloc, /* special_function */ -+ "R_NDS32_SDA15S2", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Small data area 15 bits offset. */ -- HOWTO (R_NDS32_SDA15S1, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- nds32_elf_sda15_reloc, /* special_function */ -- "R_NDS32_SDA15S1", /* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA15S1, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ nds32_elf_sda15_reloc, /* special_function */ -+ "R_NDS32_SDA15S1", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Small data area 15 bits offset. */ -- HOWTO (R_NDS32_SDA15S0, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- nds32_elf_sda15_reloc, /* special_function */ -- "R_NDS32_SDA15S0", /* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- /* GNU extension to record C++ vtable hierarchy */ -- HOWTO (R_NDS32_GNU_VTINHERIT, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 0, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- NULL, /* special_function */ -- "R_NDS32_GNU_VTINHERIT", /* name */ -- FALSE, /* partial_inplace */ -- 0, /* src_mask */ -- 0, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- /* GNU extension to record C++ vtable member usage */ -- HOWTO (R_NDS32_GNU_VTENTRY, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 0, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- _bfd_elf_rel_vtable_reloc_fn, /* special_function */ -- "R_NDS32_GNU_VTENTRY", /* name */ -- FALSE, /* partial_inplace */ -- 0, /* src_mask */ -- 0, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA15S0, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ nds32_elf_sda15_reloc, /* special_function */ -+ "R_NDS32_SDA15S0", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* GNU extension to record C++ vtable hierarchy */ -+ HOWTO2 (R_NDS32_GNU_VTINHERIT,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 0, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ NULL, /* special_function */ -+ "R_NDS32_GNU_VTINHERIT",/* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* GNU extension to record C++ vtable member usage */ -+ HOWTO2 (R_NDS32_GNU_VTENTRY, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 0, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ _bfd_elf_rel_vtable_reloc_fn,/* special_function */ -+ "R_NDS32_GNU_VTENTRY", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* A 16 bit absolute relocation. */ -- HOWTO (R_NDS32_16_RELA, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_16_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_16_RELA, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_16_RELA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* A 32 bit absolute relocation. */ -- HOWTO (R_NDS32_32_RELA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_32_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_32_RELA, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_32_RELA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* A 20 bit address. */ -- HOWTO (R_NDS32_20_RELA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_20_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xfffff, /* src_mask */ -- 0xfffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- HOWTO (R_NDS32_9_PCREL_RELA, /* type */ -- 1, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 8, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_9_PCREL_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0xff, /* src_mask */ -- 0xff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_20_RELA, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_20_RELA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO2 (R_NDS32_9_PCREL_RELA, /* type */ -+ 1, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 8, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_9_PCREL_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xff, /* src_mask */ -+ 0xff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* A relative 15 bit relocation, right shifted by 1. */ -- HOWTO (R_NDS32_15_PCREL_RELA, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 14, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_15_PCREL_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x3fff, /* src_mask */ -- 0x3fff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_15_PCREL_RELA,/* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 14, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_15_PCREL_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x3fff, /* src_mask */ -+ 0x3fff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* A relative 17 bit relocation, right shifted by 1. */ -- HOWTO (R_NDS32_17_PCREL_RELA, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_17_PCREL_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_17_PCREL_RELA,/* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_17_PCREL_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* A relative 25 bit relocation, right shifted by 2. */ -- HOWTO (R_NDS32_25_PCREL_RELA, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 24, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_25_PCREL_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffff, /* src_mask */ -- 0xffffff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_25_PCREL_RELA,/* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 24, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_25_PCREL_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffff, /* src_mask */ -+ 0xffffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* High 20 bits of address when lower 16 is or'd in. */ -- HOWTO (R_NDS32_HI20_RELA, /* type */ -- 12, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_HI20_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x000fffff, /* src_mask */ -- 0x000fffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_HI20_RELA, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_HI20_RELA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Lower 12 bits of address. */ -- HOWTO (R_NDS32_LO12S3_RELA, /* type */ -- 3, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 9, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_LO12S3_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x000001ff, /* src_mask */ -- 0x000001ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S3_RELA, /* type */ -+ 3, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 9, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_LO12S3_RELA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000001ff, /* src_mask */ -+ 0x000001ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Lower 12 bits of address. */ -- HOWTO (R_NDS32_LO12S2_RELA, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 10, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_LO12S2_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x000003ff, /* src_mask */ -- 0x000003ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S2_RELA, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 10, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_LO12S2_RELA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000003ff, /* src_mask */ -+ 0x000003ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Lower 12 bits of address. */ -- HOWTO (R_NDS32_LO12S1_RELA, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 11, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_LO12S1_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x000007ff, /* src_mask */ -- 0x000007ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S1_RELA, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 11, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_LO12S1_RELA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000007ff, /* src_mask */ -+ 0x000007ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Lower 12 bits of address. */ -- HOWTO (R_NDS32_LO12S0_RELA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_LO12S0_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S0_RELA, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_LO12S0_RELA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Small data area 15 bits offset. */ -- HOWTO (R_NDS32_SDA15S3_RELA, /* type */ -- 3, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA15S3_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA15S3_RELA, /* type */ -+ 3, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA15S3_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Small data area 15 bits offset. */ -- HOWTO (R_NDS32_SDA15S2_RELA, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA15S2_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- HOWTO (R_NDS32_SDA15S1_RELA, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA15S1_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- HOWTO (R_NDS32_SDA15S0_RELA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA15S0_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- /* GNU extension to record C++ vtable hierarchy */ -- HOWTO (R_NDS32_RELA_GNU_VTINHERIT, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 0, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- NULL, /* special_function */ -- "R_NDS32_RELA_GNU_VTINHERIT", /* name */ -- FALSE, /* partial_inplace */ -- 0, /* src_mask */ -- 0, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- /* GNU extension to record C++ vtable member usage */ -- HOWTO (R_NDS32_RELA_GNU_VTENTRY, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 0, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- _bfd_elf_rel_vtable_reloc_fn, /* special_function */ -- "R_NDS32_RELA_GNU_VTENTRY", /* name */ -- FALSE, /* partial_inplace */ -- 0, /* src_mask */ -- 0, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA15S2_RELA, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA15S2_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO2 (R_NDS32_SDA15S1_RELA, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA15S1_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO2 (R_NDS32_SDA15S0_RELA, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA15S0_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* GNU extension to record C++ vtable hierarchy */ -+ HOWTO2 (R_NDS32_RELA_GNU_VTINHERIT,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 0, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ NULL, /* special_function */ -+ "R_NDS32_RELA_GNU_VTINHERIT",/* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* GNU extension to record C++ vtable member usage */ -+ HOWTO2 (R_NDS32_RELA_GNU_VTENTRY,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 0, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ _bfd_elf_rel_vtable_reloc_fn,/* special_function */ -+ "R_NDS32_RELA_GNU_VTENTRY",/* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Like R_NDS32_20, but referring to the GOT table entry for - the symbol. */ -- HOWTO (R_NDS32_GOT20, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOT20", /* name */ -- FALSE, /* partial_inplace */ -- 0xfffff, /* src_mask */ -- 0xfffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOT20, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOT20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Like R_NDS32_PCREL, but referring to the procedure linkage table - entry for the symbol. */ -- HOWTO (R_NDS32_25_PLTREL, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 24, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_25_PLTREL", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffff, /* src_mask */ -- 0xffffff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_25_PLTREL, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 24, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_25_PLTREL", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffff, /* src_mask */ -+ 0xffffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* This is used only by the dynamic linker. The symbol should exist - both in the object being run and in some shared library. The - dynamic linker copies the data addressed by the symbol from the - shared library into the object, because the object being - run has to have the data at some particular address. */ -- HOWTO (R_NDS32_COPY, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_COPY", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_COPY, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_COPY", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Like R_NDS32_20, but used when setting global offset table - entries. */ -- HOWTO (R_NDS32_GLOB_DAT, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GLOB_DAT", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GLOB_DAT, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GLOB_DAT", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Marks a procedure linkage table entry for a symbol. */ -- HOWTO (R_NDS32_JMP_SLOT, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_JMP_SLOT", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_JMP_SLOT, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_JMP_SLOT", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Used only by the dynamic linker. When the object is run, this - longword is set to the load address of the object, plus the - addend. */ -- HOWTO (R_NDS32_RELATIVE, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_RELATIVE", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- HOWTO (R_NDS32_GOTOFF, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOTOFF", /* name */ -- FALSE, /* partial_inplace */ -- 0xfffff, /* src_mask */ -- 0xfffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_RELATIVE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_RELATIVE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO2 (R_NDS32_GOTOFF, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOTOFF", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* An PC Relative 20-bit relocation used when setting PIC offset - table register. */ -- HOWTO (R_NDS32_GOTPC20, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOTPC20", /* name */ -- FALSE, /* partial_inplace */ -- 0xfffff, /* src_mask */ -- 0xfffff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOTPC20, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOTPC20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* Like R_NDS32_HI20, but referring to the GOT table entry for - the symbol. */ -- HOWTO (R_NDS32_GOT_HI20, /* type */ -- 12, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOT_HI20", /* name */ -- FALSE, /* partial_inplace */ -- 0x000fffff, /* src_mask */ -- 0x000fffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_GOT_LO12, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOT_LO12", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOT_HI20, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOT_HI20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOT_LO12, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOT_LO12", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* An PC Relative relocation used when setting PIC offset table register. - Like R_NDS32_HI20, but referring to the GOT table entry for - the symbol. */ -- HOWTO (R_NDS32_GOTPC_HI20, /* type */ -- 12, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOTPC_HI20", /* name */ -- FALSE, /* partial_inplace */ -- 0x000fffff, /* src_mask */ -- 0x000fffff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -- HOWTO (R_NDS32_GOTPC_LO12, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOTPC_LO12", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -- -- HOWTO (R_NDS32_GOTOFF_HI20, /* type */ -- 12, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOTOFF_HI20", /* name */ -- FALSE, /* partial_inplace */ -- 0x000fffff, /* src_mask */ -- 0x000fffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_GOTOFF_LO12, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOTOFF_LO12", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOTPC_HI20, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOTPC_HI20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOTPC_LO12, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOTPC_LO12", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ HOWTO2 (R_NDS32_GOTOFF_HI20, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOTOFF_HI20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOTOFF_LO12, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOTOFF_LO12", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Alignment hint for relaxable instruction. This is used with - R_NDS32_LABEL as a pair. Relax this instruction from 4 bytes to 2 - in order to make next label aligned on word boundary. */ -- HOWTO (R_NDS32_INSN16, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_INSN16", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_INSN16, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_INSN16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Alignment hint for label. */ -- HOWTO (R_NDS32_LABEL, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_LABEL", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LABEL, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LABEL", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for unconditional call sequence */ -- HOWTO (R_NDS32_LONGCALL1, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_LONGCALL1", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGCALL1, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGCALL1", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for conditional call sequence. */ -- HOWTO (R_NDS32_LONGCALL2, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_LONGCALL2", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGCALL2, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGCALL2", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for conditional call sequence. */ -- HOWTO (R_NDS32_LONGCALL3, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_LONGCALL3", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGCALL3, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGCALL3", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for unconditional branch sequence. */ -- HOWTO (R_NDS32_LONGJUMP1, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_LONGJUMP1", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGJUMP1, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGJUMP1", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for conditional branch sequence. */ -- HOWTO (R_NDS32_LONGJUMP2, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_LONGJUMP2", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGJUMP2, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGJUMP2", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for conditional branch sequence. */ -- HOWTO (R_NDS32_LONGJUMP3, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_LONGJUMP3", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGJUMP3, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGJUMP3", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for load/store sequence. */ -- HOWTO (R_NDS32_LOADSTORE, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_LOADSTORE", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LOADSTORE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LOADSTORE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for load/store sequence. */ -- HOWTO (R_NDS32_9_FIXED_RELA, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_9_FIXED_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x000000ff, /* src_mask */ -- 0x000000ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_9_FIXED_RELA, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_9_FIXED_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000000ff, /* src_mask */ -+ 0x000000ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for load/store sequence. */ -- HOWTO (R_NDS32_15_FIXED_RELA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_15_FIXED_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x00003fff, /* src_mask */ -- 0x00003fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_15_FIXED_RELA,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_15_FIXED_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00003fff, /* src_mask */ -+ 0x00003fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for load/store sequence. */ -- HOWTO (R_NDS32_17_FIXED_RELA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_17_FIXED_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x0000ffff, /* src_mask */ -- 0x0000ffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_17_FIXED_RELA,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_17_FIXED_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x0000ffff, /* src_mask */ -+ 0x0000ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for load/store sequence. */ -- HOWTO (R_NDS32_25_FIXED_RELA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_25_FIXED_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x00ffffff, /* src_mask */ -- 0x00ffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_25_FIXED_RELA,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_25_FIXED_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00ffffff, /* src_mask */ -+ 0x00ffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* High 20 bits of PLT symbol offset relative to PC. */ -- HOWTO (R_NDS32_PLTREL_HI20, /* type */ -- 12, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_PLTREL_HI20", /* name */ -- FALSE, /* partial_inplace */ -- 0x000fffff, /* src_mask */ -- 0x000fffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_PLTREL_HI20, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_PLTREL_HI20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Low 12 bits of PLT symbol offset relative to PC. */ -- HOWTO (R_NDS32_PLTREL_LO12, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_PLTREL_LO12", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_PLTREL_LO12, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_PLTREL_LO12", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* High 20 bits of PLT symbol offset relative to GOT (GP). */ -- HOWTO (R_NDS32_PLT_GOTREL_HI20, /* type */ -- 12, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_PLT_GOTREL_HI20", /* name */ -- FALSE, /* partial_inplace */ -- 0x000fffff, /* src_mask */ -- 0x000fffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_PLT_GOTREL_HI20, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_PLT_GOTREL_HI20",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Low 12 bits of PLT symbol offset relative to GOT (GP). */ -- HOWTO (R_NDS32_PLT_GOTREL_LO12, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_PLT_GOTREL_LO12", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_PLT_GOTREL_LO12,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_PLT_GOTREL_LO12",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Small data area 12 bits offset. */ -- HOWTO (R_NDS32_SDA12S2_DP_RELA, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA12S2_DP_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA12S2_DP_RELA,/* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA12S2_DP_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Small data area 12 bits offset. */ -- HOWTO (R_NDS32_SDA12S2_SP_RELA, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA12S2_SP_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA12S2_SP_RELA,/* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA12S2_SP_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - /* Lower 12 bits of address. */ - -- HOWTO (R_NDS32_LO12S2_DP_RELA, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 10, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_LO12S2_DP_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x000003ff, /* src_mask */ -- 0x000003ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S2_DP_RELA, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 10, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_LO12S2_DP_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000003ff, /* src_mask */ -+ 0x000003ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Lower 12 bits of address. */ -- HOWTO (R_NDS32_LO12S2_SP_RELA,/* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 10, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_LO12S2_SP_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x000003ff, /* src_mask */ -- 0x000003ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S2_SP_RELA,/* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 10, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_LO12S2_SP_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000003ff, /* src_mask */ -+ 0x000003ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - /* Lower 12 bits of address. Special identity for or case. */ -- HOWTO (R_NDS32_LO12S0_ORI_RELA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_LO12S0_ORI_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LO12S0_ORI_RELA,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_LO12S0_ORI_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - /* Small data area 19 bits offset. */ -- HOWTO (R_NDS32_SDA16S3_RELA, /* type */ -- 3, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA16S3_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x0000ffff, /* src_mask */ -- 0x0000ffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA16S3_RELA, /* type */ -+ 3, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA16S3_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x0000ffff, /* src_mask */ -+ 0x0000ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Small data area 15 bits offset. */ -- HOWTO (R_NDS32_SDA17S2_RELA, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 17, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA17S2_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x0001ffff, /* src_mask */ -- 0x0001ffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- HOWTO (R_NDS32_SDA18S1_RELA, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 18, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA18S1_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x0003ffff, /* src_mask */ -- 0x0003ffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- HOWTO (R_NDS32_SDA19S0_RELA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 19, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA19S0_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x0007ffff, /* src_mask */ -- 0x0007ffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_DWARF2_OP1_RELA, /* type */ -- 0, /* rightshift */ -- 0, /* size (0 = byte, 1 = short, 2 = long) */ -- 8, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_DWARF2_OP1_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xff, /* src_mask */ -- 0xff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_DWARF2_OP2_RELA, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_DWARF2_OP2_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_DWARF2_LEB_RELA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_DWARF2_LEB_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_UPDATE_TA_RELA,/* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_UPDATE_TA_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA17S2_RELA, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 17, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA17S2_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x0001ffff, /* src_mask */ -+ 0x0001ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO2 (R_NDS32_SDA18S1_RELA, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 18, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA18S1_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x0003ffff, /* src_mask */ -+ 0x0003ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO2 (R_NDS32_SDA19S0_RELA, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 19, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA19S0_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x0007ffff, /* src_mask */ -+ 0x0007ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_DWARF2_OP1_RELA,/* type */ -+ 0, /* rightshift */ -+ 0, /* size (0 = byte, 1 = short, 2 = long) */ -+ 8, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_DWARF2_OP1_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xff, /* src_mask */ -+ 0xff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_DWARF2_OP2_RELA,/* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_DWARF2_OP2_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_DWARF2_LEB_RELA,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_DWARF2_LEB_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_UPDATE_TA_RELA,/* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_UPDATE_TA_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - /* Like R_NDS32_PCREL, but referring to the procedure linkage table - entry for the symbol. */ -- HOWTO (R_NDS32_9_PLTREL, /* type */ -- 1, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 8, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_9_PLTREL", /* name */ -- FALSE, /* partial_inplace */ -- 0xff, /* src_mask */ -- 0xff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_9_PLTREL, /* type */ -+ 1, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 8, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_9_PLTREL", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xff, /* src_mask */ -+ 0xff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - /* Low 20 bits of PLT symbol offset relative to GOT (GP). */ -- HOWTO (R_NDS32_PLT_GOTREL_LO20, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_PLT_GOTREL_LO20", /* name */ -- FALSE, /* partial_inplace */ -- 0x000fffff, /* src_mask */ -- 0x000fffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- /* low 15 bits of PLT symbol offset relative to GOT (GP) */ -- HOWTO (R_NDS32_PLT_GOTREL_LO15, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_PLT_GOTREL_LO15", /* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_PLT_GOTREL_LO20,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_PLT_GOTREL_LO20",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ /* low 15 bits of PLT symbol offset relative to GOT (GP) */ -+ HOWTO2 (R_NDS32_PLT_GOTREL_LO15,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_PLT_GOTREL_LO15",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - /* Low 19 bits of PLT symbol offset relative to GOT (GP). */ -- HOWTO (R_NDS32_PLT_GOTREL_LO19, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 19, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_PLT_GOTREL_LO19", /* name */ -- FALSE, /* partial_inplace */ -- 0x0007ffff, /* src_mask */ -- 0x0007ffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_GOT_LO15, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOT_LO15", /* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_GOT_LO19, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 19, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOT_LO19", /* name */ -- FALSE, /* partial_inplace */ -- 0x0007ffff, /* src_mask */ -- 0x0007ffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_GOTOFF_LO15, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOTOFF_LO15", /* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_GOTOFF_LO19, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 19, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOTOFF_LO19", /* name */ -- FALSE, /* partial_inplace */ -- 0x0007ffff, /* src_mask */ -- 0x0007ffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_PLT_GOTREL_LO19,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 19, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_PLT_GOTREL_LO19",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x0007ffff, /* src_mask */ -+ 0x0007ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOT_LO15, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOT_LO15", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOT_LO19, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 19, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOT_LO19", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x0007ffff, /* src_mask */ -+ 0x0007ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOTOFF_LO15, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOTOFF_LO15", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOTOFF_LO19, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 19, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOTOFF_LO19", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x0007ffff, /* src_mask */ -+ 0x0007ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - /* GOT 15 bits offset. */ -- HOWTO (R_NDS32_GOT15S2_RELA, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOT15S2_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x00007fff, /* src_mask */ -- 0x00007fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOT15S2_RELA, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOT15S2_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00007fff, /* src_mask */ -+ 0x00007fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - /* GOT 17 bits offset. */ -- HOWTO (R_NDS32_GOT17S2_RELA, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 17, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_GOT17S2_RELA",/* name */ -- FALSE, /* partial_inplace */ -- 0x0001ffff, /* src_mask */ -- 0x0001ffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_GOT17S2_RELA, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 17, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_GOT17S2_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x0001ffff, /* src_mask */ -+ 0x0001ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - /* A 5 bit address. */ -- HOWTO (R_NDS32_5_RELA, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 5, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_5_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x1f, /* src_mask */ -- 0x1f, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_10_UPCREL_RELA,/* type */ -- 1, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 9, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_unsigned, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_10_UPCREL_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x1ff, /* src_mask */ -- 0x1ff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -- HOWTO (R_NDS32_SDA_FP7U2_RELA,/* type */ -- 2, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 7, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_unsigned, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_SDA_FP7U2_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x0000007f, /* src_mask */ -- 0x0000007f, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_WORD_9_PCREL_RELA, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 8, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_WORD_9_PCREL_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xff, /* src_mask */ -- 0xff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -- HOWTO (R_NDS32_25_ABS_RELA, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 24, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_25_ABS_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffff, /* src_mask */ -- 0xffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_5_RELA, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 5, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_5_RELA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x1f, /* src_mask */ -+ 0x1f, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_10_UPCREL_RELA,/* type */ -+ 1, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 9, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_unsigned,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_10_UPCREL_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x1ff, /* src_mask */ -+ 0x1ff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_SDA_FP7U2_RELA,/* type */ -+ 2, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 7, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_unsigned,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SDA_FP7U2_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x0000007f, /* src_mask */ -+ 0x0000007f, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_WORD_9_PCREL_RELA,/* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 8, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_WORD_9_PCREL_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xff, /* src_mask */ -+ 0xff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_25_ABS_RELA, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 24, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_25_ABS_RELA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffff, /* src_mask */ -+ 0xffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* A relative 17 bit relocation for ifc, right shifted by 1. */ -- HOWTO (R_NDS32_17IFC_PCREL_RELA, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_17IFC_PCREL_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0xffff, /* src_mask */ -- 0xffff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_17IFC_PCREL_RELA,/* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_17IFC_PCREL_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffff, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* A relative unsigned 10 bit relocation for ifc, right shifted by 1. */ -- HOWTO (R_NDS32_10IFCU_PCREL_RELA, /* type */ -- 1, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 9, /* bitsize */ -- TRUE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_unsigned, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_10IFCU_PCREL_RELA", /* name */ -- FALSE, /* partial_inplace */ -- 0x1ff, /* src_mask */ -- 0x1ff, /* dst_mask */ -- TRUE), /* pcrel_offset */ -- -- /* Like R_NDS32_HI20, but referring to the TLS entry for the symbol. */ -- HOWTO (R_NDS32_TLS_LE_HI20, /* type */ -- 12, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_TLS_LE_HI20", /* name */ -- FALSE, /* partial_inplace */ -- 0x000fffff, /* src_mask */ -- 0x000fffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_TLS_LE_LO12, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 12, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_TLS_LE_LO12", /* name */ -- FALSE, /* partial_inplace */ -- 0x00000fff, /* src_mask */ -- 0x00000fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- -- /* Like R_NDS32_HI20, but referring to the TLS entry for the symbol. */ -- HOWTO (R_NDS32_TLS_IE_HI20, /* type */ -- 12, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_TLS_IE_HI20", /* name */ -- FALSE, /* partial_inplace */ -- 0x000fffff, /* src_mask */ -- 0x000fffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_TLS_IE_LO12S2, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 10, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_TLS_IE_LO12S2", /* name */ -- FALSE, /* partial_inplace */ -- 0x000003ff, /* src_mask */ -- 0x000003ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- /* Mark a TLS IE entry in GOT. */ -- HOWTO (R_NDS32_TLS_TPOFF, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_TLS_TPOFF", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- /* A 20 bit address. */ -- HOWTO (R_NDS32_TLS_LE_20, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 20, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_TLS_LE_20", /* name */ -- FALSE, /* partial_inplace */ -- 0xfffff, /* src_mask */ -- 0xfffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_TLS_LE_15S0, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_TLS_LE_15S0", /* name */ -- FALSE, /* partial_inplace */ -- 0x7fff, /* src_mask */ -- 0x7fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_TLS_LE_15S1, /* type */ -- 1, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_TLS_LE_15S1", /* name */ -- FALSE, /* partial_inplace */ -- 0x7fff, /* src_mask */ -- 0x7fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_TLS_LE_15S2, /* type */ -- 2, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 15, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_signed, /* complain_on_overflow */ -- bfd_elf_generic_reloc, /* special_function */ -- "R_NDS32_TLS_LE_15S2", /* name */ -- FALSE, /* partial_inplace */ -- 0x7fff, /* src_mask */ -- 0x7fff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_10IFCU_PCREL_RELA,/* type */ -+ 1, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 9, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_unsigned,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_10IFCU_PCREL_RELA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x1ff, /* src_mask */ -+ 0x1ff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - - /* Relax hint for unconditional call sequence */ -- HOWTO (R_NDS32_LONGCALL4, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- nds32_elf_ignore_reloc, /* special_function */ -- "R_NDS32_LONGCALL4", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGCALL4, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGCALL4", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for conditional call sequence. */ -- HOWTO (R_NDS32_LONGCALL5, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- nds32_elf_ignore_reloc, /* special_function */ -- "R_NDS32_LONGCALL5", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGCALL5, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGCALL5", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for conditional call sequence. */ -- HOWTO (R_NDS32_LONGCALL6, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- nds32_elf_ignore_reloc, /* special_function */ -- "R_NDS32_LONGCALL6", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGCALL6, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGCALL6", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for unconditional branch sequence. */ -- HOWTO (R_NDS32_LONGJUMP4, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- nds32_elf_ignore_reloc, /* special_function */ -- "R_NDS32_LONGJUMP4", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGJUMP4, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGJUMP4", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for conditional branch sequence. */ -- HOWTO (R_NDS32_LONGJUMP5, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- nds32_elf_ignore_reloc, /* special_function */ -- "R_NDS32_LONGJUMP5", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGJUMP5, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGJUMP5", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for conditional branch sequence. */ -- HOWTO (R_NDS32_LONGJUMP6, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- nds32_elf_ignore_reloc, /* special_function */ -- "R_NDS32_LONGJUMP6", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGJUMP6, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGJUMP6", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - - /* Relax hint for conditional branch sequence. */ -- HOWTO (R_NDS32_LONGJUMP7, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- nds32_elf_ignore_reloc, /* special_function */ -- "R_NDS32_LONGJUMP7", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_LONGJUMP7, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LONGJUMP7", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Check sum value for security. */ -+ HOWTO2 (R_NDS32_SECURITY_16, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 5, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_SECURITY_16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x1fffe0, /* src_mask */ -+ 0x1fffe0, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* TLS LE TP offset relocation */ -+ HOWTO2 (R_NDS32_TLS_TPOFF, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_TPOFF", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_NDS32_HI20, but referring to the TLS LE entry for the symbol. */ -+ HOWTO2 (R_NDS32_TLS_LE_HI20, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_LE_HI20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_TLS_LE_LO12, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_LE_LO12", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 20 bit address. */ -+ HOWTO2 (R_NDS32_TLS_LE_20, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_LE_20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xfffff, /* src_mask */ -+ 0xfffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_TLS_LE_15S0, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_LE_15S0", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x7fff, /* src_mask */ -+ 0x7fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_TLS_LE_15S1, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_LE_15S1", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x7fff, /* src_mask */ -+ 0x7fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_TLS_LE_15S2, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_LE_15S2", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x7fff, /* src_mask */ -+ 0x7fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_NDS32_HI20, but referring to the TLS IE entry for the symbol. */ -+ HOWTO2 (R_NDS32_TLS_IE_HI20, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_IE_HI20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_TLS_IE_LO12, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_IE_LO12", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_TLS_IE_LO12S2,/* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 10, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_IE_LO12S2",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000003ff, /* src_mask */ -+ 0x000003ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_NDS32_HI20, but referring to the TLS IE (PIE) entry for the symbol. */ -+ HOWTO2 (R_NDS32_TLS_IEGP_HI20,/* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_IEGP_HI20",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO2 (R_NDS32_TLS_IEGP_LO12,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_IEGP_LO12",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO2 (R_NDS32_TLS_IEGP_LO12S2,/* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 10, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_IEGP_LO12S2",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000003ff, /* src_mask */ -+ 0x000003ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* TLS description relocation */ -+ HOWTO2 (R_NDS32_TLS_DESC, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_hi20_reloc, /* special_function */ -+ "R_NDS32_TLS_DESC_HI20",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* TLS GD/LD description offset high part. */ -+ HOWTO2 (R_NDS32_TLS_DESC_HI20,/* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_hi20_reloc, /* special_function */ -+ "R_NDS32_TLS_DESC_HI20",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ /* TLS GD/LD description offset low part. */ -+ HOWTO2 (R_NDS32_TLS_DESC_LO12,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_lo12_reloc, /* special_function */ -+ "R_NDS32_TLS_DESC_LO12",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* TLS GD/LD description offset set (movi). */ -+ HOWTO2 (R_NDS32_TLS_DESC_20, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_DESC_20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* TLS GD/LD description offset set (lwi.gp). */ -+ HOWTO2 (R_NDS32_TLS_DESC_SDA17S2,/* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 17, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_TLS_DESC_SDA17S2",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x0001ffff, /* src_mask */ -+ 0x0001ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Jump-patch table relocations. */ -+ /* High 20 bits of jump-patch table address. */ -+ HOWTO2 (R_NDS32_ICT_HI20, /* type */ -+ 12, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 20, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_ICT_HI20", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000fffff, /* src_mask */ -+ 0x000fffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ /* Lower 12 bits of jump-patch table address. */ -+ HOWTO2 (R_NDS32_ICT_LO12,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 12, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_ICT_LO12",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x00000fff, /* src_mask */ -+ 0x00000fff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO2 (R_NDS32_ICT_LO12S2,/* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 10, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_ICT_LO12S2",/* name */ -+ FALSE, /* partial_inplace */ -+ 0x000003ff, /* src_mask */ -+ 0x000003ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A relative 25 bit relocation, right shifted by 2. */ -+ HOWTO2 (R_NDS32_ICT_25PC,/* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 24, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NDS32_ICT_25PC",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffff, /* src_mask */ -+ 0xffffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ - }; - - /* Relocations used for relaxation. */ --static reloc_howto_type nds32_elf_relax_howto_table[] = --{ -- HOWTO (R_NDS32_RELAX_ENTRY, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_RELAX_ENTRY", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_GOT_SUFF, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_GOT_SUFF", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_GOTOFF_SUFF, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_bitfield, /* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_GOTOFF_SUFF", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_PLT_GOT_SUFF, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_PLT_GOT_SUFF",/* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_MULCALL_SUFF, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_MULCALL_SUFF",/* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_PTR, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_PTR", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_PTR_COUNT, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_PTR_COUNT", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_PTR_RESOLVED, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_PTR_RESOLVED",/* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_PLTBLOCK, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_PLTBLOCK", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_RELAX_REGION_BEGIN, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_RELAX_REGION_BEGIN", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_RELAX_REGION_END, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_RELAX_REGION_END", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_MINUEND, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_MINUEND", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_SUBTRAHEND, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_SUBTRAHEND", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_DIFF8, /* type */ -- 0, /* rightshift */ -- 0, /* size (0 = byte, 1 = short, 2 = long) */ -- 8, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_DIFF8", /* name */ -- FALSE, /* partial_inplace */ -- 0x000000ff, /* src_mask */ -- 0x000000ff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_DIFF16, /* type */ -- 0, /* rightshift */ -- 1, /* size (0 = byte, 1 = short, 2 = long) */ -- 16, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_DIFF16", /* name */ -- FALSE, /* partial_inplace */ -- 0x0000ffff, /* src_mask */ -- 0x0000ffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_DIFF32, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_DIFF32", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_DIFF_ULEB128, /* type */ -- 0, /* rightshift */ -- 0, /* size (0 = byte, 1 = short, 2 = long) */ -- 0, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_DIFF_ULEB128",/* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_DATA, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_DATA", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_TRAN, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont,/* complain_on_overflow */ -- nds32_elf_ignore_reloc,/* special_function */ -- "R_NDS32_TRAN", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_TLS_LE_ADD, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- nds32_elf_ignore_reloc, /* special_function */ -- "R_NDS32_TLS_LE_ADD", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_TLS_LE_LS, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- nds32_elf_ignore_reloc, /* special_function */ -- "R_NDS32_TLS_LE_LS", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -- HOWTO (R_NDS32_EMPTY, /* type */ -- 0, /* rightshift */ -- 2, /* size (0 = byte, 1 = short, 2 = long) */ -- 32, /* bitsize */ -- FALSE, /* pc_relative */ -- 0, /* bitpos */ -- complain_overflow_dont, /* complain_on_overflow */ -- nds32_elf_ignore_reloc, /* special_function */ -- "R_NDS32_EMPTY", /* name */ -- FALSE, /* partial_inplace */ -- 0xffffffff, /* src_mask */ -- 0xffffffff, /* dst_mask */ -- FALSE), /* pcrel_offset */ -+#define HOWTO3(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ -+ [C-R_NDS32_RELAX_ENTRY] = HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) -+ -+static reloc_howto_type nds32_elf_relax_howto_table[] = { -+ HOWTO3 (R_NDS32_RELAX_ENTRY, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_RELAX_ENTRY", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_GOT_SUFF, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_GOT_SUFF", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_GOTOFF_SUFF, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_GOTOFF_SUFF", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_PLT_GOT_SUFF, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_PLT_GOT_SUFF",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_MULCALL_SUFF, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_MULCALL_SUFF",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_PTR, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_PTR", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_PTR_COUNT, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_PTR_COUNT", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_PTR_RESOLVED, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_PTR_RESOLVED",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_PLTBLOCK, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_PLTBLOCK", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_RELAX_REGION_BEGIN,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_RELAX_REGION_BEGIN",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_RELAX_REGION_END,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_RELAX_REGION_END",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_MINUEND, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_MINUEND", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_SUBTRAHEND, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_SUBTRAHEND", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_DIFF8, /* type */ -+ 0, /* rightshift */ -+ 0, /* size (0 = byte, 1 = short, 2 = long) */ -+ 8, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_DIFF8", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x000000ff, /* src_mask */ -+ 0x000000ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_DIFF16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_DIFF16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x0000ffff, /* src_mask */ -+ 0x0000ffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_DIFF32, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_DIFF32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_DIFF_ULEB128, /* type */ -+ 0, /* rightshift */ -+ 0, /* size (0 = byte, 1 = short, 2 = long) */ -+ 0, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_DIFF_ULEB128",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_DATA, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_DATA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_TRAN, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_TRAN", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_EMPTY, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_EMPTY", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO3 (R_NDS32_TLS_LE_ADD, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_TLS_LE_ADD", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ HOWTO3 (R_NDS32_TLS_LE_LS, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_TLS_LE_LS", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO3 (R_NDS32_TLS_IEGP_LW, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_TLS_IEGP_LW", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* TLS GD/LD description address base addition. */ -+ HOWTO3 (R_NDS32_TLS_DESC_ADD, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_TLS_DESC_ADD",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* TLS GD/LD description function load. */ -+ HOWTO3 (R_NDS32_TLS_DESC_FUNC,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_TLS_DESC_FUNC",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* TLS DESC resolve function call. */ -+ HOWTO3 (R_NDS32_TLS_DESC_CALL,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_TLS_DESC_CALL",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* TLS DESC variable access. */ -+ HOWTO3 (R_NDS32_TLS_DESC_MEM, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_TLS_DESC_MEM",/* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* TLS GD/LD description mark (@tlsdec). */ -+ HOWTO3 (R_NDS32_RELAX_REMOVE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_REMOVE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* TLS GD/LD description mark (@tlsdec). */ -+ HOWTO3 (R_NDS32_RELAX_GROUP, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_GROUP", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* LA and FLSI relaxation. */ -+ HOWTO3 (R_NDS32_LSI, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ nds32_elf_ignore_reloc,/* special_function */ -+ "R_NDS32_LSI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffff, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ - }; -- - -+ -+static unsigned long dl_tlsdesc_lazy_trampoline[] = -+{ -+ 0x46200000, /* sethi $r2,#0x0 */ -+ 0x58210000, /* ori $r2,$r2,#0x0 */ -+ 0x40217400, /* add $r2,$r2,$gp */ -+ 0x04210000, /* lwi $r2,[$r2+#0x0] */ -+ 0x46300000, /* sethi $r3,#0x0 */ -+ 0x58318000, /* ori $r3,$r3,#0x0 */ -+ 0x4031f400, /* add $r3,$r3,$gp */ -+ 0x4a000800, /* jr $r2 */ -+}; -+ -+/* === code === */ -+ -+static void -+nds32_put_trampoline (void *contents, const unsigned long *template, -+ unsigned count) -+{ -+ unsigned ix; -+ -+ for (ix = 0; ix != count; ix++) -+ { -+ unsigned long insn = template[ix]; -+ bfd_putb32 (insn, (char *) contents + ix * 4); -+ } -+} -+ - /* nds32_insertion_sort sorts an array with nmemb elements of size size. - This prototype is the same as qsort (). */ - -@@ -2224,7 +2713,7 @@ nds32_insertion_sort (void *base, size_t nmemb, size_t size, - { - char *ptr = (char *) base; - int i, j; -- char *tmp = xmalloc (size); -+ char *tmp = alloca (size); - - /* If i is less than j, i is inserted before j. - -@@ -2248,7 +2737,6 @@ nds32_insertion_sort (void *base, size_t nmemb, size_t size, - memmove (ptr + (j + 1) * size, ptr + j * size, (i - j) * size); - memcpy (ptr + j * size, tmp, size); - } -- free (tmp); - } - - /* Sort relocation by r_offset. -@@ -2277,14 +2765,13 @@ compar_reloc (const void *lhs, const void *rhs) - } - - /* Functions listed below are only used for old relocs. -- * nds32_elf_9_pcrel_reloc -- * nds32_elf_do_9_pcrel_reloc -- * nds32_elf_hi20_reloc -- * nds32_elf_relocate_hi20 -- * nds32_elf_lo12_reloc -- * nds32_elf_sda15_reloc -- * nds32_elf_generic_reloc -- */ -+ nds32_elf_9_pcrel_reloc -+ nds32_elf_do_9_pcrel_reloc -+ nds32_elf_hi20_reloc -+ nds32_elf_relocate_hi20 -+ nds32_elf_lo12_reloc -+ nds32_elf_sda15_reloc -+ nds32_elf_generic_reloc */ - - /* Handle the R_NDS32_9_PCREL & R_NDS32_9_PCREL_RELA reloc. */ - -@@ -2705,8 +3192,7 @@ struct nds32_reloc_map_entry - unsigned char elf_reloc_val; - }; - --static const struct nds32_reloc_map_entry nds32_reloc_map[] = --{ -+static const struct nds32_reloc_map_entry nds32_reloc_map[] = { - {BFD_RELOC_NONE, R_NDS32_NONE}, - {BFD_RELOC_16, R_NDS32_16_RELA}, - {BFD_RELOC_32, R_NDS32_32_RELA}, -@@ -2765,6 +3251,7 @@ static const struct nds32_reloc_map_entry nds32_reloc_map[] = - {BFD_RELOC_NDS32_LONGJUMP5, R_NDS32_LONGJUMP5}, - {BFD_RELOC_NDS32_LONGJUMP6, R_NDS32_LONGJUMP6}, - {BFD_RELOC_NDS32_LONGJUMP7, R_NDS32_LONGJUMP7}, -+ {BFD_RELOC_NDS32_SECURITY_16, R_NDS32_SECURITY_16}, - {BFD_RELOC_NDS32_LOADSTORE, R_NDS32_LOADSTORE}, - {BFD_RELOC_NDS32_9_FIXED, R_NDS32_9_FIXED_RELA}, - {BFD_RELOC_NDS32_15_FIXED, R_NDS32_15_FIXED_RELA}, -@@ -2822,15 +3309,52 @@ static const struct nds32_reloc_map_entry nds32_reloc_map[] = - {BFD_RELOC_NDS32_TLS_LE_LS, R_NDS32_TLS_LE_LS}, - {BFD_RELOC_NDS32_TLS_IE_HI20, R_NDS32_TLS_IE_HI20}, - {BFD_RELOC_NDS32_TLS_IE_LO12S2, R_NDS32_TLS_IE_LO12S2}, -- {BFD_RELOC_NDS32_TLS_TPOFF, R_NDS32_TLS_TPOFF}, - {BFD_RELOC_NDS32_TLS_LE_20, R_NDS32_TLS_LE_20}, - {BFD_RELOC_NDS32_TLS_LE_15S0, R_NDS32_TLS_LE_15S0}, - {BFD_RELOC_NDS32_TLS_LE_15S1, R_NDS32_TLS_LE_15S1}, - {BFD_RELOC_NDS32_TLS_LE_15S2, R_NDS32_TLS_LE_15S2}, -+ -+ {BFD_RELOC_NDS32_TLS_DESC, R_NDS32_TLS_DESC}, -+ {BFD_RELOC_NDS32_TLS_DESC_HI20, R_NDS32_TLS_DESC_HI20}, -+ {BFD_RELOC_NDS32_TLS_DESC_LO12, R_NDS32_TLS_DESC_LO12}, -+ {BFD_RELOC_NDS32_TLS_DESC_ADD, R_NDS32_TLS_DESC_ADD}, -+ {BFD_RELOC_NDS32_TLS_DESC_FUNC, R_NDS32_TLS_DESC_FUNC}, -+ {BFD_RELOC_NDS32_TLS_DESC_CALL, R_NDS32_TLS_DESC_CALL}, -+ {BFD_RELOC_NDS32_TLS_DESC_MEM, R_NDS32_TLS_DESC_MEM}, -+ {BFD_RELOC_NDS32_TLS_DESC_20, R_NDS32_TLS_DESC_20}, -+ {BFD_RELOC_NDS32_TLS_DESC_SDA17S2, R_NDS32_TLS_DESC_SDA17S2}, -+ {BFD_RELOC_NDS32_TLS_IE_LO12, R_NDS32_TLS_IE_LO12}, -+ {BFD_RELOC_NDS32_TLS_IEGP_HI20, R_NDS32_TLS_IEGP_HI20}, -+ {BFD_RELOC_NDS32_TLS_IEGP_LO12, R_NDS32_TLS_IEGP_LO12}, -+ {BFD_RELOC_NDS32_TLS_IEGP_LO12S2, R_NDS32_TLS_IEGP_LO12S2}, -+ {BFD_RELOC_NDS32_TLS_IEGP_LW, R_NDS32_TLS_IEGP_LW}, -+ -+ {BFD_RELOC_NDS32_REMOVE, R_NDS32_RELAX_REMOVE}, -+ {BFD_RELOC_NDS32_GROUP, R_NDS32_RELAX_GROUP}, -+ -+ {BFD_RELOC_NDS32_ICT_HI20, R_NDS32_ICT_HI20}, -+ {BFD_RELOC_NDS32_ICT_LO12, R_NDS32_ICT_LO12}, -+ {BFD_RELOC_NDS32_ICT_25PC, R_NDS32_ICT_25PC}, -+ {BFD_RELOC_NDS32_ICT_LO12S2, R_NDS32_ICT_LO12S2}, -+ -+ {BFD_RELOC_NDS32_LSI, R_NDS32_LSI}, - }; - - /* Patch tag. */ - -+/* Reserve space for COUNT dynamic relocations in relocation selection -+ SRELOC. */ -+ -+static inline void -+elf32_nds32_allocate_dynrelocs (struct bfd_link_info *info, asection *sreloc, -+ bfd_size_type count) -+{ -+ BFD_ASSERT (elf_hash_table (info)->dynamic_sections_created); -+ if (sreloc == NULL) -+ abort (); -+ sreloc->size += sizeof (Elf32_External_Rela) * count; -+} -+ - static reloc_howto_type * - bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, - const char *r_name) -@@ -2860,6 +3384,13 @@ bfd_elf32_bfd_reloc_type_table_lookup (enum elf_nds32_reloc_type code) - } - else - { -+ if ((size_t) (code - R_NDS32_RELAX_ENTRY) >= -+ ARRAY_SIZE (nds32_elf_relax_howto_table)) -+ { -+ int i = code; -+ i += 1; -+ } -+ - BFD_ASSERT ((size_t) (code - R_NDS32_RELAX_ENTRY) - < ARRAY_SIZE (nds32_elf_relax_howto_table)); - return &nds32_elf_relax_howto_table[code - R_NDS32_RELAX_ENTRY]; -@@ -2876,7 +3407,7 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, - { - if (nds32_reloc_map[i].bfd_reloc_val == code) - return bfd_elf32_bfd_reloc_type_table_lookup -- (nds32_reloc_map[i].elf_reloc_val); -+ (nds32_reloc_map[i].elf_reloc_val); - } - - return NULL; -@@ -2897,6 +3428,8 @@ nds32_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, - _bfd_error_handler (_("%B: invalid NDS32 reloc number: %d"), abfd, r_type); - r_type = 0; - } -+ -+ BFD_ASSERT (ELF32_R_TYPE (dst->r_info) <= R_NDS32_GNU_VTENTRY); - cache_ptr->howto = bfd_elf32_bfd_reloc_type_table_lookup (r_type); - } - -@@ -2922,29 +3455,29 @@ nds32_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) - switch (note->descsz) - { - case 0x114: -- /* Linux/NDS32 32-bit, ABI1 */ -+ /* Linux/NDS32 32-bit, ABI1 */ - -- /* pr_cursig */ -+ /* pr_cursig */ - elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); - -- /* pr_pid */ -+ /* pr_pid */ - elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24); - -- /* pr_reg */ -+ /* pr_reg */ - offset = 72; - size = 200; - break; - - case 0xfc: -- /* Linux/NDS32 32-bit */ -+ /* Linux/NDS32 32-bit */ - -- /* pr_cursig */ -+ /* pr_cursig */ - elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); - -- /* pr_pid */ -+ /* pr_pid */ - elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24); - -- /* pr_reg */ -+ /* pr_reg */ - offset = 72; - size = 176; - break; -@@ -2964,7 +3497,7 @@ nds32_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) - switch (note->descsz) - { - case 124: -- /* Linux/NDS32 */ -+ /* Linux/NDS32 */ - - /* __kernel_uid_t, __kernel_gid_t are short on NDS32 platform. */ - elf_tdata (abfd)->core->program = -@@ -3097,20 +3630,20 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info, - struct elf_nds32_link_hash_table *table; - struct bfd_link_hash_entry *h, *h2; - long unsigned int total = 0; -+ asection *first = NULL, *final = NULL, *temp; -+ bfd_vma sda_base = 0; - - h = bfd_link_hash_lookup (info->hash, "_SDA_BASE_", FALSE, FALSE, TRUE); - if (!h || (h->type != bfd_link_hash_defined && h->type != bfd_link_hash_defweak)) - { -- asection *first = NULL, *final = NULL, *temp; -- bfd_vma sda_base; - /* The first section must be 4-byte aligned to promise _SDA_BASE_ being - 4 byte-aligned. Therefore, it has to set the first section ".data" - 4 byte-aligned. */ - static const char sec_name[SDA_SECTION_NUM][10] = -- { -- ".data", ".got", ".sdata_d", ".sdata_w", ".sdata_h", ".sdata_b", -- ".sbss_b", ".sbss_h", ".sbss_w", ".sbss_d" -- }; -+ { -+ ".data", ".got", ".sdata_d", ".sdata_w", ".sdata_h", ".sdata_b", -+ ".sbss_b", ".sbss_h", ".sbss_w", ".sbss_d" -+ }; - size_t i = 0; - - if (output_bfd->sections == NULL) -@@ -3120,7 +3653,7 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info, - } - - /* Get the first and final section. */ -- while (i < sizeof (sec_name) / sizeof (sec_name [0])) -+ while (i < ARRAY_SIZE (sec_name)) - { - temp = bfd_get_section_by_name (output_bfd, sec_name[i]); - if (temp && !first && (temp->size != 0 || temp->rawsize != 0)) -@@ -3162,7 +3695,7 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info, - - /* Find the section sda_base located. */ - i = 0; -- while (i < sizeof (sec_name) / sizeof (sec_name [0])) -+ while (i < ARRAY_SIZE (sec_name)) - { - final = bfd_get_section_by_name (output_bfd, sec_name[i]); - if (final && (final->size != 0 || final->rawsize != 0) -@@ -3177,17 +3710,44 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info, - } - else - { -- /* There is not any data section in output bfd, and set _SDA_BASE_ in -- first output section. */ -- first = output_bfd->sections; -- while (first && first->size == 0 && first->rawsize == 0) -- first = first->next; -+ /* If there is not any default data section in output bfd, try to find -+ the first data section. If no data section be found, just simplily -+ choose the first output section. */ -+ temp = output_bfd->sections; -+ while (temp) -+ { -+ if (temp->flags & SEC_ALLOC -+ && (((temp->flags & SEC_DATA) -+ && ((temp->flags & SEC_READONLY) == 0)) -+ || (temp->flags & SEC_LOAD) == 0) -+ && (temp->size != 0 || temp->rawsize != 0)) -+ { -+ if (!first) -+ first = temp; -+ final = temp; -+ } -+ temp = temp->next; -+ } -+ -+ /* There is no data or bss section. */ -+ if (!first || (first->size == 0 && first->rawsize == 0)) -+ { -+ first = output_bfd->sections; -+ while (first && first->size == 0 && first->rawsize == 0) -+ first = first->next; -+ } -+ -+ /* There is no concrete section. */ - if (!first) - { - *psb = elf_gp (output_bfd); - return bfd_reloc_ok; - } -- sda_base = first->vma + first->rawsize; -+ -+ if (final && (final->vma + final->rawsize - first->vma) <= 0x4000) -+ sda_base = final->vma / 2 + final->rawsize / 2 + first->vma / 2; -+ else -+ sda_base = first->vma + 0x2000; - } - - sda_base -= first->vma; -@@ -3201,24 +3761,34 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info, - - sda_rela_sec = first; - -- table = nds32_elf_hash_table (info); -- relax_fp_as_gp = table->relax_fp_as_gp; -- if (relax_fp_as_gp) -- { -- h2 = bfd_link_hash_lookup (info->hash, FP_BASE_NAME, -- FALSE, FALSE, FALSE); -- /* Define a weak FP_BASE_NAME here to prevent the undefined symbol. -- And set FP equal to SDA_BASE to do relaxation for -- la $fp, _FP_BASE_. */ -- if (!_bfd_generic_link_add_one_symbol -- (info, output_bfd, FP_BASE_NAME, BSF_GLOBAL | BSF_WEAK, -- first, (bfd_vma) sda_base, (const char *) NULL, -- FALSE, get_elf_backend_data (output_bfd)->collect, &h2)) -- return FALSE; -- } - } - -- if (add_symbol) -+ /* Set _FP_BASE_ to _SDA_BASE_. */ -+ table = nds32_elf_hash_table (info); -+ relax_fp_as_gp = table->relax_fp_as_gp; -+ h2 = bfd_link_hash_lookup (info->hash, FP_BASE_NAME, FALSE, FALSE, FALSE); -+ /* _SDA_BASE_ is difined in linker script. */ -+ if (!first) -+ { -+ first = h->u.def.section; -+ sda_base = h->u.def.value; -+ } -+ -+ if (relax_fp_as_gp && h2 -+ && (h2->type == bfd_link_hash_undefweak -+ || h2->type == bfd_link_hash_undefined)) -+ { -+ /* Define a weak FP_BASE_NAME here to prevent the undefined symbol. -+ And set FP equal to SDA_BASE to do relaxation for -+ la $fp, _FP_BASE_. */ -+ if (!_bfd_generic_link_add_one_symbol -+ (info, output_bfd, FP_BASE_NAME, BSF_GLOBAL | BSF_WEAK, -+ first, sda_base, (const char *) NULL, -+ FALSE, get_elf_backend_data (output_bfd)->collect, &h2)) -+ return FALSE; -+ } -+ -+ if (add_symbol == TRUE) - { - if (h) - { -@@ -3275,6 +3845,8 @@ nds32_elf_link_hash_newfunc (struct bfd_hash_entry *entry, - eh = (struct elf_nds32_link_hash_entry *) ret; - eh->dyn_relocs = NULL; - eh->tls_type = GOT_UNKNOWN; -+ eh->offset_to_gp = 0; -+ eh->indirect_call = FALSE; - } - - return (struct bfd_hash_entry *) ret; -@@ -3303,22 +3875,61 @@ nds32_elf_link_hash_table_create (bfd *abfd) - return NULL; - } - -+ ret->sdynbss = NULL; -+ ret->srelbss = NULL; -+ ret->sym_ld_script = NULL; -+ - return &ret->root.root; - } - -+/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up -+ shortcuts to them in our hash table. */ -+ -+static bfd_boolean -+create_got_section (bfd *dynobj, struct bfd_link_info *info) -+{ -+ struct elf_link_hash_table *ehtab; -+ -+ if (!_bfd_elf_create_got_section (dynobj, info)) -+ return FALSE; -+ -+ ehtab = elf_hash_table (info); -+ ehtab->sgot = bfd_get_section_by_name (dynobj, ".got"); -+ ehtab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); -+ if (!ehtab->sgot || !ehtab->sgotplt) -+ abort (); -+ -+ /* _bfd_elf_create_got_section will create it for us. */ -+ ehtab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); -+ if (ehtab->srelgot == NULL -+ || !bfd_set_section_flags (dynobj, ehtab->srelgot, -+ (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS -+ | SEC_IN_MEMORY | SEC_LINKER_CREATED -+ | SEC_READONLY)) -+ || !bfd_set_section_alignment (dynobj, ehtab->srelgot, 2)) -+ return FALSE; -+ -+ return TRUE; -+} -+ - /* Create dynamic sections when linking against a dynamic object. */ - - static bfd_boolean - nds32_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) - { -+ struct elf_link_hash_table *ehtab; - struct elf_nds32_link_hash_table *htab; - flagword flags, pltflags; - register asection *s; - const struct elf_backend_data *bed; - int ptralign = 2; /* 32-bit */ -+ const char *secname; -+ char *relname; -+ flagword secflags; -+ asection *sec; - - bed = get_elf_backend_data (abfd); -- -+ ehtab = elf_hash_table (info); - htab = nds32_elf_hash_table (info); - - /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and -@@ -3335,7 +3946,7 @@ nds32_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) - pltflags |= SEC_READONLY; - - s = bfd_make_section (abfd, ".plt"); -- htab->root.splt = s; -+ ehtab->splt = s; - if (s == NULL - || !bfd_set_section_flags (abfd, s, pltflags) - || !bfd_set_section_alignment (abfd, s, bed->plt_alignment)) -@@ -3364,40 +3975,33 @@ nds32_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) - - s = bfd_make_section (abfd, - bed->default_use_rela_p ? ".rela.plt" : ".rel.plt"); -- htab->root.srelplt = s; -+ ehtab->srelplt = s; - if (s == NULL - || !bfd_set_section_flags (abfd, s, flags | SEC_READONLY) - || !bfd_set_section_alignment (abfd, s, ptralign)) - return FALSE; - -- if (htab->root.sgot == NULL && !_bfd_elf_create_got_section (abfd, info)) -+ if (ehtab->sgot == NULL && !create_got_section (abfd, info)) - return FALSE; - -- { -- const char *secname; -- char *relname; -- flagword secflags; -- asection *sec; -- -- for (sec = abfd->sections; sec; sec = sec->next) -- { -- secflags = bfd_get_section_flags (abfd, sec); -- if ((secflags & (SEC_DATA | SEC_LINKER_CREATED)) -- || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS)) -- continue; -- secname = bfd_get_section_name (abfd, sec); -- relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6); -- strcpy (relname, ".rela"); -- strcat (relname, secname); -- if (bfd_get_section_by_name (abfd, secname)) -- continue; -- s = bfd_make_section (abfd, relname); -- if (s == NULL -- || !bfd_set_section_flags (abfd, s, flags | SEC_READONLY) -- || !bfd_set_section_alignment (abfd, s, ptralign)) -- return FALSE; -- } -- } -+ for (sec = abfd->sections; sec; sec = sec->next) -+ { -+ secflags = bfd_get_section_flags (abfd, sec); -+ if ((secflags & (SEC_DATA | SEC_LINKER_CREATED)) -+ || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS)) -+ continue; -+ secname = bfd_get_section_name (abfd, sec); -+ relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6); -+ strcpy (relname, ".rela"); -+ strcat (relname, secname); -+ if (bfd_get_section_by_name (abfd, secname)) -+ continue; -+ s = bfd_make_section (abfd, relname); -+ if (s == NULL -+ || !bfd_set_section_flags (abfd, s, flags | SEC_READONLY) -+ || !bfd_set_section_alignment (abfd, s, ptralign)) -+ return FALSE; -+ } - - if (bed->want_dynbss) - { -@@ -3453,8 +4057,8 @@ nds32_elf_copy_indirect_symbol (struct bfd_link_info *info, - { - if (edir->dyn_relocs != NULL) - { -- struct elf_dyn_relocs **pp; -- struct elf_dyn_relocs *p; -+ struct elf_nds32_dyn_relocs **pp; -+ struct elf_nds32_dyn_relocs *p; - - if (ind->root.type == bfd_link_hash_indirect) - abort (); -@@ -3463,7 +4067,7 @@ nds32_elf_copy_indirect_symbol (struct bfd_link_info *info, - list. Merge any entries against the same section. */ - for (pp = &eind->dyn_relocs; (p = *pp) != NULL;) - { -- struct elf_dyn_relocs *q; -+ struct elf_nds32_dyn_relocs *q; - - for (q = edir->dyn_relocs; q != NULL; q = q->next) - if (q->sec == p->sec) -@@ -3483,25 +4087,18 @@ nds32_elf_copy_indirect_symbol (struct bfd_link_info *info, - eind->dyn_relocs = NULL; - } - -- _bfd_elf_link_hash_copy_indirect (info, dir, ind); --} -- --/* Find dynamic relocs for H that apply to read-only sections. */ -- --static asection * --readonly_dynrelocs (struct elf_link_hash_entry *h) --{ -- struct elf_dyn_relocs *p; -- -- for (p = elf32_nds32_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) -+ if (ind->root.type == bfd_link_hash_indirect) - { -- asection *s = p->sec->output_section; -- -- if (s != NULL && (s->flags & SEC_READONLY) != 0) -- return p->sec; -+ if (dir->got.refcount <= 0) -+ { -+ edir->tls_type = eind->tls_type; -+ eind->tls_type = GOT_UNKNOWN; -+ } - } -- return NULL; -+ -+ _bfd_elf_link_hash_copy_indirect (info, dir, ind); - } -+ - - /* Adjust a symbol defined by a dynamic object and referenced by a - regular object. The current definition is in some section of the -@@ -3514,6 +4111,8 @@ nds32_elf_adjust_dynamic_symbol (struct bfd_link_info *info, - struct elf_link_hash_entry *h) - { - struct elf_nds32_link_hash_table *htab; -+ struct elf_nds32_link_hash_entry *eh; -+ struct elf_nds32_dyn_relocs *p; - bfd *dynobj; - asection *s; - unsigned int power_of_two; -@@ -3558,7 +4157,8 @@ nds32_elf_adjust_dynamic_symbol (struct bfd_link_info *info, - if (h->is_weakalias) - { - struct elf_link_hash_entry *def = weakdef (h); -- BFD_ASSERT (def->root.type == bfd_link_hash_defined); -+ BFD_ASSERT (def->root.type == bfd_link_hash_defined -+ || def->root.type == bfd_link_hash_defweak); - h->root.u.def.section = def->root.u.def.section; - h->root.u.def.value = def->root.u.def.value; - return TRUE; -@@ -3580,15 +4180,24 @@ nds32_elf_adjust_dynamic_symbol (struct bfd_link_info *info, - return TRUE; - - /* If -z nocopyreloc was given, we won't generate them either. */ -- if (0 && info->nocopyreloc) -+ if (info->nocopyreloc) - { - h->non_got_ref = 0; - return TRUE; - } - -- /* If we don't find any dynamic relocs in read-only sections, then -- we'll be keeping the dynamic relocs and avoiding the copy reloc. */ -- if (0 && !readonly_dynrelocs (h)) -+ eh = (struct elf_nds32_link_hash_entry *) h; -+ for (p = eh->dyn_relocs; p != NULL; p = p->next) -+ { -+ s = p->sec->output_section; -+ if (s != NULL && (s->flags & (SEC_READONLY | SEC_HAS_CONTENTS)) != 0) -+ break; -+ } -+ -+ /* If we didn't find any dynamic relocs in sections which needs the -+ copy reloc, then we'll be keeping the dynamic relocs and avoiding -+ the copy reloc. */ -+ if (p == NULL) - { - h->non_got_ref = 0; - return TRUE; -@@ -3653,25 +4262,31 @@ static bfd_boolean - allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) - { - struct bfd_link_info *info; -+ struct elf_link_hash_table *ehtab; - struct elf_nds32_link_hash_table *htab; - struct elf_nds32_link_hash_entry *eh; -- struct elf_dyn_relocs *p; -+ struct elf_nds32_dyn_relocs *p; - - if (h->root.type == bfd_link_hash_indirect) - return TRUE; - -+ /* When warning symbols are created, they **replace** the "real" -+ entry in the hash table, thus we never get to see the real -+ symbol in a hash traversal. So look at it now. */ - if (h->root.type == bfd_link_hash_warning) -- /* When warning symbols are created, they **replace** the "real" -- entry in the hash table, thus we never get to see the real -- symbol in a hash traversal. So look at it now. */ - h = (struct elf_link_hash_entry *) h->root.u.i.link; - -+ eh = (struct elf_nds32_link_hash_entry *) h; -+ - info = (struct bfd_link_info *) inf; -+ ehtab = elf_hash_table (info); - htab = nds32_elf_hash_table (info); -+ if (htab == NULL) -+ return FALSE; - -- eh = (struct elf_nds32_link_hash_entry *) h; -- -- if (htab->root.dynamic_sections_created && h->plt.refcount > 0) -+ if ((htab->root.dynamic_sections_created || h->type == STT_GNU_IFUNC) -+ && h->plt.refcount > 0 -+ && !(bfd_link_pie (info) && h->def_regular)) - { - /* Make sure this symbol is output as a dynamic symbol. - Undefined weak syms won't yet be marked as dynamic. */ -@@ -3683,7 +4298,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) - - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)) - { -- asection *s = htab->root.splt; -+ asection *s = ehtab->splt; - - /* If this is the first .plt entry, make room for the special - first entry. */ -@@ -3708,10 +4323,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) - - /* We also need to make an entry in the .got.plt section, which - will be placed in the .got section by the linker script. */ -- htab->root.sgotplt->size += 4; -+ ehtab->sgotplt->size += 4; - - /* We also need to make an entry in the .rel.plt section. */ -- htab->root.srelplt->size += sizeof (Elf32_External_Rela); -+ ehtab->srelplt->size += sizeof (Elf32_External_Rela); -+ if (htab->tls_desc_trampoline) -+ htab->next_tls_desc_index++; - } - else - { -@@ -3727,7 +4344,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) - - if (h->got.refcount > 0) - { -- asection *s; -+ asection *sgot; - bfd_boolean dyn; - int tls_type = elf32_nds32_hash_entry (h)->tls_type; - -@@ -3739,22 +4356,44 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) - return FALSE; - } - -- s = htab->root.sgot; -- h->got.offset = s->size; -+ sgot = elf_hash_table (info)->sgot; -+ h->got.offset = sgot->size; - - if (tls_type == GOT_UNKNOWN) - abort (); -- else if (tls_type == GOT_NORMAL -- || tls_type == GOT_TLS_IE) -- /* Need a GOT slot. */ -- s->size += 4; -+ -+ /* Non-TLS symbols, and TLS_IE need one GOT slot. */ -+ if (tls_type & (GOT_NORMAL | GOT_TLS_IE | GOT_TLS_IEGP)) -+ sgot->size += 4; -+ else -+ { -+ /* TLS_DESC, TLS_GD, and TLS_LD need 2 consecutive GOT slots. */ -+ if (tls_type & GOT_TLS_DESC) -+ sgot->size += 8; -+ } - - dyn = htab->root.dynamic_sections_created; -+ - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)) -- htab->root.srelgot->size += sizeof (Elf32_External_Rela); -+ { -+ if (tls_type == GOT_TLS_DESC && htab->tls_desc_trampoline) -+ { -+ /* TLS_DESC with trampoline needs a relocation slot -+ within .rela.plt. */ -+ htab->num_tls_desc++; -+ ehtab->srelplt->size += sizeof (Elf32_External_Rela); -+ htab->tls_trampoline = -1; -+ } -+ else -+ { -+ /* other relocations, including TLS_DESC without trampoline, need -+ a relocation slot within .rela.got. */ -+ ehtab->srelgot->size += sizeof (Elf32_External_Rela); -+ } -+ } - } - else -- h->got.offset = (bfd_vma) - 1; -+ h->got.offset = (bfd_vma) -1; - - if (eh->dyn_relocs == NULL) - return TRUE; -@@ -3769,7 +4408,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) - { - if (h->def_regular && (h->forced_local || info->symbolic)) - { -- struct elf_dyn_relocs **pp; -+ struct elf_nds32_dyn_relocs **pp; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL;) - { -@@ -3810,7 +4449,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) - - eh->dyn_relocs = NULL; - -- keep:; -+keep:; - } - - /* Finally, allocate space. */ -@@ -3823,29 +4462,50 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) - return TRUE; - } - --/* Set DF_TEXTREL if we find any dynamic relocs that apply to -- read-only sections. */ -+/* Add relocation REL to the end of relocation section SRELOC. */ -+ -+static void -+elf32_nds32_add_dynreloc (bfd *output_bfd, -+ struct bfd_link_info *info ATTRIBUTE_UNUSED, -+ asection *sreloc, Elf_Internal_Rela *rel) -+{ -+ bfd_byte *loc; -+ if (sreloc == NULL) -+ abort (); -+ -+ loc = sreloc->contents; -+ loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); -+ if (sreloc->reloc_count * sizeof (Elf32_External_Rela) > sreloc->size) -+ abort (); -+ -+ bfd_elf32_swap_reloca_out (output_bfd, rel, loc); -+} -+ -+/* Find any dynamic relocs that apply to read-only sections. */ - - static bfd_boolean --maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p) -+readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) - { -- asection *sec; -+ struct elf_nds32_link_hash_entry *eh; -+ struct elf_nds32_dyn_relocs *p; - -- if (h->root.type == bfd_link_hash_indirect) -- return TRUE; -+ if (h->root.type == bfd_link_hash_warning) -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; - -- sec = readonly_dynrelocs (h); -- if (sec != NULL) -+ eh = (struct elf_nds32_link_hash_entry *) h; -+ for (p = eh->dyn_relocs; p != NULL; p = p->next) - { -- struct bfd_link_info *info = (struct bfd_link_info *) info_p; -+ asection *s = p->sec->output_section; -+ -+ if (s != NULL && (s->flags & SEC_READONLY) != 0) -+ { -+ struct bfd_link_info *info = (struct bfd_link_info *) inf; - -- info->flags |= DF_TEXTREL; -- info->callbacks->minfo -- (_("%B: dynamic relocation against `%T' in read-only section `%A'\n"), -- sec->owner, h->root.root.string, sec); -+ info->flags |= DF_TEXTREL; - -- /* Not an error, just cut short the traversal. */ -- return FALSE; -+ /* Not an error, just cut short the traversal. */ -+ return FALSE; -+ } - } - return TRUE; - } -@@ -3856,20 +4516,24 @@ static bfd_boolean - nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - struct bfd_link_info *info) - { -- struct elf_nds32_link_hash_table *htab; - bfd *dynobj; - asection *s; -+ bfd_boolean plt; - bfd_boolean relocs; - bfd *ibfd; -+ struct elf_nds32_link_hash_table *htab; - - htab = nds32_elf_hash_table (info); -- dynobj = htab->root.dynobj; -+ if (htab == NULL) -+ return FALSE; -+ -+ dynobj = elf_hash_table (info)->dynobj; - BFD_ASSERT (dynobj != NULL); - -- if (htab->root.dynamic_sections_created) -+ if (elf_hash_table (info)->dynamic_sections_created) - { - /* Set the contents of the .interp section to the interpreter. */ -- if (bfd_link_executable (info) && !info->nointerp) -+ if (bfd_link_executable (info)) - { - s = bfd_get_section_by_name (dynobj, ".interp"); - BFD_ASSERT (s != NULL); -@@ -3886,16 +4550,19 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - bfd_signed_vma *end_local_got; - bfd_size_type locsymcount; - Elf_Internal_Shdr *symtab_hdr; -- asection *srel; -+ asection *sgot; -+ char *local_tls_type; -+ unsigned long symndx; -+ bfd_vma *local_tlsdesc_gotent; - - if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) - continue; - - for (s = ibfd->sections; s != NULL; s = s->next) - { -- struct elf_dyn_relocs *p; -+ struct elf_nds32_dyn_relocs *p; - -- for (p = ((struct elf_dyn_relocs *) -+ for (p = ((struct elf_nds32_dyn_relocs *) - elf_section_data (s)->local_dynrel); - p != NULL; p = p->next) - { -@@ -3909,8 +4576,8 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - } - else if (p->count != 0) - { -- srel = elf_section_data (p->sec)->sreloc; -- srel->size += p->count * sizeof (Elf32_External_Rela); -+ asection *sreloc = elf_section_data (p->sec)->sreloc; -+ sreloc->size += p->count * sizeof (Elf32_External_Rela); - if ((p->sec->output_section->flags & SEC_READONLY) != 0) - info->flags |= DF_TEXTREL; - } -@@ -3924,19 +4591,57 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; - locsymcount = symtab_hdr->sh_info; - end_local_got = local_got + locsymcount; -- s = htab->root.sgot; -- srel = htab->root.srelgot; -- for (; local_got < end_local_got; ++local_got) -+ sgot = elf_hash_table (info)->sgot; -+ local_tls_type = elf32_nds32_local_got_tls_type (ibfd); -+ local_tlsdesc_gotent = elf32_nds32_local_tlsdesc_gotent (ibfd); -+ for (symndx = 0; local_got < end_local_got; -+ ++local_got, ++local_tls_type, ++local_tlsdesc_gotent, ++symndx) - { - if (*local_got > 0) - { -- *local_got = s->size; -- s->size += 4; -- if (bfd_link_pic (info)) -- srel->size += sizeof (Elf32_External_Rela); -+ int num_of_got_entry_needed = 0; -+ *local_got = sgot->size; -+ *local_tlsdesc_gotent = sgot->size; -+ -+ /* TLS_NORMAL, and TLS_IE need one slot in .got. */ -+ if (*local_tls_type & (GOT_NORMAL | GOT_TLS_IE | GOT_TLS_IEGP)) -+ num_of_got_entry_needed = 1; -+ /* TLS_GD, TLS_LD, and TLS_DESC need an 8-byte structure in the GOT. */ -+ else if (*local_tls_type & GOT_TLS_DESC) -+ num_of_got_entry_needed = 2; -+ -+ sgot->size += (num_of_got_entry_needed << 2); -+ -+ /* non-relax-able TLS_DESCs need a slot in .rela.plt. -+ others need a slot in .rela.got. */ -+ if (*local_tls_type == GOT_TLS_DESC) -+ { -+ if (bfd_link_pic (info)) -+ { -+ if (htab->tls_desc_trampoline) -+ { -+ htab->num_tls_desc++; -+ htab->root.srelplt->size += sizeof (Elf32_External_Rela); -+ htab->tls_trampoline = -1; -+ } -+ else -+ htab->root.srelgot->size += sizeof (Elf32_External_Rela); -+ } -+ else -+ { -+ /* TLS_DESC -> TLS_LE */ -+ } -+ } -+ else -+ { -+ htab->root.srelgot->size += sizeof (Elf32_External_Rela); -+ } - } - else -- *local_got = (bfd_vma) - 1; -+ { -+ *local_got = (bfd_vma) -1; -+ *local_tlsdesc_gotent = (bfd_vma) -1; -+ } - } - } - -@@ -3944,8 +4649,36 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - sym dynamic relocs. */ - elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (void *) info); - -+ /* For every jump slot reserved in the sgotplt, reloc_count is -+ incremented. However, when we reserve space for TLS descriptors, -+ it's not incremented, so in order to compute the space reserved -+ for them, it suffices to multiply the reloc count by the jump -+ slot size. */ -+ if (htab->tls_desc_trampoline && htab->root.srelplt) -+ htab->sgotplt_jump_table_size = elf32_nds32_compute_jump_table_size (htab); -+ -+ if (htab->tls_trampoline) -+ { -+ htab->tls_trampoline = htab->root.splt->size; -+ -+ /* If we're not using lazy TLS relocations, don't generate the -+ PLT and GOT entries they require. */ -+ if (!(info->flags & DF_BIND_NOW)) -+ { -+ htab->dt_tlsdesc_got = htab->root.sgot->size; -+ htab->root.sgot->size += 4; -+ -+ htab->dt_tlsdesc_plt = htab->root.splt->size; -+ htab->root.splt->size += 4 * ARRAY_SIZE (dl_tlsdesc_lazy_trampoline); -+ } -+ } -+ - /* We now have determined the sizes of the various dynamic sections. - Allocate memory for them. */ -+ /* The check_relocs and adjust_dynamic_symbol entry points have -+ determined the sizes of the various dynamic sections. Allocate -+ memory for them. */ -+ plt = FALSE; - relocs = FALSE; - for (s = dynobj->sections; s != NULL; s = s->next) - { -@@ -3956,18 +4689,19 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - { - /* Strip this section if we don't need it; see the - comment below. */ -+ plt = s->size != 0; - } -- else if (s == htab->root.sgot) -+ else if (s == elf_hash_table (info)->sgot) - { - got_size += s->size; - } -- else if (s == htab->root.sgotplt) -+ else if (s == elf_hash_table (info)->sgotplt) - { - got_size += s->size; - } - else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) - { -- if (s->size != 0 && s != htab->root.srelplt) -+ if (s->size != 0 && s != elf_hash_table (info)->srelplt) - relocs = TRUE; - - /* We use the reloc_count field as a counter if we need -@@ -4013,16 +4747,15 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - must add the entries now so that we get the correct size for - the .dynamic section. The DT_DEBUG entry is filled in by the - dynamic linker and used by the debugger. */ --#define add_dynamic_entry(TAG, VAL) \ -- _bfd_elf_add_dynamic_entry (info, TAG, VAL) -+#define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL) - -- if (!bfd_link_pic (info)) -+ if (bfd_link_executable (info)) - { - if (!add_dynamic_entry (DT_DEBUG, 0)) - return FALSE; - } - -- if (htab->root.splt->size != 0) -+ if (elf_hash_table (info)->splt->size != 0) - { - if (!add_dynamic_entry (DT_PLTGOT, 0) - || !add_dynamic_entry (DT_PLTRELSZ, 0) -@@ -4031,6 +4764,14 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - return FALSE; - } - -+ if (htab->tls_desc_trampoline && plt) -+ { -+ if (htab->dt_tlsdesc_plt -+ && (!add_dynamic_entry (DT_TLSDESC_PLT, 0) -+ || !add_dynamic_entry (DT_TLSDESC_GOT, 0))) -+ return FALSE; -+ } -+ - if (relocs) - { - if (!add_dynamic_entry (DT_RELA, 0) -@@ -4041,7 +4782,7 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - /* If any dynamic relocs apply to a read-only section, - then we need a DT_TEXTREL entry. */ - if ((info->flags & DF_TEXTREL) == 0) -- elf_link_hash_traverse (&htab->root, maybe_set_textrel, -+ elf_link_hash_traverse (&htab->root, readonly_dynrelocs, - (void *) info); - - if ((info->flags & DF_TEXTREL) != 0) -@@ -4076,10 +4817,11 @@ nds32_relocate_contents (reloc_howto_type *howto, bfd *input_bfd, - switch (size) - { - default: -+ case 0: -+ case 1: -+ case 8: - abort (); - break; -- case 0: -- return bfd_reloc_ok; - case 2: - x = bfd_getb16 (location); - break; -@@ -4297,9 +5039,9 @@ nds32_elf_output_symbol_hook (struct bfd_link_info *info, - else - source = input_sec->owner->filename; - -- fprintf (sym_ld_script, "\t%s = 0x%08lx;\t /* %s */\n", -+ fprintf (sym_ld_script, "\t%s = 0x%08lx;\t /* %s */\n", - h->root.root.string, -- (long) (h->root.u.def.value -+ (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset), source); - } -@@ -4340,59 +5082,252 @@ nds32_elf_output_symbol_hook (struct bfd_link_info *info, - section, which means that the addend must be adjusted - accordingly. */ - -+/* Return the base VMA address which should be subtracted from real addresses -+ when resolving @dtpoff relocation. -+ This is PT_TLS segment p_vaddr. */ -+ -+/* Return the relocation value for @tpoff relocation -+ if STT_TLS virtual address is ADDRESS. */ -+ -+/* Return the relocation value for @gottpoff relocation -+ if STT_TLS virtual address is ADDRESS. */ - static bfd_vma --dtpoff_base (struct bfd_link_info *info) -+gottpoff (struct bfd_link_info *info, bfd_vma address) - { -+ bfd_vma tp_base; -+ bfd_vma tp_offset; -+ - /* If tls_sec is NULL, we should have signalled an error already. */ - if (elf_hash_table (info)->tls_sec == NULL) - return 0; -- return elf_hash_table (info)->tls_sec->vma; --} -- --static bfd_boolean --nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, -- struct bfd_link_info * info, -- bfd * input_bfd, -- asection * input_section, -- bfd_byte * contents, -- Elf_Internal_Rela * relocs, -- Elf_Internal_Sym * local_syms, -- asection ** local_sections) --{ -- Elf_Internal_Shdr *symtab_hdr; -- struct elf_link_hash_entry **sym_hashes; -- Elf_Internal_Rela *rel, *relend; -- bfd_boolean ret = TRUE; /* Assume success. */ -- int align = 0; -- bfd_reloc_status_type r; -- const char *errmsg = NULL; -- bfd_vma gp; -- struct elf_nds32_link_hash_table *htab; -- bfd *dynobj; -- bfd_vma *local_got_offsets; -- asection *sgot, *splt, *sreloc; -- bfd_vma high_address; -- struct elf_nds32_link_hash_table *table; -- int eliminate_gc_relocs; -- bfd_vma fpbase_addr; - -- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; -- sym_hashes = elf_sym_hashes (input_bfd); -- htab = nds32_elf_hash_table (info); -- high_address = bfd_get_section_limit (input_bfd, input_section); -+ tp_base = elf_hash_table (info)->tls_sec->vma; -+ tp_offset = address - tp_base; - -- dynobj = htab->root.dynobj; -- local_got_offsets = elf_local_got_offsets (input_bfd); -+ return tp_offset; -+} - -- sgot = htab->root.sgot; -- splt = htab->root.splt; -- sreloc = NULL; -+/* Move all SECURITY_16 to the final one for each instruction. */ - -- rel = relocs; -+static void -+nds32_elf_crc_adjust_reloc (Elf_Internal_Rela *relocs, -+ Elf_Internal_Rela *relend) -+{ -+ Elf_Internal_Rela *rel, *crc_rel = NULL; -+ Elf_Internal_Rela rel_temp; -+ -+ for (rel = relocs; rel < relend; rel++) -+ { -+ if (crc_rel && crc_rel->r_offset == rel->r_offset) -+ { -+ memcpy (&rel_temp, rel, sizeof (Elf_Internal_Rela)); -+ memcpy (rel, crc_rel, sizeof (Elf_Internal_Rela)); -+ memcpy (crc_rel, &rel_temp, sizeof (Elf_Internal_Rela)); -+ crc_rel = rel; -+ } -+ else if (ELF32_R_TYPE (rel->r_info) == R_NDS32_SECURITY_16) -+ { -+ crc_rel = rel; -+ continue; -+ } -+ } -+} -+ -+static bfd_boolean -+patch_tls_desc_to_ie (bfd_byte *contents, Elf_Internal_Rela *rel, bfd *ibfd) -+{ -+ /* TLS_GD/TLS_LD model #1 -+ 46 00 00 00 sethi $r0,#0x0 -+ 58 00 00 00 ori $r0,$r0,#0x0 -+ 40 00 74 00 add $r0,$r0,$gp -+ 04 10 00 00 lwi $r1,[$r0+#0x0] -+ 4b e0 04 01 jral $lp,$r1 */ -+ -+ /* TLS_GD/TLS_LD model #2 -+ 46 00 00 00 sethi $r0,#0x0 -+ 58 00 00 00 ori $r0,$r0,#0x0 -+ 38 10 74 02 lw $r1,[$r0+($gp<<#0x0)] <= TODO: not necessary $r1 register allocation -+ 40 00 74 00 add $r0,$r0,$gp -+ 4b e0 04 01 jral $lp,$r1 */ -+ -+ /* TLS_IE model (non-PIC) -+ 46 00 00 00 sethi $r0,#0x0 -+ 04 00 00 00 lwi $r0,[$r0+#0x0] -+ 38 00 64 02 lw $r0,[$r0+($r25<<#0x0)] */ -+ -+ /* TLS_IE model (PIC) -+ 46 00 00 00 sethi $r0,#0x0 -+ 58 00 00 00 ori $r0,$r0,#0x0 -+ 38 00 74 02 lw $r0,[$r0+($gp<<#0x0)] -+ 38 00 64 02 lw $r0,[$r0+($r25<<#0x0)] */ -+ -+ /* TLS_GD_TO_IE model -+ 46 00 00 00 sethi $r0,#0x0 -+ 58 00 00 00 ori $r0,$r0,#0x0 -+ 40 00 74 00 add $r0,$rM,$gp -+ 04 00 00 01 lwi $r0,[$r0+#0x4] -+ 40 00 64 00 add $r0,$r0,$r25 */ -+ -+ bfd_boolean rz = FALSE; -+ -+ typedef struct -+ { -+ uint32_t opcode; -+ uint32_t mask; -+ } pat_t; -+ -+ uint32_t patch[3] = -+ { -+ 0x40007400, /* add $r0,$rM,$gp */ -+ 0x04000001, /* lwi $r0,[$r0+#0x4] */ -+ 0x40006400, /* add $r0,$r0,$r25 */ -+ }; -+ -+ pat_t mode0[3] = -+ { -+ { 0x40000000, 0xfe0003ff }, -+ { 0x04000000, 0xfe000000 }, -+ { 0x4be00001, 0xffff83ff }, -+ }; -+ -+ pat_t mode1[3] = -+ { -+ { 0x38007402, 0xfe007fff }, -+ { 0x40007400, 0xfe007fff }, -+ { 0x4be00001, 0xffff83ff }, -+ }; -+ -+ unsigned char *p = contents + rel->r_offset; -+ -+ uint32_t insn; -+ uint32_t regidx = 0; -+ insn = bfd_getb32 (p); -+ if (INSN_SETHI == (0xfe0fffffu & insn)) -+ { -+ regidx = 0x1f & (insn >> 20); -+ p += 4; -+ } -+ -+ insn = bfd_getb32 (p); -+ if (INSN_ORI == (0xfe007fffu & insn)) -+ { -+ regidx = 0x1f & (insn >> 20); -+ p += 4; -+ } -+ -+ if (patch[2] == bfd_getb32 (p + 8)) /* character instruction */ -+ { -+ /* already patched? */ -+ if ((patch[0] == (0xfff07fffu & bfd_getb32 (p + 0))) && -+ (patch[1] == bfd_getb32 (p + 4))) -+ rz = TRUE; -+ } -+ else if (mode0[0].opcode == (mode0[0].mask & bfd_getb32 (p + 0))) -+ { -+ if ((mode0[1].opcode == (mode0[1].mask & bfd_getb32 (p + 4))) && -+ (mode0[2].opcode == (mode0[2].mask & bfd_getb32 (p + 8)))) -+ { -+ bfd_putb32 (patch[0] | (regidx << 15), p + 0); -+ bfd_putb32 (patch[1], p + 4); -+ bfd_putb32 (patch[2], p + 8); -+ rz = TRUE; -+ } -+ } -+ else if (mode1[0].opcode == (mode1[0].mask & bfd_getb32 (p + 0))) -+ { -+ if ((mode1[1].opcode == (mode1[1].mask & bfd_getb32 (p + 4))) && -+ (mode1[2].opcode == (mode1[2].mask & bfd_getb32 (p + 8)))) -+ { -+ bfd_putb32 (patch[0] | (regidx << 15), p + 0); -+ bfd_putb32 (patch[1], p + 4); -+ bfd_putb32 (patch[2], p + 8); -+ rz = TRUE; -+ } -+ } -+ -+ if (!rz) -+ { -+ printf ("%s: %s @ 0x%08x\n", __func__, ibfd->filename, -+ (int) rel->r_offset); -+ BFD_ASSERT(0); /* unsupported pattern */ -+ } -+ -+ return rz; -+} -+ -+static enum elf_nds32_tls_type -+get_tls_type (enum elf_nds32_reloc_type r_type, struct elf_link_hash_entry *h); -+ -+static unsigned int -+ones32 (register unsigned int x) -+{ -+ /* 32-bit recursive reduction using SWAR... -+ but first step is mapping 2-bit values -+ into sum of 2 1-bit values in sneaky way. */ -+ x -= ((x >> 1) & 0x55555555); -+ x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); -+ x = (((x >> 4) + x) & 0x0f0f0f0f); -+ x += (x >> 8); -+ x += (x >> 16); -+ return (x & 0x0000003f); -+} -+ -+static unsigned int -+fls (register unsigned int x) -+{ -+ return ffs (x & (-x)); -+} -+ -+#define nds32_elf_local_tlsdesc_gotent(bfd) \ -+ (elf_nds32_tdata (bfd)->local_tlsdesc_gotent) -+ -+static bfd_boolean -+nds32_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info, bfd *input_bfd, -+ asection *input_section, bfd_byte *contents, -+ Elf_Internal_Rela *relocs, -+ Elf_Internal_Sym *local_syms, -+ asection **local_sections) -+{ -+ Elf_Internal_Shdr *symtab_hdr; -+ struct elf_link_hash_entry **sym_hashes; -+ Elf_Internal_Rela *rel, *relend; -+ bfd_boolean ret = TRUE; /* Assume success. */ -+ int align = 0; -+ bfd_reloc_status_type r; -+ const char *errmsg = NULL; -+ bfd_vma gp; -+ struct elf_link_hash_table *ehtab; -+ struct elf_nds32_link_hash_table *htab; -+ bfd *dynobj; -+ bfd_vma *local_got_offsets; -+ asection *sgot, *splt, *sreloc; -+ bfd_vma high_address; -+ struct elf_nds32_link_hash_table *table; -+ int eliminate_gc_relocs; -+ bfd_vma fpbase_addr; -+ Elf_Internal_Rela *crc_rel = NULL; -+ -+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; -+ sym_hashes = elf_sym_hashes (input_bfd); -+ ehtab = elf_hash_table (info); -+ htab = nds32_elf_hash_table (info); -+ high_address = bfd_get_section_limit (input_bfd, input_section); -+ -+ dynobj = htab->root.dynobj; -+ local_got_offsets = elf_local_got_offsets (input_bfd); -+ -+ sgot = ehtab->sgot; -+ splt = ehtab->splt; -+ sreloc = NULL; -+ -+ rel = relocs; - relend = relocs + input_section->reloc_count; - - table = nds32_elf_hash_table (info); - eliminate_gc_relocs = table->eliminate_gc_relocs; -+ -+ /* explain _SDA_BASE_ */ - /* By this time, we can adjust the value of _SDA_BASE_. */ - if ((!bfd_link_relocatable (info))) - { -@@ -4402,40 +5337,37 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - return FALSE; - } - -- if (is_ITB_BASE_set == 0) -- { -- /* Set the _ITB_BASE_. */ -- if (!nds32_elf_ex9_itb_base (info)) -- { -- _bfd_error_handler (_("%B: error: Cannot set _ITB_BASE_"), -- output_bfd); -- bfd_set_error (bfd_error_bad_value); -- } -- } -- -- if (table->target_optimize & NDS32_RELAX_JUMP_IFC_ON) -- if (!nds32_elf_ifc_reloc ()) -- _bfd_error_handler (_("error: IFC relocation error.")); -+#ifdef NDS32_LINUX_TOOLCHAIN -+ /* Do TLS model conversion once at first. */ -+ nds32_elf_unify_tls_model (input_bfd, input_section, contents, info); -+#endif - -- /* Relocation for .ex9.itable. */ -- if (table->target_optimize & NDS32_RELAX_EX9_ON -- || (table->ex9_import_file && table->update_ex9_table)) -- nds32_elf_ex9_reloc_jmp (info); -+ if (indirect_call_table.count > 0) -+ nds32_elf_ict_relocate (output_bfd, info); - - /* Use gp as fp to prevent truncated fit. Because in relaxation time - the fp value is set as gp, and it has be reverted for instruction - setting fp. */ - fpbase_addr = elf_gp (output_bfd); - -+ /* Move all SECURITY_16 to the final one for each instruction. */ -+ nds32_elf_crc_adjust_reloc (relocs, relend); -+ -+ /* Deal with (dynamic) relocations. */ - for (rel = relocs; rel < relend; rel++) - { - enum elf_nds32_reloc_type r_type; - reloc_howto_type *howto = NULL; - unsigned long r_symndx; - struct elf_link_hash_entry *h = NULL; -+ struct bfd_link_hash_entry *h2; - Elf_Internal_Sym *sym = NULL; - asection *sec; - bfd_vma relocation; -+ struct elf_nds32_ict_hash_entry *entry; -+ bfd_vma relocation_sym = 0xdeadbeef; -+ Elf_Internal_Rela *lorel; -+ bfd_vma off; - - /* We can't modify r_addend here as elf_link_input_bfd has an assert to - ensure it's zero (we use REL relocs, not RELA). Therefore this -@@ -4463,12 +5395,17 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - || r_type == R_NDS32_RELA_GNU_VTINHERIT - || (r_type >= R_NDS32_INSN16 && r_type <= R_NDS32_25_FIXED_RELA) - || r_type == R_NDS32_DATA -- || r_type == R_NDS32_TRAN -- || (r_type >= R_NDS32_LONGCALL4 && r_type <= R_NDS32_LONGJUMP7)) -+ || r_type == R_NDS32_TRAN) - continue; - -- /* If we enter the fp-as-gp region. Resolve the address -- of best fp-base. */ -+ /* Save security beginning. */ -+ if (r_type == R_NDS32_SECURITY_16 && crc_rel == NULL) -+ { -+ crc_rel = rel; -+ continue; -+ } -+ -+ /* If we enter the fp-as-gp region. Resolve the address of best fp-base. */ - if (ELF32_R_TYPE (rel->r_info) == R_NDS32_RELAX_REGION_BEGIN - && (rel->r_addend & R_NDS32_RELAX_REGION_OMIT_FP_FLAG)) - { -@@ -4485,9 +5422,13 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - fpbase_addr = elf_gp (output_bfd); - } - -- if (((r_type >= R_NDS32_DWARF2_OP1_RELA -- && r_type <= R_NDS32_DWARF2_LEB_RELA) -- || r_type >= R_NDS32_RELAX_ENTRY) && !bfd_link_relocatable (info)) -+ /* Skip the relocations used for relaxation. */ -+ /* Fix ticket-11832, we have to update LONGCALL and LONGJUMP -+ relocations when generating the relocatable files. */ -+ if (!bfd_link_relocatable (info) -+ && (r_type >= R_NDS32_RELAX_ENTRY -+ || (r_type >= R_NDS32_LONGCALL4 -+ && r_type <= R_NDS32_LONGJUMP7))) - continue; - - howto = bfd_elf32_bfd_reloc_type_table_lookup (r_type); -@@ -4506,10 +5447,26 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - - relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); - addend = rel->r_addend; -+ -+ /* keep symbol location for static TLS_IE GOT entry */ -+ relocation_sym = relocation; -+ if (bfd_link_relocatable (info)) -+ { -+ /* This is a relocatable link. We don't have to change -+ anything, unless the reloc is against a section symbol, -+ in which case we have to adjust according to where the -+ section symbol winds up in the output section. */ -+ if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) -+ rel->r_addend += sec->output_offset + sym->st_value; -+ -+ continue; -+ } - } - else - { - /* External symbol. */ -+ if (bfd_link_relocatable (info)) -+ continue; - bfd_boolean warned, ignored, unresolved_reloc; - int symndx = r_symndx - symtab_hdr->sh_info; - -@@ -4518,10 +5475,27 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - relocation, unresolved_reloc, warned, - ignored); - -+ /* keep symbol location for static TLS_IE GOT entry */ -+ relocation_sym = relocation; -+ - /* la $fp, _FP_BASE_ is per-function (region). - Handle it specially. */ - switch ((int) r_type) - { -+ case R_NDS32_HI20_RELA: -+ case R_NDS32_LO12S0_RELA: -+ if (strcmp (elf_sym_hashes (input_bfd)[symndx]->root.root.string, -+ FP_BASE_NAME) == 0) -+ { -+ if (!bfd_link_pie (info)) -+ { -+ _bfd_error_handler -+ ("%pB: warning: _FP_BASE_ setting insns relaxation failed.", -+ input_bfd); -+ } -+ relocation = fpbase_addr; -+ break; -+ } - case R_NDS32_SDA19S0_RELA: - case R_NDS32_SDA15S0_RELA: - case R_NDS32_20_RELA: -@@ -4532,19 +5506,6 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - break; - } - } -- -- } -- -- if (bfd_link_relocatable (info)) -- { -- /* This is a relocatable link. We don't have to change -- anything, unless the reloc is against a section symbol, -- in which case we have to adjust according to where the -- section symbol winds up in the output section. */ -- if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) -- rel->r_addend += sec->output_offset + sym->st_value; -- -- continue; - } - - /* Sanity check the address. */ -@@ -4554,16 +5515,14 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - goto check_reloc; - } - -- if ((r_type >= R_NDS32_DWARF2_OP1_RELA -- && r_type <= R_NDS32_DWARF2_LEB_RELA) -- || r_type >= R_NDS32_RELAX_ENTRY) -+ if (r_type >= R_NDS32_RELAX_ENTRY) - continue; - - switch ((int) r_type) - { - case R_NDS32_GOTOFF: - /* Relocation is relative to the start of the global offset -- table (for ld24 rx, #uimm24), e.g. access at label+addend -+ table (for ld24 rx, #uimm24), e.g. access at label + addend - - ld24 rx. #label@GOTOFF + addend - sub rx, r12. */ -@@ -4605,12 +5564,18 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - case R_NDS32_PLT_GOTREL_LO15: - case R_NDS32_PLT_GOTREL_LO19: - case R_NDS32_PLT_GOTREL_LO20: -- if (h == NULL || h->forced_local || h->plt.offset == (bfd_vma) - 1) -+ if (h == NULL -+ || h->forced_local -+ || h->plt.offset == (bfd_vma) -1 -+ || (bfd_link_pie (info) && h->def_regular)) - { -+ /* TODO: find better checking to optimize PIE PLT relocations. */ - /* We didn't make a PLT entry for this symbol. This - happens when statically linking PIC code, or when - using -Bsymbolic. */ -- relocation -= elf_gp (output_bfd); -+ if (h) -+ h->plt.offset = (bfd_vma) -1; /* cancel PLT trampoline. */ -+ relocation -= elf_gp(output_bfd); - break; - } - -@@ -4661,21 +5626,18 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - - case R_NDS32_GOTPC_HI20: - case R_NDS32_GOTPC_LO12: -- { -- /* .got(_GLOBAL_OFFSET_TABLE_) - pc relocation -- bl .+4 -- seth rx,#high(_GLOBAL_OFFSET_TABLE_) -- or3 rx,rx,#low(_GLOBAL_OFFSET_TABLE_ +4) -- or -- bl .+4 -- seth rx,#shigh(_GLOBAL_OFFSET_TABLE_) -- add3 rx,rx,#low(_GLOBAL_OFFSET_TABLE_ +4) -- */ -- relocation = elf_gp (output_bfd); -- relocation -= (input_section->output_section->vma -- + input_section->output_offset + rel->r_offset); -- break; -- } -+ /* .got(_GLOBAL_OFFSET_TABLE_) - pc relocation -+ bl .+4 -+ seth rx,#high(_GLOBAL_OFFSET_TABLE_) -+ or3 rx,rx,#low(_GLOBAL_OFFSET_TABLE_ +4) -+ or -+ bl .+4 -+ seth rx,#shigh(_GLOBAL_OFFSET_TABLE_) -+ add3 rx,rx,#low(_GLOBAL_OFFSET_TABLE_ +4) */ -+ relocation = elf_gp (output_bfd); -+ relocation -= (input_section->output_section->vma -+ + input_section->output_offset + rel->r_offset); -+ break; - - case R_NDS32_GOT20: - /* Fall through. */ -@@ -4687,17 +5649,14 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - offset table. */ - BFD_ASSERT (sgot != NULL); - -- if (h != NULL) -+ if (h != NULL) /* External symbol */ - { - bfd_boolean dyn; -- bfd_vma off; - - off = h->got.offset; - BFD_ASSERT (off != (bfd_vma) - 1); - dyn = htab->root.dynamic_sections_created; -- if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, -- bfd_link_pic (info), -- h) -+ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) - || (bfd_link_pic (info) - && (info->symbolic - || h->dynindx == -1 -@@ -4707,28 +5666,27 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - -Bsymbolic link and the symbol is defined - locally, or the symbol was forced to be local - because of a version file. We must initialize -- this entry in the global offset table. Since the -+ this entry in the global offset table. Since the - offset must always be a multiple of 4, we use the - least significant bit to record whether we have - initialized it already. - - When doing a dynamic link, we create a .rela.got -- relocation entry to initialize the value. This -+ relocation entry to initialize the value. This - is done in the finish_dynamic_symbol routine. */ -- if ((off & 1) != 0) -+ if ((off & 1) != 0) /* clear LSB */ - off &= ~1; - else - { - bfd_put_32 (output_bfd, relocation, sgot->contents + off); -- h->got.offset |= 1; -+ h->got.offset |= 1; /* mark initialized */ - } - } - relocation = sgot->output_section->vma + sgot->output_offset + off -- - elf_gp (output_bfd); -+ - elf_gp (output_bfd); - } -- else -+ else /* Local symbol */ - { -- bfd_vma off; - bfd_byte *loc; - - BFD_ASSERT (local_got_offsets != NULL -@@ -4736,10 +5694,10 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - - off = local_got_offsets[r_symndx]; - -- /* The offset must always be a multiple of 4. We use -+ /* The offset must always be a multiple of 4. We use - the least significant bit to record whether we have - already processed this entry. */ -- if ((off & 1) != 0) -+ if ((off & 1) != 0) /* clear LSB */ - off &= ~1; - else - { -@@ -4752,7 +5710,7 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - - /* We need to generate a R_NDS32_RELATIVE reloc - for the dynamic linker. */ -- srelgot = htab->root.srelgot; -+ srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); - BFD_ASSERT (srelgot != NULL); - - outrel.r_offset = (elf_gp (output_bfd) -@@ -4768,11 +5726,57 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - local_got_offsets[r_symndx] |= 1; - } - relocation = sgot->output_section->vma + sgot->output_offset + off -- - elf_gp (output_bfd); -+ - elf_gp (output_bfd); - } - - break; - -+ case R_NDS32_25_PCREL_RELA: -+ case R_NDS32_HI20_RELA: -+ case R_NDS32_LO12S0_RELA: -+ case R_NDS32_LO12S2_RELA: -+ /* Merge normal and indirect call functions. */ -+ if (!ignore_indirect_call && h -+ && elf32_nds32_hash_entry (h)->indirect_call) -+ { -+ if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) -+ { -+ _bfd_error_handler -+ (_("%pB: Error: there are mixed indirect call function in" -+ " ICT large model\'%s\'\n"), -+ input_bfd, h->root.root.string); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ else -+ _bfd_error_handler -+ (_("%pB: Warning: there are mixed indirect call function" -+ " \'%s\'\n"), input_bfd, h->root.root.string); -+ -+ entry = (struct elf_nds32_ict_hash_entry*) -+ bfd_hash_lookup (&indirect_call_table, h->root.root.string, -+ FALSE, FALSE); -+ if (!entry) -+ { -+ _bfd_error_handler -+ (_("%pB %pA: internal error indirect call relocation " -+ "0x%lx without hash.\n"), -+ input_bfd, sec, rel->r_offset); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ -+ h2 = bfd_link_hash_lookup (info->hash, -+ "_INDIRECT_CALL_TABLE_BASE_", -+ FALSE, FALSE, FALSE); -+ relocation = ((h2->u.def.value -+ + h2->u.def.section->output_section->vma -+ + h2->u.def.section->output_offset) -+ + (entry->order * 4)); -+ break; -+ } -+ -+ /* Fall through. */ - case R_NDS32_16_RELA: - case R_NDS32_20_RELA: - case R_NDS32_5_RELA: -@@ -4782,14 +5786,10 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - case R_NDS32_10_UPCREL_RELA: - case R_NDS32_15_PCREL_RELA: - case R_NDS32_17_PCREL_RELA: -- case R_NDS32_25_PCREL_RELA: -- case R_NDS32_HI20_RELA: - case R_NDS32_LO12S3_RELA: -- case R_NDS32_LO12S2_RELA: - case R_NDS32_LO12S2_DP_RELA: - case R_NDS32_LO12S2_SP_RELA: - case R_NDS32_LO12S1_RELA: -- case R_NDS32_LO12S0_RELA: - case R_NDS32_LO12S0_ORI_RELA: - if (bfd_link_pic (info) && r_symndx != 0 - && (input_section->flags & SEC_ALLOC) != 0 -@@ -4863,15 +5863,37 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - become local. */ - if (h == NULL - || ((info->symbolic || h->dynindx == -1) -- && h->def_regular)) -+ && h->def_regular) -+ || (bfd_link_pie (info) && h->def_regular)) - { - relocate = TRUE; - outrel.r_info = ELF32_R_INFO (0, R_NDS32_RELATIVE); - outrel.r_addend = relocation + rel->r_addend; -+ if (h) -+ { -+ h->plt.offset = (bfd_vma) -1; /* cancel PLT trampoline. */ -+ -+ BFD_ASSERT (sgot != NULL); -+ /* If we did not allocate got entry for the symbol, we can not -+ fill the nonexistent got entry. */ -+ if (h->got.offset != (bfd_vma) -1 && (h->got.offset & 1) == 0) -+ { -+ bfd_put_32 (output_bfd, outrel.r_addend, -+ sgot->contents + h->got.offset); -+ } -+ } - } - else - { -- BFD_ASSERT (h->dynindx != -1); -+ if (h->dynindx == -1) -+ { -+ _bfd_error_handler -+ (_("%pB: relocation %s against `%s' can not be used when" -+ "making a shared object; recompile with -fPIC"), -+ input_bfd, nds32_elf_howto_table[r_type].name, h->root.root.string); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } - outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); - outrel.r_addend = rel->r_addend; - } -@@ -4895,8 +5917,8 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - if (bfd_link_pic (info)) - { - _bfd_error_handler -- (_("%B: warning: cannot deal R_NDS32_25_ABS_RELA in shared " -- "mode."), input_bfd); -+ (_("%s: warning: cannot deal R_NDS32_25_ABS_RELA in shared mode."), -+ bfd_get_filename (input_bfd)); - return FALSE; - } - break; -@@ -4908,123 +5930,115 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - goto check_reloc; - - case R_NDS32_HI20: -+ /* We allow an arbitrary number of HI20 relocs before the -+ LO12 reloc. This permits GCC to emit the HI and LO relocs -+ itself. */ -+ for (lorel = rel + 1; -+ (lorel < relend -+ && ELF32_R_TYPE (lorel->r_info) == R_NDS32_HI20); lorel++) -+ continue; -+ if (lorel < relend -+ && (ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S3 -+ || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S2 -+ || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S1 -+ || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S0)) - { -- Elf_Internal_Rela *lorel; -- -- /* We allow an arbitrary number of HI20 relocs before the -- LO12 reloc. This permits gcc to emit the HI and LO relocs -- itself. */ -- for (lorel = rel + 1; -- (lorel < relend -- && ELF32_R_TYPE (lorel->r_info) == R_NDS32_HI20); lorel++) -- continue; -- if (lorel < relend -- && (ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S3 -- || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S2 -- || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S1 -- || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S0)) -- { -- nds32_elf_relocate_hi20 (input_bfd, r_type, rel, lorel, -- contents, relocation + addend); -- r = bfd_reloc_ok; -- } -- else -- r = _bfd_final_link_relocate (howto, input_bfd, input_section, -- contents, offset, relocation, -- addend); -+ nds32_elf_relocate_hi20 (input_bfd, r_type, rel, lorel, -+ contents, relocation + addend); -+ r = bfd_reloc_ok; - } -+ else -+ r = _bfd_final_link_relocate (howto, input_bfd, input_section, -+ contents, offset, relocation, -+ addend); - - goto check_reloc; - - case R_NDS32_GOT17S2_RELA: - case R_NDS32_GOT15S2_RELA: -+ BFD_ASSERT (sgot != NULL); -+ -+ if (h != NULL) - { -- bfd_vma off; -+ bfd_boolean dyn; - -- BFD_ASSERT (sgot != NULL); -+ off = h->got.offset; -+ BFD_ASSERT (off != (bfd_vma) - 1); - -- if (h != NULL) -+ dyn = htab->root.dynamic_sections_created; -+ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL -+ (dyn, bfd_link_pic (info), h) || (bfd_link_pic (info) -+ && (info->symbolic -+ || h->dynindx == -1 -+ || h->forced_local) -+ && h->def_regular)) - { -- bfd_boolean dyn; -- -- off = h->got.offset; -- BFD_ASSERT (off != (bfd_vma) - 1); -- -- dyn = htab->root.dynamic_sections_created; -- if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL -- (dyn, bfd_link_pic (info), h) -- || (bfd_link_pic (info) -- && (info->symbolic -- || h->dynindx == -1 -- || h->forced_local) -- && h->def_regular)) -+ /* This is actually a static link, or it is a -+ -Bsymbolic link and the symbol is defined -+ locally, or the symbol was forced to be local -+ because of a version file. We must initialize -+ this entry in the global offset table. Since the -+ offset must always be a multiple of 4, we use the -+ least significant bit to record whether we have -+ initialized it already. -+ -+ When doing a dynamic link, we create a .rela.got -+ relocation entry to initialize the value. This -+ is done in the finish_dynamic_symbol routine. */ -+ if ((off & 1) != 0) -+ off &= ~1; -+ else - { -- /* This is actually a static link, or it is a -- -Bsymbolic link and the symbol is defined -- locally, or the symbol was forced to be local -- because of a version file. We must initialize -- this entry in the global offset table. Since the -- offset must always be a multiple of 4, we use the -- least significant bit to record whether we have -- initialized it already. -- -- When doing a dynamic link, we create a .rela.got -- relocation entry to initialize the value. This -- is done in the finish_dynamic_symbol routine. */ -- if ((off & 1) != 0) -- off &= ~1; -- else -- { -- bfd_put_32 (output_bfd, relocation, -- sgot->contents + off); -- h->got.offset |= 1; -- } -+ bfd_put_32 (output_bfd, relocation, -+ sgot->contents + off); -+ h->got.offset |= 1; - } - } -- else -- { -- bfd_byte *loc; -+ } -+ else -+ { -+ bfd_byte *loc; - -- BFD_ASSERT (local_got_offsets != NULL -- && local_got_offsets[r_symndx] != (bfd_vma) - 1); -+ BFD_ASSERT (local_got_offsets != NULL -+ && local_got_offsets[r_symndx] != (bfd_vma) - 1); - -- off = local_got_offsets[r_symndx]; -+ off = local_got_offsets[r_symndx]; - -- /* The offset must always be a multiple of 4. We use -- the least significant bit to record whether we have -- already processed this entry. */ -- if ((off & 1) != 0) -- off &= ~1; -- else -+ /* The offset must always be a multiple of 4. We use -+ the least significant bit to record whether we have -+ already processed this entry. */ -+ if ((off & 1) != 0) -+ off &= ~1; -+ else -+ { -+ bfd_put_32 (output_bfd, relocation, sgot->contents + off); -+ -+ if (bfd_link_pic (info)) - { -- bfd_put_32 (output_bfd, relocation, sgot->contents + off); -+ asection *srelgot; -+ Elf_Internal_Rela outrel; - -- if (bfd_link_pic (info)) -- { -- asection *srelgot; -- Elf_Internal_Rela outrel; -- -- /* We need to generate a R_NDS32_RELATIVE reloc -- for the dynamic linker. */ -- srelgot = htab->root.srelgot; -- BFD_ASSERT (srelgot != NULL); -- -- outrel.r_offset = (elf_gp (output_bfd) -- + sgot->output_offset + off); -- outrel.r_info = ELF32_R_INFO (0, R_NDS32_RELATIVE); -- outrel.r_addend = relocation; -- loc = srelgot->contents; -- loc += -- srelgot->reloc_count * sizeof (Elf32_External_Rela); -- bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); -- ++srelgot->reloc_count; -- } -- local_got_offsets[r_symndx] |= 1; -+ /* We need to generate a R_NDS32_RELATIVE reloc -+ for the dynamic linker. */ -+ srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); -+ BFD_ASSERT (srelgot != NULL); -+ -+ outrel.r_offset = (elf_gp (output_bfd) -+ + sgot->output_offset + off); -+ outrel.r_info = ELF32_R_INFO (0, R_NDS32_RELATIVE); -+ outrel.r_addend = relocation; -+ loc = srelgot->contents; -+ loc += -+ srelgot->reloc_count * sizeof (Elf32_External_Rela); -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); -+ ++srelgot->reloc_count; - } -+ local_got_offsets[r_symndx] |= 1; - } -- relocation = sgot->output_section->vma + sgot->output_offset + off -- - elf_gp (output_bfd); - } -+ relocation = sgot->output_section->vma + sgot->output_offset + off -+ - elf_gp (output_bfd); -+ - if (relocation & align) - { - /* Incorrect alignment. */ -@@ -5060,50 +6074,48 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - case R_NDS32_SDA19S0_RELA: - case R_NDS32_SDA15S0_RELA: - case R_NDS32_SDA15S0: -- { -- align = 0x0; -+ align = 0x0; - handle_sda: -- BFD_ASSERT (sec != NULL); -+ BFD_ASSERT (sec != NULL); - -- /* If the symbol is in the abs section, the out_bfd will be null. -- This happens when the relocation has a symbol@GOTOFF. */ -- r = nds32_elf_final_sda_base (output_bfd, info, &gp, FALSE); -- if (r != bfd_reloc_ok) -- { -- _bfd_error_handler -- (_("%B: warning: relocate SDA_BASE failed."), input_bfd); -- ret = FALSE; -- goto check_reloc; -- } -+ /* If the symbol is in the abs section, the out_bfd will be null. -+ This happens when the relocation has a symbol@GOTOFF. */ -+ r = nds32_elf_final_sda_base (output_bfd, info, &gp, FALSE); -+ if (r != bfd_reloc_ok) -+ { -+ _bfd_error_handler -+ (_("%B: warning: relocate SDA_BASE failed."), input_bfd); -+ ret = FALSE; -+ goto check_reloc; -+ } - -- /* At this point `relocation' contains the object's -- address. */ -- if (r_type == R_NDS32_SDA_FP7U2_RELA) -- { -- relocation -= fpbase_addr; -- } -- else -- relocation -= gp; -- /* Now it contains the offset from _SDA_BASE_. */ -+ /* At this point `relocation' contains the object's -+ address. */ -+ if (r_type == R_NDS32_SDA_FP7U2_RELA) -+ { -+ relocation -= fpbase_addr; -+ } -+ else -+ relocation -= gp; -+ /* Now it contains the offset from _SDA_BASE_. */ - -- /* Make sure alignment is correct. */ -+ /* Make sure alignment is correct. */ - -- if (relocation & align) -- { -- /* Incorrect alignment. */ -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%B(%A): warning: unaligned small data access of type %d."), -- input_bfd, input_section, r_type); -- ret = FALSE; -- goto check_reloc; -- } -+ if (relocation & align) -+ { -+ /* Incorrect alignment. */ -+ _bfd_error_handler -+ (_("%B(%A): warning: unaligned small data access of type %d."), -+ input_bfd, input_section, r_type); -+ ret = FALSE; -+ goto check_reloc; - } - - break; - case R_NDS32_17IFC_PCREL_RELA: - case R_NDS32_10IFCU_PCREL_RELA: -- /* do nothing */ -+ ifc_flag = TRUE; -+ /* do nothing */ - break; - - case R_NDS32_TLS_LE_HI20: -@@ -5112,28 +6124,38 @@ handle_sda: - case R_NDS32_TLS_LE_15S0: - case R_NDS32_TLS_LE_15S1: - case R_NDS32_TLS_LE_15S2: -+ /* TODO: we do not have garbage collection for got entries. -+ IE to LE may have one empty entry, and DESC to LE may -+ have two. */ - if (elf_hash_table (info)->tls_sec != NULL) - relocation -= (elf_hash_table (info)->tls_sec->vma + TP_OFFSET); - break; - case R_NDS32_TLS_IE_HI20: - case R_NDS32_TLS_IE_LO12S2: -+ case R_NDS32_TLS_DESC_HI20: -+ case R_NDS32_TLS_DESC_LO12: -+ case R_NDS32_TLS_IE_LO12: -+ case R_NDS32_TLS_IEGP_HI20: -+ case R_NDS32_TLS_IEGP_LO12: -+ case R_NDS32_TLS_IEGP_LO12S2: - { - /* Relocation is to the entry for this symbol in the global - offset table. */ -- unsigned int tls_type; -+ enum elf_nds32_tls_type tls_type, org_tls_type, eff_tls_type; - asection *srelgot; - Elf_Internal_Rela outrel; -- bfd_vma off; - bfd_byte *loc; - int indx = 0; - -+ eff_tls_type = org_tls_type = get_tls_type (r_type, h); -+ - BFD_ASSERT (sgot != NULL); - if (h != NULL) - { - bfd_boolean dyn; - - off = h->got.offset; -- BFD_ASSERT (off != (bfd_vma) - 1); -+ BFD_ASSERT (off != (bfd_vma) -1); - dyn = htab->root.dynamic_sections_created; - tls_type = ((struct elf_nds32_link_hash_entry *) h)->tls_type; - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) -@@ -5143,64 +6165,184 @@ handle_sda: - } - else - { -- /* Never happen currently. */ - BFD_ASSERT (local_got_offsets != NULL - && local_got_offsets[r_symndx] != (bfd_vma) - 1); - - off = local_got_offsets[r_symndx]; -- - tls_type = elf32_nds32_local_got_tls_type (input_bfd)[r_symndx]; - } -+ - relocation = sgot->output_section->vma + sgot->output_offset + off; - -- if (r_type == R_NDS32_TLS_IE_LO12S2) -- break; -+ if (1 < ones32 (tls_type)) -+ { -+ eff_tls_type = 1 << (fls (tls_type) - 1); -+ /* TLS model shall be handled in nds32_elf_unify_tls_model () */ -+ -+ /* TLS model X -> LE is not implement yet! -+ * workaround here! */ -+ if (eff_tls_type == GOT_TLS_LE) -+ { -+ eff_tls_type = 1 << (fls (tls_type ^ eff_tls_type) - 1); -+ } -+ } - - /* The offset must always be a multiple of 4. We use - the least significant bit to record whether we have - already processed this entry. */ -- if ((off & 1) != 0) -- off &= ~1; -+ bfd_boolean need_relocs = FALSE; -+ srelgot = ehtab->srelgot; -+ if ((bfd_link_pic (info) || indx != 0) -+ && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT -+ || h->root.type != bfd_link_hash_undefweak)) -+ { -+ need_relocs = TRUE; -+ BFD_ASSERT (srelgot != NULL); -+ } -+ -+ if (off & 1) -+ { -+ off &= ~1; -+ relocation &= ~1; -+ -+ if (eff_tls_type & GOT_TLS_DESC) -+ { -+ relocation -= elf_gp (output_bfd); -+ if ((R_NDS32_TLS_DESC_HI20 == r_type) && (!need_relocs)) -+ { -+ /* TLS model shall be converted */ -+ BFD_ASSERT(0); -+ } -+ } -+ else if (eff_tls_type & GOT_TLS_IEGP) -+ { -+ relocation -= elf_gp (output_bfd); -+ } -+ } - else - { -- bfd_boolean need_relocs = FALSE; -- srelgot = htab->root.srelgot; -- if ((bfd_link_pic (info) || indx != 0) -- && (h == NULL -- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT -- || h->root.type != bfd_link_hash_undefweak)) -+ if ((eff_tls_type & GOT_TLS_LE) && (tls_type ^ eff_tls_type)) - { -- need_relocs = TRUE; -- BFD_ASSERT (srelgot != NULL); -+ /* TLS model workaround shall be applied */ -+ BFD_ASSERT(0); - } -- if (tls_type & GOT_TLS_IE) -+ else if (eff_tls_type & (GOT_TLS_IE | GOT_TLS_IEGP)) - { -+ if (eff_tls_type & GOT_TLS_IEGP) -+ relocation -= elf_gp(output_bfd); -+ - if (need_relocs) - { -- if (h->dynindx == 0) -- outrel.r_addend = relocation - dtpoff_base (info); -+ if (indx == 0) -+ outrel.r_addend = gottpoff (info, relocation_sym); - else - outrel.r_addend = 0; - outrel.r_offset = (sgot->output_section->vma -- + sgot->output_offset -- + off); -- outrel.r_info = -- ELF32_R_INFO (h->dynindx, R_NDS32_TLS_TPOFF); -- -- loc = srelgot->contents; -- loc += -- srelgot->reloc_count * sizeof (Elf32_External_Rela); -- bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); -- ++srelgot->reloc_count; -+ + sgot->output_offset + off); -+ outrel.r_info = ELF32_R_INFO (indx, R_NDS32_TLS_TPOFF); -+ -+ elf32_nds32_add_dynreloc (output_bfd, info, srelgot, -+ &outrel); - } - else -- bfd_put_32 (output_bfd, h->root.u.def.value - TP_OFFSET, -- sgot->contents + off); -+ { -+ bfd_put_32 (output_bfd, gottpoff (info, relocation_sym), -+ sgot->contents + off); -+ } -+ } -+ else if (eff_tls_type & GOT_TLS_DESC) -+ { -+ relocation -= elf_gp (output_bfd); -+ if (need_relocs) -+ { -+ if (indx == 0) -+ outrel.r_addend = gottpoff (info, relocation_sym); -+ else -+ outrel.r_addend = 0; -+ outrel.r_offset = (sgot->output_section->vma -+ + sgot->output_offset + off); -+ outrel.r_info = ELF32_R_INFO (indx, R_NDS32_TLS_DESC); -+ -+ if (htab->tls_desc_trampoline) -+ { -+ asection *srelplt; -+ srelplt = ehtab->srelplt; -+ loc = srelplt->contents; -+ loc += htab->next_tls_desc_index++ * sizeof (Elf32_External_Rela); -+ BFD_ASSERT (loc + sizeof (Elf32_External_Rela) -+ <= srelplt->contents + srelplt->size); -+ -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); -+ } -+ else -+ { -+ loc = srelgot->contents; -+ loc += srelgot->reloc_count * sizeof (Elf32_External_Rela); -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); -+ ++srelgot->reloc_count; -+ } -+ } -+ else -+ { -+ /* feed me! */ -+ bfd_put_32 (output_bfd, 0xdeadbeef, -+ sgot->contents + off); -+ bfd_put_32 (output_bfd, gottpoff (info, relocation_sym), -+ sgot->contents + off + 4); -+ patch_tls_desc_to_ie (contents, rel, input_bfd); -+ BFD_ASSERT(0); -+ } -+ } -+ else -+ { -+ /* TLS model workaround shall be applied */ -+ BFD_ASSERT(0); - } -+ -+ if (h != NULL) -+ h->got.offset |= 1; -+ else -+ local_got_offsets[r_symndx] |= 1; - } - } -- break; -+ break; -+ -+ case R_NDS32_SECURITY_16: -+ relocation = 0; -+ crc_rel->r_addend = NDS32_SECURITY_NONE; -+ r = nds32_elf_final_link_relocate (howto, input_bfd, -+ input_section, contents, -+ crc_rel->r_offset, relocation, -+ crc_rel->r_addend); -+ crc_rel = NULL; -+ goto check_reloc; -+ break; -+ /* DON'T fall through. */ -+ case R_NDS32_ICT_HI20: -+ case R_NDS32_ICT_LO12: -+ case R_NDS32_ICT_25PC: -+ case R_NDS32_ICT_LO12S2: -+ entry = (struct elf_nds32_ict_hash_entry*) -+ bfd_hash_lookup (&indirect_call_table, h->root.root.string, -+ FALSE, FALSE); -+ if (!entry) -+ { -+ _bfd_error_handler -+ (_("%pB %pA: internal error indirect call relocation " -+ "0x%lx without hash.\n"), -+ input_bfd, sec, rel->r_offset); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } - -+ h2 = bfd_link_hash_lookup (info->hash, -+ "_INDIRECT_CALL_TABLE_BASE_", -+ FALSE, FALSE, FALSE); -+ relocation = ((h2->u.def.value -+ + h2->u.def.section->output_section->vma -+ + h2->u.def.section->output_offset) -+ + (entry->order * 4)); -+ break; - /* DON'T fall through. */ - - default: -@@ -5275,6 +6417,12 @@ handle_sda: - case R_NDS32_TLS_LE_15S0: - case R_NDS32_TLS_LE_15S1: - case R_NDS32_TLS_LE_15S2: -+ case R_NDS32_TLS_DESC_HI20: -+ case R_NDS32_TLS_DESC_LO12: -+ case R_NDS32_TLS_IE_LO12: -+ case R_NDS32_TLS_IEGP_HI20: -+ case R_NDS32_TLS_IEGP_LO12: -+ case R_NDS32_TLS_IEGP_LO12S2: - /* Instruction related relocs must handle endian properly. */ - /* NOTE: PIC IS NOT HANDLE YET; DO IT LATER. */ - r = nds32_elf_final_link_relocate (howto, input_bfd, -@@ -5283,6 +6431,15 @@ handle_sda: - rel->r_addend); - break; - -+ case R_NDS32_ICT_HI20: -+ case R_NDS32_ICT_LO12: -+ case R_NDS32_ICT_25PC: -+ case R_NDS32_ICT_LO12S2: -+ r = nds32_elf_final_link_relocate (howto, input_bfd, input_section, -+ contents, rel->r_offset, -+ relocation, 0); -+ break; -+ - default: - /* All other relocs can use default handler. */ - r = _bfd_final_link_relocate (howto, input_bfd, input_section, -@@ -5314,6 +6471,17 @@ check_reloc: - switch (r) - { - case bfd_reloc_overflow: -+ if (r_type == R_NDS32_17IFC_PCREL_RELA) -+ { -+ _bfd_error_handler -+ (_("\n%pB: (%pA+0x%x): The IFC optimization range exceeded.\n" -+ "Please turn off the IFC optimization (-mno-ifc) when " -+ "compiling the file %s.\n"), -+ input_bfd, sec, (int) rel->r_offset, -+ h->root.u.def.section->owner->filename); -+ bfd_set_error (bfd_error_bad_value); -+ } -+ - (*info->callbacks->reloc_overflow) - (info, (h ? &h->root : NULL), name, howto->name, - (bfd_vma) 0, input_bfd, input_section, offset); -@@ -5340,14 +6508,18 @@ check_reloc: - errmsg = _("internal error: unknown error"); - /* Fall through. */ - -- common_error: -- (*info->callbacks->warning) (info, errmsg, name, input_bfd, -- input_section, offset); -+common_error: -+ (*info->callbacks->warning) -+ (info, errmsg, name, input_bfd, input_section, offset); - break; - } - } - } - -+ /* Resotre header size to avoid overflow load. */ -+ if (elf_nds32_tdata (input_bfd)->hdr_size != 0) -+ symtab_hdr->sh_size = elf_nds32_tdata (input_bfd)->hdr_size; -+ - return ret; - } - -@@ -5356,12 +6528,15 @@ check_reloc: - - static bfd_boolean - nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, -- struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) -+ struct elf_link_hash_entry *h, -+ Elf_Internal_Sym *sym) - { -- struct elf_nds32_link_hash_table *htab; -+ struct elf_link_hash_table *ehtab; -+ struct elf_nds32_link_hash_entry *hent; - bfd_byte *loc; - -- htab = nds32_elf_hash_table (info); -+ ehtab = elf_hash_table (info); -+ hent = (struct elf_nds32_link_hash_entry *) h; - - if (h->plt.offset != (bfd_vma) - 1) - { -@@ -5379,9 +6554,9 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, - - BFD_ASSERT (h->dynindx != -1); - -- splt = htab->root.splt; -- sgot = htab->root.sgotplt; -- srela = htab->root.srelplt; -+ splt = ehtab->splt; -+ sgot = ehtab->sgotplt; -+ srela = ehtab->srelplt; - BFD_ASSERT (splt != NULL && sgot != NULL && srela != NULL); - - /* Get the index in the procedure linkage table which -@@ -5417,7 +6592,7 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, - bfd_putb32 (insn, splt->contents + h->plt.offset + 12); - - insn = PLT_ENTRY_WORD4 -- + (((unsigned int) ((-(h->plt.offset + 16)) >> 1)) & 0xffffff); -+ + (((unsigned int) ((-(h->plt.offset + 16)) >> 1)) & 0xffffff); - bfd_putb32 (insn, splt->contents + h->plt.offset + 16); - local_plt_offset = 12; - } -@@ -5428,9 +6603,8 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, - long offset; - - /* FIXME, sda_base is 65536, it will damage opcode. */ -- /* insn = PLT_PIC_ENTRY_WORD0 + (((got_offset - sda_base) >> 2) & 0x7fff); */ - offset = sgot->output_section->vma + sgot->output_offset + got_offset -- - elf_gp (output_bfd); -+ - elf_gp (output_bfd); - insn = PLT_PIC_ENTRY_WORD0 + ((offset >> 12) & 0xfffff); - bfd_putb32 (insn, splt->contents + h->plt.offset); - -@@ -5479,18 +6653,18 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, - } - } - -- if (h->got.offset != (bfd_vma) - 1) -+ if ((h->got.offset != (bfd_vma) -1) && (hent->tls_type == GOT_NORMAL)) - { - asection *sgot; -- asection *srela; -+ asection *srelagot; - Elf_Internal_Rela rela; - - /* This symbol has an entry in the global offset table. - Set it up. */ - -- sgot = htab->root.sgot; -- srela = htab->root.srelgot; -- BFD_ASSERT (sgot != NULL && srela != NULL); -+ sgot = ehtab->sgot; -+ srelagot = ehtab->srelgot; -+ BFD_ASSERT (sgot != NULL && srelagot != NULL); - - rela.r_offset = (sgot->output_section->vma - + sgot->output_offset + (h->got.offset & ~1)); -@@ -5500,14 +6674,24 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, - the symbol was forced to be local because of a version file. - The entry in the global offset table will already have been - initialized in the relocate_section function. */ -- if (bfd_link_pic (info) -- && (info->symbolic -- || h->dynindx == -1 || h->forced_local) && h->def_regular) -+ if ((bfd_link_pic (info) -+ && (info->symbolic || h->dynindx == -1 || h->forced_local) -+ && h->def_regular) -+ || (bfd_link_pie (info) && h->def_regular)) - { - rela.r_info = ELF32_R_INFO (0, R_NDS32_RELATIVE); - rela.r_addend = (h->root.u.def.value -- + h->root.u.def.section->output_section->vma -- + h->root.u.def.section->output_offset); -+ + h->root.u.def.section->output_section->vma -+ + h->root.u.def.section->output_offset); -+ -+ /* FIXME: cancel PLT trampoline, too late ?? */ -+ /* h->plt.offset = (bfd_vma) -1; */ -+ -+ if ((h->got.offset & 1) == 0) -+ { -+ bfd_put_32 (output_bfd, rela.r_addend, -+ sgot->contents + h->got.offset); -+ } - } - else - { -@@ -5518,10 +6702,11 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, - rela.r_addend = 0; - } - -- loc = srela->contents; -- loc += srela->reloc_count * sizeof (Elf32_External_Rela); -+ loc = srelagot->contents; -+ loc += srelagot->reloc_count * sizeof (Elf32_External_Rela); - bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -- ++srela->reloc_count; -+ ++srelagot->reloc_count; -+ BFD_ASSERT (loc < (srelagot->contents + srelagot->size)); - } - - if (h->needs_copy) -@@ -5563,23 +6748,32 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, - static bfd_boolean - nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) - { -- struct elf_nds32_link_hash_table *htab; - bfd *dynobj; - asection *sdyn; -- asection *sgot; -+ asection *sgotplt; -+ struct elf_link_hash_table *ehtab; -+ struct elf_nds32_link_hash_table *htab; - -+ ehtab = elf_hash_table (info); - htab = nds32_elf_hash_table (info); -- dynobj = htab->root.dynobj; -+ if (htab == NULL) -+ return FALSE; -+ -+ dynobj = elf_hash_table (info)->dynobj; - -- sgot = htab->root.sgotplt; -+ sgotplt = ehtab->sgotplt; -+ /* A broken linker script might have discarded the dynamic sections. -+ Catch this here so that we do not seg-fault later on. */ -+ if (sgotplt != NULL && bfd_is_abs_section (sgotplt->output_section)) -+ return FALSE; - sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); - -- if (htab->root.dynamic_sections_created) -+ if (elf_hash_table (info)->dynamic_sections_created) - { - asection *splt; - Elf32_External_Dyn *dyncon, *dynconend; - -- BFD_ASSERT (sgot != NULL && sdyn != NULL); -+ BFD_ASSERT (sgotplt != NULL && sdyn != NULL); - - dyncon = (Elf32_External_Dyn *) sdyn->contents; - dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); -@@ -5597,25 +6791,60 @@ nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) - break; - - case DT_PLTGOT: -- s = htab->root.sgotplt; -+ /* name = ".got"; */ -+ s = ehtab->sgot->output_section; - goto get_vma; - case DT_JMPREL: -- s = htab->root.srelplt; -- get_vma: -- dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; -+ s = ehtab->srelplt->output_section; -+get_vma: -+ BFD_ASSERT (s != NULL); -+ dyn.d_un.d_ptr = s->vma; - bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); - break; - - case DT_PLTRELSZ: -- s = htab->root.srelplt; -+ s = ehtab->srelplt->output_section; -+ BFD_ASSERT (s != NULL); - dyn.d_un.d_val = s->size; - bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); - break; -+ -+ case DT_RELASZ: -+ /* My reading of the SVR4 ABI indicates that the -+ procedure linkage table relocs (DT_JMPREL) should be -+ included in the overall relocs (DT_RELA). This is -+ what Solaris does. However, UnixWare can not handle -+ that case. Therefore, we override the DT_RELASZ entry -+ here to make it not include the JMPREL relocs. Since -+ the linker script arranges for .rela.plt to follow all -+ other relocation sections, we don't have to worry -+ about changing the DT_RELA entry. */ -+ if (ehtab->srelplt != NULL) -+ { -+ s = ehtab->srelplt->output_section; -+ dyn.d_un.d_val -= s->size; -+ } -+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); -+ break; -+ -+ case DT_TLSDESC_PLT: -+ s = htab->root.splt; -+ dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset -+ + htab->dt_tlsdesc_plt); -+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); -+ break; -+ -+ case DT_TLSDESC_GOT: -+ s = htab->root.sgot; -+ dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset -+ + htab->dt_tlsdesc_got); -+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); -+ break; - } - } - - /* Fill in the first entry in the procedure linkage table. */ -- splt = htab->root.splt; -+ splt = ehtab->splt; - if (splt && splt->size > 0) - { - if (bfd_link_pic (info)) -@@ -5624,13 +6853,11 @@ nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) - long offset; - - /* FIXME, sda_base is 65536, it will damage opcode. */ -- /* insn = PLT_PIC_ENTRY_WORD0 + (((got_offset - sda_base) >> 2) & 0x7fff); */ -- offset = sgot->output_section->vma + sgot->output_offset + 4 -- - elf_gp (output_bfd); -+ offset = sgotplt->output_section->vma + sgotplt->output_offset + 4 -+ - elf_gp (output_bfd); - insn = PLT0_PIC_ENTRY_WORD0 | ((offset >> 12) & 0xfffff); - bfd_putb32 (insn, splt->contents); - -- /* insn = PLT0_PIC_ENTRY_WORD0 | (((8 - sda_base) >> 2) & 0x7fff) ; */ - /* here has a typo? */ - insn = PLT0_PIC_ENTRY_WORD1 | (offset & 0xfff); - bfd_putb32 (insn, splt->contents + 4); -@@ -5652,8 +6879,8 @@ nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) - unsigned long insn; - unsigned long addr; - -- /* addr = .got + 4 */ -- addr = sgot->output_section->vma + sgot->output_offset + 4; -+ /* addr = .got + 4 */ -+ addr = sgotplt->output_section->vma + sgotplt->output_offset + 4; - insn = PLT0_ENTRY_WORD0 | ((addr >> 12) & 0xfffff); - bfd_putb32 (insn, splt->contents); - -@@ -5673,21 +6900,48 @@ nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) - elf_section_data (splt->output_section)->this_hdr.sh_entsize = - PLT_ENTRY_SIZE; - } -+ -+ if (htab->dt_tlsdesc_plt) -+ { -+ /* Calculate addresses. */ -+ asection *sgot = sgot = ehtab->sgot; -+ bfd_vma pltgot = sgotplt->output_section->vma -+ + sgotplt->output_offset; -+ bfd_vma tlsdesc_got = sgot->output_section->vma + sgot->output_offset -+ + htab->dt_tlsdesc_got; -+ -+ /* Get GP offset. */ -+ pltgot -= elf_gp (output_bfd) - 4; /* PLTGOT[1] */ -+ tlsdesc_got -= elf_gp (output_bfd); -+ -+ /* Do relocation. */ -+ dl_tlsdesc_lazy_trampoline[0] += ((1 << 20) - 1) & (tlsdesc_got >> 12); -+ dl_tlsdesc_lazy_trampoline[1] += 0xfff & tlsdesc_got; -+ dl_tlsdesc_lazy_trampoline[4] += ((1 << 20) - 1) & (pltgot >> 12); -+ dl_tlsdesc_lazy_trampoline[5] += 0xfff & pltgot; -+ -+ /* TODO: relaxation. */ -+ -+ /* Insert .plt. */ -+ nds32_put_trampoline (splt->contents + htab->dt_tlsdesc_plt, -+ dl_tlsdesc_lazy_trampoline, -+ ARRAY_SIZE (dl_tlsdesc_lazy_trampoline)); -+ } - } - - /* Fill in the first three entries in the global offset table. */ -- if (sgot && sgot->size > 0) -+ if (sgotplt && sgotplt->size > 0) - { - if (sdyn == NULL) -- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); -+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents); - else - bfd_put_32 (output_bfd, - sdyn->output_section->vma + sdyn->output_offset, -- sgot->contents); -- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4); -- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8); -+ sgotplt->contents); -+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 4); -+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 8); - -- elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; -+ elf_section_data (sgotplt->output_section)->this_hdr.sh_entsize = 4; - } - - return TRUE; -@@ -5738,6 +6992,7 @@ nds32_elf_final_write_processing (bfd *abfd, - { - unsigned long val; - static unsigned int cur_mach = 0; -+ unsigned int i; - - if (bfd_mach_n1 != bfd_get_mach (abfd)) - { -@@ -5771,6 +7026,36 @@ nds32_elf_final_write_processing (bfd *abfd, - - elf_elfheader (abfd)->e_flags &= ~EF_NDS_ARCH; - elf_elfheader (abfd)->e_flags |= val; -+ if (ifc_flag) -+ elf_elfheader (abfd)->e_flags |= E_NDS32_HAS_IFC_INST ; -+ -+ if (ict_file) -+ { -+ fprintf (ict_file, ".section " NDS32_ICT_SECTION ", \"ax\"\n"); -+ if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) -+ fprintf (ict_file, ".ict_model\tlarge\n"); -+ else -+ fprintf (ict_file, ".ict_model\tsmall\n"); -+ fprintf (ict_file, ".globl _INDIRECT_CALL_TABLE_BASE_\n" -+ "_INDIRECT_CALL_TABLE_BASE_:\n"); -+ /* Output rom patch entries. */ -+ indirect_call_table.frozen = 1; -+ for (i = 0; i < indirect_call_table.size; i++) -+ { -+ struct bfd_hash_entry *p; -+ struct elf_nds32_ict_hash_entry *entry; -+ -+ for (p = indirect_call_table.table[i]; p != NULL; p = p->next) -+ { -+ entry = (struct elf_nds32_ict_hash_entry *) p; -+ if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) -+ fprintf (ict_file, "\t.word\t%s\n", entry->root.string); -+ else -+ fprintf (ict_file, "\tj\t%s\n", entry->root.string); -+ } -+ } -+ indirect_call_table.frozen = 0; -+ } - } - - /* Function to keep NDS32 specific file flags. */ -@@ -5856,13 +7141,27 @@ nds32_check_vec_size (bfd *ibfd) - return TRUE; - } - -+static unsigned int -+nds32_elf_force_to_set_output_abi (char *str) -+{ -+ flagword flags; -+ -+ if (strcmp (str, "AABI") == 0) -+ flags = E_NDS_ABI_AABI; -+ else if (strcmp (str, "V2FP+") == 0) -+ flags = E_NDS_ABI_V2FP_PLUS; -+ else -+ flags = 0; -+ -+ return flags; -+} -+ - /* Merge backend specific data from an object file to the output - object file when linking. */ - - static bfd_boolean - nds32_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) - { -- bfd *obfd = info->output_bfd; - flagword out_flags; - flagword in_flags; - flagword out_16regs; -@@ -5873,6 +7172,7 @@ nds32_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) - flagword in_version; - flagword out_fpu_config; - flagword in_fpu_config; -+ bfd *obfd = info->output_bfd; - - /* TODO: Revise to use object-attributes instead. */ - if (!nds32_check_vec_size (ibfd)) -@@ -5891,135 +7191,171 @@ nds32_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) - return FALSE; - } - -- in_version = elf_elfheader (ibfd)->e_flags & EF_NDS32_ELF_VERSION; -- if (in_version == E_NDS32_ELF_VER_1_2) -- { -- _bfd_error_handler -- (_("%B: warning: Older version of object file encountered, " -- "Please recompile with current tool chain."), ibfd); -- } -- -- /* We may need to merge V1 and V2 arch object files to V2. */ -- if ((elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) -- != (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)) -+ /* [Bug 11585] [Ticket 7067] -B option in objcopy cannot work as expected. -+ e_flags = 0 shall be treat as generic one. -+ no checking, and no merging. */ -+ if (elf_elfheader (ibfd)->e_flags) - { -- /* Need to convert version. */ -- if ((elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) -- == E_NDS_ARCH_STAR_RESERVED) -+ in_version = elf_elfheader (ibfd)->e_flags & EF_NDS32_ELF_VERSION; -+ if (in_version == E_NDS32_ELF_VER_1_2) - { -- elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; -+ _bfd_error_handler -+ (_("%pB: warning: Older version of object file encountered, " -+ "Please recompile with current tool chain."), ibfd); - } -- else if ((elf_elfheader (obfd)->e_flags & EF_NDS_ARCH) == E_NDS_ARCH_STAR_V0_9 -- || (elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) -- > (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)) -+ -+ if (output_abi != NULL) - { -- elf_elfheader (obfd)->e_flags = -- convert_e_flags (elf_elfheader (obfd)->e_flags, -- (elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH)); -+ elf_elfheader (ibfd)->e_flags &= ~(EF_NDS_ABI); -+ elf_elfheader (ibfd)->e_flags -+ |= nds32_elf_force_to_set_output_abi (output_abi); -+ elf_elfheader (obfd)->e_flags &= ~(EF_NDS_ABI); -+ elf_elfheader (obfd)->e_flags -+ |= nds32_elf_force_to_set_output_abi (output_abi); - } -- else -+ -+ /* We may need to merge V1 and V2 arch object files to V2. */ -+ if ((elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) -+ != (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)) - { -- elf_elfheader (ibfd)->e_flags = -- convert_e_flags (elf_elfheader (ibfd)->e_flags, -- (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)); -- } -- } -- -- /* Extract some flags. */ -- in_flags = elf_elfheader (ibfd)->e_flags -- & (~(E_NDS32_HAS_REDUCED_REGS | EF_NDS32_ELF_VERSION -- | E_NDS32_HAS_NO_MAC_INST | E_NDS32_FPU_REG_CONF)); -- -- /* The following flags need special treatment. */ -- in_16regs = elf_elfheader (ibfd)->e_flags & E_NDS32_HAS_REDUCED_REGS; -- in_no_mac = elf_elfheader (ibfd)->e_flags & E_NDS32_HAS_NO_MAC_INST; -- in_fpu_config = elf_elfheader (ibfd)->e_flags & E_NDS32_FPU_REG_CONF; -- -- /* Extract some flags. */ -- out_flags = elf_elfheader (obfd)->e_flags -- & (~(E_NDS32_HAS_REDUCED_REGS | EF_NDS32_ELF_VERSION -- | E_NDS32_HAS_NO_MAC_INST | E_NDS32_FPU_REG_CONF)); -- -- /* The following flags need special treatment. */ -- out_16regs = elf_elfheader (obfd)->e_flags & E_NDS32_HAS_REDUCED_REGS; -- out_no_mac = elf_elfheader (obfd)->e_flags & E_NDS32_HAS_NO_MAC_INST; -- out_fpu_config = elf_elfheader (obfd)->e_flags & E_NDS32_FPU_REG_CONF; -- out_version = elf_elfheader (obfd)->e_flags & EF_NDS32_ELF_VERSION; -- if (!elf_flags_init (obfd)) -- { -- /* If the input is the default architecture then do not -- bother setting the flags for the output architecture, -- instead allow future merges to do this. If no future -- merges ever set these flags then they will retain their -- unitialised values, which surprise surprise, correspond -- to the default values. */ -- if (bfd_get_arch_info (ibfd)->the_default) -- return TRUE; -+ /* Need to convert version. */ -+ if ((elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) -+ == E_NDS_ARCH_STAR_RESERVED) -+ { -+ elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; -+ } -+ else if ((elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) -+ == E_NDS_ARCH_STAR_V3_M -+ && (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH) -+ == E_NDS_ARCH_STAR_V3_0) -+ { -+ elf_elfheader (ibfd)->e_flags = -+ (elf_elfheader (ibfd)->e_flags & (~EF_NDS_ARCH)) -+ | E_NDS_ARCH_STAR_V3_0; -+ } -+ else if ((elf_elfheader (obfd)->e_flags & EF_NDS_ARCH) -+ == E_NDS_ARCH_STAR_V0_9 -+ || (elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) -+ > (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)) -+ { -+ elf_elfheader (obfd)->e_flags = -+ convert_e_flags (elf_elfheader (obfd)->e_flags, -+ (elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH)); -+ } -+ else -+ { -+ elf_elfheader (ibfd)->e_flags = -+ convert_e_flags (elf_elfheader (ibfd)->e_flags, -+ (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)); -+ } -+ } - -- elf_flags_init (obfd) = TRUE; -- elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; -+ /* Extract some flags. */ -+ in_flags = elf_elfheader (ibfd)->e_flags -+ & (~(E_NDS32_HAS_REDUCED_REGS | EF_NDS32_ELF_VERSION -+ | E_NDS32_HAS_NO_MAC_INST | E_NDS32_FPU_REG_CONF)); -+ -+ /* The following flags need special treatment. */ -+ in_16regs = elf_elfheader (ibfd)->e_flags & E_NDS32_HAS_REDUCED_REGS; -+ in_no_mac = elf_elfheader (ibfd)->e_flags & E_NDS32_HAS_NO_MAC_INST; -+ in_fpu_config = elf_elfheader (ibfd)->e_flags & E_NDS32_FPU_REG_CONF; -+ -+ /* Extract some flags. */ -+ out_flags = elf_elfheader (obfd)->e_flags -+ & (~(E_NDS32_HAS_REDUCED_REGS | EF_NDS32_ELF_VERSION -+ | E_NDS32_HAS_NO_MAC_INST | E_NDS32_FPU_REG_CONF)); -+ -+ /* The following flags need special treatment. */ -+ out_16regs = elf_elfheader (obfd)->e_flags & E_NDS32_HAS_REDUCED_REGS; -+ out_no_mac = elf_elfheader (obfd)->e_flags & E_NDS32_HAS_NO_MAC_INST; -+ out_fpu_config = elf_elfheader (obfd)->e_flags & E_NDS32_FPU_REG_CONF; -+ out_version = elf_elfheader (obfd)->e_flags & EF_NDS32_ELF_VERSION; -+ if (!elf_flags_init (obfd)) -+ { -+ /* If the input is the default architecture then do not -+ bother setting the flags for the output architecture, -+ instead allow future merges to do this. If no future -+ merges ever set these flags then they will retain their -+ unitialised values, which surprise surprise, correspond -+ to the default values. */ -+ if (bfd_get_arch_info (ibfd)->the_default) -+ return TRUE; - -- if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) -- && bfd_get_arch_info (obfd)->the_default) -- { -- return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), -- bfd_get_mach (ibfd)); -+ elf_flags_init (obfd) = TRUE; -+ elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; -+ -+ if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) -+ && bfd_get_arch_info (obfd)->the_default) -+ { -+ return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), -+ bfd_get_mach (ibfd)); -+ } -+ -+ return TRUE; - } - -- return TRUE; -- } -+ /* Check flag compatibility. */ -+ if ((in_flags & EF_NDS_ABI) != (out_flags & EF_NDS_ABI)) -+ { -+ asection *section = NULL; -+ bfd_byte *contents = NULL; -+ section = bfd_get_section_by_name (ibfd, ".note.v2abi_compatible"); -+ if (section) -+ bfd_get_full_section_contents (ibfd, section, &contents); - -- /* Check flag compatibility. */ -- if ((in_flags & EF_NDS_ABI) != (out_flags & EF_NDS_ABI)) -- { -- _bfd_error_handler -- (_("%B: error: ABI mismatch with previous modules."), ibfd); -+ /* Only enable v3f/v3s toolchain to link v2abi compatible objects. */ -+ if ((contents == NULL) -+ || bfd_getb32 (contents) != 1 -+ || (out_flags & EF_NDS_ABI) != E_NDS_ABI_V2FP_PLUS) -+ { -+ _bfd_error_handler -+ (_("%pB: error: ABI mismatch with previous modules."), ibfd); - -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -- } -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ } - -- if ((in_flags & EF_NDS_ARCH) != (out_flags & EF_NDS_ARCH)) -- { -- if (((in_flags & EF_NDS_ARCH) != E_N1_ARCH)) -+ if ((in_flags & EF_NDS_ARCH) != (out_flags & EF_NDS_ARCH)) - { -- _bfd_error_handler -- (_("%B: error: Instruction set mismatch with previous modules."), ibfd); -+ if (((in_flags & EF_NDS_ARCH) != E_N1_ARCH)) -+ { -+ _bfd_error_handler -+ (_("%B: error: Instruction set mismatch with previous modules."), ibfd); - -- bfd_set_error (bfd_error_bad_value); -- return FALSE; -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } - } -- } - -- /* When linking with V1.2 and V1.3 objects together the output is V1.2. -- and perf ext1 and DIV are mergerd to perf ext1. */ -- if (in_version == E_NDS32_ELF_VER_1_2 || out_version == E_NDS32_ELF_VER_1_2) -- { -- elf_elfheader (obfd)->e_flags = -- (in_flags & (~(E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) -- | (out_flags & (~(E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) -- | (((in_flags & (E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) -- ? E_NDS32_HAS_EXT_INST : 0) -- | (((out_flags & (E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) -- ? E_NDS32_HAS_EXT_INST : 0) -- | (in_16regs & out_16regs) | (in_no_mac & out_no_mac) -- | ((in_version > out_version) ? out_version : in_version); -- } -- else -- { -- if (in_version != out_version) -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%B: warning: Incompatible elf-versions %s and %s."), -- ibfd, nds32_elfver_strtab[out_version], -- nds32_elfver_strtab[in_version]); -+ /* When linking with V1.2 and V1.3 objects together the output is V1.2. -+ and perf ext1 and DIV are mergerd to perf ext1. */ -+ if (in_version == E_NDS32_ELF_VER_1_2 || out_version == E_NDS32_ELF_VER_1_2) -+ { -+ elf_elfheader (obfd)->e_flags = -+ (in_flags & (~(E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) -+ | (out_flags & (~(E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) -+ | (((in_flags & (E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) -+ ? E_NDS32_HAS_EXT_INST : 0) -+ | (((out_flags & (E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) -+ ? E_NDS32_HAS_EXT_INST : 0) -+ | (in_16regs & out_16regs) | (in_no_mac & out_no_mac) -+ | ((in_version > out_version) ? out_version : in_version); -+ } -+ else -+ { -+ if (in_version != out_version) -+ _bfd_error_handler -+ (_("%B: warning: Incompatible elf-versions %s and %s."), ibfd, -+ nds32_elfver_strtab[out_version], -+ nds32_elfver_strtab[in_version]); - -- elf_elfheader (obfd)->e_flags = in_flags | out_flags -- | (in_16regs & out_16regs) | (in_no_mac & out_no_mac) -- | (in_fpu_config > out_fpu_config ? in_fpu_config : out_fpu_config) -- | (in_version > out_version ? out_version : in_version); -+ elf_elfheader (obfd)->e_flags = in_flags | out_flags -+ | (in_16regs & out_16regs) | (in_no_mac & out_no_mac) -+ | (in_fpu_config > out_fpu_config ? in_fpu_config : out_fpu_config) -+ | (in_version > out_version ? out_version : in_version); -+ } - } -- - return TRUE; - } - -@@ -6081,6 +7417,79 @@ nds32_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info, - return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); - } - -+static enum elf_nds32_tls_type -+get_tls_type (enum elf_nds32_reloc_type r_type, -+ struct elf_link_hash_entry *h ATTRIBUTE_UNUSED) -+{ -+ enum elf_nds32_tls_type tls_type; -+ switch (r_type) -+ { -+ case R_NDS32_TLS_LE_HI20: -+ case R_NDS32_TLS_LE_LO12: -+ tls_type = GOT_TLS_LE; -+ break; -+ case R_NDS32_TLS_IE_HI20: -+ case R_NDS32_TLS_IE_LO12S2: -+ case R_NDS32_TLS_IE_LO12: -+ tls_type = GOT_TLS_IE; -+ break; -+ case R_NDS32_TLS_IEGP_HI20: -+ case R_NDS32_TLS_IEGP_LO12: -+ case R_NDS32_TLS_IEGP_LO12S2: -+ tls_type = GOT_TLS_IEGP; -+ break; -+ case R_NDS32_TLS_DESC_HI20: -+ case R_NDS32_TLS_DESC_LO12: -+ case R_NDS32_TLS_DESC_ADD: -+ case R_NDS32_TLS_DESC_FUNC: -+ case R_NDS32_TLS_DESC_CALL: -+ tls_type = GOT_TLS_DESC; -+ break; -+ default: -+ tls_type = GOT_NORMAL; -+ break; -+ } -+ return tls_type; -+} -+ -+/* Ensure that we have allocated bookkeeping structures for ABFD's local -+ symbols. */ -+ -+static bfd_boolean -+elf32_nds32_allocate_local_sym_info (bfd *abfd) -+{ -+ if (elf_local_got_refcounts (abfd) == NULL) -+ { -+ bfd_size_type num_syms; -+ bfd_size_type size; -+ char *data; -+ -+ num_syms = elf_tdata (abfd)->symtab_hdr.sh_info; -+ /* This space is for got_refcounts, got_tls_type, tlsdesc_gotent, and -+ gp_offset. The details can refer to struct elf_nds32_obj_tdata. */ -+ size = num_syms * (sizeof (bfd_signed_vma) + sizeof (char) -+ + sizeof (bfd_vma) + sizeof (int) -+ + sizeof (bfd_boolean) + sizeof (bfd_vma)); -+ data = bfd_zalloc (abfd, size); -+ if (data == NULL) -+ return FALSE; -+ -+ elf_local_got_refcounts (abfd) = (bfd_signed_vma *) data; -+ data += num_syms * sizeof (bfd_signed_vma); -+ -+ elf32_nds32_local_got_tls_type (abfd) = (char *) data; -+ data += num_syms * sizeof (char); -+ -+ elf32_nds32_local_tlsdesc_gotent (abfd) = (bfd_vma *) data; -+ data += num_syms * sizeof (bfd_vma); -+ -+ elf32_nds32_local_gp_offset (abfd) = (int *) data; -+ data += num_syms * sizeof (int); -+ } -+ -+ return TRUE; -+} -+ - /* Look through the relocs for a section during the first phase. - Since we don't do .gots or .plts, we just need to consider the - virtual table relocs for gc. */ -@@ -6093,21 +7502,17 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; - const Elf_Internal_Rela *rel; - const Elf_Internal_Rela *rel_end; -+ struct elf_link_hash_table *ehtab; - struct elf_nds32_link_hash_table *htab; - bfd *dynobj; - asection *sreloc = NULL; - -+ /* No need for relocation if relocatable already. */ - if (bfd_link_relocatable (info)) -- return TRUE; -- -- /* Don't do anything special with non-loaded, non-alloced sections. -- In particular, any relocs in such sections should not affect GOT -- and PLT reference counting (ie. we don't allow them to create GOT -- or PLT entries), there's no possibility or desire to optimize TLS -- relocs, and there's not much point in propagating relocs to shared -- libs that the dynamic linker won't relocate. */ -- if ((sec->flags & SEC_ALLOC) == 0) -- return TRUE; -+ { -+ elf32_nds32_check_relax_group (abfd, sec); -+ return TRUE; -+ } - - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - sym_hashes = elf_sym_hashes (abfd); -@@ -6116,6 +7521,7 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - if (!elf_bad_symtab (abfd)) - sym_hashes_end -= symtab_hdr->sh_info; - -+ ehtab = elf_hash_table (info); - htab = nds32_elf_hash_table (info); - dynobj = htab->root.dynobj; - -@@ -6125,7 +7531,8 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - enum elf_nds32_reloc_type r_type; - struct elf_link_hash_entry *h; - unsigned long r_symndx; -- int tls_type, old_tls_type; -+ enum elf_nds32_tls_type tls_type, old_tls_type; -+ struct elf_nds32_ict_hash_entry *entry; - - r_symndx = ELF32_R_SYM (rel->r_info); - r_type = ELF32_R_TYPE (rel->r_info); -@@ -6139,10 +7546,11 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - h = (struct elf_link_hash_entry *) h->root.u.i.link; - } - -- /* Some relocs require a global offset table. We create -- got section here, since these relocation need got section -- and it is not created yet. */ -- if (htab->root.sgot == NULL) -+ /* create .got section if necessary -+ Some relocs require a global offset table. We create -+ got section here, since these relocation need a got section -+ and if it is not created yet. */ -+ if (ehtab->sgot == NULL) - { - switch (r_type) - { -@@ -6162,10 +7570,16 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - case R_NDS32_GOTPC_LO12: - case R_NDS32_GOT20: - case R_NDS32_TLS_IE_HI20: -+ case R_NDS32_TLS_IE_LO12: - case R_NDS32_TLS_IE_LO12S2: -+ case R_NDS32_TLS_IEGP_HI20: -+ case R_NDS32_TLS_IEGP_LO12: -+ case R_NDS32_TLS_IEGP_LO12S2: -+ case R_NDS32_TLS_DESC_HI20: -+ case R_NDS32_TLS_DESC_LO12: - if (dynobj == NULL) - htab->root.dynobj = dynobj = abfd; -- if (!_bfd_elf_create_got_section (dynobj, info)) -+ if (!create_got_section (dynobj, info)) - return FALSE; - break; - -@@ -6174,59 +7588,54 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - } - } - -+ /* Check relocation type. */ - switch ((int) r_type) - { -+ case R_NDS32_TLS_LE_HI20: -+ case R_NDS32_TLS_LE_LO12: - case R_NDS32_GOT_HI20: - case R_NDS32_GOT_LO12: - case R_NDS32_GOT_LO15: - case R_NDS32_GOT_LO19: - case R_NDS32_GOT20: - case R_NDS32_TLS_IE_HI20: -+ case R_NDS32_TLS_IE_LO12: - case R_NDS32_TLS_IE_LO12S2: -- switch (r_type) -- { -- case R_NDS32_TLS_IE_HI20: -- case R_NDS32_TLS_IE_LO12S2: -- tls_type = GOT_TLS_IE; -- break; -- default: -- tls_type = GOT_NORMAL; -- break; -- } -- if (h != NULL) -+ case R_NDS32_TLS_IEGP_HI20: -+ case R_NDS32_TLS_IEGP_LO12: -+ case R_NDS32_TLS_IEGP_LO12S2: -+ case R_NDS32_TLS_DESC_HI20: -+ case R_NDS32_TLS_DESC_LO12: -+ tls_type = get_tls_type (r_type, h); -+ if (h) - { -+ if (tls_type != GOT_TLS_LE) -+ h->got.refcount += 1; - old_tls_type = elf32_nds32_hash_entry (h)->tls_type; -- h->got.refcount += 1; - } - else - { -- bfd_signed_vma *local_got_refcounts; -- -- /* This is a global offset table entry for a local -- symbol. */ -- local_got_refcounts = elf_local_got_refcounts (abfd); -- if (local_got_refcounts == NULL) -- { -- bfd_size_type size; -+ /* This is a global offset table entry for a local symbol. */ -+ if (!elf32_nds32_allocate_local_sym_info (abfd)) -+ return FALSE; - -- size = symtab_hdr->sh_info; -- size *= sizeof (bfd_signed_vma); -- local_got_refcounts = (bfd_signed_vma *) bfd_zalloc (abfd, size); -- if (local_got_refcounts == NULL) -- return FALSE; -- elf_local_got_refcounts (abfd) = local_got_refcounts; -- } -- local_got_refcounts[r_symndx] += 1; -+ BFD_ASSERT (r_symndx < symtab_hdr->sh_info); -+ if (tls_type != GOT_TLS_LE) -+ elf_local_got_refcounts (abfd)[r_symndx] += 1; - old_tls_type = elf32_nds32_local_got_tls_type (abfd)[r_symndx]; - } - -- /* We will already have issued an error message if there -+ /* We would already issued an error message if there - is a TLS/non-TLS mismatch, based on the symbol -- type. So just combine any TLS types needed. */ -+ type. So just combine any TLS types needed. */ - if (old_tls_type != GOT_UNKNOWN && old_tls_type != GOT_NORMAL - && tls_type != GOT_NORMAL) - tls_type |= old_tls_type; - -+ /* DESC to IE/IEGP if link to executable */ -+ if ((tls_type & (GOT_TLS_DESC | GOT_TLS_IEGP)) && (bfd_link_executable (info))) -+ tls_type |= (bfd_link_pie (info) ? GOT_TLS_IEGP : GOT_TLS_IE); -+ - if (old_tls_type != tls_type) - { - if (h != NULL) -@@ -6235,6 +7644,7 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - elf32_nds32_local_got_tls_type (abfd)[r_symndx] = tls_type; - } - break; -+ - case R_NDS32_9_PLTREL: - case R_NDS32_25_PLTREL: - case R_NDS32_PLTREL_HI20: -@@ -6244,19 +7654,20 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - case R_NDS32_PLT_GOTREL_LO15: - case R_NDS32_PLT_GOTREL_LO19: - case R_NDS32_PLT_GOTREL_LO20: -- -- /* This symbol requires a procedure linkage table entry. We -- actually build the entry in adjust_dynamic_symbol, -+ /* This symbol requires a procedure linkage table entry. -+ We actually build the entry in adjust_dynamic_symbol, - because this might be a case of linking PIC code without - linking in any dynamic objects, in which case we don't - need to generate a procedure linkage table after all. */ - - /* If this is a local symbol, we resolve it directly without - creating a procedure linkage table entry. */ -+ /* explain: continue v.s. break here following: */ - if (h == NULL) - continue; - -- if (h->forced_local) -+ if (h->forced_local -+ || (bfd_link_pie (info) && h->def_regular)) - break; - - elf32_nds32_hash_entry (h)->tls_type = GOT_NORMAL; -@@ -6330,8 +7741,8 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - && (h->root.type == bfd_link_hash_defweak - || !h->def_regular))) - { -- struct elf_dyn_relocs *p; -- struct elf_dyn_relocs **head; -+ struct elf_nds32_dyn_relocs *p; -+ struct elf_nds32_dyn_relocs **head; - - if (dynobj == NULL) - htab->root.dynobj = dynobj = abfd; -@@ -6380,7 +7791,6 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - else - { - asection *s; -- void *vpp; - - Elf_Internal_Sym *isym; - isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx); -@@ -6392,15 +7802,15 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - if (s == NULL) - return FALSE; - -- vpp = &elf_section_data (s)->local_dynrel; -- head = (struct elf_dyn_relocs **) vpp; -+ head = ((struct elf_nds32_dyn_relocs **) -+ &elf_section_data (s)->local_dynrel); - } - - p = *head; - if (p == NULL || p->sec != sec) - { - bfd_size_type amt = sizeof (*p); -- p = (struct elf_dyn_relocs *) bfd_alloc (dynobj, amt); -+ p = (struct elf_nds32_dyn_relocs *) bfd_alloc (dynobj, amt); - if (p == NULL) - return FALSE; - p->next = *head; -@@ -6411,19 +7821,98 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - } - - p->count += 1; -+ -+ /* FIXME: Since eh_frame is readonly, R_NDS32_32_RELA -+ reloc for eh_frame will cause shared library has -+ TEXTREL entry in the dynamic section. This lead glibc -+ testsuites to failure (bug-13092) and cause kernel fail -+ (bug-11819). I think the best solution is to replace -+ absolute reloc with pc relative reloc in the eh_frame. -+ To do that, we need to support the following issues: -+ -+ === For GCC === -+ * gcc/config/nds32/nds32.h: Define -+ ASM_PREFERRED_EH_DATA_FORMAT to encode DW_EH_PE_pcrel -+ and DW_EH_PE_sdata4 into DWARF exception header when -+ option have '-fpic'. -+ -+ === For binutils === -+ * bfd/: Define new reloc R_NDS32_32_PCREL_RELA. -+ * gas/config/tc-nds32.h: Define DIFF_EXPR_OK. This -+ may break our nds DIFF mechanism, therefore, we -+ must disable all linker relaxations to ensure -+ correctness. -+ * gas/config/tc-nds32.c (nds32_apply_fix): Replace -+ R_NDS32_32_RELA with R_NDS32_32_PCREL_RELA, and -+ do the necessary modification. -+ -+ Unfortunately, it still have some problems for nds32 -+ to support pc relative reloc in the eh_frame. So I use -+ another solution to fix this issue. -+ -+ However, I find that ld always emit TEXTREL marker for -+ R_NDS32_NONE relocs in rel.dyn. These none relocs are -+ correspond to R_NDS32_32_RELA for .eh_frame section. -+ It means that we always reserve redundant entries of rel.dyn -+ for these relocs which actually do nothing in dynamic linker. -+ -+ Therefore, we regard these relocs as pc relative relocs -+ here and increase the pc_count. */ - if (ELF32_R_TYPE (rel->r_info) == R_NDS32_25_PCREL_RELA - || ELF32_R_TYPE (rel->r_info) == R_NDS32_15_PCREL_RELA -- || ELF32_R_TYPE (rel->r_info) == R_NDS32_17_PCREL_RELA) -+ || ELF32_R_TYPE (rel->r_info) == R_NDS32_17_PCREL_RELA -+ || (r_type == R_NDS32_32_RELA -+ && strcmp (sec->name, ".eh_frame") == 0)) - p->pc_count += 1; - } - break; - -- /* This relocation describes the C++ object vtable hierarchy. -- Reconstruct it for later use during GC. */ -- case R_NDS32_RELA_GNU_VTINHERIT: -- case R_NDS32_GNU_VTINHERIT: -- if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) -- return FALSE; -+ /* Merge jump-patch table symbol here. */ -+ case R_NDS32_ICT_HI20: -+ case R_NDS32_ICT_LO12: -+ case R_NDS32_ICT_25PC: -+ if (rel->r_addend != 0) -+ { -+ _bfd_error_handler -+ (_("%pB %s: Error: Rom-patch relocation offset: 0x%lx " -+ "with addend 0x%lx\n"), -+ abfd, sec->name, rel->r_offset, rel->r_addend); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ -+ if (h) -+ { -+ elf32_nds32_hash_entry (h)->indirect_call = TRUE; -+ entry = (struct elf_nds32_ict_hash_entry *) -+ bfd_hash_lookup (&indirect_call_table, h->root.root.string, -+ TRUE, TRUE); -+ entry->h = h; -+ if (entry == NULL) -+ { -+ _bfd_error_handler -+ (_("%pB: failed creating indirect call %s hash table\n"), -+ abfd, h->root.root.string); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ } -+ else -+ { -+ /* Rom-patch functions cannot be local. */ -+ _bfd_error_handler -+ (_("%pB: indirect call relocation with local symbol.\n"), abfd); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ break; -+ -+ /* This relocation describes the C++ object vtable hierarchy. -+ Reconstruct it for later use during GC. */ -+ case R_NDS32_RELA_GNU_VTINHERIT: -+ case R_NDS32_GNU_VTINHERIT: -+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) -+ return FALSE; - break; - - /* This relocation describes which C++ vtable entries are actually -@@ -6436,6 +7925,18 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, - if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) - return FALSE; - break; -+ case R_NDS32_RELAX_ENTRY: -+ if (ict_model == 0) -+ ict_model = rel->r_addend & R_NDS32_RELAX_ENTRY_ICT_MASK; -+ else if (ict_model != (rel->r_addend & R_NDS32_RELAX_ENTRY_ICT_MASK) -+ && (rel->r_addend & R_NDS32_RELAX_ENTRY_ICT_MASK) != 0) -+ { -+ _bfd_error_handler -+ (_("%pB Error: mixed ict model objects.\n"), abfd); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ break; - } - } - -@@ -6464,8 +7965,7 @@ write_uleb128 (bfd_byte *p, unsigned int val) - - static bfd_signed_vma - calculate_offset (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -- Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr, -- int *pic_ext_target) -+ Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr) - { - bfd_signed_vma foff; - bfd_vma symval, addend; -@@ -6494,7 +7994,6 @@ calculate_offset (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - { - unsigned long indx; - struct elf_link_hash_entry *h; -- bfd *owner; - - /* An external symbol. */ - indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; -@@ -6507,9 +8006,6 @@ calculate_offset (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - symbol. Just ignore it--it will be caught by the - regular reloc processing. */ - return 0; -- owner = h->root.u.def.section->owner; -- if (owner && (elf_elfheader (owner)->e_flags & E_NDS32_HAS_PIC)) -- *pic_ext_target = 1; - - if (h->root.u.def.section->flags & SEC_MERGE) - { -@@ -6563,15 +8059,15 @@ calculate_plt_memory_address (bfd *abfd, struct bfd_link_info *link_info, - { - unsigned long indx; - struct elf_link_hash_entry *h; -- struct elf_nds32_link_hash_table *htab; -+ struct elf_link_hash_table *ehtab; - asection *splt; - - /* An external symbol. */ - indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; - h = elf_sym_hashes (abfd)[indx]; - BFD_ASSERT (h != NULL); -- htab = nds32_elf_hash_table (link_info); -- splt = htab->root.splt; -+ ehtab = elf_hash_table (link_info); -+ splt = ehtab->splt; - - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) -@@ -6582,8 +8078,8 @@ calculate_plt_memory_address (bfd *abfd, struct bfd_link_info *link_info, - if (h->root.type != bfd_link_hash_defined - && h->root.type != bfd_link_hash_defweak) - /* This appears to be a reference to an undefined -- * symbol. Just ignore it--it will be caught by the -- * regular reloc processing. */ -+ symbol. Just ignore it--it will be caught by the -+ regular reloc processing. */ - return 0; - symval = (h->root.u.def.value - + h->root.u.def.section->output_section->vma -@@ -6620,7 +8116,7 @@ nds32_convert_32_to_16_alu1 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, - int *pinsn_type) - { - uint16_t insn16 = 0; -- int insn_type = 0; -+ int insn_type; - unsigned long mach = bfd_get_mach (abfd); - - if (N32_SH5 (insn) != 0) -@@ -6919,8 +8415,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, - else if (N32_IS_RT4 (insn) && N32_RT5 (insn) == N32_RA5 (insn) - && N32_IMM15S (insn) > -32) - { -- insn16 = N16_TYPE45 (SUBI45, N32_RT54 (insn), -- 0 - N32_IMM15S (insn)); -+ insn16 = N16_TYPE45 (SUBI45, N32_RT54 (insn), 0 - N32_IMM15S (insn)); - insn_type = NDS32_INSN_SUBI45; - } - else if (mach >= MACH_V2 && N32_RT5 (insn) == REG_SP -@@ -6981,7 +8476,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, - - if (__builtin_popcount (imm15u) == 1) - { -- /* BMSKI33 */ -+ /* BMSKI33 */ - int imm3u = __builtin_ctz (imm15u); - - insn16 = N16_BFMI333 (BMSKI33, N32_RT5 (insn), imm3u); -@@ -6989,7 +8484,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, - } - else if (imm15u != 0 && __builtin_popcount (imm15u + 1) == 1) - { -- /* FEXTI33 */ -+ /* FEXTI33 */ - int imm3u = __builtin_ctz (imm15u + 1) - 1; - - insn16 = N16_BFMI333 (FEXTI33, N32_RT5 (insn), imm3u); -@@ -7150,7 +8645,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, - - if ((insn & N32_BIT (14)) == 0) - { -- /* N32_BR1_BEQ */ -+ /* N32_BR1_BEQ */ - if (N32_IS_RT3 (insn) && N32_RA5 (insn) == REG_R5 - && N32_RT5 (insn) != REG_R5) - insn16 = N16_TYPE38 (BEQS38, N32_RT5 (insn), N32_IMM14S (insn)); -@@ -7162,7 +8657,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, - } - else - { -- /* N32_BR1_BNE */ -+ /* N32_BR1_BNE */ - if (N32_IS_RT3 (insn) && N32_RA5 (insn) == REG_R5 - && N32_RT5 (insn) != REG_R5) - insn16 = N16_TYPE38 (BNES38, N32_RT5 (insn), N32_IMM14S (insn)); -@@ -7183,8 +8678,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, - insn16 = N16_TYPE38 (BEQZ38, N32_RT5 (insn), N32_IMM16S (insn)); - insn_type = NDS32_INSN_BEQZ38; - } -- else if (N32_RT5 (insn) == REG_R15 -- && IS_WITHIN_S (N32_IMM16S (insn), 8)) -+ else if (N32_RT5 (insn) == REG_R15 && IS_WITHIN_S (N32_IMM16S (insn), 8)) - { - insn16 = N16_TYPE8 (BEQZS8, N32_IMM16S (insn)); - insn_type = NDS32_INSN_BEQZS8; -@@ -7197,16 +8691,15 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, - insn16 = N16_TYPE38 (BNEZ38, N32_RT5 (insn), N32_IMM16S (insn)); - insn_type = NDS32_INSN_BNEZ38; - } -- else if (N32_RT5 (insn) == REG_R15 -- && IS_WITHIN_S (N32_IMM16S (insn), 8)) -+ else if (N32_RT5 (insn) == REG_R15 && IS_WITHIN_S (N32_IMM16S (insn), 8)) - { - insn16 = N16_TYPE8 (BNEZS8, N32_IMM16S (insn)); - insn_type = NDS32_INSN_BNEZS8; - } - break; - -- case N32_BR2_IFCALL: -- if (IS_WITHIN_U (N32_IMM16S (insn), 9)) -+ case N32_BR2_SOP0: -+ if (__GF (insn, 20, 5) == 0 && IS_WITHIN_U (N32_IMM16S (insn), 9)) - { - insn16 = N16_TYPE9 (IFCALL9, N32_IMM16S (insn)); - insn_type = NDS32_INSN_IFCALL9; -@@ -7218,7 +8711,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, - case N32_OP6_JI: - if ((insn & N32_BIT (24)) == 0) - { -- /* N32_JI_J */ -+ /* N32_JI_J */ - if (IS_WITHIN_S (N32_IMM24S (insn), 8)) - { - insn16 = N16_TYPE8 (J8, N32_IMM24S (insn)); -@@ -7236,19 +8729,19 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, - case N32_JREG_JR: - if (N32_JREG_HINT (insn) == 0) - { -- /* jr */ -+ /* jr */ - insn16 = N16_TYPE5 (JR5, N32_RB5 (insn)); - insn_type = NDS32_INSN_JR5; - } - else if (N32_JREG_HINT (insn) == 1) - { -- /* ret */ -+ /* ret */ - insn16 = N16_TYPE5 (RET5, N32_RB5 (insn)); - insn_type = NDS32_INSN_RET5; - } - else if (N32_JREG_HINT (insn) == 3) - { -- /* ifret = mov55 $sp, $sp */ -+ /* ifret = mov55 $sp, $sp */ - insn16 = N16_TYPE55 (MOV55, REG_SP, REG_SP); - insn_type = NDS32_INSN_IFRET; - } -@@ -7347,184 +8840,162 @@ nds32_convert_16_to_32 (bfd *abfd, uint16_t insn16, uint32_t *pinsn) - - switch (__GF (insn16, 9, 6)) - { -- case 0x4: /* add45 */ -- insn = N32_ALU1 (ADD, N16_RT4 (insn16), N16_RT4 (insn16), -- N16_RA5 (insn16)); -+ case 0x4: /* add45 */ -+ insn = N32_ALU1 (ADD, N16_RT4 (insn16), N16_RT4 (insn16), N16_RA5 (insn16)); - goto done; -- case 0x5: /* sub45 */ -- insn = N32_ALU1 (SUB, N16_RT4 (insn16), N16_RT4 (insn16), -- N16_RA5 (insn16)); -+ case 0x5: /* sub45 */ -+ insn = N32_ALU1 (SUB, N16_RT4 (insn16), N16_RT4 (insn16), N16_RA5 (insn16)); - goto done; -- case 0x6: /* addi45 */ -- insn = N32_TYPE2 (ADDI, N16_RT4 (insn16), N16_RT4 (insn16), -- N16_IMM5U (insn16)); -+ case 0x6: /* addi45 */ -+ insn = N32_TYPE2 (ADDI, N16_RT4 (insn16), N16_RT4 (insn16), N16_IMM5U (insn16)); - goto done; -- case 0x7: /* subi45 */ -- insn = N32_TYPE2 (ADDI, N16_RT4 (insn16), N16_RT4 (insn16), -- -N16_IMM5U (insn16)); -+ case 0x7: /* subi45 */ -+ insn = N32_TYPE2 (ADDI, N16_RT4 (insn16), N16_RT4 (insn16), -N16_IMM5U (insn16)); - goto done; -- case 0x8: /* srai45 */ -- insn = N32_ALU1 (SRAI, N16_RT4 (insn16), N16_RT4 (insn16), -- N16_IMM5U (insn16)); -+ case 0x8: /* srai45 */ -+ insn = N32_ALU1 (SRAI, N16_RT4 (insn16), N16_RT4 (insn16), N16_IMM5U (insn16)); - goto done; -- case 0x9: /* srli45 */ -- insn = N32_ALU1 (SRLI, N16_RT4 (insn16), N16_RT4 (insn16), -- N16_IMM5U (insn16)); -+ case 0x9: /* srli45 */ -+ insn = N32_ALU1 (SRLI, N16_RT4 (insn16), N16_RT4 (insn16), N16_IMM5U (insn16)); - goto done; -- case 0xa: /* slli333 */ -- insn = N32_ALU1 (SLLI, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_IMM3U (insn16)); -+ -+ case 0xa: /* slli333 */ -+ insn = N32_ALU1 (SLLI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); - goto done; -- case 0xc: /* add333 */ -- insn = N32_ALU1 (ADD, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_RB3 (insn16)); -+ case 0xc: /* add333 */ -+ insn = N32_ALU1 (ADD, N16_RT3 (insn16), N16_RA3 (insn16), N16_RB3 (insn16)); - goto done; -- case 0xd: /* sub333 */ -- insn = N32_ALU1 (SUB, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_RB3 (insn16)); -+ case 0xd: /* sub333 */ -+ insn = N32_ALU1 (SUB, N16_RT3 (insn16), N16_RA3 (insn16), N16_RB3 (insn16)); - goto done; -- case 0xe: /* addi333 */ -- insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_IMM3U (insn16)); -+ case 0xe: /* addi333 */ -+ insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); - goto done; -- case 0xf: /* subi333 */ -- insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), N16_RA3 (insn16), -- -N16_IMM3U (insn16)); -+ case 0xf: /* subi333 */ -+ insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), N16_RA3 (insn16), -N16_IMM3U (insn16)); - goto done; -- case 0x10: /* lwi333 */ -- insn = N32_TYPE2 (LWI, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_IMM3U (insn16)); -+ -+ case 0x10: /* lwi333 */ -+ insn = N32_TYPE2 (LWI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); - goto done; -- case 0x12: /* lhi333 */ -- insn = N32_TYPE2 (LHI, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_IMM3U (insn16)); -+ case 0x12: /* lhi333 */ -+ insn = N32_TYPE2 (LHI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); - goto done; -- case 0x13: /* lbi333 */ -- insn = N32_TYPE2 (LBI, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_IMM3U (insn16)); -+ case 0x13: /* lbi333 */ -+ insn = N32_TYPE2 (LBI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); - goto done; -- case 0x11: /* lwi333.bi */ -- insn = N32_TYPE2 (LWI_BI, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_IMM3U (insn16)); -+ case 0x11: /* lwi333.bi */ -+ insn = N32_TYPE2 (LWI_BI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); - goto done; -- case 0x14: /* swi333 */ -- insn = N32_TYPE2 (SWI, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_IMM3U (insn16)); -+ case 0x14: /* swi333 */ -+ insn = N32_TYPE2 (SWI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); - goto done; -- case 0x16: /* shi333 */ -- insn = N32_TYPE2 (SHI, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_IMM3U (insn16)); -+ case 0x16: /* shi333 */ -+ insn = N32_TYPE2 (SHI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); - goto done; -- case 0x17: /* sbi333 */ -- insn = N32_TYPE2 (SBI, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_IMM3U (insn16)); -+ case 0x17: /* sbi333 */ -+ insn = N32_TYPE2 (SBI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); - goto done; -- case 0x15: /* swi333.bi */ -- insn = N32_TYPE2 (SWI_BI, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_IMM3U (insn16)); -+ case 0x15: /* swi333.bi */ -+ insn = N32_TYPE2 (SWI_BI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); - goto done; -- case 0x18: /* addri36.sp */ -- insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), REG_SP, -- N16_IMM6U (insn16) << 2); -+ -+ case 0x18: /* addri36.sp */ -+ insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), REG_SP, N16_IMM6U (insn16) << 2); - goto done; -- case 0x19: /* lwi45.fe */ -- insn = N32_TYPE2 (LWI, N16_RT4 (insn16), REG_R8, -- (N16_IMM5U (insn16) - 32)); -+ -+ case 0x19: /* lwi45.fe */ -+ insn = N32_TYPE2 (LWI, N16_RT4 (insn16), REG_R8, (N16_IMM5U (insn16) - 32)); - goto done; -- case 0x1a: /* lwi450 */ -+ case 0x1a: /* lwi450 */ - insn = N32_TYPE2 (LWI, N16_RT4 (insn16), N16_RA5 (insn16), 0); - goto done; -- case 0x1b: /* swi450 */ -+ case 0x1b: /* swi450 */ - insn = N32_TYPE2 (SWI, N16_RT4 (insn16), N16_RA5 (insn16), 0); - goto done; - -- /* These are r15 implied instructions. */ -- case 0x30: /* slts45 */ -+ /* These are r15 implied instructions. */ -+ case 0x30: /* slts45 */ - insn = N32_ALU1 (SLTS, REG_TA, N16_RT4 (insn16), N16_RA5 (insn16)); - goto done; -- case 0x31: /* slt45 */ -+ case 0x31: /* slt45 */ - insn = N32_ALU1 (SLT, REG_TA, N16_RT4 (insn16), N16_RA5 (insn16)); - goto done; -- case 0x32: /* sltsi45 */ -+ case 0x32: /* sltsi45 */ - insn = N32_TYPE2 (SLTSI, REG_TA, N16_RT4 (insn16), N16_IMM5U (insn16)); - goto done; -- case 0x33: /* slti45 */ -+ case 0x33: /* slti45 */ - insn = N32_TYPE2 (SLTI, REG_TA, N16_RT4 (insn16), N16_IMM5U (insn16)); - goto done; -- case 0x34: /* beqzs8, bnezs8 */ -+ case 0x34: /* beqzs8, bnezs8 */ - if (insn16 & N32_BIT (8)) - insn = N32_BR2 (BNEZ, REG_TA, N16_IMM8S (insn16)); - else - insn = N32_BR2 (BEQZ, REG_TA, N16_IMM8S (insn16)); - goto done; - -- case 0x35: /* break16, ex9.it */ -+ case 0x35: /* break16, ex9.it */ - /* Only consider range of v3 break16. */ - insn = N32_TYPE0 (MISC, (N16_IMM5U (insn16) << 5) | N32_MISC_BREAK); - goto done; - -- case 0x3c: /* ifcall9 */ -- insn = N32_BR2 (IFCALL, 0, N16_IMM9U (insn16)); -+ case 0x3c: /* ifcall9 */ -+ insn = N32_BR2 (SOP0, 0, N16_IMM9U (insn16)); - goto done; -- case 0x3d: /* movpi45 */ -+ case 0x3d: /* movpi45 */ - insn = N32_TYPE1 (MOVI, N16_RT4 (insn16), N16_IMM5U (insn16) + 16); - goto done; - -- case 0x3f: /* MISC33 */ -+ case 0x3f: /* MISC33 */ - switch (insn16 & 0x7) - { -- case 2: /* neg33 */ -+ case 2: /* neg33 */ - insn = N32_TYPE2 (SUBRI, N16_RT3 (insn16), N16_RA3 (insn16), 0); - break; -- case 3: /* not33 */ -- insn = N32_ALU1 (NOR, N16_RT3 (insn16), N16_RA3 (insn16), -- N16_RA3 (insn16)); -+ case 3: /* not33 */ -+ insn = N32_ALU1 (NOR, N16_RT3 (insn16), N16_RA3 (insn16), N16_RA3 (insn16)); - break; -- case 4: /* mul33 */ -- insn = N32_ALU2 (MUL, N16_RT3 (insn16), N16_RT3 (insn16), -- N16_RA3 (insn16)); -+ case 4: /* mul33 */ -+ insn = N32_ALU2 (MUL, N16_RT3 (insn16), N16_RT3 (insn16), N16_RA3 (insn16)); - break; -- case 5: /* xor33 */ -- insn = N32_ALU1 (XOR, N16_RT3 (insn16), N16_RT3 (insn16), -- N16_RA3 (insn16)); -+ case 5: /* xor33 */ -+ insn = N32_ALU1 (XOR, N16_RT3 (insn16), N16_RT3 (insn16), N16_RA3 (insn16)); - break; -- case 6: /* and33 */ -- insn = N32_ALU1 (AND, N16_RT3 (insn16), N16_RT3 (insn16), -- N16_RA3 (insn16)); -+ case 6: /* and33 */ -+ insn = N32_ALU1 (AND, N16_RT3 (insn16), N16_RT3 (insn16), N16_RA3 (insn16)); - break; -- case 7: /* or33 */ -- insn = N32_ALU1 (OR, N16_RT3 (insn16), N16_RT3 (insn16), -- N16_RA3 (insn16)); -+ case 7: /* or33 */ -+ insn = N32_ALU1 (OR, N16_RT3 (insn16), N16_RT3 (insn16), N16_RA3 (insn16)); - break; - } - goto done; - -- case 0xb: -+ case 0xb: /* ... */ - switch (insn16 & 0x7) - { -- case 0: /* zeb33 */ -+ case 0: /* zeb33 */ - insn = N32_TYPE2 (ANDI, N16_RT3 (insn16), N16_RA3 (insn16), 0xff); - break; -- case 1: /* zeh33 */ -+ case 1: /* zeh33 */ - insn = N32_ALU1 (ZEH, N16_RT3 (insn16), N16_RA3 (insn16), 0); - break; -- case 2: /* seb33 */ -+ case 2: /* seb33 */ - insn = N32_ALU1 (SEB, N16_RT3 (insn16), N16_RA3 (insn16), 0); - break; -- case 3: /* seh33 */ -+ case 3: /* seh33 */ - insn = N32_ALU1 (SEH, N16_RT3 (insn16), N16_RA3 (insn16), 0); - break; -- case 4: /* xlsb33 */ -+ case 4: /* xlsb33 */ - insn = N32_TYPE2 (ANDI, N16_RT3 (insn16), N16_RA3 (insn16), 1); - break; -- case 5: /* x11b33 */ -+ case 5: /* x11b33 */ - insn = N32_TYPE2 (ANDI, N16_RT3 (insn16), N16_RA3 (insn16), 0x7ff); - break; -- case 6: /* bmski33 */ -+ case 6: /* bmski33 */ - insn = N32_TYPE2 (ANDI, N16_RT3 (insn16), N16_RT3 (insn16), - 1 << __GF (insn16, 3, 3)); - break; -- case 7: /* fexti33 */ -+ case 7: /* fexti33 */ - insn = N32_TYPE2 (ANDI, N16_RT3 (insn16), N16_RT3 (insn16), - (1 << (__GF (insn16, 3, 3) + 1)) - 1); - break; -@@ -7534,70 +9005,70 @@ nds32_convert_16_to_32 (bfd *abfd, uint16_t insn16, uint32_t *pinsn) - - switch (__GF (insn16, 10, 5)) - { -- case 0x0: /* mov55 or ifret16 */ -+ case 0x0: /* mov55 or ifret16 */ - if (mach >= MACH_V3 && N16_RT5 (insn16) == REG_SP - && N16_RT5 (insn16) == N16_RA5 (insn16)) -- insn = N32_JREG (JR, 0, 0, 0, 3); -+ insn = N32_JREG (JR, 0, 0, 0, 3); - else -- insn = N32_TYPE2 (ADDI, N16_RT5 (insn16), N16_RA5 (insn16), 0); -+ insn = N32_TYPE2 (ADDI, N16_RT5 (insn16), N16_RA5 (insn16), 0); - goto done; -- case 0x1: /* movi55 */ -+ case 0x1: /* movi55 */ - insn = N32_TYPE1 (MOVI, N16_RT5 (insn16), N16_IMM5S (insn16)); - goto done; -- case 0x1b: /* addi10s (V2) */ -+ case 0x1b: /* addi10s (V2) */ - insn = N32_TYPE2 (ADDI, REG_SP, REG_SP, N16_IMM10S (insn16)); - goto done; - } - - switch (__GF (insn16, 11, 4)) - { -- case 0x7: /* lwi37.fp/swi37.fp */ -- if (insn16 & N32_BIT (7)) /* swi37.fp */ -+ case 0x7: /* lwi37.fp/swi37.fp */ -+ if (insn16 & N32_BIT (7)) /* swi37.fp */ - insn = N32_TYPE2 (SWI, N16_RT38 (insn16), REG_FP, N16_IMM7U (insn16)); -- else /* lwi37.fp */ -+ else /* lwi37.fp */ - insn = N32_TYPE2 (LWI, N16_RT38 (insn16), REG_FP, N16_IMM7U (insn16)); - goto done; -- case 0x8: /* beqz38 */ -+ case 0x8: /* beqz38 */ - insn = N32_BR2 (BEQZ, N16_RT38 (insn16), N16_IMM8S (insn16)); - goto done; -- case 0x9: /* bnez38 */ -+ case 0x9: /* bnez38 */ - insn = N32_BR2 (BNEZ, N16_RT38 (insn16), N16_IMM8S (insn16)); - goto done; -- case 0xa: /* beqs38/j8, implied r5 */ -+ case 0xa: /* beqs38/j8, implied r5 */ - if (N16_RT38 (insn16) == 5) - insn = N32_JI (J, N16_IMM8S (insn16)); - else - insn = N32_BR1 (BEQ, N16_RT38 (insn16), REG_R5, N16_IMM8S (insn16)); - goto done; -- case 0xb: /* bnes38 and others */ -+ case 0xb: /* bnes38 and others */ - if (N16_RT38 (insn16) == 5) - { - switch (__GF (insn16, 5, 3)) - { -- case 0: /* jr5 */ -+ case 0: /* jr5 */ - insn = N32_JREG (JR, 0, N16_RA5 (insn16), 0, 0); - break; -- case 4: /* ret5 */ -+ case 4: /* ret5 */ - insn = N32_JREG (JR, 0, N16_RA5 (insn16), 0, 1); - break; -- case 1: /* jral5 */ -+ case 1: /* jral5 */ - insn = N32_JREG (JRAL, REG_LP, N16_RA5 (insn16), 0, 0); - break; -- case 2: /* ex9.it imm5 */ -+ case 2: /* ex9.it imm5 */ - /* ex9.it had no 32-bit variantl. */ - break; -- case 5: /* add5.pc */ -+ case 5: /* add5.pc */ - /* add5.pc had no 32-bit variantl. */ - break; - } - } -- else /* bnes38 */ -+ else /* bnes38 */ - insn = N32_BR1 (BNE, N16_RT38 (insn16), REG_R5, N16_IMM8S (insn16)); - goto done; -- case 0xe: /* lwi37/swi37 */ -- if (insn16 & (1 << 7)) /* swi37.sp */ -+ case 0xe: /* lwi37/swi37 */ -+ if (insn16 & (1 << 7)) /* swi37.sp */ - insn = N32_TYPE2 (SWI, N16_RT38 (insn16), REG_SP, N16_IMM7U (insn16)); -- else /* lwi37.sp */ -+ else /* lwi37.sp */ - insn = N32_TYPE2 (LWI, N16_RT38 (insn16), REG_SP, N16_IMM7U (insn16)); - goto done; - } -@@ -7650,19 +9121,19 @@ turn_insn_to_sda_access (uint32_t insn, bfd_signed_vma type, uint32_t *pinsn) - switch (N32_OP6 (insn)) - { - case N32_OP6_LBI: -- /* lbi.gp */ -+ /* lbi.gp */ - oinsn = N32_TYPE1 (LBGP, N32_RT5 (insn), 0); - break; - case N32_OP6_LBSI: -- /* lbsi.gp */ -+ /* lbsi.gp */ - oinsn = N32_TYPE1 (LBGP, N32_RT5 (insn), N32_BIT (19)); - break; - case N32_OP6_SBI: -- /* sbi.gp */ -+ /* sbi.gp */ - oinsn = N32_TYPE1 (SBGP, N32_RT5 (insn), 0); - break; - case N32_OP6_ORI: -- /* addi.gp */ -+ /* addi.gp */ - oinsn = N32_TYPE1 (SBGP, N32_RT5 (insn), N32_BIT (19)); - break; - } -@@ -7672,15 +9143,15 @@ turn_insn_to_sda_access (uint32_t insn, bfd_signed_vma type, uint32_t *pinsn) - switch (N32_OP6 (insn)) - { - case N32_OP6_LHI: -- /* lhi.gp */ -+ /* lhi.gp */ - oinsn = N32_TYPE1 (HWGP, N32_RT5 (insn), 0); - break; - case N32_OP6_LHSI: -- /* lhsi.gp */ -+ /* lhsi.gp */ - oinsn = N32_TYPE1 (HWGP, N32_RT5 (insn), N32_BIT (18)); - break; - case N32_OP6_SHI: -- /* shi.gp */ -+ /* shi.gp */ - oinsn = N32_TYPE1 (HWGP, N32_RT5 (insn), N32_BIT (19)); - break; - } -@@ -7690,11 +9161,11 @@ turn_insn_to_sda_access (uint32_t insn, bfd_signed_vma type, uint32_t *pinsn) - switch (N32_OP6 (insn)) - { - case N32_OP6_LWI: -- /* lwi.gp */ -+ /* lwi.gp */ - oinsn = N32_TYPE1 (HWGP, N32_RT5 (insn), __MF (6, 17, 3)); - break; - case N32_OP6_SWI: -- /* swi.gp */ -+ /* swi.gp */ - oinsn = N32_TYPE1 (HWGP, N32_RT5 (insn), __MF (7, 17, 3)); - break; - } -@@ -7835,7 +9306,7 @@ calculate_got_memory_address (bfd *abfd, struct bfd_link_info *link_info, - bfd_vma *local_got_offsets; - /* Get the value of the symbol referred to by the reloc. */ - struct elf_link_hash_entry *h; -- struct elf_nds32_link_hash_table *htab = nds32_elf_hash_table (link_info); -+ struct elf_link_hash_table *ehtab = elf_hash_table (link_info); - - /* An external symbol. */ - symndx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; -@@ -7847,18 +9318,13 @@ calculate_got_memory_address (bfd *abfd, struct bfd_link_info *link_info, - if (symndx >= 0) - { - BFD_ASSERT (h != NULL); -- return (htab->root.sgot->output_section->vma -- + htab->root.sgot->output_offset -- + h->got.offset); -- } -- else -- { -- local_got_offsets = elf_local_got_offsets (abfd); -- BFD_ASSERT (local_got_offsets != NULL); -- return (htab->root.sgot->output_section->vma -- + htab->root.sgot->output_offset -- + local_got_offsets[ELF32_R_SYM (irel->r_info)]); -+ return ehtab->sgot->output_section->vma + ehtab->sgot->output_offset -+ + h->got.offset; - } -+ local_got_offsets = elf_local_got_offsets (abfd); -+ BFD_ASSERT (local_got_offsets != NULL); -+ return ehtab->sgot->output_section->vma + ehtab->sgot->output_offset -+ + local_got_offsets[ELF32_R_SYM (irel->r_info)]; - - /* The _GLOBAL_OFFSET_TABLE_ may be undefweak(or should be?). */ - /* The check of h->root.type is passed. */ -@@ -7899,7 +9365,6 @@ is_convert_32_to_16 (bfd *abfd, asection *sec, - bfd_vma mem_addr; - uint32_t insn = 0; - Elf_Internal_Rela *pc_rel; -- int pic_ext_target = 0; - Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Sym *isymbuf = NULL; - int convert_type; -@@ -7938,8 +9403,7 @@ is_convert_32_to_16 (bfd *abfd, asection *sec, - || ELF32_R_TYPE (pc_rel->r_info) == R_NDS32_25_PCREL_RELA - || ELF32_R_TYPE (pc_rel->r_info) == R_NDS32_25_PLTREL) - { -- off = calculate_offset (abfd, sec, pc_rel, isymbuf, symtab_hdr, -- &pic_ext_target); -+ off = calculate_offset (abfd, sec, pc_rel, isymbuf, symtab_hdr); - if (off >= ACCURATE_8BIT_S1 || off < -ACCURATE_8BIT_S1 - || off == 0) - return FALSE; -@@ -7948,10 +9412,8 @@ is_convert_32_to_16 (bfd *abfd, asection *sec, - else if (ELF32_R_TYPE (pc_rel->r_info) == R_NDS32_20_RELA) - { - /* movi => movi55 */ -- mem_addr = calculate_memory_address (abfd, pc_rel, isymbuf, -- symtab_hdr); -- /* mem_addr is unsigned, but the value should -- be between [-16, 15]. */ -+ mem_addr = calculate_memory_address (abfd, pc_rel, isymbuf, symtab_hdr); -+ /* mem_addr is unsigned, but the value should be between [-16, 15]. */ - if ((mem_addr + 0x10) >> 5) - return FALSE; - break; -@@ -7980,14 +9442,12 @@ is_convert_32_to_16 (bfd *abfd, asection *sec, - || ((ELF32_R_TYPE (pc_rel->r_info) > R_NDS32_LOADSTORE) - && (ELF32_R_TYPE (pc_rel->r_info) < R_NDS32_DWARF2_OP1_RELA))) - { -- /* Prevent unresolved addi instruction translate -- to addi45 or addi333. */ -+ /* Prevent unresolved addi instruction translate to addi45 or addi333. */ - return FALSE; - } - else if ((ELF32_R_TYPE (pc_rel->r_info) == R_NDS32_17IFC_PCREL_RELA)) - { -- off = calculate_offset (abfd, sec, pc_rel, isymbuf, symtab_hdr, -- &pic_ext_target); -+ off = calculate_offset (abfd, sec, pc_rel, isymbuf, symtab_hdr); - if (off >= ACCURATE_U9BIT_S1 || off <= 0) - return FALSE; - break; -@@ -8085,7 +9545,7 @@ static Elf_Internal_Rela * - find_relocs_at_address_addr (Elf_Internal_Rela *reloc, - Elf_Internal_Rela *relocs, - Elf_Internal_Rela *irelend, -- enum elf_nds32_reloc_type reloc_type, -+ unsigned char reloc_type, - bfd_vma offset_p) - { - Elf_Internal_Rela *rel_t = NULL; -@@ -8281,8 +9741,9 @@ insert_nds32_elf_blank (nds32_elf_blank_t **blank_p, bfd_vma addr, bfd_vma len) - - if (addr < blank_t->offset + blank_t->size) - { -- if (addr > blank_t->offset + blank_t->size) -- blank_t->size = addr - blank_t->offset; -+ /* Extend the origin blank. */ -+ if (addr + len > blank_t->offset + blank_t->size) -+ blank_t->size = addr + len - blank_t->offset; - } - else - { -@@ -8414,7 +9875,7 @@ nds32_elf_relax_delete_blanks (bfd *abfd, asection *sec, - - /* Relocations MUST be kept in memory, because relaxation adjust them. */ - internal_relocs = _bfd_elf_link_read_relocs (abfd, sect, NULL, NULL, -- TRUE /* keep_memory */); -+ TRUE /* keep_memory */); - irelend = internal_relocs + sect->reloc_count; - - blank_t = blank_head; -@@ -8436,7 +9897,7 @@ nds32_elf_relax_delete_blanks (bfd *abfd, asection *sec, - unsigned long val = 0; - unsigned long mask; - long before, between; -- long offset = 0; -+ long offset; - - switch (ELF32_R_TYPE (irel->r_info)) - { -@@ -8468,28 +9929,23 @@ nds32_elf_relax_delete_blanks (bfd *abfd, asection *sec, - -- before ---| ***************** - --------------------- between ---| - -- We only care how much data are relax between DIFF, -- marked as ***. */ -+ We only care how much data are relax between DIFF, marked as ***. */ - - before = get_nds32_elf_blank_total (&blank_t, irel->r_addend, 0); -- between = get_nds32_elf_blank_total (&blank_t, -- irel->r_addend + offset, 0); -+ between = get_nds32_elf_blank_total (&blank_t, irel->r_addend + offset, 0); - if (between == before) - goto done_adjust_diff; - - switch (ELF32_R_TYPE (irel->r_info)) - { - case R_NDS32_DIFF8: -- bfd_put_8 (abfd, offset - (between - before), -- contents + irel->r_offset); -+ bfd_put_8 (abfd, offset - (between - before), contents + irel->r_offset); - break; - case R_NDS32_DIFF16: -- bfd_put_16 (abfd, offset - (between - before), -- contents + irel->r_offset); -+ bfd_put_16 (abfd, offset - (between - before), contents + irel->r_offset); - break; - case R_NDS32_DIFF32: -- bfd_put_32 (abfd, offset - (between - before), -- contents + irel->r_offset); -+ bfd_put_32 (abfd, offset - (between - before), contents + irel->r_offset); - break; - } - } -@@ -8501,12 +9957,10 @@ nds32_elf_relax_delete_blanks (bfd *abfd, asection *sec, - unsigned long before, between; - bfd_byte *endp, *p; - -- val = _bfd_read_unsigned_leb128 (abfd, contents + irel->r_offset, -- &len); -+ val = _bfd_read_unsigned_leb128 (abfd, contents + irel->r_offset, &len); - - before = get_nds32_elf_blank_total (&blank_t, irel->r_addend, 0); -- between = get_nds32_elf_blank_total (&blank_t, -- irel->r_addend + val, 0); -+ between = get_nds32_elf_blank_total (&blank_t, irel->r_addend + val, 0); - if (between == before) - goto done_adjust_diff; - -@@ -8523,16 +9977,14 @@ done_adjust_diff: - if (sec == sect) - { - raddr = irel->r_offset; -- irel->r_offset -= get_nds32_elf_blank_total (&blank_t2, -- irel->r_offset, 1); -+ irel->r_offset -= get_nds32_elf_blank_total (&blank_t2, irel->r_offset, 1); - - if (ELF32_R_TYPE (irel->r_info) == R_NDS32_NONE) - continue; - if (blank_t2 && blank_t2->next -- && (blank_t2->offset > raddr -- || blank_t2->next->offset <= raddr)) -- _bfd_error_handler -- (_("%B: Error: search_nds32_elf_blank reports wrong node\n"), abfd); -+ && (blank_t2->offset > raddr || blank_t2->next->offset <= raddr)) -+ _bfd_error_handler (_("%B: %s\n"), abfd, -+ "Error: search_nds32_elf_blank reports wrong node"); - - /* Mark reloc in deleted portion as NONE. - For some relocs like R_NDS32_LABEL that doesn't modify the -@@ -8584,11 +10036,9 @@ done_adjust_diff: - isym->st_value -= ahead; - - /* Adjust function size. */ -- if (ELF32_ST_TYPE (isym->st_info) == STT_FUNC -- && isym->st_size > 0) -- isym->st_size -= -- get_nds32_elf_blank_total -- (&blank_t, orig_addr + isym->st_size, 0) - ahead; -+ if (ELF32_ST_TYPE (isym->st_info) == STT_FUNC && isym->st_size > 0) -+ isym->st_size -= get_nds32_elf_blank_total -+ (&blank_t, orig_addr + isym->st_size, 0) - ahead; - } - } - } -@@ -8617,9 +10067,8 @@ done_adjust_diff: - - /* Adjust function size. */ - if (sym_hash->type == STT_FUNC) -- sym_hash->size -= -- get_nds32_elf_blank_total -- (&blank_t, orig_addr + sym_hash->size, 0) - ahead; -+ sym_hash->size -= get_nds32_elf_blank_total -+ (&blank_t, orig_addr + sym_hash->size, 0) - ahead; - - } - } -@@ -8743,7 +10192,7 @@ relax_range_measurement (bfd *abfd) - bfd_vma align; - static int decide_relax_range = 0; - int i; -- int range_number = sizeof (sdata_init_range) / sizeof (sdata_init_range[0]); -+ int range_number = ARRAY_SIZE (sdata_init_range); - - if (decide_relax_range) - return; -@@ -8789,11 +10238,7 @@ relax_range_measurement (bfd *abfd) - #define IS_OPTIMIZE(addend) ((addend) & 0x40000000) - #define IS_16BIT_ON(addend) ((addend) & 0x20000000) - --static const char * unrecognized_reloc_msg = -- /* xgettext:c-format */ -- N_("%B: warning: %s points to unrecognized reloc at %#Lx"); -- --/* Relax LONGCALL1 relocation for nds32_elf_relax_section. */ -+/* Relax LONGCALL1 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -8803,19 +10248,19 @@ nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - { - /* There are 3 variations for LONGCALL1 - case 4-4-2; 16-bit on, optimize off or optimize for space -- sethi ta, hi20(symbol) ; LONGCALL1/HI20 -+ sethi ta, hi20(symbol) ; LONGCALL1/HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jral5 ta ; -+ jral5 ta ; - - case 4-4-4; 16-bit off, optimize don't care -- sethi ta, hi20(symbol) ; LONGCALL1/HI20 -+ sethi ta, hi20(symbol) ; LONGCALL1/HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jral ta ; -+ jral ta ; - - case 4-4-4; 16-bit on, optimize for speed -- sethi ta, hi20(symbol) ; LONGCALL1/HI20 -+ sethi ta, hi20(symbol) ; LONGCALL1/HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jral ta ; -+ jral ta ; - Check code for -mlong-calls output. */ - - /* Get the reloc for the address from which the register is -@@ -8826,7 +10271,6 @@ nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - int seq_len; /* Original length of instruction sequence. */ - uint32_t insn; - Elf_Internal_Rela *hi_irelfn, *lo_irelfn, *irelend; -- int pic_ext_target = 0; - bfd_signed_vma foff; - uint16_t insn16; - -@@ -8843,21 +10287,21 @@ nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (hi_irelfn == irelend || lo_irelfn == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL1", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGCALL1 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr); - - /* This condition only happened when symbol is undefined. */ -- if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 -+ if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 - || foff >= CONSERVATIVE_24BIT_S1) - return FALSE; - -- /* Relax to: jal symbol; 25_PCREL */ -+ /* Relax to: jal symbol; 25_PCREL */ - /* For simplicity of coding, we are going to modify the section - contents, the section relocs, and the BFD symbol table. We - must tell the rest of the code not to free up this -@@ -8894,7 +10338,7 @@ nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - } - - #define CONVERT_CONDITION_CALL(insn) (((insn) & 0xffff0000) ^ 0x90000) --/* Relax LONGCALL2 relocation for nds32_elf_relax_section. */ -+/* Relax LONGCALL2 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -8904,7 +10348,7 @@ nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - { - /* bltz rt, .L1 ; LONGCALL2 - jal symbol ; 25_PCREL -- .L1: */ -+ .L1: */ - - /* Get the reloc for the address from which the register is - being loaded. This reloc will tell us which function is -@@ -8913,7 +10357,6 @@ nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - bfd_vma laddr; - uint32_t insn; - Elf_Internal_Rela *i1_irelfn, *cond_irelfn, *irelend; -- int pic_ext_target = 0; - bfd_signed_vma foff; - - irelend = internal_relocs + sec->reloc_count; -@@ -8924,23 +10367,23 @@ nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (i1_irelfn == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL2", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGCALL2 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - insn = bfd_getb32 (contents + laddr); - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, i1_irelfn, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, i1_irelfn, isymbuf, symtab_hdr); - - if (foff == 0 || foff < -CONSERVATIVE_16BIT_S1 - || foff >= CONSERVATIVE_16BIT_S1) - return FALSE; - - /* Relax to bgezal rt, label ; 17_PCREL -- or bltzal rt, label ; 17_PCREL */ -+ or bltzal rt, label ; 17_PCREL */ - - /* Convert to complimentary conditional call. */ - insn = CONVERT_CONDITION_CALL (insn); -@@ -8974,7 +10417,7 @@ nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - --/* Relax LONGCALL3 relocation for nds32_elf_relax_section. */ -+/* Relax LONGCALL3 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -8984,25 +10427,25 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - { - /* There are 3 variations for LONGCALL3 - case 4-4-4-2; 16-bit on, optimize off or optimize for space -- bltz rt, $1 ; LONGCALL3 -- sethi ta, hi20(symbol) ; HI20 -+ bltz rt, $1 ; LONGCALL3 -+ sethi ta, hi20(symbol) ; HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jral5 ta ; -+ jral5 ta ; - $1 - - case 4-4-4-4; 16-bit off, optimize don't care -- bltz rt, $1 ; LONGCALL3 -- sethi ta, hi20(symbol) ; HI20 -+ bltz rt, $1 ; LONGCALL3 -+ sethi ta, hi20(symbol) ; HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jral ta ; -+ jral ta ; - $1 - - case 4-4-4-4; 16-bit on, optimize for speed -- bltz rt, $1 ; LONGCALL3 -- sethi ta, hi20(symbol) ; HI20 -+ bltz rt, $1 ; LONGCALL3 -+ sethi ta, hi20(symbol) ; HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jral ta ; -- $1 */ -+ jral ta ; -+ $1 */ - - /* Get the reloc for the address from which the register is - being loaded. This reloc will tell us which function is -@@ -9012,7 +10455,6 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - int seq_len; /* Original length of instruction sequence. */ - uint32_t insn; - Elf_Internal_Rela *hi_irelfn, *lo_irelfn, *cond_irelfn, *irelend; -- int pic_ext_target = 0; - bfd_signed_vma foff; - uint16_t insn16; - -@@ -9030,16 +10472,16 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (hi_irelfn == irelend || lo_irelfn == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL3", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGCALL3 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr); - -- if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 -+ if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 - || foff >= CONSERVATIVE_24BIT_S1) - return FALSE; - -@@ -9047,7 +10489,7 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - if (foff >= -CONSERVATIVE_16BIT_S1 && foff < CONSERVATIVE_16BIT_S1) - { - /* Relax to bgezal rt, label ; 17_PCREL -- or bltzal rt, label ; 17_PCREL */ -+ or bltzal rt, label ; 17_PCREL */ - - /* Convert to complimentary conditional call. */ - insn = CONVERT_CONDITION_CALL (insn); -@@ -9112,7 +10554,7 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - --/* Relax LONGJUMP1 relocation for nds32_elf_relax_section. */ -+/* Relax LONGJUMP1 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -9122,19 +10564,19 @@ nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - { - /* There are 3 variations for LONGJUMP1 - case 4-4-2; 16-bit bit on, optimize off or optimize for space -- sethi ta, hi20(symbol) ; LONGJUMP1/HI20 -- ori ta, ta, lo12(symbol) ; LO12S0 -- jr5 ta ; -+ sethi ta, hi20(symbol) ; LONGJUMP1/HI20 -+ ori ta, ta, lo12(symbol) ; LO12S0 -+ jr5 ta ; - - case 4-4-4; 16-bit off, optimize don't care -- sethi ta, hi20(symbol) ; LONGJUMP1/HI20 -- ori ta, ta, lo12(symbol) ; LO12S0 -- jr ta ; -+ sethi ta, hi20(symbol) ; LONGJUMP1/HI20 -+ ori ta, ta, lo12(symbol) ; LO12S0 -+ jr ta ; - - case 4-4-4; 16-bit on, optimize for speed -- sethi ta, hi20(symbol) ; LONGJUMP1/HI20 -- ori ta, ta, lo12(symbol) ; LO12S0 -- jr ta ; */ -+ sethi ta, hi20(symbol) ; LONGJUMP1/HI20 -+ ori ta, ta, lo12(symbol) ; LO12S0 -+ jr ta ; */ - - /* Get the reloc for the address from which the register is - being loaded. This reloc will tell us which function is -@@ -9145,7 +10587,6 @@ nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - int insn16_on; /* 16-bit on/off. */ - uint32_t insn; - Elf_Internal_Rela *hi_irelfn, *lo_irelfn, *irelend; -- int pic_ext_target = 0; - bfd_signed_vma foff; - uint16_t insn16; - unsigned long reloc; -@@ -9164,23 +10605,23 @@ nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - R_NDS32_LO12S0_ORI_RELA, laddr + 4); - if (hi_irelfn == irelend || lo_irelfn == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP1", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGJUMP1 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr); - -- if (pic_ext_target || foff == 0 || foff >= CONSERVATIVE_24BIT_S1 -+ if (foff == 0 || foff >= CONSERVATIVE_24BIT_S1 - || foff < -CONSERVATIVE_24BIT_S1) - return FALSE; - - if (insn16_on && foff >= -ACCURATE_8BIT_S1 - && foff < ACCURATE_8BIT_S1 && (seq_len & 0x2)) - { -- /* j8 label */ -+ /* j8 label */ - /* 16-bit on, but not optimized for speed. */ - reloc = R_NDS32_9_PCREL_RELA; - insn16 = INSN_J8; -@@ -9191,7 +10632,7 @@ nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - } - else - { -- /* j label */ -+ /* j label */ - reloc = R_NDS32_25_PCREL_RELA; - insn = INSN_J; - bfd_putb32 (insn, contents + irel->r_offset); -@@ -9275,14 +10716,14 @@ nds32_elf_convert_branch (uint16_t insn16, uint32_t insn, - switch ((insn16 & 0xf000) >> 12) - { - case 0xc: -- /* beqz38 or bnez38 */ -+ /* beqz38 or bnez38 */ - comp_insn16 = (insn16 ^ 0x0800) & 0xff00; - comp_insn = (comp_insn16 & 0x0800) ? INSN_BNEZ : INSN_BEQZ; - comp_insn |= ((comp_insn16 & 0x0700) >> 8) << 20; - break; - - case 0xd: -- /* beqs38 or bnes38 */ -+ /* beqs38 or bnes38 */ - comp_insn16 = (insn16 ^ 0x0800) & 0xff00; - comp_insn = (comp_insn16 & 0x0800) ? INSN_BNE : INSN_BEQ; - comp_insn |= (((comp_insn16 & 0x0700) >> 8) << 20) -@@ -9290,7 +10731,7 @@ nds32_elf_convert_branch (uint16_t insn16, uint32_t insn, - break; - - case 0xe: -- /* beqzS8 or bnezS8 */ -+ /* beqzS8 or bnezS8 */ - comp_insn16 = (insn16 ^ 0x0100) & 0xff00; - comp_insn = (comp_insn16 & 0x0100) ? INSN_BNEZ : INSN_BEQZ; - comp_insn |= REG_R15 << 20; -@@ -9306,7 +10747,7 @@ nds32_elf_convert_branch (uint16_t insn16, uint32_t insn, - *re_insn16 = comp_insn16; - } - --/* Relax LONGJUMP2 relocation for nds32_elf_relax_section. */ -+/* Relax LONGJUMP2 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -9329,7 +10770,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - case 4-4; 1st insn convertible, 16-bit on, optimize for speed - bne rt, ra, $1 ; LONGJUMP2 - j label ; 25_PCREL -- $1: */ -+ $1: */ - - /* Get the reloc for the address from which the register is - being loaded. This reloc will tell us which function is -@@ -9338,7 +10779,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - bfd_vma laddr; - int seq_len; /* Original length of instruction sequence. */ - Elf_Internal_Rela *i2_irelfn, *cond_irelfn, *irelend; -- int pic_ext_target = 0, first_size; -+ int first_size; - unsigned int i; - bfd_signed_vma foff; - uint32_t insn, re_insn = 0; -@@ -9359,7 +10800,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - irelend, R_NDS32_25_PCREL_RELA, - laddr + first_size); - -- for (i = 0; i < sizeof (checked_types) / sizeof(checked_types[0]); i++) -+ for (i = 0; i < ARRAY_SIZE (checked_types); i++) - { - cond_irelfn = - find_relocs_at_address_addr (irel, internal_relocs, irelend, -@@ -9370,16 +10811,16 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (i2_irelfn == irelend || cond_irelfn == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP2", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGJUMP2 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ - foff = -- calculate_offset (abfd, sec, i2_irelfn, isymbuf, symtab_hdr, -- &pic_ext_target); -- if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_16BIT_S1 -+ calculate_offset (abfd, sec, i2_irelfn, isymbuf, symtab_hdr); -+ if (foff == 0 || foff < -CONSERVATIVE_16BIT_S1 - || foff >= CONSERVATIVE_16BIT_S1) - return FALSE; - -@@ -9422,7 +10863,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - && (foff >= -(ACCURATE_14BIT_S1 - first_size) - && foff < ACCURATE_14BIT_S1 - first_size)) - { -- /* beqs label ; 15_PCREL */ -+ /* beqs label ; 15_PCREL */ - bfd_putb32 (re_insn, contents + irel->r_offset); - *insn_len = 4; - reloc = R_NDS32_15_PCREL_RELA; -@@ -9432,7 +10873,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - && foff >= -CONSERVATIVE_16BIT_S1 - && foff < CONSERVATIVE_16BIT_S1) - { -- /* beqz label ; 17_PCREL */ -+ /* beqz label ; 17_PCREL */ - bfd_putb32 (re_insn, contents + irel->r_offset); - *insn_len = 4; - reloc = R_NDS32_17_PCREL_RELA; -@@ -9465,7 +10906,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - --/* Relax LONGJUMP3 relocation for nds32_elf_relax_section. */ -+/* Relax LONGJUMP3 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -9476,42 +10917,42 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - /* There are 5 variations for LONGJUMP3 - case 1: 2-4-4-2; 1st insn convertible, 16-bit on, - optimize off or optimize for space -- bnes38 rt, ra, $1 ; LONGJUMP3 -- sethi ta, hi20(symbol) ; HI20 -+ bnes38 rt, ra, $1 ; LONGJUMP3 -+ sethi ta, hi20(symbol) ; HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jr5 ta ; -- $1: ; -+ jr5 ta ; -+ $1: ; - - case 2: 2-4-4-2; 1st insn convertible, 16-bit on, optimize for speed -- bnes38 rt, ra, $1 ; LONGJUMP3 -- sethi ta, hi20(symbol) ; HI20 -+ bnes38 rt, ra, $1 ; LONGJUMP3 -+ sethi ta, hi20(symbol) ; HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jr5 ta ; -- $1: ; LABEL -+ jr5 ta ; -+ $1: ; LABEL - - case 3: 4-4-4-2; 1st insn not convertible, 16-bit on, - optimize off or optimize for space -- bne rt, ra, $1 ; LONGJUMP3 -- sethi ta, hi20(symbol) ; HI20 -+ bne rt, ra, $1 ; LONGJUMP3 -+ sethi ta, hi20(symbol) ; HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jr5 ta ; -- $1: ; -+ jr5 ta ; -+ $1: ; - - case 4: 4-4-4-4; 1st insn don't care, 16-bit off, optimize don't care - 16-bit off if no INSN16 -- bne rt, ra, $1 ; LONGJUMP3 -- sethi ta, hi20(symbol) ; HI20 -+ bne rt, ra, $1 ; LONGJUMP3 -+ sethi ta, hi20(symbol) ; HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jr ta ; -- $1: ; -+ jr ta ; -+ $1: ; - - case 5: 4-4-4-4; 1st insn not convertible, 16-bit on, optimize for speed - 16-bit off if no INSN16 -- bne rt, ra, $1 ; LONGJUMP3 -- sethi ta, hi20(symbol) ; HI20 -+ bne rt, ra, $1 ; LONGJUMP3 -+ sethi ta, hi20(symbol) ; HI20 - ori ta, ta, lo12(symbol) ; LO12S0 -- jr ta ; -- $1: ; LABEL */ -+ jr ta ; -+ $1: ; LABEL */ - - /* Get the reloc for the address from which the register is - being loaded. This reloc will tell us which function is -@@ -9523,7 +10964,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - bfd_vma laddr; - int seq_len; /* Original length of instruction sequence. */ - Elf_Internal_Rela *hi_irelfn, *lo_irelfn, *cond_irelfn, *irelend; -- int pic_ext_target = 0, first_size; -+ int first_size; - unsigned int i; - bfd_signed_vma foff; - uint32_t insn, re_insn = 0; -@@ -9551,7 +10992,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - R_NDS32_LO12S0_ORI_RELA, - laddr + first_size + 4); - -- for (i = 0; i < sizeof (checked_types) / sizeof (checked_types[0]); i++) -+ for (i = 0; i < ARRAY_SIZE (checked_types); i++) - { - cond_irelfn = - find_relocs_at_address_addr (irel, internal_relocs, irelend, -@@ -9562,16 +11003,16 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (hi_irelfn == irelend || lo_irelfn == irelend || cond_irelfn == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP3", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGJUMP3 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr); - -- if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 -+ if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 - || foff >= CONSERVATIVE_24BIT_S1) - return FALSE; - -@@ -9624,7 +11065,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - && (foff >= -(ACCURATE_14BIT_S1 - first_size) - && foff < ACCURATE_14BIT_S1 - first_size)) - { -- /* beqs label ; 15_PCREL */ -+ /* beqs label ; 15_PCREL */ - bfd_putb32 (re_insn, contents + irel->r_offset); - *insn_len = 4; - reloc = R_NDS32_15_PCREL_RELA; -@@ -9635,7 +11076,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - && foff >= -CONSERVATIVE_16BIT_S1 - && foff < CONSERVATIVE_16BIT_S1) - { -- /* beqz label ; 17_PCREL */ -+ /* beqz label ; 17_PCREL */ - bfd_putb32 (re_insn, contents + irel->r_offset); - *insn_len = 4; - reloc = R_NDS32_17_PCREL_RELA; -@@ -9661,7 +11102,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - case 4-4; 1st insn convertible, 16-bit on, optimize for speed - bne rt, ra, $1 ; LONGJUMP2 - j label ; 25_PCREL -- $1 */ -+ $1 */ - - /* Offset for first instruction. */ - -@@ -9711,7 +11152,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - --/* Relax LONGCALL4 relocation for nds32_elf_relax_section. */ -+/* Relax LONGCALL4 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -9728,7 +11169,6 @@ nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - uint32_t insn; - Elf_Internal_Rela *hi_irel, *ptr_irel, *insn_irel, *em_irel, *call_irel; - Elf_Internal_Rela *irelend; -- int pic_ext_target = 0; - bfd_signed_vma foff; - - irelend = internal_relocs + sec->reloc_count; -@@ -9742,21 +11182,21 @@ nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (hi_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL4", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGCALL4 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, hi_irel, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, hi_irel, isymbuf, symtab_hdr); - - /* This condition only happened when symbol is undefined. */ -- if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 -+ if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 - || foff >= CONSERVATIVE_24BIT_S1) - return FALSE; - -- /* Relax to: jal symbol; 25_PCREL */ -+ /* Relax to: jal symbol; 25_PCREL */ - /* For simplicity of coding, we are going to modify the section - contents, the section relocs, and the BFD symbol table. We - must tell the rest of the code not to free up this -@@ -9772,8 +11212,9 @@ nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (ptr_irel == irelend || em_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL4", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGCALL4 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - /* Check these is enough space to insert jal in R_NDS32_EMPTY. */ -@@ -9812,7 +11253,7 @@ nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - --/* Relax LONGCALL5 relocation for nds32_elf_relax_section. */ -+/* Relax LONGCALL5 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longcall5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -9828,7 +11269,6 @@ nds32_elf_relax_longcall5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - bfd_vma laddr; - uint32_t insn; - Elf_Internal_Rela *cond_irel, *irelend; -- int pic_ext_target = 0; - bfd_signed_vma foff; - - irelend = internal_relocs + sec->reloc_count; -@@ -9843,21 +11283,21 @@ nds32_elf_relax_longcall5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - R_NDS32_25_PCREL_RELA, irel->r_addend); - if (cond_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL5", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGCALL5 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr); - - if (foff == 0 || foff < -CONSERVATIVE_16BIT_S1 - || foff >= CONSERVATIVE_16BIT_S1) - return FALSE; - - /* Relax to bgezal rt, label ; 17_PCREL -- or bltzal rt, label ; 17_PCREL */ -+ or bltzal rt, label ; 17_PCREL */ - - /* Convert to complimentary conditional call. */ - insn = CONVERT_CONDITION_CALL (insn); -@@ -9889,7 +11329,7 @@ nds32_elf_relax_longcall5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - --/* Relax LONGCALL6 relocation for nds32_elf_relax_section. */ -+/* Relax LONGCALL6 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -9907,7 +11347,6 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - bfd_vma laddr; - uint32_t insn; - Elf_Internal_Rela *em_irel, *cond_irel, *irelend; -- int pic_ext_target = 0; - bfd_signed_vma foff; - - irelend = internal_relocs + sec->reloc_count; -@@ -9921,16 +11360,16 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (em_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL6", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGCALL6 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, em_irel, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, em_irel, isymbuf, symtab_hdr); - -- if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 -+ if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 - || foff >= CONSERVATIVE_24BIT_S1) - return FALSE; - -@@ -9943,7 +11382,7 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - if (foff >= -CONSERVATIVE_16BIT_S1 && foff < CONSERVATIVE_16BIT_S1) - { - /* Relax to bgezal rt, label ; 17_PCREL -- or bltzal rt, label ; 17_PCREL */ -+ or bltzal rt, label ; 17_PCREL */ - - /* Convert to complimentary conditional call. */ - *insn_len = 0; -@@ -9959,8 +11398,9 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - R_NDS32_PTR_RESOLVED, irel->r_addend); - if (cond_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, -- "R_NDS32_LONGCALL6", irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGCALL6 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - cond_irel->r_addend = 1; -@@ -10008,8 +11448,9 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - R_NDS32_PTR_RESOLVED, irel->r_addend); - if (cond_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, -- "R_NDS32_LONGCALL6", irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGCALL6 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - cond_irel->r_addend = 1; -@@ -10024,7 +11465,7 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - --/* Relax LONGJUMP4 relocation for nds32_elf_relax_section. */ -+/* Relax LONGJUMP4 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -10041,7 +11482,6 @@ nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - int seq_len; /* Original length of instruction sequence. */ - uint32_t insn; - Elf_Internal_Rela *hi_irel, *ptr_irel, *em_irel, *call_irel, *irelend; -- int pic_ext_target = 0; - bfd_signed_vma foff; - - irelend = internal_relocs + sec->reloc_count; -@@ -10058,21 +11498,21 @@ nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (hi_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP4", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGJUMP4 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, hi_irel, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, hi_irel, isymbuf, symtab_hdr); - -- if (pic_ext_target || foff == 0 || foff >= CONSERVATIVE_24BIT_S1 -+ if (foff == 0 || foff >= CONSERVATIVE_24BIT_S1 - || foff < -CONSERVATIVE_24BIT_S1) - return FALSE; - - /* Convert it to "j label", it may be converted to j8 in the final -- pass of relaxation. Therefore, we do not consider this currently. */ -+ pass of relaxation. Therefore, we do not consider this currently.*/ - ptr_irel = find_relocs_at_address_addr (irel, internal_relocs, irelend, - R_NDS32_PTR_RESOLVED, irel->r_addend); - em_irel = find_relocs_at_address_addr (irel, internal_relocs, irelend, -@@ -10080,8 +11520,9 @@ nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (ptr_irel == irelend || em_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP4", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGJUMP4 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - -@@ -10109,7 +11550,7 @@ nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - --/* Relax LONGJUMP5 relocation for nds32_elf_relax_section. */ -+/* Relax LONGJUMP5 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -10131,7 +11572,6 @@ nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - bfd_vma laddr; - Elf_Internal_Rela *cond_irel, *irelend; -- int pic_ext_target = 0; - unsigned int i; - bfd_signed_vma foff; - uint32_t insn, re_insn = 0; -@@ -10154,16 +11594,16 @@ nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - R_NDS32_25_PCREL_RELA, irel->r_addend); - if (cond_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP5", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGJUMP5 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr); - -- if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_16BIT_S1 -+ if (foff == 0 || foff < -CONSERVATIVE_16BIT_S1 - || foff >= CONSERVATIVE_16BIT_S1) - return FALSE; - -@@ -10208,7 +11648,7 @@ nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - /* Clean relocations. */ - irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_NONE); -- for (i = 0; i < sizeof (checked_types) / sizeof (checked_types[0]); i++) -+ for (i = 0; i < ARRAY_SIZE (checked_types); i++) - { - cond_irel = find_relocs_at_address_addr (irel, internal_relocs, irelend, - checked_types[i], laddr); -@@ -10234,7 +11674,7 @@ nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - --/* Relax LONGJUMP6 relocation for nds32_elf_relax_section. */ -+/* Relax LONGJUMP6 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -10265,7 +11705,6 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - int reloc_off = 0, cond_removed = 0; - bfd_vma laddr; - Elf_Internal_Rela *cond_irel, *em_irel, *irelend, *insn_irel; -- int pic_ext_target = 0; - unsigned int i; - bfd_signed_vma foff; - uint32_t insn, re_insn = 0; -@@ -10283,16 +11722,16 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (em_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP6", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGJUMP6 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, em_irel, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, em_irel, isymbuf, symtab_hdr); - -- if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 -+ if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 - || foff >= CONSERVATIVE_24BIT_S1) - return FALSE; - -@@ -10318,7 +11757,7 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - if (N32_OP6 (re_insn) == N32_OP6_BR1 - && (foff >= -CONSERVATIVE_14BIT_S1 && foff < CONSERVATIVE_14BIT_S1)) - { -- /* beqs label ; 15_PCREL */ -+ /* beqs label ; 15_PCREL */ - bfd_putb32 (re_insn, contents + em_irel->r_offset); - reloc = R_NDS32_15_PCREL_RELA; - cond_removed = 1; -@@ -10326,7 +11765,7 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - else if (N32_OP6 (re_insn) == N32_OP6_BR2 - && foff >= -CONSERVATIVE_16BIT_S1 && foff < CONSERVATIVE_16BIT_S1) - { -- /* beqz label ; 17_PCREL */ -+ /* beqz label ; 17_PCREL */ - bfd_putb32 (re_insn, contents + em_irel->r_offset); - reloc = R_NDS32_17_PCREL_RELA; - cond_removed = 1; -@@ -10383,7 +11822,7 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - /* Clear relocations. */ - irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_NONE); - -- for (i = 0; i < sizeof (checked_types) / sizeof (checked_types[0]); i++) -+ for (i = 0; i < ARRAY_SIZE (checked_types); i++) - { - cond_irel = - find_relocs_at_address_addr (irel, internal_relocs, irelend, -@@ -10415,7 +11854,7 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - --/* Relax LONGJUMP7 relocation for nds32_elf_relax_section. */ -+/* Relax LONGJUMP7 relocation for nds32_elf_relax_section.*/ - - static bfd_boolean - nds32_elf_relax_longjump7 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, -@@ -10435,7 +11874,6 @@ nds32_elf_relax_longjump7 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - bfd_vma laddr; - Elf_Internal_Rela *cond_irel, *irelend, *insn_irel; -- int pic_ext_target = 0; - bfd_signed_vma foff; - uint32_t insn, re_insn = 0; - uint16_t insn16; -@@ -10453,16 +11891,16 @@ nds32_elf_relax_longjump7 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - R_NDS32_15_PCREL_RELA, irel->r_addend); - if (cond_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP7", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LONGJUMP7 points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); - return FALSE; - } - - /* Get the value of the symbol referred to by the reloc. */ -- foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr, -- &pic_ext_target); -+ foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr); - -- if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_8BIT_S1 -+ if (foff == 0 || foff < -CONSERVATIVE_8BIT_S1 - || foff >= CONSERVATIVE_8BIT_S1) - return FALSE; - -@@ -10516,6 +11954,123 @@ nds32_elf_relax_longjump7 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - return TRUE; - } - -+/* Record the offset to gp, and check if it changed after relaxing. -+ If the offset is fixed or the offset is near enough, try to relax -+ the pattern. This is avoid truncated to fit when relaxing fixed -+ address symbol. Ex: _stack. */ -+static bfd_boolean -+nds32_elf_relax_guard (bfd_vma *access_addr, bfd_vma local_sda, asection *sec, -+ Elf_Internal_Rela *irel, bfd_boolean *again, -+ bfd_boolean init, -+ struct elf_nds32_link_hash_table *table, -+ Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr) -+ -+{ -+ /* The default linker script value. */ -+ int offset_to_gp; -+ static bfd_boolean sec_pass = FALSE; -+ static asection *first_sec = NULL, *sym_sec; -+ /* Record the number of instructions which may be removed. */ -+ static int count = 0, record_count; -+ Elf_Internal_Sym *isym; -+ struct elf_link_hash_entry *h = NULL; -+ int indx; -+ unsigned long r_symndx; -+ bfd *abfd = sec->owner; -+ static bfd_vma record_sda = 0; -+ int sda_offset = 0; -+ -+ /* Force doing relaxation when hyper-relax is high. */ -+ if (table->hyper_relax == 2) -+ return TRUE; -+ -+ /* Record the first section to get the round. */ -+ if (init) -+ { -+ if (!first_sec) -+ first_sec = sec; -+ else if (first_sec == sec) -+ { -+ record_count = count; -+ count = 0; -+ sec_pass = TRUE; -+ } -+ -+ if (!sec_pass) -+ *again = TRUE; -+ -+ return TRUE; -+ } -+ -+ if (record_sda == 0) -+ record_sda = local_sda; -+ else if (local_sda > record_sda) -+ /* In normal case, SDA is fixed or smaller except there is -+ DATA_SEGMENT_ALIGN in linker script.*/ -+ sda_offset = local_sda - record_sda; -+ -+ /* Although we doesn't delete all instructions here, counting all of -+ them to be conservative. */ -+ count++; -+ -+ r_symndx = ELF32_R_SYM (irel->r_info); -+ /* Global symbols. */ -+ if (r_symndx >= symtab_hdr->sh_info) -+ { -+ indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; -+ h = elf_sym_hashes (abfd)[indx]; -+ sym_sec = h->root.u.def.section; -+ if (NDS32_GUARD_SEC_P (sym_sec->flags) -+ || bfd_is_abs_section (sym_sec)) -+ { -+ /* Forbid doing relaxation when hyper-relax is low. */ -+ if (table->hyper_relax == 0) -+ return FALSE; -+ -+ offset_to_gp = *access_addr - local_sda; -+ if (elf32_nds32_hash_entry (h)->offset_to_gp == 0) -+ elf32_nds32_hash_entry (h)->offset_to_gp = offset_to_gp; -+ else if (abs (elf32_nds32_hash_entry (h)->offset_to_gp) -+ < abs (offset_to_gp) - sda_offset) -+ { -+ if (*access_addr >= local_sda) -+ *access_addr += (record_count * 4); -+ else -+ *access_addr -= (record_count * 4); -+ } -+ return sec_pass; -+ } -+ } -+ else -+ { -+ if (!elf32_nds32_allocate_local_sym_info (abfd)) -+ return FALSE; -+ isym = isymbuf + r_symndx; -+ -+ sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); -+ if (NDS32_GUARD_SEC_P (sym_sec->flags)) -+ { -+ /* Forbid doing relaxation when hyper-relax is low. */ -+ if (table->hyper_relax == 0) -+ return FALSE; -+ -+ offset_to_gp = *access_addr - local_sda; -+ if (elf32_nds32_local_gp_offset (abfd)[r_symndx] == 0) -+ elf32_nds32_local_gp_offset (abfd)[r_symndx] = offset_to_gp; -+ else if (abs (elf32_nds32_local_gp_offset (abfd)[r_symndx]) -+ < abs (offset_to_gp) - sda_offset) -+ { -+ if (*access_addr >= local_sda) -+ *access_addr += (record_count * 4); -+ else -+ *access_addr -= (record_count * 4); -+ } -+ return sec_pass; -+ } -+ } -+ -+ return TRUE; -+} - #define GET_LOADSTORE_RANGE(addend) (((addend) >> 8) & 0x3f) - - /* Relax LOADSTORE relocation for nds32_elf_relax_section. */ -@@ -10525,21 +12080,24 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, - asection *sec, Elf_Internal_Rela *irel, - Elf_Internal_Rela *internal_relocs, int *insn_len, - bfd_byte *contents, Elf_Internal_Sym *isymbuf, -- Elf_Internal_Shdr *symtab_hdr, int load_store_relax) -+ Elf_Internal_Shdr *symtab_hdr, int load_store_relax, -+ struct elf_nds32_link_hash_table *table) - { -- int eliminate_sethi = 0, range_type; -- unsigned int i; -+ int eliminate_sethi = 0, range_type, i; - bfd_vma local_sda, laddr; - int seq_len; /* Original length of instruction sequence. */ - uint32_t insn; - Elf_Internal_Rela *hi_irelfn = NULL, *irelend; - bfd_vma access_addr = 0; - bfd_vma range_l = 0, range_h = 0; /* Upper/lower bound. */ -+ struct elf_link_hash_entry *h = NULL; -+ int indx; - enum elf_nds32_reloc_type checked_types[] = - { R_NDS32_HI20_RELA, R_NDS32_GOT_HI20, - R_NDS32_GOTPC_HI20, R_NDS32_GOTOFF_HI20, - R_NDS32_PLTREL_HI20, R_NDS32_PLT_GOTREL_HI20, -- R_NDS32_TLS_LE_HI20 -+ R_NDS32_TLS_LE_HI20, R_NDS32_TLS_IE_HI20, -+ R_NDS32_TLS_IEGP_HI20, R_NDS32_TLS_DESC_HI20 - }; - - irelend = internal_relocs + sec->reloc_count; -@@ -10548,7 +12106,7 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, - *insn_len = seq_len; - - /* Get the high part relocation. */ -- for (i = 0; i < ARRAY_SIZE (checked_types); i++) -+ for (i = 0; (unsigned) i < ARRAY_SIZE (checked_types); i++) - { - hi_irelfn = find_relocs_at_address_addr (irel, internal_relocs, irelend, - checked_types[i], laddr); -@@ -10558,9 +12116,12 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, - - if (hi_irelfn == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LOADSTORE", -- irel->r_offset); -- return FALSE; -+ /* Not R_NDS32_HI20_RELA. */ -+ if (i != 0) -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_LOADSTORE points to unrecognized " -+ "reloc at 0x%lx.", abfd, (long) irel->r_offset); -+ return FALSE; - } - - range_type = GET_LOADSTORE_RANGE (irel->r_addend); -@@ -10574,39 +12135,41 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, - access_addr = - calculate_memory_address (abfd, hi_irelfn, isymbuf, symtab_hdr); - -- if (range_type == NDS32_LOADSTORE_IMM) -+ if (ELF32_R_SYM (hi_irelfn->r_info) >= symtab_hdr->sh_info) - { -- struct elf_link_hash_entry *h = NULL; -- int indx; -- -- if (ELF32_R_SYM (hi_irelfn->r_info) >= symtab_hdr->sh_info) -- { -- indx = ELF32_R_SYM (hi_irelfn->r_info) - symtab_hdr->sh_info; -- h = elf_sym_hashes (abfd)[indx]; -- } -+ indx = ELF32_R_SYM (hi_irelfn->r_info) - symtab_hdr->sh_info; -+ h = elf_sym_hashes (abfd)[indx]; -+ } - -+ /* Try movi. */ -+ if (range_type == NDS32_LOADSTORE_IMM) -+ { - if ((access_addr < CONSERVATIVE_20BIT) - && (!h || (h && strcmp (h->root.root.string, FP_BASE_NAME) != 0))) - { - eliminate_sethi = 1; - break; - } -+ } - -- /* This is avoid to relax symbol address which is fixed -- relocations. Ex: _stack. */ -- if (h && bfd_is_abs_section (h->root.u.def.section)) -- return FALSE; -+ if (h && strcmp (h->root.root.string, FP_BASE_NAME) == 0) -+ { -+ eliminate_sethi = 1; -+ break; - } -+ else if (!nds32_elf_relax_guard (&access_addr, local_sda, sec, hi_irelfn, -+ NULL, FALSE, table, isymbuf, symtab_hdr)) -+ return FALSE; - - if (!load_store_relax) - return FALSE; - - /* Case for set gp register. */ - if (N32_RT5 (insn) == REG_GP) -- break; -+ return FALSE; - - if (range_type == NDS32_LOADSTORE_FLOAT_S -- || range_type == NDS32_LOADSTORE_FLOAT_D) -+ || range_type == NDS32_LOADSTORE_FLOAT_S) - { - range_l = sdata_range[0][0]; - range_h = sdata_range[0][1]; -@@ -10618,57 +12181,6 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, - } - break; - -- case R_NDS32_GOT_HI20: -- access_addr = -- calculate_got_memory_address (abfd, link_info, hi_irelfn, symtab_hdr); -- -- /* If this symbol is not in .got, the return value will be -1. -- Since the gp value is set to SDA_BASE but not GLOBAL_OFFSET_TABLE, -- a negative offset is allowed. */ -- if ((bfd_signed_vma) (access_addr - local_sda) < CONSERVATIVE_20BIT -- && (bfd_signed_vma) (access_addr - local_sda) >= -CONSERVATIVE_20BIT) -- eliminate_sethi = 1; -- break; -- -- case R_NDS32_PLT_GOTREL_HI20: -- access_addr = calculate_plt_memory_address (abfd, link_info, isymbuf, -- hi_irelfn, symtab_hdr); -- -- if ((bfd_signed_vma) (access_addr - local_sda) < CONSERVATIVE_20BIT -- && (bfd_signed_vma) (access_addr - local_sda) >= -CONSERVATIVE_20BIT) -- eliminate_sethi = 1; -- break; -- -- case R_NDS32_GOTOFF_HI20: -- access_addr = -- calculate_memory_address (abfd, hi_irelfn, isymbuf, symtab_hdr); -- -- if ((bfd_signed_vma) (access_addr - local_sda) < CONSERVATIVE_20BIT -- && (bfd_signed_vma) (access_addr - local_sda) >= -CONSERVATIVE_20BIT) -- eliminate_sethi = 1; -- break; -- -- case R_NDS32_GOTPC_HI20: -- /* The access_addr must consider r_addend of hi_irel. */ -- access_addr = sec->output_section->vma + sec->output_offset -- + irel->r_offset + hi_irelfn->r_addend; -- -- if ((bfd_signed_vma) (local_sda - access_addr) < CONSERVATIVE_20BIT -- && (bfd_signed_vma) (local_sda - access_addr) >= -CONSERVATIVE_20BIT) -- eliminate_sethi = 1; -- break; -- -- case R_NDS32_TLS_LE_HI20: -- access_addr = -- calculate_memory_address (abfd, hi_irelfn, isymbuf, symtab_hdr); -- BFD_ASSERT (elf_hash_table (link_info)->tls_sec != NULL); -- access_addr -= (elf_hash_table (link_info)->tls_sec->vma + TP_OFFSET); -- if ((range_type == NDS32_LOADSTORE_IMM) -- && (bfd_signed_vma) (access_addr) < CONSERVATIVE_20BIT -- && (bfd_signed_vma) (access_addr) >= -CONSERVATIVE_20BIT) -- eliminate_sethi = 1; -- break; -- - default: - return FALSE; - } -@@ -10683,17 +12195,20 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, - irel->r_info = - ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_NONE); - *insn_len = 0; -+ return TRUE; - } -- return TRUE; -+ -+ return FALSE; - } - --/* Relax LO12 relocation for nds32_elf_relax_section. */ -+/* Relax LO12 relocation for nds32_elf_relax_section.*/ - - static void - nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, - asection *sec, Elf_Internal_Rela *irel, - Elf_Internal_Rela *internal_relocs, bfd_byte *contents, -- Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr) -+ Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr, -+ struct elf_nds32_link_hash_table *table) - { - uint32_t insn; - bfd_vma local_sda, laddr; -@@ -10723,6 +12238,7 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, - h = elf_sym_hashes (abfd)[indx]; - } - -+ /* Try movi. */ - if (N32_OP6 (insn) == N32_OP6_ORI && access_addr < CONSERVATIVE_20BIT - && (!h || (h && strcmp (h->root.root.string, FP_BASE_NAME) != 0))) - { -@@ -10731,13 +12247,14 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, - insn = N32_TYPE1 (MOVI, N32_RT5 (insn), 0); - bfd_putb32 (insn, contents + laddr); - } -- /* This is avoid to relax symbol address which is fixed -- relocations. Ex: _stack. */ -- else if (N32_OP6 (insn) == N32_OP6_ORI -- && h && bfd_is_abs_section (h->root.u.def.section)) -- return; - else - { -+ if (h && strcmp (h->root.root.string, FP_BASE_NAME) == 0) -+ { /* Fall through. */ } -+ else if (!nds32_elf_relax_guard (&access_addr, local_sda, sec, irel, NULL, -+ FALSE, table, isymbuf, symtab_hdr)) -+ return; -+ - range_l = sdata_range[1][0]; - range_h = sdata_range[1][1]; - switch (ELF32_R_TYPE (irel->r_info)) -@@ -10768,7 +12285,8 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, - /* There are range_h and range_l because linker has to promise - all sections move cross one page together. */ - if ((local_sda <= access_addr && (access_addr - local_sda) < range_h) -- || (local_sda > access_addr && (local_sda - access_addr) <= range_l)) -+ || (local_sda > access_addr && (local_sda - access_addr) <= range_l) -+ || (h && strcmp (h->root.root.string, FP_BASE_NAME) == 0)) - { - if (N32_OP6 (insn) == N32_OP6_ORI && N32_RT5 (insn) == REG_GP) - { -@@ -10790,7 +12308,6 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, - if (irelfn != irelend && reloc != R_NDS32_SDA17S2_RELA) - irelfn->r_info = - ELF32_R_INFO (ELF32_R_SYM (irelfn->r_info), R_NDS32_NONE); -- - } - } - return; -@@ -10798,7 +12315,7 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, - - /* Relax low part of PIC instruction pattern. */ - --static void -+ATTRIBUTE_UNUSED static void - nds32_elf_relax_piclo12 (struct bfd_link_info *link_info, bfd *abfd, - asection *sec, Elf_Internal_Rela *irel, - bfd_byte *contents, Elf_Internal_Sym *isymbuf, -@@ -10855,7 +12372,7 @@ nds32_elf_relax_piclo12 (struct bfd_link_info *link_info, bfd *abfd, - - /* Relax low part of LE TLS instruction pattern. */ - --static void -+ATTRIBUTE_UNUSED static void - nds32_elf_relax_letlslo12 (struct bfd_link_info *link_info, bfd *abfd, - Elf_Internal_Rela *irel, - bfd_byte *contents, Elf_Internal_Sym *isymbuf, -@@ -10885,7 +12402,7 @@ nds32_elf_relax_letlslo12 (struct bfd_link_info *link_info, bfd *abfd, - - /* Relax LE TLS calculate address instruction pattern. */ - --static void -+ATTRIBUTE_UNUSED static void - nds32_elf_relax_letlsadd (struct bfd_link_info *link_info, bfd *abfd, - asection *sec, Elf_Internal_Rela *irel, - Elf_Internal_Rela *internal_relocs, -@@ -10893,9 +12410,9 @@ nds32_elf_relax_letlsadd (struct bfd_link_info *link_info, bfd *abfd, - Elf_Internal_Shdr *symtab_hdr, bfd_boolean *again) - { - /* Local TLS non-pic -- sethi ta, hi20(symbol@tpoff) ; TLS_LE_HI20 -+ sethi ta, hi20(symbol@tpoff) ; TLS_LE_HI20 - ori ta, ta, lo12(symbol@tpoff) ; TLS_LE_LO12 -- add ra, ta, tp ; TLS_LE_ADD */ -+ add ra, ta, tp ; TLS_LE_ADD */ - - uint32_t insn; - bfd_vma laddr; -@@ -10931,14 +12448,13 @@ nds32_elf_relax_letlsadd (struct bfd_link_info *link_info, bfd *abfd, - - /* Relax LE TLS load store instruction pattern. */ - --static void -+ATTRIBUTE_UNUSED static void - nds32_elf_relax_letlsls (struct bfd_link_info *link_info, bfd *abfd, - asection *sec, Elf_Internal_Rela *irel, - Elf_Internal_Rela *internal_relocs, - bfd_byte *contents, Elf_Internal_Sym *isymbuf, - Elf_Internal_Shdr *symtab_hdr, bfd_boolean *again) - { -- - uint32_t insn; - bfd_vma laddr; - bfd_signed_vma foff; -@@ -10970,7 +12486,6 @@ nds32_elf_relax_letlsls (struct bfd_link_info *link_info, bfd *abfd, - success = 1; - break; - } -- /* Fall through. */ - case (N32_OP6_MEM << 8) | N32_MEM_LH: - case (N32_OP6_MEM << 8) | N32_MEM_SH: - case (N32_OP6_MEM << 8) | N32_MEM_LHS: -@@ -10985,7 +12500,6 @@ nds32_elf_relax_letlsls (struct bfd_link_info *link_info, bfd *abfd, - success = 1; - break; - } -- /* Fall through. */ - case (N32_OP6_MEM << 8) | N32_MEM_LW: - case (N32_OP6_MEM << 8) | N32_MEM_SW: - /* The range is +/-64k. */ -@@ -10999,7 +12513,6 @@ nds32_elf_relax_letlsls (struct bfd_link_info *link_info, bfd *abfd, - success = 1; - break; - } -- /* Fall through. */ - default: - break; - } -@@ -11032,8 +12545,9 @@ nds32_elf_relax_ptr (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - if (re_irel == irelend) - { -- _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_PTR", -- irel->r_offset); -+ _bfd_error_handler -+ ("%B: warning: R_NDS32_PTR points to unrecognized reloc at 0x%lx.", -+ abfd, (long) irel->r_offset); - return FALSE; - } - -@@ -11068,7 +12582,7 @@ nds32_elf_relax_ptr (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - - /* Relax PLT_GOT_SUFF relocation for nds32_elf_relax_section. */ - --static void -+ATTRIBUTE_UNUSED static void - nds32_elf_relax_pltgot_suff (struct bfd_link_info *link_info, bfd *abfd, - asection *sec, Elf_Internal_Rela *irel, - Elf_Internal_Rela *internal_relocs, -@@ -11123,7 +12637,7 @@ nds32_elf_relax_pltgot_suff (struct bfd_link_info *link_info, bfd *abfd, - return; - irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), - R_NDS32_PLT_GOTREL_LO19); -- /* addi.gp */ -+ /* addi.gp */ - insn = N32_TYPE1 (SBGP, N32_RT5 (insn), N32_BIT (19)); - } - else if (N32_OP6 (insn) == N32_OP6_JREG -@@ -11153,7 +12667,7 @@ nds32_elf_relax_pltgot_suff (struct bfd_link_info *link_info, bfd *abfd, - - /* Relax GOT_SUFF relocation for nds32_elf_relax_section. */ - --static void -+ATTRIBUTE_UNUSED static void - nds32_elf_relax_got_suff (struct bfd_link_info *link_info, bfd *abfd, - asection *sec, Elf_Internal_Rela *irel, - Elf_Internal_Rela *internal_relocs, -@@ -11200,7 +12714,7 @@ nds32_elf_relax_got_suff (struct bfd_link_info *link_info, bfd *abfd, - - /* Relax PLT_GOT_SUFF relocation for nds32_elf_relax_section. */ - --static void -+ATTRIBUTE_UNUSED static void - nds32_elf_relax_gotoff_suff (struct bfd_link_info *link_info, bfd *abfd, - asection *sec, Elf_Internal_Rela *irel, - Elf_Internal_Rela *internal_relocs, -@@ -11303,6 +12817,85 @@ nds32_elf_relax_gotoff_suff (struct bfd_link_info *link_info, bfd *abfd, - - } - -+/* Relax LWC relocation for nds32_elf_relax_section. */ -+ -+static void -+nds32_elf_relax_flsi (struct bfd_link_info *link_info, bfd *abfd, -+ asection *sec, Elf_Internal_Rela *irel, -+ Elf_Internal_Rela *internal_relocs, -+ bfd_byte *contents, Elf_Internal_Sym *isymbuf, -+ Elf_Internal_Shdr *symtab_hdr, bfd_boolean *again) -+{ -+ /* Pattern for bug-12566 -+ sethi ra, hi20(symbol) ; HI20/LOADSTORE -+ ori ra, ra, lo12(symbol) ; LO12S0/PTR/PTR/.../INSN16 -+ flsi fsa, [ra + offset1] ; LSI/PTR_RESOLVED/INSN16 -+ flsi fsb, [ra + offset2] ; LSI/PTR_RESOLVED/INSN16 -+ ... */ -+ -+ uint32_t insn; -+ bfd_vma local_sda, laddr; -+ unsigned long reloc; -+ bfd_vma access_addr, flsi_offset; -+ bfd_vma range_l = 0, range_h = 0; /* Upper/lower bound. */ -+ Elf_Internal_Rela *irelend, *re_irel; -+ unsigned int opcode; -+ -+ irelend = internal_relocs + sec->reloc_count; -+ laddr = irel->r_offset; -+ insn = bfd_getb32 (contents + laddr); -+ -+ if ((insn & 0x80000000) || !is_sda_access_insn (insn)) -+ return; -+ -+ /* Can not do relaxation for bi format. */ -+ if ((insn & 0x1000)) -+ return; -+ -+ /* Only deal with flsi, fssi, fldi, fsdi, so far. */ -+ opcode = N32_OP6 (insn); -+ if ((opcode == N32_OP6_LWC) || (opcode == N32_OP6_SWC)) -+ reloc = R_NDS32_SDA12S2_SP_RELA; -+ else if ((opcode == N32_OP6_LDC) || (opcode == N32_OP6_SDC)) -+ reloc = R_NDS32_SDA12S2_DP_RELA; -+ else -+ return; -+ -+ re_irel = find_relocs_at_address (irel, internal_relocs, irelend, -+ R_NDS32_PTR_RESOLVED); -+ if (re_irel == irelend) -+ { -+ _bfd_error_handler -+ ("%pB: warning: R_NDS32_LSI has no R_NDS32_PTR_RESOLVED at 0x%lx.", -+ abfd, (long) irel->r_offset); -+ return; -+ } -+ -+ /* For SDA base relative relaxation. */ -+ nds32_elf_final_sda_base (sec->output_section->owner, link_info, -+ &local_sda, FALSE); -+ access_addr = calculate_memory_address (abfd, irel, isymbuf, symtab_hdr); -+ flsi_offset = (insn & 0xfff) << 2; -+ access_addr += flsi_offset; -+ range_l = sdata_range[0][0]; -+ range_h = sdata_range[0][1]; -+ -+ if ((local_sda <= access_addr && (access_addr - local_sda) < range_h) -+ || (local_sda > access_addr && (local_sda - access_addr) <= range_l)) -+ { -+ /* Turn flsi instruction into sda access format. */ -+ insn = (insn & 0x7ff07000) | (REG_GP << 15); -+ -+ /* Add relocation type to flsi. */ -+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), reloc); -+ irel->r_addend += flsi_offset; -+ bfd_putb32 (insn, contents + re_irel->r_offset); -+ -+ re_irel->r_addend |= 1; -+ *again = TRUE; -+ } -+} -+ - static bfd_boolean - nds32_relax_adjust_label (bfd *abfd, asection *sec, - Elf_Internal_Rela *internal_relocs, -@@ -11387,9 +12980,11 @@ nds32_relax_adjust_label (bfd *abfd, asection *sec, - { - /* Remove all LABEL relocation from label_rel to tmp_rel - including relocations with same offset as tmp_rel. */ -- for (tmp2_rel = label_rel; tmp2_rel < tmp_rel -- || tmp2_rel->r_offset == tmp_rel->r_offset; tmp2_rel++) -+ for (tmp2_rel = label_rel; tmp2_rel < tmp_rel; tmp2_rel++) - { -+ if (tmp2_rel->r_offset == tmp_rel->r_offset) -+ break; -+ - if (ELF32_R_TYPE (tmp2_rel->r_info) == R_NDS32_LABEL - && tmp2_rel->r_addend < 2) - tmp2_rel->r_info = -@@ -11416,7 +13011,8 @@ nds32_relax_adjust_label (bfd *abfd, asection *sec, - We may convert a 16-bit instruction right before a label to - 32-bit, in order to align the label if necessary - all reloc entries has been sorted by r_offset. */ -- for (irel = internal_relocs; irel < irelend; irel++) -+ for (irel = internal_relocs; -+ irel < irelend && irel->r_offset < sec->size; irel++) - { - if (ELF32_R_TYPE (irel->r_info) != R_NDS32_INSN16 - && ELF32_R_TYPE (irel->r_info) != R_NDS32_LABEL) -@@ -11568,118 +13164,6 @@ nds32_relax_adjust_label (bfd *abfd, asection *sec, - return TRUE; - } - --/* Pick relaxation round. */ -- --static int --nds32_elf_pick_relax (bfd_boolean init, asection *sec, bfd_boolean *again, -- struct elf_nds32_link_hash_table *table, -- struct bfd_link_info *link_info) --{ -- static asection *final_sec, *first_sec = NULL; -- static bfd_boolean normal_again = FALSE; -- static bfd_boolean set = FALSE; -- static bfd_boolean first = TRUE; -- int round_table[] = { -- NDS32_RELAX_NORMAL_ROUND, -- NDS32_RELAX_JUMP_IFC_ROUND, -- NDS32_RELAX_EX9_BUILD_ROUND, -- NDS32_RELAX_EX9_REPLACE_ROUND, -- }; -- static int pass = 0; -- static int relax_round; -- -- /* The new round. */ -- if (init && first_sec == sec) -- { -- set = TRUE; -- normal_again = FALSE; -- } -- -- if (first) -- { -- /* Run an empty run to get the final section. */ -- relax_round = NDS32_RELAX_EMPTY_ROUND; -- -- /* It has to enter relax again because we can -- not make sure what the final turn is. */ -- *again = TRUE; -- -- first = FALSE; -- first_sec = sec; -- } -- -- if (!set) -- { -- /* Not reenter yet. */ -- final_sec = sec; -- return relax_round; -- } -- -- relax_round = round_table[pass]; -- -- if (!init && relax_round == NDS32_RELAX_NORMAL_ROUND && *again) -- normal_again = TRUE; -- -- if (!init && final_sec == sec) -- { -- switch (relax_round) -- { -- case NDS32_RELAX_NORMAL_ROUND: -- if (!normal_again) -- { -- /* Normal relaxation done. */ -- if (table->target_optimize & NDS32_RELAX_JUMP_IFC_ON) -- { -- pass++; -- *again = TRUE; -- } -- else if (table->target_optimize & NDS32_RELAX_EX9_ON) -- { -- pass += 2; /* NDS32_RELAX_EX9_BUILD_ROUND */ -- *again = TRUE; -- } -- else if (table->ex9_import_file) -- { -- /* Import ex9 table. */ -- if (table->update_ex9_table) -- pass += 2; /* NDS32_RELAX_EX9_BUILD_ROUND */ -- else -- pass += 3; /* NDS32_RELAX_EX9_REPLACE_ROUND */ -- nds32_elf_ex9_import_table (link_info); -- *again = TRUE; -- } -- } -- break; -- case NDS32_RELAX_JUMP_IFC_ROUND: -- if (!nds32_elf_ifc_finish (link_info)) -- _bfd_error_handler (_("error: Jump IFC Fail.")); -- if (table->target_optimize & NDS32_RELAX_EX9_ON) -- { -- pass++; -- *again = TRUE; -- } -- break; -- case NDS32_RELAX_EX9_BUILD_ROUND: -- nds32_elf_ex9_finish (link_info); -- pass++; -- *again = TRUE; -- break; -- case NDS32_RELAX_EX9_REPLACE_ROUND: -- if (table->target_optimize & NDS32_RELAX_JUMP_IFC_ON) -- { -- /* Do jump IFC optimization again. */ -- if (!nds32_elf_ifc_finish (link_info)) -- _bfd_error_handler (_("error: Jump IFC Fail.")); -- } -- break; -- default: -- break; -- } -- } -- -- return relax_round; --} -- - static bfd_boolean - nds32_elf_relax_section (bfd *abfd, asection *sec, - struct bfd_link_info *link_info, bfd_boolean *again) -@@ -11697,26 +13181,25 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, - uint32_t insn; - uint16_t insn16; - -- /* Target dependnet option. */ -+ /* Target dependent option. */ - struct elf_nds32_link_hash_table *table; - int load_store_relax; -- int relax_round; - - relax_blank_list = NULL; -- - *again = FALSE; - - /* Nothing to do for -- * relocatable link or -- * non-relocatable section or -- * non-code section or -- * empty content or -- * no reloc entry. */ -+ relocatable link or -+ non-relocatable section or -+ non-code section or -+ empty content or -+ no reloc entry. */ - if (bfd_link_relocatable (link_info) - || (sec->flags & SEC_RELOC) == 0 -- || (sec->flags & SEC_EXCLUDE) != 0 -+ || (sec->flags & SEC_EXCLUDE) == 1 - || (sec->flags & SEC_CODE) == 0 -- || sec->size == 0) -+ || sec->size == 0 -+ || sec->reloc_count == 0) - return TRUE; - - /* 09.12.11 Workaround. */ -@@ -11725,44 +13208,14 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, - if (sec->alignment_power > 2) - return TRUE; - -+#ifdef NDS32_LINUX_TOOLCHAIN -+ /* Do TLS model conversion once at first. */ -+ nds32_elf_unify_tls_model (abfd, sec, contents, link_info); -+#endif -+ - /* The optimization type to do. */ - - table = nds32_elf_hash_table (link_info); -- relax_round = nds32_elf_pick_relax (TRUE, sec, again, table, link_info); -- switch (relax_round) -- { -- case NDS32_RELAX_JUMP_IFC_ROUND: -- /* Here is the entrance of ifc jump relaxation. */ -- if (!nds32_elf_ifc_calc (link_info, abfd, sec)) -- return FALSE; -- nds32_elf_pick_relax (FALSE, sec, again, table, link_info); -- return TRUE; -- -- case NDS32_RELAX_EX9_BUILD_ROUND: -- /* Here is the entrance of ex9 relaxation. There are two pass of -- ex9 relaxation. The one is to traverse all instructions and build -- the hash table. The other one is to compare instructions and replace -- it by ex9.it. */ -- if (!nds32_elf_ex9_build_hash_table (abfd, sec, link_info)) -- return FALSE; -- nds32_elf_pick_relax (FALSE, sec, again, table, link_info); -- return TRUE; -- -- case NDS32_RELAX_EX9_REPLACE_ROUND: -- if (!nds32_elf_ex9_replace_instruction (link_info, abfd, sec)) -- return FALSE; -- return TRUE; -- -- case NDS32_RELAX_EMPTY_ROUND: -- nds32_elf_pick_relax (FALSE, sec, again, table, link_info); -- return TRUE; -- -- case NDS32_RELAX_NORMAL_ROUND: -- default: -- if (sec->reloc_count == 0) -- return TRUE; -- break; -- } - - /* The begining of general relaxation. */ - -@@ -11775,20 +13228,10 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, - relax_range_measurement (abfd); - } - -- if (is_ITB_BASE_set == 0) -- { -- /* Set the _ITB_BASE_. */ -- if (!nds32_elf_ex9_itb_base (link_info)) -- { -- _bfd_error_handler (_("%B: error: Cannot set _ITB_BASE_"), abfd); -- bfd_set_error (bfd_error_bad_value); -- } -- } -- - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - /* Relocations MUST be kept in memory, because relaxation adjust them. */ - internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, -- TRUE /* keep_memory */); -+ TRUE /* keep_memory */); - if (internal_relocs == NULL) - goto error_return; - -@@ -11802,10 +13245,7 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, - if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY) - { - if (irel->r_addend & R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG) -- { -- nds32_elf_pick_relax (FALSE, sec, again, table, link_info); -- return TRUE; -- } -+ return TRUE; - - if (irel->r_addend & R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG) - optimize = 1; -@@ -11888,7 +13328,8 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, - || ELF32_R_TYPE (irel->r_info) == R_NDS32_17IFC_PCREL_RELA - || ELF32_R_TYPE (irel->r_info) == R_NDS32_TLS_LE_LO12 - || ELF32_R_TYPE (irel->r_info) == R_NDS32_TLS_LE_ADD -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_TLS_LE_LS) -+ || ELF32_R_TYPE (irel->r_info) == R_NDS32_TLS_LE_LS -+ || ELF32_R_TYPE (irel->r_info) == R_NDS32_LSI) - seq_len = 0; - else - continue; -@@ -11967,71 +13408,41 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, - removed = nds32_elf_relax_loadstore (link_info, abfd, sec, irel, - internal_relocs, &insn_len, - contents, isymbuf, symtab_hdr, -- load_store_relax); -+ load_store_relax, table); - break; - case R_NDS32_LO12S0_RELA: - case R_NDS32_LO12S1_RELA: -+ case R_NDS32_LO12S2_RELA: - case R_NDS32_LO12S2_DP_RELA: - case R_NDS32_LO12S2_SP_RELA: -- case R_NDS32_LO12S2_RELA: - /* Relax for low part. */ - nds32_elf_relax_lo12 (link_info, abfd, sec, irel, internal_relocs, -- contents, isymbuf, symtab_hdr); -+ contents, isymbuf, symtab_hdr, table); - - /* It is impossible to delete blank, so just continue. */ - continue; -+ case R_NDS32_PTR: -+ removed = nds32_elf_relax_ptr (abfd, sec, irel, internal_relocs, -+ &insn_len, &seq_len, contents); -+ break; -+ case R_NDS32_LSI: -+ nds32_elf_relax_flsi (link_info, abfd, sec, irel, internal_relocs, -+ contents, isymbuf, symtab_hdr, again); -+ continue; - case R_NDS32_GOT_LO12: - case R_NDS32_GOTOFF_LO12: - case R_NDS32_PLTREL_LO12: - case R_NDS32_PLT_GOTREL_LO12: - case R_NDS32_GOTPC_LO12: -- /* Relax for PIC gp-relative low part. */ -- nds32_elf_relax_piclo12 (link_info, abfd, sec, irel, contents, -- isymbuf, symtab_hdr); -- -- /* It is impossible to delete blank, so just continue. */ -- continue; - case R_NDS32_TLS_LE_LO12: -- /* Relax for LE TLS low part. */ -- nds32_elf_relax_letlslo12 (link_info, abfd, irel, contents, -- isymbuf, symtab_hdr); -- -- /* It is impossible to delete blank, so just continue. */ -- continue; - case R_NDS32_TLS_LE_ADD: -- nds32_elf_relax_letlsadd (link_info, abfd, sec, irel, internal_relocs, -- contents, isymbuf, symtab_hdr, again); -- /* It is impossible to delete blank, so just continue. */ -- continue; - case R_NDS32_TLS_LE_LS: -- nds32_elf_relax_letlsls (link_info, abfd, sec, irel, internal_relocs, -- contents, isymbuf, symtab_hdr, again); -- continue; -- case R_NDS32_PTR: -- removed = nds32_elf_relax_ptr (abfd, sec, irel, internal_relocs, -- &insn_len, &seq_len, contents); -- break; - case R_NDS32_PLT_GOT_SUFF: -- nds32_elf_relax_pltgot_suff (link_info, abfd, sec, irel, -- internal_relocs, contents, -- isymbuf, symtab_hdr, again); -- /* It is impossible to delete blank, so just continue. */ -- continue; - case R_NDS32_GOT_SUFF: -- nds32_elf_relax_got_suff (link_info, abfd, sec, irel, -- internal_relocs, contents, -- symtab_hdr, again); -- /* It is impossible to delete blank, so just continue. */ -- continue; - case R_NDS32_GOTOFF_SUFF: -- nds32_elf_relax_gotoff_suff (link_info, abfd, sec, irel, -- internal_relocs, contents, -- isymbuf, symtab_hdr, again); -- /* It is impossible to delete blank, so just continue. */ - continue; - default: - continue; -- - } - if (removed && seq_len - insn_len > 0) - { -@@ -12051,7 +13462,7 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, - irelend, isymbuf)) - goto error_return; - -- if (!*again) -+ if (*again == FALSE) - { - if (!nds32_fag_remove_unused_fpbase (abfd, sec, internal_relocs, - irelend)) -@@ -12059,9 +13470,7 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, - } - } - -- nds32_elf_pick_relax (FALSE, sec, again, table, link_info); -- -- if (!*again) -+ if (*again == FALSE) - { - if (!nds32_relax_adjust_label (abfd, sec, internal_relocs, contents, - &relax_blank_list, optimize, opt_size)) -@@ -12078,15 +13487,15 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, - relax_blank_list = NULL; - } - -- if (!*again) -+ if (*again == FALSE) - { - /* Closing the section, so we don't relax it anymore. */ - bfd_vma sec_size_align; - Elf_Internal_Rela *tmp_rel; - - /* Pad to alignment boundary. Only handle current section alignment. */ -- sec_size_align = (sec->size + (~((-1U) << sec->alignment_power))) -- & ((-1U) << sec->alignment_power); -+ sec_size_align = (sec->size + (~((bfd_vma)(-1) << sec->alignment_power))) -+ & ((bfd_vma)(-1) << sec->alignment_power); - if ((sec_size_align - sec->size) & 0x2) - { - insn16 = NDS32_NOP16; -@@ -12128,8 +13537,7 @@ error_return: - goto finish; - } - --static struct bfd_elf_special_section const nds32_elf_special_sections[] = --{ -+static struct bfd_elf_special_section const nds32_elf_special_sections[] = { - {".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE}, - {".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE}, - {NULL, 0, 0, 0, 0} -@@ -12182,14 +13590,14 @@ bfd_elf32_nds32_set_target_option (struct bfd_link_info *link_info, - int eliminate_gc_relocs, - FILE * sym_ld_script, int load_store_relax, - int target_optimize, int relax_status, -- int relax_round, FILE * ex9_export_file, -- FILE * ex9_import_file, -- int update_ex9_table, int ex9_limit, -- bfd_boolean ex9_loop_aware, -- bfd_boolean ifc_loop_aware) -+ int relax_round, int hyper_relax, -+ int tls_desc_trampoline, char *abi) - { - struct elf_nds32_link_hash_table *table; - -+ /* Initialize indirect call hash table. */ -+ nds32_elf_ict_hash_init (); -+ - table = nds32_elf_hash_table (link_info); - if (table == NULL) - return; -@@ -12201,12 +13609,81 @@ bfd_elf32_nds32_set_target_option (struct bfd_link_info *link_info, - table->target_optimize = target_optimize; - table->relax_status = relax_status; - table->relax_round = relax_round; -- table->ex9_export_file = ex9_export_file; -- table->ex9_import_file = ex9_import_file; -- table->update_ex9_table = update_ex9_table; -- table->ex9_limit = ex9_limit; -- table->ex9_loop_aware = ex9_loop_aware; -- table->ifc_loop_aware = ifc_loop_aware; -+ table->hyper_relax = hyper_relax; -+ table->tls_desc_trampoline = tls_desc_trampoline; -+ output_abi = abi; -+} -+ -+void -+bfd_elf32_nds32_append_section (struct bfd_link_info *link_info, bfd *abfd) -+{ -+ asection *itable; -+ struct bfd_link_hash_entry *h; -+ unsigned int i, count = 0; -+ -+ /* Count number of indirect call function. */ -+ indirect_call_table.frozen = 1; -+ for (i = 0; i < indirect_call_table.size; i++) -+ { -+ struct bfd_hash_entry *p; -+ struct elf_nds32_ict_hash_entry *entry; -+ -+ for (p = indirect_call_table.table[i]; p != NULL; p = p->next) -+ { -+ entry = (struct elf_nds32_ict_hash_entry *) p; -+ entry->order = count; -+ count++; -+ } -+ } -+ indirect_call_table.frozen = 0; -+ -+ if (count) -+ { -+ h = bfd_link_hash_lookup (link_info->hash, "_INDIRECT_CALL_TABLE_BASE_", -+ FALSE, FALSE, FALSE); -+ if (h && (h->type == bfd_link_hash_defined -+ || h->type == bfd_link_hash_defweak -+ || h->type == bfd_link_hash_common)) -+ { -+ _bfd_error_handler (_("Warning: _INDIRECT_CALL_TABLE_BASE_ has already" -+ "be defined. All ICT suffix is ignored.")); -+ ignore_indirect_call = TRUE; -+ return; -+ } -+ -+ if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) -+ itable = bfd_make_section_with_flags (abfd, NDS32_ICT_SECTION, -+ SEC_DATA | SEC_ALLOC | SEC_LOAD -+ | SEC_HAS_CONTENTS | SEC_READONLY -+ | SEC_IN_MEMORY | SEC_KEEP -+ | SEC_RELOC); -+ else -+ itable = bfd_make_section_with_flags (abfd, NDS32_ICT_SECTION, -+ SEC_CODE | SEC_ALLOC | SEC_LOAD -+ | SEC_HAS_CONTENTS | SEC_READONLY -+ | SEC_IN_MEMORY | SEC_KEEP -+ | SEC_RELOC); -+ if (itable) -+ { -+ itable->gc_mark = 1; -+ itable->alignment_power = 2; -+ itable->size = count * 4; -+ itable->contents = bfd_zalloc (abfd, itable->size); -+ -+ /* Add a symbol in the head of .nds32.ict to objdump clearly. */ -+ h = bfd_link_hash_lookup (link_info->hash, -+ "_INDIRECT_CALL_TABLE_BASE_", -+ FALSE, FALSE, FALSE); -+ _bfd_generic_link_add_one_symbol -+ (link_info, link_info->output_bfd, "_INDIRECT_CALL_TABLE_BASE_", -+ BSF_GLOBAL | BSF_WEAK, itable, 0, (const char *) NULL, FALSE, -+ get_elf_backend_data (link_info->output_bfd)->collect, &h); -+ } -+ -+ ict_file = fopen ("nds32_ict.s", FOPEN_WT); -+ if(ict_file == NULL) -+ _bfd_error_handler (_("Warning: Fail to build nds32_ict.s.")); -+ } - } - - /* These functions and data-structures are used for fp-as-gp -@@ -12394,7 +13871,7 @@ nds32_fag_find_base (struct nds32_fag *head, struct nds32_fag **bestpp) - - static bfd_boolean - nds32_fag_mark_relax (struct bfd_link_info *link_info, -- bfd *abfd, struct nds32_fag *best_fag, -+ asection *sec, struct nds32_fag *best_fag, - Elf_Internal_Rela *internal_relocs, - Elf_Internal_Rela *irelend) - { -@@ -12402,7 +13879,7 @@ nds32_fag_mark_relax (struct bfd_link_info *link_info, - bfd_vma best_fpbase, gp; - bfd *output_bfd; - -- output_bfd = abfd->sections->output_section->owner; -+ output_bfd = sec->output_section->owner; - nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE); - best_fpbase = best_fag->addr; - -@@ -12525,7 +14002,6 @@ nds32_relax_fp_as_gp (struct bfd_link_info *link_info, - { - /* Begin of the region. */ - if (begin_rel) -- /* xgettext:c-format */ - _bfd_error_handler (_("%B: Nested OMIT_FP in %A."), abfd, sec); - - begin_rel = irel; -@@ -12544,7 +14020,6 @@ nds32_relax_fp_as_gp (struct bfd_link_info *link_info, - - if (begin_rel == NULL) - { -- /* xgettext:c-format */ - _bfd_error_handler (_("%B: Unmatched OMIT_FP in %A."), abfd, sec); - continue; - } -@@ -12557,7 +14032,7 @@ nds32_relax_fp_as_gp (struct bfd_link_info *link_info, - - /* Check if it is worth, and FP_BASE is near enough to SDA_BASE. */ - if (accu < FAG_THRESHOLD -- || !nds32_fag_mark_relax (link_info, abfd, best_fag, -+ || !nds32_fag_mark_relax (link_info, sec, best_fag, - internal_relocs, irelend)) - { - /* Not worth to do fp-as-gp. */ -@@ -12811,9 +14286,9 @@ nds32_elf_get_relocated_section_contents (bfd *abfd, - case bfd_reloc_dangerous: - BFD_ASSERT (error_message != NULL); - (*link_info->callbacks->reloc_dangerous) -- (link_info, error_message, -- input_bfd, input_section, (*parent)->address); -- break; -+ (link_info, error_message, input_bfd, input_section, -+ (*parent)->address); -+ break; - case bfd_reloc_overflow: - (*link_info->callbacks->reloc_overflow) - (link_info, NULL, -@@ -12827,9 +14302,8 @@ nds32_elf_get_relocated_section_contents (bfd *abfd, - complete binaries. Do not abort, but issue an error - message instead. */ - link_info->callbacks->einfo -- /* xgettext:c-format */ - (_("%X%P: %B(%A): relocation \"%R\" goes out of range\n"), -- abfd, input_section, * parent); -+ abfd, input_section, *parent); - goto error_return; - - default: -@@ -12847,745 +14321,807 @@ error_return: - free (reloc_vector); - return NULL; - } -- --/* Link-time IFC relaxation. -- In this optimization, we chains jump instructions -- of the same destination with ifcall. */ - -+/* Check target symbol. */ - --/* List to save jal and j relocation. */ --struct elf_nds32_ifc_symbol_entry -+static bfd_boolean -+nds32_elf_is_target_special_symbol (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym) - { -- asection *sec; -- struct elf_link_hash_entry *h; -- struct elf_nds32_ifc_irel_list *irel_head; -- unsigned long insn; -- int times; -- int enable; /* Apply ifc. */ -- int ex9_enable; /* Apply ifc after ex9. */ -- struct elf_nds32_ifc_symbol_entry *next; --}; -+ if (!sym || !sym->name || sym->name[0] != '$') -+ return FALSE; -+ return TRUE; -+} - --struct elf_nds32_ifc_irel_list -+/* nds32 find maybe function sym. Ignore target special symbol -+ first, and then go the general function. */ -+ -+static bfd_size_type -+nds32_elf_maybe_function_sym (const asymbol *sym, asection *sec, -+ bfd_vma *code_off) - { -- Elf_Internal_Rela *irel; -- asection *sec; -- bfd_vma addr; -- /* If this is set, then it is the last instruction for -- ifc-chain, so it must be keep for the actual branching. */ -- int keep; -- struct elf_nds32_ifc_irel_list *next; --}; -+ if (nds32_elf_is_target_special_symbol (NULL, (asymbol *) sym)) -+ return 0; - --static struct elf_nds32_ifc_symbol_entry *ifc_symbol_head = NULL; -+ return _bfd_elf_maybe_function_sym (sym, sec, code_off); -+} - --/* Insert symbol of jal and j for ifc. */ -+ -+/* Do TLS model conversion. */ - --static void --nds32_elf_ifc_insert_symbol (asection *sec, -- struct elf_link_hash_entry *h, -- Elf_Internal_Rela *irel, -- unsigned long insn) -+typedef struct relax_group_list_t - { -- struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head; -+ Elf_Internal_Rela *relo; -+ struct relax_group_list_t *next; -+ struct relax_group_list_t *next_sibling; -+ int id; -+} relax_group_list_t; - -- /* Check there is target of existing entry the same as the new one. */ -- while (ptr != NULL) -- { -- if (((h == NULL && ptr->sec == sec -- && ELF32_R_SYM (ptr->irel_head->irel->r_info) == ELF32_R_SYM (irel->r_info) -- && ptr->irel_head->irel->r_addend == irel->r_addend) -- || h != NULL) -- && ptr->h == h -- && ptr->insn == insn) -- { -- /* The same target exist, so insert into list. */ -- struct elf_nds32_ifc_irel_list *irel_list = ptr->irel_head; -+int -+list_insert (relax_group_list_t *pHead, Elf_Internal_Rela *pElem); - -- while (irel_list->next != NULL) -- irel_list = irel_list->next; -- irel_list->next = bfd_malloc (sizeof (struct elf_nds32_ifc_irel_list)); -- irel_list = irel_list->next; -- irel_list->irel = irel; -- irel_list->keep = 1; -+int -+list_insert_sibling (relax_group_list_t *pNode, Elf_Internal_Rela *pElem); - -- if (h == NULL) -- irel_list->sec = NULL; -- else -- irel_list->sec = sec; -- irel_list->next = NULL; -- return; -- } -- if (ptr->next == NULL) -- break; -- ptr = ptr->next; -- } -+void -+dump_chain (relax_group_list_t *pHead); - -- /* There is no same target entry, so build a new one. */ -- if (ifc_symbol_head == NULL) -- { -- ifc_symbol_head = bfd_malloc (sizeof (struct elf_nds32_ifc_symbol_entry)); -- ptr = ifc_symbol_head; -- } -- else -+int -+list_insert (relax_group_list_t *pHead, Elf_Internal_Rela *pElem) -+{ -+ relax_group_list_t *pNext = pHead; -+ -+ /* find place */ -+ while (pNext->next) - { -- ptr->next = bfd_malloc (sizeof (struct elf_nds32_ifc_symbol_entry)); -- ptr = ptr->next; -+ if (pNext->next->id > (int) pElem->r_addend) -+ break; -+ -+ pNext = pNext->next; - } - -- ptr->h = h; -- ptr->irel_head = bfd_malloc (sizeof (struct elf_nds32_ifc_irel_list)); -- ptr->irel_head->irel = irel; -- ptr->insn = insn; -- ptr->irel_head->keep = 1; -+ /* insert node */ -+ relax_group_list_t *pNew = bfd_malloc (sizeof (relax_group_list_t)); -+ if (!pNew) -+ return FALSE; -+ -+ relax_group_list_t *tmp = pNext->next; -+ pNext->next = pNew; - -- if (h == NULL) -- { -- /* Local symbols. */ -- ptr->sec = sec; -- ptr->irel_head->sec = NULL; -- } -- else -- { -- /* Global symbol. */ -- ptr->sec = NULL; -- ptr->irel_head->sec = sec; -- } -+ pNew->id = pElem->r_addend; -+ pNew->relo = pElem; -+ pNew->next = tmp; -+ pNew->next_sibling = NULL; - -- ptr->irel_head->next = NULL; -- ptr->times = 0; -- ptr->enable = 0; -- ptr->ex9_enable = 0; -- ptr->next = NULL; -+ return TRUE; - } - --/* Gather all jal and j instructions. */ -- --static bfd_boolean --nds32_elf_ifc_calc (struct bfd_link_info *info, -- bfd *abfd, asection *sec) -+int -+list_insert_sibling (relax_group_list_t *pNode, Elf_Internal_Rela *pElem) - { -- Elf_Internal_Rela *internal_relocs; -- Elf_Internal_Rela *irelend; -- Elf_Internal_Rela *irel; -- Elf_Internal_Shdr *symtab_hdr; -- bfd_byte *contents = NULL; -- uint32_t insn, insn_with_reg; -- unsigned long r_symndx; -- struct elf_link_hash_entry *h; -- struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd); -- struct elf_nds32_link_hash_table *table; -- bfd_boolean ifc_loop_aware; -+ relax_group_list_t *pNext = pNode; - -- internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, -- TRUE /* keep_memory */); -- irelend = internal_relocs + sec->reloc_count; -- symtab_hdr = &elf_tdata (abfd)->symtab_hdr; -+ /* find place */ -+ while (pNext->next_sibling) -+ { -+ pNext = pNext->next_sibling; -+ } -+ -+ /* insert node */ -+ relax_group_list_t *pNew = bfd_malloc (sizeof (relax_group_list_t)); -+ if (!pNew) -+ return FALSE; - -- /* Check if the object enable ifc. */ -- irel = find_relocs_at_address (internal_relocs, internal_relocs, irelend, -- R_NDS32_RELAX_ENTRY); -+ relax_group_list_t *tmp = pNext->next_sibling; -+ pNext->next_sibling = pNew; - -- if (irel == NULL -- || irel >= irelend -- || ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_ENTRY -- || (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY -- && !(irel->r_addend & R_NDS32_RELAX_ENTRY_IFC_FLAG))) -- return TRUE; -+ pNew->id = -1; -+ pNew->relo = pElem; -+ pNew->next = NULL; -+ pNew->next_sibling = tmp; - -- if (!nds32_get_section_contents (abfd, sec, &contents, TRUE)) -- return FALSE; -+ return TRUE; -+} - -- table = nds32_elf_hash_table (info); -- ifc_loop_aware = table->ifc_loop_aware; -- while (irel != NULL && irel < irelend) -+void -+dump_chain (relax_group_list_t *pHead) -+{ -+ relax_group_list_t *pNext = pHead->next; -+ while (pNext) - { -- /* Traverse all relocation and gather all of them to build the list. */ -- -- if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_BEGIN) -+ printf("group %d @ 0x%08x", pNext->id, (unsigned)pNext->relo->r_offset); -+ relax_group_list_t *pNextSib = pNext->next_sibling; -+ while (pNextSib) - { -- if (ifc_loop_aware == 1 -- && (irel->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG) != 0) -- { -- /* Check the region if loop or not. If it is true and -- ifc-loop-aware is true, ignore the region till region end. */ -- while (irel != NULL -- && irel < irelend -- && (ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_REGION_END -- || (irel->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG) != 0)) -- irel++; -- } -+ printf(", %d", (unsigned) ELF32_R_TYPE (pNextSib->relo->r_info)); -+ pNextSib = pNextSib->next_sibling; - } -+ pNext = pNext->next; -+ printf("\n"); -+ } -+} -+ -+/* check R_NDS32_RELAX_GROUP of each section. -+ there might be multiple sections in one object file. */ -+int -+elf32_nds32_check_relax_group (bfd *abfd, asection *asec) -+{ -+ elf32_nds32_relax_group_t *relax_group_ptr = -+ elf32_nds32_relax_group_ptr (abfd); -+ -+ int min_id = relax_group_ptr->min_id; -+ int max_id = relax_group_ptr->max_id; -+ -+ Elf_Internal_Rela *rel; -+ Elf_Internal_Rela *relend; -+ Elf_Internal_Rela *relocs; -+ enum elf_nds32_reloc_type rtype; -+ -+ do -+ { -+ /* Relocations MUST be kept in memory, because relaxation adjust them. */ -+ relocs = _bfd_elf_link_read_relocs (abfd, asec, NULL, NULL, -+ TRUE /* keep_memory */); -+ if (relocs == NULL) -+ break; - -- if (ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA) -+ /* check R_NDS32_RELAX_GROUP */ -+ relend = relocs + asec->reloc_count; -+ for (rel = relocs; rel < relend; rel++) - { -- insn = bfd_getb32 (contents + irel->r_offset); -- nds32_elf_get_insn_with_reg (irel, insn, &insn_with_reg); -- r_symndx = ELF32_R_SYM (irel->r_info); -- if (r_symndx < symtab_hdr->sh_info) -- { -- /* Local symbol. */ -- nds32_elf_ifc_insert_symbol (sec, NULL, irel, insn_with_reg); -- } -- else -- { -- /* External symbol. */ -- h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -- nds32_elf_ifc_insert_symbol (sec, h, irel, insn_with_reg); -- } -+ int id; -+ rtype = ELF32_R_TYPE (rel->r_info); -+ if (rtype != R_NDS32_RELAX_GROUP) -+ continue; -+ -+ id = rel->r_addend; -+ if (id < min_id) -+ min_id = id; -+ else if (id > max_id) -+ max_id = id; - } -- irel++; - } -- return TRUE; -+ while (FALSE); -+ -+ if ((relocs != NULL) && (elf_section_data (asec)->relocs != relocs)) -+ free (relocs); -+ -+ if ((min_id != relax_group_ptr->min_id) -+ || (max_id != relax_group_ptr->max_id)) -+ { -+ relax_group_ptr->count = max_id - min_id + 1; -+ BFD_ASSERT(min_id <= relax_group_ptr->min_id); -+ relax_group_ptr->min_id = min_id; -+ BFD_ASSERT(max_id >= relax_group_ptr->max_id); -+ relax_group_ptr->max_id = max_id; -+ } -+ -+ return relax_group_ptr->count; - } - --/* Determine whether j and jal should be substituted. */ -+/* Reorder RELAX_GROUP ID when command line option '-r' is applied. */ -+/* TODO: find a way to free me. */ -+struct section_id_list_t *relax_group_section_id_list = NULL; - --static void --nds32_elf_ifc_filter (struct bfd_link_info *info) -+struct section_id_list_t * -+elf32_nds32_lookup_section_id (int id, struct section_id_list_t **lst_ptr) - { -- struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head; -- struct elf_nds32_ifc_irel_list *irel_ptr = NULL; -- struct elf_nds32_ifc_irel_list *irel_keeper = NULL; -- struct elf_nds32_link_hash_table *table; -- int target_optimize; -- bfd_vma address; -+ struct section_id_list_t *result = NULL; -+ struct section_id_list_t *lst = *lst_ptr; - -- table = nds32_elf_hash_table (info); -- target_optimize = table->target_optimize; -- while (ptr) -+ if (NULL == lst) -+ { -+ result = (struct section_id_list_t *) calloc ( -+ 1, sizeof (struct section_id_list_t)); -+ BFD_ASSERT (result); /* feed me */ -+ result->id = id; -+ *lst_ptr = result; -+ } -+ else - { -- irel_ptr = ptr->irel_head; -- if (ptr->h == NULL) -+ struct section_id_list_t *cur = lst; -+ struct section_id_list_t *prv = NULL; -+ struct section_id_list_t *sec = NULL; -+ while (cur) - { -- /* Local symbol. */ -- irel_keeper = irel_ptr; -- while (irel_ptr && irel_ptr->next) -+ if (cur->id < id) - { -- /* Check there is jump target can be used. */ -- if ((irel_ptr->next->irel->r_offset -- - irel_keeper->irel->r_offset) > 1022) -- irel_keeper = irel_ptr->next; -- else -- { -- ptr->enable = 1; -- irel_ptr->keep = 0; -- } -- irel_ptr = irel_ptr->next; -+ prv = cur; -+ cur = cur->next; -+ continue; - } -- } -- else -- { -- /* Global symbol. */ -- /* We have to get the absolute address and decide -- whether to keep it or not. */ -- while (irel_ptr) -+ -+ if (cur->id > id) - { -- address = (irel_ptr->irel->r_offset -- + irel_ptr->sec->output_section->vma -- + irel_ptr->sec->output_offset); -- irel_ptr->addr = address; -- irel_ptr = irel_ptr->next; -+ cur = NULL; /* to insert after prv */ -+ sec = cur; /* in case prv == NULL */ - } - -- irel_ptr = ptr->irel_head; -- while (irel_ptr) -- { -- /* Sort by address. */ -- struct elf_nds32_ifc_irel_list *irel_dest = irel_ptr; -- struct elf_nds32_ifc_irel_list *irel_temp = irel_ptr; -- struct elf_nds32_ifc_irel_list *irel_ptr_prev = NULL; -- struct elf_nds32_ifc_irel_list *irel_dest_prev = NULL; -- -- /* Get the smallest one. */ -- while (irel_temp->next) -- { -- if (irel_temp->next->addr < irel_dest->addr) -- { -- irel_dest_prev = irel_temp; -- irel_dest = irel_temp->next; -- } -- irel_temp = irel_temp->next; -- } -+ break; -+ } - -- if (irel_dest != irel_ptr) -- { -- if (irel_ptr_prev) -- irel_ptr_prev->next = irel_dest; -- if (irel_dest_prev) -- irel_dest_prev->next = irel_ptr; -- irel_temp = irel_ptr->next; -- irel_ptr->next = irel_dest->next; -- irel_dest->next = irel_temp; -- } -- irel_ptr_prev = irel_ptr; -- irel_ptr = irel_ptr->next; -+ if (NULL == cur) -+ { -+ /* insert after prv */ -+ result = (struct section_id_list_t *) calloc ( -+ 1, sizeof (struct section_id_list_t)); -+ BFD_ASSERT (result); /* feed me */ -+ result->id = id; -+ if (NULL != prv) -+ { -+ result->next = prv->next; -+ prv->next = result; - } -- -- irel_ptr = ptr->irel_head; -- irel_keeper = irel_ptr; -- while (irel_ptr && irel_ptr->next) -+ else - { -- if ((irel_ptr->next->addr - irel_keeper->addr) > 1022) -- irel_keeper = irel_ptr->next; -- else -- { -- ptr->enable = 1; -- irel_ptr->keep = 0; -- } -- irel_ptr = irel_ptr->next; -+ *lst_ptr = result; -+ result->next = sec; - } - } -- -- /* Ex9 enable. Reserve it for ex9. */ -- if ((target_optimize & NDS32_RELAX_EX9_ON) -- && ptr->irel_head != irel_keeper) -- ptr->enable = 0; -- ptr = ptr->next; - } --} - --/* Determine whether j and jal should be substituted after ex9 done. */ -+ return result; -+} - --static void --nds32_elf_ifc_filter_after_ex9 (void) -+int -+elf32_nds32_unify_relax_group (bfd *abfd, asection *asec) - { -- struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head; -- struct elf_nds32_ifc_irel_list *irel_ptr = NULL; -+ static int next_relax_group_bias = 0; - -- while (ptr) -+ elf32_nds32_relax_group_t *relax_group_ptr = -+ elf32_nds32_relax_group_ptr (abfd); -+ -+ bfd_boolean result = TRUE; -+ Elf_Internal_Rela *rel; -+ Elf_Internal_Rela *relend; -+ Elf_Internal_Rela *relocs = NULL; -+ enum elf_nds32_reloc_type rtype; -+ struct section_id_list_t *node = NULL; -+ int count = 0; -+ -+ do - { -- if (ptr->enable == 0) -+ if (0 == relax_group_ptr->count) -+ break; -+ -+ /* check if this section has handled */ -+ node = elf32_nds32_lookup_section_id (asec->id, &relax_group_section_id_list); -+ if (NULL == node) -+ break; /* hit, the section id has handled. */ -+ -+ /* Relocations MUST be kept in memory, because relaxation adjust them. */ -+ relocs = _bfd_elf_link_read_relocs (abfd, asec, NULL, NULL, -+ TRUE /* keep_memory */); -+ if (relocs == NULL) - { -- /* Check whether ifc is applied or not. */ -- irel_ptr = ptr->irel_head; -- ptr->ex9_enable = 1; -- while (irel_ptr) -- { -- if (ELF32_R_TYPE (irel_ptr->irel->r_info) == R_NDS32_TRAN) -- { -- /* Ex9 already. */ -- ptr->ex9_enable = 0; -- break; -- } -- irel_ptr = irel_ptr->next; -- } -+ BFD_ASSERT (0); /* feed me */ -+ break; - } -- ptr = ptr->next; -- } --} -- --/* Wrapper to do ifc relaxation. */ - --bfd_boolean --nds32_elf_ifc_finish (struct bfd_link_info *info) --{ -- int relax_status; -- struct elf_nds32_link_hash_table *table; -+ /* allocate group id bias for this bfd! */ -+ if (0 == relax_group_ptr->init) -+ { -+ relax_group_ptr->bias = next_relax_group_bias; -+ next_relax_group_bias += relax_group_ptr->count; -+ relax_group_ptr->init = 1; -+ } - -- table = nds32_elf_hash_table (info); -- relax_status = table->relax_status; -+ /* reorder relax group groups */ -+ relend = relocs + asec->reloc_count; -+ for (rel = relocs; rel < relend; rel++) -+ { -+ rtype = ELF32_R_TYPE(rel->r_info); -+ if (rtype != R_NDS32_RELAX_GROUP) -+ continue; - -- if (!(relax_status & NDS32_RELAX_JUMP_IFC_DONE)) -- nds32_elf_ifc_filter (info); -- else -- nds32_elf_ifc_filter_after_ex9 (); -+ /* change it */ -+ rel->r_addend += relax_group_ptr->bias; -+ /* debugging count */ -+ count++; -+ } -+ } -+ while (FALSE); - -- if (!nds32_elf_ifc_replace (info)) -- return FALSE; -+ if (relocs != NULL && elf_section_data (asec)->relocs != relocs) -+ free (relocs); - -- if (table) -- table->relax_status |= NDS32_RELAX_JUMP_IFC_DONE; -- return TRUE; -+ return result; - } - --/* Traverse the result of ifc filter and replace it with ifcall9. */ -- --static bfd_boolean --nds32_elf_ifc_replace (struct bfd_link_info *info) -+int -+nds32_elf_unify_tls_model (bfd *inbfd, asection *insec, bfd_byte *incontents, -+ struct bfd_link_info *lnkinfo) - { -- struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head; -- struct elf_nds32_ifc_irel_list *irel_ptr = NULL; -- nds32_elf_blank_t *relax_blank_list = NULL; -- bfd_byte *contents = NULL; -- Elf_Internal_Rela *internal_relocs; -+ bfd_boolean result = TRUE; - Elf_Internal_Rela *irel; - Elf_Internal_Rela *irelend; -- unsigned short insn16 = INSN_IFCALL9; -- struct elf_nds32_link_hash_table *table; -- int relax_status; -+ Elf_Internal_Rela *internal_relocs; -+ unsigned long r_symndx; -+ enum elf_nds32_reloc_type r_type; - -- table = nds32_elf_hash_table (info); -- relax_status = table->relax_status; -+ Elf_Internal_Sym *local_syms = NULL; -+ bfd_byte *contents = NULL; -+ -+ relax_group_list_t chain = { .id = -1, .next = NULL, .next_sibling = NULL }; -+ -+ Elf_Internal_Shdr *symtab_hdr = &elf_tdata (inbfd)->symtab_hdr; -+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; -+ sym_hashes = elf_sym_hashes (inbfd); -+ sym_hashes_end = -+ sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym); -+ if (!elf_bad_symtab (inbfd)) -+ sym_hashes_end -= symtab_hdr->sh_info; -+ -+ /* reorder RELAX_GROUP when command line option '-r' is applied */ -+ if (bfd_link_relocatable (lnkinfo)) -+ { -+ elf32_nds32_unify_relax_group (inbfd, insec); -+ /* goto finish; */ -+ return result; -+ } -+ -+ /* Relocations MUST be kept in memory, because relaxation adjust them. */ -+ internal_relocs = _bfd_elf_link_read_relocs (inbfd, insec, NULL, NULL, -+ TRUE /* keep_memory */); -+ if (internal_relocs == NULL) -+ goto error_return; -+ -+ irelend = internal_relocs + insec->reloc_count; -+ irel = find_relocs_at_address (internal_relocs, internal_relocs, -+ irelend, R_NDS32_RELAX_ENTRY); -+ if (irel == irelend) -+ goto finish; -+ -+ /* chain/remove groups */ -+ for (irel = internal_relocs; irel < irelend; irel++) -+ { -+ r_symndx = ELF32_R_SYM (irel->r_info); -+ r_type = ELF32_R_TYPE (irel->r_info); -+ if (r_type != R_NDS32_RELAX_GROUP) -+ continue; -+ -+ /* remove it */ -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_NONE); -+ /* chain it now */ -+ if (!list_insert (&chain, irel)) -+ goto error_return; -+ } - -- while (ptr) -+ /* collect group relocations */ -+ /* presume relocations are sorted */ -+ relax_group_list_t *pNext = chain.next; -+ while (pNext) - { -- /* Traverse the ifc gather list, and replace the -- filter entries by ifcall9. */ -- if ((!(relax_status & NDS32_RELAX_JUMP_IFC_DONE) && ptr->enable == 1) -- || ((relax_status & NDS32_RELAX_JUMP_IFC_DONE) -- && ptr->ex9_enable == 1)) -+ for (irel = internal_relocs; irel < irelend; irel++) - { -- irel_ptr = ptr->irel_head; -- if (ptr->h == NULL) -+ if (irel->r_offset == pNext->relo->r_offset) - { -- /* Local symbol. */ -- internal_relocs = _bfd_elf_link_read_relocs -- (ptr->sec->owner, ptr->sec, NULL, NULL, TRUE /* keep_memory */); -- irelend = internal_relocs + ptr->sec->reloc_count; -- -- if (!nds32_get_section_contents (ptr->sec->owner, ptr->sec, -- &contents, TRUE)) -- return FALSE; -+ /* ignore Non-TLS relocation types */ -+ r_type = ELF32_R_TYPE (irel->r_info); -+ if ((R_NDS32_TLS_LE_HI20 > r_type) -+ || (R_NDS32_RELAX_ENTRY == r_type)) -+ continue; - -- while (irel_ptr) -- { -- if (irel_ptr->keep == 0 && irel_ptr->next) -- { -- /* The one can be replaced. We have to check whether -- there is any alignment point in the region. */ -- irel = irel_ptr->irel; -- while (((irel_ptr->next->keep == 0 -- && irel < irel_ptr->next->irel) -- || (irel_ptr->next->keep == 1 && irel < irelend)) -- && !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL -- && (irel->r_addend & 0x1f) == 2)) -- irel++; -- if (irel >= irelend -- || !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL -- && (irel->r_addend & 0x1f) == 2 -- && ((irel->r_offset - get_nds32_elf_blank_total -- (&relax_blank_list, irel->r_offset, 1)) -- & 0x02) == 0)) -- { -- /* Replace by ifcall9. */ -- bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset); -- if (!insert_nds32_elf_blank_recalc_total -- (&relax_blank_list, irel_ptr->irel->r_offset + 2, 2)) -- return FALSE; -- irel_ptr->irel->r_info = -- ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), -- R_NDS32_10IFCU_PCREL_RELA); -- } -- } -- irel_ptr = irel_ptr->next; -- } -+ if (!list_insert_sibling (pNext, irel)) -+ goto error_return; -+ } -+ else if (irel->r_offset > pNext->relo->r_offset) -+ { -+ pNext = pNext->next; -+ if (!pNext) -+ break; - -- /* Delete the redundant code. */ -- if (relax_blank_list) -- { -- nds32_elf_relax_delete_blanks (ptr->sec->owner, ptr->sec, -- relax_blank_list); -- relax_blank_list = NULL; -- } -+ bfd_vma current_offset = pNext->relo->r_offset; -+ if (irel->r_offset > current_offset) -+ irel = internal_relocs; /* restart from head */ -+ else -+ --irel; /* check current irel again */ -+ continue; - } - else - { -- /* Global symbol. */ -- while (irel_ptr) -- { -- if (irel_ptr->keep == 0 && irel_ptr->next) -- { -- /* The one can be replaced, and we have to check -- whether there is any alignment point in the region. */ -- internal_relocs = _bfd_elf_link_read_relocs -- (irel_ptr->sec->owner, irel_ptr->sec, NULL, NULL, -- TRUE /* keep_memory */); -- irelend = internal_relocs + irel_ptr->sec->reloc_count; -- if (!nds32_get_section_contents (irel_ptr->sec->owner, -- irel_ptr->sec, &contents, -- TRUE)) -- return FALSE; -- -- irel = irel_ptr->irel; -- while (((irel_ptr->sec == irel_ptr->next->sec -- && irel_ptr->next->keep == 0 -- && irel < irel_ptr->next->irel) -- || ((irel_ptr->sec != irel_ptr->next->sec -- || irel_ptr->next->keep == 1) -- && irel < irelend)) -- && !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL -- && (irel->r_addend & 0x1f) == 2)) -- irel++; -- if (irel >= irelend -- || !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL -- && (irel->r_addend & 0x1f) == 2 -- && ((irel->r_offset -- - get_nds32_elf_blank_total (&relax_blank_list, -- irel->r_offset, 1)) & 0x02) == 0)) -- { -- /* Replace by ifcall9. */ -- bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset); -- if (!insert_nds32_elf_blank_recalc_total -- (&relax_blank_list, irel_ptr->irel->r_offset + 2, 2)) -- return FALSE; -- -- /* Delete the redundant code, and clear the relocation. */ -- nds32_elf_relax_delete_blanks (irel_ptr->sec->owner, -- irel_ptr->sec, -- relax_blank_list); -- irel_ptr->irel->r_info = -- ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), -- R_NDS32_10IFCU_PCREL_RELA); -- relax_blank_list = NULL; -- } -- } -- -- irel_ptr = irel_ptr->next; -- } -+ //printf("irel->off = 0x%08x, pNext->relo->off = 0x%08x (0x%08x)\n", (unsigned)irel->r_offset, (unsigned)pNext->relo->r_offset, (unsigned)first_offset); - } - } -- ptr = ptr->next; -+ if (pNext) -+ pNext = pNext->next; - } - -- return TRUE; --} -- --/* Relocate ifcall. */ -- --static bfd_boolean --nds32_elf_ifc_reloc (void) --{ -- struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head; -- struct elf_nds32_ifc_irel_list *irel_ptr = NULL; -- struct elf_nds32_ifc_irel_list *irel_keeper = NULL; -- bfd_vma relocation, address; -- unsigned short insn16; -- bfd_byte *contents = NULL; -- static bfd_boolean done = FALSE; -+#ifdef DUBUG_VERBOSE -+ dump_chain(&chain); -+#endif - -- if (done) -- return TRUE; -+ /* Get symbol table and section content. */ -+ if (incontents) -+ contents = incontents; -+ else if (!nds32_get_section_contents (inbfd, insec, &contents, TRUE) -+ || !nds32_get_local_syms (inbfd, insec, &local_syms)) -+ goto error_return; - -- done = TRUE; -+ char *local_got_tls_type = elf32_nds32_local_got_tls_type (inbfd); - -- while (ptr) -+ /* convert TLS model each group if necessary */ -+ pNext = chain.next; -+ int cur_grp_id = -1; -+ int sethi_rt = -1; -+ int add_rt = -1; -+ enum elf_nds32_tls_type tls_type, org_tls_type, eff_tls_type; -+ tls_type = org_tls_type = eff_tls_type = 0; -+ while (pNext) - { -- /* Check the entry is enable ifcall. */ -- if (ptr->enable == 1 || ptr->ex9_enable == 1) -+ relax_group_list_t *pNextSig = pNext->next_sibling; -+ while (pNextSig) - { -- /* Get the reserve jump. */ -- irel_ptr = ptr->irel_head; -- while (irel_ptr) -+ struct elf_link_hash_entry *h = NULL; -+ irel = pNextSig->relo; -+ r_symndx = ELF32_R_SYM(irel->r_info); -+ r_type = ELF32_R_TYPE(irel->r_info); -+ -+ if (pNext->id != cur_grp_id) - { -- if (irel_ptr->keep == 1) -+ cur_grp_id = pNext->id; -+ org_tls_type = get_tls_type (r_type, NULL); -+ if (r_symndx >= symtab_hdr->sh_info) - { -- irel_keeper = irel_ptr; -- break; -+ h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -+ while (h->root.type == bfd_link_hash_indirect -+ || h->root.type == bfd_link_hash_warning) -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ tls_type = ((struct elf_nds32_link_hash_entry *) h)->tls_type; -+ } -+ else -+ { -+ /* TODO: find local symbol hash if necessary? */ -+ tls_type = local_got_tls_type ? local_got_tls_type[r_symndx] : GOT_NORMAL; - } -- irel_ptr = irel_ptr->next; -+ -+ eff_tls_type = 1 << (fls (tls_type) - 1); -+ sethi_rt = N32_RT5(bfd_getb32 (contents + irel->r_offset)); - } - -- irel_ptr = ptr->irel_head; -- if (ptr->h == NULL) -+ if (eff_tls_type != org_tls_type) - { -- /* Local symbol. */ -- if (!nds32_get_section_contents (ptr->sec->owner, ptr->sec, -- &contents, TRUE)) -- return FALSE; -- -- while (irel_ptr) -+ switch (org_tls_type) - { -- if (irel_ptr->keep == 0 -- && ELF32_R_TYPE (irel_ptr->irel->r_info) == R_NDS32_10IFCU_PCREL_RELA) -+ /* DESC to IEGP/IE/LE. */ -+ case GOT_TLS_DESC: -+ switch (eff_tls_type) - { -- relocation = irel_keeper->irel->r_offset; -- relocation = relocation - irel_ptr->irel->r_offset; -- while (irel_keeper && relocation > 1022) -+ case GOT_TLS_IE: -+ switch (r_type) - { -- irel_keeper = irel_keeper->next; -- if (irel_keeper && irel_keeper->keep == 1) -- { -- relocation = irel_keeper->irel->r_offset; -- relocation = relocation - irel_ptr->irel->r_offset; -- } -+ case R_NDS32_TLS_DESC_HI20: -+ irel->r_info = ELF32_R_INFO(r_symndx, -+ R_NDS32_TLS_IE_HI20); -+ break; -+ case R_NDS32_TLS_DESC_LO12: -+ irel->r_info = ELF32_R_INFO(r_symndx, -+ R_NDS32_TLS_IE_LO12); -+ break; -+ case R_NDS32_TLS_DESC_ADD: -+ { -+ uint32_t insn = bfd_getb32 ( -+ contents + irel->r_offset); -+ add_rt = N32_RT5 (insn); -+ insn = N32_TYPE2 (LWI, add_rt, sethi_rt, 0); -+ bfd_putb32 (insn, contents + irel->r_offset); -+ -+ irel->r_info = ELF32_R_INFO(r_symndx, R_NDS32_NONE); -+/* irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_IE_LW); -+*/ -+ } -+ break; -+ case R_NDS32_TLS_DESC_FUNC: -+ bfd_putb32 (INSN_NOP, contents + irel->r_offset); -+ irel->r_info = ELF32_R_INFO(r_symndx, -+ R_NDS32_RELAX_REMOVE); -+ break; -+ case R_NDS32_TLS_DESC_CALL: -+ { -+ uint32_t insn = N32_ALU1(ADD, REG_R0, add_rt, -+ REG_TP); -+ bfd_putb32 (insn, contents + irel->r_offset); -+ -+ irel->r_info = ELF32_R_INFO(r_symndx, R_NDS32_NONE); -+ } -+ break; -+ case R_NDS32_LOADSTORE: -+ case R_NDS32_PTR: -+ case R_NDS32_PTR_RESOLVED: -+ case R_NDS32_NONE: -+ case R_NDS32_LABEL: -+ break; -+ default: -+ BFD_ASSERT(0); -+ break; - } -- if (relocation > 1022) -+ break; -+ case GOT_TLS_IEGP: -+ switch (r_type) - { -- /* Double check. */ -- irel_keeper = ptr->irel_head; -- while (irel_keeper) -- { -- if (irel_keeper->keep == 1) -- { -- relocation = irel_keeper->irel->r_offset; -- relocation = relocation - irel_ptr->irel->r_offset; -- } -- if (relocation <= 1022) -- break; -- irel_keeper = irel_keeper->next; -- } -- if (!irel_keeper) -- return FALSE; -+ case R_NDS32_TLS_DESC_HI20: -+ irel->r_info = ELF32_R_INFO(r_symndx, -+ R_NDS32_TLS_IEGP_HI20); -+ break; -+ case R_NDS32_TLS_DESC_LO12: -+ irel->r_info = ELF32_R_INFO(r_symndx, -+ R_NDS32_TLS_IEGP_LO12); -+ break; -+ case R_NDS32_TLS_DESC_ADD: -+ { -+ uint32_t insn = bfd_getb32 ( -+ contents + irel->r_offset); -+ add_rt = N32_RT5 (insn); -+ insn = N32_MEM(LW, add_rt, sethi_rt, REG_GP, 0); -+ bfd_putb32 (insn, contents + irel->r_offset); -+ -+ irel->r_info = ELF32_R_INFO(r_symndx, R_NDS32_NONE); -+/* irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_IEGP_LW); -+*/ -+ } -+ break; -+ case R_NDS32_TLS_DESC_FUNC: -+ bfd_putb32 (INSN_NOP, contents + irel->r_offset); -+ irel->r_info = ELF32_R_INFO(r_symndx, -+ R_NDS32_RELAX_REMOVE); -+ break; -+ case R_NDS32_TLS_DESC_CALL: -+ { -+ uint32_t insn = N32_ALU1(ADD, REG_R0, add_rt, -+ REG_TP); -+ bfd_putb32 (insn, contents + irel->r_offset); -+ -+ irel->r_info = ELF32_R_INFO(r_symndx, R_NDS32_NONE); -+ } -+ break; -+ case R_NDS32_LOADSTORE: -+ case R_NDS32_PTR: -+ case R_NDS32_PTR_RESOLVED: -+ case R_NDS32_NONE: -+ case R_NDS32_LABEL: -+ break; -+ default: -+ BFD_ASSERT(0); -+ break; - } -- irel_ptr->irel->r_info = -- ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), -- R_NDS32_NONE); -- insn16 = INSN_IFCALL9 | (relocation >> 1); -- bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset); -+ break; -+ case GOT_TLS_LE: -+ switch (r_type) -+ { -+ case R_NDS32_TLS_DESC_HI20: -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_HI20); -+ break; -+ case R_NDS32_TLS_DESC_LO12: -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_LO12); -+ break; -+ case R_NDS32_TLS_DESC_ADD: -+ { -+ uint32_t insn = bfd_getb32 (contents + irel->r_offset); -+ add_rt = N32_RT5 (insn); -+ insn = N32_ALU1 (ADD, REG_R0, sethi_rt, REG_TP); -+ bfd_putb32 (insn, contents + irel->r_offset); -+ -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_ADD); -+ } -+ break; -+ case R_NDS32_TLS_DESC_FUNC: -+ bfd_putb32 (INSN_NOP, contents + irel->r_offset); -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_RELAX_REMOVE); -+ break; -+ case R_NDS32_TLS_DESC_CALL: -+ bfd_putb32 (INSN_NOP, contents + irel->r_offset); -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_RELAX_REMOVE); -+ break; -+ case R_NDS32_LOADSTORE: -+ case R_NDS32_PTR: -+ case R_NDS32_PTR_RESOLVED: -+ case R_NDS32_NONE: -+ case R_NDS32_LABEL: -+ break; -+ default: -+ BFD_ASSERT(0); -+ break; -+ } -+ break; -+ default: -+#ifdef DEBUG_VERBOSE -+ printf ( -+ "SKIP: %s: %s @ 0x%08x tls_type = 0x%08x, eff_tls_type = 0x%08x, org_tls_type = 0x%08x\n", -+ inbfd->filename, h ? h->root.root.string : "local", -+ (unsigned) irel->r_offset, tls_type, eff_tls_type, -+ org_tls_type); -+#endif -+ break; - } -- irel_ptr = irel_ptr->next; -- } -- } -- else -- { -- /* Global symbol. */ -- while (irel_ptr) -- { -- if (irel_ptr->keep == 0 -- && ELF32_R_TYPE (irel_ptr->irel->r_info) == R_NDS32_10IFCU_PCREL_RELA) -+ break; -+ /* IEGP to IE/LE. */ -+ case GOT_TLS_IEGP: -+ switch (eff_tls_type) - { -- /* Get the distance between ifcall and jump. */ -- relocation = (irel_keeper->irel->r_offset -- + irel_keeper->sec->output_section->vma -- + irel_keeper->sec->output_offset); -- address = (irel_ptr->irel->r_offset -- + irel_ptr->sec->output_section->vma -- + irel_ptr->sec->output_offset); -- relocation = relocation - address; -- -- /* The distance is over ragne, find callee again. */ -- while (irel_keeper && relocation > 1022) -+ case GOT_TLS_IE: -+ switch (r_type) - { -- irel_keeper = irel_keeper->next; -- if (irel_keeper && irel_keeper->keep ==1) -- { -- relocation = (irel_keeper->irel->r_offset -- + irel_keeper->sec->output_section->vma -- + irel_keeper->sec->output_offset); -- relocation = relocation - address; -- } -+ case R_NDS32_TLS_IEGP_HI20: -+ irel->r_info = ELF32_R_INFO(r_symndx, -+ R_NDS32_TLS_IE_HI20); -+ break; -+ case R_NDS32_TLS_IEGP_LO12: -+ irel->r_info = ELF32_R_INFO(r_symndx, -+ R_NDS32_TLS_IE_LO12); -+ break; -+ case R_NDS32_PTR_RESOLVED: -+ { -+ uint32_t insn = bfd_getb32 ( -+ contents + irel->r_offset); -+ add_rt = N32_RT5 (insn); -+ insn = N32_TYPE2 (LWI, add_rt, sethi_rt, 0); -+ bfd_putb32 (insn, contents + irel->r_offset); -+ } -+ break; -+ case R_NDS32_TLS_IEGP_LW: -+ break; -+ case R_NDS32_LOADSTORE: -+ case R_NDS32_PTR: -+ case R_NDS32_NONE: -+ case R_NDS32_LABEL: -+ break; -+ default: -+ BFD_ASSERT(0); -+ break; - } -- -- if (relocation > 1022) -+ break; -+ case GOT_TLS_LE: -+ switch (r_type) - { -- /* Double check. */ -- irel_keeper = ptr->irel_head; -- while (irel_keeper) -- { -- if (irel_keeper->keep == 1) -- { -- -- relocation = (irel_keeper->irel->r_offset -- + irel_keeper->sec->output_section->vma -- + irel_keeper->sec->output_offset); -- relocation = relocation - address; -- } -- if (relocation <= 1022) -- break; -- irel_keeper = irel_keeper->next; -- } -- if (!irel_keeper) -- return FALSE; -+ case R_NDS32_TLS_IEGP_HI20: -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_HI20); -+ break; -+ case R_NDS32_TLS_IEGP_LO12: -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_LO12); -+ break; -+ case R_NDS32_TLS_IEGP_LW: -+ /* irel->r_info = ELF32_R_INFO(r_symndx, R_NDS32_TLS_LE_ADD); */ -+ bfd_putb32 (INSN_NOP, contents + irel->r_offset); -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_RELAX_REMOVE); -+ break; -+ case R_NDS32_LOADSTORE: -+ case R_NDS32_PTR: -+ case R_NDS32_NONE: -+ case R_NDS32_LABEL: -+ case R_NDS32_PTR_RESOLVED: -+ break; -+ default: -+ BFD_ASSERT(0); -+ break; - } -- if (!nds32_get_section_contents -- (irel_ptr->sec->owner, irel_ptr->sec, &contents, TRUE)) -- return FALSE; -- insn16 = INSN_IFCALL9 | (relocation >> 1); -- bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset); -- irel_ptr->irel->r_info = -- ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), -- R_NDS32_NONE); -+ break; -+ default: -+#ifdef DEBUG_VERBOSE -+ printf ( -+ "SKIP: %s: %s @ 0x%08x tls_type = 0x%08x, eff_tls_type = 0x%08x, org_tls_type = 0x%08x\n", -+ inbfd->filename, h ? h->root.root.string : "local", -+ (unsigned) irel->r_offset, tls_type, eff_tls_type, -+ org_tls_type); -+#endif -+ break; -+ } -+ break; -+ /* IE to LE. */ -+ case GOT_TLS_IE: -+ switch (eff_tls_type) -+ { -+ case GOT_TLS_LE: -+ switch (r_type) -+ { -+ case R_NDS32_TLS_IE_HI20: -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_HI20); -+ break; -+ case R_NDS32_TLS_IE_LO12S2: -+ { -+ uint32_t insn = bfd_getb32 (contents + irel->r_offset); -+ add_rt = N32_RT5 (insn); -+ insn = N32_TYPE2 (ORI, add_rt, sethi_rt, 0); -+ bfd_putb32 (insn, contents + irel->r_offset); -+ -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_LO12); -+ } -+ break; -+ /* -+ case R_NDS32_TLS_IE_ADD: -+ irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_ADD); -+ break; -+ */ -+ case R_NDS32_LOADSTORE: -+ case R_NDS32_PTR: -+ case R_NDS32_NONE: -+ case R_NDS32_LABEL: -+ break; -+ default: -+ BFD_ASSERT(0); -+ break; -+ } -+ break; -+ default: -+#ifdef DEBUG_VERBOSE -+ printf ( -+ "SKIP: %s: %s @ 0x%08x tls_type = 0x%08x, eff_tls_type = 0x%08x, org_tls_type = 0x%08x\n", -+ inbfd->filename, h ? h->root.root.string : "local", -+ (unsigned) irel->r_offset, tls_type, eff_tls_type, -+ org_tls_type); -+#endif -+ break; - } -- irel_ptr =irel_ptr->next; -+ break; -+ default: -+#ifdef DEBUG_VERBOSE -+ printf ( -+ "SKIP: %s: %s @ 0x%08x tls_type = 0x%08x, eff_tls_type = 0x%08x, org_tls_type = 0x%08x\n", -+ inbfd->filename, h ? h->root.root.string : "local", -+ (unsigned) irel->r_offset, tls_type, eff_tls_type, -+ org_tls_type); -+#endif -+ break; - } - } -+ pNextSig = pNextSig->next_sibling; - } -- ptr = ptr->next; -- } -- -- return TRUE; --} - --/* End of IFC relaxation. */ -- --/* EX9 Instruction Table Relaxation. */ -+#if 1 -+ pNext = pNext->next; -+#else -+ while (pNext) -+ { -+ if (pNext->id != cur_grp_id) -+ break; -+ pNext = pNext->next; -+ } -+#endif -+ } - --/* Global hash list. */ --struct elf_link_hash_entry_list --{ -- struct elf_link_hash_entry *h; -- struct elf_link_hash_entry_list *next; --}; -+finish: -+ if (incontents) -+ contents = NULL; - --/* Save different destination but same insn. */ --struct elf_link_hash_entry_mul_list --{ -- /* Global symbol times. */ -- int times; -- /* Save relocation for each global symbol but useful?? */ -- Elf_Internal_Rela *irel; -- /* For sethi, two sethi may have the same high-part but different low-parts. */ -- Elf_Internal_Rela rel_backup; -- struct elf_link_hash_entry_list *h_list; -- struct elf_link_hash_entry_mul_list *next; --}; -+ if (internal_relocs != NULL -+ && elf_section_data (insec)->relocs != internal_relocs) -+ free (internal_relocs); - --/* Instruction hash table. */ --struct elf_nds32_code_hash_entry --{ -- struct bfd_hash_entry root; -- int times; -- /* For insn that can use relocation or constant ex: sethi. */ -- int const_insn; -- asection *sec; -- struct elf_link_hash_entry_mul_list *m_list; -- /* Using r_addend. */ -- Elf_Internal_Rela *irel; -- /* Using r_info. */ -- Elf_Internal_Rela rel_backup; --}; -+ if (contents != NULL -+ && elf_section_data (insec)->this_hdr.contents != contents) -+ free (contents); - --/* Instruction count list. */ --struct elf_nds32_insn_times_entry --{ -- const char *string; -- int times; -- int order; -- asection *sec; -- struct elf_link_hash_entry_mul_list *m_list; -- Elf_Internal_Rela *irel; -- Elf_Internal_Rela rel_backup; -- struct elf_nds32_insn_times_entry *next; --}; -+ if (local_syms != NULL && symtab_hdr->contents != (bfd_byte *) local_syms) -+ free (local_syms); - --/* J and JAL symbol list. */ --struct elf_nds32_symbol_entry --{ -- char *string; -- unsigned long insn; -- struct elf_nds32_symbol_entry *next; --}; -+ if (chain.next) -+ { -+ pNext = chain.next; -+ relax_group_list_t *pDel; -+ while (pNext) -+ { -+ pDel = pNext; -+ pNext = pNext->next; -+ free (pDel); -+ } -+ } - --/* Relocation list. */ --struct elf_nds32_irel_entry --{ -- Elf_Internal_Rela *irel; -- struct elf_nds32_irel_entry *next; --}; -+ return result; - --/* ex9.it insn need to be fixed. */ --struct elf_nds32_ex9_refix --{ -- Elf_Internal_Rela *irel; -- asection *sec; -- struct elf_link_hash_entry *h; -- int order; -- struct elf_nds32_ex9_refix *next; --}; -+error_return: -+ result = FALSE; -+ goto finish; -+} - --static struct bfd_hash_table ex9_code_table; --static struct elf_nds32_insn_times_entry *ex9_insn_head = NULL; --static struct elf_nds32_ex9_refix *ex9_refix_head = NULL; -+/* End TLS model conversion. */ -+ - --/* EX9 hash function. */ -+/* Rom-patch table hash function. */ - - static struct bfd_hash_entry * --nds32_elf_code_hash_newfunc (struct bfd_hash_entry *entry, -- struct bfd_hash_table *table, -- const char *string) -+nds32_elf_ict_hash_newfunc (struct bfd_hash_entry *entry, -+ struct bfd_hash_table *table, -+ const char *string) - { -- struct elf_nds32_code_hash_entry *ret; -+ struct elf_nds32_ict_hash_entry *ret; - - /* Allocate the structure if it has not already been allocated by a - subclass. */ -@@ -13602,1837 +15138,118 @@ nds32_elf_code_hash_newfunc (struct bfd_hash_entry *entry, - if (entry == NULL) - return entry; - -- ret = (struct elf_nds32_code_hash_entry*) entry; -- ret->times = 0; -- ret->const_insn = 0; -- ret->m_list = NULL; -- ret->sec = NULL; -- ret->irel = NULL; -+ ret = (struct elf_nds32_ict_hash_entry*) entry; -+ ret->order = 0; - return &ret->root; - } - --/* Insert ex9 entry -- this insert must be stable sorted by times. */ -+static void -+nds32_elf_ict_hash_init (void) -+{ -+ if (!bfd_hash_table_init_n (&indirect_call_table, nds32_elf_ict_hash_newfunc, -+ sizeof (struct elf_nds32_ict_hash_entry), -+ 1023)) -+ _bfd_error_handler (_("ld error: cannot init rom patch hash table\n")); -+ return; -+} - -+/* Relocate for NDS32_ICT_SECTION. */ - static void --nds32_elf_ex9_insert_entry (struct elf_nds32_insn_times_entry *ptr) -+nds32_elf_ict_relocate (bfd *output_bfd, struct bfd_link_info *info) - { -- struct elf_nds32_insn_times_entry *temp; -- struct elf_nds32_insn_times_entry *temp2; -+ static bfd_boolean done = FALSE; -+ asection *sec; -+ bfd_byte *contents = NULL; -+ uint32_t insn; -+ unsigned int i; -+ struct elf_link_hash_entry *h; -+ struct bfd_link_hash_entry *h2; -+ bfd_vma relocation, base; - -- if (ex9_insn_head == NULL) -- { -- ex9_insn_head = ptr; -- ptr->next = NULL; -- } -- else -+ if (done) -+ return; -+ -+ done = TRUE; -+ -+ sec = nds32_elf_get_target_section (info, NDS32_ICT_SECTION); -+ h2 = bfd_link_hash_lookup (info->hash, "_INDIRECT_CALL_TABLE_BASE_", -+ FALSE, FALSE, FALSE); -+ base = ((h2->u.def.value -+ + h2->u.def.section->output_section->vma -+ + h2->u.def.section->output_offset)); -+ -+ if (!nds32_get_section_contents (sec->owner, sec, &contents, TRUE)) -+ return; -+ -+ indirect_call_table.frozen = 1; -+ for (i = 0; i < indirect_call_table.size; i++) - { -- temp = ex9_insn_head; -- temp2 = ex9_insn_head; -- while (temp->next && -- (temp->next->times >= ptr->times -- || temp->times == -1)) -- { -- if (temp->times == -1) -- temp2 = temp; -- temp = temp->next; -- } -- if (ptr->times > temp->times && temp->times != -1) -+ struct bfd_hash_entry *p; -+ struct elf_nds32_ict_hash_entry *entry; -+ -+ for (p = indirect_call_table.table[i]; p != NULL; p = p->next) - { -- ptr->next = temp; -- if (temp2->times == -1) -- temp2->next = ptr; -+ entry = (struct elf_nds32_ict_hash_entry *) p; -+ insn = INSN_J; -+ h = entry->h; -+ if ((h->root.type == bfd_link_hash_defined -+ || h->root.type == bfd_link_hash_defweak) -+ && h->root.u.def.section != NULL -+ && h->root.u.def.section->output_section != NULL) -+ { -+ if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) -+ { -+ insn = h->root.u.def.value + -+ h->root.u.def.section->output_section->vma + -+ h->root.u.def.section->output_offset; -+ bfd_put_32 (output_bfd, insn, contents + (entry->order) * 4); -+ } -+ else -+ { -+ relocation = h->root.u.def.value + -+ h->root.u.def.section->output_section->vma + -+ h->root.u.def.section->output_offset; -+ insn |= ((relocation - base - entry->order * 4) >> 1) -+ & 0xffffff; -+ bfd_putb32 (insn, contents + (entry->order) * 4); -+ } -+ } - else -- ex9_insn_head = ptr; -- } -- else if (temp->next == NULL) -- { -- temp->next = ptr; -- ptr->next = NULL; -- } -- else -- { -- ptr->next = temp->next; -- temp->next = ptr; -+ { -+ if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) -+ { -+ insn = 0; -+ bfd_put_32 (output_bfd, insn, contents + (entry->order) * 4); -+ } -+ else -+ bfd_putb32 (insn, contents + (entry->order) * 4); -+ } - } - } -+ indirect_call_table.frozen = 0; - } - --/* Examine each insn times in hash table. -- Handle multi-link hash entry. -- -- TODO: This function doesn't assign so much info since it is fake. */ -- --static int --nds32_elf_examine_insn_times (struct elf_nds32_code_hash_entry *h) -+static asection* -+nds32_elf_get_target_section (struct bfd_link_info *info, char *name) - { -- struct elf_nds32_insn_times_entry *ptr; -- int times; -+ asection *sec = NULL; -+ bfd *abfd; - -- if (h->m_list == NULL) -+ for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) - { -- /* Local symbol insn or insn without relocation. */ -- if (h->times < 3) -- return TRUE; -- -- ptr = (struct elf_nds32_insn_times_entry *) -- bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); -- ptr->times = h->times; -- ptr->string = h->root.string; -- ptr->m_list = NULL; -- ptr->sec = h->sec; -- ptr->irel = h->irel; -- ptr->rel_backup = h->rel_backup; -- nds32_elf_ex9_insert_entry (ptr); -+ sec = bfd_get_section_by_name (abfd, name); -+ if (sec != NULL) -+ break; - } -- else -- { -- /* Global symbol insn. */ -- /* Only sethi insn has multiple m_list. */ -- struct elf_link_hash_entry_mul_list *m_list = h->m_list; - -- times = 0; -- while (m_list) -- { -- times += m_list->times; -- m_list = m_list->next; -- } -- if (times >= 3) -- { -- m_list = h->m_list; -- ptr = (struct elf_nds32_insn_times_entry *) -- bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); -- ptr->times = times; /* Use the total times. */ -- ptr->string = h->root.string; -- ptr->m_list = m_list; -- ptr->sec = h->sec; -- ptr->irel = m_list->irel; -- ptr->rel_backup = m_list->rel_backup; -- nds32_elf_ex9_insert_entry (ptr); -- } -- if (h->const_insn == 1) -- { -- /* sethi with constant value. */ -- if (h->times < 3) -- return TRUE; -- -- ptr = (struct elf_nds32_insn_times_entry *) -- bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); -- ptr->times = h->times; -- ptr->string = h->root.string; -- ptr->m_list = NULL; -- ptr->sec = NULL; -- ptr->irel = NULL; -- ptr->rel_backup = h->rel_backup; -- nds32_elf_ex9_insert_entry (ptr); -- } -- } -- return TRUE; --} -- --/* Count each insn times in hash table. -- Handle multi-link hash entry. */ -- --static int --nds32_elf_count_insn_times (struct elf_nds32_code_hash_entry *h) --{ -- int reservation, times; -- unsigned long relocation, min_relocation; -- struct elf_nds32_insn_times_entry *ptr; -- -- if (h->m_list == NULL) -- { -- /* Local symbol insn or insn without relocation. */ -- if (h->times < 3) -- return TRUE; -- ptr = (struct elf_nds32_insn_times_entry *) -- bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); -- ptr->times = h->times; -- ptr->string = h->root.string; -- ptr->m_list = NULL; -- ptr->sec = h->sec; -- ptr->irel = h->irel; -- ptr->rel_backup = h->rel_backup; -- nds32_elf_ex9_insert_entry (ptr); -- } -- else -- { -- /* Global symbol insn. */ -- /* Only sethi insn has multiple m_list. */ -- struct elf_link_hash_entry_mul_list *m_list = h->m_list; -- -- if (ELF32_R_TYPE (m_list->rel_backup.r_info) == R_NDS32_HI20_RELA -- && m_list->next != NULL) -- { -- /* Sethi insn has different symbol or addend but has same hi20. */ -- times = 0; -- reservation = 1; -- relocation = 0; -- min_relocation = 0xffffffff; -- while (m_list) -- { -- /* Get the minimum sethi address -- and calculate how many entry the sethi-list have to use. */ -- if ((m_list->h_list->h->root.type == bfd_link_hash_defined -- || m_list->h_list->h->root.type == bfd_link_hash_defweak) -- && (m_list->h_list->h->root.u.def.section != NULL -- && m_list->h_list->h->root.u.def.section->output_section != NULL)) -- { -- relocation = (m_list->h_list->h->root.u.def.value + -- m_list->h_list->h->root.u.def.section->output_section->vma + -- m_list->h_list->h->root.u.def.section->output_offset); -- relocation += m_list->irel->r_addend; -- } -- else -- relocation = 0; -- if (relocation < min_relocation) -- min_relocation = relocation; -- times += m_list->times; -- m_list = m_list->next; -- } -- if (min_relocation < ex9_relax_size) -- reservation = (min_relocation >> 12) + 1; -- else -- reservation = (min_relocation >> 12) -- - ((min_relocation - ex9_relax_size) >> 12) + 1; -- if (reservation < (times / 3)) -- { -- /* Efficient enough to use ex9. */ -- int i; -- -- for (i = reservation ; i > 0; i--) -- { -- /* Allocate number of reservation ex9 entry. */ -- ptr = (struct elf_nds32_insn_times_entry *) -- bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); -- ptr->times = h->m_list->times / reservation; -- ptr->string = h->root.string; -- ptr->m_list = h->m_list; -- ptr->sec = h->sec; -- ptr->irel = h->m_list->irel; -- ptr->rel_backup = h->m_list->rel_backup; -- nds32_elf_ex9_insert_entry (ptr); -- } -- } -- } -- else -- { -- /* Normal global symbol that means no different address symbol -- using same ex9 entry. */ -- if (m_list->times >= 3) -- { -- ptr = (struct elf_nds32_insn_times_entry *) -- bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); -- ptr->times = m_list->times; -- ptr->string = h->root.string; -- ptr->m_list = h->m_list; -- ptr->sec = h->sec; -- ptr->irel = h->m_list->irel; -- ptr->rel_backup = h->m_list->rel_backup; -- nds32_elf_ex9_insert_entry (ptr); -- } -- } -- -- if (h->const_insn == 1) -- { -- /* sethi with constant value. */ -- if (h->times < 3) -- return TRUE; -- -- ptr = (struct elf_nds32_insn_times_entry *) -- bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); -- ptr->times = h->times; -- ptr->string = h->root.string; -- ptr->m_list = NULL; -- ptr->sec = NULL; -- ptr->irel = NULL; -- ptr->rel_backup = h->rel_backup; -- nds32_elf_ex9_insert_entry (ptr); -- } -- } -- -- return TRUE; --} -- --/* Hash table traverse function. */ -- --static void --nds32_elf_code_hash_traverse (int (*func) (struct elf_nds32_code_hash_entry*)) --{ -- unsigned int i; -- -- ex9_code_table.frozen = 1; -- for (i = 0; i < ex9_code_table.size; i++) -- { -- struct bfd_hash_entry *p; -- -- for (p = ex9_code_table.table[i]; p != NULL; p = p->next) -- if (!func ((struct elf_nds32_code_hash_entry *) p)) -- goto out; -- } --out: -- ex9_code_table.frozen = 0; --} -- -- --/* Give order number to insn list. */ -- --static void --nds32_elf_order_insn_times (struct bfd_link_info *info) --{ -- struct elf_nds32_insn_times_entry *ex9_insn; -- struct elf_nds32_insn_times_entry *temp = NULL; -- struct elf_nds32_link_hash_table *table; -- int ex9_limit; -- int number = 0; -- -- if (ex9_insn_head == NULL) -- return; -- --/* The max number of entries is 512. */ -- ex9_insn = ex9_insn_head; -- table = nds32_elf_hash_table (info); -- ex9_limit = table->ex9_limit; -- -- ex9_insn = ex9_insn_head; -- -- while (ex9_insn != NULL && number < ex9_limit) -- { -- ex9_insn->order = number; -- number++; -- temp = ex9_insn; -- ex9_insn = ex9_insn->next; -- } -- -- if (ex9_insn && temp) -- temp->next = NULL; -- -- while (ex9_insn != NULL) -- { -- /* Free useless entry. */ -- temp = ex9_insn; -- ex9_insn = ex9_insn->next; -- free (temp); -- } --} -- --/* Build .ex9.itable section. */ -- --static void --nds32_elf_ex9_build_itable (struct bfd_link_info *link_info) --{ -- asection *table_sec; -- struct elf_nds32_insn_times_entry *ptr; -- bfd *it_abfd; -- int number = 0; -- bfd_byte *contents = NULL; -- -- for (it_abfd = link_info->input_bfds; it_abfd != NULL; -- it_abfd = it_abfd->link.next) -- { -- /* Find the section .ex9.itable, and put all entries into it. */ -- table_sec = bfd_get_section_by_name (it_abfd, ".ex9.itable"); -- if (table_sec != NULL) -- { -- if (!nds32_get_section_contents (it_abfd, table_sec, &contents, TRUE)) -- return; -- -- for (ptr = ex9_insn_head; ptr !=NULL ; ptr = ptr->next) -- number++; -- -- table_sec->size = number * 4; -- -- if (number == 0) -- return; -- -- elf_elfheader (link_info->output_bfd)->e_flags |= E_NDS32_HAS_EX9_INST; -- number = 0; -- for (ptr = ex9_insn_head; ptr !=NULL ; ptr = ptr->next) -- { -- long val; -- -- val = strtol (ptr->string, NULL, 16); -- bfd_putb32 ((bfd_vma) val, (char *) contents + (number * 4)); -- number++; -- } -- break; -- } -- } --} -- --/* Get insn with regs according to relocation type. */ -- --static void --nds32_elf_get_insn_with_reg (Elf_Internal_Rela *irel, -- uint32_t insn, uint32_t *insn_with_reg) --{ -- reloc_howto_type *howto = NULL; -- -- if (irel == NULL -- || (ELF32_R_TYPE (irel->r_info) >= (int) ARRAY_SIZE (nds32_elf_howto_table) -- && (ELF32_R_TYPE (irel->r_info) - R_NDS32_RELAX_ENTRY) -- >= (int) ARRAY_SIZE (nds32_elf_relax_howto_table))) -- { -- *insn_with_reg = insn; -- return; -- } -- -- howto = bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE (irel->r_info)); -- *insn_with_reg = insn & (0xffffffff ^ howto->dst_mask); --} -- --/* Mask number of address bits according to relocation. */ -- --static unsigned long --nds32_elf_irel_mask (Elf_Internal_Rela *irel) --{ -- reloc_howto_type *howto = NULL; -- -- if (irel == NULL -- || (ELF32_R_TYPE (irel->r_info) >= (int) ARRAY_SIZE (nds32_elf_howto_table) -- && (ELF32_R_TYPE (irel->r_info) - R_NDS32_RELAX_ENTRY) -- >= (int) ARRAY_SIZE (nds32_elf_relax_howto_table))) -- return 0; -- -- howto = bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE (irel->r_info)); -- return howto->dst_mask; --} -- --static void --nds32_elf_insert_irel_entry (struct elf_nds32_irel_entry **irel_list, -- struct elf_nds32_irel_entry *irel_ptr) --{ -- if (*irel_list == NULL) -- { -- *irel_list = irel_ptr; -- irel_ptr->next = NULL; -- } -- else -- { -- irel_ptr->next = *irel_list; -- *irel_list = irel_ptr; -- } --} -- --static void --nds32_elf_ex9_insert_fix (asection * sec, Elf_Internal_Rela * irel, -- struct elf_link_hash_entry *h, int order) --{ -- struct elf_nds32_ex9_refix *ptr; -- -- ptr = bfd_malloc (sizeof (struct elf_nds32_ex9_refix)); -- ptr->sec = sec; -- ptr->irel = irel; -- ptr->h = h; -- ptr->order = order; -- ptr->next = NULL; -- -- if (ex9_refix_head == NULL) -- ex9_refix_head = ptr; -- else -- { -- struct elf_nds32_ex9_refix *temp = ex9_refix_head; -- -- while (temp->next != NULL) -- temp = temp->next; -- temp->next = ptr; -- } --} -- --enum --{ -- DATA_EXIST = 1, -- CLEAN_PRE = 1 << 1, -- PUSH_PRE = 1 << 2 --}; -- --/* Check relocation type if supporting for ex9. */ -- --static int --nds32_elf_ex9_relocation_check (struct bfd_link_info *info, -- Elf_Internal_Rela **irel, -- Elf_Internal_Rela *irelend, -- nds32_elf_blank_t *relax_blank_list, -- asection *sec,bfd_vma *off, -- bfd_byte *contents) --{ -- /* Suppress ex9 if `.no_relax ex9' or inner loop. */ -- bfd_boolean nested_ex9, nested_loop; -- bfd_boolean ex9_loop_aware; -- /* We use the highest 1 byte of result to record -- how many bytes location counter has to move. */ -- int result = 0; -- Elf_Internal_Rela *irel_save = NULL; -- struct elf_nds32_link_hash_table *table; -- -- table = nds32_elf_hash_table (info); -- ex9_loop_aware = table->ex9_loop_aware; -- -- while ((*irel) != NULL && (*irel) < irelend && *off == (*irel)->r_offset) -- { -- switch (ELF32_R_TYPE ((*irel)->r_info)) -- { -- case R_NDS32_RELAX_REGION_BEGIN: -- /* Ignore code block. */ -- nested_ex9 = FALSE; -- nested_loop = FALSE; -- if (((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG) -- || (ex9_loop_aware -- && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG))) -- { -- /* Check the region if loop or not. If it is true and -- ex9-loop-aware is true, ignore the region till region end. */ -- /* To save the status for in .no_relax ex9 region and -- loop region to conform the block can do ex9 relaxation. */ -- nested_ex9 = ((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG); -- nested_loop = (ex9_loop_aware -- && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG)); -- while ((*irel) && (*irel) < irelend && (nested_ex9 || nested_loop)) -- { -- (*irel)++; -- if (ELF32_R_TYPE ((*irel)->r_info) == R_NDS32_RELAX_REGION_BEGIN) -- { -- /* There may be nested region. */ -- if (((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG) != 0) -- nested_ex9 = TRUE; -- else if (ex9_loop_aware -- && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG)) -- nested_loop = TRUE; -- } -- else if (ELF32_R_TYPE ((*irel)->r_info) == R_NDS32_RELAX_REGION_END) -- { -- /* The end of region. */ -- if (((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG) != 0) -- nested_ex9 = FALSE; -- else if (ex9_loop_aware -- && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG)) -- nested_loop = FALSE; -- } -- else if (ELF32_R_TYPE ((*irel)->r_info) == R_NDS32_LABEL -- && ((*irel)->r_addend & 0x1f) == 2) -- { -- /* Alignment exist in the region. */ -- result |= CLEAN_PRE; -- if (((*irel)->r_offset - -- get_nds32_elf_blank_total (&relax_blank_list, -- (*irel)->r_offset, 0)) & 0x02) -- result |= PUSH_PRE; -- } -- } -- if ((*irel) >= irelend) -- *off = sec->size; -- else -- *off = (*irel)->r_offset; -- -- /* The final instruction in the region, regard this one as data to ignore it. */ -- result |= DATA_EXIST; -- return result; -- } -- break; -- -- case R_NDS32_LABEL: -- if (((*irel)->r_addend & 0x1f) == 2) -- { -- /* Check this point is align and decide to do ex9 or not. */ -- result |= CLEAN_PRE; -- if (((*irel)->r_offset - -- get_nds32_elf_blank_total (&relax_blank_list, -- (*irel)->r_offset, 0)) & 0x02) -- result |= PUSH_PRE; -- } -- break; -- case R_NDS32_32_RELA: -- /* Data. */ -- result |= (4 << 24); -- result |= DATA_EXIST; -- break; -- case R_NDS32_16_RELA: -- /* Data. */ -- result |= (2 << 24); -- result |= DATA_EXIST; -- break; -- case R_NDS32_DATA: -- /* Data. */ -- /* The least code alignment is 2. If the data is only one byte, -- we have to shift one more byte. */ -- if ((*irel)->r_addend == 1) -- result |= ((*irel)->r_addend << 25) ; -- else -- result |= ((*irel)->r_addend << 24) ; -- -- result |= DATA_EXIST; -- break; -- -- case R_NDS32_25_PCREL_RELA: -- case R_NDS32_SDA16S3_RELA: -- case R_NDS32_SDA15S3_RELA: -- case R_NDS32_SDA15S3: -- case R_NDS32_SDA17S2_RELA: -- case R_NDS32_SDA15S2_RELA: -- case R_NDS32_SDA12S2_SP_RELA: -- case R_NDS32_SDA12S2_DP_RELA: -- case R_NDS32_SDA15S2: -- case R_NDS32_SDA18S1_RELA: -- case R_NDS32_SDA15S1_RELA: -- case R_NDS32_SDA15S1: -- case R_NDS32_SDA19S0_RELA: -- case R_NDS32_SDA15S0_RELA: -- case R_NDS32_SDA15S0: -- case R_NDS32_HI20_RELA: -- case R_NDS32_LO12S0_ORI_RELA: -- case R_NDS32_LO12S0_RELA: -- case R_NDS32_LO12S1_RELA: -- case R_NDS32_LO12S2_RELA: -- /* These relocation is supported ex9 relaxation currently. */ -- /* We have to save the relocation for using later, since we have -- to check there is any alignment in the same address. */ -- irel_save = *irel; -- break; -- default: -- /* Not support relocations. */ -- if (ELF32_R_TYPE ((*irel)->r_info) < ARRAY_SIZE (nds32_elf_howto_table) -- && ELF32_R_TYPE ((*irel)->r_info) != R_NDS32_NONE -- && ELF32_R_TYPE ((*irel)->r_info) != R_NDS32_INSN16) -- { -- /* Note: To optimize aggressively, it maybe can ignore R_NDS32_INSN16 here. -- But we have to consider if there is any side-effect. */ -- if (!(result & DATA_EXIST)) -- { -- /* We have to confirm there is no data relocation in the -- same address. In general case, this won't happen. */ -- /* We have to do ex9 conservative, for those relocation not -- considerd we ignore instruction. */ -- result |= DATA_EXIST; -- if (*(contents + *off) & 0x80) -- result |= (2 << 24); -- else -- result |= (4 << 24); -- break; -- } -- } -- } -- if ((*irel) < irelend -- && ((*irel) + 1) < irelend -- && (*irel)->r_offset == ((*irel) + 1)->r_offset) -- /* There are relocations pointing to the same address, we have to -- check all of them. */ -- (*irel)++; -- else -- { -- if (irel_save) -- *irel = irel_save; -- return result; -- } -- } -- return result; --} -- --/* Replace with ex9 instruction. */ -- --static bfd_boolean --nds32_elf_ex9_push_insn (uint16_t insn16, bfd_byte *contents, bfd_vma pre_off, -- nds32_elf_blank_t **relax_blank_list, -- struct elf_nds32_irel_entry *pre_irel_ptr, -- struct elf_nds32_irel_entry **irel_list) --{ -- if (insn16 != 0) -- { -- /* Implement the ex9 relaxation. */ -- bfd_putb16 (insn16, contents + pre_off); -- if (!insert_nds32_elf_blank_recalc_total (relax_blank_list, -- pre_off + 2, 2)) -- return FALSE; -- if (pre_irel_ptr != NULL) -- nds32_elf_insert_irel_entry (irel_list, pre_irel_ptr); -- } -- return TRUE; --} -- --/* Replace input file instruction which is in ex9 itable. */ -- --static bfd_boolean --nds32_elf_ex9_replace_instruction (struct bfd_link_info *info, bfd *abfd, asection *sec) --{ -- struct elf_nds32_insn_times_entry *ex9_insn = ex9_insn_head; -- bfd_byte *contents = NULL; -- bfd_vma off; -- uint16_t insn16, insn_ex9; -- /* `pre_*' are used to track previous instruction that can use ex9.it. */ -- bfd_vma pre_off = -1; -- uint16_t pre_insn16 = 0; -- struct elf_nds32_irel_entry *pre_irel_ptr = NULL; -- Elf_Internal_Rela *internal_relocs; -- Elf_Internal_Rela *irel; -- Elf_Internal_Rela *irelend; -- Elf_Internal_Shdr *symtab_hdr; -- Elf_Internal_Sym *isym = NULL; -- nds32_elf_blank_t *relax_blank_list = NULL; -- uint32_t insn = 0; -- uint32_t insn_with_reg = 0; -- uint32_t it_insn; -- uint32_t it_insn_with_reg; -- unsigned long r_symndx; -- asection *isec; -- struct elf_nds32_irel_entry *irel_list = NULL; -- struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd); -- int data_flag, do_replace, save_irel; -- struct elf_link_hash_entry_list *h_list; -- -- -- /* Load section instructions, relocations, and symbol table. */ -- if (!nds32_get_section_contents (abfd, sec, &contents, TRUE) -- || !nds32_get_local_syms (abfd, sec, &isym)) -- return FALSE; -- internal_relocs = -- _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, TRUE /* keep_memory */); -- irelend = internal_relocs + sec->reloc_count; -- symtab_hdr = &elf_tdata (abfd)->symtab_hdr; -- -- off = 0; -- -- /* Check if the object enable ex9. */ -- irel = find_relocs_at_address (internal_relocs, internal_relocs, -- irelend, R_NDS32_RELAX_ENTRY); -- -- /* Check this section trigger ex9 relaxation. */ -- if (irel == NULL -- || irel >= irelend -- || ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_ENTRY -- || (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY -- && !(irel->r_addend & R_NDS32_RELAX_ENTRY_EX9_FLAG))) -- return TRUE; -- -- irel = internal_relocs; -- -- /* Check alignment and fetch proper relocation. */ -- while (off < sec->size) -- { -- struct elf_link_hash_entry *h = NULL; -- struct elf_nds32_irel_entry *irel_ptr = NULL; -- -- /* Syn the instruction and the relocation. */ -- while (irel != NULL && irel < irelend && irel->r_offset < off) -- irel++; -- -- data_flag = nds32_elf_ex9_relocation_check (info, &irel, irelend, -- relax_blank_list, sec, -- &off, contents); -- if (data_flag & PUSH_PRE) -- if (!nds32_elf_ex9_push_insn (pre_insn16, contents, pre_off, -- &relax_blank_list, pre_irel_ptr, -- &irel_list)) -- return FALSE; -- -- if (data_flag & CLEAN_PRE) -- { -- pre_off = 0; -- pre_insn16 = 0; -- pre_irel_ptr = NULL; -- } -- if (data_flag & DATA_EXIST) -- { -- /* We save the move offset in the highest byte. */ -- off += (data_flag >> 24); -- continue; -- } -- -- if (*(contents + off) & 0x80) -- { -- /* 2-byte instruction. */ -- off += 2; -- continue; -- } -- -- /* Load the instruction and its opcode with register for comparing. */ -- ex9_insn = ex9_insn_head; -- insn = bfd_getb32 (contents + off); -- insn_with_reg = 0; -- while (ex9_insn) -- { -- it_insn = strtol (ex9_insn->string, NULL, 16); -- it_insn_with_reg = 0; -- do_replace = 0; -- save_irel = 0; -- -- if (irel != NULL && irel < irelend && irel->r_offset == off) -- { -- /* Insn with relocation. */ -- nds32_elf_get_insn_with_reg (irel, insn, &insn_with_reg); -- -- if (ex9_insn->irel != NULL) -- nds32_elf_get_insn_with_reg (ex9_insn->irel, it_insn, -- &it_insn_with_reg); -- -- if (ex9_insn->irel != NULL -- && (ELF32_R_TYPE (irel->r_info) == -- ELF32_R_TYPE (ex9_insn->irel->r_info)) -- && (insn_with_reg == it_insn_with_reg)) -- { -- /* Insn relocation and format is the same as table entry. */ -- -- if (ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_ORI_RELA -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_RELA -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S1_RELA -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S2_RELA -- || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3 -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0) -- || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3_RELA -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0_RELA) -- || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA12S2_DP_RELA -- && ELF32_R_TYPE (irel->r_info) <= -- R_NDS32_SDA12S2_SP_RELA) -- || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA16S3_RELA -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA19S0_RELA)) -- { -- r_symndx = ELF32_R_SYM (irel->r_info); -- if (r_symndx < symtab_hdr->sh_info) -- { -- /* Local symbol. */ -- int shndx = isym[r_symndx].st_shndx; -- -- isec = elf_elfsections (abfd)[shndx]->bfd_section; -- if (ex9_insn->sec == isec -- && ex9_insn->irel->r_addend == irel->r_addend -- && ex9_insn->irel->r_info == irel->r_info) -- { -- do_replace = 1; -- save_irel = 1; -- } -- } -- else -- { -- /* External symbol. */ -- h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -- if (ex9_insn->m_list) -- { -- h_list = ex9_insn->m_list->h_list; -- while (h_list) -- { -- if (h == h_list->h -- && (ex9_insn->m_list->irel->r_addend == -- irel->r_addend)) -- { -- do_replace = 1; -- save_irel = 1; -- break; -- } -- h_list = h_list->next; -- } -- } -- } -- } -- else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_HI20_RELA) -- { -- r_symndx = ELF32_R_SYM (irel->r_info); -- if (r_symndx < symtab_hdr->sh_info) -- { -- /* Local symbols. Compare its base symbol and offset. */ -- int shndx = isym[r_symndx].st_shndx; -- -- isec = elf_elfsections (abfd)[shndx]->bfd_section; -- if (ex9_insn->sec == isec -- && ex9_insn->irel->r_addend == irel->r_addend -- && ex9_insn->irel->r_info == irel->r_info) -- { -- do_replace = 1; -- save_irel = 1; -- } -- } -- else -- { -- /* External symbol. */ -- struct elf_link_hash_entry_mul_list *m_list; -- -- h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -- m_list = ex9_insn->m_list; -- -- while (m_list) -- { -- h_list = m_list->h_list; -- -- while (h_list) -- { -- if (h == h_list->h -- && (m_list->irel->r_addend -- == irel->r_addend)) -- { -- do_replace = 1; -- save_irel = 1; -- if (ex9_insn->next -- && ex9_insn->m_list -- && ex9_insn->m_list == ex9_insn->next->m_list) -- { -- /* sethi multiple entry must be fixed */ -- nds32_elf_ex9_insert_fix (sec, irel, -- h, ex9_insn->order); -- } -- break; -- } -- h_list = h_list->next; -- } -- m_list = m_list->next; -- } -- } -- } -- } -- -- /* Import table: Check the symbol hash table and the -- jump target. Only R_NDS32_25_PCREL_RELA now. */ -- else if (ex9_insn->times == -1 -- && ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA) -- { -- nds32_elf_get_insn_with_reg (irel, it_insn, &it_insn_with_reg); -- if (insn_with_reg == it_insn_with_reg) -- { -- char code[10]; -- bfd_vma relocation; -- -- r_symndx = ELF32_R_SYM (irel->r_info); -- if (r_symndx >= symtab_hdr->sh_info) -- { -- h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -- if ((h->root.type == bfd_link_hash_defined -- || h->root.type == bfd_link_hash_defweak) -- && h->root.u.def.section != NULL -- && h->root.u.def.section->output_section != NULL -- && h->root.u.def.section->gc_mark == 1 -- && bfd_is_abs_section (h->root.u.def.section) -- && h->root.u.def.value > sec->size) -- { -- relocation = h->root.u.def.value + -- h->root.u.def.section->output_section->vma + -- h->root.u.def.section->output_offset; -- relocation += irel->r_addend; -- insn = insn_with_reg -- | ((relocation >> 1) & 0xffffff); -- snprintf (code, sizeof (code), "%08x", insn); -- if (strcmp (code, ex9_insn->string) == 0) -- { -- do_replace = 1; -- save_irel = 1; -- } -- } -- } -- } -- } -- else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_BEGIN -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_END -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_NONE) -- { -- /* These relocations do not have to relocate contens, so it can -- be regard as instruction without relocation. */ -- if (insn == it_insn && ex9_insn->irel == NULL) -- do_replace = 1; -- } -- } -- else -- { -- /* Instruction without relocation, we only -- have to compare their byte code. */ -- if (insn == it_insn && ex9_insn->irel == NULL) -- do_replace = 1; -- } -- -- /* Insntruction match so replacing the code here. */ -- if (do_replace == 1) -- { -- /* There are two formats of ex9 instruction. */ -- if (ex9_insn->order < 32) -- insn_ex9 = INSN_EX9_IT_2; -- else -- insn_ex9 = INSN_EX9_IT_1; -- insn16 = insn_ex9 | ex9_insn->order; -- -- /* Insert ex9 instruction. */ -- nds32_elf_ex9_push_insn (pre_insn16, contents, pre_off, -- &relax_blank_list, pre_irel_ptr, -- &irel_list); -- pre_off = off; -- pre_insn16 = insn16; -- -- if (save_irel) -- { -- /* For instuction with relocation do relax. */ -- irel_ptr = (struct elf_nds32_irel_entry *) -- bfd_malloc (sizeof (struct elf_nds32_irel_entry)); -- irel_ptr->irel = irel; -- irel_ptr->next = NULL; -- pre_irel_ptr = irel_ptr; -- } -- else -- pre_irel_ptr = NULL; -- break; -- } -- ex9_insn = ex9_insn->next; -- } -- off += 4; -- } -- -- /* Insert ex9 instruction. */ -- nds32_elf_ex9_push_insn (pre_insn16, contents, pre_off, -- &relax_blank_list, pre_irel_ptr, -- &irel_list); -- -- /* Delete the redundant code. */ -- if (relax_blank_list) -- { -- nds32_elf_relax_delete_blanks (abfd, sec, relax_blank_list); -- relax_blank_list = NULL; -- } -- -- /* Clear the relocation that is replaced by ex9. */ -- while (irel_list) -- { -- struct elf_nds32_irel_entry *irel_ptr; -- -- irel_ptr = irel_list; -- irel_list = irel_ptr->next; -- irel_ptr->irel->r_info = -- ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), R_NDS32_TRAN); -- free (irel_ptr); -- } -- return TRUE; --} -- --/* Initialize ex9 hash table. */ -- --int --nds32_elf_ex9_init (void) --{ -- if (!bfd_hash_table_init_n (&ex9_code_table, nds32_elf_code_hash_newfunc, -- sizeof (struct elf_nds32_code_hash_entry), -- 1023)) -- { -- _bfd_error_handler (_("Linker: cannot init ex9 hash table error \n")); -- return FALSE; -- } -- return TRUE; --} -- --/* Predict how many bytes will be relaxed with ex9 and ifc. */ -- --static void --nds32_elf_ex9_total_relax (struct bfd_link_info *info) --{ -- struct elf_nds32_insn_times_entry *ex9_insn; -- struct elf_nds32_insn_times_entry *temp; -- int target_optimize; -- struct elf_nds32_link_hash_table *table; -- -- if (ex9_insn_head == NULL) -- return; -- -- table = nds32_elf_hash_table (info); -- target_optimize = table->target_optimize; -- ex9_insn = ex9_insn_head; -- while (ex9_insn) -- { -- ex9_relax_size = ex9_insn->times * 2 + ex9_relax_size; -- temp = ex9_insn; -- ex9_insn = ex9_insn->next; -- free (temp); -- } -- ex9_insn_head = NULL; -- -- if ((target_optimize & NDS32_RELAX_JUMP_IFC_ON)) -- { -- /* Examine ifc reduce size. */ -- struct elf_nds32_ifc_symbol_entry *ifc_ent = ifc_symbol_head; -- struct elf_nds32_ifc_irel_list *irel_ptr = NULL; -- int size = 0; -- -- while (ifc_ent) -- { -- if (ifc_ent->enable == 0) -- { -- /* Not ifc yet. */ -- irel_ptr = ifc_ent->irel_head; -- while (irel_ptr) -- { -- size += 2; -- irel_ptr = irel_ptr->next; -- } -- } -- size -= 2; -- ifc_ent = ifc_ent->next; -- } -- ex9_relax_size += size; -- } --} -- --/* Finish ex9 table. */ -- --void --nds32_elf_ex9_finish (struct bfd_link_info *link_info) --{ -- nds32_elf_code_hash_traverse (nds32_elf_examine_insn_times); -- nds32_elf_order_insn_times (link_info); -- nds32_elf_ex9_total_relax (link_info); -- /* Traverse the hash table and count its times. */ -- nds32_elf_code_hash_traverse (nds32_elf_count_insn_times); -- nds32_elf_order_insn_times (link_info); -- nds32_elf_ex9_build_itable (link_info); --} -- --/* Relocate the entries in ex9 table. */ -- --static bfd_vma --nds32_elf_ex9_reloc_insn (struct elf_nds32_insn_times_entry *ptr, -- struct bfd_link_info *link_info) --{ -- Elf_Internal_Sym *isym = NULL; -- bfd_vma relocation = -1; -- struct elf_link_hash_entry *h; -- -- if (ptr->m_list != NULL) -- { -- /* Global symbol. */ -- h = ptr->m_list->h_list->h; -- if ((h->root.type == bfd_link_hash_defined -- || h->root.type == bfd_link_hash_defweak) -- && h->root.u.def.section != NULL -- && h->root.u.def.section->output_section != NULL) -- { -- -- relocation = h->root.u.def.value + -- h->root.u.def.section->output_section->vma + -- h->root.u.def.section->output_offset; -- relocation += ptr->m_list->irel->r_addend; -- } -- else -- relocation = 0; -- } -- else if (ptr->sec !=NULL) -- { -- /* Local symbol. */ -- Elf_Internal_Sym sym; -- asection *sec = NULL; -- asection isec; -- asection *isec_ptr = &isec; -- Elf_Internal_Rela irel_backup = *(ptr->irel); -- asection *sec_backup = ptr->sec; -- bfd *abfd = ptr->sec->owner; -- -- if (!nds32_get_local_syms (abfd, sec, &isym)) -- return FALSE; -- isym = isym + ELF32_R_SYM (ptr->irel->r_info); -- -- sec = bfd_section_from_elf_index (abfd, isym->st_shndx); -- if (sec != NULL) -- *isec_ptr = *sec; -- sym = *isym; -- -- /* The purpose is same as elf_link_input_bfd. */ -- if (isec_ptr != NULL -- && isec_ptr->sec_info_type == SEC_INFO_TYPE_MERGE -- && ELF_ST_TYPE (isym->st_info) != STT_SECTION) -- { -- sym.st_value = -- _bfd_merged_section_offset (ptr->sec->output_section->owner, &isec_ptr, -- elf_section_data (isec_ptr)->sec_info, -- isym->st_value); -- } -- relocation = _bfd_elf_rela_local_sym (link_info->output_bfd, &sym, -- &ptr->sec, ptr->irel); -- if (ptr->irel != NULL) -- relocation += ptr->irel->r_addend; -- -- /* Restore origin value since there may be some insntructions that -- could not be replaced with ex9.it. */ -- *(ptr->irel) = irel_backup; -- ptr->sec = sec_backup; -- } -- -- return relocation; --} -- --/* Import ex9 table and build list. */ -- --void --nds32_elf_ex9_import_table (struct bfd_link_info *info) --{ -- int num = 0; -- bfd_byte *contents; -- FILE *ex9_import_file; -- int update_ex9_table; -- struct elf_nds32_link_hash_table *table; -- -- table = nds32_elf_hash_table (info); -- ex9_import_file = table->ex9_import_file; -- rewind (table->ex9_import_file); -- -- contents = bfd_malloc (sizeof (bfd_byte) * 4); -- -- /* Read instructions from the input file and build the list. */ -- while (!feof (ex9_import_file)) -- { -- unsigned long insn; -- char *code; -- struct elf_nds32_insn_times_entry *ptr; -- size_t nread; -- -- nread = fread (contents, sizeof (bfd_byte) * 4, 1, ex9_import_file); -- /* Ignore the final byte 0x0a. */ -- if (nread < 1) -- break; -- insn = bfd_getb32 (contents); -- code = bfd_malloc (sizeof (char) * 9); -- snprintf (code, 9, "%08lx", (insn & 0xffffffff)); -- ptr = bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); -- ptr->string = code; -- ptr->order = num; -- ptr->times = -1; -- ptr->sec = NULL; -- ptr->m_list = NULL; -- ptr->rel_backup.r_offset = 0; -- ptr->rel_backup.r_info = 0; -- ptr->rel_backup.r_addend = 0; -- ptr->irel = NULL; -- ptr->next = NULL; -- nds32_elf_ex9_insert_entry (ptr); -- num++; -- } -- -- update_ex9_table = table->update_ex9_table; -- if (update_ex9_table == 1) -- { -- /* It has to consider of sethi need to use multiple page -- but it not be done yet. */ -- nds32_elf_code_hash_traverse (nds32_elf_examine_insn_times); -- nds32_elf_order_insn_times (info); -- } --} -- --/* Export ex9 table. */ -- --static void --nds32_elf_ex9_export (struct bfd_link_info *info, -- bfd_byte *contents, int size) --{ -- FILE *ex9_export_file; -- struct elf_nds32_link_hash_table *table; -- -- table = nds32_elf_hash_table (info); -- ex9_export_file = table->ex9_export_file; -- fwrite (contents, sizeof (bfd_byte), size, ex9_export_file); -- fclose (ex9_export_file); --} -- --/* Adjust relocations of J and JAL in ex9.itable. -- Export ex9 table. */ -- --static void --nds32_elf_ex9_reloc_jmp (struct bfd_link_info *link_info) --{ -- asection *table_sec = NULL; -- struct elf_nds32_insn_times_entry *ex9_insn = ex9_insn_head; -- struct elf_nds32_insn_times_entry *temp_ptr, *temp_ptr2; -- bfd *it_abfd; -- uint32_t insn, insn_with_reg, source_insn; -- bfd_byte *contents = NULL, *source_contents = NULL; -- int size = 0; -- bfd_vma gp; -- int shift, update_ex9_table, offset = 0; -- reloc_howto_type *howto = NULL; -- Elf_Internal_Rela rel_backup; -- unsigned short insn_ex9; -- struct elf_nds32_link_hash_table *table; -- FILE *ex9_export_file; -- static bfd_boolean done = FALSE; -- -- if (done) -- return; -- -- done = TRUE; -- -- table = nds32_elf_hash_table (link_info); -- if (table) -- table->relax_status |= NDS32_RELAX_EX9_DONE; -- -- -- update_ex9_table = table->update_ex9_table; -- /* Generated ex9.itable exactly. */ -- if (update_ex9_table == 0) -- { -- for (it_abfd = link_info->input_bfds; it_abfd != NULL; -- it_abfd = it_abfd->link.next) -- { -- table_sec = bfd_get_section_by_name (it_abfd, ".ex9.itable"); -- if (table_sec != NULL) -- break; -- } -- -- if (table_sec != NULL) -- { -- bfd *output_bfd; -- -- output_bfd = table_sec->output_section->owner; -- nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE); -- if (table_sec->size == 0) -- return; -- -- if (!nds32_get_section_contents (it_abfd, table_sec, &contents, TRUE)) -- return; -- } -- } -- else -- { -- /* Set gp. */ -- bfd *output_bfd; -- -- output_bfd = link_info->input_bfds->sections->output_section->owner; -- nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE); -- contents = bfd_malloc (sizeof (bfd_byte) * 2048); -- } -- -- /* Relocate instruction. */ -- while (ex9_insn) -- { -- bfd_vma relocation, min_relocation = 0xffffffff; -- -- insn = strtol (ex9_insn->string, NULL, 16); -- insn_with_reg = 0; -- if (ex9_insn->m_list != NULL || ex9_insn->sec != NULL) -- { -- if (ex9_insn->m_list) -- rel_backup = ex9_insn->m_list->rel_backup; -- else -- rel_backup = ex9_insn->rel_backup; -- -- nds32_elf_get_insn_with_reg (&rel_backup, insn, &insn_with_reg); -- howto = -- bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE -- (rel_backup.r_info)); -- shift = howto->rightshift; -- if (ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_25_PCREL_RELA -- || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S0_ORI_RELA -- || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S0_RELA -- || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S1_RELA -- || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S2_RELA) -- { -- relocation = nds32_elf_ex9_reloc_insn (ex9_insn, link_info); -- insn = -- insn_with_reg | ((relocation >> shift) & -- nds32_elf_irel_mask (&rel_backup)); -- bfd_putb32 (insn, contents + (ex9_insn->order) * 4); -- } -- else if ((ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA15S3 -- && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA15S0) -- || (ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA15S3_RELA -- && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA15S0_RELA) -- || (ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA12S2_DP_RELA -- && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA12S2_SP_RELA) -- || (ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA16S3_RELA -- && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA19S0_RELA)) -- { -- relocation = nds32_elf_ex9_reloc_insn (ex9_insn, link_info); -- insn = -- insn_with_reg | (((relocation - gp) >> shift) & -- nds32_elf_irel_mask (&rel_backup)); -- bfd_putb32 (insn, contents + (ex9_insn->order) * 4); -- } -- else if (ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_HI20_RELA) -- { -- /* Sethi may be multiple entry for one insn. */ -- if (ex9_insn->next && ex9_insn->m_list -- && ex9_insn->m_list == ex9_insn->next->m_list) -- { -- struct elf_link_hash_entry_mul_list *m_list; -- struct elf_nds32_ex9_refix *fix_ptr; -- struct elf_link_hash_entry *h; -- -- temp_ptr = ex9_insn; -- temp_ptr2 = ex9_insn; -- m_list = ex9_insn->m_list; -- while (m_list) -- { -- h = m_list->h_list->h; -- relocation = h->root.u.def.value + -- h->root.u.def.section->output_section->vma + -- h->root.u.def.section->output_offset; -- relocation += m_list->irel->r_addend; -- -- if (relocation < min_relocation) -- min_relocation = relocation; -- m_list = m_list->next; -- } -- relocation = min_relocation; -- -- /* Put insntruction into ex9 table. */ -- insn = insn_with_reg -- | ((relocation >> shift) & nds32_elf_irel_mask (&rel_backup)); -- bfd_putb32 (insn, contents + (ex9_insn->order) * 4); -- relocation = relocation + 0x1000; /* hi20 */ -- -- while (ex9_insn->next && ex9_insn->m_list -- && ex9_insn->m_list == ex9_insn->next->m_list) -- { -- /* Multiple sethi. */ -- ex9_insn = ex9_insn->next; -- size += 4; -- insn = -- insn_with_reg | ((relocation >> shift) & -- nds32_elf_irel_mask (&rel_backup)); -- bfd_putb32 (insn, contents + (ex9_insn->order) * 4); -- relocation = relocation + 0x1000; /* hi20 */ -- } -- -- fix_ptr = ex9_refix_head; -- while (fix_ptr) -- { -- /* Fix ex9 insn. */ -- /* temp_ptr2 points to the head of multiple sethi. */ -- temp_ptr = temp_ptr2; -- while (fix_ptr->order != temp_ptr->order && fix_ptr->next) -- { -- fix_ptr = fix_ptr->next; -- } -- if (fix_ptr->order != temp_ptr->order) -- break; -- -- /* Set source insn. */ -- relocation = -- fix_ptr->h->root.u.def.value + -- fix_ptr->h->root.u.def.section->output_section->vma + -- fix_ptr->h->root.u.def.section->output_offset; -- relocation += fix_ptr->irel->r_addend; -- /* sethi imm is imm20s. */ -- source_insn = insn_with_reg | ((relocation >> shift) & 0xfffff); -- -- while (temp_ptr) -- { -- /* Match entry and source code. */ -- insn = bfd_getb32 (contents + (temp_ptr->order) * 4 + offset); -- if (insn == source_insn) -- { -- /* Fix the ex9 insn. */ -- if (temp_ptr->order != fix_ptr->order) -- { -- if (!nds32_get_section_contents -- (fix_ptr->sec->owner, fix_ptr->sec, -- &source_contents, TRUE)) -- _bfd_error_handler -- (_("Linker: error cannot fixed ex9 relocation \n")); -- if (temp_ptr->order < 32) -- insn_ex9 = INSN_EX9_IT_2; -- else -- insn_ex9 = INSN_EX9_IT_1; -- insn_ex9 = insn_ex9 | temp_ptr->order; -- bfd_putb16 (insn_ex9, source_contents + fix_ptr->irel->r_offset); -- } -- break; -- } -- else -- { -- if (!temp_ptr->next || temp_ptr->m_list != temp_ptr->next->m_list) -- _bfd_error_handler -- (_("Linker: error cannot fixed ex9 relocation \n")); -- else -- temp_ptr = temp_ptr->next; -- } -- } -- fix_ptr = fix_ptr->next; -- } -- } -- else -- { -- relocation = nds32_elf_ex9_reloc_insn (ex9_insn, link_info); -- insn = insn_with_reg -- | ((relocation >> shift) & nds32_elf_irel_mask (&rel_backup)); -- bfd_putb32 (insn, contents + (ex9_insn->order) * 4); -- } -- } -- } -- else -- { -- /* Insn without relocation does not have to be fixed -- if need to update export table. */ -- if (update_ex9_table == 1) -- bfd_putb32 (insn, contents + (ex9_insn->order) * 4); -- } -- ex9_insn = ex9_insn->next; -- size += 4; -- } -- -- ex9_export_file = table->ex9_export_file; -- if (ex9_export_file != NULL) -- nds32_elf_ex9_export (link_info, contents, table_sec->size); -- else if (update_ex9_table == 1) -- { -- table->ex9_export_file = table->ex9_import_file; -- rewind (table->ex9_export_file); -- nds32_elf_ex9_export (link_info, contents, size); -- } --} -- --/* Generate ex9 hash table. */ -- --static bfd_boolean --nds32_elf_ex9_build_hash_table (bfd *abfd, asection *sec, -- struct bfd_link_info *link_info) --{ -- Elf_Internal_Rela *internal_relocs; -- Elf_Internal_Rela *irelend; -- Elf_Internal_Rela *irel; -- Elf_Internal_Rela *jrel; -- Elf_Internal_Rela rel_backup; -- Elf_Internal_Shdr *symtab_hdr; -- Elf_Internal_Sym *isym = NULL; -- asection *isec; -- struct elf_link_hash_entry **sym_hashes; -- bfd_byte *contents = NULL; -- bfd_vma off = 0; -- unsigned long r_symndx; -- uint32_t insn, insn_with_reg; -- struct elf_link_hash_entry *h; -- int data_flag, shift, align; -- bfd_vma relocation; -- /* Suppress ex9 if `.no_relax ex9' or inner loop. */ -- reloc_howto_type *howto = NULL; -- -- sym_hashes = elf_sym_hashes (abfd); -- /* Load section instructions, relocations, and symbol table. */ -- if (!nds32_get_section_contents (abfd, sec, &contents, TRUE)) -- return FALSE; -- -- internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, -- TRUE /* keep_memory */); -- irelend = internal_relocs + sec->reloc_count; -- symtab_hdr = &elf_tdata (abfd)->symtab_hdr; -- if (!nds32_get_local_syms (abfd, sec, &isym)) -- return FALSE; -- -- /* Check the object if enable ex9. */ -- irel = find_relocs_at_address (internal_relocs, internal_relocs, irelend, -- R_NDS32_RELAX_ENTRY); -- -- /* Check this section trigger ex9 relaxation. */ -- if (irel == NULL -- || irel >= irelend -- || ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_ENTRY -- || (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY -- && !(irel->r_addend & R_NDS32_RELAX_ENTRY_EX9_FLAG))) -- return TRUE; -- -- irel = internal_relocs; -- -- /* Push each insn into hash table. */ -- while (off < sec->size) -- { -- char code[10]; -- struct elf_nds32_code_hash_entry *entry; -- -- while (irel != NULL && irel < irelend && irel->r_offset < off) -- irel++; -- -- data_flag = nds32_elf_ex9_relocation_check (link_info, &irel, irelend, -- NULL, sec, &off, contents); -- if (data_flag & DATA_EXIST) -- { -- /* We save the move offset in the highest byte. */ -- off += (data_flag >> 24); -- continue; -- } -- -- if (*(contents + off) & 0x80) -- { -- off += 2; -- } -- else -- { -- h = NULL; -- isec = NULL; -- jrel = NULL; -- rel_backup.r_info = 0; -- rel_backup.r_offset = 0; -- rel_backup.r_addend = 0; -- /* Load the instruction and its opcode with register for comparing. */ -- insn = bfd_getb32 (contents + off); -- insn_with_reg = 0; -- if (irel != NULL && irel < irelend && irel->r_offset == off) -- { -- nds32_elf_get_insn_with_reg (irel, insn, &insn_with_reg); -- howto = bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE (irel->r_info)); -- shift = howto->rightshift; -- align = (1 << shift) - 1; -- if (ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_HI20_RELA -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_ORI_RELA -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_RELA -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S1_RELA -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S2_RELA -- ||(ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3 -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0) -- || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3_RELA -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0_RELA) -- || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA12S2_DP_RELA -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA12S2_SP_RELA) -- || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA16S3_RELA -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA19S0_RELA)) -- { -- r_symndx = ELF32_R_SYM (irel->r_info); -- jrel = irel; -- rel_backup = *irel; -- if (r_symndx < symtab_hdr->sh_info) -- { -- /* Local symbol. */ -- int shndx = isym[r_symndx].st_shndx; -- -- bfd_vma st_value = (isym + r_symndx)->st_value; -- isec = elf_elfsections (abfd)[shndx]->bfd_section; -- relocation = (isec->output_section->vma + isec->output_offset -- + st_value + irel->r_addend); -- } -- else -- { -- /* External symbol. */ -- bfd_boolean warned ATTRIBUTE_UNUSED; -- bfd_boolean ignored ATTRIBUTE_UNUSED; -- bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED; -- asection *sym_sec; -- -- /* Maybe there is a better way to get h and relocation */ -- RELOC_FOR_GLOBAL_SYMBOL (link_info, abfd, sec, irel, -- r_symndx, symtab_hdr, sym_hashes, -- h, sym_sec, relocation, -- unresolved_reloc, warned, ignored); -- relocation += irel->r_addend; -- if ((h->root.type != bfd_link_hash_defined -- && h->root.type != bfd_link_hash_defweak) -- || strcmp (h->root.root.string, "_FP_BASE_") == 0) -- { -- off += 4; -- continue; -- } -- } -- -- /* Check for gp relative instruction alignment. */ -- if ((ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3 -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0) -- || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3_RELA -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0_RELA) -- || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA12S2_DP_RELA -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA12S2_SP_RELA) -- || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA16S3_RELA -- && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA19S0_RELA)) -- { -- bfd_vma gp; -- bfd *output_bfd = sec->output_section->owner; -- bfd_reloc_status_type r; -- -- /* If the symbol is in the abs section, the out_bfd will be null. -- This happens when the relocation has a symbol@GOTOFF. */ -- r = nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE); -- if (r != bfd_reloc_ok) -- { -- off += 4; -- continue; -- } -- -- relocation -= gp; -- -- /* Make sure alignment is correct. */ -- if (relocation & align) -- { -- /* Incorrect alignment. */ -- _bfd_error_handler -- /* xgettext:c-format */ -- (_("%B: warning: unaligned small data access " -- "for entry: {%Ld, %Ld, %Ld}, addr = %#Lx, align = %#x"), -- abfd, irel->r_offset, -- irel->r_info, irel->r_addend, relocation, align); -- off += 4; -- continue; -- } -- } -- -- insn = insn_with_reg -- | ((relocation >> shift) & nds32_elf_irel_mask (irel)); -- } -- else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_BEGIN -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_END -- || ELF32_R_TYPE (irel->r_info) == R_NDS32_NONE) -- { -- /* These relocations do not have to relocate contens, so it can -- be regard as instruction without relocation. */ -- } -- else -- { -- off += 4; -- continue; -- } -- } -- -- snprintf (code, sizeof (code), "%08x", insn); -- /* Copy "code". */ -- entry = (struct elf_nds32_code_hash_entry*) -- bfd_hash_lookup (&ex9_code_table, code, TRUE, TRUE); -- if (entry == NULL) -- { -- _bfd_error_handler -- (_("failed creating ex9.it %s hash table entry"), code); -- return FALSE; -- } -- if (h) -- { -- if (h->root.type == bfd_link_hash_undefined) -- return TRUE; -- /* Global symbol. */ -- /* In order to do sethi with different symbol but same value. */ -- if (entry->m_list == NULL) -- { -- struct elf_link_hash_entry_mul_list *m_list_new; -- struct elf_link_hash_entry_list *h_list_new; -- -- m_list_new = (struct elf_link_hash_entry_mul_list *) -- bfd_malloc (sizeof (struct elf_link_hash_entry_mul_list)); -- h_list_new = (struct elf_link_hash_entry_list *) -- bfd_malloc (sizeof (struct elf_link_hash_entry_list)); -- entry->m_list = m_list_new; -- m_list_new->h_list = h_list_new; -- m_list_new->rel_backup = rel_backup; -- m_list_new->times = 1; -- m_list_new->irel = jrel; -- m_list_new->next = NULL; -- h_list_new->h = h; -- h_list_new->next = NULL; -- } -- else -- { -- struct elf_link_hash_entry_mul_list *m_list = entry->m_list; -- struct elf_link_hash_entry_list *h_list; -- -- while (m_list) -- { -- /* Build the different symbols that point to the same address. */ -- h_list = m_list->h_list; -- if (h_list->h->root.u.def.value == h->root.u.def.value -- && h_list->h->root.u.def.section->output_section->vma -- == h->root.u.def.section->output_section->vma -- && h_list->h->root.u.def.section->output_offset -- == h->root.u.def.section->output_offset -- && m_list->rel_backup.r_addend == rel_backup.r_addend) -- { -- m_list->times++; -- m_list->irel = jrel; -- while (h_list->h != h && h_list->next) -- h_list = h_list->next; -- if (h_list->h != h) -- { -- struct elf_link_hash_entry_list *h_list_new; -- -- h_list_new = (struct elf_link_hash_entry_list *) -- bfd_malloc (sizeof (struct elf_link_hash_entry_list)); -- h_list->next = h_list_new; -- h_list_new->h = h; -- h_list_new->next = NULL; -- } -- break; -- } -- /* The sethi case may have different address but the -- hi20 is the same. */ -- else if (ELF32_R_TYPE (jrel->r_info) == R_NDS32_HI20_RELA -- && m_list->next == NULL) -- { -- struct elf_link_hash_entry_mul_list *m_list_new; -- struct elf_link_hash_entry_list *h_list_new; -- -- m_list_new = (struct elf_link_hash_entry_mul_list *) -- bfd_malloc (sizeof (struct elf_link_hash_entry_mul_list)); -- h_list_new = (struct elf_link_hash_entry_list *) -- bfd_malloc (sizeof (struct elf_link_hash_entry_list)); -- m_list->next = m_list_new; -- m_list_new->h_list = h_list_new; -- m_list_new->rel_backup = rel_backup; -- m_list_new->times = 1; -- m_list_new->irel = jrel; -- m_list_new->next = NULL; -- h_list_new->h = h; -- h_list_new->next = NULL; -- break; -- } -- m_list = m_list->next; -- } -- if (!m_list) -- { -- off += 4; -- continue; -- } -- } -- } -- else -- { -- /* Local symbol and insn without relocation*/ -- entry->times++; -- entry->rel_backup = rel_backup; -- } -- -- /* Use in sethi insn with constant and global symbol in same format. */ -- if (!jrel) -- entry->const_insn = 1; -- else -- entry->irel = jrel; -- entry->sec = isec; -- off += 4; -- } -- } -- return TRUE; -+ return sec; - } -- --/* Set the _ITB_BASE, and point it to ex9 table. */ -- --bfd_boolean --nds32_elf_ex9_itb_base (struct bfd_link_info *link_info) --{ -- bfd *abfd; -- asection *sec; -- bfd *output_bfd = NULL; -- struct bfd_link_hash_entry *bh = NULL; -- -- if (is_ITB_BASE_set == 1) -- return TRUE; -- -- is_ITB_BASE_set = 1; -- -- bh = bfd_link_hash_lookup (link_info->hash, "_ITB_BASE_", FALSE, FALSE, TRUE); -- -- if (bh && (bh->type == bfd_link_hash_defined -- || bh->type == bfd_link_hash_defweak)) -- return TRUE; -- -- for (abfd = link_info->input_bfds; abfd != NULL; -- abfd = abfd->link.next) -- { -- sec = bfd_get_section_by_name (abfd, ".ex9.itable"); -- if (sec != NULL) -- { -- output_bfd = sec->output_section->owner; -- break; -- } -- } -- if (output_bfd == NULL) -- { -- output_bfd = link_info->output_bfd; -- if (output_bfd->sections == NULL) -- return TRUE; -- else -- sec = bfd_abs_section_ptr; -- } -- bh = bfd_link_hash_lookup (link_info->hash, "_ITB_BASE_", -- FALSE, FALSE, TRUE); -- return (_bfd_generic_link_add_one_symbol -- (link_info, output_bfd, "_ITB_BASE_", -- BSF_GLOBAL | BSF_WEAK, sec, 0, -- (const char *) NULL, FALSE, get_elf_backend_data -- (output_bfd)->collect, &bh)); --} /* End EX9.IT */ - - - #define ELF_ARCH bfd_arch_nds32 - #define ELF_MACHINE_CODE EM_NDS32 - #define ELF_MAXPAGESIZE 0x1000 --#define ELF_TARGET_ID NDS32_ELF_DATA -+#define ELF_TARGET_ID NDS32_ELF_DATA - - #define TARGET_BIG_SYM nds32_elf32_be_vec - #define TARGET_BIG_NAME "elf32-nds32be" -@@ -15448,7 +15265,7 @@ nds32_elf_ex9_itb_base (struct bfd_link_info *link_info) - #define bfd_elf32_bfd_relax_section nds32_elf_relax_section - #define bfd_elf32_bfd_set_private_flags nds32_elf_set_private_flags - --#define bfd_elf32_mkobject nds32_elf_mkobject -+#define bfd_elf32_mkobject nds32_elf_mkobject - #define elf_backend_action_discarded nds32_elf_action_discarded - #define elf_backend_add_symbol_hook nds32_elf_add_symbol_hook - #define elf_backend_check_relocs nds32_elf_check_relocs -@@ -15469,7 +15286,9 @@ nds32_elf_ex9_itb_base (struct bfd_link_info *link_info) - #define elf_backend_final_write_processing nds32_elf_final_write_processing - #define elf_backend_special_sections nds32_elf_special_sections - #define bfd_elf32_bfd_get_relocated_section_contents \ -- nds32_elf_get_relocated_section_contents -+ nds32_elf_get_relocated_section_contents -+#define bfd_elf32_bfd_is_target_special_symbol nds32_elf_is_target_special_symbol -+#define elf_backend_maybe_function_sym nds32_elf_maybe_function_sym - - #define elf_backend_can_gc_sections 1 - #define elf_backend_can_refcount 1 -@@ -15480,7 +15299,6 @@ nds32_elf_ex9_itb_base (struct bfd_link_info *link_info) - #define elf_backend_may_use_rel_p 1 - #define elf_backend_default_use_rela_p 1 - #define elf_backend_may_use_rela_p 1 --#define elf_backend_dtrel_excludes_plt 1 - - #include "elf32-target.h" - -diff --git binutils-2.30/bfd/elf32-nds32.h binutils-2.30-nds32/bfd/elf32-nds32.h -index 7e09e01a3f..fda4155ab3 100644 ---- binutils-2.30/bfd/elf32-nds32.h -+++ binutils-2.30-nds32/bfd/elf32-nds32.h -@@ -22,6 +22,8 @@ - #ifndef ELF32_NDS32_H - #define ELF32_NDS32_H - -+#include "bfd_stdint.h" -+ - #ifdef __cplusplus - extern "C" { - #endif -@@ -46,6 +48,13 @@ extern "C" { - #define R_NDS32_RELAX_ENTRY_EX9_FLAG (1 << 2) - /* Enable IFC optimization for this section. */ - #define R_NDS32_RELAX_ENTRY_IFC_FLAG (1 << 3) -+/* Two bits for ICT to comply with files without directive. */ -+/* ICT small model. */ -+#define R_NDS32_RELAX_ENTRY_ICT_SMALL (0x2 << 4) -+/* ICT large model. */ -+#define R_NDS32_RELAX_ENTRY_ICT_LARGE (0x3 << 4) -+/* Mask for get ict bits. */ -+#define R_NDS32_RELAX_ENTRY_ICT_MASK (0x3 << 4) - - - /* Relocation flags for R_NDS32_INSN16. */ -@@ -66,8 +75,6 @@ extern "C" { - /* NOT_OMIT_FP_FLAG is set if this region is not worth - for fp-as-gp. */ - #define R_NDS32_RELAX_REGION_NOT_OMIT_FP_FLAG (1 << 1) --/* Suppress EX9 optimization in the region. */ --#define R_NDS32_RELAX_REGION_NO_EX9_FLAG (1 << 2) - /* A Innermost loop region. Some optimizations is suppressed - in this region due to performance drop. */ - #define R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG (1 << 4) -@@ -91,35 +98,57 @@ enum - NDS32_RELAX_NONE_ROUND = 0, - NDS32_RELAX_NORMAL_ROUND, - NDS32_RELAX_JUMP_IFC_ROUND, -+ NDS32_RELAX_IFC_ROUND, - NDS32_RELAX_EX9_BUILD_ROUND, - NDS32_RELAX_EX9_REPLACE_ROUND, - NDS32_RELAX_EMPTY_ROUND - }; - --/* Optimization status mask. */ --#define NDS32_RELAX_JUMP_IFC_DONE (1 << 0) --#define NDS32_RELAX_EX9_DONE (1 << 1) -+/* Security tag. */ -+enum -+{ -+ NDS32_SECURITY_NONE = 0, -+ NDS32_SECURITY_START, -+ NDS32_SECURITY_RESTART, -+ NDS32_SECURITY_END -+}; - - /* Optimization turn on mask. */ --#define NDS32_RELAX_JUMP_IFC_ON (1 << 0) -+#define NDS32_RELAX_IFC_ON (1 << 0) - #define NDS32_RELAX_EX9_ON (1 << 1) - - extern void nds32_insertion_sort - (void *, size_t, size_t, int (*) (const void *, const void *)); - --extern int nds32_elf_ex9_init (void); --extern int nds32_convert_32_to_16 (bfd *, uint32_t, uint16_t *, int *); --extern int nds32_convert_16_to_32 (bfd *, uint16_t, uint32_t *); --extern void bfd_elf32_nds32_set_target_option (struct bfd_link_info *, -- int, int, FILE *, int, -- int, int, int, FILE *, -- FILE *, int, int, -- bfd_boolean, bfd_boolean); -+struct section_id_list_t -+{ -+ int id; -+ struct section_id_list_t *next; -+}; -+ -+extern struct section_id_list_t * -+elf32_nds32_lookup_section_id (int, struct section_id_list_t **); -+extern int elf32_nds32_check_relax_group (bfd *, asection *); -+extern int elf32_nds32_unify_relax_group (bfd *, asection *); -+extern int nds32_elf_unify_tls_model (bfd *, asection *, bfd_byte *, -+ struct bfd_link_info *); -+ -+extern void bfd_elf32_nds32_set_target_option (struct bfd_link_info *, int, int, -+ FILE *, int, int, int, int, int, -+ int, char *); -+extern void bfd_elf32_nds32_append_section (struct bfd_link_info*, bfd *); -+extern int nds32_convert_32_to_16 (bfd *, uint32_t, uint16_t *, int *); -+extern int nds32_convert_16_to_32 (bfd *, uint16_t, uint32_t *); - - #define nds32_elf_hash_table(info) \ - (elf_hash_table_id ((struct elf_link_hash_table *) ((info)->hash)) \ -- == NDS32_ELF_DATA ? \ -- ((struct elf_nds32_link_hash_table *) ((info)->hash)) : NULL) -+ == NDS32_ELF_DATA ? ((struct elf_nds32_link_hash_table *) ((info)->hash)) : NULL) -+ -+#define elf32_nds32_compute_jump_table_size(htab) \ -+ ((htab)->next_tls_desc_index * 4) -+ -+#define elf32_nds32_local_tlsdesc_gotent(bfd) \ -+ (elf_nds32_tdata (bfd)->local_tlsdesc_gotent) - - /* Hash table structure for target nds32. There are some members to - save target options passed from nds32elf.em to bfd. */ -@@ -144,12 +173,34 @@ struct elf_nds32_link_hash_table - int target_optimize; /* Switch optimization. */ - int relax_status; /* Finished optimization. */ - int relax_round; /* Going optimization. */ -- FILE *ex9_export_file; /* --mexport-ex9= */ -- FILE *ex9_import_file; /* --mimport-ex9= */ -- int update_ex9_table; /* --mupdate-ex9. */ -- int ex9_limit; -- bfd_boolean ex9_loop_aware; /* Ignore ex9 if inside a loop. */ -- bfd_boolean ifc_loop_aware; /* Ignore ifc if inside a loop. */ -+ bfd_boolean hyper_relax; /* Relax for symbol not in RW sections. */ -+ int tls_desc_trampoline; /* --m[no-]tlsdesc-trampoline. */ -+ -+ /* The offset into splt of the PLT entry for the TLS descriptor -+ resolver. Special values are 0, if not necessary (or not found -+ to be necessary yet), and -1 if needed but not determined -+ yet. */ -+ bfd_vma dt_tlsdesc_plt; -+ -+ /* The offset into sgot of the GOT entry used by the PLT entry -+ above. */ -+ bfd_vma dt_tlsdesc_got; -+ -+ /* Offset in .plt section of tls_nds32_trampoline. */ -+ bfd_vma tls_trampoline; -+ -+ /* The index of the next unused R_NDS32_TLS_DESC slot in .rel.plt. */ -+ bfd_vma next_tls_desc_index; -+ -+ /* How many R_NDS32_TLS_DESC relocations were generated so far. */ -+ bfd_vma num_tls_desc; -+ -+ /* The amount of space used by the reserved portion of the sgotplt -+ section, plus whatever space is used by the jump slots. */ -+ bfd_vma sgotplt_jump_table_size; -+ -+ /* True if the target uses REL relocations. */ -+ int use_rel; - }; - - #ifdef __cplusplus -diff --git binutils-2.30/bfd/libbfd.h binutils-2.30-nds32/bfd/libbfd.h -index 2f5f16e776..ff89105086 100644 ---- binutils-2.30/bfd/libbfd.h -+++ binutils-2.30-nds32/bfd/libbfd.h -@@ -1872,6 +1872,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", - "BFD_RELOC_NDS32_SDA17S2", - "BFD_RELOC_NDS32_SDA18S1", - "BFD_RELOC_NDS32_SDA19S0", -+ "BFD_RELOC_NDS32_SECURITY_16", - "BFD_RELOC_NDS32_GOT20", - "BFD_RELOC_NDS32_9_PLTREL", - "BFD_RELOC_NDS32_25_PLTREL", -@@ -1955,18 +1956,39 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", - "BFD_RELOC_NDS32_17IFC_PCREL", - "BFD_RELOC_NDS32_10IFCU_PCREL", - "BFD_RELOC_NDS32_TPOFF", -+ "BFD_RELOC_NDS32_GOTTPOFF", - "BFD_RELOC_NDS32_TLS_LE_HI20", - "BFD_RELOC_NDS32_TLS_LE_LO12", -- "BFD_RELOC_NDS32_TLS_LE_ADD", -- "BFD_RELOC_NDS32_TLS_LE_LS", -- "BFD_RELOC_NDS32_GOTTPOFF", -- "BFD_RELOC_NDS32_TLS_IE_HI20", -- "BFD_RELOC_NDS32_TLS_IE_LO12S2", -- "BFD_RELOC_NDS32_TLS_TPOFF", - "BFD_RELOC_NDS32_TLS_LE_20", - "BFD_RELOC_NDS32_TLS_LE_15S0", - "BFD_RELOC_NDS32_TLS_LE_15S1", - "BFD_RELOC_NDS32_TLS_LE_15S2", -+ "BFD_RELOC_NDS32_TLS_LE_ADD", -+ "BFD_RELOC_NDS32_TLS_LE_LS", -+ "BFD_RELOC_NDS32_TLS_IE_HI20", -+ "BFD_RELOC_NDS32_TLS_IE_LO12", -+ "BFD_RELOC_NDS32_TLS_IE_LO12S2", -+ "BFD_RELOC_NDS32_TLS_IEGP_HI20", -+ "BFD_RELOC_NDS32_TLS_IEGP_LO12", -+ "BFD_RELOC_NDS32_TLS_IEGP_LO12S2", -+ "BFD_RELOC_NDS32_TLS_IEGP_LW", -+ "BFD_RELOC_NDS32_TLS_DESC", -+ "BFD_RELOC_NDS32_TLS_DESC_HI20", -+ "BFD_RELOC_NDS32_TLS_DESC_LO12", -+ "BFD_RELOC_NDS32_TLS_DESC_20", -+ "BFD_RELOC_NDS32_TLS_DESC_SDA17S2", -+ "BFD_RELOC_NDS32_TLS_DESC_ADD", -+ "BFD_RELOC_NDS32_TLS_DESC_FUNC", -+ "BFD_RELOC_NDS32_TLS_DESC_CALL", -+ "BFD_RELOC_NDS32_TLS_DESC_MEM", -+ "BFD_RELOC_NDS32_REMOVE", -+ "BFD_RELOC_NDS32_GROUP", -+ "BFD_RELOC_NDS32_ICT", -+ "BFD_RELOC_NDS32_ICT_HI20", -+ "BFD_RELOC_NDS32_ICT_LO12", -+ "BFD_RELOC_NDS32_ICT_25PC", -+ "BFD_RELOC_NDS32_ICT_LO12S2", -+ "BFD_RELOC_NDS32_LSI", - "BFD_RELOC_V850_9_PCREL", - "BFD_RELOC_V850_22_PCREL", - "BFD_RELOC_V850_SDA_16_16_OFFSET", -diff --git binutils-2.30/bfd/reloc.c binutils-2.30-nds32/bfd/reloc.c -index a1353a281b..0d96e13027 100644 ---- binutils-2.30/bfd/reloc.c -+++ binutils-2.30-nds32/bfd/reloc.c -@@ -4182,6 +4182,10 @@ ENUMDOC - This is a 19-bit reloc containing the small data area 19-bit signed offset - and shift left by 0 for use in lbi.gp, sbi.gp... - ENUM -+ BFD_RELOC_NDS32_SECURITY_16 -+ENUMDOC -+ This is a 24-bit reloc for security check sum. -+ENUM - BFD_RELOC_NDS32_GOT20 - ENUMX - BFD_RELOC_NDS32_9_PLTREL -@@ -4375,33 +4379,62 @@ ENUMDOC - ENUM - BFD_RELOC_NDS32_TPOFF - ENUMX -+ BFD_RELOC_NDS32_GOTTPOFF -+ENUMX - BFD_RELOC_NDS32_TLS_LE_HI20 - ENUMX - BFD_RELOC_NDS32_TLS_LE_LO12 - ENUMX -+ BFD_RELOC_NDS32_TLS_LE_20 -+ENUMX -+ BFD_RELOC_NDS32_TLS_LE_15S0 -+ENUMX -+ BFD_RELOC_NDS32_TLS_LE_15S1 -+ENUMX -+ BFD_RELOC_NDS32_TLS_LE_15S2 -+ENUMX - BFD_RELOC_NDS32_TLS_LE_ADD - ENUMX - BFD_RELOC_NDS32_TLS_LE_LS - ENUMX -- BFD_RELOC_NDS32_GOTTPOFF --ENUMX - BFD_RELOC_NDS32_TLS_IE_HI20 - ENUMX -+ BFD_RELOC_NDS32_TLS_IE_LO12 -+ENUMX - BFD_RELOC_NDS32_TLS_IE_LO12S2 - ENUMX -- BFD_RELOC_NDS32_TLS_TPOFF -+ BFD_RELOC_NDS32_TLS_IEGP_HI20 - ENUMX -- BFD_RELOC_NDS32_TLS_LE_20 -+ BFD_RELOC_NDS32_TLS_IEGP_LO12 - ENUMX -- BFD_RELOC_NDS32_TLS_LE_15S0 -+ BFD_RELOC_NDS32_TLS_IEGP_LO12S2 - ENUMX -- BFD_RELOC_NDS32_TLS_LE_15S1 -+ BFD_RELOC_NDS32_TLS_IEGP_LW - ENUMX -- BFD_RELOC_NDS32_TLS_LE_15S2 -+ BFD_RELOC_NDS32_TLS_DESC -+ENUMX -+ BFD_RELOC_NDS32_TLS_DESC_HI20 -+ENUMX -+ BFD_RELOC_NDS32_TLS_DESC_LO12 -+ENUMX -+ BFD_RELOC_NDS32_TLS_DESC_20 -+ENUMX -+ BFD_RELOC_NDS32_TLS_DESC_SDA17S2 -+ENUMX -+ BFD_RELOC_NDS32_TLS_DESC_ADD -+ENUMX -+ BFD_RELOC_NDS32_TLS_DESC_FUNC -+ENUMX -+ BFD_RELOC_NDS32_TLS_DESC_CALL -+ENUMX -+ BFD_RELOC_NDS32_TLS_DESC_MEM -+ENUMX -+ BFD_RELOC_NDS32_REMOVE -+ENUMX -+ BFD_RELOC_NDS32_GROUP - ENUMDOC - For TLS. - -- - ENUM - BFD_RELOC_V850_9_PCREL - ENUMDOC -diff --git binutils-2.30/gas/config.in binutils-2.30-nds32/gas/config.in -index 0855179696..551434a45b 100644 ---- binutils-2.30/gas/config.in -+++ binutils-2.30-nds32/gas/config.in -@@ -202,6 +202,9 @@ - /* Define default value for nds32_audio_ext */ - #undef NDS32_DEFAULT_AUDIO_EXT - -+/* Define default value for nds32_dsp_ext */ -+#undef NDS32_DEFAULT_DSP_EXT -+ - /* Define default value for nds32_dx_regs */ - #undef NDS32_DEFAULT_DX_REGS - -@@ -214,6 +217,12 @@ - /* Define default value for nds32_string_ext */ - #undef NDS32_DEFAULT_STRING_EXT - -+/* Define default value for nds32_zol_ext */ -+#undef NDS32_DEFAULT_ZOL_EXT -+ -+/* Defined for linux toolchain */ -+#undef NDS32_LINUX_TOOLCHAIN -+ - /* Define if environ is not declared in system header files. */ - #undef NEED_DECLARATION_ENVIRON - -diff --git binutils-2.30/gas/config/tc-nds32.c binutils-2.30-nds32/gas/config/tc-nds32.c -index b2741b8213..f8cbd80edc 100644 ---- binutils-2.30/gas/config/tc-nds32.c -+++ binutils-2.30-nds32/gas/config/tc-nds32.c -@@ -19,6 +19,8 @@ - Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA - 02110-1301, USA. */ - -+#pragma GCC diagnostic ignored "-Wstack-usage=" -+ - #include "as.h" - #include "safe-ctype.h" - #include "subsegs.h" -@@ -35,6 +37,8 @@ - #include "opcode/nds32.h" - - #include -+#include -+#include - - /* GAS definitions. */ - -@@ -66,6 +70,8 @@ struct nds32_relocs_pattern - struct nds32_opcode *opcode; - char *where; - struct nds32_relocs_pattern *next; -+ /* Assembled instruction bytes. */ -+ uint32_t insn; - }; - - /* Suffix name and relocation. */ -@@ -73,7 +79,6 @@ struct suffix_name - { - const char *suffix; - short unsigned int reloc; -- int pic; - }; - static int vec_size = 0; - /* If the assembly code is generated by compiler, it is supposed to have -@@ -87,11 +92,7 @@ static struct hash_control *nds32_hint_hash; - - /* Generate relocation for relax or not, and the default is true. */ - static int enable_relax_relocs = 1; --/* The value will be used in RELAX_ENTRY. */ --static int enable_relax_ex9 = 0; --/* The value will be used in RELAX_ENTRY. */ --static int enable_relax_ifc = 0; --/* Save option -O for performance. */ -+/* Save option -O for perfomance. */ - static int optimize = 0; - /* Save option -Os for code size. */ - static int optimize_for_space = 0; -@@ -99,1768 +100,1798 @@ static int optimize_for_space = 0; - static int label_exist = 0; - /* Flag to save state in omit_fp region. */ - static int in_omit_fp = 0; --extern struct nds32_keyword keyword_gpr[]; -+extern keyword_t keyword_gpr[]; - /* Tag there is relax relocation having to link. */ - static bfd_boolean relaxing = FALSE; -+/* Save security status. */ -+static bfd_boolean crcing = FALSE; -+/* Inline asm status. */ -+static bfd_boolean inline_asm = FALSE; -+/* v3 is compatiable with v3f/v3s. */ -+static bfd_boolean compatible_abi = FALSE; -+/* ICT model. */ -+enum ict_option { -+ ICT_NONE = 0, -+ ICT_SMALL, -+ ICT_LARGE -+}; -+static enum ict_option ict_flag = ICT_NONE; -+/* True if ICT existed. */ -+static bfd_boolean ict_exist = FALSE; - - static struct hash_control *nds32_relax_info_hash; -+/* Branch pattern. */ - static relax_info_t relax_table[] = - { -- { -- "jal", /* opcode */ -- BR_RANGE_S16M, /* br_range */ -- {{0, 0, 0, FALSE}}, /* cond_field */ -- { -- { -- INSN_JAL /* jal label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_JAL /* jal label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_JAL /* jal label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_JAL /* jal label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JRAL_TA -- }, /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ -- {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 4, 4, 12}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, 0, BFD_RELOC_NDS32_HI20}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4}, -- {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bltzal", /* opcode */ -- BR_RANGE_S64K, /* br_range */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BLTZAL /* bltzal $rt, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BLTZAL /* bltzal $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BLTZAL /* bltzal $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BGEZ, /* bgez $rt, $1 */ -- INSN_JAL /* jal label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BGEZ, /* bgez $rt, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JRAL_TA /* jral $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 4, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bgezal", /* opcode */ -- BR_RANGE_S64K, /* br_range */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BGEZAL /* bgezal $rt, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BGEZAL /* bgezal $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BGEZAL /* bgezal $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BLTZ, /* bltz $rt, $1 */ -- INSN_JAL /* jal label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BLTZ, /* bltz $rt, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JRAL_TA /* jral $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 4, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "j", /* opcode */ -- BR_RANGE_S16M, /* br_range */ -- {{0, 0, 0, FALSE}}, /* cond_field */ -- { -- { -- (INSN_J8 << 16) /* j8 label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_J /* j label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_J /* j label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- }, /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ -- {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {2, 4, 4, 4, 12}, /* relax_code_size */ -- {2, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, 0, BFD_RELOC_NDS32_HI20}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, -- {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "j8", /* opcode */ -- BR_RANGE_S256, /* br_range */ -- {{0, 0, 0, FALSE}}, /* cond_field */ -- { -- { -- (INSN_J8 << 16) /* j8 label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_J /* j label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_J /* j label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- }, /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ -- {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {2, 4, 4, 4, 12}, /* relax_code_size */ -- {2, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, 0, BFD_RELOC_NDS32_HI20}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, -- {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "beqz", /* opcode */ -- BR_RANGE_S64K, /* br_range */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BEQZ /* beqz $rt, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BEQZ /* beqz $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BEQZ /* beqz $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BNEZ, /* bnez $rt, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BNEZ, /* bnez $rt, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 4, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bgez", /* opcode */ -- BR_RANGE_S64K, /* br_range */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BGEZ /* bgez $rt, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BGEZ /* bgez $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BGEZ /* bgez $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BLTZ, /* bltz $rt, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BLTZ, /* bltz $rt, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 4, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bnez", /* opcode */ -- BR_RANGE_S64K, /* br_range */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BNEZ /* bnez $rt, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BNEZ /* bnez $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BNEZ /* bnez $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BEQZ, /* beqz $rt, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BEQZ, /* beqz $rt, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 4, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bgtz", /* opcode */ -- BR_RANGE_S64K, /* br_range */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BGTZ /* bgtz $rt, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BGTZ /* bgtz $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BGTZ /* bgtz $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BLEZ, /* blez $rt, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BLEZ, /* blez $rt, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 4, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "blez", /* opcode */ -- BR_RANGE_S64K, /* br_range */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BLEZ /* blez $rt, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BLEZ /* blez $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BLEZ /* blez $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BGTZ, /* bgtz $rt, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BGTZ, /* bgtz $rt, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 4, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bltz", /* opcode */ -- BR_RANGE_S64K, /* br_range */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BLTZ /* bltz $rt, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BLTZ /* bltz $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BLTZ /* bltz $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BGEZ, /* bgez $rt, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BGEZ, /* bgez $rt, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 4, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "beq", /* opcode */ -- BR_RANGE_S16K, /* br_range */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BEQ /* beq $rt, $ra, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BEQ /* beq $rt, $ra, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BNE, /* bne $rt, $ra, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BNE, /* bne $rt, $ra, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BNE, /* bne $rt, $ra, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 8, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_ABS, BFD_RELOC_NDS32_EMPTY}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bne", /* opcode */ -- BR_RANGE_S16K, /* br_range */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BNE /* bne $rt, $ra, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BNE /* bne $rt, $ra, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BEQ, /* beq $rt, $ra, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BEQ, /* beq $rt, $ra, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BEQ, /* beq $rt, $ra, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 15, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 4, 8, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "beqz38", /* opcode */ -- BR_RANGE_S256, /* br_range */ -- { -- {0, 8, 0x7, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BEQZ38 << 16 /* beqz $rt, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BEQZ /* beqz $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BEQZ /* beqz $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BNEZ, /* bnez $rt, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BNEZ, /* bnez $rt, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- { -- {0, 8, 0x7, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {2, 4, 4, 8, 16}, /* relax_code_size */ -- {2, 4, 4, 4, 4}, /* relax_branch_isize */ -- { -- { -- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bnez38", /* opcode */ -- BR_RANGE_S256, /* br_range */ -- { -- {0, 8, 0x7, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -- { -- { -- INSN_BNEZ38 << 16 /* bnez $rt, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BNEZ /* bnez $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BNEZ /* bnez $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BEQZ, /* beqz $rt, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BEQZ, /* beqz $rt, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ - { -- { -- {0, 8, 0x7, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {2, 4, 4, 8, 16}, /* relax_code_size */ -- {2, 4, 4, 4, 4}, /* relax_branch_isize */ -+ .opcode = "jal", -+ .br_range = BR_RANGE_S16M, -+ .cond_field = { -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_JAL}, /* jal label */ -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_JAL}, /* jal label */ -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_JAL}, /* jal label */ -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_JAL}, /* jal label */ -+ .relax_code_size[BR_RANGE_S16M] = 4, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JRAL_TA}, /* jral $ta */ -+ .relax_code_size[BR_RANGE_U4G] = 12, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4}, -+ {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "beqzs8", /* opcode */ -- BR_RANGE_S256, /* br_range */ -- {{0, 0, 0, FALSE}}, /* cond_field */ -+ .opcode = "bgezal", -+ .br_range = BR_RANGE_S64K, -+ .cond_field = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BGEZAL}, /* bgezal $rt, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BGEZAL}, /* bgezal $rt, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BGEZAL}, /* bgezal $rt, label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BLTZ, /* bltz $rt, $1 */ -+ INSN_JAL}, /* jal label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BLTZ, /* bltz $rt, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JRAL_TA}, /* jral $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- INSN_BEQZS8 << 16 /* beqz $r15, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BEQZ_TA /* bnez $rt, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BEQZ_TA /* bnez $rt, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BNEZ_TA, /* bnez $r15, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BNEZ_TA, /* bnez $r15, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ -- {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {2, 4, 4, 8, 16}, /* relax_code_size */ -- {2, 4, 4, 4, 4}, /* relax_branch_isize */ -+ .opcode = "bltzal", -+ .br_range = BR_RANGE_S64K, -+ .cond_field = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BLTZAL}, /* bltzal $rt, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BLTZAL}, /* bltzal $rt, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BLTZAL}, /* bltzal $rt, label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BGEZ, /* bgez $rt, $1 */ -+ INSN_JAL}, /* jal label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BGEZ, /* bgez $rt, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JRAL_TA}, /* jral $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bnezs8", /* opcode */ -- BR_RANGE_S256, /* br_range */ -- {{0, 0, 0, FALSE}}, /* cond_field */ -+ .opcode = "j", -+ .br_range = BR_RANGE_S16M, -+ .cond_field = { -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ (INSN_J8 << 16)}, /* j8 label */ -+ .relax_code_size[BR_RANGE_S256] = 2, -+ .relax_branch_isize[BR_RANGE_S256] = 2, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_J}, /* j label */ -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_J}, /* j label */ -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_J}, /* j label */ -+ .relax_code_size[BR_RANGE_S16M] = 4, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_size[BR_RANGE_U4G] = 12, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, -+ {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- INSN_BNEZS8 << 16 /* bnez $r15, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BNEZ_TA /* bnez $r15, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BNEZ_TA /* bnez $r15, label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BEQZ_TA, /* beqz $r15, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BEQZ_TA, /* beqz $r15, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -- { -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ -- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ -- {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {2, 4, 4, 8, 16}, /* relax_code_size */ -- {2, 4, 4, 4, 4}, /* relax_branch_isize */ -+ .opcode = "j8", -+ .br_range = BR_RANGE_S256, -+ .cond_field = { -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ (INSN_J8 << 16)}, /* j8 label */ -+ .relax_code_size[BR_RANGE_S256] = 2, -+ .relax_branch_isize[BR_RANGE_S256] = 2, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_J}, /* j label */ -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_J}, /* j label */ -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_J}, /* j label */ -+ .relax_code_size[BR_RANGE_S16M] = 4, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_size[BR_RANGE_U4G] = 12, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, -+ {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bnes38", /* opcode */ -- BR_RANGE_S256, /* br_range */ -+ .opcode = "beqz", -+ .br_range = BR_RANGE_S64K, -+ .cond_field = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ /* We do not use beqz38 and beqzs8 here directly because we -+ don't want to check register number for specail condition. */ -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BEQZ}, /* beqz $rt, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BEQZ}, /* beqz $rt, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BEQZ}, /* beqz $rt, label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BNEZ, /* bnez $rt, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ /* bnez range is 17 pcrel, but it use 15 pcrel here since link time -+ relaxtion. If 17 pcrel can reach, it do not have to -+ use S16M. Therefore, 15 pcrel is just for linker to -+ distinguish LONGJUMP5 and LONGJUMP6. */ -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BNEZ, /* bnez $rt, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- {0, 8, 0x7, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -+ .opcode = "bgez", -+ .br_range = BR_RANGE_S64K, -+ .cond_field = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BGEZ}, /* bgez $rt, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BGEZ}, /* bgez $rt, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BGEZ}, /* bgez $rt, label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BLTZ, /* bltz $rt, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BLTZ, /* bltz $rt, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- INSN_BNES38 << 16 /* bne $rt, $R5, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BNE_R5 /* bne $rt, $R5, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BEQ_R5, /* beq $rt, $R5, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BEQ_R5, /* beq $rt, $R5, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BEQ_R5, /* beq $rt, $R5, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -+ .opcode = "bnez", -+ .br_range = BR_RANGE_S64K, -+ .cond_field = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BNEZ}, /* bnez $rt, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BNEZ}, /* bnez $rt, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BNEZ}, /* bnez $rt, label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BEQZ, /* beqz $rt, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BEQZ, /* beqz $rt, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 8, 0x7, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {2, 4, 8, 8, 16}, /* relax_code_size */ -- {2, 4, 4, 4, 4}, /* relax_branch_isize */ -+ .opcode = "bgtz", -+ .br_range = BR_RANGE_S64K, -+ .cond_field = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BGTZ}, /* bgtz $rt, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BGTZ}, /* bgtz $rt, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BGTZ}, /* bgtz $rt, label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BLEZ, /* blez $rt, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BLEZ, /* blez $rt, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "beqs38", /* opcode */ -- BR_RANGE_S256, /* br_range */ -+ .opcode = "blez", -+ .br_range = BR_RANGE_S64K, -+ .cond_field = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BLEZ}, /* blez $rt, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BLEZ}, /* blez $rt, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BLEZ}, /* blez $rt, label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BGTZ, /* bgtz $rt, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BGTZ, /* bgtz $rt, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- {0, 8, 0x7, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -+ .opcode = "bltz", -+ .br_range = BR_RANGE_S64K, -+ .cond_field = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BLTZ}, /* bltz $rt, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BLTZ}, /* bltz $rt, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BLTZ}, /* bltz $rt, label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BGEZ, /* bgez $rt, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BGEZ, /* bgez $rt, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE}, -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- INSN_BEQS38 << 16 /* beq $rt, $R5, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_BEQ_R5 /* beq $rt, $R5, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BNE_R5, /* bne $rt, $R5, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BNE_R5, /* bne $rt, $R5, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BNE_R5, /* bne $rt, $R5, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -+ .opcode = "beq", -+ .br_range = BR_RANGE_S16K, -+ .cond_field = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BEQ}, /* beq $rt, $ra, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BEQ}, /* beq $rt, $ra, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BNE, /* bne $rt, $ra, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 8, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BNE, /* bne $rt, $ra, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BNE, /* bne $rt, $ra, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 8, 0x7, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {2, 4, 8, 8, 16}, /* relax_code_size */ -- {2, 4, 4, 4, 4}, /* relax_branch_isize */ -+ .opcode = "bne", -+ .br_range = BR_RANGE_S16K, -+ .cond_field = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BNE}, /* bne $rt, $ra, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BNE}, /* bne $rt, $ra, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BEQ, /* beq $rt, $ra, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 8, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BEQ, /* beq $rt, $ra, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BEQ, /* beq $rt, $ra, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 15, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "beqc", /* opcode */ -- BR_RANGE_S256, /* br_range */ -+ .opcode = "beqz38", -+ .br_range = BR_RANGE_S256, -+ .cond_field = { -+ {0, 8, 0x7, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BEQZ38 << 16}, /* beqz $rt, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 8, 0x7, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S256] = 2, -+ .relax_branch_isize[BR_RANGE_S256] = 2, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BEQZ}, /* beqz $rt, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BEQZ}, /* beqz $rt, label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BNEZ, /* bnez $rt, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BNEZ, /* bnez $rt, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ta */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- {0, 8, 0x7FF, TRUE}, -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -+ .opcode = "bnez38", -+ .br_range = BR_RANGE_S256, -+ .cond_field = { -+ {0, 8, 0x7, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BNEZ38 << 16}, /* bnez $rt, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 8, 0x7, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S256] = 2, -+ .relax_branch_isize[BR_RANGE_S256] = 2, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BNEZ}, /* bnez $rt, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BNEZ}, /* bnez $rt, label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BEQZ, /* beqz $rt, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BEQZ, /* beqz $rt, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ a */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- INSN_BEQC /* beqc $rt, imm11s, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_MOVI_TA, /* movi $ta, imm11s */ -- INSN_BEQ_TA /* beq $rt, $ta, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BNEC, /* bnec $rt, imm11s, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BNEC, /* bnec $rt, imm11s, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BNEC, /* bnec $rt, imm11s, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -+ .opcode = "beqzs8", -+ .br_range = BR_RANGE_S256, -+ .cond_field = { -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BEQZS8 << 16}, /* beqz $r15, label */ -+ .relax_code_size[BR_RANGE_S256] = 2, -+ .relax_branch_isize[BR_RANGE_S256] = 2, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BEQZ_TA}, /* beqz $r15, label */ -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BEQZ_TA}, /* beqz $r15, label */ -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BNEZ_TA, /* bnez $r15, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BNEZ_TA, /* bnez $r15, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ a */ -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 8, 0x7FF, TRUE}, -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 0, 0xFFFFF, FALSE}, -- {4, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 8, 0x7FF, FALSE}, -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 8, 0x7FF, FALSE}, -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 8, 0x7FF, FALSE}, -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 8, 8, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -+ .opcode = "bnezs8", -+ .br_range = BR_RANGE_S256, -+ .cond_field = { -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BNEZS8 << 16}, /* bnez $r15, label */ -+ .relax_code_size[BR_RANGE_S256] = 2, -+ .relax_branch_isize[BR_RANGE_S256] = 2, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BNEZ_TA}, /* bnez $r15, label */ -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BNEZ_TA}, /* bnez $r15, label */ -+ .relax_code_size[BR_RANGE_S64K] = 4, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BEQZ_TA, /* beqz $r15, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BEQZ_TA, /* beqz $r15, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ a */ -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, -- {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- }, -- { -- "bnec", /* opcode */ -- BR_RANGE_S256, /* br_range */ -+ .opcode = "bnes38", -+ .br_range = BR_RANGE_S256, -+ .cond_field = { -+ {0, 8, 0x7, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BNES38 << 16}, /* bne $rt, $r5, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 8, 0x7, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S256] = 2, -+ .relax_branch_isize[BR_RANGE_S256] = 2, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BNE_R5}, /* bne $rt, $r5, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BEQ_R5, /* beq $rt, $r5, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 8, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BEQ_R5, /* beq $rt, $r5, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BEQ_R5, /* beq $rt, $r5, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ a */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- {0, 8, 0x7FF, TRUE}, -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* cond_field */ -+ .opcode = "beqs38", -+ .br_range = BR_RANGE_S256, -+ .cond_field = { -+ {0, 8, 0x7, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BEQS38 << 16}, /* beq $rt, $r5, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 8, 0x7, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S256] = 2, -+ .relax_branch_isize[BR_RANGE_S256] = 2, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_BEQ_R5}, /* beq $rt, $r5, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 4, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BNE_R5, /* bne $rt, $r5, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 8, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BNE_R5, /* bne $rt, $r5, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BNE_R5, /* bne $rt, $r5, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ a */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, -+ {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- INSN_BNEC /* bnec $rt, imm11s, label */ -- }, /* BR_RANGE_S256 */ -- { -- INSN_MOVI_TA, /* movi $ta, imm11s */ -- INSN_BNE_TA /* bne $rt, $ta, label */ -- }, /* BR_RANGE_S16K */ -- { -- INSN_BEQC, /* beqc $rt, imm11s, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S64K */ -- { -- INSN_BEQC, /* beqc $rt, imm11s, $1 */ -- INSN_J /* j label */ -- }, /* BR_RANGE_S16M */ -- { -- INSN_BEQC, /* beqc $rt, imm11s, $1 */ -- INSN_SETHI_TA, /* sethi $ta, label */ -- INSN_ORI_TA, /* ori $ta, $ta, label */ -- INSN_JR_TA /* jr $ta */ -- } /* BR_RANGE_U4G */ -- }, /* relax_code_seq */ -+ .opcode = "beqc", -+ .br_range = BR_RANGE_S256, -+ .cond_field = { -+ {0, 8, 0x7FF, TRUE}, -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BEQC}, /* beqc $rt, imm11s, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 8, 0x7FF, FALSE}, -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_MOVI_TA, /* movi $ta, imm11s */ -+ INSN_BEQ_TA}, /* beq $rt, $ta, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 0, 0xFFFFF, FALSE}, -+ {4, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 8, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BNEC, /* bnec $rt, imm11s, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 8, 0x7FF, FALSE}, -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 8, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BNEC, /* bnec $rt, imm11s, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 8, 0x7FF, FALSE}, -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BNEC, /* bnec $rt, imm11s, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ a */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 8, 0x7FF, FALSE}, -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 8, 0x7FF, TRUE}, -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S256 */ -- { -- {0, 0, 0xFFFFF, FALSE}, -- {4, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16K */ -- { -- {0, 8, 0x7FF, FALSE}, -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S64K */ -- { -- {0, 8, 0x7FF, FALSE}, -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- }, /* BR_RANGE_S16M */ -- { -- {0, 8, 0x7FF, FALSE}, -- {0, 20, 0x1F, FALSE}, -- {0, 0, 0, FALSE} -- } /* BR_RANGE_U4G */ -- }, /* relax_code_condition */ -- {4, 8, 8, 8, 16}, /* relax_code_size */ -- {4, 4, 4, 4, 4}, /* relax_branch_isize */ -+ .opcode = "bnec", -+ .br_range = BR_RANGE_S256, -+ .cond_field = { -+ {0, 8, 0x7FF, TRUE}, -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_seq[BR_RANGE_S256] = { -+ INSN_BNEC}, /* bnec $rt, imm11s, label */ -+ .relax_code_condition[BR_RANGE_S256] = { -+ {0, 8, 0x7FF, FALSE}, -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S256] = 4, -+ .relax_branch_isize[BR_RANGE_S256] = 4, -+ .relax_fixup[BR_RANGE_S256] = { -+ {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16K] = { -+ INSN_MOVI_TA, /* movi $ta, imm11s */ -+ INSN_BNE_TA}, /* bne $rt, $ta, label */ -+ .relax_code_condition[BR_RANGE_S16K] = { -+ {0, 0, 0xFFFFF, FALSE}, -+ {4, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16K] = 8, -+ .relax_branch_isize[BR_RANGE_S16K] = 4, -+ .relax_fixup[BR_RANGE_S16K] = { -+ {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -+ {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S64K] = { -+ INSN_BEQC, /* beqc $rt, imm11s, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S64K] = { -+ {0, 8, 0x7FF, FALSE}, -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S64K] = 8, -+ .relax_branch_isize[BR_RANGE_S64K] = 4, -+ .relax_fixup[BR_RANGE_S64K] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_S16M] = { -+ INSN_BEQC, /* beqc $rt, imm11s, $1 */ -+ INSN_J}, /* j label */ -+ .relax_code_condition[BR_RANGE_S16M] = { -+ {0, 8, 0x7FF, FALSE}, -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_S16M] = 8, -+ .relax_branch_isize[BR_RANGE_S16M] = 4, -+ .relax_fixup[BR_RANGE_S16M] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -+ {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -+ {0, 0, 0, 0} -+ }, -+ -+ .relax_code_seq[BR_RANGE_U4G] = { -+ INSN_BEQC, /* beqc $rt, imm11s, $1 */ -+ INSN_SETHI_TA, /* sethi $ta, label */ -+ INSN_ORI_TA, /* ori $ta, $ta, label */ -+ INSN_JR_TA}, /* jr $ a */ -+ .relax_code_condition[BR_RANGE_U4G] = { -+ {0, 8, 0x7FF, FALSE}, -+ {0, 20, 0x1F, FALSE}, -+ {0, 0, 0, FALSE} -+ }, -+ .relax_code_size[BR_RANGE_U4G] = 16, -+ .relax_branch_isize[BR_RANGE_U4G] = 4, -+ .relax_fixup[BR_RANGE_U4G] = { -+ {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -+ {4, 4, 0, BFD_RELOC_NDS32_HI20}, -+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, -+ {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ }, -+ }, - { -- { -- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S256 */ -- { -- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, -- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S64K */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, -- {0, 0, 0, 0} -- }, /* BR_RANGE_S16M */ -- { -- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, -- {4, 4, 0, BFD_RELOC_NDS32_HI20}, -- {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, -- {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -- {0, 0, 0, 0} -- } /* BR_RANGE_U4G */ -- } /* relax_fixup */ -- } -+ .opcode = NULL, -+ }, - }; -+ - - /* GAS definitions for command-line options. */ - enum options -@@ -1901,9 +1932,9 @@ size_t md_longopts_size = sizeof (md_longopts); - - struct nds32_parse_option_table - { -- const char *name; /* Option string. */ -- const char *help; /* Help description. */ -- int (*func) (const char *arg); /* How to parse it. */ -+ const char *name; /* Option string. */ -+ const char *help; /* Help description. */ -+ int (*func) (const char *arg); /* How to parse it. */ - }; - - -@@ -1920,7 +1951,7 @@ static int nds32_fpu_dp_ext = -1; - static int nds32_freg = -1; - static int nds32_abi = -1; - --/* Record ELF flags */ -+/* Record ELF flags. */ - static int nds32_elf_flags = 0; - static int nds32_fpu_com = 0; - -@@ -1929,34 +1960,49 @@ static int nds32_parse_baseline (const char *str); - static int nds32_parse_freg (const char *str); - static int nds32_parse_abi (const char *str); - -+static void add_mapping_symbol (enum mstate state, -+ unsigned int padding_byte, unsigned int align); -+ - static struct nds32_parse_option_table parse_opts [] = - { -+ {"ace=", N_("\t Support user defined instruction extension"), -+ nds32_parse_udi}, -+ {"cop0=", N_("\t Support coprocessor 0 extension"), -+ nds32_parse_cop0}, -+ {"cop1=", N_("\t Support coprocessor 1 extension"), -+ nds32_parse_cop1}, -+ {"cop2=", N_("\t Support coprocessor 2 extension"), -+ nds32_parse_cop2}, -+ {"cop3=", N_("\t Support coprocessor 3 extension"), -+ nds32_parse_cop3}, - {"arch=", N_("\t Assemble for architecture \n\ - could be\n\ -- v3, v3j, v3m, v3f, v3s, "\ -+ v3, v3j, v3m, v3m+ v3f, v3s, "\ - "v2, v2j, v2f, v2s"), nds32_parse_arch}, - {"baseline=", N_("\t Assemble for baseline \n\ - could be v2, v3, v3m"), - nds32_parse_baseline}, - {"fpu-freg=", N_("\t Specify a FPU configuration\n\ - \n\ -- 0: 8 SP / 4 DP registers\n\ -- 1: 16 SP / 8 DP registers\n\ -- 2: 32 SP / 16 DP registers\n\ -- 3: 32 SP / 32 DP registers"), nds32_parse_freg}, -+ 0/4: 8 SP / 4 DP registers\n\ -+ 1/5: 16 SP / 8 DP registers\n\ -+ 2/6: 32 SP / 16 DP registers\n\ -+ 3/7: 32 SP / 32 DP registers"), nds32_parse_freg}, - {"abi=", N_("\t Specify a abi version\n\ -- could be v1, v2, v2fp, v2fpp"), nds32_parse_abi}, -+ could be v1, v2, v2fp, v2fp+"), nds32_parse_abi}, - {NULL, NULL, NULL} - }; - - static int nds32_mac = 1; - static int nds32_div = 1; - static int nds32_16bit_ext = 1; --static int nds32_dx_regs = 1; --static int nds32_perf_ext = 1; --static int nds32_perf_ext2 = 1; --static int nds32_string_ext = 1; --static int nds32_audio_ext = 1; -+static int nds32_dx_regs = NDS32_DEFAULT_DX_REGS; -+static int nds32_perf_ext = NDS32_DEFAULT_PERF_EXT; -+static int nds32_perf_ext2 = NDS32_DEFAULT_PERF_EXT2; -+static int nds32_string_ext = NDS32_DEFAULT_STRING_EXT; -+static int nds32_audio_ext = NDS32_DEFAULT_AUDIO_EXT; -+static int nds32_dsp_ext = NDS32_DEFAULT_DSP_EXT; -+static int nds32_zol_ext = NDS32_DEFAULT_ZOL_EXT; - static int nds32_fpu_fma = 0; - static int nds32_pic = 0; - static int nds32_relax_fp_as_gp = 1; -@@ -1965,7 +2011,7 @@ static int nds32_relax_all = 1; - struct nds32_set_option_table - { - const char *name; /* Option string. */ -- const char *help; /* Help description. */ -+ const char *help; /* Help description. */ - int *var; /* Variable to be set. */ - int value; /* Value to set. */ - }; -@@ -1987,6 +2033,8 @@ static struct nds32_set_option_table toggle_opts [] = - {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1}, - {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1}, - {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1}, -+ {"dsp-ext", N_("DSP extension"), &nds32_dsp_ext, 1}, -+ {"zol-ext", N_("hardware loop extension"), &nds32_zol_ext, 1}, - {NULL, NULL, NULL, 0} - }; - -@@ -2000,7 +2048,7 @@ nds32_asm_parse_operand (struct nds32_asm_desc *pdesc, - char **pstr, int64_t *value); - - --struct nds32_asm_desc asm_desc; -+static struct nds32_asm_desc asm_desc; - - /* md_after_parse_args () - -@@ -2086,11 +2134,9 @@ nds32_start_line_hook (void) - { - } - --/* -- * Pseudo opcodes -- */ -+/* Pseudo opcodes. */ - --typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], unsigned int pv); -+typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], int pv); - struct nds32_pseudo_opcode - { - const char *opcode; -@@ -2183,13 +2229,12 @@ static void do_pseudo_li_internal (const char *rt, int imm32s); - static void do_pseudo_move_reg_internal (char *dst, char *src); - - static void --do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - char *arg_label = argv[0]; - relaxing = TRUE; - /* b label */ -- if (nds32_pic && strstr (arg_label, "@PLT")) -+ if (nds32_pic) - { - md_assemblef ("sethi $ta,hi20(%s)", arg_label); - md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); -@@ -2204,18 +2249,16 @@ do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - char *arg_label = argv[0]; - relaxing = TRUE; - /* bal|call label */ -- if (nds32_pic -- && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT"))) -+ if (nds32_pic) - { - md_assemblef ("sethi $ta,hi20(%s)", arg_label); - md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); -- md_assemble ((char *) "add $ta,$ta,$gp"); -+ md_assemble ((char *) "add $ta,$ta,$gp"); - md_assemble ((char *) "jral $ta"); - } - else -@@ -2226,8 +2269,7 @@ do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* rt5, ra5, label */ - md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]); -@@ -2235,8 +2277,7 @@ do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* rt5, ra5, label */ - md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]); -@@ -2244,8 +2285,7 @@ do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* bgt rt5, ra5, label */ - md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]); -@@ -2253,8 +2293,7 @@ do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* bgt rt5, ra5, label */ - md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]); -@@ -2262,8 +2301,7 @@ do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* bgt rt5, ra5, label */ - md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]); -@@ -2271,8 +2309,7 @@ do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* bgt rt5, ra5, label */ - md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]); -@@ -2280,8 +2317,7 @@ do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* rt5, ra5, label */ - md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]); -@@ -2289,8 +2325,7 @@ do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* rt5, ra5, label */ - md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]); -@@ -2298,15 +2333,13 @@ do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - md_assemblef ("jr %s", argv[0]); - } - - static void --do_pseudo_bral (int argc, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_bral (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) - { - if (argc == 1) - md_assemblef ("jral $lp,%s", argv[0]); -@@ -2329,19 +2362,24 @@ do_pseudo_la_internal (const char *arg_reg, char *arg_label, - - relaxing = TRUE; - /* rt, label */ -- if (!nds32_pic && !strstr(arg_label, "@")) -+ if (!nds32_pic && !strstr (arg_label, "@")) -+ { -+ md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label); -+ md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label); -+ } -+ else if (strstr (arg_label, "@ICT")) - { - md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label); - md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label); - } - else if (strstr (arg_label, "@TPOFF")) - { -- /* la $rt, sym@TPOFF */ -+ /* la $rt, sym@TPOFF */ - md_assemblef ("sethi $ta,hi20(%s)", arg_label); - md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); - md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG); - } -- else if (strstr(arg_label, "@GOTTPOFF")) -+ else if (strstr (arg_label, "@GOTTPOFF")) - { - /* la $rt, sym@GOTTPOFF*/ - md_assemblef ("sethi $ta,hi20(%s)", arg_label); -@@ -2381,8 +2419,7 @@ do_pseudo_la_internal (const char *arg_reg, char *arg_label, - } - - static void --do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - do_pseudo_la_internal (argv[0], argv[1], argv[argc]); - } -@@ -2404,8 +2441,7 @@ do_pseudo_li_internal (const char *rt, int imm32s) - } - - static void --do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* Validate argv[1] for constant expression. */ - expressionS exp; -@@ -2421,8 +2457,7 @@ do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv) -+do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) - { - char ls = 'r'; - char size = 'x'; -@@ -2451,14 +2486,14 @@ do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], - relaxing = TRUE; - if (strstr (argv[1], "@TPOFF")) - { -- /* ls.w $rt, sym@TPOFF */ -+ /* ls.w $rt, sym@TPOFF */ - md_assemblef ("sethi $ta,hi20(%s)", argv[1]); - md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]); - md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG); - } - else if (strstr (argv[1], "@GOTTPOFF")) - { -- /* ls.w $rt, sym@GOTTPOFF */ -+ /* ls.w $rt, sym@GOTTPOFF */ - md_assemblef ("sethi $ta,hi20(%s)", argv[1]); - md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]); - md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG); -@@ -2509,8 +2544,7 @@ do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv) -+do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) - { - char *arg_rt = argv[0]; - char *arg_label = argv[1]; -@@ -2537,8 +2571,7 @@ do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv) -+do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) - { - char *arg_rt = argv[0]; - char *arg_inc = argv[1]; -@@ -2563,8 +2596,7 @@ do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv) -+do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) - { - char ls = 'r'; - char size = 'x'; -@@ -2597,8 +2629,7 @@ do_pseudo_move_reg_internal (char *dst, char *src) - } - - static void --do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - expressionS exp; - -@@ -2617,23 +2648,20 @@ do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* Instead of "subri". */ - md_assemblef ("subri %s,%s,0", argv[0], argv[1]); - } - - static void --do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]); - } - - static void --do_pseudo_pushpopm (int argc, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_pushpopm (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* posh/pop $ra, $rb */ - /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */ -@@ -2683,11 +2711,11 @@ do_pseudo_pushpopm (int argc, char *argv[], - /* Reduce register. */ - if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31)) - { -- if (re >= 15 && strstr(opc, "smw") != NULL) -+ if (re >= 15 && strstr (opc, "smw") != NULL) - md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4); - if (rb <= 10) - md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb); -- if (re >= 15 && strstr(opc, "lmw") != NULL) -+ if (re >= 15 && strstr (opc, "lmw") != NULL) - md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4); - } - else -@@ -2695,10 +2723,9 @@ do_pseudo_pushpopm (int argc, char *argv[], - } - - static void --do_pseudo_pushpop (int argc, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_pushpop (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) - { -- /* push/pop $ra5, $label=$sp */ -+ /* push/pop $ra5, $label=$sp */ - char *argvm[3]; - - if (argc == 2) -@@ -2712,15 +2739,13 @@ do_pseudo_pushpop (int argc, char *argv[], - } - - static void --do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - md_assemblef ("push25 %s,%s", argv[0], argv[1]); - } - - static void --do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - md_assemblef ("pop25 %s,%s", argv[0], argv[1]); - } -@@ -2729,11 +2754,10 @@ do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], - pv != 0, parsing "pop.s" pseudo instruction operands. */ - - static void --do_pseudo_pushpop_stack (int argc, char *argv[], -- unsigned int pv) -+do_pseudo_pushpop_stack (int argc, char *argv[], int pv) - { -- /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */ -- /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */ -+ /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */ -+ /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */ - - int rb, re; - int en4; -@@ -2794,8 +2818,7 @@ do_pseudo_pushpop_stack (int argc, char *argv[], - } - - static void --do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - char size = 'x'; - /* If users omit push location, use $sp as default value. */ -@@ -2818,7 +2841,7 @@ do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], - md_assemblef ("l.%c $ta,%s", size, argv[0]); - md_assemblef ("smw.adm $ta,[%s],$ta", location); - -- if ((pv & 0x3) == 0x3) /* double-word */ -+ if ((pv & 0x3) == 0x3) /* double-word */ - { - md_assemblef ("l.w $ta,%s+4", argv[0]); - md_assemblef ("smw.adm $ta,[%s],$ta", location); -@@ -2826,8 +2849,7 @@ do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - char size = 'x'; - /* If users omit pop location, use $sp as default value. */ -@@ -2847,7 +2869,7 @@ do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], - location[7] = '\0'; - } - -- if ((pv & 0x3) == 0x3) /* double-word */ -+ if ((pv & 0x3) == 0x3) /* double-word */ - { - md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]); - md_assemblef ("s.w %s,%s+4", argv[1], argv[0]); -@@ -2858,8 +2880,7 @@ do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* If users omit push location, use $sp as default value. */ - char location[8] = "$sp"; /* 8 is enough for register name. */ -@@ -2875,8 +2896,7 @@ do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], - } - - static void --do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], -- unsigned int pv ATTRIBUTE_UNUSED) -+do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) - { - /* If users omit push location, use $sp as default value. */ - char location[8] = "$sp"; /* 8 is enough for register name. */ -@@ -2891,8 +2911,7 @@ do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], - md_assemblef ("smw.adm $ta,[%s],$ta", location); - } - --struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] = --{ -+static struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] = { - {"b", 1, do_pseudo_b, 0, 0}, - {"bal", 1, do_pseudo_bal, 0, 0}, - -@@ -2967,8 +2986,8 @@ struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] = - {"v3pop", 2, do_pseudo_v3pop, 0, 0}, - - /* Support pseudo instructions of pushing/poping registers into/from stack -- push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4 -- pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */ -+ push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4 -+ pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */ - { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 }, - { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 }, - { "push.b", 2, do_pseudo_push_bhwd, 0, 0 }, -@@ -3009,18 +3028,16 @@ static struct nds32_pseudo_opcode * - nds32_lookup_pseudo_opcode (const char *str) - { - int i = 0; -- /* Assume pseudo-opcode are less than 16-char in length. */ -- char op[16] = {0}; -+ /* *op = first word of current source line (*str) */ -+ int maxlen = strlen (str); -+ char *op = alloca (maxlen + 1); - -- for (i = 0; i < (int)ARRAY_SIZE (op); i++) -+ for (i = 0; i < maxlen; i++) - { - if (ISSPACE (op[i] = str[i])) - break; - } - -- if (i >= (int)ARRAY_SIZE (op)) -- return NULL; -- - op[i] = '\0'; - - return hash_find (nds32_pseudo_opcode_hash, op); -@@ -3081,6 +3098,7 @@ nds32_parse_arch (const char *str) - } archs[] = - { - {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, -+ {"v3m+",ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, - {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, - {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS}, - {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS}, -@@ -3119,11 +3137,11 @@ nds32_parse_arch (const char *str) - static int - nds32_parse_baseline (const char *str) - { -- if (strcmp (str, "v3") == 0) -+ if (strcasecmp (str, "v3") == 0) - nds32_baseline = ISA_V3; -- else if (strcmp (str, "v3m") == 0) -+ else if (strcasecmp (str, "v3m") == 0) - nds32_baseline = ISA_V3M; -- else if (strcmp (str, "v2") == 0) -+ else if (strcasecmp (str, "v2") == 0) - nds32_baseline = ISA_V2; - else - { -@@ -3140,13 +3158,13 @@ nds32_parse_baseline (const char *str) - static int - nds32_parse_freg (const char *str) - { -- if (strcmp (str, "2") == 0) -+ if (strcmp (str, "2") == 0 || strcmp (str, "6") == 0) - nds32_freg = E_NDS32_FPU_REG_32SP_16DP; -- else if (strcmp (str, "3") == 0) -+ else if (strcmp (str, "3") == 0 || strcmp (str, "7") == 0) - nds32_freg = E_NDS32_FPU_REG_32SP_32DP; -- else if (strcmp (str, "1") == 0) -+ else if (strcmp (str, "1") == 0 || strcmp (str, "5") == 0) - nds32_freg = E_NDS32_FPU_REG_16SP_8DP; -- else if (strcmp (str, "0") == 0) -+ else if (strcmp (str, "0") == 0 || strcmp (str, "4") == 0) - nds32_freg = E_NDS32_FPU_REG_8SP_4DP; - else - { -@@ -3170,13 +3188,19 @@ nds32_parse_abi (const char *str) - nds32_abi = E_NDS_ABI_V2FP; - else if (strcmp (str, "v1") == 0) - nds32_abi = E_NDS_ABI_V1; -- else if (strcmp (str,"v2fpp") == 0) -+ else if (strcmp (str,"v2fpp") == 0 || strcmp (str,"v2fp+") == 0) - nds32_abi = E_NDS_ABI_V2FP_PLUS; - else - { -- /* Logic here rejects the input abi version. */ -- as_bad (_("unknown ABI version`%s'\n"), str); -- return 0; -+ /* bug-10880, decided to accept any other versions but drop them. */ -+ if (TRUE) -+ return 1; -+ else -+ { -+ /* Logic here rejects the input abi version. */ -+ as_bad (_("unknown ABI version`%s'\n"), str); -+ return 0; -+ } - } - - return 1; -@@ -3198,6 +3222,10 @@ nds32_all_ext (void) - nds32_fpu_fma = 1; - nds32_fpu_sp_ext = 1; - nds32_fpu_dp_ext = 1; -+ nds32_dsp_ext = 1; -+ nds32_zol_ext = 1; -+ /* Turn off reduced register. */ -+ nds32_gpr16 = 0; - - return 1; - } -@@ -3295,7 +3323,7 @@ nds32_parse_option (int c, const char *arg) - return 1; - } - --/* tc_check_label */ -+/* tc_check_label */ - - void - nds32_check_label (symbolS *label ATTRIBUTE_UNUSED) -@@ -3342,8 +3370,7 @@ typedef struct nds32_seg_entryT - flagword flags; - } nds32_seg_entry; - --nds32_seg_entry nds32_seg_table[] = --{ -+static nds32_seg_entry nds32_seg_table[] = { - {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA - | SEC_HAS_CONTENTS | SEC_SMALL_DATA}, - {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA -@@ -3409,24 +3436,40 @@ nds32_seg (int i) - } - - /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */ --static symbolS *nds32_last_label; /* Last label for alignment. */ -+static symbolS *nds32_last_label; /* Last label for aligment. */ -+ -+static void -+add_mapping_symbol_for_align (int shift, valueT addr, int is_data_align) -+{ -+ if ((shift > 1) && (addr & 1)) -+ { -+ int n = (1 << shift) - 1; -+ if (!is_data_align) -+ add_mapping_symbol (MAP_CODE, 1, 0); -+ else if ((int) (addr & n) != n) -+ add_mapping_symbol (MAP_CODE, 1, 0); -+ } -+ else if ((shift > 1) && ((int) (addr & 1) == 0)) -+ add_mapping_symbol (MAP_CODE, 0, 0); - --/* This code is referred from D30V for adjust label to be with pending -- alignment. For example, -+} -+ -+/* This code is referred from D30V for adjust label to be with pedning -+ aligment. For example, - LBYTE: .byte 0x12 - LHALF: .half 0x12 - LWORD: .word 0x12 -- Without this, the above label will not attach to incoming data. */ -+ Without this, the above label will not attatch to incoming data. */ - - static void - nds32_adjust_label (int n) - { -- /* FIXME: I think adjust label and alignment is -- the programmer's obligation. Sadly, VLSI team doesn't -+ /* FIXME: I think adjust lable and alignment is -+ the programmer's obligation. Saddly, VLSI team doesn't - properly use .align for their test cases. - So I re-implement cons_align and auto adjust labels, again. - -- I think d30v's implementation is simple and good enough. */ -+ I think d30v's implmentation is simple and good enough. */ - - symbolS *label = nds32_last_label; - nds32_last_label = NULL; -@@ -3441,10 +3484,14 @@ nds32_adjust_label (int n) - /* Only frag by alignment when needed. - Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454) - See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */ -+ - if (frag_now_fix () & ((1 << n) -1 )) - { - if (subseg_text_p (now_seg)) -- frag_align_code (n, 0); -+ { -+ add_mapping_symbol_for_align (n, frag_now_fix (), 1); -+ frag_align_code (n, 0); -+ } - else - frag_align (n, 0, 0); - -@@ -3474,7 +3521,7 @@ nds32_adjust_label (int n) - if (symbol_get_frag (sym) == old_frag - && S_GET_VALUE (sym) == old_value) - { -- /* Warning HERE! */ -+ /* Warning HERE! */ - label_seen = TRUE; - symbol_set_frag (sym, frag_now); - S_SET_VALUE (sym, new_value); -@@ -3493,7 +3540,7 @@ nds32_cons_align (int size ATTRIBUTE_UNUSED) - - There are two things should be done for auto-adjust-label. - 1. Align data/instructions and adjust label to be attached to them. -- 2. Clear auto-adjust state, so incoming data/instructions will not -+ 2. Clear auto-adjust state, so incommng data/instructions will not - adjust the label. - - For example, -@@ -3510,15 +3557,67 @@ nds32_cons_align (int size ATTRIBUTE_UNUSED) - } - - static void -+make_mapping_symbol (enum mstate state, valueT value, fragS * frag, unsigned int align) -+{ -+ symbolS *symbol_p = NULL; -+ const char *symbol_name = NULL; -+ switch (state) -+ { -+ case MAP_DATA: -+ if (align == 0) { -+ symbol_name = "$d0"; -+ } -+ else if (align == 1) { -+ symbol_name = "$d1"; -+ } -+ else if (align == 2) -+ symbol_name = "$d2"; -+ else if (align == 3) -+ symbol_name = "$d3"; -+ else if (align == 4) -+ symbol_name = "$d4"; -+ break; -+ case MAP_CODE: -+ symbol_name = "$c"; -+ break; -+ default: -+ abort (); -+ } -+ -+ symbol_p = symbol_new (symbol_name, now_seg, value, frag); -+ /* local scope attribute */ -+ symbol_get_bfdsym (symbol_p)->flags |= BSF_NO_FLAGS | BSF_LOCAL; -+} -+ -+static void -+add_mapping_symbol (enum mstate state, unsigned int padding_byte, unsigned int align) -+{ -+ enum mstate current_mapping_state = -+ seg_info (now_seg)->tc_segment_info_data.mapstate; -+ -+ if (state == MAP_CODE && current_mapping_state == state) -+ return; -+ -+ if (!SEG_NORMAL (now_seg) || !subseg_text_p (now_seg)) -+ return; -+ -+ /* start adding mapping symbol */ -+ seg_info (now_seg)->tc_segment_info_data.mapstate = state; -+ make_mapping_symbol (state, (valueT) frag_now_fix () + padding_byte, -+ frag_now, align); -+} -+ -+static void - nds32_aligned_cons (int idx) - { - nds32_adjust_label (idx); -+ add_mapping_symbol (MAP_DATA, 0, idx); - /* Call default handler. */ - cons (1 << idx); - if (now_seg->flags & SEC_CODE - && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC) - { -- /* Use BFD_RELOC_NDS32_DATA to avoid EX9 optimization replacing data. */ -+ /* Use BFD_RELOC_NDS32_DATA to avoid linker optimization replacing data. */ - expressionS exp; - - exp.X_add_number = 0; -@@ -3578,7 +3677,7 @@ nds32_relax_relocs (int relax) - char *name; - int i; - const char *subtype_relax[] = -- {"", "", "ex9", "ifc"}; -+ {"", "",}; - - name = input_line_pointer; - while (*input_line_pointer && !ISSPACE (*input_line_pointer)) -@@ -3595,14 +3694,6 @@ nds32_relax_relocs (int relax) - case 0: - case 1: - enable_relax_relocs = relax & enable_relax_relocs; -- enable_relax_ex9 = relax & enable_relax_ex9; -- enable_relax_ifc = relax & enable_relax_ifc; -- break; -- case 2: -- enable_relax_ex9 = relax; -- break; -- case 3: -- enable_relax_ifc = relax; - break; - default: - break; -@@ -3652,51 +3743,36 @@ nds32_omit_fp_begin (int mode) - } - } - --/* Insert relocations to mark the begin and end of ex9 region, -- for further relaxation use. -- bit[i] for $ri */ -- - static void --nds32_no_ex9_begin (int mode) -+nds32_loop_begin (int mode) - { -+ /* Insert loop region relocation here. */ - expressionS exp; - - exp.X_op = O_symbol; - exp.X_add_symbol = abs_section_sym; - if (mode == 1) - { -- exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG; -+ exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG; - fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, - BFD_RELOC_NDS32_RELAX_REGION_BEGIN); - } - else - { -- exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG; -+ exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG; - fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, - BFD_RELOC_NDS32_RELAX_REGION_END); - } - } - -+/* Record if in the inline assembly code segment. */ - static void --nds32_loop_begin (int mode) -+nds32_inline_asm (int mode) - { -- /* Insert loop region relocation here. */ -- expressionS exp; -- -- exp.X_op = O_symbol; -- exp.X_add_symbol = abs_section_sym; -- if (mode == 1) -- { -- exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG; -- fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, -- BFD_RELOC_NDS32_RELAX_REGION_BEGIN); -- } -+ if (mode) -+ inline_asm = TRUE; - else -- { -- exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG; -- fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, -- BFD_RELOC_NDS32_RELAX_REGION_END); -- } -+ inline_asm = FALSE; - } - - struct nds32_relocs_group -@@ -3706,16 +3782,49 @@ struct nds32_relocs_group - }; - - static struct nds32_relocs_group *nds32_relax_hint_current = NULL; -+/* Used to reorder the id for ".relax_hint id". */ -+static int relax_hint_bias = 0; -+/* Record current relax hint id. */ -+static int relax_hint_id_current = -1; -+int reset_bias = 0; -+/* If ".relax_hint begin" is triggered? */ -+int relax_hint_begin = 0; -+ -+/* Record the reordered relax hint id. */ -+ -+struct relax_hint_id -+{ -+ int old_id; -+ int new_id; -+ struct relax_hint_id *next; -+}; -+ -+/* FIXME: Need to find somewhere to free the list. */ -+struct relax_hint_id *record_id_head = NULL; -+ -+/* Is the buffer large enough? */ -+#define MAX_BUFFER 12 -+ -+static char *nds_itoa (int n); -+ -+static char * -+nds_itoa (int n) -+{ -+ char *buf = xmalloc (MAX_BUFFER * sizeof (char)); -+ snprintf (buf, MAX_BUFFER, "%d", n); -+ return buf; -+} - - /* Insert a relax hint. */ - - static void - nds32_relax_hint (int mode ATTRIBUTE_UNUSED) - { -- char *name; -+ char *name = NULL; - char saved_char; - struct nds32_relocs_pattern *relocs = NULL; - struct nds32_relocs_group *group, *new; -+ struct relax_hint_id *record_id; - - name = input_line_pointer; - while (*input_line_pointer && !ISSPACE (*input_line_pointer)) -@@ -3724,20 +3833,66 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED) - *input_line_pointer = 0; - name = strdup (name); - -+ if (name && strcmp (name, "begin") == 0) -+ { -+ if (relax_hint_id_current == -1) -+ reset_bias = 1; -+ relax_hint_bias++; -+ relax_hint_id_current++; -+ relax_hint_begin = 1; -+ } -+ -+ /* Original case ".relax_hint id". It's id may need to be reordered. */ -+ if (!relax_hint_begin) -+ { -+ int tmp = strtol (name, NULL, 10); -+ record_id = record_id_head; -+ while (record_id) -+ { -+ if (record_id->old_id == tmp) -+ { -+ name = nds_itoa (record_id->new_id); -+ goto reordered_id; -+ } -+ record_id = record_id->next; -+ } -+ if (reset_bias) -+ { -+ relax_hint_bias = relax_hint_id_current - atoi (name) + 1; -+ reset_bias = 0; -+ } -+ relax_hint_id_current = tmp + relax_hint_bias; -+ -+ /* Insert the element to the head of the link list. */ -+ struct relax_hint_id *tmp_id = malloc (sizeof (struct relax_hint_id)); -+ tmp_id->old_id = tmp; -+ tmp_id->new_id = relax_hint_id_current; -+ tmp_id->next = record_id_head; -+ record_id_head = tmp_id; -+ } -+ -+ if (name && strcmp (name, "end") == 0) -+ relax_hint_begin = 0; -+ name = nds_itoa (relax_hint_id_current); -+ -+reordered_id: -+ - /* Find relax hint entry for next instruction, and all member will be - initialized at that time. */ - relocs = hash_find (nds32_hint_hash, name); - if (relocs == NULL) - { -- relocs = XNEW (struct nds32_relocs_pattern); -+ relocs = malloc (sizeof (struct nds32_relocs_pattern)); -+ memset (relocs, 0, sizeof (struct nds32_relocs_pattern)); - hash_insert (nds32_hint_hash, name, relocs); - } - else - { - while (relocs->next) - relocs=relocs->next; -- relocs->next = XNEW (struct nds32_relocs_pattern); -+ relocs->next = malloc (sizeof (struct nds32_relocs_pattern)); - relocs = relocs->next; -+ memset (relocs, 0, sizeof (struct nds32_relocs_pattern)); - } - - relocs->next = NULL; -@@ -3749,7 +3904,8 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED) - /* It has to build this list because there are maybe more than one - instructions relative to the same instruction. It to connect to - next instruction after md_assemble. */ -- new = XNEW (struct nds32_relocs_group); -+ new = malloc (sizeof (struct nds32_relocs_group)); -+ memset (new, 0, sizeof (struct nds32_relocs_group)); - new->pattern = relocs; - new->next = NULL; - group = nds32_relax_hint_current; -@@ -3764,6 +3920,27 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED) - relaxing = TRUE; - } - -+/* This is directive generated for compiler to estimate branch target -+ alignment. But assembler does not use the info currently. */ -+ -+static void -+nds32_maybe_align (int mode ATTRIBUTE_UNUSED) -+{ -+ /* Ignore the reset of line. */ -+ ignore_rest_of_line (); -+} -+ -+/* The end of security. It must check if there is any branch -+ between begin and end. */ -+static void -+nds32_security_end (int mode ATTRIBUTE_UNUSED) -+{ -+ if (crcing == FALSE) -+ as_bad (_("Found unexpected branches inside the " -+ "signature protected region.")); -+ -+} -+ - /* Decide the size of vector entries, only accepts 4 or 16 now. */ - - static void -@@ -3819,7 +3996,7 @@ nds32_flag (int ignore ATTRIBUTE_UNUSED) - switch (i) - { - case 0: -- /* flag: verbatim */ -+ /* flag: verbatim */ - verbatim = 1; - break; - default: -@@ -3835,6 +4012,54 @@ nds32_flag (int ignore ATTRIBUTE_UNUSED) - } - - static void -+ict_model (int ignore ATTRIBUTE_UNUSED) -+{ -+ char *name; -+ char saved_char; -+ int i; -+ const char *possible_flags[] = { "small", "large" }; -+ -+ /* Skip whitespaces. */ -+ name = input_line_pointer; -+ while (*input_line_pointer && !ISSPACE (*input_line_pointer)) -+ input_line_pointer++; -+ saved_char = *input_line_pointer; -+ *input_line_pointer = 0; -+ -+ for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++) -+ { -+ if (strcmp (name, possible_flags[i]) == 0) -+ { -+ switch (i) -+ { -+ case 0: -+ /* flag: verbatim */ -+ ict_flag = ICT_SMALL; -+ break; -+ case 1: -+ ict_flag = ICT_LARGE; -+ break; -+ default: -+ break; -+ } -+ /* Already found the flag, no need to continue next loop. */ -+ break; -+ } -+ } -+ -+ *input_line_pointer = saved_char; -+ ignore_rest_of_line (); -+} -+ -+/* Create .note.v2abi_compatible section if the object is compatible with v3f/v3s. -+ Do it at the md_end(). */ -+static void -+nds32_compatible_abi (int mode ATTRIBUTE_UNUSED) -+{ -+ compatible_abi = TRUE; -+} -+ -+static void - nds32_n12hc (int ignore ATTRIBUTE_UNUSED) - { - /* N1213HC core is used. */ -@@ -3842,8 +4067,7 @@ nds32_n12hc (int ignore ATTRIBUTE_UNUSED) - - - /* The target specific pseudo-ops which we support. */ --const pseudo_typeS md_pseudo_table[] = --{ -+const pseudo_typeS md_pseudo_table[] = { - /* Forced alignment if declared these ways. */ - {"ascii", stringer, 8 + 0}, - {"asciz", stringer, 8 + 1}, -@@ -3894,13 +4118,17 @@ const pseudo_typeS md_pseudo_table[] = - {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */ - {"omit_fp_begin", nds32_omit_fp_begin, 1}, - {"omit_fp_end", nds32_omit_fp_begin, 0}, -- {"no_ex9_begin", nds32_no_ex9_begin, 1}, -- {"no_ex9_end", nds32_no_ex9_begin, 0}, - {"vec_size", nds32_vec_size, 0}, - {"flag", nds32_flag, 0}, - {"innermost_loop_begin", nds32_loop_begin, 1}, - {"innermost_loop_end", nds32_loop_begin, 0}, - {"relax_hint", nds32_relax_hint, 0}, -+ {"maybe_align", nds32_maybe_align, 0}, -+ {"signature_end", nds32_security_end, 0}, -+ {"inline_asm_begin", nds32_inline_asm, 1}, -+ {"inline_asm_end", nds32_inline_asm, 0}, -+ {"ict_model", ict_model, 0}, -+ {"v2abi_compatible", nds32_compatible_abi, 0}, - {NULL, NULL, 0} - }; - -@@ -3917,9 +4145,10 @@ nds32_pre_do_align (int n, char *fill, int len, int max) - { - dwarf2_emit_insn (0); - fragP = frag_now; -+ add_mapping_symbol_for_align (n, frag_now_fix (), 0); - frag_align_code (n, max); - -- /* Tag this alignment when there is a label before it. */ -+ /* Tag this alignment when there is a lable before it. */ - if (label_exist) - { - fragP->tc_frag_data.flag = NDS32_FRAG_LABEL; -@@ -4003,24 +4232,26 @@ void - md_begin (void) - { - struct nds32_keyword *k; -- unsigned int i; -+ relax_info_t *relax_info; -+ int flags = 0; - - bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline); - - nds32_init_nds32_pseudo_opcodes (); - asm_desc.parse_operand = nds32_asm_parse_operand; -- nds32_asm_init (&asm_desc, 0); -+ if (nds32_gpr16) -+ flags |= NASM_OPEN_REDUCED_REG; -+ nds32_asm_init (&asm_desc, flags); - -- /* Initial general purpose registers hash table. */ -+ /* Initial general pupose registers hash table. */ - nds32_gprs_hash = hash_new (); - for (k = keyword_gpr; k->name; k++) - hash_insert (nds32_gprs_hash, k->name, k); - - /* Initial branch hash table. */ - nds32_relax_info_hash = hash_new (); -- for (i = 0; i < ARRAY_SIZE (relax_table); i++) -- hash_insert (nds32_relax_info_hash, relax_table[i].opcode, -- &relax_table[i]); -+ for (relax_info = relax_table; relax_info->opcode; relax_info++) -+ hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info); - - /* Initial relax hint hash table. */ - nds32_hint_hash = hash_new (); -@@ -4138,13 +4369,14 @@ get_range_type (const struct nds32_field *field) - /* Save pseudo instruction relocation list. */ - - static struct nds32_relocs_pattern* --nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode, -+nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_asm_insn *insn, - char *out, symbolS *sym, - struct nds32_relocs_pattern *reloc_ptr, - fragS *fragP) - { -+ struct nds32_opcode *opcode = insn->opcode; - if (!reloc_ptr) -- reloc_ptr = XNEW (struct nds32_relocs_pattern); -+ reloc_ptr = malloc (sizeof (struct nds32_relocs_pattern)); - reloc_ptr->seg = now_seg; - reloc_ptr->sym = sym; - reloc_ptr->frag = fragP; -@@ -4152,6 +4384,7 @@ nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode, - reloc_ptr->fixP = fixP; - reloc_ptr->opcode = opcode; - reloc_ptr->where = out; -+ reloc_ptr->insn = insn->insn; - reloc_ptr->next = NULL; - return reloc_ptr; - } -@@ -4193,10 +4426,21 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, - reloc = BFD_RELOC_NDS32_TLS_LE_HI20; - break; - case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */ -- reloc = BFD_RELOC_NDS32_TLS_IE_HI20; -+ reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_HI20 : BFD_RELOC_NDS32_TLS_IE_HI20; -+ break; -+ case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */ -+ reloc = BFD_RELOC_NDS32_TLS_DESC_HI20; -+ break; -+ case BFD_RELOC_NDS32_ICT: -+ reloc = BFD_RELOC_NDS32_ICT_HI20; - break; - default: /* No suffix. */ -- reloc = BFD_RELOC_NDS32_HI20; -+ if (nds32_pic) -+ /* When the file is pic, the address must be offset to gp. -+ It may define another relocation or use GOTOFF. */ -+ reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20; -+ else -+ reloc = BFD_RELOC_NDS32_HI20; - break; - } - fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, -@@ -4228,8 +4472,22 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, - case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */ - reloc = BFD_RELOC_NDS32_TLS_LE_LO12; - break; -+ case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */ -+ reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12 : BFD_RELOC_NDS32_TLS_IE_LO12; -+ break; -+ case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */ -+ reloc = BFD_RELOC_NDS32_TLS_DESC_LO12; -+ break; -+ case BFD_RELOC_NDS32_ICT: -+ reloc = BFD_RELOC_NDS32_ICT_LO12; -+ break; - default: /* No suffix. */ -- reloc = BFD_RELOC_NDS32_LO12S0; -+ if (nds32_pic) -+ /* When the file is pic, the address must be offset to gp. -+ It may define another relocation or use GOTOFF. */ -+ reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12; -+ else -+ reloc = BFD_RELOC_NDS32_LO12S0; - break; - } - } -@@ -4237,11 +4495,14 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, - reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */ - else if (fld->bitsize == 15 && fld->shift == 2) - { -- /* [ls]wi */ -+ /* [ls]wi */ - switch (pexp->X_md) - { - case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */ -- reloc = BFD_RELOC_NDS32_TLS_IE_LO12S2; -+ reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12S2 : BFD_RELOC_NDS32_TLS_IE_LO12S2; -+ break; -+ case BFD_RELOC_NDS32_ICT: -+ reloc = BFD_RELOC_NDS32_ICT_LO12S2; - break; - default: /* No suffix. */ - reloc = BFD_RELOC_NDS32_LO12S2; -@@ -4251,7 +4512,7 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, - else if (fld->bitsize == 15 && fld->shift == 3) - reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */ - else if (fld->bitsize == 12 && fld->shift == 2) -- reloc = R_NDS32_LO12S2_SP_RELA; /* f[ls][sd]i */ -+ reloc = BFD_RELOC_NDS32_LO12S2_SP; /* f[ls][sd]i */ - - fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, - insn->info, 0 /* pcrel */, reloc); -@@ -4261,7 +4522,12 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, - { - /* Relocation for 32-bit branch instructions. */ - if (fld->bitsize == 24 && fld->shift == 1) -- reloc = BFD_RELOC_NDS32_25_PCREL; -+ { -+ if (pexp->X_md == BFD_RELOC_NDS32_ICT) -+ reloc = BFD_RELOC_NDS32_ICT_25PC; -+ else -+ reloc = BFD_RELOC_NDS32_25_PCREL; -+ } - else if (fld->bitsize == 16 && fld->shift == 1) - reloc = BFD_RELOC_NDS32_17_PCREL; - else if (fld->bitsize == 14 && fld->shift == 1) -@@ -4272,7 +4538,7 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, - abort (); - - fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, -- insn->info, 1 /* pcrel */, reloc); -+ insn->info, 1 /* pcrel */, reloc); - } - else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4 - && (insn->attr & NASM_ATTR_GPREL)) -@@ -4288,7 +4554,7 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, - abort (); - - fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, -- insn->info, 0 /* pcrel */, reloc); -+ insn->info, 0 /* pcrel */, reloc); - /* Insert INSN16 for converting fp_as_gp. */ - exp.X_op = O_symbol; - exp.X_add_symbol = abs_section_sym; -@@ -4310,20 +4576,6 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, - fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, - insn->info, 1 /* pcrel */, reloc); - } -- else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_IFC_EXT)) -- { -- /* Relocation for ifcall instruction. */ -- if (insn->opcode->isize == 2 && fld->bitsize == 9 && fld->shift == 1) -- reloc = BFD_RELOC_NDS32_10IFCU_PCREL; -- else if (insn->opcode->isize == 4 && fld->bitsize == 16 -- && fld->shift == 1) -- reloc = BFD_RELOC_NDS32_17IFC_PCREL; -- else -- abort (); -- -- fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, -- insn->info, 1 /* pcrel */, reloc); -- } - else if (fld) - as_bad (_("Don't know how to handle this field. %s"), str); - -@@ -4335,8 +4587,9 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, - - static void - nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, -- struct nds32_opcode *opcode, fragS *fragP, -- const struct nds32_field *fld) -+ struct nds32_asm_insn *insn, fragS *fragP, -+ const struct nds32_field *fld, -+ bfd_boolean pseudo_hint) - { - struct nds32_relocs_pattern *reloc_ptr; - struct nds32_relocs_group *group; -@@ -4346,10 +4599,32 @@ nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, - if (fld) - sym = pexp->X_add_symbol; - -- if (pseudo_opcode) -+ if (pseudo_hint) -+ { -+ /* We cannot know how many instructions will be expanded for -+ the pseudo instruction here. The first expanded instruction fills -+ the memory created by relax_hint. The follower will created and link -+ here. */ -+ group = nds32_relax_hint_current; -+ while (group) -+ { -+ if (group->pattern->opcode == NULL) -+ nds32_elf_save_pseudo_pattern (fixP, insn, out, sym, -+ group->pattern, fragP); -+ else -+ { -+ group->pattern->next = -+ nds32_elf_save_pseudo_pattern (fixP, insn, out, sym, -+ NULL, fragP); -+ group->pattern = group->pattern->next; -+ } -+ group = group->next; -+ } -+ } -+ else if (pseudo_opcode) - { - /* Save instruction relation for pseudo instruction expanding pattern. */ -- reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym, -+ reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, insn, out, sym, - NULL, fragP); - if (!relocs_list) - relocs_list = reloc_ptr; -@@ -4367,7 +4642,7 @@ nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, - group = nds32_relax_hint_current; - while (group) - { -- nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym, -+ nds32_elf_save_pseudo_pattern (fixP, insn, out, sym, - group->pattern, fragP); - group = group->next; - free (nds32_relax_hint_current); -@@ -4383,40 +4658,214 @@ nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, - #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn) - - /* Relax pattern for link time relaxation. */ -+/* relaxation types only! relocation types are not necessary */ -+/* refer to nds32_elf_record_fixup_exp() */ - - static struct nds32_relax_hint_table relax_ls_table[] = - { - { -- /* Set address: la -> sethi ori. */ -- NDS32_RELAX_HINT_LA, /* main_type */ -- 8, /* relax_code_size */ -- { -- OP6 (SETHI), -- OP6 (ORI), -- }, /* relax_code_seq */ -- { -- {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -- {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16} -- } /* relax_fixup */ -+ /* For bug-12566, LA and Floating LSI. */ -+ .main_type = NDS32_RELAX_HINT_LA_FLSI, -+ .relax_code_size = 12, -+ .relax_code_seq = -+ { -+ OP6 (SETHI), -+ OP6 (ORI), -+ OP6 (LBI), -+ }, -+ .relax_fixup = -+ { -+ {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -+ {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR}, -+ {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_LSI}, -+ {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ } - }, - { -- /* Set address: l.w -> sethi ori. */ -- NDS32_RELAX_HINT_LS, /* main_type */ -- 8, /* relax_code_size */ -- { -- OP6 (SETHI), -- OP6 (LBI), -- }, /* relax_code_seq */ -- { -- {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -- {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16} -- } /* relax_fixup */ -+ /* Load Address / Load-Store (LALS). */ -+ .main_type = NDS32_RELAX_HINT_LALS, -+ .relax_code_size = 12, -+ .relax_code_seq = -+ { -+ OP6 (SETHI), -+ OP6 (ORI), -+ OP6 (LBI), -+ }, -+ .relax_fixup = -+ { -+ {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -+ {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ } - }, - { -- 0, -- 0, -- {0}, -- {{0, 0 , 0, 0}} -+ /* B(AL) symbol@PLT */ -+ .main_type = NDS32_RELAX_HINT_LA_PLT, -+ .relax_code_size = 16, -+ .relax_code_seq = -+ { -+ OP6 (SETHI), -+ OP6 (ORI), -+ OP6 (ALU1), -+ OP6 (JREG), -+ }, -+ .relax_fixup = -+ { -+ {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -+ {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR}, -+ {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PLT_GOT_SUFF}, -+ {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ } -+ }, -+ { -+ /* LA (@GOT). */ -+ .main_type = NDS32_RELAX_HINT_LA_GOT, -+ .relax_code_size = 12, -+ .relax_code_seq = -+ { -+ OP6 (SETHI), -+ OP6 (ORI), -+ OP6 (MEM), -+ }, -+ .relax_fixup = -+ { -+ {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -+ {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOT_SUFF}, -+ {0, 0, 0, 0} -+ } -+ }, -+ { -+ /* LA (@GOTOFF). */ -+ .main_type = NDS32_RELAX_HINT_LA_GOTOFF, -+ .relax_code_size = 16, -+ .relax_code_seq = -+ { -+ OP6 (SETHI), -+ OP6 (ORI), -+ OP6 (ALU1), -+ OP6 (MEM), -+ }, -+ .relax_fixup = -+ { -+ {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -+ {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF}, -+ {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF}, -+ {0, 0, 0, 0} -+ } -+ }, -+ { -+ /* TLS LE LS|LA */ -+ .main_type = NDS32_RELAX_HINT_TLS_LE_LS, -+ .relax_code_size = 16, -+ .relax_code_seq = -+ { -+ OP6(SETHI), -+ OP6(ORI), -+ OP6(MEM), -+ OP6(ALU1), -+ }, -+ .relax_fixup = -+ { -+ {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -+ {4, 4, NDS32_HINT | NDS32_PTR_MULTIPLE, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_LS}, -+ {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_ADD}, -+ {0, 0, 0, 0} -+ } -+ }, -+ { -+ /* TLS IE LA */ -+ .main_type = NDS32_RELAX_HINT_TLS_IE_LA, -+ .relax_code_size = 8, -+ .relax_code_seq = -+ { -+ OP6(SETHI), -+ OP6(LBI), -+ }, -+ .relax_fixup = -+ { -+ {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -+ {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, -+ {0, 0, 0, 0} -+ } -+ }, -+ { -+ /* TLS IEGP LA */ -+ .main_type = NDS32_RELAX_HINT_TLS_IEGP_LA, -+ .relax_code_size = 12, -+ .relax_code_seq = -+ { -+ OP6 (SETHI), -+ OP6 (ORI), -+ OP6 (MEM), -+ }, -+ .relax_fixup = -+ { -+ {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -+ {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_IEGP_LW}, -+ {0, 0, 0, 0} -+ } -+ }, -+ { -+ /* TLS DESC LS: */ -+ .main_type = NDS32_RELAX_HINT_TLS_DESC_LS, -+ .relax_code_size = 24, -+ .relax_code_seq = -+ { -+ OP6 (SETHI), -+ OP6 (ORI), -+ OP6 (ALU1), -+ OP6 (LBI), /* load argument */ -+ OP6 (JREG), -+ OP6 (MEM), /* load/store variable or load argument */ -+ }, -+ .relax_fixup = -+ { -+ {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, -+ {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR}, -+ {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, -+ {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_ADD}, -+ {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_FUNC}, -+ {16, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_CALL}, -+ {20, 4, NDS32_HINT | NDS32_SYM_DESC_MEM, BFD_RELOC_NDS32_TLS_DESC_MEM}, -+ {0, 0, 0, 0} -+ } -+ }, -+ { -+ /* Load Address of ICT. */ -+ .main_type = NDS32_RELAX_HINT_ICT_LA, -+ .relax_code_size = 8, -+ .relax_code_seq = -+ { -+ OP6 (SETHI), -+ OP6 (ORI), -+ }, -+ .relax_fixup = -+ { -+ /* TODO: insert relocations to do relax. */ -+ {0, 0, 0, 0} -+ } -+ }, -+ { -+ .main_type = 0, -+ .relax_code_seq = {0}, -+ .relax_fixup = {{0, 0 , 0, 0}} - } - }; - -@@ -4481,118 +4930,189 @@ nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern) - (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \ - | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0)) - -+#define MAC_COMBO (E_NDS32_HAS_FPU_MAC_INST|E_NDS32_HAS_MAC_DX_INST) - static void - nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn) - { -- /* Set E_NDS32_HAS_EXT_INST. */ -- if (insn->opcode->attr & NASM_ATTR_PERF_EXT) -- { -- if (nds32_perf_ext) -- nds32_elf_flags |= E_NDS32_HAS_EXT_INST; -- else -- as_bad (_("instruction %s requires enabling performance extension"), -- insn->opcode->opcode); -- } -- else if (insn->opcode->attr & NASM_ATTR_PERF2_EXT) -- { -- if (nds32_perf_ext2) -- nds32_elf_flags |= E_NDS32_HAS_EXT2_INST; -- else -- as_bad (_("instruction %s requires enabling performance extension II"), -- insn->opcode->opcode); -- } -- else if (insn->opcode->attr & NASM_ATTR_AUDIO_ISAEXT) -- { -- if (nds32_audio_ext) -- nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST; -- else -- as_bad (_("instruction %s requires enabling AUDIO extension"), -- insn->opcode->opcode); -- } -- else if (insn->opcode->attr & NASM_ATTR_STR_EXT) -- { -- if (nds32_string_ext) -- nds32_elf_flags |= E_NDS32_HAS_STRING_INST; -- else -- as_bad (_("instruction %s requires enabling STRING extension"), -- insn->opcode->opcode); -- } -- else if ((insn->opcode->attr & NASM_ATTR_DIV) -- && (insn->opcode->attr & NASM_ATTR_DXREG)) -- { -- if (nds32_div && nds32_dx_regs) -- nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST; -- else -- as_bad (_("instruction %s requires enabling DIV & DX_REGS extension"), -- insn->opcode->opcode); -- } -- else if (insn->opcode->attr & NASM_ATTR_FPU) -- { -- if (nds32_fpu_sp_ext || nds32_fpu_dp_ext) -- { -- if (!(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))) -- nds32_fpu_com = 1; -- } -- else -- as_bad (_("instruction %s requires enabling FPU extension"), -- insn->opcode->opcode); -- } -- else if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT) -- { -- if (nds32_fpu_sp_ext) -- nds32_elf_flags |= E_NDS32_HAS_FPU_INST; -- else -- as_bad (_("instruction %s requires enabling FPU_SP extension"), -- insn->opcode->opcode); -- } -- else if ((insn->opcode->attr & NASM_ATTR_FPU_SP_EXT) -- && (insn->opcode->attr & NASM_ATTR_MAC)) -- { -- if (nds32_fpu_sp_ext && nds32_mac) -- { -- nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST; -- nds32_elf_flags |= E_NDS32_HAS_FPU_INST; -- } -- else -- as_bad (_("instruction %s requires enabling FPU_MAC extension"), -- insn->opcode->opcode); -- } -- else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT) -- { -- if (nds32_fpu_dp_ext) -- nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST; -- else -- as_bad (_("instruction %s requires enabling FPU_DP extension"), -- insn->opcode->opcode); -- } -- else if ((insn->opcode->attr & NASM_ATTR_FPU_DP_EXT) -- && (insn->opcode->attr & NASM_ATTR_MAC)) -+ static int skip_flags = NASM_ATTR_EX9_EXT | NASM_ATTR_FPU_FMA -+ | NASM_ATTR_BRANCH | NASM_ATTR_SATURATION_EXT | NASM_ATTR_GPREL -+ | NASM_ATTR_DXREG | NASM_ATTR_ISA_V1 | NASM_ATTR_ISA_V2 | NASM_ATTR_ISA_V3 -+ | NASM_ATTR_ISA_V3M | NASM_ATTR_PCREL; -+ -+ int new_flags = insn->opcode->attr & ~skip_flags; -+ while (new_flags) - { -- if (nds32_fpu_dp_ext && nds32_mac) -+ int next = 1 << (ffs (new_flags) - 1); -+ new_flags &= ~next; -+ switch (next) - { -- nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST; -- nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST; -+ case NASM_ATTR_PERF_EXT: -+ { -+ if (nds32_perf_ext) -+ { -+ nds32_elf_flags |= E_NDS32_HAS_EXT_INST; -+ skip_flags |= NASM_ATTR_PERF_EXT; -+ } -+ else -+ as_bad (_("instruction %s requires enabling performance " -+ "extension"), insn->opcode->opcode); -+ } -+ break; -+ case NASM_ATTR_PERF2_EXT: -+ { -+ if (nds32_perf_ext2) -+ { -+ nds32_elf_flags |= E_NDS32_HAS_EXT2_INST; -+ skip_flags |= NASM_ATTR_PERF2_EXT; -+ } -+ else -+ as_bad (_("instruction %s requires enabling performance " -+ "extension II"), insn->opcode->opcode); -+ } -+ break; -+ case NASM_ATTR_AUDIO_ISAEXT: -+ { -+ if (nds32_audio_ext) -+ { -+ nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST; -+ skip_flags |= NASM_ATTR_AUDIO_ISAEXT; -+ } -+ else -+ as_bad (_("instruction %s requires enabling AUDIO extension"), -+ insn->opcode->opcode); -+ } -+ break; -+ case NASM_ATTR_STR_EXT: -+ { -+ if (nds32_string_ext) -+ { -+ nds32_elf_flags |= E_NDS32_HAS_STRING_INST; -+ skip_flags |= NASM_ATTR_STR_EXT; -+ } -+ else -+ as_bad (_("instruction %s requires enabling STRING extension"), -+ insn->opcode->opcode); -+ } -+ break; -+ case NASM_ATTR_DIV: -+ { -+ if (insn->opcode->attr & NASM_ATTR_DXREG) -+ { -+ if (nds32_div && nds32_dx_regs) -+ { -+ nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST; -+ skip_flags |= NASM_ATTR_DIV; -+ } -+ else -+ as_bad (_("instruction %s requires enabling DIV & DX_REGS " -+ "extension"), insn->opcode->opcode); -+ } -+ } -+ break; -+ case NASM_ATTR_FPU: -+ { -+ if (nds32_fpu_sp_ext || nds32_fpu_dp_ext) -+ { -+ if (!(nds32_elf_flags -+ & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))) -+ nds32_fpu_com = 1; -+ skip_flags |= NASM_ATTR_FPU; -+ } -+ else -+ as_bad (_("instruction %s requires enabling FPU extension"), -+ insn->opcode->opcode); -+ } -+ break; -+ case NASM_ATTR_FPU_SP_EXT: -+ { -+ if (nds32_fpu_sp_ext) -+ { -+ nds32_elf_flags |= E_NDS32_HAS_FPU_INST; -+ skip_flags |= NASM_ATTR_FPU_SP_EXT; -+ } -+ else -+ as_bad (_("instruction %s requires enabling FPU_SP extension"), -+ insn->opcode->opcode); -+ } -+ break; -+ case NASM_ATTR_FPU_DP_EXT: -+ { -+ if (nds32_fpu_dp_ext) -+ { -+ nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST; -+ skip_flags |= NASM_ATTR_FPU_DP_EXT; -+ } -+ else -+ as_bad (_("instruction %s requires enabling FPU_DP extension"), -+ insn->opcode->opcode); -+ } -+ break; -+ case NASM_ATTR_MAC: -+ { -+ if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT) -+ { -+ if (nds32_fpu_sp_ext && nds32_mac) -+ nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST; -+ else -+ as_bad (_("instruction %s requires enabling FPU_MAC " -+ "extension"), insn->opcode->opcode); -+ } -+ else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT) -+ { -+ if (nds32_fpu_dp_ext && nds32_mac) -+ nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST; -+ else -+ as_bad (_("instruction %s requires enabling FPU_MAC " -+ "extension"), insn->opcode->opcode); -+ } -+ else if (insn->opcode->attr & NASM_ATTR_DXREG) -+ { -+ if (nds32_dx_regs && nds32_mac) -+ nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST; -+ else -+ as_bad (_("instruction %s requires enabling DX_REGS " -+ "extension"), insn->opcode->opcode); -+ } -+ -+ if (MAC_COMBO == (MAC_COMBO & nds32_elf_flags)) -+ skip_flags |= NASM_ATTR_MAC; -+ } -+ break; -+ case NASM_ATTR_IFC_EXT: -+ { -+ nds32_elf_flags |= E_NDS32_HAS_IFC_INST; -+ skip_flags |= NASM_ATTR_IFC_EXT; -+ } -+ break; -+ case NASM_ATTR_DSP_ISAEXT: -+ { -+ if (nds32_dsp_ext) -+ { -+ nds32_elf_flags |= E_NDS32_HAS_DSP_INST; -+ skip_flags |= NASM_ATTR_DSP_ISAEXT; -+ } -+ else -+ as_bad (_("instruction %s requires enabling dsp extension"), -+ insn->opcode->opcode); -+ } -+ break; -+ case NASM_ATTR_ZOL: -+ { -+ if (nds32_zol_ext) -+ { -+ nds32_elf_flags |= E_NDS32_HAS_ZOL; -+ skip_flags |= NASM_ATTR_ZOL; -+ } -+ else -+ as_bad (_("instruction %s requires enabling zol extension"), -+ insn->opcode->opcode); -+ } -+ break; -+ default: -+ as_bad (_("internal error: unknown instruction attribute: 0x%08x"), -+ next); - } -- else -- as_bad (_("instruction %s requires enabling FPU_MAC extension"), -- insn->opcode->opcode); -- } -- /* TODO: FPU_BOTH */ -- else if ((insn->opcode->attr & NASM_ATTR_MAC) -- && (insn->opcode->attr & NASM_ATTR_DXREG)) -- { -- if (nds32_mac && nds32_dx_regs) -- nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST; -- else -- as_bad (_("instruction %s requires enabling DX_REGS extension"), -- insn->opcode->opcode); -- } -- /* TODO: for DX_REG set but not for MAC, DIV, AUDIO */ -- else if (insn->opcode->attr & NASM_ATTR_IFC_EXT) -- { -- nds32_elf_flags |= E_NDS32_HAS_IFC_INST; - } -- /* TODO: E_NDS32_HAS_SATURATION_INST */ - } - - /* Flag for analysis relaxation type. */ -@@ -4607,100 +5127,212 @@ enum nds32_insn_type - N32_RELAX_ORI = (1 << 5), - N32_RELAX_MEM = (1 << 6), - N32_RELAX_MOVI = (1 << 7), -+ N32_RELAX_ALU1 = (1 << 8), -+ N32_RELAX_16BIT = (1 << 9), - }; - - struct nds32_hint_map - { -+ /* the preamble relocation */ - bfd_reloc_code_real_type hi_type; -+ /* mnemonic */ - const char *opc; -+ /* relax pattern ID */ - enum nds32_relax_hint_type hint_type; -+ /* range */ - enum nds32_br_range range; -+ /* pattern character flags */ - enum nds32_insn_type insn_list; -+ /* optional pattern character flags */ -+ enum nds32_insn_type option_list; - }; - - /* Table to match instructions with hint and relax pattern. */ - - static struct nds32_hint_map hint_map [] = - { -- { -- /* LONGCALL4. */ -- BFD_RELOC_NDS32_HI20, -- "jal", -- NDS32_RELAX_HINT_NONE, -- BR_RANGE_U4G, -- N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL -- }, -- { -- /* LONGCALL5. */ -- _dummy_first_bfd_reloc_code_real, -- "bgezal", -- NDS32_RELAX_HINT_NONE, -- BR_RANGE_S16M, -- N32_RELAX_BR | N32_RELAX_CALL -- }, -- { -- /* LONGCALL6. */ -- BFD_RELOC_NDS32_HI20, -- "bgezal", -- NDS32_RELAX_HINT_NONE, -- BR_RANGE_U4G, -- N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL -- }, -- { -- /* LONGJUMP4. */ -- BFD_RELOC_NDS32_HI20, -- "j", -- NDS32_RELAX_HINT_NONE, -- BR_RANGE_U4G, -- N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP -- }, -- { -- /* LONGJUMP5. */ -- /* There is two kinds of variations of LONGJUMP5. One of them -- generate EMPTY relocation for converted INSN16 if needed. -- But we don't distinguish them here. */ -- _dummy_first_bfd_reloc_code_real, -- "beq", -- NDS32_RELAX_HINT_NONE, -- BR_RANGE_S16M, -- N32_RELAX_BR | N32_RELAX_JUMP -- }, -- { -- /* LONGJUMP6. */ -- BFD_RELOC_NDS32_HI20, -- "beq", -- NDS32_RELAX_HINT_NONE, -- BR_RANGE_U4G, -- N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP -- }, -- { -- /* LONGJUMP7. */ -- _dummy_first_bfd_reloc_code_real, -- "beqc", -- NDS32_RELAX_HINT_NONE, -- BR_RANGE_S16K, -- N32_RELAX_MOVI | N32_RELAX_BR -- }, -- { -- /* LOADSTORE ADDRESS. */ -- BFD_RELOC_NDS32_HI20, -- NULL, -- NDS32_RELAX_HINT_LA, -- BR_RANGE_U4G, -- N32_RELAX_SETHI | N32_RELAX_ORI -- }, -- { -- /* LOADSTORE ADDRESS. */ -- BFD_RELOC_NDS32_HI20, -- NULL, -- NDS32_RELAX_HINT_LS, -- BR_RANGE_U4G, -- N32_RELAX_SETHI | N32_RELAX_LSI -- }, -- {0, NULL, 0, 0 ,0} -+ { -+ /* LONGCALL4. */ -+ BFD_RELOC_NDS32_HI20, -+ "jal", -+ NDS32_RELAX_HINT_NONE, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL, -+ 0, -+ }, -+ { -+ /* LONGCALL5. */ -+ _dummy_first_bfd_reloc_code_real, -+ "bgezal", -+ NDS32_RELAX_HINT_NONE, -+ BR_RANGE_S16M, -+ N32_RELAX_BR | N32_RELAX_CALL, -+ 0, -+ }, -+ { -+ /* LONGCALL6. */ -+ BFD_RELOC_NDS32_HI20, -+ "bgezal", -+ NDS32_RELAX_HINT_NONE, -+ BR_RANGE_U4G, -+ N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL, -+ 0, -+ }, -+ { -+ /* LONGJUMP4. */ -+ BFD_RELOC_NDS32_HI20, -+ "j", -+ NDS32_RELAX_HINT_NONE, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP, -+ 0, -+ }, -+ { -+ /* LONGJUMP5. */ -+ /* There is two kinds of variation of LONGJUMP5. One of them -+ generate EMPTY relocation for converted INSN16 if needed. -+ But we don't distinguish them here. */ -+ _dummy_first_bfd_reloc_code_real, -+ "beq", -+ NDS32_RELAX_HINT_NONE, -+ BR_RANGE_S16M, -+ N32_RELAX_BR | N32_RELAX_JUMP, -+ 0, -+ }, -+ { -+ /* LONGJUMP6. */ -+ BFD_RELOC_NDS32_HI20, -+ "beq", -+ NDS32_RELAX_HINT_NONE, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP, -+ 0, -+ }, -+ { -+ /* LONGJUMP7. */ -+ _dummy_first_bfd_reloc_code_real, -+ "beqc", -+ NDS32_RELAX_HINT_NONE, -+ BR_RANGE_S16K, -+ N32_RELAX_MOVI | N32_RELAX_BR, -+ 0, -+ }, -+ { -+ /* LONGCALL (BAL|JR|LA symbol@PLT). */ -+ BFD_RELOC_NDS32_PLT_GOTREL_HI20, -+ NULL, -+ NDS32_RELAX_HINT_LA_PLT, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI, -+ N32_RELAX_ALU1 | N32_RELAX_CALL | N32_RELAX_JUMP, -+ }, -+ /* relative issue: #12566 */ -+ { -+ /* LA and Floating LSI. */ -+ BFD_RELOC_NDS32_HI20, -+ NULL, -+ NDS32_RELAX_HINT_LA_FLSI, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_LSI, -+ 0, -+ }, -+ /* relative issue: #11685 #11602 */ -+ { -+ /* load address / load-store (LALS). */ -+ BFD_RELOC_NDS32_HI20, -+ NULL, -+ NDS32_RELAX_HINT_LALS, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI, -+ N32_RELAX_ORI | N32_RELAX_LSI, -+ }, -+ { -+ /* setup $GP (_GLOBAL_OFFSET_TABLE_) */ -+ BFD_RELOC_NDS32_GOTPC_HI20, -+ NULL, -+ NDS32_RELAX_HINT_LALS, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI, -+ 0, -+ }, -+ { -+ /* GOT LA/LS (symbol@GOT) */ -+ BFD_RELOC_NDS32_GOT_HI20, -+ NULL, -+ NDS32_RELAX_HINT_LA_GOT, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI, -+ N32_RELAX_MEM, -+ }, -+ { -+ /* GOTOFF LA/LS (symbol@GOTOFF) */ -+ BFD_RELOC_NDS32_GOTOFF_HI20, -+ NULL, -+ NDS32_RELAX_HINT_LA_GOTOFF, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI, -+ N32_RELAX_ALU1 | N32_RELAX_MEM, /* | N32_RELAX_LSI, */ -+ }, -+ { -+ /* TLS LE LA|LS (@TPOFF) */ -+ BFD_RELOC_NDS32_TLS_LE_HI20, -+ NULL, -+ NDS32_RELAX_HINT_TLS_LE_LS, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI, -+ N32_RELAX_ALU1 | N32_RELAX_MEM, -+ }, -+ { -+ /* TLS IE LA */ -+ BFD_RELOC_NDS32_TLS_IE_HI20, -+ NULL, -+ NDS32_RELAX_HINT_TLS_IE_LA, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_LSI, -+ 0, -+ }, -+ { -+ /* TLS IE LS */ -+ BFD_RELOC_NDS32_TLS_IE_HI20, -+ NULL, -+ NDS32_RELAX_HINT_TLS_IE_LS, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_LSI | N32_RELAX_MEM, -+ 0, -+ }, -+ { -+ /* TLS IEGP LA */ -+ BFD_RELOC_NDS32_TLS_IEGP_HI20, -+ NULL, -+ NDS32_RELAX_HINT_TLS_IEGP_LA, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_MEM, -+ 0, -+ }, -+ { -+ /* TLS DESC LS */ -+ BFD_RELOC_NDS32_TLS_DESC_HI20, -+ NULL, -+ NDS32_RELAX_HINT_TLS_DESC_LS, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_ALU1 | N32_RELAX_CALL, -+ N32_RELAX_LSI | N32_RELAX_MEM, -+ }, -+ { -+ /* Jump-patch load address (LA). */ -+ BFD_RELOC_NDS32_ICT_HI20, -+ NULL, -+ NDS32_RELAX_HINT_ICT_LA, -+ BR_RANGE_U4G, -+ N32_RELAX_SETHI | N32_RELAX_ORI, -+ 0, -+ }, -+ /* last one */ -+ {0, NULL, 0, 0 ,0, 0} - }; - - /* Find the relaxation pattern according to instructions. */ -+/* TODO: refine this function with hash or so */ - - static bfd_boolean - nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, -@@ -4739,6 +5371,9 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, - case N32_OP6_MEM: - relax_type |= N32_RELAX_MEM; - break; -+ case N32_OP6_ALU1: -+ relax_type |= N32_RELAX_ALU1; -+ break; - case N32_OP6_ORI: - relax_type |= N32_RELAX_ORI; - break; -@@ -4760,6 +5395,8 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, - case N32_OP6_SWI: - case N32_OP6_LWC: - case N32_OP6_SWC: -+ case N32_OP6_LDC: -+ case N32_OP6_SDC: - relax_type |= N32_RELAX_LSI; - break; - case N32_OP6_JREG: -@@ -4784,16 +5421,20 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, - { - /* 2 byte instruction. Compare by opcode name because the opcode of - 2byte instruction is not regular. */ -- for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++) -+ int is_matched = 0; -+ for (i = 0; i < ARRAY_SIZE (check_insn); i++) - { - if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0) - { - relax_type |= N32_RELAX_BR; -+ is_matched += 1; - break; - } - } -- if (strcmp (pattern->opcode->opcode, "movi55") == 0) -- relax_type |= N32_RELAX_MOVI; -+ if (!is_matched) -+ { -+ relax_type |= N32_RELAX_16BIT; -+ } - } - pattern = pattern->next; - } -@@ -4801,23 +5442,35 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, - /* Analysis instruction flag to choose relaxation table. */ - while (map_ptr->insn_list != 0) - { -- if (map_ptr->insn_list == relax_type -- && (!hi_pattern -- || (hi_pattern->fixP -- && hi_pattern->fixP->fx_r_type == map_ptr->hi_type))) -+ struct nds32_hint_map *hint = map_ptr++; -+ enum nds32_insn_type must = hint->insn_list; -+ enum nds32_insn_type optional = hint->option_list; -+ enum nds32_insn_type extra; -+ -+ if (must != (must & relax_type)) -+ continue; -+ -+ extra = relax_type ^ must; -+ if (extra != (extra & optional)) -+ continue; -+ -+ if (!hi_pattern -+ || (hi_pattern->fixP -+ && hi_pattern->fixP->fx_r_type == hint->hi_type)) - { -- opc = map_ptr->opc; -- hint_type = map_ptr->hint_type; -- range = map_ptr->range; -+ opc = hint->opc; -+ hint_type = hint->hint_type; -+ range = hint->range; -+ map_ptr = hint; - break; - } -- map_ptr++; - } - - if (map_ptr->insn_list == 0) - { -- as_warn (_("Can not find match relax hint. Line: %d"), -- relocs_pattern->frag->fr_line); -+ if (!nds32_pic) -+ as_warn (_("Can not find match relax hint. line : %d"), -+ relocs_pattern->fixP->fx_line); - return FALSE; - } - -@@ -4876,12 +5529,14 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, - /* Because there are a lot of variant of load-store, check - all these type here. */ - --#define CLEAN_REG(insn) ((insn) & 0xff0003ff) -+#define CLEAN_REG(insn) ((insn) & 0xfe0003ff) -+#define GET_OPCODE(insn) ((insn) & 0xfe000000) -+ - static bfd_boolean - nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq) - { - const char *check_insn[] = -- { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" }; -+ { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8", "jral5" }; - uint32_t insn = opcode->value; - unsigned int i; - -@@ -4897,22 +5552,23 @@ nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq) - if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI) - || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI) - || insn == OP6 (LWI) || insn == OP6 (SWI) -- || insn == OP6 (LWC) || insn == OP6 (SWC)) -- return TRUE; -+ || insn == OP6 (LWC) || insn == OP6 (SWC) -+ || insn == OP6 (LDC) || insn == OP6 (SDC)) -+ return TRUE; - break; - case OP6 (BR2): - /* This is for LONGCALL5 and LONGCALL6. */ - if (insn == OP6 (BR2)) -- return TRUE; -+ return TRUE; - break; - case OP6 (BR1): - /* This is for LONGJUMP5 and LONGJUMP6. */ - if (opcode->isize == 4 - && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3))) -- return TRUE; -+ return TRUE; - else if (opcode->isize == 2) - { -- for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++) -+ for (i = 0; i < ARRAY_SIZE (check_insn); i++) - if (strcmp (opcode->opcode, check_insn[i]) == 0) - return TRUE; - } -@@ -4920,8 +5576,28 @@ nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq) - case OP6 (MOVI): - /* This is for LONGJUMP7. */ - if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0) -- return TRUE; -+ return TRUE; -+ break; -+ case OP6 (MEM): -+ if (OP6 (MEM) == GET_OPCODE (insn)) -+ return TRUE; - break; -+ case OP6 (JREG): -+ /* bit 24: N32_JI_JAL */ /* feed me! */ -+ if ((insn & ~(N32_BIT (24))) == JREG (JRAL)) -+ return TRUE; -+ break; -+ default: -+ if (opcode->isize == 2) -+ { -+ for (i = 0; i < ARRAY_SIZE (check_insn); i++) -+ if (strcmp (opcode->opcode, check_insn[i]) == 0) -+ return TRUE; -+ -+ if ((strcmp (opcode->opcode, "add5.pc") == 0) || -+ (strcmp (opcode->opcode, "add45") == 0)) -+ return TRUE; -+ } - } - return FALSE; - } -@@ -4929,7 +5605,7 @@ nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq) - /* Append relax relocation for link time relaxing. */ - - static void --nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) -+nds32_elf_append_relax_relocs (const char *key, void *value) - { - struct nds32_relocs_pattern *relocs_pattern = - (struct nds32_relocs_pattern *) value; -@@ -4942,7 +5618,7 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) - struct nds32_relax_hint_table hint_info; - nds32_relax_fixup_info_t *hint_fixup, *fixup_now; - size_t fixup_size; -- offsetT branch_offset; -+ offsetT branch_offset, hi_branch_offset = 0; - fixS *fixP; - int range, offset; - unsigned int ptr_offset, hint_count, relax_code_size, count = 0; -@@ -4963,6 +5639,7 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) - if (pattern_now->opcode->value == OP6 (SETHI)) - { - hi_sym = pattern_now->sym; -+ hi_branch_offset = pattern_now->fixP->fx_offset; - break; - } - pattern_now = pattern_now->next; -@@ -4979,15 +5656,36 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) - relax_code_size = hint_info.relax_code_size; - pattern_now = relocs_pattern; - -+#ifdef NDS32_LINUX_TOOLCHAIN -+ /* prepare group relocation ID (number). */ -+ long group_id = 0; -+ if (key) -+ { -+ /* convert .relax_hint key to number */ -+ errno = 0; -+ group_id = strtol (key, NULL, 10); -+ if ((errno == ERANGE && (group_id == LONG_MAX || group_id == LONG_MIN)) -+ || (errno != 0 && group_id == 0)) -+ { -+ as_bad (_("Internal error: .relax_hint KEY is not a number!")); -+ goto restore; -+ } -+ } -+#endif -+ - /* Insert relaxation. */ - exp.X_op = O_symbol; - -+ /* for each instruction in the hint group */ - while (pattern_now) - { -- /* Choose the match fixup by instruction. */ -+ if (count >= relax_code_size / 4) -+ count = 0; -+ /* Choose the match fix-up by instruction. */ - code_insn = CLEAN_REG (*(code_seq + count)); - if (!nds32_match_hint_insn (pattern_now->opcode, code_insn)) - { -+ /* try search from head again */ - count = 0; - code_insn = CLEAN_REG (*(code_seq + count)); - -@@ -4996,8 +5694,11 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) - count++; - if (count >= relax_code_size / 4) - { -- as_bad (_("Internal error: Relax hint error. %s: %x"), -- now_seg->name, pattern_now->opcode->value); -+ as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"), -+ key, -+ now_seg->name, -+ pattern_now->opcode->opcode, -+ pattern_now->opcode->value); - goto restore; - } - code_insn = CLEAN_REG (*(code_seq + count)); -@@ -5024,7 +5725,7 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) - } - fixup_size = fixup_now->size; - -- /* Insert all fixup. */ -+ /* Insert all fix-up. */ - while (fixup_size != 0 && fixup_now->offset == offset) - { - /* Set the real instruction size in element. */ -@@ -5093,7 +5794,108 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) - { - /* For EMPTY relocation save the true symbol. */ - exp.X_add_symbol = hi_sym; -- exp.X_add_number = branch_offset; -+ exp.X_add_number = hi_branch_offset; -+ } -+ else if (NDS32_SYM_DESC_MEM & fixup_now->ramp) -+ { -+ /* do the same as NDS32_SYM */ -+ exp.X_add_symbol = hi_sym; -+ exp.X_add_number = hi_branch_offset; -+ -+ /* extra to NDS32_SYM */ -+ /* detect if DESC_FUNC relax type do apply */ -+ if ((REG_GP == N32_RA5 (pattern_now->insn)) -+ || (REG_GP == N32_RB5 (pattern_now->insn))) -+ { -+ fixP = fix_new_exp (fragP, where - fragP->fr_literal, -+ fixup_size, &exp, pcrel, -+ BFD_RELOC_NDS32_TLS_DESC_FUNC); -+ fixP->fx_addnumber = fixP->fx_offset; -+ -+ fixup_size = 0; -+ } -+ /* else do as usual */ -+ } -+ else if (fixup_now->ramp & NDS32_PTR_PATTERN) -+ { -+ /* find out PTR_RESOLVED code pattern */ -+ nds32_relax_fixup_info_t *next_fixup = fixup_now + 1; -+ uint32_t resolved_pattern = 0; -+ while (next_fixup->offset) -+ { -+ if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED) -+ { -+ uint32_t new_pattern = code_seq[next_fixup->offset >> 2]; -+ if (!resolved_pattern) -+ resolved_pattern = new_pattern; -+ else if (new_pattern != resolved_pattern) -+ { -+ as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED patterns are not supported yet!")); -+ break; -+ } -+ } -+ ++next_fixup; -+ } -+ -+ /* find matched code and insert fix-ups */ -+ struct nds32_relocs_pattern *next_pattern = pattern_now->next; -+ /* This relocation has to point to another instruction. Make -+ sure each resolved relocation has to be pointed. */ -+ /* All instruction in relax_table should be 32-bit. */ -+ while (next_pattern) -+ { -+ uint32_t cur_pattern = GET_OPCODE (next_pattern->opcode->value); -+ if (cur_pattern == resolved_pattern) -+ { -+ ptr_offset = next_pattern->where -+ - next_pattern->frag->fr_literal; -+ exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset, -+ next_pattern->frag); -+ exp.X_add_number = 0; -+ fixP = fix_new_exp (fragP, where - fragP->fr_literal, -+ fixup_size, &exp, 0, -+ fixup_now->r_type); -+ fixP->fx_addnumber = fixP->fx_offset; -+ } -+ next_pattern = next_pattern->next; -+ } -+ -+ fixup_size = 0; -+ } -+ else if (fixup_now->ramp & NDS32_PTR_MULTIPLE) -+ { -+ /* find each PTR_RESOLVED pattern after PTR */ -+ nds32_relax_fixup_info_t *next_fixup = fixup_now + 1; -+ while (next_fixup->offset) -+ { -+ if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED) -+ { -+ uint32_t pattern = code_seq[next_fixup->offset >> 2]; -+ /* find matched code to insert fix-ups */ -+ struct nds32_relocs_pattern *next_insn = pattern_now->next; -+ while (next_insn) -+ { -+ uint32_t insn_pattern = GET_OPCODE( -+ next_insn->opcode->value); -+ if (insn_pattern == pattern) -+ { -+ ptr_offset = next_insn->where -+ - next_insn->frag->fr_literal; -+ exp.X_add_symbol = symbol_temp_new ( -+ now_seg, ptr_offset, next_insn->frag); -+ exp.X_add_number = 0; -+ fixP = fix_new_exp (fragP, -+ where - fragP->fr_literal, -+ fixup_size, &exp, 0, -+ fixup_now->r_type); -+ fixP->fx_addnumber = fixP->fx_offset; -+ } -+ next_insn = next_insn->next; -+ } -+ } -+ ++next_fixup; -+ } -+ fixup_size = 0; - } - else - { -@@ -5110,6 +5912,19 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) - fixup_now++; - fixup_size = fixup_now->size; - } -+ -+#ifdef NDS32_LINUX_TOOLCHAIN -+ /* Insert group relocation for each relax hint. */ -+ if (key) -+ { -+ exp.X_add_symbol = hi_sym; /* for eyes only */ -+ exp.X_add_number = group_id; -+ fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size, -+ &exp, pcrel, BFD_RELOC_NDS32_GROUP); -+ fixP->fx_addnumber = fixP->fx_offset; -+ } -+#endif -+ - if (count < relax_code_size / 4) - count++; - pattern_now = pattern_now->next; -@@ -5120,6 +5935,19 @@ restore: - frchain_now = frchain_bak; - } - -+static void -+nds32_str_tolower (const char *src, char *dest) -+{ -+ unsigned int i, len; -+ -+ len = strlen (src); -+ -+ for (i = 0; i < len; i++) -+ *(dest + i) = TOLOWER (*(src + i)); -+ -+ *(dest + i) = '\0'; -+} -+ - /* Check instruction if it can be used for the baseline. */ - - static bfd_boolean -@@ -5127,6 +5955,28 @@ nds32_check_insn_available (struct nds32_asm_insn insn, const char *str) - { - int attr = insn.attr & ATTR_ALL; - static int baseline_isa = 0; -+ char *s; -+ -+ s = alloca (strlen (str) + 1); -+ nds32_str_tolower (str, s); -+ if (verbatim && inline_asm -+ && (((insn.opcode->value == ALU2 (MTUSR) -+ || insn.opcode->value == ALU2 (MFUSR)) -+ && (strstr (s, "lc") -+ || strstr (s, "le") -+ || strstr (s, "lb"))) -+ || (insn.attr & NASM_ATTR_ZOL))) -+ { -+ as_bad (_("Not support instruction %s in verbatim."), str); -+ return FALSE; -+ } -+ -+ if (!enable_16bit && insn.opcode->isize == 2) -+ { -+ as_bad (_("16-bit instruction is disabled: %s."), str); -+ return FALSE; -+ } -+ - /* No isa setting or all isa can use. */ - if (attr == 0 || attr == ATTR_ALL) - return TRUE; -@@ -5150,28 +6000,70 @@ nds32_check_insn_available (struct nds32_asm_insn insn, const char *str) - - if ((baseline_isa & attr) == 0) - { -- as_bad (_("Instruction %s not supported in the baseline."), str); -+ as_bad (_("Not support instruction %s in the baseline."), str); - return FALSE; - } - return TRUE; - } - -+/* Clear security and insert relocation. */ -+static void -+nds32_set_crc (fragS *fragP, struct nds32_asm_insn *insn, char *out) -+{ -+ expressionS exp; -+ -+ /* The security region begin. */ -+ if (strcmp (insn->opcode->opcode, "isps") == 0) -+ { -+ exp.X_op = O_symbol; -+ exp.X_add_symbol = abs_section_sym; -+ /* Meet the new crc in previos crc region. */ -+ if (crcing == TRUE) -+ { -+ exp.X_add_number = NDS32_SECURITY_RESTART; -+ fix_new_exp (fragP, out - fragP->fr_literal, 0, &exp, -+ 0, BFD_RELOC_NDS32_SECURITY_16); -+ } -+ crcing = TRUE; -+ /* For security used only. */ -+ exp.X_add_number = NDS32_SECURITY_START; -+ fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, -+ &exp, 0 /* pcrel */, BFD_RELOC_NDS32_SECURITY_16); -+ } -+ /* Turn off security region when meeting branch. */ -+ else if (crcing && ((insn->attr & NASM_ATTR_BRANCH) -+ || insn->opcode->value == MISC (SYSCALL) -+ || insn->opcode->value == MISC (TRAP) -+ || insn->opcode->value == MISC (TEQZ) -+ || insn->opcode->value == MISC (TNEZ) -+ || insn->opcode->value == MISC (IRET) -+ || insn->attr & NASM_ATTR_IFC_EXT)) -+ { -+ crcing = FALSE; -+ exp.X_op = O_symbol; -+ exp.X_add_symbol = abs_section_sym; -+ exp.X_add_number = NDS32_SECURITY_END; -+ fix_new_exp (fragP, out - fragP->fr_literal, 0, &exp, -+ 0, BFD_RELOC_NDS32_SECURITY_16); -+ } -+} -+ - /* Stub of machine dependent. */ - - void - md_assemble (char *str) - { - struct nds32_asm_insn insn; -- expressionS expr; - char *out; - struct nds32_pseudo_opcode *popcode; - const struct nds32_field *fld = NULL; - fixS *fixP; - uint16_t insn_16; - struct nds32_relocs_pattern *relocs_temp; -- expressionS *pexp; -+ struct nds32_relocs_group *group_temp; - fragS *fragP; - int label = label_exist; -+ static bfd_boolean pseudo_hint = FALSE; - - popcode = nds32_lookup_pseudo_opcode (str); - /* Note that we need to check 'verbatim' and -@@ -5180,11 +6072,23 @@ md_assemble (char *str) - need to perform pseudo instruction expansion/transformation. */ - if (popcode && !(verbatim && popcode->physical_op)) - { -+ /* Pseudo instruction is with relax_hint. */ -+ if (relaxing) -+ pseudo_hint = TRUE; - pseudo_opcode = TRUE; - nds32_pseudo_opcode_wrapper (str, popcode); - pseudo_opcode = FALSE; -+ pseudo_hint = FALSE; - nds32_elf_append_relax_relocs (NULL, relocs_list); - -+ /* Free relax_hint group list. */ -+ while (nds32_relax_hint_current) -+ { -+ group_temp = nds32_relax_hint_current->next; -+ free (nds32_relax_hint_current); -+ nds32_relax_hint_current = group_temp; -+ } -+ - /* Free pseudo list. */ - relocs_temp = relocs_list; - while (relocs_temp) -@@ -5193,12 +6097,11 @@ md_assemble (char *str) - free (relocs_temp); - relocs_temp = relocs_list; - } -- - return; - } - - label_exist = 0; -- insn.info = & expr; -+ insn.info = (expressionS *) alloca (sizeof (expressionS)); - asm_desc.result = NASM_OK; - nds32_assemble (&asm_desc, &insn, str); - -@@ -5235,11 +6138,13 @@ md_assemble (char *str) - - /* Make sure the beginning of text being 2-byte align. */ - nds32_adjust_label (1); -+ add_mapping_symbol (MAP_CODE, 0, 0); - fld = insn.field; - /* Try to allocate the max size to guarantee relaxable same branch - instructions in the same fragment. */ - frag_grow (NDS32_MAXCHAR); - fragP = frag_now; -+ - if (fld && (insn.attr & NASM_ATTR_BRANCH) - && (pseudo_opcode || (insn.opcode->value != INSN_JAL - && insn.opcode->value != INSN_J)) -@@ -5247,7 +6152,7 @@ md_assemble (char *str) - { - /* User assembly code branch relax for it. */ - /* If fld is not NULL, it is a symbol. */ -- /* Branch must relax to proper pattern in user assembly code exclude -+ /* Branch msut relax to proper pattern in user assembly code exclude - J and JAL. Keep these two in original type for users which wants - to keep their size be fixed. In general, assembler does not convert - instruction generated by compiler. But jump instruction may be -@@ -5257,8 +6162,8 @@ md_assemble (char *str) - /* Get branch range type. */ - dwarf2_emit_insn (0); - enum nds32_br_range range_type; -+ expressionS *pexp = insn.info; - -- pexp = insn.info; - range_type = get_range_type (fld); - - out = frag_var (rs_machine_dependent, NDS32_MAXCHAR, -@@ -5274,6 +6179,12 @@ md_assemble (char *str) - else if (insn.opcode->isize == 2) - bfd_putb16 (insn.insn, out); - fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH; -+ -+ if (fld->bitsize == 24 && fld->shift == 1 -+ && pexp->X_md == BFD_RELOC_NDS32_ICT) -+ fragP->tc_frag_data.flag |= NDS32_FRAG_ICT_BRANCH; -+ -+ nds32_set_crc (fragP, &insn, out); - return; - /* md_convert_frag will insert relocations. */ - } -@@ -5284,7 +6195,7 @@ md_assemble (char *str) - && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL)))) - { - /* Record this one is relaxable. */ -- pexp = insn.info; -+ expressionS *pexp = insn.info; - dwarf2_emit_insn (0); - if (fld) - { -@@ -5304,7 +6215,7 @@ md_assemble (char *str) - fragP->tc_frag_data.insn = insn.insn; - fragP->fr_fix += 2; - -- /* In original, we don't relax the instruction with label on it, -+ /* In original, we don't relax the instrucion with label on it, - but this may cause some redundant nop16. Therefore, tag this - relaxable instruction and relax it carefully. */ - if (label) -@@ -5314,6 +6225,7 @@ md_assemble (char *str) - bfd_putb16 (insn_16, out); - else if (insn.opcode->isize == 2) - bfd_putb16 (insn.insn, out); -+ nds32_set_crc (fragP, &insn, out); - return; - } - else if ((verbatim || !relaxing) && optimize && label) -@@ -5322,7 +6234,7 @@ md_assemble (char *str) - expressionS exp; - out = frag_var (rs_machine_dependent, insn.opcode->isize, - 0, 0, NULL, 0, NULL); -- /* If this instruction is branch target, it is not relaxable. */ -+ /* If this insturction is branch target, it is not relaxable. */ - fragP->tc_frag_data.flag = NDS32_FRAG_LABEL; - fragP->tc_frag_data.opcode = insn.opcode; - fragP->tc_frag_data.insn = insn.insn; -@@ -5343,18 +6255,20 @@ md_assemble (char *str) - - if (insn.opcode->isize == 4) - bfd_putb32 (insn.insn, out); -- if (insn.opcode->isize == 2) -+ else if (insn.opcode->isize == 2) - bfd_putb16 (insn.insn, out); - - dwarf2_emit_insn (insn.opcode->isize); - - /* Compiler generating code and user assembly pseudo load-store, insert - fixup here. */ -- pexp = insn.info; -+ expressionS *pexp = insn.info; - fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn); - /* Build relaxation pattern when relaxing is enable. */ - if (relaxing) -- nds32_elf_build_relax_relation (fixP, pexp, out, insn.opcode, fragP, fld); -+ nds32_elf_build_relax_relation (fixP, pexp, out, &insn, fragP, fld, -+ pseudo_hint); -+ nds32_set_crc (fragP, &insn, out); - } - - /* md_macro_start */ -@@ -5402,7 +6316,7 @@ md_section_align (segT segment, valueT size) - { - int align = bfd_get_section_alignment (stdoutput, segment); - -- return ((size + (1 << align) - 1) & -(1 << align)); -+ return ((size + (1 << align) - 1) & ((valueT) -1 << align)); - } - - /* GAS will call this function when a symbol table lookup fails, before it -@@ -5441,6 +6355,7 @@ nds32_calc_branch_offset (segT segment, fragS *fragP, - { - /* Calculate symbol-to-instruction offset. */ - branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset; -+ - /* If the destination symbol is beyond current frag address, - STRETCH will take effect to symbol's position. */ - if (S_GET_VALUE (branch_symbol) > fragP->fr_address) -@@ -5464,31 +6379,31 @@ nds32_convert_to_range_type (long offset) - { - enum nds32_br_range range_type; - -- if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */ -+ if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */ - range_type = BR_RANGE_S256; -- else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */ -+ else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */ - range_type = BR_RANGE_S16K; -- else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */ -+ else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */ - range_type = BR_RANGE_S64K; -- else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */ -+ else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */ - range_type = BR_RANGE_S16M; -- else /* 4G bytes */ -+ else /* 4G bytes */ - range_type = BR_RANGE_U4G; - - return range_type; - } - --/* Set instruction register mask. */ -+/* Set insntruction register mask. */ - - static void - nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn, - uint32_t ori_insn, int range) - { -- nds32_cond_field_t *cond_fields = relax_info->cond_field; -+ nds32_cond_field_t *cond_fields; -+ cond_fields = relax_info->cond_field; - nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range]; - uint32_t mask; - int i = 0; -- - /* The instruction has conditions. Collect condition values. */ - while (code_seq_cond[i].bitmask != 0) - { -@@ -5525,24 +6440,45 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP, - int insn_size; - int code_seq_offset; - -- /* Replace with gas_assert (fragP->fr_symbol != NULL); */ -+ /* Replace with gas_assert (fragP->fr_symbol != NULL); */ - if (fragP->fr_symbol == NULL) - return adjust; - -- /* If frag_var is not enough room, the previous frag is fr_full and with -+ /* If frag_var is not enough room, the previos frag is fr_full and with - opcode. The new one is rs_dependent but without opcode. */ - if (opcode == NULL) - return adjust; - -+ /* Use U4G mode for b and bal in verbatim mode because lto may combine -+ functions into a file. And order the file in the last when linking. -+ Once there is multiple definition, the same function will be kicked. -+ This may cause relocation truncated error. */ -+ if (verbatim && !nds32_pic -+ && (strcmp (opcode->opcode, "j") == 0 -+ || strcmp (opcode->opcode, "jal") == 0)) -+ { -+ fragP->fr_subtype = BR_RANGE_U4G; -+ if (init) -+ return 8; -+ else -+ return 0; -+ } -+ - relax_info = hash_find (nds32_relax_info_hash, opcode->opcode); - - if (relax_info == NULL) - return adjust; - - if (init) -- branch_range_type = relax_info->br_range; -+ { -+ branch_range_type = relax_info->br_range; -+ i = BR_RANGE_S256; -+ } - else -- branch_range_type = fragP->fr_subtype; -+ { -+ branch_range_type = fragP->fr_subtype; -+ i = branch_range_type; -+ } - - offset = nds32_calc_branch_offset (segment, fragP, stretch, - relax_info, branch_range_type); -@@ -5551,15 +6487,21 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP, - - /* If actual range is equal to instruction jump range, do nothing. */ - if (real_range_type == branch_range_type) -- return adjust; -+ { -+ fragP->fr_subtype = real_range_type; -+ return adjust; -+ } - - /* Find out proper relaxation code sequence. */ -- for (i = BR_RANGE_S256; i < BR_RANGE_NUM; i++) -+ for (; i < BR_RANGE_NUM; i++) - { - if (real_range_type <= (unsigned int) i) - { - if (init) - diff = relax_info->relax_code_size[i] - opcode->isize; -+ else if (real_range_type < (unsigned int) i) -+ diff = relax_info->relax_code_size[real_range_type] -+ - relax_info->relax_code_size[branch_range_type]; - else - diff = relax_info->relax_code_size[i] - - relax_info->relax_code_size[branch_range_type]; -@@ -5592,7 +6534,7 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP, - } - - /* Update fr_subtype to new NDS32_BR_RANGE. */ -- fragP->fr_subtype = i; -+ fragP->fr_subtype = real_range_type; - break; - } - } -@@ -5631,19 +6573,19 @@ nds32_get_align (addressT address, int align) - { - addressT mask, new_address; - -- mask = ~((~0U) << align); -+ mask = ~((addressT) (~0) << align); - new_address = (address + mask) & (~mask); - return (new_address - address); - } - - /* Check the prev_frag is legal. */ - static void --invalid_prev_frag (fragS * fragP, fragS **prev_frag) -+invalid_prev_frag (fragS * fragP, fragS **prev_frag, bfd_boolean relax) - { - addressT address; - fragS *frag_start = *prev_frag; - -- if (!frag_start) -+ if (!frag_start || !relax) - return; - - if (frag_start->last_fr_address >= fragP->last_fr_address) -@@ -5659,13 +6601,13 @@ invalid_prev_frag (fragS * fragP, fragS **prev_frag) - || frag_t->fr_type == rs_align_code - || frag_t->fr_type == rs_align_test) - { -- /* Relax instruction can not walk across label. */ -+ /* Relax instruction can not walk across lable. */ - if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL) - { - prev_frag = NULL; - return; - } -- /* Relax previous relaxable to align rs_align frag. */ -+ /* Relax previos relaxable to align rs_align frag. */ - address = frag_t->fr_address + frag_t->fr_fix; - addressT offset = nds32_get_align (address, (int) frag_t->fr_offset); - if (offset & 0x2) -@@ -5711,7 +6653,7 @@ nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED) - static fragS *prev_frag = NULL; - int adjust = 0; - -- invalid_prev_frag (fragP, &prev_frag); -+ invalid_prev_frag (fragP, &prev_frag, TRUE); - - if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH) - adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0); -@@ -5720,8 +6662,8 @@ nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED) - if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE - && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0) - /* Here is considered relaxed case originally. But it may cause -- an endless loop when relaxing. Once the instruction is relaxed, -- it can not be undone. */ -+ unendless loop when relaxing. Once the instruction is relaxed, -+ it can not be undo. */ - prev_frag = fragP; - - return adjust; -@@ -5744,11 +6686,11 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) - 1. relax for branch - 2. relax for 32-bits to 16-bits */ - -- /* Save previous relaxable frag. */ -+ /* Save previos relaxable frag. */ - static fragS *prev_frag = NULL; - int adjust = 0; - -- invalid_prev_frag (fragP, &prev_frag); -+ invalid_prev_frag (fragP, &prev_frag, FALSE); - - if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH) - adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1); -@@ -5798,12 +6740,14 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) - nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX]; - /* Save the 1st instruction is converted to 16 bit or not. */ - unsigned int branch_size; -+ bfd_boolean is_ict_sym; -+ enum bfd_reloc_code_real final_r_type; - -- /* Replace with gas_assert (branch_symbol != NULL); */ -+ /* Replace with gas_assert (branch_symbol != NULL); */ - if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)) - return; - -- /* If frag_var is not enough room, the previous frag is fr_full and with -+ /* If frag_var is not enough room, the previos frag is fr_full and with - opcode. The new one is rs_dependent but without opcode. */ - if (opcode == NULL) - return; -@@ -5872,6 +6816,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) - /* Branch instruction adjust and append relocations. */ - relax_info = hash_find (nds32_relax_info_hash, opcode->opcode); - -+ is_ict_sym = fragP->tc_frag_data.flag & NDS32_FRAG_ICT_BRANCH; -+ - if (relax_info == NULL) - return; - -@@ -5902,8 +6848,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) - /* Fill in frag. */ - i = 0; - k = 0; -- offset = 0; /* code_seq offset */ -- buf_offset = 0; /* fr_buffer offset */ -+ offset = 0; /* code_seq offset */ -+ buf_offset = 0; /* fr_buffer offset */ - while (offset < code_size) - { - insn = code_seq[i]; -@@ -5921,7 +6867,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) - origin_insn, branch_range_type); - - /* Try to convert to 16-bits instruction. Currently, only the first -- instruction in pattern can be converted. EX: bnez sethi ori jr, -+ insntruction in pattern can be converted. EX: bnez sethi ori jr, - only bnez can be converted to 16 bit and ori can't. */ - - while (fixup_info[k].size != 0 -@@ -5978,9 +6924,20 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) - - if (fixup_info[i].r_type != 0) - { -+ final_r_type = fixup_info[i].r_type; -+ -+ /* Convert reloc type to ICT style if this frag is -+ handle for ICT symbol. */ -+ if (is_ict_sym && final_r_type == BFD_RELOC_NDS32_HI20) -+ final_r_type = BFD_RELOC_NDS32_ICT_HI20; -+ else if (is_ict_sym && final_r_type == BFD_RELOC_NDS32_LO12S0_ORI) -+ final_r_type = BFD_RELOC_NDS32_ICT_LO12; -+ else if (is_ict_sym && fixup_info[i].ramp & NDS32_HINT) -+ continue; -+ - fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset, - fixup_size, &exp, pcrel, -- fixup_info[i].r_type); -+ final_r_type); - fixP->fx_addnumber = fixP->fx_offset; - } - } -@@ -6003,7 +6960,7 @@ nds32_relaxable_section (asection *sec) - && strcmp (sec->name, ".eh_frame") != 0); - } - --/* TC_FORCE_RELOCATION */ -+/* TC_FORCE_RELOCATION */ - int - nds32_force_relocation (fixS * fix) - { -@@ -6041,8 +6998,8 @@ nds32_force_relocation (fixS * fix) - && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy)); - case BFD_RELOC_64: - if (fix->fx_subsy) -- as_bad ("Double word for difference between two symbols " -- "is not supported across relaxation."); -+ as_bad ("Double word for difference between two symbols is not " -+ "supported across relaxation."); - default: - ; - } -@@ -6202,14 +7159,16 @@ nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, - fixS *fixp; - - seginfo = seg_info (sec); -+ if (symbol_find ("_INDIRECT_CALL_TABLE_BASE_")) -+ ict_exist = TRUE; - if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0) - return; -- /* If there is no relocation and relax is disabled, it is not necessary to -- insert R_NDS32_RELAX_ENTRY for linker do EX9 or IFC optimization. */ -+ - for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next) - if (!fixp->fx_done) - break; -- if (!fixp && !enable_relax_ex9 && !verbatim) -+ -+ if (!fixp && !verbatim && (!ict_exist || ict_flag == ICT_NONE)) - return; - - subseg_change (sec, 0); -@@ -6217,21 +7176,21 @@ nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, - /* Set RELAX_ENTRY flags for linker. */ - fragP = seginfo->frchainP->frch_root; - exp.X_op = O_symbol; -- exp.X_add_symbol = section_symbol (sec); -+ exp.X_add_symbol = abs_section_sym; - exp.X_add_number = 0; - if (!enable_relax_relocs) - exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG; - else - { - /* These flags are only enabled when global relax is enabled. -- Maybe we can check DISABLE_RELAX_FLAG at link-time, -+ Maybe we can check DISABLE_RELAX_FLAG at linke-time, - so we set them anyway. */ -- if (enable_relax_ex9) -- exp.X_add_number |= R_NDS32_RELAX_ENTRY_EX9_FLAG; -- if (enable_relax_ifc) -- exp.X_add_number |= R_NDS32_RELAX_ENTRY_IFC_FLAG; - if (verbatim) - exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG; -+ if (ict_exist && ict_flag == ICT_SMALL) -+ exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_SMALL; -+ else if (ict_exist && ict_flag == ICT_LARGE) -+ exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_LARGE; - } - if (optimize) - exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG; -@@ -6282,9 +7241,28 @@ nds32_elf_insert_final_frag (void) - } - } - -+static void -+nds32_create_section_compatible_abi (void) -+{ -+ segT comp_section = subseg_new (".note.v2abi_compatible", 0); -+ bfd_set_section_flags (stdoutput, comp_section, -+ SEC_READONLY | SEC_DATA | SEC_EXCLUDE); -+ -+ /* Set content to .v2abi_compatible section. */ -+ now_seg = comp_section; -+ frag_grow (NDS32_MAXCHAR); -+ char *out = frag_more (4); -+ if (compatible_abi) -+ bfd_putb32 ((bfd_vma) 1, out); -+ else -+ bfd_putb32 ((bfd_vma) 0, out); -+} -+ - void - md_end (void) - { -+ if (compatible_abi) -+ nds32_create_section_compatible_abi (); - nds32_elf_insert_final_frag (); - nds32_elf_analysis_relax_hint (); - bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL); -@@ -6390,6 +7368,8 @@ nds32_fix_adjustable (fixS *fixP) - case BFD_RELOC_NDS32_LONGJUMP5: - case BFD_RELOC_NDS32_LONGJUMP6: - case BFD_RELOC_NDS32_LONGJUMP7: -+ case BFD_RELOC_NDS32_10IFCU_PCREL: -+ case BFD_RELOC_NDS32_17IFC_PCREL: - return 1; - default: - return 0; -@@ -6407,7 +7387,7 @@ elf_nds32_final_processing (void) - && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))) - { - /* Since only FPU_COM instructions are used and no other FPU instructions -- are used. The nds32_elf_flags will be decided by the enabled options -+ are used. The nds32_elf_flags will be decided by the enabled options - by command line or default configuration. */ - if (nds32_fpu_dp_ext || nds32_fpu_sp_ext) - { -@@ -6430,9 +7410,6 @@ elf_nds32_final_processing (void) - nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT); - } - -- if (nds32_pic) -- nds32_elf_flags |= E_NDS32_HAS_PIC; -- - if (nds32_gpr16) - nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS; - -@@ -6440,7 +7417,7 @@ elf_nds32_final_processing (void) - elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags; - } - --/* Implement md_apply_fix. Apply the fix-up or transform the fix-up for -+/* Implement md_apply_fix. Apply the fix-up or tranform the fix-up for - later relocation generation. */ - - void -@@ -6463,14 +7440,10 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) - fixP->fx_addnumber = value; - fixP->tc_fix_data = NULL; - -- /* Transform specific relocations here for later relocation generation. -- Tag data here for ex9 relaxation and tag tls data for linker. */ -+ /* Tranform specific relocations here for later relocation generation. -+ Tag tls data here for linker. */ - switch (fixP->fx_r_type) - { -- case BFD_RELOC_NDS32_DATA: -- if (!enable_relax_ex9) -- fixP->fx_done = 1; -- break; - case BFD_RELOC_NDS32_TPOFF: - case BFD_RELOC_NDS32_TLS_LE_HI20: - case BFD_RELOC_NDS32_TLS_LE_LO12: -@@ -6479,6 +7452,12 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) - case BFD_RELOC_NDS32_GOTTPOFF: - case BFD_RELOC_NDS32_TLS_IE_HI20: - case BFD_RELOC_NDS32_TLS_IE_LO12S2: -+ case BFD_RELOC_NDS32_TLS_DESC_HI20: -+ case BFD_RELOC_NDS32_TLS_DESC_LO12: -+ case BFD_RELOC_NDS32_TLS_IE_LO12: -+ case BFD_RELOC_NDS32_TLS_IEGP_HI20: -+ case BFD_RELOC_NDS32_TLS_IEGP_LO12: -+ case BFD_RELOC_NDS32_TLS_IEGP_LO12S2: - S_SET_THREAD_LOCAL (fixP->fx_addsy); - break; - default: -@@ -6519,7 +7498,7 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) - ---- 8< ---- 8< ---- 8< ---- 8< ---- - - We use a single relocation entry for this expression. -- * The initial distance value is stored directly in that location -+ * The initial distance value is stored direcly in that location - specified by r_offset (i.e., foo in this example.) - * The begin of the region, i.e., .LBEGIN, is specified by - r_info/R_SYM and r_addend, e.g., .text + 0x32. -@@ -6605,7 +7584,6 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) - break; - case BFD_RELOC_64: - md_number_to_chars (where, value, 8); -- break; - default: - as_bad_where (fixP->fx_file, fixP->fx_line, - _("Internal error: Unknown fixup type %d (`%s')"), -@@ -6624,9 +7602,9 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) - arelent *reloc; - bfd_reloc_code_real_type code; - -- reloc = XNEW (arelent); -+ reloc = (arelent *) xmalloc (sizeof (arelent)); - -- reloc->sym_ptr_ptr = XNEW (asymbol *); -+ reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); - *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); - reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; - -@@ -6661,13 +7639,15 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) - return reloc; - } - --struct suffix_name suffix_table[] = -+static struct suffix_name suffix_table[] = - { -- {"GOTOFF", BFD_RELOC_NDS32_GOTOFF, 1}, -- {"GOT", BFD_RELOC_NDS32_GOT20, 1}, -- {"TPOFF", BFD_RELOC_NDS32_TPOFF, 0}, -- {"PLT", BFD_RELOC_NDS32_25_PLTREL, 1}, -- {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF, 0} -+ {"GOTOFF", BFD_RELOC_NDS32_GOTOFF}, -+ {"GOT", BFD_RELOC_NDS32_GOT20}, -+ {"TPOFF", BFD_RELOC_NDS32_TPOFF}, -+ {"PLT", BFD_RELOC_NDS32_25_PLTREL}, -+ {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF}, -+ {"TLSDESC", BFD_RELOC_NDS32_TLS_DESC}, -+ {"ICT", BFD_RELOC_NDS32_ICT} - }; - - /* Implement md_parse_name. */ -@@ -6686,9 +7666,9 @@ nds32_parse_name (char const *name, expressionS *exprP, - exprP->X_op = O_symbol; - exprP->X_add_number = 0; - -- /* Check the special name if a symbol. */ -+ /* Check the specail name if a symbol. */ - segment = S_GET_SEGMENT (exprP->X_add_symbol); -- if (segment != undefined_section) -+ if ((segment != undefined_section) && (*nextcharP != '@')) - return 0; - - if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@') -@@ -6702,13 +7682,11 @@ nds32_parse_name (char const *name, expressionS *exprP, - char *next; - for (i = 0; i < ARRAY_SIZE (suffix_table); i++) - { -- next = input_line_pointer + 1 + strlen(suffix_table[i].suffix); -+ next = input_line_pointer + 1 + strlen (suffix_table[i].suffix); - if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix, - strlen (suffix_table[i].suffix)) == 0 - && !is_part_of_name (*next)) - { -- if (!nds32_pic && suffix_table[i].pic) -- as_bad (_("need PIC qualifier with symbol.")); - exprP->X_md = suffix_table[i].reloc; - *input_line_pointer = *nextcharP; - input_line_pointer = next; -@@ -6718,6 +7696,10 @@ nds32_parse_name (char const *name, expressionS *exprP, - } - } - } -+ -+ if (exprP->X_md == BFD_RELOC_NDS32_ICT) -+ ict_exist = TRUE; -+ - return 1; - } - -diff --git binutils-2.30/gas/config/tc-nds32.h binutils-2.30-nds32/gas/config/tc-nds32.h -index 178ca4ec33..bcea94afe0 100644 ---- binutils-2.30/gas/config/tc-nds32.h -+++ binutils-2.30-nds32/gas/config/tc-nds32.h -@@ -24,13 +24,28 @@ - - #include "bfd_stdint.h" - -+/* Enum mapping symbol. */ -+enum mstate -+{ -+ MAP_UNDEFINED = 0, /* Must be zero, for seginfo in new sections. */ -+ MAP_DATA, -+ MAP_CODE, -+}; -+#define TC_SEGMENT_INFO_TYPE struct nds32_segment_info_type -+ -+/* For mapping symbol. */ -+struct nds32_segment_info_type -+{ -+ enum mstate mapstate; -+}; -+ - #define LISTING_HEADER \ - (target_big_endian ? "NDS32 GAS" : "NDS32 GAS Little Endian") - - /* The target BFD architecture. */ - #define TARGET_ARCH bfd_arch_nds32 - --/* mapping to mach_table[5] */ -+/* mapping to mach_table[5] */ - #define ISA_V1 bfd_mach_n1h - #define ISA_V2 bfd_mach_n1h_v2 - #define ISA_V3 bfd_mach_n1h_v3 -@@ -42,29 +57,28 @@ - #define TARGET_BYTES_BIG_ENDIAN 1 - #endif - --/* as.c. */ --/* Extend GAS command line option handling capability. */ -+/* as.c */ -+/* Extend GAS command line option handling capability */ - extern int nds32_parse_option (int, const char *); - extern void nds32_after_parse_args (void); - /* The endianness of the target format may change based on command - line arguments. */ --extern const char * nds32_target_format (void); -- -+extern const char *nds32_target_format (void); - #define md_parse_option(optc, optarg) nds32_parse_option (optc, optarg) - #define md_after_parse_args() nds32_after_parse_args () - #define TARGET_FORMAT nds32_target_format() - --/* expr.c */ -+/* expr.c */ - extern int nds32_parse_name (char const *, expressionS *, enum expr_mode, char *); - extern bfd_boolean nds32_allow_local_subtract (expressionS *, expressionS *, segT); - #define md_parse_name(name, exprP, mode, nextcharP) \ - nds32_parse_name (name, exprP, mode, nextcharP) - #define md_allow_local_subtract(lhs,rhs,sect) nds32_allow_local_subtract (lhs, rhs, sect) - --/* dwarf2dbg.c. */ -+/* dwarf2dbg.c */ - #define DWARF2_USE_FIXED_ADVANCE_PC 1 - --/* write.c. */ -+/* write.c */ - extern long nds32_pcrel_from_section (struct fix *, segT); - extern bfd_boolean nds32_fix_adjustable (struct fix *); - extern void nds32_frob_file (void); -@@ -73,14 +87,13 @@ extern void nds32_frob_file_before_fix (void); - extern void elf_nds32_final_processing (void); - extern int nds32_validate_fix_sub (struct fix *, segT); - extern int nds32_force_relocation (struct fix *); --extern void nds32_set_section_relocs (asection *, arelent ** , unsigned int); -+extern void nds32_set_section_relocs (asection *, arelent **, unsigned int); - - /* Fill in rs_align_code fragments. TODO: Review this. */ - extern void nds32_handle_align (fragS *); - extern int nds32_relax_frag (segT, fragS *, long); - extern int tc_nds32_regname_to_dw2regnum (char *); - extern void tc_nds32_frame_initial_instructions (void); -- - #define MD_PCREL_FROM_SECTION(fix, sect) nds32_pcrel_from_section (fix, sect) - #define TC_FINALIZE_SYMS_BEFORE_SIZE_SEG 0 - #define tc_fix_adjustable(FIX) nds32_fix_adjustable (FIX) -@@ -103,7 +116,7 @@ extern void tc_nds32_frame_initial_instructions (void); - #define md_relax_frag(segment, fragP, stretch) nds32_relax_frag (segment, fragP, stretch) - #define WORKING_DOT_WORD /* We don't need to handle .word strangely. */ - /* Using to chain fixup with previous fixup. */ --#define TC_FIX_TYPE struct fix * -+#define TC_FIX_TYPE struct fix* - #define TC_INIT_FIX_DATA(fixP) \ - do \ - { \ -@@ -111,8 +124,8 @@ extern void tc_nds32_frame_initial_instructions (void); - } \ - while (0) - --/* read.c. */ --/* Extend GAS macro handling capability. */ -+/* read.c */ -+/* Extend GAS macro handling capability */ - extern void nds32_macro_start (void); - extern void nds32_macro_end (void); - extern void nds32_macro_info (void *); -@@ -128,7 +141,6 @@ extern void nds32_check_label (symbolS *); - extern void nds32_frob_label (symbolS *); - extern void nds32_pre_do_align (int, char *, int, int); - extern void nds32_do_align (int); -- - #define md_macro_start() nds32_macro_start () - #define md_macro_end() nds32_macro_end () - #define md_macro_info(args) nds32_macro_info (args) -@@ -143,7 +155,7 @@ extern void nds32_do_align (int); - #define md_do_align(N, FILL, LEN, MAX, LABEL) \ - nds32_pre_do_align (N, FILL, LEN, MAX); \ - if ((N) > 1 && (subseg_text_p (now_seg) \ -- || strncmp (now_seg->name, ".gcc_except_table", sizeof(".gcc_except_table") - 1) == 0)) \ -+ || strncmp (now_seg->name, ".gcc_except_table", sizeof (".gcc_except_table") - 1) == 0)) \ - nds32_do_align (N); \ - goto LABEL; - #define md_elf_section_change_hook() nds32_elf_section_change_hook () -@@ -151,7 +163,7 @@ extern void nds32_do_align (int); - #define md_cleanup() nds32_cleanup () - #define LOCAL_LABELS_FB 1 /* Permit temporary numeric labels. */ - --/* frags.c. */ -+/* frags.c */ - - enum FRAG_ATTR - { -@@ -161,7 +173,8 @@ enum FRAG_ATTR - NDS32_FRAG_LABEL = 0x8, - NDS32_FRAG_FINAL = 0x10, - NDS32_FRAG_RELAXABLE_BRANCH = 0x20, -- NDS32_FRAG_ALIGN = 0x40 -+ NDS32_FRAG_ALIGN = 0x40, -+ NDS32_FRAG_ICT_BRANCH = 0x80 - }; - - struct nds32_frag_type -@@ -231,7 +244,11 @@ enum nds32_ramp - NDS32_FIX = (1 << 7), - NDS32_ADDEND = (1 << 8), - NDS32_SYM = (1 << 9), -- NDS32_PCREL = (1 << 10) -+ NDS32_PCREL = (1 << 10), -+ NDS32_PTR_PATTERN = (1 << 11), -+ NDS32_PTR_MULTIPLE = (1 << 12), -+ NDS32_GROUP = (1 << 13), -+ NDS32_SYM_DESC_MEM = (1 << 14) - }; - - typedef struct nds32_relax_fixup_info -@@ -255,7 +272,7 @@ typedef struct nds32_cond_field - #define NDS32_MAXCHAR 20 - /* In current, the max extended number of instruction for one pseudo instruction - is 4, but its number of relocation may be 12. */ --#define MAX_RELAX_NUM 4 -+#define MAX_RELAX_NUM 6 - #define MAX_RELAX_FIX 12 - - typedef struct nds32_relax_info -@@ -275,8 +292,18 @@ typedef struct nds32_relax_info - enum nds32_relax_hint_type - { - NDS32_RELAX_HINT_NONE = 0, -- NDS32_RELAX_HINT_LA, -- NDS32_RELAX_HINT_LS -+ NDS32_RELAX_HINT_LA_FLSI, -+ NDS32_RELAX_HINT_LALS, -+ NDS32_RELAX_HINT_LA_PLT, -+ NDS32_RELAX_HINT_LA_GOT, -+ NDS32_RELAX_HINT_LA_GOTOFF, -+ NDS32_RELAX_HINT_TLS_START = 0x100, -+ NDS32_RELAX_HINT_TLS_LE_LS, -+ NDS32_RELAX_HINT_TLS_IE_LS, -+ NDS32_RELAX_HINT_TLS_IE_LA, -+ NDS32_RELAX_HINT_TLS_IEGP_LA, -+ NDS32_RELAX_HINT_TLS_DESC_LS, -+ NDS32_RELAX_HINT_ICT_LA, - }; - - struct nds32_relax_hint_table -@@ -287,4 +314,4 @@ struct nds32_relax_hint_table - nds32_relax_fixup_info_t relax_fixup[MAX_RELAX_FIX]; - }; - --#endif /* TC_NDS32 */ -+#endif /* TC_NDS32 */ -diff --git binutils-2.30/gas/configure binutils-2.30-nds32/gas/configure -index 0d5422572f..41a83a2998 100755 ---- binutils-2.30/gas/configure -+++ binutils-2.30-nds32/gas/configure -@@ -12491,6 +12491,11 @@ _ACEOF - ;; - - nds32) -+ # setup NDS32_LINUX_TOOLCHAIN definition -+ if test "linux" = $em; then -+$as_echo "#define NDS32_LINUX_TOOLCHAIN 1" >>confdefs.h -+ fi -+ - # Decide BASELINE, REDUCED_REGS, FPU_DP_EXT, FPU_SP_EXT features - # based on arch_name. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --with-arch" >&5 -@@ -12582,6 +12587,34 @@ $as_echo "#define NDS32_DEFAULT_AUDIO_EXT 1" >>confdefs.h - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_audio_ext" >&5 - $as_echo "$enable_audio_ext" >&6; } -+ -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-dsp-ext" >&5 -+$as_echo_n "checking for default configuration of --enable-dsp-ext... " >&6; } -+ if test "x${enable_dsp_ext}" == xno; then -+ -+$as_echo "#define NDS32_DEFAULT_DSP_EXT 0" >>confdefs.h -+ -+ else -+ -+$as_echo "#define NDS32_DEFAULT_DSP_EXT 1" >>confdefs.h -+ -+ fi -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_dsp_ext" >&5 -+$as_echo "$enable_dsp_ext" >&6; } -+ -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-zol-ext" >&5 -+$as_echo_n "checking for default configuration of --enable-zol-ext... " >&6; } -+ if test "x${enable_zol_ext}" == xno; then -+ -+$as_echo "#define NDS32_DEFAULT_ZOL_EXT 0" >>confdefs.h -+ -+ else -+ -+$as_echo "#define NDS32_DEFAULT_ZOL_EXT 1" >>confdefs.h -+ -+ fi -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_zol_ext" >&5 -+$as_echo "$enable_zol_ext" >&6; } - ;; - - aarch64 | i386 | riscv | s390 | sparc) -diff --git binutils-2.30/include/dis-asm.h binutils-2.30-nds32/include/dis-asm.h -index eebdaf874f..5cbe83aad7 100644 ---- binutils-2.30/include/dis-asm.h -+++ binutils-2.30-nds32/include/dis-asm.h -@@ -261,11 +261,13 @@ extern void print_arm_disassembler_options (FILE *); - extern void print_arc_disassembler_options (FILE *); - extern void print_s390_disassembler_options (FILE *); - extern void print_wasm32_disassembler_options (FILE *); -+extern void print_nds32_disassembler_options (FILE *); - extern bfd_boolean aarch64_symbol_is_valid (asymbol *, struct disassemble_info *); - extern bfd_boolean arm_symbol_is_valid (asymbol *, struct disassemble_info *); - extern void disassemble_init_powerpc (struct disassemble_info *); - extern void disassemble_init_s390 (struct disassemble_info *); - extern void disassemble_init_wasm32 (struct disassemble_info *); -+extern void disassemble_init_nds32 (struct disassemble_info *); - extern const disasm_options_t *disassembler_options_powerpc (void); - extern const disasm_options_t *disassembler_options_arm (void); - extern const disasm_options_t *disassembler_options_s390 (void); -diff --git binutils-2.30/include/elf/nds32.h binutils-2.30-nds32/include/elf/nds32.h -index 1b3a3219d0..7250f2bb0c 100644 ---- binutils-2.30/include/elf/nds32.h -+++ binutils-2.30-nds32/include/elf/nds32.h -@@ -107,9 +107,9 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type) - RELOC_NUMBER (R_NDS32_SDA17S2_RELA, 74) - RELOC_NUMBER (R_NDS32_SDA18S1_RELA, 75) - RELOC_NUMBER (R_NDS32_SDA19S0_RELA, 76) -- RELOC_NUMBER (R_NDS32_DWARF2_OP1_RELA, 77) -- RELOC_NUMBER (R_NDS32_DWARF2_OP2_RELA, 78) -- RELOC_NUMBER (R_NDS32_DWARF2_LEB_RELA, 79) -+ RELOC_NUMBER (R_NDS32_DWARF2_OP1_RELA, 77) /* This is obsoleted. */ -+ RELOC_NUMBER (R_NDS32_DWARF2_OP2_RELA, 78) /* This is obsoleted. */ -+ RELOC_NUMBER (R_NDS32_DWARF2_LEB_RELA, 79) /* This is obsoleted. */ - RELOC_NUMBER (R_NDS32_UPDATE_TA_RELA, 80) /* This is obsoleted. */ - RELOC_NUMBER (R_NDS32_9_PLTREL, 81) - RELOC_NUMBER (R_NDS32_PLT_GOTREL_LO20, 82) -@@ -128,15 +128,6 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type) - RELOC_NUMBER (R_NDS32_25_ABS_RELA, 95) - RELOC_NUMBER (R_NDS32_17IFC_PCREL_RELA, 96) - RELOC_NUMBER (R_NDS32_10IFCU_PCREL_RELA, 97) -- RELOC_NUMBER (R_NDS32_TLS_LE_HI20, 98) -- RELOC_NUMBER (R_NDS32_TLS_LE_LO12, 99) -- RELOC_NUMBER (R_NDS32_TLS_IE_HI20, 100) -- RELOC_NUMBER (R_NDS32_TLS_IE_LO12S2, 101) -- RELOC_NUMBER (R_NDS32_TLS_TPOFF, 102) -- RELOC_NUMBER (R_NDS32_TLS_LE_20, 103) -- RELOC_NUMBER (R_NDS32_TLS_LE_15S0, 104) -- RELOC_NUMBER (R_NDS32_TLS_LE_15S1, 105) -- RELOC_NUMBER (R_NDS32_TLS_LE_15S2, 106) - RELOC_NUMBER (R_NDS32_LONGCALL4, 107) - RELOC_NUMBER (R_NDS32_LONGCALL5, 108) - RELOC_NUMBER (R_NDS32_LONGCALL6, 109) -@@ -144,7 +135,37 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type) - RELOC_NUMBER (R_NDS32_LONGJUMP5, 111) - RELOC_NUMBER (R_NDS32_LONGJUMP6, 112) - RELOC_NUMBER (R_NDS32_LONGJUMP7, 113) -+ RELOC_NUMBER (R_NDS32_SECURITY_16, 114) -+ /* TLS support { */ -+ RELOC_NUMBER (R_NDS32_TLS_TPOFF, 102) -+ RELOC_NUMBER (R_NDS32_TLS_LE_HI20, 98) -+ RELOC_NUMBER (R_NDS32_TLS_LE_LO12, 99) -+ RELOC_NUMBER (R_NDS32_TLS_LE_20, 103) -+ RELOC_NUMBER (R_NDS32_TLS_LE_15S0, 104) -+ RELOC_NUMBER (R_NDS32_TLS_LE_15S1, 105) -+ RELOC_NUMBER (R_NDS32_TLS_LE_15S2, 106) -+ RELOC_NUMBER (R_NDS32_TLS_IE_HI20, 100) -+ RELOC_NUMBER (R_NDS32_TLS_IE_LO12, 115) -+ RELOC_NUMBER (R_NDS32_TLS_IE_LO12S2, 101) -+ RELOC_NUMBER (R_NDS32_TLS_IEGP_HI20, 116) -+ RELOC_NUMBER (R_NDS32_TLS_IEGP_LO12, 117) -+ RELOC_NUMBER (R_NDS32_TLS_IEGP_LO12S2, 118) -+ RELOC_NUMBER (R_NDS32_TLS_DESC, 119) -+ RELOC_NUMBER (R_NDS32_TLS_DESC_HI20, 120) -+ RELOC_NUMBER (R_NDS32_TLS_DESC_LO12, 121) -+ RELOC_NUMBER (R_NDS32_TLS_DESC_20, 122) -+ RELOC_NUMBER (R_NDS32_TLS_DESC_SDA17S2, 123) -+ /* TLS support } */ -+ /* new relocation type add here. */ -+ RELOC_NUMBER (R_NDS32_RELOC_NEXT, 124) -+ -+ /* Jump-patch table relocations. */ -+ RELOC_NUMBER (R_NDS32_ICT_HI20, 125) -+ RELOC_NUMBER (R_NDS32_ICT_LO12, 126) -+ RELOC_NUMBER (R_NDS32_ICT_25PC, 127) -+ RELOC_NUMBER (R_NDS32_ICT_LO12S2, 128) - -+ /* relax only following */ - RELOC_NUMBER (R_NDS32_RELAX_ENTRY, 192) - RELOC_NUMBER (R_NDS32_GOT_SUFF, 193) - RELOC_NUMBER (R_NDS32_GOTOFF_SUFF, 194) -@@ -164,9 +185,21 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type) - RELOC_NUMBER (R_NDS32_DIFF_ULEB128, 208) - RELOC_NUMBER (R_NDS32_DATA, 209) - RELOC_NUMBER (R_NDS32_TRAN, 210) -+ RELOC_NUMBER (R_NDS32_EMPTY, 213) -+ /* TLS support { */ - RELOC_NUMBER (R_NDS32_TLS_LE_ADD, 211) - RELOC_NUMBER (R_NDS32_TLS_LE_LS, 212) -- RELOC_NUMBER (R_NDS32_EMPTY, 213) -+ RELOC_NUMBER (R_NDS32_TLS_IEGP_LW, 220) -+ RELOC_NUMBER (R_NDS32_TLS_DESC_ADD, 214) -+ RELOC_NUMBER (R_NDS32_TLS_DESC_FUNC, 215) -+ RELOC_NUMBER (R_NDS32_TLS_DESC_CALL, 216) -+ RELOC_NUMBER (R_NDS32_TLS_DESC_MEM, 217) -+ RELOC_NUMBER (R_NDS32_RELAX_REMOVE, 218) -+ RELOC_NUMBER (R_NDS32_RELAX_GROUP, 219) -+ /* TLS support } */ -+ /* new relaxation type add here. */ -+ RELOC_NUMBER (R_NDS32_LSI, 221) -+ RELOC_NUMBER (R_NDS32_RELAX_NEXT, 222) - - END_RELOC_NUMBERS (R_NDS32_max) - -@@ -259,10 +292,10 @@ END_RELOC_NUMBERS (R_NDS32_max) - #define E_NDS32_FPU_REG_32SP_32DP 0x3 - /* FPU MAC instruction used. */ - #define E_NDS32_HAS_FPU_MAC_INST 0x01000000 --/* <<>>. */ --#define E_NDS32_NULL 0x02000000 --/* PIC enabled. */ --#define E_NDS32_HAS_PIC 0x04000000 -+/* DSP extension. */ -+#define E_NDS32_HAS_DSP_INST 0x02000000 -+/* Hardware zero-overhead loop enabled. */ -+#define E_NDS32_HAS_ZOL (1 << 26) - /* Use custom section. */ - #define E_NDS32_HAS_CUSTOM_SEC 0x08000000 - -diff --git binutils-2.30/include/opcode/nds32.h binutils-2.30-nds32/include/opcode/nds32.h -index 4d113be8b8..04a02b5222 100644 ---- binutils-2.30/include/opcode/nds32.h -+++ binutils-2.30-nds32/include/opcode/nds32.h -@@ -21,31 +21,32 @@ - #define OPCODE_NDS32_H - - /* Registers. */ --#define REG_R5 5 --#define REG_R8 8 --#define REG_R10 10 --#define REG_R12 12 --#define REG_R15 15 --#define REG_R16 16 --#define REG_R20 20 --#define REG_TA 15 --#define REG_TP 27 --#define REG_FP 28 --#define REG_GP 29 --#define REG_LP 30 --#define REG_SP 31 -+#define REG_R0 (0) -+#define REG_R5 (5) -+#define REG_R8 (8) -+#define REG_R10 (10) -+#define REG_R12 (12) -+#define REG_R15 (15) -+#define REG_R16 (16) -+#define REG_R20 (20) -+#define REG_TA (15) -+#define REG_TP (25) -+#define REG_FP (28) -+#define REG_GP (29) -+#define REG_LP (30) -+#define REG_SP (31) - - /* Macros for extracting fields or making an instruction. */ - static const int nds32_r45map[] ATTRIBUTE_UNUSED = - { -- 0, 1, 2, 3, 4, 5, 6, 7, -+ 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 16, 17, 18, 19 - }; - - static const int nds32_r54map[] ATTRIBUTE_UNUSED = - { -- 0, 1, 2, 3, 4, 5, 6, 7, -- 8, 9, 10, 11, -1, -1, -1, -1, -+ 0, 1, 2, 3, 4, 5, 6, 7, -+ 8, 9, 10, 11, -1, -1, -1, -1, - 12, 13, 14, 15, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 - }; -@@ -146,6 +147,7 @@ static const int nds32_r54map[] ATTRIBUTE_UNUSED = - #define N32_RD5(insn) (((insn) >> 5) & 0x1f) - #define N32_SH5(insn) (((insn) >> 5) & 0x1f) - #define N32_SUB5(insn) (((insn) >> 0) & 0x1f) -+#define N32_SUB6(insn) (((insn) >> 0) & 0x3f) - #define N32_SWID(insn) (((insn) >> 5) & 0x3ff) - #define N32_IMMU(insn, bs) ((insn) & __MASK (bs)) - #define N32_IMMS(insn, bs) ((signed) __SEXT (((insn) & __MASK (bs)), bs)) -@@ -275,7 +277,7 @@ enum n32_opcodes - N32_BR1_BNE = 1, - - /* bit[16:19] */ -- N32_BR2_IFCALL = 0, -+ N32_BR2_SOP0 = 0, - N32_BR2_BEQZ = 2, - N32_BR2_BNEZ = 3, - N32_BR2_BGEZ = 4, -@@ -365,7 +367,8 @@ enum n32_opcodes - N32_ALU2_FFZMISM, - N32_ALU2_KADD = 0x18, - N32_ALU2_KSUB, -- N32_ALU2_KSLRA, -+ N32_ALU2_KSLRAW, -+ N32_ALU2_KSLRAWu, - N32_ALU2_MFUSR = 0x20, - N32_ALU2_MTUSR, - N32_ALU2_0x22, -@@ -381,20 +384,173 @@ enum n32_opcodes - N32_ALU2_MSUB64, - N32_ALU2_DIVS, - N32_ALU2_DIV, -- N32_ALU2_0x30 = 0x30, -+ N32_ALU2_ADD64 = 0x30, - N32_ALU2_MULT32, -- N32_ALU2_0x32, -+ N32_ALU2_SMAL, - N32_ALU2_MADD32, -- N32_ALU2_0x34, -+ N32_ALU2_SUB64, - N32_ALU2_MSUB32, -- -- /* bit[0:5], where bit[6:9] != 0 */ -+ N32_ALU2_0x36, -+ N32_ALU2_0x37, -+ N32_ALU2_RADD64 = 0x38, -+ N32_ALU2_URADD64, -+ N32_ALU2_KADD64, -+ N32_ALU2_UKADD64, -+ N32_ALU2_RSUB64, -+ N32_ALU2_URSUB64, -+ N32_ALU2_KSUB64, -+ N32_ALU2_UKSUB64, -+ -+ /* bit[0:5], where bit[6:9] = 0001 */ -+ N32_ALU2_SMAR64 = 0x0, -+ N32_ALU2_UMAR64, -+ N32_ALU2_SMSR64, -+ N32_ALU2_UMSR64, -+ N32_ALU2_KMAR64, -+ N32_ALU2_UKMAR64, -+ N32_ALU2_KMSR64, -+ N32_ALU2_UKMSR64, -+ N32_ALU2_SMALDA = 0x8, -+ N32_ALU2_SMSLDA, -+ N32_ALU2_SMALDS, -+ N32_ALU2_SMALBB, - N32_ALU2_FFBI = 0xe, - N32_ALU2_FLMISM = 0xf, -+ N32_ALU2_SMALXDA = 0x10, -+ N32_ALU2_SMSLXDA, -+ N32_ALU2_SMALXDS, -+ N32_ALU2_SMALBT, -+ N32_ALU2_SMALDRS = 0x1a, -+ N32_ALU2_SMALTT, -+ N32_ALU2_RDOV = 0x20, -+ N32_ALU2_CLROV, - N32_ALU2_MULSR64 = 0x28, - N32_ALU2_MULR64 = 0x29, -- N32_ALU2_MADDR32 = 0x33, -- N32_ALU2_MSUBR32 = 0x35, -+ N32_ALU2_SMDS = 0x30, -+ N32_ALU2_SMXDS, -+ N32_ALU2_SMDRS, -+ N32_ALU2_MADDR32, -+ N32_ALU2_KMADRS, -+ N32_ALU2_MSUBR32, -+ N32_ALU2_KMADS, -+ N32_ALU2_KMAXDS, -+ -+ /* bit[0:5], where bit[6:9] = 0010 */ -+ N32_ALU2_KADD16 = 0x0, -+ N32_ALU2_KSUB16, -+ N32_ALU2_KCRAS16, -+ N32_ALU2_KCRSA16, -+ N32_ALU2_KADD8, -+ N32_ALU2_KSUB8, -+ N32_ALU2_WEXT, -+ N32_ALU2_WEXTI, -+ N32_ALU2_UKADD16 = 0x8, -+ N32_ALU2_UKSUB16, -+ N32_ALU2_UKCRAS16, -+ N32_ALU2_UKCRSA16, -+ N32_ALU2_UKADD8, -+ N32_ALU2_UKSUB8, -+ N32_ALU2_ONEOP = 0xf, -+ N32_ALU2_SMBB = 0x10, -+ N32_ALU2_SMBT, -+ N32_ALU2_SMTT, -+ N32_ALU2_KMABB = 0x15, -+ N32_ALU2_KMABT, -+ N32_ALU2_KMATT, -+ N32_ALU2_KMDA = 0x18, -+ N32_ALU2_KMXDA, -+ N32_ALU2_KMADA, -+ N32_ALU2_KMAXDA, -+ N32_ALU2_KMSDA, -+ N32_ALU2_KMSXDA, -+ N32_ALU2_RADD16 = 0x20, -+ N32_ALU2_RSUB16, -+ N32_ALU2_RCRAS16, -+ N32_ALU2_RCRSA16, -+ N32_ALU2_RADD8, -+ N32_ALU2_RSUB8, -+ N32_ALU2_RADDW, -+ N32_ALU2_RSUBW, -+ N32_ALU2_URADD16 = 0x28, -+ N32_ALU2_URSUB16, -+ N32_ALU2_URCRAS16, -+ N32_ALU2_URCRSA16, -+ N32_ALU2_URADD8, -+ N32_ALU2_URSUB8, -+ N32_ALU2_URADDW, -+ N32_ALU2_URSUBW, -+ N32_ALU2_ADD16 = 0x30, -+ N32_ALU2_SUB16, -+ N32_ALU2_CRAS16, -+ N32_ALU2_CRSA16, -+ N32_ALU2_ADD8, -+ N32_ALU2_SUB8, -+ N32_ALU2_BITREV, -+ N32_ALU2_BITREVI, -+ N32_ALU2_SMMUL = 0x38, -+ N32_ALU2_SMMULu, -+ N32_ALU2_KMMAC, -+ N32_ALU2_KMMACu, -+ N32_ALU2_KMMSB, -+ N32_ALU2_KMMSBu, -+ N32_ALU2_KWMMUL, -+ N32_ALU2_KWMMULu, -+ -+ /* bit[0:5], where bit[6:9] = 0011 */ -+ N32_ALU2_SMMWB = 0x0, -+ N32_ALU2_SMMWBu, -+ N32_ALU2_SMMWT, -+ N32_ALU2_SMMWTu, -+ N32_ALU2_KMMAWB, -+ N32_ALU2_KMMAWBu, -+ N32_ALU2_KMMAWT, -+ N32_ALU2_KMMAWTu, -+ N32_ALU2_PKTT16 = 0x8, -+ N32_ALU2_PKTB16, -+ N32_ALU2_PKBT16, -+ N32_ALU2_PKBB16, -+ N32_ALU2_0x10 = 0x10, -+ N32_ALU2_SCLIP16, -+ N32_ALU2_0x12, -+ N32_ALU2_SMAX16, -+ N32_ALU2_SMAX8 = 0x17, -+ N32_ALU2_0x18 = 0x18, -+ N32_ALU2_UCLIP16, -+ N32_ALU2_0x1a, -+ N32_ALU2_UMAX16, -+ N32_ALU2_UMAX8 = 0x1f, -+ N32_ALU2_SRA16 = 0x20, -+ N32_ALU2_SRA16u, -+ N32_ALU2_SRL16, -+ N32_ALU2_SRL16u, -+ N32_ALU2_SLL16, -+ N32_ALU2_KSLRA16, -+ N32_ALU2_KSLRA16u, -+ N32_ALU2_SRAu, -+ N32_ALU2_SRAI16 = 0x28, -+ N32_ALU2_SRAI16u, -+ N32_ALU2_SRLI16, -+ N32_ALU2_SRLI16u, -+ N32_ALU2_SLLI16, -+ N32_ALU2_KSLLI16, -+ N32_ALU2_KSLLI, -+ N32_ALU2_SRAIu, -+ N32_ALU2_CMPEQ16 = 0x30, -+ N32_ALU2_SCMPLT16, -+ N32_ALU2_SCMPLE16, -+ N32_ALU2_SMIN16, -+ N32_ALU2_CMPEQ8, -+ N32_ALU2_SCMPLT8, -+ N32_ALU2_SCMPLE8, -+ N32_ALU2_SMIN8, -+ N32_ALU2_0x38, -+ N32_ALU2_UCMPLT16 = 0x39, -+ N32_ALU2_UCMPLE16, -+ N32_ALU2_UMIN16, -+ N32_ALU2_0x3c, -+ N32_ALU2_UCMPLT8, -+ N32_ALU2_UCMPLE8, -+ N32_ALU2_UMIN8, - - /* bit[0:5] */ - N32_MEM_LB = 0, -@@ -459,7 +615,8 @@ enum n32_opcodes - N32_MISC_MSYNC, - N32_MISC_ISYNC, - N32_MISC_TLBOP, -- N32_MISC_0xf, -+ N32_MISC_SPECL, -+ N32_MISC_BPICK = 0x10, - - /* bit[0:4] */ - N32_SIMD_PBSAD = 0, -@@ -582,7 +739,7 @@ enum n32_opcodes - N32_FPU_MTCP_XR = 0xc, - - /* MTCP/XR b[14:10] */ -- N32_FPU_MTCP_XR_FMTCSR = 0x1 -+ N32_FPU_MTCP_XR_FMTCSR = 0x1, - }; - - enum n16_opcodes -@@ -675,7 +832,7 @@ enum n16_opcodes - N16_BFMI333_XLSB33 = 4, - N16_BFMI333_X11B33 = 5, - N16_BFMI333_BMSKI33 = 6, -- N16_BFMI333_FEXTI33 = 7 -+ N16_BFMI333_FEXTI33 = 7, - }; - - /* These macros a deprecated. DO NOT use them anymore. -@@ -704,6 +861,7 @@ enum n16_opcodes - #define INSN_ANDI 0x54000000 - #define INSN_LDI 0x06000000 - #define INSN_SDI 0x16000000 -+#define INSN_LW 0x38000002 - #define INSN_LWI 0x04000000 - #define INSN_LWSI 0x24000000 - #define INSN_LWIP 0x0c000000 -diff --git binutils-2.30/ld/config.in binutils-2.30-nds32/ld/config.in -index a846743da6..9cc2f6303a 100644 ---- binutils-2.30/ld/config.in -+++ binutils-2.30-nds32/ld/config.in -@@ -63,9 +63,18 @@ - */ - #undef HAVE_DIRENT_H - -+/* Define to 1 if you have the `dlclose' function. */ -+#undef HAVE_DLCLOSE -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_DLFCN_H - -+/* Define to 1 if you have the `dlopen' function. */ -+#undef HAVE_DLOPEN -+ -+/* Define to 1 if you have the `dlsym' function. */ -+#undef HAVE_DLSYM -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_ELF_HINTS_H - -@@ -168,6 +177,9 @@ - */ - #undef LT_OBJDIR - -+/* Define if linux toolchain is to be built. */ -+#undef NDS32_LINUX_TOOLCHAIN -+ - /* Name of package */ - #undef PACKAGE - -diff --git binutils-2.30/ld/configure binutils-2.30-nds32/ld/configure -index 48606ae36b..732630063d 100755 ---- binutils-2.30/ld/configure -+++ binutils-2.30-nds32/ld/configure -@@ -17165,6 +17165,53 @@ do - - . ${srcdir}/configure.tgt - -+ case ${target_cpu} in -+ nds32*) -+ case ${targ} in -+ *-*-linux*) -+ -+$as_echo "#define NDS32_LINUX_TOOLCHAIN 1" >>confdefs.h -+ -+ ;; -+ esac -+ -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-ifc-ext" >&5 -+$as_echo_n "checking for default configuration of --enable-ifc-ext... " >&6; } -+ if test "x${enable_ifc_ext}" == xyes; then -+ -+$as_echo "#define NDS32_IFC_EXT 1" >>confdefs.h -+ -+ fi -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_ifc_ext" >&5 -+$as_echo "$enable_ifc_ext" >&6; } -+ -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-ex9-ext" >&5 -+$as_echo_n "checking for default configuration of --enable-ex9-ext... " >&6; } -+ if test "x${enable_ex9_ext}" == xyes; then -+ -+$as_echo "#define NDS32_EX9_EXT 1" >>confdefs.h -+ -+ fi -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_ex9_ext" >&5 -+$as_echo "$enable_ex9_ext" >&6; } -+ -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-16m-addr" >&5 -+$as_echo_n "checking for default configuration of --enable-16m-addr... " >&6; } -+ if test "x${enable_16m_addr}" == xyes; then -+ case ${targ} in -+ nds32*le-*-elf*) -+ targ_emul=nds32elf16m -+ ;; -+ nds32*be-*-elf*) -+ targ_emul=nds32belf16m -+ ;; -+ esac -+ fi -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_16m-addr" >&5 -+$as_echo "$enable_16m-addr" >&6; } -+ ;; -+ esac -+ - if test "$targ" = "$target"; then - EMUL=$targ_emul - fi -diff --git binutils-2.30/ld/configure.tgt binutils-2.30-nds32/ld/configure.tgt -index 6183a85b3d..b3d285faaa 100644 ---- binutils-2.30/ld/configure.tgt -+++ binutils-2.30-nds32/ld/configure.tgt -@@ -583,8 +583,8 @@ nds32*le-*-elf*) targ_emul=nds32elf - nds32*be-*-elf*) targ_emul=nds32belf - targ_extra_emuls="nds32elf nds32elf16m nds32belf16m" - ;; --nds32*le-*-linux-gnu*) targ_emul=nds32elf_linux ;; --nds32*be-*-linux-gnu*) targ_emul=nds32belf_linux ;; -+nds32*le-*-linux*) targ_emul=nds32elf_linux ;; -+nds32*be-*-linux*) targ_emul=nds32belf_linux ;; - nios2*-*-linux*) targ_emul=nios2linux ;; - nios2*-*-*) targ_emul=nios2elf ;; - ns32k-pc532-mach* | ns32k-pc532-ux*) targ_emul=pc532macha ;; -diff --git binutils-2.30/ld/emulparams/nds32elf.sh binutils-2.30-nds32/ld/emulparams/nds32elf.sh -index f0a7c31329..e2fde5d0a2 100644 ---- binutils-2.30/ld/emulparams/nds32elf.sh -+++ binutils-2.30-nds32/ld/emulparams/nds32elf.sh -@@ -14,5 +14,9 @@ MAXPAGESIZE=0x20 - EMBEDDED=yes - COMMONPAGESIZE=0x20 - --# Use external linker script files. --COMPILE_IN=no -+# Instruct genscripts.sh not to compile scripts in by COMPILE_IN -+# in order to use external linker scripts files. -+EMULATION_LIBPATH= -+ -+GENERATE_SHLIB_SCRIPT=yes -+GENERATE_PIE_SCRIPT=yes -diff --git binutils-2.30/ld/emulparams/nds32elf16m.sh binutils-2.30-nds32/ld/emulparams/nds32elf16m.sh -index deb8699004..7d3b063abd 100644 ---- binutils-2.30/ld/emulparams/nds32elf16m.sh -+++ binutils-2.30-nds32/ld/emulparams/nds32elf16m.sh -@@ -14,5 +14,6 @@ MAXPAGESIZE=0x20 - EMBEDDED=yes - COMMONPAGESIZE=0x20 - --# Use external linker script files. --COMPILE_IN=no -+# Instruct genscripts.sh not to compile scripts in by COMPILE_IN -+# in order to use external linker scripts files. -+EMULATION_LIBPATH= -diff --git binutils-2.30/ld/emulparams/nds32elf_linux.sh binutils-2.30-nds32/ld/emulparams/nds32elf_linux.sh -index 1145c0eeea..6d89f7924f 100644 ---- binutils-2.30/ld/emulparams/nds32elf_linux.sh -+++ binutils-2.30-nds32/ld/emulparams/nds32elf_linux.sh -@@ -31,5 +31,6 @@ fi - GENERATE_SHLIB_SCRIPT=yes - GENERATE_PIE_SCRIPT=yes - --# Use external linker script files. --COMPILE_IN=no -+# Instruct genscripts.sh not to compile scripts in by COMPILE_IN -+# in order to use external linker scripts files. -+EMULATION_LIBPATH= -diff --git binutils-2.30/ld/emultempl/elf32.em binutils-2.30-nds32/ld/emultempl/elf32.em -index c0925fc9b9..e5f109d3ce 100644 ---- binutils-2.30/ld/emultempl/elf32.em -+++ binutils-2.30-nds32/ld/emultempl/elf32.em -@@ -114,7 +114,7 @@ fi - if test x"$LDEMUL_AFTER_PARSE" != xgld"$EMULATION_NAME"_after_parse; then - fragment < */ -+static int hyper_relax = 1; /* --mhyper-relax */ - /* Disable if linking a dynamically linked executable. */ - static int load_store_relax = 1; - static int target_optimize = 0; /* Switch optimization. */ - static int relax_status = 0; /* Finished optimization. */ - static int relax_round = 0; /* Going optimization. */ --static FILE *ex9_export_file = NULL; /* --mexport-ex9= */ --static FILE *ex9_import_file = NULL; /* --mimport-ex9= */ --static int update_ex9_table = 0; /* --mupdate-ex9. */ --static int ex9_limit = 511; --static bfd_boolean ex9_loop_aware = FALSE; /* Ignore ex9 if inside a loop. */ --static bfd_boolean ifc_loop_aware = FALSE; /* Ignore ifc if inside a loop. */ -+static int tls_desc_trampoline = 0; /* --m[no]tlsdesc-trampoline. */ -+static char *set_output_abi = NULL; /* --mabi. */ - - /* Save the target options into output bfd to avoid using to many global - variables. Do this after the output has been created, but before -@@ -61,39 +59,41 @@ nds32_elf_create_output_section_statements (void) - sym_ld_script, - load_store_relax, - target_optimize, relax_status, relax_round, -- ex9_export_file, ex9_import_file, -- update_ex9_table, ex9_limit, -- ex9_loop_aware, ifc_loop_aware); -+ hyper_relax, -+ tls_desc_trampoline, -+ set_output_abi); - } - - static void - nds32_elf_after_parse (void) - { -+#ifdef NDS32_LINUX_TOOLCHAIN -+ if (RELAXATION_ENABLED) -+ { -+ einfo ("%P: warning: The relaxation isn't supported yet.\n"); -+ DISABLE_RELAXATION; -+ } -+#endif -+ - if (bfd_link_relocatable (&link_info)) - DISABLE_RELAXATION; - - if (!RELAXATION_ENABLED) - { -- target_optimize = target_optimize & (!NDS32_RELAX_JUMP_IFC_ON); -- target_optimize = target_optimize & (!NDS32_RELAX_EX9_ON); -+ target_optimize &= ~(NDS32_RELAX_IFC_ON | NDS32_RELAX_EX9_ON); - relax_fp_as_gp = 0; - } - -- if (ex9_import_file != NULL) -- { -- ex9_export_file = NULL; -- target_optimize = target_optimize & (!NDS32_RELAX_EX9_ON); -- } -- else -- update_ex9_table = 0; -- - if (bfd_link_pic (&link_info)) - { -- target_optimize = target_optimize & (!NDS32_RELAX_JUMP_IFC_ON); -- target_optimize = target_optimize & (!NDS32_RELAX_EX9_ON); -+ target_optimize &= ~(NDS32_RELAX_IFC_ON | NDS32_RELAX_EX9_ON); - } - -- gld${EMULATION_NAME}_after_parse (); -+ after_parse_default (); -+ -+ /* Backward compatible for linker script output_format. */ -+ if (output_target && strcmp (output_target, "elf32-nds32") == 0) -+ output_target = default_target; - } - - static void -@@ -107,10 +107,15 @@ nds32_elf_after_open (void) - We may try to merge object files with different architecture together. */ - for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next) - { -- if (arch_ver == (unsigned int)-1 && E_N1_ARCH != (elf_elfheader (abfd)->e_flags & EF_NDS_ARCH)) -+ if (arch_ver == (unsigned int)-1 -+ && E_N1_ARCH != (elf_elfheader (abfd)->e_flags & EF_NDS_ARCH)) - arch_ver = elf_elfheader (abfd)->e_flags & EF_NDS_ARCH ; - -- if (abi_ver == (unsigned int)-1) -+ if (set_output_abi != NULL) -+ { -+ /* do not check ABI. */ -+ } -+ else if (abi_ver == (unsigned int)-1) - { - /* Initialize ABI version, if not ABI0. - (OS uses empty file to create empty ELF with ABI0). */ -@@ -120,67 +125,34 @@ nds32_elf_after_open (void) - else if ((elf_elfheader (abfd)->e_flags & EF_NDS_ABI) != 0 - && abi_ver != (elf_elfheader (abfd)->e_flags & EF_NDS_ABI)) - { -+ asection *section = NULL; -+ bfd_byte *contents = NULL; -+ section = bfd_get_section_by_name (abfd, ".note.v2abi_compatible"); -+ if (section) -+ bfd_get_full_section_contents (abfd, section, &contents); -+ - /* Incompatible objects. */ -- einfo (_("%F%B: ABI version of object files mismatched\n"), abfd); -+ if ((contents == NULL) -+ || bfd_getb32 (contents) != 1 -+ || abi_ver != E_NDS_ABI_V2FP_PLUS) -+ einfo (_("%F%B: ABI version of object files mismatched\n"), abfd); - } - --#if defined NDS32_EX9_EXT -- /* Append .ex9.itable section in the last input object file. */ -- if (abfd->link_next == NULL && (target_optimize & NDS32_RELAX_EX9_ON)) -- { -- asection *itable; -- struct bfd_link_hash_entry *h; -- itable = bfd_make_section_with_flags (abfd, ".ex9.itable", -- SEC_CODE | SEC_ALLOC | SEC_LOAD -- | SEC_HAS_CONTENTS | SEC_READONLY -- | SEC_IN_MEMORY | SEC_KEEP); -- if (itable) -- { -- itable->gc_mark = 1; -- itable->alignment_power = 2; -- itable->size = 0x1000; -- itable->contents = bfd_zalloc (abfd, itable->size); -- -- /* Add a symbol in the head of ex9.itable to objdump clearly. */ -- h = bfd_link_hash_lookup (link_info.hash, "_EX9_BASE_", -- FALSE, FALSE, FALSE); -- _bfd_generic_link_add_one_symbol -- (&link_info, link_info.output_bfd, "_EX9_BASE_", -- BSF_GLOBAL | BSF_WEAK, itable, 0, (const char *) NULL, FALSE, -- get_elf_backend_data (link_info.output_bfd)->collect, &h); -- } -- } --#endif -+ /* Append target needed section in the last input object file. */ -+ if (abfd->link.next == NULL) -+ bfd_elf32_nds32_append_section (&link_info, abfd); - } - - /* Check object files if the target is dynamic linked executable - or shared object. */ - if (elf_hash_table (&link_info)->dynamic_sections_created -- || bfd_link_pic (&link_info)) -+ || bfd_link_pic (&link_info) || bfd_link_pie (&link_info)) - { -- for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next) -- { -- if (!(elf_elfheader (abfd)->e_flags & E_NDS32_HAS_PIC)) -- { -- /* Non-PIC object file is used. */ -- if (bfd_link_pic (&link_info)) -- { -- /* For PIE or shared object, all input must be PIC. */ -- einfo (_("%B: must use -fpic to compile this file " -- "for shared object or PIE\n"), abfd); -- } -- else -- { -- /* Dynamic linked executable with SDA and non-PIC. -- Turn off load/store relaxtion. */ -- /* TODO: This may support in the future. */ -- load_store_relax = 0 ; -- relax_fp_as_gp = 0; -- } -- } -- } -- /* Turn off relax when building shared object or PIE -- until we can support their relaxation. */ -+ /* Dynamic linked executable with SDA and non-PIC. -+ Turn off load/store relaxtion. */ -+ /* TODO: This may support in the future. */ -+ load_store_relax = 0 ; -+ relax_fp_as_gp = 0; - } - - /* Call the standard elf routine. */ -@@ -190,19 +162,26 @@ nds32_elf_after_open (void) - static void - nds32_elf_after_allocation (void) - { -- if (target_optimize & NDS32_RELAX_EX9_ON -- || (ex9_import_file != NULL && update_ex9_table == 1)) -- { -- /* Initialize ex9 hash table. */ -- if (!nds32_elf_ex9_init ()) -- return; -- } -+ struct bfd_link_hash_entry *h; - - /* Call default after allocation callback. - 1. This is where relaxation is done. - 2. It calls gld${EMULATION_NAME}_map_segments to build ELF segment table. - 3. Any relaxation requires relax being done must be called after it. */ - gld${EMULATION_NAME}_after_allocation (); -+ -+ /* Add a symbol for linker script check the max size. */ -+ if (link_info.output_bfd->sections) -+ { -+ h = bfd_link_hash_lookup (link_info.hash, "_RELAX_END_", -+ FALSE, FALSE, FALSE); -+ if (!h) -+ _bfd_generic_link_add_one_symbol -+ (&link_info, link_info.output_bfd, "_RELAX_END_", -+ BSF_GLOBAL | BSF_WEAK, link_info.output_bfd->sections, -+ 0, (const char *) NULL, FALSE, -+ get_elf_backend_data (link_info.output_bfd)->collect, &h); -+ } - } - - EOF -@@ -217,31 +196,19 @@ PARSE_AND_LIST_PROLOGUE=' - #define OPTION_REDUCE_FP_UPDATE (OPTION_BASELINE + 4) - #define OPTION_NO_REDUCE_FP_UPDATE (OPTION_BASELINE + 5) - #define OPTION_EXPORT_SYMBOLS (OPTION_BASELINE + 6) -- --/* These are only available to ex9. */ --#if defined NDS32_EX9_EXT --#define OPTION_EX9_BASELINE 320 --#define OPTION_EX9_TABLE (OPTION_EX9_BASELINE + 1) --#define OPTION_NO_EX9_TABLE (OPTION_EX9_BASELINE + 2) --#define OPTION_EXPORT_EX9 (OPTION_EX9_BASELINE + 3) --#define OPTION_IMPORT_EX9 (OPTION_EX9_BASELINE + 4) --#define OPTION_UPDATE_EX9 (OPTION_EX9_BASELINE + 5) --#define OPTION_EX9_LIMIT (OPTION_EX9_BASELINE + 6) --#define OPTION_EX9_LOOP (OPTION_EX9_BASELINE + 7) --#endif -- --/* These are only available to link-time ifc. */ --#if defined NDS32_IFC_EXT --#define OPTION_IFC_BASELINE 340 --#define OPTION_JUMP_IFC (OPTION_IFC_BASELINE + 1) --#define OPTION_NO_JUMP_IFC (OPTION_IFC_BASELINE + 2) --#define OPTION_IFC_LOOP (OPTION_IFC_BASELINE + 3) --#endif -+#define OPTION_HYPER_RELAX (OPTION_BASELINE + 7) -+#define OPTION_TLSDESC_TRAMPOLINE (OPTION_BASELINE + 8) -+#define OPTION_NO_TLSDESC_TRAMPOLINE (OPTION_BASELINE + 9) -+#define OPTION_SET_ABI (OPTION_BASELINE + 10) - ' - PARSE_AND_LIST_LONGOPTS=' - { "mfp-as-gp", no_argument, NULL, OPTION_FP_AS_GP}, - { "mno-fp-as-gp", no_argument, NULL, OPTION_NO_FP_AS_GP}, - { "mexport-symbols", required_argument, NULL, OPTION_EXPORT_SYMBOLS}, -+ { "mhyper-relax", required_argument, NULL, OPTION_HYPER_RELAX}, -+ { "mtlsdesc-trampoline", no_argument, NULL, OPTION_TLSDESC_TRAMPOLINE}, -+ { "mno-tlsdesc-trampoline", no_argument, NULL, OPTION_NO_TLSDESC_TRAMPOLINE}, -+ { "mabi", required_argument, NULL, OPTION_SET_ABI}, - /* These are deprecated options. Remove them in the future. */ - { "mrelax-reduce-fp-update", no_argument, NULL, OPTION_REDUCE_FP_UPDATE}, - { "mrelax-no-reduce-fp-update", no_argument, NULL, OPTION_NO_REDUCE_FP_UPDATE}, -@@ -250,46 +217,14 @@ PARSE_AND_LIST_LONGOPTS=' - { "mrelax-omit-fp", no_argument, NULL, OPTION_FP_AS_GP}, - { "mrelax-no-omit-fp", no_argument, NULL, OPTION_NO_FP_AS_GP}, - { "mgen-symbol-ld-script", required_argument, NULL, OPTION_EXPORT_SYMBOLS}, -- /* These are specific optioins for ex9-ext support. */ --#if defined NDS32_EX9_EXT -- { "mex9", no_argument, NULL, OPTION_EX9_TABLE}, -- { "mno-ex9", no_argument, NULL, OPTION_NO_EX9_TABLE}, -- { "mexport-ex9", required_argument, NULL, OPTION_EXPORT_EX9}, -- { "mimport-ex9", required_argument, NULL, OPTION_IMPORT_EX9}, -- { "mupdate-ex9", no_argument, NULL, OPTION_UPDATE_EX9}, -- { "mex9-limit", required_argument, NULL, OPTION_EX9_LIMIT}, -- { "mex9-loop-aware", no_argument, NULL, OPTION_EX9_LOOP}, --#endif -- /* These are specific optioins for ifc-ext support. */ --#if defined NDS32_IFC_EXT -- { "mifc", no_argument, NULL, OPTION_JUMP_IFC}, -- { "mno-ifc", no_argument, NULL, OPTION_NO_JUMP_IFC}, -- { "mifc-loop-aware", no_argument, NULL, OPTION_IFC_LOOP}, --#endif - ' - PARSE_AND_LIST_OPTIONS=' - fprintf (file, _("\ - --m[no-]fp-as-gp Disable/enable fp-as-gp relaxation\n\ - --mexport-symbols=FILE Exporting symbols in linker script\n\ -+ --mhyper-relax=level Adjust relax level (low|medium|high). default: medium\n\ -+ --m[no-]tlsdesc-trampoline Disable/enable TLS DESC trampoline\n\ - ")); -- --#if defined NDS32_EX9_EXT -- fprintf (file, _("\ -- --m[no-]ex9 Disable/enable link-time EX9 relaxation\n\ -- --mexport-ex9=FILE Export EX9 table after linking\n\ -- --mimport-ex9=FILE Import Ex9 table for EX9 relaxation\n\ -- --mupdate-ex9 Update existing EX9 table\n\ -- --mex9-limit=NUM Maximum number of entries in ex9 table\n\ -- --mex9-loop-aware Avoid generate EX9 instruction inside loop\n\ --")); --#endif -- --#if defined NDS32_IFC_EXT -- fprintf (file, _("\ -- --m[no-]ifc Disable/enable link-time IFC optimization\n\ -- --mifc-loop-aware Avoid generate IFC instruction inside loop\n\ --")); --#endif - ' - PARSE_AND_LIST_ARGS_CASES=' - case OPTION_BASELINE: -@@ -319,65 +254,33 @@ PARSE_AND_LIST_ARGS_CASES=' - einfo (_("%P%F: cannot open map file %s: %E.\n"), optarg); - } - break; --#if defined NDS32_EX9_EXT -- case OPTION_EX9_TABLE: -- target_optimize = target_optimize | NDS32_RELAX_EX9_ON; -- break; -- case OPTION_NO_EX9_TABLE: -- target_optimize = target_optimize & (!NDS32_RELAX_EX9_ON); -- break; -- case OPTION_EXPORT_EX9: -+ case OPTION_HYPER_RELAX: - if (!optarg) -- einfo (_("Missing file for --mexport-ex9=.\n")); -+ einfo (_("Valid arguments to --mhyper-relax=(low|medium|high).\n")); - -- if(strcmp (optarg, "-") == 0) -- ex9_export_file = stdout; -+ if (strcmp (optarg, "low") == 0) -+ hyper_relax = 0; -+ else if (strcmp (optarg, "medium") == 0) -+ hyper_relax = 1; -+ else if (strcmp (optarg, "high") == 0) -+ hyper_relax = 2; - else -- { -- ex9_export_file = fopen (optarg, "wb"); -- if(ex9_export_file == NULL) -- einfo (_("ERROR %P%F: cannot open ex9 export file %s.\n"), optarg); -- } -- break; -- case OPTION_IMPORT_EX9: -- if (!optarg) -- einfo (_("Missing file for --mimport-ex9=.\n")); -+ einfo (_("Valid arguments to --mhyper-relax=(low|medium|high).\n")); - -- ex9_import_file = fopen (optarg, "rb+"); -- if(ex9_import_file == NULL) -- einfo (_("ERROR %P%F: cannot open ex9 import file %s.\n"), optarg); -+ break; -+ case OPTION_TLSDESC_TRAMPOLINE: -+ tls_desc_trampoline = 1; - break; -- case OPTION_UPDATE_EX9: -- update_ex9_table = 1; -- break; -- case OPTION_EX9_LIMIT: -- if (optarg) -- { -- ex9_limit = atoi (optarg); -- if (ex9_limit > 511 || ex9_limit < 1) -- { -- einfo (_("ERROR: the range of ex9_limit must between 1 and 511\n")); -- exit (1); -- } -- } -+ case OPTION_NO_TLSDESC_TRAMPOLINE: -+ tls_desc_trampoline = 0; - break; -- case OPTION_EX9_LOOP: -- target_optimize = target_optimize | NDS32_RELAX_EX9_ON; -- ex9_loop_aware = 1; -- break; --#endif --#if defined NDS32_IFC_EXT -- case OPTION_JUMP_IFC: -- target_optimize = target_optimize | NDS32_RELAX_JUMP_IFC_ON; -- break; -- case OPTION_NO_JUMP_IFC: -- target_optimize = target_optimize & (!NDS32_RELAX_JUMP_IFC_ON); -- break; -- case OPTION_IFC_LOOP: -- target_optimize = target_optimize | NDS32_RELAX_JUMP_IFC_ON; -- ifc_loop_aware = 1; -+ case OPTION_SET_ABI: -+ if (strcmp (optarg, "AABI") != 0 -+ && strcmp (optarg, "V2FP+") != 0) -+ einfo (_("Valid arguments to --mabi=(AABI|V2FP+).\n")); -+ else -+ set_output_abi = optarg; - break; --#endif - ' - LDEMUL_AFTER_OPEN=nds32_elf_after_open - LDEMUL_AFTER_PARSE=nds32_elf_after_parse -diff --git binutils-2.30/ld/scripttempl/nds32elf.sc binutils-2.30-nds32/ld/scripttempl/nds32elf.sc -index dd9a0c11f7..6c09275e4d 100644 ---- binutils-2.30/ld/scripttempl/nds32elf.sc -+++ binutils-2.30-nds32/ld/scripttempl/nds32elf.sc -@@ -185,7 +185,7 @@ test "${LARGE_SECTIONS}" = "yes" && LARGE_SECTIONS=" - *(.ldata${RELOCATING+ .ldata.* .gnu.linkonce.l.*}) - ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);} - }" --if test "${ENABLE_INITFINI_ARRAY}" = "yes"; then -+if test "${ENABLE_INITFINI_ARRAY}" = "no"; then - SORT_INIT_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))" - SORT_FINI_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))" - CTORS_IN_INIT_ARRAY="EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o $OTHER_EXCLUDE_FILES) .ctors" -@@ -335,6 +335,9 @@ eval $COMBRELOCCAT <> ldscripts/dyntmp.$$ < - #include - #include -+#include - - #include "safe-ctype.h" - #include "libiberty.h" -@@ -43,8 +44,8 @@ - #define MAX_KEYWORD_LEN 32 - /* This LEX is a plain char or operand. */ - #define IS_LEX_CHAR(c) (((c) >> 7) == 0) --#define LEX_SET_FIELD(c) ((c) | SYN_FIELD) --#define LEX_GET_FIELD(c) operand_fields[((c) & 0xff)] -+#define LEX_SET_FIELD(k,c) ((c) | (((k) + 1) << 8)) -+#define LEX_GET_FIELD(k,c) (nds32_field_table[k])[((c) & 0xff)] - /* Get the char in this lexical element. */ - #define LEX_CHAR(c) ((c) & 0xff) - -@@ -60,7 +61,8 @@ static int parse_fe5 (struct nds32_asm_desc *, struct nds32_asm_insn *, - char **, int64_t *); - static int parse_pi5 (struct nds32_asm_desc *, struct nds32_asm_insn *, - char **, int64_t *); --static int parse_aext_reg (char **, int *, int); -+static int parse_aext_reg (struct nds32_asm_desc *, char **, -+ int *, int); - static int parse_a30b20 (struct nds32_asm_desc *, struct nds32_asm_insn *, - char **, int64_t *); - static int parse_rt21 (struct nds32_asm_desc *, struct nds32_asm_insn *, -@@ -159,6 +161,7 @@ const field_t operand_fields[] = - {"i14s1", 0, 14, 1, HW_INT, NULL}, - {"i15s1", 0, 15, 1, HW_INT, NULL}, - {"i16s1", 0, 16, 1, HW_INT, NULL}, -+ {"i16u5", 5, 16, 0, HW_UINT, NULL}, - {"i18s1", 0, 18, 1, HW_INT, NULL}, - {"i24s1", 0, 24, 1, HW_INT, NULL}, - {"i8s2", 0, 8, 2, HW_INT, NULL}, -@@ -170,7 +173,6 @@ const field_t operand_fields[] = - {"i5u", 0, 5, 0, HW_UINT, NULL}, - {"ib5u", 10, 5, 0, HW_UINT, NULL}, /* imm5 field in ALU. */ - {"ib5s", 10, 5, 0, HW_INT, NULL}, /* imm5 field in ALU. */ -- {"i9u", 0, 9, 0, HW_UINT, NULL}, /* for ex9.it. */ - {"ia3u", 3, 3, 0, HW_UINT, NULL}, /* for bmski33, fexti33. */ - {"i8u", 0, 8, 0, HW_UINT, NULL}, - {"ib8u", 7, 8, 0, HW_UINT, NULL}, /* for ffbi. */ -@@ -183,6 +185,8 @@ const field_t operand_fields[] = - {"i7u2", 0, 7, 2, HW_UINT, NULL}, - {"i5u3", 0, 5, 3, HW_UINT, NULL}, /* for pop25/pop25. */ - {"i15s3", 0, 15, 3, HW_INT, NULL}, /* for dprefi.d. */ -+ {"ib4u", 10, 4, 0, HW_UINT, NULL}, /* imm5 field in ALU. */ -+ {"ib2u", 10, 2, 0, HW_UINT, NULL}, /* imm5 field in ALU. */ - - {"a_rt", 15, 5, 0, HW_GPR, NULL}, /* for audio-extension. */ - {"a_ru", 10, 5, 0, HW_GPR, NULL}, /* for audio-extension. */ -@@ -199,7 +203,9 @@ const field_t operand_fields[] = - {"aridx", 0, 5, 0, HW_AEXT_ARIDX, NULL}, /* for audio-extension. */ - {"aridx2", 0, 5, 0, HW_AEXT_ARIDX2, NULL}, /* for audio-extension. */ - {"aridxi", 16, 4, 0, HW_AEXT_ARIDXI, NULL}, /* for audio-extension. */ -- {"imm16", 0, 16, 0, HW_UINT, NULL}, /* for audio-extension. */ -+ {"aridxi_mx", 16, 4, 0, HW_AEXT_ARIDXI_MX, NULL}, /* for audio-extension. */ -+ {"imm16s", 0, 16, 0, HW_INT, NULL}, /* for audio-extension. */ -+ {"imm16u", 0, 16, 0, HW_UINT, NULL}, /* for audio-extension. */ - {"im5_i", 0, 5, 0, HW_AEXT_IM_I, parse_im5_ip}, /* for audio-extension. */ - {"im5_m", 0, 5, 0, HW_AEXT_IM_M, parse_im5_mr}, /* for audio-extension. */ - {"im6_ip", 0, 2, 0, HW_AEXT_IM_I, parse_im6_ip}, /* for audio-extension. */ -@@ -209,6 +215,7 @@ const field_t operand_fields[] = - {"cp45", 4, 2, 0, HW_CP, NULL}, /* for cop-extension. */ - {"i12u", 8, 12, 0, HW_UINT, NULL}, /* for cop-extension. */ - {"cpi19", 6, 19, 0, HW_UINT, NULL}, /* for cop-extension. */ -+ - {NULL, 0, 0, 0, 0, NULL} - }; - -@@ -294,7 +301,6 @@ struct nds32_opcode nds32_opcodes[] = - {"jrnez", "%rb", JREG (JRNEZ), 4, ATTR (BRANCH) | ATTR_V3, 0, NULL, 0, NULL}, - {"jralnez", "%rt,%rb", JREG (JRALNEZ), 4, ATTR (BRANCH) | ATTR_V3, 0, NULL, 0, NULL}, - {"ret", "%rb", JREG (JR) | JREG_RET, 4, ATTR (BRANCH) | ATTR_ALL, 0, NULL, 0, NULL}, -- {"ifret", "", JREG (JR) | JREG_IFC | JREG_RET, 4, ATTR (BRANCH) | ATTR (IFC_EXT), 0, NULL, 0, NULL}, - {"jral", "%rb", JREG (JRAL) | RT (30), 4, ATTR (BRANCH) | ATTR_ALL, 0, NULL, 0, NULL}, - {"jralnez", "%rb", JREG (JRALNEZ) | RT (30), 4, ATTR (BRANCH) | ATTR_V3, 0, NULL, 0, NULL}, - {"ret", "", JREG (JR) | JREG_RET | RB (30), 4, ATTR (BRANCH) | ATTR_ALL, 0, NULL, 0, NULL}, -@@ -306,8 +312,6 @@ struct nds32_opcode nds32_opcodes[] = - {"beq", "%rt,%ra,%i14s1", OP6 (BR1), 4, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, - {"bne", "%rt,%ra,%i14s1", OP6 (BR1) | N32_BIT (14), 4, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, - /* seg-BR2. */ --#define BR2(sub) (OP6 (BR2) | (N32_BR2_ ## sub << 16)) -- {"ifcall", "%i16s1", BR2 (IFCALL), 4, ATTR (IFC_EXT), 0, NULL, 0, NULL}, - {"beqz", "%rt,%i16s1", BR2 (BEQZ), 4, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, - {"bnez", "%rt,%i16s1", BR2 (BNEZ), 4, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, - {"bgez", "%rt,%i16s1", BR2 (BGEZ), 4, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, -@@ -377,10 +381,10 @@ struct nds32_opcode nds32_opcodes[] = - {"bse", "=rt,%ra,=rb", ALU2 (BSE), 4, ATTR (PERF2_EXT), 0, NULL, 0, NULL}, - {"bsp", "=rt,%ra,=rb", ALU2 (BSP), 4, ATTR (PERF2_EXT), 0, NULL, 0, NULL}, - {"ffzmism", "=rt,%ra,%rb", ALU2 (FFZMISM), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, -- {"mfusr", "=rt,%usr", ALU2 (MFUSR), 4, ATTR_V3MEX_V1, 0, NULL, 0, NULL}, -- {"mtusr", "%rt,%usr", ALU2 (MTUSR), 4, ATTR_V3MEX_V1, 0, NULL, 0, NULL}, -- {"mfusr", "=rt,%ridx", ALU2 (MFUSR), 4, ATTR_V3MEX_V1, 0, NULL, 0, NULL}, -- {"mtusr", "%rt,%ridx", ALU2 (MTUSR), 4, ATTR_V3MEX_V1, 0, NULL, 0, NULL}, -+ {"mfusr", "=rt,%usr", ALU2 (MFUSR), 4, ATTR_ALL, 0, NULL, 0, NULL}, -+ {"mtusr", "%rt,%usr", ALU2 (MTUSR), 4, ATTR_ALL, 0, NULL, 0, NULL}, -+ {"mfusr", "=rt,%ridx", ALU2 (MFUSR), 4, ATTR_ALL, 0, NULL, 0, NULL}, -+ {"mtusr", "%rt,%ridx", ALU2 (MTUSR), 4, ATTR_ALL, 0, NULL, 0, NULL}, - {"mul", "=rt,%ra,%rb", ALU2 (MUL), 4, ATTR_ALL, 0, NULL, 0, NULL}, - {"madds64", "=dt,%ra,%rb", ALU2 (MADDS64), 4, ATTR (MAC) | ATTR_ALL, 0, NULL, 0, NULL}, - {"madd64", "=dt,%ra,%rb", ALU2 (MADD64), 4, ATTR (MAC) | ATTR_ALL, 0, NULL, 0, NULL}, -@@ -392,22 +396,22 @@ struct nds32_opcode nds32_opcodes[] = - - /* seg-ALU2_FFBI. */ - {"ffb", "=rt,%ra,%rb", ALU2 (FFB), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, -- {"ffbi", "=rt,%ra,%ib8u", ALU2 (FFBI) | N32_BIT (6), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, -+ {"ffbi", "=rt,%ra,%ib8u", ALU2_1 (FFBI), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, - /* seg-ALU2_FLMISM. */ - {"ffmism", "=rt,%ra,%rb", ALU2 (FFMISM), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, -- {"flmism", "=rt,%ra,%rb", ALU2 (FLMISM) | N32_BIT (6), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, -+ {"flmism", "=rt,%ra,%rb", ALU2_1 (FLMISM), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, - /* seg-ALU2_MULSR64. */ - {"mults64", "=dt,%ra,%rb", ALU2 (MULTS64), 4, ATTR_ALL, 0, NULL, 0, NULL}, -- {"mulsr64", "=rt,%ra,%rb", ALU2 (MULSR64)| N32_BIT (6), 4, ATTR_V3MEX_V2, 0, NULL, 0, NULL}, -+ {"mulsr64", "=rt,%ra,%rb", ALU2_1 (MULSR64), 4, ATTR_V3MEX_V2, 0, NULL, 0, NULL}, - /* seg-ALU2_MULR64. */ - {"mult64", "=dt,%ra,%rb", ALU2 (MULT64), 4, ATTR_ALL, 0, NULL, 0, NULL}, -- {"mulr64", "=rt,%ra,%rb", ALU2 (MULR64) | N32_BIT (6), 4, ATTR_V3MEX_V2, 0, NULL, 0, NULL}, -+ {"mulr64", "=rt,%ra,%rb", ALU2_1 (MULR64), 4, ATTR_V3MEX_V2, 0, NULL, 0, NULL}, - /* seg-ALU2_MADDR32. */ - {"madd32", "=dt,%ra,%rb", ALU2 (MADD32), 4, ATTR (MAC) | ATTR (DXREG) | ATTR_ALL, 0, NULL, 0, NULL}, -- {"maddr32", "=rt,%ra,%rb", ALU2 (MADDR32) | N32_BIT (6), 4, ATTR (MAC) | ATTR_V2UP, 0, NULL, 0, NULL}, -+ {"maddr32", "=rt,%ra,%rb", ALU2_1 (MADDR32), 4, ATTR (MAC) | ATTR_V2UP, 0, NULL, 0, NULL}, - /* seg-ALU2_MSUBR32. */ - {"msub32", "=dt,%ra,%rb", ALU2 (MSUB32), 4, ATTR (MAC) | ATTR (DXREG) | ATTR_ALL, 0, NULL, 0, NULL}, -- {"msubr32", "=rt,%ra,%rb", ALU2 (MSUBR32) | N32_BIT (6), 4, ATTR (MAC) | ATTR_V2UP, 0, NULL, 0, NULL}, -+ {"msubr32", "=rt,%ra,%rb", ALU2_1 (MSUBR32), 4, ATTR (MAC) | ATTR_V2UP, 0, NULL, 0, NULL}, - - /* seg-MISC. */ - {"standby", "%stdby_st", MISC (STANDBY), 4, ATTR_ALL, 0, NULL, 0, NULL}, -@@ -439,8 +443,12 @@ struct nds32_opcode nds32_opcodes[] = - {"tlbop", "%ra,%tlbop_st", MISC (TLBOP), 4, ATTR_ALL, 0, NULL, 0, NULL}, - {"tlbop", "%ra,%tlbop_stx", MISC (TLBOP), 4, ATTR_ALL, 0, NULL, 0, NULL}, - {"tlbop", "%rt,%ra,pb", MISC (TLBOP) | (5 << 5), 4, ATTR_ALL, 0, NULL, 0, NULL}, -+ {"tlbop", "%rt,%ra,probe", MISC (TLBOP) | (5 << 5), 4, ATTR_ALL, 0, NULL, 0, NULL}, - {"tlbop", "flua", MISC (TLBOP) | (7 << 5), 4, ATTR_ALL, 0, NULL, 0, NULL}, - {"tlbop", "flushall", MISC (TLBOP) | (7 << 5), 4, ATTR_ALL, 0, NULL, 0, NULL}, -+ /* seg-MISC_SPECL. */ -+ {"isps", "%i16u5", MISC (SPECL), 4, ATTR_ALL, 0, NULL, 0, NULL}, -+ {"isps", "", MISC (SPECL), 4, ATTR_ALL, 0, NULL, 0, NULL}, - - /* seg-MEM. */ - {"lb", "=rt,[%ra+(%rb<<%sv)]", MEM (LB), 4, ATTR_ALL, 0, NULL, 0, NULL}, -@@ -542,7 +550,6 @@ struct nds32_opcode nds32_opcodes[] = - {"fnmsubs", "=fst,%fsa,%fsb", FS1 (FNMSUBS), 4, ATTR (FPU) | ATTR (FPU_SP_EXT), 0, NULL, 0, NULL}, - {"fmuls", "=fst,%fsa,%fsb", FS1 (FMULS), 4, ATTR (FPU) | ATTR (FPU_SP_EXT), 0, NULL, 0, NULL}, - {"fdivs", "=fst,%fsa,%fsb", FS1 (FDIVS), 4, ATTR (FPU) | ATTR (FPU_SP_EXT), 0, NULL, 0, NULL}, -- - /* seg-FPU_FS1_F2OP. */ - {"fs2d", "=fdt,%fsa", FS1_F2OP (FS2D), 4, ATTR (FPU) | ATTR (FPU_SP_EXT) | ATTR (FPU_DP_EXT), 0, NULL, 0, NULL}, - {"fsqrts", "=fst,%fsa", FS1_F2OP (FSQRTS), 4, ATTR (FPU) | ATTR (FPU_SP_EXT), 0, NULL, 0, NULL}, -@@ -601,7 +608,6 @@ struct nds32_opcode nds32_opcodes[] = - {"fmfcfg", "=rt", MFCP_XR(FMFCFG), 4, ATTR (FPU), 0, NULL, 0, NULL}, - {"fmfcsr", "=rt", MFCP_XR(FMFCSR), 4, ATTR (FPU), 0, NULL, 0, NULL}, - /* seg-FPU_MTCP. */ -- - {"fmtsr", "%rt,=fsa", MTCP (FMTSR), 4, ATTR (FPU), 0, NULL, 0, NULL}, - {"fmtdr", "%rt,=fda", MTCP (FMTDR), 4, ATTR (FPU), 0, NULL, 0, NULL}, - /* seg-FPU_MTCP_XR. */ -@@ -707,14 +713,14 @@ struct nds32_opcode nds32_opcodes[] = - {"swi37", "%rt38,[$fp{+%i7u2}]", 0xb880, 2, ATTR_ALL, USE_REG (28), NULL, 0, NULL}, - /* SEG10_1 if Rt3=5. */ - {"j8", "%i8s1", 0xd500, 2, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, -+ /* SEG11_1 if Rt3=5. */ - /* SEG11_2 bit7~bit5. */ -- {"jr5", "%ra5", 0xdd00, 2, ATTR_ALL, 0, NULL, 0, NULL}, -- {"jral5", "%ra5", 0xdd20, 2, ATTR_ALL, 0, NULL, 0, NULL}, -- {"ex9.it", "%i5u", 0xdd40, 2, ATTR (EX9_EXT), 0, NULL, 0, NULL}, -- {"ret5", "%ra5", 0xdd80, 2, ATTR_ALL, 0, NULL, 0, NULL}, -+ {"jr5", "%ra5", 0xdd00, 2, ATTR_ALL | ATTR (BRANCH), 0, NULL, 0, NULL}, -+ {"jral5", "%ra5", 0xdd20, 2, ATTR_ALL | ATTR (BRANCH), 0, NULL, 0, NULL}, -+ {"ret5", "%ra5", 0xdd80, 2, ATTR_ALL | ATTR (BRANCH), 0, NULL, 0, NULL}, - {"add5.pc", "%ra5", 0xdda0, 2, ATTR_V3, 0, NULL, 0, NULL}, - /* SEG11_3 if Ra5=30. */ -- {"ret5", "", 0xdd80 | RA5 (30), 2, ATTR_ALL, 0, NULL, 0, NULL}, -+ {"ret5", "", 0xdd80 | RA5 (30), 2, ATTR_ALL | ATTR (BRANCH), 0, NULL, 0, NULL}, - /* SEG12 bit10~bit9. */ - {"slts45", "%rt4,%ra5", 0xe000, 2, ATTR_ALL, DEF_REG (15), NULL, 0, NULL}, - {"slt45", "%rt4,%ra5", 0xe200, 2, ATTR_ALL, DEF_REG (15), NULL, 0, NULL}, -@@ -727,13 +733,10 @@ struct nds32_opcode nds32_opcodes[] = - /* SEG13_1 bit8. */ - {"beqzs8", "%i8s1", 0xe800, 2, ATTR_PCREL | ATTR_ALL, USE_REG (15), NULL, 0, NULL}, - {"bnezs8", "%i8s1", 0xe900, 2, ATTR_PCREL | ATTR_ALL, USE_REG (15), NULL, 0, NULL}, -- /* SEG13_2 bit8~bit5. */ -- {"ex9.it", "%i9u", 0xea00, 2, ATTR (EX9_EXT), 0, NULL, 0, NULL}, - /* SEG14 bit7. */ - {"lwi37.sp", "=rt38,[+%i7u2]", 0xf000, 2, ATTR_V2UP, USE_REG (31), NULL, 0, NULL}, - {"swi37.sp", "%rt38,[+%i7u2]", 0xf080, 2, ATTR_V2UP, USE_REG (31), NULL, 0, NULL}, - /* SEG15 bit10~bit9. */ -- {"ifcall9", "%i9u1", 0xf800, 2, ATTR (IFC_EXT), 0, NULL, 0, NULL}, - {"movpi45", "=rt4,%pi5", 0xfa00, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, - /* SEG15_1 bit8. */ - {"movd44", "=rt5e,%ra5e", 0xfd00, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, -@@ -749,7 +752,7 @@ struct nds32_opcode nds32_opcodes[] = - {"fexti33", "=rt3,%ia3u", 0x9607, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, - /* SEG-PUSHPOP25 bit8~bit7. */ - {"push25", "%re2,%i5u3", 0xfc00, 2, ATTR_V3MUP, USE_REG (31) | DEF_REG (31), NULL, 0, NULL}, -- {"pop25", "%re2,%i5u3", 0xfc80, 2, ATTR_V3MUP, USE_REG (31) | DEF_REG (31), NULL, 0, NULL}, -+ {"pop25", "%re2,%i5u3", 0xfc80, 2, ATTR_V3MUP | ATTR (BRANCH), USE_REG (31) | DEF_REG (31), NULL, 0, NULL}, - /* SEG-MISC33 bit2~bit0. */ - {"neg33", "=rt3,%ra3", 0xfe02, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, - {"not33", "=rt3,%ra3", 0xfe03, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, -@@ -759,29 +762,31 @@ struct nds32_opcode nds32_opcodes[] = - {"or33", "=rt3,%ra3", 0xfe07, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, - /* SEG-Alias instructions. */ - {"nop16", "", 0x9200, 2, ATTR_ALL, 0, NULL, 0, NULL}, -- {"ifret16", "", 0x83ff, 2, ATTR (IFC_EXT), 0, NULL, 0, NULL}, - - /* Saturation ext ISA. */ - {"kaddw", "=rt,%ra,%rb", ALU2 (KADD), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"ksubw", "=rt,%ra,%rb", ALU2 (KSUB), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -- {"kaddh", "=rt,%ra,%rb", ALU2 (KADD) | N32_BIT (6), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -- {"ksubh", "=rt,%ra,%rb", ALU2 (KSUB) | N32_BIT (6), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -+ {"kaddh", "=rt,%ra,%rb", ALU2_1 (KADD), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -+ {"ksubh", "=rt,%ra,%rb", ALU2_1 (KSUB), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"kdmbb", "=rt,%ra,%rb", ALU2 (KMxy), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"kdmbt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (6), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"kdmtb", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (7), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"kdmtt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (6) | N32_BIT (7), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"khmbb", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (8), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -- {"khmbt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (8) | N32_BIT (6), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -- {"khmtb", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (8) | N32_BIT (7), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -- {"khmtt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (8) | N32_BIT (6) | N32_BIT (7), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -- {"kslraw", "=rt,%ra,%rb", ALU2 (KSLRA), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -- {"rdov", "=rt", ALU2 (MFUSR) | N32_BIT (6) | ( 0x1e << 15), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -- {"clrov", "", ALU2 (MTUSR) | N32_BIT (6) | ( 0x1e << 15), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -+ {"khmbt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (6) | N32_BIT (8), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -+ {"khmtb", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (7) | N32_BIT (8), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -+ {"khmtt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (6) | N32_BIT (7) | N32_BIT (8), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -+ {"kslraw", "=rt,%ra,%rb", ALU2 (KSLRAW), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -+ {"ksll", "=rt,%ra,%rb", ALU2 (KSLRAW), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -+ {"kslraw.u", "=rt,%ra,%rb", ALU2 (KSLRAWu), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -+ {"rdov", "=rt", ALU2_1 (RDOV) | ( 0x1e << 15), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, -+ {"clrov", "", ALU2_1 (CLROV) | ( 0x1e << 15), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - - /* Audio ext. instructions. */ - -- {"amtari", "%aridxi,%imm16", AUDIO (AMTARI), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMADD */ -+ {"amtari", "%aridxi,%imm16u", AUDIO (AMTARI), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -+ {"amtari", "%aridxi_mx,%imm16s", AUDIO (AMTARI), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -+ /* N32_AEXT_AMADD. */ - {"alr2", "=a_rt,=a_ru,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMADD) | (0x1 << 6), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amaddl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMADD) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amaddl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMADD) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -@@ -791,7 +796,7 @@ struct nds32_opcode nds32_opcodes[] = - {"alr", "=a_rt,[%im5_i],%im5_m", AUDIO (AMADD) | (0x01 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amadd", "=a_dx,%ra,%rb", AUDIO (AMADD), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amabbs", "=a_dx,%ra,%rb", AUDIO (AMADD) | 0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMSUB */ -+ /* N32_AEXT_AMSUB. */ - {"amsubl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMSUB) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amsubl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMSUB) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amsubl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMSUB) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -@@ -800,7 +805,7 @@ struct nds32_opcode nds32_opcodes[] = - {"asr", "%ra,[%im5_i],%im5_m", AUDIO (AMSUB) | (0x01 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amsub", "=a_dx,%ra,%rb", AUDIO (AMSUB), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amabts", "=a_dx,%ra,%rb", AUDIO (AMSUB) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMULT */ -+ /* N32_AEXT_AMULT. */ - {"amultl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMULT) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amultl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMULT) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amultl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMULT) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -@@ -811,14 +816,14 @@ struct nds32_opcode nds32_opcodes[] = - {"amatbs", "=a_dx,%ra,%rb", AUDIO (AMULT) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"asats48", "=a_dx", AUDIO (AMULT) | (0x02 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"awext", "%ra,%a_dx,%i5u", AUDIO (AMULT) | (0x03 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMFAR */ -+ /* N32_AEXT_AMFAR. */ - {"amatts", "=a_dx,%ra,%rb", AUDIO (AMFAR) | 0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"asa", "=dxh,[%im5_i],%im5_m", AUDIO (AMFAR) | (0x01 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amtar", "%ra,%aridx", AUDIO (AMFAR) | (0x02 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amtar2", "%ra,%aridx2", AUDIO (AMFAR) | (0x12 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amfar", "=ra,%aridx", AUDIO (AMFAR) | (0x03 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amfar2", "=ra,%aridx2", AUDIO (AMFAR) | (0x13 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMADDS */ -+ /* N32_AEXT_AMADDS. */ - {"amaddsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMADDS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amaddsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMADDS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amaddsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMADDS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -@@ -828,7 +833,7 @@ struct nds32_opcode nds32_opcodes[] = - {"amadds", "=a_dx,%ra,%rb", AUDIO (AMADDS), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"ambbs", "=a_dx,%ra,%rb", AUDIO (AMADDS) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amawbs", "=a_dx,%ra,%rb", AUDIO (AMADDS) |0x02, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMSUBS */ -+ /* N32_AEXT_AMSUBS. */ - {"amsubsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMSUBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amsubsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMSUBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amsubsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMSUBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -@@ -837,7 +842,7 @@ struct nds32_opcode nds32_opcodes[] = - {"amsubs", "=a_dx,%ra,%rb", AUDIO (AMSUBS), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"ambts", "=a_dx,%ra,%rb", AUDIO (AMSUBS) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amawts", "=a_dx,%ra,%rb", AUDIO (AMSUBS) |0x02, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMULTS */ -+ /* N32_AEXT_AMULTS. */ - {"amultsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMULTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amultsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMULTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amultsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMULTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -@@ -846,7 +851,7 @@ struct nds32_opcode nds32_opcodes[] = - {"amults", "=a_dx,%ra,%rb", AUDIO (AMULTS), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amtbs", "=a_dx,%ra,%rb", AUDIO (AMULTS) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwbs", "=a_dx,%ra,%rb", AUDIO (AMULTS) |0x02, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMNEGS */ -+ /* N32_AEXT_AMNEGS. */ - {"amnegsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMNEGS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amnegsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMNEGS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amnegsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMNEGS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -@@ -855,82 +860,258 @@ struct nds32_opcode nds32_opcodes[] = - {"amnegs", "=a_dx,%ra,%rb", AUDIO (AMNEGS), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amtts", "=a_dx,%ra,%rb", AUDIO (AMNEGS) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwts", "=a_dx,%ra,%rb", AUDIO (AMNEGS) |0x02, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AADDL */ -+ /* N32_AEXT_AADDL. */ - {"aaddl", "=a_rte69,%ra,%rb,%a_rte69_1,[%im5_i],%im5_m", AUDIO (AADDL), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"asubl", "=a_rte69,%ra,%rb,%a_rte69_1,[%im5_i],%im5_m", AUDIO (AADDL) | (0x01 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMAWBS */ -+ /* N32_AEXT_AMAWBS. */ - {"amawbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMAWBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amawbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMAWBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amawbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMAWBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amawbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMAWBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amawbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMAWBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMAWTS */ -+ /* N32_AEXT_AMAWTS. */ - {"amawtsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMAWTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amawtsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMAWTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amawtsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMAWTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amawtsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMAWTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amawtssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMAWTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMWBS */ -+ /* N32_AEXT_AMWBS. */ - {"amwbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMWBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMWBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMWBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMWBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMWBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMWBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMWTS */ -+ /* N32_AEXT_AMWTS. */ - {"amwtsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMWTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwtsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMWTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwtsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMWTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwtsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMWTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amwtssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMWTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMABBS */ -+ /* N32_AEXT_AMABBS. */ - {"amabbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMABBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amabbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMABBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amabbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMABBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amabbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMABBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amabbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMABBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMABTS */ -+ /* N32_AEXT_AMABTS. */ - {"amabtsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMABTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amabtsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMABTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amabtsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMABTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amabtsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMABTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amabtssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMABTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMATBS */ -+ /* N32_AEXT_AMATBS. */ - {"amatbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMATBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amatbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMATBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amatbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMATBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amatbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMATBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amatbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMATBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMATTS */ -+ /* N32_AEXT_AMATTS. */ - {"amattsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMATTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amattsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMATTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amattsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMATTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amattsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMATTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amattssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMATTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMBBS */ -+ /* N32_AEXT_AMBBS. */ - {"ambbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMBBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"ambbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMBBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"ambbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMBBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"ambbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMBBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"ambbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMBBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMBTS */ -+ /* N32_AEXT_AMBTS. */ - {"ambtsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMBTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"ambtsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMBTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"ambtsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMBTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"ambtsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMBTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"ambtssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMBTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMTBS */ -+ /* N32_AEXT_AMTBS. */ - {"amtbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMTBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amtbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMTBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amtbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMTBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amtbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMTBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amtbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMTBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -- /* N32_AEXT_AMTTS */ -+ /* N32_AEXT_AMTTS. */ - {"amttsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMTTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amttsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMTTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amttsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMTTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amttsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMTTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - {"amttssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMTTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, -+ -+ /* DSP ISA. */ -+ /* ALU2 Bit 9-6 = 0000. */ -+ {"add64", "=rt,%ra,%rb", ALU2 (ADD64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sub64", "=rt,%ra,%rb", ALU2 (SUB64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smal", "=rt,%ra,%rb", ALU2 (SMAL), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"radd64", "=rt,%ra,%rb", ALU2 (RADD64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"rsub64", "=rt,%ra,%rb", ALU2 (RSUB64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"uradd64", "=rt,%ra,%rb", ALU2 (URADD64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ursub64", "=rt,%ra,%rb", ALU2 (URSUB64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kadd64", "=rt,%ra,%rb", ALU2 (KADD64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ksub64", "=rt,%ra,%rb", ALU2 (KSUB64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ukadd64", "=rt,%ra,%rb", ALU2 (UKADD64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"uksub64", "=rt,%ra,%rb", ALU2 (UKSUB64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ /* ALU2 Bit 9-6 = 0001. */ -+ {"smar64", "=rt,%ra,%rb", ALU2_1 (SMAR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"umar64", "=rt,%ra,%rb", ALU2_1 (UMAR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smsr64", "=rt,%ra,%rb", ALU2_1 (SMSR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"umsr64", "=rt,%ra,%rb", ALU2_1 (UMSR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmar64", "=rt,%ra,%rb", ALU2_1 (KMAR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ukmar64", "=rt,%ra,%rb", ALU2_1 (UKMAR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmsr64", "=rt,%ra,%rb", ALU2_1 (KMSR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ukmsr64", "=rt,%ra,%rb", ALU2_1 (UKMSR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smalda", "=rt,%ra,%rb", ALU2_1 (SMALDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smslda", "=rt,%ra,%rb", ALU2_1 (SMSLDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smalds", "=rt,%ra,%rb", ALU2_1 (SMALDS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smalbb", "=rt,%ra,%rb", ALU2_1 (SMALBB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smalxda", "=rt,%ra,%rb", ALU2_1 (SMALXDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smslxda", "=rt,%ra,%rb", ALU2_1 (SMSLXDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smalxds", "=rt,%ra,%rb", ALU2_1 (SMALXDS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smalbt", "=rt,%ra,%rb", ALU2_1 (SMALBT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smalbt", "=rt,%ra,%rb", ALU2_1 (SMALBT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smaldrs", "=rt,%ra,%rb", ALU2_1 (SMALDRS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smaltt", "=rt,%ra,%rb", ALU2_1 (SMALTT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smds", "=rt,%ra,%rb", ALU2_1 (SMDS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smxds", "=rt,%ra,%rb", ALU2_1 (SMXDS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smdrs", "=rt,%ra,%rb", ALU2_1 (SMDRS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmadrs", "=rt,%ra,%rb", ALU2_1 (KMADRS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmads", "=rt,%ra,%rb", ALU2_1 (KMADS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmaxds", "=rt,%ra,%rb", ALU2_1 (KMAXDS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ /* DSP MISC. */ -+ {"bpick", "=rt,%ra,%rb,%rd", MISC (BPICK), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ /* ALU_2 KMxy. */ -+ {"khm16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9) | N32_BIT (8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"khmx16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9) | N32_BIT (8) | N32_BIT (6), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smul16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smulx16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9) | N32_BIT (6), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"umul16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9) | N32_BIT (7), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"umulx16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9) | N32_BIT (7) | N32_BIT (6), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ /* ALU2 Bit 9-6 = 0010. */ -+ {"kadd16", "=rt,%ra,%rb", ALU2_2 (KADD16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ksub16", "=rt,%ra,%rb", ALU2_2 (KSUB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kcras16", "=rt,%ra,%rb", ALU2_2 (KCRAS16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kcrsa16", "=rt,%ra,%rb", ALU2_2 (KCRSA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kadd8", "=rt,%ra,%rb", ALU2_2 (KADD8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ksub8", "=rt,%ra,%rb", ALU2_2 (KSUB8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"wext", "=rt,%ra,%rb", ALU2_2 (WEXT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"wexti", "=rt,%ra,%ib5u", ALU2_2 (WEXTI), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ukadd16", "=rt,%ra,%rb", ALU2_2 (UKADD16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"uksub16", "=rt,%ra,%rb", ALU2_2 (UKSUB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ukcras16", "=rt,%ra,%rb", ALU2_2 (UKCRAS16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ukcrsa16", "=rt,%ra,%rb", ALU2_2 (UKCRSA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ukadd8", "=rt,%ra,%rb", ALU2_2 (UKADD8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"uksub8", "=rt,%ra,%rb", ALU2_2 (UKSUB8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ /* ONEOP. */ -+#define DSP_ONEOP(n) ((n) << 10) -+ {"sunpkd810", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x0), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sunpkd820", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x1), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sunpkd830", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x2), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sunpkd831", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x3), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"zunpkd810", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x4), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"zunpkd820", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x5), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"zunpkd830", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x6), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"zunpkd831", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x7), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kabs", "=rt,%ra", ALU2 (ABS), 4, ATTR (PERF_EXT), 0, NULL, 0, NULL}, -+ {"kabs16", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kabs8", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0xc), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"insb", "=rt,%ra,%ib2u", ALU2_2 (ONEOP) | DSP_ONEOP (0x10), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smbb", "=rt,%ra,%rb", ALU2_2 (SMBB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smbt", "=rt,%ra,%rb", ALU2_2 (SMBT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smtt", "=rt,%ra,%rb", ALU2_2 (SMTT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmabb", "=rt,%ra,%rb", ALU2_2 (KMABB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmabt", "=rt,%ra,%rb", ALU2_2 (KMABT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmatt", "=rt,%ra,%rb", ALU2_2 (KMATT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmda", "=rt,%ra,%rb", ALU2_2 (KMDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmxda", "=rt,%ra,%rb", ALU2_2 (KMXDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmada", "=rt,%ra,%rb", ALU2_2 (KMADA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmaxda", "=rt,%ra,%rb", ALU2_2 (KMAXDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmsda", "=rt,%ra,%rb", ALU2_2 (KMSDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmsxda", "=rt,%ra,%rb", ALU2_2 (KMSXDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"radd16", "=rt,%ra,%rb", ALU2_2 (RADD16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"rsub16", "=rt,%ra,%rb", ALU2_2 (RSUB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"rcras16", "=rt,%ra,%rb", ALU2_2 (RCRAS16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"rcrsa16", "=rt,%ra,%rb", ALU2_2 (RCRSA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"radd8", "=rt,%ra,%rb", ALU2_2 (RADD8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"rsub8", "=rt,%ra,%rb", ALU2_2 (RSUB8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"raddw", "=rt,%ra,%rb", ALU2_2 (RADDW), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"rsubw", "=rt,%ra,%rb", ALU2_2 (RSUBW), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"uradd16", "=rt,%ra,%rb", ALU2_2 (URADD16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ursub16", "=rt,%ra,%rb", ALU2_2 (URSUB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"urcras16", "=rt,%ra,%rb", ALU2_2 (URCRAS16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"urcrsa16", "=rt,%ra,%rb", ALU2_2 (URCRSA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"uradd8", "=rt,%ra,%rb", ALU2_2 (URADD8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ursub8", "=rt,%ra,%rb", ALU2_2 (URSUB8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"uraddw", "=rt,%ra,%rb", ALU2_2 (URADDW), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ursubw", "=rt,%ra,%rb", ALU2_2 (URSUBW), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"add16", "=rt,%ra,%rb", ALU2_2 (ADD16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sub16", "=rt,%ra,%rb", ALU2_2 (SUB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"cras16", "=rt,%ra,%rb", ALU2_2 (CRAS16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"crsa16", "=rt,%ra,%rb", ALU2_2 (CRSA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"add8", "=rt,%ra,%rb", ALU2_2 (ADD8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sub8", "=rt,%ra,%rb", ALU2_2 (SUB8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"bitrev", "=rt,%ra,%rb", ALU2_2 (BITREV), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"bitrevi", "=rt,%ra,%ib5u", ALU2_2 (BITREVI), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smmul", "=rt,%ra,%rb", ALU2_2 (SMMUL), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smmul.u", "=rt,%ra,%rb", ALU2_2 (SMMULu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmmac", "=rt,%ra,%rb", ALU2_2 (KMMAC), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmmac.u", "=rt,%ra,%rb", ALU2_2 (KMMACu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmmsb", "=rt,%ra,%rb", ALU2_2 (KMMSB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmmsb.u", "=rt,%ra,%rb", ALU2_2 (KMMSBu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kwmmul", "=rt,%ra,%rb", ALU2_2 (KWMMUL), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kwmmul.u", "=rt,%ra,%rb", ALU2_2 (KWMMULu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ /* ALU2 Bit 9-6 = 0010. */ -+ {"smmwb", "=rt,%ra,%rb", ALU2_3 (SMMWB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smmwb.u", "=rt,%ra,%rb", ALU2_3 (SMMWBu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smmwt", "=rt,%ra,%rb", ALU2_3 (SMMWT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smmwt.u", "=rt,%ra,%rb", ALU2_3 (SMMWTu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmmawb", "=rt,%ra,%rb", ALU2_3 (KMMAWB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmmawb.u", "=rt,%ra,%rb", ALU2_3 (KMMAWBu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmmawt", "=rt,%ra,%rb", ALU2_3 (KMMAWT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kmmawt.u", "=rt,%ra,%rb", ALU2_3 (KMMAWTu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"pktt16", "=rt,%ra,%rb", ALU2_3 (PKTT16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"pktb16", "=rt,%ra,%rb", ALU2_3 (PKTB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"pkbt16", "=rt,%ra,%rb", ALU2_3 (PKBT16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"pkbb16", "=rt,%ra,%rb", ALU2_3 (PKBB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sclip32", "=rt,%ra,%ib5u", ALU2 (CLIPS), 4, ATTR (PERF_EXT), 0, NULL, 0, NULL}, -+ {"sclip16", "=rt,%ra,%ib4u", ALU2_3 (SCLIP16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smax16", "=rt,%ra,%rb", ALU2_3 (SMAX16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smax8", "=rt,%ra,%rb", ALU2_3 (SMAX8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"uclip32", "=rt,%ra,%ib5u", ALU2 (CLIP), 4, ATTR (PERF_EXT), 0, NULL, 0, NULL}, -+ {"uclip16", "=rt,%ra,%ib4u", ALU2_3 (UCLIP16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"umax16", "=rt,%ra,%rb", ALU2_3 (UMAX16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"umax8", "=rt,%ra,%rb", ALU2_3 (UMAX8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sra16", "=rt,%ra,%rb", ALU2_3 (SRA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sra16.u", "=rt,%ra,%rb", ALU2_3 (SRA16u), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"srl16", "=rt,%ra,%rb", ALU2_3 (SRL16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"srl16.u", "=rt,%ra,%rb", ALU2_3 (SRL16u), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sll16", "=rt,%ra,%rb", ALU2_3 (SLL16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kslra16", "=rt,%ra,%rb", ALU2_3 (KSLRA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ksll16", "=rt,%ra,%rb", ALU2_3 (KSLRA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kslra16.u", "=rt,%ra,%rb", ALU2_3 (KSLRA16u), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"sra.u", "=rt,%ra,%rb", ALU2_3 (SRAu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"srai16", "=rt,%ra,%ib4u", ALU2_3 (SRAI16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"srai16.u", "=rt,%ra,%ib4u", ALU2_3 (SRAI16u), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"srli16", "=rt,%ra,%ib4u", ALU2_3 (SRLI16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"srli16.u", "=rt,%ra,%ib4u", ALU2_3 (SRLI16u), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"slli16", "=rt,%ra,%ib4u", ALU2_3 (SLLI16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kslli16", "=rt,%ra,%ib4u", ALU2_3 (KSLLI16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"kslli", "=rt,%ra,%ib5u", ALU2_3 (KSLLI), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"srai.u", "=rt,%ra,%ib5u", ALU2_3 (SRAIu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"cmpeq16", "=rt,%ra,%rb", ALU2_3 (CMPEQ16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"scmplt16", "=rt,%ra,%rb", ALU2_3 (SCMPLT16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"scmple16", "=rt,%ra,%rb", ALU2_3 (SCMPLE16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smin16", "=rt,%ra,%rb", ALU2_3 (SMIN16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"cmpeq8", "=rt,%ra,%rb", ALU2_3 (CMPEQ8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"scmplt8", "=rt,%ra,%rb", ALU2_3 (SCMPLT8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"scmple8", "=rt,%ra,%rb", ALU2_3 (SCMPLE8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"smin8", "=rt,%ra,%rb", ALU2_3 (SMIN8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ucmplt16", "=rt,%ra,%rb", ALU2_3 (UCMPLT16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ucmple16", "=rt,%ra,%rb", ALU2_3 (UCMPLE16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"umin16", "=rt,%ra,%rb", ALU2_3 (UMIN16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ucmplt8", "=rt,%ra,%rb", ALU2_3 (UCMPLT8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"ucmple8", "=rt,%ra,%rb", ALU2_3 (UCMPLE8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"umin8", "=rt,%ra,%rb", ALU2_3 (UMIN8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, -+ {"mtlbi", "%i16s1", BR2 (SOP0) | N32_BIT (20), 4, ATTR (ZOL) | ATTR (DSP_ISAEXT) | ATTR (PCREL), 0, NULL, 0, NULL}, -+ {"mtlei", "%i16s1", BR2 (SOP0) | N32_BIT (21), 4, ATTR (ZOL) | ATTR (DSP_ISAEXT) | ATTR (PCREL), 0, NULL, 0, NULL}, - {NULL, NULL, 0, 0, 0, 0, NULL, 0, NULL}, - }; - -@@ -986,6 +1167,9 @@ const keyword_t keyword_usr[] = - {"d0.hi", USRIDX (0, 1), 0}, - {"d1.lo", USRIDX (0, 2), 0}, - {"d1.hi", USRIDX (0, 3), 0}, -+ {"lb", USRIDX (0, 25), 0}, -+ {"le", USRIDX (0, 26), 0}, -+ {"lc", USRIDX (0, 27), 0}, - {"itb", USRIDX (0, 28), 0}, - {"ifc_lp", USRIDX (0, 29), 0}, - {"pc", USRIDX (0, 31), 0}, -@@ -1040,6 +1224,7 @@ const keyword_t keyword_sr[] = - {"ipc", SRIDX (1, 5, 1), 0}, {"ir9", SRIDX (1, 5, 1), 0}, - {"p_ipc", SRIDX (1, 5, 2), 0}, {"ir10", SRIDX (1, 5, 2), 0}, - {"oipc", SRIDX (1, 5, 3), 0}, {"ir11", SRIDX (1, 5, 3), 0}, -+ {"dipc", SRIDX (1, 5, 3), 0}, - {"p_p0", SRIDX (1, 6, 2), 0}, {"ir12", SRIDX (1, 6, 2), 0}, - {"p_p1", SRIDX (1, 7, 2), 0}, {"ir13", SRIDX (1, 7, 2), 0}, - {"int_mask", SRIDX (1, 8, 0), 0}, {"ir14", SRIDX (1, 8, 0), 0}, -@@ -1059,6 +1244,11 @@ const keyword_t keyword_sr[] = - {"int_pri2", SRIDX (1, 11, 1), 0}, {"ir28", SRIDX (1, 11, 1), 0}, - {"int_trigger", SRIDX (1, 9, 4), 0}, {"ir29", SRIDX (1, 9, 4), 0}, - {"int_gpr_push_dis", SRIDX(1, 1, 3), 0}, {"ir30", SRIDX (1, 1, 3), 0}, -+ {"int_mask3", SRIDX(1, 8, 2), 0}, {"ir31", SRIDX (1, 8, 2), 0}, -+ {"int_pend3", SRIDX(1, 9, 2), 0}, {"ir32", SRIDX (1, 9, 2), 0}, -+ {"int_pri3", SRIDX(1, 11, 2), 0}, {"ir33", SRIDX (1, 11, 2), 0}, -+ {"int_pri4", SRIDX(1, 11, 3), 0}, {"ir34", SRIDX (1, 11, 3), 0}, -+ {"int_trigger2", SRIDX(1, 9, 5), 0}, {"ir35", SRIDX (1, 9, 5), 0}, - - {"mmu_ctl", SRIDX (2, 0, 0), 0}, {"mr0", SRIDX (2, 0, 0), 0}, - {"l1_pptb", SRIDX (2, 1, 0), 0}, {"mr1", SRIDX (2, 1, 0), 0}, -@@ -1077,9 +1267,12 @@ const keyword_t keyword_sr[] = - {"pfmc1", SRIDX (4, 0, 1), 0}, {"pfr1", SRIDX (4, 0, 1), 0}, - {"pfmc2", SRIDX (4, 0, 2), 0}, {"pfr2", SRIDX (4, 0, 2), 0}, - {"pfm_ctl", SRIDX (4, 1, 0), 0}, {"pfr3", SRIDX (4, 1, 0), 0}, -+ {"pft_ctl", SRIDX (4, 2, 0), 0}, {"pfr4", SRIDX (4, 2, 0), 0}, - {"hsp_ctl", SRIDX (4, 6, 0), 0}, {"hspr0", SRIDX (4, 6, 0), 0}, - {"sp_bound", SRIDX (4, 6, 1), 0}, {"hspr1", SRIDX (4, 6, 1), 0}, - {"sp_bound_priv", SRIDX (4, 6, 2), 0},{"hspr2", SRIDX (4, 6, 2), 0}, -+ {"sp_base", SRIDX (4, 6, 3), 0}, {"hspr3", SRIDX (4, 6, 3), 0}, -+ {"sp_base_priv", SRIDX (4, 6, 4), 0}, {"hspr4", SRIDX (4, 6, 4), 0}, - - {"dma_cfg", SRIDX (5, 0, 0), 0}, {"dmar0", SRIDX (5, 0, 0), 0}, - {"dma_gcsw", SRIDX (5, 1, 0), 0}, {"dmar1", SRIDX (5, 1, 0), 0}, -@@ -1102,51 +1295,51 @@ const keyword_t keyword_sr[] = - - {"secur0", SRIDX (6, 0, 0), 0}, {"sfcr", SRIDX (6, 0, 0), 0}, - {"secur1", SRIDX (6, 1, 0), 0}, {"sign", SRIDX (6, 1, 0), 0}, -- {"secur2", SRIDX (6, 1, 1), 0}, {"isign", SRIDX (6, 1, 1), 0}, -- {"secur3", SRIDX (6, 1, 2), 0}, {"p_isign", SRIDX (6, 1, 2), 0}, -+ {"secur2", SRIDX (6, 1, 1), 0}, {"isign", SRIDX (6, 1, 1), 0}, -+ {"secur3", SRIDX (6, 1, 2), 0}, {"p_isign", SRIDX (6, 1, 2), 0}, - - {"prusr_acc_ctl", SRIDX (4, 4, 0), 0}, - {"fucpr", SRIDX (4, 5, 0), 0}, {"fucop_ctl", SRIDX (4, 5, 0), 0}, - - {"bpc0", SRIDX (3, 0, 0), 0}, {"dr0", SRIDX (3, 0, 0), 0}, -- {"bpc1", SRIDX (3, 0, 1), 0}, {"dr1", SRIDX (3, 0, 1), 0}, -- {"bpc2", SRIDX (3, 0, 2), 0}, {"dr2", SRIDX (3, 0, 2), 0}, -- {"bpc3", SRIDX (3, 0, 3), 0}, {"dr3", SRIDX (3, 0, 3), 0}, -- {"bpc4", SRIDX (3, 0, 4), 0}, {"dr4", SRIDX (3, 0, 4), 0}, -- {"bpc5", SRIDX (3, 0, 5), 0}, {"dr5", SRIDX (3, 0, 5), 0}, -- {"bpc6", SRIDX (3, 0, 6), 0}, {"dr6", SRIDX (3, 0, 6), 0}, -- {"bpc7", SRIDX (3, 0, 7), 0}, {"dr7", SRIDX (3, 0, 7), 0}, -- {"bpa0", SRIDX (3, 1, 0), 0}, {"dr8", SRIDX (3, 1, 0), 0}, -- {"bpa1", SRIDX (3, 1, 1), 0}, {"dr9", SRIDX (3, 1, 1), 0}, -- {"bpa2", SRIDX (3, 1, 2), 0}, {"dr10", SRIDX (3, 1, 2), 0}, -- {"bpa3", SRIDX (3, 1, 3), 0}, {"dr11", SRIDX (3, 1, 3), 0}, -- {"bpa4", SRIDX (3, 1, 4), 0}, {"dr12", SRIDX (3, 1, 4), 0}, -- {"bpa5", SRIDX (3, 1, 5), 0}, {"dr13", SRIDX (3, 1, 5), 0}, -- {"bpa6", SRIDX (3, 1, 6), 0}, {"dr14", SRIDX (3, 1, 6), 0}, -- {"bpa7", SRIDX (3, 1, 7), 0}, {"dr15", SRIDX (3, 1, 7), 0}, -- {"bpam0", SRIDX (3, 2, 0), 0}, {"dr16", SRIDX (3, 2, 0), 0}, -- {"bpam1", SRIDX (3, 2, 1), 0}, {"dr17", SRIDX (3, 2, 1), 0}, -- {"bpam2", SRIDX (3, 2, 2), 0}, {"dr18", SRIDX (3, 2, 2), 0}, -- {"bpam3", SRIDX (3, 2, 3), 0}, {"dr19", SRIDX (3, 2, 3), 0}, -- {"bpam4", SRIDX (3, 2, 4), 0}, {"dr20", SRIDX (3, 2, 4), 0}, -- {"bpam5", SRIDX (3, 2, 5), 0}, {"dr21", SRIDX (3, 2, 5), 0}, -- {"bpam6", SRIDX (3, 2, 6), 0}, {"dr22", SRIDX (3, 2, 6), 0}, -- {"bpam7", SRIDX (3, 2, 7), 0}, {"dr23", SRIDX (3, 2, 7), 0}, -- {"bpv0", SRIDX (3, 3, 0), 0}, {"dr24", SRIDX (3, 3, 0), 0}, -- {"bpv1", SRIDX (3, 3, 1), 0}, {"dr25", SRIDX (3, 3, 1), 0}, -- {"bpv2", SRIDX (3, 3, 2), 0}, {"dr26", SRIDX (3, 3, 2), 0}, -- {"bpv3", SRIDX (3, 3, 3), 0}, {"dr27", SRIDX (3, 3, 3), 0}, -- {"bpv4", SRIDX (3, 3, 4), 0}, {"dr28", SRIDX (3, 3, 4), 0}, -- {"bpv5", SRIDX (3, 3, 5), 0}, {"dr29", SRIDX (3, 3, 5), 0}, -- {"bpv6", SRIDX (3, 3, 6), 0}, {"dr30", SRIDX (3, 3, 6), 0}, -- {"bpv7", SRIDX (3, 3, 7), 0}, {"dr31", SRIDX (3, 3, 7), 0}, -- {"bpcid0", SRIDX (3, 4, 0), 0}, {"dr32", SRIDX (3, 4, 0), 0}, -- {"bpcid1", SRIDX (3, 4, 1), 0}, {"dr33", SRIDX (3, 4, 1), 0}, -- {"bpcid2", SRIDX (3, 4, 2), 0}, {"dr34", SRIDX (3, 4, 2), 0}, -- {"bpcid3", SRIDX (3, 4, 3), 0}, {"dr35", SRIDX (3, 4, 3), 0}, -- {"bpcid4", SRIDX (3, 4, 4), 0}, {"dr36", SRIDX (3, 4, 4), 0}, -- {"bpcid5", SRIDX (3, 4, 5), 0}, {"dr37", SRIDX (3, 4, 5), 0}, -- {"bpcid6", SRIDX (3, 4, 6), 0}, {"dr38", SRIDX (3, 4, 6), 0}, -+ {"bpc1", SRIDX (3, 0, 1), 0}, {"dr5", SRIDX (3, 0, 1), 0}, -+ {"bpc2", SRIDX (3, 0, 2), 0}, {"dr10", SRIDX (3, 0, 2), 0}, -+ {"bpc3", SRIDX (3, 0, 3), 0}, {"dr15", SRIDX (3, 0, 3), 0}, -+ {"bpc4", SRIDX (3, 0, 4), 0}, {"dr20", SRIDX (3, 0, 4), 0}, -+ {"bpc5", SRIDX (3, 0, 5), 0}, {"dr25", SRIDX (3, 0, 5), 0}, -+ {"bpc6", SRIDX (3, 0, 6), 0}, {"dr30", SRIDX (3, 0, 6), 0}, -+ {"bpc7", SRIDX (3, 0, 7), 0}, {"dr35", SRIDX (3, 0, 7), 0}, -+ {"bpa0", SRIDX (3, 1, 0), 0}, {"dr1", SRIDX (3, 1, 0), 0}, -+ {"bpa1", SRIDX (3, 1, 1), 0}, {"dr6", SRIDX (3, 1, 1), 0}, -+ {"bpa2", SRIDX (3, 1, 2), 0}, {"dr11", SRIDX (3, 1, 2), 0}, -+ {"bpa3", SRIDX (3, 1, 3), 0}, {"dr16", SRIDX (3, 1, 3), 0}, -+ {"bpa4", SRIDX (3, 1, 4), 0}, {"dr21", SRIDX (3, 1, 4), 0}, -+ {"bpa5", SRIDX (3, 1, 5), 0}, {"dr26", SRIDX (3, 1, 5), 0}, -+ {"bpa6", SRIDX (3, 1, 6), 0}, {"dr31", SRIDX (3, 1, 6), 0}, -+ {"bpa7", SRIDX (3, 1, 7), 0}, {"dr36", SRIDX (3, 1, 7), 0}, -+ {"bpam0", SRIDX (3, 2, 0), 0}, {"dr2", SRIDX (3, 2, 0), 0}, -+ {"bpam1", SRIDX (3, 2, 1), 0}, {"dr7", SRIDX (3, 2, 1), 0}, -+ {"bpam2", SRIDX (3, 2, 2), 0}, {"dr12", SRIDX (3, 2, 2), 0}, -+ {"bpam3", SRIDX (3, 2, 3), 0}, {"dr17", SRIDX (3, 2, 3), 0}, -+ {"bpam4", SRIDX (3, 2, 4), 0}, {"dr22", SRIDX (3, 2, 4), 0}, -+ {"bpam5", SRIDX (3, 2, 5), 0}, {"dr27", SRIDX (3, 2, 5), 0}, -+ {"bpam6", SRIDX (3, 2, 6), 0}, {"dr32", SRIDX (3, 2, 6), 0}, -+ {"bpam7", SRIDX (3, 2, 7), 0}, {"dr37", SRIDX (3, 2, 7), 0}, -+ {"bpv0", SRIDX (3, 3, 0), 0}, {"dr3", SRIDX (3, 3, 0), 0}, -+ {"bpv1", SRIDX (3, 3, 1), 0}, {"dr8", SRIDX (3, 3, 1), 0}, -+ {"bpv2", SRIDX (3, 3, 2), 0}, {"dr13", SRIDX (3, 3, 2), 0}, -+ {"bpv3", SRIDX (3, 3, 3), 0}, {"dr18", SRIDX (3, 3, 3), 0}, -+ {"bpv4", SRIDX (3, 3, 4), 0}, {"dr23", SRIDX (3, 3, 4), 0}, -+ {"bpv5", SRIDX (3, 3, 5), 0}, {"dr28", SRIDX (3, 3, 5), 0}, -+ {"bpv6", SRIDX (3, 3, 6), 0}, {"dr33", SRIDX (3, 3, 6), 0}, -+ {"bpv7", SRIDX (3, 3, 7), 0}, {"dr38", SRIDX (3, 3, 7), 0}, -+ {"bpcid0", SRIDX (3, 4, 0), 0}, {"dr4", SRIDX (3, 4, 0), 0}, -+ {"bpcid1", SRIDX (3, 4, 1), 0}, {"dr9", SRIDX (3, 4, 1), 0}, -+ {"bpcid2", SRIDX (3, 4, 2), 0}, {"dr14", SRIDX (3, 4, 2), 0}, -+ {"bpcid3", SRIDX (3, 4, 3), 0}, {"dr19", SRIDX (3, 4, 3), 0}, -+ {"bpcid4", SRIDX (3, 4, 4), 0}, {"dr24", SRIDX (3, 4, 4), 0}, -+ {"bpcid5", SRIDX (3, 4, 5), 0}, {"dr29", SRIDX (3, 4, 5), 0}, -+ {"bpcid6", SRIDX (3, 4, 6), 0}, {"dr34", SRIDX (3, 4, 6), 0}, - {"bpcid7", SRIDX (3, 4, 7), 0}, {"dr39", SRIDX (3, 4, 7), 0}, - {"edm_cfg", SRIDX (3, 5, 0), 0}, {"dr40", SRIDX (3, 5, 0), 0}, - {"edmsw", SRIDX (3, 6, 0), 0}, {"dr41", SRIDX (3, 6, 0), 0}, -@@ -1360,6 +1553,14 @@ const keyword_t keyword_aridxi[] = - {NULL, 0, 0} - }; - -+const keyword_t keyword_aridxi_mx[] = -+{ -+ {"m1", 9, 0}, {"m2", 10, 0}, {"m3",11, 0}, -+ {"m5",13, 0}, {"m6",14, 0}, {"m7",15, 0}, -+ {NULL, 0, 0} -+}; -+ -+ - const keyword_t *keywords[_HW_LAST] = - { - keyword_gpr, keyword_usr, keyword_dxr, keyword_sr, keyword_fsr, -@@ -1370,15 +1571,21 @@ const keyword_t *keywords[_HW_LAST] = - keyword_cctl_lv, keyword_tlbop_st, keyword_standby_st, - keyword_msync_st, - keyword_im5_i, keyword_im5_m, -- keyword_accumulator, keyword_aridx, keyword_aridx2, keyword_aridxi -+ keyword_accumulator, keyword_aridx, keyword_aridx2, -+ keyword_aridxi, keyword_aridxi_mx - }; -+ -+const keyword_t **nds32_keyword_table[NDS32_CORE_COUNT]; -+static unsigned int nds32_keyword_count_table[NDS32_CORE_COUNT]; -+const field_t *nds32_field_table[NDS32_CORE_COUNT]; -+opcode_t *nds32_opcode_table[NDS32_CORE_COUNT]; - - /* Hash table for syntax lex. */ - static htab_t field_htab; - /* Hash table for opcodes. */ - static htab_t opcode_htab; - /* Hash table for hardware resources. */ --static htab_t hw_ktabs[_HW_LAST]; -+static htab_t *hw_ktabs; - - static hashval_t - htab_hash_hash (const void *p) -@@ -1396,44 +1603,198 @@ htab_hash_eq (const void *p, const void *q) - - return strcmp (name, h->name) == 0; - } -+ - --/* Build a hash table for array BASE. Each element is in size of SIZE, -- and it's first element is a pointer to the key of string. -- It stops inserting elements until reach an NULL key. */ -+/* These functions parse "share library file name" specified for ACE. */ - --static htab_t --build_hash_table (const void *base, size_t size) -+static int -+nds32_parse_ace (const char *str, unsigned id) - { -- htab_t htab; -- hashval_t hash; -- const char *p; -+ void *obj, *dlc = dlopen (str, RTLD_NOW | RTLD_LOCAL); -+ char *err; - -- htab = htab_create_alloc (128, htab_hash_hash, htab_hash_eq, -- NULL, xcalloc, free); -+ if (dlc == NULL) -+ err = (char*) dlerror (); -+ else -+ { -+ obj = dlsym (dlc, "keyword_count"); -+ err = (char*) dlerror (); -+ if (err == NULL) -+ { -+ nds32_keyword_count_table[id] = *(unsigned int*) obj; -+ if (nds32_keyword_count_table[id] != 0) -+ { -+ nds32_keyword_table[id] = -+ (const keyword_t**) dlsym (dlc, "keywords"); -+ err = (char*) dlerror (); -+ } -+ if (err == NULL) -+ { -+ nds32_field_table[id] = -+ (const field_t*) dlsym (dlc, "nds32_ace_field"); -+ err = (char*) dlerror (); -+ } -+ if (err == NULL) -+ { -+ nds32_opcode_table[id] = -+ (opcode_t*) dlsym (dlc, "nds32_ace_opcode"); -+ err = (char*) dlerror (); -+ } -+ -+ if (err == NULL) -+ { -+ if (id != NDS32_ACE) -+ { -+ opcode_t *opc = nds32_opcode_table[id]; -+ unsigned cpid = id - NDS32_COP0; -+ unsigned matched = 0; -+ -+ /* Check whether the coprocessor ID encoded matches. */ -+ /* If not, coprocessor ID is fixed for flexibitlity. */ -+ if (N32_OP6 (opc->value) == N32_OP6_COP) -+ { -+ if (__GF (opc->value, 4, 2) == cpid) -+ matched = 1; -+ } -+ else -+ { -+ if (__GF (opc->value, 13, 2) == cpid) -+ matched = 1; -+ } -+ if (!matched) -+ { -+ for (; opc->opcode != NULL; opc++) -+ { -+ if (N32_OP6 (opc->value) == N32_OP6_COP) -+ opc->value = (opc->value >> 6) | __MF(cpid, 4, 2) -+ | (opc->value & 0xf); -+ else -+ opc->value = (opc->value >> 15) | __MF(cpid, 13, 2) -+ | (opc->value & 0x1fff); -+ } -+ } -+ } -+ -+ return 1; -+ } -+ } -+ } -+ -+ printf("%s\n", err); -+ return 0; -+} -+ -+int -+nds32_parse_udi (const char *str) -+{ -+ return nds32_parse_ace (str, NDS32_ACE); -+} - -- p = base; -- while (1) -+int -+nds32_parse_cop0 (const char *str) -+{ -+ return nds32_parse_ace (str, NDS32_COP0); -+} -+ -+int -+nds32_parse_cop1 (const char *str) -+{ -+ return nds32_parse_ace (str, NDS32_COP1); -+} -+ -+int -+nds32_parse_cop2 (const char *str) -+{ -+ return nds32_parse_ace (str, NDS32_COP2); -+} -+ -+int -+nds32_parse_cop3 (const char *str) -+{ -+ return nds32_parse_ace (str, NDS32_COP3); -+} -+ -+static void -+build_operand_hash_table (void) -+{ -+ unsigned k; -+ -+ field_htab = htab_create_alloc (128, htab_hash_hash, htab_hash_eq, -+ NULL, xcalloc, free); -+ -+ for (k = 0; k < NDS32_CORE_COUNT; k++) - { -- struct nds32_hash_entry **slot; -- struct nds32_hash_entry *h; -+ const field_t *fld; - -- h = (struct nds32_hash_entry *) p; -+ fld = nds32_field_table[k]; -+ if (fld == NULL) -+ continue; - -- if (h->name == NULL) -- break; -+ /* Add op-codes. */ -+ while (fld->name != NULL) -+ { -+ hashval_t hash; -+ const field_t **slot; - -- hash = htab_hash_string (h->name); -- slot = (struct nds32_hash_entry **) -- htab_find_slot_with_hash (htab, h->name, hash, INSERT); -+ hash = htab_hash_string (fld->name); -+ slot = (const field_t **) -+ htab_find_slot_with_hash (field_htab, fld->name, hash, INSERT); - -- assert (slot != NULL && *slot == NULL); -+ assert (slot != NULL && *slot == NULL); -+ *slot = fld++; -+ } -+ } -+} - -- *slot = h; -+static void -+build_keyword_hash_table (void) -+{ -+ unsigned int i, j, k, n; - -- p = p + size; -+ /* Count total keyword tables. */ -+ for (n = 0, i = 0; i < NDS32_CORE_COUNT; i++) -+ { -+ n += nds32_keyword_count_table[i]; - } - -- return htab; -+ /* Allocate space. */ -+ hw_ktabs = (htab_t *) malloc (n * sizeof (struct htab)); -+ for (i = 0; i < n; i++) -+ { -+ hw_ktabs[i] = htab_create_alloc (128, htab_hash_hash, htab_hash_eq, -+ NULL, xcalloc, free); -+ } -+ -+ for (n = 0, k = 0; k < NDS32_CORE_COUNT; k++, n += j) -+ { -+ const keyword_t **kwd; -+ -+ if ((j = nds32_keyword_count_table[k]) == 0) -+ continue; -+ -+ /* Add keywords. */ -+ kwd = nds32_keyword_table[k]; -+ for (i = 0; i < j; i++) -+ { -+ htab_t htab; -+ const keyword_t *kw; -+ -+ kw = kwd[i]; -+ htab = hw_ktabs[n + i]; -+ while (kw->name != NULL) -+ { -+ hashval_t hash; -+ const keyword_t **slot; -+ -+ hash = htab_hash_string (kw->name); -+ slot = (const keyword_t **) -+ htab_find_slot_with_hash (htab, kw->name, hash, INSERT); -+ -+ assert (slot != NULL && *slot == NULL); -+ *slot = kw++; -+ } -+ } -+ } - } - - /* Build the syntax for a given opcode OPC. It parses the string -@@ -1458,36 +1819,31 @@ build_opcode_syntax (struct nds32_opcode *opc) - return; - - opc->syntax = xmalloc (MAX_LEX_NUM * sizeof (lex_t)); -+ memset (opc->syntax, 0, MAX_LEX_NUM * sizeof (lex_t)); - - str = opc->instruction; - plex = opc->syntax; - while (*str) - { -- int fidx; -+ int i, k, fidx; - - switch (*str) - { -- case '%': -- *plex = SYN_INPUT; -- break; -- case '=': -- *plex = SYN_OUTPUT; -- break; -- case '&': -- *plex = SYN_INPUT | SYN_OUTPUT; -- break; -+ case '%': *plex = SYN_INPUT; break; -+ case '=': *plex = SYN_OUTPUT; break; -+ case '&': *plex = SYN_INPUT | SYN_OUTPUT; break; - case '{': -- *plex++ = SYN_LOPT; -- opt++; -- str++; -- continue; -+ *plex++ = SYN_LOPT; -+ opt++; -+ str++; -+ continue; - case '}': -- *plex++ = SYN_ROPT; -- str++; -- continue; -+ *plex++ = SYN_ROPT; -+ str++; -+ continue; - default: -- *plex++ = *str++; -- continue; -+ *plex++ = *str++; -+ continue; - } - str++; - -@@ -1501,14 +1857,25 @@ build_opcode_syntax (struct nds32_opcode *opc) - - hash = htab_hash_string (odstr); - fd = (field_t *) htab_find_with_hash (field_htab, odstr, hash); -- fidx = fd - operand_fields; -- - if (fd == NULL) - { - fprintf (stderr, "Internal error: Unknown operand, %s\n", str); - } -- assert (fd && fidx >= 0 && fidx < (int) ARRAY_SIZE (operand_fields)); -- *plex |= LEX_SET_FIELD (fidx); -+ -+ /* We are not sure how these tables are organized. */ -+ /* Thus, the minimal index should be the right one. */ -+ for (fidx = 256, k = 0, i = 0; i < NDS32_CORE_COUNT; i++) -+ { -+ int tmp; -+ -+ tmp = fd - nds32_field_table[i]; -+ if (tmp >= 0 && tmp < fidx) -+ { -+ fidx = tmp; -+ k = i; -+ } -+ } -+ *plex |= LEX_SET_FIELD (k, fidx); - - str += len; - plex++; -@@ -1519,44 +1886,37 @@ build_opcode_syntax (struct nds32_opcode *opc) - return; - } - --/* Initialize the assembler. It must be called before assembling. */ -- --void --nds32_asm_init (nds32_asm_desc_t *pdesc, int flags) -+static void -+build_opcode_hash_table (void) - { -- int i; -- hashval_t hash; -+ unsigned k; - -- pdesc->flags = flags; -- pdesc->mach = flags & NASM_OPEN_ARCH_MASK; -- -- /* Build keyword tables. */ -- field_htab = build_hash_table (operand_fields, -- sizeof (operand_fields[0])); -- -- for (i = 0; i < _HW_LAST; i++) -- hw_ktabs[i] = build_hash_table (keywords[i], sizeof (keyword_t)); -- -- /* Build opcode table. */ -- opcode_htab = htab_create_alloc (128, htab_hash_hash, htab_hash_eq, -+ opcode_htab = htab_create_alloc (512, htab_hash_hash, htab_hash_eq, - NULL, xcalloc, free); - -- for (i = 0; i < (int) ARRAY_SIZE (nds32_opcodes); i++) -+ for (k = 0; k < NDS32_CORE_COUNT; k++) - { -- struct nds32_opcode **slot; -- struct nds32_opcode *opc; -+ opcode_t *opc; -+ -+ opc = nds32_opcode_table[k]; -+ if (opc == NULL) -+ continue; - -- opc = &nds32_opcodes[i]; -- if ((opc->opcode != NULL) && (opc->instruction != NULL)) -+ /* Add op-codes. */ -+ while ((opc->opcode != NULL) && (opc->instruction != NULL)) - { -+ hashval_t hash; -+ opcode_t **slot; -+ - hash = htab_hash_string (opc->opcode); -- slot = (struct nds32_opcode **) -- htab_find_slot_with_hash (opcode_htab, opc->opcode, hash, INSERT); -+ slot = (opcode_t **) -+ htab_find_slot_with_hash (opcode_htab, opc->opcode, hash, -+ INSERT); - - #define NDS32_PREINIT_SYNTAX - #if defined (NDS32_PREINIT_SYNTAX) -- /* Initial SYNTAX when build opcode table, so bug in syntax can be -- found when initialized rather than used. */ -+ /* Initial SYNTAX when build opcode table, so bug in syntax -+ can be found when initialized rather than used. */ - build_opcode_syntax (opc); - #endif - -@@ -1567,16 +1927,44 @@ nds32_asm_init (nds32_asm_desc_t *pdesc, int flags) - } - else - { -+ opcode_t *ptr; -+ - /* Already exists. Append to the list. */ -- opc = *slot; -- while (opc->next) -- opc = opc->next; -- opc->next = &nds32_opcodes[i]; -+ ptr = *slot; -+ while (ptr->next) -+ ptr = ptr->next; -+ ptr->next = opc; -+ opc->next = NULL; - } -+ opc++; - } - } - } - -+/* Initialize the assembler. It must be called before assembling. */ -+ -+void -+nds32_asm_init (nds32_asm_desc_t *pdesc, int flags) -+{ -+ pdesc->flags = flags; -+ pdesc->mach = flags & NASM_OPEN_ARCH_MASK; -+ -+ /* Setup main core. */ -+ nds32_keyword_table[NDS32_MAIN_CORE] = &keywords[0]; -+ nds32_keyword_count_table[NDS32_MAIN_CORE] = _HW_LAST; -+ nds32_opcode_table[NDS32_MAIN_CORE] = &nds32_opcodes[0]; -+ nds32_field_table[NDS32_MAIN_CORE] = &operand_fields[0]; -+ -+ /* Build operand hash table. */ -+ build_operand_hash_table (); -+ -+ /* Build keyword hash tables. */ -+ build_keyword_hash_table (); -+ -+ /* Build op-code hash table. */ -+ build_opcode_hash_table (); -+} -+ - /* Parse the input and store operand keyword string in ODSTR. - This function is only used for parsing keywords, - HW_INT/HW_UINT are parsed parse_operand callback handler. */ -@@ -1617,6 +2005,11 @@ parse_re (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - if (__GF (pinsn->insn, 20, 5) > (unsigned int) k->value) - return NASM_ERR_OPERAND; - -+ /* Register not allowed in reduced register. */ -+ if ((pdesc->flags & NASM_OPEN_REDUCED_REG) -+ && (k->attr & ATTR (RDREG)) == 0) -+ return NASM_ERR_REG_REDUCED; -+ - *value = k->value; - *pstr = end; - return NASM_R_CONST; -@@ -1644,6 +2037,11 @@ parse_re2 (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - if (k == NULL) - return NASM_ERR_OPERAND; - -+ /* Register not allowed in reduced register. */ -+ if ((pdesc->flags & NASM_OPEN_REDUCED_REG) -+ && (k->attr & ATTR (RDREG)) == 0) -+ return NASM_ERR_REG_REDUCED; -+ - if (k->value == 6) - *value = 0; - else if (k->value == 8) -@@ -1699,7 +2097,8 @@ static int aext_im5_ip = 0; - static int aext_im6_ip = 0; - /* Parse the operand of audio ext. */ - static int --parse_aext_reg (char **pstr, int *value, int hw_res) -+parse_aext_reg (struct nds32_asm_desc *pdesc, char **pstr, -+ int *value, int hw_res) - { - char *end = *pstr; - char odstr[MAX_KEYWORD_LEN]; -@@ -1716,20 +2115,27 @@ parse_aext_reg (char **pstr, int *value, int hw_res) - if (k == NULL) - return NASM_ERR_OPERAND; - -+ if (hw_res == HW_GPR -+ && (pdesc->flags & NASM_OPEN_REDUCED_REG) -+ && (k->attr & ATTR (RDREG)) == 0) -+ return NASM_ERR_REG_REDUCED; -+ - *value = k->value; - *pstr = end; - return NASM_R_CONST; - } - - static int --parse_a30b20 (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_a30b20 (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret; - -- ret = parse_aext_reg (pstr, &rt_value, HW_GPR); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); - -+ if (ret == NASM_ERR_REG_REDUCED) -+ return NASM_ERR_REG_REDUCED; - if ((ret == NASM_ERR_OPERAND) || (rt_value > 15)) - return NASM_ERR_OPERAND; - -@@ -1739,14 +2145,16 @@ parse_a30b20 (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_rt21 (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_rt21 (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret, tmp_value, tmp1, tmp2; - -- ret = parse_aext_reg (pstr, &rt_value, HW_GPR); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); - -+ if (ret == NASM_ERR_REG_REDUCED) -+ return NASM_ERR_REG_REDUCED; - if ((ret == NASM_ERR_OPERAND) || (rt_value > 15)) - return NASM_ERR_OPERAND; - tmp1 = (aext_a30b20 & 0x08); -@@ -1762,14 +2170,16 @@ parse_rt21 (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_rte_start (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_rte_start (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret, tmp1, tmp2; - -- ret = parse_aext_reg (pstr, &rt_value, HW_GPR); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); - -+ if (ret == NASM_ERR_REG_REDUCED) -+ return NASM_ERR_REG_REDUCED; - if ((ret == NASM_ERR_OPERAND) || (rt_value > 15) - || (rt_value & 0x01)) - return NASM_ERR_OPERAND; -@@ -1786,13 +2196,16 @@ parse_rte_start (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_rte_end (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_rte_end (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret, tmp1, tmp2; - -- ret = parse_aext_reg (pstr, &rt_value, HW_GPR); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); -+ -+ if (ret == NASM_ERR_REG_REDUCED) -+ return NASM_ERR_REG_REDUCED; - if ((ret == NASM_ERR_OPERAND) || (rt_value > 15) - || ((rt_value & 0x01) == 0) - || (rt_value != (aext_rte + 1))) -@@ -1801,6 +2214,7 @@ parse_rte_end (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - tmp2 = (rt_value & 0x08); - if (tmp1 != tmp2) - return NASM_ERR_OPERAND; -+ - /* Rt=CONCAT(c, t21, 0), t21:bit11-10. */ - rt_value = (rt_value & 0x06) << 4; - *value = rt_value; -@@ -1808,16 +2222,20 @@ parse_rte_end (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_rte69_start (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_rte69_start (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret; - -- ret = parse_aext_reg (pstr, &rt_value, HW_GPR); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); -+ -+ if (ret == NASM_ERR_REG_REDUCED) -+ return NASM_ERR_REG_REDUCED; - if ((ret == NASM_ERR_OPERAND) - || (rt_value & 0x01)) - return NASM_ERR_OPERAND; -+ - aext_rte = rt_value; - rt_value = (rt_value >> 1); - *value = rt_value; -@@ -1825,17 +2243,21 @@ parse_rte69_start (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_rte69_end (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_rte69_end (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret; - -- ret = parse_aext_reg (pstr, &rt_value, HW_GPR); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); -+ -+ if (ret == NASM_ERR_REG_REDUCED) -+ return NASM_ERR_REG_REDUCED; - if ((ret == NASM_ERR_OPERAND) - || ((rt_value & 0x01) == 0) - || (rt_value != (aext_rte + 1))) - return NASM_ERR_OPERAND; -+ - aext_rte = rt_value; - rt_value = (rt_value >> 1); - *value = rt_value; -@@ -1843,13 +2265,13 @@ parse_rte69_end (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_im5_ip (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_im5_ip (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret, new_value; - -- ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_I); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_I); - if (ret == NASM_ERR_OPERAND) - return NASM_ERR_OPERAND; - /* p = bit[4].bit[1:0], r = bit[4].bit[3:2]. */ -@@ -1861,13 +2283,13 @@ parse_im5_ip (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_im5_mr (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_im5_mr (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret, new_value, tmp1, tmp2; - -- ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_M); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_M); - if (ret == NASM_ERR_OPERAND) - return NASM_ERR_OPERAND; - /* p = bit[4].bit[1:0], r = bit[4].bit[3:2]. */ -@@ -1881,13 +2303,13 @@ parse_im5_mr (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_im6_ip (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_im6_ip (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret; - -- ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_I); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_I); - if ((ret == NASM_ERR_OPERAND) || (rt_value > 3)) - return NASM_ERR_OPERAND; - /* p = 0.bit[1:0]. */ -@@ -1897,13 +2319,13 @@ parse_im6_ip (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_im6_iq (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_im6_iq (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret; - -- ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_I); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_I); - if ((ret == NASM_ERR_OPERAND) || (rt_value < 4)) - return NASM_ERR_OPERAND; - /* q = 1.bit[1:0]. */ -@@ -1914,13 +2336,13 @@ parse_im6_iq (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_im6_mr (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_im6_mr (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret; - -- ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_M); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_M); - if ((ret == NASM_ERR_OPERAND) || (rt_value > 3)) - return NASM_ERR_OPERAND; - /* r = 0.bit[3:2]. */ -@@ -1929,13 +2351,13 @@ parse_im6_mr (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, - } - - static int --parse_im6_ms (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, -+parse_im6_ms (struct nds32_asm_desc *pdesc, - struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, - char **pstr, int64_t *value) - { - int rt_value, ret; - -- ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_M); -+ ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_M); - if ((ret == NASM_ERR_OPERAND) || (rt_value < 4)) - return NASM_ERR_OPERAND; - /* s = 1.bit[5:4]. */ -@@ -1952,9 +2374,9 @@ parse_operand (nds32_asm_desc_t *pdesc, nds32_asm_insn_t *pinsn, - char odstr[MAX_KEYWORD_LEN]; - char *end; - hashval_t hash; -- const field_t *fld = &LEX_GET_FIELD (syn); -+ const field_t *fld = &LEX_GET_FIELD (((syn >> 8) & 0xff) - 1, syn); - keyword_t *k; -- int64_t value; -+ int64_t value = 0; /* 0x100000000; Big enough to overflow. */ - int r; - uint64_t modifier = 0; - -@@ -1963,23 +2385,31 @@ parse_operand (nds32_asm_desc_t *pdesc, nds32_asm_insn_t *pinsn, - if (fld->parse) - { - r = fld->parse (pdesc, pinsn, &end, &value); -- if (r == NASM_ERR_OPERAND) -+ if (r == NASM_ERR_OPERAND || r == NASM_ERR_REG_REDUCED) - { -- pdesc->result = NASM_ERR_OPERAND; -+ pdesc->result = r; - return 0; - } - goto done; - } - -- if (fld->hw_res < _HW_LAST) -+ /* Check valid keyword group. */ -+ if (fld->hw_res < HW_INT) - { -+ int n = 0, i; -+ -+ /* Calculate index of keyword hash table. */ -+ for (i = 0; i < (fld->hw_res >> 8); i++) -+ n += nds32_keyword_count_table[i]; -+ - /* Parse the operand in assembly code. */ - if (*end == '$') - end++; - end = parse_to_delimiter (end, odstr); - - hash = htab_hash_string (odstr); -- k = htab_find_with_hash (hw_ktabs[fld->hw_res], odstr, hash); -+ k = htab_find_with_hash (hw_ktabs[n + (fld->hw_res & 0xff)], odstr, -+ hash); - - if (k == NULL) - { -@@ -2086,7 +2516,7 @@ done: - { - /* Sign-ext the value. */ - if (((value >> 32) == 0) && (value & 0x80000000)) -- value |= (int64_t) -1U << 31; -+ value |= (int64_t)((uint64_t) -1 << 31); - - - /* Shift the value to positive domain. */ -diff --git binutils-2.30/opcodes/nds32-asm.h binutils-2.30-nds32/opcodes/nds32-asm.h -index c67e590c64..ea165833c3 100644 ---- binutils-2.30/opcodes/nds32-asm.h -+++ binutils-2.30-nds32/opcodes/nds32-asm.h -@@ -77,6 +77,8 @@ enum - NASM_ATTR_SATURATION_EXT = 0x0400000, - NASM_ATTR_PCREL = 0x0800000, - NASM_ATTR_GPREL = 0x1000000, -+ NASM_ATTR_DSP_ISAEXT = 0x2000000, -+ NASM_ATTR_ZOL = (1 << 26), - - /* Attributes for relocations. */ - NASM_ATTR_HI20 = 0x10000000, -@@ -84,22 +86,30 @@ enum - NASM_ATTR_LO20 = 0x40000000, - - /* Attributes for registers. */ -- NASM_ATTR_RDREG = 0x000100 -+ NASM_ATTR_RDREG = 0x000100, -+ - }; - -+#define NDS32_CORE_COUNT 6 -+#define NDS32_MAIN_CORE 0 -+#define NDS32_ACE 1 -+#define NDS32_COP0 2 -+#define NDS32_COP1 3 -+#define NDS32_COP2 4 -+#define NDS32_COP3 5 -+ - enum - { -- /* This is a field (operand) of just a separator char. */ -- SYN_FIELD = 0x100, -- - /* This operand is used for input or output. (define or use) */ -- SYN_INPUT = 0x1000, -- SYN_OUTPUT = 0x2000, -- SYN_LOPT = 0x4000, -- SYN_ROPT = 0x8000, -- -- /* Hardware resources. */ -- HW_GPR = 0, -+ SYN_INPUT = 0x10000, -+ SYN_OUTPUT = 0x20000, -+ SYN_LOPT = 0x40000, -+ SYN_ROPT = 0x80000, -+ -+ /* Hardware resources: -+ Current set up allows up to 256 resources for each class -+ defined above. */ -+ HW_GPR = NDS32_MAIN_CORE << 8, - HW_USR, - HW_DXR, - HW_SR, -@@ -128,14 +138,20 @@ enum - HW_AEXT_ARIDX, - HW_AEXT_ARIDX2, - HW_AEXT_ARIDXI, -+ HW_AEXT_ARIDXI_MX, - _HW_LAST, - /* TODO: Maybe we should add a new type to distinguish address and -- const int. Only the former allows symbols and relocations. */ -- HW_INT, -+ const int. Only the former allows symbols and relocations. */ -+ HW_ACE_BASE = NDS32_ACE << 8, -+ HW_COP0_BASE = NDS32_COP0 << 8, -+ HW_COP1_BASE = NDS32_COP1 << 8, -+ HW_COP2_BASE = NDS32_COP2 << 8, -+ HW_COP3_BASE = NDS32_COP3 << 8, -+ HW_INT = 0x1000, - HW_UINT - }; - --/* for audio-extension. */ -+/* For audio-extension. */ - enum - { - N32_AEXT_AMADD = 0, -@@ -159,7 +175,7 @@ enum - N32_AEXT_AMBBS, - N32_AEXT_AMBTS, - N32_AEXT_AMTBS, -- N32_AEXT_AMTTS -+ N32_AEXT_AMTTS, - }; - - /* Macro for instruction attribute. */ -@@ -212,7 +228,7 @@ typedef struct nds32_opcode - struct nds32_opcode *next; - - /* TODO: Extra constrains and verification. -- For example, `mov55 $sp, $sp' is not allowed in v3. */ -+ For example, `mov55 $sp, $sp' is not allowed in v3. */ - } opcode_t; - - typedef struct nds32_asm_insn -@@ -266,6 +282,11 @@ typedef struct nds32_field - - extern void nds32_assemble (nds32_asm_desc_t *, nds32_asm_insn_t *, char *); - extern void nds32_asm_init (nds32_asm_desc_t *, int); -+extern int nds32_parse_udi (const char *); -+extern int nds32_parse_cop0 (const char *); -+extern int nds32_parse_cop1 (const char *); -+extern int nds32_parse_cop2 (const char *); -+extern int nds32_parse_cop3 (const char *); - - #define OP6(op6) (N32_OP6_ ## op6 << 25) - -@@ -277,6 +298,9 @@ extern void nds32_asm_init (nds32_asm_desc_t *, int); - #define SIMD(sub) (OP6 (SIMD) | N32_SIMD_ ## sub) - #define ALU1(sub) (OP6 (ALU1) | N32_ALU1_ ## sub) - #define ALU2(sub) (OP6 (ALU2) | N32_ALU2_ ## sub) -+#define ALU2_1(sub) (OP6 (ALU2) | N32_BIT (6) | N32_ALU2_ ## sub) -+#define ALU2_2(sub) (OP6 (ALU2) | N32_BIT (7) | N32_ALU2_ ## sub) -+#define ALU2_3(sub) (OP6 (ALU2) | N32_BIT (6) | N32_BIT (7) | N32_ALU2_ ## sub) - #define MISC(sub) (OP6 (MISC) | N32_MISC_ ## sub) - #define MEM(sub) (OP6 (MEM) | N32_MEM_ ## sub) - #define FPU_RA_IMMBI(sub) (OP6 (sub) | N32_BIT (12)) -diff --git binutils-2.30/opcodes/nds32-dis.c binutils-2.30-nds32/opcodes/nds32-dis.c -index 418019ae87..bb5106f954 100644 ---- binutils-2.30/opcodes/nds32-dis.c -+++ binutils-2.30-nds32/opcodes/nds32-dis.c -@@ -35,92 +35,71 @@ - /* Get fields macro define. */ - #define MASK_OP(insn, mask) ((insn) & (0x3f << 25 | (mask))) - -+/* For mapping symbol. */ -+enum map_type -+{ -+ MAP_DATA0, -+ MAP_DATA1, -+ MAP_DATA2, -+ MAP_DATA3, -+ MAP_DATA4, -+ MAP_CODE, -+}; -+ -+struct nds32_private_data -+{ -+ /* Whether any mapping symbols are present in the provided symbol -+ table. -1 if we do not know yet, otherwise 0 or 1. */ -+ int has_mapping_symbols; -+ -+ /* Track the last type (although this doesn't seem to be useful). */ -+ enum map_type last_mapping_type; -+ -+ /* Tracking symbol table information. */ -+ int last_symbol_index; -+ bfd_vma last_addr; -+}; - /* Default text to print if an instruction isn't recognized. */ - #define UNKNOWN_INSN_MSG _("*unknown*") -+ - #define NDS32_PARSE_INSN16 0x01 - #define NDS32_PARSE_INSN32 0x02 --#define NDS32_PARSE_EX9IT 0x04 --#define NDS32_PARSE_EX9TAB 0x08 - -+static void print_insn16 (bfd_vma, disassemble_info *, -+ uint32_t, uint32_t); -+static void print_insn32 (bfd_vma, disassemble_info *, uint32_t, -+ uint32_t); -+static uint32_t nds32_mask_opcode (uint32_t); -+static void nds32_special_opcode (uint32_t, struct nds32_opcode **); -+static int get_mapping_symbol_type (struct disassemble_info *, int, -+ enum map_type *); -+static int is_mapping_symbol (struct disassemble_info *, int, -+ enum map_type *); -+ -+extern const field_t *nds32_field_table[NDS32_CORE_COUNT]; -+extern opcode_t *nds32_opcode_table[NDS32_CORE_COUNT]; -+extern keyword_t **nds32_keyword_table[NDS32_CORE_COUNT]; - extern struct nds32_opcode nds32_opcodes[]; - extern const field_t operand_fields[]; --extern const keyword_t *keywords[]; -+extern keyword_t *keywords[]; - extern const keyword_t keyword_gpr[]; --static void print_insn16 (bfd_vma pc, disassemble_info *info, -- uint32_t insn, uint32_t parse_mode); --static void print_insn32 (bfd_vma pc, disassemble_info *info, uint32_t insn, -- uint32_t parse_mode); --static uint32_t nds32_mask_opcode (uint32_t); --static void nds32_special_opcode (uint32_t, struct nds32_opcode **); - --/* define in objdump.c. */ -+/* Defined in objdump.c. */ - struct objdump_disasm_info - { -- bfd * abfd; -- asection * sec; -- bfd_boolean require_sec; -- arelent ** dynrelbuf; -- long dynrelcount; -+ bfd *abfd; -+ asection *sec; -+ bfd_boolean require_sec; -+ arelent **dynrelbuf; -+ long dynrelcount; - disassembler_ftype disassemble_fn; -- arelent * reloc; -+ arelent *reloc; - }; - --/* file_ptr ex9_filepos=NULL;. */ --bfd_byte *ex9_data = NULL; --int ex9_ready = 0, ex9_base_offset = 0; -- - /* Hash function for disassemble. */ - - static htab_t opcode_htab; - --static void --nds32_ex9_info (bfd_vma pc ATTRIBUTE_UNUSED, -- disassemble_info *info, uint32_t ex9_index) --{ -- uint32_t insn; -- static asymbol *itb = NULL; -- bfd_byte buffer[4]; -- long unsigned int isec_vma; -- -- /* Lookup itb symbol. */ -- if (!itb) -- { -- int i; -- -- for (i = 0; i < info->symtab_size; i++) -- if (bfd_asymbol_name (info->symtab[i]) -- && (strcmp (bfd_asymbol_name (info->symtab[i]), "$_ITB_BASE_") == 0 -- || strcmp (bfd_asymbol_name (info->symtab[i]), -- "_ITB_BASE_") == 0)) -- { -- itb = info->symtab[i]; -- break; -- } -- -- /* Lookup it only once, in case _ITB_BASE_ doesn't exist at all. */ -- if (itb == NULL) -- itb = (void *) -1; -- } -- -- if (itb == (void *) -1) -- return; -- -- isec_vma = itb->section->vma; -- isec_vma = itb->section->vma - bfd_asymbol_value (itb); -- if (!itb->section || !itb->section->owner) -- return; -- bfd_get_section_contents (itb->section->owner, itb->section, buffer, -- ex9_index * 4 - isec_vma, 4); -- insn = bfd_getb32 (buffer); -- /* 16-bit instructions in ex9 table. */ -- if (insn & 0x80000000) -- print_insn16 (pc, info, (insn & 0x0000FFFF), -- NDS32_PARSE_INSN16 | NDS32_PARSE_EX9IT); -- /* 32-bit instructions in ex9 table. */ -- else -- print_insn32 (pc, info, insn, NDS32_PARSE_INSN32 | NDS32_PARSE_EX9IT); --} -- - /* Find the value map register name. */ - - static keyword_t * -@@ -155,7 +134,7 @@ nds32_parse_audio_ext (const field_t *pfd, - else - int_value = __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; - -- if (int_value < 10) -+ if (int_value < 0) - func (stream, "#%d", int_value); - else - func (stream, "#0x%x", int_value); -@@ -186,7 +165,7 @@ nds32_parse_audio_ext (const field_t *pfd, - { - new_value |= 0x04; - } -- /* Rt CONCAT(c, t21, t0). */ -+ /* Rt CONCAT(c, t21, t0). */ - else if (strcmp (pfd->name, "a_rt21") == 0) - { - new_value = (insn & 0x00000020) >> 5; -@@ -221,12 +200,33 @@ nds32_parse_audio_ext (const field_t *pfd, - func (stream, "$%s", psys_reg->name); - } - --/* Dump instruction. If the opcode is unknown, return FALSE. */ -+/* Match instruction opcode with keyword table. */ -+ -+static field_t * -+match_field (char *name) -+{ -+ field_t *pfd; -+ int k; -+ -+ for (k = 0; k < NDS32_CORE_COUNT; k++) -+ { -+ pfd = (field_t *) nds32_field_table[k]; -+ while (1) -+ { -+ if (pfd->name == NULL) -+ break; -+ if (strcmp (name, pfd->name) == 0) -+ return pfd; -+ pfd++; -+ } -+ } -+ -+ return NULL; -+} - - static void - nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, -- disassemble_info *info, uint32_t insn, -- uint32_t parse_mode) -+ disassemble_info *info, uint32_t insn, uint32_t parse_mode) - { - int op = 0; - fprintf_ftype func = info->fprintf_func; -@@ -245,9 +245,6 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - return; - } - -- if (parse_mode & NDS32_PARSE_EX9IT) -- func (stream, " !"); -- - pstr_src = opc->instruction; - if (*pstr_src == 0) - { -@@ -259,7 +256,6 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - { - func (stream, "%s ", opc->opcode); - } -- - /* NDS32_PARSE_INSN32. */ - else - { -@@ -269,7 +265,7 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - else if (strstr (opc->instruction, "tito")) - func (stream, "%s", opc->opcode); - else -- func (stream, "%s\t", opc->opcode); -+ func (stream, "%s ", opc->opcode); - } - - while (*pstr_src) -@@ -280,7 +276,7 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - case '=': - case '&': - pstr_src++; -- /* Compare with operand_fields[].name. */ -+ /* Compare name with operand table entries. */ - pstr_tmp = &tmp_string[0]; - while (*pstr_src) - { -@@ -293,18 +289,9 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - *pstr_tmp++ = *pstr_src++; - } - *pstr_tmp = 0; -+ if ((pfd = match_field (&tmp_string[0])) == NULL) -+ return; - -- pfd = (const field_t *) &operand_fields[0]; -- while (1) -- { -- if (pfd->name == NULL) -- return; -- else if (strcmp (&tmp_string[0], pfd->name) == 0) -- break; -- pfd++; -- } -- -- /* For insn-16. */ - if (parse_mode & NDS32_PARSE_INSN16) - { - if (pfd->hw_res == HW_GPR) -@@ -331,7 +318,7 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - if (pfd->hw_res == HW_INT) - int_value = - N32_IMMS ((insn >> pfd->bitpos), -- pfd->bitsize) << pfd->shift; -+ pfd->bitsize) << pfd->shift; - else - int_value = - __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; -@@ -348,12 +335,11 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - int_value = 0 - (128 - int_value); - func (stream, "#%d", int_value); - } -- /* beqz38/bnez38/beqs38/bnes38/j8/beqzs8/bnezs8/ifcall9. */ -+ /* beqz38/bnez38/beqs38/bnes38/j8/beqzs8/bnezs8. */ - else if ((opc->value == 0xc000) || (opc->value == 0xc800) - || (opc->value == 0xd000) || (opc->value == 0xd800) - || (opc->value == 0xd500) || (opc->value == 0xe800) -- || (opc->value == 0xe900) -- || (opc->value == 0xf800)) -+ || (opc->value == 0xe900)) - { - info->print_address_func (int_value + pc, info); - } -@@ -365,28 +351,17 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - func (stream, "~$%s", keyword_gpr[push25gpr].name); - func (stream, ", $fp, $gp, $lp}"); - } -- /* ex9.it. */ -- else if ((opc->value == 0xdd40) || (opc->value == 0xea00)) -- { -- func (stream, "#%d", int_value); -- nds32_ex9_info (pc, info, int_value); -- } - else if (pfd->hw_res == HW_INT) - { -- if (int_value < 10) -+ if (int_value < 0) - func (stream, "#%d", int_value); - else - func (stream, "#0x%x", int_value); - } -- else /* if (pfd->hw_res == HW_UINT). */ -- { -- if (int_value < 10) -- func (stream, "#%u", int_value); -- else -- func (stream, "#0x%x", int_value); -- } -+ /* if(pfd->hw_res == HW_UINT). */ -+ else -+ func (stream, "#0x%x", int_value); - } -- - } - /* for audio-ext. */ - else if (op == N32_OP6_AEXT) -@@ -394,12 +369,13 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - nds32_parse_audio_ext (pfd, info, insn); - } - /* for insn-32. */ -- else if (pfd->hw_res < _HW_LAST) -+ else if (pfd->hw_res < HW_INT) - { - int_value = - __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; - -- psys_reg = (keyword_t*) keywords[pfd->hw_res]; -+ psys_reg = *(nds32_keyword_table[pfd->hw_res >> 8] -+ + (pfd->hw_res & 0xff)); - - psys_reg = nds32_find_reg_keyword (psys_reg, int_value); - /* For HW_SR, dump the index when it can't -@@ -444,15 +420,7 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - /* FIXME: Handle relocation. */ - if (info->flags & INSN_HAS_RELOC) - pc = 0; -- /* Check if insn32 in ex9 table. */ -- if (parse_mode & NDS32_PARSE_EX9IT) -- info->print_address_func ((pc & 0xFE000000) | int_value, -- info); -- /* Check if decode ex9 table, PC(31,25)|Inst(23,0)<<1. */ -- else if (parse_mode & NDS32_PARSE_EX9TAB) -- func (stream, "PC(31,25)|#0x%x", int_value); -- else -- info->print_address_func (int_value + pc, info); -+ info->print_address_func (int_value + pc, info); - } - else if (op == N32_OP6_LSMW) - { -@@ -496,17 +464,14 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - } - else if (pfd->hw_res == HW_INT) - { -- if (int_value < 10) -+ if (int_value < 0) - func (stream, "#%d", int_value); - else - func (stream, "#0x%x", int_value); - } -- else /* if (pfd->hw_res == HW_UINT). */ -+ else /* if(pfd->hw_res == HW_UINT). */ - { -- if (int_value < 10) -- func (stream, "#%u", int_value); -- else -- func (stream, "#0x%x", int_value); -+ func (stream, "#0x%x", int_value); - } - } - break; -@@ -516,34 +481,13 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - pstr_src++; - break; - -- case ',': -- func (stream, ", "); -- pstr_src++; -- break; -- -- case '+': -- func (stream, " + "); -- pstr_src++; -- break; -- -- case '<': -- if (pstr_src[1] == '<') -- { -- func (stream, " << "); -- pstr_src += 2; -- } -- else -- { -- func (stream, " <"); -- pstr_src++; -- } -- break; -- - default: - func (stream, "%c", *pstr_src++); - break; -- } -- } -+ } /* switch (*pstr_src). */ -+ -+ } /* while (*pstr_src). */ -+ return; - } - - /* Filter instructions with some bits must be fixed. */ -@@ -571,7 +515,7 @@ nds32_filter_unknown_insn (uint32_t insn, struct nds32_opcode **opc) - if (__GF (insn, 5, 5) != 0) - *opc = NULL; - break; -- case BR2 (IFCALL): -+ case BR2 (SOP0): - if (__GF (insn, 20, 5) != 0) - *opc = NULL; - break; -@@ -692,6 +636,7 @@ print_insn16 (bfd_vma pc, disassemble_info *info, - } - break; - } -+ - opcode = insn & mask; - opc = (struct nds32_opcode *) htab_find (opcode_htab, &opcode); - -@@ -715,6 +660,21 @@ htab_hash_eq (const void *p, const void *q) - return (pinsn == qinsn); - } - -+static uint32_t -+mask_CEXT (uint32_t insn) -+{ -+ opcode_t *opc = nds32_opcode_table[NDS32_ACE], *max_opc = NULL; -+ -+ for (; opc != NULL && opc->opcode != NULL; opc++) -+ { -+ if ((insn & opc->value) == opc->value -+ && (max_opc == NULL || opc->value > max_opc->value)) -+ max_opc = opc; -+ } -+ -+ return max_opc ? max_opc->value : insn; -+} -+ - /* Get the format of instruction. */ - - static uint32_t -@@ -754,18 +714,26 @@ nds32_mask_opcode (uint32_t insn) - case N32_OP6_ORI: - case N32_OP6_SLTI: - case N32_OP6_SLTSI: -- case N32_OP6_CEXT: - case N32_OP6_BITCI: - return MASK_OP (insn, 0); -+ case N32_OP6_CEXT: -+ return mask_CEXT (insn); - case N32_OP6_ALU2: - /* FFBI */ - if (__GF (insn, 0, 7) == (N32_ALU2_FFBI | N32_BIT (6))) - return MASK_OP (insn, 0x7f); -- else if (__GF (insn, 0, 7) == (N32_ALU2_MFUSR | N32_BIT (6)) -- || __GF (insn, 0, 7) == (N32_ALU2_MTUSR | N32_BIT (6))) -+ else if (__GF (insn, 0, 10) == (N32_ALU2_MFUSR | N32_BIT (6)) -+ || __GF (insn, 0, 10) == (N32_ALU2_MTUSR | N32_BIT (6))) - /* RDOV CLROV */ - return MASK_OP (insn, 0xf81ff); -- return MASK_OP (insn, 0x1ff); -+ else if (__GF (insn, 0, 10) == (N32_ALU2_ONEOP | N32_BIT (7))) -+ { -+ /* INSB */ -+ if (__GF (insn, 12, 3) == 4) -+ return MASK_OP (insn, 0x73ff); -+ return MASK_OP (insn, 0x7fff); -+ } -+ return MASK_OP (insn, 0x3ff); - case N32_OP6_ALU1: - case N32_OP6_SIMD: - return MASK_OP (insn, 0x1f); -@@ -794,113 +762,116 @@ nds32_mask_opcode (uint32_t insn) - case N32_OP6_BR1: - return MASK_OP (insn, 0x1 << 14); - case N32_OP6_BR2: -- return MASK_OP (insn, 0xf << 16); -+ if (__GF (insn, 16, 4) == 0) -+ return MASK_OP (insn, 0x1ff << 16); -+ else -+ return MASK_OP (insn, 0xf << 16); - case N32_OP6_BR3: - return MASK_OP (insn, 0x1 << 19); - case N32_OP6_MISC: -- switch (__GF (insn, 0, 5)) -- { -- case N32_MISC_MTSR: -- /* SETGIE and SETEND */ -- if (__GF (insn, 5, 5) == 0x1 || __GF (insn, 5, 5) == 0x2) -- return MASK_OP (insn, 0x1fffff); -- return MASK_OP (insn, 0x1f); -- case N32_MISC_TLBOP: -- if (__GF (insn, 5, 5) == 5 || __GF (insn, 5, 5) == 7) -- /* PB FLUA */ -- return MASK_OP (insn, 0x3ff); -- return MASK_OP (insn, 0x1f); -- default: -- return MASK_OP (insn, 0x1f); -- } -+ switch (__GF (insn, 0, 5)) -+ { -+ case N32_MISC_MTSR: -+ /* SETGIE and SETEND */ -+ if (__GF (insn, 5, 5) == 0x1 || __GF (insn, 5, 5) == 0x2) -+ return MASK_OP (insn, 0x1fffff); -+ return MASK_OP (insn, 0x1f); -+ case N32_MISC_TLBOP: -+ if (__GF (insn, 5, 5) == 5 || __GF (insn, 5, 5) == 7) -+ /* PB FLUA */ -+ return MASK_OP (insn, 0x3ff); -+ return MASK_OP (insn, 0x1f); -+ default: -+ return MASK_OP (insn, 0x1f); -+ } - case N32_OP6_COP: -- if (__GF (insn, 4, 2) == 0) -- { -- /* FPU */ -- switch (__GF (insn, 0, 4)) -- { -- case 0x0: -- case 0x8: -- /* FS1/F2OP FD1/F2OP */ -- if (__GF (insn, 6, 4) == 0xf) -- return MASK_OP (insn, 0x7fff); -- /* FS1 FD1 */ -- return MASK_OP (insn, 0x3ff); -- case 0x4: -- case 0xc: -- /* FS2 */ -- return MASK_OP (insn, 0x3ff); -- case 0x1: -- case 0x9: -- /* XR */ -- if (__GF (insn, 6, 4) == 0xc) -- return MASK_OP (insn, 0x7fff); -- /* MFCP MTCP */ -- return MASK_OP (insn, 0x3ff); -- default: -- return MASK_OP (insn, 0xff); -- } -- } -- else if (__GF (insn, 0, 2) == 0) -- return MASK_OP (insn, 0xf); -- return MASK_OP (insn, 0xcf); -+ if (__GF (insn, 4, 2) == 0) -+ { -+ /* FPU */ -+ switch (__GF (insn, 0, 4)) -+ { -+ case 0x0: -+ case 0x8: -+ /* FS1/F2OP FD1/F2OP */ -+ if (__GF (insn, 6, 4) == 0xf) -+ return MASK_OP (insn, 0x7fff); -+ /* FS1 FD1 */ -+ return MASK_OP (insn, 0x3ff); -+ case 0x4: -+ case 0xc: -+ /* FS2 */ -+ return MASK_OP (insn, 0x3ff); -+ case 0x1: -+ case 0x9: -+ /* XR */ -+ if (__GF (insn, 6, 4) == 0xc) -+ return MASK_OP (insn, 0x7fff); -+ /* MFCP MTCP */ -+ return MASK_OP (insn, 0x3ff); -+ default: -+ return MASK_OP (insn, 0xff); -+ } -+ } -+ else if (__GF (insn, 0, 2) == 0) -+ return MASK_OP (insn, 0xf); -+ return MASK_OP (insn, 0xcf); - case N32_OP6_AEXT: -- /* AUDIO */ -- switch (__GF (insn, 23, 2)) -- { -- case 0x0: -- if (__GF (insn, 5, 4) == 0) -- /* AMxxx AMAyyS AMyyS AMAWzS AMWzS */ -- return MASK_OP (insn, (0x1f << 20) | 0x1ff); -- else if (__GF (insn, 5, 4) == 1) -- /* ALR ASR ALA ASA AUPI */ -- return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); -- else if (__GF (insn, 20, 3) == 0 && __GF (insn, 6, 3) == 1) -- /* ALR2 */ -- return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); -- else if (__GF (insn, 20 ,3) == 2 && __GF (insn, 6, 3) == 1) -- /* AWEXT ASATS48 */ -- return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); -- else if (__GF (insn, 20 ,3) == 3 && __GF (insn, 6, 3) == 1) -- /* AMTAR AMTAR2 AMFAR AMFAR2 */ -- return MASK_OP (insn, (0x1f << 20) | (0x1f << 5)); -- else if (__GF (insn, 7, 2) == 3) -- /* AMxxxSA */ -- return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); -- else if (__GF (insn, 6, 3) == 2) -- /* AMxxxL.S */ -- return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); -- else -- /* AmxxxL.l AmxxxL2.S AMxxxL2.L */ -- return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); -- case 0x1: -- if (__GF (insn, 20, 3) == 0) -- /* AADDL ASUBL */ -- return MASK_OP (insn, (0x1f << 20) | (0x1 << 5)); -- else if (__GF (insn, 20, 3) == 1) -- /* AMTARI Ix AMTARI Mx */ -- return MASK_OP (insn, (0x1f << 20)); -- else if (__GF (insn, 6, 3) == 2) -- /* AMAWzSl.S AMWzSl.S */ -- return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); -- else if (__GF (insn, 7, 2) == 3) -- /* AMAWzSSA AMWzSSA */ -- return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); -- else -- /* AMAWzSL.L AMAWzSL2.S AMAWzSL2.L AMWzSL.L AMWzSL.L AMWzSL2.S */ -- return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); -- case 0x2: -- if (__GF (insn, 6, 3) == 2) -- /* AMAyySl.S AMWyySl.S */ -- return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); -- else if (__GF (insn, 7, 2) == 3) -- /* AMAWyySSA AMWyySSA */ -- return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); -- else -- /* AMAWyySL.L AMAWyySL2.S AMAWyySL2.L AMWyySL.L AMWyySL.L AMWyySL2.S */ -- return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); -- } -- return MASK_OP (insn, 0x1f << 20); -+ /* AUDIO */ -+ switch (__GF (insn, 23, 2)) -+ { -+ case 0x0: -+ if (__GF (insn, 5, 4) == 0) -+ /* AMxxx AMAyyS AMyyS AMAWzS AMWzS */ -+ return MASK_OP (insn, (0x1f << 20) | 0x1ff); -+ else if (__GF (insn, 5, 4) == 1) -+ /* ALR ASR ALA ASA AUPI */ -+ return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); -+ else if (__GF (insn, 20, 3) == 0 && __GF (insn, 6, 3) == 1) -+ /* ALR2 */ -+ return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); -+ else if (__GF (insn, 20 ,3) == 2 && __GF (insn, 6, 3) == 1) -+ /* AWEXT ASATS48 */ -+ return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); -+ else if (__GF (insn, 20 ,3) == 3 && __GF (insn, 6, 3) == 1) -+ /* AMTAR AMTAR2 AMFAR AMFAR2 */ -+ return MASK_OP (insn, (0x1f << 20) | (0x1f << 5)); -+ else if (__GF (insn, 7, 2) == 3) -+ /* AMxxxSA */ -+ return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); -+ else if (__GF (insn, 6, 3) == 2) -+ /* AMxxxL.S */ -+ return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); -+ else -+ /* AmxxxL.l AmxxxL2.S AMxxxL2.L */ -+ return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); -+ case 0x1: -+ if (__GF (insn, 20, 3) == 0) -+ /* AADDL ASUBL */ -+ return MASK_OP (insn, (0x1f << 20) | (0x1 << 5)); -+ else if (__GF (insn, 20, 3) == 1) -+ /* AMTARI Ix AMTARI Mx */ -+ return MASK_OP (insn, (0x1f << 20)); -+ else if (__GF (insn, 6, 3) == 2) -+ /* AMAWzSl.S AMWzSl.S */ -+ return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); -+ else if (__GF (insn, 7, 2) == 3) -+ /* AMAWzSSA AMWzSSA */ -+ return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); -+ else -+ /* AMAWzSL.L AMAWzSL2.S AMAWzSL2.L AMWzSL.L AMWzSL.L AMWzSL2.S */ -+ return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); -+ case 0x2: -+ if (__GF (insn, 6, 3) == 2) -+ /* AMAyySl.S AMWyySl.S */ -+ return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); -+ else if (__GF (insn, 7, 2) == 3) -+ /* AMAWyySSA AMWyySSA */ -+ return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); -+ else -+ /* AMAWyySL.L AMAWyySL2.S AMAWyySL2.L AMWyySL.L AMWyySL.L AMWyySL2.S */ -+ return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); -+ } -+ return MASK_OP (insn, 0x1f << 20); - default: - return (1 << 31); - } -@@ -971,11 +942,6 @@ nds32_special_opcode (uint32_t insn, struct nds32_opcode **opc) - break; - case N32_OP6_COP: - break; -- case 0xea00: -- /* break16 ex9 */ -- if (__GF (insn, 5, 4) != 0) -- string = "ex9"; -- break; - case 0x9200: - /* nop16 */ - if (__GF (insn, 0, 9) == 0) -@@ -1005,46 +971,195 @@ print_insn_nds32 (bfd_vma pc, disassemble_info *info) - { - int status; - bfd_byte buf[4]; -+ bfd_byte buf_data[16]; -+ long long given; -+ long long given1; - uint32_t insn; -- static int init = 1; -- int i = 0; -- struct nds32_opcode *opc; -- struct nds32_opcode **slot; -+ int n; -+ int last_symbol_index = -1; -+ bfd_vma addr; -+ int is_data = FALSE; -+ bfd_boolean found = FALSE; -+ struct nds32_private_data *private_data; -+ unsigned int size = 16; -+ enum map_type mapping_type = MAP_CODE; -+ -+ if (info->private_data == NULL) -+ { -+ /* Note: remain lifecycle throughout whole execution. */ -+ static struct nds32_private_data private; -+ private.has_mapping_symbols = -1; /* unknown yet. */ -+ private.last_symbol_index = -1; -+ private.last_addr = 0; -+ info->private_data = &private; -+ } -+ private_data = info->private_data; - -- if (init) -+ if (info->symtab_size != 0) - { -- /* Build opcode table. */ -- opcode_htab = htab_create_alloc (1024, htab_hash_hash, htab_hash_eq, -- NULL, xcalloc, free); -+ int start; -+ if (pc == 0) -+ start = 0; -+ else -+ { -+ start = info->symtab_pos; -+ if (start < private_data->last_symbol_index) -+ start = private_data->last_symbol_index; -+ } - -- while (nds32_opcodes[i].opcode != NULL) -+ if (0 > start) -+ start = 0; -+ -+ if (private_data->has_mapping_symbols != 0 -+ && ((strncmp (".text", info->section->name, 5) == 0))) - { -- opc = &nds32_opcodes[i]; -- slot = -- (struct nds32_opcode **) htab_find_slot (opcode_htab, &opc->value, -- INSERT); -- if (*slot == NULL) -+ for (n = start; n < info->symtab_size; n++) - { -- /* This is the new one. */ -- *slot = opc; -+ addr = bfd_asymbol_value (info->symtab[n]); -+ if (addr > pc) -+ break; -+ if (get_mapping_symbol_type (info, n, &mapping_type)) -+ { -+ last_symbol_index = n; -+ found = TRUE; -+ } - } -- else -+ -+ if (found) -+ private_data->has_mapping_symbols = 1; -+ else if (!found && private_data->has_mapping_symbols == -1) -+ { -+ /* Make sure there are no any mapping symbol. */ -+ for (n = 0; n < info->symtab_size; n++) -+ { -+ if (is_mapping_symbol (info, n, &mapping_type)) -+ { -+ private_data->has_mapping_symbols = -1; -+ break; -+ } -+ } -+ if (private_data->has_mapping_symbols == -1) -+ private_data->has_mapping_symbols = 0; -+ -+ } -+ -+ private_data->last_symbol_index = last_symbol_index; -+ private_data->last_mapping_type = mapping_type; -+ is_data = (private_data->last_mapping_type == MAP_DATA0 -+ || private_data->last_mapping_type == MAP_DATA1 -+ || private_data->last_mapping_type == MAP_DATA2 -+ || private_data->last_mapping_type == MAP_DATA3 -+ || private_data->last_mapping_type == MAP_DATA4); -+ } -+ } -+ -+ /* Wonder data or instruction. */ -+ if (is_data) -+ { -+ unsigned int i1; -+ -+ /* fix corner case: there is no next mapping symbol, -+ * let mapping type decides size */ -+ if (last_symbol_index + 1 >= info->symtab_size) -+ { -+ if (mapping_type == MAP_DATA0) -+ size = 1; -+ if (mapping_type == MAP_DATA1) -+ size = 2; -+ if (mapping_type == MAP_DATA2) -+ size = 4; -+ if (mapping_type == MAP_DATA3) -+ size = 8; -+ if (mapping_type == MAP_DATA4) -+ size = 16; -+ } -+ for (n = last_symbol_index + 1; n < info->symtab_size; n++) -+ { -+ addr = bfd_asymbol_value (info->symtab[n]); -+ -+ enum map_type fake_mapping_type; -+ if (get_mapping_symbol_type (info, n, &fake_mapping_type)) -+ { -+ if (addr > pc -+ && ((info->section == NULL) -+ || (info->section == info->symtab[n]->section))) -+ { -+ if (addr - pc < size) -+ { -+ size = addr - pc; -+ break; -+ } -+ } -+ } -+ } -+ -+ -+ if (size == 3) -+ size = (pc & 1) ? 1 : 2; -+ -+ -+ /* Read bytes from BFD. */ -+ info->read_memory_func (pc, (bfd_byte *) buf_data, size, info); -+ given = 0; -+ given1 = 0; -+ /* Start assembling data. */ -+ /* Little endian of data. */ -+ if (info->endian == BFD_ENDIAN_LITTLE) -+ { -+ for (i1 = size - 1;; i1--) - { -- /* Already exists. Append to the list. */ -- opc = *slot; -- while (opc->next) -- opc = opc->next; -- opc->next = &nds32_opcodes[i]; -+ if (i1 >= 8) -+ given1 = buf_data[i1] | (given1 << 8); -+ else -+ given = buf_data[i1] | (given << 8); -+ if (i1 == 0) -+ break; - } -- i++; - } -- init = 0; -+ else -+ { -+ /* Big endian of data. */ -+ for (i1 = 0; i1 < size; i1++) { -+ if (i1 <= 7) -+ given = buf_data[i1] | (given << 8); -+ else -+ given1 = buf_data[i1] | (given1 << 8); -+ } -+ } -+ -+ info->bytes_per_line = 4; -+ -+ if (size == 16) -+ { -+ info->fprintf_func (info->stream, ".qword\t0x%016llx%016llx", -+ given, given1); -+ } -+ else if (size == 8) -+ { -+ info->fprintf_func (info->stream, ".dword\t0x%016llx", given); -+ } -+ else if (size == 4) -+ { -+ info->fprintf_func (info->stream, ".word\t0x%08llx", given); -+ } -+ else if (size == 2) /* short */ -+ { -+ if (mapping_type == MAP_DATA0) -+ info->fprintf_func (info->stream, ".byte\t0x%02llx", given & 0xFF); -+ else -+ info->fprintf_func (info->stream, ".short\t0x%04llx", given); -+ } -+ else -+ { /* byte */ -+ info->fprintf_func (info->stream, ".byte\t0x%02llx", given); -+ } -+ return size; - } - - status = info->read_memory_func (pc, (bfd_byte *) buf, 4, info); - if (status) - { -- /* for the last 16-bit instruction. */ -+ /* For the last 16-bit instruction. */ - status = info->read_memory_func (pc, (bfd_byte *) buf, 2, info); - if (status) - { -@@ -1052,17 +1167,10 @@ print_insn_nds32 (bfd_vma pc, disassemble_info *info) - return -1; - } - } -- - insn = bfd_getb32 (buf); - /* 16-bit instruction. */ - if (insn & 0x80000000) - { -- if (info->section && strstr (info->section->name, ".ex9.itable") != NULL) -- { -- print_insn16 (pc, info, (insn & 0x0000FFFF), -- NDS32_PARSE_INSN16 | NDS32_PARSE_EX9TAB); -- return 4; -- } - print_insn16 (pc, info, (insn >> 16), NDS32_PARSE_INSN16); - return 2; - } -@@ -1070,11 +1178,206 @@ print_insn_nds32 (bfd_vma pc, disassemble_info *info) - /* 32-bit instructions. */ - else - { -- if (info->section -- && strstr (info->section->name, ".ex9.itable") != NULL) -- print_insn32 (pc, info, insn, NDS32_PARSE_INSN32 | NDS32_PARSE_EX9TAB); -- else -- print_insn32 (pc, info, insn, NDS32_PARSE_INSN32); -+ print_insn32 (pc, info, insn, NDS32_PARSE_INSN32); - return 4; - } - } -+ -+/* Ignore disassembling unnecessary name. */ -+ -+static bfd_boolean -+nds32_symbol_is_valid (asymbol *sym, -+ struct disassemble_info *info ATTRIBUTE_UNUSED) -+{ -+ const char *name; -+ -+ if (sym == NULL) -+ return FALSE; -+ -+ name = bfd_asymbol_name (sym); -+ -+ /* Mapping symbol is invalid. */ -+ if (name[0] == '$') -+ return FALSE; -+ return TRUE; -+} -+ -+static void -+nds32_add_opcode_hash_table (unsigned indx) -+{ -+ opcode_t *opc; -+ -+ opc = nds32_opcode_table[indx]; -+ if (opc == NULL) -+ return; -+ -+ while (opc->opcode != NULL) -+ { -+ opcode_t **slot; -+ -+ slot = (opcode_t **) htab_find_slot (opcode_htab, &opc->value, INSERT); -+ if (*slot == NULL) -+ { -+ /* This is the new one. */ -+ *slot = opc; -+ } -+ else -+ { -+ opcode_t *tmp; -+ -+ /* Already exists. Append to the list. */ -+ tmp = *slot; -+ while (tmp->next) -+ tmp = tmp->next; -+ tmp->next = opc; -+ opc->next = NULL; -+ } -+ opc++; -+ } -+} -+ -+void -+disassemble_init_nds32 (struct disassemble_info *info) -+{ -+ static unsigned init_done = 0; -+ const char *ptr; -+ unsigned k; -+ -+ /* Set up symbol checking function. */ -+ info->symbol_is_valid = nds32_symbol_is_valid; -+ -+ /* Only need to initialize once: */ -+ /* High level will call this function for every object file. */ -+ /* For example, when disassemble all members of a library. */ -+ if (init_done) -+ return; -+ -+ /* Setup main core. */ -+ nds32_keyword_table[NDS32_MAIN_CORE] = &keywords[0]; -+ nds32_opcode_table[NDS32_MAIN_CORE] = &nds32_opcodes[0]; -+ nds32_field_table[NDS32_MAIN_CORE] = &operand_fields[0]; -+ -+ /* Process command line options. */ -+ ptr = info->disassembler_options; -+ if (ptr != NULL) -+ { -+ const char *start, *end; -+ do -+ { -+ char name[256]; -+ -+ /* Get one option. */ -+ start = strchr(ptr, '='); -+ end = strchr(ptr, ','); -+ if (start == NULL) -+ fprintf (stderr, "Unknown nds32 disassembler option: %s\n", ptr); -+ else -+ { -+ start++; -+ if (end == NULL) -+ strcpy (name, start); -+ else -+ strncpy (name, start, end - start); -+ -+ /* Parse and process the option. */ -+ if (strncmp (ptr, "ace=", 4) == 0) -+ nds32_parse_udi (name); -+ else if (strncmp (ptr, "cop0=", 5) == 0) -+ nds32_parse_cop0 (name); -+ else if (strncmp (ptr, "cop1=", 5) == 0) -+ nds32_parse_cop1 (name); -+ else if (strncmp (ptr, "cop2=", 5) == 0) -+ nds32_parse_cop2 (name); -+ else if (strncmp (ptr, "cop3=", 5) == 0) -+ nds32_parse_cop3 (name); -+ else -+ fprintf (stderr, "Unknown nds32 disassembler option: %s\n", -+ ptr); -+ -+ if (end == NULL) -+ break; -+ ptr = end + 1; -+ } -+ } while (1); -+ } -+ -+ /* Build opcode table. */ -+ opcode_htab = htab_create_alloc (1024, htab_hash_hash, htab_hash_eq, NULL, -+ xcalloc, free); -+ -+ for (k = 0; k < NDS32_CORE_COUNT; k++) -+ { -+ /* Add op-codes. */ -+ nds32_add_opcode_hash_table (k); -+ } -+ -+ init_done = 1; -+} -+ -+static int -+is_mapping_symbol (struct disassemble_info *info, int n, -+ enum map_type *map_type) -+{ -+ const char *name = NULL; -+ -+ /* Get symbol name. */ -+ name = bfd_asymbol_name (info->symtab[n]); -+ -+ if (name[1] == 'c') -+ { -+ *map_type = MAP_CODE; -+ return TRUE; -+ } -+ else if (name[1] == 'd' && name[2] == '0') -+ { -+ *map_type = MAP_DATA0; -+ return TRUE; -+ } -+ else if (name[1] == 'd' && name[2] == '1') -+ { -+ *map_type = MAP_DATA1; -+ return TRUE; -+ } -+ else if (name[1] == 'd' && name[2] == '2') -+ { -+ *map_type = MAP_DATA2; -+ return TRUE; -+ } -+ else if (name[1] == 'd' && name[2] == '3') -+ { -+ *map_type = MAP_DATA3; -+ return TRUE; -+ } -+ else if (name[1] == 'd' && name[2] == '4') -+ { -+ *map_type = MAP_DATA4; -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+static int -+get_mapping_symbol_type (struct disassemble_info *info, int n, -+ enum map_type *map_type) -+{ -+ /* If the symbol is in a different section, ignore it. */ -+ if (info->section != NULL && info->section != info->symtab[n]->section) -+ return FALSE; -+ -+ return is_mapping_symbol (info, n, map_type); -+} -+ -+void -+print_nds32_disassembler_options (FILE *stream) -+{ -+ fprintf (stream, _("\n\ -+The following Andes specific disassembler options are supported for use with\n\ -+the -M switch:\n")); -+ -+ fprintf (stream, " ace= Support user defined instruction extension\n"); -+ fprintf (stream, " cop0= Support coprocessor 0 extension\n"); -+ fprintf (stream, " cop1= Support coprocessor 1 extension\n"); -+ fprintf (stream, " cop2= Support coprocessor 2 extension\n"); -+ fprintf (stream, " cop3= Support coprocessor 3 extension\n\n"); -+} diff --git a/util/crossgcc/patches/binutils-2.30_no-bfd-doc.patch b/util/crossgcc/patches/binutils-2.30_no-bfd-doc.patch deleted file mode 100644 index 607d479313..0000000000 --- a/util/crossgcc/patches/binutils-2.30_no-bfd-doc.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -ur binutils-2.26.1/bfd/Makefile.in binutils-2.26.1.patched/bfd/Makefile.in ---- binutils-2.26.1/bfd/Makefile.in 2015-11-13 16:27:40.000000000 +0800 -+++ binutils-2.27/bfd/Makefile.in 2016-04-02 11:05:43.398422394 +0800 -@@ -341,7 +341,7 @@ - ACLOCAL_AMFLAGS = -I . -I .. -I ../config - INCDIR = $(srcdir)/../include - CSEARCH = -I. -I$(srcdir) -I$(INCDIR) --SUBDIRS = doc po -+SUBDIRS = po - bfddocdir = doc - libbfd_la_LDFLAGS = $(am__append_1) -release `cat libtool-soversion` \ - @SHARED_LDFLAGS@ $(am__empty) diff --git a/util/crossgcc/patches/binutils-2.31.1_mips-gold.patch b/util/crossgcc/patches/binutils-2.31.1_mips-gold.patch new file mode 100644 index 0000000000..d9a40210ff --- /dev/null +++ b/util/crossgcc/patches/binutils-2.31.1_mips-gold.patch @@ -0,0 +1,11 @@ +diff -urN binutils-2.27.orig/gold/configure.tgt binutils-2.27/gold/configure.tgt +--- binutils-2.27.orig/gold/configure.tgt 2016-08-03 15:36:53.000000000 +0800 ++++ binutils-2.27/gold/configure.tgt 2016-10-29 19:28:56.140587026 +0800 +@@ -157,6 +157,7 @@ + targ_obj=mips + targ_machine=EM_MIPS_RS3_LE + targ_size=32 ++ targ_extra_size=64 + targ_big_endian=false + targ_extra_big_endian=true + ;; diff --git a/util/crossgcc/patches/binutils-2.31.1_no-bfd-doc.patch b/util/crossgcc/patches/binutils-2.31.1_no-bfd-doc.patch new file mode 100644 index 0000000000..98707d444d --- /dev/null +++ b/util/crossgcc/patches/binutils-2.31.1_no-bfd-doc.patch @@ -0,0 +1,12 @@ +diff -ur binutils-2.26.1/bfd/Makefile.in binutils-2.26.1.patched/bfd/Makefile.in +--- binutils-2.26.1/bfd/Makefile.in 2015-11-13 16:27:40.000000000 +0800 ++++ binutils-2.27/bfd/Makefile.in 2016-04-02 11:05:43.398422394 +0800 +@@ -459,7 +459,7 @@ + ACLOCAL_AMFLAGS = -I . -I .. -I ../config + INCDIR = $(srcdir)/../include + CSEARCH = -I. -I$(srcdir) -I$(INCDIR) +-SUBDIRS = doc po ++SUBDIRS = po + bfddocdir = doc + libbfd_la_LDFLAGS = $(am__append_1) -release `cat libtool-soversion` \ + @SHARED_LDFLAGS@ $(am__empty) diff --git a/util/crossgcc/patches/gcc-8.1.0_ada-musl_workaround.patch b/util/crossgcc/patches/gcc-8.1.0_ada-musl_workaround.patch deleted file mode 100644 index 1f504a4b5e..0000000000 --- a/util/crossgcc/patches/gcc-8.1.0_ada-musl_workaround.patch +++ /dev/null @@ -1,120 +0,0 @@ -diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c -index 3b0aea92c05..998f2c66289 100644 ---- a/gcc/ada/adaint.c -+++ b/gcc/ada/adaint.c -@@ -107,6 +107,15 @@ - #define xmalloc(S) malloc (S) - #define xrealloc(V,S) realloc (V,S) - #else -+#if !defined(__ANDROID__) && defined(__linux__) -+#ifdef __cplusplus -+extern "C" { -+#endif -+#include -+#ifdef __cplusplus -+} -+#endif -+#endif - #include "config.h" - #include "system.h" - #include "version.h" -@@ -3265,7 +3274,7 @@ __gnat_lwp_self (void) - - /* Dynamic cpu sets */ - --cpu_set_t * -+void * - __gnat_cpu_alloc (size_t count) - { - return CPU_ALLOC (count); -@@ -3278,33 +3287,33 @@ __gnat_cpu_alloc_size (size_t count) - } - - void --__gnat_cpu_free (cpu_set_t *set) -+__gnat_cpu_free (void *set) - { -- CPU_FREE (set); -+ CPU_FREE ((cpu_set_t *)set); - } - - void --__gnat_cpu_zero (size_t count, cpu_set_t *set) -+__gnat_cpu_zero (size_t count, void *set) - { - CPU_ZERO_S (count, set); - } - - void --__gnat_cpu_set (int cpu, size_t count, cpu_set_t *set) -+__gnat_cpu_set (int cpu, size_t count, void *set) - { - /* Ada handles CPU numbers starting from 1, while C identifies the first - CPU by a 0, so we need to adjust. */ -- CPU_SET_S (cpu - 1, count, set); -+ CPU_SET_S (cpu - 1, count, (cpu_set_t *)set); - } - - #else /* !CPU_ALLOC */ - - /* Static cpu sets */ - --cpu_set_t * -+void * - __gnat_cpu_alloc (size_t count ATTRIBUTE_UNUSED) - { -- return (cpu_set_t *) xmalloc (sizeof (cpu_set_t)); -+ return xmalloc (sizeof (cpu_set_t)); - } - - size_t -@@ -3314,23 +3323,23 @@ __gnat_cpu_alloc_size (size_t count ATTRIBUTE_UNUSED) - } - - void --__gnat_cpu_free (cpu_set_t *set) -+__gnat_cpu_free (void *set) - { - free (set); - } - - void --__gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED, cpu_set_t *set) -+__gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED, void *set) - { - CPU_ZERO (set); - } - - void --__gnat_cpu_set (int cpu, size_t count ATTRIBUTE_UNUSED, cpu_set_t *set) -+__gnat_cpu_set (int cpu, size_t count ATTRIBUTE_UNUSED, void *set) - { - /* Ada handles CPU numbers starting from 1, while C identifies the first - CPU by a 0, so we need to adjust. */ -- CPU_SET (cpu - 1, set); -+ CPU_SET (cpu - 1, (cpu_set_t *)set); - } - #endif /* !CPU_ALLOC */ - #endif /* __linux__ */ -diff --git a/gcc/ada/adaint.h b/gcc/ada/adaint.h -index 0d12f7e9020..7b3def03fb0 100644 ---- a/gcc/ada/adaint.h -+++ b/gcc/ada/adaint.h -@@ -316,13 +316,11 @@ extern void *__gnat_lwp_self (void); - - /* Routines for interface to required CPU set primitives */ - --#include -- --extern cpu_set_t *__gnat_cpu_alloc (size_t); -+extern void *__gnat_cpu_alloc (size_t); - extern size_t __gnat_cpu_alloc_size (size_t); --extern void __gnat_cpu_free (cpu_set_t *); --extern void __gnat_cpu_zero (size_t, cpu_set_t *); --extern void __gnat_cpu_set (int, size_t, cpu_set_t *); -+extern void __gnat_cpu_free (void *); -+extern void __gnat_cpu_zero (size_t, void *); -+extern void __gnat_cpu_set (int, size_t, void *); - #endif - - #if defined (_WIN32) diff --git a/util/crossgcc/patches/gcc-8.1.0_armv6s-m.patch b/util/crossgcc/patches/gcc-8.1.0_armv6s-m.patch deleted file mode 100644 index d56ff4caa8..0000000000 --- a/util/crossgcc/patches/gcc-8.1.0_armv6s-m.patch +++ /dev/null @@ -1,64 +0,0 @@ -Taken from https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=260158 ---- gcc-8-branch/gcc/config/arm/arm-cpus.in 2018/05/11 09:28:10 260157 -+++ gcc-8-branch/gcc/config/arm/arm-cpus.in 2018/05/11 09:30:49 260158 -@@ -446,6 +446,8 @@ - isa ARMv6m - end arch armv6-m - -+# This is now equivalent to armv6-m, but we keep it because some -+# versions of GAS still distinguish between the two. - begin arch armv6s-m - tune for cortex-m1 - base 6M -@@ -1168,21 +1170,21 @@ - begin cpu cortex-m1 - cname cortexm1 - tune flags LDSCHED -- architecture armv6-m -+ architecture armv6s-m - costs v6m - end cpu cortex-m1 - - begin cpu cortex-m0 - cname cortexm0 - tune flags LDSCHED -- architecture armv6-m -+ architecture armv6s-m - costs v6m - end cpu cortex-m0 - - begin cpu cortex-m0plus - cname cortexm0plus - tune flags LDSCHED -- architecture armv6-m -+ architecture armv6s-m - costs v6m - end cpu cortex-m0plus - -@@ -1192,7 +1194,7 @@ - cname cortexm1smallmultiply - tune for cortex-m1 - tune flags LDSCHED SMALLMUL -- architecture armv6-m -+ architecture armv6s-m - costs v6m - end cpu cortex-m1.small-multiply - -@@ -1200,7 +1202,7 @@ - cname cortexm0smallmultiply - tune for cortex-m0 - tune flags LDSCHED SMALLMUL -- architecture armv6-m -+ architecture armv6s-m - costs v6m - end cpu cortex-m0.small-multiply - -@@ -1208,7 +1210,7 @@ - cname cortexm0plussmallmultiply - tune for cortex-m0plus - tune flags LDSCHED SMALLMUL -- architecture armv6-m -+ architecture armv6s-m - costs v6m - end cpu cortex-m0plus.small-multiply - diff --git a/util/crossgcc/patches/gcc-8.1.0_bsd.patch b/util/crossgcc/patches/gcc-8.1.0_bsd.patch deleted file mode 100644 index 75b0b65772..0000000000 --- a/util/crossgcc/patches/gcc-8.1.0_bsd.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur gcc-8.1.0/gcc/ada/link.c gcc-8.1.0_/gcc/ada/link.c ---- gcc-8.1.0/gcc/ada/link.c 2018-01-11 01:55:25.000000000 -0700 -+++ gcc-8.1.0_/gcc/ada/link.c 2018-08-25 20:47:29.274166706 -0600 -@@ -104,7 +104,7 @@ - const char *__gnat_default_libgcc_subdir = "lib"; - - #elif defined (__FreeBSD__) || defined (__DragonFly__) \ -- || defined (__NetBSD__) || defined (__OpenBSD__) -+ || defined (__NetBSD__) || defined (__OpenBSD__) \ - || defined (__QNX__) - const char *__gnat_object_file_option = "-Wl,@"; - const char *__gnat_run_path_option = "-Wl,-rpath,"; diff --git a/util/crossgcc/patches/gcc-8.1.0_gnat.patch b/util/crossgcc/patches/gcc-8.1.0_gnat.patch deleted file mode 100644 index 2d7cecee24..0000000000 --- a/util/crossgcc/patches/gcc-8.1.0_gnat.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- gcc-6.1.0/gcc/ada/gcc-interface/Make-lang.in.bak 2015-08-24 16:23:25.004493665 +0200 -+++ gcc-6.1.0/gcc/ada/gcc-interface/Make-lang.in 2015-08-24 17:53:52.496636113 +0200 -@@ -45,7 +45,7 @@ - - - # Extra flags to pass to recursive makes. --COMMON_ADAFLAGS= -gnatpg -+COMMON_ADAFLAGS= -gnatpg -gnatwGUR - ifeq ($(TREECHECKING),) - CHECKING_ADAFLAGS= - else diff --git a/util/crossgcc/patches/gcc-8.1.0_libgcc.patch b/util/crossgcc/patches/gcc-8.1.0_libgcc.patch deleted file mode 100644 index 2f75c92b41..0000000000 --- a/util/crossgcc/patches/gcc-8.1.0_libgcc.patch +++ /dev/null @@ -1,60 +0,0 @@ -This enables building on Mac OS and FreeBSD by adding support to their -variants of the sed utility. - -diff -urN gcc-5.2.0.orig/libgcc/config/t-hardfp gcc-5.2.0/libgcc/config/t-hardfp ---- gcc-5.2.0.orig/libgcc/config/t-hardfp 2015-01-05 04:33:28.000000000 -0800 -+++ gcc-8.1.0/libgcc/config/t-hardfp 2016-04-06 12:04:51.000000000 -0700 -@@ -59,21 +59,52 @@ - - hardfp_func_list := $(filter-out $(hardfp_exclusions),$(hardfp_func_list)) - -+HOST_OS ?= $(shell uname) -+ - # Regexp for matching a floating-point mode. -+ifeq ($(HOST_OS), Darwin) -+hardfp_mode_regexp := $(shell echo $(hardfp_float_modes) | sed 's/ /|/g') -+else -+ifeq ($(HOST_OS), FreeBSD) -+hardfp_mode_regexp := $(shell echo $(hardfp_float_modes) | sed 's/ /|/g') -+else - hardfp_mode_regexp := $(shell echo $(hardfp_float_modes) | sed 's/ /\\|/g') -+endif -+endif - - # Regexp for matching the end of a function name, after the last - # floating-point mode. -+ifeq ($(HOST_OS), Darwin) -+hardfp_suffix_regexp := $(shell echo $(hardfp_int_modes) 2 3 | sed 's/ /|/g') -+else -+ifeq ($(HOST_OS), FreeBSD) -+hardfp_suffix_regexp := $(shell echo $(hardfp_int_modes) 2 3 | sed 's/ /|/g') -+else - hardfp_suffix_regexp := $(shell echo $(hardfp_int_modes) 2 3 | sed 's/ /\\|/g') -+endif -+endif - - # Add -D options to define: - # FUNC: the function name (e.g. __addsf3) - # OP: the function name without the leading __ and with the last - # floating-point mode removed (e.g. add3) - # TYPE: the last floating-point mode (e.g. sf) -+ -+ifeq ($(HOST_OS), Darwin) - hardfp_defines_for = \ - $(shell echo $1 | \ -- sed 's/\(.*\)\($(hardfp_mode_regexp)\)\($(hardfp_suffix_regexp)\|\)$$/-DFUNC=__& -DOP_\1\3 -DTYPE=\2/') -+ sed -E 's/(.*)($(hardfp_mode_regexp))($(hardfp_suffix_regexp)|.*)$$/-DFUNC=__& -DOP_\1\3 -DTYPE=\2/') -+else -+ifeq ($(HOST_OS), FreeBSD) -+hardfp_defines_for = \ -+ $(shell echo $1 | \ -+ sed -r 's/(.*)($(hardfp_mode_regexp))($(hardfp_suffix_regexp)|.*)$$/-DFUNC=__& -DOP_\1\3 -DTYPE=\2/') -+else -+hardfp_defines_for = \ -+ $(shell echo $1 | \ -+ sed 's/\(.*\)\($(hardfp_mode_regexp)\)\($(hardfp_suffix_regexp)\|\)$$/-DFUNC=__& -DOP_\1\3 -DTYPE=\2/') -+endif -+endif - - hardfp-o = $(patsubst %,%$(objext),$(hardfp_func_list)) - $(hardfp-o): %$(objext): $(srcdir)/config/hardfp.c diff --git a/util/crossgcc/patches/gcc-8.1.0_nds32_ite.patch b/util/crossgcc/patches/gcc-8.1.0_nds32_ite.patch deleted file mode 100644 index 0cfedd3f8a..0000000000 --- a/util/crossgcc/patches/gcc-8.1.0_nds32_ite.patch +++ /dev/null @@ -1,21164 +0,0 @@ -diff --git a/gcc/common/config/nds32/nds32-common.c b/gcc/common/config/nds32/nds32-common.c -index dbcc390728e..48236605118 100644 ---- a/gcc/common/config/nds32/nds32-common.c -+++ b/gcc/common/config/nds32/nds32-common.c -@@ -53,6 +53,16 @@ nds32_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED, - - return true; - -+ case OPT_misr_secure_: -+ /* Check the valid security level: 0 1 2 3. */ -+ if (value < 0 || value > 3) -+ { -+ error_at (loc, "for the option -misr-secure=X, the valid X " -+ "must be: 0, 1, 2, or 3"); -+ return false; -+ } -+ return true; -+ - case OPT_mcache_block_size_: - /* Check valid value: 4 8 16 32 64 128 256 512. */ - if (exact_log2 (value) < 2 || exact_log2 (value) > 9) -@@ -74,12 +84,19 @@ nds32_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED, - /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ - static const struct default_options nds32_option_optimization_table[] = - { -+#if TARGET_LINUX_ABI == 0 -+ /* Disable -fdelete-null-pointer-checks by default in ELF toolchain. */ -+ { OPT_LEVELS_ALL, OPT_fdelete_null_pointer_checks, -+ NULL, 0 }, -+#endif - /* Enable -fsched-pressure by default at -O1 and above. */ - { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, - /* Enable -fomit-frame-pointer by default at all optimization levels. */ - { OPT_LEVELS_ALL, OPT_fomit_frame_pointer, NULL, 1 }, - /* Enable -mrelax-hint by default at all optimization levels. */ - { OPT_LEVELS_ALL, OPT_mrelax_hint, NULL, 1 }, -+ /* Enalbe -malways-align by default at -O1 and above, but not -Os or -Og. */ -+ { OPT_LEVELS_1_PLUS_SPEED_ONLY, OPT_malways_align, NULL, 1 }, - /* Enable -mv3push by default at -Os, but it is useless under V2 ISA. */ - { OPT_LEVELS_SIZE, OPT_mv3push, NULL, 1 }, - -@@ -87,6 +104,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. */ - -@@ -103,6 +133,7 @@ static const struct default_options nds32_option_optimization_table[] = - TARGET_EXT_PERF : Generate performance extention instrcution. - TARGET_EXT_PERF2 : Generate performance extention version 2 instrcution. - TARGET_EXT_STRING : Generate string extention instrcution. -+ TARGET_HW_ABS : Generate hardware abs instruction. - TARGET_CMOV : Generate conditional move instruction. */ - #undef TARGET_DEFAULT_TARGET_FLAGS - #define TARGET_DEFAULT_TARGET_FLAGS \ -@@ -113,6 +144,7 @@ static const struct default_options nds32_option_optimization_table[] = - | MASK_EXT_PERF \ - | MASK_EXT_PERF2 \ - | MASK_EXT_STRING \ -+ | MASK_HW_ABS \ - | MASK_CMOV) - - #undef TARGET_HANDLE_OPTION -@@ -125,7 +157,7 @@ static const struct default_options nds32_option_optimization_table[] = - /* Defining the Output Assembler Language. */ - - #undef TARGET_EXCEPT_UNWIND_INFO --#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info -+#define TARGET_EXCEPT_UNWIND_INFO nds32_except_unwind_info - - /* ------------------------------------------------------------------------ */ - -diff --git a/gcc/config.gcc b/gcc/config.gcc -index e58494c1c17..5ccf9e4ec72 100644 ---- a/gcc/config.gcc -+++ b/gcc/config.gcc -@@ -444,7 +444,17 @@ mips*-*-*) - ;; - nds32*) - cpu_type=nds32 -- extra_headers="nds32_intrinsic.h" -+ extra_headers="nds32_intrinsic.h nds32_isr.h nds32_init.inc" -+ 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" - ;; - nios2-*-*) -@@ -2332,17 +2342,36 @@ msp430*-*-*) - tmake_file="${tmake_file} msp430/t-msp430" - extra_gcc_objs="driver-msp430.o" - ;; --nds32le-*-*) -+nds32*-*-*) - target_cpu_default="0" - tm_defines="${tm_defines}" -- tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} nds32/nds32_intrinsic.h" -- tmake_file="nds32/t-nds32 nds32/t-mlibs" -- ;; --nds32be-*-*) -- target_cpu_default="0|MASK_BIG_ENDIAN" -- 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" -+ case ${target} in -+ nds32le*-*-*) -+ ;; -+ nds32be-*-*) -+ target_cpu_default="${target_cpu_default}|MASK_BIG_ENDIAN" -+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" -+ ;; -+ 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 -+ if test x${with_ext_dsp} = xyes; then -+ tm_defines="${tm_defines} TARGET_DEFAULT_EXT_DSP=1" -+ fi - ;; - nios2-*-*) - tm_file="elfos.h ${tm_file}" -@@ -4315,11 +4344,11 @@ case "${target}" in - "") - with_cpu=n9 - ;; -- n6 | n7 | n8 | e8 | s8 | n9) -+ n6 | n7 |n8 | e8 | s8 | n9 | n10 | d10 | n12 | n13 | n15) - # OK - ;; - *) -- echo "Cannot accept --with-cpu=$with_cpu, available values are: n6 n7 n8 e8 s8 n9" 1>&2 -+ echo "Cannot accept --with-cpu=$with_cpu, available values are: n6 n7 n8 e8 s8 n9 n10 d10 n12 n13 n15" 1>&2 - exit 1 - ;; - esac -@@ -4329,15 +4358,30 @@ case "${target}" in - "") - # the default library is newlib - with_nds32_lib=newlib -+ tm_defines="${tm_defines} TARGET_DEFAULT_CTOR_DTOR=1" - ;; - newlib) - # OK -+ tm_defines="${tm_defines} TARGET_DEFAULT_CTOR_DTOR=1" - ;; - mculib) - # 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}" -+ ;; -+ 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 - ;; - esac -diff --git a/gcc/config/nds32/constants.md b/gcc/config/nds32/constants.md -index 37c27049ef0..6d42f50c882 100644 ---- a/gcc/config/nds32/constants.md -+++ b/gcc/config/nds32/constants.md -@@ -23,6 +23,7 @@ - (define_constants - [(R8_REGNUM 8) - (TA_REGNUM 15) -+ (TP_REGNUM 25) - (FP_REGNUM 28) - (GP_REGNUM 29) - (LP_REGNUM 30) -@@ -49,6 +50,16 @@ - UNSPEC_FFB - UNSPEC_FFMISM - UNSPEC_FLMISM -+ UNSPEC_KDMBB -+ UNSPEC_KDMBT -+ UNSPEC_KDMTB -+ UNSPEC_KDMTT -+ UNSPEC_KHMBB -+ UNSPEC_KHMBT -+ UNSPEC_KHMTB -+ UNSPEC_KHMTT -+ UNSPEC_KSLRAW -+ UNSPEC_KSLRAWU - UNSPEC_SVA - UNSPEC_SVS - UNSPEC_WSBH -@@ -62,6 +73,29 @@ - UNSPEC_UASTORE_HW - UNSPEC_UASTORE_W - UNSPEC_UASTORE_DW -+ UNSPEC_GOTINIT -+ UNSPEC_GOT -+ UNSPEC_GOTOFF -+ UNSPEC_PLT -+ UNSPEC_TLSGD -+ UNSPEC_TLSLD -+ UNSPEC_TLSIE -+ UNSPEC_TLSLE -+ UNSPEC_ROUND -+ UNSPEC_VEC_COMPARE -+ UNSPEC_KHM -+ UNSPEC_KHMX -+ UNSPEC_CLIP_OV -+ UNSPEC_CLIPS_OV -+ UNSPEC_BITREV -+ UNSPEC_KABS -+ UNSPEC_LOOP_END -+ UNSPEC_TLS_DESC -+ UNSPEC_TLS_IE -+ UNSPEC_ADD32 -+ UNSPEC_ICT -+ UNSPEC_KADDH -+ UNSPEC_KSUBH - ]) - - ;; The unspec_volatile operation index. -@@ -135,10 +169,14 @@ - UNSPEC_VOLATILE_SET_TRIG_EDGE - UNSPEC_VOLATILE_GET_TRIG_TYPE - UNSPEC_VOLATILE_RELAX_GROUP -+ UNSPEC_VOLATILE_OMIT_FP_BEGIN -+ UNSPEC_VOLATILE_OMIT_FP_END - UNSPEC_VOLATILE_POP25_RETURN - UNSPEC_VOLATILE_UNALIGNED_FEATURE - UNSPEC_VOLATILE_ENABLE_UNALIGNED - UNSPEC_VOLATILE_DISABLE_UNALIGNED -+ UNSPEC_VOLATILE_RDOV -+ UNSPEC_VOLATILE_CLROV - ]) - - ;; ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/constraints.md b/gcc/config/nds32/constraints.md -index 7af7769fcbf..315c60313e5 100644 ---- a/gcc/config/nds32/constraints.md -+++ b/gcc/config/nds32/constraints.md -@@ -127,6 +127,11 @@ - (and (match_code "const_int") - (match_test "IN_RANGE (ival, -31, 0)"))) - -+(define_constraint "Iu06" -+ "Unsigned immediate 6-bit value" -+ (and (match_code "const_int") -+ (match_test "ival < (1 << 6) && ival >= 0"))) -+ - ;; Ip05 is special and dedicated for v3 movpi45 instruction. - ;; movpi45 has imm5u field but the range is 16 ~ 47. - (define_constraint "Ip05" -@@ -136,10 +141,10 @@ - && ival >= (0 + 16) - && (TARGET_ISA_V3 || TARGET_ISA_V3M)"))) - --(define_constraint "Iu06" -+(define_constraint "IU06" - "Unsigned immediate 6-bit value constraint for addri36.sp instruction" - (and (match_code "const_int") -- (match_test "ival < (1 << 6) -+ (match_test "ival < (1 << 8) - && ival >= 0 - && (ival % 4 == 0) - && (TARGET_ISA_V3 || TARGET_ISA_V3M)"))) -@@ -302,6 +307,25 @@ - (match_test "(TARGET_ISA_V3 || TARGET_ISA_V3M) - && (IN_RANGE (exact_log2 (ival + 1), 1, 8))"))) - -+(define_constraint "CVp5" -+ "Unsigned immediate 5-bit value for movpi45 instruction with range 16-47" -+ (and (match_code "const_vector") -+ (match_test "nds32_valid_CVp5_p (op)"))) -+ -+(define_constraint "CVs5" -+ "Signed immediate 5-bit value" -+ (and (match_code "const_vector") -+ (match_test "nds32_valid_CVs5_p (op)"))) -+ -+(define_constraint "CVs2" -+ "Signed immediate 20-bit value" -+ (and (match_code "const_vector") -+ (match_test "nds32_valid_CVs2_p (op)"))) -+ -+(define_constraint "CVhi" -+ "The immediate value that can be simply set high 20-bit" -+ (and (match_code "const_vector") -+ (match_test "nds32_valid_CVhi_p (op)"))) - - (define_memory_constraint "U33" - "Memory constraint for 333 format" -@@ -349,4 +373,9 @@ - (match_test "(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) - && nds32_float_mem_operand_p (op)"))) - -+(define_constraint "S" -+ "@internal -+ A constant call address." -+ (match_operand 0 "nds32_symbolic_operand")) -+ - ;; ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/elf.h b/gcc/config/nds32/elf.h -new file mode 100644 -index 00000000000..66397ac2e30 ---- /dev/null -+++ b/gcc/config/nds32/elf.h -@@ -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 -+ . */ -+ -+ -+/* ------------------------------------------------------------------------ */ -+ -+#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}" -diff --git a/gcc/config/nds32/iterators.md b/gcc/config/nds32/iterators.md -index c2062de2e97..f4fb58181b1 100644 ---- a/gcc/config/nds32/iterators.md -+++ b/gcc/config/nds32/iterators.md -@@ -68,6 +68,28 @@ - ;; shifts - (define_code_iterator shift_rotate [ashift ashiftrt lshiftrt rotatert]) - -+(define_code_iterator shifts [ashift ashiftrt lshiftrt]) -+ -+(define_code_iterator shiftrt [ashiftrt lshiftrt]) -+ -+(define_code_iterator sat_plus [ss_plus us_plus]) -+ -+(define_code_iterator all_plus [plus ss_plus us_plus]) -+ -+(define_code_iterator sat_minus [ss_minus us_minus]) -+ -+(define_code_iterator all_minus [minus ss_minus us_minus]) -+ -+(define_code_iterator plus_minus [plus minus]) -+ -+(define_code_iterator extend [sign_extend zero_extend]) -+ -+(define_code_iterator sumax [smax umax]) -+ -+(define_code_iterator sumin [smin umin]) -+ -+(define_code_iterator sumin_max [smax umax smin umin]) -+ - ;;---------------------------------------------------------------------------- - ;; Code attributes. - ;;---------------------------------------------------------------------------- -@@ -76,5 +98,23 @@ - (define_code_attr shift - [(ashift "ashl") (ashiftrt "ashr") (lshiftrt "lshr") (rotatert "rotr")]) - -+(define_code_attr su -+ [(ashiftrt "") (lshiftrt "u") (sign_extend "s") (zero_extend "u")]) -+ -+(define_code_attr zs -+ [(sign_extend "s") (zero_extend "z")]) -+ -+(define_code_attr uk -+ [(plus "") (ss_plus "k") (us_plus "uk") -+ (minus "") (ss_minus "k") (us_minus "uk")]) -+ -+(define_code_attr opcode -+ [(plus "add") (minus "sub") (smax "smax") (umax "umax") (smin "smin") (umin "umin")]) -+ -+(define_code_attr add_rsub -+ [(plus "a") (minus "rs")]) -+ -+(define_code_attr add_sub -+ [(plus "a") (minus "s")]) - - ;;---------------------------------------------------------------------------- -diff --git a/gcc/config/nds32/linux.h b/gcc/config/nds32/linux.h -new file mode 100644 -index 00000000000..f66f9076baf ---- /dev/null -+++ b/gcc/config/nds32/linux.h -@@ -0,0 +1,86 @@ -+/* 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 -+ . */ -+ -+ -+/* ------------------------------------------------------------------------ */ -+ -+#define TARGET_LINUX_ABI 1 -+ -+#undef SIZE_TYPE -+#define SIZE_TYPE "unsigned int" -+ -+#undef PTRDIFF_TYPE -+#define PTRDIFF_TYPE "int" -+ -+#define TARGET_OS_CPP_BUILTINS() \ -+ do \ -+ { \ -+ GNU_USER_TARGET_OS_CPP_BUILTINS(); \ -+ } \ -+ while (0) -+ -+#ifdef TARGET_BIG_ENDIAN_DEFAULT -+#define LD_SO_ENDIAN_SPEC "%{mlittle-endian:le}%{!mlittle-endian:be}" -+#else -+#define LD_SO_ENDIAN_SPEC "%{mbig-endian:be}%{!mbig-endian:le}" -+#endif -+ -+/* Record arch version in TARGET_ARCH_DEFAULT. 0 means soft ABI, -+ 1 means hard ABI and using full floating-point instruction, -+ 2 means hard ABI and only using single-precision floating-point -+ instruction */ -+#if TARGET_ARCH_DEFAULT -+#define LD_SO_ABI_SPEC "%{!mabi=2:f}" -+#else -+#define LD_SO_ABI_SPEC "%{mabi=2fp+:f}" -+#endif -+ -+#define GLIBC_DYNAMIC_LINKER \ -+ "/lib/ld-linux-nds32" LD_SO_ENDIAN_SPEC LD_SO_ABI_SPEC ".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 -+ -+#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 -diff --git a/gcc/config/nds32/nds32-cost.c b/gcc/config/nds32/nds32-cost.c -index 8d01e8afee2..979000fcc45 100644 ---- a/gcc/config/nds32/nds32-cost.c -+++ b/gcc/config/nds32/nds32-cost.c -@@ -34,66 +34,379 @@ - #include "optabs.h" /* For GEN_FCN. */ - #include "recog.h" - #include "tm-constrs.h" -+#include "tree-pass.h" - - /* ------------------------------------------------------------------------ */ - --bool --nds32_rtx_costs_impl (rtx x, -- machine_mode mode ATTRIBUTE_UNUSED, -- int outer_code, -- int opno ATTRIBUTE_UNUSED, -- int *total, -- bool speed) --{ -- int code = GET_CODE (x); -+typedef bool (*rtx_cost_func) (rtx, int, int, int, int*); - -- /* According to 'speed', goto suitable cost model section. */ -- if (speed) -- goto performance_cost; -- else -- goto size_cost; -+struct rtx_cost_model_t { -+ rtx_cost_func speed_prefer; -+ rtx_cost_func size_prefer; -+}; - -+static rtx_cost_model_t rtx_cost_model; - --performance_cost: -- /* This is section for performance cost model. */ -+static int insn_size_16bit; /* Initial at nds32_init_rtx_costs. */ -+static const int insn_size_32bit = 4; -+ -+static bool -+nds32_rtx_costs_speed_prefer (rtx x ATTRIBUTE_UNUSED, -+ int code, -+ int outer_code ATTRIBUTE_UNUSED, -+ int opno ATTRIBUTE_UNUSED, -+ int *total) -+{ -+ rtx op0; -+ rtx op1; -+ machine_mode mode = GET_MODE (x); -+ /* Scale cost by mode size. */ -+ int cost = COSTS_N_INSNS (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode)); - -- /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4. -- We treat it as 4-cycle cost for each instruction -- under performance consideration. */ - switch (code) - { -- case SET: -- /* For 'SET' rtx, we need to return false -- so that it can recursively calculate costs. */ -- return false; -- - case USE: - /* Used in combine.c as a marker. */ - *total = 0; -- break; -+ return true; -+ -+ case CONST_INT: -+ /* When not optimizing for size, we care more about the cost -+ of hot code, and hot code is often in a loop. If a constant -+ operand needs to be forced into a register, we will often be -+ able to hoist the constant load out of the loop, so the load -+ should not contribute to the cost. */ -+ if (outer_code == SET || outer_code == PLUS) -+ *total = satisfies_constraint_Is20 (x) ? 0 : 4; -+ else if (outer_code == AND || outer_code == IOR || outer_code == XOR -+ || outer_code == MINUS) -+ *total = satisfies_constraint_Iu15 (x) ? 0 : 4; -+ else if (outer_code == ASHIFT || outer_code == ASHIFTRT -+ || outer_code == LSHIFTRT) -+ *total = satisfies_constraint_Iu05 (x) ? 0 : 4; -+ else if (GET_RTX_CLASS (outer_code) == RTX_COMPARE -+ || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE) -+ *total = satisfies_constraint_Is16 (x) ? 0 : 4; -+ else -+ *total = COSTS_N_INSNS (1); -+ return true; -+ -+ case CONST: -+ case LO_SUM: -+ case HIGH: -+ case SYMBOL_REF: -+ *total = COSTS_N_INSNS (1); -+ return true; -+ -+ case MEM: -+ *total = COSTS_N_INSNS (1); -+ return true; -+ -+ case SET: -+ op0 = SET_DEST (x); -+ op1 = SET_SRC (x); -+ mode = GET_MODE (op0); -+ /* Scale cost by mode size. */ -+ cost = COSTS_N_INSNS (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode)); -+ -+ switch (GET_CODE (op1)) -+ { -+ case REG: -+ case SUBREG: -+ /* Register move and Store instructions. */ -+ if ((REG_P (op0) || MEM_P (op0)) -+ && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (DImode)) -+ *total = COSTS_N_INSNS (1); -+ else -+ *total = cost; -+ return true; -+ -+ case MEM: -+ /* Load instructions. */ -+ if (REG_P (op0) && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (DImode)) -+ *total = COSTS_N_INSNS (1); -+ else -+ *total = cost; -+ return true; -+ -+ case CONST_INT: -+ /* movi instruction. */ -+ if (REG_P (op0) && GET_MODE_SIZE (mode) < GET_MODE_SIZE (DImode)) -+ { -+ if (satisfies_constraint_Is20 (op1)) -+ *total = COSTS_N_INSNS (1) - 1; -+ else -+ *total = COSTS_N_INSNS (2); -+ } -+ else -+ *total = cost; -+ return true; -+ -+ case CONST: -+ case SYMBOL_REF: -+ case LABEL_REF: -+ /* la instruction. */ -+ if (REG_P (op0) && GET_MODE_SIZE (mode) < GET_MODE_SIZE (DImode)) -+ *total = COSTS_N_INSNS (1) - 1; -+ else -+ *total = cost; -+ return true; -+ case VEC_SELECT: -+ *total = cost; -+ return true; -+ -+ default: -+ *total = cost; -+ return true; -+ } -+ -+ case PLUS: -+ op0 = XEXP (x, 0); -+ op1 = XEXP (x, 1); -+ -+ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) -+ *total = cost; -+ else if (GET_CODE (op0) == MULT || GET_CODE (op0) == LSHIFTRT -+ || GET_CODE (op1) == MULT || GET_CODE (op1) == LSHIFTRT) -+ /* ALU_SHIFT */ -+ *total = COSTS_N_INSNS (2); -+ -+ else if ((GET_CODE (op1) == CONST_INT -+ && satisfies_constraint_Is15 (op1)) -+ || REG_P (op1)) -+ /* ADD instructions */ -+ *total = COSTS_N_INSNS (1); -+ else -+ /* ADD instructions: IMM out of range. */ -+ *total = COSTS_N_INSNS (2); -+ return true; -+ -+ case MINUS: -+ op0 = XEXP (x, 0); -+ op1 = XEXP (x, 1); -+ -+ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) -+ *total = cost; -+ else if (GET_CODE (op0) == MULT || GET_CODE (op0) == LSHIFTRT -+ || GET_CODE (op1) == MULT || GET_CODE (op1) == LSHIFTRT) -+ /* ALU_SHIFT */ -+ *total = COSTS_N_INSNS (2); -+ else if ((GET_CODE (op0) == CONST_INT -+ && satisfies_constraint_Is15 (op0)) -+ || REG_P (op0)) -+ /* SUB instructions */ -+ *total = COSTS_N_INSNS (1); -+ else -+ /* SUB instructions: IMM out of range. */ -+ *total = COSTS_N_INSNS (2); -+ return true; -+ -+ case TRUNCATE: -+ /* TRUNCATE and AND behavior is same. */ -+ *total = COSTS_N_INSNS (1); -+ return true; -+ -+ case AND: -+ case IOR: -+ case XOR: -+ op0 = XEXP (x, 0); -+ op1 = XEXP (x, 1); -+ -+ if (NDS32_EXT_DSP_P ()) -+ { -+ /* We prefer (and (ior) (ior)) than (ior (and) (and)) for -+ synthetize pk** and insb instruction. */ -+ if (code == AND && GET_CODE (op0) == IOR && GET_CODE (op1) == IOR) -+ return COSTS_N_INSNS (1); -+ -+ if (code == IOR && GET_CODE (op0) == AND && GET_CODE (op1) == AND) -+ return COSTS_N_INSNS (10); -+ } -+ -+ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) -+ *total = cost; -+ else if (GET_CODE (op0) == ASHIFT || GET_CODE (op0) == LSHIFTRT) -+ *total = COSTS_N_INSNS (2); -+ else if ((GET_CODE (op1) == CONST_INT -+ && satisfies_constraint_Iu15 (op1)) -+ || REG_P (op1)) -+ /* AND, OR, XOR instructions */ -+ *total = COSTS_N_INSNS (1); -+ else if (code == AND || GET_CODE (op0) == NOT) -+ /* BITC instruction */ -+ *total = COSTS_N_INSNS (1); -+ else -+ /* AND, OR, XOR instructions: IMM out of range. */ -+ *total = COSTS_N_INSNS (2); -+ return true; - - case MULT: -+ if (GET_MODE (x) == DImode -+ || GET_CODE (XEXP (x, 1)) == SIGN_EXTEND -+ || GET_CODE (XEXP (x, 1)) == ZERO_EXTEND) -+ /* MUL instructions */ -+ *total = COSTS_N_INSNS (1); -+ else if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) -+ *total = cost; -+ else if (outer_code == PLUS || outer_code == MINUS) -+ *total = COSTS_N_INSNS (2); -+ else if ((GET_CODE (XEXP (x, 1)) == CONST_INT -+ && satisfies_constraint_Iu05 (XEXP (x, 1))) -+ || REG_P (XEXP (x, 1))) -+ /* MUL instructions */ -+ *total = COSTS_N_INSNS (1); -+ else -+ /* MUL instructions: IMM out of range. */ -+ *total = COSTS_N_INSNS (2); -+ -+ if (TARGET_MUL_SLOW) -+ *total += COSTS_N_INSNS (4); -+ -+ return true; -+ -+ case LSHIFTRT: -+ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) -+ *total = cost; -+ else if (outer_code == PLUS || outer_code == MINUS -+ || outer_code == AND || outer_code == IOR -+ || outer_code == XOR) -+ *total = COSTS_N_INSNS (2); -+ else if ((GET_CODE (XEXP (x, 1)) == CONST_INT -+ && satisfies_constraint_Iu05 (XEXP (x, 1))) -+ || REG_P (XEXP (x, 1))) -+ /* SRL instructions */ -+ *total = COSTS_N_INSNS (1); -+ else -+ /* SRL instructions: IMM out of range. */ -+ *total = COSTS_N_INSNS (2); -+ return true; -+ -+ case ASHIFT: -+ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) -+ *total = cost; -+ else if (outer_code == AND || outer_code == IOR -+ || outer_code == XOR) -+ *total = COSTS_N_INSNS (2); -+ else if ((GET_CODE (XEXP (x, 1)) == CONST_INT -+ && satisfies_constraint_Iu05 (XEXP (x, 1))) -+ || REG_P (XEXP (x, 1))) -+ /* SLL instructions */ -+ *total = COSTS_N_INSNS (1); -+ else -+ /* SLL instructions: IMM out of range. */ -+ *total = COSTS_N_INSNS (2); -+ return true; -+ -+ case ASHIFTRT: -+ case ROTATERT: -+ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) -+ *total = cost; -+ else if ((GET_CODE (XEXP (x, 1)) == CONST_INT -+ && satisfies_constraint_Iu05 (XEXP (x, 1))) -+ || REG_P (XEXP (x, 1))) -+ /* ROTR, SLL instructions */ -+ *total = COSTS_N_INSNS (1); -+ else -+ /* ROTR, SLL instructions: IMM out of range. */ -+ *total = COSTS_N_INSNS (2); -+ return true; -+ -+ case LT: -+ case LTU: -+ if (outer_code == SET) -+ { -+ if ((GET_CODE (XEXP (x, 1)) == CONST_INT -+ && satisfies_constraint_Iu15 (XEXP (x, 1))) -+ || REG_P (XEXP (x, 1))) -+ /* SLT, SLTI instructions */ -+ *total = COSTS_N_INSNS (1); -+ else -+ /* SLT, SLT instructions: IMM out of range. */ -+ *total = COSTS_N_INSNS (2); -+ } -+ else -+ /* branch */ -+ *total = COSTS_N_INSNS (2); -+ return true; -+ -+ case EQ: -+ case NE: -+ case GE: -+ case LE: -+ case GT: -+ /* branch */ -+ *total = COSTS_N_INSNS (2); -+ return true; -+ -+ case IF_THEN_ELSE: -+ if (GET_CODE (XEXP (x, 1)) == LABEL_REF) -+ /* branch */ -+ *total = COSTS_N_INSNS (2); -+ else -+ /* cmovz, cmovn instructions */ -+ *total = COSTS_N_INSNS (1); -+ return true; -+ -+ case LABEL_REF: -+ if (outer_code == IF_THEN_ELSE) -+ /* branch */ -+ *total = COSTS_N_INSNS (2); -+ else -+ *total = COSTS_N_INSNS (1); -+ return true; -+ -+ case ZERO_EXTEND: -+ case SIGN_EXTEND: -+ if (MEM_P (XEXP (x, 0))) -+ /* Using memory access. */ -+ *total = COSTS_N_INSNS (1); -+ else -+ /* Zero extend and sign extend instructions. */ -+ *total = COSTS_N_INSNS (1); -+ return true; -+ -+ case NEG: -+ case NOT: - *total = COSTS_N_INSNS (1); -- break; -+ return true; - - case DIV: - case UDIV: - case MOD: - case UMOD: -- *total = COSTS_N_INSNS (7); -- break; -+ *total = COSTS_N_INSNS (20); -+ return true; - -- default: -+ case CALL: -+ *total = COSTS_N_INSNS (2); -+ return true; -+ -+ case CLZ: -+ case SMIN: -+ case SMAX: -+ case ZERO_EXTRACT: -+ if (TARGET_EXT_PERF) -+ *total = COSTS_N_INSNS (1); -+ else -+ *total = COSTS_N_INSNS (3); -+ return true; -+ case VEC_SELECT: - *total = COSTS_N_INSNS (1); -- break; -- } -- -- return true; -+ return true; - -+ default: -+ *total = COSTS_N_INSNS (3); -+ return true; -+ } -+} - --size_cost: -- /* This is section for size cost model. */ -- -+static bool -+nds32_rtx_costs_size_prefer (rtx x, -+ int code, -+ int outer_code, -+ int opno ATTRIBUTE_UNUSED, -+ int *total) -+{ - /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4. - We treat it as 4-byte cost for each instruction - under code size consideration. */ -@@ -118,85 +431,162 @@ nds32_rtx_costs_impl (rtx x, - (set X imm20s), use movi, 4-byte cost. - (set X BIG_INT), use sethi/ori, 8-byte cost. */ - if (satisfies_constraint_Is05 (x)) -- *total = COSTS_N_INSNS (1) - 2; -+ *total = insn_size_16bit; - else if (satisfies_constraint_Is20 (x)) -- *total = COSTS_N_INSNS (1); -+ *total = insn_size_32bit; - else -- *total = COSTS_N_INSNS (2); -+ *total = insn_size_32bit * 2; - } - else if (outer_code == PLUS || outer_code == MINUS) - { - /* Possible addi333/subi333 or subi45/addi45, 2-byte cost. - General case, cost 1 instruction with 4-byte. */ - if (satisfies_constraint_Iu05 (x)) -- *total = COSTS_N_INSNS (1) - 2; -+ *total = insn_size_16bit; - else -- *total = COSTS_N_INSNS (1); -+ *total = insn_size_32bit; - } - else if (outer_code == ASHIFT) - { - /* Possible slli333, 2-byte cost. - General case, cost 1 instruction with 4-byte. */ - if (satisfies_constraint_Iu03 (x)) -- *total = COSTS_N_INSNS (1) - 2; -+ *total = insn_size_16bit; - else -- *total = COSTS_N_INSNS (1); -+ *total = insn_size_32bit; - } - else if (outer_code == ASHIFTRT || outer_code == LSHIFTRT) - { - /* Possible srai45 or srli45, 2-byte cost. - General case, cost 1 instruction with 4-byte. */ - if (satisfies_constraint_Iu05 (x)) -- *total = COSTS_N_INSNS (1) - 2; -+ *total = insn_size_16bit; - else -- *total = COSTS_N_INSNS (1); -+ *total = insn_size_32bit; - } - else - { - /* For other cases, simply set it 4-byte cost. */ -- *total = COSTS_N_INSNS (1); -+ *total = insn_size_32bit; - } - break; - - case CONST_DOUBLE: - /* It requires high part and low part processing, set it 8-byte cost. */ -- *total = COSTS_N_INSNS (2); -+ *total = insn_size_32bit * 2; -+ break; -+ -+ case CONST: -+ case SYMBOL_REF: -+ *total = insn_size_32bit * 2; - break; - - default: - /* For other cases, generally we set it 4-byte cost -- and stop resurively traversing. */ -- *total = COSTS_N_INSNS (1); -+ and stop resurively traversing. */ -+ *total = insn_size_32bit; - break; - } - - return true; - } - --int --nds32_address_cost_impl (rtx address, -- machine_mode mode ATTRIBUTE_UNUSED, -- addr_space_t as ATTRIBUTE_UNUSED, -- bool speed) -+void -+nds32_init_rtx_costs (void) -+{ -+ rtx_cost_model.speed_prefer = nds32_rtx_costs_speed_prefer; -+ rtx_cost_model.size_prefer = nds32_rtx_costs_size_prefer; -+ -+ if (TARGET_16_BIT) -+ insn_size_16bit = 2; -+ else -+ insn_size_16bit = 4; -+} -+ -+/* This target hook describes the relative costs of RTL expressions. -+ Return 'true' when all subexpressions of x have been processed. -+ Return 'false' to sum the costs of sub-rtx, plus cost of this operation. -+ Refer to gcc/rtlanal.c for more information. */ -+bool -+nds32_rtx_costs_impl (rtx x, -+ machine_mode mode ATTRIBUTE_UNUSED, -+ int outer_code, -+ int opno, -+ int *total, -+ bool speed) -+{ -+ int code = GET_CODE (x); -+ -+ /* According to 'speed', use suitable cost model section. */ -+ if (speed) -+ return rtx_cost_model.speed_prefer(x, code, outer_code, opno, total); -+ else -+ return rtx_cost_model.size_prefer(x, code, outer_code, opno, total); -+} -+ -+ -+int nds32_address_cost_speed_prefer (rtx address) - { - rtx plus0, plus1; - enum rtx_code code; - - code = GET_CODE (address); - -- /* According to 'speed', goto suitable cost model section. */ -- if (speed) -- goto performance_cost; -- else -- goto size_cost; -+ switch (code) -+ { -+ case POST_MODIFY: -+ case POST_INC: -+ case POST_DEC: -+ /* We encourage that rtx contains -+ POST_MODIFY/POST_INC/POST_DEC behavior. */ -+ return COSTS_N_INSNS (1) - 2; -+ -+ case SYMBOL_REF: -+ /* We can have gp-relative load/store for symbol_ref. -+ Have it 4-byte cost. */ -+ return COSTS_N_INSNS (2); -+ -+ case CONST: -+ /* It is supposed to be the pattern (const (plus symbol_ref const_int)). -+ Have it 4-byte cost. */ -+ return COSTS_N_INSNS (2); -+ -+ case REG: -+ /* Simply return 4-byte costs. */ -+ return COSTS_N_INSNS (1) - 2; -+ -+ case PLUS: -+ /* We do not need to check if the address is a legitimate address, -+ because this hook is never called with an invalid address. -+ But we better check the range of -+ const_int value for cost, if it exists. */ -+ plus0 = XEXP (address, 0); -+ plus1 = XEXP (address, 1); -+ -+ if (REG_P (plus0) && CONST_INT_P (plus1)) -+ return COSTS_N_INSNS (1) - 2; -+ else if (ARITHMETIC_P (plus0) || ARITHMETIC_P (plus1)) -+ return COSTS_N_INSNS (1) - 1; -+ else if (REG_P (plus0) && REG_P (plus1)) -+ return COSTS_N_INSNS (1); -+ -+ /* For other 'plus' situation, make it cost 4-byte. */ -+ return COSTS_N_INSNS (1); -+ -+ default: -+ break; -+ } -+ -+ return COSTS_N_INSNS (4); - --performance_cost: -- /* This is section for performance cost model. */ -+} - -- /* FALLTHRU, currently we use same cost model as size_cost. */ -+int nds32_address_cost_speed_fwprop (rtx address) -+{ -+ rtx plus0, plus1; -+ enum rtx_code code; - --size_cost: -- /* This is section for size cost model. */ -+ code = GET_CODE (address); - - switch (code) - { -@@ -210,12 +600,12 @@ nds32_address_cost_impl (rtx address, - case SYMBOL_REF: - /* We can have gp-relative load/store for symbol_ref. - Have it 4-byte cost. */ -- return COSTS_N_INSNS (1); -+ return COSTS_N_INSNS (2); - - case CONST: - /* It is supposed to be the pattern (const (plus symbol_ref const_int)). - Have it 4-byte cost. */ -- return COSTS_N_INSNS (1); -+ return COSTS_N_INSNS (2); - - case REG: - /* Simply return 4-byte costs. */ -@@ -233,11 +623,15 @@ nds32_address_cost_impl (rtx address, - { - /* If it is possible to be lwi333/swi333 form, - make it 2-byte cost. */ -- if (satisfies_constraint_Iu05 (plus1)) -+ if (satisfies_constraint_Iu03 (plus1)) - return (COSTS_N_INSNS (1) - 2); - else - return COSTS_N_INSNS (1); - } -+ if (ARITHMETIC_P (plus0) || ARITHMETIC_P (plus1)) -+ return COSTS_N_INSNS (1) - 2; -+ else if (REG_P (plus0) && REG_P (plus1)) -+ return COSTS_N_INSNS (1); - - /* For other 'plus' situation, make it cost 4-byte. */ - return COSTS_N_INSNS (1); -@@ -249,4 +643,84 @@ nds32_address_cost_impl (rtx address, - return COSTS_N_INSNS (4); - } - -+ -+int nds32_address_cost_size_prefer (rtx address) -+{ -+ rtx plus0, plus1; -+ enum rtx_code code; -+ -+ code = GET_CODE (address); -+ -+ switch (code) -+ { -+ case POST_MODIFY: -+ case POST_INC: -+ case POST_DEC: -+ /* We encourage that rtx contains -+ POST_MODIFY/POST_INC/POST_DEC behavior. */ -+ return 0; -+ -+ case SYMBOL_REF: -+ /* We can have gp-relative load/store for symbol_ref. -+ Have it 4-byte cost. */ -+ return COSTS_N_INSNS (2); -+ -+ case CONST: -+ /* It is supposed to be the pattern (const (plus symbol_ref const_int)). -+ Have it 4-byte cost. */ -+ return COSTS_N_INSNS (2); -+ -+ case REG: -+ /* Simply return 4-byte costs. */ -+ return COSTS_N_INSNS (1) - 1; -+ -+ case PLUS: -+ /* We do not need to check if the address is a legitimate address, -+ because this hook is never called with an invalid address. -+ But we better check the range of -+ const_int value for cost, if it exists. */ -+ plus0 = XEXP (address, 0); -+ plus1 = XEXP (address, 1); -+ -+ if (REG_P (plus0) && CONST_INT_P (plus1)) -+ { -+ /* If it is possible to be lwi333/swi333 form, -+ make it 2-byte cost. */ -+ if (satisfies_constraint_Iu03 (plus1)) -+ return (COSTS_N_INSNS (1) - 2); -+ else -+ return COSTS_N_INSNS (1) - 1; -+ } -+ -+ /* (plus (reg) (mult (reg) (const))) */ -+ if (ARITHMETIC_P (plus0) || ARITHMETIC_P (plus1)) -+ return (COSTS_N_INSNS (1) - 1); -+ -+ /* For other 'plus' situation, make it cost 4-byte. */ -+ return COSTS_N_INSNS (1); -+ -+ default: -+ break; -+ } -+ -+ return COSTS_N_INSNS (4); -+ -+} -+ -+int nds32_address_cost_impl (rtx address, -+ machine_mode mode ATTRIBUTE_UNUSED, -+ addr_space_t as ATTRIBUTE_UNUSED, -+ bool speed_p) -+{ -+ if (speed_p) -+ { -+ if (current_pass->tv_id == TV_FWPROP) -+ return nds32_address_cost_speed_fwprop (address); -+ else -+ return nds32_address_cost_speed_prefer (address); -+ } -+ else -+ return nds32_address_cost_size_prefer (address); -+} -+ - /* ------------------------------------------------------------------------ */ -diff --git a/gcc/config/nds32/nds32-doubleword.md b/gcc/config/nds32/nds32-doubleword.md -index 7df715a771f..7ee6489d034 100644 ---- a/gcc/config/nds32/nds32-doubleword.md -+++ b/gcc/config/nds32/nds32-doubleword.md -@@ -118,10 +118,28 @@ - ]) - (set_attr "feature" " v1, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu")]) - -+;; Split move_di pattern when the hard register is odd. -+(define_split -+ [(set (match_operand:DIDF 0 "register_operand" "") -+ (match_operand:DIDF 1 "register_operand" ""))] -+ "(NDS32_IS_GPR_REGNUM (REGNO (operands[0])) -+ && ((REGNO (operands[0]) & 0x1) == 1)) -+ || (NDS32_IS_GPR_REGNUM (REGNO (operands[1])) -+ && ((REGNO (operands[1]) & 0x1) == 1))" -+ [(set (match_dup 2) (match_dup 3)) -+ (set (match_dup 4) (match_dup 5))] -+ { -+ operands[2] = gen_lowpart (SImode, operands[0]); -+ operands[4] = gen_highpart (SImode, operands[0]); -+ operands[3] = gen_lowpart (SImode, operands[1]); -+ operands[5] = gen_highpart (SImode, operands[1]); -+ } -+) -+ - (define_split - [(set (match_operand:DIDF 0 "register_operand" "") - (match_operand:DIDF 1 "const_double_operand" ""))] -- "reload_completed" -+ "flag_pic || reload_completed" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - { -diff --git a/gcc/config/nds32/nds32-dspext.md b/gcc/config/nds32/nds32-dspext.md -new file mode 100644 -index 00000000000..4c643a7528f ---- /dev/null -+++ b/gcc/config/nds32/nds32-dspext.md -@@ -0,0 +1,5278 @@ -+;; Machine description 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 -+;; . -+ -+(define_expand "mov" -+ [(set (match_operand:VQIHI 0 "general_operand" "") -+ (match_operand:VQIHI 1 "general_operand" ""))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ /* Need to force register if mem <- !reg. */ -+ if (MEM_P (operands[0]) && !REG_P (operands[1])) -+ operands[1] = force_reg (mode, operands[1]); -+ -+ /* If operands[1] is a large constant and cannot be performed -+ by a single instruction, we need to split it. */ -+ if (GET_CODE (operands[1]) == CONST_VECTOR -+ && !satisfies_constraint_CVs2 (operands[1]) -+ && !satisfies_constraint_CVhi (operands[1])) -+ { -+ HOST_WIDE_INT ival = const_vector_to_hwint (operands[1]); -+ rtx tmp_rtx; -+ -+ tmp_rtx = can_create_pseudo_p () -+ ? gen_reg_rtx (SImode) -+ : simplify_gen_subreg (SImode, operands[0], mode, 0); -+ -+ emit_move_insn (tmp_rtx, gen_int_mode (ival, SImode)); -+ convert_move (operands[0], tmp_rtx, false); -+ DONE; -+ } -+ -+ if (REG_P (operands[0]) && SYMBOLIC_CONST_P (operands[1])) -+ { -+ if (nds32_tls_referenced_p (operands [1])) -+ { -+ nds32_expand_tls_move (operands); -+ DONE; -+ } -+ else if (flag_pic) -+ { -+ nds32_expand_pic_move (operands); -+ DONE; -+ } -+ } -+}) -+ -+(define_insn "*mov" -+ [(set (match_operand:VQIHI 0 "nonimmediate_operand" "=r, r,$U45,$U33,$U37,$U45, m,$ l,$ l,$ l,$ d, d, r,$ d, r, r, r, *f, *f, r, *f, Q") -+ (match_operand:VQIHI 1 "nds32_vmove_operand" " r, r, l, l, l, d, r, U45, U33, U37, U45,Ufe, m, CVp5, CVs5, CVs2, CVhi, *f, r, *f, Q, *f"))] -+ "NDS32_EXT_DSP_P () -+ && (register_operand(operands[0], mode) -+ || register_operand(operands[1], mode))" -+{ -+ switch (which_alternative) -+ { -+ case 0: -+ return "mov55\t%0, %1"; -+ case 1: -+ return "ori\t%0, %1, 0"; -+ case 2: -+ case 3: -+ case 4: -+ case 5: -+ return nds32_output_16bit_store (operands, ); -+ case 6: -+ return nds32_output_32bit_store (operands, ); -+ case 7: -+ case 8: -+ case 9: -+ case 10: -+ case 11: -+ return nds32_output_16bit_load (operands, ); -+ case 12: -+ return nds32_output_32bit_load (operands, ); -+ case 13: -+ return "movpi45\t%0, %1"; -+ case 14: -+ return "movi55\t%0, %1"; -+ case 15: -+ return "movi\t%0, %1"; -+ case 16: -+ return "sethi\t%0, hi20(%1)"; -+ case 17: -+ if (TARGET_FPU_SINGLE) -+ return "fcpyss\t%0, %1, %1"; -+ else -+ return "#"; -+ case 18: -+ return "fmtsr\t%1, %0"; -+ case 19: -+ return "fmfsr\t%0, %1"; -+ case 20: -+ return nds32_output_float_load (operands); -+ case 21: -+ return nds32_output_float_store (operands); -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "alu,alu,store,store,store,store,store,load,load,load,load,load,load,alu,alu,alu,alu,fcpy,fmtsr,fmfsr,fload,fstore") -+ (set_attr "length" " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 4, 2, 2, 4, 4, 4, 4, 4, 4, 4") -+ (set_attr "feature" " v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v3m, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu")]) -+ -+(define_expand "movv2si" -+ [(set (match_operand:V2SI 0 "general_operand" "") -+ (match_operand:V2SI 1 "general_operand" ""))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ /* Need to force register if mem <- !reg. */ -+ if (MEM_P (operands[0]) && !REG_P (operands[1])) -+ operands[1] = force_reg (V2SImode, operands[1]); -+}) -+ -+(define_insn "*movv2si" -+ [(set (match_operand:V2SI 0 "nonimmediate_operand" "=r, r, r, r, Da, m, f, Q, f, r, f") -+ (match_operand:V2SI 1 "general_operand" " r, i, Da, m, r, r, Q, f, f, f, r"))] -+ "NDS32_EXT_DSP_P () -+ && (register_operand(operands[0], V2SImode) -+ || register_operand(operands[1], V2SImode))" -+{ -+ switch (which_alternative) -+ { -+ case 0: -+ return "movd44\t%0, %1"; -+ case 1: -+ /* reg <- const_int, we ask gcc to split instruction. */ -+ return "#"; -+ case 2: -+ /* The memory format is (mem (reg)), -+ we can generate 'lmw.bi' instruction. */ -+ return nds32_output_double (operands, true); -+ case 3: -+ /* We haven't 64-bit load instruction, -+ we split this pattern to two SImode pattern. */ -+ return "#"; -+ case 4: -+ /* The memory format is (mem (reg)), -+ we can generate 'smw.bi' instruction. */ -+ return nds32_output_double (operands, false); -+ case 5: -+ /* We haven't 64-bit store instruction, -+ we split this pattern to two SImode pattern. */ -+ return "#"; -+ case 6: -+ return nds32_output_float_load (operands); -+ case 7: -+ return nds32_output_float_store (operands); -+ case 8: -+ return "fcpysd\t%0, %1, %1"; -+ case 9: -+ return "fmfdr\t%0, %1"; -+ case 10: -+ return "fmtdr\t%1, %0"; -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "alu,alu,load,load,store,store,unknown,unknown,unknown,unknown,unknown") -+ (set_attr_alternative "length" -+ [ -+ ;; Alternative 0 -+ (if_then_else (match_test "!TARGET_16_BIT") -+ (const_int 4) -+ (const_int 2)) -+ ;; Alternative 1 -+ (const_int 16) -+ ;; Alternative 2 -+ (const_int 4) -+ ;; Alternative 3 -+ (const_int 8) -+ ;; Alternative 4 -+ (const_int 4) -+ ;; Alternative 5 -+ (const_int 8) -+ ;; Alternative 6 -+ (const_int 4) -+ ;; Alternative 7 -+ (const_int 4) -+ ;; Alternative 8 -+ (const_int 4) -+ ;; Alternative 9 -+ (const_int 4) -+ ;; Alternative 10 -+ (const_int 4) -+ ]) -+ (set_attr "feature" " v1, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu")]) -+ -+(define_expand "movmisalign" -+ [(set (match_operand:VQIHI 0 "general_operand" "") -+ (match_operand:VQIHI 1 "general_operand" ""))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ rtx addr; -+ if (MEM_P (operands[0]) && !REG_P (operands[1])) -+ operands[1] = force_reg (mode, operands[1]); -+ -+ if (MEM_P (operands[0])) -+ { -+ addr = force_reg (Pmode, XEXP (operands[0], 0)); -+ emit_insn (gen_unaligned_store (addr, operands[1])); -+ } -+ else -+ { -+ addr = force_reg (Pmode, XEXP (operands[1], 0)); -+ emit_insn (gen_unaligned_load (operands[0], addr)); -+ } -+ DONE; -+}) -+ -+(define_expand "unaligned_load" -+ [(set (match_operand:VQIHI 0 "register_operand" "=r") -+ (unspec:VQIHI [(mem:VQIHI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_W))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_ISA_V3M) -+ nds32_expand_unaligned_load (operands, mode); -+ else -+ emit_insn (gen_unaligned_load_w (operands[0], gen_rtx_MEM (mode, operands[1]))); -+ DONE; -+}) -+ -+(define_insn "unaligned_load_w" -+ [(set (match_operand:VQIHI 0 "register_operand" "= r") -+ (unspec:VQIHI [(match_operand:VQIHI 1 "nds32_lmw_smw_base_operand" " Umw")] UNSPEC_UALOAD_W))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ return nds32_output_lmw_single_word (operands); -+} -+ [(set_attr "type" "load") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "unaligned_store" -+ [(set (mem:VQIHI (match_operand:SI 0 "register_operand" "r")) -+ (unspec:VQIHI [(match_operand:VQIHI 1 "register_operand" "r")] UNSPEC_UASTORE_W))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_ISA_V3M) -+ nds32_expand_unaligned_store (operands, mode); -+ else -+ emit_insn (gen_unaligned_store_w (gen_rtx_MEM (mode, operands[0]), operands[1])); -+ DONE; -+}) -+ -+(define_insn "unaligned_store_w" -+ [(set (match_operand:VQIHI 0 "nds32_lmw_smw_base_operand" "=Umw") -+ (unspec:VQIHI [(match_operand:VQIHI 1 "register_operand" " r")] UNSPEC_UASTORE_W))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ return nds32_output_smw_single_word (operands); -+} -+ [(set_attr "type" "store") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "add3" -+ [(set (match_operand:VQIHI 0 "register_operand" "=r") -+ (all_plus:VQIHI (match_operand:VQIHI 1 "register_operand" " r") -+ (match_operand:VQIHI 2 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "add %0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+(define_insn "adddi3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (all_plus:DI (match_operand:DI 1 "register_operand" " r") -+ (match_operand:DI 2 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "add64 %0, %1, %2" -+ [(set_attr "type" "dalu64") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+(define_insn "raddv4qi3" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (truncate:V4QI -+ (ashiftrt:V4HI -+ (plus:V4HI (sign_extend:V4HI (match_operand:V4QI 1 "register_operand" " r")) -+ (sign_extend:V4HI (match_operand:V4QI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "radd8\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+ -+(define_insn "uraddv4qi3" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (truncate:V4QI -+ (lshiftrt:V4HI -+ (plus:V4HI (zero_extend:V4HI (match_operand:V4QI 1 "register_operand" " r")) -+ (zero_extend:V4HI (match_operand:V4QI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "uradd8\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+(define_insn "raddv2hi3" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (truncate:V2HI -+ (ashiftrt:V2SI -+ (plus:V2SI (sign_extend:V2SI (match_operand:V2HI 1 "register_operand" " r")) -+ (sign_extend:V2SI (match_operand:V2HI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "radd16\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+(define_insn "uraddv2hi3" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (truncate:V2HI -+ (lshiftrt:V2SI -+ (plus:V2SI (zero_extend:V2SI (match_operand:V2HI 1 "register_operand" " r")) -+ (zero_extend:V2SI (match_operand:V2HI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "uradd16\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+(define_insn "radddi3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (truncate:DI -+ (ashiftrt:TI -+ (plus:TI (sign_extend:TI (match_operand:DI 1 "register_operand" " r")) -+ (sign_extend:TI (match_operand:DI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "radd64\t%0, %1, %2" -+ [(set_attr "type" "dalu64") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+ -+(define_insn "uradddi3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (truncate:DI -+ (lshiftrt:TI -+ (plus:TI (zero_extend:TI (match_operand:DI 1 "register_operand" " r")) -+ (zero_extend:TI (match_operand:DI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "uradd64\t%0, %1, %2" -+ [(set_attr "type" "dalu64") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+(define_insn "sub3" -+ [(set (match_operand:VQIHI 0 "register_operand" "=r") -+ (all_minus:VQIHI (match_operand:VQIHI 1 "register_operand" " r") -+ (match_operand:VQIHI 2 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "sub %0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+(define_insn "subdi3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (all_minus:DI (match_operand:DI 1 "register_operand" " r") -+ (match_operand:DI 2 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "sub64 %0, %1, %2" -+ [(set_attr "type" "dalu64") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+(define_insn "rsubv4qi3" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (truncate:V4QI -+ (ashiftrt:V4HI -+ (minus:V4HI (sign_extend:V4HI (match_operand:V4QI 1 "register_operand" " r")) -+ (sign_extend:V4HI (match_operand:V4QI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "rsub8\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn "ursubv4qi3" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (truncate:V4QI -+ (lshiftrt:V4HI -+ (minus:V4HI (zero_extend:V4HI (match_operand:V4QI 1 "register_operand" " r")) -+ (zero_extend:V4HI (match_operand:V4QI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "ursub8\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn "rsubv2hi3" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (truncate:V2HI -+ (ashiftrt:V2SI -+ (minus:V2SI (sign_extend:V2SI (match_operand:V2HI 1 "register_operand" " r")) -+ (sign_extend:V2SI (match_operand:V2HI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "rsub16\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn "ursubv2hi3" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (truncate:V2HI -+ (lshiftrt:V2SI -+ (minus:V2SI (zero_extend:V2SI (match_operand:V2HI 1 "register_operand" " r")) -+ (zero_extend:V2SI (match_operand:V2HI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "ursub16\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn "rsubdi3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (truncate:DI -+ (ashiftrt:TI -+ (minus:TI (sign_extend:TI (match_operand:DI 1 "register_operand" " r")) -+ (sign_extend:TI (match_operand:DI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "rsub64\t%0, %1, %2" -+ [(set_attr "type" "dalu64") -+ (set_attr "length" "4")]) -+ -+ -+(define_insn "ursubdi3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (truncate:DI -+ (lshiftrt:TI -+ (minus:TI (zero_extend:TI (match_operand:DI 1 "register_operand" " r")) -+ (zero_extend:TI (match_operand:DI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "ursub64\t%0, %1, %2" -+ [(set_attr "type" "dalu64") -+ (set_attr "length" "4")]) -+ -+(define_expand "cras16_1" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_cras16_1_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_cras16_1_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "cras16_1_le" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (vec_duplicate:V2HI -+ (plus:HI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "cras16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_insn "cras16_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (plus:HI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "cras16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_expand "kcras16_1" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_kcras16_1_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_kcras16_1_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "kcras16_1_le" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (ss_minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (vec_duplicate:V2HI -+ (ss_plus:HI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "kcras16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_insn "kcras16_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (ss_minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (ss_plus:HI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "kcras16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_expand "ukcras16_1" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_ukcras16_1_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_ukcras16_1_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "ukcras16_1_le" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (us_minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (vec_duplicate:V2HI -+ (us_plus:HI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "ukcras16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_insn "ukcras16_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (us_minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (us_plus:HI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "ukcras16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_expand "crsa16_1" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_crsa16_1_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_crsa16_1_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "crsa16_1_le" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (plus:HI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "crsa16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_insn "crsa16_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (vec_duplicate:V2HI -+ (plus:HI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "crsa16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_expand "kcrsa16_1" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_kcrsa16_1_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_kcrsa16_1_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "kcrsa16_1_le" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (ss_minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (ss_plus:HI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "kcrsa16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_insn "kcrsa16_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (ss_minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (vec_duplicate:V2HI -+ (ss_plus:HI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "kcrsa16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_expand "ukcrsa16_1" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_ukcrsa16_1_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_ukcrsa16_1_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "ukcrsa16_1_le" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (us_minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (us_plus:HI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "ukcrsa16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_insn "ukcrsa16_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (us_minus:HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (vec_duplicate:V2HI -+ (us_plus:HI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "ukcrsa16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_expand "rcras16_1" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_rcras16_1_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_rcras16_1_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "rcras16_1_le" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (ashiftrt:SI -+ (minus:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (const_int 1)))) -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (ashiftrt:SI -+ (plus:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)])))) -+ (const_int 1)))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "rcras16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_insn "rcras16_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (ashiftrt:SI -+ (minus:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (const_int 1)))) -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (ashiftrt:SI -+ (plus:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)])))) -+ (const_int 1)))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "rcras16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_expand "urcras16_1" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_urcras16_1_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_urcras16_1_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "urcras16_1_le" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (lshiftrt:SI -+ (minus:SI -+ (zero_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (zero_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (const_int 1)))) -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (lshiftrt:SI -+ (plus:SI -+ (zero_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (zero_extend:SI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)])))) -+ (const_int 1)))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "urcras16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_insn "urcras16_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (lshiftrt:SI -+ (minus:SI -+ (zero_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (zero_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (const_int 1)))) -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (lshiftrt:SI -+ (plus:SI -+ (zero_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))) -+ (zero_extend:SI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)])))) -+ (const_int 1)))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "urcras16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_expand "rcrsa16_1" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_rcrsa16_1_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_rcrsa16_1_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "rcrsa16_1_le" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (ashiftrt:SI -+ (minus:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (const_int 1)))) -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (ashiftrt:SI -+ (plus:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)])))) -+ (const_int 1)))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "rcrsa16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_insn "rcrsa16_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (ashiftrt:SI -+ (minus:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (const_int 1)))) -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (ashiftrt:SI -+ (plus:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)])))) -+ (const_int 1)))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "rcrsa16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_expand "urcrsa16_1" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_urcrsa16_1_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_urcrsa16_1_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "urcrsa16_1_le" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (lshiftrt:SI -+ (minus:SI -+ (zero_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (zero_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (const_int 1)))) -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (lshiftrt:SI -+ (plus:SI -+ (zero_extend:SI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)]))) -+ (zero_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)])))) -+ (const_int 1)))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "urcrsa16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_insn "urcrsa16_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (lshiftrt:SI -+ (minus:SI -+ (zero_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (zero_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (const_int 1)))) -+ (vec_duplicate:V2HI -+ (truncate:HI -+ (lshiftrt:SI -+ (plus:SI -+ (zero_extend:SI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)]))) -+ (zero_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)])))) -+ (const_int 1)))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "urcrsa16\t%0, %1, %2" -+ [(set_attr "type" "dalu")] -+) -+ -+(define_expand "v2hi3" -+ [(set (match_operand:V2HI 0 "register_operand" "") -+ (shifts:V2HI (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:SI 2 "nds32_rimm4u_operand" "")))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (operands[2] == const0_rtx) -+ { -+ emit_move_insn (operands[0], operands[1]); -+ DONE; -+ } -+}) -+ -+(define_insn "*ashlv2hi3" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r") -+ (ashift:V2HI (match_operand:V2HI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r")))] -+ "NDS32_EXT_DSP_P ()" -+ "@ -+ slli16\t%0, %1, %2 -+ sll16\t%0, %1, %2" -+ [(set_attr "type" "dalu,dalu") -+ (set_attr "length" " 4, 4")]) -+ -+(define_insn "kslli16" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r") -+ (ss_ashift:V2HI (match_operand:V2HI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r")))] -+ "NDS32_EXT_DSP_P ()" -+ "@ -+ kslli16\t%0, %1, %2 -+ ksll16\t%0, %1, %2" -+ [(set_attr "type" "dalu,dalu") -+ (set_attr "length" " 4, 4")]) -+ -+(define_insn "*ashrv2hi3" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r") -+ (ashiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r")))] -+ "NDS32_EXT_DSP_P ()" -+ "@ -+ srai16\t%0, %1, %2 -+ sra16\t%0, %1, %2" -+ [(set_attr "type" "dalu,dalu") -+ (set_attr "length" " 4, 4")]) -+ -+(define_insn "sra16_round" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r") -+ (unspec:V2HI [(ashiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r"))] -+ UNSPEC_ROUND))] -+ "NDS32_EXT_DSP_P ()" -+ "@ -+ srai16.u\t%0, %1, %2 -+ sra16.u\t%0, %1, %2" -+ [(set_attr "type" "daluround,daluround") -+ (set_attr "length" " 4, 4")]) -+ -+(define_insn "*lshrv2hi3" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r") -+ (lshiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r")))] -+ "NDS32_EXT_DSP_P ()" -+ "@ -+ srli16\t%0, %1, %2 -+ srl16\t%0, %1, %2" -+ [(set_attr "type" "dalu,dalu") -+ (set_attr "length" " 4, 4")]) -+ -+(define_insn "srl16_round" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r") -+ (unspec:V2HI [(lshiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r"))] -+ UNSPEC_ROUND))] -+ "NDS32_EXT_DSP_P ()" -+ "@ -+ srli16.u\t%0, %1, %2 -+ srl16.u\t%0, %1, %2" -+ [(set_attr "type" "daluround,daluround") -+ (set_attr "length" " 4, 4")]) -+ -+(define_insn "kslra16" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (if_then_else:V2HI -+ (lt:SI (match_operand:SI 2 "register_operand" " r") -+ (const_int 0)) -+ (ashiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r") -+ (neg:SI (match_dup 2))) -+ (ashift:V2HI (match_dup 1) -+ (match_dup 2))))] -+ "NDS32_EXT_DSP_P ()" -+ "kslra16\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn "kslra16_round" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (if_then_else:V2HI -+ (lt:SI (match_operand:SI 2 "register_operand" " r") -+ (const_int 0)) -+ (unspec:V2HI [(ashiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r") -+ (neg:SI (match_dup 2)))] -+ UNSPEC_ROUND) -+ (ashift:V2HI (match_dup 1) -+ (match_dup 2))))] -+ "NDS32_EXT_DSP_P ()" -+ "kslra16.u\t%0, %1, %2" -+ [(set_attr "type" "daluround") -+ (set_attr "length" "4")]) -+ -+(define_insn "cmpeq" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(eq:SI (match_operand:VQIHI 1 "register_operand" " r") -+ (match_operand:VQIHI 2 "register_operand" " r"))] -+ UNSPEC_VEC_COMPARE))] -+ "NDS32_EXT_DSP_P ()" -+ "cmpeq\t%0, %1, %2" -+ [(set_attr "type" "dcmp") -+ (set_attr "length" "4")]) -+ -+(define_insn "scmplt" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(lt:SI (match_operand:VQIHI 1 "register_operand" " r") -+ (match_operand:VQIHI 2 "register_operand" " r"))] -+ UNSPEC_VEC_COMPARE))] -+ "NDS32_EXT_DSP_P ()" -+ "scmplt\t%0, %1, %2" -+ [(set_attr "type" "dcmp") -+ (set_attr "length" "4")]) -+ -+(define_insn "scmple" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(le:SI (match_operand:VQIHI 1 "register_operand" " r") -+ (match_operand:VQIHI 2 "register_operand" " r"))] -+ UNSPEC_VEC_COMPARE))] -+ "NDS32_EXT_DSP_P ()" -+ "scmple\t%0, %1, %2" -+ [(set_attr "type" "dcmp") -+ (set_attr "length" "4")]) -+ -+(define_insn "ucmplt" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(ltu:SI (match_operand:VQIHI 1 "register_operand" " r") -+ (match_operand:VQIHI 2 "register_operand" " r"))] -+ UNSPEC_VEC_COMPARE))] -+ "NDS32_EXT_DSP_P ()" -+ "ucmplt\t%0, %1, %2" -+ [(set_attr "type" "dcmp") -+ (set_attr "length" "4")]) -+ -+(define_insn "ucmple" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(leu:SI (match_operand:VQIHI 1 "register_operand" " r") -+ (match_operand:VQIHI 2 "register_operand" " r"))] -+ UNSPEC_VEC_COMPARE))] -+ "NDS32_EXT_DSP_P ()" -+ "ucmple\t%0, %1, %2" -+ [(set_attr "type" "dcmp") -+ (set_attr "length" "4")]) -+ -+(define_insn "sclip16" -+ [(set (match_operand:V2HI 0 "register_operand" "= r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" " r") -+ (match_operand:SI 2 "nds32_imm4u_operand" " Iu04")] -+ UNSPEC_CLIPS))] -+ "NDS32_EXT_DSP_P ()" -+ "sclip16\t%0, %1, %2" -+ [(set_attr "type" "dclip") -+ (set_attr "length" "4")]) -+ -+(define_insn "uclip16" -+ [(set (match_operand:V2HI 0 "register_operand" "= r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" " r") -+ (match_operand:SI 2 "nds32_imm4u_operand" " Iu04")] -+ UNSPEC_CLIP))] -+ "NDS32_EXT_DSP_P ()" -+ "uclip16\t%0, %1, %2" -+ [(set_attr "type" "dclip") -+ (set_attr "length" "4")]) -+ -+(define_insn "khm16" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" " r") -+ (match_operand:V2HI 2 "register_operand" " r")] -+ UNSPEC_KHM))] -+ "NDS32_EXT_DSP_P ()" -+ "khm16\t%0, %1, %2" -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_insn "khmx16" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" " r") -+ (match_operand:V2HI 2 "register_operand" " r")] -+ UNSPEC_KHMX))] -+ "NDS32_EXT_DSP_P ()" -+ "khmx16\t%0, %1, %2" -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_expand "vec_setv4qi" -+ [(match_operand:V4QI 0 "register_operand" "") -+ (match_operand:QI 1 "register_operand" "") -+ (match_operand:SI 2 "immediate_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ HOST_WIDE_INT pos = INTVAL (operands[2]); -+ if (pos > 4) -+ gcc_unreachable (); -+ HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << pos; -+ emit_insn (gen_vec_setv4qi_internal (operands[0], operands[1], -+ operands[0], GEN_INT (elem))); -+ DONE; -+}) -+ -+(define_expand "insb" -+ [(match_operand:V4QI 0 "register_operand" "") -+ (match_operand:V4QI 1 "register_operand" "") -+ (match_operand:SI 2 "register_operand" "") -+ (match_operand:SI 3 "const_int_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (INTVAL (operands[3]) > 3 || INTVAL (operands[3]) < 0) -+ gcc_unreachable (); -+ -+ rtx src = gen_reg_rtx (QImode); -+ -+ convert_move (src, operands[2], false); -+ -+ HOST_WIDE_INT selector_index; -+ /* Big endian need reverse index. */ -+ if (TARGET_BIG_ENDIAN) -+ selector_index = 4 - INTVAL (operands[3]) - 1; -+ else -+ selector_index = INTVAL (operands[3]); -+ rtx selector = gen_int_mode (1 << selector_index, SImode); -+ emit_insn (gen_vec_setv4qi_internal (operands[0], src, -+ operands[1], selector)); -+ DONE; -+}) -+ -+(define_expand "insvsi" -+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "const_int_operand" "") -+ (match_operand:SI 2 "nds32_insv_operand" "")) -+ (match_operand:SI 3 "register_operand" ""))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (INTVAL (operands[1]) != 8) -+ FAIL; -+} -+ [(set_attr "type" "dinsb") -+ (set_attr "length" "4")]) -+ -+ -+(define_insn "insvsi_internal" -+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") -+ (const_int 8) -+ (match_operand:SI 1 "nds32_insv_operand" "i")) -+ (match_operand:SI 2 "register_operand" "r"))] -+ "NDS32_EXT_DSP_P ()" -+ "insb\t%0, %2, %v1" -+ [(set_attr "type" "dinsb") -+ (set_attr "length" "4")]) -+ -+(define_insn "insvsiqi_internal" -+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") -+ (const_int 8) -+ (match_operand:SI 1 "nds32_insv_operand" "i")) -+ (zero_extend:SI (match_operand:QI 2 "register_operand" "r")))] -+ "NDS32_EXT_DSP_P ()" -+ "insb\t%0, %2, %v1" -+ [(set_attr "type" "dinsb") -+ (set_attr "length" "4")]) -+ -+;; Intermedium pattern for synthetize insvsiqi_internal -+;; v0 = ((v1 & 0xff) << 8) -+(define_insn_and_split "and0xff_s8" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") -+ (const_int 8)) -+ (const_int 65280)))] -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx tmp = gen_reg_rtx (SImode); -+ emit_insn (gen_ashlsi3 (tmp, operands[1], gen_int_mode (8, SImode))); -+ emit_insn (gen_andsi3 (operands[0], tmp, gen_int_mode (0xffff, SImode))); -+ DONE; -+}) -+ -+;; v0 = (v1 & 0xff00ffff) | ((v2 << 16) | 0xff0000) -+(define_insn_and_split "insbsi2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0") -+ (const_int -16711681)) -+ (and:SI (ashift:SI (match_operand:SI 2 "register_operand" "r") -+ (const_int 16)) -+ (const_int 16711680))))] -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx tmp = gen_reg_rtx (SImode); -+ emit_move_insn (tmp, operands[1]); -+ emit_insn (gen_insvsi_internal (tmp, gen_int_mode(16, SImode), operands[2])); -+ emit_move_insn (operands[0], tmp); -+ DONE; -+}) -+ -+;; v0 = (v1 & 0xff00ffff) | v2 -+(define_insn_and_split "ior_and0xff00ffff_reg" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "r") -+ (const_int -16711681)) -+ (match_operand:SI 2 "register_operand" "r")))] -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx tmp = gen_reg_rtx (SImode); -+ emit_insn (gen_andsi3 (tmp, operands[1], gen_int_mode (0xff00ffff, SImode))); -+ emit_insn (gen_iorsi3 (operands[0], tmp, operands[2])); -+ DONE; -+}) -+ -+(define_insn "vec_setv4qi_internal" -+ [(set (match_operand:V4QI 0 "register_operand" "= r, r, r, r") -+ (vec_merge:V4QI -+ (vec_duplicate:V4QI -+ (match_operand:QI 1 "register_operand" " r, r, r, r")) -+ (match_operand:V4QI 2 "register_operand" " 0, 0, 0, 0") -+ (match_operand:SI 3 "nds32_imm_1_2_4_8_operand" " Iv01, Iv02, Iv04, Iv08")))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "insb\t%0, %1, 3", -+ "insb\t%0, %1, 2", -+ "insb\t%0, %1, 1", -+ "insb\t%0, %1, 0" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "insb\t%0, %1, 0", -+ "insb\t%0, %1, 1", -+ "insb\t%0, %1, 2", -+ "insb\t%0, %1, 3" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dinsb") -+ (set_attr "length" "4")]) -+ -+(define_insn "vec_setv4qi_internal_vec" -+ [(set (match_operand:V4QI 0 "register_operand" "= r, r, r, r") -+ (vec_merge:V4QI -+ (vec_duplicate:V4QI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r, r, r, r") -+ (parallel [(const_int 0)]))) -+ (match_operand:V4QI 2 "register_operand" " 0, 0, 0, 0") -+ (match_operand:SI 3 "nds32_imm_1_2_4_8_operand" " Iv01, Iv02, Iv04, Iv08")))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ insb\t%0, %1, 0 -+ insb\t%0, %1, 1 -+ insb\t%0, %1, 2 -+ insb\t%0, %1, 3" -+ [(set_attr "type" "dinsb") -+ (set_attr "length" "4")]) -+ -+(define_insn "vec_mergev4qi_and_cv0_1" -+ [(set (match_operand:V4QI 0 "register_operand" "=$l,r") -+ (vec_merge:V4QI -+ (vec_duplicate:V4QI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " l,r") -+ (parallel [(const_int 0)]))) -+ (const_vector:V4QI [ -+ (const_int 0) -+ (const_int 0) -+ (const_int 0) -+ (const_int 0)]) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ zeb33\t%0, %1 -+ zeb\t%0, %1" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_mergev4qi_and_cv0_2" -+ [(set (match_operand:V4QI 0 "register_operand" "=$l,r") -+ (vec_merge:V4QI -+ (const_vector:V4QI [ -+ (const_int 0) -+ (const_int 0) -+ (const_int 0) -+ (const_int 0)]) -+ (vec_duplicate:V4QI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " l,r") -+ (parallel [(const_int 0)]))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ zeb33\t%0, %1 -+ zeb\t%0, %1" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_mergeqi_and_cv0_1" -+ [(set (match_operand:V4QI 0 "register_operand" "=$l,r") -+ (vec_merge:V4QI -+ (vec_duplicate:V4QI (match_operand:QI 1 "register_operand" " l,r")) -+ (const_vector:V4QI [ -+ (const_int 0) -+ (const_int 0) -+ (const_int 0) -+ (const_int 0)]) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ zeb33\t%0, %1 -+ zeb\t%0, %1" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_mergeqi_and_cv0_2" -+ [(set (match_operand:V4QI 0 "register_operand" "=$l,r") -+ (vec_merge:V4QI -+ (const_vector:V4QI [ -+ (const_int 0) -+ (const_int 0) -+ (const_int 0) -+ (const_int 0)]) -+ (vec_duplicate:V4QI (match_operand:QI 1 "register_operand" " l,r")) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ zeb33\t%0, %1 -+ zeb\t%0, %1" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_expand "vec_setv2hi" -+ [(match_operand:V2HI 0 "register_operand" "") -+ (match_operand:HI 1 "register_operand" "") -+ (match_operand:SI 2 "immediate_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ HOST_WIDE_INT pos = INTVAL (operands[2]); -+ if (pos > 2) -+ gcc_unreachable (); -+ HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << pos; -+ emit_insn (gen_vec_setv2hi_internal (operands[0], operands[1], -+ operands[0], GEN_INT (elem))); -+ DONE; -+}) -+ -+(define_insn "vec_setv2hi_internal" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (match_operand:HI 1 "register_operand" " r, r")) -+ (match_operand:V2HI 2 "register_operand" " r, r") -+ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv02")))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "pkbb16\t%0, %1, %2", -+ "pktb16\t%0, %2, %1" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "pktb16\t%0, %2, %1", -+ "pkbb16\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "vec_mergev2hi_and_cv0_1" -+ [(set (match_operand:V2HI 0 "register_operand" "=$l,r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " l,r") -+ (parallel [(const_int 0)]))) -+ (const_vector:V2HI [ -+ (const_int 0) -+ (const_int 0)]) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ zeh33\t%0, %1 -+ zeh\t%0, %1" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_mergev2hi_and_cv0_2" -+ [(set (match_operand:V2HI 0 "register_operand" "=$l,r") -+ (vec_merge:V2HI -+ (const_vector:V2HI [ -+ (const_int 0) -+ (const_int 0)]) -+ (vec_duplicate:V2HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " l,r") -+ (parallel [(const_int 0)]))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ zeh33\t%0, %1 -+ zeh\t%0, %1" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_mergehi_and_cv0_1" -+ [(set (match_operand:V2HI 0 "register_operand" "=$l,r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI (match_operand:HI 1 "register_operand" " l,r")) -+ (const_vector:V2HI [ -+ (const_int 0) -+ (const_int 0)]) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ zeh33\t%0, %1 -+ zeh\t%0, %1" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_mergehi_and_cv0_2" -+ [(set (match_operand:V2HI 0 "register_operand" "=$l,r") -+ (vec_merge:V2HI -+ (const_vector:V2HI [ -+ (const_int 0) -+ (const_int 0)]) -+ (vec_duplicate:V2HI (match_operand:HI 1 "register_operand" " l,r")) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ zeh33\t%0, %1 -+ zeh\t%0, %1" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_expand "pkbb" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V2HI 1 "register_operand") -+ (match_operand:V2HI 2 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], -+ GEN_INT (1), GEN_INT (1), GEN_INT (1))); -+ } -+ else -+ { -+ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], -+ GEN_INT (2), GEN_INT (0), GEN_INT (0))); -+ } -+ DONE; -+}) -+ -+(define_insn "pkbbsi_1" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "r") -+ (const_int 65535)) -+ (ashift:SI (match_operand:SI 2 "register_operand" "r") -+ (const_int 16))))] -+ "NDS32_EXT_DSP_P ()" -+ "pkbb16\t%0, %2, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "pkbbsi_2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI (ashift:SI (match_operand:SI 2 "register_operand" "r") -+ (const_int 16)) -+ (and:SI (match_operand:SI 1 "register_operand" "r") -+ (const_int 65535))))] -+ "NDS32_EXT_DSP_P ()" -+ "pkbb16\t%0, %2, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "pkbbsi_3" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) -+ (ashift:SI (match_operand:SI 2 "register_operand" "r") -+ (const_int 16))))] -+ "NDS32_EXT_DSP_P ()" -+ "pkbb16\t%0, %2, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "pkbbsi_4" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI (ashift:SI (match_operand:SI 2 "register_operand" "r") -+ (const_int 16)) -+ (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))))] -+ "NDS32_EXT_DSP_P ()" -+ "pkbb16\t%0, %2, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+;; v0 = (v1 & 0xffff0000) | (v2 & 0xffff) -+(define_insn "pktbsi_1" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "r") -+ (const_int -65536)) -+ (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] -+ "NDS32_EXT_DSP_P ()" -+ "pktb16\t%0, %1, %2" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "pktbsi_2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "r") -+ (const_int -65536)) -+ (and:SI (match_operand:SI 2 "register_operand" "r") -+ (const_int 65535))))] -+ "NDS32_EXT_DSP_P ()" -+ "pktb16\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "pktbsi_3" -+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") -+ (const_int 16 ) -+ (const_int 0)) -+ (match_operand:SI 1 "register_operand" " r"))] -+ "NDS32_EXT_DSP_P ()" -+ "pktb16\t%0, %0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "pktbsi_4" -+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") -+ (const_int 16 ) -+ (const_int 0)) -+ (zero_extend:SI (match_operand:HI 1 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "pktb16\t%0, %0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "pkttsi" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI (and:SI (match_operand:SI 1 "register_operand" " r") -+ (const_int -65536)) -+ (lshiftrt:SI (match_operand:SI 2 "register_operand" " r") -+ (const_int 16))))] -+ "NDS32_EXT_DSP_P ()" -+ "pktt16\t%0, %1, %2" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_expand "pkbt" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V2HI 1 "register_operand") -+ (match_operand:V2HI 2 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], -+ GEN_INT (1), GEN_INT (1), GEN_INT (0))); -+ } -+ else -+ { -+ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], -+ GEN_INT (2), GEN_INT (0), GEN_INT (1))); -+ } -+ DONE; -+}) -+ -+(define_expand "pktt" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V2HI 1 "register_operand") -+ (match_operand:V2HI 2 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], -+ GEN_INT (1), GEN_INT (0), GEN_INT (0))); -+ } -+ else -+ { -+ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], -+ GEN_INT (2), GEN_INT (1), GEN_INT (1))); -+ } -+ DONE; -+}) -+ -+(define_expand "pktb" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V2HI 1 "register_operand") -+ (match_operand:V2HI 2 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], -+ GEN_INT (1), GEN_INT (0), GEN_INT (1))); -+ } -+ else -+ { -+ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], -+ GEN_INT (2), GEN_INT (1), GEN_INT (0))); -+ } -+ DONE; -+}) -+ -+(define_insn "vec_mergerr" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (match_operand:HI 1 "register_operand" " r, r")) -+ (vec_duplicate:V2HI -+ (match_operand:HI 2 "register_operand" " r, r")) -+ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv02")))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ pkbb16\t%0, %2, %1 -+ pkbb16\t%0, %1, %2" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+ -+(define_insn "vec_merge" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r") -+ (vec_merge:V2HI -+ (match_operand:V2HI 1 "register_operand" " r, r") -+ (match_operand:V2HI 2 "register_operand" " r, r") -+ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv02")))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "pktb16\t%0, %1, %2", -+ "pktb16\t%0, %2, %1" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "pktb16\t%0, %2, %1", -+ "pktb16\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "vec_mergerv" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r, r, r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (match_operand:HI 1 "register_operand" " r, r, r, r")) -+ (vec_duplicate:V2HI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r, r, r, r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv00, Iv01")]))) -+ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv01, Iv02, Iv02")))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ pkbb16\t%0, %2, %1 -+ pktb16\t%0, %2, %1 -+ pkbb16\t%0, %1, %2 -+ pkbt16\t%0, %1, %2" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "vec_mergevr" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r, r, r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r, r, r, r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv00, Iv01")]))) -+ (vec_duplicate:V2HI -+ (match_operand:HI 2 "register_operand" " r, r, r, r")) -+ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv01, Iv02, Iv02")))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ pkbb16\t%0, %2, %1 -+ pkbt16\t%0, %2, %1 -+ pkbb16\t%0, %1, %2 -+ pktb16\t%0, %1, %2" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "vec_mergevv" -+ [(set (match_operand:V2HI 0 "register_operand" "= r, r, r, r, r, r, r, r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r, r, r, r, r, r, r, r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv00, Iv01, Iv01, Iv00, Iv00, Iv01, Iv01")]))) -+ (vec_duplicate:V2HI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r, r, r, r, r, r, r, r") -+ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv01, Iv00, Iv00, Iv01, Iv01, Iv00")]))) -+ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv01, Iv01, Iv01, Iv02, Iv02, Iv02, Iv02")))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "pktt16\t%0, %1, %2", -+ "pktb16\t%0, %1, %2", -+ "pkbb16\t%0, %1, %2", -+ "pkbt16\t%0, %1, %2", -+ "pktt16\t%0, %2, %1", -+ "pkbt16\t%0, %2, %1", -+ "pkbb16\t%0, %2, %1", -+ "pktb16\t%0, %2, %1" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "pkbb16\t%0, %2, %1", -+ "pktb16\t%0, %2, %1", -+ "pktt16\t%0, %2, %1", -+ "pkbt16\t%0, %2, %1", -+ "pkbb16\t%0, %1, %2", -+ "pkbt16\t%0, %1, %2", -+ "pktt16\t%0, %1, %2", -+ "pktb16\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_expand "vec_extractv4qi" -+ [(set (match_operand:QI 0 "register_operand" "") -+ (vec_select:QI -+ (match_operand:V4QI 1 "nonimmediate_operand" "") -+ (parallel [(match_operand:SI 2 "const_int_operand" "")])))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+{ -+ if (INTVAL (operands[2]) != 0 -+ && INTVAL (operands[2]) != 1 -+ && INTVAL (operands[2]) != 2 -+ && INTVAL (operands[2]) != 3) -+ gcc_unreachable (); -+ -+ if (INTVAL (operands[2]) != 0 && MEM_P (operands[0])) -+ FAIL; -+}) -+ -+(define_insn "vec_extractv4qi0" -+ [(set (match_operand:QI 0 "register_operand" "=l,r,r") -+ (vec_select:QI -+ (match_operand:V4QI 1 "nonimmediate_operand" " l,r,m") -+ (parallel [(const_int 0)])))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+{ -+ switch (which_alternative) -+ { -+ case 0: -+ return "zeb33\t%0, %1"; -+ case 1: -+ return "zeb\t%0, %1"; -+ case 2: -+ return nds32_output_32bit_load (operands, 1); -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "vec_extractv4qi0_ze" -+ [(set (match_operand:SI 0 "register_operand" "=l,r,r") -+ (zero_extend:SI -+ (vec_select:QI -+ (match_operand:V4QI 1 "nonimmediate_operand" " l,r,m") -+ (parallel [(const_int 0)]))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+{ -+ switch (which_alternative) -+ { -+ case 0: -+ return "zeb33\t%0, %1"; -+ case 1: -+ return "zeb\t%0, %1"; -+ case 2: -+ return nds32_output_32bit_load (operands, 1); -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "vec_extractv4qi0_se" -+ [(set (match_operand:SI 0 "register_operand" "=l,r,r") -+ (sign_extend:SI -+ (vec_select:QI -+ (match_operand:V4QI 1 "nonimmediate_operand" " l,r,m") -+ (parallel [(const_int 0)]))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+{ -+ switch (which_alternative) -+ { -+ case 0: -+ return "seb33\t%0, %1"; -+ case 1: -+ return "seb\t%0, %1"; -+ case 2: -+ return nds32_output_32bit_load_s (operands, 1); -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "vec_extractv4qi1" -+ [(set (match_operand:QI 0 "register_operand" "=r") -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 1)])))] -+ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx tmp = gen_reg_rtx (V4QImode); -+ emit_insn (gen_rotrv4qi_1 (tmp, operands[1])); -+ emit_insn (gen_vec_extractv4qi0 (operands[0], tmp)); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "vec_extractv4qi2" -+ [(set (match_operand:QI 0 "register_operand" "=r") -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 2)])))] -+ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx tmp = gen_reg_rtx (V4QImode); -+ emit_insn (gen_rotrv4qi_2 (tmp, operands[1])); -+ emit_insn (gen_vec_extractv4qi0 (operands[0], tmp)); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "vec_extractv4qi3" -+ [(set (match_operand:QI 0 "register_operand" "=r") -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 3)])))] -+ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx tmp = gen_reg_rtx (V4QImode); -+ emit_insn (gen_rotrv4qi_3 (tmp, operands[1])); -+ emit_insn (gen_vec_extractv4qi0 (operands[0], tmp)); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "vec_extractv4qi3_se" -+ [(set (match_operand:SI 0 "register_operand" "=$d,r") -+ (sign_extend:SI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " 0,r") -+ (parallel [(const_int 3)]))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ srai45\t%0, 24 -+ srai\t%0, %1, 24" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_extractv4qi3_ze" -+ [(set (match_operand:SI 0 "register_operand" "=$d,r") -+ (zero_extend:SI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " 0,r") -+ (parallel [(const_int 3)]))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ srli45\t%0, 24 -+ srli\t%0, %1, 24" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn_and_split "vec_extractv4qihi0" -+ [(set (match_operand:HI 0 "register_operand" "=r") -+ (sign_extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 0)]))))] -+ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx tmp = gen_reg_rtx (QImode); -+ emit_insn (gen_vec_extractv4qi0 (tmp, operands[1])); -+ emit_insn (gen_extendqihi2 (operands[0], tmp)); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "vec_extractv4qihi1" -+ [(set (match_operand:HI 0 "register_operand" "=r") -+ (sign_extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 1)]))))] -+ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx tmp = gen_reg_rtx (QImode); -+ emit_insn (gen_vec_extractv4qi1 (tmp, operands[1])); -+ emit_insn (gen_extendqihi2 (operands[0], tmp)); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "vec_extractv4qihi2" -+ [(set (match_operand:HI 0 "register_operand" "=r") -+ (sign_extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 2)]))))] -+ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx tmp = gen_reg_rtx (QImode); -+ emit_insn (gen_vec_extractv4qi2 (tmp, operands[1])); -+ emit_insn (gen_extendqihi2 (operands[0], tmp)); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "vec_extractv4qihi3" -+ [(set (match_operand:HI 0 "register_operand" "=r") -+ (sign_extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 3)]))))] -+ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx tmp = gen_reg_rtx (QImode); -+ emit_insn (gen_vec_extractv4qi3 (tmp, operands[1])); -+ emit_insn (gen_extendqihi2 (operands[0], tmp)); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_expand "vec_extractv2hi" -+ [(set (match_operand:HI 0 "register_operand" "") -+ (vec_select:HI -+ (match_operand:V2HI 1 "nonimmediate_operand" "") -+ (parallel [(match_operand:SI 2 "const_int_operand" "")])))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (INTVAL (operands[2]) != 0 -+ && INTVAL (operands[2]) != 1) -+ gcc_unreachable (); -+ -+ if (INTVAL (operands[2]) != 0 && MEM_P (operands[0])) -+ FAIL; -+}) -+ -+(define_insn "vec_extractv2hi0" -+ [(set (match_operand:HI 0 "register_operand" "=$l,r,r") -+ (vec_select:HI -+ (match_operand:V2HI 1 "nonimmediate_operand" " l,r,m") -+ (parallel [(const_int 0)])))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+{ -+ switch (which_alternative) -+ { -+ case 0: -+ return "seh33\t%0, %1"; -+ case 1: -+ return "seh\t%0, %1"; -+ case 2: -+ return nds32_output_32bit_load_s (operands, 2); -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "alu,alu,load") -+ (set_attr "length" " 2, 4, 4")]) -+ -+(define_insn "vec_extractv2hi0_ze" -+ [(set (match_operand:SI 0 "register_operand" "=$l, r,$ l, *r") -+ (zero_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "nonimmediate_operand" " l, r, U33, m") -+ (parallel [(const_int 0)]))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+{ -+ switch (which_alternative) -+ { -+ case 0: -+ return "zeh33\t%0, %1"; -+ case 1: -+ return "zeh\t%0, %1"; -+ case 2: -+ return nds32_output_16bit_load (operands, 2); -+ case 3: -+ return nds32_output_32bit_load (operands, 2); -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "alu,alu,load,load") -+ (set_attr "length" " 2, 4, 2, 4")]) -+ -+(define_insn "vec_extractv2hi0_se" -+ [(set (match_operand:SI 0 "register_operand" "=$l, r, r") -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "nonimmediate_operand" " l,r,m") -+ (parallel [(const_int 0)]))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+{ -+ switch (which_alternative) -+ { -+ case 0: -+ return "seh33\t%0, %1"; -+ case 1: -+ return "seh\t%0, %1"; -+ case 2: -+ return nds32_output_32bit_load_s (operands, 2); -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "alu,alu,load") -+ (set_attr "length" " 2, 4, 4")]) -+ -+(define_insn "vec_extractv2hi0_be" -+ [(set (match_operand:HI 0 "register_operand" "=$d,r") -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " 0,r") -+ (parallel [(const_int 0)])))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "@ -+ srai45\t%0, 16 -+ srai\t%0, %1, 16" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_extractv2hi1" -+ [(set (match_operand:HI 0 "register_operand" "=$d,r") -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " 0,r") -+ (parallel [(const_int 1)])))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ srai45\t%0, 16 -+ srai\t%0, %1, 16" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_extractv2hi1_se" -+ [(set (match_operand:SI 0 "register_operand" "=$d,r") -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " 0,r") -+ (parallel [(const_int 1)]))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ srai45\t%0, 16 -+ srai\t%0, %1, 16" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_extractv2hi1_ze" -+ [(set (match_operand:SI 0 "register_operand" "=$d,r") -+ (zero_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " 0,r") -+ (parallel [(const_int 1)]))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "@ -+ srli45\t%0, 16 -+ srli\t%0, %1, 16" -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_insn "vec_extractv2hi1_be" -+ [(set (match_operand:HI 0 "register_operand" "=$l,r,r") -+ (vec_select:HI -+ (match_operand:V2HI 1 "nonimmediate_operand" " l,r,m") -+ (parallel [(const_int 1)])))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+{ -+ switch (which_alternative) -+ { -+ case 0: -+ return "seh33\t%0, %1"; -+ case 1: -+ return "seh\t%0, %1"; -+ case 2: -+ return nds32_output_32bit_load_s (operands, 2); -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "alu,alu,load") -+ (set_attr "length" " 2, 4, 4")]) -+ -+(define_insn "mul16" -+ [(set (match_operand:V2SI 0 "register_operand" "=r") -+ (mult:V2SI (extend:V2SI (match_operand:V2HI 1 "register_operand" "%r")) -+ (extend:V2SI (match_operand:V2HI 2 "register_operand" " r"))))] -+ "NDS32_EXT_DSP_P ()" -+ "mul16\t%0, %1, %2" -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_insn "mulx16" -+ [(set (match_operand:V2SI 0 "register_operand" "=r") -+ (vec_merge:V2SI -+ (vec_duplicate:V2SI -+ (mult:SI -+ (extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))))) -+ (vec_duplicate:V2SI -+ (mult:SI -+ (extend:SI -+ (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)]))) -+ (extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P ()" -+ "mulx16\t%0, %1, %2" -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_insn "rotrv2hi_1" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_select:V2HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1) (const_int 0)])))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "rotri\t%0, %1, 16" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "rotrv2hi_1_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_select:V2HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0) (const_int 1)])))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "rotri\t%0, %1, 16" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "rotrv4qi_1" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (vec_select:V4QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 1) (const_int 2) (const_int 3) (const_int 0)])))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "rotri\t%0, %1, 8" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "rotrv4qi_1_be" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (vec_select:V4QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 2) (const_int 1) (const_int 0) (const_int 3)])))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "rotri\t%0, %1, 8" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "rotrv4qi_2" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (vec_select:V4QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 2) (const_int 3) (const_int 0) (const_int 1)])))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "rotri\t%0, %1, 16" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "rotrv4qi_2_be" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (vec_select:V4QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 1) (const_int 0) (const_int 3) (const_int 2)])))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "rotri\t%0, %1, 16" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "rotrv4qi_3" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (vec_select:V4QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 3) (const_int 0) (const_int 1) (const_int 2)])))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "rotri\t%0, %1, 24" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "rotrv4qi_3_be" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (vec_select:V4QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 0) (const_int 3) (const_int 2) (const_int 1)])))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "rotri\t%0, %1, 24" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "v4qi_dup_10" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (vec_select:V4QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 0) (const_int 1) (const_int 0) (const_int 1)])))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "pkbb\t%0, %1, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "v4qi_dup_32" -+ [(set (match_operand:V4QI 0 "register_operand" "=r") -+ (vec_select:V4QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 2) (const_int 3) (const_int 2) (const_int 3)])))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "pktt\t%0, %1, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_expand "vec_unpacks_lo_v4qi" -+ [(match_operand:V2HI 0 "register_operand" "=r") -+ (match_operand:V4QI 1 "register_operand" " r")] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+{ -+ emit_insn (gen_sunpkd810 (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_expand "sunpkd810" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V4QI 1 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_sunpkd810_imp_be (operands[0], operands[1])); -+ else -+ emit_insn (gen_sunpkd810_imp (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_insn "unpkd810_imp" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 0)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "unpkd810\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd810_imp_inv" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 1)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "unpkd810\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd810_imp_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 2)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 3)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "unpkd810\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd810_imp_inv_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 3)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 2)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "unpkd810\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_expand "sunpkd820" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V4QI 1 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_sunpkd820_imp_be (operands[0], operands[1])); -+ else -+ emit_insn (gen_sunpkd820_imp (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_insn "unpkd820_imp" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 2)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 0)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "unpkd820\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd820_imp_inv" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 2)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "unpkd820\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd820_imp_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 3)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "unpkd820\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd820_imp_inv_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 3)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 1)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "unpkd820\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_expand "sunpkd830" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V4QI 1 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_sunpkd830_imp_be (operands[0], operands[1])); -+ else -+ emit_insn (gen_sunpkd830_imp (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_insn "unpkd830_imp" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 3)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 0)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "unpkd830\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd830_imp_inv" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 3)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "unpkd830\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd830_imp_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 3)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "unpkd830\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd830_imp_inv_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 3)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 0)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "unpkd830\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_expand "sunpkd831" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V4QI 1 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_sunpkd831_imp_be (operands[0], operands[1])); -+ else -+ emit_insn (gen_sunpkd831_imp (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_insn "unpkd831_imp" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 3)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 1)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "unpkd831\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd831_imp_inv" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 3)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "unpkd831\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd831_imp_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 2)])))) -+ (const_int 1)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "unpkd831\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "unpkd831_imp_inv_be" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 2)])))) -+ (vec_duplicate:V2HI -+ (extend:HI -+ (vec_select:QI -+ (match_dup 1) -+ (parallel [(const_int 0)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "unpkd831\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_expand "zunpkd810" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V4QI 1 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_zunpkd810_imp_be (operands[0], operands[1])); -+ else -+ emit_insn (gen_zunpkd810_imp (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_expand "zunpkd820" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V4QI 1 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_zunpkd820_imp_be (operands[0], operands[1])); -+ else -+ emit_insn (gen_zunpkd820_imp (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_expand "zunpkd830" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V4QI 1 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_zunpkd830_imp_be (operands[0], operands[1])); -+ else -+ emit_insn (gen_zunpkd830_imp (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_expand "zunpkd831" -+ [(match_operand:V2HI 0 "register_operand") -+ (match_operand:V4QI 1 "register_operand")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_zunpkd831_imp_be (operands[0], operands[1])); -+ else -+ emit_insn (gen_zunpkd831_imp (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_expand "smbb" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], -+ GEN_INT (1), GEN_INT (1))); -+ else -+ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], -+ GEN_INT (0), GEN_INT (0))); -+ DONE; -+}) -+ -+(define_expand "smbt" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], -+ GEN_INT (1), GEN_INT (0))); -+ else -+ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], -+ GEN_INT (0), GEN_INT (1))); -+ DONE; -+}) -+ -+(define_expand "smtt" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], -+ GEN_INT (0), GEN_INT (0))); -+ else -+ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], -+ GEN_INT (1), GEN_INT (1))); -+ DONE; -+}) -+ -+(define_insn "mulhisi3v" -+ [(set (match_operand:SI 0 "register_operand" "= r, r, r, r") -+ (mult:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r, r, r, r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv00, Iv01, Iv01")]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r, r, r, r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv01, Iv00")])))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "smtt\t%0, %1, %2", -+ "smbt\t%0, %2, %1", -+ "smbb\t%0, %1, %2", -+ "smbt\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "smbb\t%0, %1, %2", -+ "smbt\t%0, %1, %2", -+ "smtt\t%0, %1, %2", -+ "smbt\t%0, %2, %1" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_expand "kmabb" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "") -+ (match_operand:V2HI 3 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], -+ GEN_INT (1), GEN_INT (1), -+ operands[1])); -+ else -+ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], -+ GEN_INT (0), GEN_INT (0), -+ operands[1])); -+ DONE; -+}) -+ -+(define_expand "kmabt" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "") -+ (match_operand:V2HI 3 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], -+ GEN_INT (1), GEN_INT (0), -+ operands[1])); -+ else -+ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], -+ GEN_INT (0), GEN_INT (1), -+ operands[1])); -+ DONE; -+}) -+ -+(define_expand "kmatt" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "") -+ (match_operand:V2HI 3 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], -+ GEN_INT (0), GEN_INT (0), -+ operands[1])); -+ else -+ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], -+ GEN_INT (1), GEN_INT (1), -+ operands[1])); -+ DONE; -+}) -+ -+(define_insn "kma_internal" -+ [(set (match_operand:SI 0 "register_operand" "= r, r, r, r") -+ (ss_plus:SI -+ (mult:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r, r, r, r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv00, Iv01, Iv01")]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r, r, r, r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv01, Iv00")])))) -+ (match_operand:SI 5 "register_operand" " 0, 0, 0, 0")))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "kmatt\t%0, %1, %2", -+ "kmabt\t%0, %2, %1", -+ "kmabb\t%0, %1, %2", -+ "kmabt\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "kmabb\t%0, %1, %2", -+ "kmabt\t%0, %1, %2", -+ "kmatt\t%0, %1, %2", -+ "kmabt\t%0, %2, %1" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_expand "smds" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smds_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_smds_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_expand "smds_le" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+}) -+ -+(define_expand "smds_be" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+}) -+ -+(define_expand "smdrs" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smdrs_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_smdrs_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_expand "smdrs_le" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+}) -+ -+(define_expand "smdrs_be" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+}) -+ -+(define_expand "smxdsv" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:V2HI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smxdsv_be (operands[0], operands[1], operands[2])); -+ else -+ emit_insn (gen_smxdsv_le (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+ -+(define_expand "smxdsv_le" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+}) -+ -+(define_expand "smxdsv_be" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+}) -+ -+(define_insn "smal1" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI (match_operand:DI 1 "register_operand" " r") -+ (sign_extend:DI -+ (mult:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "smal\t%0, %1, %2" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smal2" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI (match_operand:DI 1 "register_operand" " r") -+ (mult:DI -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:DI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))))))] -+ "NDS32_EXT_DSP_P ()" -+ "smal\t%0, %1, %2" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smal3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI (match_operand:DI 1 "register_operand" " r") -+ (sign_extend:DI -+ (mult:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "smal\t%0, %1, %2" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smal4" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI (match_operand:DI 1 "register_operand" " r") -+ (mult:DI -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:DI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))))))] -+ "NDS32_EXT_DSP_P ()" -+ "smal\t%0, %1, %2" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smal5" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (sign_extend:DI -+ (mult:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))))) -+ (match_operand:DI 1 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "smal\t%0, %1, %2" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smal6" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (mult:DI -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:DI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)])))) -+ (match_operand:DI 1 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "smal\t%0, %1, %2" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smal7" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (sign_extend:DI -+ (mult:SI -+ (sign_extend:SI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))))) -+ (match_operand:DI 1 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "smal\t%0, %1, %2" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smal8" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (mult:DI -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:DI -+ (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)])))) -+ (match_operand:DI 1 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "smal\t%0, %1, %2" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+;; We need this dummy pattern for smal -+(define_insn_and_split "extendsidi2" -+ [(set (match_operand:DI 0 "register_operand" "") -+ (sign_extend:DI (match_operand:SI 1 "nds32_move_operand" "")))] -+ "NDS32_EXT_DSP_P ()" -+ "#" -+ "NDS32_EXT_DSP_P ()" -+ [(const_int 0)] -+{ -+ rtx high_part_dst, low_part_dst; -+ -+ low_part_dst = nds32_di_low_part_subreg (operands[0]); -+ high_part_dst = nds32_di_high_part_subreg (operands[0]); -+ -+ emit_move_insn (low_part_dst, operands[1]); -+ emit_insn (gen_ashrsi3 (high_part_dst, low_part_dst, GEN_INT (31))); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+;; We need this dummy pattern for usmar64/usmsr64 -+(define_insn_and_split "zero_extendsidi2" -+ [(set (match_operand:DI 0 "register_operand" "") -+ (zero_extend:DI (match_operand:SI 1 "nds32_move_operand" "")))] -+ "NDS32_EXT_DSP_P ()" -+ "#" -+ "NDS32_EXT_DSP_P ()" -+ [(const_int 0)] -+{ -+ rtx high_part_dst, low_part_dst; -+ -+ low_part_dst = nds32_di_low_part_subreg (operands[0]); -+ high_part_dst = nds32_di_high_part_subreg (operands[0]); -+ -+ emit_move_insn (low_part_dst, operands[1]); -+ emit_move_insn (high_part_dst, const0_rtx); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "extendhidi2" -+ [(set (match_operand:DI 0 "register_operand" "") -+ (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "")))] -+ "NDS32_EXT_DSP_P ()" -+ "#" -+ "NDS32_EXT_DSP_P ()" -+ [(const_int 0)] -+{ -+ rtx high_part_dst, low_part_dst; -+ -+ low_part_dst = nds32_di_low_part_subreg (operands[0]); -+ high_part_dst = nds32_di_high_part_subreg (operands[0]); -+ -+ -+ emit_insn (gen_extendhisi2 (low_part_dst, operands[1])); -+ emit_insn (gen_ashrsi3 (high_part_dst, low_part_dst, GEN_INT (31))); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_insn "extendqihi2" -+ [(set (match_operand:HI 0 "register_operand" "=r") -+ (sign_extend:HI (match_operand:QI 1 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "sunpkd820\t%0, %1" -+ [(set_attr "type" "dpack") -+ (set_attr "length" "4")]) -+ -+(define_insn "smulsi3_highpart" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (lshiftrt:DI -+ (mult:DI -+ (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) -+ (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))) -+ (const_int 32))))] -+ "NDS32_EXT_DSP_P ()" -+ "smmul\t%0, %1, %2" -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_insn "smmul_round" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (lshiftrt:DI -+ (unspec:DI [(mult:DI -+ (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) -+ (sign_extend:DI (match_operand:SI 2 "register_operand" " r")))] -+ UNSPEC_ROUND) -+ (const_int 32))))] -+ "NDS32_EXT_DSP_P ()" -+ "smmul.u\t%0, %1, %2" -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmmac" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI (match_operand:SI 1 "register_operand" " 0") -+ (truncate:SI -+ (lshiftrt:DI -+ (mult:DI -+ (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) -+ (sign_extend:DI (match_operand:SI 3 "register_operand" " r"))) -+ (const_int 32)))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmmac\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmmac_round" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI (match_operand:SI 1 "register_operand" " 0") -+ (truncate:SI -+ (lshiftrt:DI -+ (unspec:DI [(mult:DI -+ (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) -+ (sign_extend:DI (match_operand:SI 3 "register_operand" " r")))] -+ UNSPEC_ROUND) -+ (const_int 32)))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmmac.u\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmmsb" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_minus:SI (match_operand:SI 1 "register_operand" " 0") -+ (truncate:SI -+ (lshiftrt:DI -+ (mult:DI -+ (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) -+ (sign_extend:DI (match_operand:SI 3 "register_operand" " r"))) -+ (const_int 32)))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmmsb\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmmsb_round" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_minus:SI (match_operand:SI 1 "register_operand" " 0") -+ (truncate:SI -+ (lshiftrt:DI -+ (unspec:DI [(mult:DI -+ (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) -+ (sign_extend:DI (match_operand:SI 3 "register_operand" " r")))] -+ UNSPEC_ROUND) -+ (const_int 32)))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmmsb.u\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kwmmul" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (lshiftrt:DI -+ (ss_mult:DI -+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) (const_int 2)) -+ (mult:DI (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) (const_int 2))) -+ (const_int 32))))] -+ "NDS32_EXT_DSP_P ()" -+ "kwmmul\t%0, %1, %2" -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_insn "kwmmul_round" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (lshiftrt:DI -+ (unspec:DI [ -+ (ss_mult:DI -+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) (const_int 2)) -+ (mult:DI (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) (const_int 2)))] -+ UNSPEC_ROUND) -+ (const_int 32))))] -+ "NDS32_EXT_DSP_P ()" -+ "kwmmul.u\t%0, %1, %2" -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_expand "smmwb" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smulhisi3_highpart_1 (operands[0], operands[1], operands[2], GEN_INT (1))); -+ else -+ emit_insn (gen_smulhisi3_highpart_1 (operands[0], operands[1], operands[2], GEN_INT (0))); -+ DONE; -+}) -+ -+(define_expand "smmwt" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smulhisi3_highpart_1 (operands[0], operands[1], operands[2], GEN_INT (0))); -+ else -+ emit_insn (gen_smulhisi3_highpart_1 (operands[0], operands[1], operands[2], GEN_INT (1))); -+ DONE; -+}) -+ -+(define_insn "smulhisi3_highpart_1" -+ [(set (match_operand:SI 0 "register_operand" "= r, r") -+ (truncate:SI -+ (lshiftrt:DI -+ (mult:DI -+ (sign_extend:DI (match_operand:SI 1 "register_operand" " r, r")) -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r, r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv01")])))) -+ (const_int 16))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "smmwt\t%0, %1, %2", -+ "smmwb\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "smmwb\t%0, %1, %2", -+ "smmwt\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_insn "smulhisi3_highpart_2" -+ [(set (match_operand:SI 0 "register_operand" "= r, r") -+ (truncate:SI -+ (lshiftrt:DI -+ (mult:DI -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r, r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv01")]))) -+ (sign_extend:DI (match_operand:SI 2 "register_operand" " r, r"))) -+ (const_int 16))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "smmwt\t%0, %1, %2", -+ "smmwb\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "smmwb\t%0, %1, %2", -+ "smmwt\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_expand "smmwb_round" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smmw_round_internal (operands[0], operands[1], operands[2], GEN_INT (1))); -+ else -+ emit_insn (gen_smmw_round_internal (operands[0], operands[1], operands[2], GEN_INT (0))); -+ DONE; -+}) -+ -+(define_expand "smmwt_round" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smmw_round_internal (operands[0], operands[1], operands[2], GEN_INT (0))); -+ else -+ emit_insn (gen_smmw_round_internal (operands[0], operands[1], operands[2], GEN_INT (1))); -+ DONE; -+}) -+ -+(define_insn "smmw_round_internal" -+ [(set (match_operand:SI 0 "register_operand" "= r, r") -+ (truncate:SI -+ (lshiftrt:DI -+ (unspec:DI -+ [(mult:DI -+ (sign_extend:DI (match_operand:SI 1 "register_operand" " r, r")) -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r, r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv01")]))))] -+ UNSPEC_ROUND) -+ (const_int 16))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "smmwt.u\t%0, %1, %2", -+ "smmwb.u\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "smmwb.u\t%0, %1, %2", -+ "smmwt.u\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dmul") -+ (set_attr "length" "4")]) -+ -+(define_expand "kmmawb" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "register_operand" "") -+ (match_operand:V2HI 3 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_kmmaw_internal (operands[0], operands[2], operands[3], GEN_INT (1), operands[1])); -+ else -+ emit_insn (gen_kmmaw_internal (operands[0], operands[2], operands[3], GEN_INT (0), operands[1])); -+ DONE; -+}) -+ -+(define_expand "kmmawt" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "register_operand" "") -+ (match_operand:V2HI 3 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_kmmaw_internal (operands[0], operands[2], operands[3], GEN_INT (0), operands[1])); -+ else -+ emit_insn (gen_kmmaw_internal (operands[0], operands[2], operands[3], GEN_INT (1), operands[1])); -+ DONE; -+}) -+ -+(define_insn "kmmaw_internal" -+ [(set (match_operand:SI 0 "register_operand" "= r, r") -+ (ss_plus:SI -+ (match_operand:SI 4 "register_operand" " 0, 0") -+ (truncate:SI -+ (lshiftrt:DI -+ (mult:DI -+ (sign_extend:DI (match_operand:SI 1 "register_operand" " r, r")) -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r, r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv01")])))) -+ (const_int 16)))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "kmmawt\t%0, %1, %2", -+ "kmmawb\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "kmmawb\t%0, %1, %2", -+ "kmmawt\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_expand "kmmawb_round" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "register_operand" "") -+ (match_operand:V2HI 3 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_kmmaw_round_internal (operands[0], operands[2], operands[3], GEN_INT (1), operands[1])); -+ else -+ emit_insn (gen_kmmaw_round_internal (operands[0], operands[2], operands[3], GEN_INT (0), operands[1])); -+ DONE; -+} -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ -+(define_expand "kmmawt_round" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "register_operand" "") -+ (match_operand:V2HI 3 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_kmmaw_round_internal (operands[0], operands[2], operands[3], GEN_INT (0), operands[1])); -+ else -+ emit_insn (gen_kmmaw_round_internal (operands[0], operands[2], operands[3], GEN_INT (1), operands[1])); -+ DONE; -+} -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+ -+(define_insn "kmmaw_round_internal" -+ [(set (match_operand:SI 0 "register_operand" "= r, r") -+ (ss_plus:SI -+ (match_operand:SI 4 "register_operand" " 0, 0") -+ (truncate:SI -+ (lshiftrt:DI -+ (unspec:DI -+ [(mult:DI -+ (sign_extend:DI (match_operand:SI 1 "register_operand" " r, r")) -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r, r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv01")]))))] -+ UNSPEC_ROUND) -+ (const_int 16)))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "kmmawt.u\t%0, %1, %2", -+ "kmmawb.u\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "kmmawb.u\t%0, %1, %2", -+ "kmmawt.u\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_expand "smalbb" -+ [(match_operand:DI 0 "register_operand" "") -+ (match_operand:DI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "") -+ (match_operand:V2HI 3 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smaddhidi (operands[0], operands[2], -+ operands[3], operands[1], -+ GEN_INT (1), GEN_INT (1))); -+ else -+ emit_insn (gen_smaddhidi (operands[0], operands[2], -+ operands[3], operands[1], -+ GEN_INT (0), GEN_INT (0))); -+ DONE; -+}) -+ -+(define_expand "smalbt" -+ [(match_operand:DI 0 "register_operand" "") -+ (match_operand:DI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "") -+ (match_operand:V2HI 3 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smaddhidi (operands[0], operands[2], -+ operands[3], operands[1], -+ GEN_INT (1), GEN_INT (0))); -+ else -+ emit_insn (gen_smaddhidi (operands[0], operands[2], -+ operands[3], operands[1], -+ GEN_INT (0), GEN_INT (1))); -+ DONE; -+}) -+ -+(define_expand "smaltt" -+ [(match_operand:DI 0 "register_operand" "") -+ (match_operand:DI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" "") -+ (match_operand:V2HI 3 "register_operand" "")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smaddhidi (operands[0], operands[2], -+ operands[3], operands[1], -+ GEN_INT (0), GEN_INT (0))); -+ else -+ emit_insn (gen_smaddhidi (operands[0], operands[2], -+ operands[3], operands[1], -+ GEN_INT (1), GEN_INT (1))); -+ DONE; -+}) -+ -+(define_insn "smaddhidi" -+ [(set (match_operand:DI 0 "register_operand" "= r, r, r, r") -+ (plus:DI -+ (match_operand:DI 3 "register_operand" " 0, 0, 0, 0") -+ (mult:DI -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r, r, r, r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv00, Iv01, Iv01")]))) -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r, r, r, r") -+ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv01, Iv00")]))))))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "smaltt\t%0, %1, %2", -+ "smalbt\t%0, %2, %1", -+ "smalbb\t%0, %1, %2", -+ "smalbt\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "smalbb\t%0, %1, %2", -+ "smalbt\t%0, %1, %2", -+ "smaltt\t%0, %1, %2", -+ "smalbt\t%0, %2, %1" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smaddhidi2" -+ [(set (match_operand:DI 0 "register_operand" "= r, r, r, r") -+ (plus:DI -+ (mult:DI -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r, r, r, r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv00, Iv01, Iv01")]))) -+ (sign_extend:DI -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r, r, r, r") -+ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv01, Iv00")])))) -+ (match_operand:DI 3 "register_operand" " 0, 0, 0, 0")))] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ { -+ const char *pats[] = { "smaltt\t%0, %1, %2", -+ "smalbt\t%0, %2, %1", -+ "smalbb\t%0, %1, %2", -+ "smalbt\t%0, %1, %2" }; -+ return pats[which_alternative]; -+ } -+ else -+ { -+ const char *pats[] = { "smalbb\t%0, %1, %2", -+ "smalbt\t%0, %1, %2", -+ "smaltt\t%0, %1, %2", -+ "smalbt\t%0, %2, %1" }; -+ return pats[which_alternative]; -+ } -+} -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_expand "smalda1" -+ [(match_operand:DI 0 "register_operand" "") -+ (match_operand:DI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" " r") -+ (match_operand:V2HI 3 "register_operand" " r")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smalda1_be (operands[0], operands[1], operands[2], operands[3])); -+ else -+ emit_insn (gen_smalda1_le (operands[0], operands[1], operands[2], operands[3])); -+ DONE; -+}) -+ -+(define_expand "smalds1" -+ [(match_operand:DI 0 "register_operand" "") -+ (match_operand:DI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" " r") -+ (match_operand:V2HI 3 "register_operand" " r")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smalds1_be (operands[0], operands[1], operands[2], operands[3])); -+ else -+ emit_insn (gen_smalds1_le (operands[0], operands[1], operands[2], operands[3])); -+ DONE; -+}) -+ -+(define_insn "smalda1_le" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (sign_extend:DI -+ (plus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 0)]))))))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "smalda\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smalds1_le" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (sign_extend:DI -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 0)]))))))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "smalds\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smalda1_be" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (sign_extend:DI -+ (plus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 1)]))))))))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "smalda\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smalds1_be" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (sign_extend:DI -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 1)]))))))))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "smalds\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_expand "smaldrs3" -+ [(match_operand:DI 0 "register_operand" "") -+ (match_operand:DI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" " r") -+ (match_operand:V2HI 3 "register_operand" " r")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smaldrs3_be (operands[0], operands[1], operands[2], operands[3])); -+ else -+ emit_insn (gen_smaldrs3_le (operands[0], operands[1], operands[2], operands[3])); -+ DONE; -+}) -+ -+(define_insn "smaldrs3_le" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (sign_extend:DI -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 1)]))))))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "smaldrs\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smaldrs3_be" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (sign_extend:DI -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 0)]))))))))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "smaldrs\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_expand "smalxda1" -+ [(match_operand:DI 0 "register_operand" "") -+ (match_operand:DI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" " r") -+ (match_operand:V2HI 3 "register_operand" " r")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smalxda1_be (operands[0], operands[1], operands[2], operands[3])); -+ else -+ emit_insn (gen_smalxda1_le (operands[0], operands[1], operands[2], operands[3])); -+ DONE; -+}) -+ -+(define_expand "smalxds1" -+ [(match_operand:DI 0 "register_operand" "") -+ (match_operand:DI 1 "register_operand" "") -+ (match_operand:V2HI 2 "register_operand" " r") -+ (match_operand:V2HI 3 "register_operand" " r")] -+ "NDS32_EXT_DSP_P ()" -+{ -+ if (TARGET_BIG_ENDIAN) -+ emit_insn (gen_smalxds1_be (operands[0], operands[1], operands[2], operands[3])); -+ else -+ emit_insn (gen_smalxds1_le (operands[0], operands[1], operands[2], operands[3])); -+ DONE; -+}) -+ -+(define_insn "smalxd1_le" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (sign_extend:DI -+ (plus_minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 1)]))))))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "smalxd\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+ -+(define_insn "smalxd1_be" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (sign_extend:DI -+ (plus_minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 0)]))))))))] -+ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" -+ "smalxd\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smslda1" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (minus:DI -+ (minus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (sign_extend:DI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 1)])))))) -+ (sign_extend:DI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 0)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "smslda\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "smslxda1" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (minus:DI -+ (minus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (sign_extend:DI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 0)])))))) -+ (sign_extend:DI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 1)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "smslxda\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+;; mada for synthetize smalda -+(define_insn_and_split "mada1" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (plus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" "r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iu01")]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" "r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iu01")])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iu01")]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(match_operand:SI 6 "nds32_imm_0_1_operand" " Iu01")]))))))] -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx result0 = gen_reg_rtx (SImode); -+ rtx result1 = gen_reg_rtx (SImode); -+ emit_insn (gen_mulhisi3v (result0, operands[1], operands[2], -+ operands[3], operands[4])); -+ emit_insn (gen_mulhisi3v (result1, operands[1], operands[2], -+ operands[5], operands[6])); -+ emit_insn (gen_addsi3 (operands[0], result0, result1)); -+ DONE; -+}) -+ -+(define_insn_and_split "mada2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (plus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" "r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iu01")]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" "r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iu01")])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iu01")]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(match_operand:SI 6 "nds32_imm_0_1_operand" " Iu01")]))))))] -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 1)] -+{ -+ rtx result0 = gen_reg_rtx (SImode); -+ rtx result1 = gen_reg_rtx (SImode); -+ emit_insn (gen_mulhisi3v (result0, operands[1], operands[2], -+ operands[3], operands[4])); -+ emit_insn (gen_mulhisi3v (result1, operands[1], operands[2], -+ operands[6], operands[5])); -+ emit_insn (gen_addsi3 (operands[0], result0, result1)); -+ DONE; -+}) -+ -+;; sms for synthetize smalds -+(define_insn_and_split "sms1" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iu01")]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iu01")])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iu01")]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(match_operand:SI 6 "nds32_imm_0_1_operand" " Iu01")]))))))] -+ "NDS32_EXT_DSP_P () -+ && (!reload_completed -+ || !nds32_need_split_sms_p (operands[3], operands[4], -+ operands[5], operands[6]))" -+ -+{ -+ return nds32_output_sms (operands[3], operands[4], -+ operands[5], operands[6]); -+} -+ "NDS32_EXT_DSP_P () -+ && !reload_completed -+ && nds32_need_split_sms_p (operands[3], operands[4], -+ operands[5], operands[6])" -+ [(const_int 1)] -+{ -+ nds32_split_sms (operands[0], operands[1], operands[2], -+ operands[3], operands[4], -+ operands[5], operands[6]); -+ DONE; -+} -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "sms2" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iu01")]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iu01")])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iu01")]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(match_operand:SI 6 "nds32_imm_0_1_operand" " Iu01")]))))))] -+ "NDS32_EXT_DSP_P () -+ && (!reload_completed -+ || !nds32_need_split_sms_p (operands[3], operands[4], -+ operands[6], operands[5]))" -+{ -+ return nds32_output_sms (operands[3], operands[4], -+ operands[6], operands[5]); -+} -+ "NDS32_EXT_DSP_P () -+ && !reload_completed -+ && nds32_need_split_sms_p (operands[3], operands[4], -+ operands[6], operands[5])" -+ [(const_int 1)] -+{ -+ nds32_split_sms (operands[0], operands[1], operands[2], -+ operands[3], operands[4], -+ operands[6], operands[5]); -+ DONE; -+} -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmda" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" "r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" "r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmda\t%0, %1, %2" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmxda" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" "r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" "r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 1) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmxda\t%0, %1, %2" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmada" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI -+ (match_operand:SI 1 "register_operand" " 0") -+ (ss_plus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 0)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmada\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmada2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI -+ (match_operand:SI 1 "register_operand" " 0") -+ (ss_plus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 1)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmada\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmaxda" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI -+ (match_operand:SI 1 "register_operand" " 0") -+ (ss_plus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 1)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmaxda\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmads" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI -+ (match_operand:SI 1 "register_operand" " 0") -+ (ss_minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 0)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmads\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmadrs" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI -+ (match_operand:SI 1 "register_operand" " 0") -+ (ss_minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 1)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmadrs\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmaxds" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI -+ (match_operand:SI 1 "register_operand" " 0") -+ (ss_minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 1)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmaxds\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmsda" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_minus:SI -+ (match_operand:SI 1 "register_operand" " 0") -+ (ss_minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 0)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmsda\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmsxda" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_minus:SI -+ (match_operand:SI 1 "register_operand" " 0") -+ (ss_minus:SI -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_operand:V2HI 3 "register_operand" " r") -+ (parallel [(const_int 0)])))) -+ (mult:SI -+ (sign_extend:SI (vec_select:HI -+ (match_dup 2) -+ (parallel [(const_int 0)]))) -+ (sign_extend:SI (vec_select:HI -+ (match_dup 3) -+ (parallel [(const_int 1)])))))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmsxda\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+;; smax[8|16] and umax[8|16] -+(define_insn "3" -+ [(set (match_operand:VQIHI 0 "register_operand" "=r") -+ (sumax:VQIHI (match_operand:VQIHI 1 "register_operand" " r") -+ (match_operand:VQIHI 2 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+;; smin[8|16] and umin[8|16] -+(define_insn "3" -+ [(set (match_operand:VQIHI 0 "register_operand" "=r") -+ (sumin:VQIHI (match_operand:VQIHI 1 "register_operand" " r") -+ (match_operand:VQIHI 2 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn "3_bb" -+ [(set (match_operand: 0 "register_operand" "=r") -+ (sumin_max: (vec_select: -+ (match_operand:VQIHI 1 "register_operand" " r") -+ (parallel [(const_int 0)])) -+ (vec_select: -+ (match_operand:VQIHI 2 "register_operand" " r") -+ (parallel [(const_int 0)]))))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "3_tt" -+ [(set (match_operand: 0 "register_operand" "=r") -+ (sumin_max: (vec_select: -+ (match_operand:VQIHI 1 "register_operand" " r") -+ (parallel [(const_int 1)])) -+ (vec_select: -+ (match_operand:VQIHI 2 "register_operand" " r") -+ (parallel [(const_int 1)]))))] -+ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 0)] -+{ -+ rtx tmp = gen_reg_rtx (mode); -+ emit_insn (gen_3 (tmp, operands[1], operands[2])); -+ emit_insn (gen_rotr_1 (tmp, tmp)); -+ emit_move_insn (operands[0], simplify_gen_subreg (mode, tmp, mode, 0)); -+ DONE; -+} -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "v4qi3_22" -+ [(set (match_operand:QI 0 "register_operand" "=r") -+ (sumin_max:QI (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 2)])) -+ (vec_select:QI -+ (match_operand:V4QI 2 "register_operand" " r") -+ (parallel [(const_int 2)]))))] -+ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 0)] -+{ -+ rtx tmp = gen_reg_rtx (V4QImode); -+ emit_insn (gen_v4qi3 (tmp, operands[1], operands[2])); -+ emit_insn (gen_rotrv4qi_2 (tmp, tmp)); -+ emit_move_insn (operands[0], simplify_gen_subreg (QImode, tmp, V4QImode, 0)); -+ DONE; -+} -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "v4qi3_33" -+ [(set (match_operand:QI 0 "register_operand" "=r") -+ (sumin_max:QI (vec_select:QI -+ (match_operand:V4QI 1 "register_operand" " r") -+ (parallel [(const_int 3)])) -+ (vec_select:QI -+ (match_operand:V4QI 2 "register_operand" " r") -+ (parallel [(const_int 3)]))))] -+ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 0)] -+{ -+ rtx tmp = gen_reg_rtx (V4QImode); -+ emit_insn (gen_v4qi3 (tmp, operands[1], operands[2])); -+ emit_insn (gen_rotrv4qi_3 (tmp, tmp)); -+ emit_move_insn (operands[0], simplify_gen_subreg (QImode, tmp, V4QImode, 0)); -+ DONE; -+} -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "v2hi3_bbtt" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (vec_merge:V2HI -+ (vec_duplicate:V2HI -+ (sumin_max:HI (vec_select:HI -+ (match_operand:V2HI 1 "register_operand" " r") -+ (parallel [(const_int 1)])) -+ (vec_select:HI -+ (match_operand:V2HI 2 "register_operand" " r") -+ (parallel [(const_int 1)])))) -+ (vec_duplicate:V2HI -+ (sumin_max:HI (vec_select:HI -+ (match_dup:V2HI 1) -+ (parallel [(const_int 0)])) -+ (vec_select:HI -+ (match_dup:V2HI 2) -+ (parallel [(const_int 0)])))) -+ (const_int 2)))] -+ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" -+ "#" -+ "NDS32_EXT_DSP_P ()" -+ [(const_int 0)] -+{ -+ emit_insn (gen_v2hi3 (operands[0], operands[1], operands[2])); -+ DONE; -+} -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_expand "abs2" -+ [(set (match_operand:VQIHI 0 "register_operand" "=r") -+ (ss_abs:VQIHI (match_operand:VQIHI 1 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P () && TARGET_HW_ABS && !flag_wrapv" -+{ -+}) -+ -+(define_insn "kabs2" -+ [(set (match_operand:VQIHI 0 "register_operand" "=r") -+ (ss_abs:VQIHI (match_operand:VQIHI 1 "register_operand" " r")))] -+ "NDS32_EXT_DSP_P ()" -+ "kabs\t%0, %1" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn "mar64_1" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (mult:DI -+ (extend:DI -+ (match_operand:SI 2 "register_operand" " r")) -+ (extend:DI -+ (match_operand:SI 3 "register_operand" " r")))))] -+ "NDS32_EXT_DSP_P ()" -+ "mar64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "mar64_2" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (mult:DI -+ (extend:DI -+ (match_operand:SI 2 "register_operand" " r")) -+ (extend:DI -+ (match_operand:SI 3 "register_operand" " r"))) -+ (match_operand:DI 1 "register_operand" " 0")))] -+ "NDS32_EXT_DSP_P ()" -+ "mar64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "mar64_3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (extend:DI -+ (mult:SI -+ (match_operand:SI 2 "register_operand" " r") -+ (match_operand:SI 3 "register_operand" " r")))))] -+ "NDS32_EXT_DSP_P ()" -+ "mar64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "mar64_4" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (plus:DI -+ (extend:DI -+ (mult:SI -+ (match_operand:SI 2 "register_operand" " r") -+ (match_operand:SI 3 "register_operand" " r"))) -+ (match_operand:DI 1 "register_operand" " 0")))] -+ "NDS32_EXT_DSP_P ()" -+ "mar64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "msr64" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (minus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (mult:DI -+ (extend:DI -+ (match_operand:SI 2 "register_operand" " r")) -+ (extend:DI -+ (match_operand:SI 3 "register_operand" " r")))))] -+ "NDS32_EXT_DSP_P ()" -+ "msr64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "msr64_2" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (minus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (extend:DI -+ (mult:SI -+ (match_operand:SI 2 "register_operand" " r") -+ (match_operand:SI 3 "register_operand" " r")))))] -+ "NDS32_EXT_DSP_P ()" -+ "msr64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+;; kmar64, kmsr64, ukmar64 and ukmsr64 -+(define_insn "kmar64_1" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (ss_plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (mult:DI -+ (sign_extend:DI -+ (match_operand:SI 2 "register_operand" " r")) -+ (sign_extend:DI -+ (match_operand:SI 3 "register_operand" " r")))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmar64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmar64_2" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (ss_plus:DI -+ (mult:DI -+ (sign_extend:DI -+ (match_operand:SI 2 "register_operand" " r")) -+ (sign_extend:DI -+ (match_operand:SI 3 "register_operand" " r"))) -+ (match_operand:DI 1 "register_operand" " 0")))] -+ "NDS32_EXT_DSP_P ()" -+ "kmar64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "kmsr64" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (ss_minus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (mult:DI -+ (sign_extend:DI -+ (match_operand:SI 2 "register_operand" " r")) -+ (sign_extend:DI -+ (match_operand:SI 3 "register_operand" " r")))))] -+ "NDS32_EXT_DSP_P ()" -+ "kmsr64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "ukmar64_1" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (us_plus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (mult:DI -+ (zero_extend:DI -+ (match_operand:SI 2 "register_operand" " r")) -+ (zero_extend:DI -+ (match_operand:SI 3 "register_operand" " r")))))] -+ "NDS32_EXT_DSP_P ()" -+ "ukmar64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "ukmar64_2" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (us_plus:DI -+ (mult:DI -+ (zero_extend:DI -+ (match_operand:SI 2 "register_operand" " r")) -+ (zero_extend:DI -+ (match_operand:SI 3 "register_operand" " r"))) -+ (match_operand:DI 1 "register_operand" " 0")))] -+ "NDS32_EXT_DSP_P ()" -+ "ukmar64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "ukmsr64" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (us_minus:DI -+ (match_operand:DI 1 "register_operand" " 0") -+ (mult:DI -+ (zero_extend:DI -+ (match_operand:SI 2 "register_operand" " r")) -+ (zero_extend:DI -+ (match_operand:SI 3 "register_operand" " r")))))] -+ "NDS32_EXT_DSP_P ()" -+ "ukmsr64\t%0, %2, %3" -+ [(set_attr "type" "dmac") -+ (set_attr "length" "4")]) -+ -+(define_insn "bpick1" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI -+ (and:SI -+ (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 3 "register_operand" " r")) -+ (and:SI -+ (match_operand:SI 2 "register_operand" " r") -+ (not:SI (match_dup 3)))))] -+ "NDS32_EXT_DSP_P ()" -+ "bpick\t%0, %1, %2, %3" -+ [(set_attr "type" "dbpick") -+ (set_attr "length" "4")]) -+ -+(define_insn "bpick2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI -+ (and:SI -+ (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "register_operand" " r")) -+ (and:SI -+ (not:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" " r"))))] -+ "NDS32_EXT_DSP_P ()" -+ "bpick\t%0, %1, %3, %2" -+ [(set_attr "type" "dbpick") -+ (set_attr "length" "4")]) -+ -+(define_insn "bpick3" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI -+ (and:SI -+ (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "register_operand" " r")) -+ (and:SI -+ (match_operand:SI 3 "register_operand" " r") -+ (not:SI (match_dup 1)))))] -+ "NDS32_EXT_DSP_P ()" -+ "bpick\t%0, %2, %3, %1" -+ [(set_attr "type" "dbpick") -+ (set_attr "length" "4")]) -+ -+(define_insn "bpick4" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI -+ (and:SI -+ (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "register_operand" " r")) -+ (and:SI -+ (not:SI (match_dup 1)) -+ (match_operand:SI 3 "register_operand" " r"))))] -+ "NDS32_EXT_DSP_P ()" -+ "bpick\t%0, %2, %3, %1" -+ [(set_attr "type" "dbpick") -+ (set_attr "length" "4")]) -+ -+(define_insn "bpick5" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI -+ (and:SI -+ (match_operand:SI 1 "register_operand" " r") -+ (not:SI (match_operand:SI 2 "register_operand" " r"))) -+ (and:SI -+ (match_operand:SI 3 "register_operand" " r") -+ (match_dup 2))))] -+ "NDS32_EXT_DSP_P ()" -+ "bpick\t%0, %3, %1, %2" -+ [(set_attr "type" "dbpick") -+ (set_attr "length" "4")]) -+ -+(define_insn "bpick6" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI -+ (and:SI -+ (not:SI (match_operand:SI 1 "register_operand" " r")) -+ (match_operand:SI 2 "register_operand" " r")) -+ (and:SI -+ (match_operand:SI 3 "register_operand" " r") -+ (match_dup 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "bpick\t%0, %3, %2, %1" -+ [(set_attr "type" "dbpick") -+ (set_attr "length" "4")]) -+ -+(define_insn "bpick7" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI -+ (and:SI -+ (match_operand:SI 1 "register_operand" " r") -+ (not:SI (match_operand:SI 2 "register_operand" " r"))) -+ (and:SI -+ (match_dup 2) -+ (match_operand:SI 3 "register_operand" " r"))))] -+ "NDS32_EXT_DSP_P ()" -+ "bpick\t%0, %3, %1, %2" -+ [(set_attr "type" "dbpick") -+ (set_attr "length" "4")]) -+ -+(define_insn "bpick8" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ior:SI -+ (and:SI -+ (not:SI (match_operand:SI 1 "register_operand" " r")) -+ (match_operand:SI 2 "register_operand" " r")) -+ (and:SI -+ (match_dup 1) -+ (match_operand:SI 3 "register_operand" " r"))))] -+ "NDS32_EXT_DSP_P ()" -+ "bpick\t%0, %3, %2, %1" -+ [(set_attr "type" "dbpick") -+ (set_attr "length" "4")]) -+ -+(define_insn "sraiu" -+ [(set (match_operand:SI 0 "register_operand" "= r, r") -+ (unspec:SI [(ashiftrt:SI (match_operand:SI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r"))] -+ UNSPEC_ROUND))] -+ "NDS32_EXT_DSP_P ()" -+ "@ -+ srai.u\t%0, %1, %2 -+ sra.u\t%0, %1, %2" -+ [(set_attr "type" "daluround") -+ (set_attr "length" "4")]) -+ -+(define_insn "kssl" -+ [(set (match_operand:SI 0 "register_operand" "= r, r") -+ (ss_ashift:SI (match_operand:SI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r")))] -+ "NDS32_EXT_DSP_P ()" -+ "@ -+ kslli\t%0, %1, %2 -+ ksll\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+(define_insn "kslraw_round" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (if_then_else:SI -+ (lt:SI (match_operand:SI 2 "register_operand" " r") -+ (const_int 0)) -+ (unspec:SI [(ashiftrt:SI (match_operand:SI 1 "register_operand" " r") -+ (neg:SI (match_dup 2)))] -+ UNSPEC_ROUND) -+ (ss_ashift:SI (match_dup 1) -+ (match_dup 2))))] -+ "NDS32_EXT_DSP_P ()" -+ "kslraw.u\t%0, %1, %2" -+ [(set_attr "type" "daluround") -+ (set_attr "length" "4")]) -+ -+(define_insn_and_split "di3" -+ [(set (match_operand:DI 0 "register_operand" "") -+ (shift_rotate:DI (match_operand:DI 1 "register_operand" "") -+ (match_operand:SI 2 "nds32_rimm6u_operand" "")))] -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ "#" -+ "NDS32_EXT_DSP_P () && !reload_completed" -+ [(const_int 0)] -+{ -+ if (REGNO (operands[0]) == REGNO (operands[1])) -+ { -+ rtx tmp = gen_reg_rtx (DImode); -+ nds32_split_di3 (tmp, operands[1], operands[2]); -+ emit_move_insn (operands[0], tmp); -+ } -+ else -+ nds32_split_di3 (operands[0], operands[1], operands[2]); -+ DONE; -+}) -+ -+(define_insn "sclip32" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_CLIPS_OV))] -+ "NDS32_EXT_DSP_P ()" -+ "sclip32\t%0, %1, %2" -+ [(set_attr "type" "dclip") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "uclip32" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_CLIP_OV))] -+ "NDS32_EXT_DSP_P ()" -+ "uclip32\t%0, %1, %2" -+ [(set_attr "type" "dclip") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "bitrev" -+ [(set (match_operand:SI 0 "register_operand" "=r, r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm5u_operand" " r, Iu05")] -+ UNSPEC_BITREV))] -+ "" -+ "@ -+ bitrev\t%0, %1, %2 -+ bitrevi\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")] -+) -+ -+;; wext, wexti -+(define_insn "wext" -+ [(set (match_operand:SI 0 "register_operand" "=r, r") -+ (truncate:SI -+ (shiftrt:DI -+ (match_operand:DI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm5u_operand" " r,Iu05"))))] -+ "NDS32_EXT_DSP_P ()" -+ "@ -+ wext\t%0, %1, %2 -+ wexti\t%0, %1, %2" -+ [(set_attr "type" "dwext") -+ (set_attr "length" "4")]) -+ -+;; 32-bit add/sub instruction: raddw and rsubw. -+(define_insn "rsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (ashiftrt:DI -+ (plus_minus:DI -+ (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) -+ (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "rw\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -+ -+;; 32-bit add/sub instruction: uraddw and ursubw. -+(define_insn "ursi3" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (lshiftrt:DI -+ (plus_minus:DI -+ (zero_extend:DI (match_operand:SI 1 "register_operand" " r")) -+ (zero_extend:DI (match_operand:SI 2 "register_operand" " r"))) -+ (const_int 1))))] -+ "NDS32_EXT_DSP_P ()" -+ "urw\t%0, %1, %2" -+ [(set_attr "type" "dalu") -+ (set_attr "length" "4")]) -diff --git a/gcc/config/nds32/nds32-elf.opt b/gcc/config/nds32/nds32-elf.opt -new file mode 100644 -index 00000000000..afe6aadd089 ---- /dev/null -+++ b/gcc/config/nds32/nds32-elf.opt -@@ -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) -diff --git a/gcc/config/nds32/nds32-fp-as-gp.c b/gcc/config/nds32/nds32-fp-as-gp.c -index 95c9586c3b6..26d2865d450 100644 ---- a/gcc/config/nds32/nds32-fp-as-gp.c -+++ b/gcc/config/nds32/nds32-fp-as-gp.c -@@ -26,19 +26,256 @@ - #include "system.h" - #include "coretypes.h" - #include "backend.h" -+#include "hard-reg-set.h" -+#include "tm_p.h" -+#include "rtl.h" -+#include "memmodel.h" -+#include "emit-rtl.h" -+#include "insn-config.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "ira.h" -+#include "ira-int.h" -+#include "df.h" -+#include "tree-core.h" -+#include "tree-pass.h" -+#include "nds32-protos.h" - - /* ------------------------------------------------------------------------ */ - -+/* A helper function to check if this function should contain prologue. */ -+static bool -+nds32_have_prologue_p (void) -+{ -+ int i; -+ -+ for (i = 0; i < 28; i++) -+ if (NDS32_REQUIRED_CALLEE_SAVED_P (i)) -+ return true; -+ -+ return (flag_pic -+ || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM) -+ || NDS32_REQUIRED_CALLEE_SAVED_P (LP_REGNUM)); -+} -+ -+static int -+nds32_get_symbol_count (void) -+{ -+ int symbol_count = 0; -+ rtx_insn *insn; -+ basic_block bb; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ FOR_BB_INSNS (bb, insn) -+ { -+ /* Counting the insn number which the addressing mode is symbol. */ -+ if (single_set (insn) && nds32_symbol_load_store_p (insn)) -+ { -+ rtx pattern = PATTERN (insn); -+ rtx mem; -+ gcc_assert (GET_CODE (pattern) == SET); -+ if (GET_CODE (SET_SRC (pattern)) == REG ) -+ mem = SET_DEST (pattern); -+ else -+ mem = SET_SRC (pattern); -+ -+ /* We have only lwi37 and swi37 for fp-as-gp optimization, -+ so don't count any other than SImode. -+ MEM for QImode and HImode will wrap by ZERO_EXTEND -+ or SIGN_EXTEND */ -+ if (GET_CODE (mem) == MEM) -+ symbol_count++; -+ } -+ } -+ } -+ -+ return symbol_count; -+} -+ - /* Function to determine whether it is worth to do fp_as_gp optimization. -- Return 0: It is NOT worth to do fp_as_gp optimization. -- Return 1: It is APPROXIMATELY worth to do fp_as_gp optimization. -+ Return false: It is NOT worth to do fp_as_gp optimization. -+ Return true: It is APPROXIMATELY worth to do fp_as_gp optimization. - Note that if it is worth to do fp_as_gp optimization, - we MUST set FP_REGNUM ever live in this function. */ --int -+static bool - nds32_fp_as_gp_check_available (void) - { -- /* By default we return 0. */ -- return 0; -+ basic_block bb; -+ basic_block exit_bb; -+ edge_iterator ei; -+ edge e; -+ bool first_exit_blocks_p; -+ -+ /* If there exists ANY of following conditions, -+ we DO NOT perform fp_as_gp optimization: -+ 1. TARGET_FORBID_FP_AS_GP is set -+ regardless of the TARGET_FORCE_FP_AS_GP. -+ 2. User explicitly uses 'naked'/'no_prologue' attribute. -+ We use nds32_naked_function_p() to help such checking. -+ 3. Not optimize for size. -+ 4. Need frame pointer. -+ 5. If $fp is already required to be saved, -+ it means $fp is already choosen by register allocator. -+ Thus we better not to use it for fp_as_gp optimization. -+ 6. This function is a vararg function. -+ DO NOT apply fp_as_gp optimization on this function -+ because it may change and break stack frame. -+ 7. The epilogue is empty. -+ This happens when the function uses exit() -+ or its attribute is no_return. -+ In that case, compiler will not expand epilogue -+ so that we have no chance to output .omit_fp_end directive. */ -+ if (TARGET_FORBID_FP_AS_GP -+ || nds32_naked_function_p (current_function_decl) -+ || !optimize_size -+ || frame_pointer_needed -+ || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM) -+ || (cfun->stdarg == 1) -+ || (find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == NULL)) -+ return false; -+ -+ /* Disable fp_as_gp if there is any infinite loop since the fp may -+ reuse in infinite loops by register rename. -+ For check infinite loops we should make sure exit_bb is post dominate -+ all other basic blocks if there is no infinite loops. */ -+ first_exit_blocks_p = true; -+ exit_bb = NULL; -+ -+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) -+ { -+ /* More than one exit block also do not perform fp_as_gp optimization. */ -+ if (!first_exit_blocks_p) -+ return false; -+ -+ exit_bb = e->src; -+ first_exit_blocks_p = false; -+ } -+ -+ /* Not found exit_bb? just abort fp_as_gp! */ -+ if (!exit_bb) -+ return false; -+ -+ /* Each bb should post dominate by exit_bb if there is no infinite loop! */ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ if (!dominated_by_p (CDI_POST_DOMINATORS, -+ bb, -+ exit_bb)) -+ return false; -+ } -+ -+ /* Now we can check the possibility of using fp_as_gp optimization. */ -+ if (TARGET_FORCE_FP_AS_GP) -+ { -+ /* User explicitly issues -mforce-fp-as-gp option. */ -+ return true; -+ } -+ else -+ { -+ /* In the following we are going to evaluate whether -+ it is worth to do fp_as_gp optimization. */ -+ bool good_gain = false; -+ int symbol_count; -+ -+ int threshold; -+ -+ /* We check if there already requires prologue. -+ Note that $gp will be saved in prologue for PIC code generation. -+ After that, we can set threshold by the existence of prologue. -+ Each fp-implied instruction will gain 2-byte code size -+ from gp-aware instruction, so we have following heuristics. */ -+ if (flag_pic -+ || nds32_have_prologue_p ()) -+ { -+ /* Have-prologue: -+ Compiler already intends to generate prologue content, -+ so the fp_as_gp optimization will only insert -+ 'la $fp,_FP_BASE_' instruction, which will be -+ converted into 4-byte instruction at link time. -+ The threshold is "3" symbol accesses, 2 + 2 + 2 > 4. */ -+ threshold = 3; -+ } -+ else -+ { -+ /* None-prologue: -+ Compiler originally does not generate prologue content, -+ so the fp_as_gp optimization will NOT ONLY insert -+ 'la $fp,_FP_BASE' instruction, but also causes -+ push/pop instructions. -+ If we are using v3push (push25/pop25), -+ the threshold is "5" symbol accesses, 5*2 > 4 + 2 + 2; -+ If we are using normal push (smw/lmw), -+ the threshold is "5+2" symbol accesses 7*2 > 4 + 4 + 4. */ -+ threshold = 5 + (TARGET_V3PUSH ? 0 : 2); -+ } -+ -+ symbol_count = nds32_get_symbol_count (); -+ -+ if (symbol_count >= threshold) -+ good_gain = true; -+ -+ /* Enable fp_as_gp optimization when potential gain is good enough. */ -+ return good_gain; -+ } -+} -+ -+static unsigned int -+nds32_fp_as_gp (void) -+{ -+ bool fp_as_gp_p; -+ calculate_dominance_info (CDI_POST_DOMINATORS); -+ fp_as_gp_p = nds32_fp_as_gp_check_available (); -+ -+ /* Here is a hack to IRA for enable/disable a hard register per function. -+ We *MUST* review this way after migrate gcc 4.9! */ -+ if (fp_as_gp_p) { -+ SET_HARD_REG_BIT(this_target_ira_int->x_no_unit_alloc_regs, FP_REGNUM); -+ df_set_regs_ever_live (FP_REGNUM, 1); -+ } else { -+ CLEAR_HARD_REG_BIT(this_target_ira_int->x_no_unit_alloc_regs, FP_REGNUM); -+ } -+ -+ cfun->machine->fp_as_gp_p = fp_as_gp_p; -+ -+ free_dominance_info (CDI_POST_DOMINATORS); -+ return 1; -+} -+ -+const pass_data pass_data_nds32_fp_as_gp = -+{ -+ RTL_PASS, /* type */ -+ "fp_as_gp", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ 0, /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ 0 /* todo_flags_finish */ -+}; -+ -+class pass_nds32_fp_as_gp : public rtl_opt_pass -+{ -+public: -+ pass_nds32_fp_as_gp (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_fp_as_gp, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) -+ { -+ return !TARGET_LINUX_ABI -+ && TARGET_16_BIT -+ && optimize_size; -+ } -+ unsigned int execute (function *) { return nds32_fp_as_gp (); } -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_fp_as_gp (gcc::context *ctxt) -+{ -+ return new pass_nds32_fp_as_gp (ctxt); - } - - /* ------------------------------------------------------------------------ */ -diff --git a/gcc/config/nds32/nds32-fpu.md b/gcc/config/nds32/nds32-fpu.md -index 719b0428ced..9b844021a24 100644 ---- a/gcc/config/nds32/nds32-fpu.md -+++ b/gcc/config/nds32/nds32-fpu.md -@@ -1,5 +1,5 @@ - ;; Machine description of Andes NDS32 cpu for GNU compiler --;; Copyright (C) 2012-2015 Free Software Foundation, Inc. -+;; Copyright (C) 2012-2018 Free Software Foundation, Inc. - ;; Contributed by Andes Technology Corporation. - ;; - ;; This file is part of GCC. -diff --git a/gcc/config/nds32/nds32-graywolf.md b/gcc/config/nds32/nds32-graywolf.md -new file mode 100644 -index 00000000000..f0c98a6f75d ---- /dev/null -+++ b/gcc/config/nds32/nds32-graywolf.md -@@ -0,0 +1,471 @@ -+;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler -+;; Copyright (C) 2012-2013 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 -+;; . -+ -+;; ------------------------------------------------------------------------ -+;; Define Graywolf pipeline settings. -+;; ------------------------------------------------------------------------ -+ -+(define_automaton "nds32_graywolf_machine") -+ -+(define_cpu_unit "gw_ii_0" "nds32_graywolf_machine") -+(define_cpu_unit "gw_ii_1" "nds32_graywolf_machine") -+(define_cpu_unit "gw_ex_p0" "nds32_graywolf_machine") -+(define_cpu_unit "gw_mm_p0" "nds32_graywolf_machine") -+(define_cpu_unit "gw_wb_p0" "nds32_graywolf_machine") -+(define_cpu_unit "gw_ex_p1" "nds32_graywolf_machine") -+(define_cpu_unit "gw_mm_p1" "nds32_graywolf_machine") -+(define_cpu_unit "gw_wb_p1" "nds32_graywolf_machine") -+(define_cpu_unit "gw_iq_p2" "nds32_graywolf_machine") -+(define_cpu_unit "gw_rf_p2" "nds32_graywolf_machine") -+(define_cpu_unit "gw_e1_p2" "nds32_graywolf_machine") -+(define_cpu_unit "gw_e2_p2" "nds32_graywolf_machine") -+(define_cpu_unit "gw_e3_p2" "nds32_graywolf_machine") -+(define_cpu_unit "gw_e4_p2" "nds32_graywolf_machine") -+ -+(define_reservation "gw_ii" "gw_ii_0 | gw_ii_1") -+(define_reservation "gw_ex" "gw_ex_p0 | gw_ex_p1") -+(define_reservation "gw_mm" "gw_mm_p0 | gw_mm_p1") -+(define_reservation "gw_wb" "gw_wb_p0 | gw_wb_p1") -+ -+(define_reservation "gw_ii_all" "gw_ii_0 + gw_ii_1") -+ -+(define_insn_reservation "nds_gw_unknown" 1 -+ (and (eq_attr "type" "unknown") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_ex, gw_mm, gw_wb") -+ -+(define_insn_reservation "nds_gw_misc" 1 -+ (and (eq_attr "type" "misc") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_ex, gw_mm, gw_wb") -+ -+(define_insn_reservation "nds_gw_mmu" 1 -+ (and (eq_attr "type" "mmu") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_ex, gw_mm, gw_wb") -+ -+(define_insn_reservation "nds_gw_alu" 1 -+ (and (and (eq_attr "type" "alu") -+ (match_test "!nds32::movd44_insn_p (insn)")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_ex, gw_mm, gw_wb") -+ -+(define_insn_reservation "nds_gw_movd44" 1 -+ (and (and (eq_attr "type" "alu") -+ (match_test "nds32::movd44_insn_p (insn)")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex, gw_mm, gw_wb") -+ -+(define_insn_reservation "nds_gw_alu_shift" 1 -+ (and (eq_attr "type" "alu_shift") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_ex*2, gw_mm, gw_wb") -+ -+(define_insn_reservation "nds_gw_pbsad" 1 -+ (and (eq_attr "type" "pbsad") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_ex*3, gw_mm, gw_wb") -+ -+(define_insn_reservation "nds_gw_pbsada" 1 -+ (and (eq_attr "type" "pbsada") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_ex*3, gw_mm, gw_wb") -+ -+(define_insn_reservation "nds_gw_load" 1 -+ (and (and (eq_attr "type" "load") -+ (match_test "!nds32::post_update_insn_p (insn)")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_load_2w" 1 -+ (and (and (eq_attr "type" "load") -+ (match_test "nds32::post_update_insn_p (insn)")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_all, gw_ex_p1, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store" 1 -+ (and (and (eq_attr "type" "store") -+ (match_test "!nds32::store_offset_reg_p (insn)")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store_3r" 1 -+ (and (and (eq_attr "type" "store") -+ (match_test "nds32::store_offset_reg_p (insn)")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_all, gw_ex_p1, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_load_multiple_1" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_load_multiple_2" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "2")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*2, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_load_multiple_3" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*3, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_load_multiple_4" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_load_multiple_5" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_load_multiple_6" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "6")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_load_multiple_7" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_load_multiple_8" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_load_multiple_12" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store_multiple_1" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store_multiple_2" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "2")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*2, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store_multiple_3" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*3, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store_multiple_4" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store_multiple_5" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store_multiple_6" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "6")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store_multiple_7" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store_multiple_8" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_store_multiple_12" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") -+ -+(define_insn_reservation "nds_gw_mul_fast1" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_FAST_1") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "graywolf"))) -+ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_mul_fast2" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_FAST_2") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "graywolf"))) -+ "gw_ii_0, gw_ex_p0*2, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_mul_slow" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "graywolf"))) -+ "gw_ii_0, gw_ex_p0*4, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_mac_fast1" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_FAST_1") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "graywolf"))) -+ "gw_ii_all, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_mac_fast2" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_FAST_2") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "graywolf"))) -+ "gw_ii_all, gw_ex_p0*2, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_mac_slow" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "graywolf"))) -+ "gw_ii_all, gw_ex_p0*4, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_div" 1 -+ (and (and (eq_attr "type" "div") -+ (match_test "!nds32::divmod_p (insn)")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_0, gw_ex_p0*4, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_div_2w" 1 -+ (and (and (eq_attr "type" "div") -+ (match_test "nds32::divmod_p (insn)")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_all, gw_ex_p0*4, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_branch" 1 -+ (and (eq_attr "type" "branch") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_dsp_alu" 1 -+ (and (eq_attr "type" "dalu") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_ex, gw_mm, gw_wb") -+ -+(define_insn_reservation "nds_gw_dsp_alu64" 1 -+ (and (eq_attr "type" "dalu64") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_all, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_dsp_alu_round" 1 -+ (and (eq_attr "type" "daluround") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_dsp_cmp" 1 -+ (and (eq_attr "type" "dcmp") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_dsp_clip" 1 -+ (and (eq_attr "type" "dclip") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_dsp_mul" 1 -+ (and (eq_attr "type" "dmul") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_dsp_mac" 1 -+ (and (eq_attr "type" "dmac") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_all, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_dsp_insb" 1 -+ (and (eq_attr "type" "dinsb") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_dsp_pack" 1 -+ (and (eq_attr "type" "dpack") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_dsp_bpick" 1 -+ (and (eq_attr "type" "dbpick") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_dsp_wext" 1 -+ (and (eq_attr "type" "dwext") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii_all, gw_ex_p0, gw_mm_p0, gw_wb_p0") -+ -+(define_insn_reservation "nds_gw_fpu_alu" 4 -+ (and (eq_attr "type" "falu") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_muls" 4 -+ (and (eq_attr "type" "fmuls") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_muld" 4 -+ (and (eq_attr "type" "fmuld") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2*2, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_macs" 4 -+ (and (eq_attr "type" "fmacs") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2*3, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_macd" 4 -+ (and (eq_attr "type" "fmacd") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2*4, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_divs" 4 -+ (and (ior (eq_attr "type" "fdivs") -+ (eq_attr "type" "fsqrts")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2*14, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_divd" 4 -+ (and (ior (eq_attr "type" "fdivd") -+ (eq_attr "type" "fsqrtd")) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2*28, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_fast_alu" 2 -+ (and (ior (eq_attr "type" "fcmp") -+ (ior (eq_attr "type" "fabs") -+ (ior (eq_attr "type" "fcpy") -+ (eq_attr "type" "fcmov")))) -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_fmtsr" 1 -+ (and (eq_attr "type" "fmtsr") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_fmtdr" 1 -+ (and (eq_attr "type" "fmtdr") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_ii+gw_iq_p2, gw_iq_p2+gw_rf_p2, gw_rf_p2+gw_e1_p2, gw_e1_p2+gw_e2_p2, gw_e2_p2+gw_e3_p2, gw_e3_p2+gw_e4_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_fmfsr" 1 -+ (and (eq_attr "type" "fmfsr") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_fmfdr" 1 -+ (and (eq_attr "type" "fmfdr") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_ii+gw_iq_p2, gw_iq_p2+gw_rf_p2, gw_rf_p2+gw_e1_p2, gw_e1_p2+gw_e2_p2, gw_e2_p2+gw_e3_p2, gw_e3_p2+gw_e4_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_load" 3 -+ (and (eq_attr "type" "fload") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") -+ -+(define_insn_reservation "nds_gw_fpu_store" 1 -+ (and (eq_attr "type" "fstore") -+ (eq_attr "pipeline_model" "graywolf")) -+ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") -+ -+;; FPU_ADDR_OUT -> FPU_ADDR_IN -+;; Main pipeline rules don't need this because those default latency is 1. -+(define_bypass 1 -+ "nds_gw_fpu_load, nds_gw_fpu_store" -+ "nds_gw_fpu_load, nds_gw_fpu_store" -+ "nds32_gw_ex_to_ex_p" -+) -+ -+;; LD, MUL, MAC, DIV, DALU64, DMUL, DMAC, DALUROUND, DBPICK, DWEXT -+;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44, MUL, MAC_RaRb, DIV, ADDR_IN, BR, MMU, -+;; DALU, DALUROUND, DMUL, DMAC_RaRb, DPACK, DINSB, DCMP, DCLIP, WEXT_O, BPICK_RaRb -+(define_bypass 2 -+ "nds_gw_load, nds_gw_load_2w,\ -+ nds_gw_mul_fast1, nds_gw_mul_fast2, nds_gw_mul_slow,\ -+ nds_gw_mac_fast1, nds_gw_mac_fast2, nds_gw_mac_slow,\ -+ nds_gw_div, nds_gw_div_2w,\ -+ nds_gw_dsp_alu64, nds_gw_dsp_mul, nds_gw_dsp_mac,\ -+ nds_gw_dsp_alu_round, nds_gw_dsp_bpick, nds_gw_dsp_wext" -+ "nds_gw_alu, nds_gw_movd44, nds_gw_alu_shift,\ -+ nds_gw_pbsad, nds_gw_pbsada,\ -+ nds_gw_mul_fast1, nds_gw_mul_fast2, nds_gw_mul_slow,\ -+ nds_gw_mac_fast1, nds_gw_mac_fast2, nds_gw_mac_slow,\ -+ nds_gw_branch,\ -+ nds_gw_div, nds_gw_div_2w,\ -+ nds_gw_load, nds_gw_load_2w, nds_gw_store, nds_gw_store_3r,\ -+ nds_gw_load_multiple_1,nds_gw_load_multiple_2, nds_gw_load_multiple_3,\ -+ nds_gw_load_multiple_4,nds_gw_load_multiple_5, nds_gw_load_multiple_6,\ -+ nds_gw_load_multiple_7,nds_gw_load_multiple_8, nds_gw_load_multiple_12,\ -+ nds_gw_store_multiple_1,nds_gw_store_multiple_2, nds_gw_store_multiple_3,\ -+ nds_gw_store_multiple_4,nds_gw_store_multiple_5, nds_gw_store_multiple_6,\ -+ nds_gw_store_multiple_7,nds_gw_store_multiple_8, nds_gw_store_multiple_12,\ -+ nds_gw_mmu,\ -+ nds_gw_dsp_alu, nds_gw_dsp_alu_round,\ -+ nds_gw_dsp_mul, nds_gw_dsp_mac, nds_gw_dsp_pack,\ -+ nds_gw_dsp_insb, nds_gw_dsp_cmp, nds_gw_dsp_clip,\ -+ nds_gw_dsp_wext, nds_gw_dsp_bpick" -+ "nds32_gw_mm_to_ex_p" -+) -+ -+;; LMW(N, N) -+;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44, MUL, MAC_RaRb, DIV, ADDR_IN, BR, MMU -+;; DALU, DALUROUND, DMUL, DMAC_RaRb, DPACK, DINSB, DCMP, DCLIP, WEXT_O, BPICK_RaRb -+(define_bypass 2 -+ "nds_gw_load_multiple_1,nds_gw_load_multiple_2, nds_gw_load_multiple_3,\ -+ nds_gw_load_multiple_4,nds_gw_load_multiple_5, nds_gw_load_multiple_6,\ -+ nds_gw_load_multiple_7,nds_gw_load_multiple_8, nds_gw_load_multiple_12" -+ "nds_gw_alu, nds_gw_movd44, nds_gw_alu_shift,\ -+ nds_gw_pbsad, nds_gw_pbsada,\ -+ nds_gw_mul_fast1, nds_gw_mul_fast2, nds_gw_mul_slow,\ -+ nds_gw_mac_fast1, nds_gw_mac_fast2, nds_gw_mac_slow,\ -+ nds_gw_branch,\ -+ nds_gw_div, nds_gw_div_2w,\ -+ nds_gw_load, nds_gw_load_2w, nds_gw_store, nds_gw_store_3r,\ -+ nds_gw_load_multiple_1,nds_gw_load_multiple_2, nds_gw_load_multiple_3,\ -+ nds_gw_load_multiple_4,nds_gw_load_multiple_5, nds_gw_load_multiple_6,\ -+ nds_gw_load_multiple_7,nds_gw_load_multiple_8, nds_gw_load_multiple_12,\ -+ nds_gw_store_multiple_1,nds_gw_store_multiple_2, nds_gw_store_multiple_3,\ -+ nds_gw_store_multiple_4,nds_gw_store_multiple_5, nds_gw_store_multiple_6,\ -+ nds_gw_store_multiple_7,nds_gw_store_multiple_8, nds_gw_store_multiple_12,\ -+ nds_gw_mmu,\ -+ nds_gw_dsp_alu, nds_gw_dsp_alu_round,\ -+ nds_gw_dsp_mul, nds_gw_dsp_mac, nds_gw_dsp_pack,\ -+ nds_gw_dsp_insb, nds_gw_dsp_cmp, nds_gw_dsp_clip,\ -+ nds_gw_dsp_wext, nds_gw_dsp_bpick" -+ "nds32_gw_last_load_to_ex_p" -+) -diff --git a/gcc/config/nds32/nds32-intrinsic.c b/gcc/config/nds32/nds32-intrinsic.c -index b9bb2d995f7..c2ad927b05d 100644 ---- a/gcc/config/nds32/nds32-intrinsic.c -+++ b/gcc/config/nds32/nds32-intrinsic.c -@@ -519,6 +519,7 @@ static struct builtin_description bdesc_noarg[] = - { - NDS32_BUILTIN(unspec_fmfcfg, "fmfcfg", FMFCFG) - NDS32_BUILTIN(unspec_fmfcsr, "fmfcsr", FMFCSR) -+ NDS32_BUILTIN(unspec_volatile_rdov, "rdov", RDOV) - NDS32_BUILTIN(unspec_get_current_sp, "get_current_sp", GET_CURRENT_SP) - NDS32_BUILTIN(unspec_return_address, "return_address", RETURN_ADDRESS) - NDS32_BUILTIN(unspec_get_all_pending_int, "get_all_pending_int", -@@ -558,6 +559,31 @@ static struct builtin_description bdesc_1arg[] = - NDS32_NO_TARGET_BUILTIN(unspec_ret_itoff, "ret_itoff", RET_ITOFF) - NDS32_NO_TARGET_BUILTIN(unspec_set_current_sp, - "set_current_sp", SET_CURRENT_SP) -+ NDS32_BUILTIN(kabsv2hi2, "kabs16", KABS16) -+ NDS32_BUILTIN(kabsv2hi2, "v_kabs16", V_KABS16) -+ NDS32_BUILTIN(kabsv4qi2, "kabs8", KABS8) -+ NDS32_BUILTIN(kabsv4qi2, "v_kabs8", V_KABS8) -+ NDS32_BUILTIN(sunpkd810, "sunpkd810", SUNPKD810) -+ NDS32_BUILTIN(sunpkd810, "v_sunpkd810", V_SUNPKD810) -+ NDS32_BUILTIN(sunpkd820, "sunpkd820", SUNPKD820) -+ NDS32_BUILTIN(sunpkd820, "v_sunpkd820", V_SUNPKD820) -+ NDS32_BUILTIN(sunpkd830, "sunpkd830", SUNPKD830) -+ NDS32_BUILTIN(sunpkd830, "v_sunpkd830", V_SUNPKD830) -+ NDS32_BUILTIN(sunpkd831, "sunpkd831", SUNPKD831) -+ NDS32_BUILTIN(sunpkd831, "v_sunpkd831", V_SUNPKD831) -+ NDS32_BUILTIN(zunpkd810, "zunpkd810", ZUNPKD810) -+ NDS32_BUILTIN(zunpkd810, "v_zunpkd810", V_ZUNPKD810) -+ NDS32_BUILTIN(zunpkd820, "zunpkd820", ZUNPKD820) -+ NDS32_BUILTIN(zunpkd820, "v_zunpkd820", V_ZUNPKD820) -+ NDS32_BUILTIN(zunpkd830, "zunpkd830", ZUNPKD830) -+ NDS32_BUILTIN(zunpkd830, "v_zunpkd830", V_ZUNPKD830) -+ NDS32_BUILTIN(zunpkd831, "zunpkd831", ZUNPKD831) -+ NDS32_BUILTIN(zunpkd831, "v_zunpkd831", V_ZUNPKD831) -+ NDS32_BUILTIN(unspec_kabs, "kabs", KABS) -+ NDS32_BUILTIN(unaligned_loadv2hi, "get_unaligned_u16x2", UALOAD_U16) -+ NDS32_BUILTIN(unaligned_loadv2hi, "get_unaligned_s16x2", UALOAD_S16) -+ NDS32_BUILTIN(unaligned_loadv4qi, "get_unaligned_u8x4", UALOAD_U8) -+ NDS32_BUILTIN(unaligned_loadv4qi, "get_unaligned_s8x4", UALOAD_S8) - }; - - /* Intrinsics that take just one argument. and the argument is immediate. */ -@@ -593,6 +619,28 @@ static struct builtin_description bdesc_2arg[] = - NDS32_BUILTIN(unspec_ffb, "ffb", FFB) - NDS32_BUILTIN(unspec_ffmism, "ffmsim", FFMISM) - NDS32_BUILTIN(unspec_flmism, "flmism", FLMISM) -+ NDS32_BUILTIN(unspec_kaddw, "kaddw", KADDW) -+ NDS32_BUILTIN(unspec_kaddh, "kaddh", KADDH) -+ NDS32_BUILTIN(unspec_ksubw, "ksubw", KSUBW) -+ NDS32_BUILTIN(unspec_ksubh, "ksubh", KSUBH) -+ NDS32_BUILTIN(unspec_kdmbb, "kdmbb", KDMBB) -+ NDS32_BUILTIN(unspec_kdmbb, "v_kdmbb", V_KDMBB) -+ NDS32_BUILTIN(unspec_kdmbt, "kdmbt", KDMBT) -+ NDS32_BUILTIN(unspec_kdmbt, "v_kdmbt", V_KDMBT) -+ NDS32_BUILTIN(unspec_kdmtb, "kdmtb", KDMTB) -+ NDS32_BUILTIN(unspec_kdmtb, "v_kdmtb", V_KDMTB) -+ NDS32_BUILTIN(unspec_kdmtt, "kdmtt", KDMTT) -+ NDS32_BUILTIN(unspec_kdmtt, "v_kdmtt", V_KDMTT) -+ NDS32_BUILTIN(unspec_khmbb, "khmbb", KHMBB) -+ NDS32_BUILTIN(unspec_khmbb, "v_khmbb", V_KHMBB) -+ NDS32_BUILTIN(unspec_khmbt, "khmbt", KHMBT) -+ NDS32_BUILTIN(unspec_khmbt, "v_khmbt", V_KHMBT) -+ NDS32_BUILTIN(unspec_khmtb, "khmtb", KHMTB) -+ NDS32_BUILTIN(unspec_khmtb, "v_khmtb", V_KHMTB) -+ NDS32_BUILTIN(unspec_khmtt, "khmtt", KHMTT) -+ NDS32_BUILTIN(unspec_khmtt, "v_khmtt", V_KHMTT) -+ NDS32_BUILTIN(unspec_kslraw, "kslraw", KSLRAW) -+ NDS32_BUILTIN(unspec_kslrawu, "kslraw_u", KSLRAW_U) - NDS32_BUILTIN(rotrsi3, "rotr", ROTR) - NDS32_BUILTIN(unspec_sva, "sva", SVA) - NDS32_BUILTIN(unspec_svs, "svs", SVS) -@@ -603,7 +651,202 @@ static struct builtin_description bdesc_2arg[] = - NDS32_NO_TARGET_BUILTIN(unaligned_store_hw, "unaligned_store_hw", UASTORE_HW) - NDS32_NO_TARGET_BUILTIN(unaligned_storesi, "unaligned_store_hw", UASTORE_W) - NDS32_NO_TARGET_BUILTIN(unaligned_storedi, "unaligned_store_hw", UASTORE_DW) -- -+ NDS32_BUILTIN(addv2hi3, "add16", ADD16) -+ NDS32_BUILTIN(addv2hi3, "v_uadd16", V_UADD16) -+ NDS32_BUILTIN(addv2hi3, "v_sadd16", V_SADD16) -+ NDS32_BUILTIN(raddv2hi3, "radd16", RADD16) -+ NDS32_BUILTIN(raddv2hi3, "v_radd16", V_RADD16) -+ NDS32_BUILTIN(uraddv2hi3, "uradd16", URADD16) -+ NDS32_BUILTIN(uraddv2hi3, "v_uradd16", V_URADD16) -+ NDS32_BUILTIN(kaddv2hi3, "kadd16", KADD16) -+ NDS32_BUILTIN(kaddv2hi3, "v_kadd16", V_KADD16) -+ NDS32_BUILTIN(ukaddv2hi3, "ukadd16", UKADD16) -+ NDS32_BUILTIN(ukaddv2hi3, "v_ukadd16", V_UKADD16) -+ NDS32_BUILTIN(subv2hi3, "sub16", SUB16) -+ NDS32_BUILTIN(subv2hi3, "v_usub16", V_USUB16) -+ NDS32_BUILTIN(subv2hi3, "v_ssub16", V_SSUB16) -+ NDS32_BUILTIN(rsubv2hi3, "rsub16", RSUB16) -+ NDS32_BUILTIN(rsubv2hi3, "v_rsub16", V_RSUB16) -+ NDS32_BUILTIN(ursubv2hi3, "ursub16", URSUB16) -+ NDS32_BUILTIN(ursubv2hi3, "v_ursub16", V_URSUB16) -+ NDS32_BUILTIN(ksubv2hi3, "ksub16", KSUB16) -+ NDS32_BUILTIN(ksubv2hi3, "v_ksub16", V_KSUB16) -+ NDS32_BUILTIN(uksubv2hi3, "uksub16", UKSUB16) -+ NDS32_BUILTIN(uksubv2hi3, "v_uksub16", V_UKSUB16) -+ NDS32_BUILTIN(cras16_1, "cras16", CRAS16) -+ NDS32_BUILTIN(cras16_1, "v_ucras16", V_UCRAS16) -+ NDS32_BUILTIN(cras16_1, "v_scras16", V_SCRAS16) -+ NDS32_BUILTIN(rcras16_1, "rcras16", RCRAS16) -+ NDS32_BUILTIN(rcras16_1, "v_rcras16", V_RCRAS16) -+ NDS32_BUILTIN(urcras16_1, "urcras16", URCRAS16) -+ NDS32_BUILTIN(urcras16_1, "v_urcras16", V_URCRAS16) -+ NDS32_BUILTIN(kcras16_1, "kcras16", KCRAS16) -+ NDS32_BUILTIN(kcras16_1, "v_kcras16", V_KCRAS16) -+ NDS32_BUILTIN(ukcras16_1, "ukcras16", UKCRAS16) -+ NDS32_BUILTIN(ukcras16_1, "v_ukcras16", V_UKCRAS16) -+ NDS32_BUILTIN(crsa16_1, "crsa16", CRSA16) -+ NDS32_BUILTIN(crsa16_1, "v_ucrsa16", V_UCRSA16) -+ NDS32_BUILTIN(crsa16_1, "v_scrsa16", V_SCRSA16) -+ NDS32_BUILTIN(rcrsa16_1, "rcrsa16", RCRSA16) -+ NDS32_BUILTIN(rcrsa16_1, "v_rcrsa16", V_RCRSA16) -+ NDS32_BUILTIN(urcrsa16_1, "urcrsa16", URCRSA16) -+ NDS32_BUILTIN(urcrsa16_1, "v_urcrsa16", V_URCRSA16) -+ NDS32_BUILTIN(kcrsa16_1, "kcrsa16", KCRSA16) -+ NDS32_BUILTIN(kcrsa16_1, "v_kcrsa16", V_KCRSA16) -+ NDS32_BUILTIN(ukcrsa16_1, "ukcrsa16", UKCRSA16) -+ NDS32_BUILTIN(ukcrsa16_1, "v_ukcrsa16", V_UKCRSA16) -+ NDS32_BUILTIN(addv4qi3, "add8", ADD8) -+ NDS32_BUILTIN(addv4qi3, "v_uadd8", V_UADD8) -+ NDS32_BUILTIN(addv4qi3, "v_sadd8", V_SADD8) -+ NDS32_BUILTIN(raddv4qi3, "radd8", RADD8) -+ NDS32_BUILTIN(raddv4qi3, "v_radd8", V_RADD8) -+ NDS32_BUILTIN(uraddv4qi3, "uradd8", URADD8) -+ NDS32_BUILTIN(uraddv4qi3, "v_uradd8", V_URADD8) -+ NDS32_BUILTIN(kaddv4qi3, "kadd8", KADD8) -+ NDS32_BUILTIN(kaddv4qi3, "v_kadd8", V_KADD8) -+ NDS32_BUILTIN(ukaddv4qi3, "ukadd8", UKADD8) -+ NDS32_BUILTIN(ukaddv4qi3, "v_ukadd8", V_UKADD8) -+ NDS32_BUILTIN(subv4qi3, "sub8", SUB8) -+ NDS32_BUILTIN(subv4qi3, "v_usub8", V_USUB8) -+ NDS32_BUILTIN(subv4qi3, "v_ssub8", V_SSUB8) -+ NDS32_BUILTIN(rsubv4qi3, "rsub8", RSUB8) -+ NDS32_BUILTIN(rsubv4qi3, "v_rsub8", V_RSUB8) -+ NDS32_BUILTIN(ursubv4qi3, "ursub8", URSUB8) -+ NDS32_BUILTIN(ursubv4qi3, "v_ursub8", V_URSUB8) -+ NDS32_BUILTIN(ksubv4qi3, "ksub8", KSUB8) -+ NDS32_BUILTIN(ksubv4qi3, "v_ksub8", V_KSUB8) -+ NDS32_BUILTIN(uksubv4qi3, "uksub8", UKSUB8) -+ NDS32_BUILTIN(uksubv4qi3, "v_uksub8", V_UKSUB8) -+ NDS32_BUILTIN(ashrv2hi3, "sra16", SRA16) -+ NDS32_BUILTIN(ashrv2hi3, "v_sra16", V_SRA16) -+ NDS32_BUILTIN(sra16_round, "sra16_u", SRA16_U) -+ NDS32_BUILTIN(sra16_round, "v_sra16_u", V_SRA16_U) -+ NDS32_BUILTIN(lshrv2hi3, "srl16", SRL16) -+ NDS32_BUILTIN(lshrv2hi3, "v_srl16", V_SRL16) -+ NDS32_BUILTIN(srl16_round, "srl16_u", SRL16_U) -+ NDS32_BUILTIN(srl16_round, "v_srl16_u", V_SRL16_U) -+ NDS32_BUILTIN(ashlv2hi3, "sll16", SLL16) -+ NDS32_BUILTIN(ashlv2hi3, "v_sll16", V_SLL16) -+ NDS32_BUILTIN(kslli16, "ksll16", KSLL16) -+ NDS32_BUILTIN(kslli16, "v_ksll16", V_KSLL16) -+ NDS32_BUILTIN(kslra16, "kslra16", KSLRA16) -+ NDS32_BUILTIN(kslra16, "v_kslra16", V_KSLRA16) -+ NDS32_BUILTIN(kslra16_round, "kslra16_u", KSLRA16_U) -+ NDS32_BUILTIN(kslra16_round, "v_kslra16_u", V_KSLRA16_U) -+ NDS32_BUILTIN(cmpeq16, "cmpeq16", CMPEQ16) -+ NDS32_BUILTIN(cmpeq16, "v_scmpeq16", V_SCMPEQ16) -+ NDS32_BUILTIN(cmpeq16, "v_ucmpeq16", V_UCMPEQ16) -+ NDS32_BUILTIN(scmplt16, "scmplt16", SCMPLT16) -+ NDS32_BUILTIN(scmplt16, "v_scmplt16", V_SCMPLT16) -+ NDS32_BUILTIN(scmple16, "scmple16", SCMPLE16) -+ NDS32_BUILTIN(scmple16, "v_scmple16", V_SCMPLE16) -+ NDS32_BUILTIN(ucmplt16, "ucmplt16", UCMPLT16) -+ NDS32_BUILTIN(ucmplt16, "v_ucmplt16", V_UCMPLT16) -+ NDS32_BUILTIN(ucmplt16, "ucmple16", UCMPLE16) -+ NDS32_BUILTIN(ucmplt16, "v_ucmple16", V_UCMPLE16) -+ NDS32_BUILTIN(cmpeq8, "cmpeq8", CMPEQ8) -+ NDS32_BUILTIN(cmpeq8, "v_scmpeq8", V_SCMPEQ8) -+ NDS32_BUILTIN(cmpeq8, "v_ucmpeq8", V_UCMPEQ8) -+ NDS32_BUILTIN(scmplt8, "scmplt8", SCMPLT8) -+ NDS32_BUILTIN(scmplt8, "v_scmplt8", V_SCMPLT8) -+ NDS32_BUILTIN(scmple8, "scmple8", SCMPLE8) -+ NDS32_BUILTIN(scmple8, "v_scmple8", V_SCMPLE8) -+ NDS32_BUILTIN(ucmplt8, "ucmplt8", UCMPLT8) -+ NDS32_BUILTIN(ucmplt8, "v_ucmplt8", V_UCMPLT8) -+ NDS32_BUILTIN(ucmplt8, "ucmple8", UCMPLE8) -+ NDS32_BUILTIN(ucmplt8, "v_ucmple8", V_UCMPLE8) -+ NDS32_BUILTIN(sminv2hi3, "smin16", SMIN16) -+ NDS32_BUILTIN(sminv2hi3, "v_smin16", V_SMIN16) -+ NDS32_BUILTIN(uminv2hi3, "umin16", UMIN16) -+ NDS32_BUILTIN(uminv2hi3, "v_umin16", V_UMIN16) -+ NDS32_BUILTIN(smaxv2hi3, "smax16", SMAX16) -+ NDS32_BUILTIN(smaxv2hi3, "v_smax16", V_SMAX16) -+ NDS32_BUILTIN(umaxv2hi3, "umax16", UMAX16) -+ NDS32_BUILTIN(umaxv2hi3, "v_umax16", V_UMAX16) -+ NDS32_BUILTIN(khm16, "khm16", KHM16) -+ NDS32_BUILTIN(khm16, "v_khm16", V_KHM16) -+ NDS32_BUILTIN(khmx16, "khmx16", KHMX16) -+ NDS32_BUILTIN(khmx16, "v_khmx16", V_KHMX16) -+ NDS32_BUILTIN(sminv4qi3, "smin8", SMIN8) -+ NDS32_BUILTIN(sminv4qi3, "v_smin8", V_SMIN8) -+ NDS32_BUILTIN(uminv4qi3, "umin8", UMIN8) -+ NDS32_BUILTIN(uminv4qi3, "v_umin8", V_UMIN8) -+ NDS32_BUILTIN(smaxv4qi3, "smax8", SMAX8) -+ NDS32_BUILTIN(smaxv4qi3, "v_smax8", V_SMAX8) -+ NDS32_BUILTIN(umaxv4qi3, "umax8", UMAX8) -+ NDS32_BUILTIN(umaxv4qi3, "v_umax8", V_UMAX8) -+ NDS32_BUILTIN(raddsi3, "raddw", RADDW) -+ NDS32_BUILTIN(uraddsi3, "uraddw", URADDW) -+ NDS32_BUILTIN(rsubsi3, "rsubw", RSUBW) -+ NDS32_BUILTIN(ursubsi3, "ursubw", URSUBW) -+ NDS32_BUILTIN(sraiu, "sra_u", SRA_U) -+ NDS32_BUILTIN(kssl, "ksll", KSLL) -+ NDS32_BUILTIN(pkbb, "pkbb16", PKBB16) -+ NDS32_BUILTIN(pkbb, "v_pkbb16", V_PKBB16) -+ NDS32_BUILTIN(pkbt, "pkbt16", PKBT16) -+ NDS32_BUILTIN(pkbt, "v_pkbt16", V_PKBT16) -+ NDS32_BUILTIN(pktb, "pktb16", PKTB16) -+ NDS32_BUILTIN(pktb, "v_pktb16", V_PKTB16) -+ NDS32_BUILTIN(pktt, "pktt16", PKTT16) -+ NDS32_BUILTIN(pktt, "v_pktt16", V_PKTT16) -+ NDS32_BUILTIN(smulsi3_highpart, "smmul", SMMUL) -+ NDS32_BUILTIN(smmul_round, "smmul_u", SMMUL_U) -+ NDS32_BUILTIN(smmwb, "smmwb", SMMWB) -+ NDS32_BUILTIN(smmwb, "v_smmwb", V_SMMWB) -+ NDS32_BUILTIN(smmwb_round, "smmwb_u", SMMWB_U) -+ NDS32_BUILTIN(smmwb_round, "v_smmwb_u", V_SMMWB_U) -+ NDS32_BUILTIN(smmwt, "smmwt", SMMWT) -+ NDS32_BUILTIN(smmwt, "v_smmwt", V_SMMWT) -+ NDS32_BUILTIN(smmwt_round, "smmwt_u", SMMWT_U) -+ NDS32_BUILTIN(smmwt_round, "v_smmwt_u", V_SMMWT_U) -+ NDS32_BUILTIN(smbb, "smbb", SMBB) -+ NDS32_BUILTIN(smbb, "v_smbb", V_SMBB) -+ NDS32_BUILTIN(smbt, "smbt", SMBT) -+ NDS32_BUILTIN(smbt, "v_smbt", V_SMBT) -+ NDS32_BUILTIN(smtt, "smtt", SMTT) -+ NDS32_BUILTIN(smtt, "v_smtt", V_SMTT) -+ NDS32_BUILTIN(kmda, "kmda", KMDA) -+ NDS32_BUILTIN(kmda, "v_kmda", V_KMDA) -+ NDS32_BUILTIN(kmxda, "kmxda", KMXDA) -+ NDS32_BUILTIN(kmxda, "v_kmxda", V_KMXDA) -+ NDS32_BUILTIN(smds, "smds", SMDS) -+ NDS32_BUILTIN(smds, "v_smds", V_SMDS) -+ NDS32_BUILTIN(smdrs, "smdrs", SMDRS) -+ NDS32_BUILTIN(smdrs, "v_smdrs", V_SMDRS) -+ NDS32_BUILTIN(smxdsv, "smxds", SMXDS) -+ NDS32_BUILTIN(smxdsv, "v_smxds", V_SMXDS) -+ NDS32_BUILTIN(smal1, "smal", SMAL) -+ NDS32_BUILTIN(smal1, "v_smal", V_SMAL) -+ NDS32_BUILTIN(bitrev, "bitrev", BITREV) -+ NDS32_BUILTIN(wext, "wext", WEXT) -+ NDS32_BUILTIN(adddi3, "sadd64", SADD64) -+ NDS32_BUILTIN(adddi3, "uadd64", UADD64) -+ NDS32_BUILTIN(radddi3, "radd64", RADD64) -+ NDS32_BUILTIN(uradddi3, "uradd64", URADD64) -+ NDS32_BUILTIN(kadddi3, "kadd64", KADD64) -+ NDS32_BUILTIN(ukadddi3, "ukadd64", UKADD64) -+ NDS32_BUILTIN(subdi3, "ssub64", SSUB64) -+ NDS32_BUILTIN(subdi3, "usub64", USUB64) -+ NDS32_BUILTIN(rsubdi3, "rsub64", RSUB64) -+ NDS32_BUILTIN(ursubdi3, "ursub64", URSUB64) -+ NDS32_BUILTIN(ksubdi3, "ksub64", KSUB64) -+ NDS32_BUILTIN(uksubdi3, "uksub64", UKSUB64) -+ NDS32_BUILTIN(smul16, "smul16", SMUL16) -+ NDS32_BUILTIN(smul16, "v_smul16", V_SMUL16) -+ NDS32_BUILTIN(smulx16, "smulx16", SMULX16) -+ NDS32_BUILTIN(smulx16, "v_smulx16", V_SMULX16) -+ NDS32_BUILTIN(umul16, "umul16", UMUL16) -+ NDS32_BUILTIN(umul16, "v_umul16", V_UMUL16) -+ NDS32_BUILTIN(umulx16, "umulx16", UMULX16) -+ NDS32_BUILTIN(umulx16, "v_umulx16", V_UMULX16) -+ NDS32_BUILTIN(kwmmul, "kwmmul", KWMMUL) -+ NDS32_BUILTIN(kwmmul_round, "kwmmul_u", KWMMUL_U) -+ NDS32_NO_TARGET_BUILTIN(unaligned_storev2hi, -+ "put_unaligned_u16x2", UASTORE_U16) -+ NDS32_NO_TARGET_BUILTIN(unaligned_storev2hi, -+ "put_unaligned_s16x2", UASTORE_S16) -+ NDS32_NO_TARGET_BUILTIN(unaligned_storev4qi, "put_unaligned_u8x4", UASTORE_U8) -+ NDS32_NO_TARGET_BUILTIN(unaligned_storev4qi, "put_unaligned_s8x4", UASTORE_S8) - }; - - /* Two-argument intrinsics with an immediate second argument. */ -@@ -617,6 +860,22 @@ static struct builtin_description bdesc_2argimm[] = - NDS32_BUILTIN(unspec_clips, "clips", CLIPS) - NDS32_NO_TARGET_BUILTIN(unspec_teqz, "teqz", TEQZ) - NDS32_NO_TARGET_BUILTIN(unspec_tnez, "tnez", TNEZ) -+ NDS32_BUILTIN(ashrv2hi3, "srl16", SRL16) -+ NDS32_BUILTIN(ashrv2hi3, "v_srl16", V_SRL16) -+ NDS32_BUILTIN(srl16_round, "srl16_u", SRL16_U) -+ NDS32_BUILTIN(srl16_round, "v_srl16_u", V_SRL16_U) -+ NDS32_BUILTIN(kslli16, "ksll16", KSLL16) -+ NDS32_BUILTIN(kslli16, "v_ksll16", V_KSLL16) -+ NDS32_BUILTIN(sclip16, "sclip16", SCLIP16) -+ NDS32_BUILTIN(sclip16, "v_sclip16", V_SCLIP16) -+ NDS32_BUILTIN(uclip16, "uclip16", UCLIP16) -+ NDS32_BUILTIN(uclip16, "v_uclip16", V_UCLIP16) -+ NDS32_BUILTIN(sraiu, "sra_u", SRA_U) -+ NDS32_BUILTIN(kssl, "ksll", KSLL) -+ NDS32_BUILTIN(bitrev, "bitrev", BITREV) -+ NDS32_BUILTIN(wext, "wext", WEXT) -+ NDS32_BUILTIN(uclip32, "uclip32", UCLIP32) -+ NDS32_BUILTIN(sclip32, "sclip32", SCLIP32) - }; - - /* Intrinsics that take three arguments. */ -@@ -625,6 +884,67 @@ static struct builtin_description bdesc_3arg[] = - NDS32_BUILTIN(unspec_pbsada, "pbsada", PBSADA) - NDS32_NO_TARGET_BUILTIN(bse, "bse", BSE) - NDS32_NO_TARGET_BUILTIN(bsp, "bsp", BSP) -+ NDS32_BUILTIN(kmabb, "kmabb", KMABB) -+ NDS32_BUILTIN(kmabb, "v_kmabb", V_KMABB) -+ NDS32_BUILTIN(kmabt, "kmabt", KMABT) -+ NDS32_BUILTIN(kmabt, "v_kmabt", V_KMABT) -+ NDS32_BUILTIN(kmatt, "kmatt", KMATT) -+ NDS32_BUILTIN(kmatt, "v_kmatt", V_KMATT) -+ NDS32_BUILTIN(kmada, "kmada", KMADA) -+ NDS32_BUILTIN(kmada, "v_kmada", V_KMADA) -+ NDS32_BUILTIN(kmaxda, "kmaxda", KMAXDA) -+ NDS32_BUILTIN(kmaxda, "v_kmaxda", V_KMAXDA) -+ NDS32_BUILTIN(kmads, "kmads", KMADS) -+ NDS32_BUILTIN(kmads, "v_kmads", V_KMADS) -+ NDS32_BUILTIN(kmadrs, "kmadrs", KMADRS) -+ NDS32_BUILTIN(kmadrs, "v_kmadrs", V_KMADRS) -+ NDS32_BUILTIN(kmaxds, "kmaxds", KMAXDS) -+ NDS32_BUILTIN(kmaxds, "v_kmaxds", V_KMAXDS) -+ NDS32_BUILTIN(kmsda, "kmsda", KMSDA) -+ NDS32_BUILTIN(kmsda, "v_kmsda", V_KMSDA) -+ NDS32_BUILTIN(kmsxda, "kmsxda", KMSXDA) -+ NDS32_BUILTIN(kmsxda, "v_kmsxda", V_KMSXDA) -+ NDS32_BUILTIN(bpick1, "bpick", BPICK) -+ NDS32_BUILTIN(smar64_1, "smar64", SMAR64) -+ NDS32_BUILTIN(smsr64, "smsr64", SMSR64) -+ NDS32_BUILTIN(umar64_1, "umar64", UMAR64) -+ NDS32_BUILTIN(umsr64, "umsr64", UMSR64) -+ NDS32_BUILTIN(kmar64_1, "kmar64", KMAR64) -+ NDS32_BUILTIN(kmsr64, "kmsr64", KMSR64) -+ NDS32_BUILTIN(ukmar64_1, "ukmar64", UKMAR64) -+ NDS32_BUILTIN(ukmsr64, "ukmsr64", UKMSR64) -+ NDS32_BUILTIN(smalbb, "smalbb", SMALBB) -+ NDS32_BUILTIN(smalbb, "v_smalbb", V_SMALBB) -+ NDS32_BUILTIN(smalbt, "smalbt", SMALBT) -+ NDS32_BUILTIN(smalbt, "v_smalbt", V_SMALBT) -+ NDS32_BUILTIN(smaltt, "smaltt", SMALTT) -+ NDS32_BUILTIN(smaltt, "v_smaltt", V_SMALTT) -+ NDS32_BUILTIN(smalda1, "smalda", SMALDA) -+ NDS32_BUILTIN(smalda1, "v_smalda", V_SMALDA) -+ NDS32_BUILTIN(smalxda1, "smalxda", SMALXDA) -+ NDS32_BUILTIN(smalxda1, "v_smalxda", V_SMALXDA) -+ NDS32_BUILTIN(smalds1, "smalds", SMALDS) -+ NDS32_BUILTIN(smalds1, "v_smalds", V_SMALDS) -+ NDS32_BUILTIN(smaldrs3, "smaldrs", SMALDRS) -+ NDS32_BUILTIN(smaldrs3, "v_smaldrs", V_SMALDRS) -+ NDS32_BUILTIN(smalxds1, "smalxds", SMALXDS) -+ NDS32_BUILTIN(smalxds1, "v_smalxds", V_SMALXDS) -+ NDS32_BUILTIN(smslda1, "smslda", SMSLDA) -+ NDS32_BUILTIN(smslda1, "v_smslda", V_SMSLDA) -+ NDS32_BUILTIN(smslxda1, "smslxda", SMSLXDA) -+ NDS32_BUILTIN(smslxda1, "v_smslxda", V_SMSLXDA) -+ NDS32_BUILTIN(kmmawb, "kmmawb", KMMAWB) -+ NDS32_BUILTIN(kmmawb, "v_kmmawb", V_KMMAWB) -+ NDS32_BUILTIN(kmmawb_round, "kmmawb_u", KMMAWB_U) -+ NDS32_BUILTIN(kmmawb_round, "v_kmmawb_u", V_KMMAWB_U) -+ NDS32_BUILTIN(kmmawt, "kmmawt", KMMAWT) -+ NDS32_BUILTIN(kmmawt, "v_kmmawt", V_KMMAWT) -+ NDS32_BUILTIN(kmmawt_round, "kmmawt_u", KMMAWT_U) -+ NDS32_BUILTIN(kmmawt_round, "v_kmmawt_u", V_KMMAWT_U) -+ NDS32_BUILTIN(kmmac, "kmmac", KMMAC) -+ NDS32_BUILTIN(kmmac_round, "kmmac_u", KMMAC_U) -+ NDS32_BUILTIN(kmmsb, "kmmsb", KMMSB) -+ NDS32_BUILTIN(kmmsb_round, "kmmsb_u", KMMSB_U) - }; - - /* Three-argument intrinsics with an immediate third argument. */ -@@ -634,6 +954,7 @@ static struct builtin_description bdesc_3argimm[] = - NDS32_NO_TARGET_BUILTIN(prefetch_hw, "prefetch_hw", DPREF_HW) - NDS32_NO_TARGET_BUILTIN(prefetch_w, "prefetch_w", DPREF_W) - NDS32_NO_TARGET_BUILTIN(prefetch_dw, "prefetch_dw", DPREF_DW) -+ NDS32_BUILTIN(insb, "insb", INSB) - }; - - /* Intrinsics that load a value. */ -@@ -676,6 +997,11 @@ nds32_expand_builtin_impl (tree exp, - unsigned i; - struct builtin_description *d; - -+ if (!NDS32_EXT_DSP_P () -+ && fcode > NDS32_BUILTIN_DSP_BEGIN -+ && fcode < NDS32_BUILTIN_DSP_END) -+ error ("don't support DSP extension instructions"); -+ - switch (fcode) - { - /* FPU Register Transfer. */ -@@ -812,6 +1138,9 @@ nds32_expand_builtin_impl (tree exp, - case NDS32_BUILTIN_CCTL_L1D_WBALL_ONE_LVL: - emit_insn (gen_cctl_l1d_wball_one_lvl()); - return target; -+ case NDS32_BUILTIN_CLROV: -+ emit_insn (gen_unspec_volatile_clrov ()); -+ return target; - case NDS32_BUILTIN_STANDBY_NO_WAKE_GRANT: - emit_insn (gen_unspec_standby_no_wake_grant ()); - return target; -@@ -947,10 +1276,18 @@ nds32_init_builtins_impl (void) - NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE) - - /* Looking for return type and argument can be found in tree.h file. */ -+ tree ptr_char_type_node = build_pointer_type (char_type_node); - tree ptr_uchar_type_node = build_pointer_type (unsigned_char_type_node); - tree ptr_ushort_type_node = build_pointer_type (short_unsigned_type_node); -+ tree ptr_short_type_node = build_pointer_type (short_integer_type_node); - tree ptr_uint_type_node = build_pointer_type (unsigned_type_node); - tree ptr_ulong_type_node = build_pointer_type (long_long_unsigned_type_node); -+ tree v4qi_type_node = build_vector_type (intQI_type_node, 4); -+ tree u_v4qi_type_node = build_vector_type (unsigned_intQI_type_node, 4); -+ tree v2hi_type_node = build_vector_type (intHI_type_node, 2); -+ tree u_v2hi_type_node = build_vector_type (unsigned_intHI_type_node, 2); -+ tree v2si_type_node = build_vector_type (intSI_type_node, 2); -+ tree u_v2si_type_node = build_vector_type (unsigned_intSI_type_node, 2); - - /* Cache. */ - ADD_NDS32_BUILTIN1 ("isync", void, ptr_uint, ISYNC); -@@ -1050,6 +1387,31 @@ nds32_init_builtins_impl (void) - ADD_NDS32_BUILTIN2 ("se_ffmism", integer, unsigned, unsigned, FFMISM); - ADD_NDS32_BUILTIN2 ("se_flmism", integer, unsigned, unsigned, FLMISM); - -+ /* SATURATION */ -+ ADD_NDS32_BUILTIN2 ("kaddw", integer, integer, integer, KADDW); -+ ADD_NDS32_BUILTIN2 ("ksubw", integer, integer, integer, KSUBW); -+ ADD_NDS32_BUILTIN2 ("kaddh", integer, integer, integer, KADDH); -+ ADD_NDS32_BUILTIN2 ("ksubh", integer, integer, integer, KSUBH); -+ ADD_NDS32_BUILTIN2 ("kdmbb", integer, unsigned, unsigned, KDMBB); -+ ADD_NDS32_BUILTIN2 ("v_kdmbb", integer, v2hi, v2hi, V_KDMBB); -+ ADD_NDS32_BUILTIN2 ("kdmbt", integer, unsigned, unsigned, KDMBT); -+ ADD_NDS32_BUILTIN2 ("v_kdmbt", integer, v2hi, v2hi, V_KDMBT); -+ ADD_NDS32_BUILTIN2 ("kdmtb", integer, unsigned, unsigned, KDMTB); -+ ADD_NDS32_BUILTIN2 ("v_kdmtb", integer, v2hi, v2hi, V_KDMTB); -+ ADD_NDS32_BUILTIN2 ("kdmtt", integer, unsigned, unsigned, KDMTT); -+ ADD_NDS32_BUILTIN2 ("v_kdmtt", integer, v2hi, v2hi, V_KDMTT); -+ ADD_NDS32_BUILTIN2 ("khmbb", integer, unsigned, unsigned, KHMBB); -+ ADD_NDS32_BUILTIN2 ("v_khmbb", integer, v2hi, v2hi, V_KHMBB); -+ ADD_NDS32_BUILTIN2 ("khmbt", integer, unsigned, unsigned, KHMBT); -+ ADD_NDS32_BUILTIN2 ("v_khmbt", integer, v2hi, v2hi, V_KHMBT); -+ ADD_NDS32_BUILTIN2 ("khmtb", integer, unsigned, unsigned, KHMTB); -+ ADD_NDS32_BUILTIN2 ("v_khmtb", integer, v2hi, v2hi, V_KHMTB); -+ ADD_NDS32_BUILTIN2 ("khmtt", integer, unsigned, unsigned, KHMTT); -+ ADD_NDS32_BUILTIN2 ("v_khmtt", integer, v2hi, v2hi, V_KHMTT); -+ ADD_NDS32_BUILTIN2 ("kslraw", integer, integer, integer, KSLRAW); -+ ADD_NDS32_BUILTIN2 ("kslraw_u", integer, integer, integer, KSLRAW_U); -+ ADD_NDS32_BUILTIN0 ("rdov", unsigned, RDOV); -+ ADD_NDS32_BUILTIN0 ("clrov", void, CLROV); - - /* ROTR */ - ADD_NDS32_BUILTIN2 ("rotr", unsigned, unsigned, unsigned, ROTR); -@@ -1109,4 +1471,384 @@ nds32_init_builtins_impl (void) - ADD_NDS32_BUILTIN0 ("enable_unaligned", void, ENABLE_UNALIGNED); - ADD_NDS32_BUILTIN0 ("disable_unaligned", void, DISABLE_UNALIGNED); - -+ /* DSP Extension: SIMD 16bit Add and Subtract. */ -+ ADD_NDS32_BUILTIN2 ("add16", unsigned, unsigned, unsigned, ADD16); -+ ADD_NDS32_BUILTIN2 ("v_uadd16", u_v2hi, u_v2hi, u_v2hi, V_UADD16); -+ ADD_NDS32_BUILTIN2 ("v_sadd16", v2hi, v2hi, v2hi, V_SADD16); -+ ADD_NDS32_BUILTIN2 ("radd16", unsigned, unsigned, unsigned, RADD16); -+ ADD_NDS32_BUILTIN2 ("v_radd16", v2hi, v2hi, v2hi, V_RADD16); -+ ADD_NDS32_BUILTIN2 ("uradd16", unsigned, unsigned, unsigned, URADD16); -+ ADD_NDS32_BUILTIN2 ("v_uradd16", u_v2hi, u_v2hi, u_v2hi, V_URADD16); -+ ADD_NDS32_BUILTIN2 ("kadd16", unsigned, unsigned, unsigned, KADD16); -+ ADD_NDS32_BUILTIN2 ("v_kadd16", v2hi, v2hi, v2hi, V_KADD16); -+ ADD_NDS32_BUILTIN2 ("ukadd16", unsigned, unsigned, unsigned, UKADD16); -+ ADD_NDS32_BUILTIN2 ("v_ukadd16", u_v2hi, u_v2hi, u_v2hi, V_UKADD16); -+ ADD_NDS32_BUILTIN2 ("sub16", unsigned, unsigned, unsigned, SUB16); -+ ADD_NDS32_BUILTIN2 ("v_usub16", u_v2hi, u_v2hi, u_v2hi, V_USUB16); -+ ADD_NDS32_BUILTIN2 ("v_ssub16", v2hi, v2hi, v2hi, V_SSUB16); -+ ADD_NDS32_BUILTIN2 ("rsub16", unsigned, unsigned, unsigned, RSUB16); -+ ADD_NDS32_BUILTIN2 ("v_rsub16", v2hi, v2hi, v2hi, V_RSUB16); -+ ADD_NDS32_BUILTIN2 ("ursub16", unsigned, unsigned, unsigned, URSUB16); -+ ADD_NDS32_BUILTIN2 ("v_ursub16", u_v2hi, u_v2hi, u_v2hi, V_URSUB16); -+ ADD_NDS32_BUILTIN2 ("ksub16", unsigned, unsigned, unsigned, KSUB16); -+ ADD_NDS32_BUILTIN2 ("v_ksub16", v2hi, v2hi, v2hi, V_KSUB16); -+ ADD_NDS32_BUILTIN2 ("uksub16", unsigned, unsigned, unsigned, UKSUB16); -+ ADD_NDS32_BUILTIN2 ("v_uksub16", u_v2hi, u_v2hi, u_v2hi, V_UKSUB16); -+ ADD_NDS32_BUILTIN2 ("cras16", unsigned, unsigned, unsigned, CRAS16); -+ ADD_NDS32_BUILTIN2 ("v_ucras16", u_v2hi, u_v2hi, u_v2hi, V_UCRAS16); -+ ADD_NDS32_BUILTIN2 ("v_scras16", v2hi, v2hi, v2hi, V_SCRAS16); -+ ADD_NDS32_BUILTIN2 ("rcras16", unsigned, unsigned, unsigned, RCRAS16); -+ ADD_NDS32_BUILTIN2 ("v_rcras16", v2hi, v2hi, v2hi, V_RCRAS16); -+ ADD_NDS32_BUILTIN2 ("urcras16", unsigned, unsigned, unsigned, URCRAS16); -+ ADD_NDS32_BUILTIN2 ("v_urcras16", u_v2hi, u_v2hi, u_v2hi, V_URCRAS16); -+ ADD_NDS32_BUILTIN2 ("kcras16", unsigned, unsigned, unsigned, KCRAS16); -+ ADD_NDS32_BUILTIN2 ("v_kcras16", v2hi, v2hi, v2hi, V_KCRAS16); -+ ADD_NDS32_BUILTIN2 ("ukcras16", unsigned, unsigned, unsigned, UKCRAS16); -+ ADD_NDS32_BUILTIN2 ("v_ukcras16", u_v2hi, u_v2hi, u_v2hi, V_UKCRAS16); -+ ADD_NDS32_BUILTIN2 ("crsa16", unsigned, unsigned, unsigned, CRSA16); -+ ADD_NDS32_BUILTIN2 ("v_ucrsa16", u_v2hi, u_v2hi, u_v2hi, V_UCRSA16); -+ ADD_NDS32_BUILTIN2 ("v_scrsa16", v2hi, v2hi, v2hi, V_SCRSA16); -+ ADD_NDS32_BUILTIN2 ("rcrsa16", unsigned, unsigned, unsigned, RCRSA16); -+ ADD_NDS32_BUILTIN2 ("v_rcrsa16", v2hi, v2hi, v2hi, V_RCRSA16); -+ ADD_NDS32_BUILTIN2 ("urcrsa16", unsigned, unsigned, unsigned, URCRSA16); -+ ADD_NDS32_BUILTIN2 ("v_urcrsa16", u_v2hi, u_v2hi, u_v2hi, V_URCRSA16); -+ ADD_NDS32_BUILTIN2 ("kcrsa16", unsigned, unsigned, unsigned, KCRSA16); -+ ADD_NDS32_BUILTIN2 ("v_kcrsa16", v2hi, v2hi, v2hi, V_KCRSA16); -+ ADD_NDS32_BUILTIN2 ("ukcrsa16", unsigned, unsigned, unsigned, UKCRSA16); -+ ADD_NDS32_BUILTIN2 ("v_ukcrsa16", u_v2hi, u_v2hi, u_v2hi, V_UKCRSA16); -+ -+ /* DSP Extension: SIMD 8bit Add and Subtract. */ -+ ADD_NDS32_BUILTIN2 ("add8", integer, integer, integer, ADD8); -+ ADD_NDS32_BUILTIN2 ("v_uadd8", u_v4qi, u_v4qi, u_v4qi, V_UADD8); -+ ADD_NDS32_BUILTIN2 ("v_sadd8", v4qi, v4qi, v4qi, V_SADD8); -+ ADD_NDS32_BUILTIN2 ("radd8", unsigned, unsigned, unsigned, RADD8); -+ ADD_NDS32_BUILTIN2 ("v_radd8", v4qi, v4qi, v4qi, V_RADD8); -+ ADD_NDS32_BUILTIN2 ("uradd8", unsigned, unsigned, unsigned, URADD8); -+ ADD_NDS32_BUILTIN2 ("v_uradd8", u_v4qi, u_v4qi, u_v4qi, V_URADD8); -+ ADD_NDS32_BUILTIN2 ("kadd8", unsigned, unsigned, unsigned, KADD8); -+ ADD_NDS32_BUILTIN2 ("v_kadd8", v4qi, v4qi, v4qi, V_KADD8); -+ ADD_NDS32_BUILTIN2 ("ukadd8", unsigned, unsigned, unsigned, UKADD8); -+ ADD_NDS32_BUILTIN2 ("v_ukadd8", u_v4qi, u_v4qi, u_v4qi, V_UKADD8); -+ ADD_NDS32_BUILTIN2 ("sub8", integer, integer, integer, SUB8); -+ ADD_NDS32_BUILTIN2 ("v_usub8", u_v4qi, u_v4qi, u_v4qi, V_USUB8); -+ ADD_NDS32_BUILTIN2 ("v_ssub8", v4qi, v4qi, v4qi, V_SSUB8); -+ ADD_NDS32_BUILTIN2 ("rsub8", unsigned, unsigned, unsigned, RSUB8); -+ ADD_NDS32_BUILTIN2 ("v_rsub8", v4qi, v4qi, v4qi, V_RSUB8); -+ ADD_NDS32_BUILTIN2 ("ursub8", unsigned, unsigned, unsigned, URSUB8); -+ ADD_NDS32_BUILTIN2 ("v_ursub8", u_v4qi, u_v4qi, u_v4qi, V_URSUB8); -+ ADD_NDS32_BUILTIN2 ("ksub8", unsigned, unsigned, unsigned, KSUB8); -+ ADD_NDS32_BUILTIN2 ("v_ksub8", v4qi, v4qi, v4qi, V_KSUB8); -+ ADD_NDS32_BUILTIN2 ("uksub8", unsigned, unsigned, unsigned, UKSUB8); -+ ADD_NDS32_BUILTIN2 ("v_uksub8", u_v4qi, u_v4qi, u_v4qi, V_UKSUB8); -+ -+ /* DSP Extension: SIMD 16bit Shift. */ -+ ADD_NDS32_BUILTIN2 ("sra16", unsigned, unsigned, unsigned, SRA16); -+ ADD_NDS32_BUILTIN2 ("v_sra16", v2hi, v2hi, unsigned, V_SRA16); -+ ADD_NDS32_BUILTIN2 ("sra16_u", unsigned, unsigned, unsigned, SRA16_U); -+ ADD_NDS32_BUILTIN2 ("v_sra16_u", v2hi, v2hi, unsigned, V_SRA16_U); -+ ADD_NDS32_BUILTIN2 ("srl16", unsigned, unsigned, unsigned, SRL16); -+ ADD_NDS32_BUILTIN2 ("v_srl16", u_v2hi, u_v2hi, unsigned, V_SRL16); -+ ADD_NDS32_BUILTIN2 ("srl16_u", unsigned, unsigned, unsigned, SRL16_U); -+ ADD_NDS32_BUILTIN2 ("v_srl16_u", u_v2hi, u_v2hi, unsigned, V_SRL16_U); -+ ADD_NDS32_BUILTIN2 ("sll16", unsigned, unsigned, unsigned, SLL16); -+ ADD_NDS32_BUILTIN2 ("v_sll16", u_v2hi, u_v2hi, unsigned, V_SLL16); -+ ADD_NDS32_BUILTIN2 ("ksll16", unsigned, unsigned, unsigned, KSLL16); -+ ADD_NDS32_BUILTIN2 ("v_ksll16", v2hi, v2hi, unsigned, V_KSLL16); -+ ADD_NDS32_BUILTIN2 ("kslra16", unsigned, unsigned, unsigned, KSLRA16); -+ ADD_NDS32_BUILTIN2 ("v_kslra16", v2hi, v2hi, unsigned, V_KSLRA16); -+ ADD_NDS32_BUILTIN2 ("kslra16_u", unsigned, unsigned, unsigned, KSLRA16_U); -+ ADD_NDS32_BUILTIN2 ("v_kslra16_u", v2hi, v2hi, unsigned, V_KSLRA16_U); -+ -+ /* DSP Extension: 16bit Compare. */ -+ ADD_NDS32_BUILTIN2 ("cmpeq16", unsigned, unsigned, unsigned, CMPEQ16); -+ ADD_NDS32_BUILTIN2 ("v_scmpeq16", u_v2hi, v2hi, v2hi, V_SCMPEQ16); -+ ADD_NDS32_BUILTIN2 ("v_ucmpeq16", u_v2hi, u_v2hi, u_v2hi, V_UCMPEQ16); -+ ADD_NDS32_BUILTIN2 ("scmplt16", unsigned, unsigned, unsigned, SCMPLT16); -+ ADD_NDS32_BUILTIN2 ("v_scmplt16", u_v2hi, v2hi, v2hi, V_SCMPLT16); -+ ADD_NDS32_BUILTIN2 ("scmple16", unsigned, unsigned, unsigned, SCMPLE16); -+ ADD_NDS32_BUILTIN2 ("v_scmple16", u_v2hi, v2hi, v2hi, V_SCMPLE16); -+ ADD_NDS32_BUILTIN2 ("ucmplt16", unsigned, unsigned, unsigned, UCMPLT16); -+ ADD_NDS32_BUILTIN2 ("v_ucmplt16", u_v2hi, u_v2hi, u_v2hi, V_UCMPLT16); -+ ADD_NDS32_BUILTIN2 ("ucmple16", unsigned, unsigned, unsigned, UCMPLE16); -+ ADD_NDS32_BUILTIN2 ("v_ucmple16", u_v2hi, u_v2hi, u_v2hi, V_UCMPLE16); -+ -+ /* DSP Extension: 8bit Compare. */ -+ ADD_NDS32_BUILTIN2 ("cmpeq8", unsigned, unsigned, unsigned, CMPEQ8); -+ ADD_NDS32_BUILTIN2 ("v_scmpeq8", u_v4qi, v4qi, v4qi, V_SCMPEQ8); -+ ADD_NDS32_BUILTIN2 ("v_ucmpeq8", u_v4qi, u_v4qi, u_v4qi, V_UCMPEQ8); -+ ADD_NDS32_BUILTIN2 ("scmplt8", unsigned, unsigned, unsigned, SCMPLT8); -+ ADD_NDS32_BUILTIN2 ("v_scmplt8", u_v4qi, v4qi, v4qi, V_SCMPLT8); -+ ADD_NDS32_BUILTIN2 ("scmple8", unsigned, unsigned, unsigned, SCMPLE8); -+ ADD_NDS32_BUILTIN2 ("v_scmple8", u_v4qi, v4qi, v4qi, V_SCMPLE8); -+ ADD_NDS32_BUILTIN2 ("ucmplt8", unsigned, unsigned, unsigned, UCMPLT8); -+ ADD_NDS32_BUILTIN2 ("v_ucmplt8", u_v4qi, u_v4qi, u_v4qi, V_UCMPLT8); -+ ADD_NDS32_BUILTIN2 ("ucmple8", unsigned, unsigned, unsigned, UCMPLE8); -+ ADD_NDS32_BUILTIN2 ("v_ucmple8", u_v4qi, u_v4qi, u_v4qi, V_UCMPLE8); -+ -+ /* DSP Extension: SIMD 16bit MISC. */ -+ ADD_NDS32_BUILTIN2 ("smin16", unsigned, unsigned, unsigned, SMIN16); -+ ADD_NDS32_BUILTIN2 ("v_smin16", v2hi, v2hi, v2hi, V_SMIN16); -+ ADD_NDS32_BUILTIN2 ("umin16", unsigned, unsigned, unsigned, UMIN16); -+ ADD_NDS32_BUILTIN2 ("v_umin16", u_v2hi, u_v2hi, u_v2hi, V_UMIN16); -+ ADD_NDS32_BUILTIN2 ("smax16", unsigned, unsigned, unsigned, SMAX16); -+ ADD_NDS32_BUILTIN2 ("v_smax16", v2hi, v2hi, v2hi, V_SMAX16); -+ ADD_NDS32_BUILTIN2 ("umax16", unsigned, unsigned, unsigned, UMAX16); -+ ADD_NDS32_BUILTIN2 ("v_umax16", u_v2hi, u_v2hi, u_v2hi, V_UMAX16); -+ ADD_NDS32_BUILTIN2 ("sclip16", unsigned, unsigned, unsigned, SCLIP16); -+ ADD_NDS32_BUILTIN2 ("v_sclip16", v2hi, v2hi, unsigned, V_SCLIP16); -+ ADD_NDS32_BUILTIN2 ("uclip16", unsigned, unsigned, unsigned, UCLIP16); -+ ADD_NDS32_BUILTIN2 ("v_uclip16", v2hi, v2hi, unsigned, V_UCLIP16); -+ ADD_NDS32_BUILTIN2 ("khm16", unsigned, unsigned, unsigned, KHM16); -+ ADD_NDS32_BUILTIN2 ("v_khm16", v2hi, v2hi, v2hi, V_KHM16); -+ ADD_NDS32_BUILTIN2 ("khmx16", unsigned, unsigned, unsigned, KHMX16); -+ ADD_NDS32_BUILTIN2 ("v_khmx16", v2hi, v2hi, v2hi, V_KHMX16); -+ ADD_NDS32_BUILTIN1 ("kabs16", unsigned, unsigned, KABS16); -+ ADD_NDS32_BUILTIN1 ("v_kabs16", v2hi, v2hi, V_KABS16); -+ ADD_NDS32_BUILTIN2 ("smul16", long_long_unsigned, unsigned, unsigned, SMUL16); -+ ADD_NDS32_BUILTIN2 ("v_smul16", v2si, v2hi, v2hi, V_SMUL16); -+ ADD_NDS32_BUILTIN2 ("smulx16", -+ long_long_unsigned, unsigned, unsigned, SMULX16); -+ ADD_NDS32_BUILTIN2 ("v_smulx16", v2si, v2hi, v2hi, V_SMULX16); -+ ADD_NDS32_BUILTIN2 ("umul16", long_long_unsigned, unsigned, unsigned, UMUL16); -+ ADD_NDS32_BUILTIN2 ("v_umul16", u_v2si, u_v2hi, u_v2hi, V_UMUL16); -+ ADD_NDS32_BUILTIN2 ("umulx16", -+ long_long_unsigned, unsigned, unsigned, UMULX16); -+ ADD_NDS32_BUILTIN2 ("v_umulx16", u_v2si, u_v2hi, u_v2hi, V_UMULX16); -+ -+ /* DSP Extension: SIMD 8bit MISC. */ -+ ADD_NDS32_BUILTIN2 ("smin8", unsigned, unsigned, unsigned, SMIN8); -+ ADD_NDS32_BUILTIN2 ("v_smin8", v4qi, v4qi, v4qi, V_SMIN8); -+ ADD_NDS32_BUILTIN2 ("umin8", unsigned, unsigned, unsigned, UMIN8); -+ ADD_NDS32_BUILTIN2 ("v_umin8", u_v4qi, u_v4qi, u_v4qi, V_UMIN8); -+ ADD_NDS32_BUILTIN2 ("smax8", unsigned, unsigned, unsigned, SMAX8); -+ ADD_NDS32_BUILTIN2 ("v_smax8", v4qi, v4qi, v4qi, V_SMAX8); -+ ADD_NDS32_BUILTIN2 ("umax8", unsigned, unsigned, unsigned, UMAX8); -+ ADD_NDS32_BUILTIN2 ("v_umax8", u_v4qi, u_v4qi, u_v4qi, V_UMAX8); -+ ADD_NDS32_BUILTIN1 ("kabs8", unsigned, unsigned, KABS8); -+ ADD_NDS32_BUILTIN1 ("v_kabs8", v4qi, v4qi, V_KABS8); -+ -+ /* DSP Extension: 8bit Unpacking. */ -+ ADD_NDS32_BUILTIN1 ("sunpkd810", unsigned, unsigned, SUNPKD810); -+ ADD_NDS32_BUILTIN1 ("v_sunpkd810", v2hi, v4qi, V_SUNPKD810); -+ ADD_NDS32_BUILTIN1 ("sunpkd820", unsigned, unsigned, SUNPKD820); -+ ADD_NDS32_BUILTIN1 ("v_sunpkd820", v2hi, v4qi, V_SUNPKD820); -+ ADD_NDS32_BUILTIN1 ("sunpkd830", unsigned, unsigned, SUNPKD830); -+ ADD_NDS32_BUILTIN1 ("v_sunpkd830", v2hi, v4qi, V_SUNPKD830); -+ ADD_NDS32_BUILTIN1 ("sunpkd831", unsigned, unsigned, SUNPKD831); -+ ADD_NDS32_BUILTIN1 ("v_sunpkd831", v2hi, v4qi, V_SUNPKD831); -+ ADD_NDS32_BUILTIN1 ("zunpkd810", unsigned, unsigned, ZUNPKD810); -+ ADD_NDS32_BUILTIN1 ("v_zunpkd810", u_v2hi, u_v4qi, V_ZUNPKD810); -+ ADD_NDS32_BUILTIN1 ("zunpkd820", unsigned, unsigned, ZUNPKD820); -+ ADD_NDS32_BUILTIN1 ("v_zunpkd820", u_v2hi, u_v4qi, V_ZUNPKD820); -+ ADD_NDS32_BUILTIN1 ("zunpkd830", unsigned, unsigned, ZUNPKD830); -+ ADD_NDS32_BUILTIN1 ("v_zunpkd830", u_v2hi, u_v4qi, V_ZUNPKD830); -+ ADD_NDS32_BUILTIN1 ("zunpkd831", unsigned, unsigned, ZUNPKD831); -+ ADD_NDS32_BUILTIN1 ("v_zunpkd831", u_v2hi, u_v4qi, V_ZUNPKD831); -+ -+ /* DSP Extension: 32bit Add and Subtract. */ -+ ADD_NDS32_BUILTIN2 ("raddw", integer, integer, integer, RADDW); -+ ADD_NDS32_BUILTIN2 ("uraddw", unsigned, unsigned, unsigned, URADDW); -+ ADD_NDS32_BUILTIN2 ("rsubw", integer, integer, integer, RSUBW); -+ ADD_NDS32_BUILTIN2 ("ursubw", unsigned, unsigned, unsigned, URSUBW); -+ -+ /* DSP Extension: 32bit Shift. */ -+ ADD_NDS32_BUILTIN2 ("sra_u", integer, integer, unsigned, SRA_U); -+ ADD_NDS32_BUILTIN2 ("ksll", integer, integer, unsigned, KSLL); -+ -+ /* DSP Extension: 16bit Packing. */ -+ ADD_NDS32_BUILTIN2 ("pkbb16", unsigned, unsigned, unsigned, PKBB16); -+ ADD_NDS32_BUILTIN2 ("v_pkbb16", u_v2hi, u_v2hi, u_v2hi, V_PKBB16); -+ ADD_NDS32_BUILTIN2 ("pkbt16", unsigned, unsigned, unsigned, PKBT16); -+ ADD_NDS32_BUILTIN2 ("v_pkbt16", u_v2hi, u_v2hi, u_v2hi, V_PKBT16); -+ ADD_NDS32_BUILTIN2 ("pktb16", unsigned, unsigned, unsigned, PKTB16); -+ ADD_NDS32_BUILTIN2 ("v_pktb16", u_v2hi, u_v2hi, u_v2hi, V_PKTB16); -+ ADD_NDS32_BUILTIN2 ("pktt16", unsigned, unsigned, unsigned, PKTT16); -+ ADD_NDS32_BUILTIN2 ("v_pktt16", u_v2hi, u_v2hi, u_v2hi, V_PKTT16); -+ -+ /* DSP Extension: Signed MSW 32x32 Multiply and ADD. */ -+ ADD_NDS32_BUILTIN2 ("smmul", integer, integer, integer, SMMUL); -+ ADD_NDS32_BUILTIN2 ("smmul_u", integer, integer, integer, SMMUL_U); -+ ADD_NDS32_BUILTIN3 ("kmmac", integer, integer, integer, integer, KMMAC); -+ ADD_NDS32_BUILTIN3 ("kmmac_u", integer, integer, integer, integer, KMMAC_U); -+ ADD_NDS32_BUILTIN3 ("kmmsb", integer, integer, integer, integer, KMMSB); -+ ADD_NDS32_BUILTIN3 ("kmmsb_u", integer, integer, integer, integer, KMMSB_U); -+ ADD_NDS32_BUILTIN2 ("kwmmul", integer, integer, integer, KWMMUL); -+ ADD_NDS32_BUILTIN2 ("kwmmul_u", integer, integer, integer, KWMMUL_U); -+ -+ /* DSP Extension: Most Significant Word 32x16 Multiply and ADD. */ -+ ADD_NDS32_BUILTIN2 ("smmwb", integer, integer, unsigned, SMMWB); -+ ADD_NDS32_BUILTIN2 ("v_smmwb", integer, integer, v2hi, V_SMMWB); -+ ADD_NDS32_BUILTIN2 ("smmwb_u", integer, integer, unsigned, SMMWB_U); -+ ADD_NDS32_BUILTIN2 ("v_smmwb_u", integer, integer, v2hi, V_SMMWB_U); -+ ADD_NDS32_BUILTIN2 ("smmwt", integer, integer, unsigned, SMMWT); -+ ADD_NDS32_BUILTIN2 ("v_smmwt", integer, integer, v2hi, V_SMMWT); -+ ADD_NDS32_BUILTIN2 ("smmwt_u", integer, integer, unsigned, SMMWT_U); -+ ADD_NDS32_BUILTIN2 ("v_smmwt_u", integer, integer, v2hi, V_SMMWT_U); -+ ADD_NDS32_BUILTIN3 ("kmmawb", integer, integer, integer, unsigned, KMMAWB); -+ ADD_NDS32_BUILTIN3 ("v_kmmawb", integer, integer, integer, v2hi, V_KMMAWB); -+ ADD_NDS32_BUILTIN3 ("kmmawb_u", -+ integer, integer, integer, unsigned, KMMAWB_U); -+ ADD_NDS32_BUILTIN3 ("v_kmmawb_u", -+ integer, integer, integer, v2hi, V_KMMAWB_U); -+ ADD_NDS32_BUILTIN3 ("kmmawt", integer, integer, integer, unsigned, KMMAWT); -+ ADD_NDS32_BUILTIN3 ("v_kmmawt", integer, integer, integer, v2hi, V_KMMAWT); -+ ADD_NDS32_BUILTIN3 ("kmmawt_u", -+ integer, integer, integer, unsigned, KMMAWT_U); -+ ADD_NDS32_BUILTIN3 ("v_kmmawt_u", -+ integer, integer, integer, v2hi, V_KMMAWT_U); -+ -+ /* DSP Extension: Signed 16bit Multiply with ADD/Subtract. */ -+ ADD_NDS32_BUILTIN2 ("smbb", integer, unsigned, unsigned, SMBB); -+ ADD_NDS32_BUILTIN2 ("v_smbb", integer, v2hi, v2hi, V_SMBB); -+ ADD_NDS32_BUILTIN2 ("smbt", integer, unsigned, unsigned, SMBT); -+ ADD_NDS32_BUILTIN2 ("v_smbt", integer, v2hi, v2hi, V_SMBT); -+ ADD_NDS32_BUILTIN2 ("smtt", integer, unsigned, unsigned, SMTT); -+ ADD_NDS32_BUILTIN2 ("v_smtt", integer, v2hi, v2hi, V_SMTT); -+ ADD_NDS32_BUILTIN2 ("kmda", integer, unsigned, unsigned, KMDA); -+ ADD_NDS32_BUILTIN2 ("v_kmda", integer, v2hi, v2hi, V_KMDA); -+ ADD_NDS32_BUILTIN2 ("kmxda", integer, unsigned, unsigned, KMXDA); -+ ADD_NDS32_BUILTIN2 ("v_kmxda", integer, v2hi, v2hi, V_KMXDA); -+ ADD_NDS32_BUILTIN2 ("smds", integer, unsigned, unsigned, SMDS); -+ ADD_NDS32_BUILTIN2 ("v_smds", integer, v2hi, v2hi, V_SMDS); -+ ADD_NDS32_BUILTIN2 ("smdrs", integer, unsigned, unsigned, SMDRS); -+ ADD_NDS32_BUILTIN2 ("v_smdrs", integer, v2hi, v2hi, V_SMDRS); -+ ADD_NDS32_BUILTIN2 ("smxds", integer, unsigned, unsigned, SMXDS); -+ ADD_NDS32_BUILTIN2 ("v_smxds", integer, v2hi, v2hi, V_SMXDS); -+ ADD_NDS32_BUILTIN3 ("kmabb", integer, integer, unsigned, unsigned, KMABB); -+ ADD_NDS32_BUILTIN3 ("v_kmabb", integer, integer, v2hi, v2hi, V_KMABB); -+ ADD_NDS32_BUILTIN3 ("kmabt", integer, integer, unsigned, unsigned, KMABT); -+ ADD_NDS32_BUILTIN3 ("v_kmabt", integer, integer, v2hi, v2hi, V_KMABT); -+ ADD_NDS32_BUILTIN3 ("kmatt", integer, integer, unsigned, unsigned, KMATT); -+ ADD_NDS32_BUILTIN3 ("v_kmatt", integer, integer, v2hi, v2hi, V_KMATT); -+ ADD_NDS32_BUILTIN3 ("kmada", integer, integer, unsigned, unsigned, KMADA); -+ ADD_NDS32_BUILTIN3 ("v_kmada", integer, integer, v2hi, v2hi, V_KMADA); -+ ADD_NDS32_BUILTIN3 ("kmaxda", integer, integer, unsigned, unsigned, KMAXDA); -+ ADD_NDS32_BUILTIN3 ("v_kmaxda", integer, integer, v2hi, v2hi, V_KMAXDA); -+ ADD_NDS32_BUILTIN3 ("kmads", integer, integer, unsigned, unsigned, KMADS); -+ ADD_NDS32_BUILTIN3 ("v_kmads", integer, integer, v2hi, v2hi, V_KMADS); -+ ADD_NDS32_BUILTIN3 ("kmadrs", integer, integer, unsigned, unsigned, KMADRS); -+ ADD_NDS32_BUILTIN3 ("v_kmadrs", integer, integer, v2hi, v2hi, V_KMADRS); -+ ADD_NDS32_BUILTIN3 ("kmaxds", integer, integer, unsigned, unsigned, KMAXDS); -+ ADD_NDS32_BUILTIN3 ("v_kmaxds", integer, integer, v2hi, v2hi, V_KMAXDS); -+ ADD_NDS32_BUILTIN3 ("kmsda", integer, integer, unsigned, unsigned, KMSDA); -+ ADD_NDS32_BUILTIN3 ("v_kmsda", integer, integer, v2hi, v2hi, V_KMSDA); -+ ADD_NDS32_BUILTIN3 ("kmsxda", integer, integer, unsigned, unsigned, KMSXDA); -+ ADD_NDS32_BUILTIN3 ("v_kmsxda", integer, integer, v2hi, v2hi, V_KMSXDA); -+ -+ /* DSP Extension: Signed 16bit Multiply with 64bit ADD/Subtract. */ -+ ADD_NDS32_BUILTIN2 ("smal", long_long_integer, -+ long_long_integer, unsigned, SMAL); -+ ADD_NDS32_BUILTIN2 ("v_smal", long_long_integer, -+ long_long_integer, v2hi, V_SMAL); -+ -+ /* DSP Extension: 32bit MISC. */ -+ ADD_NDS32_BUILTIN2 ("bitrev", unsigned, unsigned, unsigned, BITREV); -+ ADD_NDS32_BUILTIN2 ("wext", unsigned, long_long_integer, unsigned, WEXT); -+ ADD_NDS32_BUILTIN3 ("bpick", unsigned, unsigned, unsigned, unsigned, BPICK); -+ ADD_NDS32_BUILTIN3 ("insb", unsigned, unsigned, unsigned, unsigned, INSB); -+ -+ /* DSP Extension: 64bit Add and Subtract. */ -+ ADD_NDS32_BUILTIN2 ("sadd64", long_long_integer, -+ long_long_integer, long_long_integer, SADD64); -+ ADD_NDS32_BUILTIN2 ("uadd64", long_long_unsigned, -+ long_long_unsigned, long_long_unsigned, UADD64); -+ ADD_NDS32_BUILTIN2 ("radd64", long_long_integer, -+ long_long_integer, long_long_integer, RADD64); -+ ADD_NDS32_BUILTIN2 ("uradd64", long_long_unsigned, -+ long_long_unsigned, long_long_unsigned, URADD64); -+ ADD_NDS32_BUILTIN2 ("kadd64", long_long_integer, -+ long_long_integer, long_long_integer, KADD64); -+ ADD_NDS32_BUILTIN2 ("ukadd64", long_long_unsigned, -+ long_long_unsigned, long_long_unsigned, UKADD64); -+ ADD_NDS32_BUILTIN2 ("ssub64", long_long_integer, -+ long_long_integer, long_long_integer, SSUB64); -+ ADD_NDS32_BUILTIN2 ("usub64", long_long_unsigned, -+ long_long_unsigned, long_long_unsigned, USUB64); -+ ADD_NDS32_BUILTIN2 ("rsub64", long_long_integer, -+ long_long_integer, long_long_integer, RSUB64); -+ ADD_NDS32_BUILTIN2 ("ursub64", long_long_unsigned, -+ long_long_unsigned, long_long_unsigned, URSUB64); -+ ADD_NDS32_BUILTIN2 ("ksub64", long_long_integer, -+ long_long_integer, long_long_integer, KSUB64); -+ ADD_NDS32_BUILTIN2 ("uksub64", long_long_unsigned, -+ long_long_unsigned, long_long_unsigned, UKSUB64); -+ -+ /* DSP Extension: 32bit Multiply with 64bit Add/Subtract. */ -+ ADD_NDS32_BUILTIN3 ("smar64", long_long_integer, -+ long_long_integer, integer, integer, SMAR64); -+ ADD_NDS32_BUILTIN3 ("smsr64", long_long_integer, -+ long_long_integer, integer, integer, SMSR64); -+ ADD_NDS32_BUILTIN3 ("umar64", long_long_unsigned, -+ long_long_unsigned, unsigned, unsigned, UMAR64); -+ ADD_NDS32_BUILTIN3 ("umsr64", long_long_unsigned, -+ long_long_unsigned, unsigned, unsigned, UMSR64); -+ ADD_NDS32_BUILTIN3 ("kmar64", long_long_integer, -+ long_long_integer, integer, integer, KMAR64); -+ ADD_NDS32_BUILTIN3 ("kmsr64", long_long_integer, -+ long_long_integer, integer, integer, KMSR64); -+ ADD_NDS32_BUILTIN3 ("ukmar64", long_long_unsigned, -+ long_long_unsigned, unsigned, unsigned, UKMAR64); -+ ADD_NDS32_BUILTIN3 ("ukmsr64", long_long_unsigned, -+ long_long_unsigned, unsigned, unsigned, UKMSR64); -+ -+ /* DSP Extension: Signed 16bit Multiply with 64bit Add/Subtract. */ -+ ADD_NDS32_BUILTIN3 ("smalbb", long_long_integer, -+ long_long_integer, unsigned, unsigned, SMALBB); -+ ADD_NDS32_BUILTIN3 ("v_smalbb", long_long_integer, -+ long_long_integer, v2hi, v2hi, V_SMALBB); -+ ADD_NDS32_BUILTIN3 ("smalbt", long_long_integer, -+ long_long_integer, unsigned, unsigned, SMALBT); -+ ADD_NDS32_BUILTIN3 ("v_smalbt", long_long_integer, -+ long_long_integer, v2hi, v2hi, V_SMALBT); -+ ADD_NDS32_BUILTIN3 ("smaltt", long_long_integer, -+ long_long_integer, unsigned, unsigned, SMALTT); -+ ADD_NDS32_BUILTIN3 ("v_smaltt", long_long_integer, -+ long_long_integer, v2hi, v2hi, V_SMALTT); -+ ADD_NDS32_BUILTIN3 ("smalda", long_long_integer, -+ long_long_integer, unsigned, unsigned, SMALDA); -+ ADD_NDS32_BUILTIN3 ("v_smalda", long_long_integer, -+ long_long_integer, v2hi, v2hi, V_SMALDA); -+ ADD_NDS32_BUILTIN3 ("smalxda", long_long_integer, -+ long_long_integer, unsigned, unsigned, SMALXDA); -+ ADD_NDS32_BUILTIN3 ("v_smalxda", long_long_integer, -+ long_long_integer, v2hi, v2hi, V_SMALXDA); -+ ADD_NDS32_BUILTIN3 ("smalds", long_long_integer, -+ long_long_integer, unsigned, unsigned, SMALDS); -+ ADD_NDS32_BUILTIN3 ("v_smalds", long_long_integer, -+ long_long_integer, v2hi, v2hi, V_SMALDS); -+ ADD_NDS32_BUILTIN3 ("smaldrs", long_long_integer, -+ long_long_integer, unsigned, unsigned, SMALDRS); -+ ADD_NDS32_BUILTIN3 ("v_smaldrs", long_long_integer, -+ long_long_integer, v2hi, v2hi, V_SMALDRS); -+ ADD_NDS32_BUILTIN3 ("smalxds", long_long_integer, -+ long_long_integer, unsigned, unsigned, SMALXDS); -+ ADD_NDS32_BUILTIN3 ("v_smalxds", long_long_integer, -+ long_long_integer, v2hi, v2hi, V_SMALXDS); -+ ADD_NDS32_BUILTIN3 ("smslda", long_long_integer, -+ long_long_integer, unsigned, unsigned, SMSLDA); -+ ADD_NDS32_BUILTIN3 ("v_smslda", long_long_integer, -+ long_long_integer, v2hi, v2hi, V_SMSLDA); -+ ADD_NDS32_BUILTIN3 ("smslxda", long_long_integer, -+ long_long_integer, unsigned, unsigned, SMSLXDA); -+ ADD_NDS32_BUILTIN3 ("v_smslxda", long_long_integer, -+ long_long_integer, v2hi, v2hi, V_SMSLXDA); -+ -+ /* DSP Extension: augmented baseline. */ -+ ADD_NDS32_BUILTIN2 ("uclip32", unsigned, integer, unsigned, UCLIP32); -+ ADD_NDS32_BUILTIN2 ("sclip32", integer, integer, unsigned, SCLIP32); -+ ADD_NDS32_BUILTIN1 ("kabs", integer, integer, KABS); -+ -+ /* DSP Extension: vector type unaligned Load/Store */ -+ ADD_NDS32_BUILTIN1 ("get_unaligned_u16x2", u_v2hi, ptr_ushort, UALOAD_U16); -+ ADD_NDS32_BUILTIN1 ("get_unaligned_s16x2", v2hi, ptr_short, UALOAD_S16); -+ ADD_NDS32_BUILTIN1 ("get_unaligned_u8x4", u_v4qi, ptr_uchar, UALOAD_U8); -+ ADD_NDS32_BUILTIN1 ("get_unaligned_s8x4", v4qi, ptr_char, UALOAD_S8); -+ ADD_NDS32_BUILTIN2 ("put_unaligned_u16x2", void, ptr_ushort, -+ u_v2hi, UASTORE_U16); -+ ADD_NDS32_BUILTIN2 ("put_unaligned_s16x2", void, ptr_short, -+ v2hi, UASTORE_S16); -+ ADD_NDS32_BUILTIN2 ("put_unaligned_u8x4", void, ptr_uchar, -+ u_v4qi, UASTORE_U8); -+ ADD_NDS32_BUILTIN2 ("put_unaligned_s8x4", void, ptr_char, -+ v4qi, UASTORE_S8); - } -diff --git a/gcc/config/nds32/nds32-intrinsic.md b/gcc/config/nds32/nds32-intrinsic.md -index 24e7c0bf4a1..c70a6fcc99b 100644 ---- a/gcc/config/nds32/nds32-intrinsic.md -+++ b/gcc/config/nds32/nds32-intrinsic.md -@@ -1037,6 +1037,187 @@ - (set_attr "length" "4")] - ) - -+;; SATURATION -+ -+(define_insn "unspec_kaddw" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_plus:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")))] -+ "" -+ "kaddw\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_ksubw" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_minus:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")))] -+ "" -+ "ksubw\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_kaddh" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] UNSPEC_KADDH))] -+ "" -+ "kaddh\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_ksubh" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSUBH))] -+ "" -+ "ksubh\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_kaddh_dsp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")) -+ (const_int 15)] UNSPEC_CLIPS))] -+ "NDS32_EXT_DSP_P ()" -+ "kaddh\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_ksubh_dsp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(minus:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")) -+ (const_int 15)] UNSPEC_CLIPS))] -+ "NDS32_EXT_DSP_P ()" -+ "ksubh\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_kdmbb" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") -+ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMBB))] -+ "" -+ "kdmbb\t%0, %1, %2" -+ [(set_attr "type" "mul") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_kdmbt" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") -+ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMBT))] -+ "" -+ "kdmbt\t%0, %1, %2" -+ [(set_attr "type" "mul") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_kdmtb" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") -+ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMTB))] -+ "" -+ "kdmtb\t%0, %1, %2" -+ [(set_attr "type" "mul") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_kdmtt" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") -+ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMTT))] -+ "" -+ "kdmtt\t%0, %1, %2" -+ [(set_attr "type" "mul") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_khmbb" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") -+ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMBB))] -+ "" -+ "khmbb\t%0, %1, %2" -+ [(set_attr "type" "mul") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_khmbt" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") -+ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMBT))] -+ "" -+ "khmbt\t%0, %1, %2" -+ [(set_attr "type" "mul") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_khmtb" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") -+ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMTB))] -+ "" -+ "khmtb\t%0, %1, %2" -+ [(set_attr "type" "mul") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_khmtt" -+ [(set (match_operand:V2HI 0 "register_operand" "=r") -+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") -+ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMTT))] -+ "" -+ "khmtt\t%0, %1, %2" -+ [(set_attr "type" "mul") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_kslraw" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSLRAW))] -+ "" -+ "kslraw\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_kslrawu" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSLRAWU))] -+ "" -+ "kslraw.u\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_volatile_rdov" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_RDOV))] -+ "" -+ "rdov\t%0" -+ [(set_attr "type" "misc") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_volatile_clrov" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CLROV)] -+ "" -+ "clrov" -+ [(set_attr "type" "misc") -+ (set_attr "length" "4")] -+) -+ - ;; System - - (define_insn "unspec_sva" -@@ -1415,22 +1596,17 @@ - if (TARGET_ISA_V3M) - nds32_expand_unaligned_store (operands, DImode); - else -- emit_insn (gen_unaligned_store_dw (operands[0], operands[1])); -+ emit_insn (gen_unaligned_store_dw (gen_rtx_MEM (DImode, operands[0]), -+ operands[1])); - DONE; - }) - - (define_insn "unaligned_store_dw" -- [(set (mem:DI (match_operand:SI 0 "register_operand" "r")) -- (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_UASTORE_DW))] -+ [(set (match_operand:DI 0 "nds32_lmw_smw_base_operand" "=Umw") -+ (unspec:DI [(match_operand:DI 1 "register_operand" " r")] UNSPEC_UASTORE_DW))] - "" - { -- rtx otherops[3]; -- otherops[0] = gen_rtx_REG (SImode, REGNO (operands[1])); -- otherops[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); -- otherops[2] = operands[0]; -- -- output_asm_insn ("smw.bi\t%0, [%2], %1, 0", otherops); -- return ""; -+ return nds32_output_smw_double_word (operands); - } - [(set_attr "type" "store") - (set_attr "length" "4")] -@@ -1495,4 +1671,15 @@ - DONE; - }) - -+;; abs alias kabs -+ -+(define_insn "unspec_kabs" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_KABS))] -+ "" -+ "kabs\t%0, %1" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ - ;; ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/nds32-isr.c b/gcc/config/nds32/nds32-isr.c -index 2c3aac7a256..db67a0e3666 100644 ---- a/gcc/config/nds32/nds32-isr.c -+++ b/gcc/config/nds32/nds32-isr.c -@@ -43,7 +43,260 @@ - We use an array to record essential information for each vector. */ - static struct nds32_isr_info nds32_isr_vectors[NDS32_N_ISR_VECTORS]; - --/* ------------------------------------------------------------------------ */ -+/* ------------------------------------------------------------- */ -+/* FIXME: -+ FOR BACKWARD COMPATIBILITY, we need to support following patterns: -+ -+ __attribute__((interrupt("XXX;YYY;id=ZZZ"))) -+ __attribute__((exception("XXX;YYY;id=ZZZ"))) -+ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ"))) -+ -+ We provide several functions to parse the strings. */ -+ -+static void -+nds32_interrupt_attribute_parse_string (const char *original_str, -+ const char *func_name, -+ unsigned int s_level) -+{ -+ char target_str[100]; -+ enum nds32_isr_save_reg save_reg; -+ enum nds32_isr_nested_type nested_type; -+ -+ char *save_all_regs_str, *save_caller_regs_str; -+ char *nested_str, *not_nested_str, *ready_nested_str, *critical_str; -+ char *id_str, *value_str; -+ -+ /* Copy original string into a character array so that -+ the string APIs can handle it. */ -+ strcpy (target_str, original_str); -+ -+ /* 1. Detect 'save_all_regs' : NDS32_SAVE_ALL -+ 'save_caller_regs' : NDS32_PARTIAL_SAVE */ -+ save_all_regs_str = strstr (target_str, "save_all_regs"); -+ save_caller_regs_str = strstr (target_str, "save_caller_regs"); -+ -+ /* Note that if no argument is found, -+ use NDS32_PARTIAL_SAVE by default. */ -+ if (save_all_regs_str) -+ save_reg = NDS32_SAVE_ALL; -+ else if (save_caller_regs_str) -+ save_reg = NDS32_PARTIAL_SAVE; -+ else -+ save_reg = NDS32_PARTIAL_SAVE; -+ -+ /* 2. Detect 'nested' : NDS32_NESTED -+ 'not_nested' : NDS32_NOT_NESTED -+ 'ready_nested' : NDS32_NESTED_READY -+ 'critical' : NDS32_CRITICAL */ -+ nested_str = strstr (target_str, "nested"); -+ not_nested_str = strstr (target_str, "not_nested"); -+ ready_nested_str = strstr (target_str, "ready_nested"); -+ critical_str = strstr (target_str, "critical"); -+ -+ /* Note that if no argument is found, -+ use NDS32_NOT_NESTED by default. -+ Also, since 'not_nested' and 'ready_nested' both contains -+ 'nested' string, we check 'nested' with lowest priority. */ -+ if (not_nested_str) -+ nested_type = NDS32_NOT_NESTED; -+ else if (ready_nested_str) -+ nested_type = NDS32_NESTED_READY; -+ else if (nested_str) -+ nested_type = NDS32_NESTED; -+ else if (critical_str) -+ nested_type = NDS32_CRITICAL; -+ else -+ nested_type = NDS32_NOT_NESTED; -+ -+ /* 3. Traverse each id value and set corresponding information. */ -+ id_str = strstr (target_str, "id="); -+ -+ /* If user forgets to assign 'id', issue an error message. */ -+ if (id_str == NULL) -+ error ("require id argument in the string"); -+ /* Extract the value_str first. */ -+ id_str = strtok (id_str, "="); -+ value_str = strtok (NULL, ";"); -+ -+ /* Pick up the first id value token. */ -+ value_str = strtok (value_str, ","); -+ while (value_str != NULL) -+ { -+ int i; -+ i = atoi (value_str); -+ -+ /* For interrupt(0..63), the actual vector number is (9..72). */ -+ i = i + 9; -+ if (i < 9 || i > 72) -+ error ("invalid id value for interrupt attribute"); -+ -+ /* Setup nds32_isr_vectors[] array. */ -+ nds32_isr_vectors[i].category = NDS32_ISR_INTERRUPT; -+ strcpy (nds32_isr_vectors[i].func_name, func_name); -+ nds32_isr_vectors[i].save_reg = save_reg; -+ nds32_isr_vectors[i].nested_type = nested_type; -+ nds32_isr_vectors[i].security_level = s_level; -+ -+ /* Fetch next token. */ -+ value_str = strtok (NULL, ","); -+ } -+ -+ return; -+} -+ -+static void -+nds32_exception_attribute_parse_string (const char *original_str, -+ const char *func_name, -+ unsigned int s_level) -+{ -+ char target_str[100]; -+ enum nds32_isr_save_reg save_reg; -+ enum nds32_isr_nested_type nested_type; -+ -+ char *save_all_regs_str, *save_caller_regs_str; -+ char *nested_str, *not_nested_str, *ready_nested_str, *critical_str; -+ char *id_str, *value_str; -+ -+ /* Copy original string into a character array so that -+ the string APIs can handle it. */ -+ strcpy (target_str, original_str); -+ -+ /* 1. Detect 'save_all_regs' : NDS32_SAVE_ALL -+ 'save_caller_regs' : NDS32_PARTIAL_SAVE */ -+ save_all_regs_str = strstr (target_str, "save_all_regs"); -+ save_caller_regs_str = strstr (target_str, "save_caller_regs"); -+ -+ /* Note that if no argument is found, -+ use NDS32_PARTIAL_SAVE by default. */ -+ if (save_all_regs_str) -+ save_reg = NDS32_SAVE_ALL; -+ else if (save_caller_regs_str) -+ save_reg = NDS32_PARTIAL_SAVE; -+ else -+ save_reg = NDS32_PARTIAL_SAVE; -+ -+ /* 2. Detect 'nested' : NDS32_NESTED -+ 'not_nested' : NDS32_NOT_NESTED -+ 'ready_nested' : NDS32_NESTED_READY -+ 'critical' : NDS32_CRITICAL */ -+ nested_str = strstr (target_str, "nested"); -+ not_nested_str = strstr (target_str, "not_nested"); -+ ready_nested_str = strstr (target_str, "ready_nested"); -+ critical_str = strstr (target_str, "critical"); -+ -+ /* Note that if no argument is found, -+ use NDS32_NOT_NESTED by default. -+ Also, since 'not_nested' and 'ready_nested' both contains -+ 'nested' string, we check 'nested' with lowest priority. */ -+ if (not_nested_str) -+ nested_type = NDS32_NOT_NESTED; -+ else if (ready_nested_str) -+ nested_type = NDS32_NESTED_READY; -+ else if (nested_str) -+ nested_type = NDS32_NESTED; -+ else if (critical_str) -+ nested_type = NDS32_CRITICAL; -+ else -+ nested_type = NDS32_NOT_NESTED; -+ -+ /* 3. Traverse each id value and set corresponding information. */ -+ id_str = strstr (target_str, "id="); -+ -+ /* If user forgets to assign 'id', issue an error message. */ -+ if (id_str == NULL) -+ error ("require id argument in the string"); -+ /* Extract the value_str first. */ -+ id_str = strtok (id_str, "="); -+ value_str = strtok (NULL, ";"); -+ -+ /* Pick up the first id value token. */ -+ value_str = strtok (value_str, ","); -+ while (value_str != NULL) -+ { -+ int i; -+ i = atoi (value_str); -+ -+ /* For exception(1..8), the actual vector number is (1..8). */ -+ if (i < 1 || i > 8) -+ error ("invalid id value for exception attribute"); -+ -+ /* Setup nds32_isr_vectors[] array. */ -+ nds32_isr_vectors[i].category = NDS32_ISR_EXCEPTION; -+ strcpy (nds32_isr_vectors[i].func_name, func_name); -+ nds32_isr_vectors[i].save_reg = save_reg; -+ nds32_isr_vectors[i].nested_type = nested_type; -+ nds32_isr_vectors[i].security_level = s_level; -+ -+ /* Fetch next token. */ -+ value_str = strtok (NULL, ","); -+ } -+ -+ return; -+} -+ -+static void -+nds32_reset_attribute_parse_string (const char *original_str, -+ const char *func_name) -+{ -+ char target_str[100]; -+ char *vectors_str, *nmi_str, *warm_str, *value_str; -+ -+ /* Deal with reset attribute. Its vector number is always 0. */ -+ nds32_isr_vectors[0].category = NDS32_ISR_RESET; -+ -+ -+ /* 1. Parse 'vectors=XXXX'. */ -+ -+ /* Copy original string into a character array so that -+ the string APIs can handle it. */ -+ strcpy (target_str, original_str); -+ vectors_str = strstr (target_str, "vectors="); -+ /* The total vectors = interrupt + exception numbers + reset. -+ There are 8 exception and 1 reset in nds32 architecture. -+ If user forgets to assign 'vectors', user default 16 interrupts. */ -+ if (vectors_str != NULL) -+ { -+ /* Extract the value_str. */ -+ vectors_str = strtok (vectors_str, "="); -+ value_str = strtok (NULL, ";"); -+ nds32_isr_vectors[0].total_n_vectors = atoi (value_str) + 8 + 1; -+ } -+ else -+ nds32_isr_vectors[0].total_n_vectors = 16 + 8 + 1; -+ strcpy (nds32_isr_vectors[0].func_name, func_name); -+ -+ -+ /* 2. Parse 'nmi_func=YYYY'. */ -+ -+ /* Copy original string into a character array so that -+ the string APIs can handle it. */ -+ strcpy (target_str, original_str); -+ nmi_str = strstr (target_str, "nmi_func="); -+ if (nmi_str != NULL) -+ { -+ /* Extract the value_str. */ -+ nmi_str = strtok (nmi_str, "="); -+ value_str = strtok (NULL, ";"); -+ strcpy (nds32_isr_vectors[0].nmi_name, value_str); -+ } -+ -+ /* 3. Parse 'warm_func=ZZZZ'. */ -+ -+ /* Copy original string into a character array so that -+ the string APIs can handle it. */ -+ strcpy (target_str, original_str); -+ warm_str = strstr (target_str, "warm_func="); -+ if (warm_str != NULL) -+ { -+ /* Extract the value_str. */ -+ warm_str = strtok (warm_str, "="); -+ value_str = strtok (NULL, ";"); -+ strcpy (nds32_isr_vectors[0].warm_name, value_str); -+ } -+ -+ return; -+} -+/* ------------------------------------------------------------- */ - - /* A helper function to emit section head template. */ - static void -@@ -79,6 +332,15 @@ nds32_emit_isr_jmptbl_section (int vector_id) - char section_name[100]; - char symbol_name[100]; - -+ /* A critical isr does not need jump table section because -+ its behavior is not performed by two-level handler. */ -+ if (nds32_isr_vectors[vector_id].nested_type == NDS32_CRITICAL) -+ { -+ fprintf (asm_out_file, "\t! The vector %02d is a critical isr !\n", -+ vector_id); -+ return; -+ } -+ - /* Prepare jmptbl section and symbol name. */ - snprintf (section_name, sizeof (section_name), - ".nds32_jmptbl.%02d", vector_id); -@@ -99,7 +361,6 @@ nds32_emit_isr_vector_section (int vector_id) - const char *c_str = "CATEGORY"; - const char *sr_str = "SR"; - const char *nt_str = "NT"; -- const char *vs_str = "VS"; - char first_level_handler_name[100]; - char section_name[100]; - char symbol_name[100]; -@@ -147,30 +408,47 @@ nds32_emit_isr_vector_section (int vector_id) - case NDS32_NESTED_READY: - nt_str = "nr"; - break; -+ case NDS32_CRITICAL: -+ /* The critical isr is not performed by two-level handler. */ -+ nt_str = ""; -+ break; - } - -- /* Currently we have 4-byte or 16-byte size for each vector. -- If it is 4-byte, the first level handler name has suffix string "_4b". */ -- vs_str = (nds32_isr_vector_size == 4) ? "_4b" : ""; -- - /* Now we can create first level handler name. */ -- snprintf (first_level_handler_name, sizeof (first_level_handler_name), -- "_nds32_%s_%s_%s%s", c_str, sr_str, nt_str, vs_str); -+ if (nds32_isr_vectors[vector_id].security_level == 0) -+ { -+ /* For security level 0, use normal first level handler name. */ -+ snprintf (first_level_handler_name, sizeof (first_level_handler_name), -+ "_nds32_%s_%s_%s", c_str, sr_str, nt_str); -+ } -+ else -+ { -+ /* For security level 1-3, use corresponding spl_1, spl_2, or spl_3. */ -+ snprintf (first_level_handler_name, sizeof (first_level_handler_name), -+ "_nds32_spl_%d", nds32_isr_vectors[vector_id].security_level); -+ } - - /* Prepare vector section and symbol name. */ - snprintf (section_name, sizeof (section_name), - ".nds32_vector.%02d", vector_id); - snprintf (symbol_name, sizeof (symbol_name), -- "_nds32_vector_%02d%s", vector_id, vs_str); -+ "_nds32_vector_%02d", vector_id); - - - /* Everything is ready. We can start emit vector section content. */ - nds32_emit_section_head_template (section_name, symbol_name, - floor_log2 (nds32_isr_vector_size), false); - -- /* According to the vector size, the instructions in the -- vector section may be different. */ -- if (nds32_isr_vector_size == 4) -+ /* First we check if it is a critical isr. -+ If so, jump to user handler directly; otherwise, the instructions -+ in the vector section may be different according to the vector size. */ -+ if (nds32_isr_vectors[vector_id].nested_type == NDS32_CRITICAL) -+ { -+ /* This block is for critical isr. Jump to user handler directly. */ -+ fprintf (asm_out_file, "\tj\t%s ! jump to user handler directly\n", -+ nds32_isr_vectors[vector_id].func_name); -+ } -+ else if (nds32_isr_vector_size == 4) - { - /* This block is for 4-byte vector size. - Hardware $VID support is necessary and only one instruction -@@ -239,13 +517,11 @@ nds32_emit_isr_reset_content (void) - { - unsigned int i; - unsigned int total_n_vectors; -- const char *vs_str; - char reset_handler_name[100]; - char section_name[100]; - char symbol_name[100]; - - total_n_vectors = nds32_isr_vectors[0].total_n_vectors; -- vs_str = (nds32_isr_vector_size == 4) ? "_4b" : ""; - - fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - BEGIN !\n"); - -@@ -261,7 +537,7 @@ nds32_emit_isr_reset_content (void) - /* Emit vector references. */ - fprintf (asm_out_file, "\t ! references to vector section entries\n"); - for (i = 0; i < total_n_vectors; i++) -- fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d%s\n", i, vs_str); -+ fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d\n", i); - - /* Emit jmptbl_00 section. */ - snprintf (section_name, sizeof (section_name), ".nds32_jmptbl.00"); -@@ -275,9 +551,9 @@ nds32_emit_isr_reset_content (void) - - /* Emit vector_00 section. */ - snprintf (section_name, sizeof (section_name), ".nds32_vector.00"); -- snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00%s", vs_str); -+ snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00"); - snprintf (reset_handler_name, sizeof (reset_handler_name), -- "_nds32_reset%s", vs_str); -+ "_nds32_reset"); - - fprintf (asm_out_file, "\t! ....................................\n"); - nds32_emit_section_head_template (section_name, symbol_name, -@@ -323,12 +599,12 @@ void - nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs) - { - int save_all_p, partial_save_p; -- int nested_p, not_nested_p, nested_ready_p; -+ int nested_p, not_nested_p, nested_ready_p, critical_p; - int intr_p, excp_p, reset_p; - - /* Initialize variables. */ - save_all_p = partial_save_p = 0; -- nested_p = not_nested_p = nested_ready_p = 0; -+ nested_p = not_nested_p = nested_ready_p = critical_p = 0; - intr_p = excp_p = reset_p = 0; - - /* We must check at MOST one attribute to set save-reg. */ -@@ -347,8 +623,10 @@ nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs) - not_nested_p = 1; - if (lookup_attribute ("nested_ready", func_attrs)) - nested_ready_p = 1; -+ if (lookup_attribute ("critical", func_attrs)) -+ critical_p = 1; - -- if ((nested_p + not_nested_p + nested_ready_p) > 1) -+ if ((nested_p + not_nested_p + nested_ready_p + critical_p) > 1) - error ("multiple nested types attributes to function %qD", func_decl); - - /* We must check at MOST one attribute to -@@ -362,6 +640,17 @@ nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs) - - if ((intr_p + excp_p + reset_p) > 1) - error ("multiple interrupt attributes to function %qD", func_decl); -+ -+ /* Do not allow isr attributes under linux toolchain. */ -+ if (TARGET_LINUX_ABI && intr_p) -+ error ("cannot use interrupt attributes to function %qD " -+ "under linux toolchain", func_decl); -+ if (TARGET_LINUX_ABI && excp_p) -+ error ("cannot use exception attributes to function %qD " -+ "under linux toolchain", func_decl); -+ if (TARGET_LINUX_ABI && reset_p) -+ error ("cannot use reset attributes to function %qD " -+ "under linux toolchain", func_decl); - } - - /* Function to construct isr vectors information array. -@@ -373,15 +662,21 @@ nds32_construct_isr_vectors_information (tree func_attrs, - const char *func_name) - { - tree save_all, partial_save; -- tree nested, not_nested, nested_ready; -+ tree nested, not_nested, nested_ready, critical; - tree intr, excp, reset; - -+ tree secure; -+ tree security_level_list; -+ tree security_level; -+ unsigned int s_level; -+ - save_all = lookup_attribute ("save_all", func_attrs); - partial_save = lookup_attribute ("partial_save", func_attrs); - - nested = lookup_attribute ("nested", func_attrs); - not_nested = lookup_attribute ("not_nested", func_attrs); - nested_ready = lookup_attribute ("nested_ready", func_attrs); -+ critical = lookup_attribute ("critical", func_attrs); - - intr = lookup_attribute ("interrupt", func_attrs); - excp = lookup_attribute ("exception", func_attrs); -@@ -391,6 +686,63 @@ nds32_construct_isr_vectors_information (tree func_attrs, - if (!intr && !excp && !reset) - return; - -+ /* At first, we need to retrieve security level. */ -+ secure = lookup_attribute ("secure", func_attrs); -+ if (secure != NULL) -+ { -+ security_level_list = TREE_VALUE (secure); -+ security_level = TREE_VALUE (security_level_list); -+ s_level = TREE_INT_CST_LOW (security_level); -+ } -+ else -+ { -+ /* If there is no secure attribute, the security level is set by -+ nds32_isr_secure_level, which is controlled by -misr-secure=X option. -+ By default nds32_isr_secure_level should be 0. */ -+ s_level = nds32_isr_secure_level; -+ } -+ -+ /* ------------------------------------------------------------- */ -+ /* FIXME: -+ FOR BACKWARD COMPATIBILITY, we need to support following patterns: -+ -+ __attribute__((interrupt("XXX;YYY;id=ZZZ"))) -+ __attribute__((exception("XXX;YYY;id=ZZZ"))) -+ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ"))) -+ -+ If interrupt/exception/reset appears and its argument is a -+ STRING_CST, we will parse string with some auxiliary functions -+ which set necessary isr information in the nds32_isr_vectors[] array. -+ After that, we can return immediately to avoid new-syntax isr -+ information construction. */ -+ if (intr != NULL_TREE -+ && TREE_CODE (TREE_VALUE (TREE_VALUE (intr))) == STRING_CST) -+ { -+ tree string_arg = TREE_VALUE (TREE_VALUE (intr)); -+ nds32_interrupt_attribute_parse_string (TREE_STRING_POINTER (string_arg), -+ func_name, -+ s_level); -+ return; -+ } -+ if (excp != NULL_TREE -+ && TREE_CODE (TREE_VALUE (TREE_VALUE (excp))) == STRING_CST) -+ { -+ tree string_arg = TREE_VALUE (TREE_VALUE (excp)); -+ nds32_exception_attribute_parse_string (TREE_STRING_POINTER (string_arg), -+ func_name, -+ s_level); -+ return; -+ } -+ if (reset != NULL_TREE -+ && TREE_CODE (TREE_VALUE (TREE_VALUE (reset))) == STRING_CST) -+ { -+ tree string_arg = TREE_VALUE (TREE_VALUE (reset)); -+ nds32_reset_attribute_parse_string (TREE_STRING_POINTER (string_arg), -+ func_name); -+ return; -+ } -+ /* ------------------------------------------------------------- */ -+ - /* If we are here, either we have interrupt/exception, - or reset attribute. */ - if (intr || excp) -@@ -417,6 +769,9 @@ nds32_construct_isr_vectors_information (tree func_attrs, - /* Add vector_number_offset to get actual vector number. */ - vector_id = TREE_INT_CST_LOW (id) + vector_number_offset; - -+ /* Set security level. */ -+ nds32_isr_vectors[vector_id].security_level = s_level; -+ - /* Enable corresponding vector and set function name. */ - nds32_isr_vectors[vector_id].category = (intr) - ? (NDS32_ISR_INTERRUPT) -@@ -436,6 +791,8 @@ nds32_construct_isr_vectors_information (tree func_attrs, - nds32_isr_vectors[vector_id].nested_type = NDS32_NOT_NESTED; - else if (nested_ready) - nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED_READY; -+ else if (critical) -+ nds32_isr_vectors[vector_id].nested_type = NDS32_CRITICAL; - - /* Advance to next id. */ - id_list = TREE_CHAIN (id_list); -@@ -492,7 +849,6 @@ nds32_construct_isr_vectors_information (tree func_attrs, - } - } - --/* A helper function to handle isr stuff at the beginning of asm file. */ - void - nds32_asm_file_start_for_isr (void) - { -@@ -505,15 +861,14 @@ nds32_asm_file_start_for_isr (void) - strcpy (nds32_isr_vectors[i].func_name, ""); - nds32_isr_vectors[i].save_reg = NDS32_PARTIAL_SAVE; - nds32_isr_vectors[i].nested_type = NDS32_NOT_NESTED; -+ nds32_isr_vectors[i].security_level = 0; - nds32_isr_vectors[i].total_n_vectors = 0; - strcpy (nds32_isr_vectors[i].nmi_name, ""); - strcpy (nds32_isr_vectors[i].warm_name, ""); - } - } - --/* A helper function to handle isr stuff at the end of asm file. */ --void --nds32_asm_file_end_for_isr (void) -+void nds32_asm_file_end_for_isr (void) - { - int i; - -@@ -547,6 +902,8 @@ nds32_asm_file_end_for_isr (void) - /* Found one vector which is interupt or exception. - Output its jmptbl and vector section content. */ - fprintf (asm_out_file, "\t! interrupt/exception vector %02d\n", i); -+ fprintf (asm_out_file, "\t! security level: %d\n", -+ nds32_isr_vectors[i].security_level); - fprintf (asm_out_file, "\t! ------------------------------------\n"); - nds32_emit_isr_jmptbl_section (i); - fprintf (asm_out_file, "\t! ....................................\n"); -@@ -580,4 +937,65 @@ nds32_isr_function_p (tree func) - || (t_reset != NULL_TREE)); - } - --/* ------------------------------------------------------------------------ */ -+/* Return true if FUNC is a isr function with critical attribute. */ -+bool -+nds32_isr_function_critical_p (tree func) -+{ -+ tree t_intr; -+ tree t_excp; -+ tree t_critical; -+ -+ tree attrs; -+ -+ if (TREE_CODE (func) != FUNCTION_DECL) -+ abort (); -+ -+ attrs = DECL_ATTRIBUTES (func); -+ -+ t_intr = lookup_attribute ("interrupt", attrs); -+ t_excp = lookup_attribute ("exception", attrs); -+ -+ t_critical = lookup_attribute ("critical", attrs); -+ -+ /* If both interrupt and exception attribute does not appear, -+ we can return false immediately. */ -+ if ((t_intr == NULL_TREE) && (t_excp == NULL_TREE)) -+ return false; -+ -+ /* Here we can guarantee either interrupt or ecxception attribute -+ does exist, so further check critical attribute. -+ If it also appears, we can return true. */ -+ if (t_critical != NULL_TREE) -+ return true; -+ -+ /* ------------------------------------------------------------- */ -+ /* FIXME: -+ FOR BACKWARD COMPATIBILITY, we need to handle string type. -+ If the string 'critical' appears in the interrupt/exception -+ string argument, we can return true. */ -+ if (t_intr != NULL_TREE || t_excp != NULL_TREE) -+ { -+ char target_str[100]; -+ char *critical_str; -+ tree t_check; -+ tree string_arg; -+ -+ t_check = t_intr ? t_intr : t_excp; -+ if (TREE_CODE (TREE_VALUE (TREE_VALUE (t_check))) == STRING_CST) -+ { -+ string_arg = TREE_VALUE (TREE_VALUE (t_check)); -+ strcpy (target_str, TREE_STRING_POINTER (string_arg)); -+ critical_str = strstr (target_str, "critical"); -+ -+ /* Found 'critical' string, so return true. */ -+ if (critical_str) -+ return true; -+ } -+ } -+ /* ------------------------------------------------------------- */ -+ -+ /* Other cases, this isr function is not critical type. */ -+ return false; -+} -+ -+/* ------------------------------------------------------------- */ -diff --git a/gcc/config/nds32/nds32-linux.opt b/gcc/config/nds32/nds32-linux.opt -new file mode 100644 -index 00000000000..75ccd7625a2 ---- /dev/null -+++ b/gcc/config/nds32/nds32-linux.opt -@@ -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) -diff --git a/gcc/config/nds32/nds32-md-auxiliary.c b/gcc/config/nds32/nds32-md-auxiliary.c -index 720e85a20eb..f157dce3366 100644 ---- a/gcc/config/nds32/nds32-md-auxiliary.c -+++ b/gcc/config/nds32/nds32-md-auxiliary.c -@@ -39,6 +39,9 @@ - #include "expr.h" - #include "emit-rtl.h" - #include "explow.h" -+#include "stringpool.h" -+#include "attribs.h" -+ - - /* ------------------------------------------------------------------------ */ - -@@ -261,6 +264,118 @@ output_cond_branch_compare_zero (int code, const char *suffix, - output_asm_insn (pattern, operands); - } - -+static void -+nds32_split_shiftrtdi3 (rtx dst, rtx src, rtx shiftamount, bool logic_shift_p) -+{ -+ rtx src_high_part; -+ rtx dst_high_part, dst_low_part; -+ -+ dst_high_part = nds32_di_high_part_subreg (dst); -+ src_high_part = nds32_di_high_part_subreg (src); -+ dst_low_part = nds32_di_low_part_subreg (dst); -+ -+ if (CONST_INT_P (shiftamount)) -+ { -+ if (INTVAL (shiftamount) < 32) -+ { -+ if (logic_shift_p) -+ { -+ emit_insn (gen_uwext (dst_low_part, src, -+ shiftamount)); -+ emit_insn (gen_lshrsi3 (dst_high_part, src_high_part, -+ shiftamount)); -+ } -+ else -+ { -+ emit_insn (gen_wext (dst_low_part, src, -+ shiftamount)); -+ emit_insn (gen_ashrsi3 (dst_high_part, src_high_part, -+ shiftamount)); -+ } -+ } -+ else -+ { -+ rtx new_shift_amout = gen_int_mode(INTVAL (shiftamount) - 32, SImode); -+ -+ if (logic_shift_p) -+ { -+ emit_insn (gen_lshrsi3 (dst_low_part, src_high_part, -+ new_shift_amout)); -+ emit_move_insn (dst_high_part, const0_rtx); -+ } -+ else -+ { -+ emit_insn (gen_ashrsi3 (dst_low_part, src_high_part, -+ new_shift_amout)); -+ emit_insn (gen_ashrsi3 (dst_high_part, src_high_part, -+ GEN_INT (31))); -+ } -+ } -+ } -+ else -+ { -+ rtx dst_low_part_l32, dst_high_part_l32; -+ rtx dst_low_part_g32, dst_high_part_g32; -+ rtx new_shift_amout, select_reg; -+ dst_low_part_l32 = gen_reg_rtx (SImode); -+ dst_high_part_l32 = gen_reg_rtx (SImode); -+ dst_low_part_g32 = gen_reg_rtx (SImode); -+ dst_high_part_g32 = gen_reg_rtx (SImode); -+ new_shift_amout = gen_reg_rtx (SImode); -+ select_reg = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_andsi3 (shiftamount, shiftamount, GEN_INT (0x3f))); -+ -+ if (logic_shift_p) -+ { -+ /* -+ if (shiftamount < 32) -+ dst_low_part = wext (src, shiftamount) -+ dst_high_part = src_high_part >> shiftamount -+ else -+ dst_low_part = src_high_part >> (shiftamount & 0x1f) -+ dst_high_part = 0 -+ */ -+ emit_insn (gen_uwext (dst_low_part_l32, src, shiftamount)); -+ emit_insn (gen_lshrsi3 (dst_high_part_l32, src_high_part, -+ shiftamount)); -+ -+ emit_insn (gen_andsi3 (new_shift_amout, shiftamount, GEN_INT (0x1f))); -+ emit_insn (gen_lshrsi3 (dst_low_part_g32, src_high_part, -+ new_shift_amout)); -+ emit_move_insn (dst_high_part_g32, const0_rtx); -+ } -+ else -+ { -+ /* -+ if (shiftamount < 32) -+ dst_low_part = wext (src, shiftamount) -+ dst_high_part = src_high_part >> shiftamount -+ else -+ dst_low_part = src_high_part >> (shiftamount & 0x1f) -+ # shift 31 for sign extend -+ dst_high_part = src_high_part >> 31 -+ */ -+ emit_insn (gen_wext (dst_low_part_l32, src, shiftamount)); -+ emit_insn (gen_ashrsi3 (dst_high_part_l32, src_high_part, -+ shiftamount)); -+ -+ emit_insn (gen_andsi3 (new_shift_amout, shiftamount, GEN_INT (0x1f))); -+ emit_insn (gen_ashrsi3 (dst_low_part_g32, src_high_part, -+ new_shift_amout)); -+ emit_insn (gen_ashrsi3 (dst_high_part_g32, src_high_part, -+ GEN_INT (31))); -+ } -+ -+ emit_insn (gen_slt_compare (select_reg, shiftamount, GEN_INT (32))); -+ -+ emit_insn (gen_cmovnsi (dst_low_part, select_reg, -+ dst_low_part_l32, dst_low_part_g32)); -+ emit_insn (gen_cmovnsi (dst_high_part, select_reg, -+ dst_high_part_l32, dst_high_part_g32)); -+ } -+} -+ - /* ------------------------------------------------------------------------ */ - - /* Auxiliary function for expand RTL pattern. */ -@@ -1195,8 +1310,166 @@ nds32_emit_v3pop_fpr_callee_saved (int base) - } - } - -+enum nds32_expand_result_type -+nds32_expand_extv (rtx *operands) -+{ -+ gcc_assert (CONST_INT_P (operands[2]) && CONST_INT_P (operands[3])); -+ HOST_WIDE_INT width = INTVAL (operands[2]); -+ HOST_WIDE_INT bitpos = INTVAL (operands[3]); -+ rtx dst = operands[0]; -+ rtx src = operands[1]; -+ -+ if (MEM_P (src) -+ && width == 32 -+ && (bitpos % BITS_PER_UNIT) == 0 -+ && GET_MODE_BITSIZE (GET_MODE (dst)) == width) -+ { -+ rtx newmem = adjust_address (src, GET_MODE (dst), -+ bitpos / BITS_PER_UNIT); -+ -+ rtx base_addr = force_reg (Pmode, XEXP (newmem, 0)); -+ -+ emit_insn (gen_unaligned_loadsi (dst, base_addr)); -+ -+ return EXPAND_DONE; -+ } -+ return EXPAND_FAIL; -+} -+ -+enum nds32_expand_result_type -+nds32_expand_insv (rtx *operands) -+{ -+ gcc_assert (CONST_INT_P (operands[1]) && CONST_INT_P (operands[2])); -+ HOST_WIDE_INT width = INTVAL (operands[1]); -+ HOST_WIDE_INT bitpos = INTVAL (operands[2]); -+ rtx dst = operands[0]; -+ rtx src = operands[3]; -+ -+ if (MEM_P (dst) -+ && width == 32 -+ && (bitpos % BITS_PER_UNIT) == 0 -+ && GET_MODE_BITSIZE (GET_MODE (src)) == width) -+ { -+ rtx newmem = adjust_address (dst, GET_MODE (src), -+ bitpos / BITS_PER_UNIT); -+ -+ rtx base_addr = force_reg (Pmode, XEXP (newmem, 0)); -+ -+ emit_insn (gen_unaligned_storesi (base_addr, src)); -+ -+ return EXPAND_DONE; -+ } -+ return EXPAND_FAIL; -+} -+ - /* ------------------------------------------------------------------------ */ - -+/* Function to generate PC relative jump table. -+ Refer to nds32.md for more details. -+ -+ The following is the sample for the case that diff value -+ can be presented in '.short' size. -+ -+ addi $r1, $r1, -(case_lower_bound) -+ slti $ta, $r1, (case_number) -+ beqz $ta, .L_skip_label -+ -+ la $ta, .L35 ! get jump table address -+ lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry -+ addi $ta, $r1, $ta -+ jr5 $ta -+ -+ ! jump table entry -+ L35: -+ .short .L25-.L35 -+ .short .L26-.L35 -+ .short .L27-.L35 -+ .short .L28-.L35 -+ .short .L29-.L35 -+ .short .L30-.L35 -+ .short .L31-.L35 -+ .short .L32-.L35 -+ .short .L33-.L35 -+ .short .L34-.L35 */ -+const char * -+nds32_output_casesi_pc_relative (rtx *operands) -+{ -+ machine_mode mode; -+ rtx diff_vec; -+ -+ diff_vec = PATTERN (NEXT_INSN (as_a (operands[1]))); -+ -+ gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); -+ -+ /* Step C: "t <-- operands[1]". */ -+ if (flag_pic) -+ { -+ output_asm_insn ("sethi\t$ta, hi20(%l1@GOTOFF)", operands); -+ output_asm_insn ("ori\t$ta, $ta, lo12(%l1@GOTOFF)", operands); -+ output_asm_insn ("add\t$ta, $ta, $gp", operands); -+ } -+ else -+ output_asm_insn ("la\t$ta, %l1", operands); -+ -+ /* Get the mode of each element in the difference vector. */ -+ mode = GET_MODE (diff_vec); -+ -+ /* Step D: "z <-- (mem (plus (operands[0] << m) t))", -+ where m is 0, 1, or 2 to load address-diff value from table. */ -+ switch (mode) -+ { -+ case E_QImode: -+ output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands); -+ break; -+ case E_HImode: -+ output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands); -+ break; -+ case E_SImode: -+ output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); -+ break; -+ default: -+ gcc_unreachable (); -+ } -+ -+ /* Step E: "t <-- z + t". -+ Add table label_ref with address-diff value to -+ obtain target case address. */ -+ output_asm_insn ("add\t$ta, %2, $ta", operands); -+ -+ /* Step F: jump to target with register t. */ -+ if (TARGET_16_BIT) -+ return "jr5\t$ta"; -+ else -+ return "jr\t$ta"; -+} -+ -+/* Function to generate normal jump table. */ -+const char * -+nds32_output_casesi (rtx *operands) -+{ -+ /* Step C: "t <-- operands[1]". */ -+ if (flag_pic) -+ { -+ output_asm_insn ("sethi\t$ta, hi20(%l1@GOTOFF)", operands); -+ output_asm_insn ("ori\t$ta, $ta, lo12(%l1@GOTOFF)", operands); -+ output_asm_insn ("add\t$ta, $ta, $gp", operands); -+ } -+ else -+ output_asm_insn ("la\t$ta, %l1", operands); -+ -+ /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */ -+ output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); -+ -+ /* No need to perform Step E, which is only used for -+ pc relative jump table. */ -+ -+ /* Step F: jump to target with register z. */ -+ if (TARGET_16_BIT) -+ return "jr5\t%2"; -+ else -+ return "jr\t%2"; -+} -+ - /* Function to return memory format. */ - enum nds32_16bit_address_type - nds32_mem_format (rtx op) -@@ -1757,11 +2030,8 @@ nds32_output_stack_push (rtx par_rtx) - - /* If we step here, we are going to do v3push or multiple push operation. */ - -- /* The v3push/v3pop instruction should only be applied on -- none-isr and none-variadic function. */ -- if (TARGET_V3PUSH -- && !nds32_isr_function_p (current_function_decl) -- && (cfun->machine->va_args_size == 0)) -+ /* Refer to nds32.h, where we comment when push25/pop25 are available. */ -+ if (NDS32_V3PUSH_AVAILABLE_P) - { - /* For stack v3push: - operands[0]: Re -@@ -1881,11 +2151,8 @@ nds32_output_stack_pop (rtx par_rtx ATTRIBUTE_UNUSED) - - /* If we step here, we are going to do v3pop or multiple pop operation. */ - -- /* The v3push/v3pop instruction should only be applied on -- none-isr and none-variadic function. */ -- if (TARGET_V3PUSH -- && !nds32_isr_function_p (current_function_decl) -- && (cfun->machine->va_args_size == 0)) -+ /* Refer to nds32.h, where we comment when push25/pop25 are available. */ -+ if (NDS32_V3PUSH_AVAILABLE_P) - { - /* For stack v3pop: - operands[0]: Re -@@ -2022,77 +2289,6 @@ nds32_output_return (void) - return ""; - } - --/* Function to generate PC relative jump table. -- Refer to nds32.md for more details. -- -- The following is the sample for the case that diff value -- can be presented in '.short' size. -- -- addi $r1, $r1, -(case_lower_bound) -- slti $ta, $r1, (case_number) -- beqz $ta, .L_skip_label -- -- la $ta, .L35 ! get jump table address -- lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry -- addi $ta, $r1, $ta -- jr5 $ta -- -- ! jump table entry -- L35: -- .short .L25-.L35 -- .short .L26-.L35 -- .short .L27-.L35 -- .short .L28-.L35 -- .short .L29-.L35 -- .short .L30-.L35 -- .short .L31-.L35 -- .short .L32-.L35 -- .short .L33-.L35 -- .short .L34-.L35 */ --const char * --nds32_output_casesi_pc_relative (rtx *operands) --{ -- machine_mode mode; -- rtx diff_vec; -- -- diff_vec = PATTERN (NEXT_INSN (as_a (operands[1]))); -- -- gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); -- -- /* Step C: "t <-- operands[1]". */ -- output_asm_insn ("la\t$ta, %l1", operands); -- -- /* Get the mode of each element in the difference vector. */ -- mode = GET_MODE (diff_vec); -- -- /* Step D: "z <-- (mem (plus (operands[0] << m) t))", -- where m is 0, 1, or 2 to load address-diff value from table. */ -- switch (mode) -- { -- case E_QImode: -- output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands); -- break; -- case E_HImode: -- output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands); -- break; -- case E_SImode: -- output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); -- break; -- default: -- gcc_unreachable (); -- } -- -- /* Step E: "t <-- z + t". -- Add table label_ref with address-diff value to -- obtain target case address. */ -- output_asm_insn ("add\t$ta, %2, $ta", operands); -- -- /* Step F: jump to target with register t. */ -- if (TARGET_16_BIT) -- return "jr5\t$ta"; -- else -- return "jr\t$ta"; --} - - /* output a float load instruction */ - const char * -@@ -2250,52 +2446,51 @@ nds32_output_float_store (rtx *operands) - return ""; - } - --/* Function to generate normal jump table. */ - const char * --nds32_output_casesi (rtx *operands) -+nds32_output_smw_single_word (rtx *operands) - { -- /* Step C: "t <-- operands[1]". */ -- output_asm_insn ("la\t$ta, %l1", operands); -- -- /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */ -- output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); -- -- /* No need to perform Step E, which is only used for -- pc relative jump table. */ -+ char buff[100]; -+ unsigned regno; -+ int enable4; -+ bool update_base_p; -+ rtx base_addr = operands[0]; -+ rtx base_reg; -+ rtx otherops[2]; - -- /* Step F: jump to target with register z. */ -- if (TARGET_16_BIT) -- return "jr5\t%2"; -+ if (REG_P (XEXP (base_addr, 0))) -+ { -+ update_base_p = false; -+ base_reg = XEXP (base_addr, 0); -+ } - else -- return "jr\t%2"; --} -+ { -+ update_base_p = true; -+ base_reg = XEXP (XEXP (base_addr, 0), 0); -+ } - --/* Auxiliary functions for lwm/smw. */ --bool --nds32_valid_smw_lwm_base_p (rtx op) --{ -- rtx base_addr; -+ const char *update_base = update_base_p ? "m" : ""; - -- if (!MEM_P (op)) -- return false; -+ regno = REGNO (operands[1]); - -- base_addr = XEXP (op, 0); -+ otherops[0] = base_reg; -+ otherops[1] = operands[1]; - -- if (REG_P (base_addr)) -- return true; -+ if (regno >= 28) -+ { -+ enable4 = nds32_regno_to_enable4 (regno); -+ sprintf (buff, "smw.bi%s\t$sp, [%%0], $sp, %x", update_base, enable4); -+ } - else - { -- if (GET_CODE (base_addr) == POST_INC -- && REG_P (XEXP (base_addr, 0))) -- return true; -+ sprintf (buff, "smw.bi%s\t%%1, [%%0], %%1", update_base); - } -- -- return false; -+ output_asm_insn (buff, otherops); -+ return ""; - } - - /* ------------------------------------------------------------------------ */ - const char * --nds32_output_smw_single_word (rtx *operands) -+nds32_output_smw_double_word (rtx *operands) - { - char buff[100]; - unsigned regno; -@@ -2303,7 +2498,7 @@ nds32_output_smw_single_word (rtx *operands) - bool update_base_p; - rtx base_addr = operands[0]; - rtx base_reg; -- rtx otherops[2]; -+ rtx otherops[3]; - - if (REG_P (XEXP (base_addr, 0))) - { -@@ -2322,15 +2517,22 @@ nds32_output_smw_single_word (rtx *operands) - - otherops[0] = base_reg; - otherops[1] = operands[1]; -+ otherops[2] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);; - - if (regno >= 28) - { -- enable4 = nds32_regno_to_enable4 (regno); -+ enable4 = nds32_regno_to_enable4 (regno) -+ | nds32_regno_to_enable4 (regno + 1); - sprintf (buff, "smw.bi%s\t$sp, [%%0], $sp, %x", update_base, enable4); - } -+ else if (regno == 27) -+ { -+ enable4 = nds32_regno_to_enable4 (regno + 1); -+ sprintf (buff, "smw.bi%s\t%%1, [%%0], %%1, %x", update_base, enable4); -+ } - else - { -- sprintf (buff, "smw.bi%s\t%%1, [%%0], %%1", update_base); -+ sprintf (buff, "smw.bi%s\t%%1, [%%0], %%2", update_base); - } - output_asm_insn (buff, otherops); - return ""; -@@ -2415,16 +2617,17 @@ nds32_expand_unaligned_load (rtx *operands, enum machine_mode mode) - if (mode == DImode) - { - /* Load doubleword, we need two registers to access. */ -- reg[0] = simplify_gen_subreg (SImode, operands[0], -- GET_MODE (operands[0]), 0); -- reg[1] = simplify_gen_subreg (SImode, operands[0], -- GET_MODE (operands[0]), 4); -+ reg[0] = nds32_di_low_part_subreg (operands[0]); -+ reg[1] = nds32_di_high_part_subreg (operands[0]); - /* A register only store 4 byte. */ - width = GET_MODE_SIZE (SImode) - 1; - } - else - { -- reg[0] = operands[0]; -+ if (VECTOR_MODE_P (mode)) -+ reg[0] = gen_reg_rtx (SImode); -+ else -+ reg[0] = operands[0]; - } - - for (num_reg = (mode == DImode) ? 2 : 1; num_reg > 0; num_reg--) -@@ -2466,6 +2669,8 @@ nds32_expand_unaligned_load (rtx *operands, enum machine_mode mode) - offset = offset + offset_adj; - } - } -+ if (VECTOR_MODE_P (mode)) -+ convert_move (operands[0], reg[0], false); - } - - void -@@ -2499,16 +2704,20 @@ nds32_expand_unaligned_store (rtx *operands, enum machine_mode mode) - if (mode == DImode) - { - /* Load doubleword, we need two registers to access. */ -- reg[0] = simplify_gen_subreg (SImode, operands[1], -- GET_MODE (operands[1]), 0); -- reg[1] = simplify_gen_subreg (SImode, operands[1], -- GET_MODE (operands[1]), 4); -+ reg[0] = nds32_di_low_part_subreg (operands[1]); -+ reg[1] = nds32_di_high_part_subreg (operands[1]); - /* A register only store 4 byte. */ - width = GET_MODE_SIZE (SImode) - 1; - } - else - { -- reg[0] = operands[1]; -+ if (VECTOR_MODE_P (mode)) -+ { -+ reg[0] = gen_reg_rtx (SImode); -+ convert_move (reg[0], operands[1], false); -+ } -+ else -+ reg[0] = operands[1]; - } - - for (num_reg = (mode == DImode) ? 2 : 1; num_reg > 0; num_reg--) -@@ -2765,6 +2974,36 @@ nds32_output_cbranchsi4_greater_less_zero (rtx_insn *insn, rtx *operands) - return ""; - } - -+const char * -+nds32_output_unpkd8 (rtx output, rtx input, -+ rtx high_idx_rtx, rtx low_idx_rtx, -+ bool signed_p) -+{ -+ char pattern[100]; -+ rtx output_operands[2]; -+ HOST_WIDE_INT high_idx, low_idx; -+ high_idx = INTVAL (high_idx_rtx); -+ low_idx = INTVAL (low_idx_rtx); -+ -+ gcc_assert (high_idx >= 0 && high_idx <= 3); -+ gcc_assert (low_idx >= 0 && low_idx <= 3); -+ -+ /* We only have 10, 20, 30 and 31. */ -+ if ((low_idx != 0 || high_idx == 0) && -+ !(low_idx == 1 && high_idx == 3)) -+ return "#"; -+ -+ char sign_char = signed_p ? 's' : 'z'; -+ -+ sprintf (pattern, -+ "%cunpkd8" HOST_WIDE_INT_PRINT_DEC HOST_WIDE_INT_PRINT_DEC "\t%%0, %%1", -+ sign_char, high_idx, low_idx); -+ output_operands[0] = output; -+ output_operands[1] = input; -+ output_asm_insn (pattern, output_operands); -+ return ""; -+} -+ - /* Return true if SYMBOL_REF X binds locally. */ - - static bool -@@ -2782,22 +3021,15 @@ nds32_output_call (rtx insn, rtx *operands, rtx symbol, const char *long_call, - char pattern[100]; - bool noreturn_p; - -- if (GET_CODE (symbol) == CONST) -- { -- symbol= XEXP (symbol, 0); -- -- if (GET_CODE (symbol) == PLUS) -- symbol = XEXP (symbol, 0); -- } -- -- gcc_assert (GET_CODE (symbol) == SYMBOL_REF -- || REG_P (symbol)); -- - if (nds32_long_call_p (symbol)) - strcpy (pattern, long_call); - else - strcpy (pattern, call); - -+ if (flag_pic && CONSTANT_P (symbol) -+ && !nds32_symbol_binds_local_p (symbol)) -+ strcat (pattern, "@PLT"); -+ - if (align_p) - strcat (pattern, "\n\t.align 2"); - -@@ -2815,6 +3047,91 @@ nds32_output_call (rtx insn, rtx *operands, rtx symbol, const char *long_call, - return ""; - } - -+bool -+nds32_need_split_sms_p (rtx in0_idx0, rtx in1_idx0, -+ rtx in0_idx1, rtx in1_idx1) -+{ -+ /* smds or smdrs. */ -+ if (INTVAL (in0_idx0) == INTVAL (in1_idx0) -+ && INTVAL (in0_idx1) == INTVAL (in1_idx1) -+ && INTVAL (in0_idx0) != INTVAL (in0_idx1)) -+ return false; -+ -+ /* smxds. */ -+ if (INTVAL (in0_idx0) != INTVAL (in0_idx1) -+ && INTVAL (in1_idx0) != INTVAL (in1_idx1)) -+ return false; -+ -+ return true; -+} -+ -+const char * -+nds32_output_sms (rtx in0_idx0, rtx in1_idx0, -+ rtx in0_idx1, rtx in1_idx1) -+{ -+ if (nds32_need_split_sms_p (in0_idx0, in1_idx0, -+ in0_idx1, in1_idx1)) -+ return "#"; -+ /* out = in0[in0_idx0] * in1[in1_idx0] - in0[in0_idx1] * in1[in1_idx1] */ -+ -+ /* smds or smdrs. */ -+ if (INTVAL (in0_idx0) == INTVAL (in1_idx0) -+ && INTVAL (in0_idx1) == INTVAL (in1_idx1) -+ && INTVAL (in0_idx0) != INTVAL (in0_idx1)) -+ { -+ if (INTVAL (in0_idx0) == 0) -+ { -+ if (TARGET_BIG_ENDIAN) -+ return "smds\t%0, %1, %2"; -+ else -+ return "smdrs\t%0, %1, %2"; -+ } -+ else -+ { -+ if (TARGET_BIG_ENDIAN) -+ return "smdrs\t%0, %1, %2"; -+ else -+ return "smds\t%0, %1, %2"; -+ } -+ } -+ -+ if (INTVAL (in0_idx0) != INTVAL (in0_idx1) -+ && INTVAL (in1_idx0) != INTVAL (in1_idx1)) -+ { -+ if (INTVAL (in0_idx0) == 1) -+ { -+ if (TARGET_BIG_ENDIAN) -+ return "smxds\t%0, %2, %1"; -+ else -+ return "smxds\t%0, %1, %2"; -+ } -+ else -+ { -+ if (TARGET_BIG_ENDIAN) -+ return "smxds\t%0, %1, %2"; -+ else -+ return "smxds\t%0, %2, %1"; -+ } -+ } -+ -+ gcc_unreachable (); -+ return ""; -+} -+ -+void -+nds32_split_sms (rtx out, rtx in0, rtx in1, -+ rtx in0_idx0, rtx in1_idx0, -+ rtx in0_idx1, rtx in1_idx1) -+{ -+ rtx result0 = gen_reg_rtx (SImode); -+ rtx result1 = gen_reg_rtx (SImode); -+ emit_insn (gen_mulhisi3v (result0, in0, in1, -+ in0_idx0, in1_idx0)); -+ emit_insn (gen_mulhisi3v (result1, in0, in1, -+ in0_idx1, in1_idx1)); -+ emit_insn (gen_subsi3 (out, result0, result1)); -+} -+ - /* Spilt a doubleword instrucion to two single word instructions. */ - void - nds32_spilt_doubleword (rtx *operands, bool load_p) -@@ -2846,16 +3163,30 @@ nds32_spilt_doubleword (rtx *operands, bool load_p) - /* generate low_part and high_part memory format: - low_part: (post_modify ((reg) (plus (reg) (const 4))) - high_part: (post_modify ((reg) (plus (reg) (const -12))) */ -- low_part[mem] = gen_frame_mem (SImode, -- gen_rtx_POST_MODIFY (Pmode, sub_mem, -- gen_rtx_PLUS (Pmode, -- sub_mem, -- GEN_INT (4)))); -- high_part[mem] = gen_frame_mem (SImode, -- gen_rtx_POST_MODIFY (Pmode, sub_mem, -- gen_rtx_PLUS (Pmode, -- sub_mem, -- GEN_INT (-12)))); -+ low_part[mem] = gen_rtx_MEM (SImode, -+ gen_rtx_POST_MODIFY (Pmode, sub_mem, -+ gen_rtx_PLUS (Pmode, -+ sub_mem, -+ GEN_INT (4)))); -+ high_part[mem] = gen_rtx_MEM (SImode, -+ gen_rtx_POST_MODIFY (Pmode, sub_mem, -+ gen_rtx_PLUS (Pmode, -+ sub_mem, -+ GEN_INT (-12)))); -+ } -+ else if (GET_CODE (sub_mem) == POST_INC) -+ { -+ /* memory format is (post_inc (reg)), -+ so that extract (reg) from the (post_inc (reg)) pattern. */ -+ sub_mem = XEXP (sub_mem, 0); -+ -+ /* generate low_part and high_part memory format: -+ low_part: (post_inc (reg)) -+ high_part: (post_inc (reg)) */ -+ low_part[mem] = gen_rtx_MEM (SImode, -+ gen_rtx_POST_INC (Pmode, sub_mem)); -+ high_part[mem] = gen_rtx_MEM (SImode, -+ gen_rtx_POST_INC (Pmode, sub_mem)); - } - else if (GET_CODE (sub_mem) == POST_MODIFY) - { -@@ -2872,14 +3203,14 @@ nds32_spilt_doubleword (rtx *operands, bool load_p) - /* Generate low_part and high_part memory format: - low_part: (post_modify ((reg) (plus (reg) (const))) - high_part: ((plus (reg) (const 4))) */ -- low_part[mem] = gen_frame_mem (SImode, -- gen_rtx_POST_MODIFY (Pmode, post_mem, -- gen_rtx_PLUS (Pmode, -- post_mem, -- post_val))); -- high_part[mem] = gen_frame_mem (SImode, plus_constant (Pmode, -- post_mem, -- 4)); -+ low_part[mem] = gen_rtx_MEM (SImode, -+ gen_rtx_POST_MODIFY (Pmode, post_mem, -+ gen_rtx_PLUS (Pmode, -+ post_mem, -+ post_val))); -+ high_part[mem] = gen_rtx_MEM (SImode, plus_constant (Pmode, -+ post_mem, -+ 4)); - } - else - { -@@ -2924,11 +3255,516 @@ nds32_spilt_doubleword (rtx *operands, bool load_p) - } - } - -+void -+nds32_split_ashiftdi3 (rtx dst, rtx src, rtx shiftamount) -+{ -+ rtx src_high_part, src_low_part; -+ rtx dst_high_part, dst_low_part; -+ -+ dst_high_part = nds32_di_high_part_subreg (dst); -+ dst_low_part = nds32_di_low_part_subreg (dst); -+ -+ src_high_part = nds32_di_high_part_subreg (src); -+ src_low_part = nds32_di_low_part_subreg (src); -+ -+ /* We need to handle shift more than 32 bit!!!! */ -+ if (CONST_INT_P (shiftamount)) -+ { -+ if (INTVAL (shiftamount) < 32) -+ { -+ rtx ext_start; -+ ext_start = gen_int_mode(32 - INTVAL (shiftamount), SImode); -+ -+ emit_insn (gen_wext (dst_high_part, src, ext_start)); -+ emit_insn (gen_ashlsi3 (dst_low_part, src_low_part, shiftamount)); -+ } -+ else -+ { -+ rtx new_shift_amout = gen_int_mode(INTVAL (shiftamount) - 32, SImode); -+ -+ emit_insn (gen_ashlsi3 (dst_high_part, src_low_part, -+ new_shift_amout)); -+ -+ emit_move_insn (dst_low_part, GEN_INT (0)); -+ } -+ } -+ else -+ { -+ rtx dst_low_part_l32, dst_high_part_l32; -+ rtx dst_low_part_g32, dst_high_part_g32; -+ rtx new_shift_amout, select_reg; -+ dst_low_part_l32 = gen_reg_rtx (SImode); -+ dst_high_part_l32 = gen_reg_rtx (SImode); -+ dst_low_part_g32 = gen_reg_rtx (SImode); -+ dst_high_part_g32 = gen_reg_rtx (SImode); -+ new_shift_amout = gen_reg_rtx (SImode); -+ select_reg = gen_reg_rtx (SImode); -+ -+ rtx ext_start; -+ ext_start = gen_reg_rtx (SImode); -+ -+ /* -+ if (shiftamount < 32) -+ dst_low_part = src_low_part << shiftamout -+ dst_high_part = wext (src, 32 - shiftamount) -+ # wext can't handle wext (src, 32) since it's only take rb[0:4] -+ # for extract. -+ dst_high_part = shiftamount == 0 ? src_high_part : dst_high_part -+ else -+ dst_low_part = 0 -+ dst_high_part = src_low_part << shiftamount & 0x1f -+ */ -+ -+ emit_insn (gen_subsi3 (ext_start, -+ gen_int_mode (32, SImode), -+ shiftamount)); -+ emit_insn (gen_wext (dst_high_part_l32, src, ext_start)); -+ -+ /* Handle for shiftamout == 0. */ -+ emit_insn (gen_cmovzsi (dst_high_part_l32, shiftamount, -+ src_high_part, dst_high_part_l32)); -+ -+ emit_insn (gen_ashlsi3 (dst_low_part_l32, src_low_part, shiftamount)); -+ -+ emit_move_insn (dst_low_part_g32, const0_rtx); -+ emit_insn (gen_andsi3 (new_shift_amout, shiftamount, GEN_INT (0x1f))); -+ emit_insn (gen_ashlsi3 (dst_high_part_g32, src_low_part, -+ new_shift_amout)); -+ -+ emit_insn (gen_slt_compare (select_reg, shiftamount, GEN_INT (32))); -+ -+ emit_insn (gen_cmovnsi (dst_low_part, select_reg, -+ dst_low_part_l32, dst_low_part_g32)); -+ emit_insn (gen_cmovnsi (dst_high_part, select_reg, -+ dst_high_part_l32, dst_high_part_g32)); -+ } -+} -+ -+void -+nds32_split_ashiftrtdi3 (rtx dst, rtx src, rtx shiftamount) -+{ -+ nds32_split_shiftrtdi3 (dst, src, shiftamount, false); -+} -+ -+void -+nds32_split_lshiftrtdi3 (rtx dst, rtx src, rtx shiftamount) -+{ -+ nds32_split_shiftrtdi3 (dst, src, shiftamount, true); -+} -+ -+void -+nds32_split_rotatertdi3 (rtx dst, rtx src, rtx shiftamount) -+{ -+ rtx dst_low_part_l32, dst_high_part_l32; -+ rtx dst_low_part_g32, dst_high_part_g32; -+ rtx select_reg, low5bit, low5bit_inv, minus32sa; -+ rtx dst_low_part_g32_tmph; -+ rtx dst_low_part_g32_tmpl; -+ rtx dst_high_part_l32_tmph; -+ rtx dst_high_part_l32_tmpl; -+ -+ rtx src_low_part, src_high_part; -+ rtx dst_high_part, dst_low_part; -+ -+ shiftamount = force_reg (SImode, shiftamount); -+ -+ emit_insn (gen_andsi3 (shiftamount, -+ shiftamount, -+ gen_int_mode (0x3f, SImode))); -+ -+ dst_high_part = nds32_di_high_part_subreg (dst); -+ dst_low_part = nds32_di_low_part_subreg (dst); -+ -+ src_high_part = nds32_di_high_part_subreg (src); -+ src_low_part = nds32_di_low_part_subreg (src); -+ -+ dst_low_part_l32 = gen_reg_rtx (SImode); -+ dst_high_part_l32 = gen_reg_rtx (SImode); -+ dst_low_part_g32 = gen_reg_rtx (SImode); -+ dst_high_part_g32 = gen_reg_rtx (SImode); -+ low5bit = gen_reg_rtx (SImode); -+ low5bit_inv = gen_reg_rtx (SImode); -+ minus32sa = gen_reg_rtx (SImode); -+ select_reg = gen_reg_rtx (SImode); -+ -+ dst_low_part_g32_tmph = gen_reg_rtx (SImode); -+ dst_low_part_g32_tmpl = gen_reg_rtx (SImode); -+ -+ dst_high_part_l32_tmph = gen_reg_rtx (SImode); -+ dst_high_part_l32_tmpl = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_slt_compare (select_reg, shiftamount, GEN_INT (32))); -+ -+ /* if shiftamount < 32 -+ dst_low_part = wext(src, shiftamount) -+ else -+ dst_low_part = ((src_high_part >> (shiftamount & 0x1f)) -+ | (src_low_part << (32 - (shiftamount & 0x1f)))) -+ */ -+ emit_insn (gen_andsi3 (low5bit, shiftamount, gen_int_mode (0x1f, SImode))); -+ emit_insn (gen_subsi3 (low5bit_inv, gen_int_mode (32, SImode), low5bit)); -+ -+ emit_insn (gen_wext (dst_low_part_l32, src, shiftamount)); -+ -+ emit_insn (gen_lshrsi3 (dst_low_part_g32_tmpl, src_high_part, low5bit)); -+ emit_insn (gen_ashlsi3 (dst_low_part_g32_tmph, src_low_part, low5bit_inv)); -+ -+ emit_insn (gen_iorsi3 (dst_low_part_g32, -+ dst_low_part_g32_tmpl, -+ dst_low_part_g32_tmph)); -+ -+ emit_insn (gen_cmovnsi (dst_low_part, select_reg, -+ dst_low_part_l32, dst_low_part_g32)); -+ -+ /* if shiftamount < 32 -+ dst_high_part = ((src_high_part >> shiftamount) -+ | (src_low_part << (32 - shiftamount))) -+ dst_high_part = shiftamount == 0 ? src_high_part : dst_high_part -+ else -+ dst_high_part = wext(src, shiftamount & 0x1f) -+ */ -+ -+ emit_insn (gen_subsi3 (minus32sa, gen_int_mode (32, SImode), shiftamount)); -+ -+ emit_insn (gen_lshrsi3 (dst_high_part_l32_tmpl, src_high_part, shiftamount)); -+ emit_insn (gen_ashlsi3 (dst_high_part_l32_tmph, src_low_part, minus32sa)); -+ -+ emit_insn (gen_iorsi3 (dst_high_part_l32, -+ dst_high_part_l32_tmpl, -+ dst_high_part_l32_tmph)); -+ -+ emit_insn (gen_cmovzsi (dst_high_part_l32, shiftamount, -+ src_high_part, dst_high_part_l32)); -+ -+ emit_insn (gen_wext (dst_high_part_g32, src, low5bit)); -+ -+ emit_insn (gen_cmovnsi (dst_high_part, select_reg, -+ dst_high_part_l32, dst_high_part_g32)); -+} -+ -+/* Return true if OP contains a symbol reference. */ -+bool -+symbolic_reference_mentioned_p (rtx op) -+{ -+ const char *fmt; -+ int i; -+ -+ if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) -+ return true; -+ -+ fmt = GET_RTX_FORMAT (GET_CODE (op)); -+ for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) -+ { -+ if (fmt[i] == 'E') -+ { -+ int j; -+ -+ for (j = XVECLEN (op, i) - 1; j >= 0; j--) -+ if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) -+ return true; -+ } -+ -+ else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i))) -+ return true; -+ } -+ -+ return false; -+} -+ -+/* Expand PIC code for @GOTOFF and @GOT. -+ -+ Example for @GOTOFF: -+ -+ la $r0, symbol@GOTOFF -+ -> sethi $ta, hi20(symbol@GOTOFF) -+ ori $ta, $ta, lo12(symbol@GOTOFF) -+ add $r0, $ta, $gp -+ -+ Example for @GOT: -+ -+ la $r0, symbol@GOT -+ -> sethi $ta, hi20(symbol@GOT) -+ ori $ta, $ta, lo12(symbol@GOT) -+ lw $r0, [$ta + $gp] -+*/ -+rtx -+nds32_legitimize_pic_address (rtx x) -+{ -+ rtx addr = x; -+ rtx reg = gen_reg_rtx (Pmode); -+ rtx pat; -+ -+ if (GET_CODE (x) == LABEL_REF -+ || (GET_CODE (x) == SYMBOL_REF -+ && (CONSTANT_POOL_ADDRESS_P (x) -+ || SYMBOL_REF_LOCAL_P (x)))) -+ { -+ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_GOTOFF); -+ addr = gen_rtx_CONST (SImode, addr); -+ emit_insn (gen_sethi (reg, addr)); -+ emit_insn (gen_lo_sum (reg, reg, addr)); -+ x = gen_rtx_PLUS (Pmode, reg, pic_offset_table_rtx); -+ } -+ else if (GET_CODE (x) == SYMBOL_REF) -+ { -+ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_GOT); -+ addr = gen_rtx_CONST (SImode, addr); -+ emit_insn (gen_sethi (reg, addr)); -+ emit_insn (gen_lo_sum (reg, reg, addr)); -+ -+ x = gen_const_mem (SImode, gen_rtx_PLUS (Pmode, pic_offset_table_rtx, -+ reg)); -+ } -+ else if (GET_CODE (x) == CONST) -+ { -+ /* We don't split constant in expand_pic_move because GOTOFF can combine -+ the addend with the symbol. */ -+ addr = XEXP (x, 0); -+ gcc_assert (GET_CODE (addr) == PLUS); -+ -+ rtx op0 = XEXP (addr, 0); -+ rtx op1 = XEXP (addr, 1); -+ -+ if ((GET_CODE (op0) == LABEL_REF -+ || (GET_CODE (op0) == SYMBOL_REF -+ && (CONSTANT_POOL_ADDRESS_P (op0) -+ || SYMBOL_REF_LOCAL_P (op0)))) -+ && GET_CODE (op1) == CONST_INT) -+ { -+ pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), UNSPEC_GOTOFF); -+ pat = gen_rtx_PLUS (Pmode, pat, op1); -+ pat = gen_rtx_CONST (Pmode, pat); -+ emit_insn (gen_sethi (reg, pat)); -+ emit_insn (gen_lo_sum (reg, reg, pat)); -+ x = gen_rtx_PLUS (Pmode, reg, pic_offset_table_rtx); -+ } -+ else if (GET_CODE (op0) == SYMBOL_REF -+ && GET_CODE (op1) == CONST_INT) -+ { -+ /* This is a constant offset from a @GOT symbol reference. */ -+ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, op0), UNSPEC_GOT); -+ addr = gen_rtx_CONST (SImode, addr); -+ emit_insn (gen_sethi (reg, addr)); -+ emit_insn (gen_lo_sum (reg, reg, addr)); -+ addr = gen_const_mem (SImode, gen_rtx_PLUS (Pmode, -+ pic_offset_table_rtx, -+ reg)); -+ emit_move_insn (reg, addr); -+ if (satisfies_constraint_Is15 (op1)) -+ x = gen_rtx_PLUS (Pmode, reg, op1); -+ else -+ { -+ rtx tmp_reg = gen_reg_rtx (SImode); -+ emit_insn (gen_movsi (tmp_reg, op1)); -+ x = gen_rtx_PLUS (Pmode, reg, tmp_reg); -+ } -+ } -+ else -+ { -+ /* Don't handle this pattern. */ -+ debug_rtx (x); -+ gcc_unreachable (); -+ } -+ } -+ return x; -+} -+ -+void -+nds32_expand_pic_move (rtx *operands) -+{ -+ rtx src; -+ -+ src = nds32_legitimize_pic_address (operands[1]); -+ emit_move_insn (operands[0], src); -+} -+ -+/* Expand ICT symbol. -+ Example for @ICT and ICT model=large: -+ -+ la $r0, symbol@ICT -+ -> sethi $rt, hi20(symbol@ICT) -+ lwi $r0, [$rt + lo12(symbol@ICT)] -+ -+*/ -+rtx -+nds32_legitimize_ict_address (rtx x) -+{ -+ rtx symbol = x; -+ rtx addr = x; -+ rtx reg = gen_reg_rtx (Pmode); -+ gcc_assert (GET_CODE (x) == SYMBOL_REF -+ && nds32_indirect_call_referenced_p (x)); -+ -+ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, symbol), UNSPEC_ICT); -+ addr = gen_rtx_CONST (SImode, addr); -+ emit_insn (gen_sethi (reg, addr)); -+ -+ x = gen_const_mem (SImode, gen_rtx_LO_SUM (Pmode, reg, addr)); -+ -+ return x; -+} -+ -+void -+nds32_expand_ict_move (rtx *operands) -+{ -+ rtx src = operands[1]; -+ -+ src = nds32_legitimize_ict_address (src); -+ -+ emit_move_insn (operands[0], src); -+} -+ -+/* Return true X is a indirect call symbol. */ -+bool -+nds32_indirect_call_referenced_p (rtx x) -+{ -+ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_ICT) -+ x = XVECEXP (x, 0, 0); -+ -+ if (GET_CODE (x) == SYMBOL_REF) -+ { -+ tree decl = SYMBOL_REF_DECL (x); -+ -+ return decl -+ && (lookup_attribute("indirect_call", -+ DECL_ATTRIBUTES(decl)) -+ != NULL); -+ } -+ -+ return false; -+} -+ - /* Return true X is need use long call. */ - bool - nds32_long_call_p (rtx symbol) - { -- return TARGET_CMODEL_LARGE; -+ if (nds32_indirect_call_referenced_p (symbol)) -+ return TARGET_ICT_MODEL_LARGE; -+ else -+ return TARGET_CMODEL_LARGE; -+} -+ -+/* Return true if X contains a thread-local symbol. */ -+bool -+nds32_tls_referenced_p (rtx x) -+{ -+ if (!targetm.have_tls) -+ return false; -+ -+ if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS) -+ x = XEXP (XEXP (x, 0), 0); -+ -+ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x)) -+ return true; -+ -+ return false; -+} -+ -+/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute -+ this (thread-local) address. */ -+rtx -+nds32_legitimize_tls_address (rtx x) -+{ -+ rtx tmp_reg; -+ rtx tp_reg = gen_rtx_REG (Pmode, TP_REGNUM); -+ rtx pat, insns, reg0; -+ -+ if (GET_CODE (x) == SYMBOL_REF) -+ switch (SYMBOL_REF_TLS_MODEL (x)) -+ { -+ case TLS_MODEL_GLOBAL_DYNAMIC: -+ case TLS_MODEL_LOCAL_DYNAMIC: -+ /* Emit UNSPEC_TLS_DESC rather than expand rtl directly because spill -+ may destroy the define-use chain anylysis to insert relax_hint. */ -+ if (SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_GLOBAL_DYNAMIC) -+ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_TLSGD); -+ else -+ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_TLSLD); -+ -+ pat = gen_rtx_CONST (SImode, pat); -+ reg0 = gen_rtx_REG (Pmode, 0); -+ /* If we can confirm all clobber reigsters, it doesn't have to use call -+ instruction. */ -+ insns = emit_call_insn (gen_tls_desc (pat, GEN_INT (0))); -+ use_reg (&CALL_INSN_FUNCTION_USAGE (insns), pic_offset_table_rtx); -+ RTL_CONST_CALL_P (insns) = 1; -+ tmp_reg = gen_reg_rtx (SImode); -+ emit_move_insn (tmp_reg, reg0); -+ x = tmp_reg; -+ break; -+ -+ case TLS_MODEL_INITIAL_EXEC: -+ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_TLSIE); -+ tmp_reg = gen_reg_rtx (SImode); -+ pat = gen_rtx_CONST (SImode, pat); -+ emit_insn (gen_tls_ie (tmp_reg, pat, GEN_INT (0))); -+ if (flag_pic) -+ emit_use (pic_offset_table_rtx); -+ x = gen_rtx_PLUS (Pmode, tmp_reg, tp_reg); -+ break; -+ -+ case TLS_MODEL_LOCAL_EXEC: -+ /* Expand symbol_ref@TPOFF': -+ sethi $ta, hi20(symbol_ref@TPOFF) -+ ori $ta, $ta, lo12(symbol_ref@TPOFF) -+ add $r0, $ta, $tp */ -+ tmp_reg = gen_reg_rtx (SImode); -+ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_TLSLE); -+ pat = gen_rtx_CONST (SImode, pat); -+ emit_insn (gen_sethi (tmp_reg, pat)); -+ emit_insn (gen_lo_sum (tmp_reg, tmp_reg, pat)); -+ x = gen_rtx_PLUS (Pmode, tmp_reg, tp_reg); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ else if (GET_CODE (x) == CONST) -+ { -+ rtx base, addend; -+ split_const (x, &base, &addend); -+ -+ if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_LOCAL_EXEC) -+ { -+ /* Expand symbol_ref@TPOFF': -+ sethi $ta, hi20(symbol_ref@TPOFF + addend) -+ ori $ta, $ta, lo12(symbol_ref@TPOFF + addend) -+ add $r0, $ta, $tp */ -+ tmp_reg = gen_reg_rtx (SImode); -+ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, base), UNSPEC_TLSLE); -+ pat = gen_rtx_PLUS (SImode, pat, addend); -+ pat = gen_rtx_CONST (SImode, pat); -+ emit_insn (gen_sethi (tmp_reg, pat)); -+ emit_insn (gen_lo_sum (tmp_reg, tmp_reg, pat)); -+ x = gen_rtx_PLUS (Pmode, tmp_reg, tp_reg); -+ } -+ } -+ -+ return x; -+} -+ -+void -+nds32_expand_tls_move (rtx *operands) -+{ -+ rtx src = operands[1]; -+ rtx base, addend; -+ -+ if (CONSTANT_P (src)) -+ split_const (src, &base, &addend); -+ -+ if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_LOCAL_EXEC) -+ src = nds32_legitimize_tls_address (src); -+ else -+ { -+ src = nds32_legitimize_tls_address (base); -+ if (addend != const0_rtx) -+ { -+ src = gen_rtx_PLUS (SImode, src, addend); -+ src = force_operand (src, operands[0]); -+ } -+ } -+ -+ emit_move_insn (operands[0], src); - } - - void -@@ -2976,3 +3812,105 @@ nds32_expand_constant (machine_mode mode, HOST_WIDE_INT val, - emit_move_insn (target, gen_rtx_fmt_ee (AND, mode, source, temp)); - } - } -+ -+/* Auxiliary functions for lwm/smw. */ -+bool -+nds32_valid_smw_lwm_base_p (rtx op) -+{ -+ rtx base_addr; -+ -+ if (!MEM_P (op)) -+ return false; -+ -+ base_addr = XEXP (op, 0); -+ -+ if (REG_P (base_addr)) -+ return true; -+ else -+ { -+ if (GET_CODE (base_addr) == POST_INC -+ && REG_P (XEXP (base_addr, 0))) -+ return true; -+ } -+ -+ return false; -+} -+ -+/* Auxiliary functions for manipulation DI mode. */ -+rtx nds32_di_high_part_subreg(rtx reg) -+{ -+ unsigned high_part_offset = subreg_highpart_offset (SImode, DImode); -+ -+ return simplify_gen_subreg ( -+ SImode, reg, -+ DImode, high_part_offset); -+} -+ -+rtx nds32_di_low_part_subreg(rtx reg) -+{ -+ unsigned low_part_offset = subreg_lowpart_offset (SImode, DImode); -+ -+ return simplify_gen_subreg ( -+ SImode, reg, -+ DImode, low_part_offset); -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* Auxiliary function for output TLS patterns. */ -+ -+const char * -+nds32_output_tls_desc (rtx *operands) -+{ -+ char pattern[1000]; -+ -+ if (TARGET_RELAX_HINT) -+ snprintf (pattern, sizeof (pattern), -+ ".relax_hint %%1\n\tsethi $r0, hi20(%%0)\n\t" -+ ".relax_hint %%1\n\tori $r0, $r0, lo12(%%0)\n\t" -+ ".relax_hint %%1\n\tlw $r15, [$r0 + $gp]\n\t" -+ ".relax_hint %%1\n\tadd $r0, $r0, $gp\n\t" -+ ".relax_hint %%1\n\tjral $r15"); -+ else -+ snprintf (pattern, sizeof (pattern), -+ "sethi $r0, hi20(%%0)\n\t" -+ "ori $r0, $r0, lo12(%%0)\n\t" -+ "lw $r15, [$r0 + $gp]\n\t" -+ "add $r0, $r0, $gp\n\t" -+ "jral $r15"); -+ output_asm_insn (pattern, operands); -+ return ""; -+} -+ -+const char * -+nds32_output_tls_ie (rtx *operands) -+{ -+ char pattern[1000]; -+ -+ if (flag_pic) -+ { -+ if (TARGET_RELAX_HINT) -+ snprintf (pattern, sizeof (pattern), -+ ".relax_hint %%2\n\tsethi %%0, hi20(%%1)\n\t" -+ ".relax_hint %%2\n\tori %%0, %%0, lo12(%%1)\n\t" -+ ".relax_hint %%2\n\tlw %%0, [%%0 + $gp]"); -+ else -+ snprintf (pattern, sizeof (pattern), -+ "sethi %%0, hi20(%%1)\n\t" -+ "ori %%0, %%0, lo12(%%1)\n\t" -+ "lw %%0, [%%0 + $gp]"); -+ } -+ else -+ { -+ if (TARGET_RELAX_HINT) -+ snprintf (pattern, sizeof (pattern), -+ ".relax_hint %%2\n\tsethi %%0, hi20(%%1)\n\t" -+ ".relax_hint %%2\n\tlwi %%0, [%%0 + lo12(%%1)]"); -+ else -+ snprintf (pattern, sizeof (pattern), -+ "sethi %%0, hi20(%%1)\n\t" -+ "lwi %%0, [%%0 + lo12(%%1)]"); -+ } -+ output_asm_insn (pattern, operands); -+ return ""; -+} -diff --git a/gcc/config/nds32/nds32-memory-manipulation.c b/gcc/config/nds32/nds32-memory-manipulation.c -index 8dea13047b6..f6140e65130 100644 ---- a/gcc/config/nds32/nds32-memory-manipulation.c -+++ b/gcc/config/nds32/nds32-memory-manipulation.c -@@ -257,8 +257,124 @@ static bool - nds32_expand_movmemsi_loop_known_size (rtx dstmem, rtx srcmem, - rtx size, rtx alignment) - { -- return nds32_expand_movmemsi_loop_unknown_size (dstmem, srcmem, -- size, alignment); -+ rtx dst_base_reg, src_base_reg; -+ rtx dst_itr, src_itr; -+ rtx dstmem_m, srcmem_m, dst_itr_m, src_itr_m; -+ rtx dst_end; -+ rtx double_word_mode_loop, byte_mode_loop; -+ rtx tmp; -+ int start_regno; -+ bool align_to_4_bytes = (INTVAL (alignment) & 3) == 0; -+ unsigned HOST_WIDE_INT total_bytes = UINTVAL (size); -+ -+ if (TARGET_ISA_V3M && !align_to_4_bytes) -+ return 0; -+ -+ if (TARGET_REDUCED_REGS) -+ start_regno = 2; -+ else -+ start_regno = 16; -+ -+ dst_itr = gen_reg_rtx (Pmode); -+ src_itr = gen_reg_rtx (Pmode); -+ dst_end = gen_reg_rtx (Pmode); -+ tmp = gen_reg_rtx (QImode); -+ -+ double_word_mode_loop = gen_label_rtx (); -+ byte_mode_loop = gen_label_rtx (); -+ -+ dst_base_reg = copy_to_mode_reg (Pmode, XEXP (dstmem, 0)); -+ src_base_reg = copy_to_mode_reg (Pmode, XEXP (srcmem, 0)); -+ -+ if (total_bytes < 8) -+ { -+ /* Emit total_bytes less than 8 loop version of movmem. -+ add $dst_end, $dst, $size -+ move $dst_itr, $dst -+ .Lbyte_mode_loop: -+ lbi.bi $tmp, [$src_itr], #1 -+ sbi.bi $tmp, [$dst_itr], #1 -+ ! Not readch upper bound. Loop. -+ bne $dst_itr, $dst_end, .Lbyte_mode_loop */ -+ -+ /* add $dst_end, $dst, $size */ -+ dst_end = expand_binop (Pmode, add_optab, dst_base_reg, size, -+ NULL_RTX, 0, OPTAB_WIDEN); -+ /* move $dst_itr, $dst -+ move $src_itr, $src */ -+ emit_move_insn (dst_itr, dst_base_reg); -+ emit_move_insn (src_itr, src_base_reg); -+ -+ /* .Lbyte_mode_loop: */ -+ emit_label (byte_mode_loop); -+ -+ /* lbi.bi $tmp, [$src_itr], #1 */ -+ nds32_emit_post_inc_load_store (tmp, src_itr, QImode, true); -+ -+ /* sbi.bi $tmp, [$dst_itr], #1 */ -+ nds32_emit_post_inc_load_store (tmp, dst_itr, QImode, false); -+ /* ! Not readch upper bound. Loop. -+ bne $dst_itr, $dst_end, .Lbyte_mode_loop */ -+ emit_cmp_and_jump_insns (dst_itr, dst_end, NE, NULL, -+ SImode, 1, byte_mode_loop); -+ return true; -+ } -+ else if (total_bytes % 8 == 0) -+ { -+ /* Emit multiple of 8 loop version of movmem. -+ -+ add $dst_end, $dst, $size -+ move $dst_itr, $dst -+ move $src_itr, $src -+ -+ .Ldouble_word_mode_loop: -+ lmw.bim $tmp-begin, [$src_itr], $tmp-end, #0 ! $src_itr' = $src_itr -+ smw.bim $tmp-begin, [$dst_itr], $tmp-end, #0 ! $dst_itr' = $dst_itr -+ ! move will delete after register allocation -+ move $src_itr, $src_itr' -+ move $dst_itr, $dst_itr' -+ ! Not readch upper bound. Loop. -+ bne $double_word_end, $dst_itr, .Ldouble_word_mode_loop */ -+ -+ /* add $dst_end, $dst, $size */ -+ dst_end = expand_binop (Pmode, add_optab, dst_base_reg, size, -+ NULL_RTX, 0, OPTAB_WIDEN); -+ -+ /* move $dst_itr, $dst -+ move $src_itr, $src */ -+ emit_move_insn (dst_itr, dst_base_reg); -+ emit_move_insn (src_itr, src_base_reg); -+ -+ /* .Ldouble_word_mode_loop: */ -+ emit_label (double_word_mode_loop); -+ /* lmw.bim $tmp-begin, [$src_itr], $tmp-end, #0 ! $src_itr' = $src_itr -+ smw.bim $tmp-begin, [$dst_itr], $tmp-end, #0 ! $dst_itr' = $dst_itr */ -+ src_itr_m = src_itr; -+ dst_itr_m = dst_itr; -+ srcmem_m = srcmem; -+ dstmem_m = dstmem; -+ nds32_emit_mem_move_block (start_regno, 2, -+ &dst_itr_m, &dstmem_m, -+ &src_itr_m, &srcmem_m, -+ true); -+ /* move $src_itr, $src_itr' -+ move $dst_itr, $dst_itr' */ -+ emit_move_insn (dst_itr, dst_itr_m); -+ emit_move_insn (src_itr, src_itr_m); -+ -+ /* ! Not readch upper bound. Loop. -+ bne $double_word_end, $dst_itr, .Ldouble_word_mode_loop */ -+ emit_cmp_and_jump_insns (dst_end, dst_itr, NE, NULL, -+ Pmode, 1, double_word_mode_loop); -+ } -+ else -+ { -+ /* Handle size greater than 8, and not a multiple of 8. */ -+ return nds32_expand_movmemsi_loop_unknown_size (dstmem, srcmem, -+ size, alignment); -+ } -+ -+ return true; - } - - static bool -@@ -433,10 +549,8 @@ nds32_expand_movmemsi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment) - /* Auxiliary function for expand setmem pattern. */ - - static rtx --nds32_gen_dup_4_byte_to_word_value (rtx value) -+nds32_gen_dup_4_byte_to_word_value_aux (rtx value, rtx value4word) - { -- rtx value4word = gen_reg_rtx (SImode); -- - gcc_assert (GET_MODE (value) == QImode || CONST_INT_P (value)); - - if (CONST_INT_P (value)) -@@ -449,36 +563,74 @@ nds32_gen_dup_4_byte_to_word_value (rtx value) - } - else - { -- /* ! prepare word -- andi $tmp1, $value, 0xff ! $tmp1 <- 0x000000ab -- slli $tmp2, $tmp1, 8 ! $tmp2 <- 0x0000ab00 -- or $tmp3, $tmp1, $tmp2 ! $tmp3 <- 0x0000abab -- slli $tmp4, $tmp3, 16 ! $tmp4 <- 0xabab0000 -- or $val4word, $tmp3, $tmp4 ! $value4word <- 0xabababab */ -- -- rtx tmp1, tmp2, tmp3, tmp4, final_value; -- tmp1 = expand_binop (SImode, and_optab, value, -- gen_int_mode (0xff, SImode), -- NULL_RTX, 0, OPTAB_WIDEN); -- tmp2 = expand_binop (SImode, ashl_optab, tmp1, -- gen_int_mode (8, SImode), -- NULL_RTX, 0, OPTAB_WIDEN); -- tmp3 = expand_binop (SImode, ior_optab, tmp1, tmp2, -- NULL_RTX, 0, OPTAB_WIDEN); -- tmp4 = expand_binop (SImode, ashl_optab, tmp3, -- gen_int_mode (16, SImode), -- NULL_RTX, 0, OPTAB_WIDEN); -- -- final_value = expand_binop (SImode, ior_optab, tmp3, tmp4, -- NULL_RTX, 0, OPTAB_WIDEN); -- emit_move_insn (value4word, final_value); -+ if (NDS32_EXT_DSP_P ()) -+ { -+ /* ! prepare word -+ insb $tmp, $value, 1 ! $tmp <- 0x0000abab -+ pkbb16 $tmp6, $tmp2, $tmp2 ! $value4word <- 0xabababab */ -+ rtx tmp = gen_reg_rtx (SImode); -+ -+ convert_move (tmp, value, true); -+ -+ emit_insn ( -+ gen_insvsi_internal (tmp, gen_int_mode (0x8, SImode), tmp)); -+ -+ emit_insn (gen_pkbbsi_1 (value4word, tmp, tmp)); -+ } -+ else -+ { -+ /* ! prepare word -+ andi $tmp1, $value, 0xff ! $tmp1 <- 0x000000ab -+ slli $tmp2, $tmp1, 8 ! $tmp2 <- 0x0000ab00 -+ or $tmp3, $tmp1, $tmp2 ! $tmp3 <- 0x0000abab -+ slli $tmp4, $tmp3, 16 ! $tmp4 <- 0xabab0000 -+ or $val4word, $tmp3, $tmp4 ! $value4word <- 0xabababab */ -+ -+ rtx tmp1, tmp2, tmp3, tmp4; -+ tmp1 = expand_binop (SImode, and_optab, value, -+ gen_int_mode (0xff, SImode), -+ NULL_RTX, 0, OPTAB_WIDEN); -+ tmp2 = expand_binop (SImode, ashl_optab, tmp1, -+ gen_int_mode (8, SImode), -+ NULL_RTX, 0, OPTAB_WIDEN); -+ tmp3 = expand_binop (SImode, ior_optab, tmp1, tmp2, -+ NULL_RTX, 0, OPTAB_WIDEN); -+ tmp4 = expand_binop (SImode, ashl_optab, tmp3, -+ gen_int_mode (16, SImode), -+ NULL_RTX, 0, OPTAB_WIDEN); -+ -+ emit_insn (gen_iorsi3 (value4word, tmp3, tmp4)); -+ } - } - - return value4word; - } - - static rtx --emit_setmem_word_loop (rtx itr, rtx size, rtx value) -+nds32_gen_dup_4_byte_to_word_value (rtx value) -+{ -+ rtx value4word = gen_reg_rtx (SImode); -+ nds32_gen_dup_4_byte_to_word_value_aux (value, value4word); -+ -+ return value4word; -+} -+ -+static rtx -+nds32_gen_dup_8_byte_to_double_word_value (rtx value) -+{ -+ rtx value4doubleword = gen_reg_rtx (DImode); -+ -+ nds32_gen_dup_4_byte_to_word_value_aux ( -+ value, nds32_di_low_part_subreg(value4doubleword)); -+ -+ emit_move_insn (nds32_di_high_part_subreg(value4doubleword), -+ nds32_di_low_part_subreg(value4doubleword)); -+ return value4doubleword; -+} -+ -+ -+static rtx -+emit_setmem_doubleword_loop (rtx itr, rtx size, rtx value) - { - rtx word_mode_label = gen_label_rtx (); - rtx word_mode_end_label = gen_label_rtx (); -@@ -487,9 +639,9 @@ emit_setmem_word_loop (rtx itr, rtx size, rtx value) - rtx word_mode_end = gen_reg_rtx (SImode); - rtx size_for_word = gen_reg_rtx (SImode); - -- /* and $size_for_word, $size, #~3 */ -+ /* and $size_for_word, $size, #~0x7 */ - size_for_word = expand_binop (SImode, and_optab, size, -- gen_int_mode (~3, SImode), -+ gen_int_mode (~0x7, SImode), - NULL_RTX, 0, OPTAB_WIDEN); - - emit_move_insn (byte_mode_size, size); -@@ -501,8 +653,8 @@ emit_setmem_word_loop (rtx itr, rtx size, rtx value) - word_mode_end = expand_binop (Pmode, add_optab, itr, size_for_word, - NULL_RTX, 0, OPTAB_WIDEN); - -- /* andi $byte_mode_size, $size, 3 */ -- byte_mode_size_tmp = expand_binop (SImode, and_optab, size, GEN_INT (3), -+ /* andi $byte_mode_size, $size, 0x7 */ -+ byte_mode_size_tmp = expand_binop (SImode, and_optab, size, GEN_INT (0x7), - NULL_RTX, 0, OPTAB_WIDEN); - - emit_move_insn (byte_mode_size, byte_mode_size_tmp); -@@ -512,9 +664,9 @@ emit_setmem_word_loop (rtx itr, rtx size, rtx value) - /* ! word-mode set loop - smw.bim $value4word, [$dst_itr], $value4word, 0 - bne $word_mode_end, $dst_itr, .Lword_mode */ -- emit_insn (gen_unaligned_store_update_base_w (itr, -- itr, -- value)); -+ emit_insn (gen_unaligned_store_update_base_dw (itr, -+ itr, -+ value)); - emit_cmp_and_jump_insns (word_mode_end, itr, NE, NULL, - Pmode, 1, word_mode_label); - -@@ -566,7 +718,7 @@ emit_setmem_byte_loop (rtx itr, rtx size, rtx value, bool need_end) - static bool - nds32_expand_setmem_loop (rtx dstmem, rtx size, rtx value) - { -- rtx value4word; -+ rtx value4doubleword; - rtx value4byte; - rtx dst; - rtx byte_mode_size; -@@ -609,7 +761,7 @@ nds32_expand_setmem_loop (rtx dstmem, rtx size, rtx value) - or $tmp3, $tmp1, $tmp2 ! $tmp3 <- 0x0000abab - slli $tmp4, $tmp3, 16 ! $tmp4 <- 0xabab0000 - or $val4word, $tmp3, $tmp4 ! $value4word <- 0xabababab */ -- value4word = nds32_gen_dup_4_byte_to_word_value (value); -+ value4doubleword = nds32_gen_dup_8_byte_to_double_word_value (value); - - /* and $size_for_word, $size, #-4 - beqz $size_for_word, .Lword_mode_end -@@ -622,7 +774,7 @@ nds32_expand_setmem_loop (rtx dstmem, rtx size, rtx value) - smw.bim $value4word, [$dst], $value4word, 0 - bne $word_mode_end, $dst, .Lword_mode - .Lword_mode_end: */ -- byte_mode_size = emit_setmem_word_loop (dst, size, value4word); -+ byte_mode_size = emit_setmem_doubleword_loop (dst, size, value4doubleword); - - /* beqz $byte_mode_size, .Lend - add $byte_mode_end, $dst, $byte_mode_size -@@ -633,8 +785,8 @@ nds32_expand_setmem_loop (rtx dstmem, rtx size, rtx value) - bne $byte_mode_end, $dst, .Lbyte_mode - .Lend: */ - -- value4byte = simplify_gen_subreg (QImode, value4word, SImode, -- subreg_lowpart_offset (QImode, SImode)); -+ value4byte = simplify_gen_subreg (QImode, value4doubleword, DImode, -+ subreg_lowpart_offset (QImode, DImode)); - - emit_setmem_byte_loop (dst, byte_mode_size, value4byte, false); - -@@ -651,14 +803,15 @@ nds32_expand_setmem_loop_v3m (rtx dstmem, rtx size, rtx value) - rtx byte_loop_size = gen_reg_rtx (SImode); - rtx remain_size = gen_reg_rtx (SImode); - rtx new_base_reg; -- rtx value4byte, value4word; -+ rtx value4byte, value4doubleword; - rtx byte_mode_size; - rtx last_byte_loop_label = gen_label_rtx (); - - size = force_reg (SImode, size); - -- value4word = nds32_gen_dup_4_byte_to_word_value (value); -- value4byte = simplify_gen_subreg (QImode, value4word, SImode, 0); -+ value4doubleword = nds32_gen_dup_8_byte_to_double_word_value (value); -+ value4byte = simplify_gen_subreg (QImode, value4doubleword, DImode, -+ subreg_lowpart_offset (QImode, DImode)); - - emit_move_insn (byte_loop_size, size); - emit_move_insn (byte_loop_base, base_reg); -@@ -686,9 +839,9 @@ nds32_expand_setmem_loop_v3m (rtx dstmem, rtx size, rtx value) - emit_insn (gen_subsi3 (remain_size, size, need_align_bytes)); - - /* Set memory word by word. */ -- byte_mode_size = emit_setmem_word_loop (new_base_reg, -- remain_size, -- value4word); -+ byte_mode_size = emit_setmem_doubleword_loop (new_base_reg, -+ remain_size, -+ value4doubleword); - - emit_move_insn (byte_loop_base, new_base_reg); - emit_move_insn (byte_loop_size, byte_mode_size); -diff --git a/gcc/config/nds32/nds32-multiple.md b/gcc/config/nds32/nds32-multiple.md -index a8f77175927..80746b19323 100644 ---- a/gcc/config/nds32/nds32-multiple.md -+++ b/gcc/config/nds32/nds32-multiple.md -@@ -2854,6 +2854,25 @@ - (set_attr "length" "4")] - ) - -+(define_expand "unaligned_store_update_base_dw" -+ [(parallel [(set (match_operand:SI 0 "register_operand" "=r") -+ (plus:SI (match_operand:SI 1 "register_operand" "0") (const_int 8))) -+ (set (mem:DI (match_dup 1)) -+ (unspec:DI [(match_operand:DI 2 "register_operand" "r")] UNSPEC_UASTORE_DW))])] -+ "" -+{ -+ /* DO NOT emit unaligned_store_w_m immediately since web pass don't -+ recognize post_inc, try it again after GCC 5.0. -+ REF: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63156 */ -+ emit_insn (gen_unaligned_store_dw (gen_rtx_MEM (DImode, operands[1]), operands[2])); -+ emit_insn (gen_addsi3 (operands[0], operands[1], gen_int_mode (8, Pmode))); -+ DONE; -+} -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "2") -+ (set_attr "length" "4")] -+) -+ - (define_insn "*stmsi25" - [(match_parallel 0 "nds32_store_multiple_operation" - [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -diff --git a/gcc/config/nds32/nds32-n10.md b/gcc/config/nds32/nds32-n10.md -new file mode 100644 -index 00000000000..0dd76da1ef8 ---- /dev/null -+++ b/gcc/config/nds32/nds32-n10.md -@@ -0,0 +1,439 @@ -+;; Pipeline descriptions 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 -+;; . -+ -+ -+;; ------------------------------------------------------------------------ -+;; Define N10 pipeline settings. -+;; ------------------------------------------------------------------------ -+ -+(define_automaton "nds32_n10_machine") -+ -+;; ------------------------------------------------------------------------ -+;; Pipeline Stages -+;; ------------------------------------------------------------------------ -+;; IF - Instruction Fetch -+;; II - Instruction Issue / Instruction Decode -+;; EX - Instruction Execution -+;; MM - Memory Execution -+;; WB - Instruction Retire / Result Write-Back -+ -+(define_cpu_unit "n10_ii" "nds32_n10_machine") -+(define_cpu_unit "n10_ex" "nds32_n10_machine") -+(define_cpu_unit "n10_mm" "nds32_n10_machine") -+(define_cpu_unit "n10_wb" "nds32_n10_machine") -+(define_cpu_unit "n10f_iq" "nds32_n10_machine") -+(define_cpu_unit "n10f_rf" "nds32_n10_machine") -+(define_cpu_unit "n10f_e1" "nds32_n10_machine") -+(define_cpu_unit "n10f_e2" "nds32_n10_machine") -+(define_cpu_unit "n10f_e3" "nds32_n10_machine") -+(define_cpu_unit "n10f_e4" "nds32_n10_machine") -+ -+(define_insn_reservation "nds_n10_unknown" 1 -+ (and (eq_attr "type" "unknown") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_misc" 1 -+ (and (eq_attr "type" "misc") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_mmu" 1 -+ (and (eq_attr "type" "mmu") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_alu" 1 -+ (and (eq_attr "type" "alu") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_alu_shift" 1 -+ (and (eq_attr "type" "alu_shift") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ii+n10_ex, n10_ex+n10_mm, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_pbsad" 1 -+ (and (eq_attr "type" "pbsad") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex*3, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_pbsada" 1 -+ (and (eq_attr "type" "pbsada") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex*3, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_load" 1 -+ (and (match_test "nds32::load_single_p (insn)") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_store" 1 -+ (and (match_test "nds32::store_single_p (insn)") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_load_multiple_1" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "1"))) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_load_multiple_2" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (ior (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "2")) -+ (match_test "nds32::load_double_p (insn)"))) -+ "n10_ii, n10_ii+n10_ex, n10_ex+n10_mm, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_load_multiple_3" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "3"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_load_multiple_4" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "4"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, n10_ii+n10_ex+n10_mm+n10_wb, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_load_multiple_5" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "5"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*2, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_load_multiple_6" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "6"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*3, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_load_multiple_7" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "7"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*4, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_load_multiple_N" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "load_multiple") -+ (match_test "get_attr_combo (insn) >= 8"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*5, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_store_multiple_1" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "1"))) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_store_multiple_2" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (ior (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "2")) -+ (match_test "nds32::store_double_p (insn)"))) -+ "n10_ii, n10_ii+n10_ex, n10_ex+n10_mm, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_store_multiple_3" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "3"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_store_multiple_4" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "4"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, n10_ii+n10_ex+n10_mm+n10_wb, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_store_multiple_5" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "5"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*2, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_store_multiple_6" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "6"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*3, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_store_multiple_7" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "7"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*4, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_store_multiple_N" 1 -+ (and (eq_attr "pipeline_model" "n10") -+ (and (eq_attr "type" "store_multiple") -+ (match_test "get_attr_combo (insn) >= 8"))) -+ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*5, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") -+ -+(define_insn_reservation "nds_n10_mul" 1 -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_mac" 1 -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_div" 1 -+ (and (eq_attr "type" "div") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex*34, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_branch" 1 -+ (and (eq_attr "type" "branch") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_alu" 1 -+ (and (eq_attr "type" "dalu") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_alu64" 1 -+ (and (eq_attr "type" "dalu64") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_alu_round" 1 -+ (and (eq_attr "type" "daluround") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_cmp" 1 -+ (and (eq_attr "type" "dcmp") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_clip" 1 -+ (and (eq_attr "type" "dclip") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_mul" 1 -+ (and (eq_attr "type" "dmul") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_mac" 1 -+ (and (eq_attr "type" "dmac") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_insb" 1 -+ (and (eq_attr "type" "dinsb") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_pack" 1 -+ (and (eq_attr "type" "dpack") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_bpick" 1 -+ (and (eq_attr "type" "dbpick") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_dsp_wext" 1 -+ (and (eq_attr "type" "dwext") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ex, n10_mm, n10_wb") -+ -+(define_insn_reservation "nds_n10_fpu_alu" 4 -+ (and (eq_attr "type" "falu") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_muls" 4 -+ (and (eq_attr "type" "fmuls") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_muld" 4 -+ (and (eq_attr "type" "fmuld") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2*2, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_macs" 4 -+ (and (eq_attr "type" "fmacs") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2*3, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_macd" 4 -+ (and (eq_attr "type" "fmacd") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2*4, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_divs" 4 -+ (and (ior (eq_attr "type" "fdivs") -+ (eq_attr "type" "fsqrts")) -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2*14, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_divd" 4 -+ (and (ior (eq_attr "type" "fdivd") -+ (eq_attr "type" "fsqrtd")) -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2*28, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_fast_alu" 2 -+ (and (ior (eq_attr "type" "fcmp") -+ (ior (eq_attr "type" "fabs") -+ (ior (eq_attr "type" "fcpy") -+ (eq_attr "type" "fcmov")))) -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_fmtsr" 4 -+ (and (eq_attr "type" "fmtsr") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_fmtdr" 4 -+ (and (eq_attr "type" "fmtdr") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ii+n10f_iq, n10f_iq+n10f_rf, n10f_rf+n10f_e1, n10f_e1+n10f_e2, n10f_e2+n10f_e3, n10f_e3+n10f_e4, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_fmfsr" 2 -+ (and (eq_attr "type" "fmfsr") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_fmfdr" 2 -+ (and (eq_attr "type" "fmfdr") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10_ii+n10f_iq, n10f_iq+n10f_rf, n10f_rf+n10f_e1, n10f_e1+n10f_e2, n10f_e2+n10f_e3, n10f_e3+n10f_e4, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_load" 3 -+ (and (eq_attr "type" "fload") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") -+ -+(define_insn_reservation "nds_n10_fpu_store" 1 -+ (and (eq_attr "type" "fstore") -+ (eq_attr "pipeline_model" "n10")) -+ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") -+ -+;; ------------------------------------------------------------------------ -+;; Comment Notations and Bypass Rules -+;; ------------------------------------------------------------------------ -+;; Producers (LHS) -+;; LD -+;; Load data from the memory and produce the loaded data. The result is -+;; ready at MM. -+;; LMW(N, M) -+;; There are N micro-operations within an instruction that loads multiple -+;; words. The result produced by the M-th micro-operation is sent to -+;; consumers. The result is ready at MM. -+;; MUL, MAC -+;; Compute data in the multiply-adder and produce the data. The result -+;; is ready at MM. -+;; DIV -+;; Compute data in the divider and produce the data. The result is ready -+;; at MM. -+;; -+;; Consumers (RHS) -+;; ALU, MOVD44, PBSAD, PBSADA_RaRb, MUL, MAC, DIV, MMU -+;; Require operands at EX. -+;; ALU_SHIFT_Rb -+;; An ALU-SHIFT instruction consists of a shift micro-operation followed -+;; by an arithmetic micro-operation. The operand Rb is used by the first -+;; micro-operation, and there are some latencies if data dependency occurs. -+;; MAC_RaRb -+;; A MAC instruction does multiplication at EX and does accumulation at MM, -+;; so the operand Rt is required at MM, and operands Ra and Rb are required -+;; at EX. -+;; ADDR_IN -+;; If an instruction requires an address as its input operand, the address -+;; is required at EX. -+;; ST -+;; A store instruction requires its data at MM. -+;; SMW(N, M) -+;; There are N micro-operations within an instruction that stores multiple -+;; words. Each M-th micro-operation requires its data at MM. -+;; BR -+;; If a branch instruction is conditional, its input data is required at EX. -+ -+;; FPU_ADDR_OUT -> FPU_ADDR_IN -+;; Main pipeline rules don't need this because those default latency is 1. -+(define_bypass 1 -+ "nds_n10_fpu_load, nds_n10_fpu_store" -+ "nds_n10_fpu_load, nds_n10_fpu_store" -+ "nds32_n10_ex_to_ex_p" -+) -+ -+;; LD, MUL, MAC, DIV, DALU64, DMUL, DMAC, DALUROUND, DBPICK, DWEXT -+;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44, MUL, MAC_RaRb, DIV, ADDR_IN, BR, MMU, -+;; DALU, DALUROUND, DMUL, DMAC_RaRb, DPACK, DINSB, DCMP, DCLIP, WEXT_O, BPICK_RaRb -+(define_bypass 2 -+ "nds_n10_load, nds_n10_mul, nds_n10_mac, nds_n10_div,\ -+ nds_n10_dsp_alu64, nds_n10_dsp_mul, nds_n10_dsp_mac,\ -+ nds_n10_dsp_alu_round, nds_n10_dsp_bpick, nds_n10_dsp_wext" -+ "nds_n10_alu, nds_n10_alu_shift,\ -+ nds_n10_pbsad, nds_n10_pbsada,\ -+ nds_n10_mul, nds_n10_mac, nds_n10_div,\ -+ nds_n10_branch,\ -+ nds_n10_load, nds_n10_store,\ -+ nds_n10_load_multiple_1, nds_n10_load_multiple_2, nds_n10_load_multiple_3,\ -+ nds_n10_load_multiple_4, nds_n10_load_multiple_5, nds_n10_load_multiple_6,\ -+ nds_n10_load_multiple_7, nds_n10_load_multiple_N,\ -+ nds_n10_store_multiple_1, nds_n10_store_multiple_2, nds_n10_store_multiple_3,\ -+ nds_n10_store_multiple_4, nds_n10_store_multiple_5, nds_n10_store_multiple_6,\ -+ nds_n10_store_multiple_7, nds_n10_store_multiple_N,\ -+ nds_n10_mmu,\ -+ nds_n10_dsp_alu, nds_n10_dsp_alu_round,\ -+ nds_n10_dsp_mul, nds_n10_dsp_mac, nds_n10_dsp_pack,\ -+ nds_n10_dsp_insb, nds_n10_dsp_cmp, nds_n10_dsp_clip,\ -+ nds_n10_dsp_wext, nds_n10_dsp_bpick" -+ "nds32_n10_mm_to_ex_p" -+) -+ -+;; LMW(N, N) -+;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44, MUL, MAC_RaRb, DIV, ADDR_IN, BR, MMU -+;; DALU, DALUROUND, DMUL, DMAC_RaRb, DPACK, DINSB, DCMP, DCLIP, WEXT_O, BPICK_RaRb -+(define_bypass 2 -+ "nds_n10_load_multiple_1, nds_n10_load_multiple_2, nds_n10_load_multiple_3,\ -+ nds_n10_load_multiple_4, nds_n10_load_multiple_5, nds_n10_load_multiple_6,\ -+ nds_n10_load_multiple_7, nds_n10_load_multiple_N" -+ "nds_n10_alu, nds_n10_alu_shift,\ -+ nds_n10_pbsad, nds_n10_pbsada,\ -+ nds_n10_mul, nds_n10_mac, nds_n10_div,\ -+ nds_n10_branch,\ -+ nds_n10_load, nds_n10_store,\ -+ nds_n10_load_multiple_1, nds_n10_load_multiple_2, nds_n10_load_multiple_3,\ -+ nds_n10_load_multiple_4, nds_n10_load_multiple_5, nds_n10_load_multiple_6,\ -+ nds_n10_load_multiple_7, nds_n10_load_multiple_N,\ -+ nds_n10_store_multiple_1, nds_n10_store_multiple_2, nds_n10_store_multiple_3,\ -+ nds_n10_store_multiple_4, nds_n10_store_multiple_5, nds_n10_store_multiple_6,\ -+ nds_n10_store_multiple_7, nds_n10_store_multiple_N,\ -+ nds_n10_mmu,\ -+ nds_n10_dsp_alu, nds_n10_dsp_alu_round,\ -+ nds_n10_dsp_mul, nds_n10_dsp_mac, nds_n10_dsp_pack,\ -+ nds_n10_dsp_insb, nds_n10_dsp_cmp, nds_n10_dsp_clip,\ -+ nds_n10_dsp_wext, nds_n10_dsp_bpick" -+ "nds32_n10_last_load_to_ex_p" -+) -diff --git a/gcc/config/nds32/nds32-n13.md b/gcc/config/nds32/nds32-n13.md -new file mode 100644 -index 00000000000..ca7546bc2a7 ---- /dev/null -+++ b/gcc/config/nds32/nds32-n13.md -@@ -0,0 +1,401 @@ -+;; Pipeline descriptions 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 -+;; . -+ -+ -+;; ------------------------------------------------------------------------ -+;; Define N13 pipeline settings. -+;; ------------------------------------------------------------------------ -+ -+(define_automaton "nds32_n13_machine") -+ -+;; ------------------------------------------------------------------------ -+;; Pipeline Stages -+;; ------------------------------------------------------------------------ -+;; F1 - Instruction Fetch First -+;; Instruction Tag/Data Arrays -+;; ITLB Address Translation -+;; Branch Target Buffer Prediction -+;; F2 - Instruction Fetch Second -+;; Instruction Cache Hit Detection -+;; Cache Way Selection -+;; Inustruction Alignment -+;; I1 - Instruction Issue First / Instruction Decode -+;; Instruction Cache Replay Triggering -+;; 32/16-Bit Instruction Decode -+;; Return Address Stack Prediction -+;; I2 - Instruction Issue Second / Register File Access -+;; Instruction Issue Logic -+;; Register File Access -+;; E1 - Instruction Execute First / Address Generation / MAC First -+;; Data Access Address generation -+;; Multiply Operation -+;; E2 - Instruction Execute Second / Data Access First / MAC Second / -+;; ALU Execute -+;; Skewed ALU -+;; Branch/Jump/Return Resolution -+;; Data Tag/Data arrays -+;; DTLB address translation -+;; Accumulation Operation -+;; E3 - Instruction Execute Third / Data Access Second -+;; Data Cache Hit Detection -+;; Cache Way Selection -+;; Data Alignment -+;; E4 - Instruction Execute Fourth / Write Back -+;; Interruption Resolution -+;; Instruction Retire -+;; Register File Write Back -+ -+(define_cpu_unit "n13_i1" "nds32_n13_machine") -+(define_cpu_unit "n13_i2" "nds32_n13_machine") -+(define_cpu_unit "n13_e1" "nds32_n13_machine") -+(define_cpu_unit "n13_e2" "nds32_n13_machine") -+(define_cpu_unit "n13_e3" "nds32_n13_machine") -+(define_cpu_unit "n13_e4" "nds32_n13_machine") -+ -+(define_insn_reservation "nds_n13_unknown" 1 -+ (and (eq_attr "type" "unknown") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_misc" 1 -+ (and (eq_attr "type" "misc") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_mmu" 1 -+ (and (eq_attr "type" "mmu") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_alu" 1 -+ (and (eq_attr "type" "alu") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_alu_shift" 1 -+ (and (eq_attr "type" "alu_shift") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i2+n13_e1, n13_e1+n13_e2, n13_e2+n13_e3, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_pbsad" 1 -+ (and (eq_attr "type" "pbsad") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2*2, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_pbsada" 1 -+ (and (eq_attr "type" "pbsada") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2*3, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_load" 1 -+ (and (match_test "nds32::load_single_p (insn)") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_store" 1 -+ (and (match_test "nds32::store_single_p (insn)") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_load_multiple_1" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_load_multiple_2" 1 -+ (and (ior (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "2")) -+ (match_test "nds32::load_double_p (insn)")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i2+n13_e1, n13_e1+n13_e2, n13_e2+n13_e3, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_load_multiple_3" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2+n13_i2, n13_i1+n13_i2+n13_e1, n13_i2+n13_e1+n13_e2, n13_e1+n13_e2+n13_e3, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_load_multiple_4" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i2+n13_e1+n13_e2+n13_e3, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_load_multiple_5" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_load_multiple_6" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "6")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_load_multiple_7" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*2, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_load_multiple_8" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*3, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_load_multiple_12" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*7, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_store_multiple_1" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_store_multiple_2" 1 -+ (and (ior (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "2")) -+ (match_test "nds32::store_double_p (insn)")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i2+n13_e1, n13_e1+n13_e2, n13_e2+n13_e3, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_store_multiple_3" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2+n13_i2, n13_i1+n13_i2+n13_e1, n13_i2+n13_e1+n13_e2, n13_e1+n13_e2+n13_e3, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_store_multiple_4" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i2+n13_e1+n13_e2+n13_e3, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_store_multiple_5" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_store_multiple_6" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "6")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_store_multiple_7" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*2, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_store_multiple_8" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*3, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+(define_insn_reservation "nds_n13_store_multiple_12" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*7, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") -+ -+;; The multiplier at E1 takes two cycles. -+(define_insn_reservation "nds_n13_mul" 1 -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1*2, n13_e2, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_mac" 1 -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1*2, n13_e2, n13_e3, n13_e4") -+ -+;; The cycles consumed at E2 are 32 - CLZ(abs(Ra)) + 2, -+;; so the worst case is 34. -+(define_insn_reservation "nds_n13_div" 1 -+ (and (eq_attr "type" "div") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2*34, n13_e3, n13_e4") -+ -+(define_insn_reservation "nds_n13_branch" 1 -+ (and (eq_attr "type" "branch") -+ (eq_attr "pipeline_model" "n13")) -+ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") -+ -+;; ------------------------------------------------------------------------ -+;; Comment Notations and Bypass Rules -+;; ------------------------------------------------------------------------ -+;; Producers (LHS) -+;; LD -+;; Load data from the memory and produce the loaded data. The result is -+;; ready at E3. -+;; LMW(N, M) -+;; There are N micro-operations within an instruction that loads multiple -+;; words. The result produced by the M-th micro-operation is sent to -+;; consumers. The result is ready at E3. -+;; ADDR_OUT -+;; Most load/store instructions can produce an address output if updating -+;; the base register is required. The result is ready at E2, which is -+;; produced by ALU. -+;; ALU, ALU_SHIFT, SIMD -+;; Compute data in ALU and produce the data. The result is ready at E2. -+;; MUL, MAC -+;; Compute data in the multiply-adder and produce the data. The result -+;; is ready at E2. -+;; DIV -+;; Compute data in the divider and produce the data. The result is ready -+;; at E2. -+;; BR -+;; Branch-with-link instructions produces a result containing the return -+;; address. The result is ready at E2. -+;; -+;; Consumers (RHS) -+;; ALU -+;; General ALU instructions require operands at E2. -+;; ALU_E1 -+;; Some special ALU instructions, such as BSE, BSP and MOVD44, require -+;; operand at E1. -+;; MUL, DIV, PBSAD, MMU -+;; Operands are required at E1. -+;; PBSADA_Rt, PBSADA_RaRb -+;; Operands Ra and Rb are required at E1, and the operand Rt is required -+;; at E2. -+;; ALU_SHIFT_Rb -+;; An ALU-SHIFT instruction consists of a shift micro-operation followed -+;; by an arithmetic micro-operation. The operand Rb is used by the first -+;; micro-operation, and there are some latencies if data dependency occurs. -+;; MAC_RaRb -+;; A MAC instruction does multiplication at E1 and does accumulation at E2, -+;; so the operand Rt is required at E2, and operands Ra and Rb are required -+;; at E1. -+;; ADDR_IN -+;; If an instruction requires an address as its input operand, the address -+;; is required at E1. -+;; ST -+;; A store instruction requires its data at E2. -+;; SMW(N, M) -+;; There are N micro-operations within an instruction that stores multiple -+;; words. Each M-th micro-operation requires its data at E2. -+;; BR -+;; If a branch instruction is conditional, its input data is required at E2. -+ -+;; LD -> ALU_E1, PBSAD, PBSADA_RaRb, MUL, MAC_RaRb, DIV, MMU, ADDR_IN -+(define_bypass 3 -+ "nds_n13_load" -+ "nds_n13_alu, nds_n13_pbsad, nds_n13_pbsada,\ -+ nds_n13_mul, nds_n13_mac, nds_n13_div,\ -+ nds_n13_mmu,\ -+ nds_n13_load, nds_n13_store,\ -+ nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ -+ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ -+ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12,\ -+ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ -+ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ -+ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" -+ "nds32_n13_load_to_e1_p" -+) -+ -+;; LD -> ALU, ALU_SHIFT_Rb, PBSADA_Rt, BR, ST, SMW(N, 1) -+(define_bypass 2 -+ "nds_n13_load" -+ "nds_n13_alu, nds_n13_alu_shift, nds_n13_pbsada, nds_n13_branch, nds_n13_store,\ -+ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ -+ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ -+ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" -+ "nds32_n13_load_to_e2_p" -+) -+ -+;; LMW(N, N) -> ALU_E1, PBSAD, PBSADA_RaRb, MUL, MAC_RaRb, DIV, MMU, ADDR_IN -+(define_bypass 3 -+ "nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ -+ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ -+ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12" -+ "nds_n13_alu, nds_n13_pbsad, nds_n13_pbsada,\ -+ nds_n13_mul, nds_n13_mac, nds_n13_div,\ -+ nds_n13_mmu,\ -+ nds_n13_load, nds_n13_store,\ -+ nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ -+ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ -+ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12,\ -+ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ -+ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ -+ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" -+ "nds32_n13_last_load_to_e1_p") -+ -+;; LMW(N, N) -> ALU, ALU_SHIFT_Rb, PBSADA_Rt, BR, ST, SMW(N, 1) -+(define_bypass 2 -+ "nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ -+ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ -+ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12" -+ "nds_n13_alu, nds_n13_alu_shift, nds_n13_pbsada, nds_n13_branch, nds_n13_store,\ -+ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ -+ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ -+ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" -+ "nds32_n13_last_load_to_e2_p" -+) -+ -+;; LMW(N, N - 1) -> ALU_E1, PBSAD, PBSADA_RaRb, MUL, MAC_RaRb, DIV, MMU, ADDR_IN -+(define_bypass 2 -+ "nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ -+ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ -+ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12" -+ "nds_n13_alu, nds_n13_pbsad, nds_n13_pbsada,\ -+ nds_n13_mul, nds_n13_mac, nds_n13_div,\ -+ nds_n13_mmu,\ -+ nds_n13_load, nds_n13_store,\ -+ nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ -+ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ -+ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12,\ -+ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ -+ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ -+ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" -+ "nds32_n13_last_two_load_to_e1_p") -+ -+;; ALU, ALU_SHIFT, SIMD, BR, MUL, MAC, DIV, ADDR_OUT -+;; -> ALU_E1, PBSAD, PBSADA_RaRb, MUL, MAC_RaRb, DIV, MMU, ADDR_IN -+(define_bypass 2 -+ "nds_n13_alu, nds_n13_alu_shift, nds_n13_pbsad, nds_n13_pbsada, nds_n13_branch,\ -+ nds_n13_mul, nds_n13_mac, nds_n13_div,\ -+ nds_n13_load, nds_n13_store,\ -+ nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ -+ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ -+ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12,\ -+ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ -+ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ -+ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" -+ "nds_n13_alu, nds_n13_pbsad, nds_n13_pbsada,\ -+ nds_n13_mul, nds_n13_mac, nds_n13_div,\ -+ nds_n13_mmu,\ -+ nds_n13_load, nds_n13_store,\ -+ nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ -+ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ -+ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12,\ -+ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ -+ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ -+ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" -+ "nds32_n13_e2_to_e1_p") -diff --git a/gcc/config/nds32/nds32-opts.h b/gcc/config/nds32/nds32-opts.h -index 5d7e1652749..8d761964439 100644 ---- a/gcc/config/nds32/nds32-opts.h -+++ b/gcc/config/nds32/nds32-opts.h -@@ -29,6 +29,7 @@ enum nds32_arch_type - { - ARCH_V2, - ARCH_V3, -+ ARCH_V3J, - ARCH_V3M, - ARCH_V3F, - ARCH_V3S -@@ -42,6 +43,10 @@ enum nds32_cpu_type - CPU_N8, - CPU_E8, - CPU_N9, -+ CPU_N10, -+ CPU_GRAYWOLF, -+ CPU_N12, -+ CPU_N13, - CPU_SIMPLE - }; - -@@ -53,6 +58,13 @@ enum nds32_cmodel_type - CMODEL_LARGE - }; - -+/* The code model defines the address generation strategy. */ -+enum nds32_ict_model_type -+{ -+ ICT_MODEL_SMALL, -+ ICT_MODEL_LARGE -+}; -+ - /* Multiply instruction configuration. */ - enum nds32_mul_type - { -diff --git a/gcc/config/nds32/nds32-peephole2.md b/gcc/config/nds32/nds32-peephole2.md -index a5e77b1dcc7..033f62bae5a 100644 ---- a/gcc/config/nds32/nds32-peephole2.md -+++ b/gcc/config/nds32/nds32-peephole2.md -@@ -22,3 +22,139 @@ - ;; Use define_peephole2 to handle possible target-specific optimization. - - ;; ------------------------------------------------------------------------ -+;; Try to utilize 16-bit instruction by swap operand if possible. -+;; ------------------------------------------------------------------------ -+ -+;; Try to make add as add45. -+(define_peephole2 -+ [(set (match_operand:QIHISI 0 "register_operand" "") -+ (plus:QIHISI (match_operand:QIHISI 1 "register_operand" "") -+ (match_operand:QIHISI 2 "register_operand" "")))] -+ "reload_completed -+ && TARGET_16_BIT -+ && REGNO (operands[0]) == REGNO (operands[2]) -+ && REGNO (operands[0]) != REGNO (operands[1]) -+ && TEST_HARD_REG_BIT (reg_class_contents[MIDDLE_REGS], REGNO (operands[0]))" -+ [(set (match_dup 0) (plus:QIHISI (match_dup 2) (match_dup 1)))]) -+ -+;; Try to make xor/ior/and/mult as xor33/ior33/and33/mult33. -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operator:SI 1 "nds32_have_33_inst_operator" -+ [(match_operand:SI 2 "register_operand" "") -+ (match_operand:SI 3 "register_operand" "")]))] -+ "reload_completed -+ && TARGET_16_BIT -+ && REGNO (operands[0]) == REGNO (operands[3]) -+ && REGNO (operands[0]) != REGNO (operands[2]) -+ && TEST_HARD_REG_BIT (reg_class_contents[LOW_REGS], REGNO (operands[0])) -+ && TEST_HARD_REG_BIT (reg_class_contents[LOW_REGS], REGNO (operands[2]))" -+ [(set (match_dup 0) (match_op_dup 1 [(match_dup 3) (match_dup 2)]))]) -+ -+(define_peephole -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "")) -+ (set (match_operand:SI 2 "register_operand" "") -+ (match_operand:SI 3 "register_operand" ""))] -+ "TARGET_16_BIT -+ && !TARGET_ISA_V2 -+ && NDS32_IS_GPR_REGNUM (REGNO (operands[0])) -+ && NDS32_IS_GPR_REGNUM (REGNO (operands[1])) -+ && ((REGNO (operands[0]) & 0x1) == 0) -+ && ((REGNO (operands[1]) & 0x1) == 0) -+ && (REGNO (operands[0]) + 1) == REGNO (operands[2]) -+ && (REGNO (operands[1]) + 1) == REGNO (operands[3])" -+ "movd44\t%0, %1" -+ [(set_attr "type" "alu") -+ (set_attr "length" "2")]) -+ -+;; Merge two fcpyss to fcpysd. -+(define_peephole2 -+ [(set (match_operand:SF 0 "float_even_register_operand" "") -+ (match_operand:SF 1 "float_even_register_operand" "")) -+ (set (match_operand:SF 2 "float_odd_register_operand" "") -+ (match_operand:SF 3 "float_odd_register_operand" ""))] -+ "(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) -+ && REGNO (operands[0]) == REGNO (operands[2]) - 1 -+ && REGNO (operands[1]) == REGNO (operands[3]) - 1" -+ [(set (match_dup 4) (match_dup 5))] -+ { -+ operands[4] = gen_rtx_REG (DFmode, REGNO (operands[0])); -+ operands[5] = gen_rtx_REG (DFmode, REGNO (operands[1])); -+ }) -+ -+(define_peephole2 -+ [(set (match_operand:SF 0 "float_odd_register_operand" "") -+ (match_operand:SF 1 "float_odd_register_operand" "")) -+ (set (match_operand:SF 2 "float_even_register_operand" "") -+ (match_operand:SF 3 "float_even_register_operand" ""))] -+ "(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) -+ && REGNO (operands[2]) == REGNO (operands[0]) - 1 -+ && REGNO (operands[3]) == REGNO (operands[1]) - 1" -+ [(set (match_dup 4) (match_dup 5))] -+ { -+ operands[4] = gen_rtx_REG (DFmode, REGNO (operands[2])); -+ operands[5] = gen_rtx_REG (DFmode, REGNO (operands[3])); -+ }) -+ -+;; ------------------------------------------------------------------------ -+;; GCC will prefer [u]divmodsi3 rather than [u]divsi3 even remainder is -+;; unused, so we use split to drop mod operation for lower register pressure. -+ -+(define_split -+ [(set (match_operand:SI 0 "register_operand") -+ (div:SI (match_operand:SI 1 "register_operand") -+ (match_operand:SI 2 "register_operand"))) -+ (set (match_operand:SI 3 "register_operand") -+ (mod:SI (match_dup 1) (match_dup 2)))] -+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[3])) != NULL -+ && can_create_pseudo_p ()" -+ [(set (match_dup 0) -+ (div:SI (match_dup 1) -+ (match_dup 2)))]) -+ -+(define_split -+ [(set (match_operand:SI 0 "register_operand") -+ (udiv:SI (match_operand:SI 1 "register_operand") -+ (match_operand:SI 2 "register_operand"))) -+ (set (match_operand:SI 3 "register_operand") -+ (umod:SI (match_dup 1) (match_dup 2)))] -+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[3])) != NULL -+ && can_create_pseudo_p ()" -+ [(set (match_dup 0) -+ (udiv:SI (match_dup 1) -+ (match_dup 2)))]) -+ -+(define_peephole2 -+ [(set (match_operand:DI 0 "register_operand") -+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand")) -+ (sign_extend:DI (match_operand:SI 2 "register_operand"))))] -+ "NDS32_EXT_DSP_P () -+ && peep2_regno_dead_p (1, WORDS_BIG_ENDIAN ? REGNO (operands[0]) + 1 : REGNO (operands[0]))" -+ [(const_int 1)] -+{ -+ rtx highpart = nds32_di_high_part_subreg (operands[0]); -+ emit_insn (gen_smulsi3_highpart (highpart, operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_split -+ [(set (match_operand:DI 0 "nds32_general_register_operand" "") -+ (match_operand:DI 1 "nds32_general_register_operand" ""))] -+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) != NULL -+ || find_regno_note (insn, REG_UNUSED, REGNO (operands[0]) + 1) != NULL" -+ [(set (match_dup 0) (match_dup 1))] -+{ -+ rtx dead_note = find_regno_note (curr_insn, REG_UNUSED, REGNO (operands[0])); -+ HOST_WIDE_INT offset; -+ if (dead_note == NULL_RTX) -+ offset = 0; -+ else -+ offset = 4; -+ operands[0] = simplify_gen_subreg ( -+ SImode, operands[0], -+ DImode, offset); -+ operands[1] = simplify_gen_subreg ( -+ SImode, operands[1], -+ DImode, offset); -+}) -diff --git a/gcc/config/nds32/nds32-pipelines-auxiliary.c b/gcc/config/nds32/nds32-pipelines-auxiliary.c -index a983238cdbb..53619d22510 100644 ---- a/gcc/config/nds32/nds32-pipelines-auxiliary.c -+++ b/gcc/config/nds32/nds32-pipelines-auxiliary.c -@@ -306,6 +306,19 @@ pbsada_insn_ra_rb_dep_reg_p (rtx pbsada_insn, rtx def_reg) - return false; - } - -+/* Determine if the latency is occured when the consumer PBSADA_INSN uses the -+ value of DEF_REG in its Rt field. */ -+bool -+pbsada_insn_rt_dep_reg_p (rtx pbsada_insn, rtx def_reg) -+{ -+ rtx pbsada_rt = SET_DEST (PATTERN (pbsada_insn)); -+ -+ if (rtx_equal_p (def_reg, pbsada_rt)) -+ return true; -+ -+ return false; -+} -+ - /* Check if INSN is a movd44 insn consuming DEF_REG. */ - bool - movd44_even_dep_p (rtx_insn *insn, rtx def_reg) -@@ -335,6 +348,103 @@ movd44_even_dep_p (rtx_insn *insn, rtx def_reg) - return false; - } - -+/* Check if INSN is a wext insn consuming DEF_REG. */ -+bool -+wext_odd_dep_p (rtx insn, rtx def_reg) -+{ -+ rtx shift_rtx = XEXP (SET_SRC (PATTERN (insn)), 0); -+ rtx use_reg = XEXP (shift_rtx, 0); -+ rtx pos_rtx = XEXP (shift_rtx, 1); -+ -+ if (REG_P (pos_rtx) && reg_overlap_p (def_reg, pos_rtx)) -+ return true; -+ -+ if (GET_MODE (def_reg) == DImode) -+ return reg_overlap_p (def_reg, use_reg); -+ -+ gcc_assert (REG_P (def_reg) || GET_CODE (def_reg) == SUBREG); -+ gcc_assert (REG_P (use_reg)); -+ -+ if (REG_P (def_reg)) -+ { -+ if (!TARGET_BIG_ENDIAN) -+ return REGNO (def_reg) == REGNO (use_reg) + 1; -+ else -+ return REGNO (def_reg) == REGNO (use_reg); -+ } -+ -+ if (GET_CODE (def_reg) == SUBREG) -+ { -+ if (!reg_overlap_p (def_reg, use_reg)) -+ return false; -+ -+ if (!TARGET_BIG_ENDIAN) -+ return SUBREG_BYTE (def_reg) == 4; -+ else -+ return SUBREG_BYTE (def_reg) == 0; -+ } -+ -+ return false; -+} -+ -+/* Check if INSN is a bpick insn consuming DEF_REG. */ -+bool -+bpick_ra_rb_dep_p (rtx insn, rtx def_reg) -+{ -+ rtx ior_rtx = SET_SRC (PATTERN (insn)); -+ rtx and1_rtx = XEXP (ior_rtx, 0); -+ rtx and2_rtx = XEXP (ior_rtx, 1); -+ rtx reg1_0 = XEXP (and1_rtx, 0); -+ rtx reg1_1 = XEXP (and1_rtx, 1); -+ rtx reg2_0 = XEXP (and2_rtx, 0); -+ rtx reg2_1 = XEXP (and2_rtx, 1); -+ -+ if (GET_CODE (reg1_0) == NOT) -+ { -+ if (rtx_equal_p (reg1_0, reg2_0)) -+ return reg_overlap_p (def_reg, reg1_1) -+ || reg_overlap_p (def_reg, reg2_1); -+ -+ if (rtx_equal_p (reg1_0, reg2_1)) -+ return reg_overlap_p (def_reg, reg1_1) -+ || reg_overlap_p (def_reg, reg2_0); -+ } -+ -+ if (GET_CODE (reg1_1) == NOT) -+ { -+ if (rtx_equal_p (reg1_1, reg2_0)) -+ return reg_overlap_p (def_reg, reg1_0) -+ || reg_overlap_p (def_reg, reg2_1); -+ -+ if (rtx_equal_p (reg1_1, reg2_1)) -+ return reg_overlap_p (def_reg, reg1_0) -+ || reg_overlap_p (def_reg, reg2_0); -+ } -+ -+ if (GET_CODE (reg2_0) == NOT) -+ { -+ if (rtx_equal_p (reg2_0, reg1_0)) -+ return reg_overlap_p (def_reg, reg2_1) -+ || reg_overlap_p (def_reg, reg1_1); -+ -+ if (rtx_equal_p (reg2_0, reg1_1)) -+ return reg_overlap_p (def_reg, reg2_1) -+ || reg_overlap_p (def_reg, reg1_0); -+ } -+ -+ if (GET_CODE (reg2_1) == NOT) -+ { -+ if (rtx_equal_p (reg2_1, reg1_0)) -+ return reg_overlap_p (def_reg, reg2_0) -+ || reg_overlap_p (def_reg, reg1_1); -+ -+ if (rtx_equal_p (reg2_1, reg1_1)) -+ return reg_overlap_p (def_reg, reg2_0) -+ || reg_overlap_p (def_reg, reg1_0); -+ } -+ -+ gcc_unreachable (); -+} - } // namespace scheduling - } // namespace nds32 - -@@ -375,8 +485,7 @@ n7_consumed_by_ii_dep_p (rtx_insn *consumer, rtx def_reg) - operations in order to write two registers. We have to check the - dependency from the producer to the first micro-operation. */ - case TYPE_DIV: -- if (INSN_CODE (consumer) == CODE_FOR_divmodsi4 -- || INSN_CODE (consumer) == CODE_FOR_udivmodsi4) -+ if (divmod_p (consumer)) - use_rtx = SET_SRC (parallel_element (consumer, 0)); - else - use_rtx = SET_SRC (PATTERN (consumer)); -@@ -506,8 +615,7 @@ n8_consumed_by_ex_p (rtx_insn *consumer, rtx def_reg) - operations in order to write two registers. We have to check the - dependency from the producer to the first micro-operation. */ - case TYPE_DIV: -- if (INSN_CODE (consumer) == CODE_FOR_divmodsi4 -- || INSN_CODE (consumer) == CODE_FOR_udivmodsi4) -+ if (divmod_p (consumer)) - use_rtx = SET_SRC (parallel_element (consumer, 0)); - else - use_rtx = SET_SRC (PATTERN (consumer)); -@@ -606,8 +714,7 @@ n9_2r1w_consumed_by_ex_dep_p (rtx_insn *consumer, rtx def_reg) - break; - - case TYPE_DIV: -- if (INSN_CODE (consumer) == CODE_FOR_divmodsi4 -- || INSN_CODE (consumer) == CODE_FOR_udivmodsi4) -+ if (divmod_p (consumer)) - use_rtx = SET_SRC (parallel_element (consumer, 0)); - else - use_rtx = SET_SRC (PATTERN (consumer)); -@@ -706,8 +813,7 @@ n9_3r2w_consumed_by_ex_dep_p (rtx_insn *consumer, rtx def_reg) - We have to check the dependency from the producer to the first - micro-operation. */ - case TYPE_DIV: -- if (INSN_CODE (consumer) == CODE_FOR_divmodsi4 -- || INSN_CODE (consumer) == CODE_FOR_udivmodsi4) -+ if (divmod_p (consumer)) - use_rtx = SET_SRC (parallel_element (consumer, 0)); - else - use_rtx = SET_SRC (PATTERN (consumer)); -@@ -744,7 +850,316 @@ n9_3r2w_consumed_by_ex_dep_p (rtx_insn *consumer, rtx def_reg) - return false; - } - -+/* Check the dependency between the producer defining DEF_REG and CONSUMER -+ requiring input operand at EX. */ -+bool -+n10_consumed_by_ex_dep_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ case TYPE_ALU: -+ case TYPE_PBSAD: -+ case TYPE_MUL: -+ case TYPE_DALU: -+ case TYPE_DALU64: -+ case TYPE_DMUL: -+ case TYPE_DPACK: -+ case TYPE_DINSB: -+ case TYPE_DCMP: -+ case TYPE_DCLIP: -+ case TYPE_DALUROUND: -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_ALU_SHIFT: -+ use_rtx = extract_shift_reg (consumer); -+ break; -+ -+ case TYPE_PBSADA: -+ return pbsada_insn_ra_rb_dep_reg_p (consumer, def_reg); -+ -+ case TYPE_MAC: -+ case TYPE_DMAC: -+ use_rtx = extract_mac_non_acc_rtx (consumer); -+ break; -+ -+ /* Some special instructions, divmodsi4 and udivmodsi4, produce two -+ results, the quotient and the remainder. */ -+ case TYPE_DIV: -+ if (divmod_p (consumer)) -+ use_rtx = SET_SRC (parallel_element (consumer, 0)); -+ else -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_DWEXT: -+ return wext_odd_dep_p (consumer, def_reg); -+ -+ case TYPE_DBPICK: -+ return bpick_ra_rb_dep_p (consumer, def_reg); -+ -+ case TYPE_MMU: -+ if (GET_CODE (PATTERN (consumer)) == SET) -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ else -+ return true; -+ break; -+ -+ case TYPE_LOAD: -+ case TYPE_STORE: -+ use_rtx = extract_mem_rtx (consumer); -+ break; -+ -+ case TYPE_LOAD_MULTIPLE: -+ case TYPE_STORE_MULTIPLE: -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ case TYPE_BRANCH: -+ use_rtx = PATTERN (consumer); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ if (reg_overlap_p (def_reg, use_rtx)) -+ return true; -+ -+ return false; -+} -+ -+/* Check the dependency between the producer defining DEF_REG and CONSUMER -+ requiring input operand at EX. */ -+bool -+gw_consumed_by_ex_dep_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ case TYPE_ALU: -+ case TYPE_PBSAD: -+ case TYPE_MUL: -+ case TYPE_DALU: -+ case TYPE_DALU64: -+ case TYPE_DMUL: -+ case TYPE_DPACK: -+ case TYPE_DINSB: -+ case TYPE_DCMP: -+ case TYPE_DCLIP: -+ case TYPE_DALUROUND: -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_ALU_SHIFT: -+ use_rtx = extract_shift_reg (consumer); -+ break; -+ -+ case TYPE_PBSADA: -+ return pbsada_insn_ra_rb_dep_reg_p (consumer, def_reg); -+ -+ case TYPE_MAC: -+ case TYPE_DMAC: -+ use_rtx = extract_mac_non_acc_rtx (consumer); -+ break; -+ -+ /* Some special instructions, divmodsi4 and udivmodsi4, produce two -+ results, the quotient and the remainder. We have to check the -+ dependency from the producer to the first micro-operation. */ -+ case TYPE_DIV: -+ if (divmod_p (consumer)) -+ use_rtx = SET_SRC (parallel_element (consumer, 0)); -+ else -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_DWEXT: -+ return wext_odd_dep_p (consumer, def_reg); -+ -+ case TYPE_DBPICK: -+ return bpick_ra_rb_dep_p (consumer, def_reg); -+ -+ case TYPE_MMU: -+ if (GET_CODE (PATTERN (consumer)) == SET) -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ else -+ return true; -+ break; -+ -+ case TYPE_LOAD: -+ case TYPE_STORE: -+ use_rtx = extract_mem_rtx (consumer); -+ break; -+ -+ case TYPE_LOAD_MULTIPLE: -+ case TYPE_STORE_MULTIPLE: -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ case TYPE_BRANCH: -+ use_rtx = PATTERN (consumer); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ if (reg_overlap_p (def_reg, use_rtx)) -+ return true; -+ -+ return false; -+} -+ -+/* Check dependencies from any stages to ALU_E1 (E1). This is a helper -+ function of n13_consumed_by_e1_dep_p (). */ -+bool -+n13_alu_e1_insn_dep_reg_p (rtx_insn *alu_e1_insn, rtx def_reg) -+{ -+ rtx unspec_rtx, operand_ra, operand_rb; -+ rtx src_rtx, dst_rtx; -+ -+ switch (INSN_CODE (alu_e1_insn)) -+ { -+ /* BSP and BSE are supported by built-in functions, the corresponding -+ patterns are formed by UNSPEC RTXs. We have to handle them -+ individually. */ -+ case CODE_FOR_unspec_bsp: -+ case CODE_FOR_unspec_bse: -+ unspec_rtx = SET_SRC (parallel_element (alu_e1_insn, 0)); -+ gcc_assert (GET_CODE (unspec_rtx) == UNSPEC); -+ -+ operand_ra = XVECEXP (unspec_rtx, 0, 0); -+ operand_rb = XVECEXP (unspec_rtx, 0, 1); -+ -+ if (rtx_equal_p (def_reg, operand_ra) -+ || rtx_equal_p (def_reg, operand_rb)) -+ return true; -+ -+ return false; -+ -+ /* Unlink general ALU instructions, MOVD44 requires operands at E1. */ -+ case CODE_FOR_move_di: -+ case CODE_FOR_move_df: -+ src_rtx = SET_SRC (PATTERN (alu_e1_insn)); -+ dst_rtx = SET_DEST (PATTERN (alu_e1_insn)); -+ -+ if (REG_P (dst_rtx) && REG_P (src_rtx) -+ && rtx_equal_p (src_rtx, def_reg)) -+ return true; -+ -+ return false; -+ -+ default: -+ return false; -+ } -+} -+ -+/* Check the dependency between the producer defining DEF_REG and CONSUMER -+ requiring input operand at E1. Because the address generation unti is -+ at E1, the address input should be ready at E1. Note that the branch -+ target is also a kind of addresses, so we have to check it. */ -+bool -+n13_consumed_by_e1_dep_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ /* ALU_E1 */ -+ case TYPE_ALU: -+ return n13_alu_e1_insn_dep_reg_p (consumer, def_reg); -+ -+ case TYPE_PBSADA: -+ return pbsada_insn_ra_rb_dep_reg_p (consumer, def_reg); -+ -+ case TYPE_PBSAD: -+ case TYPE_MUL: -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_MAC: -+ use_rtx = extract_mac_non_acc_rtx (consumer); -+ break; -+ -+ case TYPE_DIV: -+ if (divmod_p (consumer)) -+ use_rtx = SET_SRC (parallel_element (consumer, 0)); -+ else -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_MMU: -+ if (GET_CODE (PATTERN (consumer)) == SET) -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ else -+ return true; -+ break; -+ -+ case TYPE_BRANCH: -+ use_rtx = extract_branch_target_rtx (consumer); -+ break; -+ -+ case TYPE_LOAD: -+ case TYPE_STORE: -+ use_rtx = extract_mem_rtx (consumer); -+ break; -+ -+ case TYPE_LOAD_MULTIPLE: -+ case TYPE_STORE_MULTIPLE: -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ default: -+ return false; -+ } -+ -+ if (reg_overlap_p (def_reg, use_rtx)) -+ return true; -+ -+ return false; -+} -+ -+/* Check the dependency between the producer defining DEF_REG and CONSUMER -+ requiring input operand at E2. */ -+bool -+n13_consumed_by_e2_dep_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ case TYPE_ALU: -+ case TYPE_STORE: -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_ALU_SHIFT: -+ use_rtx = extract_shift_reg (consumer); -+ break; -+ -+ case TYPE_PBSADA: -+ return pbsada_insn_rt_dep_reg_p (consumer, def_reg); -+ -+ case TYPE_STORE_MULTIPLE: -+ use_rtx = extract_nth_access_rtx (consumer, 0); -+ break; -+ -+ case TYPE_BRANCH: -+ use_rtx = extract_branch_condition_rtx (consumer); -+ break; -+ -+ default: -+ gcc_unreachable(); -+ } -+ -+ if (reg_overlap_p (def_reg, use_rtx)) -+ return true; - -+ return false; -+} - } // anonymous namespace - - /* ------------------------------------------------------------------------ */ -@@ -837,8 +1252,7 @@ nds32_n8_ex_to_ii_p (rtx_insn *producer, rtx_insn *consumer) - break; - - case TYPE_DIV: -- if (INSN_CODE (producer) == CODE_FOR_divmodsi4 -- || INSN_CODE (producer) == CODE_FOR_udivmodsi4) -+ if (divmod_p (producer)) - def_reg = SET_DEST (parallel_element (producer, 1)); - else - def_reg = SET_DEST (PATTERN (producer)); -@@ -969,8 +1383,7 @@ nds32_e8_ex_to_ii_p (rtx_insn *producer, rtx_insn *consumer) - break; - - case TYPE_DIV: -- if (INSN_CODE (producer) == CODE_FOR_divmodsi4 -- || INSN_CODE (producer) == CODE_FOR_udivmodsi4) -+ if (divmod_p (producer)) - { - rtx def_reg1 = SET_DEST (parallel_element (producer, 0)); - rtx def_reg2 = SET_DEST (parallel_element (producer, 1)); -@@ -1073,8 +1486,7 @@ nds32_n9_3r2w_mm_to_ex_p (rtx_insn *producer, rtx_insn *consumer) - results, the quotient and the remainder. We have to handle them - individually. */ - case TYPE_DIV: -- if (INSN_CODE (producer) == CODE_FOR_divmodsi4 -- || INSN_CODE (producer) == CODE_FOR_udivmodsi4) -+ if (divmod_p (producer)) - { - rtx def_reg1 = SET_DEST (parallel_element (producer, 0)); - rtx def_reg2 = SET_DEST (parallel_element (producer, 1)); -@@ -1132,4 +1544,245 @@ nds32_n9_last_load_to_ex_p (rtx_insn *producer, rtx_insn *consumer) - return n9_3r2w_consumed_by_ex_dep_p (consumer, last_def_reg); - } - -+/* Guard functions for N10 cores. */ -+ -+/* Check dependencies from EX to EX (ADDR_OUT -> ADDR_IN). */ -+bool -+nds32_n10_ex_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ gcc_assert (get_attr_type (producer) == TYPE_FLOAD -+ || get_attr_type (producer) == TYPE_FSTORE); -+ gcc_assert (get_attr_type (consumer) == TYPE_FLOAD -+ || get_attr_type (consumer) == TYPE_FSTORE); -+ -+ if (!post_update_insn_p (producer)) -+ return false; -+ -+ return reg_overlap_p (extract_base_reg (producer), -+ extract_mem_rtx (consumer)); -+} -+ -+/* Check dependencies from MM to EX. */ -+bool -+nds32_n10_mm_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_LOAD: -+ case TYPE_MUL: -+ case TYPE_MAC: -+ case TYPE_DALU64: -+ case TYPE_DMUL: -+ case TYPE_DMAC: -+ case TYPE_DALUROUND: -+ case TYPE_DBPICK: -+ case TYPE_DWEXT: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ /* Some special instructions, divmodsi4 and udivmodsi4, produce two -+ results, the quotient and the remainder. We have to handle them -+ individually. */ -+ case TYPE_DIV: -+ if (divmod_p (producer)) -+ { -+ rtx def_reg1 = SET_DEST (parallel_element (producer, 0)); -+ rtx def_reg2 = SET_DEST (parallel_element (producer, 1)); -+ -+ return (n10_consumed_by_ex_dep_p (consumer, def_reg1) -+ || n10_consumed_by_ex_dep_p (consumer, def_reg2)); -+ } -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return n10_consumed_by_ex_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from LMW(N, N) to EX. */ -+bool -+nds32_n10_last_load_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ return n10_consumed_by_ex_dep_p (consumer, last_def_reg); -+} -+ -+/* Guard functions for Graywolf cores. */ -+ -+/* Check dependencies from EX to EX (ADDR_OUT -> ADDR_IN). */ -+bool -+nds32_gw_ex_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ return nds32_n10_ex_to_ex_p (producer, consumer); -+} -+ -+/* Check dependencies from MM to EX. */ -+bool -+nds32_gw_mm_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_LOAD: -+ case TYPE_MUL: -+ case TYPE_MAC: -+ case TYPE_DALU64: -+ case TYPE_DMUL: -+ case TYPE_DMAC: -+ case TYPE_DALUROUND: -+ case TYPE_DBPICK: -+ case TYPE_DWEXT: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ /* Some special instructions, divmodsi4 and udivmodsi4, produce two -+ results, the quotient and the remainder. We have to handle them -+ individually. */ -+ case TYPE_DIV: -+ if (divmod_p (producer)) -+ { -+ rtx def_reg1 = SET_DEST (parallel_element (producer, 0)); -+ rtx def_reg2 = SET_DEST (parallel_element (producer, 1)); -+ -+ return (gw_consumed_by_ex_dep_p (consumer, def_reg1) -+ || gw_consumed_by_ex_dep_p (consumer, def_reg2)); -+ } -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return gw_consumed_by_ex_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from LMW(N, N) to EX. */ -+bool -+nds32_gw_last_load_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ return gw_consumed_by_ex_dep_p (consumer, last_def_reg); -+} -+ -+/* Guard functions for N12/N13 cores. */ -+ -+/* Check dependencies from E2 to E1. */ -+bool -+nds32_n13_e2_to_e1_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ /* Only post-update load/store instructions are considered. These -+ instructions produces address output at E2. */ -+ case TYPE_LOAD: -+ case TYPE_STORE: -+ case TYPE_LOAD_MULTIPLE: -+ case TYPE_STORE_MULTIPLE: -+ if (!post_update_insn_p (producer)) -+ return false; -+ -+ def_reg = extract_base_reg (producer); -+ break; -+ -+ case TYPE_ALU: -+ case TYPE_ALU_SHIFT: -+ case TYPE_PBSAD: -+ case TYPE_PBSADA: -+ case TYPE_MUL: -+ case TYPE_MAC: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ case TYPE_BRANCH: -+ return true; -+ -+ case TYPE_DIV: -+ /* Some special instructions, divmodsi4 and udivmodsi4, produce two -+ results, the quotient and the remainder. We have to handle them -+ individually. */ -+ if (divmod_p (producer)) -+ { -+ rtx def_reg1 = SET_DEST (parallel_element (producer, 0)); -+ rtx def_reg2 = SET_DEST (parallel_element (producer, 1)); -+ -+ return (n13_consumed_by_e1_dep_p (consumer, def_reg1) -+ || n13_consumed_by_e1_dep_p (consumer, def_reg2)); -+ } -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return n13_consumed_by_e1_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from Load-Store Unit (E3) to E1. */ -+bool -+nds32_n13_load_to_e1_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg = SET_DEST (PATTERN (producer)); -+ -+ gcc_assert (get_attr_type (producer) == TYPE_LOAD); -+ gcc_assert (REG_P (def_reg) || GET_CODE (def_reg) == SUBREG); -+ -+ return n13_consumed_by_e1_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from Load-Store Unit (E3) to E2. */ -+bool -+nds32_n13_load_to_e2_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg = SET_DEST (PATTERN (producer)); -+ -+ gcc_assert (get_attr_type (producer) == TYPE_LOAD); -+ gcc_assert (REG_P (def_reg) || GET_CODE (def_reg) == SUBREG); -+ -+ return n13_consumed_by_e2_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from LMW(N, N) to E1. */ -+bool -+nds32_n13_last_load_to_e1_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ return n13_consumed_by_e1_dep_p (consumer, last_def_reg); -+} -+ -+/* Check dependencies from LMW(N, N) to E2. */ -+bool -+nds32_n13_last_load_to_e2_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ return n13_consumed_by_e2_dep_p (consumer, last_def_reg); -+} -+ -+/* Check dependencies from LMW(N, N-1) to E2. */ -+bool -+nds32_n13_last_two_load_to_e1_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_two_def_reg = extract_nth_access_reg (producer, -2); -+ -+ if (last_two_def_reg == NULL_RTX) -+ return false; -+ -+ return n13_consumed_by_e1_dep_p (consumer, last_two_def_reg); -+} - /* ------------------------------------------------------------------------ */ -diff --git a/gcc/config/nds32/nds32-predicates.c b/gcc/config/nds32/nds32-predicates.c -index 5e01430c8e3..b41b6c7f438 100644 ---- a/gcc/config/nds32/nds32-predicates.c -+++ b/gcc/config/nds32/nds32-predicates.c -@@ -356,54 +356,57 @@ nds32_valid_stack_push_pop_p (rtx op, bool push_p) - } - - /* Function to check if 'bclr' instruction can be used with IVAL. */ --int --nds32_can_use_bclr_p (int ival) -+bool -+nds32_can_use_bclr_p (HOST_WIDE_INT ival) - { - int one_bit_count; -+ unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode); - - /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit, - it means the original ival has only one 0-bit, - So it is ok to perform 'bclr' operation. */ - -- one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival)); -+ one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival) & mask); - - /* 'bclr' is a performance extension instruction. */ - return (TARGET_EXT_PERF && (one_bit_count == 1)); - } - - /* Function to check if 'bset' instruction can be used with IVAL. */ --int --nds32_can_use_bset_p (int ival) -+bool -+nds32_can_use_bset_p (HOST_WIDE_INT ival) - { - int one_bit_count; -+ unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode); - - /* Caculate the number of 1-bit of ival, if there is only one 1-bit, - it is ok to perform 'bset' operation. */ - -- one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival)); -+ one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask); - - /* 'bset' is a performance extension instruction. */ - return (TARGET_EXT_PERF && (one_bit_count == 1)); - } - - /* Function to check if 'btgl' instruction can be used with IVAL. */ --int --nds32_can_use_btgl_p (int ival) -+bool -+nds32_can_use_btgl_p (HOST_WIDE_INT ival) - { - int one_bit_count; -+ unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode); - - /* Caculate the number of 1-bit of ival, if there is only one 1-bit, - it is ok to perform 'btgl' operation. */ - -- one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival)); -+ one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask); - - /* 'btgl' is a performance extension instruction. */ - return (TARGET_EXT_PERF && (one_bit_count == 1)); - } - - /* Function to check if 'bitci' instruction can be used with IVAL. */ --int --nds32_can_use_bitci_p (int ival) -+bool -+nds32_can_use_bitci_p (HOST_WIDE_INT ival) - { - /* If we are using V3 ISA, we have 'bitci' instruction. - Try to see if we can present 'andi' semantic with -@@ -515,4 +518,117 @@ nds32_const_double_range_ok_p (rtx op, machine_mode mode, - - return val >= lower && val < upper; - } -+ -+bool -+nds32_const_unspec_p (rtx x) -+{ -+ if (GET_CODE (x) == CONST) -+ { -+ x = XEXP (x, 0); -+ -+ if (GET_CODE (x) == PLUS) -+ x = XEXP (x, 0); -+ -+ if (GET_CODE (x) == UNSPEC) -+ { -+ switch (XINT (x, 1)) -+ { -+ case UNSPEC_GOTINIT: -+ case UNSPEC_GOT: -+ case UNSPEC_GOTOFF: -+ case UNSPEC_PLT: -+ case UNSPEC_TLSGD: -+ case UNSPEC_TLSLD: -+ case UNSPEC_TLSIE: -+ case UNSPEC_TLSLE: -+ return false; -+ default: -+ return true; -+ } -+ } -+ } -+ -+ if (GET_CODE (x) == SYMBOL_REF -+ && SYMBOL_REF_TLS_MODEL (x)) -+ return false; -+ -+ return true; -+} -+ -+HOST_WIDE_INT -+const_vector_to_hwint (rtx op) -+{ -+ HOST_WIDE_INT hwint = 0; -+ HOST_WIDE_INT mask; -+ int i; -+ int shift_adv; -+ int shift = 0; -+ int nelem; -+ -+ switch (GET_MODE (op)) -+ { -+ case E_V2HImode: -+ mask = 0xffff; -+ shift_adv = 16; -+ nelem = 2; -+ break; -+ case E_V4QImode: -+ mask = 0xff; -+ shift_adv = 8; -+ nelem = 4; -+ break; -+ default: -+ gcc_unreachable (); -+ } -+ -+ if (TARGET_BIG_ENDIAN) -+ { -+ for (i = 0; i < nelem; ++i) -+ { -+ HOST_WIDE_INT val = XINT (XVECEXP (op, 0, nelem - i - 1), 0); -+ hwint |= (val & mask) << shift; -+ shift = shift + shift_adv; -+ } -+ } -+ else -+ { -+ for (i = 0; i < nelem; ++i) -+ { -+ HOST_WIDE_INT val = XINT (XVECEXP (op, 0, i), 0); -+ hwint |= (val & mask) << shift; -+ shift = shift + shift_adv; -+ } -+ } -+ -+ return hwint; -+} -+ -+bool -+nds32_valid_CVp5_p (rtx op) -+{ -+ HOST_WIDE_INT ival = const_vector_to_hwint (op); -+ return (ival < ((1 << 5) + 16)) && (ival >= (0 + 16)); -+} -+ -+bool -+nds32_valid_CVs5_p (rtx op) -+{ -+ HOST_WIDE_INT ival = const_vector_to_hwint (op); -+ return (ival < (1 << 4)) && (ival >= -(1 << 4)); -+} -+ -+bool -+nds32_valid_CVs2_p (rtx op) -+{ -+ HOST_WIDE_INT ival = const_vector_to_hwint (op); -+ return (ival < (1 << 19)) && (ival >= -(1 << 19)); -+} -+ -+bool -+nds32_valid_CVhi_p (rtx op) -+{ -+ HOST_WIDE_INT ival = const_vector_to_hwint (op); -+ return (ival != 0) && ((ival & 0xfff) == 0); -+} -+ - /* ------------------------------------------------------------------------ */ -diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h -index e7b7d4170cc..7fb2315d0ff 100644 ---- a/gcc/config/nds32/nds32-protos.h -+++ b/gcc/config/nds32/nds32-protos.h -@@ -69,9 +69,10 @@ extern unsigned int nds32_dbx_register_number (unsigned int); - - /* ------------------------------------------------------------------------ */ - --/* Auxiliary functions for lwm/smw. */ -+/* Auxiliary functions for manipulation DI mode. */ - --extern bool nds32_valid_smw_lwm_base_p (rtx); -+extern rtx nds32_di_high_part_subreg(rtx); -+extern rtx nds32_di_low_part_subreg(rtx); - - /* Auxiliary functions for expanding rtl used in nds32-multiple.md. */ - -@@ -116,6 +117,20 @@ extern bool nds32_n9_2r1w_mm_to_ex_p (rtx_insn *, rtx_insn *); - extern bool nds32_n9_3r2w_mm_to_ex_p (rtx_insn *, rtx_insn *); - extern bool nds32_n9_last_load_to_ex_p (rtx_insn *, rtx_insn *); - -+extern bool nds32_n10_ex_to_ex_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n10_mm_to_ex_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n10_last_load_to_ex_p (rtx_insn *, rtx_insn *); -+ -+extern bool nds32_gw_ex_to_ex_p (rtx_insn *, rtx_insn *); -+extern bool nds32_gw_mm_to_ex_p (rtx_insn *, rtx_insn *); -+extern bool nds32_gw_last_load_to_ex_p (rtx_insn *, rtx_insn *); -+ -+extern bool nds32_n13_e2_to_e1_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n13_load_to_e1_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n13_load_to_e2_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n13_last_load_to_e1_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n13_last_load_to_e2_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n13_last_two_load_to_e1_p (rtx_insn *, rtx_insn *); - - /* Auxiliary functions for stack operation predicate checking. */ - -@@ -123,24 +138,25 @@ extern bool nds32_valid_stack_push_pop_p (rtx, bool); - - /* Auxiliary functions for bit operation detection. */ - --extern int nds32_can_use_bclr_p (int); --extern int nds32_can_use_bset_p (int); --extern int nds32_can_use_btgl_p (int); -+extern bool nds32_can_use_bclr_p (HOST_WIDE_INT); -+extern bool nds32_can_use_bset_p (HOST_WIDE_INT); -+extern bool nds32_can_use_btgl_p (HOST_WIDE_INT); - --extern int nds32_can_use_bitci_p (int); -+extern bool nds32_can_use_bitci_p (HOST_WIDE_INT); - - extern bool nds32_const_double_range_ok_p (rtx, machine_mode, - HOST_WIDE_INT, HOST_WIDE_INT); - -+extern bool nds32_const_unspec_p (rtx x); -+ - /* Auxiliary function for 'Computing the Length of an Insn'. */ - - extern int nds32_adjust_insn_length (rtx_insn *, int); - - /* Auxiliary functions for FP_AS_GP detection. */ - --extern int nds32_fp_as_gp_check_available (void); -- - extern bool nds32_symbol_load_store_p (rtx_insn *); -+extern bool nds32_naked_function_p (tree); - - /* Auxiliary functions for jump table generation. */ - -@@ -159,10 +175,50 @@ extern void nds32_expand_float_cstore (rtx *); - extern enum nds32_expand_result_type nds32_expand_movcc (rtx *); - extern void nds32_expand_float_movcc (rtx *); - -+/* Auxiliary functions for expand extv/insv instruction. */ -+ -+extern enum nds32_expand_result_type nds32_expand_extv (rtx *); -+extern enum nds32_expand_result_type nds32_expand_insv (rtx *); -+ -+/* Auxiliary functions for expand PIC instruction. */ -+ -+extern void nds32_expand_pic_move (rtx *); -+ -+/* Auxiliary functions to legitimize PIC address. */ -+ -+extern rtx nds32_legitimize_pic_address (rtx); -+ -+/* Auxiliary functions for expand TLS instruction. */ -+ -+extern void nds32_expand_tls_move (rtx *); -+ -+/* Auxiliary functions to legitimize TLS address. */ -+ -+extern rtx nds32_legitimize_tls_address (rtx); -+ -+/* Auxiliary functions to identify thread-local symbol. */ -+ -+extern bool nds32_tls_referenced_p (rtx); -+ -+/* Auxiliary functions for expand ICT instruction. */ -+ -+extern void nds32_expand_ict_move (rtx *); -+ -+/* Auxiliary functions to legitimize address for indirect-call symbol. */ -+ -+extern rtx nds32_legitimize_ict_address (rtx); -+ -+/* Auxiliary functions to identify indirect-call symbol. */ -+ -+extern bool nds32_indirect_call_referenced_p (rtx); - - /* Auxiliary functions to identify long-call symbol. */ - extern bool nds32_long_call_p (rtx); - -+/* Auxiliary functions to identify SYMBOL_REF and LABEL_REF pattern. */ -+ -+extern bool symbolic_reference_mentioned_p (rtx); -+ - /* Auxiliary functions to identify conditional move comparison operand. */ - - extern int nds32_cond_move_p (rtx); -@@ -185,6 +241,7 @@ extern const char *nds32_output_32bit_load_s (rtx *, int); - extern const char *nds32_output_float_load(rtx *); - extern const char *nds32_output_float_store(rtx *); - extern const char *nds32_output_smw_single_word (rtx *); -+extern const char *nds32_output_smw_double_word (rtx *); - extern const char *nds32_output_lmw_single_word (rtx *); - extern const char *nds32_output_double (rtx *, bool); - extern const char *nds32_output_cbranchsi4_equality_zero (rtx_insn *, rtx *); -@@ -193,9 +250,12 @@ extern const char *nds32_output_cbranchsi4_equality_reg_or_const_int (rtx_insn * - rtx *); - extern const char *nds32_output_cbranchsi4_greater_less_zero (rtx_insn *, rtx *); - -+extern const char *nds32_output_unpkd8 (rtx, rtx, rtx, rtx, bool); -+ - extern const char *nds32_output_call (rtx, rtx *, rtx, - const char *, const char *, bool); -- -+extern const char *nds32_output_tls_desc (rtx *); -+extern const char *nds32_output_tls_ie (rtx *); - - /* Auxiliary functions to output stack push/pop instruction. */ - -@@ -203,9 +263,19 @@ extern const char *nds32_output_stack_push (rtx); - extern const char *nds32_output_stack_pop (rtx); - extern const char *nds32_output_return (void); - -+ -+/* Auxiliary functions to split/output sms pattern. */ -+extern bool nds32_need_split_sms_p (rtx, rtx, rtx, rtx); -+extern const char *nds32_output_sms (rtx, rtx, rtx, rtx); -+extern void nds32_split_sms (rtx, rtx, rtx, rtx, rtx, rtx, rtx); -+ - /* Auxiliary functions to split double word RTX pattern. */ - - extern void nds32_spilt_doubleword (rtx *, bool); -+extern void nds32_split_ashiftdi3 (rtx, rtx, rtx); -+extern void nds32_split_ashiftrtdi3 (rtx, rtx, rtx); -+extern void nds32_split_lshiftrtdi3 (rtx, rtx, rtx); -+extern void nds32_split_rotatertdi3 (rtx, rtx, rtx); - - /* Auxiliary functions to split large constant RTX pattern. */ - -@@ -237,15 +307,29 @@ extern void nds32_construct_isr_vectors_information (tree, const char *); - extern void nds32_asm_file_start_for_isr (void); - extern void nds32_asm_file_end_for_isr (void); - extern bool nds32_isr_function_p (tree); -+extern bool nds32_isr_function_critical_p (tree); - - /* Auxiliary functions for cost calculation. */ - -+extern void nds32_init_rtx_costs (void); - extern bool nds32_rtx_costs_impl (rtx, machine_mode, int, int, int *, bool); - extern int nds32_address_cost_impl (rtx, machine_mode, addr_space_t, bool); - - /* Auxiliary functions for pre-define marco. */ - extern void nds32_cpu_cpp_builtins(struct cpp_reader *); - -+/* Auxiliary functions for const_vector's constraints. */ -+ -+extern HOST_WIDE_INT const_vector_to_hwint (rtx); -+extern bool nds32_valid_CVp5_p (rtx); -+extern bool nds32_valid_CVs5_p (rtx); -+extern bool nds32_valid_CVs2_p (rtx); -+extern bool nds32_valid_CVhi_p (rtx); -+ -+/* Auxiliary functions for lwm/smw. */ -+ -+extern bool nds32_valid_smw_lwm_base_p (rtx); -+ - extern bool nds32_split_double_word_load_store_p (rtx *,bool); - - namespace nds32 { -@@ -258,11 +342,13 @@ bool load_single_p (rtx_insn *); - bool store_single_p (rtx_insn *); - bool load_double_p (rtx_insn *); - bool store_double_p (rtx_insn *); -+bool store_offset_reg_p (rtx_insn *); - bool post_update_insn_p (rtx_insn *); - bool immed_offset_p (rtx); - int find_post_update_rtx (rtx_insn *); - rtx extract_mem_rtx (rtx_insn *); - rtx extract_base_reg (rtx_insn *); -+rtx extract_offset_rtx (rtx_insn *); - - rtx extract_shift_reg (rtx); - -@@ -271,6 +357,8 @@ rtx extract_movd44_odd_reg (rtx_insn *); - - rtx extract_mac_non_acc_rtx (rtx_insn *); - -+bool divmod_p (rtx_insn *); -+ - rtx extract_branch_target_rtx (rtx_insn *); - rtx extract_branch_condition_rtx (rtx_insn *); - } // namespace nds32 -@@ -279,5 +367,6 @@ extern bool nds32_use_load_post_increment(machine_mode); - - /* Functions for create nds32 specific optimization pass. */ - extern rtl_opt_pass *make_pass_nds32_relax_opt (gcc::context *); -+extern rtl_opt_pass *make_pass_nds32_fp_as_gp (gcc::context *); - - /* ------------------------------------------------------------------------ */ -diff --git a/gcc/config/nds32/nds32-relax-opt.c b/gcc/config/nds32/nds32-relax-opt.c -index 0349be4725d..e54bd978c2e 100644 ---- a/gcc/config/nds32/nds32-relax-opt.c -+++ b/gcc/config/nds32/nds32-relax-opt.c -@@ -52,6 +52,8 @@ - #include "cfgrtl.h" - #include "tree-pass.h" - -+using namespace nds32; -+ - /* This is used to create unique relax hint id value. - The initial value is 0. */ - static int relax_group_id = 0; -@@ -185,6 +187,121 @@ nds32_plus_reg_load_store_p (rtx_insn *insn) - return false; - } - -+/* Return true if x is const and the referance is ict symbol. */ -+static bool -+nds32_ict_const_p (rtx x) -+{ -+ if (GET_CODE (x) == CONST) -+ { -+ x = XEXP (x, 0); -+ return nds32_indirect_call_referenced_p (x); -+ } -+ return FALSE; -+} -+ -+/* Group the following pattern as relax candidates: -+ -+ GOT: -+ sethi $ra, hi20(sym) -+ ori $ra, $ra, lo12(sym) -+ lw $rb, [$ra + $gp] -+ -+ GOTOFF, TLSLE: -+ sethi $ra, hi20(sym) -+ ori $ra, $ra, lo12(sym) -+ LS $rb, [$ra + $gp] -+ -+ GOTOFF, TLSLE: -+ sethi $ra, hi20(sym) -+ ori $ra, $ra, lo12(sym) -+ add $rb, $ra, $gp($tp) -+ -+ Initial GOT table: -+ sethi $gp,hi20(sym) -+ ori $gp, $gp, lo12(sym) -+ add5.pc $gp */ -+ -+static auto_vec nds32_group_infos; -+/* Group the PIC and TLS relax candidate instructions for linker. */ -+static bool -+nds32_pic_tls_group (rtx_insn *def_insn, -+ enum nds32_relax_insn_type relax_type, -+ int sym_type) -+{ -+ df_ref def_record; -+ df_link *link; -+ rtx_insn *use_insn = NULL; -+ rtx pat, new_pat; -+ def_record = DF_INSN_DEFS (def_insn); -+ for (link = DF_REF_CHAIN (def_record); link; link = link->next) -+ { -+ if (!DF_REF_INSN_INFO (link->ref)) -+ continue; -+ -+ use_insn = DF_REF_INSN (link->ref); -+ -+ /* Skip if define insn and use insn not in the same basic block. */ -+ if (!dominated_by_p (CDI_DOMINATORS, -+ BLOCK_FOR_INSN (use_insn), -+ BLOCK_FOR_INSN (def_insn))) -+ return FALSE; -+ -+ /* Skip if use_insn not active insn. */ -+ if (!active_insn_p (use_insn)) -+ return FALSE; -+ -+ switch (relax_type) -+ { -+ case RELAX_ORI: -+ -+ /* GOTOFF, TLSLE: -+ sethi $ra, hi20(sym) -+ ori $ra, $ra, lo12(sym) -+ add $rb, $ra, $gp($tp) */ -+ if ((sym_type == UNSPEC_TLSLE -+ || sym_type == UNSPEC_GOTOFF) -+ && (recog_memoized (use_insn) == CODE_FOR_addsi3)) -+ { -+ pat = XEXP (PATTERN (use_insn), 1); -+ new_pat = -+ gen_rtx_UNSPEC (SImode, -+ gen_rtvec (2, XEXP (pat, 0), XEXP (pat, 1)), -+ UNSPEC_ADD32); -+ validate_replace_rtx (pat, new_pat, use_insn); -+ nds32_group_infos.safe_push (use_insn); -+ } -+ else if (nds32_plus_reg_load_store_p (use_insn) -+ && !nds32_sp_base_or_plus_load_store_p (use_insn)) -+ nds32_group_infos.safe_push (use_insn); -+ else -+ return FALSE; -+ break; -+ -+ default: -+ return FALSE; -+ } -+ } -+ return TRUE; -+} -+ -+static int -+nds32_pic_tls_symbol_type (rtx x) -+{ -+ x = XEXP (SET_SRC (PATTERN (x)), 1); -+ -+ if (GET_CODE (x) == CONST) -+ { -+ x = XEXP (x, 0); -+ -+ if (GET_CODE (x) == PLUS) -+ x = XEXP (x, 0); -+ -+ return XINT (x, 1); -+ } -+ -+ return XINT (x, 1); -+} -+ - /* Group the relax candidates with group id. */ - static void - nds32_group_insns (rtx sethi) -@@ -193,6 +310,7 @@ nds32_group_insns (rtx sethi) - df_link *link; - rtx_insn *use_insn = NULL; - rtx group_id; -+ bool valid; - - def_record = DF_INSN_DEFS (sethi); - -@@ -242,6 +360,132 @@ nds32_group_insns (rtx sethi) - /* Insert .relax_* directive. */ - if (active_insn_p (use_insn)) - emit_insn_before (gen_relax_group (group_id), use_insn); -+ -+ /* Find ori ra, ra, unspec(symbol) instruction. */ -+ if (use_insn != NULL -+ && recog_memoized (use_insn) == CODE_FOR_lo_sum -+ && !nds32_const_unspec_p (XEXP (SET_SRC (PATTERN (use_insn)), 1))) -+ { -+ int sym_type = nds32_pic_tls_symbol_type (use_insn); -+ valid = nds32_pic_tls_group (use_insn, RELAX_ORI, sym_type); -+ -+ /* Insert .relax_* directive. */ -+ while (!nds32_group_infos.is_empty ()) -+ { -+ use_insn = nds32_group_infos.pop (); -+ if (valid) -+ emit_insn_before (gen_relax_group (group_id), use_insn); -+ } -+ } -+ } -+ -+ relax_group_id++; -+} -+ -+/* Convert relax group id in rtl. */ -+ -+static void -+nds32_group_tls_insn (rtx insn) -+{ -+ rtx pat = PATTERN (insn); -+ rtx unspec_relax_group = XEXP (XVECEXP (pat, 0, 1), 0); -+ -+ while (GET_CODE (pat) != SET && GET_CODE (pat) == PARALLEL) -+ { -+ pat = XVECEXP (pat, 0, 0); -+ } -+ -+ if (GET_CODE (unspec_relax_group) == UNSPEC -+ && XINT (unspec_relax_group, 1) == UNSPEC_VOLATILE_RELAX_GROUP) -+ { -+ XVECEXP (unspec_relax_group, 0, 0) = GEN_INT (relax_group_id); -+ } -+ -+ relax_group_id++; -+} -+ -+static bool -+nds32_float_reg_load_store_p (rtx_insn *insn) -+{ -+ rtx pat = PATTERN (insn); -+ -+ if (get_attr_type (insn) == TYPE_FLOAD -+ && GET_CODE (pat) == SET -+ && (GET_MODE (XEXP (pat, 0)) == SFmode -+ || GET_MODE (XEXP (pat, 0)) == DFmode) -+ && MEM_P (XEXP (pat, 1))) -+ { -+ rtx addr = XEXP (XEXP (pat, 1), 0); -+ -+ /* [$ra] */ -+ if (REG_P (addr)) -+ return true; -+ /* [$ra + offset] */ -+ if (GET_CODE (addr) == PLUS -+ && REG_P (XEXP (addr, 0)) -+ && CONST_INT_P (XEXP (addr, 1))) -+ return true; -+ } -+ return false; -+} -+ -+ -+/* Group float load-store instructions: -+ la $ra, symbol -+ flsi $rt, [$ra + offset] */ -+ -+static void -+nds32_group_float_insns (rtx insn) -+{ -+ df_ref def_record, use_record; -+ df_link *link; -+ rtx_insn *use_insn = NULL; -+ rtx group_id; -+ -+ def_record = DF_INSN_DEFS (insn); -+ -+ for (link = DF_REF_CHAIN (def_record); link; link = link->next) -+ { -+ if (!DF_REF_INSN_INFO (link->ref)) -+ continue; -+ -+ use_insn = DF_REF_INSN (link->ref); -+ -+ /* Skip if define insn and use insn not in the same basic block. */ -+ if (!dominated_by_p (CDI_DOMINATORS, -+ BLOCK_FOR_INSN (use_insn), -+ BLOCK_FOR_INSN (insn))) -+ return; -+ -+ /* Skip if the low-part used register is from different high-part -+ instructions. */ -+ use_record = DF_INSN_USES (use_insn); -+ if (DF_REF_CHAIN (use_record) && DF_REF_CHAIN (use_record)->next) -+ return; -+ -+ /* Skip if use_insn not active insn. */ -+ if (!active_insn_p (use_insn)) -+ return; -+ -+ if (!nds32_float_reg_load_store_p (use_insn) -+ || find_post_update_rtx (use_insn) != -1) -+ return; -+ } -+ -+ group_id = GEN_INT (relax_group_id); -+ /* Insert .relax_* directive for insn. */ -+ emit_insn_before (gen_relax_group (group_id), insn); -+ -+ /* Scan the use insns and insert the directive. */ -+ for (link = DF_REF_CHAIN (def_record); link; link = link->next) -+ { -+ if (!DF_REF_INSN_INFO (link->ref)) -+ continue; -+ -+ use_insn = DF_REF_INSN (link->ref); -+ -+ /* Insert .relax_* directive. */ -+ emit_insn_before (gen_relax_group (group_id), use_insn); - } - - relax_group_id++; -@@ -271,8 +515,21 @@ nds32_relax_group (void) - /* Find sethi ra, symbol instruction. */ - if (recog_memoized (insn) == CODE_FOR_sethi - && nds32_symbolic_operand (XEXP (SET_SRC (PATTERN (insn)), 0), -- SImode)) -+ SImode) -+ && !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0))) - nds32_group_insns (insn); -+ else if (recog_memoized (insn) == CODE_FOR_tls_ie) -+ nds32_group_tls_insn (insn); -+ else if (TARGET_FPU_SINGLE -+ && recog_memoized (insn) == CODE_FOR_move_addr -+ && !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0))) -+ { -+ nds32_group_float_insns (insn); -+ } -+ } -+ else if (CALL_P (insn) && recog_memoized (insn) == CODE_FOR_tls_desc) -+ { -+ nds32_group_tls_insn (insn); - } - } - -diff --git a/gcc/config/nds32/nds32-utils.c b/gcc/config/nds32/nds32-utils.c -index b0151be39dc..7c93cd2edd0 100644 ---- a/gcc/config/nds32/nds32-utils.c -+++ b/gcc/config/nds32/nds32-utils.c -@@ -142,6 +142,23 @@ store_double_p (rtx_insn *insn) - return true; - } - -+bool -+store_offset_reg_p (rtx_insn *insn) -+{ -+ if (get_attr_type (insn) != TYPE_STORE) -+ return false; -+ -+ rtx offset_rtx = extract_offset_rtx (insn); -+ -+ if (offset_rtx == NULL_RTX) -+ return false; -+ -+ if (REG_P (offset_rtx)) -+ return true; -+ -+ return false; -+} -+ - /* Determine if INSN is a post update insn. */ - bool - post_update_insn_p (rtx_insn *insn) -@@ -316,22 +333,114 @@ extract_base_reg (rtx_insn *insn) - if (REG_P (XEXP (mem_rtx, 0))) - return XEXP (mem_rtx, 0); - -+ /* (mem (lo_sum (reg) (symbol_ref)) */ -+ if (GET_CODE (XEXP (mem_rtx, 0)) == LO_SUM) -+ return XEXP (XEXP (mem_rtx, 0), 0); -+ - plus_rtx = XEXP (mem_rtx, 0); - - if (GET_CODE (plus_rtx) == SYMBOL_REF - || GET_CODE (plus_rtx) == CONST) - return NULL_RTX; - -- gcc_assert (GET_CODE (plus_rtx) == PLUS -- || GET_CODE (plus_rtx) == POST_INC -- || GET_CODE (plus_rtx) == POST_DEC -- || GET_CODE (plus_rtx) == POST_MODIFY); -- gcc_assert (REG_P (XEXP (plus_rtx, 0))); - /* (mem (plus (reg) (const_int))) or -+ (mem (plus (mult (reg) (const_int 4)) (reg))) or - (mem (post_inc (reg))) or - (mem (post_dec (reg))) or - (mem (post_modify (reg) (plus (reg) (reg)))) */ -- return XEXP (plus_rtx, 0); -+ gcc_assert (GET_CODE (plus_rtx) == PLUS -+ || GET_CODE (plus_rtx) == POST_INC -+ || GET_CODE (plus_rtx) == POST_DEC -+ || GET_CODE (plus_rtx) == POST_MODIFY); -+ -+ if (REG_P (XEXP (plus_rtx, 0))) -+ return XEXP (plus_rtx, 0); -+ -+ gcc_assert (REG_P (XEXP (plus_rtx, 1))); -+ return XEXP (plus_rtx, 1); -+} -+ -+/* Extract the offset rtx from load/store insns. The function returns -+ NULL_RTX if offset is absent. */ -+rtx -+extract_offset_rtx (rtx_insn *insn) -+{ -+ rtx mem_rtx; -+ rtx plus_rtx; -+ rtx offset_rtx; -+ -+ /* Find the MEM rtx. The multiple load/store insns doens't have -+ the offset field so we can return NULL_RTX here. */ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD_MULTIPLE: -+ case TYPE_STORE_MULTIPLE: -+ return NULL_RTX; -+ -+ case TYPE_LOAD: -+ case TYPE_FLOAD: -+ case TYPE_STORE: -+ case TYPE_FSTORE: -+ mem_rtx = extract_mem_rtx (insn); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ gcc_assert (MEM_P (mem_rtx)); -+ -+ /* (mem (reg)) */ -+ if (REG_P (XEXP (mem_rtx, 0))) -+ return NULL_RTX; -+ -+ plus_rtx = XEXP (mem_rtx, 0); -+ -+ switch (GET_CODE (plus_rtx)) -+ { -+ case SYMBOL_REF: -+ case CONST: -+ case POST_INC: -+ case POST_DEC: -+ return NULL_RTX; -+ -+ case PLUS: -+ /* (mem (plus (reg) (const_int))) or -+ (mem (plus (mult (reg) (const_int 4)) (reg))) */ -+ if (REG_P (XEXP (plus_rtx, 0))) -+ offset_rtx = XEXP (plus_rtx, 1); -+ else -+ { -+ gcc_assert (REG_P (XEXP (plus_rtx, 1))); -+ offset_rtx = XEXP (plus_rtx, 0); -+ } -+ -+ if (ARITHMETIC_P (offset_rtx)) -+ { -+ gcc_assert (GET_CODE (offset_rtx) == MULT); -+ gcc_assert (REG_P (XEXP (offset_rtx, 0))); -+ offset_rtx = XEXP (offset_rtx, 0); -+ } -+ break; -+ -+ case LO_SUM: -+ /* (mem (lo_sum (reg) (symbol_ref)) */ -+ offset_rtx = XEXP (plus_rtx, 1); -+ break; -+ -+ case POST_MODIFY: -+ /* (mem (post_modify (reg) (plus (reg) (reg / const_int)))) */ -+ gcc_assert (REG_P (XEXP (plus_rtx, 0))); -+ plus_rtx = XEXP (plus_rtx, 1); -+ gcc_assert (GET_CODE (plus_rtx) == PLUS); -+ offset_rtx = XEXP (plus_rtx, 0); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return offset_rtx; - } - - /* Extract the register of the shift operand from an ALU_SHIFT rtx. */ -@@ -413,6 +522,7 @@ extract_mac_non_acc_rtx (rtx_insn *insn) - switch (get_attr_type (insn)) - { - case TYPE_MAC: -+ case TYPE_DMAC: - if (REG_P (XEXP (exp, 0))) - return XEXP (exp, 1); - else -@@ -423,6 +533,19 @@ extract_mac_non_acc_rtx (rtx_insn *insn) - } - } - -+/* Check if the DIV insn needs two write ports. */ -+bool -+divmod_p (rtx_insn *insn) -+{ -+ gcc_assert (get_attr_type (insn) == TYPE_DIV); -+ -+ if (INSN_CODE (insn) == CODE_FOR_divmodsi4 -+ || INSN_CODE (insn) == CODE_FOR_udivmodsi4) -+ return true; -+ -+ return false; -+} -+ - /* Extract the rtx representing the branch target to help recognize - data hazards. */ - rtx -diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c -index 8994c13d7b0..1d23ec3fb9a 100644 ---- a/gcc/config/nds32/nds32.c -+++ b/gcc/config/nds32/nds32.c -@@ -305,6 +305,7 @@ static const struct attribute_spec nds32_attribute_table[] = - { "nested", 0, 0, false, false, false, false, NULL, NULL }, - { "not_nested", 0, 0, false, false, false, false, NULL, NULL }, - { "nested_ready", 0, 0, false, false, false, false, NULL, NULL }, -+ { "critical", 0, 0, false, false, false, false, NULL, NULL }, - - /* The attributes describing isr register save scheme. */ - { "save_all", 0, 0, false, false, false, false, NULL, NULL }, -@@ -314,9 +315,19 @@ static const struct attribute_spec nds32_attribute_table[] = - { "nmi", 1, 1, false, false, false, false, NULL, NULL }, - { "warm", 1, 1, false, false, false, false, NULL, NULL }, - -+ /* The attributes describing isr security level. */ -+ { "secure", 1, 1, false, false, false, false, NULL, NULL }, -+ - /* The attribute telling no prologue/epilogue. */ - { "naked", 0, 0, false, false, false, false, NULL, NULL }, - -+ /* The attribute is used to tell this function to be ROM patch. */ -+ { "indirect_call",0, 0, false, false, false, false, NULL, NULL }, -+ -+ /* FOR BACKWARD COMPATIBILITY, -+ this attribute also tells no prologue/epilogue. */ -+ { "no_prologue", 0, 0, false, false, false, false, NULL, NULL }, -+ - /* The last attribute spec is set to be NULL. */ - { NULL, 0, 0, false, false, false, false, NULL, NULL } - }; -@@ -345,6 +356,10 @@ nds32_init_machine_status (void) - /* Initially this function is not under strictly aligned situation. */ - machine->strict_aligned_p = 0; - -+ /* Initially this function has no naked and no_prologue attributes. */ -+ machine->attr_naked_p = 0; -+ machine->attr_no_prologue_p = 0; -+ - return machine; - } - -@@ -362,6 +377,15 @@ nds32_compute_stack_frame (void) - needs prologue/epilogue. */ - cfun->machine->naked_p = 0; - -+ /* We need to mark whether this function has naked and no_prologue -+ attribute so that we can distinguish the difference if users applies -+ -mret-in-naked-func option. */ -+ cfun->machine->attr_naked_p -+ = lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) -+ ? 1 : 0; -+ cfun->machine->attr_no_prologue_p -+ = lookup_attribute ("no_prologue", DECL_ATTRIBUTES (current_function_decl)) -+ ? 1 : 0; - - /* If __builtin_eh_return is used, we better have frame pointer needed - so that we can easily locate the stack slot of return address. */ -@@ -432,7 +456,8 @@ nds32_compute_stack_frame (void) - - /* If $gp value is required to be saved on stack, it needs 4 bytes space. - Check whether we are using PIC code genration. */ -- cfun->machine->gp_size = (flag_pic) ? 4 : 0; -+ cfun->machine->gp_size = -+ (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) ? 4 : 0; - - /* If $lp value is required to be saved on stack, it needs 4 bytes space. - Check whether $lp is ever live. */ -@@ -497,7 +522,7 @@ nds32_compute_stack_frame (void) - } - - /* Check if this function can omit prologue/epilogue code fragment. -- If there is 'naked' attribute in this function, -+ If there is 'no_prologue'/'naked'/'secure' attribute in this function, - we can set 'naked_p' flag to indicate that - we do not have to generate prologue/epilogue. - Or, if all the following conditions succeed, -@@ -510,14 +535,17 @@ nds32_compute_stack_frame (void) - is no outgoing size. - condition 3: There is no local_size, which means - we do not need to adjust $sp. */ -- if (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) -+ if (lookup_attribute ("no_prologue", DECL_ATTRIBUTES (current_function_decl)) -+ || lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) -+ || lookup_attribute ("secure", DECL_ATTRIBUTES (current_function_decl)) - || (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM - && cfun->machine->callee_saved_last_gpr_regno == SP_REGNUM - && cfun->machine->callee_saved_first_fpr_regno == SP_REGNUM - && cfun->machine->callee_saved_last_fpr_regno == SP_REGNUM - && !df_regs_ever_live_p (FP_REGNUM) - && !df_regs_ever_live_p (LP_REGNUM) -- && cfun->machine->local_size == 0)) -+ && cfun->machine->local_size == 0 -+ && !flag_pic)) - { - /* Set this function 'naked_p' and other functions can check this flag. - Note that in nds32 port, the 'naked_p = 1' JUST means there is no -@@ -1259,6 +1287,32 @@ nds32_emit_stack_v3pop (unsigned Rb, - REG_NOTES (parallel_insn) = dwarf; - } - -+static void -+nds32_emit_load_gp (void) -+{ -+ rtx got_symbol, pat; -+ -+ /* Initial GLOBAL OFFSET TABLE don't do the scheduling. */ -+ emit_insn (gen_blockage ()); -+ -+ got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); -+ /* sethi $gp, _GLOBAL_OFFSET_TABLE_ -8 */ -+ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, got_symbol), UNSPEC_GOTINIT); -+ pat = gen_rtx_CONST (SImode, gen_rtx_PLUS (Pmode, pat, GEN_INT (-8))); -+ emit_insn (gen_sethi (pic_offset_table_rtx,pat)); -+ -+ /* ori $gp, $gp, _GLOBAL_OFFSET_TABLE_ -4 */ -+ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, got_symbol), UNSPEC_GOTINIT); -+ pat = gen_rtx_CONST (SImode, gen_rtx_PLUS (Pmode, pat, GEN_INT (-4))); -+ emit_insn (gen_lo_sum (pic_offset_table_rtx, pic_offset_table_rtx, pat)); -+ -+ /* add5.pc $gp */ -+ emit_insn (gen_add_pc (pic_offset_table_rtx, pic_offset_table_rtx)); -+ -+ /* Initial GLOBAL OFFSET TABLE don't do the scheduling. */ -+ emit_insn (gen_blockage ()); -+} -+ - /* Function that may creates more instructions - for large value on adjusting stack pointer. - -@@ -1342,17 +1396,25 @@ nds32_needs_double_word_align (machine_mode mode, const_tree type) - } - - /* Return true if FUNC is a naked function. */ --static bool -+bool - nds32_naked_function_p (tree func) - { -- tree t; -+ /* FOR BACKWARD COMPATIBILITY, -+ we need to support 'no_prologue' attribute as well. */ -+ tree t_naked; -+ tree t_no_prologue; - - if (TREE_CODE (func) != FUNCTION_DECL) - abort (); - -- t = lookup_attribute ("naked", DECL_ATTRIBUTES (func)); -+ /* We have to use lookup_attribute() to check attributes. -+ Because attr_naked_p and attr_no_prologue_p are set in -+ nds32_compute_stack_frame() and the function has not been -+ invoked yet. */ -+ t_naked = lookup_attribute ("naked", DECL_ATTRIBUTES (func)); -+ t_no_prologue = lookup_attribute ("no_prologue", DECL_ATTRIBUTES (func)); - -- return (t != NULL_TREE); -+ return ((t_naked != NULL_TREE) || (t_no_prologue != NULL_TREE)); - } - - /* Function that determine whether a load postincrement is a good thing to use -@@ -1569,6 +1631,11 @@ nds32_register_pass ( - static void - nds32_register_passes (void) - { -+ nds32_register_pass ( -+ make_pass_nds32_fp_as_gp, -+ PASS_POS_INSERT_BEFORE, -+ "ira"); -+ - nds32_register_pass ( - make_pass_nds32_relax_opt, - PASS_POS_INSERT_AFTER, -@@ -1636,6 +1703,9 @@ nds32_conditional_register_usage (void) - { - int regno; - -+ if (TARGET_LINUX_ABI) -+ fixed_regs[TP_REGNUM] = 1; -+ - if (TARGET_HARD_FLOAT) - { - for (regno = NDS32_FIRST_FPR_REGNUM; -@@ -1987,6 +2057,16 @@ nds32_function_arg_boundary (machine_mode mode, const_tree type) - : PARM_BOUNDARY); - } - -+bool -+nds32_vector_mode_supported_p (machine_mode mode) -+{ -+ if (mode == V4QImode -+ || mode == V2HImode) -+ return NDS32_EXT_DSP_P (); -+ -+ return false; -+} -+ - /* -- How Scalar Function Values Are Returned. */ - - static rtx -@@ -2124,56 +2204,12 @@ static void - nds32_asm_function_end_prologue (FILE *file) - { - fprintf (file, "\t! END PROLOGUE\n"); -- -- /* If frame pointer is NOT needed and -mfp-as-gp is issued, -- we can generate special directive: ".omit_fp_begin" -- to guide linker doing fp-as-gp optimization. -- However, for a naked function, which means -- it should not have prologue/epilogue, -- using fp-as-gp still requires saving $fp by push/pop behavior and -- there is no benefit to use fp-as-gp on such small function. -- So we need to make sure this function is NOT naked as well. */ -- if (!frame_pointer_needed -- && !cfun->machine->naked_p -- && cfun->machine->fp_as_gp_p) -- { -- fprintf (file, "\t! ----------------------------------------\n"); -- fprintf (file, "\t! Guide linker to do " -- "link time optimization: fp-as-gp\n"); -- fprintf (file, "\t! We add one more instruction to " -- "initialize $fp near to $gp location.\n"); -- fprintf (file, "\t! If linker fails to use fp-as-gp transformation,\n"); -- fprintf (file, "\t! this extra instruction should be " -- "eliminated at link stage.\n"); -- fprintf (file, "\t.omit_fp_begin\n"); -- fprintf (file, "\tla\t$fp,_FP_BASE_\n"); -- fprintf (file, "\t! ----------------------------------------\n"); -- } - } - - /* Before rtl epilogue has been expanded, this function is used. */ - static void - nds32_asm_function_begin_epilogue (FILE *file) - { -- /* If frame pointer is NOT needed and -mfp-as-gp is issued, -- we can generate special directive: ".omit_fp_end" -- to claim fp-as-gp optimization range. -- However, for a naked function, -- which means it should not have prologue/epilogue, -- using fp-as-gp still requires saving $fp by push/pop behavior and -- there is no benefit to use fp-as-gp on such small function. -- So we need to make sure this function is NOT naked as well. */ -- if (!frame_pointer_needed -- && !cfun->machine->naked_p -- && cfun->machine->fp_as_gp_p) -- { -- fprintf (file, "\t! ----------------------------------------\n"); -- fprintf (file, "\t! Claim the range of fp-as-gp " -- "link time optimization\n"); -- fprintf (file, "\t.omit_fp_end\n"); -- fprintf (file, "\t! ----------------------------------------\n"); -- } -- - fprintf (file, "\t! BEGIN EPILOGUE\n"); - } - -@@ -2200,6 +2236,26 @@ nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, - ? 1 - : 0); - -+ if (flag_pic) -+ { -+ fprintf (file, "\tsmw.adm\t$r31, [$r31], $r31, 4\n"); -+ fprintf (file, "\tsethi\t%s, hi20(_GLOBAL_OFFSET_TABLE_-8)\n", -+ reg_names [PIC_OFFSET_TABLE_REGNUM]); -+ fprintf (file, "\tori\t%s, %s, lo12(_GLOBAL_OFFSET_TABLE_-4)\n", -+ reg_names [PIC_OFFSET_TABLE_REGNUM], -+ reg_names [PIC_OFFSET_TABLE_REGNUM]); -+ -+ if (TARGET_ISA_V3) -+ fprintf (file, "\tadd5.pc\t$gp\n"); -+ else -+ { -+ fprintf (file, "\tmfusr\t$ta, $pc\n"); -+ fprintf (file, "\tadd\t%s, $ta, %s\n", -+ reg_names [PIC_OFFSET_TABLE_REGNUM], -+ reg_names [PIC_OFFSET_TABLE_REGNUM]); -+ } -+ } -+ - if (delta != 0) - { - if (satisfies_constraint_Is15 (GEN_INT (delta))) -@@ -2224,9 +2280,23 @@ nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, - } - } - -- fprintf (file, "\tb\t"); -- assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); -- fprintf (file, "\n"); -+ if (flag_pic) -+ { -+ fprintf (file, "\tla\t$ta, "); -+ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); -+ fprintf (file, "@PLT\n"); -+ fprintf (file, "\t! epilogue\n"); -+ fprintf (file, "\tlwi.bi\t%s, [%s], 4\n", -+ reg_names[PIC_OFFSET_TABLE_REGNUM], -+ reg_names[STACK_POINTER_REGNUM]); -+ fprintf (file, "\tbr\t$ta\n"); -+ } -+ else -+ { -+ fprintf (file, "\tb\t"); -+ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); -+ fprintf (file, "\n"); -+ } - - final_end_function (); - } -@@ -2242,15 +2312,20 @@ nds32_function_ok_for_sibcall (tree decl, - - /* 1. Do not apply sibling call if -mv3push is enabled, - because pop25 instruction also represents return behavior. -- 2. If this function is a variadic function, do not apply sibling call -+ 2. If this function is a isr function, do not apply sibling call -+ because it may perform the behavior that user does not expect. -+ 3. If this function is a variadic function, do not apply sibling call - because the stack layout may be a mess. -- 3. We don't want to apply sibling call optimization for indirect -+ 4. We don't want to apply sibling call optimization for indirect - sibcall because the pop behavior in epilogue may pollute the - content of caller-saved regsiter when the register is used for -- indirect sibcall. */ -+ indirect sibcall. -+ 5. In pic mode, it may use some registers for PLT call. */ - return (!TARGET_V3PUSH -+ && !nds32_isr_function_p (current_function_decl) - && (cfun->machine->va_args_size == 0) -- && decl); -+ && decl -+ && !flag_pic); - } - - /* Determine whether we need to enable warning for function return check. */ -@@ -2566,6 +2641,13 @@ nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) - - case SYMBOL_REF: - /* (mem (symbol_ref A)) => [symbol_ref] */ -+ -+ if (flag_pic || SYMBOL_REF_TLS_MODEL (x)) -+ return false; -+ -+ if (TARGET_ICT_MODEL_LARGE && nds32_indirect_call_referenced_p (x)) -+ return false; -+ - /* If -mcmodel=large, the 'symbol_ref' is not a valid address - during or after LRA/reload phase. */ - if (TARGET_CMODEL_LARGE -@@ -2577,7 +2659,8 @@ nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) - the 'symbol_ref' is not a valid address during or after - LRA/reload phase. */ - if (TARGET_CMODEL_MEDIUM -- && NDS32_SYMBOL_REF_RODATA_P (x) -+ && (NDS32_SYMBOL_REF_RODATA_P (x) -+ || CONSTANT_POOL_ADDRESS_P (x)) - && (reload_completed - || reload_in_progress - || lra_in_progress)) -@@ -2599,6 +2682,10 @@ nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) - { - /* Now we see the [ + const_addr ] pattern, but we need - some further checking. */ -+ -+ if (flag_pic || SYMBOL_REF_TLS_MODEL (op0)) -+ return false; -+ - /* If -mcmodel=large, the 'const_addr' is not a valid address - during or after LRA/reload phase. */ - if (TARGET_CMODEL_LARGE -@@ -2675,17 +2762,202 @@ nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) - - case LO_SUM: - /* (mem (lo_sum (reg) (symbol_ref))) */ -- /* (mem (lo_sum (reg) (const))) */ -- gcc_assert (REG_P (XEXP (x, 0))); -- if (GET_CODE (XEXP (x, 1)) == SYMBOL_REF -- || GET_CODE (XEXP (x, 1)) == CONST) -- return nds32_legitimate_address_p (mode, XEXP (x, 1), strict); -- else -+ /* (mem (lo_sum (reg) (const (plus (symbol_ref) (reg)))) */ -+ /* TLS case: (mem (lo_sum (reg) (const (unspec symbol_ref X)))) */ -+ /* The LO_SUM is a valid address if and only if we would like to -+ generate 32-bit full address memory access with any of following -+ circumstance: -+ 1. -mcmodel=large. -+ 2. -mcmodel=medium and the symbol_ref references to rodata. */ -+ { -+ rtx sym = NULL_RTX; -+ -+ if (flag_pic) -+ return false; -+ -+ if (!REG_P (XEXP (x, 0))) -+ return false; -+ -+ if (GET_CODE (XEXP (x, 1)) == SYMBOL_REF) -+ sym = XEXP (x, 1); -+ else if (GET_CODE (XEXP (x, 1)) == CONST) -+ { -+ rtx plus = XEXP(XEXP (x, 1), 0); -+ if (GET_CODE (plus) == PLUS) -+ sym = XEXP (plus, 0); -+ else if (GET_CODE (plus) == UNSPEC) -+ sym = XVECEXP (plus, 0, 0); -+ } -+ else -+ return false; -+ -+ gcc_assert (GET_CODE (sym) == SYMBOL_REF); -+ -+ if (TARGET_ICT_MODEL_LARGE -+ && nds32_indirect_call_referenced_p (sym)) -+ return true; -+ -+ if (TARGET_CMODEL_LARGE) -+ return true; -+ else if (TARGET_CMODEL_MEDIUM -+ && NDS32_SYMBOL_REF_RODATA_P (sym)) -+ return true; -+ else -+ return false; -+ } -+ -+ default: -+ return false; -+ } -+} -+ -+static rtx -+nds32_legitimize_address (rtx x, -+ rtx oldx ATTRIBUTE_UNUSED, -+ machine_mode mode ATTRIBUTE_UNUSED) -+{ -+ if (nds32_tls_referenced_p (x)) -+ x = nds32_legitimize_tls_address (x); -+ else if (flag_pic && SYMBOLIC_CONST_P (x)) -+ x = nds32_legitimize_pic_address (x); -+ else if (TARGET_ICT_MODEL_LARGE && nds32_indirect_call_referenced_p (x)) -+ x = nds32_legitimize_ict_address (x); -+ -+ return x; -+} -+ -+static bool -+nds32_legitimate_constant_p (machine_mode mode, rtx x) -+{ -+ switch (GET_CODE (x)) -+ { -+ case CONST_DOUBLE: -+ if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) -+ && (mode == DFmode || mode == SFmode)) - return false; -+ break; -+ case CONST: -+ x = XEXP (x, 0); -+ -+ if (GET_CODE (x) == PLUS) -+ { -+ if (!CONST_INT_P (XEXP (x, 1))) -+ return false; -+ x = XEXP (x, 0); -+ } -+ -+ if (GET_CODE (x) == UNSPEC) -+ { -+ switch (XINT (x, 1)) -+ { -+ case UNSPEC_GOT: -+ case UNSPEC_GOTOFF: -+ case UNSPEC_PLT: -+ case UNSPEC_TLSGD: -+ case UNSPEC_TLSLD: -+ case UNSPEC_TLSIE: -+ case UNSPEC_TLSLE: -+ case UNSPEC_ICT: -+ return false; -+ default: -+ return true; -+ } -+ } -+ break; -+ case SYMBOL_REF: -+ /* TLS symbols need a call to resolve in -+ precompute_register_parameters. */ -+ if (SYMBOL_REF_TLS_MODEL (x)) -+ return false; -+ break; -+ default: -+ return true; -+ } -+ -+ return true; -+} - -+/* Reorgnize the UNSPEC CONST and return its direct symbol. */ -+static rtx -+nds32_delegitimize_address (rtx x) -+{ -+ x = delegitimize_mem_from_attrs (x); -+ -+ if (GET_CODE(x) == CONST) -+ { -+ rtx inner = XEXP (x, 0); -+ -+ /* Handle for GOTOFF. */ -+ if (GET_CODE (inner) == PLUS) -+ inner = XEXP (inner, 0); -+ -+ if (GET_CODE (inner) == UNSPEC) -+ { -+ switch (XINT (inner, 1)) -+ { -+ case UNSPEC_GOTINIT: -+ case UNSPEC_GOT: -+ case UNSPEC_GOTOFF: -+ case UNSPEC_PLT: -+ case UNSPEC_TLSGD: -+ case UNSPEC_TLSLD: -+ case UNSPEC_TLSIE: -+ case UNSPEC_TLSLE: -+ case UNSPEC_ICT: -+ x = XVECEXP (inner, 0, 0); -+ break; -+ default: -+ break; -+ } -+ } -+ } -+ return x; -+} -+ -+static machine_mode -+nds32_vectorize_preferred_simd_mode (scalar_mode mode) -+{ -+ if (!NDS32_EXT_DSP_P ()) -+ return word_mode; -+ -+ switch (mode) -+ { -+ case E_QImode: -+ return V4QImode; -+ case E_HImode: -+ return V2HImode; -+ default: -+ return word_mode; -+ } -+} -+ -+static bool -+nds32_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x) -+{ -+ switch (GET_CODE (x)) -+ { -+ case CONST: -+ return !nds32_legitimate_constant_p (mode, x); -+ case SYMBOL_REF: -+ /* All symbols have to be accessed through gp-relative in PIC mode. */ -+ /* We don't want to force symbol as constant pool in .text section, -+ because we use the gp-relatived instruction to load in small -+ or medium model. */ -+ if (flag_pic -+ || SYMBOL_REF_TLS_MODEL (x) -+ || TARGET_CMODEL_SMALL -+ || TARGET_CMODEL_MEDIUM) -+ return true; -+ break; -+ case CONST_INT: -+ case CONST_DOUBLE: -+ if (flag_pic && (lra_in_progress || reload_completed)) -+ return true; -+ break; - default: - return false; - } -+ return false; - } - - -@@ -2731,13 +3003,33 @@ nds32_canonicalize_comparison (int *code, - /* Describing Relative Costs of Operations. */ - - static int --nds32_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED, -+nds32_register_move_cost (machine_mode mode, - reg_class_t from, - reg_class_t to) - { -+ /* In garywolf cpu, FPR to GPR is chaper than other cpu. */ -+ if (TARGET_PIPELINE_GRAYWOLF) -+ { -+ if (GET_MODE_SIZE (mode) == 8) -+ { -+ /* DPR to GPR. */ -+ if (from == FP_REGS && to != FP_REGS) -+ return 3; -+ /* GPR to DPR. */ -+ if (from != FP_REGS && to == FP_REGS) -+ return 2; -+ } -+ else -+ { -+ if ((from == FP_REGS && to != FP_REGS) -+ || (from != FP_REGS && to == FP_REGS)) -+ return 2; -+ } -+ } -+ - if ((from == FP_REGS && to != FP_REGS) - || (from != FP_REGS && to == FP_REGS)) -- return 9; -+ return 3; - else if (from == HIGH_REGS || to == HIGH_REGS) - return optimize_size ? 6 : 2; - else -@@ -2825,6 +3117,9 @@ nds32_asm_file_start (void) - { - default_file_start (); - -+ if (flag_pic) -+ fprintf (asm_out_file, "\t.pic\n"); -+ - /* Tell assembler which ABI we are using. */ - fprintf (asm_out_file, "\t! ABI version\n"); - if (TARGET_HARD_FLOAT) -@@ -2835,10 +3130,36 @@ nds32_asm_file_start (void) - /* Tell assembler that this asm code is generated by compiler. */ - fprintf (asm_out_file, "\t! This asm file is generated by compiler\n"); - fprintf (asm_out_file, "\t.flag\tverbatim\n"); -- /* Give assembler the size of each vector for interrupt handler. */ -- 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); -+ -+ /* Insert directive for linker to distinguish object's ict flag. */ -+ if (!TARGET_LINUX_ABI) -+ { -+ if (TARGET_ICT_MODEL_LARGE) -+ fprintf (asm_out_file, "\t.ict_model\tlarge\n"); -+ else -+ fprintf (asm_out_file, "\t.ict_model\tsmall\n"); -+ } -+ -+ /* 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, -+ the compiler may produce 'la $fp,_FP_BASE_' instruction -+ at prologue for fp-as-gp optimization. -+ We should emit weak reference of _FP_BASE_ to avoid undefined reference -+ in case user does not pass '--relax' option to linker. */ -+ if (!TARGET_LINUX_ABI && (TARGET_FORCE_FP_AS_GP || optimize_size)) -+ { -+ fprintf (asm_out_file, "\t! This weak reference is required to do " -+ "fp-as-gp link time optimization\n"); -+ fprintf (asm_out_file, "\t.weak\t_FP_BASE_\n"); -+ } - - fprintf (asm_out_file, "\t! ------------------------------------\n"); - -@@ -2849,6 +3170,49 @@ nds32_asm_file_start (void) - if (TARGET_ISA_V3M) - fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3M"); - -+ switch (nds32_cpu_option) -+ { -+ case CPU_N6: -+ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N6"); -+ break; -+ -+ case CPU_N7: -+ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N7"); -+ break; -+ -+ case CPU_N8: -+ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N8"); -+ break; -+ -+ case CPU_E8: -+ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "E8"); -+ break; -+ -+ case CPU_N9: -+ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N9"); -+ break; -+ -+ case CPU_N10: -+ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N10"); -+ break; -+ -+ case CPU_GRAYWOLF: -+ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "Graywolf"); -+ break; -+ -+ case CPU_N12: -+ case CPU_N13: -+ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N13"); -+ break; -+ -+ case CPU_SIMPLE: -+ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "SIMPLE"); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ - if (TARGET_CMODEL_SMALL) - fprintf (asm_out_file, "\t! Code model\t\t: %s\n", "SMALL"); - if (TARGET_CMODEL_MEDIUM) -@@ -2926,9 +3290,65 @@ nds32_asm_file_end (void) - { - 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"); - } - -+static bool -+nds32_asm_output_addr_const_extra (FILE *file, rtx x) -+{ -+ if (GET_CODE (x) == UNSPEC) -+ { -+ switch (XINT (x, 1)) -+ { -+ case UNSPEC_GOTINIT: -+ output_addr_const (file, XVECEXP (x, 0, 0)); -+ break; -+ case UNSPEC_GOTOFF: -+ output_addr_const (file, XVECEXP (x, 0, 0)); -+ fputs ("@GOTOFF", file); -+ break; -+ case UNSPEC_GOT: -+ output_addr_const (file, XVECEXP (x, 0, 0)); -+ fputs ("@GOT", file); -+ break; -+ case UNSPEC_PLT: -+ output_addr_const (file, XVECEXP (x, 0, 0)); -+ fputs ("@PLT", file); -+ break; -+ case UNSPEC_TLSGD: -+ output_addr_const (file, XVECEXP (x, 0, 0)); -+ fputs ("@TLSDESC", file); -+ break; -+ case UNSPEC_TLSLD: -+ output_addr_const (file, XVECEXP (x, 0, 0)); -+ fputs ("@TLSDESC", file); -+ break; -+ case UNSPEC_TLSIE: -+ output_addr_const (file, XVECEXP (x, 0, 0)); -+ fputs ("@GOTTPOFF", file); -+ break; -+ case UNSPEC_TLSLE: -+ output_addr_const (file, XVECEXP (x, 0, 0)); -+ fputs ("@TPOFF", file); -+ break; -+ case UNSPEC_ICT: -+ output_addr_const (file, XVECEXP (x, 0, 0)); -+ fputs ("@ICT", file); -+ break; -+ default: -+ return false; -+ } -+ return true; -+ } -+ else -+ return false; -+} -+ - /* -- Output and Generation of Labels. */ - - static void -@@ -2944,13 +3364,15 @@ nds32_asm_globalize_label (FILE *stream, const char *name) - static void - nds32_print_operand (FILE *stream, rtx x, int code) - { -+ HOST_WIDE_INT op_value = 0; - HOST_WIDE_INT one_position; - HOST_WIDE_INT zero_position; - bool pick_lsb_p = false; - bool pick_msb_p = false; - int regno; - -- int op_value; -+ if (CONST_INT_P (x)) -+ op_value = INTVAL (x); - - switch (code) - { -@@ -2976,6 +3398,18 @@ nds32_print_operand (FILE *stream, rtx x, int code) - - /* No need to handle following process, so return immediately. */ - return; -+ -+ case 'v': -+ gcc_assert (CONST_INT_P (x) -+ && (INTVAL (x) == 0 -+ || INTVAL (x) == 8 -+ || INTVAL (x) == 16 -+ || INTVAL (x) == 24)); -+ fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) / 8); -+ -+ /* No need to handle following process, so return immediately. */ -+ return; -+ - case 'B': - /* Use exact_log2() to search the 1-bit position. */ - gcc_assert (CONST_INT_P (x)); -@@ -3003,7 +3437,6 @@ nds32_print_operand (FILE *stream, rtx x, int code) - case 'V': - /* 'x' is supposed to be CONST_INT, get the value. */ - gcc_assert (CONST_INT_P (x)); -- op_value = INTVAL (x); - - /* According to the Andes architecture, - the system/user register index range is 0 ~ 1023. -@@ -3083,8 +3516,15 @@ nds32_print_operand (FILE *stream, rtx x, int code) - switch (GET_CODE (x)) - { - case LABEL_REF: -+ output_addr_const (stream, x); -+ break; -+ - case SYMBOL_REF: - output_addr_const (stream, x); -+ -+ if (!TARGET_LINUX_ABI && nds32_indirect_call_referenced_p (x)) -+ fprintf (stream, "@ICT"); -+ - break; - - case REG: -@@ -3167,6 +3607,17 @@ nds32_print_operand (FILE *stream, rtx x, int code) - output_addr_const (stream, x); - break; - -+ case CONST_VECTOR: -+ fprintf (stream, HOST_WIDE_INT_PRINT_HEX, const_vector_to_hwint (x)); -+ break; -+ -+ case LO_SUM: -+ /* This is a special case for inline assembly using memory address 'p'. -+ The inline assembly code is expected to use pesudo instruction -+ for the operand. EX: la */ -+ output_addr_const (stream, XEXP(x, 1)); -+ break; -+ - default: - /* Generally, output_addr_const () is able to handle most cases. - We want to see what CODE could appear, -@@ -3178,7 +3629,9 @@ nds32_print_operand (FILE *stream, rtx x, int code) - } - - static void --nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) -+nds32_print_operand_address (FILE *stream, -+ machine_mode mode ATTRIBUTE_UNUSED, -+ rtx x) - { - rtx op0, op1; - -@@ -3193,6 +3646,16 @@ nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) - fputs ("]", stream); - break; - -+ case LO_SUM: -+ /* This is a special case for inline assembly using memory operand 'm'. -+ The inline assembly code is expected to use pesudo instruction -+ for the operand. EX: [ls].[bhw] */ -+ fputs ("[ + ", stream); -+ op1 = XEXP (x, 1); -+ output_addr_const (stream, op1); -+ fputs ("]", stream); -+ break; -+ - case REG: - /* Forbid using static chain register ($r16) - on reduced-set registers configuration. */ -@@ -3259,6 +3722,20 @@ nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) - reg_names[REGNO (XEXP (op0, 0))], - sv); - } -+ else if (GET_CODE (op0) == ASHIFT && REG_P (op1)) -+ { -+ /* [Ra + Rb << sv] -+ In normal, ASHIFT can be converted to MULT like above case. -+ But when the address rtx does not go through canonicalize_address -+ defined in fwprop, we'll need this case. */ -+ int sv = INTVAL (XEXP (op0, 1)); -+ gcc_assert (sv <= 3 && sv >=0); -+ -+ fprintf (stream, "[%s + %s << %d]", -+ reg_names[REGNO (op1)], -+ reg_names[REGNO (XEXP (op0, 0))], -+ sv); -+ } - else - { - /* The control flow is not supposed to be here. */ -@@ -3453,6 +3930,27 @@ nds32_merge_decl_attributes (tree olddecl, tree newdecl) - static void - nds32_insert_attributes (tree decl, tree *attributes) - { -+ /* A "indirect_call" function attribute implies "noinline" and "noclone" -+ for elf toolchain to support ROM patch mechanism. */ -+ if (TREE_CODE (decl) == FUNCTION_DECL -+ && lookup_attribute ("indirect_call", *attributes) != NULL) -+ { -+ tree new_attrs = *attributes; -+ -+ if (TARGET_LINUX_ABI) -+ error("cannot use indirect_call attribute under linux toolchain"); -+ -+ if (lookup_attribute ("noinline", new_attrs) == NULL) -+ new_attrs = tree_cons (get_identifier ("noinline"), NULL, new_attrs); -+ if (lookup_attribute ("noclone", new_attrs) == NULL) -+ new_attrs = tree_cons (get_identifier ("noclone"), NULL, new_attrs); -+ -+ if (!TREE_PUBLIC (decl)) -+ error("indirect_call attribute can't apply for static function"); -+ -+ *attributes = new_attrs; -+ } -+ - /* For function declaration, we need to check isr-specific attributes: - 1. Call nds32_check_isr_attrs_conflict() to check any conflict. - 2. Check valid integer value for interrupt/exception. -@@ -3478,6 +3976,38 @@ nds32_insert_attributes (tree decl, tree *attributes) - excp = lookup_attribute ("exception", func_attrs); - reset = lookup_attribute ("reset", func_attrs); - -+ /* The following code may use attribute arguments. If there is no -+ argument from source code, it will cause segmentation fault. -+ Therefore, return dircetly and report error message later. */ -+ if ((intr && TREE_VALUE (intr) == NULL) -+ || (excp && TREE_VALUE (excp) == NULL) -+ || (reset && TREE_VALUE (reset) == NULL)) -+ return; -+ -+ /* ------------------------------------------------------------- */ -+ /* FIXME: -+ FOR BACKWARD COMPATIBILITY, we need to support following patterns: -+ -+ __attribute__((interrupt("XXX;YYY;id=ZZZ"))) -+ __attribute__((exception("XXX;YYY;id=ZZZ"))) -+ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ"))) -+ -+ If interrupt/exception/reset appears and its argument is a -+ STRING_CST, we will use other functions to parse string in the -+ nds32_construct_isr_vectors_information() and then set necessary -+ isr information in the nds32_isr_vectors[] array. Here we can -+ just return immediately to avoid new-syntax checking. */ -+ if (intr != NULL_TREE -+ && TREE_CODE (TREE_VALUE (TREE_VALUE (intr))) == STRING_CST) -+ return; -+ if (excp != NULL_TREE -+ && TREE_CODE (TREE_VALUE (TREE_VALUE (excp))) == STRING_CST) -+ return; -+ if (reset != NULL_TREE -+ && TREE_CODE (TREE_VALUE (TREE_VALUE (reset))) == STRING_CST) -+ return; -+ /* ------------------------------------------------------------- */ -+ - if (intr || excp) - { - /* Deal with interrupt/exception. */ -@@ -3597,7 +4127,9 @@ nds32_option_override (void) - } - if (TARGET_ISA_V3) - { -- /* Under V3 ISA, currently nothing should be strictly set. */ -+ /* If this is ARCH_V3J, we need to enable TARGET_REDUCED_REGS. */ -+ if (nds32_arch_option == ARCH_V3J) -+ target_flags |= MASK_REDUCED_REGS; - } - if (TARGET_ISA_V3M) - { -@@ -3609,6 +4141,9 @@ nds32_option_override (void) - target_flags &= ~MASK_EXT_PERF2; - /* Under V3M ISA, we need to strictly disable TARGET_EXT_STRING. */ - target_flags &= ~MASK_EXT_STRING; -+ -+ if (flag_pic) -+ error ("not support -fpic option for v3m toolchain"); - } - - /* See if we are using reduced-set registers: -@@ -3626,6 +4161,12 @@ nds32_option_override (void) - fixed_regs[r] = call_used_regs[r] = 1; - } - -+ /* See if user explicitly would like to use fp-as-gp optimization. -+ If so, we must prevent $fp from being allocated -+ during register allocation. */ -+ if (TARGET_FORCE_FP_AS_GP) -+ fixed_regs[FP_REGNUM] = call_used_regs[FP_REGNUM] = 1; -+ - if (!TARGET_16_BIT) - { - /* Under no 16 bit ISA, we need to strictly disable TARGET_V3PUSH. */ -@@ -3642,9 +4183,7 @@ nds32_option_override (void) - "must be enable '-mext-fpu-sp' or '-mext-fpu-dp'"); - } - -- /* Currently, we don't support PIC code generation yet. */ -- if (flag_pic) -- sorry ("position-independent code not supported"); -+ nds32_init_rtx_costs (); - - nds32_register_passes (); - } -@@ -3658,8 +4197,11 @@ nds32_md_asm_adjust (vec &outputs ATTRIBUTE_UNUSED, - vec &constraints ATTRIBUTE_UNUSED, - vec &clobbers, HARD_REG_SET &clobbered_regs) - { -- clobbers.safe_push (gen_rtx_REG (SImode, TA_REGNUM)); -- SET_HARD_REG_BIT (clobbered_regs, TA_REGNUM); -+ if (!flag_inline_asm_r15) -+ { -+ clobbers.safe_push (gen_rtx_REG (SImode, TA_REGNUM)); -+ SET_HARD_REG_BIT (clobbered_regs, TA_REGNUM); -+ } - return NULL; - } - -@@ -3686,6 +4228,13 @@ nds32_expand_builtin (tree exp, - 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); -+} - - /* ------------------------------------------------------------------------ */ - -@@ -3702,6 +4251,16 @@ nds32_cpu_cpp_builtins(struct cpp_reader *pfile) - builtin_define ("__nds32__"); - builtin_define ("__NDS32__"); - -+ /* We need to provide builtin macro to describe the size of -+ each vector for interrupt handler under elf toolchain. */ -+ if (!TARGET_LINUX_ABI) -+ { -+ if (TARGET_ISR_VECTOR_SIZE_4_BYTE) -+ builtin_define ("__NDS32_ISR_VECTOR_SIZE_4__"); -+ else -+ builtin_define ("__NDS32_ISR_VECTOR_SIZE_16__"); -+ } -+ - if (TARGET_HARD_FLOAT) - builtin_define ("__NDS32_ABI_2FP_PLUS__"); - else -@@ -3769,6 +4328,8 @@ nds32_cpu_cpp_builtins(struct cpp_reader *pfile) - builtin_define ("__NDS32_GP_DIRECT__"); - if (TARGET_VH) - builtin_define ("__NDS32_VH__"); -+ if (NDS32_EXT_DSP_P ()) -+ builtin_define ("__NDS32_EXT_DSP__"); - - if (TARGET_BIG_ENDIAN) - builtin_define ("__big_endian__"); -@@ -4041,6 +4602,10 @@ nds32_expand_prologue (void) - The result will be in cfun->machine. */ - nds32_compute_stack_frame (); - -+ /* Check frame_pointer_needed again to prevent fp is need after reload. */ -+ if (frame_pointer_needed) -+ cfun->machine->fp_as_gp_p = false; -+ - /* If this is a variadic function, first we need to push argument - registers that hold the unnamed argument value. */ - if (cfun->machine->va_args_size != 0) -@@ -4065,7 +4630,7 @@ nds32_expand_prologue (void) - - /* If the function is 'naked', - we do not have to generate prologue code fragment. */ -- if (cfun->machine->naked_p) -+ if (cfun->machine->naked_p && !flag_pic) - return; - - /* Get callee_first_regno and callee_last_regno. */ -@@ -4194,9 +4759,15 @@ nds32_expand_prologue (void) - -1 * sp_adjust); - } - -- /* Prevent the instruction scheduler from -- moving instructions across the boundary. */ -- emit_insn (gen_blockage ()); -+ /* Emit gp setup instructions for -fpic. */ -+ if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) -+ nds32_emit_load_gp (); -+ -+ /* If user applies -mno-sched-prolog-epilog option, -+ we need to prevent instructions of function body from being -+ scheduled with stack adjustment in prologue. */ -+ if (!flag_sched_prolog_epilog) -+ emit_insn (gen_blockage ()); - } - - /* Function for normal multiple pop epilogue. */ -@@ -4210,9 +4781,11 @@ nds32_expand_epilogue (bool sibcall_p) - The result will be in cfun->machine. */ - nds32_compute_stack_frame (); - -- /* Prevent the instruction scheduler from -- moving instructions across the boundary. */ -- emit_insn (gen_blockage ()); -+ /* If user applies -mno-sched-prolog-epilog option, -+ we need to prevent instructions of function body from being -+ scheduled with stack adjustment in epilogue. */ -+ if (!flag_sched_prolog_epilog) -+ emit_insn (gen_blockage ()); - - /* If the function is 'naked', we do not have to generate - epilogue code fragment BUT 'ret' instruction. -@@ -4238,7 +4811,16 @@ nds32_expand_epilogue (bool sibcall_p) - /* Generate return instruction by using 'return_internal' pattern. - Make sure this instruction is after gen_blockage(). */ - if (!sibcall_p) -- emit_jump_insn (gen_return_internal ()); -+ { -+ /* We need to further check attributes to determine whether -+ there should be return instruction at epilogue. -+ If the attribute naked exists but -mno-ret-in-naked-func -+ is issued, there is NO need to generate return instruction. */ -+ if (cfun->machine->attr_naked_p && !flag_ret_in_naked_func) -+ return; -+ -+ emit_jump_insn (gen_return_internal ()); -+ } - return; - } - -@@ -4435,9 +5017,13 @@ nds32_expand_prologue_v3push (void) - if (cfun->machine->callee_saved_gpr_regs_size > 0) - df_set_regs_ever_live (FP_REGNUM, 1); - -+ /* Check frame_pointer_needed again to prevent fp is need after reload. */ -+ if (frame_pointer_needed) -+ cfun->machine->fp_as_gp_p = false; -+ - /* If the function is 'naked', - we do not have to generate prologue code fragment. */ -- if (cfun->machine->naked_p) -+ if (cfun->machine->naked_p && !flag_pic) - return; - - /* Get callee_first_regno and callee_last_regno. */ -@@ -4565,6 +5151,10 @@ nds32_expand_prologue_v3push (void) - -1 * sp_adjust); - } - -+ /* Emit gp setup instructions for -fpic. */ -+ if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) -+ nds32_emit_load_gp (); -+ - /* Prevent the instruction scheduler from - moving instructions across the boundary. */ - emit_insn (gen_blockage ()); -@@ -4590,9 +5180,19 @@ nds32_expand_epilogue_v3pop (bool sibcall_p) - if (cfun->machine->naked_p) - { - /* Generate return instruction by using 'return_internal' pattern. -- Make sure this instruction is after gen_blockage(). */ -+ Make sure this instruction is after gen_blockage(). -+ First we need to check this is a function without sibling call. */ - if (!sibcall_p) -- emit_jump_insn (gen_return_internal ()); -+ { -+ /* We need to further check attributes to determine whether -+ there should be return instruction at epilogue. -+ If the attribute naked exists but -mno-ret-in-naked-func -+ is issued, there is NO need to generate return instruction. */ -+ if (cfun->machine->attr_naked_p && !flag_ret_in_naked_func) -+ return; -+ -+ emit_jump_insn (gen_return_internal ()); -+ } - return; - } - -@@ -4756,6 +5356,11 @@ nds32_can_use_return_insn (void) - if (!reload_completed) - return 0; - -+ /* If attribute 'naked' appears but -mno-ret-in-naked-func is used, -+ we cannot use return instruction. */ -+ if (cfun->machine->attr_naked_p && !flag_ret_in_naked_func) -+ return 0; -+ - sp_adjust = cfun->machine->local_size - + cfun->machine->out_args_size - + cfun->machine->callee_saved_area_gpr_padding_bytes -@@ -5009,6 +5614,9 @@ nds32_use_blocks_for_constant_p (machine_mode mode, - #undef TARGET_FUNCTION_ARG_BOUNDARY - #define TARGET_FUNCTION_ARG_BOUNDARY nds32_function_arg_boundary - -+#undef TARGET_VECTOR_MODE_SUPPORTED_P -+#define TARGET_VECTOR_MODE_SUPPORTED_P nds32_vector_mode_supported_p -+ - /* -- How Scalar Function Values Are Returned. */ - - #undef TARGET_FUNCTION_VALUE -@@ -5086,6 +5694,21 @@ nds32_use_blocks_for_constant_p (machine_mode mode, - #undef TARGET_LEGITIMATE_ADDRESS_P - #define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p - -+#undef TARGET_LEGITIMIZE_ADDRESS -+#define TARGET_LEGITIMIZE_ADDRESS nds32_legitimize_address -+ -+#undef TARGET_LEGITIMATE_CONSTANT_P -+#define TARGET_LEGITIMATE_CONSTANT_P nds32_legitimate_constant_p -+ -+#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE -+#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE nds32_vectorize_preferred_simd_mode -+ -+#undef TARGET_CANNOT_FORCE_CONST_MEM -+#define TARGET_CANNOT_FORCE_CONST_MEM nds32_cannot_force_const_mem -+ -+#undef TARGET_DELEGITIMIZE_ADDRESS -+#define TARGET_DELEGITIMIZE_ADDRESS nds32_delegitimize_address -+ - - /* Anchored Addresses. */ - -@@ -5146,6 +5769,9 @@ nds32_use_blocks_for_constant_p (machine_mode mode, - #undef TARGET_ASM_ALIGNED_SI_OP - #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" - -+#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA -+#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nds32_asm_output_addr_const_extra -+ - /* -- Output of Uninitialized Variables. */ - - /* -- Output and Generation of Labels. */ -@@ -5215,6 +5841,9 @@ nds32_use_blocks_for_constant_p (machine_mode mode, - - /* Emulating TLS. */ - -+#undef TARGET_HAVE_TLS -+#define TARGET_HAVE_TLS TARGET_LINUX_ABI -+ - - /* Defining coprocessor specifics for MIPS targets. */ - -@@ -5242,6 +5871,8 @@ nds32_use_blocks_for_constant_p (machine_mode mode, - #undef TARGET_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 - #define TARGET_USE_BLOCKS_FOR_CONSTANT_P nds32_use_blocks_for_constant_p -diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h -index 29edccdd040..e3ceb632ebd 100644 ---- a/gcc/config/nds32/nds32.h -+++ b/gcc/config/nds32/nds32.h -@@ -36,6 +36,16 @@ - #define NDS32_SYMBOL_REF_RODATA_P(x) \ - ((SYMBOL_REF_FLAGS (x) & NDS32_SYMBOL_FLAG_RODATA) != 0) - -+enum nds32_relax_insn_type -+{ -+ RELAX_ORI, -+ RELAX_PLT_ADD, -+ RELAX_TLS_ADD_or_LW, -+ RELAX_TLS_ADD_LW, -+ RELAX_TLS_LW_JRAL, -+ RELAX_DONE -+}; -+ - /* Classifies expand result for expand helper function. */ - enum nds32_expand_result_type - { -@@ -140,6 +150,9 @@ enum nds32_16bit_address_type - Check gcc/common/config/nds32/nds32-common.c for the optimizations that - apply -malways-align. */ - #define NDS32_ALIGN_P() (TARGET_ALWAYS_ALIGN) -+ -+#define NDS32_EXT_DSP_P() (TARGET_EXT_DSP && !TARGET_FORCE_NO_EXT_DSP) -+ - /* Get alignment according to mode or type information. - When 'type' is nonnull, there is no need to look at 'mode'. */ - #define NDS32_MODE_TYPE_ALIGN(mode, type) \ -@@ -305,6 +318,10 @@ struct GTY(()) machine_function - 2. The rtl lowering and optimization are close to target code. - For this case we need address to be strictly aligned. */ - int strict_aligned_p; -+ -+ /* Record two similar attributes status. */ -+ int attr_naked_p; -+ int attr_no_prologue_p; - }; - - /* A C structure that contains the arguments information. */ -@@ -350,7 +367,8 @@ enum nds32_isr_nested_type - { - NDS32_NESTED, - NDS32_NOT_NESTED, -- NDS32_NESTED_READY -+ NDS32_NESTED_READY, -+ NDS32_CRITICAL - }; - - /* Define structure to record isr information. -@@ -378,6 +396,13 @@ struct nds32_isr_info - unless user specifies attribute to change it. */ - enum nds32_isr_nested_type nested_type; - -+ /* Secure isr level. -+ Currently we have 0-3 security level. -+ It should be set to 0 by default. -+ For security processors, this is determined by secure -+ attribute or compiler options. */ -+ unsigned int security_level; -+ - /* Total vectors. - The total vectors = interrupt + exception numbers + reset. - It should be set to 0 by default. -@@ -439,7 +464,30 @@ enum nds32_builtins - NDS32_BUILTIN_FFB, - NDS32_BUILTIN_FFMISM, - NDS32_BUILTIN_FLMISM, -- -+ NDS32_BUILTIN_KADDW, -+ NDS32_BUILTIN_KSUBW, -+ NDS32_BUILTIN_KADDH, -+ NDS32_BUILTIN_KSUBH, -+ NDS32_BUILTIN_KDMBB, -+ NDS32_BUILTIN_V_KDMBB, -+ NDS32_BUILTIN_KDMBT, -+ NDS32_BUILTIN_V_KDMBT, -+ NDS32_BUILTIN_KDMTB, -+ NDS32_BUILTIN_V_KDMTB, -+ NDS32_BUILTIN_KDMTT, -+ NDS32_BUILTIN_V_KDMTT, -+ NDS32_BUILTIN_KHMBB, -+ NDS32_BUILTIN_V_KHMBB, -+ NDS32_BUILTIN_KHMBT, -+ NDS32_BUILTIN_V_KHMBT, -+ NDS32_BUILTIN_KHMTB, -+ NDS32_BUILTIN_V_KHMTB, -+ NDS32_BUILTIN_KHMTT, -+ NDS32_BUILTIN_V_KHMTT, -+ NDS32_BUILTIN_KSLRAW, -+ NDS32_BUILTIN_KSLRAW_U, -+ NDS32_BUILTIN_RDOV, -+ NDS32_BUILTIN_CLROV, - NDS32_BUILTIN_ROTR, - NDS32_BUILTIN_SVA, - NDS32_BUILTIN_SVS, -@@ -512,7 +560,295 @@ enum nds32_builtins - NDS32_BUILTIN_SET_TRIG_LEVEL, - NDS32_BUILTIN_SET_TRIG_EDGE, - NDS32_BUILTIN_GET_TRIG_TYPE, -- -+ NDS32_BUILTIN_DSP_BEGIN, -+ NDS32_BUILTIN_ADD16, -+ NDS32_BUILTIN_V_UADD16, -+ NDS32_BUILTIN_V_SADD16, -+ NDS32_BUILTIN_RADD16, -+ NDS32_BUILTIN_V_RADD16, -+ NDS32_BUILTIN_URADD16, -+ NDS32_BUILTIN_V_URADD16, -+ NDS32_BUILTIN_KADD16, -+ NDS32_BUILTIN_V_KADD16, -+ NDS32_BUILTIN_UKADD16, -+ NDS32_BUILTIN_V_UKADD16, -+ NDS32_BUILTIN_SUB16, -+ NDS32_BUILTIN_V_USUB16, -+ NDS32_BUILTIN_V_SSUB16, -+ NDS32_BUILTIN_RSUB16, -+ NDS32_BUILTIN_V_RSUB16, -+ NDS32_BUILTIN_URSUB16, -+ NDS32_BUILTIN_V_URSUB16, -+ NDS32_BUILTIN_KSUB16, -+ NDS32_BUILTIN_V_KSUB16, -+ NDS32_BUILTIN_UKSUB16, -+ NDS32_BUILTIN_V_UKSUB16, -+ NDS32_BUILTIN_CRAS16, -+ NDS32_BUILTIN_V_UCRAS16, -+ NDS32_BUILTIN_V_SCRAS16, -+ NDS32_BUILTIN_RCRAS16, -+ NDS32_BUILTIN_V_RCRAS16, -+ NDS32_BUILTIN_URCRAS16, -+ NDS32_BUILTIN_V_URCRAS16, -+ NDS32_BUILTIN_KCRAS16, -+ NDS32_BUILTIN_V_KCRAS16, -+ NDS32_BUILTIN_UKCRAS16, -+ NDS32_BUILTIN_V_UKCRAS16, -+ NDS32_BUILTIN_CRSA16, -+ NDS32_BUILTIN_V_UCRSA16, -+ NDS32_BUILTIN_V_SCRSA16, -+ NDS32_BUILTIN_RCRSA16, -+ NDS32_BUILTIN_V_RCRSA16, -+ NDS32_BUILTIN_URCRSA16, -+ NDS32_BUILTIN_V_URCRSA16, -+ NDS32_BUILTIN_KCRSA16, -+ NDS32_BUILTIN_V_KCRSA16, -+ NDS32_BUILTIN_UKCRSA16, -+ NDS32_BUILTIN_V_UKCRSA16, -+ NDS32_BUILTIN_ADD8, -+ NDS32_BUILTIN_V_UADD8, -+ NDS32_BUILTIN_V_SADD8, -+ NDS32_BUILTIN_RADD8, -+ NDS32_BUILTIN_V_RADD8, -+ NDS32_BUILTIN_URADD8, -+ NDS32_BUILTIN_V_URADD8, -+ NDS32_BUILTIN_KADD8, -+ NDS32_BUILTIN_V_KADD8, -+ NDS32_BUILTIN_UKADD8, -+ NDS32_BUILTIN_V_UKADD8, -+ NDS32_BUILTIN_SUB8, -+ NDS32_BUILTIN_V_USUB8, -+ NDS32_BUILTIN_V_SSUB8, -+ NDS32_BUILTIN_RSUB8, -+ NDS32_BUILTIN_V_RSUB8, -+ NDS32_BUILTIN_URSUB8, -+ NDS32_BUILTIN_V_URSUB8, -+ NDS32_BUILTIN_KSUB8, -+ NDS32_BUILTIN_V_KSUB8, -+ NDS32_BUILTIN_UKSUB8, -+ NDS32_BUILTIN_V_UKSUB8, -+ NDS32_BUILTIN_SRA16, -+ NDS32_BUILTIN_V_SRA16, -+ NDS32_BUILTIN_SRA16_U, -+ NDS32_BUILTIN_V_SRA16_U, -+ NDS32_BUILTIN_SRL16, -+ NDS32_BUILTIN_V_SRL16, -+ NDS32_BUILTIN_SRL16_U, -+ NDS32_BUILTIN_V_SRL16_U, -+ NDS32_BUILTIN_SLL16, -+ NDS32_BUILTIN_V_SLL16, -+ NDS32_BUILTIN_KSLL16, -+ NDS32_BUILTIN_V_KSLL16, -+ NDS32_BUILTIN_KSLRA16, -+ NDS32_BUILTIN_V_KSLRA16, -+ NDS32_BUILTIN_KSLRA16_U, -+ NDS32_BUILTIN_V_KSLRA16_U, -+ NDS32_BUILTIN_CMPEQ16, -+ NDS32_BUILTIN_V_SCMPEQ16, -+ NDS32_BUILTIN_V_UCMPEQ16, -+ NDS32_BUILTIN_SCMPLT16, -+ NDS32_BUILTIN_V_SCMPLT16, -+ NDS32_BUILTIN_SCMPLE16, -+ NDS32_BUILTIN_V_SCMPLE16, -+ NDS32_BUILTIN_UCMPLT16, -+ NDS32_BUILTIN_V_UCMPLT16, -+ NDS32_BUILTIN_UCMPLE16, -+ NDS32_BUILTIN_V_UCMPLE16, -+ NDS32_BUILTIN_CMPEQ8, -+ NDS32_BUILTIN_V_SCMPEQ8, -+ NDS32_BUILTIN_V_UCMPEQ8, -+ NDS32_BUILTIN_SCMPLT8, -+ NDS32_BUILTIN_V_SCMPLT8, -+ NDS32_BUILTIN_SCMPLE8, -+ NDS32_BUILTIN_V_SCMPLE8, -+ NDS32_BUILTIN_UCMPLT8, -+ NDS32_BUILTIN_V_UCMPLT8, -+ NDS32_BUILTIN_UCMPLE8, -+ NDS32_BUILTIN_V_UCMPLE8, -+ NDS32_BUILTIN_SMIN16, -+ NDS32_BUILTIN_V_SMIN16, -+ NDS32_BUILTIN_UMIN16, -+ NDS32_BUILTIN_V_UMIN16, -+ NDS32_BUILTIN_SMAX16, -+ NDS32_BUILTIN_V_SMAX16, -+ NDS32_BUILTIN_UMAX16, -+ NDS32_BUILTIN_V_UMAX16, -+ NDS32_BUILTIN_SCLIP16, -+ NDS32_BUILTIN_V_SCLIP16, -+ NDS32_BUILTIN_UCLIP16, -+ NDS32_BUILTIN_V_UCLIP16, -+ NDS32_BUILTIN_KHM16, -+ NDS32_BUILTIN_V_KHM16, -+ NDS32_BUILTIN_KHMX16, -+ NDS32_BUILTIN_V_KHMX16, -+ NDS32_BUILTIN_KABS16, -+ NDS32_BUILTIN_V_KABS16, -+ NDS32_BUILTIN_SMIN8, -+ NDS32_BUILTIN_V_SMIN8, -+ NDS32_BUILTIN_UMIN8, -+ NDS32_BUILTIN_V_UMIN8, -+ NDS32_BUILTIN_SMAX8, -+ NDS32_BUILTIN_V_SMAX8, -+ NDS32_BUILTIN_UMAX8, -+ NDS32_BUILTIN_V_UMAX8, -+ NDS32_BUILTIN_KABS8, -+ NDS32_BUILTIN_V_KABS8, -+ NDS32_BUILTIN_SUNPKD810, -+ NDS32_BUILTIN_V_SUNPKD810, -+ NDS32_BUILTIN_SUNPKD820, -+ NDS32_BUILTIN_V_SUNPKD820, -+ NDS32_BUILTIN_SUNPKD830, -+ NDS32_BUILTIN_V_SUNPKD830, -+ NDS32_BUILTIN_SUNPKD831, -+ NDS32_BUILTIN_V_SUNPKD831, -+ NDS32_BUILTIN_ZUNPKD810, -+ NDS32_BUILTIN_V_ZUNPKD810, -+ NDS32_BUILTIN_ZUNPKD820, -+ NDS32_BUILTIN_V_ZUNPKD820, -+ NDS32_BUILTIN_ZUNPKD830, -+ NDS32_BUILTIN_V_ZUNPKD830, -+ NDS32_BUILTIN_ZUNPKD831, -+ NDS32_BUILTIN_V_ZUNPKD831, -+ NDS32_BUILTIN_RADDW, -+ NDS32_BUILTIN_URADDW, -+ NDS32_BUILTIN_RSUBW, -+ NDS32_BUILTIN_URSUBW, -+ NDS32_BUILTIN_SRA_U, -+ NDS32_BUILTIN_KSLL, -+ NDS32_BUILTIN_PKBB16, -+ NDS32_BUILTIN_V_PKBB16, -+ NDS32_BUILTIN_PKBT16, -+ NDS32_BUILTIN_V_PKBT16, -+ NDS32_BUILTIN_PKTB16, -+ NDS32_BUILTIN_V_PKTB16, -+ NDS32_BUILTIN_PKTT16, -+ NDS32_BUILTIN_V_PKTT16, -+ NDS32_BUILTIN_SMMUL, -+ NDS32_BUILTIN_SMMUL_U, -+ NDS32_BUILTIN_KMMAC, -+ NDS32_BUILTIN_KMMAC_U, -+ NDS32_BUILTIN_KMMSB, -+ NDS32_BUILTIN_KMMSB_U, -+ NDS32_BUILTIN_KWMMUL, -+ NDS32_BUILTIN_KWMMUL_U, -+ NDS32_BUILTIN_SMMWB, -+ NDS32_BUILTIN_V_SMMWB, -+ NDS32_BUILTIN_SMMWB_U, -+ NDS32_BUILTIN_V_SMMWB_U, -+ NDS32_BUILTIN_SMMWT, -+ NDS32_BUILTIN_V_SMMWT, -+ NDS32_BUILTIN_SMMWT_U, -+ NDS32_BUILTIN_V_SMMWT_U, -+ NDS32_BUILTIN_KMMAWB, -+ NDS32_BUILTIN_V_KMMAWB, -+ NDS32_BUILTIN_KMMAWB_U, -+ NDS32_BUILTIN_V_KMMAWB_U, -+ NDS32_BUILTIN_KMMAWT, -+ NDS32_BUILTIN_V_KMMAWT, -+ NDS32_BUILTIN_KMMAWT_U, -+ NDS32_BUILTIN_V_KMMAWT_U, -+ NDS32_BUILTIN_SMBB, -+ NDS32_BUILTIN_V_SMBB, -+ NDS32_BUILTIN_SMBT, -+ NDS32_BUILTIN_V_SMBT, -+ NDS32_BUILTIN_SMTT, -+ NDS32_BUILTIN_V_SMTT, -+ NDS32_BUILTIN_KMDA, -+ NDS32_BUILTIN_V_KMDA, -+ NDS32_BUILTIN_KMXDA, -+ NDS32_BUILTIN_V_KMXDA, -+ NDS32_BUILTIN_SMDS, -+ NDS32_BUILTIN_V_SMDS, -+ NDS32_BUILTIN_SMDRS, -+ NDS32_BUILTIN_V_SMDRS, -+ NDS32_BUILTIN_SMXDS, -+ NDS32_BUILTIN_V_SMXDS, -+ NDS32_BUILTIN_KMABB, -+ NDS32_BUILTIN_V_KMABB, -+ NDS32_BUILTIN_KMABT, -+ NDS32_BUILTIN_V_KMABT, -+ NDS32_BUILTIN_KMATT, -+ NDS32_BUILTIN_V_KMATT, -+ NDS32_BUILTIN_KMADA, -+ NDS32_BUILTIN_V_KMADA, -+ NDS32_BUILTIN_KMAXDA, -+ NDS32_BUILTIN_V_KMAXDA, -+ NDS32_BUILTIN_KMADS, -+ NDS32_BUILTIN_V_KMADS, -+ NDS32_BUILTIN_KMADRS, -+ NDS32_BUILTIN_V_KMADRS, -+ NDS32_BUILTIN_KMAXDS, -+ NDS32_BUILTIN_V_KMAXDS, -+ NDS32_BUILTIN_KMSDA, -+ NDS32_BUILTIN_V_KMSDA, -+ NDS32_BUILTIN_KMSXDA, -+ NDS32_BUILTIN_V_KMSXDA, -+ NDS32_BUILTIN_SMAL, -+ NDS32_BUILTIN_V_SMAL, -+ NDS32_BUILTIN_BITREV, -+ NDS32_BUILTIN_WEXT, -+ NDS32_BUILTIN_BPICK, -+ NDS32_BUILTIN_INSB, -+ NDS32_BUILTIN_SADD64, -+ NDS32_BUILTIN_UADD64, -+ NDS32_BUILTIN_RADD64, -+ NDS32_BUILTIN_URADD64, -+ NDS32_BUILTIN_KADD64, -+ NDS32_BUILTIN_UKADD64, -+ NDS32_BUILTIN_SSUB64, -+ NDS32_BUILTIN_USUB64, -+ NDS32_BUILTIN_RSUB64, -+ NDS32_BUILTIN_URSUB64, -+ NDS32_BUILTIN_KSUB64, -+ NDS32_BUILTIN_UKSUB64, -+ NDS32_BUILTIN_SMAR64, -+ NDS32_BUILTIN_SMSR64, -+ NDS32_BUILTIN_UMAR64, -+ NDS32_BUILTIN_UMSR64, -+ NDS32_BUILTIN_KMAR64, -+ NDS32_BUILTIN_KMSR64, -+ NDS32_BUILTIN_UKMAR64, -+ NDS32_BUILTIN_UKMSR64, -+ NDS32_BUILTIN_SMALBB, -+ NDS32_BUILTIN_V_SMALBB, -+ NDS32_BUILTIN_SMALBT, -+ NDS32_BUILTIN_V_SMALBT, -+ NDS32_BUILTIN_SMALTT, -+ NDS32_BUILTIN_V_SMALTT, -+ NDS32_BUILTIN_SMALDA, -+ NDS32_BUILTIN_V_SMALDA, -+ NDS32_BUILTIN_SMALXDA, -+ NDS32_BUILTIN_V_SMALXDA, -+ NDS32_BUILTIN_SMALDS, -+ NDS32_BUILTIN_V_SMALDS, -+ NDS32_BUILTIN_SMALDRS, -+ NDS32_BUILTIN_V_SMALDRS, -+ NDS32_BUILTIN_SMALXDS, -+ NDS32_BUILTIN_V_SMALXDS, -+ NDS32_BUILTIN_SMUL16, -+ NDS32_BUILTIN_V_SMUL16, -+ NDS32_BUILTIN_SMULX16, -+ NDS32_BUILTIN_V_SMULX16, -+ NDS32_BUILTIN_UMUL16, -+ NDS32_BUILTIN_V_UMUL16, -+ NDS32_BUILTIN_UMULX16, -+ NDS32_BUILTIN_V_UMULX16, -+ NDS32_BUILTIN_SMSLDA, -+ NDS32_BUILTIN_V_SMSLDA, -+ NDS32_BUILTIN_SMSLXDA, -+ NDS32_BUILTIN_V_SMSLXDA, -+ NDS32_BUILTIN_UCLIP32, -+ NDS32_BUILTIN_SCLIP32, -+ NDS32_BUILTIN_KABS, -+ NDS32_BUILTIN_UALOAD_U16, -+ NDS32_BUILTIN_UALOAD_S16, -+ NDS32_BUILTIN_UALOAD_U8, -+ NDS32_BUILTIN_UALOAD_S8, -+ NDS32_BUILTIN_UASTORE_U16, -+ NDS32_BUILTIN_UASTORE_S16, -+ NDS32_BUILTIN_UASTORE_U8, -+ NDS32_BUILTIN_UASTORE_S8, -+ NDS32_BUILTIN_DSP_END, - NDS32_BUILTIN_UNALIGNED_FEATURE, - NDS32_BUILTIN_ENABLE_UNALIGNED, - NDS32_BUILTIN_DISABLE_UNALIGNED, -@@ -521,16 +857,30 @@ enum nds32_builtins - - /* ------------------------------------------------------------------------ */ - --#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2) -+#define TARGET_ISR_VECTOR_SIZE_4_BYTE \ -+ (nds32_isr_vector_size == 4) - -+#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2) - #define TARGET_ISA_V3 \ - (nds32_arch_option == ARCH_V3 \ -+ || nds32_arch_option == ARCH_V3J \ - || nds32_arch_option == ARCH_V3F \ - || nds32_arch_option == ARCH_V3S) - #define TARGET_ISA_V3M (nds32_arch_option == ARCH_V3M) - -+#define TARGET_PIPELINE_N7 \ -+ (nds32_cpu_option == CPU_N7) -+#define TARGET_PIPELINE_N8 \ -+ (nds32_cpu_option == CPU_N6 \ -+ || nds32_cpu_option == CPU_N8) - #define TARGET_PIPELINE_N9 \ - (nds32_cpu_option == CPU_N9) -+#define TARGET_PIPELINE_N10 \ -+ (nds32_cpu_option == CPU_N10) -+#define TARGET_PIPELINE_N13 \ -+ (nds32_cpu_option == CPU_N12 || nds32_cpu_option == CPU_N13) -+#define TARGET_PIPELINE_GRAYWOLF \ -+ (nds32_cpu_option == CPU_GRAYWOLF) - #define TARGET_PIPELINE_SIMPLE \ - (nds32_cpu_option == CPU_SIMPLE) - -@@ -541,6 +891,12 @@ enum nds32_builtins - #define TARGET_CMODEL_LARGE \ - (nds32_cmodel_option == CMODEL_LARGE) - -+#define TARGET_ICT_MODEL_SMALL \ -+ (nds32_ict_model == ICT_MODEL_SMALL) -+ -+#define TARGET_ICT_MODEL_LARGE \ -+ (nds32_ict_model == ICT_MODEL_LARGE) -+ - /* When -mcmodel=small or -mcmodel=medium, - compiler may generate gp-base instruction directly. */ - #define TARGET_GP_DIRECT \ -@@ -576,6 +932,21 @@ enum nds32_builtins - #endif - - #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 -+# define NDS32_EXT_DSP_SPEC " %{!mno-ext-dsp:-mext-dsp}" -+#else -+# define NDS32_EXT_DSP_SPEC "" -+#endif -+ - /* ------------------------------------------------------------------------ */ - - /* Controlling the Compilation Driver. */ -@@ -591,11 +962,15 @@ enum nds32_builtins - {"float", "%{!mfloat-abi=*:-mfloat-abi=%(VALUE)}" } - - #define CC1_SPEC \ -- "" -+ NDS32_EXT_DSP_SPEC - - #define ASM_SPEC \ - " %{mbig-endian:-EB} %{mlittle-endian:-EL}" \ - " %{march=*:-march=%*}" \ -+ " %{mno-16-bit|mno-16bit:-mno-16bit-ext}" \ -+ " %{march=v3m:%{!mfull-regs:%{!mreduced-regs:-mreduced-regs}}}" \ -+ " %{mfull-regs:-mno-reduced-regs}" \ -+ " %{mreduced-regs:-mreduced-regs}" \ - " %{mabi=*:-mabi=v%*}" \ - " %{mconfig-fpu=*:-mfpu-freg=%*}" \ - " %{mext-fpu-mac:-mmac}" \ -@@ -603,35 +978,9 @@ enum nds32_builtins - " %{mext-fpu-sp:-mfpu-sp-ext}" \ - " %{mno-ext-fpu-sp:-mno-fpu-sp-ext}" \ - " %{mext-fpu-dp:-mfpu-dp-ext}" \ -- " %{mno-ext-fpu-sp:-mno-fpu-dp-ext}" -- --/* 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}" -+ " %{mno-ext-fpu-sp:-mno-fpu-dp-ext}" \ -+ " %{mext-dsp:-mdsp-ext}" \ -+ " %{O|O1|O2|O3|Ofast:-O1;:-Os}" - - /* The TARGET_BIG_ENDIAN_DEFAULT is defined if we - configure gcc with --target=nds32be-* setting. -@@ -642,9 +991,11 @@ enum nds32_builtins - # define NDS32_ENDIAN_DEFAULT "mlittle-endian" - #endif - --/* Currently we only have elf toolchain, -- where -mcmodel=medium is always the default. */ --#define NDS32_CMODEL_DEFAULT "mcmodel=medium" -+#if TARGET_ELF -+# define NDS32_CMODEL_DEFAULT "mcmodel=medium" -+#else -+# define NDS32_CMODEL_DEFAULT "mcmodel=large" -+#endif - - #define MULTILIB_DEFAULTS \ - { NDS32_ENDIAN_DEFAULT, NDS32_CMODEL_DEFAULT } -@@ -1139,12 +1490,17 @@ enum reg_class - - #define PIC_OFFSET_TABLE_REGNUM GP_REGNUM - -+#define SYMBOLIC_CONST_P(X) \ -+(GET_CODE (X) == SYMBOL_REF \ -+ || GET_CODE (X) == LABEL_REF \ -+ || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X))) -+ - - /* Defining the Output Assembler Language. */ - - #define ASM_COMMENT_START "!" - --#define ASM_APP_ON "! #APP" -+#define ASM_APP_ON "! #APP\n" - - #define ASM_APP_OFF "! #NO_APP\n" - -diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md -index 3b8107e8fbf..f5349d7cc76 100644 ---- a/gcc/config/nds32/nds32.md -+++ b/gcc/config/nds32/nds32.md -@@ -56,24 +56,29 @@ - ;; ------------------------------------------------------------------------ - - ;; CPU pipeline model. --(define_attr "pipeline_model" "n7,n8,e8,n9,simple" -+(define_attr "pipeline_model" "n7,n8,e8,n9,n10,graywolf,n13,simple" - (const - (cond [(match_test "nds32_cpu_option == CPU_N7") (const_string "n7") - (match_test "nds32_cpu_option == CPU_E8") (const_string "e8") - (match_test "nds32_cpu_option == CPU_N6 || nds32_cpu_option == CPU_N8") (const_string "n8") - (match_test "nds32_cpu_option == CPU_N9") (const_string "n9") -+ (match_test "nds32_cpu_option == CPU_N10") (const_string "n10") -+ (match_test "nds32_cpu_option == CPU_GRAYWOLF") (const_string "graywolf") -+ (match_test "nds32_cpu_option == CPU_N12") (const_string "n13") -+ (match_test "nds32_cpu_option == CPU_N13") (const_string "n13") - (match_test "nds32_cpu_option == CPU_SIMPLE") (const_string "simple")] - (const_string "n9")))) - - ;; Insn type, it is used to default other attribute values. - (define_attr "type" - "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,pbsad,pbsada,mul,mac,div,branch,mmu,misc,\ -- falu,fmuls,fmuld,fmacs,fmacd,fdivs,fdivd,fsqrts,fsqrtd,fcmp,fabs,fcpy,fcmov,fmfsr,fmfdr,fmtsr,fmtdr,fload,fstore" -+ falu,fmuls,fmuld,fmacs,fmacd,fdivs,fdivd,fsqrts,fsqrtd,fcmp,fabs,fcpy,fcmov,fmfsr,fmfdr,fmtsr,fmtdr,fload,fstore,\ -+ dalu,dalu64,daluround,dcmp,dclip,dmul,dmac,dinsb,dpack,dbpick,dwext" - (const_string "unknown")) - - ;; Insn sub-type - (define_attr "subtype" -- "simple,shift" -+ "simple,shift,saturation" - (const_string "simple")) - - ;; Length, in bytes, default is 4-bytes. -@@ -133,6 +138,7 @@ - - ;; ---------------------------------------------------------------------------- - -+(include "nds32-dspext.md") - - ;; Move instructions. - -@@ -209,6 +215,27 @@ - low12_int)); - DONE; - } -+ -+ if ((REG_P (operands[0]) || GET_CODE (operands[0]) == SUBREG) -+ && SYMBOLIC_CONST_P (operands[1])) -+ { -+ if (TARGET_ICT_MODEL_LARGE -+ && nds32_indirect_call_referenced_p (operands[1])) -+ { -+ nds32_expand_ict_move (operands); -+ DONE; -+ } -+ else if (nds32_tls_referenced_p (operands [1])) -+ { -+ nds32_expand_tls_move (operands); -+ DONE; -+ } -+ else if (flag_pic) -+ { -+ nds32_expand_pic_move (operands); -+ DONE; -+ } -+ } - }) - - (define_insn "*mov" -@@ -271,8 +298,8 @@ - ;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF - ;; are able to match such instruction template. - (define_insn "move_addr" -- [(set (match_operand:SI 0 "register_operand" "=l, r") -- (match_operand:SI 1 "nds32_symbolic_operand" " i, i"))] -+ [(set (match_operand:SI 0 "nds32_general_register_operand" "=l, r") -+ (match_operand:SI 1 "nds32_nonunspec_symbolic_operand" " i, i"))] - "" - "la\t%0, %1" - [(set_attr "type" "alu") -@@ -351,13 +378,58 @@ - - - ;; ---------------------------------------------------------------------------- -+(define_expand "extv" -+ [(set (match_operand 0 "register_operand" "") -+ (sign_extract (match_operand 1 "nonimmediate_operand" "") -+ (match_operand 2 "const_int_operand" "") -+ (match_operand 3 "const_int_operand" "")))] -+ "" -+{ -+ enum nds32_expand_result_type result = nds32_expand_extv (operands); -+ switch (result) -+ { -+ case EXPAND_DONE: -+ DONE; -+ break; -+ case EXPAND_FAIL: -+ FAIL; -+ break; -+ case EXPAND_CREATE_TEMPLATE: -+ break; -+ default: -+ gcc_unreachable (); -+ } -+}) -+ -+(define_expand "insv" -+ [(set (zero_extract (match_operand 0 "nonimmediate_operand" "") -+ (match_operand 1 "const_int_operand" "") -+ (match_operand 2 "const_int_operand" "")) -+ (match_operand 3 "register_operand" ""))] -+ "" -+{ -+ enum nds32_expand_result_type result = nds32_expand_insv (operands); -+ switch (result) -+ { -+ case EXPAND_DONE: -+ DONE; -+ break; -+ case EXPAND_FAIL: -+ FAIL; -+ break; -+ case EXPAND_CREATE_TEMPLATE: -+ break; -+ default: -+ gcc_unreachable (); -+ } -+}) - - ;; Arithmetic instructions. - - (define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "= d, l, d, l, d, l, k, l, r, r") - (plus:SI (match_operand:SI 1 "register_operand" "% 0, l, 0, l, 0, l, 0, k, r, r") -- (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,Iu06, Is15, r")))] -+ (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,IU06, Is15, r")))] - "" - { - switch (which_alternative) -@@ -1428,11 +1500,30 @@ - (clobber (reg:SI LP_REGNUM)) - (clobber (reg:SI TA_REGNUM))])] - "" -- "" -+ { -+ rtx insn; -+ rtx sym = XEXP (operands[0], 0); -+ -+ if (TARGET_ICT_MODEL_LARGE -+ && nds32_indirect_call_referenced_p (sym)) -+ { -+ rtx reg = gen_reg_rtx (Pmode); -+ emit_move_insn (reg, sym); -+ operands[0] = gen_const_mem (Pmode, reg); -+ } -+ -+ if (flag_pic) -+ { -+ insn = emit_call_insn (gen_call_internal -+ (XEXP (operands[0], 0), GEN_INT (0))); -+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); -+ DONE; -+ } -+ } - ) - - (define_insn "call_internal" -- [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i")) -+ [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, S")) - (match_operand 1)) - (clobber (reg:SI LP_REGNUM)) - (clobber (reg:SI TA_REGNUM))])] -@@ -1474,9 +1565,11 @@ - (const_int 2) - (const_int 4)) - ;; Alternative 1 -- (if_then_else (match_test "nds32_long_call_p (operands[0])") -- (const_int 12) -- (const_int 4)) -+ (if_then_else (match_test "flag_pic") -+ (const_int 16) -+ (if_then_else (match_test "nds32_long_call_p (operands[0])") -+ (const_int 12) -+ (const_int 4))) - ])] - ) - -@@ -1492,11 +1585,33 @@ - (match_operand 2))) - (clobber (reg:SI LP_REGNUM)) - (clobber (reg:SI TA_REGNUM))])] -- "") -+ "" -+ { -+ rtx insn; -+ rtx sym = XEXP (operands[1], 0); -+ -+ if (TARGET_ICT_MODEL_LARGE -+ && nds32_indirect_call_referenced_p (sym)) -+ { -+ rtx reg = gen_reg_rtx (Pmode); -+ emit_move_insn (reg, sym); -+ operands[1] = gen_const_mem (Pmode, reg); -+ } -+ -+ if (flag_pic) -+ { -+ insn = -+ emit_call_insn (gen_call_value_internal -+ (operands[0], XEXP (operands[1], 0), GEN_INT (0))); -+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); -+ DONE; -+ } -+ } -+) - - (define_insn "call_value_internal" - [(parallel [(set (match_operand 0) -- (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i")) -+ (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, S")) - (match_operand 2))) - (clobber (reg:SI LP_REGNUM)) - (clobber (reg:SI TA_REGNUM))])] -@@ -1538,9 +1653,11 @@ - (const_int 2) - (const_int 4)) - ;; Alternative 1 -- (if_then_else (match_test "nds32_long_call_p (operands[1])") -- (const_int 12) -- (const_int 4)) -+ (if_then_else (match_test "flag_pic") -+ (const_int 16) -+ (if_then_else (match_test "nds32_long_call_p (operands[1])") -+ (const_int 12) -+ (const_int 4))) - ])] - ) - -@@ -1583,10 +1700,21 @@ - (const_int 0)) - (clobber (reg:SI TA_REGNUM)) - (return)])] -- "") -+ "" -+{ -+ rtx sym = XEXP (operands[0], 0); -+ -+ if (TARGET_ICT_MODEL_LARGE -+ && nds32_indirect_call_referenced_p (sym)) -+ { -+ rtx reg = gen_reg_rtx (Pmode); -+ emit_move_insn (reg, sym); -+ operands[0] = gen_const_mem (Pmode, reg); -+ } -+}) - - (define_insn "sibcall_internal" -- [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i")) -+ [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, S")) - (match_operand 1)) - (clobber (reg:SI TA_REGNUM)) - (return)])] -@@ -1617,9 +1745,11 @@ - (const_int 2) - (const_int 4)) - ;; Alternative 1 -- (if_then_else (match_test "nds32_long_call_p (operands[0])") -- (const_int 12) -- (const_int 4)) -+ (if_then_else (match_test "flag_pic") -+ (const_int 16) -+ (if_then_else (match_test "nds32_long_call_p (operands[0])") -+ (const_int 12) -+ (const_int 4))) - ])] - ) - -@@ -1633,11 +1763,22 @@ - (const_int 0))) - (clobber (reg:SI TA_REGNUM)) - (return)])] -- "") -+ "" -+{ -+ rtx sym = XEXP (operands[1], 0); -+ -+ if (TARGET_ICT_MODEL_LARGE -+ && nds32_indirect_call_referenced_p (sym)) -+ { -+ rtx reg = gen_reg_rtx (Pmode); -+ emit_move_insn (reg, sym); -+ operands[1] = gen_const_mem (Pmode, reg); -+ } -+}) - - (define_insn "sibcall_value_internal" - [(parallel [(set (match_operand 0) -- (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i")) -+ (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, S")) - (match_operand 2))) - (clobber (reg:SI TA_REGNUM)) - (return)])] -@@ -1668,9 +1809,11 @@ - (const_int 2) - (const_int 4)) - ;; Alternative 1 -- (if_then_else (match_test "nds32_long_call_p (operands[1])") -- (const_int 12) -- (const_int 4)) -+ (if_then_else (match_test "flag_pic") -+ (const_int 16) -+ (if_then_else (match_test "nds32_long_call_p (operands[1])") -+ (const_int 12) -+ (const_int 4))) - ])] - ) - -@@ -1687,12 +1830,33 @@ - nds32_expand_prologue_v3push (); - else - nds32_expand_prologue (); -+ -+ /* If cfun->machine->fp_as_gp_p is true, we can generate special -+ directive to guide linker doing fp-as-gp optimization. -+ However, for a naked function, which means -+ it should not have prologue/epilogue, -+ using fp-as-gp still requires saving $fp by push/pop behavior and -+ there is no benefit to use fp-as-gp on such small function. -+ So we need to make sure this function is NOT naked as well. */ -+ if (cfun->machine->fp_as_gp_p && !cfun->machine->naked_p) -+ emit_insn (gen_omit_fp_begin (gen_rtx_REG (SImode, FP_REGNUM))); -+ - DONE; - }) - - (define_expand "epilogue" [(const_int 0)] - "" - { -+ /* If cfun->machine->fp_as_gp_p is true, we can generate special -+ directive to guide linker doing fp-as-gp optimization. -+ However, for a naked function, which means -+ it should not have prologue/epilogue, -+ using fp-as-gp still requires saving $fp by push/pop behavior and -+ there is no benefit to use fp-as-gp on such small function. -+ So we need to make sure this function is NOT naked as well. */ -+ if (cfun->machine->fp_as_gp_p && !cfun->machine->naked_p) -+ emit_insn (gen_omit_fp_end (gen_rtx_REG (SImode, FP_REGNUM))); -+ - /* Note that only under V3/V3M ISA, we could use v3pop epilogue. - In addition, we need to check if v3push is indeed available. */ - if (NDS32_V3PUSH_AVAILABLE_P) -@@ -1792,7 +1956,8 @@ - "nds32_can_use_return_insn ()" - { - /* Emit as the simple return. */ -- if (cfun->machine->naked_p -+ if (!cfun->machine->fp_as_gp_p -+ && cfun->machine->naked_p - && (cfun->machine->va_args_size == 0)) - { - emit_jump_insn (gen_return_internal ()); -@@ -1802,9 +1967,14 @@ - - ;; This pattern is expanded only by the shrink-wrapping optimization - ;; on paths where the function prologue has not been executed. -+;; However, such optimization may reorder the prologue/epilogue blocks -+;; together with basic blocks within function body. -+;; So we must disable this pattern if we have already decided -+;; to perform fp_as_gp optimization, which requires prologue to be -+;; first block and epilogue to be last block. - (define_expand "simple_return" - [(simple_return)] -- "" -+ "!cfun->machine->fp_as_gp_p" - "" - ) - -@@ -1823,6 +1993,9 @@ - [(simple_return)] - "" - { -+ if (nds32_isr_function_critical_p (current_function_decl)) -+ return "iret"; -+ - if (TARGET_16_BIT) - return "ret5"; - else -@@ -1831,9 +2004,11 @@ - [(set_attr "type" "branch") - (set_attr "enabled" "yes") - (set (attr "length") -- (if_then_else (match_test "TARGET_16_BIT") -- (const_int 2) -- (const_int 4)))]) -+ (if_then_else (match_test "nds32_isr_function_critical_p (current_function_decl)") -+ (const_int 4) -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_int 2) -+ (const_int 4))))]) - - - ;; ---------------------------------------------------------------------------- -@@ -1868,6 +2043,7 @@ - { - rtx add_tmp; - rtx reg, test; -+ rtx tmp_reg; - - /* Step A: "k <-- (plus (operands[0]) (-operands[1]))". */ - if (operands[1] != const0_rtx) -@@ -1889,9 +2065,14 @@ - emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], - operands[4])); - -- /* Step C, D, E, and F, using another temporary register. */ -- rtx tmp = gen_reg_rtx (SImode); -- emit_jump_insn (gen_casesi_internal (operands[0], operands[3], tmp)); -+ tmp_reg = gen_reg_rtx (SImode); -+ /* Step C, D, E, and F, using another temporary register tmp_reg. */ -+ if (flag_pic) -+ emit_use (pic_offset_table_rtx); -+ -+ emit_jump_insn (gen_casesi_internal (operands[0], -+ operands[3], -+ tmp_reg)); - DONE; - }) - -@@ -1927,13 +2108,30 @@ - else - return nds32_output_casesi (operands); - } -- [(set_attr "length" "20") -- (set_attr "type" "branch")]) -+ [(set_attr "type" "branch") -+ (set (attr "length") -+ (if_then_else (match_test "flag_pic") -+ (const_int 28) -+ (const_int 20)))]) - - ;; ---------------------------------------------------------------------------- - - ;; Performance Extension - -+; If -fwrapv option is issued, GCC expects there will be -+; signed overflow situation. So the ABS(INT_MIN) is still INT_MIN -+; (e.g. ABS(0x80000000)=0x80000000). -+; However, the hardware ABS instruction of nds32 target -+; always performs saturation: abs 0x80000000 -> 0x7fffffff. -+; So that we can only enable abssi2 pattern if flag_wrapv is NOT presented. -+(define_insn "abssi2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (abs:SI (match_operand:SI 1 "register_operand" " r")))] -+ "TARGET_EXT_PERF && TARGET_HW_ABS && !flag_wrapv" -+ "abs\t%0, %1" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ - (define_insn "clzsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (clz:SI (match_operand:SI 1 "register_operand" " r")))] -@@ -1996,6 +2194,25 @@ - [(set_attr "length" "0")] - ) - -+;; Output .omit_fp_begin for fp-as-gp optimization. -+;; Also we have to set $fp register. -+(define_insn "omit_fp_begin" -+ [(set (match_operand:SI 0 "register_operand" "=x") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_OMIT_FP_BEGIN))] -+ "" -+ "! -----\;.omit_fp_begin\;la\t$fp,_FP_BASE_\;! -----" -+ [(set_attr "length" "8")] -+) -+ -+;; Output .omit_fp_end for fp-as-gp optimization. -+;; Claim that we have to use $fp register. -+(define_insn "omit_fp_end" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "x")] UNSPEC_VOLATILE_OMIT_FP_END)] -+ "" -+ "! -----\;.omit_fp_end\;! -----" -+ [(set_attr "length" "0")] -+) -+ - (define_insn "pop25return" - [(return) - (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_POP25_RETURN)] -@@ -2004,6 +2221,36 @@ - [(set_attr "length" "0")] - ) - -+;; Add pc -+(define_insn "add_pc" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (plus:SI (match_operand:SI 1 "register_operand" "0") -+ (pc)))] -+ "TARGET_LINUX_ABI || flag_pic" -+ "add5.pc\t%0" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "bswapsi2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (bswap:SI (match_operand:SI 1 "register_operand" "r")))] -+ "" -+{ -+ emit_insn (gen_unspec_wsbh (operands[0], operands[1])); -+ emit_insn (gen_rotrsi3 (operands[0], operands[0], GEN_INT (16))); -+ DONE; -+}) -+ -+(define_insn "bswaphi2" -+ [(set (match_operand:HI 0 "register_operand" "=r") -+ (bswap:HI (match_operand:HI 1 "register_operand" "r")))] -+ "" -+ "wsbh\t%0, %1" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ - ;; ---------------------------------------------------------------------------- - - ;; Patterns for exception handling -@@ -2068,3 +2315,57 @@ - }) - - ;; ---------------------------------------------------------------------------- -+ -+;; Patterns for TLS. -+;; The following two tls patterns don't be expanded directly because the -+;; intermediate value may be spilled into the stack. As a result, it is -+;; hard to analyze the define-use chain in the relax_opt pass. -+ -+ -+;; There is a unspec operand to record RELAX_GROUP number because each -+;; emitted instruction need a relax_hint above it. -+(define_insn "tls_desc" -+ [(set (reg:SI 0) -+ (call (unspec_volatile:SI [(match_operand:SI 0 "nds32_symbolic_operand" "i")] UNSPEC_TLS_DESC) -+ (const_int 1))) -+ (use (unspec [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)) -+ (use (reg:SI GP_REGNUM)) -+ (clobber (reg:SI LP_REGNUM)) -+ (clobber (reg:SI TA_REGNUM))] -+ "" -+ { -+ return nds32_output_tls_desc (operands); -+ } -+ [(set_attr "length" "20") -+ (set_attr "type" "branch")] -+) -+ -+;; There is a unspec operand to record RELAX_GROUP number because each -+;; emitted instruction need a relax_hint above it. -+(define_insn "tls_ie" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_TLS_IE)) -+ (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)) -+ (use (reg:SI GP_REGNUM))] -+ "" -+ { -+ return nds32_output_tls_ie (operands); -+ } -+ [(set (attr "length") (if_then_else (match_test "flag_pic") -+ (const_int 12) -+ (const_int 8))) -+ (set_attr "type" "misc")] -+) -+ -+;; The pattern is for some relaxation groups that have to keep addsi3 in 32-bit mode. -+(define_insn "addsi3_32bit" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "%r") -+ (match_operand:SI 2 "register_operand" " r")] UNSPEC_ADD32))] -+ "" -+ "add\t%0, %1, %2"; -+ [(set_attr "type" "alu") -+ (set_attr "length" "4") -+ (set_attr "feature" "v1")]) -+ -+;; ---------------------------------------------------------------------------- -diff --git a/gcc/config/nds32/nds32.opt b/gcc/config/nds32/nds32.opt -index dcf6d396bc3..0e50c991aba 100644 ---- a/gcc/config/nds32/nds32.opt -+++ b/gcc/config/nds32/nds32.opt -@@ -32,6 +32,13 @@ EL - Target RejectNegative Alias(mlittle-endian) - Generate code in little-endian mode. - -+mfp-as-gp -+Target RejectNegative Alias(mforce-fp-as-gp) -+Force performing fp-as-gp optimization. -+ -+mno-fp-as-gp -+Target RejectNegative Alias(mforbid-fp-as-gp) -+Forbid performing fp-as-gp optimization. - - ; --------------------------------------------------------------- - -@@ -85,11 +92,36 @@ mlittle-endian - Target Undocumented RejectNegative Negative(mbig-endian) InverseMask(BIG_ENDIAN) - Generate code in little-endian mode. - -+mforce-fp-as-gp -+Target Undocumented Mask(FORCE_FP_AS_GP) -+Prevent $fp being allocated during register allocation so that compiler is able to force performing fp-as-gp optimization. -+ -+mforbid-fp-as-gp -+Target Undocumented Mask(FORBID_FP_AS_GP) -+Forbid using $fp to access static and global variables. This option strictly forbids fp-as-gp optimization regardless of '-mforce-fp-as-gp'. -+ -+mict-model= -+Target Undocumented RejectNegative Joined Enum(nds32_ict_model_type) Var(nds32_ict_model) Init(ICT_MODEL_SMALL) -+Specify the address generation strategy for ICT call's code model. -+ -+Enum -+Name(nds32_ict_model_type) Type(enum nds32_ict_model_type) -+Known cmodel types (for use with the -mict-model= option): -+ -+EnumValue -+Enum(nds32_ict_model_type) String(small) Value(ICT_MODEL_SMALL) -+ -+EnumValue -+Enum(nds32_ict_model_type) String(large) Value(ICT_MODEL_LARGE) - - mcmov - Target Report Mask(CMOV) - Generate conditional move instructions. - -+mhw-abs -+Target Report Mask(HW_ABS) -+Generate hardware abs instructions. -+ - mext-perf - Target Report Mask(EXT_PERF) - Generate performance extension instructions. -@@ -102,6 +134,10 @@ mext-string - Target Report Mask(EXT_STRING) - Generate string extension instructions. - -+mext-dsp -+Target Report Mask(EXT_DSP) -+Generate DSP extension instructions. -+ - mv3push - Target Report Mask(V3PUSH) - Generate v3 push25/pop25 instructions. -@@ -115,13 +151,17 @@ Target Report Mask(RELAX_HINT) - Insert relax hint for linker to do relaxation. - - mvh --Target Report Mask(VH) -+Target Report Mask(VH) Condition(!TARGET_LINUX_ABI) - Enable Virtual Hosting support. - - misr-vector-size= - Target RejectNegative Joined UInteger Var(nds32_isr_vector_size) Init(NDS32_DEFAULT_ISR_VECTOR_SIZE) - Specify the size of each interrupt vector, which must be 4 or 16. - -+misr-secure= -+Target RejectNegative Joined UInteger Var(nds32_isr_secure_level) Init(0) -+Specify the security level of c-isr for the whole file. -+ - mcache-block-size= - Target RejectNegative Joined UInteger Var(nds32_cache_block_size) Init(NDS32_DEFAULT_CACHE_BLOCK_SIZE) - Specify the size of each cache block, which must be a power of 2 between 4 and 512. -@@ -140,6 +180,9 @@ Enum(nds32_arch_type) String(v2) Value(ARCH_V2) - EnumValue - Enum(nds32_arch_type) String(v3) Value(ARCH_V3) - -+EnumValue -+Enum(nds32_arch_type) String(v3j) Value(ARCH_V3J) -+ - EnumValue - Enum(nds32_arch_type) String(v3m) Value(ARCH_V3M) - -@@ -149,23 +192,6 @@ Enum(nds32_arch_type) String(v3f) Value(ARCH_V3F) - EnumValue - 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= - Target RejectNegative Joined Enum(nds32_cpu_type) Var(nds32_cpu_option) Init(CPU_N9) - Specify the cpu for pipeline model. -@@ -234,6 +260,99 @@ Enum(nds32_cpu_type) String(n968) Value(CPU_N9) - EnumValue - Enum(nds32_cpu_type) String(n968a) Value(CPU_N9) - -+EnumValue -+Enum(nds32_cpu_type) String(n10) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1033) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1033a) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1033-fpu) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1033-spu) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1068) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1068a) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1068-fpu) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1068a-fpu) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1068-spu) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1068a-spu) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(d10) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(d1088) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(d1088-fpu) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) String(d1088-spu) Value(CPU_N10) -+ -+EnumValue -+Enum(nds32_cpu_type) Undocumented String(graywolf) Value(CPU_GRAYWOLF) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n15) Value(CPU_GRAYWOLF) -+ -+EnumValue -+Enum(nds32_cpu_type) String(d15) Value(CPU_GRAYWOLF) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n15s) Value(CPU_GRAYWOLF) -+ -+EnumValue -+Enum(nds32_cpu_type) String(d15s) Value(CPU_GRAYWOLF) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n15f) Value(CPU_GRAYWOLF) -+ -+EnumValue -+Enum(nds32_cpu_type) String(d15f) Value(CPU_GRAYWOLF) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n12) Value(CPU_N12) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1213) Value(CPU_N12) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1233) Value(CPU_N12) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1233-fpu) Value(CPU_N12) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1233-spu) Value(CPU_N12) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n13) Value(CPU_N13) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1337) Value(CPU_N13) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1337-fpu) Value(CPU_N13) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n1337-spu) Value(CPU_N13) -+ - EnumValue - Enum(nds32_cpu_type) String(simple) Value(CPU_SIMPLE) - -@@ -321,6 +440,18 @@ mext-fpu-dp - Target Report Mask(FPU_DOUBLE) - Generate double-precision floating-point instructions. - -+mforce-no-ext-dsp -+Target Undocumented Report Mask(FORCE_NO_EXT_DSP) -+Force disable hardware loop, even use -mext-dsp. -+ -+msched-prolog-epilog -+Target Var(flag_sched_prolog_epilog) Init(0) -+Permit scheduling of a function's prologue and epilogue sequence. -+ -+mret-in-naked-func -+Target Var(flag_ret_in_naked_func) Init(1) -+Generate return instruction in naked function. -+ - malways-save-lp - Target Var(flag_always_save_lp) Init(0) - Always save $lp in the stack. -@@ -328,3 +459,7 @@ Always save $lp in the stack. - munaligned-access - Target Report Var(flag_unaligned_access) Init(0) - Enable unaligned word and halfword accesses to packed data. -+ -+minline-asm-r15 -+Target Report Var(flag_inline_asm_r15) Init(0) -+Allow use r15 for inline ASM. -diff --git a/gcc/config/nds32/nds32_init.inc b/gcc/config/nds32/nds32_init.inc -new file mode 100644 -index 00000000000..1084ad0e471 ---- /dev/null -+++ b/gcc/config/nds32/nds32_init.inc -@@ -0,0 +1,43 @@ -+/* -+ * nds32_init.inc -+ * -+ * NDS32 architecture startup assembler header file -+ * -+ */ -+ -+.macro nds32_init -+ -+ ! Initialize GP for data access -+ la $gp, _SDA_BASE_ -+ -+#if defined(__NDS32_EXT_EX9__) -+ ! Check HW for EX9 -+ mfsr $r0, $MSC_CFG -+ li $r1, (1 << 24) -+ and $r2, $r0, $r1 -+ beqz $r2, 1f -+ -+ ! Initialize the table base of EX9 instruction -+ la $r0, _ITB_BASE_ -+ mtusr $r0, $ITB -+1: -+#endif -+ -+#if defined(__NDS32_EXT_FPU_DP__) || defined(__NDS32_EXT_FPU_SP__) -+ ! Enable FPU -+ mfsr $r0, $FUCOP_CTL -+ ori $r0, $r0, #0x1 -+ mtsr $r0, $FUCOP_CTL -+ dsb -+ -+ ! Enable denormalized flush-to-Zero mode -+ fmfcsr $r0 -+ ori $r0,$r0,#0x1000 -+ fmtcsr $r0 -+ dsb -+#endif -+ -+ ! Initialize default stack pointer -+ la $sp, _stack -+ -+.endm -diff --git a/gcc/config/nds32/nds32_intrinsic.h b/gcc/config/nds32/nds32_intrinsic.h -index 7bb117712dc..24cb2915491 100644 ---- a/gcc/config/nds32/nds32_intrinsic.h -+++ b/gcc/config/nds32/nds32_intrinsic.h -@@ -26,6 +26,13 @@ - #ifndef _NDS32_INTRINSIC_H - #define _NDS32_INTRINSIC_H - -+typedef signed char int8x4_t __attribute ((vector_size(4))); -+typedef short int16x2_t __attribute ((vector_size(4))); -+typedef int int32x2_t __attribute__((vector_size(8))); -+typedef unsigned char uint8x4_t __attribute__ ((vector_size (4))); -+typedef unsigned short uint16x2_t __attribute__ ((vector_size (4))); -+typedef unsigned int uint32x2_t __attribute__((vector_size(8))); -+ - /* General instrinsic register names. */ - enum nds32_intrinsic_registers - { -@@ -691,6 +698,55 @@ enum nds32_dpref - #define __nds32__tlbop_flua() \ - (__builtin_nds32_tlbop_flua()) - -+#define __nds32__kaddw(a, b) \ -+ (__builtin_nds32_kaddw ((a), (b))) -+#define __nds32__kaddh(a, b) \ -+ (__builtin_nds32_kaddh ((a), (b))) -+#define __nds32__ksubw(a, b) \ -+ (__builtin_nds32_ksubw ((a), (b))) -+#define __nds32__ksubh(a, b) \ -+ (__builtin_nds32_ksubh ((a), (b))) -+#define __nds32__kdmbb(a, b) \ -+ (__builtin_nds32_kdmbb ((a), (b))) -+#define __nds32__v_kdmbb(a, b) \ -+ (__builtin_nds32_v_kdmbb ((a), (b))) -+#define __nds32__kdmbt(a, b) \ -+ (__builtin_nds32_kdmbt ((a), (b))) -+#define __nds32__v_kdmbt(a, b) \ -+ (__builtin_nds32_v_kdmbt ((a), (b))) -+#define __nds32__kdmtb(a, b) \ -+ (__builtin_nds32_kdmtb ((a), (b))) -+#define __nds32__v_kdmtb(a, b) \ -+ (__builtin_nds32_v_kdmtb ((a), (b))) -+#define __nds32__kdmtt(a, b) \ -+ (__builtin_nds32_kdmtt ((a), (b))) -+#define __nds32__v_kdmtt(a, b) \ -+ (__builtin_nds32_v_kdmtt ((a), (b))) -+#define __nds32__khmbb(a, b) \ -+ (__builtin_nds32_khmbb ((a), (b))) -+#define __nds32__v_khmbb(a, b) \ -+ (__builtin_nds32_v_khmbb ((a), (b))) -+#define __nds32__khmbt(a, b) \ -+ (__builtin_nds32_khmbt ((a), (b))) -+#define __nds32__v_khmbt(a, b) \ -+ (__builtin_nds32_v_khmbt ((a), (b))) -+#define __nds32__khmtb(a, b) \ -+ (__builtin_nds32_khmtb ((a), (b))) -+#define __nds32__v_khmtb(a, b) \ -+ (__builtin_nds32_v_khmtb ((a), (b))) -+#define __nds32__khmtt(a, b) \ -+ (__builtin_nds32_khmtt ((a), (b))) -+#define __nds32__v_khmtt(a, b) \ -+ (__builtin_nds32_v_khmtt ((a), (b))) -+#define __nds32__kslraw(a, b) \ -+ (__builtin_nds32_kslraw ((a), (b))) -+#define __nds32__kslraw_u(a, b) \ -+ (__builtin_nds32_kslraw_u ((a), (b))) -+ -+#define __nds32__rdov() \ -+ (__builtin_nds32_rdov()) -+#define __nds32__clrov() \ -+ (__builtin_nds32_clrov()) - #define __nds32__gie_dis() \ - (__builtin_nds32_gie_dis()) - #define __nds32__gie_en() \ -@@ -720,10 +776,622 @@ enum nds32_dpref - #define __nds32__get_trig_type(a) \ - (__builtin_nds32_get_trig_type ((a))) - -+#define __nds32__get_unaligned_hw(a) \ -+ (__builtin_nds32_unaligned_load_hw ((a))) -+#define __nds32__get_unaligned_w(a) \ -+ (__builtin_nds32_unaligned_load_w ((a))) -+#define __nds32__get_unaligned_dw(a) \ -+ (__builtin_nds32_unaligned_load_dw ((a))) -+#define __nds32__put_unaligned_hw(a, data) \ -+ (__builtin_nds32_unaligned_store_hw ((a), (data))) -+#define __nds32__put_unaligned_w(a, data) \ -+ (__builtin_nds32_unaligned_store_w ((a), (data))) -+#define __nds32__put_unaligned_dw(a, data) \ -+ (__builtin_nds32_unaligned_store_dw ((a), (data))) -+ -+#define __nds32__add16(a, b) \ -+ (__builtin_nds32_add16 ((a), (b))) -+#define __nds32__v_uadd16(a, b) \ -+ (__builtin_nds32_v_uadd16 ((a), (b))) -+#define __nds32__v_sadd16(a, b) \ -+ (__builtin_nds32_v_sadd16 ((a), (b))) -+#define __nds32__radd16(a, b) \ -+ (__builtin_nds32_radd16 ((a), (b))) -+#define __nds32__v_radd16(a, b) \ -+ (__builtin_nds32_v_radd16 ((a), (b))) -+#define __nds32__uradd16(a, b) \ -+ (__builtin_nds32_uradd16 ((a), (b))) -+#define __nds32__v_uradd16(a, b) \ -+ (__builtin_nds32_v_uradd16 ((a), (b))) -+#define __nds32__kadd16(a, b) \ -+ (__builtin_nds32_kadd16 ((a), (b))) -+#define __nds32__v_kadd16(a, b) \ -+ (__builtin_nds32_v_kadd16 ((a), (b))) -+#define __nds32__ukadd16(a, b) \ -+ (__builtin_nds32_ukadd16 ((a), (b))) -+#define __nds32__v_ukadd16(a, b) \ -+ (__builtin_nds32_v_ukadd16 ((a), (b))) -+#define __nds32__sub16(a, b) \ -+ (__builtin_nds32_sub16 ((a), (b))) -+#define __nds32__v_usub16(a, b) \ -+ (__builtin_nds32_v_usub16 ((a), (b))) -+#define __nds32__v_ssub16(a, b) \ -+ (__builtin_nds32_v_ssub16 ((a), (b))) -+#define __nds32__rsub16(a, b) \ -+ (__builtin_nds32_rsub16 ((a), (b))) -+#define __nds32__v_rsub16(a, b) \ -+ (__builtin_nds32_v_rsub16 ((a), (b))) -+#define __nds32__ursub16(a, b) \ -+ (__builtin_nds32_ursub16 ((a), (b))) -+#define __nds32__v_ursub16(a, b) \ -+ (__builtin_nds32_v_ursub16 ((a), (b))) -+#define __nds32__ksub16(a, b) \ -+ (__builtin_nds32_ksub16 ((a), (b))) -+#define __nds32__v_ksub16(a, b) \ -+ (__builtin_nds32_v_ksub16 ((a), (b))) -+#define __nds32__uksub16(a, b) \ -+ (__builtin_nds32_uksub16 ((a), (b))) -+#define __nds32__v_uksub16(a, b) \ -+ (__builtin_nds32_v_uksub16 ((a), (b))) -+#define __nds32__cras16(a, b) \ -+ (__builtin_nds32_cras16 ((a), (b))) -+#define __nds32__v_ucras16(a, b) \ -+ (__builtin_nds32_v_ucras16 ((a), (b))) -+#define __nds32__v_scras16(a, b) \ -+ (__builtin_nds32_v_scras16 ((a), (b))) -+#define __nds32__rcras16(a, b) \ -+ (__builtin_nds32_rcras16 ((a), (b))) -+#define __nds32__v_rcras16(a, b) \ -+ (__builtin_nds32_v_rcras16 ((a), (b))) -+#define __nds32__urcras16(a, b) \ -+ (__builtin_nds32_urcras16 ((a), (b))) -+#define __nds32__v_urcras16(a, b) \ -+ (__builtin_nds32_v_urcras16 ((a), (b))) -+#define __nds32__kcras16(a, b) \ -+ (__builtin_nds32_kcras16 ((a), (b))) -+#define __nds32__v_kcras16(a, b) \ -+ (__builtin_nds32_v_kcras16 ((a), (b))) -+#define __nds32__ukcras16(a, b) \ -+ (__builtin_nds32_ukcras16 ((a), (b))) -+#define __nds32__v_ukcras16(a, b) \ -+ (__builtin_nds32_v_ukcras16 ((a), (b))) -+#define __nds32__crsa16(a, b) \ -+ (__builtin_nds32_crsa16 ((a), (b))) -+#define __nds32__v_ucrsa16(a, b) \ -+ (__builtin_nds32_v_ucrsa16 ((a), (b))) -+#define __nds32__v_scrsa16(a, b) \ -+ (__builtin_nds32_v_scrsa16 ((a), (b))) -+#define __nds32__rcrsa16(a, b) \ -+ (__builtin_nds32_rcrsa16 ((a), (b))) -+#define __nds32__v_rcrsa16(a, b) \ -+ (__builtin_nds32_v_rcrsa16 ((a), (b))) -+#define __nds32__urcrsa16(a, b) \ -+ (__builtin_nds32_urcrsa16 ((a), (b))) -+#define __nds32__v_urcrsa16(a, b) \ -+ (__builtin_nds32_v_urcrsa16 ((a), (b))) -+#define __nds32__kcrsa16(a, b) \ -+ (__builtin_nds32_kcrsa16 ((a), (b))) -+#define __nds32__v_kcrsa16(a, b) \ -+ (__builtin_nds32_v_kcrsa16 ((a), (b))) -+#define __nds32__ukcrsa16(a, b) \ -+ (__builtin_nds32_ukcrsa16 ((a), (b))) -+#define __nds32__v_ukcrsa16(a, b) \ -+ (__builtin_nds32_v_ukcrsa16 ((a), (b))) -+ -+#define __nds32__add8(a, b) \ -+ (__builtin_nds32_add8 ((a), (b))) -+#define __nds32__v_uadd8(a, b) \ -+ (__builtin_nds32_v_uadd8 ((a), (b))) -+#define __nds32__v_sadd8(a, b) \ -+ (__builtin_nds32_v_sadd8 ((a), (b))) -+#define __nds32__radd8(a, b) \ -+ (__builtin_nds32_radd8 ((a), (b))) -+#define __nds32__v_radd8(a, b) \ -+ (__builtin_nds32_v_radd8 ((a), (b))) -+#define __nds32__uradd8(a, b) \ -+ (__builtin_nds32_uradd8 ((a), (b))) -+#define __nds32__v_uradd8(a, b) \ -+ (__builtin_nds32_v_uradd8 ((a), (b))) -+#define __nds32__kadd8(a, b) \ -+ (__builtin_nds32_kadd8 ((a), (b))) -+#define __nds32__v_kadd8(a, b) \ -+ (__builtin_nds32_v_kadd8 ((a), (b))) -+#define __nds32__ukadd8(a, b) \ -+ (__builtin_nds32_ukadd8 ((a), (b))) -+#define __nds32__v_ukadd8(a, b) \ -+ (__builtin_nds32_v_ukadd8 ((a), (b))) -+#define __nds32__sub8(a, b) \ -+ (__builtin_nds32_sub8 ((a), (b))) -+#define __nds32__v_usub8(a, b) \ -+ (__builtin_nds32_v_usub8 ((a), (b))) -+#define __nds32__v_ssub8(a, b) \ -+ (__builtin_nds32_v_ssub8 ((a), (b))) -+#define __nds32__rsub8(a, b) \ -+ (__builtin_nds32_rsub8 ((a), (b))) -+#define __nds32__v_rsub8(a, b) \ -+ (__builtin_nds32_v_rsub8 ((a), (b))) -+#define __nds32__ursub8(a, b) \ -+ (__builtin_nds32_ursub8 ((a), (b))) -+#define __nds32__v_ursub8(a, b) \ -+ (__builtin_nds32_v_ursub8 ((a), (b))) -+#define __nds32__ksub8(a, b) \ -+ (__builtin_nds32_ksub8 ((a), (b))) -+#define __nds32__v_ksub8(a, b) \ -+ (__builtin_nds32_v_ksub8 ((a), (b))) -+#define __nds32__uksub8(a, b) \ -+ (__builtin_nds32_uksub8 ((a), (b))) -+#define __nds32__v_uksub8(a, b) \ -+ (__builtin_nds32_v_uksub8 ((a), (b))) -+ -+#define __nds32__sra16(a, b) \ -+ (__builtin_nds32_sra16 ((a), (b))) -+#define __nds32__v_sra16(a, b) \ -+ (__builtin_nds32_v_sra16 ((a), (b))) -+#define __nds32__sra16_u(a, b) \ -+ (__builtin_nds32_sra16_u ((a), (b))) -+#define __nds32__v_sra16_u(a, b) \ -+ (__builtin_nds32_v_sra16_u ((a), (b))) -+#define __nds32__srl16(a, b) \ -+ (__builtin_nds32_srl16 ((a), (b))) -+#define __nds32__v_srl16(a, b) \ -+ (__builtin_nds32_v_srl16 ((a), (b))) -+#define __nds32__srl16_u(a, b) \ -+ (__builtin_nds32_srl16_u ((a), (b))) -+#define __nds32__v_srl16_u(a, b) \ -+ (__builtin_nds32_v_srl16_u ((a), (b))) -+#define __nds32__sll16(a, b) \ -+ (__builtin_nds32_sll16 ((a), (b))) -+#define __nds32__v_sll16(a, b) \ -+ (__builtin_nds32_v_sll16 ((a), (b))) -+#define __nds32__ksll16(a, b) \ -+ (__builtin_nds32_ksll16 ((a), (b))) -+#define __nds32__v_ksll16(a, b) \ -+ (__builtin_nds32_v_ksll16 ((a), (b))) -+#define __nds32__kslra16(a, b) \ -+ (__builtin_nds32_kslra16 ((a), (b))) -+#define __nds32__v_kslra16(a, b) \ -+ (__builtin_nds32_v_kslra16 ((a), (b))) -+#define __nds32__kslra16_u(a, b) \ -+ (__builtin_nds32_kslra16_u ((a), (b))) -+#define __nds32__v_kslra16_u(a, b) \ -+ (__builtin_nds32_v_kslra16_u ((a), (b))) -+ -+#define __nds32__cmpeq16(a, b) \ -+ (__builtin_nds32_cmpeq16 ((a), (b))) -+#define __nds32__v_scmpeq16(a, b) \ -+ (__builtin_nds32_v_scmpeq16 ((a), (b))) -+#define __nds32__v_ucmpeq16(a, b) \ -+ (__builtin_nds32_v_ucmpeq16 ((a), (b))) -+#define __nds32__scmplt16(a, b) \ -+ (__builtin_nds32_scmplt16 ((a), (b))) -+#define __nds32__v_scmplt16(a, b) \ -+ (__builtin_nds32_v_scmplt16 ((a), (b))) -+#define __nds32__scmple16(a, b) \ -+ (__builtin_nds32_scmple16 ((a), (b))) -+#define __nds32__v_scmple16(a, b) \ -+ (__builtin_nds32_v_scmple16 ((a), (b))) -+#define __nds32__ucmplt16(a, b) \ -+ (__builtin_nds32_ucmplt16 ((a), (b))) -+#define __nds32__v_ucmplt16(a, b) \ -+ (__builtin_nds32_v_ucmplt16 ((a), (b))) -+#define __nds32__ucmple16(a, b) \ -+ (__builtin_nds32_ucmple16 ((a), (b))) -+#define __nds32__v_ucmple16(a, b) \ -+ (__builtin_nds32_v_ucmple16 ((a), (b))) -+ -+#define __nds32__cmpeq8(a, b) \ -+ (__builtin_nds32_cmpeq8 ((a), (b))) -+#define __nds32__v_scmpeq8(a, b) \ -+ (__builtin_nds32_v_scmpeq8 ((a), (b))) -+#define __nds32__v_ucmpeq8(a, b) \ -+ (__builtin_nds32_v_ucmpeq8 ((a), (b))) -+#define __nds32__scmplt8(a, b) \ -+ (__builtin_nds32_scmplt8 ((a), (b))) -+#define __nds32__v_scmplt8(a, b) \ -+ (__builtin_nds32_v_scmplt8 ((a), (b))) -+#define __nds32__scmple8(a, b) \ -+ (__builtin_nds32_scmple8 ((a), (b))) -+#define __nds32__v_scmple8(a, b) \ -+ (__builtin_nds32_v_scmple8 ((a), (b))) -+#define __nds32__ucmplt8(a, b) \ -+ (__builtin_nds32_ucmplt8 ((a), (b))) -+#define __nds32__v_ucmplt8(a, b) \ -+ (__builtin_nds32_v_ucmplt8 ((a), (b))) -+#define __nds32__ucmple8(a, b) \ -+ (__builtin_nds32_ucmple8 ((a), (b))) -+#define __nds32__v_ucmple8(a, b) \ -+ (__builtin_nds32_v_ucmple8 ((a), (b))) -+ -+#define __nds32__smin16(a, b) \ -+ (__builtin_nds32_smin16 ((a), (b))) -+#define __nds32__v_smin16(a, b) \ -+ (__builtin_nds32_v_smin16 ((a), (b))) -+#define __nds32__umin16(a, b) \ -+ (__builtin_nds32_umin16 ((a), (b))) -+#define __nds32__v_umin16(a, b) \ -+ (__builtin_nds32_v_umin16 ((a), (b))) -+#define __nds32__smax16(a, b) \ -+ (__builtin_nds32_smax16 ((a), (b))) -+#define __nds32__v_smax16(a, b) \ -+ (__builtin_nds32_v_smax16 ((a), (b))) -+#define __nds32__umax16(a, b) \ -+ (__builtin_nds32_umax16 ((a), (b))) -+#define __nds32__v_umax16(a, b) \ -+ (__builtin_nds32_v_umax16 ((a), (b))) -+#define __nds32__sclip16(a, b) \ -+ (__builtin_nds32_sclip16 ((a), (b))) -+#define __nds32__v_sclip16(a, b) \ -+ (__builtin_nds32_v_sclip16 ((a), (b))) -+#define __nds32__uclip16(a, b) \ -+ (__builtin_nds32_uclip16 ((a), (b))) -+#define __nds32__v_uclip16(a, b) \ -+ (__builtin_nds32_v_uclip16 ((a), (b))) -+#define __nds32__khm16(a, b) \ -+ (__builtin_nds32_khm16 ((a), (b))) -+#define __nds32__v_khm16(a, b) \ -+ (__builtin_nds32_v_khm16 ((a), (b))) -+#define __nds32__khmx16(a, b) \ -+ (__builtin_nds32_khmx16 ((a), (b))) -+#define __nds32__v_khmx16(a, b) \ -+ (__builtin_nds32_v_khmx16 ((a), (b))) -+#define __nds32__kabs16(a) \ -+ (__builtin_nds32_kabs16 ((a))) -+#define __nds32__v_kabs16(a) \ -+ (__builtin_nds32_v_kabs16 ((a))) -+ -+#define __nds32__smin8(a, b) \ -+ (__builtin_nds32_smin8 ((a), (b))) -+#define __nds32__v_smin8(a, b) \ -+ (__builtin_nds32_v_smin8 ((a), (b))) -+#define __nds32__umin8(a, b) \ -+ (__builtin_nds32_umin8 ((a), (b))) -+#define __nds32__v_umin8(a, b) \ -+ (__builtin_nds32_v_umin8 ((a), (b))) -+#define __nds32__smax8(a, b) \ -+ (__builtin_nds32_smax8 ((a), (b))) -+#define __nds32__v_smax8(a, b) \ -+ (__builtin_nds32_v_smax8 ((a), (b))) -+#define __nds32__umax8(a, b) \ -+ (__builtin_nds32_umax8 ((a), (b))) -+#define __nds32__v_umax8(a, b) \ -+ (__builtin_nds32_v_umax8 ((a), (b))) -+#define __nds32__kabs8(a) \ -+ (__builtin_nds32_kabs8 ((a))) -+#define __nds32__v_kabs8(a) \ -+ (__builtin_nds32_v_kabs8 ((a))) -+ -+#define __nds32__sunpkd810(a) \ -+ (__builtin_nds32_sunpkd810 ((a))) -+#define __nds32__v_sunpkd810(a) \ -+ (__builtin_nds32_v_sunpkd810 ((a))) -+#define __nds32__sunpkd820(a) \ -+ (__builtin_nds32_sunpkd820 ((a))) -+#define __nds32__v_sunpkd820(a) \ -+ (__builtin_nds32_v_sunpkd820 ((a))) -+#define __nds32__sunpkd830(a) \ -+ (__builtin_nds32_sunpkd830 ((a))) -+#define __nds32__v_sunpkd830(a) \ -+ (__builtin_nds32_v_sunpkd830 ((a))) -+#define __nds32__sunpkd831(a) \ -+ (__builtin_nds32_sunpkd831 ((a))) -+#define __nds32__v_sunpkd831(a) \ -+ (__builtin_nds32_v_sunpkd831 ((a))) -+#define __nds32__zunpkd810(a) \ -+ (__builtin_nds32_zunpkd810 ((a))) -+#define __nds32__v_zunpkd810(a) \ -+ (__builtin_nds32_v_zunpkd810 ((a))) -+#define __nds32__zunpkd820(a) \ -+ (__builtin_nds32_zunpkd820 ((a))) -+#define __nds32__v_zunpkd820(a) \ -+ (__builtin_nds32_v_zunpkd820 ((a))) -+#define __nds32__zunpkd830(a) \ -+ (__builtin_nds32_zunpkd830 ((a))) -+#define __nds32__v_zunpkd830(a) \ -+ (__builtin_nds32_v_zunpkd830 ((a))) -+#define __nds32__zunpkd831(a) \ -+ (__builtin_nds32_zunpkd831 ((a))) -+#define __nds32__v_zunpkd831(a) \ -+ (__builtin_nds32_v_zunpkd831 ((a))) -+ -+#define __nds32__raddw(a, b) \ -+ (__builtin_nds32_raddw ((a), (b))) -+#define __nds32__uraddw(a, b) \ -+ (__builtin_nds32_uraddw ((a), (b))) -+#define __nds32__rsubw(a, b) \ -+ (__builtin_nds32_rsubw ((a), (b))) -+#define __nds32__ursubw(a, b) \ -+ (__builtin_nds32_ursubw ((a), (b))) -+ -+#define __nds32__sra_u(a, b) \ -+ (__builtin_nds32_sra_u ((a), (b))) -+#define __nds32__ksll(a, b) \ -+ (__builtin_nds32_ksll ((a), (b))) -+#define __nds32__pkbb16(a, b) \ -+ (__builtin_nds32_pkbb16 ((a), (b))) -+#define __nds32__v_pkbb16(a, b) \ -+ (__builtin_nds32_v_pkbb16 ((a), (b))) -+#define __nds32__pkbt16(a, b) \ -+ (__builtin_nds32_pkbt16 ((a), (b))) -+#define __nds32__v_pkbt16(a, b) \ -+ (__builtin_nds32_v_pkbt16 ((a), (b))) -+#define __nds32__pktb16(a, b) \ -+ (__builtin_nds32_pktb16 ((a), (b))) -+#define __nds32__v_pktb16(a, b) \ -+ (__builtin_nds32_v_pktb16 ((a), (b))) -+#define __nds32__pktt16(a, b) \ -+ (__builtin_nds32_pktt16 ((a), (b))) -+#define __nds32__v_pktt16(a, b) \ -+ (__builtin_nds32_v_pktt16 ((a), (b))) -+ -+#define __nds32__smmul(a, b) \ -+ (__builtin_nds32_smmul ((a), (b))) -+#define __nds32__smmul_u(a, b) \ -+ (__builtin_nds32_smmul_u ((a), (b))) -+#define __nds32__kmmac(r, a, b) \ -+ (__builtin_nds32_kmmac ((r), (a), (b))) -+#define __nds32__kmmac_u(r, a, b) \ -+ (__builtin_nds32_kmmac_u ((r), (a), (b))) -+#define __nds32__kmmsb(r, a, b) \ -+ (__builtin_nds32_kmmsb ((r), (a), (b))) -+#define __nds32__kmmsb_u(r, a, b) \ -+ (__builtin_nds32_kmmsb_u ((r), (a), (b))) -+#define __nds32__kwmmul(a, b) \ -+ (__builtin_nds32_kwmmul ((a), (b))) -+#define __nds32__kwmmul_u(a, b) \ -+ (__builtin_nds32_kwmmul_u ((a), (b))) -+ -+#define __nds32__smmwb(a, b) \ -+ (__builtin_nds32_smmwb ((a), (b))) -+#define __nds32__v_smmwb(a, b) \ -+ (__builtin_nds32_v_smmwb ((a), (b))) -+#define __nds32__smmwb_u(a, b) \ -+ (__builtin_nds32_smmwb_u ((a), (b))) -+#define __nds32__v_smmwb_u(a, b) \ -+ (__builtin_nds32_v_smmwb_u ((a), (b))) -+#define __nds32__smmwt(a, b) \ -+ (__builtin_nds32_smmwt ((a), (b))) -+#define __nds32__v_smmwt(a, b) \ -+ (__builtin_nds32_v_smmwt ((a), (b))) -+#define __nds32__smmwt_u(a, b) \ -+ (__builtin_nds32_smmwt_u ((a), (b))) -+#define __nds32__v_smmwt_u(a, b) \ -+ (__builtin_nds32_v_smmwt_u ((a), (b))) -+#define __nds32__kmmawb(r, a, b) \ -+ (__builtin_nds32_kmmawb ((r), (a), (b))) -+#define __nds32__v_kmmawb(r, a, b) \ -+ (__builtin_nds32_v_kmmawb ((r), (a), (b))) -+#define __nds32__kmmawb_u(r, a, b) \ -+ (__builtin_nds32_kmmawb_u ((r), (a), (b))) -+#define __nds32__v_kmmawb_u(r, a, b) \ -+ (__builtin_nds32_v_kmmawb_u ((r), (a), (b))) -+#define __nds32__kmmawt(r, a, b) \ -+ (__builtin_nds32_kmmawt ((r), (a), (b))) -+#define __nds32__v_kmmawt(r, a, b) \ -+ (__builtin_nds32_v_kmmawt ((r), (a), (b))) -+#define __nds32__kmmawt_u(r, a, b) \ -+ (__builtin_nds32_kmmawt_u ((r), (a), (b))) -+#define __nds32__v_kmmawt_u(r, a, b) \ -+ (__builtin_nds32_v_kmmawt_u ((r), (a), (b))) -+ -+#define __nds32__smbb(a, b) \ -+ (__builtin_nds32_smbb ((a), (b))) -+#define __nds32__v_smbb(a, b) \ -+ (__builtin_nds32_v_smbb ((a), (b))) -+#define __nds32__smbt(a, b) \ -+ (__builtin_nds32_smbt ((a), (b))) -+#define __nds32__v_smbt(a, b) \ -+ (__builtin_nds32_v_smbt ((a), (b))) -+#define __nds32__smtt(a, b) \ -+ (__builtin_nds32_smtt ((a), (b))) -+#define __nds32__v_smtt(a, b) \ -+ (__builtin_nds32_v_smtt ((a), (b))) -+#define __nds32__kmda(a, b) \ -+ (__builtin_nds32_kmda ((a), (b))) -+#define __nds32__v_kmda(a, b) \ -+ (__builtin_nds32_v_kmda ((a), (b))) -+#define __nds32__kmxda(a, b) \ -+ (__builtin_nds32_kmxda ((a), (b))) -+#define __nds32__v_kmxda(a, b) \ -+ (__builtin_nds32_v_kmxda ((a), (b))) -+#define __nds32__smds(a, b) \ -+ (__builtin_nds32_smds ((a), (b))) -+#define __nds32__v_smds(a, b) \ -+ (__builtin_nds32_v_smds ((a), (b))) -+#define __nds32__smdrs(a, b) \ -+ (__builtin_nds32_smdrs ((a), (b))) -+#define __nds32__v_smdrs(a, b) \ -+ (__builtin_nds32_v_smdrs ((a), (b))) -+#define __nds32__smxds(a, b) \ -+ (__builtin_nds32_smxds ((a), (b))) -+#define __nds32__v_smxds(a, b) \ -+ (__builtin_nds32_v_smxds ((a), (b))) -+#define __nds32__kmabb(r, a, b) \ -+ (__builtin_nds32_kmabb ((r), (a), (b))) -+#define __nds32__v_kmabb(r, a, b) \ -+ (__builtin_nds32_v_kmabb ((r), (a), (b))) -+#define __nds32__kmabt(r, a, b) \ -+ (__builtin_nds32_kmabt ((r), (a), (b))) -+#define __nds32__v_kmabt(r, a, b) \ -+ (__builtin_nds32_v_kmabt ((r), (a), (b))) -+#define __nds32__kmatt(r, a, b) \ -+ (__builtin_nds32_kmatt ((r), (a), (b))) -+#define __nds32__v_kmatt(r, a, b) \ -+ (__builtin_nds32_v_kmatt ((r), (a), (b))) -+#define __nds32__kmada(r, a, b) \ -+ (__builtin_nds32_kmada ((r), (a), (b))) -+#define __nds32__v_kmada(r, a, b) \ -+ (__builtin_nds32_v_kmada ((r), (a), (b))) -+#define __nds32__kmaxda(r, a, b) \ -+ (__builtin_nds32_kmaxda ((r), (a), (b))) -+#define __nds32__v_kmaxda(r, a, b) \ -+ (__builtin_nds32_v_kmaxda ((r), (a), (b))) -+#define __nds32__kmads(r, a, b) \ -+ (__builtin_nds32_kmads ((r), (a), (b))) -+#define __nds32__v_kmads(r, a, b) \ -+ (__builtin_nds32_v_kmads ((r), (a), (b))) -+#define __nds32__kmadrs(r, a, b) \ -+ (__builtin_nds32_kmadrs ((r), (a), (b))) -+#define __nds32__v_kmadrs(r, a, b) \ -+ (__builtin_nds32_v_kmadrs ((r), (a), (b))) -+#define __nds32__kmaxds(r, a, b) \ -+ (__builtin_nds32_kmaxds ((r), (a), (b))) -+#define __nds32__v_kmaxds(r, a, b) \ -+ (__builtin_nds32_v_kmaxds ((r), (a), (b))) -+#define __nds32__kmsda(r, a, b) \ -+ (__builtin_nds32_kmsda ((r), (a), (b))) -+#define __nds32__v_kmsda(r, a, b) \ -+ (__builtin_nds32_v_kmsda ((r), (a), (b))) -+#define __nds32__kmsxda(r, a, b) \ -+ (__builtin_nds32_kmsxda ((r), (a), (b))) -+#define __nds32__v_kmsxda(r, a, b) \ -+ (__builtin_nds32_v_kmsxda ((r), (a), (b))) -+ -+#define __nds32__smal(a, b) \ -+ (__builtin_nds32_smal ((a), (b))) -+#define __nds32__v_smal(a, b) \ -+ (__builtin_nds32_v_smal ((a), (b))) -+ -+#define __nds32__bitrev(a, b) \ -+ (__builtin_nds32_bitrev ((a), (b))) -+#define __nds32__wext(a, b) \ -+ (__builtin_nds32_wext ((a), (b))) -+#define __nds32__bpick(r, a, b) \ -+ (__builtin_nds32_bpick ((r), (a), (b))) -+#define __nds32__insb(r, a, b) \ -+ (__builtin_nds32_insb ((r), (a), (b))) -+ -+#define __nds32__sadd64(a, b) \ -+ (__builtin_nds32_sadd64 ((a), (b))) -+#define __nds32__uadd64(a, b) \ -+ (__builtin_nds32_uadd64 ((a), (b))) -+#define __nds32__radd64(a, b) \ -+ (__builtin_nds32_radd64 ((a), (b))) -+#define __nds32__uradd64(a, b) \ -+ (__builtin_nds32_uradd64 ((a), (b))) -+#define __nds32__kadd64(a, b) \ -+ (__builtin_nds32_kadd64 ((a), (b))) -+#define __nds32__ukadd64(a, b) \ -+ (__builtin_nds32_ukadd64 ((a), (b))) -+#define __nds32__ssub64(a, b) \ -+ (__builtin_nds32_ssub64 ((a), (b))) -+#define __nds32__usub64(a, b) \ -+ (__builtin_nds32_usub64 ((a), (b))) -+#define __nds32__rsub64(a, b) \ -+ (__builtin_nds32_rsub64 ((a), (b))) -+#define __nds32__ursub64(a, b) \ -+ (__builtin_nds32_ursub64 ((a), (b))) -+#define __nds32__ksub64(a, b) \ -+ (__builtin_nds32_ksub64 ((a), (b))) -+#define __nds32__uksub64(a, b) \ -+ (__builtin_nds32_uksub64 ((a), (b))) -+ -+#define __nds32__smar64(r, a, b) \ -+ (__builtin_nds32_smar64 ((r), (a), (b))) -+#define __nds32__smsr64(r, a, b) \ -+ (__builtin_nds32_smsr64 ((r), (a), (b))) -+#define __nds32__umar64(r, a, b) \ -+ (__builtin_nds32_umar64 ((r), (a), (b))) -+#define __nds32__umsr64(r, a, b) \ -+ (__builtin_nds32_umsr64 ((r), (a), (b))) -+#define __nds32__kmar64(r, a, b) \ -+ (__builtin_nds32_kmar64 ((r), (a), (b))) -+#define __nds32__kmsr64(r, a, b) \ -+ (__builtin_nds32_kmsr64 ((r), (a), (b))) -+#define __nds32__ukmar64(r, a, b) \ -+ (__builtin_nds32_ukmar64 ((r), (a), (b))) -+#define __nds32__ukmsr64(r, a, b) \ -+ (__builtin_nds32_ukmsr64 ((r), (a), (b))) -+ -+#define __nds32__smalbb(r, a, b) \ -+ (__builtin_nds32_smalbb ((r), (a), (b))) -+#define __nds32__v_smalbb(r, a, b) \ -+ (__builtin_nds32_v_smalbb ((r), (a), (b))) -+#define __nds32__smalbt(r, a, b) \ -+ (__builtin_nds32_smalbt ((r), (a), (b))) -+#define __nds32__v_smalbt(r, a, b) \ -+ (__builtin_nds32_v_smalbt ((r), (a), (b))) -+#define __nds32__smaltt(r, a, b) \ -+ (__builtin_nds32_smaltt ((r), (a), (b))) -+#define __nds32__v_smaltt(r, a, b) \ -+ (__builtin_nds32_v_smaltt ((r), (a), (b))) -+#define __nds32__smalda(r, a, b) \ -+ (__builtin_nds32_smalda ((r), (a), (b))) -+#define __nds32__v_smalda(r, a, b) \ -+ (__builtin_nds32_v_smalda ((r), (a), (b))) -+#define __nds32__smalxda(r, a, b) \ -+ (__builtin_nds32_smalxda ((r), (a), (b))) -+#define __nds32__v_smalxda(r, a, b) \ -+ (__builtin_nds32_v_smalxda ((r), (a), (b))) -+#define __nds32__smalds(r, a, b) \ -+ (__builtin_nds32_smalds ((r), (a), (b))) -+#define __nds32__v_smalds(r, a, b) \ -+ (__builtin_nds32_v_smalds ((r), (a), (b))) -+#define __nds32__smaldrs(r, a, b) \ -+ (__builtin_nds32_smaldrs ((r), (a), (b))) -+#define __nds32__v_smaldrs(r, a, b) \ -+ (__builtin_nds32_v_smaldrs ((r), (a), (b))) -+#define __nds32__smalxds(r, a, b) \ -+ (__builtin_nds32_smalxds ((r), (a), (b))) -+#define __nds32__v_smalxds(r, a, b) \ -+ (__builtin_nds32_v_smalxds ((r), (a), (b))) -+#define __nds32__smslda(r, a, b) \ -+ (__builtin_nds32_smslda ((r), (a), (b))) -+#define __nds32__v_smslda(r, a, b) \ -+ (__builtin_nds32_v_smslda ((r), (a), (b))) -+#define __nds32__smslxda(r, a, b) \ -+ (__builtin_nds32_smslxda ((r), (a), (b))) -+#define __nds32__v_smslxda(r, a, b) \ -+ (__builtin_nds32_v_smslxda ((r), (a), (b))) -+ -+#define __nds32__smul16(a, b) \ -+ (__builtin_nds32_smul16 ((a), (b))) -+#define __nds32__v_smul16(a, b) \ -+ (__builtin_nds32_v_smul16 ((a), (b))) -+#define __nds32__smulx16(a, b) \ -+ (__builtin_nds32_smulx16 ((a), (b))) -+#define __nds32__v_smulx16(a, b) \ -+ (__builtin_nds32_v_smulx16 ((a), (b))) -+#define __nds32__umul16(a, b) \ -+ (__builtin_nds32_umul16 ((a), (b))) -+#define __nds32__v_umul16(a, b) \ -+ (__builtin_nds32_v_umul16 ((a), (b))) -+#define __nds32__umulx16(a, b) \ -+ (__builtin_nds32_umulx16 ((a), (b))) -+#define __nds32__v_umulx16(a, b) \ -+ (__builtin_nds32_v_umulx16 ((a), (b))) -+ -+#define __nds32__uclip32(a, imm) \ -+ (__builtin_nds32_uclip32 ((a), (imm))) -+#define __nds32__sclip32(a, imm) \ -+ (__builtin_nds32_sclip32 ((a), (imm))) -+#define __nds32__kabs(a) \ -+ (__builtin_nds32_kabs ((a))) -+ - #define __nds32__unaligned_feature() \ - (__builtin_nds32_unaligned_feature()) - #define __nds32__enable_unaligned() \ - (__builtin_nds32_enable_unaligned()) - #define __nds32__disable_unaligned() \ - (__builtin_nds32_disable_unaligned()) -+ -+#define __nds32__get_unaligned_u16x2(a) \ -+ (__builtin_nds32_get_unaligned_u16x2 ((a))) -+#define __nds32__get_unaligned_s16x2(a) \ -+ (__builtin_nds32_get_unaligned_s16x2 ((a))) -+#define __nds32__get_unaligned_u8x4(a) \ -+ (__builtin_nds32_get_unaligned_u8x4 ((a))) -+#define __nds32__get_unaligned_s8x4(a) \ -+ (__builtin_nds32_get_unaligned_s8x4 ((a))) -+ -+#define __nds32__put_unaligned_u16x2(a, data) \ -+ (__builtin_nds32_put_unaligned_u16x2 ((a), (data))) -+#define __nds32__put_unaligned_s16x2(a, data) \ -+ (__builtin_nds32_put_unaligned_s16x2 ((a), (data))) -+#define __nds32__put_unaligned_u8x4(a, data) \ -+ (__builtin_nds32_put_unaligned_u8x4 ((a), (data))) -+#define __nds32__put_unaligned_s8x4(a, data) \ -+ (__builtin_nds32_put_unaligned_s8x4 ((a), (data))) -+ -+#define NDS32ATTR_SIGNATURE __attribute__((signature)) -+ - #endif /* nds32_intrinsic.h */ -diff --git a/gcc/config/nds32/nds32_isr.h b/gcc/config/nds32/nds32_isr.h -new file mode 100644 -index 00000000000..8ea58f951e1 ---- /dev/null -+++ b/gcc/config/nds32/nds32_isr.h -@@ -0,0 +1,526 @@ -+/* Intrinsic definitions 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. -+ -+ 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 -+ . */ -+ -+#ifndef _NDS32_ISR_H -+#define _NDS32_ISR_H -+ -+/* Attribute of a interrupt or exception handler: -+ -+ NDS32_READY_NESTED: This handler is interruptible if user re-enable GIE bit. -+ NDS32_NESTED : This handler is interruptible. This is not suitable -+ exception handler. -+ NDS32_NOT_NESTED : This handler is NOT interruptible. Users have to do -+ some work if nested is wanted -+ NDS32_CRITICAL : This handler is critical ISR, which means it is small -+ and efficient. */ -+#define NDS32_READY_NESTED 0 -+#define NDS32_NESTED 1 -+#define NDS32_NOT_NESTED 2 -+#define NDS32_CRITICAL 3 -+ -+/* Attribute of a interrupt or exception handler: -+ -+ NDS32_SAVE_ALL_REGS : Save all registers in a table. -+ NDS32_SAVE_PARTIAL_REGS: Save partial registers. */ -+#define NDS32_SAVE_CALLER_REGS 0 -+#define NDS32_SAVE_ALL_REGS 1 -+ -+/* There are two version of Register table for interrupt and exception handler, -+ one for 16-register CPU the other for 32-register CPU. These structures are -+ used for context switching or system call handling. The address of this -+ data can be get from the input argument of the handler functions. -+ -+ For system call handling, r0 to r5 are used to pass arguments. If more -+ arguments are used they are put into the stack and its starting address is -+ in sp. Return value of system call can be put into r0 and r1 upon exit from -+ system call handler. System call ID is in a system register and it can be -+ fetched via intrinsic function. For more information please read ABI and -+ other related documents. -+ -+ For context switching, at least 2 values need to saved in kernel. One is -+ IPC and the other is the stack address of current task. Use intrinsic -+ function to get IPC and the input argument of the handler functions + 8 to -+ get stack address of current task. To do context switching, you replace -+ new_sp with the stack address of new task and replace IPC system register -+ with IPC of new task, then, just return from handler. The context switching -+ will happen. */ -+ -+/* Register table for exception handler; 32-register version. */ -+typedef struct -+{ -+ int r0; -+ int r1; -+ int r2; -+ int r3; -+ int r4; -+ int r5; -+ int r6; -+ int r7; -+ int r8; -+ int r9; -+ int r10; -+ int r11; -+ int r12; -+ int r13; -+ int r14; -+ int r15; -+ int r16; -+ int r17; -+ int r18; -+ int r19; -+ int r20; -+ int r21; -+ int r22; -+ int r23; -+ int r24; -+ int r25; -+ int r26; -+ int r27; -+ int fp; -+ int gp; -+ int lp; -+ int sp; -+} NDS32_GPR32; -+ -+/* Register table for exception handler; 16-register version. */ -+typedef struct -+{ -+ int r0; -+ int r1; -+ int r2; -+ int r3; -+ int r4; -+ int r5; -+ int r6; -+ int r7; -+ int r8; -+ int r9; -+ int r10; -+ int r15; -+ int fp; -+ int gp; -+ int lp; -+ int sp; -+} NDS32_GPR16; -+ -+ -+/* Use NDS32_REG32_TAB or NDS32_REG16_TAB in your program to -+ access register table. */ -+typedef struct -+{ -+ union -+ { -+ int reg_a[32] ; -+ NDS32_GPR32 reg_s ; -+ } u ; -+} NDS32_REG32_TAB; -+ -+typedef struct -+{ -+ union -+ { -+ int reg_a[16] ; -+ NDS32_GPR16 reg_s ; -+ } u ; -+} NDS32_REG16_TAB; -+ -+typedef struct -+{ -+ int d0lo; -+ int d0hi; -+ int d1lo; -+ int d1hi; -+} NDS32_DX_TAB; -+ -+typedef struct -+{ -+#ifdef __NDS32_EB__ -+ float fsr0; -+ float fsr1; -+ float fsr2; -+ float fsr3; -+ float fsr4; -+ float fsr5; -+ float fsr6; -+ float fsr7; -+#else -+ float fsr1; -+ float fsr0; -+ float fsr3; -+ float fsr2; -+ float fsr5; -+ float fsr4; -+ float fsr7; -+ float fsr6; -+#endif -+} NDS32_FSR8; -+ -+typedef struct -+{ -+ double dsr0; -+ double dsr1; -+ double dsr2; -+ double dsr3; -+} NDS32_DSR4; -+ -+typedef struct -+{ -+#ifdef __NDS32_EB__ -+ float fsr0; -+ float fsr1; -+ float fsr2; -+ float fsr3; -+ float fsr4; -+ float fsr5; -+ float fsr6; -+ float fsr7; -+ float fsr8; -+ float fsr9; -+ float fsr10; -+ float fsr11; -+ float fsr12; -+ float fsr13; -+ float fsr14; -+ float fsr15; -+#else -+ float fsr1; -+ float fsr0; -+ float fsr3; -+ float fsr2; -+ float fsr5; -+ float fsr4; -+ float fsr7; -+ float fsr6; -+ float fsr9; -+ float fsr8; -+ float fsr11; -+ float fsr10; -+ float fsr13; -+ float fsr12; -+ float fsr15; -+ float fsr14; -+#endif -+} NDS32_FSR16; -+ -+typedef struct -+{ -+ double dsr0; -+ double dsr1; -+ double dsr2; -+ double dsr3; -+ double dsr4; -+ double dsr5; -+ double dsr6; -+ double dsr7; -+} NDS32_DSR8; -+ -+typedef struct -+{ -+#ifdef __NDS32_EB__ -+ float fsr0; -+ float fsr1; -+ float fsr2; -+ float fsr3; -+ float fsr4; -+ float fsr5; -+ float fsr6; -+ float fsr7; -+ float fsr8; -+ float fsr9; -+ float fsr10; -+ float fsr11; -+ float fsr12; -+ float fsr13; -+ float fsr14; -+ float fsr15; -+ float fsr16; -+ float fsr17; -+ float fsr18; -+ float fsr19; -+ float fsr20; -+ float fsr21; -+ float fsr22; -+ float fsr23; -+ float fsr24; -+ float fsr25; -+ float fsr26; -+ float fsr27; -+ float fsr28; -+ float fsr29; -+ float fsr30; -+ float fsr31; -+#else -+ float fsr1; -+ float fsr0; -+ float fsr3; -+ float fsr2; -+ float fsr5; -+ float fsr4; -+ float fsr7; -+ float fsr6; -+ float fsr9; -+ float fsr8; -+ float fsr11; -+ float fsr10; -+ float fsr13; -+ float fsr12; -+ float fsr15; -+ float fsr14; -+ float fsr17; -+ float fsr16; -+ float fsr19; -+ float fsr18; -+ float fsr21; -+ float fsr20; -+ float fsr23; -+ float fsr22; -+ float fsr25; -+ float fsr24; -+ float fsr27; -+ float fsr26; -+ float fsr29; -+ float fsr28; -+ float fsr31; -+ float fsr30; -+#endif -+} NDS32_FSR32; -+ -+typedef struct -+{ -+ double dsr0; -+ double dsr1; -+ double dsr2; -+ double dsr3; -+ double dsr4; -+ double dsr5; -+ double dsr6; -+ double dsr7; -+ double dsr8; -+ double dsr9; -+ double dsr10; -+ double dsr11; -+ double dsr12; -+ double dsr13; -+ double dsr14; -+ double dsr15; -+} NDS32_DSR16; -+ -+typedef struct -+{ -+ double dsr0; -+ double dsr1; -+ double dsr2; -+ double dsr3; -+ double dsr4; -+ double dsr5; -+ double dsr6; -+ double dsr7; -+ double dsr8; -+ double dsr9; -+ double dsr10; -+ double dsr11; -+ double dsr12; -+ double dsr13; -+ double dsr14; -+ double dsr15; -+ double dsr16; -+ double dsr17; -+ double dsr18; -+ double dsr19; -+ double dsr20; -+ double dsr21; -+ double dsr22; -+ double dsr23; -+ double dsr24; -+ double dsr25; -+ double dsr26; -+ double dsr27; -+ double dsr28; -+ double dsr29; -+ double dsr30; -+ double dsr31; -+} NDS32_DSR32; -+ -+typedef struct -+{ -+ union -+ { -+ NDS32_FSR8 fsr_s ; -+ NDS32_DSR4 dsr_s ; -+ } u ; -+} NDS32_FPU8_TAB; -+ -+typedef struct -+{ -+ union -+ { -+ NDS32_FSR16 fsr_s ; -+ NDS32_DSR8 dsr_s ; -+ } u ; -+} NDS32_FPU16_TAB; -+ -+typedef struct -+{ -+ union -+ { -+ NDS32_FSR32 fsr_s ; -+ NDS32_DSR16 dsr_s ; -+ } u ; -+} NDS32_FPU32_TAB; -+ -+typedef struct -+{ -+ union -+ { -+ NDS32_FSR32 fsr_s ; -+ NDS32_DSR32 dsr_s ; -+ } u ; -+} NDS32_FPU64_TAB; -+ -+typedef struct -+{ -+ int ipc; -+ int ipsw; -+#if defined(NDS32_EXT_FPU_CONFIG_0) -+ NDS32_FPU8_TAB fpr; -+#elif defined(NDS32_EXT_FPU_CONFIG_1) -+ NDS32_FPU16_TAB fpr; -+#elif defined(NDS32_EXT_FPU_CONFIG_2) -+ NDS32_FPU32_TAB fpr; -+#elif defined(NDS32_EXT_FPU_CONFIG_3) -+ NDS32_FPU64_TAB fpr; -+#endif -+#if __NDS32_DX_REGS__ -+ NDS32_DX_TAB dxr; -+#endif -+#if __NDS32_EXT_IFC__ -+ int ifc_lp; -+ int filler; -+#endif -+#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS -+ NDS32_REG16_TAB gpr; -+#else -+ NDS32_REG32_TAB gpr; -+#endif -+} NDS32_CONTEXT; -+ -+/* Predefined Vector Definition. -+ -+ For IVIC Mode: 9 to 14 are for hardware interrupt -+ and 15 is for software interrupt. -+ For EVIC Mode: 9 to 72 are for hardware interrupt -+ and software interrupt can be routed to any one of them. -+ -+ You may want to define your hardware interrupts in the following way -+ for easy maintainance. -+ -+ IVIC mode: -+ #define MY_HW_IVIC_TIMER NDS32_VECTOR_INTERRUPT_HW0 + 1 -+ #define MY_HW_IVIC_USB NDS32_VECTOR_INTERRUPT_HW0 + 3 -+ EVIC mode: -+ #define MY_HW_EVIC_DMA NDS32_VECTOR_INTERRUPT_HW0 + 2 -+ #define MY_HW_EVIC_SWI NDS32_VECTOR_INTERRUPT_HW0 + 10 */ -+#define NDS32_VECTOR_RESET 0 -+#define NDS32_VECTOR_TLB_FILL 1 -+#define NDS32_VECTOR_PTE_NOT_PRESENT 2 -+#define NDS32_VECTOR_TLB_MISC 3 -+#define NDS32_VECTOR_TLB_VLPT_MISS 4 -+#define NDS32_VECTOR_MACHINE_ERROR 5 -+#define NDS32_VECTOR_DEBUG_RELATED 6 -+#define NDS32_VECTOR_GENERAL_EXCEPTION 7 -+#define NDS32_VECTOR_SYSCALL 8 -+#define NDS32_VECTOR_INTERRUPT_HW0 9 -+#define NDS32_VECTOR_INTERRUPT_HW1 10 -+#define NDS32_VECTOR_INTERRUPT_HW2 11 -+#define NDS32_VECTOR_INTERRUPT_HW3 12 -+#define NDS32_VECTOR_INTERRUPT_HW4 13 -+#define NDS32_VECTOR_INTERRUPT_HW5 14 -+#define NDS32_VECTOR_INTERRUPT_HW6 15 -+#define NDS32_VECTOR_SWI 15 /* THIS IS FOR IVIC MODE ONLY */ -+#define NDS32_VECTOR_INTERRUPT_HW7 16 -+#define NDS32_VECTOR_INTERRUPT_HW8 17 -+#define NDS32_VECTOR_INTERRUPT_HW9 18 -+#define NDS32_VECTOR_INTERRUPT_HW10 19 -+#define NDS32_VECTOR_INTERRUPT_HW11 20 -+#define NDS32_VECTOR_INTERRUPT_HW12 21 -+#define NDS32_VECTOR_INTERRUPT_HW13 22 -+#define NDS32_VECTOR_INTERRUPT_HW14 23 -+#define NDS32_VECTOR_INTERRUPT_HW15 24 -+#define NDS32_VECTOR_INTERRUPT_HW16 25 -+#define NDS32_VECTOR_INTERRUPT_HW17 26 -+#define NDS32_VECTOR_INTERRUPT_HW18 27 -+#define NDS32_VECTOR_INTERRUPT_HW19 28 -+#define NDS32_VECTOR_INTERRUPT_HW20 29 -+#define NDS32_VECTOR_INTERRUPT_HW21 30 -+#define NDS32_VECTOR_INTERRUPT_HW22 31 -+#define NDS32_VECTOR_INTERRUPT_HW23 32 -+#define NDS32_VECTOR_INTERRUPT_HW24 33 -+#define NDS32_VECTOR_INTERRUPT_HW25 34 -+#define NDS32_VECTOR_INTERRUPT_HW26 35 -+#define NDS32_VECTOR_INTERRUPT_HW27 36 -+#define NDS32_VECTOR_INTERRUPT_HW28 37 -+#define NDS32_VECTOR_INTERRUPT_HW29 38 -+#define NDS32_VECTOR_INTERRUPT_HW30 39 -+#define NDS32_VECTOR_INTERRUPT_HW31 40 -+#define NDS32_VECTOR_INTERRUPT_HW32 41 -+#define NDS32_VECTOR_INTERRUPT_HW33 42 -+#define NDS32_VECTOR_INTERRUPT_HW34 43 -+#define NDS32_VECTOR_INTERRUPT_HW35 44 -+#define NDS32_VECTOR_INTERRUPT_HW36 45 -+#define NDS32_VECTOR_INTERRUPT_HW37 46 -+#define NDS32_VECTOR_INTERRUPT_HW38 47 -+#define NDS32_VECTOR_INTERRUPT_HW39 48 -+#define NDS32_VECTOR_INTERRUPT_HW40 49 -+#define NDS32_VECTOR_INTERRUPT_HW41 50 -+#define NDS32_VECTOR_INTERRUPT_HW42 51 -+#define NDS32_VECTOR_INTERRUPT_HW43 52 -+#define NDS32_VECTOR_INTERRUPT_HW44 53 -+#define NDS32_VECTOR_INTERRUPT_HW45 54 -+#define NDS32_VECTOR_INTERRUPT_HW46 55 -+#define NDS32_VECTOR_INTERRUPT_HW47 56 -+#define NDS32_VECTOR_INTERRUPT_HW48 57 -+#define NDS32_VECTOR_INTERRUPT_HW49 58 -+#define NDS32_VECTOR_INTERRUPT_HW50 59 -+#define NDS32_VECTOR_INTERRUPT_HW51 60 -+#define NDS32_VECTOR_INTERRUPT_HW52 61 -+#define NDS32_VECTOR_INTERRUPT_HW53 62 -+#define NDS32_VECTOR_INTERRUPT_HW54 63 -+#define NDS32_VECTOR_INTERRUPT_HW55 64 -+#define NDS32_VECTOR_INTERRUPT_HW56 65 -+#define NDS32_VECTOR_INTERRUPT_HW57 66 -+#define NDS32_VECTOR_INTERRUPT_HW58 67 -+#define NDS32_VECTOR_INTERRUPT_HW59 68 -+#define NDS32_VECTOR_INTERRUPT_HW60 69 -+#define NDS32_VECTOR_INTERRUPT_HW61 70 -+#define NDS32_VECTOR_INTERRUPT_HW62 71 -+#define NDS32_VECTOR_INTERRUPT_HW63 72 -+ -+#define NDS32ATTR_RESET(option) __attribute__((reset(option))) -+#define NDS32ATTR_EXCEPT(type) __attribute__((exception(type))) -+#define NDS32ATTR_EXCEPTION(type) __attribute__((exception(type))) -+#define NDS32ATTR_INTERRUPT(type) __attribute__((interrupt(type))) -+#define NDS32ATTR_ISR(type) __attribute__((interrupt(type))) -+ -+#endif /* nds32_isr.h */ -diff --git a/gcc/config/nds32/pipelines.md b/gcc/config/nds32/pipelines.md -index 34288076f42..12cd2623f1c 100644 ---- a/gcc/config/nds32/pipelines.md -+++ b/gcc/config/nds32/pipelines.md -@@ -43,6 +43,24 @@ - (include "nds32-n9-2r1w.md") - - -+;; ------------------------------------------------------------------------ -+;; Include N10 pipeline settings. -+;; ------------------------------------------------------------------------ -+(include "nds32-n10.md") -+ -+ -+;; ------------------------------------------------------------------------ -+;; Include Graywolf pipeline settings. -+;; ------------------------------------------------------------------------ -+(include "nds32-graywolf.md") -+ -+ -+;; ------------------------------------------------------------------------ -+;; Include N12/N13 pipeline settings. -+;; ------------------------------------------------------------------------ -+(include "nds32-n13.md") -+ -+ - ;; ------------------------------------------------------------------------ - ;; Define simple pipeline settings. - ;; ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/predicates.md b/gcc/config/nds32/predicates.md -index 9eb84685514..ee4cf3cf48e 100644 ---- a/gcc/config/nds32/predicates.md -+++ b/gcc/config/nds32/predicates.md -@@ -40,7 +40,15 @@ - (match_code "mult,and,ior,xor")) - - (define_predicate "nds32_symbolic_operand" -- (match_code "const,symbol_ref,label_ref")) -+ (and (match_code "const,symbol_ref,label_ref") -+ (match_test "!(TARGET_ICT_MODEL_LARGE -+ && nds32_indirect_call_referenced_p (op))"))) -+ -+(define_predicate "nds32_nonunspec_symbolic_operand" -+ (and (match_code "const,symbol_ref,label_ref") -+ (match_test "!flag_pic && nds32_const_unspec_p (op) -+ && !(TARGET_ICT_MODEL_LARGE -+ && nds32_indirect_call_referenced_p (op))"))) - - (define_predicate "nds32_reg_constant_operand" - (ior (match_operand 0 "register_operand") -@@ -56,14 +64,51 @@ - (and (match_operand 0 "const_int_operand") - (match_test "satisfies_constraint_Is11 (op)")))) - -+(define_predicate "nds32_imm_0_1_operand" -+ (and (match_operand 0 "const_int_operand") -+ (ior (match_test "satisfies_constraint_Iv00 (op)") -+ (match_test "satisfies_constraint_Iv01 (op)")))) -+ -+(define_predicate "nds32_imm_1_2_operand" -+ (and (match_operand 0 "const_int_operand") -+ (ior (match_test "satisfies_constraint_Iv01 (op)") -+ (match_test "satisfies_constraint_Iv02 (op)")))) -+ -+(define_predicate "nds32_imm_1_2_4_8_operand" -+ (and (match_operand 0 "const_int_operand") -+ (ior (ior (match_test "satisfies_constraint_Iv01 (op)") -+ (match_test "satisfies_constraint_Iv02 (op)")) -+ (ior (match_test "satisfies_constraint_Iv04 (op)") -+ (match_test "satisfies_constraint_Iv08 (op)"))))) -+ -+(define_predicate "nds32_imm2u_operand" -+ (and (match_operand 0 "const_int_operand") -+ (match_test "satisfies_constraint_Iu02 (op)"))) -+ -+(define_predicate "nds32_imm4u_operand" -+ (and (match_operand 0 "const_int_operand") -+ (match_test "satisfies_constraint_Iu04 (op)"))) -+ - (define_predicate "nds32_imm5u_operand" - (and (match_operand 0 "const_int_operand") - (match_test "satisfies_constraint_Iu05 (op)"))) - -+(define_predicate "nds32_imm6u_operand" -+ (and (match_operand 0 "const_int_operand") -+ (match_test "satisfies_constraint_Iu06 (op)"))) -+ -+(define_predicate "nds32_rimm4u_operand" -+ (ior (match_operand 0 "register_operand") -+ (match_operand 0 "nds32_imm4u_operand"))) -+ - (define_predicate "nds32_rimm5u_operand" - (ior (match_operand 0 "register_operand") - (match_operand 0 "nds32_imm5u_operand"))) - -+(define_predicate "nds32_rimm6u_operand" -+ (ior (match_operand 0 "register_operand") -+ (match_operand 0 "nds32_imm6u_operand"))) -+ - (define_predicate "nds32_move_operand" - (and (match_operand 0 "general_operand") - (not (match_code "high,const,symbol_ref,label_ref"))) -@@ -78,6 +123,20 @@ - return true; - }) - -+(define_predicate "nds32_vmove_operand" -+ (and (match_operand 0 "general_operand") -+ (not (match_code "high,const,symbol_ref,label_ref"))) -+{ -+ /* If the constant op does NOT satisfy Is20 nor Ihig, -+ we can not perform move behavior by a single instruction. */ -+ if (GET_CODE (op) == CONST_VECTOR -+ && !satisfies_constraint_CVs2 (op) -+ && !satisfies_constraint_CVhi (op)) -+ return false; -+ -+ return true; -+}) -+ - (define_predicate "nds32_and_operand" - (match_operand 0 "nds32_reg_constant_operand") - { -@@ -127,6 +186,15 @@ - (ior (match_operand 0 "nds32_symbolic_operand") - (match_operand 0 "nds32_general_register_operand"))) - -+(define_predicate "nds32_insv_operand" -+ (match_code "const_int") -+{ -+ return INTVAL (op) == 0 -+ || INTVAL (op) == 8 -+ || INTVAL (op) == 16 -+ || INTVAL (op) == 24; -+}) -+ - (define_predicate "nds32_lmw_smw_base_operand" - (and (match_code "mem") - (match_test "nds32_valid_smw_lwm_base_p (op)"))) -diff --git a/gcc/config/nds32/t-elf b/gcc/config/nds32/t-elf -new file mode 100644 -index 00000000000..3401dae4881 ---- /dev/null -+++ b/gcc/config/nds32/t-elf -@@ -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 -+# . -+ -+# 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 -+ -+# ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/t-linux b/gcc/config/nds32/t-linux -new file mode 100644 -index 00000000000..33328f65e7b ---- /dev/null -+++ b/gcc/config/nds32/t-linux -@@ -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 -+# . -+ -+# 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 += -+ -+# ------------------------------------------------------------------------ -diff --git a/gcc/configure b/gcc/configure -index 6121e163259..07a485e8598 100755 ---- a/gcc/configure -+++ b/gcc/configure -@@ -27784,7 +27784,7 @@ esac - # version to the per-target configury. - case "$cpu_type" in - aarch64 | alpha | arc | arm | avr | bfin | cris | i386 | m32c | m68k \ -- | microblaze | mips | nios2 | pa | riscv | rs6000 | score | sparc | spu \ -+ | microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc | spu \ - | tilegx | tilepro | visium | xstormy16 | xtensa) - insn="nop" - ;; -diff --git a/gcc/configure.ac b/gcc/configure.ac -index b066cc609e1..ae73df30b42 100644 ---- a/gcc/configure.ac -+++ b/gcc/configure.ac -@@ -4910,7 +4910,7 @@ esac - # version to the per-target configury. - case "$cpu_type" in - aarch64 | alpha | arc | arm | avr | bfin | cris | i386 | m32c | m68k \ -- | microblaze | mips | nios2 | pa | riscv | rs6000 | score | sparc | spu \ -+ | microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc | spu \ - | tilegx | tilepro | visium | xstormy16 | xtensa) - insn="nop" - ;; -diff --git a/gcc/testsuite/gcc.c-torture/execute/20010122-1.c b/gcc/testsuite/gcc.c-torture/execute/20010122-1.c -index 4eeb8c7a30b..6cd02bc2aa8 100644 ---- a/gcc/testsuite/gcc.c-torture/execute/20010122-1.c -+++ b/gcc/testsuite/gcc.c-torture/execute/20010122-1.c -@@ -1,4 +1,5 @@ - /* { dg-skip-if "requires frame pointers" { *-*-* } "-fomit-frame-pointer" "" } */ -+/* { dg-additional-options "-malways-save-lp" { target nds32*-*-* } } */ - /* { dg-require-effective-target return_address } */ - - extern void exit (int); -diff --git a/gcc/testsuite/gcc.dg/lower-subreg-1.c b/gcc/testsuite/gcc.dg/lower-subreg-1.c -index 6bae73055a9..4a5099bfbdb 100644 ---- a/gcc/testsuite/gcc.dg/lower-subreg-1.c -+++ b/gcc/testsuite/gcc.dg/lower-subreg-1.c -@@ -1,4 +1,4 @@ --/* { dg-do compile { target { ! { mips64 || { aarch64*-*-* arm*-*-* ia64-*-* sparc*-*-* spu-*-* tilegx-*-* } } } } } */ -+/* { dg-do compile { target { ! { mips64 || { aarch64*-*-* arm*-*-* ia64-*-* nds32*-*-* sparc*-*-* spu-*-* tilegx-*-* } } } } } */ - /* { dg-options "-O -fdump-rtl-subreg1" } */ - /* { dg-additional-options "-mno-stv" { target ia32 } } */ - /* { dg-skip-if "" { { i?86-*-* x86_64-*-* } && x32 } } */ -diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c -index 45d2c7b6aae..b9ae9dc6030 100644 ---- a/gcc/testsuite/gcc.dg/stack-usage-1.c -+++ b/gcc/testsuite/gcc.dg/stack-usage-1.c -@@ -2,6 +2,7 @@ - /* { dg-options "-fstack-usage" } */ - /* nvptx doesn't have a reg allocator, and hence no stack usage data. */ - /* { dg-skip-if "" { nvptx-*-* } } */ -+/* { dg-options "-fstack-usage -fno-omit-frame-pointer" { target { nds32*-*-* } } } */ - - /* This is aimed at testing basic support for -fstack-usage in the back-ends. - See the SPARC back-end for example (grep flag_stack_usage_info in sparc.c). -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-setgie-dis.c b/gcc/testsuite/gcc.target/nds32/builtin-setgie-dis.c -deleted file mode 100644 -index 2dceed98ac8..00000000000 ---- a/gcc/testsuite/gcc.target/nds32/builtin-setgie-dis.c -+++ /dev/null -@@ -1,11 +0,0 @@ --/* Verify that we generate setgie.d instruction with builtin function. */ -- --/* { dg-do compile } */ --/* { dg-options "-O0" } */ --/* { dg-final { scan-assembler "\\tsetgie.d" } } */ -- --void --test (void) --{ -- __builtin_nds32_setgie_dis (); --} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-setgie-en.c b/gcc/testsuite/gcc.target/nds32/builtin-setgie-en.c -deleted file mode 100644 -index 892887019c9..00000000000 ---- a/gcc/testsuite/gcc.target/nds32/builtin-setgie-en.c -+++ /dev/null -@@ -1,11 +0,0 @@ --/* Verify that we generate setgie.e instruction with builtin function. */ -- --/* { dg-do compile } */ --/* { dg-options "-O0" } */ --/* { dg-final { scan-assembler "\\tsetgie.e" } } */ -- --void --test (void) --{ -- __builtin_nds32_setgie_en (); --} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-setgie_mtsr_mfsr.c b/gcc/testsuite/gcc.target/nds32/builtin-setgie_mtsr_mfsr.c -new file mode 100644 -index 00000000000..3b4eede295d ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-setgie_mtsr_mfsr.c -@@ -0,0 +1,36 @@ -+/* This is a test program for checking gie with -+ mtsr/mfsr instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O0" } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int psw; -+ unsigned int gie; -+ unsigned int pfm_ctl; -+ -+ __nds32__setgie_en (); -+ __nds32__dsb(); /* This is needed for waiting pipeline. */ -+ psw = __nds32__mfsr (NDS32_SR_PSW); -+ -+ gie = psw & 0x00000001; -+ -+ if (gie != 1) -+ abort (); -+ -+ psw = psw & 0xFFFFFFFE; -+ __nds32__mtsr (psw,NDS32_SR_PSW); -+ __nds32__dsb(); /* This is needed for waiting pipeline. */ -+ psw = __nds32__mfsr (NDS32_SR_PSW); -+ gie = psw & 0x00000001; -+ -+ if (gie != 0) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending-hw.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending-hw.c -new file mode 100644 -index 00000000000..fce90e9720b ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending-hw.c -@@ -0,0 +1,16 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+void -+main (void) -+{ -+ __nds32__clr_pending_hwint (NDS32_INT_H0); -+ __nds32__clr_pending_hwint (NDS32_INT_H1); -+ __nds32__clr_pending_hwint (NDS32_INT_H2); -+ -+ __nds32__clr_pending_hwint (NDS32_INT_H15); -+ __nds32__clr_pending_hwint (NDS32_INT_H16); -+ __nds32__clr_pending_hwint (NDS32_INT_H31); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending.c -new file mode 100644 -index 00000000000..08e1dd0c83f ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending.c -@@ -0,0 +1,10 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+void -+main (void) -+{ -+ __nds32__clr_pending_swint (); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-disable.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-disable.c -new file mode 100644 -index 00000000000..a3a1f44fce5 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-disable.c -@@ -0,0 +1,13 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+void -+main (void) -+{ -+ __nds32__disable_int (NDS32_INT_H15); -+ __nds32__disable_int (NDS32_INT_H16); -+ __nds32__disable_int (NDS32_INT_H31); -+ __nds32__disable_int (NDS32_INT_SWI); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-enable.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-enable.c -new file mode 100644 -index 00000000000..e18ed7a9ff0 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-enable.c -@@ -0,0 +1,13 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+void -+main (void) -+{ -+ __nds32__enable_int (NDS32_INT_H15); -+ __nds32__enable_int (NDS32_INT_H16); -+ __nds32__enable_int (NDS32_INT_H31); -+ __nds32__enable_int (NDS32_INT_SWI); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-get-pending-int.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-get-pending-int.c -new file mode 100644 -index 00000000000..4ced0a55d96 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-get-pending-int.c -@@ -0,0 +1,14 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+int -+main (void) -+{ -+ int a = __nds32__get_pending_int (NDS32_INT_H15); -+ int b = __nds32__get_pending_int (NDS32_INT_SWI); -+ int c = __nds32__get_pending_int (NDS32_INT_H16); -+ -+ return a + b + c; -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-get-trig.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-get-trig.c -new file mode 100644 -index 00000000000..a394a60958a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-get-trig.c -@@ -0,0 +1,14 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+int -+main (void) -+{ -+ int a = __nds32__get_trig_type (NDS32_INT_H0); -+ int b = __nds32__get_trig_type (NDS32_INT_H15); -+ int c = __nds32__get_trig_type (NDS32_INT_H16); -+ int d = __nds32__get_trig_type (NDS32_INT_H31); -+ return a + b + c + d; -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-isb.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-isb.c -similarity index 100% -rename from gcc/testsuite/gcc.target/nds32/builtin-isb.c -rename to gcc/testsuite/gcc.target/nds32/compile/builtin-isb.c -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-isync.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-isync.c -similarity index 100% -rename from gcc/testsuite/gcc.target/nds32/builtin-isync.c -rename to gcc/testsuite/gcc.target/nds32/compile/builtin-isync.c -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-mfsr-mtsr.c -similarity index 100% -rename from gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c -rename to gcc/testsuite/gcc.target/nds32/compile/builtin-mfsr-mtsr.c -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-mfusr-mtusr.c -similarity index 100% -rename from gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c -rename to gcc/testsuite/gcc.target/nds32/compile/builtin-mfusr-mtusr.c -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-set-pending.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-set-pending.c -new file mode 100644 -index 00000000000..f10b83d2d60 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-set-pending.c -@@ -0,0 +1,10 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+int -+main (void) -+{ -+ __nds32__set_pending_swint (); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-edge.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-edge.c -new file mode 100644 -index 00000000000..bd8178c7165 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-edge.c -@@ -0,0 +1,13 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+void -+main (void) -+{ -+ __nds32__set_trig_type_edge (NDS32_INT_H0); -+ __nds32__set_trig_type_edge (NDS32_INT_H15); -+ __nds32__set_trig_type_edge (NDS32_INT_H16); -+ __nds32__set_trig_type_edge (NDS32_INT_H31); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-level.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-level.c -new file mode 100644 -index 00000000000..17805433280 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-level.c -@@ -0,0 +1,13 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+void -+main (void) -+{ -+ __nds32__set_trig_type_level (NDS32_INT_H0); -+ __nds32__set_trig_type_level (NDS32_INT_H15); -+ __nds32__set_trig_type_level (NDS32_INT_H16); -+ __nds32__set_trig_type_level (NDS32_INT_H31); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-dis.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-dis.c -new file mode 100644 -index 00000000000..e143d3fefb7 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-dis.c -@@ -0,0 +1,13 @@ -+/* Verify that we generate setgie.d instruction with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "\\tsetgie.d" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ __nds32__setgie_dis (); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-en.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-en.c -new file mode 100644 -index 00000000000..ed95782ee5f ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-en.c -@@ -0,0 +1,13 @@ -+/* Verify that we generate setgie.e instruction with builtin function. */ -+ -+/* { dg-do compile */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "\\tsetgie.e" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ __nds32__setgie_en (); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/nds32.exp b/gcc/testsuite/gcc.target/nds32/nds32.exp -index 44ce72d2583..2f1bff60d67 100644 ---- a/gcc/testsuite/gcc.target/nds32/nds32.exp -+++ b/gcc/testsuite/gcc.target/nds32/nds32.exp -@@ -38,8 +38,10 @@ if ![info exists DEFAULT_CFLAGS] then { - dg-init - - # Main loop. --dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \ -+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/compile/*.\[cS\]]] \ - "" $DEFAULT_CFLAGS -+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \ -+ "" "" - - # All done. - dg-finish -diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp -index 50665dfd30e..fbf7998b7ed 100644 ---- a/gcc/testsuite/lib/target-supports.exp -+++ b/gcc/testsuite/lib/target-supports.exp -@@ -8767,6 +8767,7 @@ proc check_effective_target_logical_op_short_circuit {} { - || [istarget avr*-*-*] - || [istarget crisv32-*-*] || [istarget cris-*-*] - || [istarget mmix-*-*] -+ || [istarget nds32*-*-*] - || [istarget s390*-*-*] - || [istarget powerpc*-*-*] - || [istarget nios2*-*-*] -diff --git a/libgcc/config.host b/libgcc/config.host -index 11b4acaff55..fbbc9219d68 100644 ---- a/libgcc/config.host -+++ b/libgcc/config.host -@@ -974,6 +974,23 @@ msp430*-*-elf) - 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" - ;; -+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*) - # Basic makefile fragment and extra_parts for crt stuff. - # We also append c-isr library implementation. -diff --git a/libgcc/config/nds32/initfini.c b/libgcc/config/nds32/initfini.c -index 49ca44fa659..dfbcc43f776 100644 ---- a/libgcc/config/nds32/initfini.c -+++ b/libgcc/config/nds32/initfini.c -@@ -25,6 +25,10 @@ - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - . */ - -+#include -+/* Need header file for `struct object' type. */ -+#include "../libgcc/unwind-dw2-fde.h" -+ - /* Declare a pointer to void function type. */ - typedef void (*func_ptr) (void); - -@@ -42,11 +46,59 @@ typedef void (*func_ptr) (void); - refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__ - symbol in crtinit.o, where they are defined. */ - --static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors"))) -- = { (func_ptr) (-1) }; -+static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors"), used)) -+ = { (func_ptr) 0 }; -+ -+static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors"), used)) -+ = { (func_ptr) 0 }; -+ -+ -+#ifdef SUPPORT_UNWINDING_DWARF2 -+/* Preparation of exception handling with dwar2 mechanism registration. */ - --static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors"))) -- = { (func_ptr) (-1) }; -+asm ("\n\ -+ .section .eh_frame,\"aw\",@progbits\n\ -+ .global __EH_FRAME_BEGIN__\n\ -+ .type __EH_FRAME_BEGIN__, @object\n\ -+ .align 2\n\ -+__EH_FRAME_BEGIN__:\n\ -+ ! Beginning location of eh_frame section\n\ -+ .previous\n\ -+"); -+ -+extern func_ptr __EH_FRAME_BEGIN__[]; -+ -+ -+/* Note that the following two functions are going to be chained into -+ constructor and destructor list, repectively. So these two declarations -+ must be placed after __CTOR_LIST__ and __DTOR_LIST. */ -+extern void __nds32_register_eh(void) __attribute__((constructor, used)); -+extern void __nds32_deregister_eh(void) __attribute__((destructor, used)); -+ -+/* Register the exception handling table as the first constructor. */ -+void -+__nds32_register_eh (void) -+{ -+ static struct object object; -+ if (__register_frame_info) -+ __register_frame_info (__EH_FRAME_BEGIN__, &object); -+} -+ -+/* Unregister the exception handling table as a deconstructor. */ -+void -+__nds32_deregister_eh (void) -+{ -+ static int completed = 0; -+ -+ if (completed) -+ return; -+ -+ if (__deregister_frame_info) -+ __deregister_frame_info (__EH_FRAME_BEGIN__); -+ -+ completed = 1; -+} -+#endif - - /* Run all the global destructors on exit from the program. */ - -@@ -63,7 +115,7 @@ static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors"))) - same particular root executable or shared library file. */ - - static void __do_global_dtors (void) --asm ("__do_global_dtors") __attribute__ ((section (".text"))); -+asm ("__do_global_dtors") __attribute__ ((section (".text"), used)); - - static void - __do_global_dtors (void) -@@ -116,23 +168,37 @@ void *__dso_handle = 0; - last, these words naturally end up at the very ends of the two lists - contained in these two sections. */ - --static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors"))) -+static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors"), used)) - = { (func_ptr) 0 }; - --static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors"))) -+static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors"), used)) - = { (func_ptr) 0 }; - -+#ifdef SUPPORT_UNWINDING_DWARF2 -+/* ZERO terminator in .eh_frame section. */ -+asm ("\n\ -+ .section .eh_frame,\"aw\",@progbits\n\ -+ .global __EH_FRAME_END__\n\ -+ .type __EH_FRAME_END__, @object\n\ -+ .align 2\n\ -+__EH_FRAME_END__:\n\ -+ ! End location of eh_frame section with ZERO terminator\n\ -+ .word 0\n\ -+ .previous\n\ -+"); -+#endif -+ - /* Run all global constructors for the program. - Note that they are run in reverse order. */ - - static void __do_global_ctors (void) --asm ("__do_global_ctors") __attribute__ ((section (".text"))); -+asm ("__do_global_ctors") __attribute__ ((section (".text"), used)); - - static void - __do_global_ctors (void) - { - func_ptr *p; -- for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--) -+ for (p = __CTOR_END__ - 1; *p; p--) - (*p) (); - } - -diff --git a/libgcc/config/nds32/isr-library/adj_intr_lvl.inc b/libgcc/config/nds32/isr-library/adj_intr_lvl.inc -index 5cc1a6fc88a..275e5580ef3 100644 ---- a/libgcc/config/nds32/isr-library/adj_intr_lvl.inc -+++ b/libgcc/config/nds32/isr-library/adj_intr_lvl.inc -@@ -26,13 +26,26 @@ - .macro ADJ_INTR_LVL - #if defined(NDS32_NESTED) /* Nested handler. */ - mfsr $r3, $PSW -+ /* By substracting 1 from $PSW, we can lower PSW.INTL -+ and enable GIE simultaneously. */ - addi $r3, $r3, #-0x1 -+ #if __NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__ -+ ori $r3, $r3, 0x2000 /* Set PSW.AEN(b'13) */ -+ #endif - mtsr $r3, $PSW - #elif defined(NDS32_NESTED_READY) /* Nested ready handler. */ - /* Save ipc and ipsw and lower INT level. */ - mfsr $r3, $PSW - addi $r3, $r3, #-0x2 -+ #if __NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__ -+ ori $r3, $r3, 0x2000 /* Set PSW.AEN(b'13) */ -+ #endif - mtsr $r3, $PSW - #else /* Not nested handler. */ -+ #if __NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__ -+ mfsr $r3, $PSW -+ ori $r3, $r3, 0x2000 /* Set PSW.AEN(b'13) */ -+ mtsr $r3, $PSW -+ #endif - #endif - .endm -diff --git a/libgcc/config/nds32/isr-library/excp_isr.S b/libgcc/config/nds32/isr-library/excp_isr.S -index f24f856e6ee..6e7de5f8fb5 100644 ---- a/libgcc/config/nds32/isr-library/excp_isr.S -+++ b/libgcc/config/nds32/isr-library/excp_isr.S -@@ -23,6 +23,7 @@ - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - . */ - -+#include "save_usr_regs.inc" - #include "save_mac_regs.inc" - #include "save_fpu_regs.inc" - #include "save_fpu_regs_00.inc" -@@ -32,35 +33,33 @@ - #include "save_all.inc" - #include "save_partial.inc" - #include "adj_intr_lvl.inc" --#include "restore_mac_regs.inc" - #include "restore_fpu_regs_00.inc" - #include "restore_fpu_regs_01.inc" - #include "restore_fpu_regs_02.inc" - #include "restore_fpu_regs_03.inc" - #include "restore_fpu_regs.inc" -+#include "restore_mac_regs.inc" -+#include "restore_usr_regs.inc" - #include "restore_all.inc" - #include "restore_partial.inc" -+ - .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */ - .align 1 --/* -- First Level Handlers -- 1. First Level Handlers are invokded in vector section via jump instruction -- with specific names for different configurations. -- 2. Naming Format: _nds32_e_SR_NT for exception handlers. -- _nds32_i_SR_NT for interrupt handlers. -- 2.1 All upper case letters are replaced with specific lower case letters encodings. -- 2.2 SR: Saved Registers -- sa: Save All regs (context) -- ps: Partial Save (all caller-saved regs) -- 2.3 NT: Nested Type -- ns: nested -- nn: not nested -- nr: nested ready --*/ -- --/* -- This is original 16-byte vector size version. --*/ -+ -+/* First Level Handlers -+ 1. First Level Handlers are invokded in vector section via jump instruction -+ with specific names for different configurations. -+ 2. Naming Format: _nds32_e_SR_NT for exception handlers. -+ _nds32_i_SR_NT for interrupt handlers. -+ 2.1 All upper case letters are replaced with specific lower case letters encodings. -+ 2.2 SR -- Saved Registers -+ sa: Save All regs (context) -+ ps: Partial Save (all caller-saved regs) -+ 2.3 NT -- Nested Type -+ ns: nested -+ nn: not nested -+ nr: nested ready */ -+ - #ifdef NDS32_SAVE_ALL_REGS - #if defined(NDS32_NESTED) - .globl _nds32_e_sa_ns -@@ -91,21 +90,26 @@ _nds32_e_ps_nn: - #endif /* endif for Nest Type */ - #endif /* not NDS32_SAVE_ALL_REGS */ - --/* -- This is 16-byte vector size version. -- The vector id was restored into $r0 in vector by compiler. --*/ -+ -+/* For 4-byte vector size version, the vector id is -+ extracted from $ITYPE and is set into $r0 by library. -+ For 16-byte vector size version, the vector id -+ is set into $r0 in vector section by compiler. */ -+ -+/* Save used registers. */ - #ifdef NDS32_SAVE_ALL_REGS - SAVE_ALL - #else - SAVE_PARTIAL - #endif -+ - /* Prepare to call 2nd level handler. */ - la $r2, _nds32_jmptbl_00 - lw $r2, [$r2 + $r0 << #2] - ADJ_INTR_LVL /* Adjust INTR level. $r3 is clobbered. */ - jral $r2 -- /* Restore used registers. */ -+ -+/* Restore used registers. */ - #ifdef NDS32_SAVE_ALL_REGS - RESTORE_ALL - #else -@@ -113,6 +117,7 @@ _nds32_e_ps_nn: - #endif - iret - -+ - #ifdef NDS32_SAVE_ALL_REGS - #if defined(NDS32_NESTED) - .size _nds32_e_sa_ns, .-_nds32_e_sa_ns -diff --git a/libgcc/config/nds32/isr-library/intr_isr.S b/libgcc/config/nds32/isr-library/intr_isr.S -index 0431ac114fb..23ffa100206 100644 ---- a/libgcc/config/nds32/isr-library/intr_isr.S -+++ b/libgcc/config/nds32/isr-library/intr_isr.S -@@ -23,6 +23,7 @@ - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - . */ - -+#include "save_usr_regs.inc" - #include "save_mac_regs.inc" - #include "save_fpu_regs.inc" - #include "save_fpu_regs_00.inc" -@@ -32,35 +33,33 @@ - #include "save_all.inc" - #include "save_partial.inc" - #include "adj_intr_lvl.inc" --#include "restore_mac_regs.inc" - #include "restore_fpu_regs_00.inc" - #include "restore_fpu_regs_01.inc" - #include "restore_fpu_regs_02.inc" - #include "restore_fpu_regs_03.inc" - #include "restore_fpu_regs.inc" -+#include "restore_mac_regs.inc" -+#include "restore_usr_regs.inc" - #include "restore_all.inc" - #include "restore_partial.inc" -+ - .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */ - .align 1 --/* -- First Level Handlers -- 1. First Level Handlers are invokded in vector section via jump instruction -- with specific names for different configurations. -- 2. Naming Format: _nds32_e_SR_NT for exception handlers. -- _nds32_i_SR_NT for interrupt handlers. -- 2.1 All upper case letters are replaced with specific lower case letters encodings. -- 2.2 SR: Saved Registers -- sa: Save All regs (context) -- ps: Partial Save (all caller-saved regs) -- 2.3 NT: Nested Type -- ns: nested -- nn: not nested -- nr: nested ready --*/ -- --/* -- This is original 16-byte vector size version. --*/ -+ -+/* First Level Handlers -+ 1. First Level Handlers are invokded in vector section via jump instruction -+ with specific names for different configurations. -+ 2. Naming Format: _nds32_e_SR_NT for exception handlers. -+ _nds32_i_SR_NT for interrupt handlers. -+ 2.1 All upper case letters are replaced with specific lower case letters encodings. -+ 2.2 SR -- Saved Registers -+ sa: Save All regs (context) -+ ps: Partial Save (all caller-saved regs) -+ 2.3 NT -- Nested Type -+ ns: nested -+ nn: not nested -+ nr: nested ready */ -+ - #ifdef NDS32_SAVE_ALL_REGS - #if defined(NDS32_NESTED) - .globl _nds32_i_sa_ns -@@ -91,21 +90,36 @@ _nds32_i_ps_nn: - #endif /* endif for Nest Type */ - #endif /* not NDS32_SAVE_ALL_REGS */ - --/* -- This is 16-byte vector size version. -- The vector id was restored into $r0 in vector by compiler. --*/ -+ -+/* For 4-byte vector size version, the vector id is -+ extracted from $ITYPE and is set into $r0 by library. -+ For 16-byte vector size version, the vector id -+ is set into $r0 in vector section by compiler. */ -+ -+/* Save used registers first. */ - #ifdef NDS32_SAVE_ALL_REGS - SAVE_ALL - #else - SAVE_PARTIAL - #endif -- /* Prepare to call 2nd level handler. */ -+ -+/* According to vector size, we need to have different implementation. */ -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* Prepare to call 2nd level handler. */ -+ la $r2, _nds32_jmptbl_00 -+ lw $r2, [$r2 + $r0 << #2] -+ addi $r0, $r0, #-9 /* Make interrput vector id zero-based. */ -+ ADJ_INTR_LVL /* Adjust INTR level. $r3 is clobbered. */ -+ jral $r2 -+#else /* not __NDS32_ISR_VECTOR_SIZE_4__ */ -+ /* Prepare to call 2nd level handler. */ - la $r2, _nds32_jmptbl_09 /* For zero-based vcetor id. */ - lw $r2, [$r2 + $r0 << #2] - ADJ_INTR_LVL /* Adjust INTR level. $r3 is clobbered. */ - jral $r2 -- /* Restore used registers. */ -+#endif /* not __NDS32_ISR_VECTOR_SIZE_4__ */ -+ -+/* Restore used registers. */ - #ifdef NDS32_SAVE_ALL_REGS - RESTORE_ALL - #else -@@ -113,6 +127,7 @@ _nds32_i_ps_nn: - #endif - iret - -+ - #ifdef NDS32_SAVE_ALL_REGS - #if defined(NDS32_NESTED) - .size _nds32_i_sa_ns, .-_nds32_i_sa_ns -diff --git a/libgcc/config/nds32/isr-library/reset.S b/libgcc/config/nds32/isr-library/reset.S -index 78abeb2127c..2ac247e99fb 100644 ---- a/libgcc/config/nds32/isr-library/reset.S -+++ b/libgcc/config/nds32/isr-library/reset.S -@@ -26,22 +26,18 @@ - .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */ - .align 1 - .weak _SDA_BASE_ /* For reset handler only. */ -- .weak _FP_BASE_ /* For reset handler only. */ - .weak _nds32_init_mem /* User defined memory initialization function. */ - .globl _start - .globl _nds32_reset - .type _nds32_reset, @function - _nds32_reset: - _start: --#ifdef NDS32_EXT_EX9 -- .no_ex9_begin --#endif - /* Handle NMI and warm boot if any of them exists. */ - beqz $sp, 1f /* Reset, NMI or warm boot? */ - /* Either NMI or warm boot; save all regs. */ - - /* Preserve registers for context-switching. */ --#ifdef __NDS32_REDUCED_REGS__ -+#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS - /* For 16-reg mode. */ - smw.adm $r0, [$sp], $r10, #0x0 - smw.adm $r15, [$sp], $r15, #0xf -@@ -49,10 +45,9 @@ _start: - /* For 32-reg mode. */ - smw.adm $r0, [$sp], $r27, #0xf - #endif --#ifdef NDS32_EXT_IFC -+#if __NDS32_EXT_IFC__ - mfusr $r1, $IFC_LP -- smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep -- stack 8-byte alignment. */ -+ smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep stack 8-byte alignment. */ - #endif - - la $gp, _SDA_BASE_ /* Init GP for small data access. */ -@@ -71,12 +66,11 @@ _start: - bnez $r0, 1f /* If fail to resume, do cold boot. */ - - /* Restore registers for context-switching. */ --#ifdef NDS32_EXT_IFC -- lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep -- stack 8-byte alignment. */ -+#if __NDS32_EXT_IFC__ -+ lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep stack 8-byte alignment. */ - mtusr $r1, $IFC_LP - #endif --#ifdef __NDS32_REDUCED_REGS__ -+#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS - /* For 16-reg mode. */ - lmw.bim $r15, [$sp], $r15, #0xf - lmw.bim $r0, [$sp], $r10, #0x0 -@@ -88,6 +82,17 @@ _start: - - - 1: /* Cold boot. */ -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* With vector ID feature for v3 architecture, default vector size is 4-byte. */ -+ /* Set IVB.ESZ = 0 (vector table entry size = 4 bytes) */ -+ mfsr $r0, $IVB -+ li $r1, #0xc000 -+ or $r0, $r0, $r1 -+ xor $r0, $r0, $r1 -+ mtsr $r0, $IVB -+ dsb -+#else -+ /* There is no vector ID feature, so the vector size must be 16-byte. */ - /* Set IVB.ESZ = 1 (vector table entry size = 16 bytes) */ - mfsr $r0, $IVB - li $r1, #0xffff3fff -@@ -95,36 +100,54 @@ _start: - ori $r0, $r0, #0x4000 - mtsr $r0, $IVB - dsb -+#endif - - la $gp, _SDA_BASE_ /* Init $gp. */ -- la $fp, _FP_BASE_ /* Init $fp. */ - la $sp, _stack /* Init $sp. */ --#ifdef NDS32_EXT_EX9 --/* -- * Initialize the table base of EX9 instruction -- * ex9 generation needs to disable before the ITB is set -- */ -- mfsr $r0, $MSC_CFG /* Check if HW support of EX9. */ -+ -+#if __NDS32_EXT_EX9__ -+.L_init_itb: -+ /* Initialization for Instruction Table Base (ITB). -+ The symbol _ITB_BASE_ is determined by Linker. -+ Set $ITB only if MSC_CFG.EIT (cr4.b'24) is set. */ -+ mfsr $r0, $MSC_CFG - srli $r0, $r0, 24 - andi $r0, $r0, 0x1 -- beqz $r0, 4f /* Zero means HW does not support EX9. */ -- la $r0, _ITB_BASE_ /* Init $ITB. */ -+ beqz $r0, 4f /* Fall through ? */ -+ la $r0, _ITB_BASE_ - mtusr $r0, $ITB -- .no_ex9_end - 4: - #endif -- la $r15, _nds32_init_mem /* Call DRAM init. _nds32_init_mem -- may written by C language. */ -+ -+#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__ -+.L_init_fpu: -+ /* Initialize FPU -+ Set FUCOP_CTL.CP0EN (fucpr.b'0). */ -+ mfsr $r0, $FUCOP_CTL -+ ori $r0, $r0, 0x1 -+ mtsr $r0, $FUCOP_CTL -+ dsb -+ /* According to [bugzilla #9425], set flush-to-zero mode. -+ That is, set $FPCSR.DNZ(b'12) = 1. */ -+ FMFCSR $r0 -+ ori $r0, $r0, 0x1000 -+ FMTCSR $r0 -+ dsb -+#endif -+ -+ /* Call DRAM init. _nds32_init_mem may written by C language. */ -+ la $r15, _nds32_init_mem - beqz $r15, 6f - jral $r15 - 6: - l.w $r15, _nds32_jmptbl_00 /* Load reset handler. */ - jral $r15 --/* Reset handler() should never return in a RTOS or non-OS system. -- In case it does return, an exception will be generated. -- This exception will be caught either by default break handler or by EDM. -- Default break handle may just do an infinite loop. -- EDM will notify GDB and GDB will regain control when the ID is 0x7fff. */ -+ -+ /* Reset handler() should never return in a RTOS or non-OS system. -+ In case it does return, an exception will be generated. -+ This exception will be caught either by default break handler or by EDM. -+ Default break handle may just do an infinite loop. -+ EDM will notify GDB and GDB will regain control when the ID is 0x7fff. */ - 5: - break #0x7fff - .size _nds32_reset, .-_nds32_reset -diff --git a/libgcc/config/nds32/isr-library/restore_all.inc b/libgcc/config/nds32/isr-library/restore_all.inc -index 74556466fa9..23cdf8c6f16 100644 ---- a/libgcc/config/nds32/isr-library/restore_all.inc -+++ b/libgcc/config/nds32/isr-library/restore_all.inc -@@ -31,15 +31,11 @@ - mtsr $r2, $IPSW - RESTORE_FPU_REGS - RESTORE_MAC_REGS --#ifdef NDS32_EXT_IFC -- lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep -- stack 8-byte alignment. */ -- mtusr $r1, $IFC_LP --#endif --#ifdef __NDS32_REDUCED_REGS__ -+ RESTORE_USR_REGS -+#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS - lmw.bim $r0, [$sp], $r10, #0x0 /* Restore all regs. */ - lmw.bim $r15, [$sp], $r15, #0xf --#else /* not __NDS32_REDUCED_REGS__ */ -+#else - lmw.bim $r0, [$sp], $r27, #0xf /* Restore all regs. */ - #endif - .endm -diff --git a/libgcc/config/nds32/isr-library/restore_mac_regs.inc b/libgcc/config/nds32/isr-library/restore_mac_regs.inc -index 1e6aac669af..a4340833a76 100644 ---- a/libgcc/config/nds32/isr-library/restore_mac_regs.inc -+++ b/libgcc/config/nds32/isr-library/restore_mac_regs.inc -@@ -24,7 +24,7 @@ - . */ - - .macro RESTORE_MAC_REGS --#ifdef NDS32_DX_REGS -+#if __NDS32_DX_REGS__ - lmw.bim $r1, [$sp], $r4, #0x0 - mtusr $r1, $d0.lo - mtusr $r2, $d0.hi -diff --git a/libgcc/config/nds32/isr-library/restore_partial.inc b/libgcc/config/nds32/isr-library/restore_partial.inc -index d406a99820d..c43ad1600e1 100644 ---- a/libgcc/config/nds32/isr-library/restore_partial.inc -+++ b/libgcc/config/nds32/isr-library/restore_partial.inc -@@ -31,15 +31,11 @@ - mtsr $r1, $IPC /* Set IPC. */ - mtsr $r2, $IPSW /* Set IPSW. */ - #endif -- RESTORE_FPU_REGS -- RESTORE_MAC_REGS --#ifdef NDS32_EXT_IFC -- lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep -- stack 8-byte alignment. */ -- mtusr $r1, $IFC_LP --#endif -+ RESTORE_FPU_REGS -+ RESTORE_MAC_REGS -+ RESTORE_USR_REGS - lmw.bim $r0, [$sp], $r5, #0x0 /* Restore all regs. */ --#ifdef __NDS32_REDUCED_REGS__ -+#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS - lmw.bim $r15, [$sp], $r15, #0x2 - #else - lmw.bim $r15, [$sp], $r27, #0x2 /* Restore all regs. */ -diff --git a/libgcc/config/nds32/isr-library/restore_usr_regs.inc b/libgcc/config/nds32/isr-library/restore_usr_regs.inc -new file mode 100644 -index 00000000000..9602c741cbd ---- /dev/null -+++ b/libgcc/config/nds32/isr-library/restore_usr_regs.inc -@@ -0,0 +1,42 @@ -+/* c-isr library stuff 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. -+ -+ 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 -+ . */ -+ -+.macro RESTORE_USR_REGS -+#if __NDS32_EXT_IFC__ && (__NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__) -+ lmw.bim $r1, [$sp], $r4, #0x0 -+ mtusr $r1, $IFC_LP -+ mtusr $r2, $LB -+ mtusr $r3, $LE -+ mtusr $r4, $LC -+#elif __NDS32_EXT_IFC__ -+ lmw.bim $r1, [$sp], $r2, #0x0 -+ mtusr $r1, $IFC_LP -+#elif __NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__ -+ lmw.bim $r1, [$sp], $r4, #0x0 -+ mtusr $r1, $LB -+ mtusr $r2, $LE -+ mtusr $r3, $LC -+#endif -+.endm -diff --git a/libgcc/config/nds32/isr-library/save_all.inc b/libgcc/config/nds32/isr-library/save_all.inc -index fa08b399bb4..8886edb1f64 100644 ---- a/libgcc/config/nds32/isr-library/save_all.inc -+++ b/libgcc/config/nds32/isr-library/save_all.inc -@@ -23,45 +23,42 @@ - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - . */ - --.macro SAVE_ALL_4B --#ifdef __NDS32_REDUCED_REGS__ -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ -+/* If vector size is 4-byte, we have to save registers -+ in the macro implementation. */ -+.macro SAVE_ALL -+#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS - smw.adm $r15, [$sp], $r15, #0xf - smw.adm $r0, [$sp], $r10, #0x0 --#else /* not __NDS32_REDUCED_REGS__ */ -+#else - smw.adm $r0, [$sp], $r27, #0xf --#endif /* not __NDS32_REDUCED_REGS__ */ --#ifdef NDS32_EXT_IFC -- mfusr $r1, $IFC_LP -- smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep -- stack 8-byte alignment. */ - #endif -- SAVE_MAC_REGS -- SAVE_FPU_REGS -+ SAVE_USR_REGS -+ SAVE_MAC_REGS -+ SAVE_FPU_REGS - mfsr $r1, $IPC /* Get IPC. */ - mfsr $r2, $IPSW /* Get IPSW. */ - smw.adm $r1, [$sp], $r2, #0x0 /* Push IPC, IPSW. */ - move $r1, $sp /* $r1 is ptr to NDS32_CONTEXT. */ - mfsr $r0, $ITYPE /* Get VID to $r0. */ - srli $r0, $r0, #5 --#ifdef __NDS32_ISA_V2__ - andi $r0, $r0, #127 --#else -- fexti33 $r0, #6 --#endif - .endm - -+#else /* not __NDS32_ISR_VECTOR_SIZE_4__ */ -+ -+/* If vector size is 16-byte, some works can be done in -+ the vector section generated by compiler, so that we -+ can implement less in the macro. */ - .macro SAVE_ALL --/* SAVE_REG_TBL code has been moved to -- vector table generated by compiler. */ --#ifdef NDS32_EXT_IFC -- mfusr $r1, $IFC_LP -- smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep -- stack 8-byte alignment. */ --#endif -- SAVE_MAC_REGS -- SAVE_FPU_REGS -+ SAVE_USR_REGS -+ SAVE_MAC_REGS -+ SAVE_FPU_REGS - mfsr $r1, $IPC /* Get IPC. */ - mfsr $r2, $IPSW /* Get IPSW. */ - smw.adm $r1, [$sp], $r2, #0x0 /* Push IPC, IPSW. */ - move $r1, $sp /* $r1 is ptr to NDS32_CONTEXT. */ - .endm -+ -+#endif /* not __NDS32_ISR_VECTOR_SIZE_4__ */ -diff --git a/libgcc/config/nds32/isr-library/save_mac_regs.inc b/libgcc/config/nds32/isr-library/save_mac_regs.inc -index ff120e87a8f..a6a92307fef 100644 ---- a/libgcc/config/nds32/isr-library/save_mac_regs.inc -+++ b/libgcc/config/nds32/isr-library/save_mac_regs.inc -@@ -24,7 +24,7 @@ - . */ - - .macro SAVE_MAC_REGS --#ifdef NDS32_DX_REGS -+#if __NDS32_DX_REGS__ - mfusr $r1, $d0.lo - mfusr $r2, $d0.hi - mfusr $r3, $d1.lo -diff --git a/libgcc/config/nds32/isr-library/save_partial.inc b/libgcc/config/nds32/isr-library/save_partial.inc -index 2445e48067e..c81ebaa693c 100644 ---- a/libgcc/config/nds32/isr-library/save_partial.inc -+++ b/libgcc/config/nds32/isr-library/save_partial.inc -@@ -23,20 +23,20 @@ - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - . */ - --.macro SAVE_PARTIAL_4B --#ifdef __NDS32_REDUCED_REGS__ -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ -+/* If vector size is 4-byte, we have to save registers -+ in the macro implementation. */ -+.macro SAVE_PARTIAL -+#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS - smw.adm $r15, [$sp], $r15, #0x2 --#else /* not __NDS32_REDUCED_REGS__ */ -+#else - smw.adm $r15, [$sp], $r27, #0x2 --#endif /* not __NDS32_REDUCED_REGS__ */ -- smw.adm $r0, [$sp], $r5, #0x0 --#ifdef NDS32_EXT_IFC -- mfusr $r1, $IFC_LP -- smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep -- stack 8-byte alignment. */ - #endif -- SAVE_MAC_REGS -- SAVE_FPU_REGS -+ smw.adm $r0, [$sp], $r5, #0x0 -+ SAVE_USR_REGS -+ SAVE_MAC_REGS -+ SAVE_FPU_REGS - #if defined(NDS32_NESTED) || defined(NDS32_NESTED_READY) - mfsr $r1, $IPC /* Get IPC. */ - mfsr $r2, $IPSW /* Get IPSW. */ -@@ -44,26 +44,24 @@ - #endif - mfsr $r0, $ITYPE /* Get VID to $r0. */ - srli $r0, $r0, #5 --#ifdef __NDS32_ISA_V2__ - andi $r0, $r0, #127 --#else -- fexti33 $r0, #6 --#endif - .endm - -+#else /* not __NDS32_ISR_VECTOR_SIZE_4__ */ -+ -+/* If vector size is 16-byte, some works can be done in -+ the vector section generated by compiler, so that we -+ can implement less in the macro. */ -+ - .macro SAVE_PARTIAL --/* SAVE_CALLER_REGS code has been moved to -- vector table generated by compiler. */ --#ifdef NDS32_EXT_IFC -- mfusr $r1, $IFC_LP -- smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep -- stack 8-byte alignment. */ --#endif -- SAVE_MAC_REGS -- SAVE_FPU_REGS -+ SAVE_USR_REGS -+ SAVE_MAC_REGS -+ SAVE_FPU_REGS - #if defined(NDS32_NESTED) || defined(NDS32_NESTED_READY) - mfsr $r1, $IPC /* Get IPC. */ - mfsr $r2, $IPSW /* Get IPSW. */ - smw.adm $r1, [$sp], $r2, #0x0 /* Push IPC, IPSW. */ - #endif - .endm -+ -+#endif /* not __NDS32_ISR_VECTOR_SIZE_4__ */ -diff --git a/libgcc/config/nds32/isr-library/save_usr_regs.inc b/libgcc/config/nds32/isr-library/save_usr_regs.inc -new file mode 100644 -index 00000000000..5a3f6183b68 ---- /dev/null -+++ b/libgcc/config/nds32/isr-library/save_usr_regs.inc -@@ -0,0 +1,44 @@ -+/* c-isr library stuff 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. -+ -+ 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 -+ . */ -+ -+.macro SAVE_USR_REGS -+/* Store User Special Registers according to supported ISA extension -+ !!! WATCH OUT !!! Take care of 8-byte alignment issue. */ -+#if __NDS32_EXT_IFC__ && (__NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__) -+ mfusr $r1, $IFC_LP -+ mfusr $r2, $LB -+ mfusr $r3, $LE -+ mfusr $r4, $LC -+ smw.adm $r1, [$sp], $r4, #0x0 /* Save even. Ok! */ -+#elif __NDS32_EXT_IFC__ -+ mfusr $r1, $IFC_LP -+ smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep stack 8-byte aligned. */ -+#elif (__NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__) -+ mfusr $r1, $LB -+ mfusr $r2, $LE -+ mfusr $r3, $LC -+ smw.adm $r1, [$sp], $r4, #0x0 /* Save extra $r4 to keep stack 8-byte aligned. */ -+#endif -+.endm -diff --git a/libgcc/config/nds32/isr-library/vec_vid00.S b/libgcc/config/nds32/isr-library/vec_vid00.S -index b2a645c53f0..643009eb800 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid00.S -+++ b/libgcc/config/nds32/isr-library/vec_vid00.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.00, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_00 - .type _nds32_vector_00, @function - _nds32_vector_00: -diff --git a/libgcc/config/nds32/isr-library/vec_vid01.S b/libgcc/config/nds32/isr-library/vec_vid01.S -index 9e796c70524..fd9bc8b6850 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid01.S -+++ b/libgcc/config/nds32/isr-library/vec_vid01.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.01, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_01 - .type _nds32_vector_01, @function - _nds32_vector_01: -diff --git a/libgcc/config/nds32/isr-library/vec_vid02.S b/libgcc/config/nds32/isr-library/vec_vid02.S -index a6b34b7d63a..c5a88435cab 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid02.S -+++ b/libgcc/config/nds32/isr-library/vec_vid02.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.02, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_02 - .type _nds32_vector_02, @function - _nds32_vector_02: -diff --git a/libgcc/config/nds32/isr-library/vec_vid03.S b/libgcc/config/nds32/isr-library/vec_vid03.S -index 680f6d9a60f..7f11fb9166b 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid03.S -+++ b/libgcc/config/nds32/isr-library/vec_vid03.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.03, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_03 - .type _nds32_vector_03, @function - _nds32_vector_03: -diff --git a/libgcc/config/nds32/isr-library/vec_vid04.S b/libgcc/config/nds32/isr-library/vec_vid04.S -index f0b616ceb8a..de2e249b78f 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid04.S -+++ b/libgcc/config/nds32/isr-library/vec_vid04.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.04, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_04 - .type _nds32_vector_04, @function - _nds32_vector_04: -diff --git a/libgcc/config/nds32/isr-library/vec_vid05.S b/libgcc/config/nds32/isr-library/vec_vid05.S -index 47cbcea0a51..62e1cdac4a3 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid05.S -+++ b/libgcc/config/nds32/isr-library/vec_vid05.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.05, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_05 - .type _nds32_vector_05, @function - _nds32_vector_05: -diff --git a/libgcc/config/nds32/isr-library/vec_vid06.S b/libgcc/config/nds32/isr-library/vec_vid06.S -index 851836cf9ea..e41a60c4db4 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid06.S -+++ b/libgcc/config/nds32/isr-library/vec_vid06.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.06, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_06 - .type _nds32_vector_06, @function - _nds32_vector_06: -diff --git a/libgcc/config/nds32/isr-library/vec_vid07.S b/libgcc/config/nds32/isr-library/vec_vid07.S -index 664ee0ca7b0..b5447a85045 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid07.S -+++ b/libgcc/config/nds32/isr-library/vec_vid07.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.07, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_07 - .type _nds32_vector_07, @function - _nds32_vector_07: -diff --git a/libgcc/config/nds32/isr-library/vec_vid08.S b/libgcc/config/nds32/isr-library/vec_vid08.S -index 1b5534c3475..2c07dd35416 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid08.S -+++ b/libgcc/config/nds32/isr-library/vec_vid08.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.08, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_08 - .type _nds32_vector_08, @function - _nds32_vector_08: -diff --git a/libgcc/config/nds32/isr-library/vec_vid09.S b/libgcc/config/nds32/isr-library/vec_vid09.S -index 81a56753202..e858cea5f11 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid09.S -+++ b/libgcc/config/nds32/isr-library/vec_vid09.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.09, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_09 - .type _nds32_vector_09, @function - _nds32_vector_09: -diff --git a/libgcc/config/nds32/isr-library/vec_vid10.S b/libgcc/config/nds32/isr-library/vec_vid10.S -index 102f7cf2ae6..e8bbc0b6a2c 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid10.S -+++ b/libgcc/config/nds32/isr-library/vec_vid10.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.10, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_10 - .type _nds32_vector_10, @function - _nds32_vector_10: -diff --git a/libgcc/config/nds32/isr-library/vec_vid11.S b/libgcc/config/nds32/isr-library/vec_vid11.S -index ade2ee5190c..92aebb41022 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid11.S -+++ b/libgcc/config/nds32/isr-library/vec_vid11.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.11, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_11 - .type _nds32_vector_11, @function - _nds32_vector_11: -diff --git a/libgcc/config/nds32/isr-library/vec_vid12.S b/libgcc/config/nds32/isr-library/vec_vid12.S -index a5958111946..6fd050afd40 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid12.S -+++ b/libgcc/config/nds32/isr-library/vec_vid12.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.12, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_12 - .type _nds32_vector_12, @function - _nds32_vector_12: -diff --git a/libgcc/config/nds32/isr-library/vec_vid13.S b/libgcc/config/nds32/isr-library/vec_vid13.S -index 55863be5e72..0a45c456b24 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid13.S -+++ b/libgcc/config/nds32/isr-library/vec_vid13.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.13, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_13 - .type _nds32_vector_13, @function - _nds32_vector_13: -diff --git a/libgcc/config/nds32/isr-library/vec_vid14.S b/libgcc/config/nds32/isr-library/vec_vid14.S -index abe7f42d1df..837b8487606 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid14.S -+++ b/libgcc/config/nds32/isr-library/vec_vid14.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.14, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_14 - .type _nds32_vector_14, @function - _nds32_vector_14: -diff --git a/libgcc/config/nds32/isr-library/vec_vid15.S b/libgcc/config/nds32/isr-library/vec_vid15.S -index 890819f3ec2..c639aa444ba 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid15.S -+++ b/libgcc/config/nds32/isr-library/vec_vid15.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.15, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_15 - .type _nds32_vector_15, @function - _nds32_vector_15: -diff --git a/libgcc/config/nds32/isr-library/vec_vid16.S b/libgcc/config/nds32/isr-library/vec_vid16.S -index 20db62501ba..a762130631c 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid16.S -+++ b/libgcc/config/nds32/isr-library/vec_vid16.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.16, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_16 - .type _nds32_vector_16, @function - _nds32_vector_16: -diff --git a/libgcc/config/nds32/isr-library/vec_vid17.S b/libgcc/config/nds32/isr-library/vec_vid17.S -index c1ca9f62353..b17681fcb96 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid17.S -+++ b/libgcc/config/nds32/isr-library/vec_vid17.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.17, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_17 - .type _nds32_vector_17, @function - _nds32_vector_17: -diff --git a/libgcc/config/nds32/isr-library/vec_vid18.S b/libgcc/config/nds32/isr-library/vec_vid18.S -index ef4cbeec2e6..4166fa1957f 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid18.S -+++ b/libgcc/config/nds32/isr-library/vec_vid18.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.18, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_18 - .type _nds32_vector_18, @function - _nds32_vector_18: -diff --git a/libgcc/config/nds32/isr-library/vec_vid19.S b/libgcc/config/nds32/isr-library/vec_vid19.S -index 5efab98f379..0d7d1de38c7 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid19.S -+++ b/libgcc/config/nds32/isr-library/vec_vid19.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.19, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_19 - .type _nds32_vector_19, @function - _nds32_vector_19: -diff --git a/libgcc/config/nds32/isr-library/vec_vid20.S b/libgcc/config/nds32/isr-library/vec_vid20.S -index 95e124700c3..d39d74b9ad6 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid20.S -+++ b/libgcc/config/nds32/isr-library/vec_vid20.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.20, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_20 - .type _nds32_vector_20, @function - _nds32_vector_20: -diff --git a/libgcc/config/nds32/isr-library/vec_vid21.S b/libgcc/config/nds32/isr-library/vec_vid21.S -index f3f401e25a0..deff0cf9ea9 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid21.S -+++ b/libgcc/config/nds32/isr-library/vec_vid21.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.21, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_21 - .type _nds32_vector_21, @function - _nds32_vector_21: -diff --git a/libgcc/config/nds32/isr-library/vec_vid22.S b/libgcc/config/nds32/isr-library/vec_vid22.S -index 28d0d99795f..ebd3891af71 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid22.S -+++ b/libgcc/config/nds32/isr-library/vec_vid22.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.22, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_22 - .type _nds32_vector_22, @function - _nds32_vector_22: -diff --git a/libgcc/config/nds32/isr-library/vec_vid23.S b/libgcc/config/nds32/isr-library/vec_vid23.S -index a8246298fed..90562e77bad 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid23.S -+++ b/libgcc/config/nds32/isr-library/vec_vid23.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.23, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_23 - .type _nds32_vector_23, @function - _nds32_vector_23: -diff --git a/libgcc/config/nds32/isr-library/vec_vid24.S b/libgcc/config/nds32/isr-library/vec_vid24.S -index 2c0e2d81c8c..7bd344c6c26 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid24.S -+++ b/libgcc/config/nds32/isr-library/vec_vid24.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.24, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_24 - .type _nds32_vector_24, @function - _nds32_vector_24: -diff --git a/libgcc/config/nds32/isr-library/vec_vid25.S b/libgcc/config/nds32/isr-library/vec_vid25.S -index 56f78863cef..245db6e67b0 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid25.S -+++ b/libgcc/config/nds32/isr-library/vec_vid25.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.25, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_25 - .type _nds32_vector_25, @function - _nds32_vector_25: -diff --git a/libgcc/config/nds32/isr-library/vec_vid26.S b/libgcc/config/nds32/isr-library/vec_vid26.S -index b02163ead68..4df61ff52e4 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid26.S -+++ b/libgcc/config/nds32/isr-library/vec_vid26.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.26, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_26 - .type _nds32_vector_26, @function - _nds32_vector_26: -diff --git a/libgcc/config/nds32/isr-library/vec_vid27.S b/libgcc/config/nds32/isr-library/vec_vid27.S -index 276d1f0b49e..50960dbd12c 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid27.S -+++ b/libgcc/config/nds32/isr-library/vec_vid27.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.27, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_27 - .type _nds32_vector_27, @function - _nds32_vector_27: -diff --git a/libgcc/config/nds32/isr-library/vec_vid28.S b/libgcc/config/nds32/isr-library/vec_vid28.S -index 59e8cc2c4ea..e44adbb58af 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid28.S -+++ b/libgcc/config/nds32/isr-library/vec_vid28.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.28, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_28 - .type _nds32_vector_28, @function - _nds32_vector_28: -diff --git a/libgcc/config/nds32/isr-library/vec_vid29.S b/libgcc/config/nds32/isr-library/vec_vid29.S -index 7119e254afc..f7e6c770e2b 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid29.S -+++ b/libgcc/config/nds32/isr-library/vec_vid29.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.29, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_29 - .type _nds32_vector_29, @function - _nds32_vector_29: -diff --git a/libgcc/config/nds32/isr-library/vec_vid30.S b/libgcc/config/nds32/isr-library/vec_vid30.S -index 7c7bd5fd191..7fac25da175 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid30.S -+++ b/libgcc/config/nds32/isr-library/vec_vid30.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.30, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_30 - .type _nds32_vector_30, @function - _nds32_vector_30: -diff --git a/libgcc/config/nds32/isr-library/vec_vid31.S b/libgcc/config/nds32/isr-library/vec_vid31.S -index bd29e03c4b8..5857765d22e 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid31.S -+++ b/libgcc/config/nds32/isr-library/vec_vid31.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.31, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_31 - .type _nds32_vector_31, @function - _nds32_vector_31: -diff --git a/libgcc/config/nds32/isr-library/vec_vid32.S b/libgcc/config/nds32/isr-library/vec_vid32.S -index 57b8db0bbe4..bcd5dbf88c8 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid32.S -+++ b/libgcc/config/nds32/isr-library/vec_vid32.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.32, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_32 - .type _nds32_vector_32, @function - _nds32_vector_32: -diff --git a/libgcc/config/nds32/isr-library/vec_vid33.S b/libgcc/config/nds32/isr-library/vec_vid33.S -index 609735e731d..abfed4eaf7a 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid33.S -+++ b/libgcc/config/nds32/isr-library/vec_vid33.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.33, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_33 - .type _nds32_vector_33, @function - _nds32_vector_33: -diff --git a/libgcc/config/nds32/isr-library/vec_vid34.S b/libgcc/config/nds32/isr-library/vec_vid34.S -index 2a91328fb11..f9446bb1b07 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid34.S -+++ b/libgcc/config/nds32/isr-library/vec_vid34.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.34, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_34 - .type _nds32_vector_34, @function - _nds32_vector_34: -diff --git a/libgcc/config/nds32/isr-library/vec_vid35.S b/libgcc/config/nds32/isr-library/vec_vid35.S -index 65dd081d7b3..8862137b38f 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid35.S -+++ b/libgcc/config/nds32/isr-library/vec_vid35.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.35, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_35 - .type _nds32_vector_35, @function - _nds32_vector_35: -diff --git a/libgcc/config/nds32/isr-library/vec_vid36.S b/libgcc/config/nds32/isr-library/vec_vid36.S -index fa47b8e879c..dbcbbf4298f 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid36.S -+++ b/libgcc/config/nds32/isr-library/vec_vid36.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.36, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_36 - .type _nds32_vector_36, @function - _nds32_vector_36: -diff --git a/libgcc/config/nds32/isr-library/vec_vid37.S b/libgcc/config/nds32/isr-library/vec_vid37.S -index ece845633f2..392f18bfe05 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid37.S -+++ b/libgcc/config/nds32/isr-library/vec_vid37.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.37, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_37 - .type _nds32_vector_37, @function - _nds32_vector_37: -diff --git a/libgcc/config/nds32/isr-library/vec_vid38.S b/libgcc/config/nds32/isr-library/vec_vid38.S -index c4a12f574ef..efe6619b3a7 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid38.S -+++ b/libgcc/config/nds32/isr-library/vec_vid38.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.38, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_38 - .type _nds32_vector_38, @function - _nds32_vector_38: -diff --git a/libgcc/config/nds32/isr-library/vec_vid39.S b/libgcc/config/nds32/isr-library/vec_vid39.S -index b3e56ed7077..238c43aec88 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid39.S -+++ b/libgcc/config/nds32/isr-library/vec_vid39.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.39, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_39 - .type _nds32_vector_39, @function - _nds32_vector_39: -diff --git a/libgcc/config/nds32/isr-library/vec_vid40.S b/libgcc/config/nds32/isr-library/vec_vid40.S -index 01364aa4909..cf3eaa21fa6 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid40.S -+++ b/libgcc/config/nds32/isr-library/vec_vid40.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.40, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_40 - .type _nds32_vector_40, @function - _nds32_vector_40: -diff --git a/libgcc/config/nds32/isr-library/vec_vid41.S b/libgcc/config/nds32/isr-library/vec_vid41.S -index f20beec98c0..27b7aac3dbb 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid41.S -+++ b/libgcc/config/nds32/isr-library/vec_vid41.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.41, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_41 - .type _nds32_vector_41, @function - _nds32_vector_41: -diff --git a/libgcc/config/nds32/isr-library/vec_vid42.S b/libgcc/config/nds32/isr-library/vec_vid42.S -index 6c29f1ff5a4..bfeed46e263 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid42.S -+++ b/libgcc/config/nds32/isr-library/vec_vid42.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.42, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_42 - .type _nds32_vector_42, @function - _nds32_vector_42: -diff --git a/libgcc/config/nds32/isr-library/vec_vid43.S b/libgcc/config/nds32/isr-library/vec_vid43.S -index 8767f998513..54640c9b4f7 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid43.S -+++ b/libgcc/config/nds32/isr-library/vec_vid43.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.43, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_43 - .type _nds32_vector_43, @function - _nds32_vector_43: -diff --git a/libgcc/config/nds32/isr-library/vec_vid44.S b/libgcc/config/nds32/isr-library/vec_vid44.S -index 8b6f53db5a8..f617243c473 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid44.S -+++ b/libgcc/config/nds32/isr-library/vec_vid44.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.44, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_44 - .type _nds32_vector_44, @function - _nds32_vector_44: -diff --git a/libgcc/config/nds32/isr-library/vec_vid45.S b/libgcc/config/nds32/isr-library/vec_vid45.S -index 52e344b0de4..2cfeb785b1b 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid45.S -+++ b/libgcc/config/nds32/isr-library/vec_vid45.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.45, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_45 - .type _nds32_vector_45, @function - _nds32_vector_45: -diff --git a/libgcc/config/nds32/isr-library/vec_vid46.S b/libgcc/config/nds32/isr-library/vec_vid46.S -index f9dc0d11382..45c88477ee9 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid46.S -+++ b/libgcc/config/nds32/isr-library/vec_vid46.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.46, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_46 - .type _nds32_vector_46, @function - _nds32_vector_46: -diff --git a/libgcc/config/nds32/isr-library/vec_vid47.S b/libgcc/config/nds32/isr-library/vec_vid47.S -index 436e7e3a977..25469e456fd 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid47.S -+++ b/libgcc/config/nds32/isr-library/vec_vid47.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.47, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_47 - .type _nds32_vector_47, @function - _nds32_vector_47: -diff --git a/libgcc/config/nds32/isr-library/vec_vid48.S b/libgcc/config/nds32/isr-library/vec_vid48.S -index 219dfd49b19..5a001194edd 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid48.S -+++ b/libgcc/config/nds32/isr-library/vec_vid48.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.48, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_48 - .type _nds32_vector_48, @function - _nds32_vector_48: -diff --git a/libgcc/config/nds32/isr-library/vec_vid49.S b/libgcc/config/nds32/isr-library/vec_vid49.S -index e3ba7537f08..dfe11f14017 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid49.S -+++ b/libgcc/config/nds32/isr-library/vec_vid49.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.49, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_49 - .type _nds32_vector_49, @function - _nds32_vector_49: -diff --git a/libgcc/config/nds32/isr-library/vec_vid50.S b/libgcc/config/nds32/isr-library/vec_vid50.S -index b0b3fc2b73f..0dacd26315d 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid50.S -+++ b/libgcc/config/nds32/isr-library/vec_vid50.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.50, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_50 - .type _nds32_vector_50, @function - _nds32_vector_50: -diff --git a/libgcc/config/nds32/isr-library/vec_vid51.S b/libgcc/config/nds32/isr-library/vec_vid51.S -index bf3011d5ccb..5ab28ef7238 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid51.S -+++ b/libgcc/config/nds32/isr-library/vec_vid51.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.51, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_51 - .type _nds32_vector_51, @function - _nds32_vector_51: -diff --git a/libgcc/config/nds32/isr-library/vec_vid52.S b/libgcc/config/nds32/isr-library/vec_vid52.S -index eaf5f14ef25..ed00f4000d1 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid52.S -+++ b/libgcc/config/nds32/isr-library/vec_vid52.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.52, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_52 - .type _nds32_vector_52, @function - _nds32_vector_52: -diff --git a/libgcc/config/nds32/isr-library/vec_vid53.S b/libgcc/config/nds32/isr-library/vec_vid53.S -index 3f92e56d665..564cadbf1d4 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid53.S -+++ b/libgcc/config/nds32/isr-library/vec_vid53.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.53, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_53 - .type _nds32_vector_53, @function - _nds32_vector_53: -diff --git a/libgcc/config/nds32/isr-library/vec_vid54.S b/libgcc/config/nds32/isr-library/vec_vid54.S -index f22793fe3f2..377c524361e 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid54.S -+++ b/libgcc/config/nds32/isr-library/vec_vid54.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.54, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_54 - .type _nds32_vector_54, @function - _nds32_vector_54: -diff --git a/libgcc/config/nds32/isr-library/vec_vid55.S b/libgcc/config/nds32/isr-library/vec_vid55.S -index 1017130a9da..497252ada22 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid55.S -+++ b/libgcc/config/nds32/isr-library/vec_vid55.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.55, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_55 - .type _nds32_vector_55, @function - _nds32_vector_55: -diff --git a/libgcc/config/nds32/isr-library/vec_vid56.S b/libgcc/config/nds32/isr-library/vec_vid56.S -index a0923e9e791..b62534b9cbc 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid56.S -+++ b/libgcc/config/nds32/isr-library/vec_vid56.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.56, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_56 - .type _nds32_vector_56, @function - _nds32_vector_56: -diff --git a/libgcc/config/nds32/isr-library/vec_vid57.S b/libgcc/config/nds32/isr-library/vec_vid57.S -index e711b890ef4..b1bb42d9c03 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid57.S -+++ b/libgcc/config/nds32/isr-library/vec_vid57.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.57, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_57 - .type _nds32_vector_57, @function - _nds32_vector_57: -diff --git a/libgcc/config/nds32/isr-library/vec_vid58.S b/libgcc/config/nds32/isr-library/vec_vid58.S -index f8d90643af1..14595a527a9 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid58.S -+++ b/libgcc/config/nds32/isr-library/vec_vid58.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.58, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_58 - .type _nds32_vector_58, @function - _nds32_vector_58: -diff --git a/libgcc/config/nds32/isr-library/vec_vid59.S b/libgcc/config/nds32/isr-library/vec_vid59.S -index 58fb6e626e3..e5be1772425 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid59.S -+++ b/libgcc/config/nds32/isr-library/vec_vid59.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.59, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_59 - .type _nds32_vector_59, @function - _nds32_vector_59: -diff --git a/libgcc/config/nds32/isr-library/vec_vid60.S b/libgcc/config/nds32/isr-library/vec_vid60.S -index 94aa6e0ef7a..f6df9712907 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid60.S -+++ b/libgcc/config/nds32/isr-library/vec_vid60.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.60, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_60 - .type _nds32_vector_60, @function - _nds32_vector_60: -diff --git a/libgcc/config/nds32/isr-library/vec_vid61.S b/libgcc/config/nds32/isr-library/vec_vid61.S -index 869f6c86514..4f97b043154 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid61.S -+++ b/libgcc/config/nds32/isr-library/vec_vid61.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.61, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_61 - .type _nds32_vector_61, @function - _nds32_vector_61: -diff --git a/libgcc/config/nds32/isr-library/vec_vid62.S b/libgcc/config/nds32/isr-library/vec_vid62.S -index acc846c320b..08d1bbb2567 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid62.S -+++ b/libgcc/config/nds32/isr-library/vec_vid62.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.62, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_62 - .type _nds32_vector_62, @function - _nds32_vector_62: -diff --git a/libgcc/config/nds32/isr-library/vec_vid63.S b/libgcc/config/nds32/isr-library/vec_vid63.S -index d0727ecdd08..2b2068c4fb5 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid63.S -+++ b/libgcc/config/nds32/isr-library/vec_vid63.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.63, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_63 - .type _nds32_vector_63, @function - _nds32_vector_63: -diff --git a/libgcc/config/nds32/isr-library/vec_vid64.S b/libgcc/config/nds32/isr-library/vec_vid64.S -index cb1659ad3ee..2c06ea0cc90 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid64.S -+++ b/libgcc/config/nds32/isr-library/vec_vid64.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.64, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_64 - .type _nds32_vector_64, @function - _nds32_vector_64: -diff --git a/libgcc/config/nds32/isr-library/vec_vid65.S b/libgcc/config/nds32/isr-library/vec_vid65.S -index da46481ec02..d2359fd6b2b 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid65.S -+++ b/libgcc/config/nds32/isr-library/vec_vid65.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.65, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_65 - .type _nds32_vector_65, @function - _nds32_vector_65: -diff --git a/libgcc/config/nds32/isr-library/vec_vid66.S b/libgcc/config/nds32/isr-library/vec_vid66.S -index a8c18b804b3..69ccf368f6d 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid66.S -+++ b/libgcc/config/nds32/isr-library/vec_vid66.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.66, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_66 - .type _nds32_vector_66, @function - _nds32_vector_66: -diff --git a/libgcc/config/nds32/isr-library/vec_vid67.S b/libgcc/config/nds32/isr-library/vec_vid67.S -index d2996a375ee..78a68cb89a9 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid67.S -+++ b/libgcc/config/nds32/isr-library/vec_vid67.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.67, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_67 - .type _nds32_vector_67, @function - _nds32_vector_67: -diff --git a/libgcc/config/nds32/isr-library/vec_vid68.S b/libgcc/config/nds32/isr-library/vec_vid68.S -index 0c9de86b1d7..a120ec34377 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid68.S -+++ b/libgcc/config/nds32/isr-library/vec_vid68.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.68, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_68 - .type _nds32_vector_68, @function - _nds32_vector_68: -diff --git a/libgcc/config/nds32/isr-library/vec_vid69.S b/libgcc/config/nds32/isr-library/vec_vid69.S -index 43cf748d442..e2bdd5f0442 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid69.S -+++ b/libgcc/config/nds32/isr-library/vec_vid69.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.69, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_69 - .type _nds32_vector_69, @function - _nds32_vector_69: -diff --git a/libgcc/config/nds32/isr-library/vec_vid70.S b/libgcc/config/nds32/isr-library/vec_vid70.S -index aba3e6aede0..a5ac1f306ff 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid70.S -+++ b/libgcc/config/nds32/isr-library/vec_vid70.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.70, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_70 - .type _nds32_vector_70, @function - _nds32_vector_70: -diff --git a/libgcc/config/nds32/isr-library/vec_vid71.S b/libgcc/config/nds32/isr-library/vec_vid71.S -index be8aaa52534..06ed89c633a 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid71.S -+++ b/libgcc/config/nds32/isr-library/vec_vid71.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.71, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_71 - .type _nds32_vector_71, @function - _nds32_vector_71: -diff --git a/libgcc/config/nds32/isr-library/vec_vid72.S b/libgcc/config/nds32/isr-library/vec_vid72.S -index 041c89517e3..2163201b620 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid72.S -+++ b/libgcc/config/nds32/isr-library/vec_vid72.S -@@ -24,8 +24,15 @@ - . */ - - .section .nds32_vector.72, "ax" -+#if __NDS32_ISR_VECTOR_SIZE_4__ -+ /* The vector size is default 4-byte for v3 architecture. */ -+ .vec_size 4 -+ .align 2 -+#else -+ /* The vector size is default 16-byte for other architectures. */ - .vec_size 16 - .align 4 -+#endif - .weak _nds32_vector_72 - .type _nds32_vector_72, @function - _nds32_vector_72: -diff --git a/libgcc/config/nds32/linux-atomic.c b/libgcc/config/nds32/linux-atomic.c -new file mode 100644 -index 00000000000..6da7be9a653 ---- /dev/null -+++ b/libgcc/config/nds32/linux-atomic.c -@@ -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 -+. */ -+ -+/* 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__and_fetch and __sync_fetch_and_ 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) -diff --git a/libgcc/config/nds32/linux-unwind.h b/libgcc/config/nds32/linux-unwind.h -new file mode 100644 -index 00000000000..00f2b2cfe43 ---- /dev/null -+++ b/libgcc/config/nds32/linux-unwind.h -@@ -0,0 +1,143 @@ -+/* 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 -+ . */ -+ -+#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 -+#include -+#include -+ -+/* Exactly the same layout as the kernel structures, unique names. */ -+ -+/* arch/nds32/kernel/signal.c */ -+struct _rt_sigframe { -+ siginfo_t info; -+ struct ucontext_t uc; -+}; -+ -+#define RT_SIGRETURN 0x8b00f044 -+ -+#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. -+ FIXME: Currently we only handle little endian (EL) case. */ -+ if (pc[0] == RT_SIGRETURN) -+ { -+ /* Using '_sigfame' memory address to locate kernal's sigcontext. -+ The sigcontext structures in arch/nds32/include/asm/sigcontext.h. */ -+ struct _rt_sigframe *rt_; -+ rt_ = context->cfa; -+ sc_ = &rt_->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 -diff --git a/libgcc/config/nds32/sfp-machine.h b/libgcc/config/nds32/sfp-machine.h -index 499bdad7423..bfbdaf9c3bf 100644 ---- a/libgcc/config/nds32/sfp-machine.h -+++ b/libgcc/config/nds32/sfp-machine.h -@@ -76,6 +76,25 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); - R##_c = FP_CLS_NAN; \ - } while (0) - -+#ifdef NDS32_ABI_2FP_PLUS -+#define FP_RND_NEAREST 0x0 -+#define FP_RND_PINF 0x1 -+#define FP_RND_MINF 0x2 -+#define FP_RND_ZERO 0x3 -+#define FP_RND_MASK 0x3 -+ -+#define _FP_DECL_EX \ -+ unsigned long int _fcsr __attribute__ ((unused)) = FP_RND_NEAREST -+ -+#define FP_INIT_ROUNDMODE \ -+ do { \ -+ _fcsr = __builtin_nds32_fmfcsr (); \ -+ } while (0) -+ -+#define FP_ROUNDMODE (_fcsr & FP_RND_MASK) -+ -+#endif -+ - /* Not checked. */ - #define _FP_TININESS_AFTER_ROUNDING 0 - -diff --git a/libgcc/config/nds32/t-nds32-glibc b/libgcc/config/nds32/t-nds32-glibc -new file mode 100644 -index 00000000000..4e229314c34 ---- /dev/null -+++ b/libgcc/config/nds32/t-nds32-glibc -@@ -0,0 +1,34 @@ -+# Rules of glibc library makefile of Andes NDS32 cpu for GNU compiler -+# Copyright (C) 2012-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. -+# -+# You should have received a copy of the GNU General Public License -+# along with GCC; see the file COPYING3. If not see -+# . -+ -+# Compiler flags to use when compiling 'libgcc2.c' -+HOST_LIBGCC2_CFLAGS = -O2 -fPIC -fwrapv -+LIB2ADD += $(srcdir)/config/nds32/linux-atomic.c -+ -+#LIB1ASMSRC = nds32/lib1asmsrc-newlib.S -+#LIB1ASMFUNCS = _divsi3 _modsi3 _udivsi3 _umodsi3 -+ -+# List of functions not to build from libgcc2.c. -+#LIB2FUNCS_EXCLUDE = _clzsi2 -+ -+# List of extra C and assembler files(*.S) to add to static libgcc2. -+#LIB2ADD_ST += $(srcdir)/config/nds32/lib2csrc-newlib/_clzsi2.c -+ -+# ------------------------------------------------------------------------ -diff --git a/libgcc/config/nds32/t-nds32-isr b/libgcc/config/nds32/t-nds32-isr -index 4f86f900395..abfd82b2248 100644 ---- a/libgcc/config/nds32/t-nds32-isr -+++ b/libgcc/config/nds32/t-nds32-isr -@@ -23,11 +23,11 @@ - # Makfile fragment rules for libnds32_isr.a to support ISR attribute extension - ############################################################################### - --# basic flags setting -+# Basic flags setting. - ISR_CFLAGS = $(CFLAGS) -c - --# the object files we would like to create --LIBNDS32_ISR_16B_OBJS = \ -+# The object files we would like to create. -+LIBNDS32_ISR_VEC_OBJS = \ - vec_vid00.o vec_vid01.o vec_vid02.o vec_vid03.o \ - vec_vid04.o vec_vid05.o vec_vid06.o vec_vid07.o \ - vec_vid08.o vec_vid09.o vec_vid10.o vec_vid11.o \ -@@ -46,40 +46,9 @@ LIBNDS32_ISR_16B_OBJS = \ - vec_vid60.o vec_vid61.o vec_vid62.o vec_vid63.o \ - vec_vid64.o vec_vid65.o vec_vid66.o vec_vid67.o \ - vec_vid68.o vec_vid69.o vec_vid70.o vec_vid71.o \ -- vec_vid72.o \ -- excp_isr_ps_nn.o excp_isr_ps_ns.o excp_isr_ps_nr.o \ -- excp_isr_sa_nn.o excp_isr_sa_ns.o excp_isr_sa_nr.o \ -- intr_isr_ps_nn.o intr_isr_ps_ns.o intr_isr_ps_nr.o \ -- intr_isr_sa_nn.o intr_isr_sa_ns.o intr_isr_sa_nr.o \ -- reset.o -- --LIBNDS32_ISR_4B_OBJS = \ -- vec_vid00_4b.o vec_vid01_4b.o vec_vid02_4b.o vec_vid03_4b.o \ -- vec_vid04_4b.o vec_vid05_4b.o vec_vid06_4b.o vec_vid07_4b.o \ -- vec_vid08_4b.o vec_vid09_4b.o vec_vid10_4b.o vec_vid11_4b.o \ -- vec_vid12_4b.o vec_vid13_4b.o vec_vid14_4b.o vec_vid15_4b.o \ -- vec_vid16_4b.o vec_vid17_4b.o vec_vid18_4b.o vec_vid19_4b.o \ -- vec_vid20_4b.o vec_vid21_4b.o vec_vid22_4b.o vec_vid23_4b.o \ -- vec_vid24_4b.o vec_vid25_4b.o vec_vid26_4b.o vec_vid27_4b.o \ -- vec_vid28_4b.o vec_vid29_4b.o vec_vid30_4b.o vec_vid31_4b.o \ -- vec_vid32_4b.o vec_vid33_4b.o vec_vid34_4b.o vec_vid35_4b.o \ -- vec_vid36_4b.o vec_vid37_4b.o vec_vid38_4b.o vec_vid39_4b.o \ -- vec_vid40_4b.o vec_vid41_4b.o vec_vid42_4b.o vec_vid43_4b.o \ -- vec_vid44_4b.o vec_vid45_4b.o vec_vid46_4b.o vec_vid47_4b.o \ -- vec_vid48_4b.o vec_vid49_4b.o vec_vid50_4b.o vec_vid51_4b.o \ -- vec_vid52_4b.o vec_vid53_4b.o vec_vid54_4b.o vec_vid55_4b.o \ -- vec_vid56_4b.o vec_vid57_4b.o vec_vid58_4b.o vec_vid59_4b.o \ -- vec_vid60_4b.o vec_vid61_4b.o vec_vid62_4b.o vec_vid63_4b.o \ -- vec_vid64_4b.o vec_vid65_4b.o vec_vid66_4b.o vec_vid67_4b.o \ -- vec_vid68_4b.o vec_vid69_4b.o vec_vid70_4b.o vec_vid71_4b.o \ -- vec_vid72_4b.o \ -- excp_isr_ps_nn_4b.o excp_isr_ps_ns_4b.o excp_isr_ps_nr_4b.o \ -- excp_isr_sa_nn_4b.o excp_isr_sa_ns_4b.o excp_isr_sa_nr_4b.o \ -- intr_isr_ps_nn_4b.o intr_isr_ps_ns_4b.o intr_isr_ps_nr_4b.o \ -- intr_isr_sa_nn_4b.o intr_isr_sa_ns_4b.o intr_isr_sa_nr_4b.o \ -- reset_4b.o -+ vec_vid72.o - --LIBNDS32_ISR_COMMON_OBJS = \ -+LIBNDS32_ISR_JMP_OBJS = \ - jmptbl_vid00.o jmptbl_vid01.o jmptbl_vid02.o jmptbl_vid03.o \ - jmptbl_vid04.o jmptbl_vid05.o jmptbl_vid06.o jmptbl_vid07.o \ - jmptbl_vid08.o jmptbl_vid09.o jmptbl_vid10.o jmptbl_vid11.o \ -@@ -98,29 +67,32 @@ LIBNDS32_ISR_COMMON_OBJS = \ - jmptbl_vid60.o jmptbl_vid61.o jmptbl_vid62.o jmptbl_vid63.o \ - jmptbl_vid64.o jmptbl_vid65.o jmptbl_vid66.o jmptbl_vid67.o \ - jmptbl_vid68.o jmptbl_vid69.o jmptbl_vid70.o jmptbl_vid71.o \ -- jmptbl_vid72.o \ -+ jmptbl_vid72.o -+ -+LIBNDS32_ISR_COMMON_OBJS = \ -+ excp_isr_ps_nn.o excp_isr_ps_ns.o excp_isr_ps_nr.o \ -+ excp_isr_sa_nn.o excp_isr_sa_ns.o excp_isr_sa_nr.o \ -+ intr_isr_ps_nn.o intr_isr_ps_ns.o intr_isr_ps_nr.o \ -+ intr_isr_sa_nn.o intr_isr_sa_ns.o intr_isr_sa_nr.o \ -+ reset.o \ - nmih.o \ - wrh.o - --LIBNDS32_ISR_COMPLETE_OBJS = $(LIBNDS32_ISR_16B_OBJS) $(LIBNDS32_ISR_4B_OBJS) $(LIBNDS32_ISR_COMMON_OBJS) -+LIBNDS32_ISR_COMPLETE_OBJS = $(LIBNDS32_ISR_VEC_OBJS) $(LIBNDS32_ISR_JMP_OBJS) $(LIBNDS32_ISR_COMMON_OBJS) - - --# Build common objects for ISR library --nmih.o: $(srcdir)/config/nds32/isr-library/nmih.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/nmih.S -o nmih.o - --wrh.o: $(srcdir)/config/nds32/isr-library/wrh.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/wrh.S -o wrh.o -- --jmptbl_vid%.o: $(srcdir)/config/nds32/isr-library/jmptbl_vid%.S -+# Build vector vid objects for ISR library. -+vec_vid%.o: $(srcdir)/config/nds32/isr-library/vec_vid%.S - $(GCC_FOR_TARGET) $(ISR_CFLAGS) $< -o $@ - - -- --# Build 16b version objects for ISR library. (no "_4b" postfix string) --vec_vid%.o: $(srcdir)/config/nds32/isr-library/vec_vid%.S -+# Build jump table objects for ISR library. -+jmptbl_vid%.o: $(srcdir)/config/nds32/isr-library/jmptbl_vid%.S - $(GCC_FOR_TARGET) $(ISR_CFLAGS) $< -o $@ - -+ -+# Build commen objects for ISR library. - excp_isr_ps_nn.o: $(srcdir)/config/nds32/isr-library/excp_isr.S - $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/excp_isr.S -o excp_isr_ps_nn.o - -@@ -160,48 +132,12 @@ intr_isr_sa_nr.o: $(srcdir)/config/nds32/isr-library/intr_isr.S - reset.o: $(srcdir)/config/nds32/isr-library/reset.S - $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/reset.S -o reset.o - --# Build 4b version objects for ISR library. --vec_vid%_4b.o: $(srcdir)/config/nds32/isr-library/vec_vid%_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $< -o $@ -- --excp_isr_ps_nn_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_ps_nn_4b.o -- --excp_isr_ps_ns_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_ps_ns_4b.o -- --excp_isr_ps_nr_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_ps_nr_4b.o -- --excp_isr_sa_nn_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_sa_nn_4b.o -- --excp_isr_sa_ns_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_sa_ns_4b.o -- --excp_isr_sa_nr_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_sa_nr_4b.o -- --intr_isr_ps_nn_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_ps_nn_4b.o -- --intr_isr_ps_ns_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_ps_ns_4b.o -- --intr_isr_ps_nr_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_ps_nr_4b.o -- --intr_isr_sa_nn_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_sa_nn_4b.o -- --intr_isr_sa_ns_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_sa_ns_4b.o -+nmih.o: $(srcdir)/config/nds32/isr-library/nmih.S -+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/nmih.S -o nmih.o - --intr_isr_sa_nr_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_sa_nr_4b.o -+wrh.o: $(srcdir)/config/nds32/isr-library/wrh.S -+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/wrh.S -o wrh.o - --reset_4b.o: $(srcdir)/config/nds32/isr-library/reset_4b.S -- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/reset_4b.S -o reset_4b.o - - - # The rule to create libnds32_isr.a file -diff --git a/libgcc/config/nds32/t-nds32-newlib b/libgcc/config/nds32/t-nds32-newlib -index 1ea2bc32163..a59646fcff5 100644 ---- a/libgcc/config/nds32/t-nds32-newlib -+++ b/libgcc/config/nds32/t-nds32-newlib -@@ -19,7 +19,7 @@ - # . - - # Compiler flags to use when compiling 'libgcc2.c' --HOST_LIBGCC2_CFLAGS = -O2 -+HOST_LIBGCC2_CFLAGS = -O2 -fwrapv - - - #LIB1ASMSRC = nds32/lib1asmsrc-newlib.S diff --git a/util/crossgcc/patches/gcc-8.2.0_ada-musl_workaround.patch b/util/crossgcc/patches/gcc-8.2.0_ada-musl_workaround.patch new file mode 100644 index 0000000000..1f504a4b5e --- /dev/null +++ b/util/crossgcc/patches/gcc-8.2.0_ada-musl_workaround.patch @@ -0,0 +1,120 @@ +diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c +index 3b0aea92c05..998f2c66289 100644 +--- a/gcc/ada/adaint.c ++++ b/gcc/ada/adaint.c +@@ -107,6 +107,15 @@ + #define xmalloc(S) malloc (S) + #define xrealloc(V,S) realloc (V,S) + #else ++#if !defined(__ANDROID__) && defined(__linux__) ++#ifdef __cplusplus ++extern "C" { ++#endif ++#include ++#ifdef __cplusplus ++} ++#endif ++#endif + #include "config.h" + #include "system.h" + #include "version.h" +@@ -3265,7 +3274,7 @@ __gnat_lwp_self (void) + + /* Dynamic cpu sets */ + +-cpu_set_t * ++void * + __gnat_cpu_alloc (size_t count) + { + return CPU_ALLOC (count); +@@ -3278,33 +3287,33 @@ __gnat_cpu_alloc_size (size_t count) + } + + void +-__gnat_cpu_free (cpu_set_t *set) ++__gnat_cpu_free (void *set) + { +- CPU_FREE (set); ++ CPU_FREE ((cpu_set_t *)set); + } + + void +-__gnat_cpu_zero (size_t count, cpu_set_t *set) ++__gnat_cpu_zero (size_t count, void *set) + { + CPU_ZERO_S (count, set); + } + + void +-__gnat_cpu_set (int cpu, size_t count, cpu_set_t *set) ++__gnat_cpu_set (int cpu, size_t count, void *set) + { + /* Ada handles CPU numbers starting from 1, while C identifies the first + CPU by a 0, so we need to adjust. */ +- CPU_SET_S (cpu - 1, count, set); ++ CPU_SET_S (cpu - 1, count, (cpu_set_t *)set); + } + + #else /* !CPU_ALLOC */ + + /* Static cpu sets */ + +-cpu_set_t * ++void * + __gnat_cpu_alloc (size_t count ATTRIBUTE_UNUSED) + { +- return (cpu_set_t *) xmalloc (sizeof (cpu_set_t)); ++ return xmalloc (sizeof (cpu_set_t)); + } + + size_t +@@ -3314,23 +3323,23 @@ __gnat_cpu_alloc_size (size_t count ATTRIBUTE_UNUSED) + } + + void +-__gnat_cpu_free (cpu_set_t *set) ++__gnat_cpu_free (void *set) + { + free (set); + } + + void +-__gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED, cpu_set_t *set) ++__gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED, void *set) + { + CPU_ZERO (set); + } + + void +-__gnat_cpu_set (int cpu, size_t count ATTRIBUTE_UNUSED, cpu_set_t *set) ++__gnat_cpu_set (int cpu, size_t count ATTRIBUTE_UNUSED, void *set) + { + /* Ada handles CPU numbers starting from 1, while C identifies the first + CPU by a 0, so we need to adjust. */ +- CPU_SET (cpu - 1, set); ++ CPU_SET (cpu - 1, (cpu_set_t *)set); + } + #endif /* !CPU_ALLOC */ + #endif /* __linux__ */ +diff --git a/gcc/ada/adaint.h b/gcc/ada/adaint.h +index 0d12f7e9020..7b3def03fb0 100644 +--- a/gcc/ada/adaint.h ++++ b/gcc/ada/adaint.h +@@ -316,13 +316,11 @@ extern void *__gnat_lwp_self (void); + + /* Routines for interface to required CPU set primitives */ + +-#include +- +-extern cpu_set_t *__gnat_cpu_alloc (size_t); ++extern void *__gnat_cpu_alloc (size_t); + extern size_t __gnat_cpu_alloc_size (size_t); +-extern void __gnat_cpu_free (cpu_set_t *); +-extern void __gnat_cpu_zero (size_t, cpu_set_t *); +-extern void __gnat_cpu_set (int, size_t, cpu_set_t *); ++extern void __gnat_cpu_free (void *); ++extern void __gnat_cpu_zero (size_t, void *); ++extern void __gnat_cpu_set (int, size_t, void *); + #endif + + #if defined (_WIN32) diff --git a/util/crossgcc/patches/gcc-8.2.0_gnat.patch b/util/crossgcc/patches/gcc-8.2.0_gnat.patch new file mode 100644 index 0000000000..2d7cecee24 --- /dev/null +++ b/util/crossgcc/patches/gcc-8.2.0_gnat.patch @@ -0,0 +1,11 @@ +--- gcc-6.1.0/gcc/ada/gcc-interface/Make-lang.in.bak 2015-08-24 16:23:25.004493665 +0200 ++++ gcc-6.1.0/gcc/ada/gcc-interface/Make-lang.in 2015-08-24 17:53:52.496636113 +0200 +@@ -45,7 +45,7 @@ + + + # Extra flags to pass to recursive makes. +-COMMON_ADAFLAGS= -gnatpg ++COMMON_ADAFLAGS= -gnatpg -gnatwGUR + ifeq ($(TREECHECKING),) + CHECKING_ADAFLAGS= + else diff --git a/util/crossgcc/patches/gcc-8.2.0_libgcc.patch b/util/crossgcc/patches/gcc-8.2.0_libgcc.patch new file mode 100644 index 0000000000..2f75c92b41 --- /dev/null +++ b/util/crossgcc/patches/gcc-8.2.0_libgcc.patch @@ -0,0 +1,60 @@ +This enables building on Mac OS and FreeBSD by adding support to their +variants of the sed utility. + +diff -urN gcc-5.2.0.orig/libgcc/config/t-hardfp gcc-5.2.0/libgcc/config/t-hardfp +--- gcc-5.2.0.orig/libgcc/config/t-hardfp 2015-01-05 04:33:28.000000000 -0800 ++++ gcc-8.1.0/libgcc/config/t-hardfp 2016-04-06 12:04:51.000000000 -0700 +@@ -59,21 +59,52 @@ + + hardfp_func_list := $(filter-out $(hardfp_exclusions),$(hardfp_func_list)) + ++HOST_OS ?= $(shell uname) ++ + # Regexp for matching a floating-point mode. ++ifeq ($(HOST_OS), Darwin) ++hardfp_mode_regexp := $(shell echo $(hardfp_float_modes) | sed 's/ /|/g') ++else ++ifeq ($(HOST_OS), FreeBSD) ++hardfp_mode_regexp := $(shell echo $(hardfp_float_modes) | sed 's/ /|/g') ++else + hardfp_mode_regexp := $(shell echo $(hardfp_float_modes) | sed 's/ /\\|/g') ++endif ++endif + + # Regexp for matching the end of a function name, after the last + # floating-point mode. ++ifeq ($(HOST_OS), Darwin) ++hardfp_suffix_regexp := $(shell echo $(hardfp_int_modes) 2 3 | sed 's/ /|/g') ++else ++ifeq ($(HOST_OS), FreeBSD) ++hardfp_suffix_regexp := $(shell echo $(hardfp_int_modes) 2 3 | sed 's/ /|/g') ++else + hardfp_suffix_regexp := $(shell echo $(hardfp_int_modes) 2 3 | sed 's/ /\\|/g') ++endif ++endif + + # Add -D options to define: + # FUNC: the function name (e.g. __addsf3) + # OP: the function name without the leading __ and with the last + # floating-point mode removed (e.g. add3) + # TYPE: the last floating-point mode (e.g. sf) ++ ++ifeq ($(HOST_OS), Darwin) + hardfp_defines_for = \ + $(shell echo $1 | \ +- sed 's/\(.*\)\($(hardfp_mode_regexp)\)\($(hardfp_suffix_regexp)\|\)$$/-DFUNC=__& -DOP_\1\3 -DTYPE=\2/') ++ sed -E 's/(.*)($(hardfp_mode_regexp))($(hardfp_suffix_regexp)|.*)$$/-DFUNC=__& -DOP_\1\3 -DTYPE=\2/') ++else ++ifeq ($(HOST_OS), FreeBSD) ++hardfp_defines_for = \ ++ $(shell echo $1 | \ ++ sed -r 's/(.*)($(hardfp_mode_regexp))($(hardfp_suffix_regexp)|.*)$$/-DFUNC=__& -DOP_\1\3 -DTYPE=\2/') ++else ++hardfp_defines_for = \ ++ $(shell echo $1 | \ ++ sed 's/\(.*\)\($(hardfp_mode_regexp)\)\($(hardfp_suffix_regexp)\|\)$$/-DFUNC=__& -DOP_\1\3 -DTYPE=\2/') ++endif ++endif + + hardfp-o = $(patsubst %,%$(objext),$(hardfp_func_list)) + $(hardfp-o): %$(objext): $(srcdir)/config/hardfp.c diff --git a/util/crossgcc/patches/gcc-8.2.0_nds32_ite.patch b/util/crossgcc/patches/gcc-8.2.0_nds32_ite.patch new file mode 100644 index 0000000000..2f0780be7f --- /dev/null +++ b/util/crossgcc/patches/gcc-8.2.0_nds32_ite.patch @@ -0,0 +1,21019 @@ +diff -urN gcc-8.2.0.orig/gcc/common/config/nds32/nds32-common.c gcc-8.2.0/gcc/common/config/nds32/nds32-common.c +--- gcc-8.2.0.orig/gcc/common/config/nds32/nds32-common.c 2018-04-06 07:51:33.000000000 +0200 ++++ gcc-8.2.0/gcc/common/config/nds32/nds32-common.c 2019-01-25 15:38:32.817242625 +0100 +@@ -53,6 +53,16 @@ + + return true; + ++ case OPT_misr_secure_: ++ /* Check the valid security level: 0 1 2 3. */ ++ if (value < 0 || value > 3) ++ { ++ error_at (loc, "for the option -misr-secure=X, the valid X " ++ "must be: 0, 1, 2, or 3"); ++ return false; ++ } ++ return true; ++ + case OPT_mcache_block_size_: + /* Check valid value: 4 8 16 32 64 128 256 512. */ + if (exact_log2 (value) < 2 || exact_log2 (value) > 9) +@@ -74,12 +84,19 @@ + /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ + static const struct default_options nds32_option_optimization_table[] = + { ++#if TARGET_LINUX_ABI == 0 ++ /* Disable -fdelete-null-pointer-checks by default in ELF toolchain. */ ++ { OPT_LEVELS_ALL, OPT_fdelete_null_pointer_checks, ++ NULL, 0 }, ++#endif + /* Enable -fsched-pressure by default at -O1 and above. */ + { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, + /* Enable -fomit-frame-pointer by default at all optimization levels. */ + { OPT_LEVELS_ALL, OPT_fomit_frame_pointer, NULL, 1 }, + /* Enable -mrelax-hint by default at all optimization levels. */ + { OPT_LEVELS_ALL, OPT_mrelax_hint, NULL, 1 }, ++ /* Enalbe -malways-align by default at -O1 and above, but not -Os or -Og. */ ++ { OPT_LEVELS_1_PLUS_SPEED_ONLY, OPT_malways_align, NULL, 1 }, + /* Enable -mv3push by default at -Os, but it is useless under V2 ISA. */ + { OPT_LEVELS_SIZE, OPT_mv3push, NULL, 1 }, + +@@ -87,6 +104,19 @@ + }; + + /* ------------------------------------------------------------------------ */ ++ ++/* 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. */ + +@@ -103,6 +133,7 @@ + TARGET_EXT_PERF : Generate performance extention instrcution. + TARGET_EXT_PERF2 : Generate performance extention version 2 instrcution. + TARGET_EXT_STRING : Generate string extention instrcution. ++ TARGET_HW_ABS : Generate hardware abs instruction. + TARGET_CMOV : Generate conditional move instruction. */ + #undef TARGET_DEFAULT_TARGET_FLAGS + #define TARGET_DEFAULT_TARGET_FLAGS \ +@@ -113,6 +144,7 @@ + | MASK_EXT_PERF \ + | MASK_EXT_PERF2 \ + | MASK_EXT_STRING \ ++ | MASK_HW_ABS \ + | MASK_CMOV) + + #undef TARGET_HANDLE_OPTION +@@ -125,7 +157,7 @@ + /* Defining the Output Assembler Language. */ + + #undef TARGET_EXCEPT_UNWIND_INFO +-#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info ++#define TARGET_EXCEPT_UNWIND_INFO nds32_except_unwind_info + + /* ------------------------------------------------------------------------ */ + +diff -urN gcc-8.2.0.orig/gcc/config/nds32/constants.md gcc-8.2.0/gcc/config/nds32/constants.md +--- gcc-8.2.0.orig/gcc/config/nds32/constants.md 2018-04-22 09:46:39.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/constants.md 2019-01-25 15:38:32.821242637 +0100 +@@ -23,6 +23,7 @@ + (define_constants + [(R8_REGNUM 8) + (TA_REGNUM 15) ++ (TP_REGNUM 25) + (FP_REGNUM 28) + (GP_REGNUM 29) + (LP_REGNUM 30) +@@ -49,6 +50,16 @@ + UNSPEC_FFB + UNSPEC_FFMISM + UNSPEC_FLMISM ++ UNSPEC_KDMBB ++ UNSPEC_KDMBT ++ UNSPEC_KDMTB ++ UNSPEC_KDMTT ++ UNSPEC_KHMBB ++ UNSPEC_KHMBT ++ UNSPEC_KHMTB ++ UNSPEC_KHMTT ++ UNSPEC_KSLRAW ++ UNSPEC_KSLRAWU + UNSPEC_SVA + UNSPEC_SVS + UNSPEC_WSBH +@@ -62,6 +73,29 @@ + UNSPEC_UASTORE_HW + UNSPEC_UASTORE_W + UNSPEC_UASTORE_DW ++ UNSPEC_GOTINIT ++ UNSPEC_GOT ++ UNSPEC_GOTOFF ++ UNSPEC_PLT ++ UNSPEC_TLSGD ++ UNSPEC_TLSLD ++ UNSPEC_TLSIE ++ UNSPEC_TLSLE ++ UNSPEC_ROUND ++ UNSPEC_VEC_COMPARE ++ UNSPEC_KHM ++ UNSPEC_KHMX ++ UNSPEC_CLIP_OV ++ UNSPEC_CLIPS_OV ++ UNSPEC_BITREV ++ UNSPEC_KABS ++ UNSPEC_LOOP_END ++ UNSPEC_TLS_DESC ++ UNSPEC_TLS_IE ++ UNSPEC_ADD32 ++ UNSPEC_ICT ++ UNSPEC_KADDH ++ UNSPEC_KSUBH + ]) + + ;; The unspec_volatile operation index. +@@ -135,10 +169,14 @@ + UNSPEC_VOLATILE_SET_TRIG_EDGE + UNSPEC_VOLATILE_GET_TRIG_TYPE + UNSPEC_VOLATILE_RELAX_GROUP ++ UNSPEC_VOLATILE_OMIT_FP_BEGIN ++ UNSPEC_VOLATILE_OMIT_FP_END + UNSPEC_VOLATILE_POP25_RETURN + UNSPEC_VOLATILE_UNALIGNED_FEATURE + UNSPEC_VOLATILE_ENABLE_UNALIGNED + UNSPEC_VOLATILE_DISABLE_UNALIGNED ++ UNSPEC_VOLATILE_RDOV ++ UNSPEC_VOLATILE_CLROV + ]) + + ;; ------------------------------------------------------------------------ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/constraints.md gcc-8.2.0/gcc/config/nds32/constraints.md +--- gcc-8.2.0.orig/gcc/config/nds32/constraints.md 2018-04-06 07:51:33.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/constraints.md 2019-01-25 15:38:32.821242637 +0100 +@@ -127,6 +127,11 @@ + (and (match_code "const_int") + (match_test "IN_RANGE (ival, -31, 0)"))) + ++(define_constraint "Iu06" ++ "Unsigned immediate 6-bit value" ++ (and (match_code "const_int") ++ (match_test "ival < (1 << 6) && ival >= 0"))) ++ + ;; Ip05 is special and dedicated for v3 movpi45 instruction. + ;; movpi45 has imm5u field but the range is 16 ~ 47. + (define_constraint "Ip05" +@@ -136,10 +141,10 @@ + && ival >= (0 + 16) + && (TARGET_ISA_V3 || TARGET_ISA_V3M)"))) + +-(define_constraint "Iu06" ++(define_constraint "IU06" + "Unsigned immediate 6-bit value constraint for addri36.sp instruction" + (and (match_code "const_int") +- (match_test "ival < (1 << 6) ++ (match_test "ival < (1 << 8) + && ival >= 0 + && (ival % 4 == 0) + && (TARGET_ISA_V3 || TARGET_ISA_V3M)"))) +@@ -302,6 +307,25 @@ + (match_test "(TARGET_ISA_V3 || TARGET_ISA_V3M) + && (IN_RANGE (exact_log2 (ival + 1), 1, 8))"))) + ++(define_constraint "CVp5" ++ "Unsigned immediate 5-bit value for movpi45 instruction with range 16-47" ++ (and (match_code "const_vector") ++ (match_test "nds32_valid_CVp5_p (op)"))) ++ ++(define_constraint "CVs5" ++ "Signed immediate 5-bit value" ++ (and (match_code "const_vector") ++ (match_test "nds32_valid_CVs5_p (op)"))) ++ ++(define_constraint "CVs2" ++ "Signed immediate 20-bit value" ++ (and (match_code "const_vector") ++ (match_test "nds32_valid_CVs2_p (op)"))) ++ ++(define_constraint "CVhi" ++ "The immediate value that can be simply set high 20-bit" ++ (and (match_code "const_vector") ++ (match_test "nds32_valid_CVhi_p (op)"))) + + (define_memory_constraint "U33" + "Memory constraint for 333 format" +@@ -349,4 +373,9 @@ + (match_test "(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) + && nds32_float_mem_operand_p (op)"))) + ++(define_constraint "S" ++ "@internal ++ A constant call address." ++ (match_operand 0 "nds32_symbolic_operand")) ++ + ;; ------------------------------------------------------------------------ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/elf.h gcc-8.2.0/gcc/config/nds32/elf.h +--- gcc-8.2.0.orig/gcc/config/nds32/elf.h 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/elf.h 2019-01-25 15:38:32.821242637 +0100 +@@ -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 ++ . */ ++ ++ ++/* ------------------------------------------------------------------------ */ ++ ++#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}" +diff -urN gcc-8.2.0.orig/gcc/config/nds32/iterators.md gcc-8.2.0/gcc/config/nds32/iterators.md +--- gcc-8.2.0.orig/gcc/config/nds32/iterators.md 2018-04-06 07:51:33.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/iterators.md 2019-01-25 15:38:32.821242637 +0100 +@@ -68,6 +68,28 @@ + ;; shifts + (define_code_iterator shift_rotate [ashift ashiftrt lshiftrt rotatert]) + ++(define_code_iterator shifts [ashift ashiftrt lshiftrt]) ++ ++(define_code_iterator shiftrt [ashiftrt lshiftrt]) ++ ++(define_code_iterator sat_plus [ss_plus us_plus]) ++ ++(define_code_iterator all_plus [plus ss_plus us_plus]) ++ ++(define_code_iterator sat_minus [ss_minus us_minus]) ++ ++(define_code_iterator all_minus [minus ss_minus us_minus]) ++ ++(define_code_iterator plus_minus [plus minus]) ++ ++(define_code_iterator extend [sign_extend zero_extend]) ++ ++(define_code_iterator sumax [smax umax]) ++ ++(define_code_iterator sumin [smin umin]) ++ ++(define_code_iterator sumin_max [smax umax smin umin]) ++ + ;;---------------------------------------------------------------------------- + ;; Code attributes. + ;;---------------------------------------------------------------------------- +@@ -76,5 +98,23 @@ + (define_code_attr shift + [(ashift "ashl") (ashiftrt "ashr") (lshiftrt "lshr") (rotatert "rotr")]) + ++(define_code_attr su ++ [(ashiftrt "") (lshiftrt "u") (sign_extend "s") (zero_extend "u")]) ++ ++(define_code_attr zs ++ [(sign_extend "s") (zero_extend "z")]) ++ ++(define_code_attr uk ++ [(plus "") (ss_plus "k") (us_plus "uk") ++ (minus "") (ss_minus "k") (us_minus "uk")]) ++ ++(define_code_attr opcode ++ [(plus "add") (minus "sub") (smax "smax") (umax "umax") (smin "smin") (umin "umin")]) ++ ++(define_code_attr add_rsub ++ [(plus "a") (minus "rs")]) ++ ++(define_code_attr add_sub ++ [(plus "a") (minus "s")]) + + ;;---------------------------------------------------------------------------- +diff -urN gcc-8.2.0.orig/gcc/config/nds32/linux.h gcc-8.2.0/gcc/config/nds32/linux.h +--- gcc-8.2.0.orig/gcc/config/nds32/linux.h 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/linux.h 2019-01-25 15:38:32.821242637 +0100 +@@ -0,0 +1,86 @@ ++/* 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 ++ . */ ++ ++ ++/* ------------------------------------------------------------------------ */ ++ ++#define TARGET_LINUX_ABI 1 ++ ++#undef SIZE_TYPE ++#define SIZE_TYPE "unsigned int" ++ ++#undef PTRDIFF_TYPE ++#define PTRDIFF_TYPE "int" ++ ++#define TARGET_OS_CPP_BUILTINS() \ ++ do \ ++ { \ ++ GNU_USER_TARGET_OS_CPP_BUILTINS(); \ ++ } \ ++ while (0) ++ ++#ifdef TARGET_BIG_ENDIAN_DEFAULT ++#define LD_SO_ENDIAN_SPEC "%{mlittle-endian:le}%{!mlittle-endian:be}" ++#else ++#define LD_SO_ENDIAN_SPEC "%{mbig-endian:be}%{!mbig-endian:le}" ++#endif ++ ++/* Record arch version in TARGET_ARCH_DEFAULT. 0 means soft ABI, ++ 1 means hard ABI and using full floating-point instruction, ++ 2 means hard ABI and only using single-precision floating-point ++ instruction */ ++#if TARGET_ARCH_DEFAULT ++#define LD_SO_ABI_SPEC "%{!mabi=2:f}" ++#else ++#define LD_SO_ABI_SPEC "%{mabi=2fp+:f}" ++#endif ++ ++#define GLIBC_DYNAMIC_LINKER \ ++ "/lib/ld-linux-nds32" LD_SO_ENDIAN_SPEC LD_SO_ABI_SPEC ".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 ++ ++#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 +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32.c gcc-8.2.0/gcc/config/nds32/nds32.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32.c 2018-05-07 03:38:02.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32.c 2019-01-25 15:38:32.833242671 +0100 +@@ -305,6 +305,7 @@ + { "nested", 0, 0, false, false, false, false, NULL, NULL }, + { "not_nested", 0, 0, false, false, false, false, NULL, NULL }, + { "nested_ready", 0, 0, false, false, false, false, NULL, NULL }, ++ { "critical", 0, 0, false, false, false, false, NULL, NULL }, + + /* The attributes describing isr register save scheme. */ + { "save_all", 0, 0, false, false, false, false, NULL, NULL }, +@@ -314,9 +315,19 @@ + { "nmi", 1, 1, false, false, false, false, NULL, NULL }, + { "warm", 1, 1, false, false, false, false, NULL, NULL }, + ++ /* The attributes describing isr security level. */ ++ { "secure", 1, 1, false, false, false, false, NULL, NULL }, ++ + /* The attribute telling no prologue/epilogue. */ + { "naked", 0, 0, false, false, false, false, NULL, NULL }, + ++ /* The attribute is used to tell this function to be ROM patch. */ ++ { "indirect_call",0, 0, false, false, false, false, NULL, NULL }, ++ ++ /* FOR BACKWARD COMPATIBILITY, ++ this attribute also tells no prologue/epilogue. */ ++ { "no_prologue", 0, 0, false, false, false, false, NULL, NULL }, ++ + /* The last attribute spec is set to be NULL. */ + { NULL, 0, 0, false, false, false, false, NULL, NULL } + }; +@@ -345,6 +356,10 @@ + /* Initially this function is not under strictly aligned situation. */ + machine->strict_aligned_p = 0; + ++ /* Initially this function has no naked and no_prologue attributes. */ ++ machine->attr_naked_p = 0; ++ machine->attr_no_prologue_p = 0; ++ + return machine; + } + +@@ -362,6 +377,15 @@ + needs prologue/epilogue. */ + cfun->machine->naked_p = 0; + ++ /* We need to mark whether this function has naked and no_prologue ++ attribute so that we can distinguish the difference if users applies ++ -mret-in-naked-func option. */ ++ cfun->machine->attr_naked_p ++ = lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) ++ ? 1 : 0; ++ cfun->machine->attr_no_prologue_p ++ = lookup_attribute ("no_prologue", DECL_ATTRIBUTES (current_function_decl)) ++ ? 1 : 0; + + /* If __builtin_eh_return is used, we better have frame pointer needed + so that we can easily locate the stack slot of return address. */ +@@ -432,7 +456,8 @@ + + /* If $gp value is required to be saved on stack, it needs 4 bytes space. + Check whether we are using PIC code genration. */ +- cfun->machine->gp_size = (flag_pic) ? 4 : 0; ++ cfun->machine->gp_size = ++ (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) ? 4 : 0; + + /* If $lp value is required to be saved on stack, it needs 4 bytes space. + Check whether $lp is ever live. */ +@@ -497,7 +522,7 @@ + } + + /* Check if this function can omit prologue/epilogue code fragment. +- If there is 'naked' attribute in this function, ++ If there is 'no_prologue'/'naked'/'secure' attribute in this function, + we can set 'naked_p' flag to indicate that + we do not have to generate prologue/epilogue. + Or, if all the following conditions succeed, +@@ -510,14 +535,17 @@ + is no outgoing size. + condition 3: There is no local_size, which means + we do not need to adjust $sp. */ +- if (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) ++ if (lookup_attribute ("no_prologue", DECL_ATTRIBUTES (current_function_decl)) ++ || lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) ++ || lookup_attribute ("secure", DECL_ATTRIBUTES (current_function_decl)) + || (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM + && cfun->machine->callee_saved_last_gpr_regno == SP_REGNUM + && cfun->machine->callee_saved_first_fpr_regno == SP_REGNUM + && cfun->machine->callee_saved_last_fpr_regno == SP_REGNUM + && !df_regs_ever_live_p (FP_REGNUM) + && !df_regs_ever_live_p (LP_REGNUM) +- && cfun->machine->local_size == 0)) ++ && cfun->machine->local_size == 0 ++ && !flag_pic)) + { + /* Set this function 'naked_p' and other functions can check this flag. + Note that in nds32 port, the 'naked_p = 1' JUST means there is no +@@ -1259,6 +1287,32 @@ + REG_NOTES (parallel_insn) = dwarf; + } + ++static void ++nds32_emit_load_gp (void) ++{ ++ rtx got_symbol, pat; ++ ++ /* Initial GLOBAL OFFSET TABLE don't do the scheduling. */ ++ emit_insn (gen_blockage ()); ++ ++ got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); ++ /* sethi $gp, _GLOBAL_OFFSET_TABLE_ -8 */ ++ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, got_symbol), UNSPEC_GOTINIT); ++ pat = gen_rtx_CONST (SImode, gen_rtx_PLUS (Pmode, pat, GEN_INT (-8))); ++ emit_insn (gen_sethi (pic_offset_table_rtx,pat)); ++ ++ /* ori $gp, $gp, _GLOBAL_OFFSET_TABLE_ -4 */ ++ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, got_symbol), UNSPEC_GOTINIT); ++ pat = gen_rtx_CONST (SImode, gen_rtx_PLUS (Pmode, pat, GEN_INT (-4))); ++ emit_insn (gen_lo_sum (pic_offset_table_rtx, pic_offset_table_rtx, pat)); ++ ++ /* add5.pc $gp */ ++ emit_insn (gen_add_pc (pic_offset_table_rtx, pic_offset_table_rtx)); ++ ++ /* Initial GLOBAL OFFSET TABLE don't do the scheduling. */ ++ emit_insn (gen_blockage ()); ++} ++ + /* Function that may creates more instructions + for large value on adjusting stack pointer. + +@@ -1342,17 +1396,25 @@ + } + + /* Return true if FUNC is a naked function. */ +-static bool ++bool + nds32_naked_function_p (tree func) + { +- tree t; ++ /* FOR BACKWARD COMPATIBILITY, ++ we need to support 'no_prologue' attribute as well. */ ++ tree t_naked; ++ tree t_no_prologue; + + if (TREE_CODE (func) != FUNCTION_DECL) + abort (); + +- t = lookup_attribute ("naked", DECL_ATTRIBUTES (func)); ++ /* We have to use lookup_attribute() to check attributes. ++ Because attr_naked_p and attr_no_prologue_p are set in ++ nds32_compute_stack_frame() and the function has not been ++ invoked yet. */ ++ t_naked = lookup_attribute ("naked", DECL_ATTRIBUTES (func)); ++ t_no_prologue = lookup_attribute ("no_prologue", DECL_ATTRIBUTES (func)); + +- return (t != NULL_TREE); ++ return ((t_naked != NULL_TREE) || (t_no_prologue != NULL_TREE)); + } + + /* Function that determine whether a load postincrement is a good thing to use +@@ -1570,6 +1632,11 @@ + nds32_register_passes (void) + { + nds32_register_pass ( ++ make_pass_nds32_fp_as_gp, ++ PASS_POS_INSERT_BEFORE, ++ "ira"); ++ ++ nds32_register_pass ( + make_pass_nds32_relax_opt, + PASS_POS_INSERT_AFTER, + "mach"); +@@ -1636,6 +1703,9 @@ + { + int regno; + ++ if (TARGET_LINUX_ABI) ++ fixed_regs[TP_REGNUM] = 1; ++ + if (TARGET_HARD_FLOAT) + { + for (regno = NDS32_FIRST_FPR_REGNUM; +@@ -1987,6 +2057,16 @@ + : PARM_BOUNDARY); + } + ++bool ++nds32_vector_mode_supported_p (machine_mode mode) ++{ ++ if (mode == V4QImode ++ || mode == V2HImode) ++ return NDS32_EXT_DSP_P (); ++ ++ return false; ++} ++ + /* -- How Scalar Function Values Are Returned. */ + + static rtx +@@ -2124,56 +2204,12 @@ + nds32_asm_function_end_prologue (FILE *file) + { + fprintf (file, "\t! END PROLOGUE\n"); +- +- /* If frame pointer is NOT needed and -mfp-as-gp is issued, +- we can generate special directive: ".omit_fp_begin" +- to guide linker doing fp-as-gp optimization. +- However, for a naked function, which means +- it should not have prologue/epilogue, +- using fp-as-gp still requires saving $fp by push/pop behavior and +- there is no benefit to use fp-as-gp on such small function. +- So we need to make sure this function is NOT naked as well. */ +- if (!frame_pointer_needed +- && !cfun->machine->naked_p +- && cfun->machine->fp_as_gp_p) +- { +- fprintf (file, "\t! ----------------------------------------\n"); +- fprintf (file, "\t! Guide linker to do " +- "link time optimization: fp-as-gp\n"); +- fprintf (file, "\t! We add one more instruction to " +- "initialize $fp near to $gp location.\n"); +- fprintf (file, "\t! If linker fails to use fp-as-gp transformation,\n"); +- fprintf (file, "\t! this extra instruction should be " +- "eliminated at link stage.\n"); +- fprintf (file, "\t.omit_fp_begin\n"); +- fprintf (file, "\tla\t$fp,_FP_BASE_\n"); +- fprintf (file, "\t! ----------------------------------------\n"); +- } + } + + /* Before rtl epilogue has been expanded, this function is used. */ + static void + nds32_asm_function_begin_epilogue (FILE *file) + { +- /* If frame pointer is NOT needed and -mfp-as-gp is issued, +- we can generate special directive: ".omit_fp_end" +- to claim fp-as-gp optimization range. +- However, for a naked function, +- which means it should not have prologue/epilogue, +- using fp-as-gp still requires saving $fp by push/pop behavior and +- there is no benefit to use fp-as-gp on such small function. +- So we need to make sure this function is NOT naked as well. */ +- if (!frame_pointer_needed +- && !cfun->machine->naked_p +- && cfun->machine->fp_as_gp_p) +- { +- fprintf (file, "\t! ----------------------------------------\n"); +- fprintf (file, "\t! Claim the range of fp-as-gp " +- "link time optimization\n"); +- fprintf (file, "\t.omit_fp_end\n"); +- fprintf (file, "\t! ----------------------------------------\n"); +- } +- + fprintf (file, "\t! BEGIN EPILOGUE\n"); + } + +@@ -2200,6 +2236,26 @@ + ? 1 + : 0); + ++ if (flag_pic) ++ { ++ fprintf (file, "\tsmw.adm\t$r31, [$r31], $r31, 4\n"); ++ fprintf (file, "\tsethi\t%s, hi20(_GLOBAL_OFFSET_TABLE_-8)\n", ++ reg_names [PIC_OFFSET_TABLE_REGNUM]); ++ fprintf (file, "\tori\t%s, %s, lo12(_GLOBAL_OFFSET_TABLE_-4)\n", ++ reg_names [PIC_OFFSET_TABLE_REGNUM], ++ reg_names [PIC_OFFSET_TABLE_REGNUM]); ++ ++ if (TARGET_ISA_V3) ++ fprintf (file, "\tadd5.pc\t$gp\n"); ++ else ++ { ++ fprintf (file, "\tmfusr\t$ta, $pc\n"); ++ fprintf (file, "\tadd\t%s, $ta, %s\n", ++ reg_names [PIC_OFFSET_TABLE_REGNUM], ++ reg_names [PIC_OFFSET_TABLE_REGNUM]); ++ } ++ } ++ + if (delta != 0) + { + if (satisfies_constraint_Is15 (GEN_INT (delta))) +@@ -2224,9 +2280,23 @@ + } + } + +- fprintf (file, "\tb\t"); +- assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); +- fprintf (file, "\n"); ++ if (flag_pic) ++ { ++ fprintf (file, "\tla\t$ta, "); ++ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); ++ fprintf (file, "@PLT\n"); ++ fprintf (file, "\t! epilogue\n"); ++ fprintf (file, "\tlwi.bi\t%s, [%s], 4\n", ++ reg_names[PIC_OFFSET_TABLE_REGNUM], ++ reg_names[STACK_POINTER_REGNUM]); ++ fprintf (file, "\tbr\t$ta\n"); ++ } ++ else ++ { ++ fprintf (file, "\tb\t"); ++ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); ++ fprintf (file, "\n"); ++ } + + final_end_function (); + } +@@ -2242,15 +2312,20 @@ + + /* 1. Do not apply sibling call if -mv3push is enabled, + because pop25 instruction also represents return behavior. +- 2. If this function is a variadic function, do not apply sibling call ++ 2. If this function is a isr function, do not apply sibling call ++ because it may perform the behavior that user does not expect. ++ 3. If this function is a variadic function, do not apply sibling call + because the stack layout may be a mess. +- 3. We don't want to apply sibling call optimization for indirect ++ 4. We don't want to apply sibling call optimization for indirect + sibcall because the pop behavior in epilogue may pollute the + content of caller-saved regsiter when the register is used for +- indirect sibcall. */ ++ indirect sibcall. ++ 5. In pic mode, it may use some registers for PLT call. */ + return (!TARGET_V3PUSH ++ && !nds32_isr_function_p (current_function_decl) + && (cfun->machine->va_args_size == 0) +- && decl); ++ && decl ++ && !flag_pic); + } + + /* Determine whether we need to enable warning for function return check. */ +@@ -2566,6 +2641,13 @@ + + case SYMBOL_REF: + /* (mem (symbol_ref A)) => [symbol_ref] */ ++ ++ if (flag_pic || SYMBOL_REF_TLS_MODEL (x)) ++ return false; ++ ++ if (TARGET_ICT_MODEL_LARGE && nds32_indirect_call_referenced_p (x)) ++ return false; ++ + /* If -mcmodel=large, the 'symbol_ref' is not a valid address + during or after LRA/reload phase. */ + if (TARGET_CMODEL_LARGE +@@ -2577,7 +2659,8 @@ + the 'symbol_ref' is not a valid address during or after + LRA/reload phase. */ + if (TARGET_CMODEL_MEDIUM +- && NDS32_SYMBOL_REF_RODATA_P (x) ++ && (NDS32_SYMBOL_REF_RODATA_P (x) ++ || CONSTANT_POOL_ADDRESS_P (x)) + && (reload_completed + || reload_in_progress + || lra_in_progress)) +@@ -2599,6 +2682,10 @@ + { + /* Now we see the [ + const_addr ] pattern, but we need + some further checking. */ ++ ++ if (flag_pic || SYMBOL_REF_TLS_MODEL (op0)) ++ return false; ++ + /* If -mcmodel=large, the 'const_addr' is not a valid address + during or after LRA/reload phase. */ + if (TARGET_CMODEL_LARGE +@@ -2675,17 +2762,202 @@ + + case LO_SUM: + /* (mem (lo_sum (reg) (symbol_ref))) */ +- /* (mem (lo_sum (reg) (const))) */ +- gcc_assert (REG_P (XEXP (x, 0))); +- if (GET_CODE (XEXP (x, 1)) == SYMBOL_REF +- || GET_CODE (XEXP (x, 1)) == CONST) +- return nds32_legitimate_address_p (mode, XEXP (x, 1), strict); +- else ++ /* (mem (lo_sum (reg) (const (plus (symbol_ref) (reg)))) */ ++ /* TLS case: (mem (lo_sum (reg) (const (unspec symbol_ref X)))) */ ++ /* The LO_SUM is a valid address if and only if we would like to ++ generate 32-bit full address memory access with any of following ++ circumstance: ++ 1. -mcmodel=large. ++ 2. -mcmodel=medium and the symbol_ref references to rodata. */ ++ { ++ rtx sym = NULL_RTX; ++ ++ if (flag_pic) ++ return false; ++ ++ if (!REG_P (XEXP (x, 0))) ++ return false; ++ ++ if (GET_CODE (XEXP (x, 1)) == SYMBOL_REF) ++ sym = XEXP (x, 1); ++ else if (GET_CODE (XEXP (x, 1)) == CONST) ++ { ++ rtx plus = XEXP(XEXP (x, 1), 0); ++ if (GET_CODE (plus) == PLUS) ++ sym = XEXP (plus, 0); ++ else if (GET_CODE (plus) == UNSPEC) ++ sym = XVECEXP (plus, 0, 0); ++ } ++ else ++ return false; ++ ++ gcc_assert (GET_CODE (sym) == SYMBOL_REF); ++ ++ if (TARGET_ICT_MODEL_LARGE ++ && nds32_indirect_call_referenced_p (sym)) ++ return true; ++ ++ if (TARGET_CMODEL_LARGE) ++ return true; ++ else if (TARGET_CMODEL_MEDIUM ++ && NDS32_SYMBOL_REF_RODATA_P (sym)) ++ return true; ++ else ++ return false; ++ } ++ ++ default: ++ return false; ++ } ++} ++ ++static rtx ++nds32_legitimize_address (rtx x, ++ rtx oldx ATTRIBUTE_UNUSED, ++ machine_mode mode ATTRIBUTE_UNUSED) ++{ ++ if (nds32_tls_referenced_p (x)) ++ x = nds32_legitimize_tls_address (x); ++ else if (flag_pic && SYMBOLIC_CONST_P (x)) ++ x = nds32_legitimize_pic_address (x); ++ else if (TARGET_ICT_MODEL_LARGE && nds32_indirect_call_referenced_p (x)) ++ x = nds32_legitimize_ict_address (x); ++ ++ return x; ++} ++ ++static bool ++nds32_legitimate_constant_p (machine_mode mode, rtx x) ++{ ++ switch (GET_CODE (x)) ++ { ++ case CONST_DOUBLE: ++ if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) ++ && (mode == DFmode || mode == SFmode)) + return false; ++ break; ++ case CONST: ++ x = XEXP (x, 0); ++ ++ if (GET_CODE (x) == PLUS) ++ { ++ if (!CONST_INT_P (XEXP (x, 1))) ++ return false; ++ x = XEXP (x, 0); ++ } ++ ++ if (GET_CODE (x) == UNSPEC) ++ { ++ switch (XINT (x, 1)) ++ { ++ case UNSPEC_GOT: ++ case UNSPEC_GOTOFF: ++ case UNSPEC_PLT: ++ case UNSPEC_TLSGD: ++ case UNSPEC_TLSLD: ++ case UNSPEC_TLSIE: ++ case UNSPEC_TLSLE: ++ case UNSPEC_ICT: ++ return false; ++ default: ++ return true; ++ } ++ } ++ break; ++ case SYMBOL_REF: ++ /* TLS symbols need a call to resolve in ++ precompute_register_parameters. */ ++ if (SYMBOL_REF_TLS_MODEL (x)) ++ return false; ++ break; ++ default: ++ return true; ++ } ++ ++ return true; ++} ++ ++/* Reorgnize the UNSPEC CONST and return its direct symbol. */ ++static rtx ++nds32_delegitimize_address (rtx x) ++{ ++ x = delegitimize_mem_from_attrs (x); ++ ++ if (GET_CODE(x) == CONST) ++ { ++ rtx inner = XEXP (x, 0); ++ ++ /* Handle for GOTOFF. */ ++ if (GET_CODE (inner) == PLUS) ++ inner = XEXP (inner, 0); ++ ++ if (GET_CODE (inner) == UNSPEC) ++ { ++ switch (XINT (inner, 1)) ++ { ++ case UNSPEC_GOTINIT: ++ case UNSPEC_GOT: ++ case UNSPEC_GOTOFF: ++ case UNSPEC_PLT: ++ case UNSPEC_TLSGD: ++ case UNSPEC_TLSLD: ++ case UNSPEC_TLSIE: ++ case UNSPEC_TLSLE: ++ case UNSPEC_ICT: ++ x = XVECEXP (inner, 0, 0); ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ return x; ++} + ++static machine_mode ++nds32_vectorize_preferred_simd_mode (scalar_mode mode) ++{ ++ if (!NDS32_EXT_DSP_P ()) ++ return word_mode; ++ ++ switch (mode) ++ { ++ case E_QImode: ++ return V4QImode; ++ case E_HImode: ++ return V2HImode; ++ default: ++ return word_mode; ++ } ++} ++ ++static bool ++nds32_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x) ++{ ++ switch (GET_CODE (x)) ++ { ++ case CONST: ++ return !nds32_legitimate_constant_p (mode, x); ++ case SYMBOL_REF: ++ /* All symbols have to be accessed through gp-relative in PIC mode. */ ++ /* We don't want to force symbol as constant pool in .text section, ++ because we use the gp-relatived instruction to load in small ++ or medium model. */ ++ if (flag_pic ++ || SYMBOL_REF_TLS_MODEL (x) ++ || TARGET_CMODEL_SMALL ++ || TARGET_CMODEL_MEDIUM) ++ return true; ++ break; ++ case CONST_INT: ++ case CONST_DOUBLE: ++ if (flag_pic && (lra_in_progress || reload_completed)) ++ return true; ++ break; + default: + return false; + } ++ return false; + } + + +@@ -2731,13 +3003,33 @@ + /* Describing Relative Costs of Operations. */ + + static int +-nds32_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED, ++nds32_register_move_cost (machine_mode mode, + reg_class_t from, + reg_class_t to) + { ++ /* In garywolf cpu, FPR to GPR is chaper than other cpu. */ ++ if (TARGET_PIPELINE_GRAYWOLF) ++ { ++ if (GET_MODE_SIZE (mode) == 8) ++ { ++ /* DPR to GPR. */ ++ if (from == FP_REGS && to != FP_REGS) ++ return 3; ++ /* GPR to DPR. */ ++ if (from != FP_REGS && to == FP_REGS) ++ return 2; ++ } ++ else ++ { ++ if ((from == FP_REGS && to != FP_REGS) ++ || (from != FP_REGS && to == FP_REGS)) ++ return 2; ++ } ++ } ++ + if ((from == FP_REGS && to != FP_REGS) + || (from != FP_REGS && to == FP_REGS)) +- return 9; ++ return 3; + else if (from == HIGH_REGS || to == HIGH_REGS) + return optimize_size ? 6 : 2; + else +@@ -2825,6 +3117,9 @@ + { + default_file_start (); + ++ if (flag_pic) ++ fprintf (asm_out_file, "\t.pic\n"); ++ + /* Tell assembler which ABI we are using. */ + fprintf (asm_out_file, "\t! ABI version\n"); + if (TARGET_HARD_FLOAT) +@@ -2835,10 +3130,36 @@ + /* Tell assembler that this asm code is generated by compiler. */ + fprintf (asm_out_file, "\t! This asm file is generated by compiler\n"); + fprintf (asm_out_file, "\t.flag\tverbatim\n"); +- /* Give assembler the size of each vector for interrupt handler. */ +- 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); ++ ++ /* Insert directive for linker to distinguish object's ict flag. */ ++ if (!TARGET_LINUX_ABI) ++ { ++ if (TARGET_ICT_MODEL_LARGE) ++ fprintf (asm_out_file, "\t.ict_model\tlarge\n"); ++ else ++ fprintf (asm_out_file, "\t.ict_model\tsmall\n"); ++ } ++ ++ /* 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, ++ the compiler may produce 'la $fp,_FP_BASE_' instruction ++ at prologue for fp-as-gp optimization. ++ We should emit weak reference of _FP_BASE_ to avoid undefined reference ++ in case user does not pass '--relax' option to linker. */ ++ if (!TARGET_LINUX_ABI && (TARGET_FORCE_FP_AS_GP || optimize_size)) ++ { ++ fprintf (asm_out_file, "\t! This weak reference is required to do " ++ "fp-as-gp link time optimization\n"); ++ fprintf (asm_out_file, "\t.weak\t_FP_BASE_\n"); ++ } + + fprintf (asm_out_file, "\t! ------------------------------------\n"); + +@@ -2849,6 +3170,49 @@ + if (TARGET_ISA_V3M) + fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3M"); + ++ switch (nds32_cpu_option) ++ { ++ case CPU_N6: ++ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N6"); ++ break; ++ ++ case CPU_N7: ++ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N7"); ++ break; ++ ++ case CPU_N8: ++ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N8"); ++ break; ++ ++ case CPU_E8: ++ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "E8"); ++ break; ++ ++ case CPU_N9: ++ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N9"); ++ break; ++ ++ case CPU_N10: ++ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N10"); ++ break; ++ ++ case CPU_GRAYWOLF: ++ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "Graywolf"); ++ break; ++ ++ case CPU_N12: ++ case CPU_N13: ++ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "N13"); ++ break; ++ ++ case CPU_SIMPLE: ++ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "SIMPLE"); ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ + if (TARGET_CMODEL_SMALL) + fprintf (asm_out_file, "\t! Code model\t\t: %s\n", "SMALL"); + if (TARGET_CMODEL_MEDIUM) +@@ -2926,9 +3290,65 @@ + { + 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"); + } + ++static bool ++nds32_asm_output_addr_const_extra (FILE *file, rtx x) ++{ ++ if (GET_CODE (x) == UNSPEC) ++ { ++ switch (XINT (x, 1)) ++ { ++ case UNSPEC_GOTINIT: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ break; ++ case UNSPEC_GOTOFF: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@GOTOFF", file); ++ break; ++ case UNSPEC_GOT: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@GOT", file); ++ break; ++ case UNSPEC_PLT: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@PLT", file); ++ break; ++ case UNSPEC_TLSGD: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@TLSDESC", file); ++ break; ++ case UNSPEC_TLSLD: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@TLSDESC", file); ++ break; ++ case UNSPEC_TLSIE: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@GOTTPOFF", file); ++ break; ++ case UNSPEC_TLSLE: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@TPOFF", file); ++ break; ++ case UNSPEC_ICT: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@ICT", file); ++ break; ++ default: ++ return false; ++ } ++ return true; ++ } ++ else ++ return false; ++} ++ + /* -- Output and Generation of Labels. */ + + static void +@@ -2978,6 +3398,18 @@ + + /* No need to handle following process, so return immediately. */ + return; ++ ++ case 'v': ++ gcc_assert (CONST_INT_P (x) ++ && (INTVAL (x) == 0 ++ || INTVAL (x) == 8 ++ || INTVAL (x) == 16 ++ || INTVAL (x) == 24)); ++ fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) / 8); ++ ++ /* No need to handle following process, so return immediately. */ ++ return; ++ + case 'B': + /* Use exact_log2() to search the 1-bit position. */ + gcc_assert (CONST_INT_P (x)); +@@ -3084,8 +3516,15 @@ + switch (GET_CODE (x)) + { + case LABEL_REF: ++ output_addr_const (stream, x); ++ break; ++ + case SYMBOL_REF: + output_addr_const (stream, x); ++ ++ if (!TARGET_LINUX_ABI && nds32_indirect_call_referenced_p (x)) ++ fprintf (stream, "@ICT"); ++ + break; + + case REG: +@@ -3168,6 +3607,17 @@ + output_addr_const (stream, x); + break; + ++ case CONST_VECTOR: ++ fprintf (stream, HOST_WIDE_INT_PRINT_HEX, const_vector_to_hwint (x)); ++ break; ++ ++ case LO_SUM: ++ /* This is a special case for inline assembly using memory address 'p'. ++ The inline assembly code is expected to use pesudo instruction ++ for the operand. EX: la */ ++ output_addr_const (stream, XEXP(x, 1)); ++ break; ++ + default: + /* Generally, output_addr_const () is able to handle most cases. + We want to see what CODE could appear, +@@ -3179,7 +3629,9 @@ + } + + static void +-nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) ++nds32_print_operand_address (FILE *stream, ++ machine_mode mode ATTRIBUTE_UNUSED, ++ rtx x) + { + rtx op0, op1; + +@@ -3194,6 +3646,16 @@ + fputs ("]", stream); + break; + ++ case LO_SUM: ++ /* This is a special case for inline assembly using memory operand 'm'. ++ The inline assembly code is expected to use pesudo instruction ++ for the operand. EX: [ls].[bhw] */ ++ fputs ("[ + ", stream); ++ op1 = XEXP (x, 1); ++ output_addr_const (stream, op1); ++ fputs ("]", stream); ++ break; ++ + case REG: + /* Forbid using static chain register ($r16) + on reduced-set registers configuration. */ +@@ -3260,6 +3722,20 @@ + reg_names[REGNO (XEXP (op0, 0))], + sv); + } ++ else if (GET_CODE (op0) == ASHIFT && REG_P (op1)) ++ { ++ /* [Ra + Rb << sv] ++ In normal, ASHIFT can be converted to MULT like above case. ++ But when the address rtx does not go through canonicalize_address ++ defined in fwprop, we'll need this case. */ ++ int sv = INTVAL (XEXP (op0, 1)); ++ gcc_assert (sv <= 3 && sv >=0); ++ ++ fprintf (stream, "[%s + %s << %d]", ++ reg_names[REGNO (op1)], ++ reg_names[REGNO (XEXP (op0, 0))], ++ sv); ++ } + else + { + /* The control flow is not supposed to be here. */ +@@ -3454,6 +3930,27 @@ + static void + nds32_insert_attributes (tree decl, tree *attributes) + { ++ /* A "indirect_call" function attribute implies "noinline" and "noclone" ++ for elf toolchain to support ROM patch mechanism. */ ++ if (TREE_CODE (decl) == FUNCTION_DECL ++ && lookup_attribute ("indirect_call", *attributes) != NULL) ++ { ++ tree new_attrs = *attributes; ++ ++ if (TARGET_LINUX_ABI) ++ error("cannot use indirect_call attribute under linux toolchain"); ++ ++ if (lookup_attribute ("noinline", new_attrs) == NULL) ++ new_attrs = tree_cons (get_identifier ("noinline"), NULL, new_attrs); ++ if (lookup_attribute ("noclone", new_attrs) == NULL) ++ new_attrs = tree_cons (get_identifier ("noclone"), NULL, new_attrs); ++ ++ if (!TREE_PUBLIC (decl)) ++ error("indirect_call attribute can't apply for static function"); ++ ++ *attributes = new_attrs; ++ } ++ + /* For function declaration, we need to check isr-specific attributes: + 1. Call nds32_check_isr_attrs_conflict() to check any conflict. + 2. Check valid integer value for interrupt/exception. +@@ -3479,6 +3976,38 @@ + excp = lookup_attribute ("exception", func_attrs); + reset = lookup_attribute ("reset", func_attrs); + ++ /* The following code may use attribute arguments. If there is no ++ argument from source code, it will cause segmentation fault. ++ Therefore, return dircetly and report error message later. */ ++ if ((intr && TREE_VALUE (intr) == NULL) ++ || (excp && TREE_VALUE (excp) == NULL) ++ || (reset && TREE_VALUE (reset) == NULL)) ++ return; ++ ++ /* ------------------------------------------------------------- */ ++ /* FIXME: ++ FOR BACKWARD COMPATIBILITY, we need to support following patterns: ++ ++ __attribute__((interrupt("XXX;YYY;id=ZZZ"))) ++ __attribute__((exception("XXX;YYY;id=ZZZ"))) ++ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ"))) ++ ++ If interrupt/exception/reset appears and its argument is a ++ STRING_CST, we will use other functions to parse string in the ++ nds32_construct_isr_vectors_information() and then set necessary ++ isr information in the nds32_isr_vectors[] array. Here we can ++ just return immediately to avoid new-syntax checking. */ ++ if (intr != NULL_TREE ++ && TREE_CODE (TREE_VALUE (TREE_VALUE (intr))) == STRING_CST) ++ return; ++ if (excp != NULL_TREE ++ && TREE_CODE (TREE_VALUE (TREE_VALUE (excp))) == STRING_CST) ++ return; ++ if (reset != NULL_TREE ++ && TREE_CODE (TREE_VALUE (TREE_VALUE (reset))) == STRING_CST) ++ return; ++ /* ------------------------------------------------------------- */ ++ + if (intr || excp) + { + /* Deal with interrupt/exception. */ +@@ -3598,7 +4127,9 @@ + } + if (TARGET_ISA_V3) + { +- /* Under V3 ISA, currently nothing should be strictly set. */ ++ /* If this is ARCH_V3J, we need to enable TARGET_REDUCED_REGS. */ ++ if (nds32_arch_option == ARCH_V3J) ++ target_flags |= MASK_REDUCED_REGS; + } + if (TARGET_ISA_V3M) + { +@@ -3610,6 +4141,9 @@ + target_flags &= ~MASK_EXT_PERF2; + /* Under V3M ISA, we need to strictly disable TARGET_EXT_STRING. */ + target_flags &= ~MASK_EXT_STRING; ++ ++ if (flag_pic) ++ error ("not support -fpic option for v3m toolchain"); + } + + /* See if we are using reduced-set registers: +@@ -3627,6 +4161,12 @@ + fixed_regs[r] = call_used_regs[r] = 1; + } + ++ /* See if user explicitly would like to use fp-as-gp optimization. ++ If so, we must prevent $fp from being allocated ++ during register allocation. */ ++ if (TARGET_FORCE_FP_AS_GP) ++ fixed_regs[FP_REGNUM] = call_used_regs[FP_REGNUM] = 1; ++ + if (!TARGET_16_BIT) + { + /* Under no 16 bit ISA, we need to strictly disable TARGET_V3PUSH. */ +@@ -3643,9 +4183,7 @@ + "must be enable '-mext-fpu-sp' or '-mext-fpu-dp'"); + } + +- /* Currently, we don't support PIC code generation yet. */ +- if (flag_pic) +- sorry ("position-independent code not supported"); ++ nds32_init_rtx_costs (); + + nds32_register_passes (); + } +@@ -3659,8 +4197,11 @@ + vec &constraints ATTRIBUTE_UNUSED, + vec &clobbers, HARD_REG_SET &clobbered_regs) + { +- clobbers.safe_push (gen_rtx_REG (SImode, TA_REGNUM)); +- SET_HARD_REG_BIT (clobbered_regs, TA_REGNUM); ++ if (!flag_inline_asm_r15) ++ { ++ clobbers.safe_push (gen_rtx_REG (SImode, TA_REGNUM)); ++ SET_HARD_REG_BIT (clobbered_regs, TA_REGNUM); ++ } + return NULL; + } + +@@ -3687,6 +4228,13 @@ + 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); ++} + + /* ------------------------------------------------------------------------ */ + +@@ -3703,6 +4251,16 @@ + builtin_define ("__nds32__"); + builtin_define ("__NDS32__"); + ++ /* We need to provide builtin macro to describe the size of ++ each vector for interrupt handler under elf toolchain. */ ++ if (!TARGET_LINUX_ABI) ++ { ++ if (TARGET_ISR_VECTOR_SIZE_4_BYTE) ++ builtin_define ("__NDS32_ISR_VECTOR_SIZE_4__"); ++ else ++ builtin_define ("__NDS32_ISR_VECTOR_SIZE_16__"); ++ } ++ + if (TARGET_HARD_FLOAT) + builtin_define ("__NDS32_ABI_2FP_PLUS__"); + else +@@ -3770,6 +4328,8 @@ + builtin_define ("__NDS32_GP_DIRECT__"); + if (TARGET_VH) + builtin_define ("__NDS32_VH__"); ++ if (NDS32_EXT_DSP_P ()) ++ builtin_define ("__NDS32_EXT_DSP__"); + + if (TARGET_BIG_ENDIAN) + builtin_define ("__big_endian__"); +@@ -4042,6 +4602,10 @@ + The result will be in cfun->machine. */ + nds32_compute_stack_frame (); + ++ /* Check frame_pointer_needed again to prevent fp is need after reload. */ ++ if (frame_pointer_needed) ++ cfun->machine->fp_as_gp_p = false; ++ + /* If this is a variadic function, first we need to push argument + registers that hold the unnamed argument value. */ + if (cfun->machine->va_args_size != 0) +@@ -4066,7 +4630,7 @@ + + /* If the function is 'naked', + we do not have to generate prologue code fragment. */ +- if (cfun->machine->naked_p) ++ if (cfun->machine->naked_p && !flag_pic) + return; + + /* Get callee_first_regno and callee_last_regno. */ +@@ -4195,9 +4759,15 @@ + -1 * sp_adjust); + } + +- /* Prevent the instruction scheduler from +- moving instructions across the boundary. */ +- emit_insn (gen_blockage ()); ++ /* Emit gp setup instructions for -fpic. */ ++ if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) ++ nds32_emit_load_gp (); ++ ++ /* If user applies -mno-sched-prolog-epilog option, ++ we need to prevent instructions of function body from being ++ scheduled with stack adjustment in prologue. */ ++ if (!flag_sched_prolog_epilog) ++ emit_insn (gen_blockage ()); + } + + /* Function for normal multiple pop epilogue. */ +@@ -4211,9 +4781,11 @@ + The result will be in cfun->machine. */ + nds32_compute_stack_frame (); + +- /* Prevent the instruction scheduler from +- moving instructions across the boundary. */ +- emit_insn (gen_blockage ()); ++ /* If user applies -mno-sched-prolog-epilog option, ++ we need to prevent instructions of function body from being ++ scheduled with stack adjustment in epilogue. */ ++ if (!flag_sched_prolog_epilog) ++ emit_insn (gen_blockage ()); + + /* If the function is 'naked', we do not have to generate + epilogue code fragment BUT 'ret' instruction. +@@ -4239,7 +4811,16 @@ + /* Generate return instruction by using 'return_internal' pattern. + Make sure this instruction is after gen_blockage(). */ + if (!sibcall_p) +- emit_jump_insn (gen_return_internal ()); ++ { ++ /* We need to further check attributes to determine whether ++ there should be return instruction at epilogue. ++ If the attribute naked exists but -mno-ret-in-naked-func ++ is issued, there is NO need to generate return instruction. */ ++ if (cfun->machine->attr_naked_p && !flag_ret_in_naked_func) ++ return; ++ ++ emit_jump_insn (gen_return_internal ()); ++ } + return; + } + +@@ -4436,9 +5017,13 @@ + if (cfun->machine->callee_saved_gpr_regs_size > 0) + df_set_regs_ever_live (FP_REGNUM, 1); + ++ /* Check frame_pointer_needed again to prevent fp is need after reload. */ ++ if (frame_pointer_needed) ++ cfun->machine->fp_as_gp_p = false; ++ + /* If the function is 'naked', + we do not have to generate prologue code fragment. */ +- if (cfun->machine->naked_p) ++ if (cfun->machine->naked_p && !flag_pic) + return; + + /* Get callee_first_regno and callee_last_regno. */ +@@ -4566,6 +5151,10 @@ + -1 * sp_adjust); + } + ++ /* Emit gp setup instructions for -fpic. */ ++ if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) ++ nds32_emit_load_gp (); ++ + /* Prevent the instruction scheduler from + moving instructions across the boundary. */ + emit_insn (gen_blockage ()); +@@ -4591,9 +5180,19 @@ + if (cfun->machine->naked_p) + { + /* Generate return instruction by using 'return_internal' pattern. +- Make sure this instruction is after gen_blockage(). */ ++ Make sure this instruction is after gen_blockage(). ++ First we need to check this is a function without sibling call. */ + if (!sibcall_p) +- emit_jump_insn (gen_return_internal ()); ++ { ++ /* We need to further check attributes to determine whether ++ there should be return instruction at epilogue. ++ If the attribute naked exists but -mno-ret-in-naked-func ++ is issued, there is NO need to generate return instruction. */ ++ if (cfun->machine->attr_naked_p && !flag_ret_in_naked_func) ++ return; ++ ++ emit_jump_insn (gen_return_internal ()); ++ } + return; + } + +@@ -4757,6 +5356,11 @@ + if (!reload_completed) + return 0; + ++ /* If attribute 'naked' appears but -mno-ret-in-naked-func is used, ++ we cannot use return instruction. */ ++ if (cfun->machine->attr_naked_p && !flag_ret_in_naked_func) ++ return 0; ++ + sp_adjust = cfun->machine->local_size + + cfun->machine->out_args_size + + cfun->machine->callee_saved_area_gpr_padding_bytes +@@ -5010,6 +5614,9 @@ + #undef TARGET_FUNCTION_ARG_BOUNDARY + #define TARGET_FUNCTION_ARG_BOUNDARY nds32_function_arg_boundary + ++#undef TARGET_VECTOR_MODE_SUPPORTED_P ++#define TARGET_VECTOR_MODE_SUPPORTED_P nds32_vector_mode_supported_p ++ + /* -- How Scalar Function Values Are Returned. */ + + #undef TARGET_FUNCTION_VALUE +@@ -5087,6 +5694,21 @@ + #undef TARGET_LEGITIMATE_ADDRESS_P + #define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p + ++#undef TARGET_LEGITIMIZE_ADDRESS ++#define TARGET_LEGITIMIZE_ADDRESS nds32_legitimize_address ++ ++#undef TARGET_LEGITIMATE_CONSTANT_P ++#define TARGET_LEGITIMATE_CONSTANT_P nds32_legitimate_constant_p ++ ++#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE ++#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE nds32_vectorize_preferred_simd_mode ++ ++#undef TARGET_CANNOT_FORCE_CONST_MEM ++#define TARGET_CANNOT_FORCE_CONST_MEM nds32_cannot_force_const_mem ++ ++#undef TARGET_DELEGITIMIZE_ADDRESS ++#define TARGET_DELEGITIMIZE_ADDRESS nds32_delegitimize_address ++ + + /* Anchored Addresses. */ + +@@ -5147,6 +5769,9 @@ + #undef TARGET_ASM_ALIGNED_SI_OP + #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" + ++#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA ++#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nds32_asm_output_addr_const_extra ++ + /* -- Output of Uninitialized Variables. */ + + /* -- Output and Generation of Labels. */ +@@ -5216,6 +5841,9 @@ + + /* Emulating TLS. */ + ++#undef TARGET_HAVE_TLS ++#define TARGET_HAVE_TLS TARGET_LINUX_ABI ++ + + /* Defining coprocessor specifics for MIPS targets. */ + +@@ -5243,6 +5871,8 @@ + #undef TARGET_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 + #define TARGET_USE_BLOCKS_FOR_CONSTANT_P nds32_use_blocks_for_constant_p +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-cost.c gcc-8.2.0/gcc/config/nds32/nds32-cost.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-cost.c 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-cost.c 2019-01-25 15:38:32.821242637 +0100 +@@ -34,66 +34,379 @@ + #include "optabs.h" /* For GEN_FCN. */ + #include "recog.h" + #include "tm-constrs.h" ++#include "tree-pass.h" + + /* ------------------------------------------------------------------------ */ + +-bool +-nds32_rtx_costs_impl (rtx x, +- machine_mode mode ATTRIBUTE_UNUSED, +- int outer_code, +- int opno ATTRIBUTE_UNUSED, +- int *total, +- bool speed) +-{ +- int code = GET_CODE (x); ++typedef bool (*rtx_cost_func) (rtx, int, int, int, int*); + +- /* According to 'speed', goto suitable cost model section. */ +- if (speed) +- goto performance_cost; +- else +- goto size_cost; +- +- +-performance_cost: +- /* This is section for performance cost model. */ ++struct rtx_cost_model_t { ++ rtx_cost_func speed_prefer; ++ rtx_cost_func size_prefer; ++}; ++ ++static rtx_cost_model_t rtx_cost_model; ++ ++static int insn_size_16bit; /* Initial at nds32_init_rtx_costs. */ ++static const int insn_size_32bit = 4; ++ ++static bool ++nds32_rtx_costs_speed_prefer (rtx x ATTRIBUTE_UNUSED, ++ int code, ++ int outer_code ATTRIBUTE_UNUSED, ++ int opno ATTRIBUTE_UNUSED, ++ int *total) ++{ ++ rtx op0; ++ rtx op1; ++ machine_mode mode = GET_MODE (x); ++ /* Scale cost by mode size. */ ++ int cost = COSTS_N_INSNS (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode)); + +- /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4. +- We treat it as 4-cycle cost for each instruction +- under performance consideration. */ + switch (code) + { +- case SET: +- /* For 'SET' rtx, we need to return false +- so that it can recursively calculate costs. */ +- return false; +- + case USE: + /* Used in combine.c as a marker. */ + *total = 0; +- break; ++ return true; ++ ++ case CONST_INT: ++ /* When not optimizing for size, we care more about the cost ++ of hot code, and hot code is often in a loop. If a constant ++ operand needs to be forced into a register, we will often be ++ able to hoist the constant load out of the loop, so the load ++ should not contribute to the cost. */ ++ if (outer_code == SET || outer_code == PLUS) ++ *total = satisfies_constraint_Is20 (x) ? 0 : 4; ++ else if (outer_code == AND || outer_code == IOR || outer_code == XOR ++ || outer_code == MINUS) ++ *total = satisfies_constraint_Iu15 (x) ? 0 : 4; ++ else if (outer_code == ASHIFT || outer_code == ASHIFTRT ++ || outer_code == LSHIFTRT) ++ *total = satisfies_constraint_Iu05 (x) ? 0 : 4; ++ else if (GET_RTX_CLASS (outer_code) == RTX_COMPARE ++ || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE) ++ *total = satisfies_constraint_Is16 (x) ? 0 : 4; ++ else ++ *total = COSTS_N_INSNS (1); ++ return true; ++ ++ case CONST: ++ case LO_SUM: ++ case HIGH: ++ case SYMBOL_REF: ++ *total = COSTS_N_INSNS (1); ++ return true; ++ ++ case MEM: ++ *total = COSTS_N_INSNS (1); ++ return true; ++ ++ case SET: ++ op0 = SET_DEST (x); ++ op1 = SET_SRC (x); ++ mode = GET_MODE (op0); ++ /* Scale cost by mode size. */ ++ cost = COSTS_N_INSNS (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode)); ++ ++ switch (GET_CODE (op1)) ++ { ++ case REG: ++ case SUBREG: ++ /* Register move and Store instructions. */ ++ if ((REG_P (op0) || MEM_P (op0)) ++ && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (DImode)) ++ *total = COSTS_N_INSNS (1); ++ else ++ *total = cost; ++ return true; ++ ++ case MEM: ++ /* Load instructions. */ ++ if (REG_P (op0) && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (DImode)) ++ *total = COSTS_N_INSNS (1); ++ else ++ *total = cost; ++ return true; ++ ++ case CONST_INT: ++ /* movi instruction. */ ++ if (REG_P (op0) && GET_MODE_SIZE (mode) < GET_MODE_SIZE (DImode)) ++ { ++ if (satisfies_constraint_Is20 (op1)) ++ *total = COSTS_N_INSNS (1) - 1; ++ else ++ *total = COSTS_N_INSNS (2); ++ } ++ else ++ *total = cost; ++ return true; ++ ++ case CONST: ++ case SYMBOL_REF: ++ case LABEL_REF: ++ /* la instruction. */ ++ if (REG_P (op0) && GET_MODE_SIZE (mode) < GET_MODE_SIZE (DImode)) ++ *total = COSTS_N_INSNS (1) - 1; ++ else ++ *total = cost; ++ return true; ++ case VEC_SELECT: ++ *total = cost; ++ return true; ++ ++ default: ++ *total = cost; ++ return true; ++ } ++ ++ case PLUS: ++ op0 = XEXP (x, 0); ++ op1 = XEXP (x, 1); ++ ++ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) ++ *total = cost; ++ else if (GET_CODE (op0) == MULT || GET_CODE (op0) == LSHIFTRT ++ || GET_CODE (op1) == MULT || GET_CODE (op1) == LSHIFTRT) ++ /* ALU_SHIFT */ ++ *total = COSTS_N_INSNS (2); ++ ++ else if ((GET_CODE (op1) == CONST_INT ++ && satisfies_constraint_Is15 (op1)) ++ || REG_P (op1)) ++ /* ADD instructions */ ++ *total = COSTS_N_INSNS (1); ++ else ++ /* ADD instructions: IMM out of range. */ ++ *total = COSTS_N_INSNS (2); ++ return true; ++ ++ case MINUS: ++ op0 = XEXP (x, 0); ++ op1 = XEXP (x, 1); ++ ++ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) ++ *total = cost; ++ else if (GET_CODE (op0) == MULT || GET_CODE (op0) == LSHIFTRT ++ || GET_CODE (op1) == MULT || GET_CODE (op1) == LSHIFTRT) ++ /* ALU_SHIFT */ ++ *total = COSTS_N_INSNS (2); ++ else if ((GET_CODE (op0) == CONST_INT ++ && satisfies_constraint_Is15 (op0)) ++ || REG_P (op0)) ++ /* SUB instructions */ ++ *total = COSTS_N_INSNS (1); ++ else ++ /* SUB instructions: IMM out of range. */ ++ *total = COSTS_N_INSNS (2); ++ return true; ++ ++ case TRUNCATE: ++ /* TRUNCATE and AND behavior is same. */ ++ *total = COSTS_N_INSNS (1); ++ return true; ++ ++ case AND: ++ case IOR: ++ case XOR: ++ op0 = XEXP (x, 0); ++ op1 = XEXP (x, 1); ++ ++ if (NDS32_EXT_DSP_P ()) ++ { ++ /* We prefer (and (ior) (ior)) than (ior (and) (and)) for ++ synthetize pk** and insb instruction. */ ++ if (code == AND && GET_CODE (op0) == IOR && GET_CODE (op1) == IOR) ++ return COSTS_N_INSNS (1); ++ ++ if (code == IOR && GET_CODE (op0) == AND && GET_CODE (op1) == AND) ++ return COSTS_N_INSNS (10); ++ } ++ ++ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) ++ *total = cost; ++ else if (GET_CODE (op0) == ASHIFT || GET_CODE (op0) == LSHIFTRT) ++ *total = COSTS_N_INSNS (2); ++ else if ((GET_CODE (op1) == CONST_INT ++ && satisfies_constraint_Iu15 (op1)) ++ || REG_P (op1)) ++ /* AND, OR, XOR instructions */ ++ *total = COSTS_N_INSNS (1); ++ else if (code == AND || GET_CODE (op0) == NOT) ++ /* BITC instruction */ ++ *total = COSTS_N_INSNS (1); ++ else ++ /* AND, OR, XOR instructions: IMM out of range. */ ++ *total = COSTS_N_INSNS (2); ++ return true; + + case MULT: ++ if (GET_MODE (x) == DImode ++ || GET_CODE (XEXP (x, 1)) == SIGN_EXTEND ++ || GET_CODE (XEXP (x, 1)) == ZERO_EXTEND) ++ /* MUL instructions */ ++ *total = COSTS_N_INSNS (1); ++ else if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) ++ *total = cost; ++ else if (outer_code == PLUS || outer_code == MINUS) ++ *total = COSTS_N_INSNS (2); ++ else if ((GET_CODE (XEXP (x, 1)) == CONST_INT ++ && satisfies_constraint_Iu05 (XEXP (x, 1))) ++ || REG_P (XEXP (x, 1))) ++ /* MUL instructions */ ++ *total = COSTS_N_INSNS (1); ++ else ++ /* MUL instructions: IMM out of range. */ ++ *total = COSTS_N_INSNS (2); ++ ++ if (TARGET_MUL_SLOW) ++ *total += COSTS_N_INSNS (4); ++ ++ return true; ++ ++ case LSHIFTRT: ++ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) ++ *total = cost; ++ else if (outer_code == PLUS || outer_code == MINUS ++ || outer_code == AND || outer_code == IOR ++ || outer_code == XOR) ++ *total = COSTS_N_INSNS (2); ++ else if ((GET_CODE (XEXP (x, 1)) == CONST_INT ++ && satisfies_constraint_Iu05 (XEXP (x, 1))) ++ || REG_P (XEXP (x, 1))) ++ /* SRL instructions */ ++ *total = COSTS_N_INSNS (1); ++ else ++ /* SRL instructions: IMM out of range. */ ++ *total = COSTS_N_INSNS (2); ++ return true; ++ ++ case ASHIFT: ++ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) ++ *total = cost; ++ else if (outer_code == AND || outer_code == IOR ++ || outer_code == XOR) ++ *total = COSTS_N_INSNS (2); ++ else if ((GET_CODE (XEXP (x, 1)) == CONST_INT ++ && satisfies_constraint_Iu05 (XEXP (x, 1))) ++ || REG_P (XEXP (x, 1))) ++ /* SLL instructions */ ++ *total = COSTS_N_INSNS (1); ++ else ++ /* SLL instructions: IMM out of range. */ ++ *total = COSTS_N_INSNS (2); ++ return true; ++ ++ case ASHIFTRT: ++ case ROTATERT: ++ if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode)) ++ *total = cost; ++ else if ((GET_CODE (XEXP (x, 1)) == CONST_INT ++ && satisfies_constraint_Iu05 (XEXP (x, 1))) ++ || REG_P (XEXP (x, 1))) ++ /* ROTR, SLL instructions */ ++ *total = COSTS_N_INSNS (1); ++ else ++ /* ROTR, SLL instructions: IMM out of range. */ ++ *total = COSTS_N_INSNS (2); ++ return true; ++ ++ case LT: ++ case LTU: ++ if (outer_code == SET) ++ { ++ if ((GET_CODE (XEXP (x, 1)) == CONST_INT ++ && satisfies_constraint_Iu15 (XEXP (x, 1))) ++ || REG_P (XEXP (x, 1))) ++ /* SLT, SLTI instructions */ ++ *total = COSTS_N_INSNS (1); ++ else ++ /* SLT, SLT instructions: IMM out of range. */ ++ *total = COSTS_N_INSNS (2); ++ } ++ else ++ /* branch */ ++ *total = COSTS_N_INSNS (2); ++ return true; ++ ++ case EQ: ++ case NE: ++ case GE: ++ case LE: ++ case GT: ++ /* branch */ ++ *total = COSTS_N_INSNS (2); ++ return true; ++ ++ case IF_THEN_ELSE: ++ if (GET_CODE (XEXP (x, 1)) == LABEL_REF) ++ /* branch */ ++ *total = COSTS_N_INSNS (2); ++ else ++ /* cmovz, cmovn instructions */ ++ *total = COSTS_N_INSNS (1); ++ return true; ++ ++ case LABEL_REF: ++ if (outer_code == IF_THEN_ELSE) ++ /* branch */ ++ *total = COSTS_N_INSNS (2); ++ else ++ *total = COSTS_N_INSNS (1); ++ return true; ++ ++ case ZERO_EXTEND: ++ case SIGN_EXTEND: ++ if (MEM_P (XEXP (x, 0))) ++ /* Using memory access. */ ++ *total = COSTS_N_INSNS (1); ++ else ++ /* Zero extend and sign extend instructions. */ ++ *total = COSTS_N_INSNS (1); ++ return true; ++ ++ case NEG: ++ case NOT: + *total = COSTS_N_INSNS (1); +- break; ++ return true; + + case DIV: + case UDIV: + case MOD: + case UMOD: +- *total = COSTS_N_INSNS (7); +- break; +- +- default: +- *total = COSTS_N_INSNS (1); +- break; +- } ++ *total = COSTS_N_INSNS (20); ++ return true; + +- return true; ++ case CALL: ++ *total = COSTS_N_INSNS (2); ++ return true; + ++ case CLZ: ++ case SMIN: ++ case SMAX: ++ case ZERO_EXTRACT: ++ if (TARGET_EXT_PERF) ++ *total = COSTS_N_INSNS (1); ++ else ++ *total = COSTS_N_INSNS (3); ++ return true; ++ case VEC_SELECT: ++ *total = COSTS_N_INSNS (1); ++ return true; + +-size_cost: +- /* This is section for size cost model. */ ++ default: ++ *total = COSTS_N_INSNS (3); ++ return true; ++ } ++} + ++static bool ++nds32_rtx_costs_size_prefer (rtx x, ++ int code, ++ int outer_code, ++ int opno ATTRIBUTE_UNUSED, ++ int *total) ++{ + /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4. + We treat it as 4-byte cost for each instruction + under code size consideration. */ +@@ -118,85 +431,162 @@ + (set X imm20s), use movi, 4-byte cost. + (set X BIG_INT), use sethi/ori, 8-byte cost. */ + if (satisfies_constraint_Is05 (x)) +- *total = COSTS_N_INSNS (1) - 2; ++ *total = insn_size_16bit; + else if (satisfies_constraint_Is20 (x)) +- *total = COSTS_N_INSNS (1); ++ *total = insn_size_32bit; + else +- *total = COSTS_N_INSNS (2); ++ *total = insn_size_32bit * 2; + } + else if (outer_code == PLUS || outer_code == MINUS) + { + /* Possible addi333/subi333 or subi45/addi45, 2-byte cost. + General case, cost 1 instruction with 4-byte. */ + if (satisfies_constraint_Iu05 (x)) +- *total = COSTS_N_INSNS (1) - 2; ++ *total = insn_size_16bit; + else +- *total = COSTS_N_INSNS (1); ++ *total = insn_size_32bit; + } + else if (outer_code == ASHIFT) + { + /* Possible slli333, 2-byte cost. + General case, cost 1 instruction with 4-byte. */ + if (satisfies_constraint_Iu03 (x)) +- *total = COSTS_N_INSNS (1) - 2; ++ *total = insn_size_16bit; + else +- *total = COSTS_N_INSNS (1); ++ *total = insn_size_32bit; + } + else if (outer_code == ASHIFTRT || outer_code == LSHIFTRT) + { + /* Possible srai45 or srli45, 2-byte cost. + General case, cost 1 instruction with 4-byte. */ + if (satisfies_constraint_Iu05 (x)) +- *total = COSTS_N_INSNS (1) - 2; ++ *total = insn_size_16bit; + else +- *total = COSTS_N_INSNS (1); ++ *total = insn_size_32bit; + } + else + { + /* For other cases, simply set it 4-byte cost. */ +- *total = COSTS_N_INSNS (1); ++ *total = insn_size_32bit; + } + break; + + case CONST_DOUBLE: + /* It requires high part and low part processing, set it 8-byte cost. */ +- *total = COSTS_N_INSNS (2); ++ *total = insn_size_32bit * 2; ++ break; ++ ++ case CONST: ++ case SYMBOL_REF: ++ *total = insn_size_32bit * 2; + break; + + default: + /* For other cases, generally we set it 4-byte cost +- and stop resurively traversing. */ +- *total = COSTS_N_INSNS (1); ++ and stop resurively traversing. */ ++ *total = insn_size_32bit; + break; + } + + return true; + } + +-int +-nds32_address_cost_impl (rtx address, +- machine_mode mode ATTRIBUTE_UNUSED, +- addr_space_t as ATTRIBUTE_UNUSED, +- bool speed) ++void ++nds32_init_rtx_costs (void) ++{ ++ rtx_cost_model.speed_prefer = nds32_rtx_costs_speed_prefer; ++ rtx_cost_model.size_prefer = nds32_rtx_costs_size_prefer; ++ ++ if (TARGET_16_BIT) ++ insn_size_16bit = 2; ++ else ++ insn_size_16bit = 4; ++} ++ ++/* This target hook describes the relative costs of RTL expressions. ++ Return 'true' when all subexpressions of x have been processed. ++ Return 'false' to sum the costs of sub-rtx, plus cost of this operation. ++ Refer to gcc/rtlanal.c for more information. */ ++bool ++nds32_rtx_costs_impl (rtx x, ++ machine_mode mode ATTRIBUTE_UNUSED, ++ int outer_code, ++ int opno, ++ int *total, ++ bool speed) ++{ ++ int code = GET_CODE (x); ++ ++ /* According to 'speed', use suitable cost model section. */ ++ if (speed) ++ return rtx_cost_model.speed_prefer(x, code, outer_code, opno, total); ++ else ++ return rtx_cost_model.size_prefer(x, code, outer_code, opno, total); ++} ++ ++ ++int nds32_address_cost_speed_prefer (rtx address) + { + rtx plus0, plus1; + enum rtx_code code; + + code = GET_CODE (address); + +- /* According to 'speed', goto suitable cost model section. */ +- if (speed) +- goto performance_cost; +- else +- goto size_cost; ++ switch (code) ++ { ++ case POST_MODIFY: ++ case POST_INC: ++ case POST_DEC: ++ /* We encourage that rtx contains ++ POST_MODIFY/POST_INC/POST_DEC behavior. */ ++ return COSTS_N_INSNS (1) - 2; ++ ++ case SYMBOL_REF: ++ /* We can have gp-relative load/store for symbol_ref. ++ Have it 4-byte cost. */ ++ return COSTS_N_INSNS (2); ++ ++ case CONST: ++ /* It is supposed to be the pattern (const (plus symbol_ref const_int)). ++ Have it 4-byte cost. */ ++ return COSTS_N_INSNS (2); ++ ++ case REG: ++ /* Simply return 4-byte costs. */ ++ return COSTS_N_INSNS (1) - 2; ++ ++ case PLUS: ++ /* We do not need to check if the address is a legitimate address, ++ because this hook is never called with an invalid address. ++ But we better check the range of ++ const_int value for cost, if it exists. */ ++ plus0 = XEXP (address, 0); ++ plus1 = XEXP (address, 1); + +-performance_cost: +- /* This is section for performance cost model. */ ++ if (REG_P (plus0) && CONST_INT_P (plus1)) ++ return COSTS_N_INSNS (1) - 2; ++ else if (ARITHMETIC_P (plus0) || ARITHMETIC_P (plus1)) ++ return COSTS_N_INSNS (1) - 1; ++ else if (REG_P (plus0) && REG_P (plus1)) ++ return COSTS_N_INSNS (1); + +- /* FALLTHRU, currently we use same cost model as size_cost. */ ++ /* For other 'plus' situation, make it cost 4-byte. */ ++ return COSTS_N_INSNS (1); + +-size_cost: +- /* This is section for size cost model. */ ++ default: ++ break; ++ } ++ ++ return COSTS_N_INSNS (4); ++ ++} ++ ++int nds32_address_cost_speed_fwprop (rtx address) ++{ ++ rtx plus0, plus1; ++ enum rtx_code code; ++ ++ code = GET_CODE (address); + + switch (code) + { +@@ -210,12 +600,12 @@ + case SYMBOL_REF: + /* We can have gp-relative load/store for symbol_ref. + Have it 4-byte cost. */ +- return COSTS_N_INSNS (1); ++ return COSTS_N_INSNS (2); + + case CONST: + /* It is supposed to be the pattern (const (plus symbol_ref const_int)). + Have it 4-byte cost. */ +- return COSTS_N_INSNS (1); ++ return COSTS_N_INSNS (2); + + case REG: + /* Simply return 4-byte costs. */ +@@ -233,11 +623,78 @@ + { + /* If it is possible to be lwi333/swi333 form, + make it 2-byte cost. */ +- if (satisfies_constraint_Iu05 (plus1)) ++ if (satisfies_constraint_Iu03 (plus1)) + return (COSTS_N_INSNS (1) - 2); + else + return COSTS_N_INSNS (1); + } ++ if (ARITHMETIC_P (plus0) || ARITHMETIC_P (plus1)) ++ return COSTS_N_INSNS (1) - 2; ++ else if (REG_P (plus0) && REG_P (plus1)) ++ return COSTS_N_INSNS (1); ++ ++ /* For other 'plus' situation, make it cost 4-byte. */ ++ return COSTS_N_INSNS (1); ++ ++ default: ++ break; ++ } ++ ++ return COSTS_N_INSNS (4); ++} ++ ++ ++int nds32_address_cost_size_prefer (rtx address) ++{ ++ rtx plus0, plus1; ++ enum rtx_code code; ++ ++ code = GET_CODE (address); ++ ++ switch (code) ++ { ++ case POST_MODIFY: ++ case POST_INC: ++ case POST_DEC: ++ /* We encourage that rtx contains ++ POST_MODIFY/POST_INC/POST_DEC behavior. */ ++ return 0; ++ ++ case SYMBOL_REF: ++ /* We can have gp-relative load/store for symbol_ref. ++ Have it 4-byte cost. */ ++ return COSTS_N_INSNS (2); ++ ++ case CONST: ++ /* It is supposed to be the pattern (const (plus symbol_ref const_int)). ++ Have it 4-byte cost. */ ++ return COSTS_N_INSNS (2); ++ ++ case REG: ++ /* Simply return 4-byte costs. */ ++ return COSTS_N_INSNS (1) - 1; ++ ++ case PLUS: ++ /* We do not need to check if the address is a legitimate address, ++ because this hook is never called with an invalid address. ++ But we better check the range of ++ const_int value for cost, if it exists. */ ++ plus0 = XEXP (address, 0); ++ plus1 = XEXP (address, 1); ++ ++ if (REG_P (plus0) && CONST_INT_P (plus1)) ++ { ++ /* If it is possible to be lwi333/swi333 form, ++ make it 2-byte cost. */ ++ if (satisfies_constraint_Iu03 (plus1)) ++ return (COSTS_N_INSNS (1) - 2); ++ else ++ return COSTS_N_INSNS (1) - 1; ++ } ++ ++ /* (plus (reg) (mult (reg) (const))) */ ++ if (ARITHMETIC_P (plus0) || ARITHMETIC_P (plus1)) ++ return (COSTS_N_INSNS (1) - 1); + + /* For other 'plus' situation, make it cost 4-byte. */ + return COSTS_N_INSNS (1); +@@ -247,6 +704,23 @@ + } + + return COSTS_N_INSNS (4); ++ ++} ++ ++int nds32_address_cost_impl (rtx address, ++ machine_mode mode ATTRIBUTE_UNUSED, ++ addr_space_t as ATTRIBUTE_UNUSED, ++ bool speed_p) ++{ ++ if (speed_p) ++ { ++ if (current_pass->tv_id == TV_FWPROP) ++ return nds32_address_cost_speed_fwprop (address); ++ else ++ return nds32_address_cost_speed_prefer (address); ++ } ++ else ++ return nds32_address_cost_size_prefer (address); + } + + /* ------------------------------------------------------------------------ */ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-doubleword.md gcc-8.2.0/gcc/config/nds32/nds32-doubleword.md +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-doubleword.md 2018-05-07 04:09:58.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-doubleword.md 2019-01-25 15:38:32.821242637 +0100 +@@ -136,10 +136,28 @@ + } + ) + ++;; Split move_di pattern when the hard register is odd. ++(define_split ++ [(set (match_operand:DIDF 0 "register_operand" "") ++ (match_operand:DIDF 1 "register_operand" ""))] ++ "(NDS32_IS_GPR_REGNUM (REGNO (operands[0])) ++ && ((REGNO (operands[0]) & 0x1) == 1)) ++ || (NDS32_IS_GPR_REGNUM (REGNO (operands[1])) ++ && ((REGNO (operands[1]) & 0x1) == 1))" ++ [(set (match_dup 2) (match_dup 3)) ++ (set (match_dup 4) (match_dup 5))] ++ { ++ operands[2] = gen_lowpart (SImode, operands[0]); ++ operands[4] = gen_highpart (SImode, operands[0]); ++ operands[3] = gen_lowpart (SImode, operands[1]); ++ operands[5] = gen_highpart (SImode, operands[1]); ++ } ++) ++ + (define_split + [(set (match_operand:DIDF 0 "register_operand" "") + (match_operand:DIDF 1 "const_double_operand" ""))] +- "reload_completed" ++ "flag_pic || reload_completed" + [(set (match_dup 2) (match_dup 3)) + (set (match_dup 4) (match_dup 5))] + { +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-dspext.md gcc-8.2.0/gcc/config/nds32/nds32-dspext.md +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-dspext.md 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-dspext.md 2019-01-25 15:38:32.825242648 +0100 +@@ -0,0 +1,5278 @@ ++;; Machine description 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 ++;; . ++ ++(define_expand "mov" ++ [(set (match_operand:VQIHI 0 "general_operand" "") ++ (match_operand:VQIHI 1 "general_operand" ""))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ /* Need to force register if mem <- !reg. */ ++ if (MEM_P (operands[0]) && !REG_P (operands[1])) ++ operands[1] = force_reg (mode, operands[1]); ++ ++ /* If operands[1] is a large constant and cannot be performed ++ by a single instruction, we need to split it. */ ++ if (GET_CODE (operands[1]) == CONST_VECTOR ++ && !satisfies_constraint_CVs2 (operands[1]) ++ && !satisfies_constraint_CVhi (operands[1])) ++ { ++ HOST_WIDE_INT ival = const_vector_to_hwint (operands[1]); ++ rtx tmp_rtx; ++ ++ tmp_rtx = can_create_pseudo_p () ++ ? gen_reg_rtx (SImode) ++ : simplify_gen_subreg (SImode, operands[0], mode, 0); ++ ++ emit_move_insn (tmp_rtx, gen_int_mode (ival, SImode)); ++ convert_move (operands[0], tmp_rtx, false); ++ DONE; ++ } ++ ++ if (REG_P (operands[0]) && SYMBOLIC_CONST_P (operands[1])) ++ { ++ if (nds32_tls_referenced_p (operands [1])) ++ { ++ nds32_expand_tls_move (operands); ++ DONE; ++ } ++ else if (flag_pic) ++ { ++ nds32_expand_pic_move (operands); ++ DONE; ++ } ++ } ++}) ++ ++(define_insn "*mov" ++ [(set (match_operand:VQIHI 0 "nonimmediate_operand" "=r, r,$U45,$U33,$U37,$U45, m,$ l,$ l,$ l,$ d, d, r,$ d, r, r, r, *f, *f, r, *f, Q") ++ (match_operand:VQIHI 1 "nds32_vmove_operand" " r, r, l, l, l, d, r, U45, U33, U37, U45,Ufe, m, CVp5, CVs5, CVs2, CVhi, *f, r, *f, Q, *f"))] ++ "NDS32_EXT_DSP_P () ++ && (register_operand(operands[0], mode) ++ || register_operand(operands[1], mode))" ++{ ++ switch (which_alternative) ++ { ++ case 0: ++ return "mov55\t%0, %1"; ++ case 1: ++ return "ori\t%0, %1, 0"; ++ case 2: ++ case 3: ++ case 4: ++ case 5: ++ return nds32_output_16bit_store (operands, ); ++ case 6: ++ return nds32_output_32bit_store (operands, ); ++ case 7: ++ case 8: ++ case 9: ++ case 10: ++ case 11: ++ return nds32_output_16bit_load (operands, ); ++ case 12: ++ return nds32_output_32bit_load (operands, ); ++ case 13: ++ return "movpi45\t%0, %1"; ++ case 14: ++ return "movi55\t%0, %1"; ++ case 15: ++ return "movi\t%0, %1"; ++ case 16: ++ return "sethi\t%0, hi20(%1)"; ++ case 17: ++ if (TARGET_FPU_SINGLE) ++ return "fcpyss\t%0, %1, %1"; ++ else ++ return "#"; ++ case 18: ++ return "fmtsr\t%1, %0"; ++ case 19: ++ return "fmfsr\t%0, %1"; ++ case 20: ++ return nds32_output_float_load (operands); ++ case 21: ++ return nds32_output_float_store (operands); ++ default: ++ gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "alu,alu,store,store,store,store,store,load,load,load,load,load,load,alu,alu,alu,alu,fcpy,fmtsr,fmfsr,fload,fstore") ++ (set_attr "length" " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 4, 2, 2, 4, 4, 4, 4, 4, 4, 4") ++ (set_attr "feature" " v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v3m, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu")]) ++ ++(define_expand "movv2si" ++ [(set (match_operand:V2SI 0 "general_operand" "") ++ (match_operand:V2SI 1 "general_operand" ""))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ /* Need to force register if mem <- !reg. */ ++ if (MEM_P (operands[0]) && !REG_P (operands[1])) ++ operands[1] = force_reg (V2SImode, operands[1]); ++}) ++ ++(define_insn "*movv2si" ++ [(set (match_operand:V2SI 0 "nonimmediate_operand" "=r, r, r, r, Da, m, f, Q, f, r, f") ++ (match_operand:V2SI 1 "general_operand" " r, i, Da, m, r, r, Q, f, f, f, r"))] ++ "NDS32_EXT_DSP_P () ++ && (register_operand(operands[0], V2SImode) ++ || register_operand(operands[1], V2SImode))" ++{ ++ switch (which_alternative) ++ { ++ case 0: ++ return "movd44\t%0, %1"; ++ case 1: ++ /* reg <- const_int, we ask gcc to split instruction. */ ++ return "#"; ++ case 2: ++ /* The memory format is (mem (reg)), ++ we can generate 'lmw.bi' instruction. */ ++ return nds32_output_double (operands, true); ++ case 3: ++ /* We haven't 64-bit load instruction, ++ we split this pattern to two SImode pattern. */ ++ return "#"; ++ case 4: ++ /* The memory format is (mem (reg)), ++ we can generate 'smw.bi' instruction. */ ++ return nds32_output_double (operands, false); ++ case 5: ++ /* We haven't 64-bit store instruction, ++ we split this pattern to two SImode pattern. */ ++ return "#"; ++ case 6: ++ return nds32_output_float_load (operands); ++ case 7: ++ return nds32_output_float_store (operands); ++ case 8: ++ return "fcpysd\t%0, %1, %1"; ++ case 9: ++ return "fmfdr\t%0, %1"; ++ case 10: ++ return "fmtdr\t%1, %0"; ++ default: ++ gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "alu,alu,load,load,store,store,unknown,unknown,unknown,unknown,unknown") ++ (set_attr_alternative "length" ++ [ ++ ;; Alternative 0 ++ (if_then_else (match_test "!TARGET_16_BIT") ++ (const_int 4) ++ (const_int 2)) ++ ;; Alternative 1 ++ (const_int 16) ++ ;; Alternative 2 ++ (const_int 4) ++ ;; Alternative 3 ++ (const_int 8) ++ ;; Alternative 4 ++ (const_int 4) ++ ;; Alternative 5 ++ (const_int 8) ++ ;; Alternative 6 ++ (const_int 4) ++ ;; Alternative 7 ++ (const_int 4) ++ ;; Alternative 8 ++ (const_int 4) ++ ;; Alternative 9 ++ (const_int 4) ++ ;; Alternative 10 ++ (const_int 4) ++ ]) ++ (set_attr "feature" " v1, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu")]) ++ ++(define_expand "movmisalign" ++ [(set (match_operand:VQIHI 0 "general_operand" "") ++ (match_operand:VQIHI 1 "general_operand" ""))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ rtx addr; ++ if (MEM_P (operands[0]) && !REG_P (operands[1])) ++ operands[1] = force_reg (mode, operands[1]); ++ ++ if (MEM_P (operands[0])) ++ { ++ addr = force_reg (Pmode, XEXP (operands[0], 0)); ++ emit_insn (gen_unaligned_store (addr, operands[1])); ++ } ++ else ++ { ++ addr = force_reg (Pmode, XEXP (operands[1], 0)); ++ emit_insn (gen_unaligned_load (operands[0], addr)); ++ } ++ DONE; ++}) ++ ++(define_expand "unaligned_load" ++ [(set (match_operand:VQIHI 0 "register_operand" "=r") ++ (unspec:VQIHI [(mem:VQIHI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_W))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_ISA_V3M) ++ nds32_expand_unaligned_load (operands, mode); ++ else ++ emit_insn (gen_unaligned_load_w (operands[0], gen_rtx_MEM (mode, operands[1]))); ++ DONE; ++}) ++ ++(define_insn "unaligned_load_w" ++ [(set (match_operand:VQIHI 0 "register_operand" "= r") ++ (unspec:VQIHI [(match_operand:VQIHI 1 "nds32_lmw_smw_base_operand" " Umw")] UNSPEC_UALOAD_W))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ return nds32_output_lmw_single_word (operands); ++} ++ [(set_attr "type" "load") ++ (set_attr "length" "4")] ++) ++ ++(define_expand "unaligned_store" ++ [(set (mem:VQIHI (match_operand:SI 0 "register_operand" "r")) ++ (unspec:VQIHI [(match_operand:VQIHI 1 "register_operand" "r")] UNSPEC_UASTORE_W))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_ISA_V3M) ++ nds32_expand_unaligned_store (operands, mode); ++ else ++ emit_insn (gen_unaligned_store_w (gen_rtx_MEM (mode, operands[0]), operands[1])); ++ DONE; ++}) ++ ++(define_insn "unaligned_store_w" ++ [(set (match_operand:VQIHI 0 "nds32_lmw_smw_base_operand" "=Umw") ++ (unspec:VQIHI [(match_operand:VQIHI 1 "register_operand" " r")] UNSPEC_UASTORE_W))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ return nds32_output_smw_single_word (operands); ++} ++ [(set_attr "type" "store") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "add3" ++ [(set (match_operand:VQIHI 0 "register_operand" "=r") ++ (all_plus:VQIHI (match_operand:VQIHI 1 "register_operand" " r") ++ (match_operand:VQIHI 2 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "add %0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++(define_insn "adddi3" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (all_plus:DI (match_operand:DI 1 "register_operand" " r") ++ (match_operand:DI 2 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "add64 %0, %1, %2" ++ [(set_attr "type" "dalu64") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++(define_insn "raddv4qi3" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (truncate:V4QI ++ (ashiftrt:V4HI ++ (plus:V4HI (sign_extend:V4HI (match_operand:V4QI 1 "register_operand" " r")) ++ (sign_extend:V4HI (match_operand:V4QI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "radd8\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++ ++(define_insn "uraddv4qi3" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (truncate:V4QI ++ (lshiftrt:V4HI ++ (plus:V4HI (zero_extend:V4HI (match_operand:V4QI 1 "register_operand" " r")) ++ (zero_extend:V4HI (match_operand:V4QI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "uradd8\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++(define_insn "raddv2hi3" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (truncate:V2HI ++ (ashiftrt:V2SI ++ (plus:V2SI (sign_extend:V2SI (match_operand:V2HI 1 "register_operand" " r")) ++ (sign_extend:V2SI (match_operand:V2HI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "radd16\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++(define_insn "uraddv2hi3" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (truncate:V2HI ++ (lshiftrt:V2SI ++ (plus:V2SI (zero_extend:V2SI (match_operand:V2HI 1 "register_operand" " r")) ++ (zero_extend:V2SI (match_operand:V2HI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "uradd16\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++(define_insn "radddi3" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (truncate:DI ++ (ashiftrt:TI ++ (plus:TI (sign_extend:TI (match_operand:DI 1 "register_operand" " r")) ++ (sign_extend:TI (match_operand:DI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "radd64\t%0, %1, %2" ++ [(set_attr "type" "dalu64") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++ ++(define_insn "uradddi3" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (truncate:DI ++ (lshiftrt:TI ++ (plus:TI (zero_extend:TI (match_operand:DI 1 "register_operand" " r")) ++ (zero_extend:TI (match_operand:DI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "uradd64\t%0, %1, %2" ++ [(set_attr "type" "dalu64") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++(define_insn "sub3" ++ [(set (match_operand:VQIHI 0 "register_operand" "=r") ++ (all_minus:VQIHI (match_operand:VQIHI 1 "register_operand" " r") ++ (match_operand:VQIHI 2 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "sub %0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++(define_insn "subdi3" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (all_minus:DI (match_operand:DI 1 "register_operand" " r") ++ (match_operand:DI 2 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "sub64 %0, %1, %2" ++ [(set_attr "type" "dalu64") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++(define_insn "rsubv4qi3" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (truncate:V4QI ++ (ashiftrt:V4HI ++ (minus:V4HI (sign_extend:V4HI (match_operand:V4QI 1 "register_operand" " r")) ++ (sign_extend:V4HI (match_operand:V4QI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "rsub8\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn "ursubv4qi3" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (truncate:V4QI ++ (lshiftrt:V4HI ++ (minus:V4HI (zero_extend:V4HI (match_operand:V4QI 1 "register_operand" " r")) ++ (zero_extend:V4HI (match_operand:V4QI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "ursub8\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn "rsubv2hi3" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (truncate:V2HI ++ (ashiftrt:V2SI ++ (minus:V2SI (sign_extend:V2SI (match_operand:V2HI 1 "register_operand" " r")) ++ (sign_extend:V2SI (match_operand:V2HI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "rsub16\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn "ursubv2hi3" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (truncate:V2HI ++ (lshiftrt:V2SI ++ (minus:V2SI (zero_extend:V2SI (match_operand:V2HI 1 "register_operand" " r")) ++ (zero_extend:V2SI (match_operand:V2HI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "ursub16\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn "rsubdi3" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (truncate:DI ++ (ashiftrt:TI ++ (minus:TI (sign_extend:TI (match_operand:DI 1 "register_operand" " r")) ++ (sign_extend:TI (match_operand:DI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "rsub64\t%0, %1, %2" ++ [(set_attr "type" "dalu64") ++ (set_attr "length" "4")]) ++ ++ ++(define_insn "ursubdi3" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (truncate:DI ++ (lshiftrt:TI ++ (minus:TI (zero_extend:TI (match_operand:DI 1 "register_operand" " r")) ++ (zero_extend:TI (match_operand:DI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "ursub64\t%0, %1, %2" ++ [(set_attr "type" "dalu64") ++ (set_attr "length" "4")]) ++ ++(define_expand "cras16_1" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_cras16_1_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_cras16_1_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_insn "cras16_1_le" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (vec_duplicate:V2HI ++ (plus:HI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "cras16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_insn "cras16_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (plus:HI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "cras16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_expand "kcras16_1" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_kcras16_1_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_kcras16_1_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_insn "kcras16_1_le" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (ss_minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (vec_duplicate:V2HI ++ (ss_plus:HI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "kcras16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_insn "kcras16_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (ss_minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (ss_plus:HI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "kcras16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_expand "ukcras16_1" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_ukcras16_1_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_ukcras16_1_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_insn "ukcras16_1_le" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (us_minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (vec_duplicate:V2HI ++ (us_plus:HI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "ukcras16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_insn "ukcras16_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (us_minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (us_plus:HI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "ukcras16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_expand "crsa16_1" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_crsa16_1_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_crsa16_1_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_insn "crsa16_1_le" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (plus:HI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "crsa16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_insn "crsa16_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (vec_duplicate:V2HI ++ (plus:HI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "crsa16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_expand "kcrsa16_1" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_kcrsa16_1_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_kcrsa16_1_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_insn "kcrsa16_1_le" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (ss_minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (ss_plus:HI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "kcrsa16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_insn "kcrsa16_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (ss_minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (vec_duplicate:V2HI ++ (ss_plus:HI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "kcrsa16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_expand "ukcrsa16_1" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_ukcrsa16_1_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_ukcrsa16_1_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_insn "ukcrsa16_1_le" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (us_minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (us_plus:HI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "ukcrsa16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_insn "ukcrsa16_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (us_minus:HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (vec_duplicate:V2HI ++ (us_plus:HI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "ukcrsa16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_expand "rcras16_1" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_rcras16_1_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_rcras16_1_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_insn "rcras16_1_le" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (ashiftrt:SI ++ (minus:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (const_int 1)))) ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (ashiftrt:SI ++ (plus:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)])))) ++ (const_int 1)))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "rcras16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_insn "rcras16_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (ashiftrt:SI ++ (minus:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (const_int 1)))) ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (ashiftrt:SI ++ (plus:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)])))) ++ (const_int 1)))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "rcras16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_expand "urcras16_1" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_urcras16_1_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_urcras16_1_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_insn "urcras16_1_le" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (lshiftrt:SI ++ (minus:SI ++ (zero_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (zero_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (const_int 1)))) ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (lshiftrt:SI ++ (plus:SI ++ (zero_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (zero_extend:SI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)])))) ++ (const_int 1)))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "urcras16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_insn "urcras16_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (lshiftrt:SI ++ (minus:SI ++ (zero_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (zero_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (const_int 1)))) ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (lshiftrt:SI ++ (plus:SI ++ (zero_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))) ++ (zero_extend:SI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)])))) ++ (const_int 1)))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "urcras16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_expand "rcrsa16_1" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_rcrsa16_1_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_rcrsa16_1_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_insn "rcrsa16_1_le" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (ashiftrt:SI ++ (minus:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (const_int 1)))) ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (ashiftrt:SI ++ (plus:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)])))) ++ (const_int 1)))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "rcrsa16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_insn "rcrsa16_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (ashiftrt:SI ++ (minus:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (const_int 1)))) ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (ashiftrt:SI ++ (plus:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)])))) ++ (const_int 1)))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "rcrsa16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_expand "urcrsa16_1" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_urcrsa16_1_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_urcrsa16_1_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_insn "urcrsa16_1_le" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (lshiftrt:SI ++ (minus:SI ++ (zero_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (zero_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (const_int 1)))) ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (lshiftrt:SI ++ (plus:SI ++ (zero_extend:SI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)]))) ++ (zero_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)])))) ++ (const_int 1)))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "urcrsa16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_insn "urcrsa16_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (lshiftrt:SI ++ (minus:SI ++ (zero_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (zero_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (const_int 1)))) ++ (vec_duplicate:V2HI ++ (truncate:HI ++ (lshiftrt:SI ++ (plus:SI ++ (zero_extend:SI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)]))) ++ (zero_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)])))) ++ (const_int 1)))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "urcrsa16\t%0, %1, %2" ++ [(set_attr "type" "dalu")] ++) ++ ++(define_expand "v2hi3" ++ [(set (match_operand:V2HI 0 "register_operand" "") ++ (shifts:V2HI (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:SI 2 "nds32_rimm4u_operand" "")))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (operands[2] == const0_rtx) ++ { ++ emit_move_insn (operands[0], operands[1]); ++ DONE; ++ } ++}) ++ ++(define_insn "*ashlv2hi3" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r") ++ (ashift:V2HI (match_operand:V2HI 1 "register_operand" " r, r") ++ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r")))] ++ "NDS32_EXT_DSP_P ()" ++ "@ ++ slli16\t%0, %1, %2 ++ sll16\t%0, %1, %2" ++ [(set_attr "type" "dalu,dalu") ++ (set_attr "length" " 4, 4")]) ++ ++(define_insn "kslli16" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r") ++ (ss_ashift:V2HI (match_operand:V2HI 1 "register_operand" " r, r") ++ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r")))] ++ "NDS32_EXT_DSP_P ()" ++ "@ ++ kslli16\t%0, %1, %2 ++ ksll16\t%0, %1, %2" ++ [(set_attr "type" "dalu,dalu") ++ (set_attr "length" " 4, 4")]) ++ ++(define_insn "*ashrv2hi3" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r") ++ (ashiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r, r") ++ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r")))] ++ "NDS32_EXT_DSP_P ()" ++ "@ ++ srai16\t%0, %1, %2 ++ sra16\t%0, %1, %2" ++ [(set_attr "type" "dalu,dalu") ++ (set_attr "length" " 4, 4")]) ++ ++(define_insn "sra16_round" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r") ++ (unspec:V2HI [(ashiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r, r") ++ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r"))] ++ UNSPEC_ROUND))] ++ "NDS32_EXT_DSP_P ()" ++ "@ ++ srai16.u\t%0, %1, %2 ++ sra16.u\t%0, %1, %2" ++ [(set_attr "type" "daluround,daluround") ++ (set_attr "length" " 4, 4")]) ++ ++(define_insn "*lshrv2hi3" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r") ++ (lshiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r, r") ++ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r")))] ++ "NDS32_EXT_DSP_P ()" ++ "@ ++ srli16\t%0, %1, %2 ++ srl16\t%0, %1, %2" ++ [(set_attr "type" "dalu,dalu") ++ (set_attr "length" " 4, 4")]) ++ ++(define_insn "srl16_round" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r") ++ (unspec:V2HI [(lshiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r, r") ++ (match_operand:SI 2 "nds32_rimm4u_operand" " Iu04, r"))] ++ UNSPEC_ROUND))] ++ "NDS32_EXT_DSP_P ()" ++ "@ ++ srli16.u\t%0, %1, %2 ++ srl16.u\t%0, %1, %2" ++ [(set_attr "type" "daluround,daluround") ++ (set_attr "length" " 4, 4")]) ++ ++(define_insn "kslra16" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (if_then_else:V2HI ++ (lt:SI (match_operand:SI 2 "register_operand" " r") ++ (const_int 0)) ++ (ashiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r") ++ (neg:SI (match_dup 2))) ++ (ashift:V2HI (match_dup 1) ++ (match_dup 2))))] ++ "NDS32_EXT_DSP_P ()" ++ "kslra16\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn "kslra16_round" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (if_then_else:V2HI ++ (lt:SI (match_operand:SI 2 "register_operand" " r") ++ (const_int 0)) ++ (unspec:V2HI [(ashiftrt:V2HI (match_operand:V2HI 1 "register_operand" " r") ++ (neg:SI (match_dup 2)))] ++ UNSPEC_ROUND) ++ (ashift:V2HI (match_dup 1) ++ (match_dup 2))))] ++ "NDS32_EXT_DSP_P ()" ++ "kslra16.u\t%0, %1, %2" ++ [(set_attr "type" "daluround") ++ (set_attr "length" "4")]) ++ ++(define_insn "cmpeq" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(eq:SI (match_operand:VQIHI 1 "register_operand" " r") ++ (match_operand:VQIHI 2 "register_operand" " r"))] ++ UNSPEC_VEC_COMPARE))] ++ "NDS32_EXT_DSP_P ()" ++ "cmpeq\t%0, %1, %2" ++ [(set_attr "type" "dcmp") ++ (set_attr "length" "4")]) ++ ++(define_insn "scmplt" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(lt:SI (match_operand:VQIHI 1 "register_operand" " r") ++ (match_operand:VQIHI 2 "register_operand" " r"))] ++ UNSPEC_VEC_COMPARE))] ++ "NDS32_EXT_DSP_P ()" ++ "scmplt\t%0, %1, %2" ++ [(set_attr "type" "dcmp") ++ (set_attr "length" "4")]) ++ ++(define_insn "scmple" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(le:SI (match_operand:VQIHI 1 "register_operand" " r") ++ (match_operand:VQIHI 2 "register_operand" " r"))] ++ UNSPEC_VEC_COMPARE))] ++ "NDS32_EXT_DSP_P ()" ++ "scmple\t%0, %1, %2" ++ [(set_attr "type" "dcmp") ++ (set_attr "length" "4")]) ++ ++(define_insn "ucmplt" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(ltu:SI (match_operand:VQIHI 1 "register_operand" " r") ++ (match_operand:VQIHI 2 "register_operand" " r"))] ++ UNSPEC_VEC_COMPARE))] ++ "NDS32_EXT_DSP_P ()" ++ "ucmplt\t%0, %1, %2" ++ [(set_attr "type" "dcmp") ++ (set_attr "length" "4")]) ++ ++(define_insn "ucmple" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(leu:SI (match_operand:VQIHI 1 "register_operand" " r") ++ (match_operand:VQIHI 2 "register_operand" " r"))] ++ UNSPEC_VEC_COMPARE))] ++ "NDS32_EXT_DSP_P ()" ++ "ucmple\t%0, %1, %2" ++ [(set_attr "type" "dcmp") ++ (set_attr "length" "4")]) ++ ++(define_insn "sclip16" ++ [(set (match_operand:V2HI 0 "register_operand" "= r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" " r") ++ (match_operand:SI 2 "nds32_imm4u_operand" " Iu04")] ++ UNSPEC_CLIPS))] ++ "NDS32_EXT_DSP_P ()" ++ "sclip16\t%0, %1, %2" ++ [(set_attr "type" "dclip") ++ (set_attr "length" "4")]) ++ ++(define_insn "uclip16" ++ [(set (match_operand:V2HI 0 "register_operand" "= r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" " r") ++ (match_operand:SI 2 "nds32_imm4u_operand" " Iu04")] ++ UNSPEC_CLIP))] ++ "NDS32_EXT_DSP_P ()" ++ "uclip16\t%0, %1, %2" ++ [(set_attr "type" "dclip") ++ (set_attr "length" "4")]) ++ ++(define_insn "khm16" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" " r") ++ (match_operand:V2HI 2 "register_operand" " r")] ++ UNSPEC_KHM))] ++ "NDS32_EXT_DSP_P ()" ++ "khm16\t%0, %1, %2" ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_insn "khmx16" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" " r") ++ (match_operand:V2HI 2 "register_operand" " r")] ++ UNSPEC_KHMX))] ++ "NDS32_EXT_DSP_P ()" ++ "khmx16\t%0, %1, %2" ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_expand "vec_setv4qi" ++ [(match_operand:V4QI 0 "register_operand" "") ++ (match_operand:QI 1 "register_operand" "") ++ (match_operand:SI 2 "immediate_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ HOST_WIDE_INT pos = INTVAL (operands[2]); ++ if (pos > 4) ++ gcc_unreachable (); ++ HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << pos; ++ emit_insn (gen_vec_setv4qi_internal (operands[0], operands[1], ++ operands[0], GEN_INT (elem))); ++ DONE; ++}) ++ ++(define_expand "insb" ++ [(match_operand:V4QI 0 "register_operand" "") ++ (match_operand:V4QI 1 "register_operand" "") ++ (match_operand:SI 2 "register_operand" "") ++ (match_operand:SI 3 "const_int_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (INTVAL (operands[3]) > 3 || INTVAL (operands[3]) < 0) ++ gcc_unreachable (); ++ ++ rtx src = gen_reg_rtx (QImode); ++ ++ convert_move (src, operands[2], false); ++ ++ HOST_WIDE_INT selector_index; ++ /* Big endian need reverse index. */ ++ if (TARGET_BIG_ENDIAN) ++ selector_index = 4 - INTVAL (operands[3]) - 1; ++ else ++ selector_index = INTVAL (operands[3]); ++ rtx selector = gen_int_mode (1 << selector_index, SImode); ++ emit_insn (gen_vec_setv4qi_internal (operands[0], src, ++ operands[1], selector)); ++ DONE; ++}) ++ ++(define_expand "insvsi" ++ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "const_int_operand" "") ++ (match_operand:SI 2 "nds32_insv_operand" "")) ++ (match_operand:SI 3 "register_operand" ""))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (INTVAL (operands[1]) != 8) ++ FAIL; ++} ++ [(set_attr "type" "dinsb") ++ (set_attr "length" "4")]) ++ ++ ++(define_insn "insvsi_internal" ++ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") ++ (const_int 8) ++ (match_operand:SI 1 "nds32_insv_operand" "i")) ++ (match_operand:SI 2 "register_operand" "r"))] ++ "NDS32_EXT_DSP_P ()" ++ "insb\t%0, %2, %v1" ++ [(set_attr "type" "dinsb") ++ (set_attr "length" "4")]) ++ ++(define_insn "insvsiqi_internal" ++ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") ++ (const_int 8) ++ (match_operand:SI 1 "nds32_insv_operand" "i")) ++ (zero_extend:SI (match_operand:QI 2 "register_operand" "r")))] ++ "NDS32_EXT_DSP_P ()" ++ "insb\t%0, %2, %v1" ++ [(set_attr "type" "dinsb") ++ (set_attr "length" "4")]) ++ ++;; Intermedium pattern for synthetize insvsiqi_internal ++;; v0 = ((v1 & 0xff) << 8) ++(define_insn_and_split "and0xff_s8" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") ++ (const_int 8)) ++ (const_int 65280)))] ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx tmp = gen_reg_rtx (SImode); ++ emit_insn (gen_ashlsi3 (tmp, operands[1], gen_int_mode (8, SImode))); ++ emit_insn (gen_andsi3 (operands[0], tmp, gen_int_mode (0xffff, SImode))); ++ DONE; ++}) ++ ++;; v0 = (v1 & 0xff00ffff) | ((v2 << 16) | 0xff0000) ++(define_insn_and_split "insbsi2" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0") ++ (const_int -16711681)) ++ (and:SI (ashift:SI (match_operand:SI 2 "register_operand" "r") ++ (const_int 16)) ++ (const_int 16711680))))] ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx tmp = gen_reg_rtx (SImode); ++ emit_move_insn (tmp, operands[1]); ++ emit_insn (gen_insvsi_internal (tmp, gen_int_mode(16, SImode), operands[2])); ++ emit_move_insn (operands[0], tmp); ++ DONE; ++}) ++ ++;; v0 = (v1 & 0xff00ffff) | v2 ++(define_insn_and_split "ior_and0xff00ffff_reg" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "r") ++ (const_int -16711681)) ++ (match_operand:SI 2 "register_operand" "r")))] ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx tmp = gen_reg_rtx (SImode); ++ emit_insn (gen_andsi3 (tmp, operands[1], gen_int_mode (0xff00ffff, SImode))); ++ emit_insn (gen_iorsi3 (operands[0], tmp, operands[2])); ++ DONE; ++}) ++ ++(define_insn "vec_setv4qi_internal" ++ [(set (match_operand:V4QI 0 "register_operand" "= r, r, r, r") ++ (vec_merge:V4QI ++ (vec_duplicate:V4QI ++ (match_operand:QI 1 "register_operand" " r, r, r, r")) ++ (match_operand:V4QI 2 "register_operand" " 0, 0, 0, 0") ++ (match_operand:SI 3 "nds32_imm_1_2_4_8_operand" " Iv01, Iv02, Iv04, Iv08")))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "insb\t%0, %1, 3", ++ "insb\t%0, %1, 2", ++ "insb\t%0, %1, 1", ++ "insb\t%0, %1, 0" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "insb\t%0, %1, 0", ++ "insb\t%0, %1, 1", ++ "insb\t%0, %1, 2", ++ "insb\t%0, %1, 3" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dinsb") ++ (set_attr "length" "4")]) ++ ++(define_insn "vec_setv4qi_internal_vec" ++ [(set (match_operand:V4QI 0 "register_operand" "= r, r, r, r") ++ (vec_merge:V4QI ++ (vec_duplicate:V4QI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r, r, r, r") ++ (parallel [(const_int 0)]))) ++ (match_operand:V4QI 2 "register_operand" " 0, 0, 0, 0") ++ (match_operand:SI 3 "nds32_imm_1_2_4_8_operand" " Iv01, Iv02, Iv04, Iv08")))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ insb\t%0, %1, 0 ++ insb\t%0, %1, 1 ++ insb\t%0, %1, 2 ++ insb\t%0, %1, 3" ++ [(set_attr "type" "dinsb") ++ (set_attr "length" "4")]) ++ ++(define_insn "vec_mergev4qi_and_cv0_1" ++ [(set (match_operand:V4QI 0 "register_operand" "=$l,r") ++ (vec_merge:V4QI ++ (vec_duplicate:V4QI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " l,r") ++ (parallel [(const_int 0)]))) ++ (const_vector:V4QI [ ++ (const_int 0) ++ (const_int 0) ++ (const_int 0) ++ (const_int 0)]) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ zeb33\t%0, %1 ++ zeb\t%0, %1" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_mergev4qi_and_cv0_2" ++ [(set (match_operand:V4QI 0 "register_operand" "=$l,r") ++ (vec_merge:V4QI ++ (const_vector:V4QI [ ++ (const_int 0) ++ (const_int 0) ++ (const_int 0) ++ (const_int 0)]) ++ (vec_duplicate:V4QI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " l,r") ++ (parallel [(const_int 0)]))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ zeb33\t%0, %1 ++ zeb\t%0, %1" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_mergeqi_and_cv0_1" ++ [(set (match_operand:V4QI 0 "register_operand" "=$l,r") ++ (vec_merge:V4QI ++ (vec_duplicate:V4QI (match_operand:QI 1 "register_operand" " l,r")) ++ (const_vector:V4QI [ ++ (const_int 0) ++ (const_int 0) ++ (const_int 0) ++ (const_int 0)]) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ zeb33\t%0, %1 ++ zeb\t%0, %1" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_mergeqi_and_cv0_2" ++ [(set (match_operand:V4QI 0 "register_operand" "=$l,r") ++ (vec_merge:V4QI ++ (const_vector:V4QI [ ++ (const_int 0) ++ (const_int 0) ++ (const_int 0) ++ (const_int 0)]) ++ (vec_duplicate:V4QI (match_operand:QI 1 "register_operand" " l,r")) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ zeb33\t%0, %1 ++ zeb\t%0, %1" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_expand "vec_setv2hi" ++ [(match_operand:V2HI 0 "register_operand" "") ++ (match_operand:HI 1 "register_operand" "") ++ (match_operand:SI 2 "immediate_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ HOST_WIDE_INT pos = INTVAL (operands[2]); ++ if (pos > 2) ++ gcc_unreachable (); ++ HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << pos; ++ emit_insn (gen_vec_setv2hi_internal (operands[0], operands[1], ++ operands[0], GEN_INT (elem))); ++ DONE; ++}) ++ ++(define_insn "vec_setv2hi_internal" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (match_operand:HI 1 "register_operand" " r, r")) ++ (match_operand:V2HI 2 "register_operand" " r, r") ++ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv02")))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "pkbb16\t%0, %1, %2", ++ "pktb16\t%0, %2, %1" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "pktb16\t%0, %2, %1", ++ "pkbb16\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "vec_mergev2hi_and_cv0_1" ++ [(set (match_operand:V2HI 0 "register_operand" "=$l,r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " l,r") ++ (parallel [(const_int 0)]))) ++ (const_vector:V2HI [ ++ (const_int 0) ++ (const_int 0)]) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ zeh33\t%0, %1 ++ zeh\t%0, %1" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_mergev2hi_and_cv0_2" ++ [(set (match_operand:V2HI 0 "register_operand" "=$l,r") ++ (vec_merge:V2HI ++ (const_vector:V2HI [ ++ (const_int 0) ++ (const_int 0)]) ++ (vec_duplicate:V2HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " l,r") ++ (parallel [(const_int 0)]))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ zeh33\t%0, %1 ++ zeh\t%0, %1" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_mergehi_and_cv0_1" ++ [(set (match_operand:V2HI 0 "register_operand" "=$l,r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI (match_operand:HI 1 "register_operand" " l,r")) ++ (const_vector:V2HI [ ++ (const_int 0) ++ (const_int 0)]) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ zeh33\t%0, %1 ++ zeh\t%0, %1" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_mergehi_and_cv0_2" ++ [(set (match_operand:V2HI 0 "register_operand" "=$l,r") ++ (vec_merge:V2HI ++ (const_vector:V2HI [ ++ (const_int 0) ++ (const_int 0)]) ++ (vec_duplicate:V2HI (match_operand:HI 1 "register_operand" " l,r")) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ zeh33\t%0, %1 ++ zeh\t%0, %1" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_expand "pkbb" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V2HI 1 "register_operand") ++ (match_operand:V2HI 2 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], ++ GEN_INT (1), GEN_INT (1), GEN_INT (1))); ++ } ++ else ++ { ++ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], ++ GEN_INT (2), GEN_INT (0), GEN_INT (0))); ++ } ++ DONE; ++}) ++ ++(define_insn "pkbbsi_1" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "r") ++ (const_int 65535)) ++ (ashift:SI (match_operand:SI 2 "register_operand" "r") ++ (const_int 16))))] ++ "NDS32_EXT_DSP_P ()" ++ "pkbb16\t%0, %2, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "pkbbsi_2" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI (ashift:SI (match_operand:SI 2 "register_operand" "r") ++ (const_int 16)) ++ (and:SI (match_operand:SI 1 "register_operand" "r") ++ (const_int 65535))))] ++ "NDS32_EXT_DSP_P ()" ++ "pkbb16\t%0, %2, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "pkbbsi_3" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) ++ (ashift:SI (match_operand:SI 2 "register_operand" "r") ++ (const_int 16))))] ++ "NDS32_EXT_DSP_P ()" ++ "pkbb16\t%0, %2, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "pkbbsi_4" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI (ashift:SI (match_operand:SI 2 "register_operand" "r") ++ (const_int 16)) ++ (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))))] ++ "NDS32_EXT_DSP_P ()" ++ "pkbb16\t%0, %2, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++;; v0 = (v1 & 0xffff0000) | (v2 & 0xffff) ++(define_insn "pktbsi_1" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "r") ++ (const_int -65536)) ++ (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] ++ "NDS32_EXT_DSP_P ()" ++ "pktb16\t%0, %1, %2" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "pktbsi_2" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI (and:SI (match_operand:SI 1 "register_operand" "r") ++ (const_int -65536)) ++ (and:SI (match_operand:SI 2 "register_operand" "r") ++ (const_int 65535))))] ++ "NDS32_EXT_DSP_P ()" ++ "pktb16\t%0, %1, %2" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "pktbsi_3" ++ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") ++ (const_int 16 ) ++ (const_int 0)) ++ (match_operand:SI 1 "register_operand" " r"))] ++ "NDS32_EXT_DSP_P ()" ++ "pktb16\t%0, %0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "pktbsi_4" ++ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") ++ (const_int 16 ) ++ (const_int 0)) ++ (zero_extend:SI (match_operand:HI 1 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "pktb16\t%0, %0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "pkttsi" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI (and:SI (match_operand:SI 1 "register_operand" " r") ++ (const_int -65536)) ++ (lshiftrt:SI (match_operand:SI 2 "register_operand" " r") ++ (const_int 16))))] ++ "NDS32_EXT_DSP_P ()" ++ "pktt16\t%0, %1, %2" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_expand "pkbt" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V2HI 1 "register_operand") ++ (match_operand:V2HI 2 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], ++ GEN_INT (1), GEN_INT (1), GEN_INT (0))); ++ } ++ else ++ { ++ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], ++ GEN_INT (2), GEN_INT (0), GEN_INT (1))); ++ } ++ DONE; ++}) ++ ++(define_expand "pktt" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V2HI 1 "register_operand") ++ (match_operand:V2HI 2 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], ++ GEN_INT (1), GEN_INT (0), GEN_INT (0))); ++ } ++ else ++ { ++ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], ++ GEN_INT (2), GEN_INT (1), GEN_INT (1))); ++ } ++ DONE; ++}) ++ ++(define_expand "pktb" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V2HI 1 "register_operand") ++ (match_operand:V2HI 2 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], ++ GEN_INT (1), GEN_INT (0), GEN_INT (1))); ++ } ++ else ++ { ++ emit_insn (gen_vec_mergevv (operands[0], operands[1], operands[2], ++ GEN_INT (2), GEN_INT (1), GEN_INT (0))); ++ } ++ DONE; ++}) ++ ++(define_insn "vec_mergerr" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (match_operand:HI 1 "register_operand" " r, r")) ++ (vec_duplicate:V2HI ++ (match_operand:HI 2 "register_operand" " r, r")) ++ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv02")))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ pkbb16\t%0, %2, %1 ++ pkbb16\t%0, %1, %2" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++ ++(define_insn "vec_merge" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r") ++ (vec_merge:V2HI ++ (match_operand:V2HI 1 "register_operand" " r, r") ++ (match_operand:V2HI 2 "register_operand" " r, r") ++ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv02")))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "pktb16\t%0, %1, %2", ++ "pktb16\t%0, %2, %1" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "pktb16\t%0, %2, %1", ++ "pktb16\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "vec_mergerv" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r, r, r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (match_operand:HI 1 "register_operand" " r, r, r, r")) ++ (vec_duplicate:V2HI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r, r, r, r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv00, Iv01")]))) ++ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv01, Iv02, Iv02")))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ pkbb16\t%0, %2, %1 ++ pktb16\t%0, %2, %1 ++ pkbb16\t%0, %1, %2 ++ pkbt16\t%0, %1, %2" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "vec_mergevr" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r, r, r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r, r, r, r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv00, Iv01")]))) ++ (vec_duplicate:V2HI ++ (match_operand:HI 2 "register_operand" " r, r, r, r")) ++ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv01, Iv02, Iv02")))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ pkbb16\t%0, %2, %1 ++ pkbt16\t%0, %2, %1 ++ pkbb16\t%0, %1, %2 ++ pktb16\t%0, %1, %2" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "vec_mergevv" ++ [(set (match_operand:V2HI 0 "register_operand" "= r, r, r, r, r, r, r, r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r, r, r, r, r, r, r, r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv00, Iv01, Iv01, Iv00, Iv00, Iv01, Iv01")]))) ++ (vec_duplicate:V2HI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r, r, r, r, r, r, r, r") ++ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv01, Iv00, Iv00, Iv01, Iv01, Iv00")]))) ++ (match_operand:SI 3 "nds32_imm_1_2_operand" " Iv01, Iv01, Iv01, Iv01, Iv02, Iv02, Iv02, Iv02")))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "pktt16\t%0, %1, %2", ++ "pktb16\t%0, %1, %2", ++ "pkbb16\t%0, %1, %2", ++ "pkbt16\t%0, %1, %2", ++ "pktt16\t%0, %2, %1", ++ "pkbt16\t%0, %2, %1", ++ "pkbb16\t%0, %2, %1", ++ "pktb16\t%0, %2, %1" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "pkbb16\t%0, %2, %1", ++ "pktb16\t%0, %2, %1", ++ "pktt16\t%0, %2, %1", ++ "pkbt16\t%0, %2, %1", ++ "pkbb16\t%0, %1, %2", ++ "pkbt16\t%0, %1, %2", ++ "pktt16\t%0, %1, %2", ++ "pktb16\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_expand "vec_extractv4qi" ++ [(set (match_operand:QI 0 "register_operand" "") ++ (vec_select:QI ++ (match_operand:V4QI 1 "nonimmediate_operand" "") ++ (parallel [(match_operand:SI 2 "const_int_operand" "")])))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++{ ++ if (INTVAL (operands[2]) != 0 ++ && INTVAL (operands[2]) != 1 ++ && INTVAL (operands[2]) != 2 ++ && INTVAL (operands[2]) != 3) ++ gcc_unreachable (); ++ ++ if (INTVAL (operands[2]) != 0 && MEM_P (operands[0])) ++ FAIL; ++}) ++ ++(define_insn "vec_extractv4qi0" ++ [(set (match_operand:QI 0 "register_operand" "=l,r,r") ++ (vec_select:QI ++ (match_operand:V4QI 1 "nonimmediate_operand" " l,r,m") ++ (parallel [(const_int 0)])))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++{ ++ switch (which_alternative) ++ { ++ case 0: ++ return "zeb33\t%0, %1"; ++ case 1: ++ return "zeb\t%0, %1"; ++ case 2: ++ return nds32_output_32bit_load (operands, 1); ++ default: ++ gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "vec_extractv4qi0_ze" ++ [(set (match_operand:SI 0 "register_operand" "=l,r,r") ++ (zero_extend:SI ++ (vec_select:QI ++ (match_operand:V4QI 1 "nonimmediate_operand" " l,r,m") ++ (parallel [(const_int 0)]))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++{ ++ switch (which_alternative) ++ { ++ case 0: ++ return "zeb33\t%0, %1"; ++ case 1: ++ return "zeb\t%0, %1"; ++ case 2: ++ return nds32_output_32bit_load (operands, 1); ++ default: ++ gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "vec_extractv4qi0_se" ++ [(set (match_operand:SI 0 "register_operand" "=l,r,r") ++ (sign_extend:SI ++ (vec_select:QI ++ (match_operand:V4QI 1 "nonimmediate_operand" " l,r,m") ++ (parallel [(const_int 0)]))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++{ ++ switch (which_alternative) ++ { ++ case 0: ++ return "seb33\t%0, %1"; ++ case 1: ++ return "seb\t%0, %1"; ++ case 2: ++ return nds32_output_32bit_load_s (operands, 1); ++ default: ++ gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "vec_extractv4qi1" ++ [(set (match_operand:QI 0 "register_operand" "=r") ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 1)])))] ++ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx tmp = gen_reg_rtx (V4QImode); ++ emit_insn (gen_rotrv4qi_1 (tmp, operands[1])); ++ emit_insn (gen_vec_extractv4qi0 (operands[0], tmp)); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "vec_extractv4qi2" ++ [(set (match_operand:QI 0 "register_operand" "=r") ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 2)])))] ++ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx tmp = gen_reg_rtx (V4QImode); ++ emit_insn (gen_rotrv4qi_2 (tmp, operands[1])); ++ emit_insn (gen_vec_extractv4qi0 (operands[0], tmp)); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "vec_extractv4qi3" ++ [(set (match_operand:QI 0 "register_operand" "=r") ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 3)])))] ++ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx tmp = gen_reg_rtx (V4QImode); ++ emit_insn (gen_rotrv4qi_3 (tmp, operands[1])); ++ emit_insn (gen_vec_extractv4qi0 (operands[0], tmp)); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "vec_extractv4qi3_se" ++ [(set (match_operand:SI 0 "register_operand" "=$d,r") ++ (sign_extend:SI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " 0,r") ++ (parallel [(const_int 3)]))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ srai45\t%0, 24 ++ srai\t%0, %1, 24" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_extractv4qi3_ze" ++ [(set (match_operand:SI 0 "register_operand" "=$d,r") ++ (zero_extend:SI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " 0,r") ++ (parallel [(const_int 3)]))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ srli45\t%0, 24 ++ srli\t%0, %1, 24" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn_and_split "vec_extractv4qihi0" ++ [(set (match_operand:HI 0 "register_operand" "=r") ++ (sign_extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 0)]))))] ++ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx tmp = gen_reg_rtx (QImode); ++ emit_insn (gen_vec_extractv4qi0 (tmp, operands[1])); ++ emit_insn (gen_extendqihi2 (operands[0], tmp)); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "vec_extractv4qihi1" ++ [(set (match_operand:HI 0 "register_operand" "=r") ++ (sign_extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 1)]))))] ++ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx tmp = gen_reg_rtx (QImode); ++ emit_insn (gen_vec_extractv4qi1 (tmp, operands[1])); ++ emit_insn (gen_extendqihi2 (operands[0], tmp)); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "vec_extractv4qihi2" ++ [(set (match_operand:HI 0 "register_operand" "=r") ++ (sign_extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 2)]))))] ++ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx tmp = gen_reg_rtx (QImode); ++ emit_insn (gen_vec_extractv4qi2 (tmp, operands[1])); ++ emit_insn (gen_extendqihi2 (operands[0], tmp)); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "vec_extractv4qihi3" ++ [(set (match_operand:HI 0 "register_operand" "=r") ++ (sign_extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 3)]))))] ++ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx tmp = gen_reg_rtx (QImode); ++ emit_insn (gen_vec_extractv4qi3 (tmp, operands[1])); ++ emit_insn (gen_extendqihi2 (operands[0], tmp)); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_expand "vec_extractv2hi" ++ [(set (match_operand:HI 0 "register_operand" "") ++ (vec_select:HI ++ (match_operand:V2HI 1 "nonimmediate_operand" "") ++ (parallel [(match_operand:SI 2 "const_int_operand" "")])))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (INTVAL (operands[2]) != 0 ++ && INTVAL (operands[2]) != 1) ++ gcc_unreachable (); ++ ++ if (INTVAL (operands[2]) != 0 && MEM_P (operands[0])) ++ FAIL; ++}) ++ ++(define_insn "vec_extractv2hi0" ++ [(set (match_operand:HI 0 "register_operand" "=$l,r,r") ++ (vec_select:HI ++ (match_operand:V2HI 1 "nonimmediate_operand" " l,r,m") ++ (parallel [(const_int 0)])))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++{ ++ switch (which_alternative) ++ { ++ case 0: ++ return "seh33\t%0, %1"; ++ case 1: ++ return "seh\t%0, %1"; ++ case 2: ++ return nds32_output_32bit_load_s (operands, 2); ++ ++ default: ++ gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "alu,alu,load") ++ (set_attr "length" " 2, 4, 4")]) ++ ++(define_insn "vec_extractv2hi0_ze" ++ [(set (match_operand:SI 0 "register_operand" "=$l, r,$ l, *r") ++ (zero_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "nonimmediate_operand" " l, r, U33, m") ++ (parallel [(const_int 0)]))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++{ ++ switch (which_alternative) ++ { ++ case 0: ++ return "zeh33\t%0, %1"; ++ case 1: ++ return "zeh\t%0, %1"; ++ case 2: ++ return nds32_output_16bit_load (operands, 2); ++ case 3: ++ return nds32_output_32bit_load (operands, 2); ++ ++ default: ++ gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "alu,alu,load,load") ++ (set_attr "length" " 2, 4, 2, 4")]) ++ ++(define_insn "vec_extractv2hi0_se" ++ [(set (match_operand:SI 0 "register_operand" "=$l, r, r") ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "nonimmediate_operand" " l,r,m") ++ (parallel [(const_int 0)]))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++{ ++ switch (which_alternative) ++ { ++ case 0: ++ return "seh33\t%0, %1"; ++ case 1: ++ return "seh\t%0, %1"; ++ case 2: ++ return nds32_output_32bit_load_s (operands, 2); ++ ++ default: ++ gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "alu,alu,load") ++ (set_attr "length" " 2, 4, 4")]) ++ ++(define_insn "vec_extractv2hi0_be" ++ [(set (match_operand:HI 0 "register_operand" "=$d,r") ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " 0,r") ++ (parallel [(const_int 0)])))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "@ ++ srai45\t%0, 16 ++ srai\t%0, %1, 16" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_extractv2hi1" ++ [(set (match_operand:HI 0 "register_operand" "=$d,r") ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " 0,r") ++ (parallel [(const_int 1)])))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ srai45\t%0, 16 ++ srai\t%0, %1, 16" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_extractv2hi1_se" ++ [(set (match_operand:SI 0 "register_operand" "=$d,r") ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " 0,r") ++ (parallel [(const_int 1)]))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ srai45\t%0, 16 ++ srai\t%0, %1, 16" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_extractv2hi1_ze" ++ [(set (match_operand:SI 0 "register_operand" "=$d,r") ++ (zero_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " 0,r") ++ (parallel [(const_int 1)]))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "@ ++ srli45\t%0, 16 ++ srli\t%0, %1, 16" ++ [(set_attr "type" "alu,alu") ++ (set_attr "length" " 2, 4")]) ++ ++(define_insn "vec_extractv2hi1_be" ++ [(set (match_operand:HI 0 "register_operand" "=$l,r,r") ++ (vec_select:HI ++ (match_operand:V2HI 1 "nonimmediate_operand" " l,r,m") ++ (parallel [(const_int 1)])))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++{ ++ switch (which_alternative) ++ { ++ case 0: ++ return "seh33\t%0, %1"; ++ case 1: ++ return "seh\t%0, %1"; ++ case 2: ++ return nds32_output_32bit_load_s (operands, 2); ++ ++ default: ++ gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "alu,alu,load") ++ (set_attr "length" " 2, 4, 4")]) ++ ++(define_insn "mul16" ++ [(set (match_operand:V2SI 0 "register_operand" "=r") ++ (mult:V2SI (extend:V2SI (match_operand:V2HI 1 "register_operand" "%r")) ++ (extend:V2SI (match_operand:V2HI 2 "register_operand" " r"))))] ++ "NDS32_EXT_DSP_P ()" ++ "mul16\t%0, %1, %2" ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_insn "mulx16" ++ [(set (match_operand:V2SI 0 "register_operand" "=r") ++ (vec_merge:V2SI ++ (vec_duplicate:V2SI ++ (mult:SI ++ (extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))))) ++ (vec_duplicate:V2SI ++ (mult:SI ++ (extend:SI ++ (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)]))) ++ (extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P ()" ++ "mulx16\t%0, %1, %2" ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_insn "rotrv2hi_1" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_select:V2HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1) (const_int 0)])))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "rotri\t%0, %1, 16" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "rotrv2hi_1_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_select:V2HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0) (const_int 1)])))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "rotri\t%0, %1, 16" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "rotrv4qi_1" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (vec_select:V4QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 1) (const_int 2) (const_int 3) (const_int 0)])))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "rotri\t%0, %1, 8" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "rotrv4qi_1_be" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (vec_select:V4QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 2) (const_int 1) (const_int 0) (const_int 3)])))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "rotri\t%0, %1, 8" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "rotrv4qi_2" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (vec_select:V4QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 2) (const_int 3) (const_int 0) (const_int 1)])))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "rotri\t%0, %1, 16" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "rotrv4qi_2_be" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (vec_select:V4QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 1) (const_int 0) (const_int 3) (const_int 2)])))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "rotri\t%0, %1, 16" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "rotrv4qi_3" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (vec_select:V4QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 3) (const_int 0) (const_int 1) (const_int 2)])))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "rotri\t%0, %1, 24" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "rotrv4qi_3_be" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (vec_select:V4QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 0) (const_int 3) (const_int 2) (const_int 1)])))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "rotri\t%0, %1, 24" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "v4qi_dup_10" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (vec_select:V4QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 0) (const_int 1) (const_int 0) (const_int 1)])))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "pkbb\t%0, %1, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "v4qi_dup_32" ++ [(set (match_operand:V4QI 0 "register_operand" "=r") ++ (vec_select:V4QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 2) (const_int 3) (const_int 2) (const_int 3)])))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "pktt\t%0, %1, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_expand "vec_unpacks_lo_v4qi" ++ [(match_operand:V2HI 0 "register_operand" "=r") ++ (match_operand:V4QI 1 "register_operand" " r")] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++{ ++ emit_insn (gen_sunpkd810 (operands[0], operands[1])); ++ DONE; ++}) ++ ++(define_expand "sunpkd810" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V4QI 1 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_sunpkd810_imp_be (operands[0], operands[1])); ++ else ++ emit_insn (gen_sunpkd810_imp (operands[0], operands[1])); ++ DONE; ++}) ++ ++(define_insn "unpkd810_imp" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 0)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "unpkd810\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd810_imp_inv" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 1)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "unpkd810\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd810_imp_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 2)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 3)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "unpkd810\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd810_imp_inv_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 3)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 2)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "unpkd810\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_expand "sunpkd820" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V4QI 1 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_sunpkd820_imp_be (operands[0], operands[1])); ++ else ++ emit_insn (gen_sunpkd820_imp (operands[0], operands[1])); ++ DONE; ++}) ++ ++(define_insn "unpkd820_imp" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 2)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 0)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "unpkd820\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd820_imp_inv" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 2)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "unpkd820\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd820_imp_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 3)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "unpkd820\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd820_imp_inv_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 3)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 1)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "unpkd820\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_expand "sunpkd830" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V4QI 1 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_sunpkd830_imp_be (operands[0], operands[1])); ++ else ++ emit_insn (gen_sunpkd830_imp (operands[0], operands[1])); ++ DONE; ++}) ++ ++(define_insn "unpkd830_imp" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 3)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 0)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "unpkd830\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd830_imp_inv" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 3)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "unpkd830\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd830_imp_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 3)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "unpkd830\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd830_imp_inv_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 3)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 0)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "unpkd830\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_expand "sunpkd831" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V4QI 1 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_sunpkd831_imp_be (operands[0], operands[1])); ++ else ++ emit_insn (gen_sunpkd831_imp (operands[0], operands[1])); ++ DONE; ++}) ++ ++(define_insn "unpkd831_imp" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 3)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 1)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "unpkd831\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd831_imp_inv" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 3)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "unpkd831\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd831_imp_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 2)])))) ++ (const_int 1)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "unpkd831\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "unpkd831_imp_inv_be" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 2)])))) ++ (vec_duplicate:V2HI ++ (extend:HI ++ (vec_select:QI ++ (match_dup 1) ++ (parallel [(const_int 0)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "unpkd831\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_expand "zunpkd810" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V4QI 1 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_zunpkd810_imp_be (operands[0], operands[1])); ++ else ++ emit_insn (gen_zunpkd810_imp (operands[0], operands[1])); ++ DONE; ++}) ++ ++(define_expand "zunpkd820" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V4QI 1 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_zunpkd820_imp_be (operands[0], operands[1])); ++ else ++ emit_insn (gen_zunpkd820_imp (operands[0], operands[1])); ++ DONE; ++}) ++ ++(define_expand "zunpkd830" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V4QI 1 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_zunpkd830_imp_be (operands[0], operands[1])); ++ else ++ emit_insn (gen_zunpkd830_imp (operands[0], operands[1])); ++ DONE; ++}) ++ ++(define_expand "zunpkd831" ++ [(match_operand:V2HI 0 "register_operand") ++ (match_operand:V4QI 1 "register_operand")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_zunpkd831_imp_be (operands[0], operands[1])); ++ else ++ emit_insn (gen_zunpkd831_imp (operands[0], operands[1])); ++ DONE; ++}) ++ ++(define_expand "smbb" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], ++ GEN_INT (1), GEN_INT (1))); ++ else ++ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], ++ GEN_INT (0), GEN_INT (0))); ++ DONE; ++}) ++ ++(define_expand "smbt" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], ++ GEN_INT (1), GEN_INT (0))); ++ else ++ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], ++ GEN_INT (0), GEN_INT (1))); ++ DONE; ++}) ++ ++(define_expand "smtt" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], ++ GEN_INT (0), GEN_INT (0))); ++ else ++ emit_insn (gen_mulhisi3v (operands[0], operands[1], operands[2], ++ GEN_INT (1), GEN_INT (1))); ++ DONE; ++}) ++ ++(define_insn "mulhisi3v" ++ [(set (match_operand:SI 0 "register_operand" "= r, r, r, r") ++ (mult:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r, r, r, r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv00, Iv01, Iv01")]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r, r, r, r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv01, Iv00")])))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "smtt\t%0, %1, %2", ++ "smbt\t%0, %2, %1", ++ "smbb\t%0, %1, %2", ++ "smbt\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "smbb\t%0, %1, %2", ++ "smbt\t%0, %1, %2", ++ "smtt\t%0, %1, %2", ++ "smbt\t%0, %2, %1" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_expand "kmabb" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "") ++ (match_operand:V2HI 3 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], ++ GEN_INT (1), GEN_INT (1), ++ operands[1])); ++ else ++ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], ++ GEN_INT (0), GEN_INT (0), ++ operands[1])); ++ DONE; ++}) ++ ++(define_expand "kmabt" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "") ++ (match_operand:V2HI 3 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], ++ GEN_INT (1), GEN_INT (0), ++ operands[1])); ++ else ++ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], ++ GEN_INT (0), GEN_INT (1), ++ operands[1])); ++ DONE; ++}) ++ ++(define_expand "kmatt" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "") ++ (match_operand:V2HI 3 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], ++ GEN_INT (0), GEN_INT (0), ++ operands[1])); ++ else ++ emit_insn (gen_kma_internal (operands[0], operands[2], operands[3], ++ GEN_INT (1), GEN_INT (1), ++ operands[1])); ++ DONE; ++}) ++ ++(define_insn "kma_internal" ++ [(set (match_operand:SI 0 "register_operand" "= r, r, r, r") ++ (ss_plus:SI ++ (mult:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r, r, r, r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv00, Iv01, Iv01")]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r, r, r, r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv01, Iv00")])))) ++ (match_operand:SI 5 "register_operand" " 0, 0, 0, 0")))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "kmatt\t%0, %1, %2", ++ "kmabt\t%0, %2, %1", ++ "kmabb\t%0, %1, %2", ++ "kmabt\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "kmabb\t%0, %1, %2", ++ "kmabt\t%0, %1, %2", ++ "kmatt\t%0, %1, %2", ++ "kmabt\t%0, %2, %1" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_expand "smds" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smds_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_smds_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_expand "smds_le" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++}) ++ ++(define_expand "smds_be" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++}) ++ ++(define_expand "smdrs" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smdrs_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_smdrs_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_expand "smdrs_le" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++}) ++ ++(define_expand "smdrs_be" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++}) ++ ++(define_expand "smxdsv" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:V2HI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smxdsv_be (operands[0], operands[1], operands[2])); ++ else ++ emit_insn (gen_smxdsv_le (operands[0], operands[1], operands[2])); ++ DONE; ++}) ++ ++ ++(define_expand "smxdsv_le" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++}) ++ ++(define_expand "smxdsv_be" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++}) ++ ++(define_insn "smal1" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI (match_operand:DI 1 "register_operand" " r") ++ (sign_extend:DI ++ (mult:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "smal\t%0, %1, %2" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smal2" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI (match_operand:DI 1 "register_operand" " r") ++ (mult:DI ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:DI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))))))] ++ "NDS32_EXT_DSP_P ()" ++ "smal\t%0, %1, %2" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smal3" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI (match_operand:DI 1 "register_operand" " r") ++ (sign_extend:DI ++ (mult:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "smal\t%0, %1, %2" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smal4" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI (match_operand:DI 1 "register_operand" " r") ++ (mult:DI ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:DI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))))))] ++ "NDS32_EXT_DSP_P ()" ++ "smal\t%0, %1, %2" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smal5" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (sign_extend:DI ++ (mult:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))))) ++ (match_operand:DI 1 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "smal\t%0, %1, %2" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smal6" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (mult:DI ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:DI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)])))) ++ (match_operand:DI 1 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "smal\t%0, %1, %2" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smal7" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (sign_extend:DI ++ (mult:SI ++ (sign_extend:SI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))))) ++ (match_operand:DI 1 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "smal\t%0, %1, %2" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smal8" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (mult:DI ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:DI ++ (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)])))) ++ (match_operand:DI 1 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "smal\t%0, %1, %2" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++;; We need this dummy pattern for smal ++(define_insn_and_split "extendsidi2" ++ [(set (match_operand:DI 0 "register_operand" "") ++ (sign_extend:DI (match_operand:SI 1 "nds32_move_operand" "")))] ++ "NDS32_EXT_DSP_P ()" ++ "#" ++ "NDS32_EXT_DSP_P ()" ++ [(const_int 0)] ++{ ++ rtx high_part_dst, low_part_dst; ++ ++ low_part_dst = nds32_di_low_part_subreg (operands[0]); ++ high_part_dst = nds32_di_high_part_subreg (operands[0]); ++ ++ emit_move_insn (low_part_dst, operands[1]); ++ emit_insn (gen_ashrsi3 (high_part_dst, low_part_dst, GEN_INT (31))); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++;; We need this dummy pattern for usmar64/usmsr64 ++(define_insn_and_split "zero_extendsidi2" ++ [(set (match_operand:DI 0 "register_operand" "") ++ (zero_extend:DI (match_operand:SI 1 "nds32_move_operand" "")))] ++ "NDS32_EXT_DSP_P ()" ++ "#" ++ "NDS32_EXT_DSP_P ()" ++ [(const_int 0)] ++{ ++ rtx high_part_dst, low_part_dst; ++ ++ low_part_dst = nds32_di_low_part_subreg (operands[0]); ++ high_part_dst = nds32_di_high_part_subreg (operands[0]); ++ ++ emit_move_insn (low_part_dst, operands[1]); ++ emit_move_insn (high_part_dst, const0_rtx); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "extendhidi2" ++ [(set (match_operand:DI 0 "register_operand" "") ++ (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "")))] ++ "NDS32_EXT_DSP_P ()" ++ "#" ++ "NDS32_EXT_DSP_P ()" ++ [(const_int 0)] ++{ ++ rtx high_part_dst, low_part_dst; ++ ++ low_part_dst = nds32_di_low_part_subreg (operands[0]); ++ high_part_dst = nds32_di_high_part_subreg (operands[0]); ++ ++ ++ emit_insn (gen_extendhisi2 (low_part_dst, operands[1])); ++ emit_insn (gen_ashrsi3 (high_part_dst, low_part_dst, GEN_INT (31))); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_insn "extendqihi2" ++ [(set (match_operand:HI 0 "register_operand" "=r") ++ (sign_extend:HI (match_operand:QI 1 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "sunpkd820\t%0, %1" ++ [(set_attr "type" "dpack") ++ (set_attr "length" "4")]) ++ ++(define_insn "smulsi3_highpart" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (truncate:SI ++ (lshiftrt:DI ++ (mult:DI ++ (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) ++ (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))) ++ (const_int 32))))] ++ "NDS32_EXT_DSP_P ()" ++ "smmul\t%0, %1, %2" ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_insn "smmul_round" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (truncate:SI ++ (lshiftrt:DI ++ (unspec:DI [(mult:DI ++ (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) ++ (sign_extend:DI (match_operand:SI 2 "register_operand" " r")))] ++ UNSPEC_ROUND) ++ (const_int 32))))] ++ "NDS32_EXT_DSP_P ()" ++ "smmul.u\t%0, %1, %2" ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmmac" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI (match_operand:SI 1 "register_operand" " 0") ++ (truncate:SI ++ (lshiftrt:DI ++ (mult:DI ++ (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) ++ (sign_extend:DI (match_operand:SI 3 "register_operand" " r"))) ++ (const_int 32)))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmmac\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmmac_round" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI (match_operand:SI 1 "register_operand" " 0") ++ (truncate:SI ++ (lshiftrt:DI ++ (unspec:DI [(mult:DI ++ (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) ++ (sign_extend:DI (match_operand:SI 3 "register_operand" " r")))] ++ UNSPEC_ROUND) ++ (const_int 32)))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmmac.u\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmmsb" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_minus:SI (match_operand:SI 1 "register_operand" " 0") ++ (truncate:SI ++ (lshiftrt:DI ++ (mult:DI ++ (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) ++ (sign_extend:DI (match_operand:SI 3 "register_operand" " r"))) ++ (const_int 32)))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmmsb\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmmsb_round" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_minus:SI (match_operand:SI 1 "register_operand" " 0") ++ (truncate:SI ++ (lshiftrt:DI ++ (unspec:DI [(mult:DI ++ (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) ++ (sign_extend:DI (match_operand:SI 3 "register_operand" " r")))] ++ UNSPEC_ROUND) ++ (const_int 32)))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmmsb.u\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kwmmul" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (truncate:SI ++ (lshiftrt:DI ++ (ss_mult:DI ++ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) (const_int 2)) ++ (mult:DI (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) (const_int 2))) ++ (const_int 32))))] ++ "NDS32_EXT_DSP_P ()" ++ "kwmmul\t%0, %1, %2" ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_insn "kwmmul_round" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (truncate:SI ++ (lshiftrt:DI ++ (unspec:DI [ ++ (ss_mult:DI ++ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) (const_int 2)) ++ (mult:DI (sign_extend:DI (match_operand:SI 2 "register_operand" " r")) (const_int 2)))] ++ UNSPEC_ROUND) ++ (const_int 32))))] ++ "NDS32_EXT_DSP_P ()" ++ "kwmmul.u\t%0, %1, %2" ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_expand "smmwb" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smulhisi3_highpart_1 (operands[0], operands[1], operands[2], GEN_INT (1))); ++ else ++ emit_insn (gen_smulhisi3_highpart_1 (operands[0], operands[1], operands[2], GEN_INT (0))); ++ DONE; ++}) ++ ++(define_expand "smmwt" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smulhisi3_highpart_1 (operands[0], operands[1], operands[2], GEN_INT (0))); ++ else ++ emit_insn (gen_smulhisi3_highpart_1 (operands[0], operands[1], operands[2], GEN_INT (1))); ++ DONE; ++}) ++ ++(define_insn "smulhisi3_highpart_1" ++ [(set (match_operand:SI 0 "register_operand" "= r, r") ++ (truncate:SI ++ (lshiftrt:DI ++ (mult:DI ++ (sign_extend:DI (match_operand:SI 1 "register_operand" " r, r")) ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r, r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv01")])))) ++ (const_int 16))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "smmwt\t%0, %1, %2", ++ "smmwb\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "smmwb\t%0, %1, %2", ++ "smmwt\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_insn "smulhisi3_highpart_2" ++ [(set (match_operand:SI 0 "register_operand" "= r, r") ++ (truncate:SI ++ (lshiftrt:DI ++ (mult:DI ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r, r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv01")]))) ++ (sign_extend:DI (match_operand:SI 2 "register_operand" " r, r"))) ++ (const_int 16))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "smmwt\t%0, %1, %2", ++ "smmwb\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "smmwb\t%0, %1, %2", ++ "smmwt\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_expand "smmwb_round" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smmw_round_internal (operands[0], operands[1], operands[2], GEN_INT (1))); ++ else ++ emit_insn (gen_smmw_round_internal (operands[0], operands[1], operands[2], GEN_INT (0))); ++ DONE; ++}) ++ ++(define_expand "smmwt_round" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smmw_round_internal (operands[0], operands[1], operands[2], GEN_INT (0))); ++ else ++ emit_insn (gen_smmw_round_internal (operands[0], operands[1], operands[2], GEN_INT (1))); ++ DONE; ++}) ++ ++(define_insn "smmw_round_internal" ++ [(set (match_operand:SI 0 "register_operand" "= r, r") ++ (truncate:SI ++ (lshiftrt:DI ++ (unspec:DI ++ [(mult:DI ++ (sign_extend:DI (match_operand:SI 1 "register_operand" " r, r")) ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r, r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv01")]))))] ++ UNSPEC_ROUND) ++ (const_int 16))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "smmwt.u\t%0, %1, %2", ++ "smmwb.u\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "smmwb.u\t%0, %1, %2", ++ "smmwt.u\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dmul") ++ (set_attr "length" "4")]) ++ ++(define_expand "kmmawb" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:SI 2 "register_operand" "") ++ (match_operand:V2HI 3 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_kmmaw_internal (operands[0], operands[2], operands[3], GEN_INT (1), operands[1])); ++ else ++ emit_insn (gen_kmmaw_internal (operands[0], operands[2], operands[3], GEN_INT (0), operands[1])); ++ DONE; ++}) ++ ++(define_expand "kmmawt" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:SI 2 "register_operand" "") ++ (match_operand:V2HI 3 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_kmmaw_internal (operands[0], operands[2], operands[3], GEN_INT (0), operands[1])); ++ else ++ emit_insn (gen_kmmaw_internal (operands[0], operands[2], operands[3], GEN_INT (1), operands[1])); ++ DONE; ++}) ++ ++(define_insn "kmmaw_internal" ++ [(set (match_operand:SI 0 "register_operand" "= r, r") ++ (ss_plus:SI ++ (match_operand:SI 4 "register_operand" " 0, 0") ++ (truncate:SI ++ (lshiftrt:DI ++ (mult:DI ++ (sign_extend:DI (match_operand:SI 1 "register_operand" " r, r")) ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r, r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv01")])))) ++ (const_int 16)))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "kmmawt\t%0, %1, %2", ++ "kmmawb\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "kmmawb\t%0, %1, %2", ++ "kmmawt\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_expand "kmmawb_round" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:SI 2 "register_operand" "") ++ (match_operand:V2HI 3 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_kmmaw_round_internal (operands[0], operands[2], operands[3], GEN_INT (1), operands[1])); ++ else ++ emit_insn (gen_kmmaw_round_internal (operands[0], operands[2], operands[3], GEN_INT (0), operands[1])); ++ DONE; ++} ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ ++(define_expand "kmmawt_round" ++ [(match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "") ++ (match_operand:SI 2 "register_operand" "") ++ (match_operand:V2HI 3 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_kmmaw_round_internal (operands[0], operands[2], operands[3], GEN_INT (0), operands[1])); ++ else ++ emit_insn (gen_kmmaw_round_internal (operands[0], operands[2], operands[3], GEN_INT (1), operands[1])); ++ DONE; ++} ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++ ++(define_insn "kmmaw_round_internal" ++ [(set (match_operand:SI 0 "register_operand" "= r, r") ++ (ss_plus:SI ++ (match_operand:SI 4 "register_operand" " 0, 0") ++ (truncate:SI ++ (lshiftrt:DI ++ (unspec:DI ++ [(mult:DI ++ (sign_extend:DI (match_operand:SI 1 "register_operand" " r, r")) ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r, r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iv00, Iv01")]))))] ++ UNSPEC_ROUND) ++ (const_int 16)))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "kmmawt.u\t%0, %1, %2", ++ "kmmawb.u\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "kmmawb.u\t%0, %1, %2", ++ "kmmawt.u\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_expand "smalbb" ++ [(match_operand:DI 0 "register_operand" "") ++ (match_operand:DI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "") ++ (match_operand:V2HI 3 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smaddhidi (operands[0], operands[2], ++ operands[3], operands[1], ++ GEN_INT (1), GEN_INT (1))); ++ else ++ emit_insn (gen_smaddhidi (operands[0], operands[2], ++ operands[3], operands[1], ++ GEN_INT (0), GEN_INT (0))); ++ DONE; ++}) ++ ++(define_expand "smalbt" ++ [(match_operand:DI 0 "register_operand" "") ++ (match_operand:DI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "") ++ (match_operand:V2HI 3 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smaddhidi (operands[0], operands[2], ++ operands[3], operands[1], ++ GEN_INT (1), GEN_INT (0))); ++ else ++ emit_insn (gen_smaddhidi (operands[0], operands[2], ++ operands[3], operands[1], ++ GEN_INT (0), GEN_INT (1))); ++ DONE; ++}) ++ ++(define_expand "smaltt" ++ [(match_operand:DI 0 "register_operand" "") ++ (match_operand:DI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" "") ++ (match_operand:V2HI 3 "register_operand" "")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smaddhidi (operands[0], operands[2], ++ operands[3], operands[1], ++ GEN_INT (0), GEN_INT (0))); ++ else ++ emit_insn (gen_smaddhidi (operands[0], operands[2], ++ operands[3], operands[1], ++ GEN_INT (1), GEN_INT (1))); ++ DONE; ++}) ++ ++(define_insn "smaddhidi" ++ [(set (match_operand:DI 0 "register_operand" "= r, r, r, r") ++ (plus:DI ++ (match_operand:DI 3 "register_operand" " 0, 0, 0, 0") ++ (mult:DI ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r, r, r, r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv00, Iv01, Iv01")]))) ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r, r, r, r") ++ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv01, Iv00")]))))))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "smaltt\t%0, %1, %2", ++ "smalbt\t%0, %2, %1", ++ "smalbb\t%0, %1, %2", ++ "smalbt\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "smalbb\t%0, %1, %2", ++ "smalbt\t%0, %1, %2", ++ "smaltt\t%0, %1, %2", ++ "smalbt\t%0, %2, %1" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smaddhidi2" ++ [(set (match_operand:DI 0 "register_operand" "= r, r, r, r") ++ (plus:DI ++ (mult:DI ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r, r, r, r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iv00, Iv00, Iv01, Iv01")]))) ++ (sign_extend:DI ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r, r, r, r") ++ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iv00, Iv01, Iv01, Iv00")])))) ++ (match_operand:DI 3 "register_operand" " 0, 0, 0, 0")))] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ { ++ const char *pats[] = { "smaltt\t%0, %1, %2", ++ "smalbt\t%0, %2, %1", ++ "smalbb\t%0, %1, %2", ++ "smalbt\t%0, %1, %2" }; ++ return pats[which_alternative]; ++ } ++ else ++ { ++ const char *pats[] = { "smalbb\t%0, %1, %2", ++ "smalbt\t%0, %1, %2", ++ "smaltt\t%0, %1, %2", ++ "smalbt\t%0, %2, %1" }; ++ return pats[which_alternative]; ++ } ++} ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_expand "smalda1" ++ [(match_operand:DI 0 "register_operand" "") ++ (match_operand:DI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" " r") ++ (match_operand:V2HI 3 "register_operand" " r")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smalda1_be (operands[0], operands[1], operands[2], operands[3])); ++ else ++ emit_insn (gen_smalda1_le (operands[0], operands[1], operands[2], operands[3])); ++ DONE; ++}) ++ ++(define_expand "smalds1" ++ [(match_operand:DI 0 "register_operand" "") ++ (match_operand:DI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" " r") ++ (match_operand:V2HI 3 "register_operand" " r")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smalds1_be (operands[0], operands[1], operands[2], operands[3])); ++ else ++ emit_insn (gen_smalds1_le (operands[0], operands[1], operands[2], operands[3])); ++ DONE; ++}) ++ ++(define_insn "smalda1_le" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (sign_extend:DI ++ (plus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 0)]))))))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "smalda\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smalds1_le" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (sign_extend:DI ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 0)]))))))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "smalds\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smalda1_be" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (sign_extend:DI ++ (plus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 1)]))))))))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "smalda\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smalds1_be" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (sign_extend:DI ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 1)]))))))))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "smalds\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_expand "smaldrs3" ++ [(match_operand:DI 0 "register_operand" "") ++ (match_operand:DI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" " r") ++ (match_operand:V2HI 3 "register_operand" " r")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smaldrs3_be (operands[0], operands[1], operands[2], operands[3])); ++ else ++ emit_insn (gen_smaldrs3_le (operands[0], operands[1], operands[2], operands[3])); ++ DONE; ++}) ++ ++(define_insn "smaldrs3_le" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (sign_extend:DI ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 1)]))))))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "smaldrs\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smaldrs3_be" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (sign_extend:DI ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 0)]))))))))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "smaldrs\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_expand "smalxda1" ++ [(match_operand:DI 0 "register_operand" "") ++ (match_operand:DI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" " r") ++ (match_operand:V2HI 3 "register_operand" " r")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smalxda1_be (operands[0], operands[1], operands[2], operands[3])); ++ else ++ emit_insn (gen_smalxda1_le (operands[0], operands[1], operands[2], operands[3])); ++ DONE; ++}) ++ ++(define_expand "smalxds1" ++ [(match_operand:DI 0 "register_operand" "") ++ (match_operand:DI 1 "register_operand" "") ++ (match_operand:V2HI 2 "register_operand" " r") ++ (match_operand:V2HI 3 "register_operand" " r")] ++ "NDS32_EXT_DSP_P ()" ++{ ++ if (TARGET_BIG_ENDIAN) ++ emit_insn (gen_smalxds1_be (operands[0], operands[1], operands[2], operands[3])); ++ else ++ emit_insn (gen_smalxds1_le (operands[0], operands[1], operands[2], operands[3])); ++ DONE; ++}) ++ ++(define_insn "smalxd1_le" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (sign_extend:DI ++ (plus_minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 1)]))))))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "smalxd\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++ ++(define_insn "smalxd1_be" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (sign_extend:DI ++ (plus_minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 0)]))))))))] ++ "NDS32_EXT_DSP_P () && TARGET_BIG_ENDIAN" ++ "smalxd\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smslda1" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (minus:DI ++ (minus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (sign_extend:DI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 1)])))))) ++ (sign_extend:DI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 0)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "smslda\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "smslxda1" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (minus:DI ++ (minus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (sign_extend:DI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 0)])))))) ++ (sign_extend:DI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 1)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "smslxda\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++;; mada for synthetize smalda ++(define_insn_and_split "mada1" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (plus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" "r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iu01")]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" "r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iu01")])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iu01")]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(match_operand:SI 6 "nds32_imm_0_1_operand" " Iu01")]))))))] ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx result0 = gen_reg_rtx (SImode); ++ rtx result1 = gen_reg_rtx (SImode); ++ emit_insn (gen_mulhisi3v (result0, operands[1], operands[2], ++ operands[3], operands[4])); ++ emit_insn (gen_mulhisi3v (result1, operands[1], operands[2], ++ operands[5], operands[6])); ++ emit_insn (gen_addsi3 (operands[0], result0, result1)); ++ DONE; ++}) ++ ++(define_insn_and_split "mada2" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (plus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" "r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iu01")]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" "r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iu01")])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iu01")]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(match_operand:SI 6 "nds32_imm_0_1_operand" " Iu01")]))))))] ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 1)] ++{ ++ rtx result0 = gen_reg_rtx (SImode); ++ rtx result1 = gen_reg_rtx (SImode); ++ emit_insn (gen_mulhisi3v (result0, operands[1], operands[2], ++ operands[3], operands[4])); ++ emit_insn (gen_mulhisi3v (result1, operands[1], operands[2], ++ operands[6], operands[5])); ++ emit_insn (gen_addsi3 (operands[0], result0, result1)); ++ DONE; ++}) ++ ++;; sms for synthetize smalds ++(define_insn_and_split "sms1" ++ [(set (match_operand:SI 0 "register_operand" "= r") ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iu01")]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iu01")])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iu01")]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(match_operand:SI 6 "nds32_imm_0_1_operand" " Iu01")]))))))] ++ "NDS32_EXT_DSP_P () ++ && (!reload_completed ++ || !nds32_need_split_sms_p (operands[3], operands[4], ++ operands[5], operands[6]))" ++ ++{ ++ return nds32_output_sms (operands[3], operands[4], ++ operands[5], operands[6]); ++} ++ "NDS32_EXT_DSP_P () ++ && !reload_completed ++ && nds32_need_split_sms_p (operands[3], operands[4], ++ operands[5], operands[6])" ++ [(const_int 1)] ++{ ++ nds32_split_sms (operands[0], operands[1], operands[2], ++ operands[3], operands[4], ++ operands[5], operands[6]); ++ DONE; ++} ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "sms2" ++ [(set (match_operand:SI 0 "register_operand" "= r") ++ (minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(match_operand:SI 3 "nds32_imm_0_1_operand" " Iu01")]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(match_operand:SI 4 "nds32_imm_0_1_operand" " Iu01")])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(match_operand:SI 5 "nds32_imm_0_1_operand" " Iu01")]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(match_operand:SI 6 "nds32_imm_0_1_operand" " Iu01")]))))))] ++ "NDS32_EXT_DSP_P () ++ && (!reload_completed ++ || !nds32_need_split_sms_p (operands[3], operands[4], ++ operands[6], operands[5]))" ++{ ++ return nds32_output_sms (operands[3], operands[4], ++ operands[6], operands[5]); ++} ++ "NDS32_EXT_DSP_P () ++ && !reload_completed ++ && nds32_need_split_sms_p (operands[3], operands[4], ++ operands[6], operands[5])" ++ [(const_int 1)] ++{ ++ nds32_split_sms (operands[0], operands[1], operands[2], ++ operands[3], operands[4], ++ operands[6], operands[5]); ++ DONE; ++} ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmda" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" "r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" "r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmda\t%0, %1, %2" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmxda" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" "r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" "r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 1) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmxda\t%0, %1, %2" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmada" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI ++ (match_operand:SI 1 "register_operand" " 0") ++ (ss_plus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 0)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmada\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmada2" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI ++ (match_operand:SI 1 "register_operand" " 0") ++ (ss_plus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 1)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmada\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmaxda" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI ++ (match_operand:SI 1 "register_operand" " 0") ++ (ss_plus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 1)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmaxda\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmads" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI ++ (match_operand:SI 1 "register_operand" " 0") ++ (ss_minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 0)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmads\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmadrs" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI ++ (match_operand:SI 1 "register_operand" " 0") ++ (ss_minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 1)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmadrs\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmaxds" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI ++ (match_operand:SI 1 "register_operand" " 0") ++ (ss_minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 1)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmaxds\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmsda" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_minus:SI ++ (match_operand:SI 1 "register_operand" " 0") ++ (ss_minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 0)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmsda\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmsxda" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_minus:SI ++ (match_operand:SI 1 "register_operand" " 0") ++ (ss_minus:SI ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_operand:V2HI 3 "register_operand" " r") ++ (parallel [(const_int 0)])))) ++ (mult:SI ++ (sign_extend:SI (vec_select:HI ++ (match_dup 2) ++ (parallel [(const_int 0)]))) ++ (sign_extend:SI (vec_select:HI ++ (match_dup 3) ++ (parallel [(const_int 1)])))))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmsxda\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++;; smax[8|16] and umax[8|16] ++(define_insn "3" ++ [(set (match_operand:VQIHI 0 "register_operand" "=r") ++ (sumax:VQIHI (match_operand:VQIHI 1 "register_operand" " r") ++ (match_operand:VQIHI 2 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++;; smin[8|16] and umin[8|16] ++(define_insn "3" ++ [(set (match_operand:VQIHI 0 "register_operand" "=r") ++ (sumin:VQIHI (match_operand:VQIHI 1 "register_operand" " r") ++ (match_operand:VQIHI 2 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn "3_bb" ++ [(set (match_operand: 0 "register_operand" "=r") ++ (sumin_max: (vec_select: ++ (match_operand:VQIHI 1 "register_operand" " r") ++ (parallel [(const_int 0)])) ++ (vec_select: ++ (match_operand:VQIHI 2 "register_operand" " r") ++ (parallel [(const_int 0)]))))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "3_tt" ++ [(set (match_operand: 0 "register_operand" "=r") ++ (sumin_max: (vec_select: ++ (match_operand:VQIHI 1 "register_operand" " r") ++ (parallel [(const_int 1)])) ++ (vec_select: ++ (match_operand:VQIHI 2 "register_operand" " r") ++ (parallel [(const_int 1)]))))] ++ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 0)] ++{ ++ rtx tmp = gen_reg_rtx (mode); ++ emit_insn (gen_3 (tmp, operands[1], operands[2])); ++ emit_insn (gen_rotr_1 (tmp, tmp)); ++ emit_move_insn (operands[0], simplify_gen_subreg (mode, tmp, mode, 0)); ++ DONE; ++} ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "v4qi3_22" ++ [(set (match_operand:QI 0 "register_operand" "=r") ++ (sumin_max:QI (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 2)])) ++ (vec_select:QI ++ (match_operand:V4QI 2 "register_operand" " r") ++ (parallel [(const_int 2)]))))] ++ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 0)] ++{ ++ rtx tmp = gen_reg_rtx (V4QImode); ++ emit_insn (gen_v4qi3 (tmp, operands[1], operands[2])); ++ emit_insn (gen_rotrv4qi_2 (tmp, tmp)); ++ emit_move_insn (operands[0], simplify_gen_subreg (QImode, tmp, V4QImode, 0)); ++ DONE; ++} ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "v4qi3_33" ++ [(set (match_operand:QI 0 "register_operand" "=r") ++ (sumin_max:QI (vec_select:QI ++ (match_operand:V4QI 1 "register_operand" " r") ++ (parallel [(const_int 3)])) ++ (vec_select:QI ++ (match_operand:V4QI 2 "register_operand" " r") ++ (parallel [(const_int 3)]))))] ++ "NDS32_EXT_DSP_P () && !reload_completed && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 0)] ++{ ++ rtx tmp = gen_reg_rtx (V4QImode); ++ emit_insn (gen_v4qi3 (tmp, operands[1], operands[2])); ++ emit_insn (gen_rotrv4qi_3 (tmp, tmp)); ++ emit_move_insn (operands[0], simplify_gen_subreg (QImode, tmp, V4QImode, 0)); ++ DONE; ++} ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "v2hi3_bbtt" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (vec_merge:V2HI ++ (vec_duplicate:V2HI ++ (sumin_max:HI (vec_select:HI ++ (match_operand:V2HI 1 "register_operand" " r") ++ (parallel [(const_int 1)])) ++ (vec_select:HI ++ (match_operand:V2HI 2 "register_operand" " r") ++ (parallel [(const_int 1)])))) ++ (vec_duplicate:V2HI ++ (sumin_max:HI (vec_select:HI ++ (match_dup:V2HI 1) ++ (parallel [(const_int 0)])) ++ (vec_select:HI ++ (match_dup:V2HI 2) ++ (parallel [(const_int 0)])))) ++ (const_int 2)))] ++ "NDS32_EXT_DSP_P () && !TARGET_BIG_ENDIAN" ++ "#" ++ "NDS32_EXT_DSP_P ()" ++ [(const_int 0)] ++{ ++ emit_insn (gen_v2hi3 (operands[0], operands[1], operands[2])); ++ DONE; ++} ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_expand "abs2" ++ [(set (match_operand:VQIHI 0 "register_operand" "=r") ++ (ss_abs:VQIHI (match_operand:VQIHI 1 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P () && TARGET_HW_ABS && !flag_wrapv" ++{ ++}) ++ ++(define_insn "kabs2" ++ [(set (match_operand:VQIHI 0 "register_operand" "=r") ++ (ss_abs:VQIHI (match_operand:VQIHI 1 "register_operand" " r")))] ++ "NDS32_EXT_DSP_P ()" ++ "kabs\t%0, %1" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn "mar64_1" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (mult:DI ++ (extend:DI ++ (match_operand:SI 2 "register_operand" " r")) ++ (extend:DI ++ (match_operand:SI 3 "register_operand" " r")))))] ++ "NDS32_EXT_DSP_P ()" ++ "mar64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "mar64_2" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (mult:DI ++ (extend:DI ++ (match_operand:SI 2 "register_operand" " r")) ++ (extend:DI ++ (match_operand:SI 3 "register_operand" " r"))) ++ (match_operand:DI 1 "register_operand" " 0")))] ++ "NDS32_EXT_DSP_P ()" ++ "mar64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "mar64_3" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (extend:DI ++ (mult:SI ++ (match_operand:SI 2 "register_operand" " r") ++ (match_operand:SI 3 "register_operand" " r")))))] ++ "NDS32_EXT_DSP_P ()" ++ "mar64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "mar64_4" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (plus:DI ++ (extend:DI ++ (mult:SI ++ (match_operand:SI 2 "register_operand" " r") ++ (match_operand:SI 3 "register_operand" " r"))) ++ (match_operand:DI 1 "register_operand" " 0")))] ++ "NDS32_EXT_DSP_P ()" ++ "mar64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "msr64" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (minus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (mult:DI ++ (extend:DI ++ (match_operand:SI 2 "register_operand" " r")) ++ (extend:DI ++ (match_operand:SI 3 "register_operand" " r")))))] ++ "NDS32_EXT_DSP_P ()" ++ "msr64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "msr64_2" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (minus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (extend:DI ++ (mult:SI ++ (match_operand:SI 2 "register_operand" " r") ++ (match_operand:SI 3 "register_operand" " r")))))] ++ "NDS32_EXT_DSP_P ()" ++ "msr64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++;; kmar64, kmsr64, ukmar64 and ukmsr64 ++(define_insn "kmar64_1" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (ss_plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (mult:DI ++ (sign_extend:DI ++ (match_operand:SI 2 "register_operand" " r")) ++ (sign_extend:DI ++ (match_operand:SI 3 "register_operand" " r")))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmar64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmar64_2" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (ss_plus:DI ++ (mult:DI ++ (sign_extend:DI ++ (match_operand:SI 2 "register_operand" " r")) ++ (sign_extend:DI ++ (match_operand:SI 3 "register_operand" " r"))) ++ (match_operand:DI 1 "register_operand" " 0")))] ++ "NDS32_EXT_DSP_P ()" ++ "kmar64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "kmsr64" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (ss_minus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (mult:DI ++ (sign_extend:DI ++ (match_operand:SI 2 "register_operand" " r")) ++ (sign_extend:DI ++ (match_operand:SI 3 "register_operand" " r")))))] ++ "NDS32_EXT_DSP_P ()" ++ "kmsr64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "ukmar64_1" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (us_plus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (mult:DI ++ (zero_extend:DI ++ (match_operand:SI 2 "register_operand" " r")) ++ (zero_extend:DI ++ (match_operand:SI 3 "register_operand" " r")))))] ++ "NDS32_EXT_DSP_P ()" ++ "ukmar64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "ukmar64_2" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (us_plus:DI ++ (mult:DI ++ (zero_extend:DI ++ (match_operand:SI 2 "register_operand" " r")) ++ (zero_extend:DI ++ (match_operand:SI 3 "register_operand" " r"))) ++ (match_operand:DI 1 "register_operand" " 0")))] ++ "NDS32_EXT_DSP_P ()" ++ "ukmar64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "ukmsr64" ++ [(set (match_operand:DI 0 "register_operand" "=r") ++ (us_minus:DI ++ (match_operand:DI 1 "register_operand" " 0") ++ (mult:DI ++ (zero_extend:DI ++ (match_operand:SI 2 "register_operand" " r")) ++ (zero_extend:DI ++ (match_operand:SI 3 "register_operand" " r")))))] ++ "NDS32_EXT_DSP_P ()" ++ "ukmsr64\t%0, %2, %3" ++ [(set_attr "type" "dmac") ++ (set_attr "length" "4")]) ++ ++(define_insn "bpick1" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI ++ (and:SI ++ (match_operand:SI 1 "register_operand" " r") ++ (match_operand:SI 3 "register_operand" " r")) ++ (and:SI ++ (match_operand:SI 2 "register_operand" " r") ++ (not:SI (match_dup 3)))))] ++ "NDS32_EXT_DSP_P ()" ++ "bpick\t%0, %1, %2, %3" ++ [(set_attr "type" "dbpick") ++ (set_attr "length" "4")]) ++ ++(define_insn "bpick2" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI ++ (and:SI ++ (match_operand:SI 1 "register_operand" " r") ++ (match_operand:SI 2 "register_operand" " r")) ++ (and:SI ++ (not:SI (match_dup 2)) ++ (match_operand:SI 3 "register_operand" " r"))))] ++ "NDS32_EXT_DSP_P ()" ++ "bpick\t%0, %1, %3, %2" ++ [(set_attr "type" "dbpick") ++ (set_attr "length" "4")]) ++ ++(define_insn "bpick3" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI ++ (and:SI ++ (match_operand:SI 1 "register_operand" " r") ++ (match_operand:SI 2 "register_operand" " r")) ++ (and:SI ++ (match_operand:SI 3 "register_operand" " r") ++ (not:SI (match_dup 1)))))] ++ "NDS32_EXT_DSP_P ()" ++ "bpick\t%0, %2, %3, %1" ++ [(set_attr "type" "dbpick") ++ (set_attr "length" "4")]) ++ ++(define_insn "bpick4" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI ++ (and:SI ++ (match_operand:SI 1 "register_operand" " r") ++ (match_operand:SI 2 "register_operand" " r")) ++ (and:SI ++ (not:SI (match_dup 1)) ++ (match_operand:SI 3 "register_operand" " r"))))] ++ "NDS32_EXT_DSP_P ()" ++ "bpick\t%0, %2, %3, %1" ++ [(set_attr "type" "dbpick") ++ (set_attr "length" "4")]) ++ ++(define_insn "bpick5" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI ++ (and:SI ++ (match_operand:SI 1 "register_operand" " r") ++ (not:SI (match_operand:SI 2 "register_operand" " r"))) ++ (and:SI ++ (match_operand:SI 3 "register_operand" " r") ++ (match_dup 2))))] ++ "NDS32_EXT_DSP_P ()" ++ "bpick\t%0, %3, %1, %2" ++ [(set_attr "type" "dbpick") ++ (set_attr "length" "4")]) ++ ++(define_insn "bpick6" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI ++ (and:SI ++ (not:SI (match_operand:SI 1 "register_operand" " r")) ++ (match_operand:SI 2 "register_operand" " r")) ++ (and:SI ++ (match_operand:SI 3 "register_operand" " r") ++ (match_dup 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "bpick\t%0, %3, %2, %1" ++ [(set_attr "type" "dbpick") ++ (set_attr "length" "4")]) ++ ++(define_insn "bpick7" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI ++ (and:SI ++ (match_operand:SI 1 "register_operand" " r") ++ (not:SI (match_operand:SI 2 "register_operand" " r"))) ++ (and:SI ++ (match_dup 2) ++ (match_operand:SI 3 "register_operand" " r"))))] ++ "NDS32_EXT_DSP_P ()" ++ "bpick\t%0, %3, %1, %2" ++ [(set_attr "type" "dbpick") ++ (set_attr "length" "4")]) ++ ++(define_insn "bpick8" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ior:SI ++ (and:SI ++ (not:SI (match_operand:SI 1 "register_operand" " r")) ++ (match_operand:SI 2 "register_operand" " r")) ++ (and:SI ++ (match_dup 1) ++ (match_operand:SI 3 "register_operand" " r"))))] ++ "NDS32_EXT_DSP_P ()" ++ "bpick\t%0, %3, %2, %1" ++ [(set_attr "type" "dbpick") ++ (set_attr "length" "4")]) ++ ++(define_insn "sraiu" ++ [(set (match_operand:SI 0 "register_operand" "= r, r") ++ (unspec:SI [(ashiftrt:SI (match_operand:SI 1 "register_operand" " r, r") ++ (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r"))] ++ UNSPEC_ROUND))] ++ "NDS32_EXT_DSP_P ()" ++ "@ ++ srai.u\t%0, %1, %2 ++ sra.u\t%0, %1, %2" ++ [(set_attr "type" "daluround") ++ (set_attr "length" "4")]) ++ ++(define_insn "kssl" ++ [(set (match_operand:SI 0 "register_operand" "= r, r") ++ (ss_ashift:SI (match_operand:SI 1 "register_operand" " r, r") ++ (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r")))] ++ "NDS32_EXT_DSP_P ()" ++ "@ ++ kslli\t%0, %1, %2 ++ ksll\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++(define_insn "kslraw_round" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (if_then_else:SI ++ (lt:SI (match_operand:SI 2 "register_operand" " r") ++ (const_int 0)) ++ (unspec:SI [(ashiftrt:SI (match_operand:SI 1 "register_operand" " r") ++ (neg:SI (match_dup 2)))] ++ UNSPEC_ROUND) ++ (ss_ashift:SI (match_dup 1) ++ (match_dup 2))))] ++ "NDS32_EXT_DSP_P ()" ++ "kslraw.u\t%0, %1, %2" ++ [(set_attr "type" "daluround") ++ (set_attr "length" "4")]) ++ ++(define_insn_and_split "di3" ++ [(set (match_operand:DI 0 "register_operand" "") ++ (shift_rotate:DI (match_operand:DI 1 "register_operand" "") ++ (match_operand:SI 2 "nds32_rimm6u_operand" "")))] ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ "#" ++ "NDS32_EXT_DSP_P () && !reload_completed" ++ [(const_int 0)] ++{ ++ if (REGNO (operands[0]) == REGNO (operands[1])) ++ { ++ rtx tmp = gen_reg_rtx (DImode); ++ nds32_split_di3 (tmp, operands[1], operands[2]); ++ emit_move_insn (operands[0], tmp); ++ } ++ else ++ nds32_split_di3 (operands[0], operands[1], operands[2]); ++ DONE; ++}) ++ ++(define_insn "sclip32" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_CLIPS_OV))] ++ "NDS32_EXT_DSP_P ()" ++ "sclip32\t%0, %1, %2" ++ [(set_attr "type" "dclip") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "uclip32" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_CLIP_OV))] ++ "NDS32_EXT_DSP_P ()" ++ "uclip32\t%0, %1, %2" ++ [(set_attr "type" "dclip") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "bitrev" ++ [(set (match_operand:SI 0 "register_operand" "=r, r") ++ (unspec:SI [(match_operand:SI 1 "register_operand" " r, r") ++ (match_operand:SI 2 "nds32_rimm5u_operand" " r, Iu05")] ++ UNSPEC_BITREV))] ++ "" ++ "@ ++ bitrev\t%0, %1, %2 ++ bitrevi\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")] ++) ++ ++;; wext, wexti ++(define_insn "wext" ++ [(set (match_operand:SI 0 "register_operand" "=r, r") ++ (truncate:SI ++ (shiftrt:DI ++ (match_operand:DI 1 "register_operand" " r, r") ++ (match_operand:SI 2 "nds32_rimm5u_operand" " r,Iu05"))))] ++ "NDS32_EXT_DSP_P ()" ++ "@ ++ wext\t%0, %1, %2 ++ wexti\t%0, %1, %2" ++ [(set_attr "type" "dwext") ++ (set_attr "length" "4")]) ++ ++;; 32-bit add/sub instruction: raddw and rsubw. ++(define_insn "rsi3" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (truncate:SI ++ (ashiftrt:DI ++ (plus_minus:DI ++ (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) ++ (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "rw\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) ++ ++;; 32-bit add/sub instruction: uraddw and ursubw. ++(define_insn "ursi3" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (truncate:SI ++ (lshiftrt:DI ++ (plus_minus:DI ++ (zero_extend:DI (match_operand:SI 1 "register_operand" " r")) ++ (zero_extend:DI (match_operand:SI 2 "register_operand" " r"))) ++ (const_int 1))))] ++ "NDS32_EXT_DSP_P ()" ++ "urw\t%0, %1, %2" ++ [(set_attr "type" "dalu") ++ (set_attr "length" "4")]) +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-elf.opt gcc-8.2.0/gcc/config/nds32/nds32-elf.opt +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-elf.opt 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-elf.opt 2019-01-25 15:38:32.825242648 +0100 +@@ -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) +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-fp-as-gp.c gcc-8.2.0/gcc/config/nds32/nds32-fp-as-gp.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-fp-as-gp.c 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-fp-as-gp.c 2019-01-25 15:38:32.825242648 +0100 +@@ -26,19 +26,256 @@ + #include "system.h" + #include "coretypes.h" + #include "backend.h" ++#include "hard-reg-set.h" ++#include "tm_p.h" ++#include "rtl.h" ++#include "memmodel.h" ++#include "emit-rtl.h" ++#include "insn-config.h" ++#include "regs.h" ++#include "hard-reg-set.h" ++#include "ira.h" ++#include "ira-int.h" ++#include "df.h" ++#include "tree-core.h" ++#include "tree-pass.h" ++#include "nds32-protos.h" + + /* ------------------------------------------------------------------------ */ + ++/* A helper function to check if this function should contain prologue. */ ++static bool ++nds32_have_prologue_p (void) ++{ ++ int i; ++ ++ for (i = 0; i < 28; i++) ++ if (NDS32_REQUIRED_CALLEE_SAVED_P (i)) ++ return true; ++ ++ return (flag_pic ++ || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM) ++ || NDS32_REQUIRED_CALLEE_SAVED_P (LP_REGNUM)); ++} ++ ++static int ++nds32_get_symbol_count (void) ++{ ++ int symbol_count = 0; ++ rtx_insn *insn; ++ basic_block bb; ++ ++ FOR_EACH_BB_FN (bb, cfun) ++ { ++ FOR_BB_INSNS (bb, insn) ++ { ++ /* Counting the insn number which the addressing mode is symbol. */ ++ if (single_set (insn) && nds32_symbol_load_store_p (insn)) ++ { ++ rtx pattern = PATTERN (insn); ++ rtx mem; ++ gcc_assert (GET_CODE (pattern) == SET); ++ if (GET_CODE (SET_SRC (pattern)) == REG ) ++ mem = SET_DEST (pattern); ++ else ++ mem = SET_SRC (pattern); ++ ++ /* We have only lwi37 and swi37 for fp-as-gp optimization, ++ so don't count any other than SImode. ++ MEM for QImode and HImode will wrap by ZERO_EXTEND ++ or SIGN_EXTEND */ ++ if (GET_CODE (mem) == MEM) ++ symbol_count++; ++ } ++ } ++ } ++ ++ return symbol_count; ++} ++ + /* Function to determine whether it is worth to do fp_as_gp optimization. +- Return 0: It is NOT worth to do fp_as_gp optimization. +- Return 1: It is APPROXIMATELY worth to do fp_as_gp optimization. ++ Return false: It is NOT worth to do fp_as_gp optimization. ++ Return true: It is APPROXIMATELY worth to do fp_as_gp optimization. + Note that if it is worth to do fp_as_gp optimization, + we MUST set FP_REGNUM ever live in this function. */ +-int ++static bool + nds32_fp_as_gp_check_available (void) + { +- /* By default we return 0. */ +- return 0; ++ basic_block bb; ++ basic_block exit_bb; ++ edge_iterator ei; ++ edge e; ++ bool first_exit_blocks_p; ++ ++ /* If there exists ANY of following conditions, ++ we DO NOT perform fp_as_gp optimization: ++ 1. TARGET_FORBID_FP_AS_GP is set ++ regardless of the TARGET_FORCE_FP_AS_GP. ++ 2. User explicitly uses 'naked'/'no_prologue' attribute. ++ We use nds32_naked_function_p() to help such checking. ++ 3. Not optimize for size. ++ 4. Need frame pointer. ++ 5. If $fp is already required to be saved, ++ it means $fp is already choosen by register allocator. ++ Thus we better not to use it for fp_as_gp optimization. ++ 6. This function is a vararg function. ++ DO NOT apply fp_as_gp optimization on this function ++ because it may change and break stack frame. ++ 7. The epilogue is empty. ++ This happens when the function uses exit() ++ or its attribute is no_return. ++ In that case, compiler will not expand epilogue ++ so that we have no chance to output .omit_fp_end directive. */ ++ if (TARGET_FORBID_FP_AS_GP ++ || nds32_naked_function_p (current_function_decl) ++ || !optimize_size ++ || frame_pointer_needed ++ || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM) ++ || (cfun->stdarg == 1) ++ || (find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == NULL)) ++ return false; ++ ++ /* Disable fp_as_gp if there is any infinite loop since the fp may ++ reuse in infinite loops by register rename. ++ For check infinite loops we should make sure exit_bb is post dominate ++ all other basic blocks if there is no infinite loops. */ ++ first_exit_blocks_p = true; ++ exit_bb = NULL; ++ ++ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) ++ { ++ /* More than one exit block also do not perform fp_as_gp optimization. */ ++ if (!first_exit_blocks_p) ++ return false; ++ ++ exit_bb = e->src; ++ first_exit_blocks_p = false; ++ } ++ ++ /* Not found exit_bb? just abort fp_as_gp! */ ++ if (!exit_bb) ++ return false; ++ ++ /* Each bb should post dominate by exit_bb if there is no infinite loop! */ ++ FOR_EACH_BB_FN (bb, cfun) ++ { ++ if (!dominated_by_p (CDI_POST_DOMINATORS, ++ bb, ++ exit_bb)) ++ return false; ++ } ++ ++ /* Now we can check the possibility of using fp_as_gp optimization. */ ++ if (TARGET_FORCE_FP_AS_GP) ++ { ++ /* User explicitly issues -mforce-fp-as-gp option. */ ++ return true; ++ } ++ else ++ { ++ /* In the following we are going to evaluate whether ++ it is worth to do fp_as_gp optimization. */ ++ bool good_gain = false; ++ int symbol_count; ++ ++ int threshold; ++ ++ /* We check if there already requires prologue. ++ Note that $gp will be saved in prologue for PIC code generation. ++ After that, we can set threshold by the existence of prologue. ++ Each fp-implied instruction will gain 2-byte code size ++ from gp-aware instruction, so we have following heuristics. */ ++ if (flag_pic ++ || nds32_have_prologue_p ()) ++ { ++ /* Have-prologue: ++ Compiler already intends to generate prologue content, ++ so the fp_as_gp optimization will only insert ++ 'la $fp,_FP_BASE_' instruction, which will be ++ converted into 4-byte instruction at link time. ++ The threshold is "3" symbol accesses, 2 + 2 + 2 > 4. */ ++ threshold = 3; ++ } ++ else ++ { ++ /* None-prologue: ++ Compiler originally does not generate prologue content, ++ so the fp_as_gp optimization will NOT ONLY insert ++ 'la $fp,_FP_BASE' instruction, but also causes ++ push/pop instructions. ++ If we are using v3push (push25/pop25), ++ the threshold is "5" symbol accesses, 5*2 > 4 + 2 + 2; ++ If we are using normal push (smw/lmw), ++ the threshold is "5+2" symbol accesses 7*2 > 4 + 4 + 4. */ ++ threshold = 5 + (TARGET_V3PUSH ? 0 : 2); ++ } ++ ++ symbol_count = nds32_get_symbol_count (); ++ ++ if (symbol_count >= threshold) ++ good_gain = true; ++ ++ /* Enable fp_as_gp optimization when potential gain is good enough. */ ++ return good_gain; ++ } ++} ++ ++static unsigned int ++nds32_fp_as_gp (void) ++{ ++ bool fp_as_gp_p; ++ calculate_dominance_info (CDI_POST_DOMINATORS); ++ fp_as_gp_p = nds32_fp_as_gp_check_available (); ++ ++ /* Here is a hack to IRA for enable/disable a hard register per function. ++ We *MUST* review this way after migrate gcc 4.9! */ ++ if (fp_as_gp_p) { ++ SET_HARD_REG_BIT(this_target_ira_int->x_no_unit_alloc_regs, FP_REGNUM); ++ df_set_regs_ever_live (FP_REGNUM, 1); ++ } else { ++ CLEAR_HARD_REG_BIT(this_target_ira_int->x_no_unit_alloc_regs, FP_REGNUM); ++ } ++ ++ cfun->machine->fp_as_gp_p = fp_as_gp_p; ++ ++ free_dominance_info (CDI_POST_DOMINATORS); ++ return 1; ++} ++ ++const pass_data pass_data_nds32_fp_as_gp = ++{ ++ RTL_PASS, /* type */ ++ "fp_as_gp", /* name */ ++ OPTGROUP_NONE, /* optinfo_flags */ ++ TV_MACH_DEP, /* tv_id */ ++ 0, /* properties_required */ ++ 0, /* properties_provided */ ++ 0, /* properties_destroyed */ ++ 0, /* todo_flags_start */ ++ 0 /* todo_flags_finish */ ++}; ++ ++class pass_nds32_fp_as_gp : public rtl_opt_pass ++{ ++public: ++ pass_nds32_fp_as_gp (gcc::context *ctxt) ++ : rtl_opt_pass (pass_data_nds32_fp_as_gp, ctxt) ++ {} ++ ++ /* opt_pass methods: */ ++ bool gate (function *) ++ { ++ return !TARGET_LINUX_ABI ++ && TARGET_16_BIT ++ && optimize_size; ++ } ++ unsigned int execute (function *) { return nds32_fp_as_gp (); } ++}; ++ ++rtl_opt_pass * ++make_pass_nds32_fp_as_gp (gcc::context *ctxt) ++{ ++ return new pass_nds32_fp_as_gp (ctxt); + } + + /* ------------------------------------------------------------------------ */ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-fpu.md gcc-8.2.0/gcc/config/nds32/nds32-fpu.md +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-fpu.md 2018-04-06 07:51:33.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-fpu.md 2019-01-25 15:38:32.825242648 +0100 +@@ -1,5 +1,5 @@ + ;; Machine description of Andes NDS32 cpu for GNU compiler +-;; Copyright (C) 2012-2015 Free Software Foundation, Inc. ++;; Copyright (C) 2012-2018 Free Software Foundation, Inc. + ;; Contributed by Andes Technology Corporation. + ;; + ;; This file is part of GCC. +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-graywolf.md gcc-8.2.0/gcc/config/nds32/nds32-graywolf.md +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-graywolf.md 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-graywolf.md 2019-01-25 15:38:32.825242648 +0100 +@@ -0,0 +1,471 @@ ++;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler ++;; Copyright (C) 2012-2013 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 ++;; . ++ ++;; ------------------------------------------------------------------------ ++;; Define Graywolf pipeline settings. ++;; ------------------------------------------------------------------------ ++ ++(define_automaton "nds32_graywolf_machine") ++ ++(define_cpu_unit "gw_ii_0" "nds32_graywolf_machine") ++(define_cpu_unit "gw_ii_1" "nds32_graywolf_machine") ++(define_cpu_unit "gw_ex_p0" "nds32_graywolf_machine") ++(define_cpu_unit "gw_mm_p0" "nds32_graywolf_machine") ++(define_cpu_unit "gw_wb_p0" "nds32_graywolf_machine") ++(define_cpu_unit "gw_ex_p1" "nds32_graywolf_machine") ++(define_cpu_unit "gw_mm_p1" "nds32_graywolf_machine") ++(define_cpu_unit "gw_wb_p1" "nds32_graywolf_machine") ++(define_cpu_unit "gw_iq_p2" "nds32_graywolf_machine") ++(define_cpu_unit "gw_rf_p2" "nds32_graywolf_machine") ++(define_cpu_unit "gw_e1_p2" "nds32_graywolf_machine") ++(define_cpu_unit "gw_e2_p2" "nds32_graywolf_machine") ++(define_cpu_unit "gw_e3_p2" "nds32_graywolf_machine") ++(define_cpu_unit "gw_e4_p2" "nds32_graywolf_machine") ++ ++(define_reservation "gw_ii" "gw_ii_0 | gw_ii_1") ++(define_reservation "gw_ex" "gw_ex_p0 | gw_ex_p1") ++(define_reservation "gw_mm" "gw_mm_p0 | gw_mm_p1") ++(define_reservation "gw_wb" "gw_wb_p0 | gw_wb_p1") ++ ++(define_reservation "gw_ii_all" "gw_ii_0 + gw_ii_1") ++ ++(define_insn_reservation "nds_gw_unknown" 1 ++ (and (eq_attr "type" "unknown") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_ex, gw_mm, gw_wb") ++ ++(define_insn_reservation "nds_gw_misc" 1 ++ (and (eq_attr "type" "misc") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_ex, gw_mm, gw_wb") ++ ++(define_insn_reservation "nds_gw_mmu" 1 ++ (and (eq_attr "type" "mmu") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_ex, gw_mm, gw_wb") ++ ++(define_insn_reservation "nds_gw_alu" 1 ++ (and (and (eq_attr "type" "alu") ++ (match_test "!nds32::movd44_insn_p (insn)")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_ex, gw_mm, gw_wb") ++ ++(define_insn_reservation "nds_gw_movd44" 1 ++ (and (and (eq_attr "type" "alu") ++ (match_test "nds32::movd44_insn_p (insn)")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex, gw_mm, gw_wb") ++ ++(define_insn_reservation "nds_gw_alu_shift" 1 ++ (and (eq_attr "type" "alu_shift") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_ex*2, gw_mm, gw_wb") ++ ++(define_insn_reservation "nds_gw_pbsad" 1 ++ (and (eq_attr "type" "pbsad") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_ex*3, gw_mm, gw_wb") ++ ++(define_insn_reservation "nds_gw_pbsada" 1 ++ (and (eq_attr "type" "pbsada") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_ex*3, gw_mm, gw_wb") ++ ++(define_insn_reservation "nds_gw_load" 1 ++ (and (and (eq_attr "type" "load") ++ (match_test "!nds32::post_update_insn_p (insn)")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_load_2w" 1 ++ (and (and (eq_attr "type" "load") ++ (match_test "nds32::post_update_insn_p (insn)")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_all, gw_ex_p1, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store" 1 ++ (and (and (eq_attr "type" "store") ++ (match_test "!nds32::store_offset_reg_p (insn)")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store_3r" 1 ++ (and (and (eq_attr "type" "store") ++ (match_test "nds32::store_offset_reg_p (insn)")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_all, gw_ex_p1, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_load_multiple_1" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "1")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_load_multiple_2" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "2")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*2, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_load_multiple_3" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "3")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*3, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_load_multiple_4" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "4")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_load_multiple_5" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "5")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_load_multiple_6" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "6")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_load_multiple_7" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "7")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_load_multiple_8" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "8")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_load_multiple_12" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "12")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store_multiple_1" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "1")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store_multiple_2" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "2")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*2, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store_multiple_3" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "3")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*3, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store_multiple_4" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "4")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store_multiple_5" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "5")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store_multiple_6" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "6")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store_multiple_7" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "7")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store_multiple_8" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "8")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_store_multiple_12" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "12")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_1, gw_ex_p1*4, gw_mm_p1, gw_wb_p1") ++ ++(define_insn_reservation "nds_gw_mul_fast1" 1 ++ (and (match_test "nds32_mul_config == MUL_TYPE_FAST_1") ++ (and (eq_attr "type" "mul") ++ (eq_attr "pipeline_model" "graywolf"))) ++ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_mul_fast2" 1 ++ (and (match_test "nds32_mul_config == MUL_TYPE_FAST_2") ++ (and (eq_attr "type" "mul") ++ (eq_attr "pipeline_model" "graywolf"))) ++ "gw_ii_0, gw_ex_p0*2, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_mul_slow" 1 ++ (and (match_test "nds32_mul_config == MUL_TYPE_SLOW") ++ (and (eq_attr "type" "mul") ++ (eq_attr "pipeline_model" "graywolf"))) ++ "gw_ii_0, gw_ex_p0*4, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_mac_fast1" 1 ++ (and (match_test "nds32_mul_config == MUL_TYPE_FAST_1") ++ (and (eq_attr "type" "mac") ++ (eq_attr "pipeline_model" "graywolf"))) ++ "gw_ii_all, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_mac_fast2" 1 ++ (and (match_test "nds32_mul_config == MUL_TYPE_FAST_2") ++ (and (eq_attr "type" "mac") ++ (eq_attr "pipeline_model" "graywolf"))) ++ "gw_ii_all, gw_ex_p0*2, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_mac_slow" 1 ++ (and (match_test "nds32_mul_config == MUL_TYPE_SLOW") ++ (and (eq_attr "type" "mac") ++ (eq_attr "pipeline_model" "graywolf"))) ++ "gw_ii_all, gw_ex_p0*4, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_div" 1 ++ (and (and (eq_attr "type" "div") ++ (match_test "!nds32::divmod_p (insn)")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_0, gw_ex_p0*4, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_div_2w" 1 ++ (and (and (eq_attr "type" "div") ++ (match_test "nds32::divmod_p (insn)")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_all, gw_ex_p0*4, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_branch" 1 ++ (and (eq_attr "type" "branch") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_dsp_alu" 1 ++ (and (eq_attr "type" "dalu") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_ex, gw_mm, gw_wb") ++ ++(define_insn_reservation "nds_gw_dsp_alu64" 1 ++ (and (eq_attr "type" "dalu64") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_all, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_dsp_alu_round" 1 ++ (and (eq_attr "type" "daluround") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_dsp_cmp" 1 ++ (and (eq_attr "type" "dcmp") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_dsp_clip" 1 ++ (and (eq_attr "type" "dclip") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_dsp_mul" 1 ++ (and (eq_attr "type" "dmul") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_dsp_mac" 1 ++ (and (eq_attr "type" "dmac") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_all, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_dsp_insb" 1 ++ (and (eq_attr "type" "dinsb") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_dsp_pack" 1 ++ (and (eq_attr "type" "dpack") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_dsp_bpick" 1 ++ (and (eq_attr "type" "dbpick") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_0, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_dsp_wext" 1 ++ (and (eq_attr "type" "dwext") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii_all, gw_ex_p0, gw_mm_p0, gw_wb_p0") ++ ++(define_insn_reservation "nds_gw_fpu_alu" 4 ++ (and (eq_attr "type" "falu") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_muls" 4 ++ (and (eq_attr "type" "fmuls") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_muld" 4 ++ (and (eq_attr "type" "fmuld") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2*2, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_macs" 4 ++ (and (eq_attr "type" "fmacs") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2*3, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_macd" 4 ++ (and (eq_attr "type" "fmacd") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2*4, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_divs" 4 ++ (and (ior (eq_attr "type" "fdivs") ++ (eq_attr "type" "fsqrts")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2*14, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_divd" 4 ++ (and (ior (eq_attr "type" "fdivd") ++ (eq_attr "type" "fsqrtd")) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2*28, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_fast_alu" 2 ++ (and (ior (eq_attr "type" "fcmp") ++ (ior (eq_attr "type" "fabs") ++ (ior (eq_attr "type" "fcpy") ++ (eq_attr "type" "fcmov")))) ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_fmtsr" 1 ++ (and (eq_attr "type" "fmtsr") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_fmtdr" 1 ++ (and (eq_attr "type" "fmtdr") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_ii+gw_iq_p2, gw_iq_p2+gw_rf_p2, gw_rf_p2+gw_e1_p2, gw_e1_p2+gw_e2_p2, gw_e2_p2+gw_e3_p2, gw_e3_p2+gw_e4_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_fmfsr" 1 ++ (and (eq_attr "type" "fmfsr") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_fmfdr" 1 ++ (and (eq_attr "type" "fmfdr") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_ii+gw_iq_p2, gw_iq_p2+gw_rf_p2, gw_rf_p2+gw_e1_p2, gw_e1_p2+gw_e2_p2, gw_e2_p2+gw_e3_p2, gw_e3_p2+gw_e4_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_load" 3 ++ (and (eq_attr "type" "fload") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") ++ ++(define_insn_reservation "nds_gw_fpu_store" 1 ++ (and (eq_attr "type" "fstore") ++ (eq_attr "pipeline_model" "graywolf")) ++ "gw_ii, gw_iq_p2, gw_rf_p2, gw_e1_p2, gw_e2_p2, gw_e3_p2, gw_e4_p2") ++ ++;; FPU_ADDR_OUT -> FPU_ADDR_IN ++;; Main pipeline rules don't need this because those default latency is 1. ++(define_bypass 1 ++ "nds_gw_fpu_load, nds_gw_fpu_store" ++ "nds_gw_fpu_load, nds_gw_fpu_store" ++ "nds32_gw_ex_to_ex_p" ++) ++ ++;; LD, MUL, MAC, DIV, DALU64, DMUL, DMAC, DALUROUND, DBPICK, DWEXT ++;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44, MUL, MAC_RaRb, DIV, ADDR_IN, BR, MMU, ++;; DALU, DALUROUND, DMUL, DMAC_RaRb, DPACK, DINSB, DCMP, DCLIP, WEXT_O, BPICK_RaRb ++(define_bypass 2 ++ "nds_gw_load, nds_gw_load_2w,\ ++ nds_gw_mul_fast1, nds_gw_mul_fast2, nds_gw_mul_slow,\ ++ nds_gw_mac_fast1, nds_gw_mac_fast2, nds_gw_mac_slow,\ ++ nds_gw_div, nds_gw_div_2w,\ ++ nds_gw_dsp_alu64, nds_gw_dsp_mul, nds_gw_dsp_mac,\ ++ nds_gw_dsp_alu_round, nds_gw_dsp_bpick, nds_gw_dsp_wext" ++ "nds_gw_alu, nds_gw_movd44, nds_gw_alu_shift,\ ++ nds_gw_pbsad, nds_gw_pbsada,\ ++ nds_gw_mul_fast1, nds_gw_mul_fast2, nds_gw_mul_slow,\ ++ nds_gw_mac_fast1, nds_gw_mac_fast2, nds_gw_mac_slow,\ ++ nds_gw_branch,\ ++ nds_gw_div, nds_gw_div_2w,\ ++ nds_gw_load, nds_gw_load_2w, nds_gw_store, nds_gw_store_3r,\ ++ nds_gw_load_multiple_1,nds_gw_load_multiple_2, nds_gw_load_multiple_3,\ ++ nds_gw_load_multiple_4,nds_gw_load_multiple_5, nds_gw_load_multiple_6,\ ++ nds_gw_load_multiple_7,nds_gw_load_multiple_8, nds_gw_load_multiple_12,\ ++ nds_gw_store_multiple_1,nds_gw_store_multiple_2, nds_gw_store_multiple_3,\ ++ nds_gw_store_multiple_4,nds_gw_store_multiple_5, nds_gw_store_multiple_6,\ ++ nds_gw_store_multiple_7,nds_gw_store_multiple_8, nds_gw_store_multiple_12,\ ++ nds_gw_mmu,\ ++ nds_gw_dsp_alu, nds_gw_dsp_alu_round,\ ++ nds_gw_dsp_mul, nds_gw_dsp_mac, nds_gw_dsp_pack,\ ++ nds_gw_dsp_insb, nds_gw_dsp_cmp, nds_gw_dsp_clip,\ ++ nds_gw_dsp_wext, nds_gw_dsp_bpick" ++ "nds32_gw_mm_to_ex_p" ++) ++ ++;; LMW(N, N) ++;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44, MUL, MAC_RaRb, DIV, ADDR_IN, BR, MMU ++;; DALU, DALUROUND, DMUL, DMAC_RaRb, DPACK, DINSB, DCMP, DCLIP, WEXT_O, BPICK_RaRb ++(define_bypass 2 ++ "nds_gw_load_multiple_1,nds_gw_load_multiple_2, nds_gw_load_multiple_3,\ ++ nds_gw_load_multiple_4,nds_gw_load_multiple_5, nds_gw_load_multiple_6,\ ++ nds_gw_load_multiple_7,nds_gw_load_multiple_8, nds_gw_load_multiple_12" ++ "nds_gw_alu, nds_gw_movd44, nds_gw_alu_shift,\ ++ nds_gw_pbsad, nds_gw_pbsada,\ ++ nds_gw_mul_fast1, nds_gw_mul_fast2, nds_gw_mul_slow,\ ++ nds_gw_mac_fast1, nds_gw_mac_fast2, nds_gw_mac_slow,\ ++ nds_gw_branch,\ ++ nds_gw_div, nds_gw_div_2w,\ ++ nds_gw_load, nds_gw_load_2w, nds_gw_store, nds_gw_store_3r,\ ++ nds_gw_load_multiple_1,nds_gw_load_multiple_2, nds_gw_load_multiple_3,\ ++ nds_gw_load_multiple_4,nds_gw_load_multiple_5, nds_gw_load_multiple_6,\ ++ nds_gw_load_multiple_7,nds_gw_load_multiple_8, nds_gw_load_multiple_12,\ ++ nds_gw_store_multiple_1,nds_gw_store_multiple_2, nds_gw_store_multiple_3,\ ++ nds_gw_store_multiple_4,nds_gw_store_multiple_5, nds_gw_store_multiple_6,\ ++ nds_gw_store_multiple_7,nds_gw_store_multiple_8, nds_gw_store_multiple_12,\ ++ nds_gw_mmu,\ ++ nds_gw_dsp_alu, nds_gw_dsp_alu_round,\ ++ nds_gw_dsp_mul, nds_gw_dsp_mac, nds_gw_dsp_pack,\ ++ nds_gw_dsp_insb, nds_gw_dsp_cmp, nds_gw_dsp_clip,\ ++ nds_gw_dsp_wext, nds_gw_dsp_bpick" ++ "nds32_gw_last_load_to_ex_p" ++) +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32.h gcc-8.2.0/gcc/config/nds32/nds32.h +--- gcc-8.2.0.orig/gcc/config/nds32/nds32.h 2018-05-07 03:27:52.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32.h 2019-01-25 15:44:03.534160189 +0100 +@@ -36,6 +36,16 @@ + #define NDS32_SYMBOL_REF_RODATA_P(x) \ + ((SYMBOL_REF_FLAGS (x) & NDS32_SYMBOL_FLAG_RODATA) != 0) + ++enum nds32_relax_insn_type ++{ ++ RELAX_ORI, ++ RELAX_PLT_ADD, ++ RELAX_TLS_ADD_or_LW, ++ RELAX_TLS_ADD_LW, ++ RELAX_TLS_LW_JRAL, ++ RELAX_DONE ++}; ++ + /* Classifies expand result for expand helper function. */ + enum nds32_expand_result_type + { +@@ -140,6 +150,9 @@ + Check gcc/common/config/nds32/nds32-common.c for the optimizations that + apply -malways-align. */ + #define NDS32_ALIGN_P() (TARGET_ALWAYS_ALIGN) ++ ++#define NDS32_EXT_DSP_P() (TARGET_EXT_DSP && !TARGET_FORCE_NO_EXT_DSP) ++ + /* Get alignment according to mode or type information. + When 'type' is nonnull, there is no need to look at 'mode'. */ + #define NDS32_MODE_TYPE_ALIGN(mode, type) \ +@@ -305,6 +318,10 @@ + 2. The rtl lowering and optimization are close to target code. + For this case we need address to be strictly aligned. */ + int strict_aligned_p; ++ ++ /* Record two similar attributes status. */ ++ int attr_naked_p; ++ int attr_no_prologue_p; + }; + + /* A C structure that contains the arguments information. */ +@@ -350,7 +367,8 @@ + { + NDS32_NESTED, + NDS32_NOT_NESTED, +- NDS32_NESTED_READY ++ NDS32_NESTED_READY, ++ NDS32_CRITICAL + }; + + /* Define structure to record isr information. +@@ -378,6 +396,13 @@ + unless user specifies attribute to change it. */ + enum nds32_isr_nested_type nested_type; + ++ /* Secure isr level. ++ Currently we have 0-3 security level. ++ It should be set to 0 by default. ++ For security processors, this is determined by secure ++ attribute or compiler options. */ ++ unsigned int security_level; ++ + /* Total vectors. + The total vectors = interrupt + exception numbers + reset. + It should be set to 0 by default. +@@ -439,7 +464,30 @@ + NDS32_BUILTIN_FFB, + NDS32_BUILTIN_FFMISM, + NDS32_BUILTIN_FLMISM, +- ++ NDS32_BUILTIN_KADDW, ++ NDS32_BUILTIN_KSUBW, ++ NDS32_BUILTIN_KADDH, ++ NDS32_BUILTIN_KSUBH, ++ NDS32_BUILTIN_KDMBB, ++ NDS32_BUILTIN_V_KDMBB, ++ NDS32_BUILTIN_KDMBT, ++ NDS32_BUILTIN_V_KDMBT, ++ NDS32_BUILTIN_KDMTB, ++ NDS32_BUILTIN_V_KDMTB, ++ NDS32_BUILTIN_KDMTT, ++ NDS32_BUILTIN_V_KDMTT, ++ NDS32_BUILTIN_KHMBB, ++ NDS32_BUILTIN_V_KHMBB, ++ NDS32_BUILTIN_KHMBT, ++ NDS32_BUILTIN_V_KHMBT, ++ NDS32_BUILTIN_KHMTB, ++ NDS32_BUILTIN_V_KHMTB, ++ NDS32_BUILTIN_KHMTT, ++ NDS32_BUILTIN_V_KHMTT, ++ NDS32_BUILTIN_KSLRAW, ++ NDS32_BUILTIN_KSLRAW_U, ++ NDS32_BUILTIN_RDOV, ++ NDS32_BUILTIN_CLROV, + NDS32_BUILTIN_ROTR, + NDS32_BUILTIN_SVA, + NDS32_BUILTIN_SVS, +@@ -512,7 +560,295 @@ + NDS32_BUILTIN_SET_TRIG_LEVEL, + NDS32_BUILTIN_SET_TRIG_EDGE, + NDS32_BUILTIN_GET_TRIG_TYPE, +- ++ NDS32_BUILTIN_DSP_BEGIN, ++ NDS32_BUILTIN_ADD16, ++ NDS32_BUILTIN_V_UADD16, ++ NDS32_BUILTIN_V_SADD16, ++ NDS32_BUILTIN_RADD16, ++ NDS32_BUILTIN_V_RADD16, ++ NDS32_BUILTIN_URADD16, ++ NDS32_BUILTIN_V_URADD16, ++ NDS32_BUILTIN_KADD16, ++ NDS32_BUILTIN_V_KADD16, ++ NDS32_BUILTIN_UKADD16, ++ NDS32_BUILTIN_V_UKADD16, ++ NDS32_BUILTIN_SUB16, ++ NDS32_BUILTIN_V_USUB16, ++ NDS32_BUILTIN_V_SSUB16, ++ NDS32_BUILTIN_RSUB16, ++ NDS32_BUILTIN_V_RSUB16, ++ NDS32_BUILTIN_URSUB16, ++ NDS32_BUILTIN_V_URSUB16, ++ NDS32_BUILTIN_KSUB16, ++ NDS32_BUILTIN_V_KSUB16, ++ NDS32_BUILTIN_UKSUB16, ++ NDS32_BUILTIN_V_UKSUB16, ++ NDS32_BUILTIN_CRAS16, ++ NDS32_BUILTIN_V_UCRAS16, ++ NDS32_BUILTIN_V_SCRAS16, ++ NDS32_BUILTIN_RCRAS16, ++ NDS32_BUILTIN_V_RCRAS16, ++ NDS32_BUILTIN_URCRAS16, ++ NDS32_BUILTIN_V_URCRAS16, ++ NDS32_BUILTIN_KCRAS16, ++ NDS32_BUILTIN_V_KCRAS16, ++ NDS32_BUILTIN_UKCRAS16, ++ NDS32_BUILTIN_V_UKCRAS16, ++ NDS32_BUILTIN_CRSA16, ++ NDS32_BUILTIN_V_UCRSA16, ++ NDS32_BUILTIN_V_SCRSA16, ++ NDS32_BUILTIN_RCRSA16, ++ NDS32_BUILTIN_V_RCRSA16, ++ NDS32_BUILTIN_URCRSA16, ++ NDS32_BUILTIN_V_URCRSA16, ++ NDS32_BUILTIN_KCRSA16, ++ NDS32_BUILTIN_V_KCRSA16, ++ NDS32_BUILTIN_UKCRSA16, ++ NDS32_BUILTIN_V_UKCRSA16, ++ NDS32_BUILTIN_ADD8, ++ NDS32_BUILTIN_V_UADD8, ++ NDS32_BUILTIN_V_SADD8, ++ NDS32_BUILTIN_RADD8, ++ NDS32_BUILTIN_V_RADD8, ++ NDS32_BUILTIN_URADD8, ++ NDS32_BUILTIN_V_URADD8, ++ NDS32_BUILTIN_KADD8, ++ NDS32_BUILTIN_V_KADD8, ++ NDS32_BUILTIN_UKADD8, ++ NDS32_BUILTIN_V_UKADD8, ++ NDS32_BUILTIN_SUB8, ++ NDS32_BUILTIN_V_USUB8, ++ NDS32_BUILTIN_V_SSUB8, ++ NDS32_BUILTIN_RSUB8, ++ NDS32_BUILTIN_V_RSUB8, ++ NDS32_BUILTIN_URSUB8, ++ NDS32_BUILTIN_V_URSUB8, ++ NDS32_BUILTIN_KSUB8, ++ NDS32_BUILTIN_V_KSUB8, ++ NDS32_BUILTIN_UKSUB8, ++ NDS32_BUILTIN_V_UKSUB8, ++ NDS32_BUILTIN_SRA16, ++ NDS32_BUILTIN_V_SRA16, ++ NDS32_BUILTIN_SRA16_U, ++ NDS32_BUILTIN_V_SRA16_U, ++ NDS32_BUILTIN_SRL16, ++ NDS32_BUILTIN_V_SRL16, ++ NDS32_BUILTIN_SRL16_U, ++ NDS32_BUILTIN_V_SRL16_U, ++ NDS32_BUILTIN_SLL16, ++ NDS32_BUILTIN_V_SLL16, ++ NDS32_BUILTIN_KSLL16, ++ NDS32_BUILTIN_V_KSLL16, ++ NDS32_BUILTIN_KSLRA16, ++ NDS32_BUILTIN_V_KSLRA16, ++ NDS32_BUILTIN_KSLRA16_U, ++ NDS32_BUILTIN_V_KSLRA16_U, ++ NDS32_BUILTIN_CMPEQ16, ++ NDS32_BUILTIN_V_SCMPEQ16, ++ NDS32_BUILTIN_V_UCMPEQ16, ++ NDS32_BUILTIN_SCMPLT16, ++ NDS32_BUILTIN_V_SCMPLT16, ++ NDS32_BUILTIN_SCMPLE16, ++ NDS32_BUILTIN_V_SCMPLE16, ++ NDS32_BUILTIN_UCMPLT16, ++ NDS32_BUILTIN_V_UCMPLT16, ++ NDS32_BUILTIN_UCMPLE16, ++ NDS32_BUILTIN_V_UCMPLE16, ++ NDS32_BUILTIN_CMPEQ8, ++ NDS32_BUILTIN_V_SCMPEQ8, ++ NDS32_BUILTIN_V_UCMPEQ8, ++ NDS32_BUILTIN_SCMPLT8, ++ NDS32_BUILTIN_V_SCMPLT8, ++ NDS32_BUILTIN_SCMPLE8, ++ NDS32_BUILTIN_V_SCMPLE8, ++ NDS32_BUILTIN_UCMPLT8, ++ NDS32_BUILTIN_V_UCMPLT8, ++ NDS32_BUILTIN_UCMPLE8, ++ NDS32_BUILTIN_V_UCMPLE8, ++ NDS32_BUILTIN_SMIN16, ++ NDS32_BUILTIN_V_SMIN16, ++ NDS32_BUILTIN_UMIN16, ++ NDS32_BUILTIN_V_UMIN16, ++ NDS32_BUILTIN_SMAX16, ++ NDS32_BUILTIN_V_SMAX16, ++ NDS32_BUILTIN_UMAX16, ++ NDS32_BUILTIN_V_UMAX16, ++ NDS32_BUILTIN_SCLIP16, ++ NDS32_BUILTIN_V_SCLIP16, ++ NDS32_BUILTIN_UCLIP16, ++ NDS32_BUILTIN_V_UCLIP16, ++ NDS32_BUILTIN_KHM16, ++ NDS32_BUILTIN_V_KHM16, ++ NDS32_BUILTIN_KHMX16, ++ NDS32_BUILTIN_V_KHMX16, ++ NDS32_BUILTIN_KABS16, ++ NDS32_BUILTIN_V_KABS16, ++ NDS32_BUILTIN_SMIN8, ++ NDS32_BUILTIN_V_SMIN8, ++ NDS32_BUILTIN_UMIN8, ++ NDS32_BUILTIN_V_UMIN8, ++ NDS32_BUILTIN_SMAX8, ++ NDS32_BUILTIN_V_SMAX8, ++ NDS32_BUILTIN_UMAX8, ++ NDS32_BUILTIN_V_UMAX8, ++ NDS32_BUILTIN_KABS8, ++ NDS32_BUILTIN_V_KABS8, ++ NDS32_BUILTIN_SUNPKD810, ++ NDS32_BUILTIN_V_SUNPKD810, ++ NDS32_BUILTIN_SUNPKD820, ++ NDS32_BUILTIN_V_SUNPKD820, ++ NDS32_BUILTIN_SUNPKD830, ++ NDS32_BUILTIN_V_SUNPKD830, ++ NDS32_BUILTIN_SUNPKD831, ++ NDS32_BUILTIN_V_SUNPKD831, ++ NDS32_BUILTIN_ZUNPKD810, ++ NDS32_BUILTIN_V_ZUNPKD810, ++ NDS32_BUILTIN_ZUNPKD820, ++ NDS32_BUILTIN_V_ZUNPKD820, ++ NDS32_BUILTIN_ZUNPKD830, ++ NDS32_BUILTIN_V_ZUNPKD830, ++ NDS32_BUILTIN_ZUNPKD831, ++ NDS32_BUILTIN_V_ZUNPKD831, ++ NDS32_BUILTIN_RADDW, ++ NDS32_BUILTIN_URADDW, ++ NDS32_BUILTIN_RSUBW, ++ NDS32_BUILTIN_URSUBW, ++ NDS32_BUILTIN_SRA_U, ++ NDS32_BUILTIN_KSLL, ++ NDS32_BUILTIN_PKBB16, ++ NDS32_BUILTIN_V_PKBB16, ++ NDS32_BUILTIN_PKBT16, ++ NDS32_BUILTIN_V_PKBT16, ++ NDS32_BUILTIN_PKTB16, ++ NDS32_BUILTIN_V_PKTB16, ++ NDS32_BUILTIN_PKTT16, ++ NDS32_BUILTIN_V_PKTT16, ++ NDS32_BUILTIN_SMMUL, ++ NDS32_BUILTIN_SMMUL_U, ++ NDS32_BUILTIN_KMMAC, ++ NDS32_BUILTIN_KMMAC_U, ++ NDS32_BUILTIN_KMMSB, ++ NDS32_BUILTIN_KMMSB_U, ++ NDS32_BUILTIN_KWMMUL, ++ NDS32_BUILTIN_KWMMUL_U, ++ NDS32_BUILTIN_SMMWB, ++ NDS32_BUILTIN_V_SMMWB, ++ NDS32_BUILTIN_SMMWB_U, ++ NDS32_BUILTIN_V_SMMWB_U, ++ NDS32_BUILTIN_SMMWT, ++ NDS32_BUILTIN_V_SMMWT, ++ NDS32_BUILTIN_SMMWT_U, ++ NDS32_BUILTIN_V_SMMWT_U, ++ NDS32_BUILTIN_KMMAWB, ++ NDS32_BUILTIN_V_KMMAWB, ++ NDS32_BUILTIN_KMMAWB_U, ++ NDS32_BUILTIN_V_KMMAWB_U, ++ NDS32_BUILTIN_KMMAWT, ++ NDS32_BUILTIN_V_KMMAWT, ++ NDS32_BUILTIN_KMMAWT_U, ++ NDS32_BUILTIN_V_KMMAWT_U, ++ NDS32_BUILTIN_SMBB, ++ NDS32_BUILTIN_V_SMBB, ++ NDS32_BUILTIN_SMBT, ++ NDS32_BUILTIN_V_SMBT, ++ NDS32_BUILTIN_SMTT, ++ NDS32_BUILTIN_V_SMTT, ++ NDS32_BUILTIN_KMDA, ++ NDS32_BUILTIN_V_KMDA, ++ NDS32_BUILTIN_KMXDA, ++ NDS32_BUILTIN_V_KMXDA, ++ NDS32_BUILTIN_SMDS, ++ NDS32_BUILTIN_V_SMDS, ++ NDS32_BUILTIN_SMDRS, ++ NDS32_BUILTIN_V_SMDRS, ++ NDS32_BUILTIN_SMXDS, ++ NDS32_BUILTIN_V_SMXDS, ++ NDS32_BUILTIN_KMABB, ++ NDS32_BUILTIN_V_KMABB, ++ NDS32_BUILTIN_KMABT, ++ NDS32_BUILTIN_V_KMABT, ++ NDS32_BUILTIN_KMATT, ++ NDS32_BUILTIN_V_KMATT, ++ NDS32_BUILTIN_KMADA, ++ NDS32_BUILTIN_V_KMADA, ++ NDS32_BUILTIN_KMAXDA, ++ NDS32_BUILTIN_V_KMAXDA, ++ NDS32_BUILTIN_KMADS, ++ NDS32_BUILTIN_V_KMADS, ++ NDS32_BUILTIN_KMADRS, ++ NDS32_BUILTIN_V_KMADRS, ++ NDS32_BUILTIN_KMAXDS, ++ NDS32_BUILTIN_V_KMAXDS, ++ NDS32_BUILTIN_KMSDA, ++ NDS32_BUILTIN_V_KMSDA, ++ NDS32_BUILTIN_KMSXDA, ++ NDS32_BUILTIN_V_KMSXDA, ++ NDS32_BUILTIN_SMAL, ++ NDS32_BUILTIN_V_SMAL, ++ NDS32_BUILTIN_BITREV, ++ NDS32_BUILTIN_WEXT, ++ NDS32_BUILTIN_BPICK, ++ NDS32_BUILTIN_INSB, ++ NDS32_BUILTIN_SADD64, ++ NDS32_BUILTIN_UADD64, ++ NDS32_BUILTIN_RADD64, ++ NDS32_BUILTIN_URADD64, ++ NDS32_BUILTIN_KADD64, ++ NDS32_BUILTIN_UKADD64, ++ NDS32_BUILTIN_SSUB64, ++ NDS32_BUILTIN_USUB64, ++ NDS32_BUILTIN_RSUB64, ++ NDS32_BUILTIN_URSUB64, ++ NDS32_BUILTIN_KSUB64, ++ NDS32_BUILTIN_UKSUB64, ++ NDS32_BUILTIN_SMAR64, ++ NDS32_BUILTIN_SMSR64, ++ NDS32_BUILTIN_UMAR64, ++ NDS32_BUILTIN_UMSR64, ++ NDS32_BUILTIN_KMAR64, ++ NDS32_BUILTIN_KMSR64, ++ NDS32_BUILTIN_UKMAR64, ++ NDS32_BUILTIN_UKMSR64, ++ NDS32_BUILTIN_SMALBB, ++ NDS32_BUILTIN_V_SMALBB, ++ NDS32_BUILTIN_SMALBT, ++ NDS32_BUILTIN_V_SMALBT, ++ NDS32_BUILTIN_SMALTT, ++ NDS32_BUILTIN_V_SMALTT, ++ NDS32_BUILTIN_SMALDA, ++ NDS32_BUILTIN_V_SMALDA, ++ NDS32_BUILTIN_SMALXDA, ++ NDS32_BUILTIN_V_SMALXDA, ++ NDS32_BUILTIN_SMALDS, ++ NDS32_BUILTIN_V_SMALDS, ++ NDS32_BUILTIN_SMALDRS, ++ NDS32_BUILTIN_V_SMALDRS, ++ NDS32_BUILTIN_SMALXDS, ++ NDS32_BUILTIN_V_SMALXDS, ++ NDS32_BUILTIN_SMUL16, ++ NDS32_BUILTIN_V_SMUL16, ++ NDS32_BUILTIN_SMULX16, ++ NDS32_BUILTIN_V_SMULX16, ++ NDS32_BUILTIN_UMUL16, ++ NDS32_BUILTIN_V_UMUL16, ++ NDS32_BUILTIN_UMULX16, ++ NDS32_BUILTIN_V_UMULX16, ++ NDS32_BUILTIN_SMSLDA, ++ NDS32_BUILTIN_V_SMSLDA, ++ NDS32_BUILTIN_SMSLXDA, ++ NDS32_BUILTIN_V_SMSLXDA, ++ NDS32_BUILTIN_UCLIP32, ++ NDS32_BUILTIN_SCLIP32, ++ NDS32_BUILTIN_KABS, ++ NDS32_BUILTIN_UALOAD_U16, ++ NDS32_BUILTIN_UALOAD_S16, ++ NDS32_BUILTIN_UALOAD_U8, ++ NDS32_BUILTIN_UALOAD_S8, ++ NDS32_BUILTIN_UASTORE_U16, ++ NDS32_BUILTIN_UASTORE_S16, ++ NDS32_BUILTIN_UASTORE_U8, ++ NDS32_BUILTIN_UASTORE_S8, ++ NDS32_BUILTIN_DSP_END, + NDS32_BUILTIN_UNALIGNED_FEATURE, + NDS32_BUILTIN_ENABLE_UNALIGNED, + NDS32_BUILTIN_DISABLE_UNALIGNED, +@@ -521,16 +857,30 @@ + + /* ------------------------------------------------------------------------ */ + +-#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2) ++#define TARGET_ISR_VECTOR_SIZE_4_BYTE \ ++ (nds32_isr_vector_size == 4) + ++#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2) + #define TARGET_ISA_V3 \ + (nds32_arch_option == ARCH_V3 \ ++ || nds32_arch_option == ARCH_V3J \ + || nds32_arch_option == ARCH_V3F \ + || nds32_arch_option == ARCH_V3S) + #define TARGET_ISA_V3M (nds32_arch_option == ARCH_V3M) + ++#define TARGET_PIPELINE_N7 \ ++ (nds32_cpu_option == CPU_N7) ++#define TARGET_PIPELINE_N8 \ ++ (nds32_cpu_option == CPU_N6 \ ++ || nds32_cpu_option == CPU_N8) + #define TARGET_PIPELINE_N9 \ + (nds32_cpu_option == CPU_N9) ++#define TARGET_PIPELINE_N10 \ ++ (nds32_cpu_option == CPU_N10) ++#define TARGET_PIPELINE_N13 \ ++ (nds32_cpu_option == CPU_N12 || nds32_cpu_option == CPU_N13) ++#define TARGET_PIPELINE_GRAYWOLF \ ++ (nds32_cpu_option == CPU_GRAYWOLF) + #define TARGET_PIPELINE_SIMPLE \ + (nds32_cpu_option == CPU_SIMPLE) + +@@ -541,6 +891,12 @@ + #define TARGET_CMODEL_LARGE \ + (nds32_cmodel_option == CMODEL_LARGE) + ++#define TARGET_ICT_MODEL_SMALL \ ++ (nds32_ict_model == ICT_MODEL_SMALL) ++ ++#define TARGET_ICT_MODEL_LARGE \ ++ (nds32_ict_model == ICT_MODEL_LARGE) ++ + /* When -mcmodel=small or -mcmodel=medium, + compiler may generate gp-base instruction directly. */ + #define TARGET_GP_DIRECT \ +@@ -576,6 +932,21 @@ + #endif + + #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 ++# define NDS32_EXT_DSP_SPEC " %{!mno-ext-dsp:-mext-dsp}" ++#else ++# define NDS32_EXT_DSP_SPEC "" ++#endif ++ + /* ------------------------------------------------------------------------ */ + + /* Controlling the Compilation Driver. */ +@@ -591,11 +962,15 @@ + {"float", "%{!mfloat-abi=*:-mfloat-abi=%(VALUE)}" } + + #define CC1_SPEC \ +- "" ++ NDS32_EXT_DSP_SPEC + + #define ASM_SPEC \ + " %{mbig-endian:-EB} %{mlittle-endian:-EL}" \ + " %{march=*:-march=%*}" \ ++ " %{mno-16-bit|mno-16bit:-mno-16bit-ext}" \ ++ " %{march=v3m:%{!mfull-regs:%{!mreduced-regs:-mreduced-regs}}}" \ ++ " %{mfull-regs:-mno-reduced-regs}" \ ++ " %{mreduced-regs:-mreduced-regs}" \ + " %{mabi=*:-mabi=v%*}" \ + " %{mconfig-fpu=*:-mfpu-freg=%*}" \ + " %{mext-fpu-mac:-mmac}" \ +@@ -603,35 +978,9 @@ + " %{mext-fpu-sp:-mfpu-sp-ext}" \ + " %{mno-ext-fpu-sp:-mno-fpu-sp-ext}" \ + " %{mext-fpu-dp:-mfpu-dp-ext}" \ +- " %{mno-ext-fpu-sp:-mno-fpu-dp-ext}" +- +-/* 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}" ++ " %{mno-ext-fpu-sp:-mno-fpu-dp-ext}" \ ++ " %{mext-dsp:-mdsp-ext}" \ ++ " %{O|O1|O2|O3|Ofast:-O1;:-Os}" + + /* The TARGET_BIG_ENDIAN_DEFAULT is defined if we + configure gcc with --target=nds32be-* setting. +@@ -642,9 +991,11 @@ + # define NDS32_ENDIAN_DEFAULT "mlittle-endian" + #endif + +-/* Currently we only have elf toolchain, +- where -mcmodel=medium is always the default. */ +-#define NDS32_CMODEL_DEFAULT "mcmodel=medium" ++#if TARGET_ELF ++# define NDS32_CMODEL_DEFAULT "mcmodel=medium" ++#else ++# define NDS32_CMODEL_DEFAULT "mcmodel=large" ++#endif + + #define MULTILIB_DEFAULTS \ + { NDS32_ENDIAN_DEFAULT, NDS32_CMODEL_DEFAULT } +@@ -1139,6 +1490,11 @@ + + #define PIC_OFFSET_TABLE_REGNUM GP_REGNUM + ++#define SYMBOLIC_CONST_P(X) \ ++(GET_CODE (X) == SYMBOL_REF \ ++ || GET_CODE (X) == LABEL_REF \ ++ || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X))) ++ + + /* Defining the Output Assembler Language. */ + +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32_init.inc gcc-8.2.0/gcc/config/nds32/nds32_init.inc +--- gcc-8.2.0.orig/gcc/config/nds32/nds32_init.inc 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32_init.inc 2019-01-25 15:38:32.833242671 +0100 +@@ -0,0 +1,43 @@ ++/* ++ * nds32_init.inc ++ * ++ * NDS32 architecture startup assembler header file ++ * ++ */ ++ ++.macro nds32_init ++ ++ ! Initialize GP for data access ++ la $gp, _SDA_BASE_ ++ ++#if defined(__NDS32_EXT_EX9__) ++ ! Check HW for EX9 ++ mfsr $r0, $MSC_CFG ++ li $r1, (1 << 24) ++ and $r2, $r0, $r1 ++ beqz $r2, 1f ++ ++ ! Initialize the table base of EX9 instruction ++ la $r0, _ITB_BASE_ ++ mtusr $r0, $ITB ++1: ++#endif ++ ++#if defined(__NDS32_EXT_FPU_DP__) || defined(__NDS32_EXT_FPU_SP__) ++ ! Enable FPU ++ mfsr $r0, $FUCOP_CTL ++ ori $r0, $r0, #0x1 ++ mtsr $r0, $FUCOP_CTL ++ dsb ++ ++ ! Enable denormalized flush-to-Zero mode ++ fmfcsr $r0 ++ ori $r0,$r0,#0x1000 ++ fmtcsr $r0 ++ dsb ++#endif ++ ++ ! Initialize default stack pointer ++ la $sp, _stack ++ ++.endm +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-intrinsic.c gcc-8.2.0/gcc/config/nds32/nds32-intrinsic.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-intrinsic.c 2018-04-22 09:46:39.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-intrinsic.c 2019-01-25 15:38:32.825242648 +0100 +@@ -519,6 +519,7 @@ + { + NDS32_BUILTIN(unspec_fmfcfg, "fmfcfg", FMFCFG) + NDS32_BUILTIN(unspec_fmfcsr, "fmfcsr", FMFCSR) ++ NDS32_BUILTIN(unspec_volatile_rdov, "rdov", RDOV) + NDS32_BUILTIN(unspec_get_current_sp, "get_current_sp", GET_CURRENT_SP) + NDS32_BUILTIN(unspec_return_address, "return_address", RETURN_ADDRESS) + NDS32_BUILTIN(unspec_get_all_pending_int, "get_all_pending_int", +@@ -558,6 +559,31 @@ + NDS32_NO_TARGET_BUILTIN(unspec_ret_itoff, "ret_itoff", RET_ITOFF) + NDS32_NO_TARGET_BUILTIN(unspec_set_current_sp, + "set_current_sp", SET_CURRENT_SP) ++ NDS32_BUILTIN(kabsv2hi2, "kabs16", KABS16) ++ NDS32_BUILTIN(kabsv2hi2, "v_kabs16", V_KABS16) ++ NDS32_BUILTIN(kabsv4qi2, "kabs8", KABS8) ++ NDS32_BUILTIN(kabsv4qi2, "v_kabs8", V_KABS8) ++ NDS32_BUILTIN(sunpkd810, "sunpkd810", SUNPKD810) ++ NDS32_BUILTIN(sunpkd810, "v_sunpkd810", V_SUNPKD810) ++ NDS32_BUILTIN(sunpkd820, "sunpkd820", SUNPKD820) ++ NDS32_BUILTIN(sunpkd820, "v_sunpkd820", V_SUNPKD820) ++ NDS32_BUILTIN(sunpkd830, "sunpkd830", SUNPKD830) ++ NDS32_BUILTIN(sunpkd830, "v_sunpkd830", V_SUNPKD830) ++ NDS32_BUILTIN(sunpkd831, "sunpkd831", SUNPKD831) ++ NDS32_BUILTIN(sunpkd831, "v_sunpkd831", V_SUNPKD831) ++ NDS32_BUILTIN(zunpkd810, "zunpkd810", ZUNPKD810) ++ NDS32_BUILTIN(zunpkd810, "v_zunpkd810", V_ZUNPKD810) ++ NDS32_BUILTIN(zunpkd820, "zunpkd820", ZUNPKD820) ++ NDS32_BUILTIN(zunpkd820, "v_zunpkd820", V_ZUNPKD820) ++ NDS32_BUILTIN(zunpkd830, "zunpkd830", ZUNPKD830) ++ NDS32_BUILTIN(zunpkd830, "v_zunpkd830", V_ZUNPKD830) ++ NDS32_BUILTIN(zunpkd831, "zunpkd831", ZUNPKD831) ++ NDS32_BUILTIN(zunpkd831, "v_zunpkd831", V_ZUNPKD831) ++ NDS32_BUILTIN(unspec_kabs, "kabs", KABS) ++ NDS32_BUILTIN(unaligned_loadv2hi, "get_unaligned_u16x2", UALOAD_U16) ++ NDS32_BUILTIN(unaligned_loadv2hi, "get_unaligned_s16x2", UALOAD_S16) ++ NDS32_BUILTIN(unaligned_loadv4qi, "get_unaligned_u8x4", UALOAD_U8) ++ NDS32_BUILTIN(unaligned_loadv4qi, "get_unaligned_s8x4", UALOAD_S8) + }; + + /* Intrinsics that take just one argument. and the argument is immediate. */ +@@ -593,6 +619,28 @@ + NDS32_BUILTIN(unspec_ffb, "ffb", FFB) + NDS32_BUILTIN(unspec_ffmism, "ffmsim", FFMISM) + NDS32_BUILTIN(unspec_flmism, "flmism", FLMISM) ++ NDS32_BUILTIN(unspec_kaddw, "kaddw", KADDW) ++ NDS32_BUILTIN(unspec_kaddh, "kaddh", KADDH) ++ NDS32_BUILTIN(unspec_ksubw, "ksubw", KSUBW) ++ NDS32_BUILTIN(unspec_ksubh, "ksubh", KSUBH) ++ NDS32_BUILTIN(unspec_kdmbb, "kdmbb", KDMBB) ++ NDS32_BUILTIN(unspec_kdmbb, "v_kdmbb", V_KDMBB) ++ NDS32_BUILTIN(unspec_kdmbt, "kdmbt", KDMBT) ++ NDS32_BUILTIN(unspec_kdmbt, "v_kdmbt", V_KDMBT) ++ NDS32_BUILTIN(unspec_kdmtb, "kdmtb", KDMTB) ++ NDS32_BUILTIN(unspec_kdmtb, "v_kdmtb", V_KDMTB) ++ NDS32_BUILTIN(unspec_kdmtt, "kdmtt", KDMTT) ++ NDS32_BUILTIN(unspec_kdmtt, "v_kdmtt", V_KDMTT) ++ NDS32_BUILTIN(unspec_khmbb, "khmbb", KHMBB) ++ NDS32_BUILTIN(unspec_khmbb, "v_khmbb", V_KHMBB) ++ NDS32_BUILTIN(unspec_khmbt, "khmbt", KHMBT) ++ NDS32_BUILTIN(unspec_khmbt, "v_khmbt", V_KHMBT) ++ NDS32_BUILTIN(unspec_khmtb, "khmtb", KHMTB) ++ NDS32_BUILTIN(unspec_khmtb, "v_khmtb", V_KHMTB) ++ NDS32_BUILTIN(unspec_khmtt, "khmtt", KHMTT) ++ NDS32_BUILTIN(unspec_khmtt, "v_khmtt", V_KHMTT) ++ NDS32_BUILTIN(unspec_kslraw, "kslraw", KSLRAW) ++ NDS32_BUILTIN(unspec_kslrawu, "kslraw_u", KSLRAW_U) + NDS32_BUILTIN(rotrsi3, "rotr", ROTR) + NDS32_BUILTIN(unspec_sva, "sva", SVA) + NDS32_BUILTIN(unspec_svs, "svs", SVS) +@@ -603,7 +651,202 @@ + NDS32_NO_TARGET_BUILTIN(unaligned_store_hw, "unaligned_store_hw", UASTORE_HW) + NDS32_NO_TARGET_BUILTIN(unaligned_storesi, "unaligned_store_hw", UASTORE_W) + NDS32_NO_TARGET_BUILTIN(unaligned_storedi, "unaligned_store_hw", UASTORE_DW) +- ++ NDS32_BUILTIN(addv2hi3, "add16", ADD16) ++ NDS32_BUILTIN(addv2hi3, "v_uadd16", V_UADD16) ++ NDS32_BUILTIN(addv2hi3, "v_sadd16", V_SADD16) ++ NDS32_BUILTIN(raddv2hi3, "radd16", RADD16) ++ NDS32_BUILTIN(raddv2hi3, "v_radd16", V_RADD16) ++ NDS32_BUILTIN(uraddv2hi3, "uradd16", URADD16) ++ NDS32_BUILTIN(uraddv2hi3, "v_uradd16", V_URADD16) ++ NDS32_BUILTIN(kaddv2hi3, "kadd16", KADD16) ++ NDS32_BUILTIN(kaddv2hi3, "v_kadd16", V_KADD16) ++ NDS32_BUILTIN(ukaddv2hi3, "ukadd16", UKADD16) ++ NDS32_BUILTIN(ukaddv2hi3, "v_ukadd16", V_UKADD16) ++ NDS32_BUILTIN(subv2hi3, "sub16", SUB16) ++ NDS32_BUILTIN(subv2hi3, "v_usub16", V_USUB16) ++ NDS32_BUILTIN(subv2hi3, "v_ssub16", V_SSUB16) ++ NDS32_BUILTIN(rsubv2hi3, "rsub16", RSUB16) ++ NDS32_BUILTIN(rsubv2hi3, "v_rsub16", V_RSUB16) ++ NDS32_BUILTIN(ursubv2hi3, "ursub16", URSUB16) ++ NDS32_BUILTIN(ursubv2hi3, "v_ursub16", V_URSUB16) ++ NDS32_BUILTIN(ksubv2hi3, "ksub16", KSUB16) ++ NDS32_BUILTIN(ksubv2hi3, "v_ksub16", V_KSUB16) ++ NDS32_BUILTIN(uksubv2hi3, "uksub16", UKSUB16) ++ NDS32_BUILTIN(uksubv2hi3, "v_uksub16", V_UKSUB16) ++ NDS32_BUILTIN(cras16_1, "cras16", CRAS16) ++ NDS32_BUILTIN(cras16_1, "v_ucras16", V_UCRAS16) ++ NDS32_BUILTIN(cras16_1, "v_scras16", V_SCRAS16) ++ NDS32_BUILTIN(rcras16_1, "rcras16", RCRAS16) ++ NDS32_BUILTIN(rcras16_1, "v_rcras16", V_RCRAS16) ++ NDS32_BUILTIN(urcras16_1, "urcras16", URCRAS16) ++ NDS32_BUILTIN(urcras16_1, "v_urcras16", V_URCRAS16) ++ NDS32_BUILTIN(kcras16_1, "kcras16", KCRAS16) ++ NDS32_BUILTIN(kcras16_1, "v_kcras16", V_KCRAS16) ++ NDS32_BUILTIN(ukcras16_1, "ukcras16", UKCRAS16) ++ NDS32_BUILTIN(ukcras16_1, "v_ukcras16", V_UKCRAS16) ++ NDS32_BUILTIN(crsa16_1, "crsa16", CRSA16) ++ NDS32_BUILTIN(crsa16_1, "v_ucrsa16", V_UCRSA16) ++ NDS32_BUILTIN(crsa16_1, "v_scrsa16", V_SCRSA16) ++ NDS32_BUILTIN(rcrsa16_1, "rcrsa16", RCRSA16) ++ NDS32_BUILTIN(rcrsa16_1, "v_rcrsa16", V_RCRSA16) ++ NDS32_BUILTIN(urcrsa16_1, "urcrsa16", URCRSA16) ++ NDS32_BUILTIN(urcrsa16_1, "v_urcrsa16", V_URCRSA16) ++ NDS32_BUILTIN(kcrsa16_1, "kcrsa16", KCRSA16) ++ NDS32_BUILTIN(kcrsa16_1, "v_kcrsa16", V_KCRSA16) ++ NDS32_BUILTIN(ukcrsa16_1, "ukcrsa16", UKCRSA16) ++ NDS32_BUILTIN(ukcrsa16_1, "v_ukcrsa16", V_UKCRSA16) ++ NDS32_BUILTIN(addv4qi3, "add8", ADD8) ++ NDS32_BUILTIN(addv4qi3, "v_uadd8", V_UADD8) ++ NDS32_BUILTIN(addv4qi3, "v_sadd8", V_SADD8) ++ NDS32_BUILTIN(raddv4qi3, "radd8", RADD8) ++ NDS32_BUILTIN(raddv4qi3, "v_radd8", V_RADD8) ++ NDS32_BUILTIN(uraddv4qi3, "uradd8", URADD8) ++ NDS32_BUILTIN(uraddv4qi3, "v_uradd8", V_URADD8) ++ NDS32_BUILTIN(kaddv4qi3, "kadd8", KADD8) ++ NDS32_BUILTIN(kaddv4qi3, "v_kadd8", V_KADD8) ++ NDS32_BUILTIN(ukaddv4qi3, "ukadd8", UKADD8) ++ NDS32_BUILTIN(ukaddv4qi3, "v_ukadd8", V_UKADD8) ++ NDS32_BUILTIN(subv4qi3, "sub8", SUB8) ++ NDS32_BUILTIN(subv4qi3, "v_usub8", V_USUB8) ++ NDS32_BUILTIN(subv4qi3, "v_ssub8", V_SSUB8) ++ NDS32_BUILTIN(rsubv4qi3, "rsub8", RSUB8) ++ NDS32_BUILTIN(rsubv4qi3, "v_rsub8", V_RSUB8) ++ NDS32_BUILTIN(ursubv4qi3, "ursub8", URSUB8) ++ NDS32_BUILTIN(ursubv4qi3, "v_ursub8", V_URSUB8) ++ NDS32_BUILTIN(ksubv4qi3, "ksub8", KSUB8) ++ NDS32_BUILTIN(ksubv4qi3, "v_ksub8", V_KSUB8) ++ NDS32_BUILTIN(uksubv4qi3, "uksub8", UKSUB8) ++ NDS32_BUILTIN(uksubv4qi3, "v_uksub8", V_UKSUB8) ++ NDS32_BUILTIN(ashrv2hi3, "sra16", SRA16) ++ NDS32_BUILTIN(ashrv2hi3, "v_sra16", V_SRA16) ++ NDS32_BUILTIN(sra16_round, "sra16_u", SRA16_U) ++ NDS32_BUILTIN(sra16_round, "v_sra16_u", V_SRA16_U) ++ NDS32_BUILTIN(lshrv2hi3, "srl16", SRL16) ++ NDS32_BUILTIN(lshrv2hi3, "v_srl16", V_SRL16) ++ NDS32_BUILTIN(srl16_round, "srl16_u", SRL16_U) ++ NDS32_BUILTIN(srl16_round, "v_srl16_u", V_SRL16_U) ++ NDS32_BUILTIN(ashlv2hi3, "sll16", SLL16) ++ NDS32_BUILTIN(ashlv2hi3, "v_sll16", V_SLL16) ++ NDS32_BUILTIN(kslli16, "ksll16", KSLL16) ++ NDS32_BUILTIN(kslli16, "v_ksll16", V_KSLL16) ++ NDS32_BUILTIN(kslra16, "kslra16", KSLRA16) ++ NDS32_BUILTIN(kslra16, "v_kslra16", V_KSLRA16) ++ NDS32_BUILTIN(kslra16_round, "kslra16_u", KSLRA16_U) ++ NDS32_BUILTIN(kslra16_round, "v_kslra16_u", V_KSLRA16_U) ++ NDS32_BUILTIN(cmpeq16, "cmpeq16", CMPEQ16) ++ NDS32_BUILTIN(cmpeq16, "v_scmpeq16", V_SCMPEQ16) ++ NDS32_BUILTIN(cmpeq16, "v_ucmpeq16", V_UCMPEQ16) ++ NDS32_BUILTIN(scmplt16, "scmplt16", SCMPLT16) ++ NDS32_BUILTIN(scmplt16, "v_scmplt16", V_SCMPLT16) ++ NDS32_BUILTIN(scmple16, "scmple16", SCMPLE16) ++ NDS32_BUILTIN(scmple16, "v_scmple16", V_SCMPLE16) ++ NDS32_BUILTIN(ucmplt16, "ucmplt16", UCMPLT16) ++ NDS32_BUILTIN(ucmplt16, "v_ucmplt16", V_UCMPLT16) ++ NDS32_BUILTIN(ucmplt16, "ucmple16", UCMPLE16) ++ NDS32_BUILTIN(ucmplt16, "v_ucmple16", V_UCMPLE16) ++ NDS32_BUILTIN(cmpeq8, "cmpeq8", CMPEQ8) ++ NDS32_BUILTIN(cmpeq8, "v_scmpeq8", V_SCMPEQ8) ++ NDS32_BUILTIN(cmpeq8, "v_ucmpeq8", V_UCMPEQ8) ++ NDS32_BUILTIN(scmplt8, "scmplt8", SCMPLT8) ++ NDS32_BUILTIN(scmplt8, "v_scmplt8", V_SCMPLT8) ++ NDS32_BUILTIN(scmple8, "scmple8", SCMPLE8) ++ NDS32_BUILTIN(scmple8, "v_scmple8", V_SCMPLE8) ++ NDS32_BUILTIN(ucmplt8, "ucmplt8", UCMPLT8) ++ NDS32_BUILTIN(ucmplt8, "v_ucmplt8", V_UCMPLT8) ++ NDS32_BUILTIN(ucmplt8, "ucmple8", UCMPLE8) ++ NDS32_BUILTIN(ucmplt8, "v_ucmple8", V_UCMPLE8) ++ NDS32_BUILTIN(sminv2hi3, "smin16", SMIN16) ++ NDS32_BUILTIN(sminv2hi3, "v_smin16", V_SMIN16) ++ NDS32_BUILTIN(uminv2hi3, "umin16", UMIN16) ++ NDS32_BUILTIN(uminv2hi3, "v_umin16", V_UMIN16) ++ NDS32_BUILTIN(smaxv2hi3, "smax16", SMAX16) ++ NDS32_BUILTIN(smaxv2hi3, "v_smax16", V_SMAX16) ++ NDS32_BUILTIN(umaxv2hi3, "umax16", UMAX16) ++ NDS32_BUILTIN(umaxv2hi3, "v_umax16", V_UMAX16) ++ NDS32_BUILTIN(khm16, "khm16", KHM16) ++ NDS32_BUILTIN(khm16, "v_khm16", V_KHM16) ++ NDS32_BUILTIN(khmx16, "khmx16", KHMX16) ++ NDS32_BUILTIN(khmx16, "v_khmx16", V_KHMX16) ++ NDS32_BUILTIN(sminv4qi3, "smin8", SMIN8) ++ NDS32_BUILTIN(sminv4qi3, "v_smin8", V_SMIN8) ++ NDS32_BUILTIN(uminv4qi3, "umin8", UMIN8) ++ NDS32_BUILTIN(uminv4qi3, "v_umin8", V_UMIN8) ++ NDS32_BUILTIN(smaxv4qi3, "smax8", SMAX8) ++ NDS32_BUILTIN(smaxv4qi3, "v_smax8", V_SMAX8) ++ NDS32_BUILTIN(umaxv4qi3, "umax8", UMAX8) ++ NDS32_BUILTIN(umaxv4qi3, "v_umax8", V_UMAX8) ++ NDS32_BUILTIN(raddsi3, "raddw", RADDW) ++ NDS32_BUILTIN(uraddsi3, "uraddw", URADDW) ++ NDS32_BUILTIN(rsubsi3, "rsubw", RSUBW) ++ NDS32_BUILTIN(ursubsi3, "ursubw", URSUBW) ++ NDS32_BUILTIN(sraiu, "sra_u", SRA_U) ++ NDS32_BUILTIN(kssl, "ksll", KSLL) ++ NDS32_BUILTIN(pkbb, "pkbb16", PKBB16) ++ NDS32_BUILTIN(pkbb, "v_pkbb16", V_PKBB16) ++ NDS32_BUILTIN(pkbt, "pkbt16", PKBT16) ++ NDS32_BUILTIN(pkbt, "v_pkbt16", V_PKBT16) ++ NDS32_BUILTIN(pktb, "pktb16", PKTB16) ++ NDS32_BUILTIN(pktb, "v_pktb16", V_PKTB16) ++ NDS32_BUILTIN(pktt, "pktt16", PKTT16) ++ NDS32_BUILTIN(pktt, "v_pktt16", V_PKTT16) ++ NDS32_BUILTIN(smulsi3_highpart, "smmul", SMMUL) ++ NDS32_BUILTIN(smmul_round, "smmul_u", SMMUL_U) ++ NDS32_BUILTIN(smmwb, "smmwb", SMMWB) ++ NDS32_BUILTIN(smmwb, "v_smmwb", V_SMMWB) ++ NDS32_BUILTIN(smmwb_round, "smmwb_u", SMMWB_U) ++ NDS32_BUILTIN(smmwb_round, "v_smmwb_u", V_SMMWB_U) ++ NDS32_BUILTIN(smmwt, "smmwt", SMMWT) ++ NDS32_BUILTIN(smmwt, "v_smmwt", V_SMMWT) ++ NDS32_BUILTIN(smmwt_round, "smmwt_u", SMMWT_U) ++ NDS32_BUILTIN(smmwt_round, "v_smmwt_u", V_SMMWT_U) ++ NDS32_BUILTIN(smbb, "smbb", SMBB) ++ NDS32_BUILTIN(smbb, "v_smbb", V_SMBB) ++ NDS32_BUILTIN(smbt, "smbt", SMBT) ++ NDS32_BUILTIN(smbt, "v_smbt", V_SMBT) ++ NDS32_BUILTIN(smtt, "smtt", SMTT) ++ NDS32_BUILTIN(smtt, "v_smtt", V_SMTT) ++ NDS32_BUILTIN(kmda, "kmda", KMDA) ++ NDS32_BUILTIN(kmda, "v_kmda", V_KMDA) ++ NDS32_BUILTIN(kmxda, "kmxda", KMXDA) ++ NDS32_BUILTIN(kmxda, "v_kmxda", V_KMXDA) ++ NDS32_BUILTIN(smds, "smds", SMDS) ++ NDS32_BUILTIN(smds, "v_smds", V_SMDS) ++ NDS32_BUILTIN(smdrs, "smdrs", SMDRS) ++ NDS32_BUILTIN(smdrs, "v_smdrs", V_SMDRS) ++ NDS32_BUILTIN(smxdsv, "smxds", SMXDS) ++ NDS32_BUILTIN(smxdsv, "v_smxds", V_SMXDS) ++ NDS32_BUILTIN(smal1, "smal", SMAL) ++ NDS32_BUILTIN(smal1, "v_smal", V_SMAL) ++ NDS32_BUILTIN(bitrev, "bitrev", BITREV) ++ NDS32_BUILTIN(wext, "wext", WEXT) ++ NDS32_BUILTIN(adddi3, "sadd64", SADD64) ++ NDS32_BUILTIN(adddi3, "uadd64", UADD64) ++ NDS32_BUILTIN(radddi3, "radd64", RADD64) ++ NDS32_BUILTIN(uradddi3, "uradd64", URADD64) ++ NDS32_BUILTIN(kadddi3, "kadd64", KADD64) ++ NDS32_BUILTIN(ukadddi3, "ukadd64", UKADD64) ++ NDS32_BUILTIN(subdi3, "ssub64", SSUB64) ++ NDS32_BUILTIN(subdi3, "usub64", USUB64) ++ NDS32_BUILTIN(rsubdi3, "rsub64", RSUB64) ++ NDS32_BUILTIN(ursubdi3, "ursub64", URSUB64) ++ NDS32_BUILTIN(ksubdi3, "ksub64", KSUB64) ++ NDS32_BUILTIN(uksubdi3, "uksub64", UKSUB64) ++ NDS32_BUILTIN(smul16, "smul16", SMUL16) ++ NDS32_BUILTIN(smul16, "v_smul16", V_SMUL16) ++ NDS32_BUILTIN(smulx16, "smulx16", SMULX16) ++ NDS32_BUILTIN(smulx16, "v_smulx16", V_SMULX16) ++ NDS32_BUILTIN(umul16, "umul16", UMUL16) ++ NDS32_BUILTIN(umul16, "v_umul16", V_UMUL16) ++ NDS32_BUILTIN(umulx16, "umulx16", UMULX16) ++ NDS32_BUILTIN(umulx16, "v_umulx16", V_UMULX16) ++ NDS32_BUILTIN(kwmmul, "kwmmul", KWMMUL) ++ NDS32_BUILTIN(kwmmul_round, "kwmmul_u", KWMMUL_U) ++ NDS32_NO_TARGET_BUILTIN(unaligned_storev2hi, ++ "put_unaligned_u16x2", UASTORE_U16) ++ NDS32_NO_TARGET_BUILTIN(unaligned_storev2hi, ++ "put_unaligned_s16x2", UASTORE_S16) ++ NDS32_NO_TARGET_BUILTIN(unaligned_storev4qi, "put_unaligned_u8x4", UASTORE_U8) ++ NDS32_NO_TARGET_BUILTIN(unaligned_storev4qi, "put_unaligned_s8x4", UASTORE_S8) + }; + + /* Two-argument intrinsics with an immediate second argument. */ +@@ -617,6 +860,22 @@ + NDS32_BUILTIN(unspec_clips, "clips", CLIPS) + NDS32_NO_TARGET_BUILTIN(unspec_teqz, "teqz", TEQZ) + NDS32_NO_TARGET_BUILTIN(unspec_tnez, "tnez", TNEZ) ++ NDS32_BUILTIN(ashrv2hi3, "srl16", SRL16) ++ NDS32_BUILTIN(ashrv2hi3, "v_srl16", V_SRL16) ++ NDS32_BUILTIN(srl16_round, "srl16_u", SRL16_U) ++ NDS32_BUILTIN(srl16_round, "v_srl16_u", V_SRL16_U) ++ NDS32_BUILTIN(kslli16, "ksll16", KSLL16) ++ NDS32_BUILTIN(kslli16, "v_ksll16", V_KSLL16) ++ NDS32_BUILTIN(sclip16, "sclip16", SCLIP16) ++ NDS32_BUILTIN(sclip16, "v_sclip16", V_SCLIP16) ++ NDS32_BUILTIN(uclip16, "uclip16", UCLIP16) ++ NDS32_BUILTIN(uclip16, "v_uclip16", V_UCLIP16) ++ NDS32_BUILTIN(sraiu, "sra_u", SRA_U) ++ NDS32_BUILTIN(kssl, "ksll", KSLL) ++ NDS32_BUILTIN(bitrev, "bitrev", BITREV) ++ NDS32_BUILTIN(wext, "wext", WEXT) ++ NDS32_BUILTIN(uclip32, "uclip32", UCLIP32) ++ NDS32_BUILTIN(sclip32, "sclip32", SCLIP32) + }; + + /* Intrinsics that take three arguments. */ +@@ -625,6 +884,67 @@ + NDS32_BUILTIN(unspec_pbsada, "pbsada", PBSADA) + NDS32_NO_TARGET_BUILTIN(bse, "bse", BSE) + NDS32_NO_TARGET_BUILTIN(bsp, "bsp", BSP) ++ NDS32_BUILTIN(kmabb, "kmabb", KMABB) ++ NDS32_BUILTIN(kmabb, "v_kmabb", V_KMABB) ++ NDS32_BUILTIN(kmabt, "kmabt", KMABT) ++ NDS32_BUILTIN(kmabt, "v_kmabt", V_KMABT) ++ NDS32_BUILTIN(kmatt, "kmatt", KMATT) ++ NDS32_BUILTIN(kmatt, "v_kmatt", V_KMATT) ++ NDS32_BUILTIN(kmada, "kmada", KMADA) ++ NDS32_BUILTIN(kmada, "v_kmada", V_KMADA) ++ NDS32_BUILTIN(kmaxda, "kmaxda", KMAXDA) ++ NDS32_BUILTIN(kmaxda, "v_kmaxda", V_KMAXDA) ++ NDS32_BUILTIN(kmads, "kmads", KMADS) ++ NDS32_BUILTIN(kmads, "v_kmads", V_KMADS) ++ NDS32_BUILTIN(kmadrs, "kmadrs", KMADRS) ++ NDS32_BUILTIN(kmadrs, "v_kmadrs", V_KMADRS) ++ NDS32_BUILTIN(kmaxds, "kmaxds", KMAXDS) ++ NDS32_BUILTIN(kmaxds, "v_kmaxds", V_KMAXDS) ++ NDS32_BUILTIN(kmsda, "kmsda", KMSDA) ++ NDS32_BUILTIN(kmsda, "v_kmsda", V_KMSDA) ++ NDS32_BUILTIN(kmsxda, "kmsxda", KMSXDA) ++ NDS32_BUILTIN(kmsxda, "v_kmsxda", V_KMSXDA) ++ NDS32_BUILTIN(bpick1, "bpick", BPICK) ++ NDS32_BUILTIN(smar64_1, "smar64", SMAR64) ++ NDS32_BUILTIN(smsr64, "smsr64", SMSR64) ++ NDS32_BUILTIN(umar64_1, "umar64", UMAR64) ++ NDS32_BUILTIN(umsr64, "umsr64", UMSR64) ++ NDS32_BUILTIN(kmar64_1, "kmar64", KMAR64) ++ NDS32_BUILTIN(kmsr64, "kmsr64", KMSR64) ++ NDS32_BUILTIN(ukmar64_1, "ukmar64", UKMAR64) ++ NDS32_BUILTIN(ukmsr64, "ukmsr64", UKMSR64) ++ NDS32_BUILTIN(smalbb, "smalbb", SMALBB) ++ NDS32_BUILTIN(smalbb, "v_smalbb", V_SMALBB) ++ NDS32_BUILTIN(smalbt, "smalbt", SMALBT) ++ NDS32_BUILTIN(smalbt, "v_smalbt", V_SMALBT) ++ NDS32_BUILTIN(smaltt, "smaltt", SMALTT) ++ NDS32_BUILTIN(smaltt, "v_smaltt", V_SMALTT) ++ NDS32_BUILTIN(smalda1, "smalda", SMALDA) ++ NDS32_BUILTIN(smalda1, "v_smalda", V_SMALDA) ++ NDS32_BUILTIN(smalxda1, "smalxda", SMALXDA) ++ NDS32_BUILTIN(smalxda1, "v_smalxda", V_SMALXDA) ++ NDS32_BUILTIN(smalds1, "smalds", SMALDS) ++ NDS32_BUILTIN(smalds1, "v_smalds", V_SMALDS) ++ NDS32_BUILTIN(smaldrs3, "smaldrs", SMALDRS) ++ NDS32_BUILTIN(smaldrs3, "v_smaldrs", V_SMALDRS) ++ NDS32_BUILTIN(smalxds1, "smalxds", SMALXDS) ++ NDS32_BUILTIN(smalxds1, "v_smalxds", V_SMALXDS) ++ NDS32_BUILTIN(smslda1, "smslda", SMSLDA) ++ NDS32_BUILTIN(smslda1, "v_smslda", V_SMSLDA) ++ NDS32_BUILTIN(smslxda1, "smslxda", SMSLXDA) ++ NDS32_BUILTIN(smslxda1, "v_smslxda", V_SMSLXDA) ++ NDS32_BUILTIN(kmmawb, "kmmawb", KMMAWB) ++ NDS32_BUILTIN(kmmawb, "v_kmmawb", V_KMMAWB) ++ NDS32_BUILTIN(kmmawb_round, "kmmawb_u", KMMAWB_U) ++ NDS32_BUILTIN(kmmawb_round, "v_kmmawb_u", V_KMMAWB_U) ++ NDS32_BUILTIN(kmmawt, "kmmawt", KMMAWT) ++ NDS32_BUILTIN(kmmawt, "v_kmmawt", V_KMMAWT) ++ NDS32_BUILTIN(kmmawt_round, "kmmawt_u", KMMAWT_U) ++ NDS32_BUILTIN(kmmawt_round, "v_kmmawt_u", V_KMMAWT_U) ++ NDS32_BUILTIN(kmmac, "kmmac", KMMAC) ++ NDS32_BUILTIN(kmmac_round, "kmmac_u", KMMAC_U) ++ NDS32_BUILTIN(kmmsb, "kmmsb", KMMSB) ++ NDS32_BUILTIN(kmmsb_round, "kmmsb_u", KMMSB_U) + }; + + /* Three-argument intrinsics with an immediate third argument. */ +@@ -634,6 +954,7 @@ + NDS32_NO_TARGET_BUILTIN(prefetch_hw, "prefetch_hw", DPREF_HW) + NDS32_NO_TARGET_BUILTIN(prefetch_w, "prefetch_w", DPREF_W) + NDS32_NO_TARGET_BUILTIN(prefetch_dw, "prefetch_dw", DPREF_DW) ++ NDS32_BUILTIN(insb, "insb", INSB) + }; + + /* Intrinsics that load a value. */ +@@ -676,6 +997,11 @@ + unsigned i; + struct builtin_description *d; + ++ if (!NDS32_EXT_DSP_P () ++ && fcode > NDS32_BUILTIN_DSP_BEGIN ++ && fcode < NDS32_BUILTIN_DSP_END) ++ error ("don't support DSP extension instructions"); ++ + switch (fcode) + { + /* FPU Register Transfer. */ +@@ -812,6 +1138,9 @@ + case NDS32_BUILTIN_CCTL_L1D_WBALL_ONE_LVL: + emit_insn (gen_cctl_l1d_wball_one_lvl()); + return target; ++ case NDS32_BUILTIN_CLROV: ++ emit_insn (gen_unspec_volatile_clrov ()); ++ return target; + case NDS32_BUILTIN_STANDBY_NO_WAKE_GRANT: + emit_insn (gen_unspec_standby_no_wake_grant ()); + return target; +@@ -947,10 +1276,18 @@ + NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE) + + /* Looking for return type and argument can be found in tree.h file. */ ++ tree ptr_char_type_node = build_pointer_type (char_type_node); + tree ptr_uchar_type_node = build_pointer_type (unsigned_char_type_node); + tree ptr_ushort_type_node = build_pointer_type (short_unsigned_type_node); ++ tree ptr_short_type_node = build_pointer_type (short_integer_type_node); + tree ptr_uint_type_node = build_pointer_type (unsigned_type_node); + tree ptr_ulong_type_node = build_pointer_type (long_long_unsigned_type_node); ++ tree v4qi_type_node = build_vector_type (intQI_type_node, 4); ++ tree u_v4qi_type_node = build_vector_type (unsigned_intQI_type_node, 4); ++ tree v2hi_type_node = build_vector_type (intHI_type_node, 2); ++ tree u_v2hi_type_node = build_vector_type (unsigned_intHI_type_node, 2); ++ tree v2si_type_node = build_vector_type (intSI_type_node, 2); ++ tree u_v2si_type_node = build_vector_type (unsigned_intSI_type_node, 2); + + /* Cache. */ + ADD_NDS32_BUILTIN1 ("isync", void, ptr_uint, ISYNC); +@@ -1050,6 +1387,31 @@ + ADD_NDS32_BUILTIN2 ("se_ffmism", integer, unsigned, unsigned, FFMISM); + ADD_NDS32_BUILTIN2 ("se_flmism", integer, unsigned, unsigned, FLMISM); + ++ /* SATURATION */ ++ ADD_NDS32_BUILTIN2 ("kaddw", integer, integer, integer, KADDW); ++ ADD_NDS32_BUILTIN2 ("ksubw", integer, integer, integer, KSUBW); ++ ADD_NDS32_BUILTIN2 ("kaddh", integer, integer, integer, KADDH); ++ ADD_NDS32_BUILTIN2 ("ksubh", integer, integer, integer, KSUBH); ++ ADD_NDS32_BUILTIN2 ("kdmbb", integer, unsigned, unsigned, KDMBB); ++ ADD_NDS32_BUILTIN2 ("v_kdmbb", integer, v2hi, v2hi, V_KDMBB); ++ ADD_NDS32_BUILTIN2 ("kdmbt", integer, unsigned, unsigned, KDMBT); ++ ADD_NDS32_BUILTIN2 ("v_kdmbt", integer, v2hi, v2hi, V_KDMBT); ++ ADD_NDS32_BUILTIN2 ("kdmtb", integer, unsigned, unsigned, KDMTB); ++ ADD_NDS32_BUILTIN2 ("v_kdmtb", integer, v2hi, v2hi, V_KDMTB); ++ ADD_NDS32_BUILTIN2 ("kdmtt", integer, unsigned, unsigned, KDMTT); ++ ADD_NDS32_BUILTIN2 ("v_kdmtt", integer, v2hi, v2hi, V_KDMTT); ++ ADD_NDS32_BUILTIN2 ("khmbb", integer, unsigned, unsigned, KHMBB); ++ ADD_NDS32_BUILTIN2 ("v_khmbb", integer, v2hi, v2hi, V_KHMBB); ++ ADD_NDS32_BUILTIN2 ("khmbt", integer, unsigned, unsigned, KHMBT); ++ ADD_NDS32_BUILTIN2 ("v_khmbt", integer, v2hi, v2hi, V_KHMBT); ++ ADD_NDS32_BUILTIN2 ("khmtb", integer, unsigned, unsigned, KHMTB); ++ ADD_NDS32_BUILTIN2 ("v_khmtb", integer, v2hi, v2hi, V_KHMTB); ++ ADD_NDS32_BUILTIN2 ("khmtt", integer, unsigned, unsigned, KHMTT); ++ ADD_NDS32_BUILTIN2 ("v_khmtt", integer, v2hi, v2hi, V_KHMTT); ++ ADD_NDS32_BUILTIN2 ("kslraw", integer, integer, integer, KSLRAW); ++ ADD_NDS32_BUILTIN2 ("kslraw_u", integer, integer, integer, KSLRAW_U); ++ ADD_NDS32_BUILTIN0 ("rdov", unsigned, RDOV); ++ ADD_NDS32_BUILTIN0 ("clrov", void, CLROV); + + /* ROTR */ + ADD_NDS32_BUILTIN2 ("rotr", unsigned, unsigned, unsigned, ROTR); +@@ -1109,4 +1471,384 @@ + ADD_NDS32_BUILTIN0 ("enable_unaligned", void, ENABLE_UNALIGNED); + ADD_NDS32_BUILTIN0 ("disable_unaligned", void, DISABLE_UNALIGNED); + ++ /* DSP Extension: SIMD 16bit Add and Subtract. */ ++ ADD_NDS32_BUILTIN2 ("add16", unsigned, unsigned, unsigned, ADD16); ++ ADD_NDS32_BUILTIN2 ("v_uadd16", u_v2hi, u_v2hi, u_v2hi, V_UADD16); ++ ADD_NDS32_BUILTIN2 ("v_sadd16", v2hi, v2hi, v2hi, V_SADD16); ++ ADD_NDS32_BUILTIN2 ("radd16", unsigned, unsigned, unsigned, RADD16); ++ ADD_NDS32_BUILTIN2 ("v_radd16", v2hi, v2hi, v2hi, V_RADD16); ++ ADD_NDS32_BUILTIN2 ("uradd16", unsigned, unsigned, unsigned, URADD16); ++ ADD_NDS32_BUILTIN2 ("v_uradd16", u_v2hi, u_v2hi, u_v2hi, V_URADD16); ++ ADD_NDS32_BUILTIN2 ("kadd16", unsigned, unsigned, unsigned, KADD16); ++ ADD_NDS32_BUILTIN2 ("v_kadd16", v2hi, v2hi, v2hi, V_KADD16); ++ ADD_NDS32_BUILTIN2 ("ukadd16", unsigned, unsigned, unsigned, UKADD16); ++ ADD_NDS32_BUILTIN2 ("v_ukadd16", u_v2hi, u_v2hi, u_v2hi, V_UKADD16); ++ ADD_NDS32_BUILTIN2 ("sub16", unsigned, unsigned, unsigned, SUB16); ++ ADD_NDS32_BUILTIN2 ("v_usub16", u_v2hi, u_v2hi, u_v2hi, V_USUB16); ++ ADD_NDS32_BUILTIN2 ("v_ssub16", v2hi, v2hi, v2hi, V_SSUB16); ++ ADD_NDS32_BUILTIN2 ("rsub16", unsigned, unsigned, unsigned, RSUB16); ++ ADD_NDS32_BUILTIN2 ("v_rsub16", v2hi, v2hi, v2hi, V_RSUB16); ++ ADD_NDS32_BUILTIN2 ("ursub16", unsigned, unsigned, unsigned, URSUB16); ++ ADD_NDS32_BUILTIN2 ("v_ursub16", u_v2hi, u_v2hi, u_v2hi, V_URSUB16); ++ ADD_NDS32_BUILTIN2 ("ksub16", unsigned, unsigned, unsigned, KSUB16); ++ ADD_NDS32_BUILTIN2 ("v_ksub16", v2hi, v2hi, v2hi, V_KSUB16); ++ ADD_NDS32_BUILTIN2 ("uksub16", unsigned, unsigned, unsigned, UKSUB16); ++ ADD_NDS32_BUILTIN2 ("v_uksub16", u_v2hi, u_v2hi, u_v2hi, V_UKSUB16); ++ ADD_NDS32_BUILTIN2 ("cras16", unsigned, unsigned, unsigned, CRAS16); ++ ADD_NDS32_BUILTIN2 ("v_ucras16", u_v2hi, u_v2hi, u_v2hi, V_UCRAS16); ++ ADD_NDS32_BUILTIN2 ("v_scras16", v2hi, v2hi, v2hi, V_SCRAS16); ++ ADD_NDS32_BUILTIN2 ("rcras16", unsigned, unsigned, unsigned, RCRAS16); ++ ADD_NDS32_BUILTIN2 ("v_rcras16", v2hi, v2hi, v2hi, V_RCRAS16); ++ ADD_NDS32_BUILTIN2 ("urcras16", unsigned, unsigned, unsigned, URCRAS16); ++ ADD_NDS32_BUILTIN2 ("v_urcras16", u_v2hi, u_v2hi, u_v2hi, V_URCRAS16); ++ ADD_NDS32_BUILTIN2 ("kcras16", unsigned, unsigned, unsigned, KCRAS16); ++ ADD_NDS32_BUILTIN2 ("v_kcras16", v2hi, v2hi, v2hi, V_KCRAS16); ++ ADD_NDS32_BUILTIN2 ("ukcras16", unsigned, unsigned, unsigned, UKCRAS16); ++ ADD_NDS32_BUILTIN2 ("v_ukcras16", u_v2hi, u_v2hi, u_v2hi, V_UKCRAS16); ++ ADD_NDS32_BUILTIN2 ("crsa16", unsigned, unsigned, unsigned, CRSA16); ++ ADD_NDS32_BUILTIN2 ("v_ucrsa16", u_v2hi, u_v2hi, u_v2hi, V_UCRSA16); ++ ADD_NDS32_BUILTIN2 ("v_scrsa16", v2hi, v2hi, v2hi, V_SCRSA16); ++ ADD_NDS32_BUILTIN2 ("rcrsa16", unsigned, unsigned, unsigned, RCRSA16); ++ ADD_NDS32_BUILTIN2 ("v_rcrsa16", v2hi, v2hi, v2hi, V_RCRSA16); ++ ADD_NDS32_BUILTIN2 ("urcrsa16", unsigned, unsigned, unsigned, URCRSA16); ++ ADD_NDS32_BUILTIN2 ("v_urcrsa16", u_v2hi, u_v2hi, u_v2hi, V_URCRSA16); ++ ADD_NDS32_BUILTIN2 ("kcrsa16", unsigned, unsigned, unsigned, KCRSA16); ++ ADD_NDS32_BUILTIN2 ("v_kcrsa16", v2hi, v2hi, v2hi, V_KCRSA16); ++ ADD_NDS32_BUILTIN2 ("ukcrsa16", unsigned, unsigned, unsigned, UKCRSA16); ++ ADD_NDS32_BUILTIN2 ("v_ukcrsa16", u_v2hi, u_v2hi, u_v2hi, V_UKCRSA16); ++ ++ /* DSP Extension: SIMD 8bit Add and Subtract. */ ++ ADD_NDS32_BUILTIN2 ("add8", integer, integer, integer, ADD8); ++ ADD_NDS32_BUILTIN2 ("v_uadd8", u_v4qi, u_v4qi, u_v4qi, V_UADD8); ++ ADD_NDS32_BUILTIN2 ("v_sadd8", v4qi, v4qi, v4qi, V_SADD8); ++ ADD_NDS32_BUILTIN2 ("radd8", unsigned, unsigned, unsigned, RADD8); ++ ADD_NDS32_BUILTIN2 ("v_radd8", v4qi, v4qi, v4qi, V_RADD8); ++ ADD_NDS32_BUILTIN2 ("uradd8", unsigned, unsigned, unsigned, URADD8); ++ ADD_NDS32_BUILTIN2 ("v_uradd8", u_v4qi, u_v4qi, u_v4qi, V_URADD8); ++ ADD_NDS32_BUILTIN2 ("kadd8", unsigned, unsigned, unsigned, KADD8); ++ ADD_NDS32_BUILTIN2 ("v_kadd8", v4qi, v4qi, v4qi, V_KADD8); ++ ADD_NDS32_BUILTIN2 ("ukadd8", unsigned, unsigned, unsigned, UKADD8); ++ ADD_NDS32_BUILTIN2 ("v_ukadd8", u_v4qi, u_v4qi, u_v4qi, V_UKADD8); ++ ADD_NDS32_BUILTIN2 ("sub8", integer, integer, integer, SUB8); ++ ADD_NDS32_BUILTIN2 ("v_usub8", u_v4qi, u_v4qi, u_v4qi, V_USUB8); ++ ADD_NDS32_BUILTIN2 ("v_ssub8", v4qi, v4qi, v4qi, V_SSUB8); ++ ADD_NDS32_BUILTIN2 ("rsub8", unsigned, unsigned, unsigned, RSUB8); ++ ADD_NDS32_BUILTIN2 ("v_rsub8", v4qi, v4qi, v4qi, V_RSUB8); ++ ADD_NDS32_BUILTIN2 ("ursub8", unsigned, unsigned, unsigned, URSUB8); ++ ADD_NDS32_BUILTIN2 ("v_ursub8", u_v4qi, u_v4qi, u_v4qi, V_URSUB8); ++ ADD_NDS32_BUILTIN2 ("ksub8", unsigned, unsigned, unsigned, KSUB8); ++ ADD_NDS32_BUILTIN2 ("v_ksub8", v4qi, v4qi, v4qi, V_KSUB8); ++ ADD_NDS32_BUILTIN2 ("uksub8", unsigned, unsigned, unsigned, UKSUB8); ++ ADD_NDS32_BUILTIN2 ("v_uksub8", u_v4qi, u_v4qi, u_v4qi, V_UKSUB8); ++ ++ /* DSP Extension: SIMD 16bit Shift. */ ++ ADD_NDS32_BUILTIN2 ("sra16", unsigned, unsigned, unsigned, SRA16); ++ ADD_NDS32_BUILTIN2 ("v_sra16", v2hi, v2hi, unsigned, V_SRA16); ++ ADD_NDS32_BUILTIN2 ("sra16_u", unsigned, unsigned, unsigned, SRA16_U); ++ ADD_NDS32_BUILTIN2 ("v_sra16_u", v2hi, v2hi, unsigned, V_SRA16_U); ++ ADD_NDS32_BUILTIN2 ("srl16", unsigned, unsigned, unsigned, SRL16); ++ ADD_NDS32_BUILTIN2 ("v_srl16", u_v2hi, u_v2hi, unsigned, V_SRL16); ++ ADD_NDS32_BUILTIN2 ("srl16_u", unsigned, unsigned, unsigned, SRL16_U); ++ ADD_NDS32_BUILTIN2 ("v_srl16_u", u_v2hi, u_v2hi, unsigned, V_SRL16_U); ++ ADD_NDS32_BUILTIN2 ("sll16", unsigned, unsigned, unsigned, SLL16); ++ ADD_NDS32_BUILTIN2 ("v_sll16", u_v2hi, u_v2hi, unsigned, V_SLL16); ++ ADD_NDS32_BUILTIN2 ("ksll16", unsigned, unsigned, unsigned, KSLL16); ++ ADD_NDS32_BUILTIN2 ("v_ksll16", v2hi, v2hi, unsigned, V_KSLL16); ++ ADD_NDS32_BUILTIN2 ("kslra16", unsigned, unsigned, unsigned, KSLRA16); ++ ADD_NDS32_BUILTIN2 ("v_kslra16", v2hi, v2hi, unsigned, V_KSLRA16); ++ ADD_NDS32_BUILTIN2 ("kslra16_u", unsigned, unsigned, unsigned, KSLRA16_U); ++ ADD_NDS32_BUILTIN2 ("v_kslra16_u", v2hi, v2hi, unsigned, V_KSLRA16_U); ++ ++ /* DSP Extension: 16bit Compare. */ ++ ADD_NDS32_BUILTIN2 ("cmpeq16", unsigned, unsigned, unsigned, CMPEQ16); ++ ADD_NDS32_BUILTIN2 ("v_scmpeq16", u_v2hi, v2hi, v2hi, V_SCMPEQ16); ++ ADD_NDS32_BUILTIN2 ("v_ucmpeq16", u_v2hi, u_v2hi, u_v2hi, V_UCMPEQ16); ++ ADD_NDS32_BUILTIN2 ("scmplt16", unsigned, unsigned, unsigned, SCMPLT16); ++ ADD_NDS32_BUILTIN2 ("v_scmplt16", u_v2hi, v2hi, v2hi, V_SCMPLT16); ++ ADD_NDS32_BUILTIN2 ("scmple16", unsigned, unsigned, unsigned, SCMPLE16); ++ ADD_NDS32_BUILTIN2 ("v_scmple16", u_v2hi, v2hi, v2hi, V_SCMPLE16); ++ ADD_NDS32_BUILTIN2 ("ucmplt16", unsigned, unsigned, unsigned, UCMPLT16); ++ ADD_NDS32_BUILTIN2 ("v_ucmplt16", u_v2hi, u_v2hi, u_v2hi, V_UCMPLT16); ++ ADD_NDS32_BUILTIN2 ("ucmple16", unsigned, unsigned, unsigned, UCMPLE16); ++ ADD_NDS32_BUILTIN2 ("v_ucmple16", u_v2hi, u_v2hi, u_v2hi, V_UCMPLE16); ++ ++ /* DSP Extension: 8bit Compare. */ ++ ADD_NDS32_BUILTIN2 ("cmpeq8", unsigned, unsigned, unsigned, CMPEQ8); ++ ADD_NDS32_BUILTIN2 ("v_scmpeq8", u_v4qi, v4qi, v4qi, V_SCMPEQ8); ++ ADD_NDS32_BUILTIN2 ("v_ucmpeq8", u_v4qi, u_v4qi, u_v4qi, V_UCMPEQ8); ++ ADD_NDS32_BUILTIN2 ("scmplt8", unsigned, unsigned, unsigned, SCMPLT8); ++ ADD_NDS32_BUILTIN2 ("v_scmplt8", u_v4qi, v4qi, v4qi, V_SCMPLT8); ++ ADD_NDS32_BUILTIN2 ("scmple8", unsigned, unsigned, unsigned, SCMPLE8); ++ ADD_NDS32_BUILTIN2 ("v_scmple8", u_v4qi, v4qi, v4qi, V_SCMPLE8); ++ ADD_NDS32_BUILTIN2 ("ucmplt8", unsigned, unsigned, unsigned, UCMPLT8); ++ ADD_NDS32_BUILTIN2 ("v_ucmplt8", u_v4qi, u_v4qi, u_v4qi, V_UCMPLT8); ++ ADD_NDS32_BUILTIN2 ("ucmple8", unsigned, unsigned, unsigned, UCMPLE8); ++ ADD_NDS32_BUILTIN2 ("v_ucmple8", u_v4qi, u_v4qi, u_v4qi, V_UCMPLE8); ++ ++ /* DSP Extension: SIMD 16bit MISC. */ ++ ADD_NDS32_BUILTIN2 ("smin16", unsigned, unsigned, unsigned, SMIN16); ++ ADD_NDS32_BUILTIN2 ("v_smin16", v2hi, v2hi, v2hi, V_SMIN16); ++ ADD_NDS32_BUILTIN2 ("umin16", unsigned, unsigned, unsigned, UMIN16); ++ ADD_NDS32_BUILTIN2 ("v_umin16", u_v2hi, u_v2hi, u_v2hi, V_UMIN16); ++ ADD_NDS32_BUILTIN2 ("smax16", unsigned, unsigned, unsigned, SMAX16); ++ ADD_NDS32_BUILTIN2 ("v_smax16", v2hi, v2hi, v2hi, V_SMAX16); ++ ADD_NDS32_BUILTIN2 ("umax16", unsigned, unsigned, unsigned, UMAX16); ++ ADD_NDS32_BUILTIN2 ("v_umax16", u_v2hi, u_v2hi, u_v2hi, V_UMAX16); ++ ADD_NDS32_BUILTIN2 ("sclip16", unsigned, unsigned, unsigned, SCLIP16); ++ ADD_NDS32_BUILTIN2 ("v_sclip16", v2hi, v2hi, unsigned, V_SCLIP16); ++ ADD_NDS32_BUILTIN2 ("uclip16", unsigned, unsigned, unsigned, UCLIP16); ++ ADD_NDS32_BUILTIN2 ("v_uclip16", v2hi, v2hi, unsigned, V_UCLIP16); ++ ADD_NDS32_BUILTIN2 ("khm16", unsigned, unsigned, unsigned, KHM16); ++ ADD_NDS32_BUILTIN2 ("v_khm16", v2hi, v2hi, v2hi, V_KHM16); ++ ADD_NDS32_BUILTIN2 ("khmx16", unsigned, unsigned, unsigned, KHMX16); ++ ADD_NDS32_BUILTIN2 ("v_khmx16", v2hi, v2hi, v2hi, V_KHMX16); ++ ADD_NDS32_BUILTIN1 ("kabs16", unsigned, unsigned, KABS16); ++ ADD_NDS32_BUILTIN1 ("v_kabs16", v2hi, v2hi, V_KABS16); ++ ADD_NDS32_BUILTIN2 ("smul16", long_long_unsigned, unsigned, unsigned, SMUL16); ++ ADD_NDS32_BUILTIN2 ("v_smul16", v2si, v2hi, v2hi, V_SMUL16); ++ ADD_NDS32_BUILTIN2 ("smulx16", ++ long_long_unsigned, unsigned, unsigned, SMULX16); ++ ADD_NDS32_BUILTIN2 ("v_smulx16", v2si, v2hi, v2hi, V_SMULX16); ++ ADD_NDS32_BUILTIN2 ("umul16", long_long_unsigned, unsigned, unsigned, UMUL16); ++ ADD_NDS32_BUILTIN2 ("v_umul16", u_v2si, u_v2hi, u_v2hi, V_UMUL16); ++ ADD_NDS32_BUILTIN2 ("umulx16", ++ long_long_unsigned, unsigned, unsigned, UMULX16); ++ ADD_NDS32_BUILTIN2 ("v_umulx16", u_v2si, u_v2hi, u_v2hi, V_UMULX16); ++ ++ /* DSP Extension: SIMD 8bit MISC. */ ++ ADD_NDS32_BUILTIN2 ("smin8", unsigned, unsigned, unsigned, SMIN8); ++ ADD_NDS32_BUILTIN2 ("v_smin8", v4qi, v4qi, v4qi, V_SMIN8); ++ ADD_NDS32_BUILTIN2 ("umin8", unsigned, unsigned, unsigned, UMIN8); ++ ADD_NDS32_BUILTIN2 ("v_umin8", u_v4qi, u_v4qi, u_v4qi, V_UMIN8); ++ ADD_NDS32_BUILTIN2 ("smax8", unsigned, unsigned, unsigned, SMAX8); ++ ADD_NDS32_BUILTIN2 ("v_smax8", v4qi, v4qi, v4qi, V_SMAX8); ++ ADD_NDS32_BUILTIN2 ("umax8", unsigned, unsigned, unsigned, UMAX8); ++ ADD_NDS32_BUILTIN2 ("v_umax8", u_v4qi, u_v4qi, u_v4qi, V_UMAX8); ++ ADD_NDS32_BUILTIN1 ("kabs8", unsigned, unsigned, KABS8); ++ ADD_NDS32_BUILTIN1 ("v_kabs8", v4qi, v4qi, V_KABS8); ++ ++ /* DSP Extension: 8bit Unpacking. */ ++ ADD_NDS32_BUILTIN1 ("sunpkd810", unsigned, unsigned, SUNPKD810); ++ ADD_NDS32_BUILTIN1 ("v_sunpkd810", v2hi, v4qi, V_SUNPKD810); ++ ADD_NDS32_BUILTIN1 ("sunpkd820", unsigned, unsigned, SUNPKD820); ++ ADD_NDS32_BUILTIN1 ("v_sunpkd820", v2hi, v4qi, V_SUNPKD820); ++ ADD_NDS32_BUILTIN1 ("sunpkd830", unsigned, unsigned, SUNPKD830); ++ ADD_NDS32_BUILTIN1 ("v_sunpkd830", v2hi, v4qi, V_SUNPKD830); ++ ADD_NDS32_BUILTIN1 ("sunpkd831", unsigned, unsigned, SUNPKD831); ++ ADD_NDS32_BUILTIN1 ("v_sunpkd831", v2hi, v4qi, V_SUNPKD831); ++ ADD_NDS32_BUILTIN1 ("zunpkd810", unsigned, unsigned, ZUNPKD810); ++ ADD_NDS32_BUILTIN1 ("v_zunpkd810", u_v2hi, u_v4qi, V_ZUNPKD810); ++ ADD_NDS32_BUILTIN1 ("zunpkd820", unsigned, unsigned, ZUNPKD820); ++ ADD_NDS32_BUILTIN1 ("v_zunpkd820", u_v2hi, u_v4qi, V_ZUNPKD820); ++ ADD_NDS32_BUILTIN1 ("zunpkd830", unsigned, unsigned, ZUNPKD830); ++ ADD_NDS32_BUILTIN1 ("v_zunpkd830", u_v2hi, u_v4qi, V_ZUNPKD830); ++ ADD_NDS32_BUILTIN1 ("zunpkd831", unsigned, unsigned, ZUNPKD831); ++ ADD_NDS32_BUILTIN1 ("v_zunpkd831", u_v2hi, u_v4qi, V_ZUNPKD831); ++ ++ /* DSP Extension: 32bit Add and Subtract. */ ++ ADD_NDS32_BUILTIN2 ("raddw", integer, integer, integer, RADDW); ++ ADD_NDS32_BUILTIN2 ("uraddw", unsigned, unsigned, unsigned, URADDW); ++ ADD_NDS32_BUILTIN2 ("rsubw", integer, integer, integer, RSUBW); ++ ADD_NDS32_BUILTIN2 ("ursubw", unsigned, unsigned, unsigned, URSUBW); ++ ++ /* DSP Extension: 32bit Shift. */ ++ ADD_NDS32_BUILTIN2 ("sra_u", integer, integer, unsigned, SRA_U); ++ ADD_NDS32_BUILTIN2 ("ksll", integer, integer, unsigned, KSLL); ++ ++ /* DSP Extension: 16bit Packing. */ ++ ADD_NDS32_BUILTIN2 ("pkbb16", unsigned, unsigned, unsigned, PKBB16); ++ ADD_NDS32_BUILTIN2 ("v_pkbb16", u_v2hi, u_v2hi, u_v2hi, V_PKBB16); ++ ADD_NDS32_BUILTIN2 ("pkbt16", unsigned, unsigned, unsigned, PKBT16); ++ ADD_NDS32_BUILTIN2 ("v_pkbt16", u_v2hi, u_v2hi, u_v2hi, V_PKBT16); ++ ADD_NDS32_BUILTIN2 ("pktb16", unsigned, unsigned, unsigned, PKTB16); ++ ADD_NDS32_BUILTIN2 ("v_pktb16", u_v2hi, u_v2hi, u_v2hi, V_PKTB16); ++ ADD_NDS32_BUILTIN2 ("pktt16", unsigned, unsigned, unsigned, PKTT16); ++ ADD_NDS32_BUILTIN2 ("v_pktt16", u_v2hi, u_v2hi, u_v2hi, V_PKTT16); ++ ++ /* DSP Extension: Signed MSW 32x32 Multiply and ADD. */ ++ ADD_NDS32_BUILTIN2 ("smmul", integer, integer, integer, SMMUL); ++ ADD_NDS32_BUILTIN2 ("smmul_u", integer, integer, integer, SMMUL_U); ++ ADD_NDS32_BUILTIN3 ("kmmac", integer, integer, integer, integer, KMMAC); ++ ADD_NDS32_BUILTIN3 ("kmmac_u", integer, integer, integer, integer, KMMAC_U); ++ ADD_NDS32_BUILTIN3 ("kmmsb", integer, integer, integer, integer, KMMSB); ++ ADD_NDS32_BUILTIN3 ("kmmsb_u", integer, integer, integer, integer, KMMSB_U); ++ ADD_NDS32_BUILTIN2 ("kwmmul", integer, integer, integer, KWMMUL); ++ ADD_NDS32_BUILTIN2 ("kwmmul_u", integer, integer, integer, KWMMUL_U); ++ ++ /* DSP Extension: Most Significant Word 32x16 Multiply and ADD. */ ++ ADD_NDS32_BUILTIN2 ("smmwb", integer, integer, unsigned, SMMWB); ++ ADD_NDS32_BUILTIN2 ("v_smmwb", integer, integer, v2hi, V_SMMWB); ++ ADD_NDS32_BUILTIN2 ("smmwb_u", integer, integer, unsigned, SMMWB_U); ++ ADD_NDS32_BUILTIN2 ("v_smmwb_u", integer, integer, v2hi, V_SMMWB_U); ++ ADD_NDS32_BUILTIN2 ("smmwt", integer, integer, unsigned, SMMWT); ++ ADD_NDS32_BUILTIN2 ("v_smmwt", integer, integer, v2hi, V_SMMWT); ++ ADD_NDS32_BUILTIN2 ("smmwt_u", integer, integer, unsigned, SMMWT_U); ++ ADD_NDS32_BUILTIN2 ("v_smmwt_u", integer, integer, v2hi, V_SMMWT_U); ++ ADD_NDS32_BUILTIN3 ("kmmawb", integer, integer, integer, unsigned, KMMAWB); ++ ADD_NDS32_BUILTIN3 ("v_kmmawb", integer, integer, integer, v2hi, V_KMMAWB); ++ ADD_NDS32_BUILTIN3 ("kmmawb_u", ++ integer, integer, integer, unsigned, KMMAWB_U); ++ ADD_NDS32_BUILTIN3 ("v_kmmawb_u", ++ integer, integer, integer, v2hi, V_KMMAWB_U); ++ ADD_NDS32_BUILTIN3 ("kmmawt", integer, integer, integer, unsigned, KMMAWT); ++ ADD_NDS32_BUILTIN3 ("v_kmmawt", integer, integer, integer, v2hi, V_KMMAWT); ++ ADD_NDS32_BUILTIN3 ("kmmawt_u", ++ integer, integer, integer, unsigned, KMMAWT_U); ++ ADD_NDS32_BUILTIN3 ("v_kmmawt_u", ++ integer, integer, integer, v2hi, V_KMMAWT_U); ++ ++ /* DSP Extension: Signed 16bit Multiply with ADD/Subtract. */ ++ ADD_NDS32_BUILTIN2 ("smbb", integer, unsigned, unsigned, SMBB); ++ ADD_NDS32_BUILTIN2 ("v_smbb", integer, v2hi, v2hi, V_SMBB); ++ ADD_NDS32_BUILTIN2 ("smbt", integer, unsigned, unsigned, SMBT); ++ ADD_NDS32_BUILTIN2 ("v_smbt", integer, v2hi, v2hi, V_SMBT); ++ ADD_NDS32_BUILTIN2 ("smtt", integer, unsigned, unsigned, SMTT); ++ ADD_NDS32_BUILTIN2 ("v_smtt", integer, v2hi, v2hi, V_SMTT); ++ ADD_NDS32_BUILTIN2 ("kmda", integer, unsigned, unsigned, KMDA); ++ ADD_NDS32_BUILTIN2 ("v_kmda", integer, v2hi, v2hi, V_KMDA); ++ ADD_NDS32_BUILTIN2 ("kmxda", integer, unsigned, unsigned, KMXDA); ++ ADD_NDS32_BUILTIN2 ("v_kmxda", integer, v2hi, v2hi, V_KMXDA); ++ ADD_NDS32_BUILTIN2 ("smds", integer, unsigned, unsigned, SMDS); ++ ADD_NDS32_BUILTIN2 ("v_smds", integer, v2hi, v2hi, V_SMDS); ++ ADD_NDS32_BUILTIN2 ("smdrs", integer, unsigned, unsigned, SMDRS); ++ ADD_NDS32_BUILTIN2 ("v_smdrs", integer, v2hi, v2hi, V_SMDRS); ++ ADD_NDS32_BUILTIN2 ("smxds", integer, unsigned, unsigned, SMXDS); ++ ADD_NDS32_BUILTIN2 ("v_smxds", integer, v2hi, v2hi, V_SMXDS); ++ ADD_NDS32_BUILTIN3 ("kmabb", integer, integer, unsigned, unsigned, KMABB); ++ ADD_NDS32_BUILTIN3 ("v_kmabb", integer, integer, v2hi, v2hi, V_KMABB); ++ ADD_NDS32_BUILTIN3 ("kmabt", integer, integer, unsigned, unsigned, KMABT); ++ ADD_NDS32_BUILTIN3 ("v_kmabt", integer, integer, v2hi, v2hi, V_KMABT); ++ ADD_NDS32_BUILTIN3 ("kmatt", integer, integer, unsigned, unsigned, KMATT); ++ ADD_NDS32_BUILTIN3 ("v_kmatt", integer, integer, v2hi, v2hi, V_KMATT); ++ ADD_NDS32_BUILTIN3 ("kmada", integer, integer, unsigned, unsigned, KMADA); ++ ADD_NDS32_BUILTIN3 ("v_kmada", integer, integer, v2hi, v2hi, V_KMADA); ++ ADD_NDS32_BUILTIN3 ("kmaxda", integer, integer, unsigned, unsigned, KMAXDA); ++ ADD_NDS32_BUILTIN3 ("v_kmaxda", integer, integer, v2hi, v2hi, V_KMAXDA); ++ ADD_NDS32_BUILTIN3 ("kmads", integer, integer, unsigned, unsigned, KMADS); ++ ADD_NDS32_BUILTIN3 ("v_kmads", integer, integer, v2hi, v2hi, V_KMADS); ++ ADD_NDS32_BUILTIN3 ("kmadrs", integer, integer, unsigned, unsigned, KMADRS); ++ ADD_NDS32_BUILTIN3 ("v_kmadrs", integer, integer, v2hi, v2hi, V_KMADRS); ++ ADD_NDS32_BUILTIN3 ("kmaxds", integer, integer, unsigned, unsigned, KMAXDS); ++ ADD_NDS32_BUILTIN3 ("v_kmaxds", integer, integer, v2hi, v2hi, V_KMAXDS); ++ ADD_NDS32_BUILTIN3 ("kmsda", integer, integer, unsigned, unsigned, KMSDA); ++ ADD_NDS32_BUILTIN3 ("v_kmsda", integer, integer, v2hi, v2hi, V_KMSDA); ++ ADD_NDS32_BUILTIN3 ("kmsxda", integer, integer, unsigned, unsigned, KMSXDA); ++ ADD_NDS32_BUILTIN3 ("v_kmsxda", integer, integer, v2hi, v2hi, V_KMSXDA); ++ ++ /* DSP Extension: Signed 16bit Multiply with 64bit ADD/Subtract. */ ++ ADD_NDS32_BUILTIN2 ("smal", long_long_integer, ++ long_long_integer, unsigned, SMAL); ++ ADD_NDS32_BUILTIN2 ("v_smal", long_long_integer, ++ long_long_integer, v2hi, V_SMAL); ++ ++ /* DSP Extension: 32bit MISC. */ ++ ADD_NDS32_BUILTIN2 ("bitrev", unsigned, unsigned, unsigned, BITREV); ++ ADD_NDS32_BUILTIN2 ("wext", unsigned, long_long_integer, unsigned, WEXT); ++ ADD_NDS32_BUILTIN3 ("bpick", unsigned, unsigned, unsigned, unsigned, BPICK); ++ ADD_NDS32_BUILTIN3 ("insb", unsigned, unsigned, unsigned, unsigned, INSB); ++ ++ /* DSP Extension: 64bit Add and Subtract. */ ++ ADD_NDS32_BUILTIN2 ("sadd64", long_long_integer, ++ long_long_integer, long_long_integer, SADD64); ++ ADD_NDS32_BUILTIN2 ("uadd64", long_long_unsigned, ++ long_long_unsigned, long_long_unsigned, UADD64); ++ ADD_NDS32_BUILTIN2 ("radd64", long_long_integer, ++ long_long_integer, long_long_integer, RADD64); ++ ADD_NDS32_BUILTIN2 ("uradd64", long_long_unsigned, ++ long_long_unsigned, long_long_unsigned, URADD64); ++ ADD_NDS32_BUILTIN2 ("kadd64", long_long_integer, ++ long_long_integer, long_long_integer, KADD64); ++ ADD_NDS32_BUILTIN2 ("ukadd64", long_long_unsigned, ++ long_long_unsigned, long_long_unsigned, UKADD64); ++ ADD_NDS32_BUILTIN2 ("ssub64", long_long_integer, ++ long_long_integer, long_long_integer, SSUB64); ++ ADD_NDS32_BUILTIN2 ("usub64", long_long_unsigned, ++ long_long_unsigned, long_long_unsigned, USUB64); ++ ADD_NDS32_BUILTIN2 ("rsub64", long_long_integer, ++ long_long_integer, long_long_integer, RSUB64); ++ ADD_NDS32_BUILTIN2 ("ursub64", long_long_unsigned, ++ long_long_unsigned, long_long_unsigned, URSUB64); ++ ADD_NDS32_BUILTIN2 ("ksub64", long_long_integer, ++ long_long_integer, long_long_integer, KSUB64); ++ ADD_NDS32_BUILTIN2 ("uksub64", long_long_unsigned, ++ long_long_unsigned, long_long_unsigned, UKSUB64); ++ ++ /* DSP Extension: 32bit Multiply with 64bit Add/Subtract. */ ++ ADD_NDS32_BUILTIN3 ("smar64", long_long_integer, ++ long_long_integer, integer, integer, SMAR64); ++ ADD_NDS32_BUILTIN3 ("smsr64", long_long_integer, ++ long_long_integer, integer, integer, SMSR64); ++ ADD_NDS32_BUILTIN3 ("umar64", long_long_unsigned, ++ long_long_unsigned, unsigned, unsigned, UMAR64); ++ ADD_NDS32_BUILTIN3 ("umsr64", long_long_unsigned, ++ long_long_unsigned, unsigned, unsigned, UMSR64); ++ ADD_NDS32_BUILTIN3 ("kmar64", long_long_integer, ++ long_long_integer, integer, integer, KMAR64); ++ ADD_NDS32_BUILTIN3 ("kmsr64", long_long_integer, ++ long_long_integer, integer, integer, KMSR64); ++ ADD_NDS32_BUILTIN3 ("ukmar64", long_long_unsigned, ++ long_long_unsigned, unsigned, unsigned, UKMAR64); ++ ADD_NDS32_BUILTIN3 ("ukmsr64", long_long_unsigned, ++ long_long_unsigned, unsigned, unsigned, UKMSR64); ++ ++ /* DSP Extension: Signed 16bit Multiply with 64bit Add/Subtract. */ ++ ADD_NDS32_BUILTIN3 ("smalbb", long_long_integer, ++ long_long_integer, unsigned, unsigned, SMALBB); ++ ADD_NDS32_BUILTIN3 ("v_smalbb", long_long_integer, ++ long_long_integer, v2hi, v2hi, V_SMALBB); ++ ADD_NDS32_BUILTIN3 ("smalbt", long_long_integer, ++ long_long_integer, unsigned, unsigned, SMALBT); ++ ADD_NDS32_BUILTIN3 ("v_smalbt", long_long_integer, ++ long_long_integer, v2hi, v2hi, V_SMALBT); ++ ADD_NDS32_BUILTIN3 ("smaltt", long_long_integer, ++ long_long_integer, unsigned, unsigned, SMALTT); ++ ADD_NDS32_BUILTIN3 ("v_smaltt", long_long_integer, ++ long_long_integer, v2hi, v2hi, V_SMALTT); ++ ADD_NDS32_BUILTIN3 ("smalda", long_long_integer, ++ long_long_integer, unsigned, unsigned, SMALDA); ++ ADD_NDS32_BUILTIN3 ("v_smalda", long_long_integer, ++ long_long_integer, v2hi, v2hi, V_SMALDA); ++ ADD_NDS32_BUILTIN3 ("smalxda", long_long_integer, ++ long_long_integer, unsigned, unsigned, SMALXDA); ++ ADD_NDS32_BUILTIN3 ("v_smalxda", long_long_integer, ++ long_long_integer, v2hi, v2hi, V_SMALXDA); ++ ADD_NDS32_BUILTIN3 ("smalds", long_long_integer, ++ long_long_integer, unsigned, unsigned, SMALDS); ++ ADD_NDS32_BUILTIN3 ("v_smalds", long_long_integer, ++ long_long_integer, v2hi, v2hi, V_SMALDS); ++ ADD_NDS32_BUILTIN3 ("smaldrs", long_long_integer, ++ long_long_integer, unsigned, unsigned, SMALDRS); ++ ADD_NDS32_BUILTIN3 ("v_smaldrs", long_long_integer, ++ long_long_integer, v2hi, v2hi, V_SMALDRS); ++ ADD_NDS32_BUILTIN3 ("smalxds", long_long_integer, ++ long_long_integer, unsigned, unsigned, SMALXDS); ++ ADD_NDS32_BUILTIN3 ("v_smalxds", long_long_integer, ++ long_long_integer, v2hi, v2hi, V_SMALXDS); ++ ADD_NDS32_BUILTIN3 ("smslda", long_long_integer, ++ long_long_integer, unsigned, unsigned, SMSLDA); ++ ADD_NDS32_BUILTIN3 ("v_smslda", long_long_integer, ++ long_long_integer, v2hi, v2hi, V_SMSLDA); ++ ADD_NDS32_BUILTIN3 ("smslxda", long_long_integer, ++ long_long_integer, unsigned, unsigned, SMSLXDA); ++ ADD_NDS32_BUILTIN3 ("v_smslxda", long_long_integer, ++ long_long_integer, v2hi, v2hi, V_SMSLXDA); ++ ++ /* DSP Extension: augmented baseline. */ ++ ADD_NDS32_BUILTIN2 ("uclip32", unsigned, integer, unsigned, UCLIP32); ++ ADD_NDS32_BUILTIN2 ("sclip32", integer, integer, unsigned, SCLIP32); ++ ADD_NDS32_BUILTIN1 ("kabs", integer, integer, KABS); ++ ++ /* DSP Extension: vector type unaligned Load/Store */ ++ ADD_NDS32_BUILTIN1 ("get_unaligned_u16x2", u_v2hi, ptr_ushort, UALOAD_U16); ++ ADD_NDS32_BUILTIN1 ("get_unaligned_s16x2", v2hi, ptr_short, UALOAD_S16); ++ ADD_NDS32_BUILTIN1 ("get_unaligned_u8x4", u_v4qi, ptr_uchar, UALOAD_U8); ++ ADD_NDS32_BUILTIN1 ("get_unaligned_s8x4", v4qi, ptr_char, UALOAD_S8); ++ ADD_NDS32_BUILTIN2 ("put_unaligned_u16x2", void, ptr_ushort, ++ u_v2hi, UASTORE_U16); ++ ADD_NDS32_BUILTIN2 ("put_unaligned_s16x2", void, ptr_short, ++ v2hi, UASTORE_S16); ++ ADD_NDS32_BUILTIN2 ("put_unaligned_u8x4", void, ptr_uchar, ++ u_v4qi, UASTORE_U8); ++ ADD_NDS32_BUILTIN2 ("put_unaligned_s8x4", void, ptr_char, ++ v4qi, UASTORE_S8); + } +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32_intrinsic.h gcc-8.2.0/gcc/config/nds32/nds32_intrinsic.h +--- gcc-8.2.0.orig/gcc/config/nds32/nds32_intrinsic.h 2018-04-22 09:46:39.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32_intrinsic.h 2019-01-25 15:38:32.833242671 +0100 +@@ -26,6 +26,13 @@ + #ifndef _NDS32_INTRINSIC_H + #define _NDS32_INTRINSIC_H + ++typedef signed char int8x4_t __attribute ((vector_size(4))); ++typedef short int16x2_t __attribute ((vector_size(4))); ++typedef int int32x2_t __attribute__((vector_size(8))); ++typedef unsigned char uint8x4_t __attribute__ ((vector_size (4))); ++typedef unsigned short uint16x2_t __attribute__ ((vector_size (4))); ++typedef unsigned int uint32x2_t __attribute__((vector_size(8))); ++ + /* General instrinsic register names. */ + enum nds32_intrinsic_registers + { +@@ -691,6 +698,55 @@ + #define __nds32__tlbop_flua() \ + (__builtin_nds32_tlbop_flua()) + ++#define __nds32__kaddw(a, b) \ ++ (__builtin_nds32_kaddw ((a), (b))) ++#define __nds32__kaddh(a, b) \ ++ (__builtin_nds32_kaddh ((a), (b))) ++#define __nds32__ksubw(a, b) \ ++ (__builtin_nds32_ksubw ((a), (b))) ++#define __nds32__ksubh(a, b) \ ++ (__builtin_nds32_ksubh ((a), (b))) ++#define __nds32__kdmbb(a, b) \ ++ (__builtin_nds32_kdmbb ((a), (b))) ++#define __nds32__v_kdmbb(a, b) \ ++ (__builtin_nds32_v_kdmbb ((a), (b))) ++#define __nds32__kdmbt(a, b) \ ++ (__builtin_nds32_kdmbt ((a), (b))) ++#define __nds32__v_kdmbt(a, b) \ ++ (__builtin_nds32_v_kdmbt ((a), (b))) ++#define __nds32__kdmtb(a, b) \ ++ (__builtin_nds32_kdmtb ((a), (b))) ++#define __nds32__v_kdmtb(a, b) \ ++ (__builtin_nds32_v_kdmtb ((a), (b))) ++#define __nds32__kdmtt(a, b) \ ++ (__builtin_nds32_kdmtt ((a), (b))) ++#define __nds32__v_kdmtt(a, b) \ ++ (__builtin_nds32_v_kdmtt ((a), (b))) ++#define __nds32__khmbb(a, b) \ ++ (__builtin_nds32_khmbb ((a), (b))) ++#define __nds32__v_khmbb(a, b) \ ++ (__builtin_nds32_v_khmbb ((a), (b))) ++#define __nds32__khmbt(a, b) \ ++ (__builtin_nds32_khmbt ((a), (b))) ++#define __nds32__v_khmbt(a, b) \ ++ (__builtin_nds32_v_khmbt ((a), (b))) ++#define __nds32__khmtb(a, b) \ ++ (__builtin_nds32_khmtb ((a), (b))) ++#define __nds32__v_khmtb(a, b) \ ++ (__builtin_nds32_v_khmtb ((a), (b))) ++#define __nds32__khmtt(a, b) \ ++ (__builtin_nds32_khmtt ((a), (b))) ++#define __nds32__v_khmtt(a, b) \ ++ (__builtin_nds32_v_khmtt ((a), (b))) ++#define __nds32__kslraw(a, b) \ ++ (__builtin_nds32_kslraw ((a), (b))) ++#define __nds32__kslraw_u(a, b) \ ++ (__builtin_nds32_kslraw_u ((a), (b))) ++ ++#define __nds32__rdov() \ ++ (__builtin_nds32_rdov()) ++#define __nds32__clrov() \ ++ (__builtin_nds32_clrov()) + #define __nds32__gie_dis() \ + (__builtin_nds32_gie_dis()) + #define __nds32__gie_en() \ +@@ -720,10 +776,622 @@ + #define __nds32__get_trig_type(a) \ + (__builtin_nds32_get_trig_type ((a))) + ++#define __nds32__get_unaligned_hw(a) \ ++ (__builtin_nds32_unaligned_load_hw ((a))) ++#define __nds32__get_unaligned_w(a) \ ++ (__builtin_nds32_unaligned_load_w ((a))) ++#define __nds32__get_unaligned_dw(a) \ ++ (__builtin_nds32_unaligned_load_dw ((a))) ++#define __nds32__put_unaligned_hw(a, data) \ ++ (__builtin_nds32_unaligned_store_hw ((a), (data))) ++#define __nds32__put_unaligned_w(a, data) \ ++ (__builtin_nds32_unaligned_store_w ((a), (data))) ++#define __nds32__put_unaligned_dw(a, data) \ ++ (__builtin_nds32_unaligned_store_dw ((a), (data))) ++ ++#define __nds32__add16(a, b) \ ++ (__builtin_nds32_add16 ((a), (b))) ++#define __nds32__v_uadd16(a, b) \ ++ (__builtin_nds32_v_uadd16 ((a), (b))) ++#define __nds32__v_sadd16(a, b) \ ++ (__builtin_nds32_v_sadd16 ((a), (b))) ++#define __nds32__radd16(a, b) \ ++ (__builtin_nds32_radd16 ((a), (b))) ++#define __nds32__v_radd16(a, b) \ ++ (__builtin_nds32_v_radd16 ((a), (b))) ++#define __nds32__uradd16(a, b) \ ++ (__builtin_nds32_uradd16 ((a), (b))) ++#define __nds32__v_uradd16(a, b) \ ++ (__builtin_nds32_v_uradd16 ((a), (b))) ++#define __nds32__kadd16(a, b) \ ++ (__builtin_nds32_kadd16 ((a), (b))) ++#define __nds32__v_kadd16(a, b) \ ++ (__builtin_nds32_v_kadd16 ((a), (b))) ++#define __nds32__ukadd16(a, b) \ ++ (__builtin_nds32_ukadd16 ((a), (b))) ++#define __nds32__v_ukadd16(a, b) \ ++ (__builtin_nds32_v_ukadd16 ((a), (b))) ++#define __nds32__sub16(a, b) \ ++ (__builtin_nds32_sub16 ((a), (b))) ++#define __nds32__v_usub16(a, b) \ ++ (__builtin_nds32_v_usub16 ((a), (b))) ++#define __nds32__v_ssub16(a, b) \ ++ (__builtin_nds32_v_ssub16 ((a), (b))) ++#define __nds32__rsub16(a, b) \ ++ (__builtin_nds32_rsub16 ((a), (b))) ++#define __nds32__v_rsub16(a, b) \ ++ (__builtin_nds32_v_rsub16 ((a), (b))) ++#define __nds32__ursub16(a, b) \ ++ (__builtin_nds32_ursub16 ((a), (b))) ++#define __nds32__v_ursub16(a, b) \ ++ (__builtin_nds32_v_ursub16 ((a), (b))) ++#define __nds32__ksub16(a, b) \ ++ (__builtin_nds32_ksub16 ((a), (b))) ++#define __nds32__v_ksub16(a, b) \ ++ (__builtin_nds32_v_ksub16 ((a), (b))) ++#define __nds32__uksub16(a, b) \ ++ (__builtin_nds32_uksub16 ((a), (b))) ++#define __nds32__v_uksub16(a, b) \ ++ (__builtin_nds32_v_uksub16 ((a), (b))) ++#define __nds32__cras16(a, b) \ ++ (__builtin_nds32_cras16 ((a), (b))) ++#define __nds32__v_ucras16(a, b) \ ++ (__builtin_nds32_v_ucras16 ((a), (b))) ++#define __nds32__v_scras16(a, b) \ ++ (__builtin_nds32_v_scras16 ((a), (b))) ++#define __nds32__rcras16(a, b) \ ++ (__builtin_nds32_rcras16 ((a), (b))) ++#define __nds32__v_rcras16(a, b) \ ++ (__builtin_nds32_v_rcras16 ((a), (b))) ++#define __nds32__urcras16(a, b) \ ++ (__builtin_nds32_urcras16 ((a), (b))) ++#define __nds32__v_urcras16(a, b) \ ++ (__builtin_nds32_v_urcras16 ((a), (b))) ++#define __nds32__kcras16(a, b) \ ++ (__builtin_nds32_kcras16 ((a), (b))) ++#define __nds32__v_kcras16(a, b) \ ++ (__builtin_nds32_v_kcras16 ((a), (b))) ++#define __nds32__ukcras16(a, b) \ ++ (__builtin_nds32_ukcras16 ((a), (b))) ++#define __nds32__v_ukcras16(a, b) \ ++ (__builtin_nds32_v_ukcras16 ((a), (b))) ++#define __nds32__crsa16(a, b) \ ++ (__builtin_nds32_crsa16 ((a), (b))) ++#define __nds32__v_ucrsa16(a, b) \ ++ (__builtin_nds32_v_ucrsa16 ((a), (b))) ++#define __nds32__v_scrsa16(a, b) \ ++ (__builtin_nds32_v_scrsa16 ((a), (b))) ++#define __nds32__rcrsa16(a, b) \ ++ (__builtin_nds32_rcrsa16 ((a), (b))) ++#define __nds32__v_rcrsa16(a, b) \ ++ (__builtin_nds32_v_rcrsa16 ((a), (b))) ++#define __nds32__urcrsa16(a, b) \ ++ (__builtin_nds32_urcrsa16 ((a), (b))) ++#define __nds32__v_urcrsa16(a, b) \ ++ (__builtin_nds32_v_urcrsa16 ((a), (b))) ++#define __nds32__kcrsa16(a, b) \ ++ (__builtin_nds32_kcrsa16 ((a), (b))) ++#define __nds32__v_kcrsa16(a, b) \ ++ (__builtin_nds32_v_kcrsa16 ((a), (b))) ++#define __nds32__ukcrsa16(a, b) \ ++ (__builtin_nds32_ukcrsa16 ((a), (b))) ++#define __nds32__v_ukcrsa16(a, b) \ ++ (__builtin_nds32_v_ukcrsa16 ((a), (b))) ++ ++#define __nds32__add8(a, b) \ ++ (__builtin_nds32_add8 ((a), (b))) ++#define __nds32__v_uadd8(a, b) \ ++ (__builtin_nds32_v_uadd8 ((a), (b))) ++#define __nds32__v_sadd8(a, b) \ ++ (__builtin_nds32_v_sadd8 ((a), (b))) ++#define __nds32__radd8(a, b) \ ++ (__builtin_nds32_radd8 ((a), (b))) ++#define __nds32__v_radd8(a, b) \ ++ (__builtin_nds32_v_radd8 ((a), (b))) ++#define __nds32__uradd8(a, b) \ ++ (__builtin_nds32_uradd8 ((a), (b))) ++#define __nds32__v_uradd8(a, b) \ ++ (__builtin_nds32_v_uradd8 ((a), (b))) ++#define __nds32__kadd8(a, b) \ ++ (__builtin_nds32_kadd8 ((a), (b))) ++#define __nds32__v_kadd8(a, b) \ ++ (__builtin_nds32_v_kadd8 ((a), (b))) ++#define __nds32__ukadd8(a, b) \ ++ (__builtin_nds32_ukadd8 ((a), (b))) ++#define __nds32__v_ukadd8(a, b) \ ++ (__builtin_nds32_v_ukadd8 ((a), (b))) ++#define __nds32__sub8(a, b) \ ++ (__builtin_nds32_sub8 ((a), (b))) ++#define __nds32__v_usub8(a, b) \ ++ (__builtin_nds32_v_usub8 ((a), (b))) ++#define __nds32__v_ssub8(a, b) \ ++ (__builtin_nds32_v_ssub8 ((a), (b))) ++#define __nds32__rsub8(a, b) \ ++ (__builtin_nds32_rsub8 ((a), (b))) ++#define __nds32__v_rsub8(a, b) \ ++ (__builtin_nds32_v_rsub8 ((a), (b))) ++#define __nds32__ursub8(a, b) \ ++ (__builtin_nds32_ursub8 ((a), (b))) ++#define __nds32__v_ursub8(a, b) \ ++ (__builtin_nds32_v_ursub8 ((a), (b))) ++#define __nds32__ksub8(a, b) \ ++ (__builtin_nds32_ksub8 ((a), (b))) ++#define __nds32__v_ksub8(a, b) \ ++ (__builtin_nds32_v_ksub8 ((a), (b))) ++#define __nds32__uksub8(a, b) \ ++ (__builtin_nds32_uksub8 ((a), (b))) ++#define __nds32__v_uksub8(a, b) \ ++ (__builtin_nds32_v_uksub8 ((a), (b))) ++ ++#define __nds32__sra16(a, b) \ ++ (__builtin_nds32_sra16 ((a), (b))) ++#define __nds32__v_sra16(a, b) \ ++ (__builtin_nds32_v_sra16 ((a), (b))) ++#define __nds32__sra16_u(a, b) \ ++ (__builtin_nds32_sra16_u ((a), (b))) ++#define __nds32__v_sra16_u(a, b) \ ++ (__builtin_nds32_v_sra16_u ((a), (b))) ++#define __nds32__srl16(a, b) \ ++ (__builtin_nds32_srl16 ((a), (b))) ++#define __nds32__v_srl16(a, b) \ ++ (__builtin_nds32_v_srl16 ((a), (b))) ++#define __nds32__srl16_u(a, b) \ ++ (__builtin_nds32_srl16_u ((a), (b))) ++#define __nds32__v_srl16_u(a, b) \ ++ (__builtin_nds32_v_srl16_u ((a), (b))) ++#define __nds32__sll16(a, b) \ ++ (__builtin_nds32_sll16 ((a), (b))) ++#define __nds32__v_sll16(a, b) \ ++ (__builtin_nds32_v_sll16 ((a), (b))) ++#define __nds32__ksll16(a, b) \ ++ (__builtin_nds32_ksll16 ((a), (b))) ++#define __nds32__v_ksll16(a, b) \ ++ (__builtin_nds32_v_ksll16 ((a), (b))) ++#define __nds32__kslra16(a, b) \ ++ (__builtin_nds32_kslra16 ((a), (b))) ++#define __nds32__v_kslra16(a, b) \ ++ (__builtin_nds32_v_kslra16 ((a), (b))) ++#define __nds32__kslra16_u(a, b) \ ++ (__builtin_nds32_kslra16_u ((a), (b))) ++#define __nds32__v_kslra16_u(a, b) \ ++ (__builtin_nds32_v_kslra16_u ((a), (b))) ++ ++#define __nds32__cmpeq16(a, b) \ ++ (__builtin_nds32_cmpeq16 ((a), (b))) ++#define __nds32__v_scmpeq16(a, b) \ ++ (__builtin_nds32_v_scmpeq16 ((a), (b))) ++#define __nds32__v_ucmpeq16(a, b) \ ++ (__builtin_nds32_v_ucmpeq16 ((a), (b))) ++#define __nds32__scmplt16(a, b) \ ++ (__builtin_nds32_scmplt16 ((a), (b))) ++#define __nds32__v_scmplt16(a, b) \ ++ (__builtin_nds32_v_scmplt16 ((a), (b))) ++#define __nds32__scmple16(a, b) \ ++ (__builtin_nds32_scmple16 ((a), (b))) ++#define __nds32__v_scmple16(a, b) \ ++ (__builtin_nds32_v_scmple16 ((a), (b))) ++#define __nds32__ucmplt16(a, b) \ ++ (__builtin_nds32_ucmplt16 ((a), (b))) ++#define __nds32__v_ucmplt16(a, b) \ ++ (__builtin_nds32_v_ucmplt16 ((a), (b))) ++#define __nds32__ucmple16(a, b) \ ++ (__builtin_nds32_ucmple16 ((a), (b))) ++#define __nds32__v_ucmple16(a, b) \ ++ (__builtin_nds32_v_ucmple16 ((a), (b))) ++ ++#define __nds32__cmpeq8(a, b) \ ++ (__builtin_nds32_cmpeq8 ((a), (b))) ++#define __nds32__v_scmpeq8(a, b) \ ++ (__builtin_nds32_v_scmpeq8 ((a), (b))) ++#define __nds32__v_ucmpeq8(a, b) \ ++ (__builtin_nds32_v_ucmpeq8 ((a), (b))) ++#define __nds32__scmplt8(a, b) \ ++ (__builtin_nds32_scmplt8 ((a), (b))) ++#define __nds32__v_scmplt8(a, b) \ ++ (__builtin_nds32_v_scmplt8 ((a), (b))) ++#define __nds32__scmple8(a, b) \ ++ (__builtin_nds32_scmple8 ((a), (b))) ++#define __nds32__v_scmple8(a, b) \ ++ (__builtin_nds32_v_scmple8 ((a), (b))) ++#define __nds32__ucmplt8(a, b) \ ++ (__builtin_nds32_ucmplt8 ((a), (b))) ++#define __nds32__v_ucmplt8(a, b) \ ++ (__builtin_nds32_v_ucmplt8 ((a), (b))) ++#define __nds32__ucmple8(a, b) \ ++ (__builtin_nds32_ucmple8 ((a), (b))) ++#define __nds32__v_ucmple8(a, b) \ ++ (__builtin_nds32_v_ucmple8 ((a), (b))) ++ ++#define __nds32__smin16(a, b) \ ++ (__builtin_nds32_smin16 ((a), (b))) ++#define __nds32__v_smin16(a, b) \ ++ (__builtin_nds32_v_smin16 ((a), (b))) ++#define __nds32__umin16(a, b) \ ++ (__builtin_nds32_umin16 ((a), (b))) ++#define __nds32__v_umin16(a, b) \ ++ (__builtin_nds32_v_umin16 ((a), (b))) ++#define __nds32__smax16(a, b) \ ++ (__builtin_nds32_smax16 ((a), (b))) ++#define __nds32__v_smax16(a, b) \ ++ (__builtin_nds32_v_smax16 ((a), (b))) ++#define __nds32__umax16(a, b) \ ++ (__builtin_nds32_umax16 ((a), (b))) ++#define __nds32__v_umax16(a, b) \ ++ (__builtin_nds32_v_umax16 ((a), (b))) ++#define __nds32__sclip16(a, b) \ ++ (__builtin_nds32_sclip16 ((a), (b))) ++#define __nds32__v_sclip16(a, b) \ ++ (__builtin_nds32_v_sclip16 ((a), (b))) ++#define __nds32__uclip16(a, b) \ ++ (__builtin_nds32_uclip16 ((a), (b))) ++#define __nds32__v_uclip16(a, b) \ ++ (__builtin_nds32_v_uclip16 ((a), (b))) ++#define __nds32__khm16(a, b) \ ++ (__builtin_nds32_khm16 ((a), (b))) ++#define __nds32__v_khm16(a, b) \ ++ (__builtin_nds32_v_khm16 ((a), (b))) ++#define __nds32__khmx16(a, b) \ ++ (__builtin_nds32_khmx16 ((a), (b))) ++#define __nds32__v_khmx16(a, b) \ ++ (__builtin_nds32_v_khmx16 ((a), (b))) ++#define __nds32__kabs16(a) \ ++ (__builtin_nds32_kabs16 ((a))) ++#define __nds32__v_kabs16(a) \ ++ (__builtin_nds32_v_kabs16 ((a))) ++ ++#define __nds32__smin8(a, b) \ ++ (__builtin_nds32_smin8 ((a), (b))) ++#define __nds32__v_smin8(a, b) \ ++ (__builtin_nds32_v_smin8 ((a), (b))) ++#define __nds32__umin8(a, b) \ ++ (__builtin_nds32_umin8 ((a), (b))) ++#define __nds32__v_umin8(a, b) \ ++ (__builtin_nds32_v_umin8 ((a), (b))) ++#define __nds32__smax8(a, b) \ ++ (__builtin_nds32_smax8 ((a), (b))) ++#define __nds32__v_smax8(a, b) \ ++ (__builtin_nds32_v_smax8 ((a), (b))) ++#define __nds32__umax8(a, b) \ ++ (__builtin_nds32_umax8 ((a), (b))) ++#define __nds32__v_umax8(a, b) \ ++ (__builtin_nds32_v_umax8 ((a), (b))) ++#define __nds32__kabs8(a) \ ++ (__builtin_nds32_kabs8 ((a))) ++#define __nds32__v_kabs8(a) \ ++ (__builtin_nds32_v_kabs8 ((a))) ++ ++#define __nds32__sunpkd810(a) \ ++ (__builtin_nds32_sunpkd810 ((a))) ++#define __nds32__v_sunpkd810(a) \ ++ (__builtin_nds32_v_sunpkd810 ((a))) ++#define __nds32__sunpkd820(a) \ ++ (__builtin_nds32_sunpkd820 ((a))) ++#define __nds32__v_sunpkd820(a) \ ++ (__builtin_nds32_v_sunpkd820 ((a))) ++#define __nds32__sunpkd830(a) \ ++ (__builtin_nds32_sunpkd830 ((a))) ++#define __nds32__v_sunpkd830(a) \ ++ (__builtin_nds32_v_sunpkd830 ((a))) ++#define __nds32__sunpkd831(a) \ ++ (__builtin_nds32_sunpkd831 ((a))) ++#define __nds32__v_sunpkd831(a) \ ++ (__builtin_nds32_v_sunpkd831 ((a))) ++#define __nds32__zunpkd810(a) \ ++ (__builtin_nds32_zunpkd810 ((a))) ++#define __nds32__v_zunpkd810(a) \ ++ (__builtin_nds32_v_zunpkd810 ((a))) ++#define __nds32__zunpkd820(a) \ ++ (__builtin_nds32_zunpkd820 ((a))) ++#define __nds32__v_zunpkd820(a) \ ++ (__builtin_nds32_v_zunpkd820 ((a))) ++#define __nds32__zunpkd830(a) \ ++ (__builtin_nds32_zunpkd830 ((a))) ++#define __nds32__v_zunpkd830(a) \ ++ (__builtin_nds32_v_zunpkd830 ((a))) ++#define __nds32__zunpkd831(a) \ ++ (__builtin_nds32_zunpkd831 ((a))) ++#define __nds32__v_zunpkd831(a) \ ++ (__builtin_nds32_v_zunpkd831 ((a))) ++ ++#define __nds32__raddw(a, b) \ ++ (__builtin_nds32_raddw ((a), (b))) ++#define __nds32__uraddw(a, b) \ ++ (__builtin_nds32_uraddw ((a), (b))) ++#define __nds32__rsubw(a, b) \ ++ (__builtin_nds32_rsubw ((a), (b))) ++#define __nds32__ursubw(a, b) \ ++ (__builtin_nds32_ursubw ((a), (b))) ++ ++#define __nds32__sra_u(a, b) \ ++ (__builtin_nds32_sra_u ((a), (b))) ++#define __nds32__ksll(a, b) \ ++ (__builtin_nds32_ksll ((a), (b))) ++#define __nds32__pkbb16(a, b) \ ++ (__builtin_nds32_pkbb16 ((a), (b))) ++#define __nds32__v_pkbb16(a, b) \ ++ (__builtin_nds32_v_pkbb16 ((a), (b))) ++#define __nds32__pkbt16(a, b) \ ++ (__builtin_nds32_pkbt16 ((a), (b))) ++#define __nds32__v_pkbt16(a, b) \ ++ (__builtin_nds32_v_pkbt16 ((a), (b))) ++#define __nds32__pktb16(a, b) \ ++ (__builtin_nds32_pktb16 ((a), (b))) ++#define __nds32__v_pktb16(a, b) \ ++ (__builtin_nds32_v_pktb16 ((a), (b))) ++#define __nds32__pktt16(a, b) \ ++ (__builtin_nds32_pktt16 ((a), (b))) ++#define __nds32__v_pktt16(a, b) \ ++ (__builtin_nds32_v_pktt16 ((a), (b))) ++ ++#define __nds32__smmul(a, b) \ ++ (__builtin_nds32_smmul ((a), (b))) ++#define __nds32__smmul_u(a, b) \ ++ (__builtin_nds32_smmul_u ((a), (b))) ++#define __nds32__kmmac(r, a, b) \ ++ (__builtin_nds32_kmmac ((r), (a), (b))) ++#define __nds32__kmmac_u(r, a, b) \ ++ (__builtin_nds32_kmmac_u ((r), (a), (b))) ++#define __nds32__kmmsb(r, a, b) \ ++ (__builtin_nds32_kmmsb ((r), (a), (b))) ++#define __nds32__kmmsb_u(r, a, b) \ ++ (__builtin_nds32_kmmsb_u ((r), (a), (b))) ++#define __nds32__kwmmul(a, b) \ ++ (__builtin_nds32_kwmmul ((a), (b))) ++#define __nds32__kwmmul_u(a, b) \ ++ (__builtin_nds32_kwmmul_u ((a), (b))) ++ ++#define __nds32__smmwb(a, b) \ ++ (__builtin_nds32_smmwb ((a), (b))) ++#define __nds32__v_smmwb(a, b) \ ++ (__builtin_nds32_v_smmwb ((a), (b))) ++#define __nds32__smmwb_u(a, b) \ ++ (__builtin_nds32_smmwb_u ((a), (b))) ++#define __nds32__v_smmwb_u(a, b) \ ++ (__builtin_nds32_v_smmwb_u ((a), (b))) ++#define __nds32__smmwt(a, b) \ ++ (__builtin_nds32_smmwt ((a), (b))) ++#define __nds32__v_smmwt(a, b) \ ++ (__builtin_nds32_v_smmwt ((a), (b))) ++#define __nds32__smmwt_u(a, b) \ ++ (__builtin_nds32_smmwt_u ((a), (b))) ++#define __nds32__v_smmwt_u(a, b) \ ++ (__builtin_nds32_v_smmwt_u ((a), (b))) ++#define __nds32__kmmawb(r, a, b) \ ++ (__builtin_nds32_kmmawb ((r), (a), (b))) ++#define __nds32__v_kmmawb(r, a, b) \ ++ (__builtin_nds32_v_kmmawb ((r), (a), (b))) ++#define __nds32__kmmawb_u(r, a, b) \ ++ (__builtin_nds32_kmmawb_u ((r), (a), (b))) ++#define __nds32__v_kmmawb_u(r, a, b) \ ++ (__builtin_nds32_v_kmmawb_u ((r), (a), (b))) ++#define __nds32__kmmawt(r, a, b) \ ++ (__builtin_nds32_kmmawt ((r), (a), (b))) ++#define __nds32__v_kmmawt(r, a, b) \ ++ (__builtin_nds32_v_kmmawt ((r), (a), (b))) ++#define __nds32__kmmawt_u(r, a, b) \ ++ (__builtin_nds32_kmmawt_u ((r), (a), (b))) ++#define __nds32__v_kmmawt_u(r, a, b) \ ++ (__builtin_nds32_v_kmmawt_u ((r), (a), (b))) ++ ++#define __nds32__smbb(a, b) \ ++ (__builtin_nds32_smbb ((a), (b))) ++#define __nds32__v_smbb(a, b) \ ++ (__builtin_nds32_v_smbb ((a), (b))) ++#define __nds32__smbt(a, b) \ ++ (__builtin_nds32_smbt ((a), (b))) ++#define __nds32__v_smbt(a, b) \ ++ (__builtin_nds32_v_smbt ((a), (b))) ++#define __nds32__smtt(a, b) \ ++ (__builtin_nds32_smtt ((a), (b))) ++#define __nds32__v_smtt(a, b) \ ++ (__builtin_nds32_v_smtt ((a), (b))) ++#define __nds32__kmda(a, b) \ ++ (__builtin_nds32_kmda ((a), (b))) ++#define __nds32__v_kmda(a, b) \ ++ (__builtin_nds32_v_kmda ((a), (b))) ++#define __nds32__kmxda(a, b) \ ++ (__builtin_nds32_kmxda ((a), (b))) ++#define __nds32__v_kmxda(a, b) \ ++ (__builtin_nds32_v_kmxda ((a), (b))) ++#define __nds32__smds(a, b) \ ++ (__builtin_nds32_smds ((a), (b))) ++#define __nds32__v_smds(a, b) \ ++ (__builtin_nds32_v_smds ((a), (b))) ++#define __nds32__smdrs(a, b) \ ++ (__builtin_nds32_smdrs ((a), (b))) ++#define __nds32__v_smdrs(a, b) \ ++ (__builtin_nds32_v_smdrs ((a), (b))) ++#define __nds32__smxds(a, b) \ ++ (__builtin_nds32_smxds ((a), (b))) ++#define __nds32__v_smxds(a, b) \ ++ (__builtin_nds32_v_smxds ((a), (b))) ++#define __nds32__kmabb(r, a, b) \ ++ (__builtin_nds32_kmabb ((r), (a), (b))) ++#define __nds32__v_kmabb(r, a, b) \ ++ (__builtin_nds32_v_kmabb ((r), (a), (b))) ++#define __nds32__kmabt(r, a, b) \ ++ (__builtin_nds32_kmabt ((r), (a), (b))) ++#define __nds32__v_kmabt(r, a, b) \ ++ (__builtin_nds32_v_kmabt ((r), (a), (b))) ++#define __nds32__kmatt(r, a, b) \ ++ (__builtin_nds32_kmatt ((r), (a), (b))) ++#define __nds32__v_kmatt(r, a, b) \ ++ (__builtin_nds32_v_kmatt ((r), (a), (b))) ++#define __nds32__kmada(r, a, b) \ ++ (__builtin_nds32_kmada ((r), (a), (b))) ++#define __nds32__v_kmada(r, a, b) \ ++ (__builtin_nds32_v_kmada ((r), (a), (b))) ++#define __nds32__kmaxda(r, a, b) \ ++ (__builtin_nds32_kmaxda ((r), (a), (b))) ++#define __nds32__v_kmaxda(r, a, b) \ ++ (__builtin_nds32_v_kmaxda ((r), (a), (b))) ++#define __nds32__kmads(r, a, b) \ ++ (__builtin_nds32_kmads ((r), (a), (b))) ++#define __nds32__v_kmads(r, a, b) \ ++ (__builtin_nds32_v_kmads ((r), (a), (b))) ++#define __nds32__kmadrs(r, a, b) \ ++ (__builtin_nds32_kmadrs ((r), (a), (b))) ++#define __nds32__v_kmadrs(r, a, b) \ ++ (__builtin_nds32_v_kmadrs ((r), (a), (b))) ++#define __nds32__kmaxds(r, a, b) \ ++ (__builtin_nds32_kmaxds ((r), (a), (b))) ++#define __nds32__v_kmaxds(r, a, b) \ ++ (__builtin_nds32_v_kmaxds ((r), (a), (b))) ++#define __nds32__kmsda(r, a, b) \ ++ (__builtin_nds32_kmsda ((r), (a), (b))) ++#define __nds32__v_kmsda(r, a, b) \ ++ (__builtin_nds32_v_kmsda ((r), (a), (b))) ++#define __nds32__kmsxda(r, a, b) \ ++ (__builtin_nds32_kmsxda ((r), (a), (b))) ++#define __nds32__v_kmsxda(r, a, b) \ ++ (__builtin_nds32_v_kmsxda ((r), (a), (b))) ++ ++#define __nds32__smal(a, b) \ ++ (__builtin_nds32_smal ((a), (b))) ++#define __nds32__v_smal(a, b) \ ++ (__builtin_nds32_v_smal ((a), (b))) ++ ++#define __nds32__bitrev(a, b) \ ++ (__builtin_nds32_bitrev ((a), (b))) ++#define __nds32__wext(a, b) \ ++ (__builtin_nds32_wext ((a), (b))) ++#define __nds32__bpick(r, a, b) \ ++ (__builtin_nds32_bpick ((r), (a), (b))) ++#define __nds32__insb(r, a, b) \ ++ (__builtin_nds32_insb ((r), (a), (b))) ++ ++#define __nds32__sadd64(a, b) \ ++ (__builtin_nds32_sadd64 ((a), (b))) ++#define __nds32__uadd64(a, b) \ ++ (__builtin_nds32_uadd64 ((a), (b))) ++#define __nds32__radd64(a, b) \ ++ (__builtin_nds32_radd64 ((a), (b))) ++#define __nds32__uradd64(a, b) \ ++ (__builtin_nds32_uradd64 ((a), (b))) ++#define __nds32__kadd64(a, b) \ ++ (__builtin_nds32_kadd64 ((a), (b))) ++#define __nds32__ukadd64(a, b) \ ++ (__builtin_nds32_ukadd64 ((a), (b))) ++#define __nds32__ssub64(a, b) \ ++ (__builtin_nds32_ssub64 ((a), (b))) ++#define __nds32__usub64(a, b) \ ++ (__builtin_nds32_usub64 ((a), (b))) ++#define __nds32__rsub64(a, b) \ ++ (__builtin_nds32_rsub64 ((a), (b))) ++#define __nds32__ursub64(a, b) \ ++ (__builtin_nds32_ursub64 ((a), (b))) ++#define __nds32__ksub64(a, b) \ ++ (__builtin_nds32_ksub64 ((a), (b))) ++#define __nds32__uksub64(a, b) \ ++ (__builtin_nds32_uksub64 ((a), (b))) ++ ++#define __nds32__smar64(r, a, b) \ ++ (__builtin_nds32_smar64 ((r), (a), (b))) ++#define __nds32__smsr64(r, a, b) \ ++ (__builtin_nds32_smsr64 ((r), (a), (b))) ++#define __nds32__umar64(r, a, b) \ ++ (__builtin_nds32_umar64 ((r), (a), (b))) ++#define __nds32__umsr64(r, a, b) \ ++ (__builtin_nds32_umsr64 ((r), (a), (b))) ++#define __nds32__kmar64(r, a, b) \ ++ (__builtin_nds32_kmar64 ((r), (a), (b))) ++#define __nds32__kmsr64(r, a, b) \ ++ (__builtin_nds32_kmsr64 ((r), (a), (b))) ++#define __nds32__ukmar64(r, a, b) \ ++ (__builtin_nds32_ukmar64 ((r), (a), (b))) ++#define __nds32__ukmsr64(r, a, b) \ ++ (__builtin_nds32_ukmsr64 ((r), (a), (b))) ++ ++#define __nds32__smalbb(r, a, b) \ ++ (__builtin_nds32_smalbb ((r), (a), (b))) ++#define __nds32__v_smalbb(r, a, b) \ ++ (__builtin_nds32_v_smalbb ((r), (a), (b))) ++#define __nds32__smalbt(r, a, b) \ ++ (__builtin_nds32_smalbt ((r), (a), (b))) ++#define __nds32__v_smalbt(r, a, b) \ ++ (__builtin_nds32_v_smalbt ((r), (a), (b))) ++#define __nds32__smaltt(r, a, b) \ ++ (__builtin_nds32_smaltt ((r), (a), (b))) ++#define __nds32__v_smaltt(r, a, b) \ ++ (__builtin_nds32_v_smaltt ((r), (a), (b))) ++#define __nds32__smalda(r, a, b) \ ++ (__builtin_nds32_smalda ((r), (a), (b))) ++#define __nds32__v_smalda(r, a, b) \ ++ (__builtin_nds32_v_smalda ((r), (a), (b))) ++#define __nds32__smalxda(r, a, b) \ ++ (__builtin_nds32_smalxda ((r), (a), (b))) ++#define __nds32__v_smalxda(r, a, b) \ ++ (__builtin_nds32_v_smalxda ((r), (a), (b))) ++#define __nds32__smalds(r, a, b) \ ++ (__builtin_nds32_smalds ((r), (a), (b))) ++#define __nds32__v_smalds(r, a, b) \ ++ (__builtin_nds32_v_smalds ((r), (a), (b))) ++#define __nds32__smaldrs(r, a, b) \ ++ (__builtin_nds32_smaldrs ((r), (a), (b))) ++#define __nds32__v_smaldrs(r, a, b) \ ++ (__builtin_nds32_v_smaldrs ((r), (a), (b))) ++#define __nds32__smalxds(r, a, b) \ ++ (__builtin_nds32_smalxds ((r), (a), (b))) ++#define __nds32__v_smalxds(r, a, b) \ ++ (__builtin_nds32_v_smalxds ((r), (a), (b))) ++#define __nds32__smslda(r, a, b) \ ++ (__builtin_nds32_smslda ((r), (a), (b))) ++#define __nds32__v_smslda(r, a, b) \ ++ (__builtin_nds32_v_smslda ((r), (a), (b))) ++#define __nds32__smslxda(r, a, b) \ ++ (__builtin_nds32_smslxda ((r), (a), (b))) ++#define __nds32__v_smslxda(r, a, b) \ ++ (__builtin_nds32_v_smslxda ((r), (a), (b))) ++ ++#define __nds32__smul16(a, b) \ ++ (__builtin_nds32_smul16 ((a), (b))) ++#define __nds32__v_smul16(a, b) \ ++ (__builtin_nds32_v_smul16 ((a), (b))) ++#define __nds32__smulx16(a, b) \ ++ (__builtin_nds32_smulx16 ((a), (b))) ++#define __nds32__v_smulx16(a, b) \ ++ (__builtin_nds32_v_smulx16 ((a), (b))) ++#define __nds32__umul16(a, b) \ ++ (__builtin_nds32_umul16 ((a), (b))) ++#define __nds32__v_umul16(a, b) \ ++ (__builtin_nds32_v_umul16 ((a), (b))) ++#define __nds32__umulx16(a, b) \ ++ (__builtin_nds32_umulx16 ((a), (b))) ++#define __nds32__v_umulx16(a, b) \ ++ (__builtin_nds32_v_umulx16 ((a), (b))) ++ ++#define __nds32__uclip32(a, imm) \ ++ (__builtin_nds32_uclip32 ((a), (imm))) ++#define __nds32__sclip32(a, imm) \ ++ (__builtin_nds32_sclip32 ((a), (imm))) ++#define __nds32__kabs(a) \ ++ (__builtin_nds32_kabs ((a))) ++ + #define __nds32__unaligned_feature() \ + (__builtin_nds32_unaligned_feature()) + #define __nds32__enable_unaligned() \ + (__builtin_nds32_enable_unaligned()) + #define __nds32__disable_unaligned() \ + (__builtin_nds32_disable_unaligned()) ++ ++#define __nds32__get_unaligned_u16x2(a) \ ++ (__builtin_nds32_get_unaligned_u16x2 ((a))) ++#define __nds32__get_unaligned_s16x2(a) \ ++ (__builtin_nds32_get_unaligned_s16x2 ((a))) ++#define __nds32__get_unaligned_u8x4(a) \ ++ (__builtin_nds32_get_unaligned_u8x4 ((a))) ++#define __nds32__get_unaligned_s8x4(a) \ ++ (__builtin_nds32_get_unaligned_s8x4 ((a))) ++ ++#define __nds32__put_unaligned_u16x2(a, data) \ ++ (__builtin_nds32_put_unaligned_u16x2 ((a), (data))) ++#define __nds32__put_unaligned_s16x2(a, data) \ ++ (__builtin_nds32_put_unaligned_s16x2 ((a), (data))) ++#define __nds32__put_unaligned_u8x4(a, data) \ ++ (__builtin_nds32_put_unaligned_u8x4 ((a), (data))) ++#define __nds32__put_unaligned_s8x4(a, data) \ ++ (__builtin_nds32_put_unaligned_s8x4 ((a), (data))) ++ ++#define NDS32ATTR_SIGNATURE __attribute__((signature)) ++ + #endif /* nds32_intrinsic.h */ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-intrinsic.md gcc-8.2.0/gcc/config/nds32/nds32-intrinsic.md +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-intrinsic.md 2018-04-22 09:46:39.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-intrinsic.md 2019-01-25 15:38:32.825242648 +0100 +@@ -1037,6 +1037,187 @@ + (set_attr "length" "4")] + ) + ++;; SATURATION ++ ++(define_insn "unspec_kaddw" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_plus:SI (match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "register_operand" "r")))] ++ "" ++ "kaddw\t%0, %1, %2" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_ksubw" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (ss_minus:SI (match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "register_operand" "r")))] ++ "" ++ "ksubw\t%0, %1, %2" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_kaddh" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "register_operand" "r")] UNSPEC_KADDH))] ++ "" ++ "kaddh\t%0, %1, %2" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_ksubh" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSUBH))] ++ "" ++ "ksubh\t%0, %1, %2" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_kaddh_dsp" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "register_operand" "r")) ++ (const_int 15)] UNSPEC_CLIPS))] ++ "NDS32_EXT_DSP_P ()" ++ "kaddh\t%0, %1, %2" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_ksubh_dsp" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(minus:SI (match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "register_operand" "r")) ++ (const_int 15)] UNSPEC_CLIPS))] ++ "NDS32_EXT_DSP_P ()" ++ "ksubh\t%0, %1, %2" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_kdmbb" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") ++ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMBB))] ++ "" ++ "kdmbb\t%0, %1, %2" ++ [(set_attr "type" "mul") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_kdmbt" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") ++ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMBT))] ++ "" ++ "kdmbt\t%0, %1, %2" ++ [(set_attr "type" "mul") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_kdmtb" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") ++ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMTB))] ++ "" ++ "kdmtb\t%0, %1, %2" ++ [(set_attr "type" "mul") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_kdmtt" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") ++ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMTT))] ++ "" ++ "kdmtt\t%0, %1, %2" ++ [(set_attr "type" "mul") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_khmbb" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") ++ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMBB))] ++ "" ++ "khmbb\t%0, %1, %2" ++ [(set_attr "type" "mul") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_khmbt" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") ++ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMBT))] ++ "" ++ "khmbt\t%0, %1, %2" ++ [(set_attr "type" "mul") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_khmtb" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") ++ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMTB))] ++ "" ++ "khmtb\t%0, %1, %2" ++ [(set_attr "type" "mul") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_khmtt" ++ [(set (match_operand:V2HI 0 "register_operand" "=r") ++ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r") ++ (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMTT))] ++ "" ++ "khmtt\t%0, %1, %2" ++ [(set_attr "type" "mul") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_kslraw" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSLRAW))] ++ "" ++ "kslraw\t%0, %1, %2" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_kslrawu" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSLRAWU))] ++ "" ++ "kslraw.u\t%0, %1, %2" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_volatile_rdov" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_RDOV))] ++ "" ++ "rdov\t%0" ++ [(set_attr "type" "misc") ++ (set_attr "length" "4")] ++) ++ ++(define_insn "unspec_volatile_clrov" ++ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CLROV)] ++ "" ++ "clrov" ++ [(set_attr "type" "misc") ++ (set_attr "length" "4")] ++) ++ + ;; System + + (define_insn "unspec_sva" +@@ -1415,22 +1596,17 @@ + if (TARGET_ISA_V3M) + nds32_expand_unaligned_store (operands, DImode); + else +- emit_insn (gen_unaligned_store_dw (operands[0], operands[1])); ++ emit_insn (gen_unaligned_store_dw (gen_rtx_MEM (DImode, operands[0]), ++ operands[1])); + DONE; + }) + + (define_insn "unaligned_store_dw" +- [(set (mem:DI (match_operand:SI 0 "register_operand" "r")) +- (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_UASTORE_DW))] ++ [(set (match_operand:DI 0 "nds32_lmw_smw_base_operand" "=Umw") ++ (unspec:DI [(match_operand:DI 1 "register_operand" " r")] UNSPEC_UASTORE_DW))] + "" + { +- rtx otherops[3]; +- otherops[0] = gen_rtx_REG (SImode, REGNO (operands[1])); +- otherops[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); +- otherops[2] = operands[0]; +- +- output_asm_insn ("smw.bi\t%0, [%2], %1, 0", otherops); +- return ""; ++ return nds32_output_smw_double_word (operands); + } + [(set_attr "type" "store") + (set_attr "length" "4")] +@@ -1495,4 +1671,15 @@ + DONE; + }) + ++;; abs alias kabs ++ ++(define_insn "unspec_kabs" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_KABS))] ++ "" ++ "kabs\t%0, %1" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ + ;; ------------------------------------------------------------------------ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-isr.c gcc-8.2.0/gcc/config/nds32/nds32-isr.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-isr.c 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-isr.c 2019-01-25 15:38:32.829242659 +0100 +@@ -43,7 +43,260 @@ + We use an array to record essential information for each vector. */ + static struct nds32_isr_info nds32_isr_vectors[NDS32_N_ISR_VECTORS]; + +-/* ------------------------------------------------------------------------ */ ++/* ------------------------------------------------------------- */ ++/* FIXME: ++ FOR BACKWARD COMPATIBILITY, we need to support following patterns: ++ ++ __attribute__((interrupt("XXX;YYY;id=ZZZ"))) ++ __attribute__((exception("XXX;YYY;id=ZZZ"))) ++ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ"))) ++ ++ We provide several functions to parse the strings. */ ++ ++static void ++nds32_interrupt_attribute_parse_string (const char *original_str, ++ const char *func_name, ++ unsigned int s_level) ++{ ++ char target_str[100]; ++ enum nds32_isr_save_reg save_reg; ++ enum nds32_isr_nested_type nested_type; ++ ++ char *save_all_regs_str, *save_caller_regs_str; ++ char *nested_str, *not_nested_str, *ready_nested_str, *critical_str; ++ char *id_str, *value_str; ++ ++ /* Copy original string into a character array so that ++ the string APIs can handle it. */ ++ strcpy (target_str, original_str); ++ ++ /* 1. Detect 'save_all_regs' : NDS32_SAVE_ALL ++ 'save_caller_regs' : NDS32_PARTIAL_SAVE */ ++ save_all_regs_str = strstr (target_str, "save_all_regs"); ++ save_caller_regs_str = strstr (target_str, "save_caller_regs"); ++ ++ /* Note that if no argument is found, ++ use NDS32_PARTIAL_SAVE by default. */ ++ if (save_all_regs_str) ++ save_reg = NDS32_SAVE_ALL; ++ else if (save_caller_regs_str) ++ save_reg = NDS32_PARTIAL_SAVE; ++ else ++ save_reg = NDS32_PARTIAL_SAVE; ++ ++ /* 2. Detect 'nested' : NDS32_NESTED ++ 'not_nested' : NDS32_NOT_NESTED ++ 'ready_nested' : NDS32_NESTED_READY ++ 'critical' : NDS32_CRITICAL */ ++ nested_str = strstr (target_str, "nested"); ++ not_nested_str = strstr (target_str, "not_nested"); ++ ready_nested_str = strstr (target_str, "ready_nested"); ++ critical_str = strstr (target_str, "critical"); ++ ++ /* Note that if no argument is found, ++ use NDS32_NOT_NESTED by default. ++ Also, since 'not_nested' and 'ready_nested' both contains ++ 'nested' string, we check 'nested' with lowest priority. */ ++ if (not_nested_str) ++ nested_type = NDS32_NOT_NESTED; ++ else if (ready_nested_str) ++ nested_type = NDS32_NESTED_READY; ++ else if (nested_str) ++ nested_type = NDS32_NESTED; ++ else if (critical_str) ++ nested_type = NDS32_CRITICAL; ++ else ++ nested_type = NDS32_NOT_NESTED; ++ ++ /* 3. Traverse each id value and set corresponding information. */ ++ id_str = strstr (target_str, "id="); ++ ++ /* If user forgets to assign 'id', issue an error message. */ ++ if (id_str == NULL) ++ error ("require id argument in the string"); ++ /* Extract the value_str first. */ ++ id_str = strtok (id_str, "="); ++ value_str = strtok (NULL, ";"); ++ ++ /* Pick up the first id value token. */ ++ value_str = strtok (value_str, ","); ++ while (value_str != NULL) ++ { ++ int i; ++ i = atoi (value_str); ++ ++ /* For interrupt(0..63), the actual vector number is (9..72). */ ++ i = i + 9; ++ if (i < 9 || i > 72) ++ error ("invalid id value for interrupt attribute"); ++ ++ /* Setup nds32_isr_vectors[] array. */ ++ nds32_isr_vectors[i].category = NDS32_ISR_INTERRUPT; ++ strcpy (nds32_isr_vectors[i].func_name, func_name); ++ nds32_isr_vectors[i].save_reg = save_reg; ++ nds32_isr_vectors[i].nested_type = nested_type; ++ nds32_isr_vectors[i].security_level = s_level; ++ ++ /* Fetch next token. */ ++ value_str = strtok (NULL, ","); ++ } ++ ++ return; ++} ++ ++static void ++nds32_exception_attribute_parse_string (const char *original_str, ++ const char *func_name, ++ unsigned int s_level) ++{ ++ char target_str[100]; ++ enum nds32_isr_save_reg save_reg; ++ enum nds32_isr_nested_type nested_type; ++ ++ char *save_all_regs_str, *save_caller_regs_str; ++ char *nested_str, *not_nested_str, *ready_nested_str, *critical_str; ++ char *id_str, *value_str; ++ ++ /* Copy original string into a character array so that ++ the string APIs can handle it. */ ++ strcpy (target_str, original_str); ++ ++ /* 1. Detect 'save_all_regs' : NDS32_SAVE_ALL ++ 'save_caller_regs' : NDS32_PARTIAL_SAVE */ ++ save_all_regs_str = strstr (target_str, "save_all_regs"); ++ save_caller_regs_str = strstr (target_str, "save_caller_regs"); ++ ++ /* Note that if no argument is found, ++ use NDS32_PARTIAL_SAVE by default. */ ++ if (save_all_regs_str) ++ save_reg = NDS32_SAVE_ALL; ++ else if (save_caller_regs_str) ++ save_reg = NDS32_PARTIAL_SAVE; ++ else ++ save_reg = NDS32_PARTIAL_SAVE; ++ ++ /* 2. Detect 'nested' : NDS32_NESTED ++ 'not_nested' : NDS32_NOT_NESTED ++ 'ready_nested' : NDS32_NESTED_READY ++ 'critical' : NDS32_CRITICAL */ ++ nested_str = strstr (target_str, "nested"); ++ not_nested_str = strstr (target_str, "not_nested"); ++ ready_nested_str = strstr (target_str, "ready_nested"); ++ critical_str = strstr (target_str, "critical"); ++ ++ /* Note that if no argument is found, ++ use NDS32_NOT_NESTED by default. ++ Also, since 'not_nested' and 'ready_nested' both contains ++ 'nested' string, we check 'nested' with lowest priority. */ ++ if (not_nested_str) ++ nested_type = NDS32_NOT_NESTED; ++ else if (ready_nested_str) ++ nested_type = NDS32_NESTED_READY; ++ else if (nested_str) ++ nested_type = NDS32_NESTED; ++ else if (critical_str) ++ nested_type = NDS32_CRITICAL; ++ else ++ nested_type = NDS32_NOT_NESTED; ++ ++ /* 3. Traverse each id value and set corresponding information. */ ++ id_str = strstr (target_str, "id="); ++ ++ /* If user forgets to assign 'id', issue an error message. */ ++ if (id_str == NULL) ++ error ("require id argument in the string"); ++ /* Extract the value_str first. */ ++ id_str = strtok (id_str, "="); ++ value_str = strtok (NULL, ";"); ++ ++ /* Pick up the first id value token. */ ++ value_str = strtok (value_str, ","); ++ while (value_str != NULL) ++ { ++ int i; ++ i = atoi (value_str); ++ ++ /* For exception(1..8), the actual vector number is (1..8). */ ++ if (i < 1 || i > 8) ++ error ("invalid id value for exception attribute"); ++ ++ /* Setup nds32_isr_vectors[] array. */ ++ nds32_isr_vectors[i].category = NDS32_ISR_EXCEPTION; ++ strcpy (nds32_isr_vectors[i].func_name, func_name); ++ nds32_isr_vectors[i].save_reg = save_reg; ++ nds32_isr_vectors[i].nested_type = nested_type; ++ nds32_isr_vectors[i].security_level = s_level; ++ ++ /* Fetch next token. */ ++ value_str = strtok (NULL, ","); ++ } ++ ++ return; ++} ++ ++static void ++nds32_reset_attribute_parse_string (const char *original_str, ++ const char *func_name) ++{ ++ char target_str[100]; ++ char *vectors_str, *nmi_str, *warm_str, *value_str; ++ ++ /* Deal with reset attribute. Its vector number is always 0. */ ++ nds32_isr_vectors[0].category = NDS32_ISR_RESET; ++ ++ ++ /* 1. Parse 'vectors=XXXX'. */ ++ ++ /* Copy original string into a character array so that ++ the string APIs can handle it. */ ++ strcpy (target_str, original_str); ++ vectors_str = strstr (target_str, "vectors="); ++ /* The total vectors = interrupt + exception numbers + reset. ++ There are 8 exception and 1 reset in nds32 architecture. ++ If user forgets to assign 'vectors', user default 16 interrupts. */ ++ if (vectors_str != NULL) ++ { ++ /* Extract the value_str. */ ++ vectors_str = strtok (vectors_str, "="); ++ value_str = strtok (NULL, ";"); ++ nds32_isr_vectors[0].total_n_vectors = atoi (value_str) + 8 + 1; ++ } ++ else ++ nds32_isr_vectors[0].total_n_vectors = 16 + 8 + 1; ++ strcpy (nds32_isr_vectors[0].func_name, func_name); ++ ++ ++ /* 2. Parse 'nmi_func=YYYY'. */ ++ ++ /* Copy original string into a character array so that ++ the string APIs can handle it. */ ++ strcpy (target_str, original_str); ++ nmi_str = strstr (target_str, "nmi_func="); ++ if (nmi_str != NULL) ++ { ++ /* Extract the value_str. */ ++ nmi_str = strtok (nmi_str, "="); ++ value_str = strtok (NULL, ";"); ++ strcpy (nds32_isr_vectors[0].nmi_name, value_str); ++ } ++ ++ /* 3. Parse 'warm_func=ZZZZ'. */ ++ ++ /* Copy original string into a character array so that ++ the string APIs can handle it. */ ++ strcpy (target_str, original_str); ++ warm_str = strstr (target_str, "warm_func="); ++ if (warm_str != NULL) ++ { ++ /* Extract the value_str. */ ++ warm_str = strtok (warm_str, "="); ++ value_str = strtok (NULL, ";"); ++ strcpy (nds32_isr_vectors[0].warm_name, value_str); ++ } ++ ++ return; ++} ++/* ------------------------------------------------------------- */ + + /* A helper function to emit section head template. */ + static void +@@ -79,6 +332,15 @@ + char section_name[100]; + char symbol_name[100]; + ++ /* A critical isr does not need jump table section because ++ its behavior is not performed by two-level handler. */ ++ if (nds32_isr_vectors[vector_id].nested_type == NDS32_CRITICAL) ++ { ++ fprintf (asm_out_file, "\t! The vector %02d is a critical isr !\n", ++ vector_id); ++ return; ++ } ++ + /* Prepare jmptbl section and symbol name. */ + snprintf (section_name, sizeof (section_name), + ".nds32_jmptbl.%02d", vector_id); +@@ -99,7 +361,6 @@ + const char *c_str = "CATEGORY"; + const char *sr_str = "SR"; + const char *nt_str = "NT"; +- const char *vs_str = "VS"; + char first_level_handler_name[100]; + char section_name[100]; + char symbol_name[100]; +@@ -147,30 +408,47 @@ + case NDS32_NESTED_READY: + nt_str = "nr"; + break; ++ case NDS32_CRITICAL: ++ /* The critical isr is not performed by two-level handler. */ ++ nt_str = ""; ++ break; + } + +- /* Currently we have 4-byte or 16-byte size for each vector. +- If it is 4-byte, the first level handler name has suffix string "_4b". */ +- vs_str = (nds32_isr_vector_size == 4) ? "_4b" : ""; +- + /* Now we can create first level handler name. */ +- snprintf (first_level_handler_name, sizeof (first_level_handler_name), +- "_nds32_%s_%s_%s%s", c_str, sr_str, nt_str, vs_str); ++ if (nds32_isr_vectors[vector_id].security_level == 0) ++ { ++ /* For security level 0, use normal first level handler name. */ ++ snprintf (first_level_handler_name, sizeof (first_level_handler_name), ++ "_nds32_%s_%s_%s", c_str, sr_str, nt_str); ++ } ++ else ++ { ++ /* For security level 1-3, use corresponding spl_1, spl_2, or spl_3. */ ++ snprintf (first_level_handler_name, sizeof (first_level_handler_name), ++ "_nds32_spl_%d", nds32_isr_vectors[vector_id].security_level); ++ } + + /* Prepare vector section and symbol name. */ + snprintf (section_name, sizeof (section_name), + ".nds32_vector.%02d", vector_id); + snprintf (symbol_name, sizeof (symbol_name), +- "_nds32_vector_%02d%s", vector_id, vs_str); ++ "_nds32_vector_%02d", vector_id); + + + /* Everything is ready. We can start emit vector section content. */ + nds32_emit_section_head_template (section_name, symbol_name, + floor_log2 (nds32_isr_vector_size), false); + +- /* According to the vector size, the instructions in the +- vector section may be different. */ +- if (nds32_isr_vector_size == 4) ++ /* First we check if it is a critical isr. ++ If so, jump to user handler directly; otherwise, the instructions ++ in the vector section may be different according to the vector size. */ ++ if (nds32_isr_vectors[vector_id].nested_type == NDS32_CRITICAL) ++ { ++ /* This block is for critical isr. Jump to user handler directly. */ ++ fprintf (asm_out_file, "\tj\t%s ! jump to user handler directly\n", ++ nds32_isr_vectors[vector_id].func_name); ++ } ++ else if (nds32_isr_vector_size == 4) + { + /* This block is for 4-byte vector size. + Hardware $VID support is necessary and only one instruction +@@ -239,13 +517,11 @@ + { + unsigned int i; + unsigned int total_n_vectors; +- const char *vs_str; + char reset_handler_name[100]; + char section_name[100]; + char symbol_name[100]; + + total_n_vectors = nds32_isr_vectors[0].total_n_vectors; +- vs_str = (nds32_isr_vector_size == 4) ? "_4b" : ""; + + fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - BEGIN !\n"); + +@@ -261,7 +537,7 @@ + /* Emit vector references. */ + fprintf (asm_out_file, "\t ! references to vector section entries\n"); + for (i = 0; i < total_n_vectors; i++) +- fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d%s\n", i, vs_str); ++ fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d\n", i); + + /* Emit jmptbl_00 section. */ + snprintf (section_name, sizeof (section_name), ".nds32_jmptbl.00"); +@@ -275,9 +551,9 @@ + + /* Emit vector_00 section. */ + snprintf (section_name, sizeof (section_name), ".nds32_vector.00"); +- snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00%s", vs_str); ++ snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00"); + snprintf (reset_handler_name, sizeof (reset_handler_name), +- "_nds32_reset%s", vs_str); ++ "_nds32_reset"); + + fprintf (asm_out_file, "\t! ....................................\n"); + nds32_emit_section_head_template (section_name, symbol_name, +@@ -323,12 +599,12 @@ + nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs) + { + int save_all_p, partial_save_p; +- int nested_p, not_nested_p, nested_ready_p; ++ int nested_p, not_nested_p, nested_ready_p, critical_p; + int intr_p, excp_p, reset_p; + + /* Initialize variables. */ + save_all_p = partial_save_p = 0; +- nested_p = not_nested_p = nested_ready_p = 0; ++ nested_p = not_nested_p = nested_ready_p = critical_p = 0; + intr_p = excp_p = reset_p = 0; + + /* We must check at MOST one attribute to set save-reg. */ +@@ -347,8 +623,10 @@ + not_nested_p = 1; + if (lookup_attribute ("nested_ready", func_attrs)) + nested_ready_p = 1; ++ if (lookup_attribute ("critical", func_attrs)) ++ critical_p = 1; + +- if ((nested_p + not_nested_p + nested_ready_p) > 1) ++ if ((nested_p + not_nested_p + nested_ready_p + critical_p) > 1) + error ("multiple nested types attributes to function %qD", func_decl); + + /* We must check at MOST one attribute to +@@ -362,6 +640,17 @@ + + if ((intr_p + excp_p + reset_p) > 1) + error ("multiple interrupt attributes to function %qD", func_decl); ++ ++ /* Do not allow isr attributes under linux toolchain. */ ++ if (TARGET_LINUX_ABI && intr_p) ++ error ("cannot use interrupt attributes to function %qD " ++ "under linux toolchain", func_decl); ++ if (TARGET_LINUX_ABI && excp_p) ++ error ("cannot use exception attributes to function %qD " ++ "under linux toolchain", func_decl); ++ if (TARGET_LINUX_ABI && reset_p) ++ error ("cannot use reset attributes to function %qD " ++ "under linux toolchain", func_decl); + } + + /* Function to construct isr vectors information array. +@@ -373,15 +662,21 @@ + const char *func_name) + { + tree save_all, partial_save; +- tree nested, not_nested, nested_ready; ++ tree nested, not_nested, nested_ready, critical; + tree intr, excp, reset; + ++ tree secure; ++ tree security_level_list; ++ tree security_level; ++ unsigned int s_level; ++ + save_all = lookup_attribute ("save_all", func_attrs); + partial_save = lookup_attribute ("partial_save", func_attrs); + + nested = lookup_attribute ("nested", func_attrs); + not_nested = lookup_attribute ("not_nested", func_attrs); + nested_ready = lookup_attribute ("nested_ready", func_attrs); ++ critical = lookup_attribute ("critical", func_attrs); + + intr = lookup_attribute ("interrupt", func_attrs); + excp = lookup_attribute ("exception", func_attrs); +@@ -391,6 +686,63 @@ + if (!intr && !excp && !reset) + return; + ++ /* At first, we need to retrieve security level. */ ++ secure = lookup_attribute ("secure", func_attrs); ++ if (secure != NULL) ++ { ++ security_level_list = TREE_VALUE (secure); ++ security_level = TREE_VALUE (security_level_list); ++ s_level = TREE_INT_CST_LOW (security_level); ++ } ++ else ++ { ++ /* If there is no secure attribute, the security level is set by ++ nds32_isr_secure_level, which is controlled by -misr-secure=X option. ++ By default nds32_isr_secure_level should be 0. */ ++ s_level = nds32_isr_secure_level; ++ } ++ ++ /* ------------------------------------------------------------- */ ++ /* FIXME: ++ FOR BACKWARD COMPATIBILITY, we need to support following patterns: ++ ++ __attribute__((interrupt("XXX;YYY;id=ZZZ"))) ++ __attribute__((exception("XXX;YYY;id=ZZZ"))) ++ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ"))) ++ ++ If interrupt/exception/reset appears and its argument is a ++ STRING_CST, we will parse string with some auxiliary functions ++ which set necessary isr information in the nds32_isr_vectors[] array. ++ After that, we can return immediately to avoid new-syntax isr ++ information construction. */ ++ if (intr != NULL_TREE ++ && TREE_CODE (TREE_VALUE (TREE_VALUE (intr))) == STRING_CST) ++ { ++ tree string_arg = TREE_VALUE (TREE_VALUE (intr)); ++ nds32_interrupt_attribute_parse_string (TREE_STRING_POINTER (string_arg), ++ func_name, ++ s_level); ++ return; ++ } ++ if (excp != NULL_TREE ++ && TREE_CODE (TREE_VALUE (TREE_VALUE (excp))) == STRING_CST) ++ { ++ tree string_arg = TREE_VALUE (TREE_VALUE (excp)); ++ nds32_exception_attribute_parse_string (TREE_STRING_POINTER (string_arg), ++ func_name, ++ s_level); ++ return; ++ } ++ if (reset != NULL_TREE ++ && TREE_CODE (TREE_VALUE (TREE_VALUE (reset))) == STRING_CST) ++ { ++ tree string_arg = TREE_VALUE (TREE_VALUE (reset)); ++ nds32_reset_attribute_parse_string (TREE_STRING_POINTER (string_arg), ++ func_name); ++ return; ++ } ++ /* ------------------------------------------------------------- */ ++ + /* If we are here, either we have interrupt/exception, + or reset attribute. */ + if (intr || excp) +@@ -417,6 +769,9 @@ + /* Add vector_number_offset to get actual vector number. */ + vector_id = TREE_INT_CST_LOW (id) + vector_number_offset; + ++ /* Set security level. */ ++ nds32_isr_vectors[vector_id].security_level = s_level; ++ + /* Enable corresponding vector and set function name. */ + nds32_isr_vectors[vector_id].category = (intr) + ? (NDS32_ISR_INTERRUPT) +@@ -436,6 +791,8 @@ + nds32_isr_vectors[vector_id].nested_type = NDS32_NOT_NESTED; + else if (nested_ready) + nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED_READY; ++ else if (critical) ++ nds32_isr_vectors[vector_id].nested_type = NDS32_CRITICAL; + + /* Advance to next id. */ + id_list = TREE_CHAIN (id_list); +@@ -492,7 +849,6 @@ + } + } + +-/* A helper function to handle isr stuff at the beginning of asm file. */ + void + nds32_asm_file_start_for_isr (void) + { +@@ -505,15 +861,14 @@ + strcpy (nds32_isr_vectors[i].func_name, ""); + nds32_isr_vectors[i].save_reg = NDS32_PARTIAL_SAVE; + nds32_isr_vectors[i].nested_type = NDS32_NOT_NESTED; ++ nds32_isr_vectors[i].security_level = 0; + nds32_isr_vectors[i].total_n_vectors = 0; + strcpy (nds32_isr_vectors[i].nmi_name, ""); + strcpy (nds32_isr_vectors[i].warm_name, ""); + } + } + +-/* A helper function to handle isr stuff at the end of asm file. */ +-void +-nds32_asm_file_end_for_isr (void) ++void nds32_asm_file_end_for_isr (void) + { + int i; + +@@ -547,6 +902,8 @@ + /* Found one vector which is interupt or exception. + Output its jmptbl and vector section content. */ + fprintf (asm_out_file, "\t! interrupt/exception vector %02d\n", i); ++ fprintf (asm_out_file, "\t! security level: %d\n", ++ nds32_isr_vectors[i].security_level); + fprintf (asm_out_file, "\t! ------------------------------------\n"); + nds32_emit_isr_jmptbl_section (i); + fprintf (asm_out_file, "\t! ....................................\n"); +@@ -580,4 +937,65 @@ + || (t_reset != NULL_TREE)); + } + +-/* ------------------------------------------------------------------------ */ ++/* Return true if FUNC is a isr function with critical attribute. */ ++bool ++nds32_isr_function_critical_p (tree func) ++{ ++ tree t_intr; ++ tree t_excp; ++ tree t_critical; ++ ++ tree attrs; ++ ++ if (TREE_CODE (func) != FUNCTION_DECL) ++ abort (); ++ ++ attrs = DECL_ATTRIBUTES (func); ++ ++ t_intr = lookup_attribute ("interrupt", attrs); ++ t_excp = lookup_attribute ("exception", attrs); ++ ++ t_critical = lookup_attribute ("critical", attrs); ++ ++ /* If both interrupt and exception attribute does not appear, ++ we can return false immediately. */ ++ if ((t_intr == NULL_TREE) && (t_excp == NULL_TREE)) ++ return false; ++ ++ /* Here we can guarantee either interrupt or ecxception attribute ++ does exist, so further check critical attribute. ++ If it also appears, we can return true. */ ++ if (t_critical != NULL_TREE) ++ return true; ++ ++ /* ------------------------------------------------------------- */ ++ /* FIXME: ++ FOR BACKWARD COMPATIBILITY, we need to handle string type. ++ If the string 'critical' appears in the interrupt/exception ++ string argument, we can return true. */ ++ if (t_intr != NULL_TREE || t_excp != NULL_TREE) ++ { ++ char target_str[100]; ++ char *critical_str; ++ tree t_check; ++ tree string_arg; ++ ++ t_check = t_intr ? t_intr : t_excp; ++ if (TREE_CODE (TREE_VALUE (TREE_VALUE (t_check))) == STRING_CST) ++ { ++ string_arg = TREE_VALUE (TREE_VALUE (t_check)); ++ strcpy (target_str, TREE_STRING_POINTER (string_arg)); ++ critical_str = strstr (target_str, "critical"); ++ ++ /* Found 'critical' string, so return true. */ ++ if (critical_str) ++ return true; ++ } ++ } ++ /* ------------------------------------------------------------- */ ++ ++ /* Other cases, this isr function is not critical type. */ ++ return false; ++} ++ ++/* ------------------------------------------------------------- */ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32_isr.h gcc-8.2.0/gcc/config/nds32/nds32_isr.h +--- gcc-8.2.0.orig/gcc/config/nds32/nds32_isr.h 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32_isr.h 2019-01-25 15:38:32.833242671 +0100 +@@ -0,0 +1,526 @@ ++/* Intrinsic definitions 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. ++ ++ 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 ++ . */ ++ ++#ifndef _NDS32_ISR_H ++#define _NDS32_ISR_H ++ ++/* Attribute of a interrupt or exception handler: ++ ++ NDS32_READY_NESTED: This handler is interruptible if user re-enable GIE bit. ++ NDS32_NESTED : This handler is interruptible. This is not suitable ++ exception handler. ++ NDS32_NOT_NESTED : This handler is NOT interruptible. Users have to do ++ some work if nested is wanted ++ NDS32_CRITICAL : This handler is critical ISR, which means it is small ++ and efficient. */ ++#define NDS32_READY_NESTED 0 ++#define NDS32_NESTED 1 ++#define NDS32_NOT_NESTED 2 ++#define NDS32_CRITICAL 3 ++ ++/* Attribute of a interrupt or exception handler: ++ ++ NDS32_SAVE_ALL_REGS : Save all registers in a table. ++ NDS32_SAVE_PARTIAL_REGS: Save partial registers. */ ++#define NDS32_SAVE_CALLER_REGS 0 ++#define NDS32_SAVE_ALL_REGS 1 ++ ++/* There are two version of Register table for interrupt and exception handler, ++ one for 16-register CPU the other for 32-register CPU. These structures are ++ used for context switching or system call handling. The address of this ++ data can be get from the input argument of the handler functions. ++ ++ For system call handling, r0 to r5 are used to pass arguments. If more ++ arguments are used they are put into the stack and its starting address is ++ in sp. Return value of system call can be put into r0 and r1 upon exit from ++ system call handler. System call ID is in a system register and it can be ++ fetched via intrinsic function. For more information please read ABI and ++ other related documents. ++ ++ For context switching, at least 2 values need to saved in kernel. One is ++ IPC and the other is the stack address of current task. Use intrinsic ++ function to get IPC and the input argument of the handler functions + 8 to ++ get stack address of current task. To do context switching, you replace ++ new_sp with the stack address of new task and replace IPC system register ++ with IPC of new task, then, just return from handler. The context switching ++ will happen. */ ++ ++/* Register table for exception handler; 32-register version. */ ++typedef struct ++{ ++ int r0; ++ int r1; ++ int r2; ++ int r3; ++ int r4; ++ int r5; ++ int r6; ++ int r7; ++ int r8; ++ int r9; ++ int r10; ++ int r11; ++ int r12; ++ int r13; ++ int r14; ++ int r15; ++ int r16; ++ int r17; ++ int r18; ++ int r19; ++ int r20; ++ int r21; ++ int r22; ++ int r23; ++ int r24; ++ int r25; ++ int r26; ++ int r27; ++ int fp; ++ int gp; ++ int lp; ++ int sp; ++} NDS32_GPR32; ++ ++/* Register table for exception handler; 16-register version. */ ++typedef struct ++{ ++ int r0; ++ int r1; ++ int r2; ++ int r3; ++ int r4; ++ int r5; ++ int r6; ++ int r7; ++ int r8; ++ int r9; ++ int r10; ++ int r15; ++ int fp; ++ int gp; ++ int lp; ++ int sp; ++} NDS32_GPR16; ++ ++ ++/* Use NDS32_REG32_TAB or NDS32_REG16_TAB in your program to ++ access register table. */ ++typedef struct ++{ ++ union ++ { ++ int reg_a[32] ; ++ NDS32_GPR32 reg_s ; ++ } u ; ++} NDS32_REG32_TAB; ++ ++typedef struct ++{ ++ union ++ { ++ int reg_a[16] ; ++ NDS32_GPR16 reg_s ; ++ } u ; ++} NDS32_REG16_TAB; ++ ++typedef struct ++{ ++ int d0lo; ++ int d0hi; ++ int d1lo; ++ int d1hi; ++} NDS32_DX_TAB; ++ ++typedef struct ++{ ++#ifdef __NDS32_EB__ ++ float fsr0; ++ float fsr1; ++ float fsr2; ++ float fsr3; ++ float fsr4; ++ float fsr5; ++ float fsr6; ++ float fsr7; ++#else ++ float fsr1; ++ float fsr0; ++ float fsr3; ++ float fsr2; ++ float fsr5; ++ float fsr4; ++ float fsr7; ++ float fsr6; ++#endif ++} NDS32_FSR8; ++ ++typedef struct ++{ ++ double dsr0; ++ double dsr1; ++ double dsr2; ++ double dsr3; ++} NDS32_DSR4; ++ ++typedef struct ++{ ++#ifdef __NDS32_EB__ ++ float fsr0; ++ float fsr1; ++ float fsr2; ++ float fsr3; ++ float fsr4; ++ float fsr5; ++ float fsr6; ++ float fsr7; ++ float fsr8; ++ float fsr9; ++ float fsr10; ++ float fsr11; ++ float fsr12; ++ float fsr13; ++ float fsr14; ++ float fsr15; ++#else ++ float fsr1; ++ float fsr0; ++ float fsr3; ++ float fsr2; ++ float fsr5; ++ float fsr4; ++ float fsr7; ++ float fsr6; ++ float fsr9; ++ float fsr8; ++ float fsr11; ++ float fsr10; ++ float fsr13; ++ float fsr12; ++ float fsr15; ++ float fsr14; ++#endif ++} NDS32_FSR16; ++ ++typedef struct ++{ ++ double dsr0; ++ double dsr1; ++ double dsr2; ++ double dsr3; ++ double dsr4; ++ double dsr5; ++ double dsr6; ++ double dsr7; ++} NDS32_DSR8; ++ ++typedef struct ++{ ++#ifdef __NDS32_EB__ ++ float fsr0; ++ float fsr1; ++ float fsr2; ++ float fsr3; ++ float fsr4; ++ float fsr5; ++ float fsr6; ++ float fsr7; ++ float fsr8; ++ float fsr9; ++ float fsr10; ++ float fsr11; ++ float fsr12; ++ float fsr13; ++ float fsr14; ++ float fsr15; ++ float fsr16; ++ float fsr17; ++ float fsr18; ++ float fsr19; ++ float fsr20; ++ float fsr21; ++ float fsr22; ++ float fsr23; ++ float fsr24; ++ float fsr25; ++ float fsr26; ++ float fsr27; ++ float fsr28; ++ float fsr29; ++ float fsr30; ++ float fsr31; ++#else ++ float fsr1; ++ float fsr0; ++ float fsr3; ++ float fsr2; ++ float fsr5; ++ float fsr4; ++ float fsr7; ++ float fsr6; ++ float fsr9; ++ float fsr8; ++ float fsr11; ++ float fsr10; ++ float fsr13; ++ float fsr12; ++ float fsr15; ++ float fsr14; ++ float fsr17; ++ float fsr16; ++ float fsr19; ++ float fsr18; ++ float fsr21; ++ float fsr20; ++ float fsr23; ++ float fsr22; ++ float fsr25; ++ float fsr24; ++ float fsr27; ++ float fsr26; ++ float fsr29; ++ float fsr28; ++ float fsr31; ++ float fsr30; ++#endif ++} NDS32_FSR32; ++ ++typedef struct ++{ ++ double dsr0; ++ double dsr1; ++ double dsr2; ++ double dsr3; ++ double dsr4; ++ double dsr5; ++ double dsr6; ++ double dsr7; ++ double dsr8; ++ double dsr9; ++ double dsr10; ++ double dsr11; ++ double dsr12; ++ double dsr13; ++ double dsr14; ++ double dsr15; ++} NDS32_DSR16; ++ ++typedef struct ++{ ++ double dsr0; ++ double dsr1; ++ double dsr2; ++ double dsr3; ++ double dsr4; ++ double dsr5; ++ double dsr6; ++ double dsr7; ++ double dsr8; ++ double dsr9; ++ double dsr10; ++ double dsr11; ++ double dsr12; ++ double dsr13; ++ double dsr14; ++ double dsr15; ++ double dsr16; ++ double dsr17; ++ double dsr18; ++ double dsr19; ++ double dsr20; ++ double dsr21; ++ double dsr22; ++ double dsr23; ++ double dsr24; ++ double dsr25; ++ double dsr26; ++ double dsr27; ++ double dsr28; ++ double dsr29; ++ double dsr30; ++ double dsr31; ++} NDS32_DSR32; ++ ++typedef struct ++{ ++ union ++ { ++ NDS32_FSR8 fsr_s ; ++ NDS32_DSR4 dsr_s ; ++ } u ; ++} NDS32_FPU8_TAB; ++ ++typedef struct ++{ ++ union ++ { ++ NDS32_FSR16 fsr_s ; ++ NDS32_DSR8 dsr_s ; ++ } u ; ++} NDS32_FPU16_TAB; ++ ++typedef struct ++{ ++ union ++ { ++ NDS32_FSR32 fsr_s ; ++ NDS32_DSR16 dsr_s ; ++ } u ; ++} NDS32_FPU32_TAB; ++ ++typedef struct ++{ ++ union ++ { ++ NDS32_FSR32 fsr_s ; ++ NDS32_DSR32 dsr_s ; ++ } u ; ++} NDS32_FPU64_TAB; ++ ++typedef struct ++{ ++ int ipc; ++ int ipsw; ++#if defined(NDS32_EXT_FPU_CONFIG_0) ++ NDS32_FPU8_TAB fpr; ++#elif defined(NDS32_EXT_FPU_CONFIG_1) ++ NDS32_FPU16_TAB fpr; ++#elif defined(NDS32_EXT_FPU_CONFIG_2) ++ NDS32_FPU32_TAB fpr; ++#elif defined(NDS32_EXT_FPU_CONFIG_3) ++ NDS32_FPU64_TAB fpr; ++#endif ++#if __NDS32_DX_REGS__ ++ NDS32_DX_TAB dxr; ++#endif ++#if __NDS32_EXT_IFC__ ++ int ifc_lp; ++ int filler; ++#endif ++#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS ++ NDS32_REG16_TAB gpr; ++#else ++ NDS32_REG32_TAB gpr; ++#endif ++} NDS32_CONTEXT; ++ ++/* Predefined Vector Definition. ++ ++ For IVIC Mode: 9 to 14 are for hardware interrupt ++ and 15 is for software interrupt. ++ For EVIC Mode: 9 to 72 are for hardware interrupt ++ and software interrupt can be routed to any one of them. ++ ++ You may want to define your hardware interrupts in the following way ++ for easy maintainance. ++ ++ IVIC mode: ++ #define MY_HW_IVIC_TIMER NDS32_VECTOR_INTERRUPT_HW0 + 1 ++ #define MY_HW_IVIC_USB NDS32_VECTOR_INTERRUPT_HW0 + 3 ++ EVIC mode: ++ #define MY_HW_EVIC_DMA NDS32_VECTOR_INTERRUPT_HW0 + 2 ++ #define MY_HW_EVIC_SWI NDS32_VECTOR_INTERRUPT_HW0 + 10 */ ++#define NDS32_VECTOR_RESET 0 ++#define NDS32_VECTOR_TLB_FILL 1 ++#define NDS32_VECTOR_PTE_NOT_PRESENT 2 ++#define NDS32_VECTOR_TLB_MISC 3 ++#define NDS32_VECTOR_TLB_VLPT_MISS 4 ++#define NDS32_VECTOR_MACHINE_ERROR 5 ++#define NDS32_VECTOR_DEBUG_RELATED 6 ++#define NDS32_VECTOR_GENERAL_EXCEPTION 7 ++#define NDS32_VECTOR_SYSCALL 8 ++#define NDS32_VECTOR_INTERRUPT_HW0 9 ++#define NDS32_VECTOR_INTERRUPT_HW1 10 ++#define NDS32_VECTOR_INTERRUPT_HW2 11 ++#define NDS32_VECTOR_INTERRUPT_HW3 12 ++#define NDS32_VECTOR_INTERRUPT_HW4 13 ++#define NDS32_VECTOR_INTERRUPT_HW5 14 ++#define NDS32_VECTOR_INTERRUPT_HW6 15 ++#define NDS32_VECTOR_SWI 15 /* THIS IS FOR IVIC MODE ONLY */ ++#define NDS32_VECTOR_INTERRUPT_HW7 16 ++#define NDS32_VECTOR_INTERRUPT_HW8 17 ++#define NDS32_VECTOR_INTERRUPT_HW9 18 ++#define NDS32_VECTOR_INTERRUPT_HW10 19 ++#define NDS32_VECTOR_INTERRUPT_HW11 20 ++#define NDS32_VECTOR_INTERRUPT_HW12 21 ++#define NDS32_VECTOR_INTERRUPT_HW13 22 ++#define NDS32_VECTOR_INTERRUPT_HW14 23 ++#define NDS32_VECTOR_INTERRUPT_HW15 24 ++#define NDS32_VECTOR_INTERRUPT_HW16 25 ++#define NDS32_VECTOR_INTERRUPT_HW17 26 ++#define NDS32_VECTOR_INTERRUPT_HW18 27 ++#define NDS32_VECTOR_INTERRUPT_HW19 28 ++#define NDS32_VECTOR_INTERRUPT_HW20 29 ++#define NDS32_VECTOR_INTERRUPT_HW21 30 ++#define NDS32_VECTOR_INTERRUPT_HW22 31 ++#define NDS32_VECTOR_INTERRUPT_HW23 32 ++#define NDS32_VECTOR_INTERRUPT_HW24 33 ++#define NDS32_VECTOR_INTERRUPT_HW25 34 ++#define NDS32_VECTOR_INTERRUPT_HW26 35 ++#define NDS32_VECTOR_INTERRUPT_HW27 36 ++#define NDS32_VECTOR_INTERRUPT_HW28 37 ++#define NDS32_VECTOR_INTERRUPT_HW29 38 ++#define NDS32_VECTOR_INTERRUPT_HW30 39 ++#define NDS32_VECTOR_INTERRUPT_HW31 40 ++#define NDS32_VECTOR_INTERRUPT_HW32 41 ++#define NDS32_VECTOR_INTERRUPT_HW33 42 ++#define NDS32_VECTOR_INTERRUPT_HW34 43 ++#define NDS32_VECTOR_INTERRUPT_HW35 44 ++#define NDS32_VECTOR_INTERRUPT_HW36 45 ++#define NDS32_VECTOR_INTERRUPT_HW37 46 ++#define NDS32_VECTOR_INTERRUPT_HW38 47 ++#define NDS32_VECTOR_INTERRUPT_HW39 48 ++#define NDS32_VECTOR_INTERRUPT_HW40 49 ++#define NDS32_VECTOR_INTERRUPT_HW41 50 ++#define NDS32_VECTOR_INTERRUPT_HW42 51 ++#define NDS32_VECTOR_INTERRUPT_HW43 52 ++#define NDS32_VECTOR_INTERRUPT_HW44 53 ++#define NDS32_VECTOR_INTERRUPT_HW45 54 ++#define NDS32_VECTOR_INTERRUPT_HW46 55 ++#define NDS32_VECTOR_INTERRUPT_HW47 56 ++#define NDS32_VECTOR_INTERRUPT_HW48 57 ++#define NDS32_VECTOR_INTERRUPT_HW49 58 ++#define NDS32_VECTOR_INTERRUPT_HW50 59 ++#define NDS32_VECTOR_INTERRUPT_HW51 60 ++#define NDS32_VECTOR_INTERRUPT_HW52 61 ++#define NDS32_VECTOR_INTERRUPT_HW53 62 ++#define NDS32_VECTOR_INTERRUPT_HW54 63 ++#define NDS32_VECTOR_INTERRUPT_HW55 64 ++#define NDS32_VECTOR_INTERRUPT_HW56 65 ++#define NDS32_VECTOR_INTERRUPT_HW57 66 ++#define NDS32_VECTOR_INTERRUPT_HW58 67 ++#define NDS32_VECTOR_INTERRUPT_HW59 68 ++#define NDS32_VECTOR_INTERRUPT_HW60 69 ++#define NDS32_VECTOR_INTERRUPT_HW61 70 ++#define NDS32_VECTOR_INTERRUPT_HW62 71 ++#define NDS32_VECTOR_INTERRUPT_HW63 72 ++ ++#define NDS32ATTR_RESET(option) __attribute__((reset(option))) ++#define NDS32ATTR_EXCEPT(type) __attribute__((exception(type))) ++#define NDS32ATTR_EXCEPTION(type) __attribute__((exception(type))) ++#define NDS32ATTR_INTERRUPT(type) __attribute__((interrupt(type))) ++#define NDS32ATTR_ISR(type) __attribute__((interrupt(type))) ++ ++#endif /* nds32_isr.h */ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-linux.opt gcc-8.2.0/gcc/config/nds32/nds32-linux.opt +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-linux.opt 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-linux.opt 2019-01-25 15:38:32.829242659 +0100 +@@ -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) +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32.md gcc-8.2.0/gcc/config/nds32/nds32.md +--- gcc-8.2.0.orig/gcc/config/nds32/nds32.md 2018-04-08 11:21:30.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32.md 2019-01-25 15:38:32.833242671 +0100 +@@ -56,24 +56,29 @@ + ;; ------------------------------------------------------------------------ + + ;; CPU pipeline model. +-(define_attr "pipeline_model" "n7,n8,e8,n9,simple" ++(define_attr "pipeline_model" "n7,n8,e8,n9,n10,graywolf,n13,simple" + (const + (cond [(match_test "nds32_cpu_option == CPU_N7") (const_string "n7") + (match_test "nds32_cpu_option == CPU_E8") (const_string "e8") + (match_test "nds32_cpu_option == CPU_N6 || nds32_cpu_option == CPU_N8") (const_string "n8") + (match_test "nds32_cpu_option == CPU_N9") (const_string "n9") ++ (match_test "nds32_cpu_option == CPU_N10") (const_string "n10") ++ (match_test "nds32_cpu_option == CPU_GRAYWOLF") (const_string "graywolf") ++ (match_test "nds32_cpu_option == CPU_N12") (const_string "n13") ++ (match_test "nds32_cpu_option == CPU_N13") (const_string "n13") + (match_test "nds32_cpu_option == CPU_SIMPLE") (const_string "simple")] + (const_string "n9")))) + + ;; Insn type, it is used to default other attribute values. + (define_attr "type" + "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,pbsad,pbsada,mul,mac,div,branch,mmu,misc,\ +- falu,fmuls,fmuld,fmacs,fmacd,fdivs,fdivd,fsqrts,fsqrtd,fcmp,fabs,fcpy,fcmov,fmfsr,fmfdr,fmtsr,fmtdr,fload,fstore" ++ falu,fmuls,fmuld,fmacs,fmacd,fdivs,fdivd,fsqrts,fsqrtd,fcmp,fabs,fcpy,fcmov,fmfsr,fmfdr,fmtsr,fmtdr,fload,fstore,\ ++ dalu,dalu64,daluround,dcmp,dclip,dmul,dmac,dinsb,dpack,dbpick,dwext" + (const_string "unknown")) + + ;; Insn sub-type + (define_attr "subtype" +- "simple,shift" ++ "simple,shift,saturation" + (const_string "simple")) + + ;; Length, in bytes, default is 4-bytes. +@@ -133,6 +138,7 @@ + + ;; ---------------------------------------------------------------------------- + ++(include "nds32-dspext.md") + + ;; Move instructions. + +@@ -209,6 +215,27 @@ + low12_int)); + DONE; + } ++ ++ if ((REG_P (operands[0]) || GET_CODE (operands[0]) == SUBREG) ++ && SYMBOLIC_CONST_P (operands[1])) ++ { ++ if (TARGET_ICT_MODEL_LARGE ++ && nds32_indirect_call_referenced_p (operands[1])) ++ { ++ nds32_expand_ict_move (operands); ++ DONE; ++ } ++ else if (nds32_tls_referenced_p (operands [1])) ++ { ++ nds32_expand_tls_move (operands); ++ DONE; ++ } ++ else if (flag_pic) ++ { ++ nds32_expand_pic_move (operands); ++ DONE; ++ } ++ } + }) + + (define_insn "*mov" +@@ -271,8 +298,8 @@ + ;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF + ;; are able to match such instruction template. + (define_insn "move_addr" +- [(set (match_operand:SI 0 "register_operand" "=l, r") +- (match_operand:SI 1 "nds32_symbolic_operand" " i, i"))] ++ [(set (match_operand:SI 0 "nds32_general_register_operand" "=l, r") ++ (match_operand:SI 1 "nds32_nonunspec_symbolic_operand" " i, i"))] + "" + "la\t%0, %1" + [(set_attr "type" "alu") +@@ -351,13 +378,58 @@ + + + ;; ---------------------------------------------------------------------------- ++(define_expand "extv" ++ [(set (match_operand 0 "register_operand" "") ++ (sign_extract (match_operand 1 "nonimmediate_operand" "") ++ (match_operand 2 "const_int_operand" "") ++ (match_operand 3 "const_int_operand" "")))] ++ "" ++{ ++ enum nds32_expand_result_type result = nds32_expand_extv (operands); ++ switch (result) ++ { ++ case EXPAND_DONE: ++ DONE; ++ break; ++ case EXPAND_FAIL: ++ FAIL; ++ break; ++ case EXPAND_CREATE_TEMPLATE: ++ break; ++ default: ++ gcc_unreachable (); ++ } ++}) ++ ++(define_expand "insv" ++ [(set (zero_extract (match_operand 0 "nonimmediate_operand" "") ++ (match_operand 1 "const_int_operand" "") ++ (match_operand 2 "const_int_operand" "")) ++ (match_operand 3 "register_operand" ""))] ++ "" ++{ ++ enum nds32_expand_result_type result = nds32_expand_insv (operands); ++ switch (result) ++ { ++ case EXPAND_DONE: ++ DONE; ++ break; ++ case EXPAND_FAIL: ++ FAIL; ++ break; ++ case EXPAND_CREATE_TEMPLATE: ++ break; ++ default: ++ gcc_unreachable (); ++ } ++}) + + ;; Arithmetic instructions. + + (define_insn "addsi3" + [(set (match_operand:SI 0 "register_operand" "= d, l, d, l, d, l, k, l, r, r") + (plus:SI (match_operand:SI 1 "register_operand" "% 0, l, 0, l, 0, l, 0, k, r, r") +- (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,Iu06, Is15, r")))] ++ (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,IU06, Is15, r")))] + "" + { + switch (which_alternative) +@@ -1428,11 +1500,30 @@ + (clobber (reg:SI LP_REGNUM)) + (clobber (reg:SI TA_REGNUM))])] + "" +- "" ++ { ++ rtx insn; ++ rtx sym = XEXP (operands[0], 0); ++ ++ if (TARGET_ICT_MODEL_LARGE ++ && nds32_indirect_call_referenced_p (sym)) ++ { ++ rtx reg = gen_reg_rtx (Pmode); ++ emit_move_insn (reg, sym); ++ operands[0] = gen_const_mem (Pmode, reg); ++ } ++ ++ if (flag_pic) ++ { ++ insn = emit_call_insn (gen_call_internal ++ (XEXP (operands[0], 0), GEN_INT (0))); ++ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); ++ DONE; ++ } ++ } + ) + + (define_insn "call_internal" +- [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i")) ++ [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, S")) + (match_operand 1)) + (clobber (reg:SI LP_REGNUM)) + (clobber (reg:SI TA_REGNUM))])] +@@ -1474,9 +1565,11 @@ + (const_int 2) + (const_int 4)) + ;; Alternative 1 +- (if_then_else (match_test "nds32_long_call_p (operands[0])") +- (const_int 12) +- (const_int 4)) ++ (if_then_else (match_test "flag_pic") ++ (const_int 16) ++ (if_then_else (match_test "nds32_long_call_p (operands[0])") ++ (const_int 12) ++ (const_int 4))) + ])] + ) + +@@ -1492,11 +1585,33 @@ + (match_operand 2))) + (clobber (reg:SI LP_REGNUM)) + (clobber (reg:SI TA_REGNUM))])] +- "") ++ "" ++ { ++ rtx insn; ++ rtx sym = XEXP (operands[1], 0); ++ ++ if (TARGET_ICT_MODEL_LARGE ++ && nds32_indirect_call_referenced_p (sym)) ++ { ++ rtx reg = gen_reg_rtx (Pmode); ++ emit_move_insn (reg, sym); ++ operands[1] = gen_const_mem (Pmode, reg); ++ } ++ ++ if (flag_pic) ++ { ++ insn = ++ emit_call_insn (gen_call_value_internal ++ (operands[0], XEXP (operands[1], 0), GEN_INT (0))); ++ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); ++ DONE; ++ } ++ } ++) + + (define_insn "call_value_internal" + [(parallel [(set (match_operand 0) +- (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i")) ++ (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, S")) + (match_operand 2))) + (clobber (reg:SI LP_REGNUM)) + (clobber (reg:SI TA_REGNUM))])] +@@ -1538,9 +1653,11 @@ + (const_int 2) + (const_int 4)) + ;; Alternative 1 +- (if_then_else (match_test "nds32_long_call_p (operands[1])") +- (const_int 12) +- (const_int 4)) ++ (if_then_else (match_test "flag_pic") ++ (const_int 16) ++ (if_then_else (match_test "nds32_long_call_p (operands[1])") ++ (const_int 12) ++ (const_int 4))) + ])] + ) + +@@ -1583,10 +1700,21 @@ + (const_int 0)) + (clobber (reg:SI TA_REGNUM)) + (return)])] +- "") ++ "" ++{ ++ rtx sym = XEXP (operands[0], 0); ++ ++ if (TARGET_ICT_MODEL_LARGE ++ && nds32_indirect_call_referenced_p (sym)) ++ { ++ rtx reg = gen_reg_rtx (Pmode); ++ emit_move_insn (reg, sym); ++ operands[0] = gen_const_mem (Pmode, reg); ++ } ++}) + + (define_insn "sibcall_internal" +- [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i")) ++ [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, S")) + (match_operand 1)) + (clobber (reg:SI TA_REGNUM)) + (return)])] +@@ -1617,9 +1745,11 @@ + (const_int 2) + (const_int 4)) + ;; Alternative 1 +- (if_then_else (match_test "nds32_long_call_p (operands[0])") +- (const_int 12) +- (const_int 4)) ++ (if_then_else (match_test "flag_pic") ++ (const_int 16) ++ (if_then_else (match_test "nds32_long_call_p (operands[0])") ++ (const_int 12) ++ (const_int 4))) + ])] + ) + +@@ -1633,11 +1763,22 @@ + (const_int 0))) + (clobber (reg:SI TA_REGNUM)) + (return)])] +- "") ++ "" ++{ ++ rtx sym = XEXP (operands[1], 0); ++ ++ if (TARGET_ICT_MODEL_LARGE ++ && nds32_indirect_call_referenced_p (sym)) ++ { ++ rtx reg = gen_reg_rtx (Pmode); ++ emit_move_insn (reg, sym); ++ operands[1] = gen_const_mem (Pmode, reg); ++ } ++}) + + (define_insn "sibcall_value_internal" + [(parallel [(set (match_operand 0) +- (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i")) ++ (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, S")) + (match_operand 2))) + (clobber (reg:SI TA_REGNUM)) + (return)])] +@@ -1668,9 +1809,11 @@ + (const_int 2) + (const_int 4)) + ;; Alternative 1 +- (if_then_else (match_test "nds32_long_call_p (operands[1])") +- (const_int 12) +- (const_int 4)) ++ (if_then_else (match_test "flag_pic") ++ (const_int 16) ++ (if_then_else (match_test "nds32_long_call_p (operands[1])") ++ (const_int 12) ++ (const_int 4))) + ])] + ) + +@@ -1687,12 +1830,33 @@ + nds32_expand_prologue_v3push (); + else + nds32_expand_prologue (); ++ ++ /* If cfun->machine->fp_as_gp_p is true, we can generate special ++ directive to guide linker doing fp-as-gp optimization. ++ However, for a naked function, which means ++ it should not have prologue/epilogue, ++ using fp-as-gp still requires saving $fp by push/pop behavior and ++ there is no benefit to use fp-as-gp on such small function. ++ So we need to make sure this function is NOT naked as well. */ ++ if (cfun->machine->fp_as_gp_p && !cfun->machine->naked_p) ++ emit_insn (gen_omit_fp_begin (gen_rtx_REG (SImode, FP_REGNUM))); ++ + DONE; + }) + + (define_expand "epilogue" [(const_int 0)] + "" + { ++ /* If cfun->machine->fp_as_gp_p is true, we can generate special ++ directive to guide linker doing fp-as-gp optimization. ++ However, for a naked function, which means ++ it should not have prologue/epilogue, ++ using fp-as-gp still requires saving $fp by push/pop behavior and ++ there is no benefit to use fp-as-gp on such small function. ++ So we need to make sure this function is NOT naked as well. */ ++ if (cfun->machine->fp_as_gp_p && !cfun->machine->naked_p) ++ emit_insn (gen_omit_fp_end (gen_rtx_REG (SImode, FP_REGNUM))); ++ + /* Note that only under V3/V3M ISA, we could use v3pop epilogue. + In addition, we need to check if v3push is indeed available. */ + if (NDS32_V3PUSH_AVAILABLE_P) +@@ -1792,7 +1956,8 @@ + "nds32_can_use_return_insn ()" + { + /* Emit as the simple return. */ +- if (cfun->machine->naked_p ++ if (!cfun->machine->fp_as_gp_p ++ && cfun->machine->naked_p + && (cfun->machine->va_args_size == 0)) + { + emit_jump_insn (gen_return_internal ()); +@@ -1802,9 +1967,14 @@ + + ;; This pattern is expanded only by the shrink-wrapping optimization + ;; on paths where the function prologue has not been executed. ++;; However, such optimization may reorder the prologue/epilogue blocks ++;; together with basic blocks within function body. ++;; So we must disable this pattern if we have already decided ++;; to perform fp_as_gp optimization, which requires prologue to be ++;; first block and epilogue to be last block. + (define_expand "simple_return" + [(simple_return)] +- "" ++ "!cfun->machine->fp_as_gp_p" + "" + ) + +@@ -1823,6 +1993,9 @@ + [(simple_return)] + "" + { ++ if (nds32_isr_function_critical_p (current_function_decl)) ++ return "iret"; ++ + if (TARGET_16_BIT) + return "ret5"; + else +@@ -1831,9 +2004,11 @@ + [(set_attr "type" "branch") + (set_attr "enabled" "yes") + (set (attr "length") +- (if_then_else (match_test "TARGET_16_BIT") +- (const_int 2) +- (const_int 4)))]) ++ (if_then_else (match_test "nds32_isr_function_critical_p (current_function_decl)") ++ (const_int 4) ++ (if_then_else (match_test "TARGET_16_BIT") ++ (const_int 2) ++ (const_int 4))))]) + + + ;; ---------------------------------------------------------------------------- +@@ -1868,6 +2043,7 @@ + { + rtx add_tmp; + rtx reg, test; ++ rtx tmp_reg; + + /* Step A: "k <-- (plus (operands[0]) (-operands[1]))". */ + if (operands[1] != const0_rtx) +@@ -1889,9 +2065,14 @@ + emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], + operands[4])); + +- /* Step C, D, E, and F, using another temporary register. */ +- rtx tmp = gen_reg_rtx (SImode); +- emit_jump_insn (gen_casesi_internal (operands[0], operands[3], tmp)); ++ tmp_reg = gen_reg_rtx (SImode); ++ /* Step C, D, E, and F, using another temporary register tmp_reg. */ ++ if (flag_pic) ++ emit_use (pic_offset_table_rtx); ++ ++ emit_jump_insn (gen_casesi_internal (operands[0], ++ operands[3], ++ tmp_reg)); + DONE; + }) + +@@ -1927,13 +2108,30 @@ + else + return nds32_output_casesi (operands); + } +- [(set_attr "length" "20") +- (set_attr "type" "branch")]) ++ [(set_attr "type" "branch") ++ (set (attr "length") ++ (if_then_else (match_test "flag_pic") ++ (const_int 28) ++ (const_int 20)))]) + + ;; ---------------------------------------------------------------------------- + + ;; Performance Extension + ++; If -fwrapv option is issued, GCC expects there will be ++; signed overflow situation. So the ABS(INT_MIN) is still INT_MIN ++; (e.g. ABS(0x80000000)=0x80000000). ++; However, the hardware ABS instruction of nds32 target ++; always performs saturation: abs 0x80000000 -> 0x7fffffff. ++; So that we can only enable abssi2 pattern if flag_wrapv is NOT presented. ++(define_insn "abssi2" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (abs:SI (match_operand:SI 1 "register_operand" " r")))] ++ "TARGET_EXT_PERF && TARGET_HW_ABS && !flag_wrapv" ++ "abs\t%0, %1" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")]) ++ + (define_insn "clzsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (clz:SI (match_operand:SI 1 "register_operand" " r")))] +@@ -1996,6 +2194,25 @@ + [(set_attr "length" "0")] + ) + ++;; Output .omit_fp_begin for fp-as-gp optimization. ++;; Also we have to set $fp register. ++(define_insn "omit_fp_begin" ++ [(set (match_operand:SI 0 "register_operand" "=x") ++ (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_OMIT_FP_BEGIN))] ++ "" ++ "! -----\;.omit_fp_begin\;la\t$fp,_FP_BASE_\;! -----" ++ [(set_attr "length" "8")] ++) ++ ++;; Output .omit_fp_end for fp-as-gp optimization. ++;; Claim that we have to use $fp register. ++(define_insn "omit_fp_end" ++ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "x")] UNSPEC_VOLATILE_OMIT_FP_END)] ++ "" ++ "! -----\;.omit_fp_end\;! -----" ++ [(set_attr "length" "0")] ++) ++ + (define_insn "pop25return" + [(return) + (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_POP25_RETURN)] +@@ -2004,6 +2221,36 @@ + [(set_attr "length" "0")] + ) + ++;; Add pc ++(define_insn "add_pc" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (plus:SI (match_operand:SI 1 "register_operand" "0") ++ (pc)))] ++ "TARGET_LINUX_ABI || flag_pic" ++ "add5.pc\t%0" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ ++(define_expand "bswapsi2" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (bswap:SI (match_operand:SI 1 "register_operand" "r")))] ++ "" ++{ ++ emit_insn (gen_unspec_wsbh (operands[0], operands[1])); ++ emit_insn (gen_rotrsi3 (operands[0], operands[0], GEN_INT (16))); ++ DONE; ++}) ++ ++(define_insn "bswaphi2" ++ [(set (match_operand:HI 0 "register_operand" "=r") ++ (bswap:HI (match_operand:HI 1 "register_operand" "r")))] ++ "" ++ "wsbh\t%0, %1" ++ [(set_attr "type" "alu") ++ (set_attr "length" "4")] ++) ++ + ;; ---------------------------------------------------------------------------- + + ;; Patterns for exception handling +@@ -2068,3 +2315,57 @@ + }) + + ;; ---------------------------------------------------------------------------- ++ ++;; Patterns for TLS. ++;; The following two tls patterns don't be expanded directly because the ++;; intermediate value may be spilled into the stack. As a result, it is ++;; hard to analyze the define-use chain in the relax_opt pass. ++ ++ ++;; There is a unspec operand to record RELAX_GROUP number because each ++;; emitted instruction need a relax_hint above it. ++(define_insn "tls_desc" ++ [(set (reg:SI 0) ++ (call (unspec_volatile:SI [(match_operand:SI 0 "nds32_symbolic_operand" "i")] UNSPEC_TLS_DESC) ++ (const_int 1))) ++ (use (unspec [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)) ++ (use (reg:SI GP_REGNUM)) ++ (clobber (reg:SI LP_REGNUM)) ++ (clobber (reg:SI TA_REGNUM))] ++ "" ++ { ++ return nds32_output_tls_desc (operands); ++ } ++ [(set_attr "length" "20") ++ (set_attr "type" "branch")] ++) ++ ++;; There is a unspec operand to record RELAX_GROUP number because each ++;; emitted instruction need a relax_hint above it. ++(define_insn "tls_ie" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_TLS_IE)) ++ (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)) ++ (use (reg:SI GP_REGNUM))] ++ "" ++ { ++ return nds32_output_tls_ie (operands); ++ } ++ [(set (attr "length") (if_then_else (match_test "flag_pic") ++ (const_int 12) ++ (const_int 8))) ++ (set_attr "type" "misc")] ++) ++ ++;; The pattern is for some relaxation groups that have to keep addsi3 in 32-bit mode. ++(define_insn "addsi3_32bit" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec:SI [(match_operand:SI 1 "register_operand" "%r") ++ (match_operand:SI 2 "register_operand" " r")] UNSPEC_ADD32))] ++ "" ++ "add\t%0, %1, %2"; ++ [(set_attr "type" "alu") ++ (set_attr "length" "4") ++ (set_attr "feature" "v1")]) ++ ++;; ---------------------------------------------------------------------------- +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-md-auxiliary.c gcc-8.2.0/gcc/config/nds32/nds32-md-auxiliary.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-md-auxiliary.c 2018-04-08 08:00:34.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-md-auxiliary.c 2019-01-25 15:38:32.829242659 +0100 +@@ -39,6 +39,9 @@ + #include "expr.h" + #include "emit-rtl.h" + #include "explow.h" ++#include "stringpool.h" ++#include "attribs.h" ++ + + /* ------------------------------------------------------------------------ */ + +@@ -261,6 +264,118 @@ + output_asm_insn (pattern, operands); + } + ++static void ++nds32_split_shiftrtdi3 (rtx dst, rtx src, rtx shiftamount, bool logic_shift_p) ++{ ++ rtx src_high_part; ++ rtx dst_high_part, dst_low_part; ++ ++ dst_high_part = nds32_di_high_part_subreg (dst); ++ src_high_part = nds32_di_high_part_subreg (src); ++ dst_low_part = nds32_di_low_part_subreg (dst); ++ ++ if (CONST_INT_P (shiftamount)) ++ { ++ if (INTVAL (shiftamount) < 32) ++ { ++ if (logic_shift_p) ++ { ++ emit_insn (gen_uwext (dst_low_part, src, ++ shiftamount)); ++ emit_insn (gen_lshrsi3 (dst_high_part, src_high_part, ++ shiftamount)); ++ } ++ else ++ { ++ emit_insn (gen_wext (dst_low_part, src, ++ shiftamount)); ++ emit_insn (gen_ashrsi3 (dst_high_part, src_high_part, ++ shiftamount)); ++ } ++ } ++ else ++ { ++ rtx new_shift_amout = gen_int_mode(INTVAL (shiftamount) - 32, SImode); ++ ++ if (logic_shift_p) ++ { ++ emit_insn (gen_lshrsi3 (dst_low_part, src_high_part, ++ new_shift_amout)); ++ emit_move_insn (dst_high_part, const0_rtx); ++ } ++ else ++ { ++ emit_insn (gen_ashrsi3 (dst_low_part, src_high_part, ++ new_shift_amout)); ++ emit_insn (gen_ashrsi3 (dst_high_part, src_high_part, ++ GEN_INT (31))); ++ } ++ } ++ } ++ else ++ { ++ rtx dst_low_part_l32, dst_high_part_l32; ++ rtx dst_low_part_g32, dst_high_part_g32; ++ rtx new_shift_amout, select_reg; ++ dst_low_part_l32 = gen_reg_rtx (SImode); ++ dst_high_part_l32 = gen_reg_rtx (SImode); ++ dst_low_part_g32 = gen_reg_rtx (SImode); ++ dst_high_part_g32 = gen_reg_rtx (SImode); ++ new_shift_amout = gen_reg_rtx (SImode); ++ select_reg = gen_reg_rtx (SImode); ++ ++ emit_insn (gen_andsi3 (shiftamount, shiftamount, GEN_INT (0x3f))); ++ ++ if (logic_shift_p) ++ { ++ /* ++ if (shiftamount < 32) ++ dst_low_part = wext (src, shiftamount) ++ dst_high_part = src_high_part >> shiftamount ++ else ++ dst_low_part = src_high_part >> (shiftamount & 0x1f) ++ dst_high_part = 0 ++ */ ++ emit_insn (gen_uwext (dst_low_part_l32, src, shiftamount)); ++ emit_insn (gen_lshrsi3 (dst_high_part_l32, src_high_part, ++ shiftamount)); ++ ++ emit_insn (gen_andsi3 (new_shift_amout, shiftamount, GEN_INT (0x1f))); ++ emit_insn (gen_lshrsi3 (dst_low_part_g32, src_high_part, ++ new_shift_amout)); ++ emit_move_insn (dst_high_part_g32, const0_rtx); ++ } ++ else ++ { ++ /* ++ if (shiftamount < 32) ++ dst_low_part = wext (src, shiftamount) ++ dst_high_part = src_high_part >> shiftamount ++ else ++ dst_low_part = src_high_part >> (shiftamount & 0x1f) ++ # shift 31 for sign extend ++ dst_high_part = src_high_part >> 31 ++ */ ++ emit_insn (gen_wext (dst_low_part_l32, src, shiftamount)); ++ emit_insn (gen_ashrsi3 (dst_high_part_l32, src_high_part, ++ shiftamount)); ++ ++ emit_insn (gen_andsi3 (new_shift_amout, shiftamount, GEN_INT (0x1f))); ++ emit_insn (gen_ashrsi3 (dst_low_part_g32, src_high_part, ++ new_shift_amout)); ++ emit_insn (gen_ashrsi3 (dst_high_part_g32, src_high_part, ++ GEN_INT (31))); ++ } ++ ++ emit_insn (gen_slt_compare (select_reg, shiftamount, GEN_INT (32))); ++ ++ emit_insn (gen_cmovnsi (dst_low_part, select_reg, ++ dst_low_part_l32, dst_low_part_g32)); ++ emit_insn (gen_cmovnsi (dst_high_part, select_reg, ++ dst_high_part_l32, dst_high_part_g32)); ++ } ++} ++ + /* ------------------------------------------------------------------------ */ + + /* Auxiliary function for expand RTL pattern. */ +@@ -1195,8 +1310,166 @@ + } + } + ++enum nds32_expand_result_type ++nds32_expand_extv (rtx *operands) ++{ ++ gcc_assert (CONST_INT_P (operands[2]) && CONST_INT_P (operands[3])); ++ HOST_WIDE_INT width = INTVAL (operands[2]); ++ HOST_WIDE_INT bitpos = INTVAL (operands[3]); ++ rtx dst = operands[0]; ++ rtx src = operands[1]; ++ ++ if (MEM_P (src) ++ && width == 32 ++ && (bitpos % BITS_PER_UNIT) == 0 ++ && GET_MODE_BITSIZE (GET_MODE (dst)) == width) ++ { ++ rtx newmem = adjust_address (src, GET_MODE (dst), ++ bitpos / BITS_PER_UNIT); ++ ++ rtx base_addr = force_reg (Pmode, XEXP (newmem, 0)); ++ ++ emit_insn (gen_unaligned_loadsi (dst, base_addr)); ++ ++ return EXPAND_DONE; ++ } ++ return EXPAND_FAIL; ++} ++ ++enum nds32_expand_result_type ++nds32_expand_insv (rtx *operands) ++{ ++ gcc_assert (CONST_INT_P (operands[1]) && CONST_INT_P (operands[2])); ++ HOST_WIDE_INT width = INTVAL (operands[1]); ++ HOST_WIDE_INT bitpos = INTVAL (operands[2]); ++ rtx dst = operands[0]; ++ rtx src = operands[3]; ++ ++ if (MEM_P (dst) ++ && width == 32 ++ && (bitpos % BITS_PER_UNIT) == 0 ++ && GET_MODE_BITSIZE (GET_MODE (src)) == width) ++ { ++ rtx newmem = adjust_address (dst, GET_MODE (src), ++ bitpos / BITS_PER_UNIT); ++ ++ rtx base_addr = force_reg (Pmode, XEXP (newmem, 0)); ++ ++ emit_insn (gen_unaligned_storesi (base_addr, src)); ++ ++ return EXPAND_DONE; ++ } ++ return EXPAND_FAIL; ++} ++ + /* ------------------------------------------------------------------------ */ + ++/* Function to generate PC relative jump table. ++ Refer to nds32.md for more details. ++ ++ The following is the sample for the case that diff value ++ can be presented in '.short' size. ++ ++ addi $r1, $r1, -(case_lower_bound) ++ slti $ta, $r1, (case_number) ++ beqz $ta, .L_skip_label ++ ++ la $ta, .L35 ! get jump table address ++ lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry ++ addi $ta, $r1, $ta ++ jr5 $ta ++ ++ ! jump table entry ++ L35: ++ .short .L25-.L35 ++ .short .L26-.L35 ++ .short .L27-.L35 ++ .short .L28-.L35 ++ .short .L29-.L35 ++ .short .L30-.L35 ++ .short .L31-.L35 ++ .short .L32-.L35 ++ .short .L33-.L35 ++ .short .L34-.L35 */ ++const char * ++nds32_output_casesi_pc_relative (rtx *operands) ++{ ++ machine_mode mode; ++ rtx diff_vec; ++ ++ diff_vec = PATTERN (NEXT_INSN (as_a (operands[1]))); ++ ++ gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); ++ ++ /* Step C: "t <-- operands[1]". */ ++ if (flag_pic) ++ { ++ output_asm_insn ("sethi\t$ta, hi20(%l1@GOTOFF)", operands); ++ output_asm_insn ("ori\t$ta, $ta, lo12(%l1@GOTOFF)", operands); ++ output_asm_insn ("add\t$ta, $ta, $gp", operands); ++ } ++ else ++ output_asm_insn ("la\t$ta, %l1", operands); ++ ++ /* Get the mode of each element in the difference vector. */ ++ mode = GET_MODE (diff_vec); ++ ++ /* Step D: "z <-- (mem (plus (operands[0] << m) t))", ++ where m is 0, 1, or 2 to load address-diff value from table. */ ++ switch (mode) ++ { ++ case E_QImode: ++ output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands); ++ break; ++ case E_HImode: ++ output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands); ++ break; ++ case E_SImode: ++ output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); ++ break; ++ default: ++ gcc_unreachable (); ++ } ++ ++ /* Step E: "t <-- z + t". ++ Add table label_ref with address-diff value to ++ obtain target case address. */ ++ output_asm_insn ("add\t$ta, %2, $ta", operands); ++ ++ /* Step F: jump to target with register t. */ ++ if (TARGET_16_BIT) ++ return "jr5\t$ta"; ++ else ++ return "jr\t$ta"; ++} ++ ++/* Function to generate normal jump table. */ ++const char * ++nds32_output_casesi (rtx *operands) ++{ ++ /* Step C: "t <-- operands[1]". */ ++ if (flag_pic) ++ { ++ output_asm_insn ("sethi\t$ta, hi20(%l1@GOTOFF)", operands); ++ output_asm_insn ("ori\t$ta, $ta, lo12(%l1@GOTOFF)", operands); ++ output_asm_insn ("add\t$ta, $ta, $gp", operands); ++ } ++ else ++ output_asm_insn ("la\t$ta, %l1", operands); ++ ++ /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */ ++ output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); ++ ++ /* No need to perform Step E, which is only used for ++ pc relative jump table. */ ++ ++ /* Step F: jump to target with register z. */ ++ if (TARGET_16_BIT) ++ return "jr5\t%2"; ++ else ++ return "jr\t%2"; ++} ++ + /* Function to return memory format. */ + enum nds32_16bit_address_type + nds32_mem_format (rtx op) +@@ -1757,11 +2030,8 @@ + + /* If we step here, we are going to do v3push or multiple push operation. */ + +- /* The v3push/v3pop instruction should only be applied on +- none-isr and none-variadic function. */ +- if (TARGET_V3PUSH +- && !nds32_isr_function_p (current_function_decl) +- && (cfun->machine->va_args_size == 0)) ++ /* Refer to nds32.h, where we comment when push25/pop25 are available. */ ++ if (NDS32_V3PUSH_AVAILABLE_P) + { + /* For stack v3push: + operands[0]: Re +@@ -1881,11 +2151,8 @@ + + /* If we step here, we are going to do v3pop or multiple pop operation. */ + +- /* The v3push/v3pop instruction should only be applied on +- none-isr and none-variadic function. */ +- if (TARGET_V3PUSH +- && !nds32_isr_function_p (current_function_decl) +- && (cfun->machine->va_args_size == 0)) ++ /* Refer to nds32.h, where we comment when push25/pop25 are available. */ ++ if (NDS32_V3PUSH_AVAILABLE_P) + { + /* For stack v3pop: + operands[0]: Re +@@ -2022,77 +2289,6 @@ + return ""; + } + +-/* Function to generate PC relative jump table. +- Refer to nds32.md for more details. +- +- The following is the sample for the case that diff value +- can be presented in '.short' size. +- +- addi $r1, $r1, -(case_lower_bound) +- slti $ta, $r1, (case_number) +- beqz $ta, .L_skip_label +- +- la $ta, .L35 ! get jump table address +- lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry +- addi $ta, $r1, $ta +- jr5 $ta +- +- ! jump table entry +- L35: +- .short .L25-.L35 +- .short .L26-.L35 +- .short .L27-.L35 +- .short .L28-.L35 +- .short .L29-.L35 +- .short .L30-.L35 +- .short .L31-.L35 +- .short .L32-.L35 +- .short .L33-.L35 +- .short .L34-.L35 */ +-const char * +-nds32_output_casesi_pc_relative (rtx *operands) +-{ +- machine_mode mode; +- rtx diff_vec; +- +- diff_vec = PATTERN (NEXT_INSN (as_a (operands[1]))); +- +- gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); +- +- /* Step C: "t <-- operands[1]". */ +- output_asm_insn ("la\t$ta, %l1", operands); +- +- /* Get the mode of each element in the difference vector. */ +- mode = GET_MODE (diff_vec); +- +- /* Step D: "z <-- (mem (plus (operands[0] << m) t))", +- where m is 0, 1, or 2 to load address-diff value from table. */ +- switch (mode) +- { +- case E_QImode: +- output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands); +- break; +- case E_HImode: +- output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands); +- break; +- case E_SImode: +- output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); +- break; +- default: +- gcc_unreachable (); +- } +- +- /* Step E: "t <-- z + t". +- Add table label_ref with address-diff value to +- obtain target case address. */ +- output_asm_insn ("add\t$ta, %2, $ta", operands); +- +- /* Step F: jump to target with register t. */ +- if (TARGET_16_BIT) +- return "jr5\t$ta"; +- else +- return "jr\t$ta"; +-} + + /* output a float load instruction */ + const char * +@@ -2250,52 +2446,51 @@ + return ""; + } + +-/* Function to generate normal jump table. */ + const char * +-nds32_output_casesi (rtx *operands) ++nds32_output_smw_single_word (rtx *operands) + { +- /* Step C: "t <-- operands[1]". */ +- output_asm_insn ("la\t$ta, %l1", operands); +- +- /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */ +- output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); +- +- /* No need to perform Step E, which is only used for +- pc relative jump table. */ ++ char buff[100]; ++ unsigned regno; ++ int enable4; ++ bool update_base_p; ++ rtx base_addr = operands[0]; ++ rtx base_reg; ++ rtx otherops[2]; + +- /* Step F: jump to target with register z. */ +- if (TARGET_16_BIT) +- return "jr5\t%2"; ++ if (REG_P (XEXP (base_addr, 0))) ++ { ++ update_base_p = false; ++ base_reg = XEXP (base_addr, 0); ++ } + else +- return "jr\t%2"; +-} ++ { ++ update_base_p = true; ++ base_reg = XEXP (XEXP (base_addr, 0), 0); ++ } + +-/* Auxiliary functions for lwm/smw. */ +-bool +-nds32_valid_smw_lwm_base_p (rtx op) +-{ +- rtx base_addr; ++ const char *update_base = update_base_p ? "m" : ""; + +- if (!MEM_P (op)) +- return false; ++ regno = REGNO (operands[1]); + +- base_addr = XEXP (op, 0); ++ otherops[0] = base_reg; ++ otherops[1] = operands[1]; + +- if (REG_P (base_addr)) +- return true; ++ if (regno >= 28) ++ { ++ enable4 = nds32_regno_to_enable4 (regno); ++ sprintf (buff, "smw.bi%s\t$sp, [%%0], $sp, %x", update_base, enable4); ++ } + else + { +- if (GET_CODE (base_addr) == POST_INC +- && REG_P (XEXP (base_addr, 0))) +- return true; ++ sprintf (buff, "smw.bi%s\t%%1, [%%0], %%1", update_base); + } +- +- return false; ++ output_asm_insn (buff, otherops); ++ return ""; + } + + /* ------------------------------------------------------------------------ */ + const char * +-nds32_output_smw_single_word (rtx *operands) ++nds32_output_smw_double_word (rtx *operands) + { + char buff[100]; + unsigned regno; +@@ -2303,7 +2498,7 @@ + bool update_base_p; + rtx base_addr = operands[0]; + rtx base_reg; +- rtx otherops[2]; ++ rtx otherops[3]; + + if (REG_P (XEXP (base_addr, 0))) + { +@@ -2322,15 +2517,22 @@ + + otherops[0] = base_reg; + otherops[1] = operands[1]; ++ otherops[2] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);; + + if (regno >= 28) + { +- enable4 = nds32_regno_to_enable4 (regno); ++ enable4 = nds32_regno_to_enable4 (regno) ++ | nds32_regno_to_enable4 (regno + 1); + sprintf (buff, "smw.bi%s\t$sp, [%%0], $sp, %x", update_base, enable4); + } ++ else if (regno == 27) ++ { ++ enable4 = nds32_regno_to_enable4 (regno + 1); ++ sprintf (buff, "smw.bi%s\t%%1, [%%0], %%1, %x", update_base, enable4); ++ } + else + { +- sprintf (buff, "smw.bi%s\t%%1, [%%0], %%1", update_base); ++ sprintf (buff, "smw.bi%s\t%%1, [%%0], %%2", update_base); + } + output_asm_insn (buff, otherops); + return ""; +@@ -2415,16 +2617,17 @@ + if (mode == DImode) + { + /* Load doubleword, we need two registers to access. */ +- reg[0] = simplify_gen_subreg (SImode, operands[0], +- GET_MODE (operands[0]), 0); +- reg[1] = simplify_gen_subreg (SImode, operands[0], +- GET_MODE (operands[0]), 4); ++ reg[0] = nds32_di_low_part_subreg (operands[0]); ++ reg[1] = nds32_di_high_part_subreg (operands[0]); + /* A register only store 4 byte. */ + width = GET_MODE_SIZE (SImode) - 1; + } + else + { +- reg[0] = operands[0]; ++ if (VECTOR_MODE_P (mode)) ++ reg[0] = gen_reg_rtx (SImode); ++ else ++ reg[0] = operands[0]; + } + + for (num_reg = (mode == DImode) ? 2 : 1; num_reg > 0; num_reg--) +@@ -2466,6 +2669,8 @@ + offset = offset + offset_adj; + } + } ++ if (VECTOR_MODE_P (mode)) ++ convert_move (operands[0], reg[0], false); + } + + void +@@ -2499,16 +2704,20 @@ + if (mode == DImode) + { + /* Load doubleword, we need two registers to access. */ +- reg[0] = simplify_gen_subreg (SImode, operands[1], +- GET_MODE (operands[1]), 0); +- reg[1] = simplify_gen_subreg (SImode, operands[1], +- GET_MODE (operands[1]), 4); ++ reg[0] = nds32_di_low_part_subreg (operands[1]); ++ reg[1] = nds32_di_high_part_subreg (operands[1]); + /* A register only store 4 byte. */ + width = GET_MODE_SIZE (SImode) - 1; + } + else + { +- reg[0] = operands[1]; ++ if (VECTOR_MODE_P (mode)) ++ { ++ reg[0] = gen_reg_rtx (SImode); ++ convert_move (reg[0], operands[1], false); ++ } ++ else ++ reg[0] = operands[1]; + } + + for (num_reg = (mode == DImode) ? 2 : 1; num_reg > 0; num_reg--) +@@ -2765,6 +2974,36 @@ + return ""; + } + ++const char * ++nds32_output_unpkd8 (rtx output, rtx input, ++ rtx high_idx_rtx, rtx low_idx_rtx, ++ bool signed_p) ++{ ++ char pattern[100]; ++ rtx output_operands[2]; ++ HOST_WIDE_INT high_idx, low_idx; ++ high_idx = INTVAL (high_idx_rtx); ++ low_idx = INTVAL (low_idx_rtx); ++ ++ gcc_assert (high_idx >= 0 && high_idx <= 3); ++ gcc_assert (low_idx >= 0 && low_idx <= 3); ++ ++ /* We only have 10, 20, 30 and 31. */ ++ if ((low_idx != 0 || high_idx == 0) && ++ !(low_idx == 1 && high_idx == 3)) ++ return "#"; ++ ++ char sign_char = signed_p ? 's' : 'z'; ++ ++ sprintf (pattern, ++ "%cunpkd8" HOST_WIDE_INT_PRINT_DEC HOST_WIDE_INT_PRINT_DEC "\t%%0, %%1", ++ sign_char, high_idx, low_idx); ++ output_operands[0] = output; ++ output_operands[1] = input; ++ output_asm_insn (pattern, output_operands); ++ return ""; ++} ++ + /* Return true if SYMBOL_REF X binds locally. */ + + static bool +@@ -2782,22 +3021,15 @@ + char pattern[100]; + bool noreturn_p; + +- if (GET_CODE (symbol) == CONST) +- { +- symbol= XEXP (symbol, 0); +- +- if (GET_CODE (symbol) == PLUS) +- symbol = XEXP (symbol, 0); +- } +- +- gcc_assert (GET_CODE (symbol) == SYMBOL_REF +- || REG_P (symbol)); +- + if (nds32_long_call_p (symbol)) + strcpy (pattern, long_call); + else + strcpy (pattern, call); + ++ if (flag_pic && CONSTANT_P (symbol) ++ && !nds32_symbol_binds_local_p (symbol)) ++ strcat (pattern, "@PLT"); ++ + if (align_p) + strcat (pattern, "\n\t.align 2"); + +@@ -2815,6 +3047,91 @@ + return ""; + } + ++bool ++nds32_need_split_sms_p (rtx in0_idx0, rtx in1_idx0, ++ rtx in0_idx1, rtx in1_idx1) ++{ ++ /* smds or smdrs. */ ++ if (INTVAL (in0_idx0) == INTVAL (in1_idx0) ++ && INTVAL (in0_idx1) == INTVAL (in1_idx1) ++ && INTVAL (in0_idx0) != INTVAL (in0_idx1)) ++ return false; ++ ++ /* smxds. */ ++ if (INTVAL (in0_idx0) != INTVAL (in0_idx1) ++ && INTVAL (in1_idx0) != INTVAL (in1_idx1)) ++ return false; ++ ++ return true; ++} ++ ++const char * ++nds32_output_sms (rtx in0_idx0, rtx in1_idx0, ++ rtx in0_idx1, rtx in1_idx1) ++{ ++ if (nds32_need_split_sms_p (in0_idx0, in1_idx0, ++ in0_idx1, in1_idx1)) ++ return "#"; ++ /* out = in0[in0_idx0] * in1[in1_idx0] - in0[in0_idx1] * in1[in1_idx1] */ ++ ++ /* smds or smdrs. */ ++ if (INTVAL (in0_idx0) == INTVAL (in1_idx0) ++ && INTVAL (in0_idx1) == INTVAL (in1_idx1) ++ && INTVAL (in0_idx0) != INTVAL (in0_idx1)) ++ { ++ if (INTVAL (in0_idx0) == 0) ++ { ++ if (TARGET_BIG_ENDIAN) ++ return "smds\t%0, %1, %2"; ++ else ++ return "smdrs\t%0, %1, %2"; ++ } ++ else ++ { ++ if (TARGET_BIG_ENDIAN) ++ return "smdrs\t%0, %1, %2"; ++ else ++ return "smds\t%0, %1, %2"; ++ } ++ } ++ ++ if (INTVAL (in0_idx0) != INTVAL (in0_idx1) ++ && INTVAL (in1_idx0) != INTVAL (in1_idx1)) ++ { ++ if (INTVAL (in0_idx0) == 1) ++ { ++ if (TARGET_BIG_ENDIAN) ++ return "smxds\t%0, %2, %1"; ++ else ++ return "smxds\t%0, %1, %2"; ++ } ++ else ++ { ++ if (TARGET_BIG_ENDIAN) ++ return "smxds\t%0, %1, %2"; ++ else ++ return "smxds\t%0, %2, %1"; ++ } ++ } ++ ++ gcc_unreachable (); ++ return ""; ++} ++ ++void ++nds32_split_sms (rtx out, rtx in0, rtx in1, ++ rtx in0_idx0, rtx in1_idx0, ++ rtx in0_idx1, rtx in1_idx1) ++{ ++ rtx result0 = gen_reg_rtx (SImode); ++ rtx result1 = gen_reg_rtx (SImode); ++ emit_insn (gen_mulhisi3v (result0, in0, in1, ++ in0_idx0, in1_idx0)); ++ emit_insn (gen_mulhisi3v (result1, in0, in1, ++ in0_idx1, in1_idx1)); ++ emit_insn (gen_subsi3 (out, result0, result1)); ++} ++ + /* Spilt a doubleword instrucion to two single word instructions. */ + void + nds32_spilt_doubleword (rtx *operands, bool load_p) +@@ -2846,16 +3163,30 @@ + /* generate low_part and high_part memory format: + low_part: (post_modify ((reg) (plus (reg) (const 4))) + high_part: (post_modify ((reg) (plus (reg) (const -12))) */ +- low_part[mem] = gen_frame_mem (SImode, +- gen_rtx_POST_MODIFY (Pmode, sub_mem, +- gen_rtx_PLUS (Pmode, +- sub_mem, +- GEN_INT (4)))); +- high_part[mem] = gen_frame_mem (SImode, +- gen_rtx_POST_MODIFY (Pmode, sub_mem, +- gen_rtx_PLUS (Pmode, +- sub_mem, +- GEN_INT (-12)))); ++ low_part[mem] = gen_rtx_MEM (SImode, ++ gen_rtx_POST_MODIFY (Pmode, sub_mem, ++ gen_rtx_PLUS (Pmode, ++ sub_mem, ++ GEN_INT (4)))); ++ high_part[mem] = gen_rtx_MEM (SImode, ++ gen_rtx_POST_MODIFY (Pmode, sub_mem, ++ gen_rtx_PLUS (Pmode, ++ sub_mem, ++ GEN_INT (-12)))); ++ } ++ else if (GET_CODE (sub_mem) == POST_INC) ++ { ++ /* memory format is (post_inc (reg)), ++ so that extract (reg) from the (post_inc (reg)) pattern. */ ++ sub_mem = XEXP (sub_mem, 0); ++ ++ /* generate low_part and high_part memory format: ++ low_part: (post_inc (reg)) ++ high_part: (post_inc (reg)) */ ++ low_part[mem] = gen_rtx_MEM (SImode, ++ gen_rtx_POST_INC (Pmode, sub_mem)); ++ high_part[mem] = gen_rtx_MEM (SImode, ++ gen_rtx_POST_INC (Pmode, sub_mem)); + } + else if (GET_CODE (sub_mem) == POST_MODIFY) + { +@@ -2872,14 +3203,14 @@ + /* Generate low_part and high_part memory format: + low_part: (post_modify ((reg) (plus (reg) (const))) + high_part: ((plus (reg) (const 4))) */ +- low_part[mem] = gen_frame_mem (SImode, +- gen_rtx_POST_MODIFY (Pmode, post_mem, +- gen_rtx_PLUS (Pmode, +- post_mem, +- post_val))); +- high_part[mem] = gen_frame_mem (SImode, plus_constant (Pmode, +- post_mem, +- 4)); ++ low_part[mem] = gen_rtx_MEM (SImode, ++ gen_rtx_POST_MODIFY (Pmode, post_mem, ++ gen_rtx_PLUS (Pmode, ++ post_mem, ++ post_val))); ++ high_part[mem] = gen_rtx_MEM (SImode, plus_constant (Pmode, ++ post_mem, ++ 4)); + } + else + { +@@ -2924,11 +3255,516 @@ + } + } + ++void ++nds32_split_ashiftdi3 (rtx dst, rtx src, rtx shiftamount) ++{ ++ rtx src_high_part, src_low_part; ++ rtx dst_high_part, dst_low_part; ++ ++ dst_high_part = nds32_di_high_part_subreg (dst); ++ dst_low_part = nds32_di_low_part_subreg (dst); ++ ++ src_high_part = nds32_di_high_part_subreg (src); ++ src_low_part = nds32_di_low_part_subreg (src); ++ ++ /* We need to handle shift more than 32 bit!!!! */ ++ if (CONST_INT_P (shiftamount)) ++ { ++ if (INTVAL (shiftamount) < 32) ++ { ++ rtx ext_start; ++ ext_start = gen_int_mode(32 - INTVAL (shiftamount), SImode); ++ ++ emit_insn (gen_wext (dst_high_part, src, ext_start)); ++ emit_insn (gen_ashlsi3 (dst_low_part, src_low_part, shiftamount)); ++ } ++ else ++ { ++ rtx new_shift_amout = gen_int_mode(INTVAL (shiftamount) - 32, SImode); ++ ++ emit_insn (gen_ashlsi3 (dst_high_part, src_low_part, ++ new_shift_amout)); ++ ++ emit_move_insn (dst_low_part, GEN_INT (0)); ++ } ++ } ++ else ++ { ++ rtx dst_low_part_l32, dst_high_part_l32; ++ rtx dst_low_part_g32, dst_high_part_g32; ++ rtx new_shift_amout, select_reg; ++ dst_low_part_l32 = gen_reg_rtx (SImode); ++ dst_high_part_l32 = gen_reg_rtx (SImode); ++ dst_low_part_g32 = gen_reg_rtx (SImode); ++ dst_high_part_g32 = gen_reg_rtx (SImode); ++ new_shift_amout = gen_reg_rtx (SImode); ++ select_reg = gen_reg_rtx (SImode); ++ ++ rtx ext_start; ++ ext_start = gen_reg_rtx (SImode); ++ ++ /* ++ if (shiftamount < 32) ++ dst_low_part = src_low_part << shiftamout ++ dst_high_part = wext (src, 32 - shiftamount) ++ # wext can't handle wext (src, 32) since it's only take rb[0:4] ++ # for extract. ++ dst_high_part = shiftamount == 0 ? src_high_part : dst_high_part ++ else ++ dst_low_part = 0 ++ dst_high_part = src_low_part << shiftamount & 0x1f ++ */ ++ ++ emit_insn (gen_subsi3 (ext_start, ++ gen_int_mode (32, SImode), ++ shiftamount)); ++ emit_insn (gen_wext (dst_high_part_l32, src, ext_start)); ++ ++ /* Handle for shiftamout == 0. */ ++ emit_insn (gen_cmovzsi (dst_high_part_l32, shiftamount, ++ src_high_part, dst_high_part_l32)); ++ ++ emit_insn (gen_ashlsi3 (dst_low_part_l32, src_low_part, shiftamount)); ++ ++ emit_move_insn (dst_low_part_g32, const0_rtx); ++ emit_insn (gen_andsi3 (new_shift_amout, shiftamount, GEN_INT (0x1f))); ++ emit_insn (gen_ashlsi3 (dst_high_part_g32, src_low_part, ++ new_shift_amout)); ++ ++ emit_insn (gen_slt_compare (select_reg, shiftamount, GEN_INT (32))); ++ ++ emit_insn (gen_cmovnsi (dst_low_part, select_reg, ++ dst_low_part_l32, dst_low_part_g32)); ++ emit_insn (gen_cmovnsi (dst_high_part, select_reg, ++ dst_high_part_l32, dst_high_part_g32)); ++ } ++} ++ ++void ++nds32_split_ashiftrtdi3 (rtx dst, rtx src, rtx shiftamount) ++{ ++ nds32_split_shiftrtdi3 (dst, src, shiftamount, false); ++} ++ ++void ++nds32_split_lshiftrtdi3 (rtx dst, rtx src, rtx shiftamount) ++{ ++ nds32_split_shiftrtdi3 (dst, src, shiftamount, true); ++} ++ ++void ++nds32_split_rotatertdi3 (rtx dst, rtx src, rtx shiftamount) ++{ ++ rtx dst_low_part_l32, dst_high_part_l32; ++ rtx dst_low_part_g32, dst_high_part_g32; ++ rtx select_reg, low5bit, low5bit_inv, minus32sa; ++ rtx dst_low_part_g32_tmph; ++ rtx dst_low_part_g32_tmpl; ++ rtx dst_high_part_l32_tmph; ++ rtx dst_high_part_l32_tmpl; ++ ++ rtx src_low_part, src_high_part; ++ rtx dst_high_part, dst_low_part; ++ ++ shiftamount = force_reg (SImode, shiftamount); ++ ++ emit_insn (gen_andsi3 (shiftamount, ++ shiftamount, ++ gen_int_mode (0x3f, SImode))); ++ ++ dst_high_part = nds32_di_high_part_subreg (dst); ++ dst_low_part = nds32_di_low_part_subreg (dst); ++ ++ src_high_part = nds32_di_high_part_subreg (src); ++ src_low_part = nds32_di_low_part_subreg (src); ++ ++ dst_low_part_l32 = gen_reg_rtx (SImode); ++ dst_high_part_l32 = gen_reg_rtx (SImode); ++ dst_low_part_g32 = gen_reg_rtx (SImode); ++ dst_high_part_g32 = gen_reg_rtx (SImode); ++ low5bit = gen_reg_rtx (SImode); ++ low5bit_inv = gen_reg_rtx (SImode); ++ minus32sa = gen_reg_rtx (SImode); ++ select_reg = gen_reg_rtx (SImode); ++ ++ dst_low_part_g32_tmph = gen_reg_rtx (SImode); ++ dst_low_part_g32_tmpl = gen_reg_rtx (SImode); ++ ++ dst_high_part_l32_tmph = gen_reg_rtx (SImode); ++ dst_high_part_l32_tmpl = gen_reg_rtx (SImode); ++ ++ emit_insn (gen_slt_compare (select_reg, shiftamount, GEN_INT (32))); ++ ++ /* if shiftamount < 32 ++ dst_low_part = wext(src, shiftamount) ++ else ++ dst_low_part = ((src_high_part >> (shiftamount & 0x1f)) ++ | (src_low_part << (32 - (shiftamount & 0x1f)))) ++ */ ++ emit_insn (gen_andsi3 (low5bit, shiftamount, gen_int_mode (0x1f, SImode))); ++ emit_insn (gen_subsi3 (low5bit_inv, gen_int_mode (32, SImode), low5bit)); ++ ++ emit_insn (gen_wext (dst_low_part_l32, src, shiftamount)); ++ ++ emit_insn (gen_lshrsi3 (dst_low_part_g32_tmpl, src_high_part, low5bit)); ++ emit_insn (gen_ashlsi3 (dst_low_part_g32_tmph, src_low_part, low5bit_inv)); ++ ++ emit_insn (gen_iorsi3 (dst_low_part_g32, ++ dst_low_part_g32_tmpl, ++ dst_low_part_g32_tmph)); ++ ++ emit_insn (gen_cmovnsi (dst_low_part, select_reg, ++ dst_low_part_l32, dst_low_part_g32)); ++ ++ /* if shiftamount < 32 ++ dst_high_part = ((src_high_part >> shiftamount) ++ | (src_low_part << (32 - shiftamount))) ++ dst_high_part = shiftamount == 0 ? src_high_part : dst_high_part ++ else ++ dst_high_part = wext(src, shiftamount & 0x1f) ++ */ ++ ++ emit_insn (gen_subsi3 (minus32sa, gen_int_mode (32, SImode), shiftamount)); ++ ++ emit_insn (gen_lshrsi3 (dst_high_part_l32_tmpl, src_high_part, shiftamount)); ++ emit_insn (gen_ashlsi3 (dst_high_part_l32_tmph, src_low_part, minus32sa)); ++ ++ emit_insn (gen_iorsi3 (dst_high_part_l32, ++ dst_high_part_l32_tmpl, ++ dst_high_part_l32_tmph)); ++ ++ emit_insn (gen_cmovzsi (dst_high_part_l32, shiftamount, ++ src_high_part, dst_high_part_l32)); ++ ++ emit_insn (gen_wext (dst_high_part_g32, src, low5bit)); ++ ++ emit_insn (gen_cmovnsi (dst_high_part, select_reg, ++ dst_high_part_l32, dst_high_part_g32)); ++} ++ ++/* Return true if OP contains a symbol reference. */ ++bool ++symbolic_reference_mentioned_p (rtx op) ++{ ++ const char *fmt; ++ int i; ++ ++ if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) ++ return true; ++ ++ fmt = GET_RTX_FORMAT (GET_CODE (op)); ++ for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) ++ { ++ if (fmt[i] == 'E') ++ { ++ int j; ++ ++ for (j = XVECLEN (op, i) - 1; j >= 0; j--) ++ if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) ++ return true; ++ } ++ ++ else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i))) ++ return true; ++ } ++ ++ return false; ++} ++ ++/* Expand PIC code for @GOTOFF and @GOT. ++ ++ Example for @GOTOFF: ++ ++ la $r0, symbol@GOTOFF ++ -> sethi $ta, hi20(symbol@GOTOFF) ++ ori $ta, $ta, lo12(symbol@GOTOFF) ++ add $r0, $ta, $gp ++ ++ Example for @GOT: ++ ++ la $r0, symbol@GOT ++ -> sethi $ta, hi20(symbol@GOT) ++ ori $ta, $ta, lo12(symbol@GOT) ++ lw $r0, [$ta + $gp] ++*/ ++rtx ++nds32_legitimize_pic_address (rtx x) ++{ ++ rtx addr = x; ++ rtx reg = gen_reg_rtx (Pmode); ++ rtx pat; ++ ++ if (GET_CODE (x) == LABEL_REF ++ || (GET_CODE (x) == SYMBOL_REF ++ && (CONSTANT_POOL_ADDRESS_P (x) ++ || SYMBOL_REF_LOCAL_P (x)))) ++ { ++ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_GOTOFF); ++ addr = gen_rtx_CONST (SImode, addr); ++ emit_insn (gen_sethi (reg, addr)); ++ emit_insn (gen_lo_sum (reg, reg, addr)); ++ x = gen_rtx_PLUS (Pmode, reg, pic_offset_table_rtx); ++ } ++ else if (GET_CODE (x) == SYMBOL_REF) ++ { ++ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_GOT); ++ addr = gen_rtx_CONST (SImode, addr); ++ emit_insn (gen_sethi (reg, addr)); ++ emit_insn (gen_lo_sum (reg, reg, addr)); ++ ++ x = gen_const_mem (SImode, gen_rtx_PLUS (Pmode, pic_offset_table_rtx, ++ reg)); ++ } ++ else if (GET_CODE (x) == CONST) ++ { ++ /* We don't split constant in expand_pic_move because GOTOFF can combine ++ the addend with the symbol. */ ++ addr = XEXP (x, 0); ++ gcc_assert (GET_CODE (addr) == PLUS); ++ ++ rtx op0 = XEXP (addr, 0); ++ rtx op1 = XEXP (addr, 1); ++ ++ if ((GET_CODE (op0) == LABEL_REF ++ || (GET_CODE (op0) == SYMBOL_REF ++ && (CONSTANT_POOL_ADDRESS_P (op0) ++ || SYMBOL_REF_LOCAL_P (op0)))) ++ && GET_CODE (op1) == CONST_INT) ++ { ++ pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), UNSPEC_GOTOFF); ++ pat = gen_rtx_PLUS (Pmode, pat, op1); ++ pat = gen_rtx_CONST (Pmode, pat); ++ emit_insn (gen_sethi (reg, pat)); ++ emit_insn (gen_lo_sum (reg, reg, pat)); ++ x = gen_rtx_PLUS (Pmode, reg, pic_offset_table_rtx); ++ } ++ else if (GET_CODE (op0) == SYMBOL_REF ++ && GET_CODE (op1) == CONST_INT) ++ { ++ /* This is a constant offset from a @GOT symbol reference. */ ++ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, op0), UNSPEC_GOT); ++ addr = gen_rtx_CONST (SImode, addr); ++ emit_insn (gen_sethi (reg, addr)); ++ emit_insn (gen_lo_sum (reg, reg, addr)); ++ addr = gen_const_mem (SImode, gen_rtx_PLUS (Pmode, ++ pic_offset_table_rtx, ++ reg)); ++ emit_move_insn (reg, addr); ++ if (satisfies_constraint_Is15 (op1)) ++ x = gen_rtx_PLUS (Pmode, reg, op1); ++ else ++ { ++ rtx tmp_reg = gen_reg_rtx (SImode); ++ emit_insn (gen_movsi (tmp_reg, op1)); ++ x = gen_rtx_PLUS (Pmode, reg, tmp_reg); ++ } ++ } ++ else ++ { ++ /* Don't handle this pattern. */ ++ debug_rtx (x); ++ gcc_unreachable (); ++ } ++ } ++ return x; ++} ++ ++void ++nds32_expand_pic_move (rtx *operands) ++{ ++ rtx src; ++ ++ src = nds32_legitimize_pic_address (operands[1]); ++ emit_move_insn (operands[0], src); ++} ++ ++/* Expand ICT symbol. ++ Example for @ICT and ICT model=large: ++ ++ la $r0, symbol@ICT ++ -> sethi $rt, hi20(symbol@ICT) ++ lwi $r0, [$rt + lo12(symbol@ICT)] ++ ++*/ ++rtx ++nds32_legitimize_ict_address (rtx x) ++{ ++ rtx symbol = x; ++ rtx addr = x; ++ rtx reg = gen_reg_rtx (Pmode); ++ gcc_assert (GET_CODE (x) == SYMBOL_REF ++ && nds32_indirect_call_referenced_p (x)); ++ ++ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, symbol), UNSPEC_ICT); ++ addr = gen_rtx_CONST (SImode, addr); ++ emit_insn (gen_sethi (reg, addr)); ++ ++ x = gen_const_mem (SImode, gen_rtx_LO_SUM (Pmode, reg, addr)); ++ ++ return x; ++} ++ ++void ++nds32_expand_ict_move (rtx *operands) ++{ ++ rtx src = operands[1]; ++ ++ src = nds32_legitimize_ict_address (src); ++ ++ emit_move_insn (operands[0], src); ++} ++ ++/* Return true X is a indirect call symbol. */ ++bool ++nds32_indirect_call_referenced_p (rtx x) ++{ ++ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_ICT) ++ x = XVECEXP (x, 0, 0); ++ ++ if (GET_CODE (x) == SYMBOL_REF) ++ { ++ tree decl = SYMBOL_REF_DECL (x); ++ ++ return decl ++ && (lookup_attribute("indirect_call", ++ DECL_ATTRIBUTES(decl)) ++ != NULL); ++ } ++ ++ return false; ++} ++ + /* Return true X is need use long call. */ + bool + nds32_long_call_p (rtx symbol) + { +- return TARGET_CMODEL_LARGE; ++ if (nds32_indirect_call_referenced_p (symbol)) ++ return TARGET_ICT_MODEL_LARGE; ++ else ++ return TARGET_CMODEL_LARGE; ++} ++ ++/* Return true if X contains a thread-local symbol. */ ++bool ++nds32_tls_referenced_p (rtx x) ++{ ++ if (!targetm.have_tls) ++ return false; ++ ++ if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS) ++ x = XEXP (XEXP (x, 0), 0); ++ ++ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x)) ++ return true; ++ ++ return false; ++} ++ ++/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute ++ this (thread-local) address. */ ++rtx ++nds32_legitimize_tls_address (rtx x) ++{ ++ rtx tmp_reg; ++ rtx tp_reg = gen_rtx_REG (Pmode, TP_REGNUM); ++ rtx pat, insns, reg0; ++ ++ if (GET_CODE (x) == SYMBOL_REF) ++ switch (SYMBOL_REF_TLS_MODEL (x)) ++ { ++ case TLS_MODEL_GLOBAL_DYNAMIC: ++ case TLS_MODEL_LOCAL_DYNAMIC: ++ /* Emit UNSPEC_TLS_DESC rather than expand rtl directly because spill ++ may destroy the define-use chain anylysis to insert relax_hint. */ ++ if (SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_GLOBAL_DYNAMIC) ++ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_TLSGD); ++ else ++ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_TLSLD); ++ ++ pat = gen_rtx_CONST (SImode, pat); ++ reg0 = gen_rtx_REG (Pmode, 0); ++ /* If we can confirm all clobber reigsters, it doesn't have to use call ++ instruction. */ ++ insns = emit_call_insn (gen_tls_desc (pat, GEN_INT (0))); ++ use_reg (&CALL_INSN_FUNCTION_USAGE (insns), pic_offset_table_rtx); ++ RTL_CONST_CALL_P (insns) = 1; ++ tmp_reg = gen_reg_rtx (SImode); ++ emit_move_insn (tmp_reg, reg0); ++ x = tmp_reg; ++ break; ++ ++ case TLS_MODEL_INITIAL_EXEC: ++ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_TLSIE); ++ tmp_reg = gen_reg_rtx (SImode); ++ pat = gen_rtx_CONST (SImode, pat); ++ emit_insn (gen_tls_ie (tmp_reg, pat, GEN_INT (0))); ++ if (flag_pic) ++ emit_use (pic_offset_table_rtx); ++ x = gen_rtx_PLUS (Pmode, tmp_reg, tp_reg); ++ break; ++ ++ case TLS_MODEL_LOCAL_EXEC: ++ /* Expand symbol_ref@TPOFF': ++ sethi $ta, hi20(symbol_ref@TPOFF) ++ ori $ta, $ta, lo12(symbol_ref@TPOFF) ++ add $r0, $ta, $tp */ ++ tmp_reg = gen_reg_rtx (SImode); ++ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_TLSLE); ++ pat = gen_rtx_CONST (SImode, pat); ++ emit_insn (gen_sethi (tmp_reg, pat)); ++ emit_insn (gen_lo_sum (tmp_reg, tmp_reg, pat)); ++ x = gen_rtx_PLUS (Pmode, tmp_reg, tp_reg); ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ else if (GET_CODE (x) == CONST) ++ { ++ rtx base, addend; ++ split_const (x, &base, &addend); ++ ++ if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_LOCAL_EXEC) ++ { ++ /* Expand symbol_ref@TPOFF': ++ sethi $ta, hi20(symbol_ref@TPOFF + addend) ++ ori $ta, $ta, lo12(symbol_ref@TPOFF + addend) ++ add $r0, $ta, $tp */ ++ tmp_reg = gen_reg_rtx (SImode); ++ pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, base), UNSPEC_TLSLE); ++ pat = gen_rtx_PLUS (SImode, pat, addend); ++ pat = gen_rtx_CONST (SImode, pat); ++ emit_insn (gen_sethi (tmp_reg, pat)); ++ emit_insn (gen_lo_sum (tmp_reg, tmp_reg, pat)); ++ x = gen_rtx_PLUS (Pmode, tmp_reg, tp_reg); ++ } ++ } ++ ++ return x; ++} ++ ++void ++nds32_expand_tls_move (rtx *operands) ++{ ++ rtx src = operands[1]; ++ rtx base, addend; ++ ++ if (CONSTANT_P (src)) ++ split_const (src, &base, &addend); ++ ++ if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_LOCAL_EXEC) ++ src = nds32_legitimize_tls_address (src); ++ else ++ { ++ src = nds32_legitimize_tls_address (base); ++ if (addend != const0_rtx) ++ { ++ src = gen_rtx_PLUS (SImode, src, addend); ++ src = force_operand (src, operands[0]); ++ } ++ } ++ ++ emit_move_insn (operands[0], src); + } + + void +@@ -2976,3 +3812,105 @@ + emit_move_insn (target, gen_rtx_fmt_ee (AND, mode, source, temp)); + } + } ++ ++/* Auxiliary functions for lwm/smw. */ ++bool ++nds32_valid_smw_lwm_base_p (rtx op) ++{ ++ rtx base_addr; ++ ++ if (!MEM_P (op)) ++ return false; ++ ++ base_addr = XEXP (op, 0); ++ ++ if (REG_P (base_addr)) ++ return true; ++ else ++ { ++ if (GET_CODE (base_addr) == POST_INC ++ && REG_P (XEXP (base_addr, 0))) ++ return true; ++ } ++ ++ return false; ++} ++ ++/* Auxiliary functions for manipulation DI mode. */ ++rtx nds32_di_high_part_subreg(rtx reg) ++{ ++ unsigned high_part_offset = subreg_highpart_offset (SImode, DImode); ++ ++ return simplify_gen_subreg ( ++ SImode, reg, ++ DImode, high_part_offset); ++} ++ ++rtx nds32_di_low_part_subreg(rtx reg) ++{ ++ unsigned low_part_offset = subreg_lowpart_offset (SImode, DImode); ++ ++ return simplify_gen_subreg ( ++ SImode, reg, ++ DImode, low_part_offset); ++} ++ ++/* ------------------------------------------------------------------------ */ ++ ++/* Auxiliary function for output TLS patterns. */ ++ ++const char * ++nds32_output_tls_desc (rtx *operands) ++{ ++ char pattern[1000]; ++ ++ if (TARGET_RELAX_HINT) ++ snprintf (pattern, sizeof (pattern), ++ ".relax_hint %%1\n\tsethi $r0, hi20(%%0)\n\t" ++ ".relax_hint %%1\n\tori $r0, $r0, lo12(%%0)\n\t" ++ ".relax_hint %%1\n\tlw $r15, [$r0 + $gp]\n\t" ++ ".relax_hint %%1\n\tadd $r0, $r0, $gp\n\t" ++ ".relax_hint %%1\n\tjral $r15"); ++ else ++ snprintf (pattern, sizeof (pattern), ++ "sethi $r0, hi20(%%0)\n\t" ++ "ori $r0, $r0, lo12(%%0)\n\t" ++ "lw $r15, [$r0 + $gp]\n\t" ++ "add $r0, $r0, $gp\n\t" ++ "jral $r15"); ++ output_asm_insn (pattern, operands); ++ return ""; ++} ++ ++const char * ++nds32_output_tls_ie (rtx *operands) ++{ ++ char pattern[1000]; ++ ++ if (flag_pic) ++ { ++ if (TARGET_RELAX_HINT) ++ snprintf (pattern, sizeof (pattern), ++ ".relax_hint %%2\n\tsethi %%0, hi20(%%1)\n\t" ++ ".relax_hint %%2\n\tori %%0, %%0, lo12(%%1)\n\t" ++ ".relax_hint %%2\n\tlw %%0, [%%0 + $gp]"); ++ else ++ snprintf (pattern, sizeof (pattern), ++ "sethi %%0, hi20(%%1)\n\t" ++ "ori %%0, %%0, lo12(%%1)\n\t" ++ "lw %%0, [%%0 + $gp]"); ++ } ++ else ++ { ++ if (TARGET_RELAX_HINT) ++ snprintf (pattern, sizeof (pattern), ++ ".relax_hint %%2\n\tsethi %%0, hi20(%%1)\n\t" ++ ".relax_hint %%2\n\tlwi %%0, [%%0 + lo12(%%1)]"); ++ else ++ snprintf (pattern, sizeof (pattern), ++ "sethi %%0, hi20(%%1)\n\t" ++ "lwi %%0, [%%0 + lo12(%%1)]"); ++ } ++ output_asm_insn (pattern, operands); ++ return ""; ++} +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-memory-manipulation.c gcc-8.2.0/gcc/config/nds32/nds32-memory-manipulation.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-memory-manipulation.c 2018-03-11 09:24:33.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-memory-manipulation.c 2019-01-25 15:38:32.829242659 +0100 +@@ -257,8 +257,124 @@ + nds32_expand_movmemsi_loop_known_size (rtx dstmem, rtx srcmem, + rtx size, rtx alignment) + { +- return nds32_expand_movmemsi_loop_unknown_size (dstmem, srcmem, +- size, alignment); ++ rtx dst_base_reg, src_base_reg; ++ rtx dst_itr, src_itr; ++ rtx dstmem_m, srcmem_m, dst_itr_m, src_itr_m; ++ rtx dst_end; ++ rtx double_word_mode_loop, byte_mode_loop; ++ rtx tmp; ++ int start_regno; ++ bool align_to_4_bytes = (INTVAL (alignment) & 3) == 0; ++ unsigned HOST_WIDE_INT total_bytes = UINTVAL (size); ++ ++ if (TARGET_ISA_V3M && !align_to_4_bytes) ++ return 0; ++ ++ if (TARGET_REDUCED_REGS) ++ start_regno = 2; ++ else ++ start_regno = 16; ++ ++ dst_itr = gen_reg_rtx (Pmode); ++ src_itr = gen_reg_rtx (Pmode); ++ dst_end = gen_reg_rtx (Pmode); ++ tmp = gen_reg_rtx (QImode); ++ ++ double_word_mode_loop = gen_label_rtx (); ++ byte_mode_loop = gen_label_rtx (); ++ ++ dst_base_reg = copy_to_mode_reg (Pmode, XEXP (dstmem, 0)); ++ src_base_reg = copy_to_mode_reg (Pmode, XEXP (srcmem, 0)); ++ ++ if (total_bytes < 8) ++ { ++ /* Emit total_bytes less than 8 loop version of movmem. ++ add $dst_end, $dst, $size ++ move $dst_itr, $dst ++ .Lbyte_mode_loop: ++ lbi.bi $tmp, [$src_itr], #1 ++ sbi.bi $tmp, [$dst_itr], #1 ++ ! Not readch upper bound. Loop. ++ bne $dst_itr, $dst_end, .Lbyte_mode_loop */ ++ ++ /* add $dst_end, $dst, $size */ ++ dst_end = expand_binop (Pmode, add_optab, dst_base_reg, size, ++ NULL_RTX, 0, OPTAB_WIDEN); ++ /* move $dst_itr, $dst ++ move $src_itr, $src */ ++ emit_move_insn (dst_itr, dst_base_reg); ++ emit_move_insn (src_itr, src_base_reg); ++ ++ /* .Lbyte_mode_loop: */ ++ emit_label (byte_mode_loop); ++ ++ /* lbi.bi $tmp, [$src_itr], #1 */ ++ nds32_emit_post_inc_load_store (tmp, src_itr, QImode, true); ++ ++ /* sbi.bi $tmp, [$dst_itr], #1 */ ++ nds32_emit_post_inc_load_store (tmp, dst_itr, QImode, false); ++ /* ! Not readch upper bound. Loop. ++ bne $dst_itr, $dst_end, .Lbyte_mode_loop */ ++ emit_cmp_and_jump_insns (dst_itr, dst_end, NE, NULL, ++ SImode, 1, byte_mode_loop); ++ return true; ++ } ++ else if (total_bytes % 8 == 0) ++ { ++ /* Emit multiple of 8 loop version of movmem. ++ ++ add $dst_end, $dst, $size ++ move $dst_itr, $dst ++ move $src_itr, $src ++ ++ .Ldouble_word_mode_loop: ++ lmw.bim $tmp-begin, [$src_itr], $tmp-end, #0 ! $src_itr' = $src_itr ++ smw.bim $tmp-begin, [$dst_itr], $tmp-end, #0 ! $dst_itr' = $dst_itr ++ ! move will delete after register allocation ++ move $src_itr, $src_itr' ++ move $dst_itr, $dst_itr' ++ ! Not readch upper bound. Loop. ++ bne $double_word_end, $dst_itr, .Ldouble_word_mode_loop */ ++ ++ /* add $dst_end, $dst, $size */ ++ dst_end = expand_binop (Pmode, add_optab, dst_base_reg, size, ++ NULL_RTX, 0, OPTAB_WIDEN); ++ ++ /* move $dst_itr, $dst ++ move $src_itr, $src */ ++ emit_move_insn (dst_itr, dst_base_reg); ++ emit_move_insn (src_itr, src_base_reg); ++ ++ /* .Ldouble_word_mode_loop: */ ++ emit_label (double_word_mode_loop); ++ /* lmw.bim $tmp-begin, [$src_itr], $tmp-end, #0 ! $src_itr' = $src_itr ++ smw.bim $tmp-begin, [$dst_itr], $tmp-end, #0 ! $dst_itr' = $dst_itr */ ++ src_itr_m = src_itr; ++ dst_itr_m = dst_itr; ++ srcmem_m = srcmem; ++ dstmem_m = dstmem; ++ nds32_emit_mem_move_block (start_regno, 2, ++ &dst_itr_m, &dstmem_m, ++ &src_itr_m, &srcmem_m, ++ true); ++ /* move $src_itr, $src_itr' ++ move $dst_itr, $dst_itr' */ ++ emit_move_insn (dst_itr, dst_itr_m); ++ emit_move_insn (src_itr, src_itr_m); ++ ++ /* ! Not readch upper bound. Loop. ++ bne $double_word_end, $dst_itr, .Ldouble_word_mode_loop */ ++ emit_cmp_and_jump_insns (dst_end, dst_itr, NE, NULL, ++ Pmode, 1, double_word_mode_loop); ++ } ++ else ++ { ++ /* Handle size greater than 8, and not a multiple of 8. */ ++ return nds32_expand_movmemsi_loop_unknown_size (dstmem, srcmem, ++ size, alignment); ++ } ++ ++ return true; + } + + static bool +@@ -433,10 +549,8 @@ + /* Auxiliary function for expand setmem pattern. */ + + static rtx +-nds32_gen_dup_4_byte_to_word_value (rtx value) ++nds32_gen_dup_4_byte_to_word_value_aux (rtx value, rtx value4word) + { +- rtx value4word = gen_reg_rtx (SImode); +- + gcc_assert (GET_MODE (value) == QImode || CONST_INT_P (value)); + + if (CONST_INT_P (value)) +@@ -449,36 +563,74 @@ + } + else + { +- /* ! prepare word +- andi $tmp1, $value, 0xff ! $tmp1 <- 0x000000ab +- slli $tmp2, $tmp1, 8 ! $tmp2 <- 0x0000ab00 +- or $tmp3, $tmp1, $tmp2 ! $tmp3 <- 0x0000abab +- slli $tmp4, $tmp3, 16 ! $tmp4 <- 0xabab0000 +- or $val4word, $tmp3, $tmp4 ! $value4word <- 0xabababab */ +- +- rtx tmp1, tmp2, tmp3, tmp4, final_value; +- tmp1 = expand_binop (SImode, and_optab, value, +- gen_int_mode (0xff, SImode), +- NULL_RTX, 0, OPTAB_WIDEN); +- tmp2 = expand_binop (SImode, ashl_optab, tmp1, +- gen_int_mode (8, SImode), +- NULL_RTX, 0, OPTAB_WIDEN); +- tmp3 = expand_binop (SImode, ior_optab, tmp1, tmp2, +- NULL_RTX, 0, OPTAB_WIDEN); +- tmp4 = expand_binop (SImode, ashl_optab, tmp3, +- gen_int_mode (16, SImode), +- NULL_RTX, 0, OPTAB_WIDEN); +- +- final_value = expand_binop (SImode, ior_optab, tmp3, tmp4, +- NULL_RTX, 0, OPTAB_WIDEN); +- emit_move_insn (value4word, final_value); ++ if (NDS32_EXT_DSP_P ()) ++ { ++ /* ! prepare word ++ insb $tmp, $value, 1 ! $tmp <- 0x0000abab ++ pkbb16 $tmp6, $tmp2, $tmp2 ! $value4word <- 0xabababab */ ++ rtx tmp = gen_reg_rtx (SImode); ++ ++ convert_move (tmp, value, true); ++ ++ emit_insn ( ++ gen_insvsi_internal (tmp, gen_int_mode (0x8, SImode), tmp)); ++ ++ emit_insn (gen_pkbbsi_1 (value4word, tmp, tmp)); ++ } ++ else ++ { ++ /* ! prepare word ++ andi $tmp1, $value, 0xff ! $tmp1 <- 0x000000ab ++ slli $tmp2, $tmp1, 8 ! $tmp2 <- 0x0000ab00 ++ or $tmp3, $tmp1, $tmp2 ! $tmp3 <- 0x0000abab ++ slli $tmp4, $tmp3, 16 ! $tmp4 <- 0xabab0000 ++ or $val4word, $tmp3, $tmp4 ! $value4word <- 0xabababab */ ++ ++ rtx tmp1, tmp2, tmp3, tmp4; ++ tmp1 = expand_binop (SImode, and_optab, value, ++ gen_int_mode (0xff, SImode), ++ NULL_RTX, 0, OPTAB_WIDEN); ++ tmp2 = expand_binop (SImode, ashl_optab, tmp1, ++ gen_int_mode (8, SImode), ++ NULL_RTX, 0, OPTAB_WIDEN); ++ tmp3 = expand_binop (SImode, ior_optab, tmp1, tmp2, ++ NULL_RTX, 0, OPTAB_WIDEN); ++ tmp4 = expand_binop (SImode, ashl_optab, tmp3, ++ gen_int_mode (16, SImode), ++ NULL_RTX, 0, OPTAB_WIDEN); ++ ++ emit_insn (gen_iorsi3 (value4word, tmp3, tmp4)); ++ } + } + + return value4word; + } + + static rtx +-emit_setmem_word_loop (rtx itr, rtx size, rtx value) ++nds32_gen_dup_4_byte_to_word_value (rtx value) ++{ ++ rtx value4word = gen_reg_rtx (SImode); ++ nds32_gen_dup_4_byte_to_word_value_aux (value, value4word); ++ ++ return value4word; ++} ++ ++static rtx ++nds32_gen_dup_8_byte_to_double_word_value (rtx value) ++{ ++ rtx value4doubleword = gen_reg_rtx (DImode); ++ ++ nds32_gen_dup_4_byte_to_word_value_aux ( ++ value, nds32_di_low_part_subreg(value4doubleword)); ++ ++ emit_move_insn (nds32_di_high_part_subreg(value4doubleword), ++ nds32_di_low_part_subreg(value4doubleword)); ++ return value4doubleword; ++} ++ ++ ++static rtx ++emit_setmem_doubleword_loop (rtx itr, rtx size, rtx value) + { + rtx word_mode_label = gen_label_rtx (); + rtx word_mode_end_label = gen_label_rtx (); +@@ -487,9 +639,9 @@ + rtx word_mode_end = gen_reg_rtx (SImode); + rtx size_for_word = gen_reg_rtx (SImode); + +- /* and $size_for_word, $size, #~3 */ ++ /* and $size_for_word, $size, #~0x7 */ + size_for_word = expand_binop (SImode, and_optab, size, +- gen_int_mode (~3, SImode), ++ gen_int_mode (~0x7, SImode), + NULL_RTX, 0, OPTAB_WIDEN); + + emit_move_insn (byte_mode_size, size); +@@ -501,8 +653,8 @@ + word_mode_end = expand_binop (Pmode, add_optab, itr, size_for_word, + NULL_RTX, 0, OPTAB_WIDEN); + +- /* andi $byte_mode_size, $size, 3 */ +- byte_mode_size_tmp = expand_binop (SImode, and_optab, size, GEN_INT (3), ++ /* andi $byte_mode_size, $size, 0x7 */ ++ byte_mode_size_tmp = expand_binop (SImode, and_optab, size, GEN_INT (0x7), + NULL_RTX, 0, OPTAB_WIDEN); + + emit_move_insn (byte_mode_size, byte_mode_size_tmp); +@@ -512,9 +664,9 @@ + /* ! word-mode set loop + smw.bim $value4word, [$dst_itr], $value4word, 0 + bne $word_mode_end, $dst_itr, .Lword_mode */ +- emit_insn (gen_unaligned_store_update_base_w (itr, +- itr, +- value)); ++ emit_insn (gen_unaligned_store_update_base_dw (itr, ++ itr, ++ value)); + emit_cmp_and_jump_insns (word_mode_end, itr, NE, NULL, + Pmode, 1, word_mode_label); + +@@ -566,7 +718,7 @@ + static bool + nds32_expand_setmem_loop (rtx dstmem, rtx size, rtx value) + { +- rtx value4word; ++ rtx value4doubleword; + rtx value4byte; + rtx dst; + rtx byte_mode_size; +@@ -609,7 +761,7 @@ + or $tmp3, $tmp1, $tmp2 ! $tmp3 <- 0x0000abab + slli $tmp4, $tmp3, 16 ! $tmp4 <- 0xabab0000 + or $val4word, $tmp3, $tmp4 ! $value4word <- 0xabababab */ +- value4word = nds32_gen_dup_4_byte_to_word_value (value); ++ value4doubleword = nds32_gen_dup_8_byte_to_double_word_value (value); + + /* and $size_for_word, $size, #-4 + beqz $size_for_word, .Lword_mode_end +@@ -622,7 +774,7 @@ + smw.bim $value4word, [$dst], $value4word, 0 + bne $word_mode_end, $dst, .Lword_mode + .Lword_mode_end: */ +- byte_mode_size = emit_setmem_word_loop (dst, size, value4word); ++ byte_mode_size = emit_setmem_doubleword_loop (dst, size, value4doubleword); + + /* beqz $byte_mode_size, .Lend + add $byte_mode_end, $dst, $byte_mode_size +@@ -633,8 +785,8 @@ + bne $byte_mode_end, $dst, .Lbyte_mode + .Lend: */ + +- value4byte = simplify_gen_subreg (QImode, value4word, SImode, +- subreg_lowpart_offset (QImode, SImode)); ++ value4byte = simplify_gen_subreg (QImode, value4doubleword, DImode, ++ subreg_lowpart_offset (QImode, DImode)); + + emit_setmem_byte_loop (dst, byte_mode_size, value4byte, false); + +@@ -651,14 +803,15 @@ + rtx byte_loop_size = gen_reg_rtx (SImode); + rtx remain_size = gen_reg_rtx (SImode); + rtx new_base_reg; +- rtx value4byte, value4word; ++ rtx value4byte, value4doubleword; + rtx byte_mode_size; + rtx last_byte_loop_label = gen_label_rtx (); + + size = force_reg (SImode, size); + +- value4word = nds32_gen_dup_4_byte_to_word_value (value); +- value4byte = simplify_gen_subreg (QImode, value4word, SImode, 0); ++ value4doubleword = nds32_gen_dup_8_byte_to_double_word_value (value); ++ value4byte = simplify_gen_subreg (QImode, value4doubleword, DImode, ++ subreg_lowpart_offset (QImode, DImode)); + + emit_move_insn (byte_loop_size, size); + emit_move_insn (byte_loop_base, base_reg); +@@ -686,9 +839,9 @@ + emit_insn (gen_subsi3 (remain_size, size, need_align_bytes)); + + /* Set memory word by word. */ +- byte_mode_size = emit_setmem_word_loop (new_base_reg, +- remain_size, +- value4word); ++ byte_mode_size = emit_setmem_doubleword_loop (new_base_reg, ++ remain_size, ++ value4doubleword); + + emit_move_insn (byte_loop_base, new_base_reg); + emit_move_insn (byte_loop_size, byte_mode_size); +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-multiple.md gcc-8.2.0/gcc/config/nds32/nds32-multiple.md +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-multiple.md 2018-03-11 09:24:33.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-multiple.md 2019-01-25 15:38:32.829242659 +0100 +@@ -2854,6 +2854,25 @@ + (set_attr "length" "4")] + ) + ++(define_expand "unaligned_store_update_base_dw" ++ [(parallel [(set (match_operand:SI 0 "register_operand" "=r") ++ (plus:SI (match_operand:SI 1 "register_operand" "0") (const_int 8))) ++ (set (mem:DI (match_dup 1)) ++ (unspec:DI [(match_operand:DI 2 "register_operand" "r")] UNSPEC_UASTORE_DW))])] ++ "" ++{ ++ /* DO NOT emit unaligned_store_w_m immediately since web pass don't ++ recognize post_inc, try it again after GCC 5.0. ++ REF: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63156 */ ++ emit_insn (gen_unaligned_store_dw (gen_rtx_MEM (DImode, operands[1]), operands[2])); ++ emit_insn (gen_addsi3 (operands[0], operands[1], gen_int_mode (8, Pmode))); ++ DONE; ++} ++ [(set_attr "type" "store_multiple") ++ (set_attr "combo" "2") ++ (set_attr "length" "4")] ++) ++ + (define_insn "*stmsi25" + [(match_parallel 0 "nds32_store_multiple_operation" + [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-n10.md gcc-8.2.0/gcc/config/nds32/nds32-n10.md +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-n10.md 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-n10.md 2019-01-25 15:38:32.829242659 +0100 +@@ -0,0 +1,439 @@ ++;; Pipeline descriptions 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 ++;; . ++ ++ ++;; ------------------------------------------------------------------------ ++;; Define N10 pipeline settings. ++;; ------------------------------------------------------------------------ ++ ++(define_automaton "nds32_n10_machine") ++ ++;; ------------------------------------------------------------------------ ++;; Pipeline Stages ++;; ------------------------------------------------------------------------ ++;; IF - Instruction Fetch ++;; II - Instruction Issue / Instruction Decode ++;; EX - Instruction Execution ++;; MM - Memory Execution ++;; WB - Instruction Retire / Result Write-Back ++ ++(define_cpu_unit "n10_ii" "nds32_n10_machine") ++(define_cpu_unit "n10_ex" "nds32_n10_machine") ++(define_cpu_unit "n10_mm" "nds32_n10_machine") ++(define_cpu_unit "n10_wb" "nds32_n10_machine") ++(define_cpu_unit "n10f_iq" "nds32_n10_machine") ++(define_cpu_unit "n10f_rf" "nds32_n10_machine") ++(define_cpu_unit "n10f_e1" "nds32_n10_machine") ++(define_cpu_unit "n10f_e2" "nds32_n10_machine") ++(define_cpu_unit "n10f_e3" "nds32_n10_machine") ++(define_cpu_unit "n10f_e4" "nds32_n10_machine") ++ ++(define_insn_reservation "nds_n10_unknown" 1 ++ (and (eq_attr "type" "unknown") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_misc" 1 ++ (and (eq_attr "type" "misc") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_mmu" 1 ++ (and (eq_attr "type" "mmu") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_alu" 1 ++ (and (eq_attr "type" "alu") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_alu_shift" 1 ++ (and (eq_attr "type" "alu_shift") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ii+n10_ex, n10_ex+n10_mm, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_pbsad" 1 ++ (and (eq_attr "type" "pbsad") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex*3, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_pbsada" 1 ++ (and (eq_attr "type" "pbsada") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex*3, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_load" 1 ++ (and (match_test "nds32::load_single_p (insn)") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_store" 1 ++ (and (match_test "nds32::store_single_p (insn)") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_load_multiple_1" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "1"))) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_load_multiple_2" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (ior (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "2")) ++ (match_test "nds32::load_double_p (insn)"))) ++ "n10_ii, n10_ii+n10_ex, n10_ex+n10_mm, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_load_multiple_3" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "3"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_load_multiple_4" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "4"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, n10_ii+n10_ex+n10_mm+n10_wb, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_load_multiple_5" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "5"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*2, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_load_multiple_6" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "6"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*3, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_load_multiple_7" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "7"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*4, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_load_multiple_N" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "load_multiple") ++ (match_test "get_attr_combo (insn) >= 8"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*5, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_store_multiple_1" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "1"))) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_store_multiple_2" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (ior (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "2")) ++ (match_test "nds32::store_double_p (insn)"))) ++ "n10_ii, n10_ii+n10_ex, n10_ex+n10_mm, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_store_multiple_3" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "3"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_store_multiple_4" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "4"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, n10_ii+n10_ex+n10_mm+n10_wb, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_store_multiple_5" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "5"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*2, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_store_multiple_6" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "6"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*3, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_store_multiple_7" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "7"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*4, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_store_multiple_N" 1 ++ (and (eq_attr "pipeline_model" "n10") ++ (and (eq_attr "type" "store_multiple") ++ (match_test "get_attr_combo (insn) >= 8"))) ++ "n10_ii, n10_ii+n10_ex, n10_ii+n10_ex+n10_mm, (n10_ii+n10_ex+n10_mm+n10_wb)*5, n10_ex+n10_mm+n10_wb, n10_mm+n10_wb, n10_wb") ++ ++(define_insn_reservation "nds_n10_mul" 1 ++ (and (eq_attr "type" "mul") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_mac" 1 ++ (and (eq_attr "type" "mac") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_div" 1 ++ (and (eq_attr "type" "div") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex*34, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_branch" 1 ++ (and (eq_attr "type" "branch") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_alu" 1 ++ (and (eq_attr "type" "dalu") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_alu64" 1 ++ (and (eq_attr "type" "dalu64") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_alu_round" 1 ++ (and (eq_attr "type" "daluround") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_cmp" 1 ++ (and (eq_attr "type" "dcmp") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_clip" 1 ++ (and (eq_attr "type" "dclip") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_mul" 1 ++ (and (eq_attr "type" "dmul") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_mac" 1 ++ (and (eq_attr "type" "dmac") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_insb" 1 ++ (and (eq_attr "type" "dinsb") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_pack" 1 ++ (and (eq_attr "type" "dpack") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_bpick" 1 ++ (and (eq_attr "type" "dbpick") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_dsp_wext" 1 ++ (and (eq_attr "type" "dwext") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ex, n10_mm, n10_wb") ++ ++(define_insn_reservation "nds_n10_fpu_alu" 4 ++ (and (eq_attr "type" "falu") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_muls" 4 ++ (and (eq_attr "type" "fmuls") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_muld" 4 ++ (and (eq_attr "type" "fmuld") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2*2, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_macs" 4 ++ (and (eq_attr "type" "fmacs") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2*3, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_macd" 4 ++ (and (eq_attr "type" "fmacd") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2*4, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_divs" 4 ++ (and (ior (eq_attr "type" "fdivs") ++ (eq_attr "type" "fsqrts")) ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2*14, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_divd" 4 ++ (and (ior (eq_attr "type" "fdivd") ++ (eq_attr "type" "fsqrtd")) ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2*28, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_fast_alu" 2 ++ (and (ior (eq_attr "type" "fcmp") ++ (ior (eq_attr "type" "fabs") ++ (ior (eq_attr "type" "fcpy") ++ (eq_attr "type" "fcmov")))) ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_fmtsr" 4 ++ (and (eq_attr "type" "fmtsr") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_fmtdr" 4 ++ (and (eq_attr "type" "fmtdr") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ii+n10f_iq, n10f_iq+n10f_rf, n10f_rf+n10f_e1, n10f_e1+n10f_e2, n10f_e2+n10f_e3, n10f_e3+n10f_e4, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_fmfsr" 2 ++ (and (eq_attr "type" "fmfsr") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_fmfdr" 2 ++ (and (eq_attr "type" "fmfdr") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10_ii+n10f_iq, n10f_iq+n10f_rf, n10f_rf+n10f_e1, n10f_e1+n10f_e2, n10f_e2+n10f_e3, n10f_e3+n10f_e4, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_load" 3 ++ (and (eq_attr "type" "fload") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") ++ ++(define_insn_reservation "nds_n10_fpu_store" 1 ++ (and (eq_attr "type" "fstore") ++ (eq_attr "pipeline_model" "n10")) ++ "n10_ii, n10f_iq, n10f_rf, n10f_e1, n10f_e2, n10f_e3, n10f_e4") ++ ++;; ------------------------------------------------------------------------ ++;; Comment Notations and Bypass Rules ++;; ------------------------------------------------------------------------ ++;; Producers (LHS) ++;; LD ++;; Load data from the memory and produce the loaded data. The result is ++;; ready at MM. ++;; LMW(N, M) ++;; There are N micro-operations within an instruction that loads multiple ++;; words. The result produced by the M-th micro-operation is sent to ++;; consumers. The result is ready at MM. ++;; MUL, MAC ++;; Compute data in the multiply-adder and produce the data. The result ++;; is ready at MM. ++;; DIV ++;; Compute data in the divider and produce the data. The result is ready ++;; at MM. ++;; ++;; Consumers (RHS) ++;; ALU, MOVD44, PBSAD, PBSADA_RaRb, MUL, MAC, DIV, MMU ++;; Require operands at EX. ++;; ALU_SHIFT_Rb ++;; An ALU-SHIFT instruction consists of a shift micro-operation followed ++;; by an arithmetic micro-operation. The operand Rb is used by the first ++;; micro-operation, and there are some latencies if data dependency occurs. ++;; MAC_RaRb ++;; A MAC instruction does multiplication at EX and does accumulation at MM, ++;; so the operand Rt is required at MM, and operands Ra and Rb are required ++;; at EX. ++;; ADDR_IN ++;; If an instruction requires an address as its input operand, the address ++;; is required at EX. ++;; ST ++;; A store instruction requires its data at MM. ++;; SMW(N, M) ++;; There are N micro-operations within an instruction that stores multiple ++;; words. Each M-th micro-operation requires its data at MM. ++;; BR ++;; If a branch instruction is conditional, its input data is required at EX. ++ ++;; FPU_ADDR_OUT -> FPU_ADDR_IN ++;; Main pipeline rules don't need this because those default latency is 1. ++(define_bypass 1 ++ "nds_n10_fpu_load, nds_n10_fpu_store" ++ "nds_n10_fpu_load, nds_n10_fpu_store" ++ "nds32_n10_ex_to_ex_p" ++) ++ ++;; LD, MUL, MAC, DIV, DALU64, DMUL, DMAC, DALUROUND, DBPICK, DWEXT ++;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44, MUL, MAC_RaRb, DIV, ADDR_IN, BR, MMU, ++;; DALU, DALUROUND, DMUL, DMAC_RaRb, DPACK, DINSB, DCMP, DCLIP, WEXT_O, BPICK_RaRb ++(define_bypass 2 ++ "nds_n10_load, nds_n10_mul, nds_n10_mac, nds_n10_div,\ ++ nds_n10_dsp_alu64, nds_n10_dsp_mul, nds_n10_dsp_mac,\ ++ nds_n10_dsp_alu_round, nds_n10_dsp_bpick, nds_n10_dsp_wext" ++ "nds_n10_alu, nds_n10_alu_shift,\ ++ nds_n10_pbsad, nds_n10_pbsada,\ ++ nds_n10_mul, nds_n10_mac, nds_n10_div,\ ++ nds_n10_branch,\ ++ nds_n10_load, nds_n10_store,\ ++ nds_n10_load_multiple_1, nds_n10_load_multiple_2, nds_n10_load_multiple_3,\ ++ nds_n10_load_multiple_4, nds_n10_load_multiple_5, nds_n10_load_multiple_6,\ ++ nds_n10_load_multiple_7, nds_n10_load_multiple_N,\ ++ nds_n10_store_multiple_1, nds_n10_store_multiple_2, nds_n10_store_multiple_3,\ ++ nds_n10_store_multiple_4, nds_n10_store_multiple_5, nds_n10_store_multiple_6,\ ++ nds_n10_store_multiple_7, nds_n10_store_multiple_N,\ ++ nds_n10_mmu,\ ++ nds_n10_dsp_alu, nds_n10_dsp_alu_round,\ ++ nds_n10_dsp_mul, nds_n10_dsp_mac, nds_n10_dsp_pack,\ ++ nds_n10_dsp_insb, nds_n10_dsp_cmp, nds_n10_dsp_clip,\ ++ nds_n10_dsp_wext, nds_n10_dsp_bpick" ++ "nds32_n10_mm_to_ex_p" ++) ++ ++;; LMW(N, N) ++;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44, MUL, MAC_RaRb, DIV, ADDR_IN, BR, MMU ++;; DALU, DALUROUND, DMUL, DMAC_RaRb, DPACK, DINSB, DCMP, DCLIP, WEXT_O, BPICK_RaRb ++(define_bypass 2 ++ "nds_n10_load_multiple_1, nds_n10_load_multiple_2, nds_n10_load_multiple_3,\ ++ nds_n10_load_multiple_4, nds_n10_load_multiple_5, nds_n10_load_multiple_6,\ ++ nds_n10_load_multiple_7, nds_n10_load_multiple_N" ++ "nds_n10_alu, nds_n10_alu_shift,\ ++ nds_n10_pbsad, nds_n10_pbsada,\ ++ nds_n10_mul, nds_n10_mac, nds_n10_div,\ ++ nds_n10_branch,\ ++ nds_n10_load, nds_n10_store,\ ++ nds_n10_load_multiple_1, nds_n10_load_multiple_2, nds_n10_load_multiple_3,\ ++ nds_n10_load_multiple_4, nds_n10_load_multiple_5, nds_n10_load_multiple_6,\ ++ nds_n10_load_multiple_7, nds_n10_load_multiple_N,\ ++ nds_n10_store_multiple_1, nds_n10_store_multiple_2, nds_n10_store_multiple_3,\ ++ nds_n10_store_multiple_4, nds_n10_store_multiple_5, nds_n10_store_multiple_6,\ ++ nds_n10_store_multiple_7, nds_n10_store_multiple_N,\ ++ nds_n10_mmu,\ ++ nds_n10_dsp_alu, nds_n10_dsp_alu_round,\ ++ nds_n10_dsp_mul, nds_n10_dsp_mac, nds_n10_dsp_pack,\ ++ nds_n10_dsp_insb, nds_n10_dsp_cmp, nds_n10_dsp_clip,\ ++ nds_n10_dsp_wext, nds_n10_dsp_bpick" ++ "nds32_n10_last_load_to_ex_p" ++) +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-n13.md gcc-8.2.0/gcc/config/nds32/nds32-n13.md +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-n13.md 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-n13.md 2019-01-25 15:38:32.829242659 +0100 +@@ -0,0 +1,401 @@ ++;; Pipeline descriptions 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 ++;; . ++ ++ ++;; ------------------------------------------------------------------------ ++;; Define N13 pipeline settings. ++;; ------------------------------------------------------------------------ ++ ++(define_automaton "nds32_n13_machine") ++ ++;; ------------------------------------------------------------------------ ++;; Pipeline Stages ++;; ------------------------------------------------------------------------ ++;; F1 - Instruction Fetch First ++;; Instruction Tag/Data Arrays ++;; ITLB Address Translation ++;; Branch Target Buffer Prediction ++;; F2 - Instruction Fetch Second ++;; Instruction Cache Hit Detection ++;; Cache Way Selection ++;; Inustruction Alignment ++;; I1 - Instruction Issue First / Instruction Decode ++;; Instruction Cache Replay Triggering ++;; 32/16-Bit Instruction Decode ++;; Return Address Stack Prediction ++;; I2 - Instruction Issue Second / Register File Access ++;; Instruction Issue Logic ++;; Register File Access ++;; E1 - Instruction Execute First / Address Generation / MAC First ++;; Data Access Address generation ++;; Multiply Operation ++;; E2 - Instruction Execute Second / Data Access First / MAC Second / ++;; ALU Execute ++;; Skewed ALU ++;; Branch/Jump/Return Resolution ++;; Data Tag/Data arrays ++;; DTLB address translation ++;; Accumulation Operation ++;; E3 - Instruction Execute Third / Data Access Second ++;; Data Cache Hit Detection ++;; Cache Way Selection ++;; Data Alignment ++;; E4 - Instruction Execute Fourth / Write Back ++;; Interruption Resolution ++;; Instruction Retire ++;; Register File Write Back ++ ++(define_cpu_unit "n13_i1" "nds32_n13_machine") ++(define_cpu_unit "n13_i2" "nds32_n13_machine") ++(define_cpu_unit "n13_e1" "nds32_n13_machine") ++(define_cpu_unit "n13_e2" "nds32_n13_machine") ++(define_cpu_unit "n13_e3" "nds32_n13_machine") ++(define_cpu_unit "n13_e4" "nds32_n13_machine") ++ ++(define_insn_reservation "nds_n13_unknown" 1 ++ (and (eq_attr "type" "unknown") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_misc" 1 ++ (and (eq_attr "type" "misc") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_mmu" 1 ++ (and (eq_attr "type" "mmu") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_alu" 1 ++ (and (eq_attr "type" "alu") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_alu_shift" 1 ++ (and (eq_attr "type" "alu_shift") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i2+n13_e1, n13_e1+n13_e2, n13_e2+n13_e3, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_pbsad" 1 ++ (and (eq_attr "type" "pbsad") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2*2, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_pbsada" 1 ++ (and (eq_attr "type" "pbsada") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2*3, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_load" 1 ++ (and (match_test "nds32::load_single_p (insn)") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_store" 1 ++ (and (match_test "nds32::store_single_p (insn)") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_load_multiple_1" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "1")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_load_multiple_2" 1 ++ (and (ior (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "2")) ++ (match_test "nds32::load_double_p (insn)")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i2+n13_e1, n13_e1+n13_e2, n13_e2+n13_e3, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_load_multiple_3" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "3")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2+n13_i2, n13_i1+n13_i2+n13_e1, n13_i2+n13_e1+n13_e2, n13_e1+n13_e2+n13_e3, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_load_multiple_4" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "4")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i2+n13_e1+n13_e2+n13_e3, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_load_multiple_5" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "5")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_load_multiple_6" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "6")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_load_multiple_7" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "7")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*2, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_load_multiple_8" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "8")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*3, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_load_multiple_12" 1 ++ (and (and (eq_attr "type" "load_multiple") ++ (eq_attr "combo" "12")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*7, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_store_multiple_1" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "1")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_store_multiple_2" 1 ++ (and (ior (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "2")) ++ (match_test "nds32::store_double_p (insn)")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i2+n13_e1, n13_e1+n13_e2, n13_e2+n13_e3, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_store_multiple_3" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "3")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2+n13_i2, n13_i1+n13_i2+n13_e1, n13_i2+n13_e1+n13_e2, n13_e1+n13_e2+n13_e3, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_store_multiple_4" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "4")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i2+n13_e1+n13_e2+n13_e3, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_store_multiple_5" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "5")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_store_multiple_6" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "6")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_store_multiple_7" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "7")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*2, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_store_multiple_8" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "8")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*3, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++(define_insn_reservation "nds_n13_store_multiple_12" 1 ++ (and (and (eq_attr "type" "store_multiple") ++ (eq_attr "combo" "12")) ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i1+n13_i2, n13_i1+n13_i2+n13_e1, n13_i1+n13_i2+n13_e1+n13_e2, n13_i1+n13_i2+n13_e1+n13_e2+n13_e3, (n13_i1+n13_i2+n13_e1+n13_e2+n13_e3+n13_e4)*7, n13_i2+n13_e1+n13_e2+n13_e3+n13_e4, n13_e1+n13_e2+n13_e3+n13_e4, n13_e2+n13_e3+n13_e4, n13_e3+n13_e4, n13_e4") ++ ++;; The multiplier at E1 takes two cycles. ++(define_insn_reservation "nds_n13_mul" 1 ++ (and (eq_attr "type" "mul") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1*2, n13_e2, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_mac" 1 ++ (and (eq_attr "type" "mac") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1*2, n13_e2, n13_e3, n13_e4") ++ ++;; The cycles consumed at E2 are 32 - CLZ(abs(Ra)) + 2, ++;; so the worst case is 34. ++(define_insn_reservation "nds_n13_div" 1 ++ (and (eq_attr "type" "div") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2*34, n13_e3, n13_e4") ++ ++(define_insn_reservation "nds_n13_branch" 1 ++ (and (eq_attr "type" "branch") ++ (eq_attr "pipeline_model" "n13")) ++ "n13_i1, n13_i2, n13_e1, n13_e2, n13_e3, n13_e4") ++ ++;; ------------------------------------------------------------------------ ++;; Comment Notations and Bypass Rules ++;; ------------------------------------------------------------------------ ++;; Producers (LHS) ++;; LD ++;; Load data from the memory and produce the loaded data. The result is ++;; ready at E3. ++;; LMW(N, M) ++;; There are N micro-operations within an instruction that loads multiple ++;; words. The result produced by the M-th micro-operation is sent to ++;; consumers. The result is ready at E3. ++;; ADDR_OUT ++;; Most load/store instructions can produce an address output if updating ++;; the base register is required. The result is ready at E2, which is ++;; produced by ALU. ++;; ALU, ALU_SHIFT, SIMD ++;; Compute data in ALU and produce the data. The result is ready at E2. ++;; MUL, MAC ++;; Compute data in the multiply-adder and produce the data. The result ++;; is ready at E2. ++;; DIV ++;; Compute data in the divider and produce the data. The result is ready ++;; at E2. ++;; BR ++;; Branch-with-link instructions produces a result containing the return ++;; address. The result is ready at E2. ++;; ++;; Consumers (RHS) ++;; ALU ++;; General ALU instructions require operands at E2. ++;; ALU_E1 ++;; Some special ALU instructions, such as BSE, BSP and MOVD44, require ++;; operand at E1. ++;; MUL, DIV, PBSAD, MMU ++;; Operands are required at E1. ++;; PBSADA_Rt, PBSADA_RaRb ++;; Operands Ra and Rb are required at E1, and the operand Rt is required ++;; at E2. ++;; ALU_SHIFT_Rb ++;; An ALU-SHIFT instruction consists of a shift micro-operation followed ++;; by an arithmetic micro-operation. The operand Rb is used by the first ++;; micro-operation, and there are some latencies if data dependency occurs. ++;; MAC_RaRb ++;; A MAC instruction does multiplication at E1 and does accumulation at E2, ++;; so the operand Rt is required at E2, and operands Ra and Rb are required ++;; at E1. ++;; ADDR_IN ++;; If an instruction requires an address as its input operand, the address ++;; is required at E1. ++;; ST ++;; A store instruction requires its data at E2. ++;; SMW(N, M) ++;; There are N micro-operations within an instruction that stores multiple ++;; words. Each M-th micro-operation requires its data at E2. ++;; BR ++;; If a branch instruction is conditional, its input data is required at E2. ++ ++;; LD -> ALU_E1, PBSAD, PBSADA_RaRb, MUL, MAC_RaRb, DIV, MMU, ADDR_IN ++(define_bypass 3 ++ "nds_n13_load" ++ "nds_n13_alu, nds_n13_pbsad, nds_n13_pbsada,\ ++ nds_n13_mul, nds_n13_mac, nds_n13_div,\ ++ nds_n13_mmu,\ ++ nds_n13_load, nds_n13_store,\ ++ nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ ++ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ ++ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12,\ ++ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ ++ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ ++ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" ++ "nds32_n13_load_to_e1_p" ++) ++ ++;; LD -> ALU, ALU_SHIFT_Rb, PBSADA_Rt, BR, ST, SMW(N, 1) ++(define_bypass 2 ++ "nds_n13_load" ++ "nds_n13_alu, nds_n13_alu_shift, nds_n13_pbsada, nds_n13_branch, nds_n13_store,\ ++ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ ++ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ ++ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" ++ "nds32_n13_load_to_e2_p" ++) ++ ++;; LMW(N, N) -> ALU_E1, PBSAD, PBSADA_RaRb, MUL, MAC_RaRb, DIV, MMU, ADDR_IN ++(define_bypass 3 ++ "nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ ++ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ ++ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12" ++ "nds_n13_alu, nds_n13_pbsad, nds_n13_pbsada,\ ++ nds_n13_mul, nds_n13_mac, nds_n13_div,\ ++ nds_n13_mmu,\ ++ nds_n13_load, nds_n13_store,\ ++ nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ ++ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ ++ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12,\ ++ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ ++ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ ++ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" ++ "nds32_n13_last_load_to_e1_p") ++ ++;; LMW(N, N) -> ALU, ALU_SHIFT_Rb, PBSADA_Rt, BR, ST, SMW(N, 1) ++(define_bypass 2 ++ "nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ ++ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ ++ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12" ++ "nds_n13_alu, nds_n13_alu_shift, nds_n13_pbsada, nds_n13_branch, nds_n13_store,\ ++ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ ++ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ ++ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" ++ "nds32_n13_last_load_to_e2_p" ++) ++ ++;; LMW(N, N - 1) -> ALU_E1, PBSAD, PBSADA_RaRb, MUL, MAC_RaRb, DIV, MMU, ADDR_IN ++(define_bypass 2 ++ "nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ ++ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ ++ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12" ++ "nds_n13_alu, nds_n13_pbsad, nds_n13_pbsada,\ ++ nds_n13_mul, nds_n13_mac, nds_n13_div,\ ++ nds_n13_mmu,\ ++ nds_n13_load, nds_n13_store,\ ++ nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ ++ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ ++ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12,\ ++ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ ++ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ ++ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" ++ "nds32_n13_last_two_load_to_e1_p") ++ ++;; ALU, ALU_SHIFT, SIMD, BR, MUL, MAC, DIV, ADDR_OUT ++;; -> ALU_E1, PBSAD, PBSADA_RaRb, MUL, MAC_RaRb, DIV, MMU, ADDR_IN ++(define_bypass 2 ++ "nds_n13_alu, nds_n13_alu_shift, nds_n13_pbsad, nds_n13_pbsada, nds_n13_branch,\ ++ nds_n13_mul, nds_n13_mac, nds_n13_div,\ ++ nds_n13_load, nds_n13_store,\ ++ nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ ++ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ ++ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12,\ ++ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ ++ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ ++ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" ++ "nds_n13_alu, nds_n13_pbsad, nds_n13_pbsada,\ ++ nds_n13_mul, nds_n13_mac, nds_n13_div,\ ++ nds_n13_mmu,\ ++ nds_n13_load, nds_n13_store,\ ++ nds_n13_load_multiple_1,nds_n13_load_multiple_2, nds_n13_load_multiple_3,\ ++ nds_n13_load_multiple_4,nds_n13_load_multiple_5, nds_n13_load_multiple_6,\ ++ nds_n13_load_multiple_7,nds_n13_load_multiple_8, nds_n13_load_multiple_12,\ ++ nds_n13_store_multiple_1,nds_n13_store_multiple_2, nds_n13_store_multiple_3,\ ++ nds_n13_store_multiple_4,nds_n13_store_multiple_5, nds_n13_store_multiple_6,\ ++ nds_n13_store_multiple_7,nds_n13_store_multiple_8, nds_n13_store_multiple_12" ++ "nds32_n13_e2_to_e1_p") +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32.opt gcc-8.2.0/gcc/config/nds32/nds32.opt +--- gcc-8.2.0.orig/gcc/config/nds32/nds32.opt 2018-04-22 12:10:00.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32.opt 2019-01-25 15:38:32.833242671 +0100 +@@ -32,6 +32,13 @@ + Target RejectNegative Alias(mlittle-endian) + Generate code in little-endian mode. + ++mfp-as-gp ++Target RejectNegative Alias(mforce-fp-as-gp) ++Force performing fp-as-gp optimization. ++ ++mno-fp-as-gp ++Target RejectNegative Alias(mforbid-fp-as-gp) ++Forbid performing fp-as-gp optimization. + + ; --------------------------------------------------------------- + +@@ -85,11 +92,36 @@ + Target Undocumented RejectNegative Negative(mbig-endian) InverseMask(BIG_ENDIAN) + Generate code in little-endian mode. + ++mforce-fp-as-gp ++Target Undocumented Mask(FORCE_FP_AS_GP) ++Prevent $fp being allocated during register allocation so that compiler is able to force performing fp-as-gp optimization. ++ ++mforbid-fp-as-gp ++Target Undocumented Mask(FORBID_FP_AS_GP) ++Forbid using $fp to access static and global variables. This option strictly forbids fp-as-gp optimization regardless of '-mforce-fp-as-gp'. ++ ++mict-model= ++Target Undocumented RejectNegative Joined Enum(nds32_ict_model_type) Var(nds32_ict_model) Init(ICT_MODEL_SMALL) ++Specify the address generation strategy for ICT call's code model. ++ ++Enum ++Name(nds32_ict_model_type) Type(enum nds32_ict_model_type) ++Known cmodel types (for use with the -mict-model= option): ++ ++EnumValue ++Enum(nds32_ict_model_type) String(small) Value(ICT_MODEL_SMALL) ++ ++EnumValue ++Enum(nds32_ict_model_type) String(large) Value(ICT_MODEL_LARGE) + + mcmov + Target Report Mask(CMOV) + Generate conditional move instructions. + ++mhw-abs ++Target Report Mask(HW_ABS) ++Generate hardware abs instructions. ++ + mext-perf + Target Report Mask(EXT_PERF) + Generate performance extension instructions. +@@ -102,6 +134,10 @@ + Target Report Mask(EXT_STRING) + Generate string extension instructions. + ++mext-dsp ++Target Report Mask(EXT_DSP) ++Generate DSP extension instructions. ++ + mv3push + Target Report Mask(V3PUSH) + Generate v3 push25/pop25 instructions. +@@ -115,13 +151,17 @@ + Insert relax hint for linker to do relaxation. + + mvh +-Target Report Mask(VH) ++Target Report Mask(VH) Condition(!TARGET_LINUX_ABI) + Enable Virtual Hosting support. + + misr-vector-size= + Target RejectNegative Joined UInteger Var(nds32_isr_vector_size) Init(NDS32_DEFAULT_ISR_VECTOR_SIZE) + Specify the size of each interrupt vector, which must be 4 or 16. + ++misr-secure= ++Target RejectNegative Joined UInteger Var(nds32_isr_secure_level) Init(0) ++Specify the security level of c-isr for the whole file. ++ + mcache-block-size= + Target RejectNegative Joined UInteger Var(nds32_cache_block_size) Init(NDS32_DEFAULT_CACHE_BLOCK_SIZE) + Specify the size of each cache block, which must be a power of 2 between 4 and 512. +@@ -141,6 +181,9 @@ + Enum(nds32_arch_type) String(v3) Value(ARCH_V3) + + EnumValue ++Enum(nds32_arch_type) String(v3j) Value(ARCH_V3J) ++ ++EnumValue + Enum(nds32_arch_type) String(v3m) Value(ARCH_V3M) + + EnumValue +@@ -149,23 +192,6 @@ + EnumValue + 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= + Target RejectNegative Joined Enum(nds32_cpu_type) Var(nds32_cpu_option) Init(CPU_N9) + Specify the cpu for pipeline model. +@@ -235,6 +261,99 @@ + Enum(nds32_cpu_type) String(n968a) Value(CPU_N9) + + EnumValue ++Enum(nds32_cpu_type) String(n10) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1033) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1033a) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1033-fpu) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1033-spu) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1068) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1068a) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1068-fpu) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1068a-fpu) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1068-spu) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1068a-spu) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(d10) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(d1088) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(d1088-fpu) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) String(d1088-spu) Value(CPU_N10) ++ ++EnumValue ++Enum(nds32_cpu_type) Undocumented String(graywolf) Value(CPU_GRAYWOLF) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n15) Value(CPU_GRAYWOLF) ++ ++EnumValue ++Enum(nds32_cpu_type) String(d15) Value(CPU_GRAYWOLF) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n15s) Value(CPU_GRAYWOLF) ++ ++EnumValue ++Enum(nds32_cpu_type) String(d15s) Value(CPU_GRAYWOLF) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n15f) Value(CPU_GRAYWOLF) ++ ++EnumValue ++Enum(nds32_cpu_type) String(d15f) Value(CPU_GRAYWOLF) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n12) Value(CPU_N12) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1213) Value(CPU_N12) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1233) Value(CPU_N12) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1233-fpu) Value(CPU_N12) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1233-spu) Value(CPU_N12) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n13) Value(CPU_N13) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1337) Value(CPU_N13) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1337-fpu) Value(CPU_N13) ++ ++EnumValue ++Enum(nds32_cpu_type) String(n1337-spu) Value(CPU_N13) ++ ++EnumValue + Enum(nds32_cpu_type) String(simple) Value(CPU_SIMPLE) + + mconfig-fpu= +@@ -321,6 +440,18 @@ + Target Report Mask(FPU_DOUBLE) + Generate double-precision floating-point instructions. + ++mforce-no-ext-dsp ++Target Undocumented Report Mask(FORCE_NO_EXT_DSP) ++Force disable hardware loop, even use -mext-dsp. ++ ++msched-prolog-epilog ++Target Var(flag_sched_prolog_epilog) Init(0) ++Permit scheduling of a function's prologue and epilogue sequence. ++ ++mret-in-naked-func ++Target Var(flag_ret_in_naked_func) Init(1) ++Generate return instruction in naked function. ++ + malways-save-lp + Target Var(flag_always_save_lp) Init(0) + Always save $lp in the stack. +@@ -328,3 +459,7 @@ + munaligned-access + Target Report Var(flag_unaligned_access) Init(0) + Enable unaligned word and halfword accesses to packed data. ++ ++minline-asm-r15 ++Target Report Var(flag_inline_asm_r15) Init(0) ++Allow use r15 for inline ASM. +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-opts.h gcc-8.2.0/gcc/config/nds32/nds32-opts.h +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-opts.h 2018-04-08 11:21:30.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-opts.h 2019-01-25 15:38:32.833242671 +0100 +@@ -29,6 +29,7 @@ + { + ARCH_V2, + ARCH_V3, ++ ARCH_V3J, + ARCH_V3M, + ARCH_V3F, + ARCH_V3S +@@ -42,6 +43,10 @@ + CPU_N8, + CPU_E8, + CPU_N9, ++ CPU_N10, ++ CPU_GRAYWOLF, ++ CPU_N12, ++ CPU_N13, + CPU_SIMPLE + }; + +@@ -53,6 +58,13 @@ + CMODEL_LARGE + }; + ++/* The code model defines the address generation strategy. */ ++enum nds32_ict_model_type ++{ ++ ICT_MODEL_SMALL, ++ ICT_MODEL_LARGE ++}; ++ + /* Multiply instruction configuration. */ + enum nds32_mul_type + { +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-peephole2.md gcc-8.2.0/gcc/config/nds32/nds32-peephole2.md +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-peephole2.md 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/nds32-peephole2.md 2019-01-25 15:38:32.833242671 +0100 +@@ -22,3 +22,139 @@ + ;; Use define_peephole2 to handle possible target-specific optimization. + + ;; ------------------------------------------------------------------------ ++;; Try to utilize 16-bit instruction by swap operand if possible. ++;; ------------------------------------------------------------------------ ++ ++;; Try to make add as add45. ++(define_peephole2 ++ [(set (match_operand:QIHISI 0 "register_operand" "") ++ (plus:QIHISI (match_operand:QIHISI 1 "register_operand" "") ++ (match_operand:QIHISI 2 "register_operand" "")))] ++ "reload_completed ++ && TARGET_16_BIT ++ && REGNO (operands[0]) == REGNO (operands[2]) ++ && REGNO (operands[0]) != REGNO (operands[1]) ++ && TEST_HARD_REG_BIT (reg_class_contents[MIDDLE_REGS], REGNO (operands[0]))" ++ [(set (match_dup 0) (plus:QIHISI (match_dup 2) (match_dup 1)))]) ++ ++;; Try to make xor/ior/and/mult as xor33/ior33/and33/mult33. ++(define_peephole2 ++ [(set (match_operand:SI 0 "register_operand" "") ++ (match_operator:SI 1 "nds32_have_33_inst_operator" ++ [(match_operand:SI 2 "register_operand" "") ++ (match_operand:SI 3 "register_operand" "")]))] ++ "reload_completed ++ && TARGET_16_BIT ++ && REGNO (operands[0]) == REGNO (operands[3]) ++ && REGNO (operands[0]) != REGNO (operands[2]) ++ && TEST_HARD_REG_BIT (reg_class_contents[LOW_REGS], REGNO (operands[0])) ++ && TEST_HARD_REG_BIT (reg_class_contents[LOW_REGS], REGNO (operands[2]))" ++ [(set (match_dup 0) (match_op_dup 1 [(match_dup 3) (match_dup 2)]))]) ++ ++(define_peephole ++ [(set (match_operand:SI 0 "register_operand" "") ++ (match_operand:SI 1 "register_operand" "")) ++ (set (match_operand:SI 2 "register_operand" "") ++ (match_operand:SI 3 "register_operand" ""))] ++ "TARGET_16_BIT ++ && !TARGET_ISA_V2 ++ && NDS32_IS_GPR_REGNUM (REGNO (operands[0])) ++ && NDS32_IS_GPR_REGNUM (REGNO (operands[1])) ++ && ((REGNO (operands[0]) & 0x1) == 0) ++ && ((REGNO (operands[1]) & 0x1) == 0) ++ && (REGNO (operands[0]) + 1) == REGNO (operands[2]) ++ && (REGNO (operands[1]) + 1) == REGNO (operands[3])" ++ "movd44\t%0, %1" ++ [(set_attr "type" "alu") ++ (set_attr "length" "2")]) ++ ++;; Merge two fcpyss to fcpysd. ++(define_peephole2 ++ [(set (match_operand:SF 0 "float_even_register_operand" "") ++ (match_operand:SF 1 "float_even_register_operand" "")) ++ (set (match_operand:SF 2 "float_odd_register_operand" "") ++ (match_operand:SF 3 "float_odd_register_operand" ""))] ++ "(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) ++ && REGNO (operands[0]) == REGNO (operands[2]) - 1 ++ && REGNO (operands[1]) == REGNO (operands[3]) - 1" ++ [(set (match_dup 4) (match_dup 5))] ++ { ++ operands[4] = gen_rtx_REG (DFmode, REGNO (operands[0])); ++ operands[5] = gen_rtx_REG (DFmode, REGNO (operands[1])); ++ }) ++ ++(define_peephole2 ++ [(set (match_operand:SF 0 "float_odd_register_operand" "") ++ (match_operand:SF 1 "float_odd_register_operand" "")) ++ (set (match_operand:SF 2 "float_even_register_operand" "") ++ (match_operand:SF 3 "float_even_register_operand" ""))] ++ "(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) ++ && REGNO (operands[2]) == REGNO (operands[0]) - 1 ++ && REGNO (operands[3]) == REGNO (operands[1]) - 1" ++ [(set (match_dup 4) (match_dup 5))] ++ { ++ operands[4] = gen_rtx_REG (DFmode, REGNO (operands[2])); ++ operands[5] = gen_rtx_REG (DFmode, REGNO (operands[3])); ++ }) ++ ++;; ------------------------------------------------------------------------ ++;; GCC will prefer [u]divmodsi3 rather than [u]divsi3 even remainder is ++;; unused, so we use split to drop mod operation for lower register pressure. ++ ++(define_split ++ [(set (match_operand:SI 0 "register_operand") ++ (div:SI (match_operand:SI 1 "register_operand") ++ (match_operand:SI 2 "register_operand"))) ++ (set (match_operand:SI 3 "register_operand") ++ (mod:SI (match_dup 1) (match_dup 2)))] ++ "find_regno_note (insn, REG_UNUSED, REGNO (operands[3])) != NULL ++ && can_create_pseudo_p ()" ++ [(set (match_dup 0) ++ (div:SI (match_dup 1) ++ (match_dup 2)))]) ++ ++(define_split ++ [(set (match_operand:SI 0 "register_operand") ++ (udiv:SI (match_operand:SI 1 "register_operand") ++ (match_operand:SI 2 "register_operand"))) ++ (set (match_operand:SI 3 "register_operand") ++ (umod:SI (match_dup 1) (match_dup 2)))] ++ "find_regno_note (insn, REG_UNUSED, REGNO (operands[3])) != NULL ++ && can_create_pseudo_p ()" ++ [(set (match_dup 0) ++ (udiv:SI (match_dup 1) ++ (match_dup 2)))]) ++ ++(define_peephole2 ++ [(set (match_operand:DI 0 "register_operand") ++ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand")) ++ (sign_extend:DI (match_operand:SI 2 "register_operand"))))] ++ "NDS32_EXT_DSP_P () ++ && peep2_regno_dead_p (1, WORDS_BIG_ENDIAN ? REGNO (operands[0]) + 1 : REGNO (operands[0]))" ++ [(const_int 1)] ++{ ++ rtx highpart = nds32_di_high_part_subreg (operands[0]); ++ emit_insn (gen_smulsi3_highpart (highpart, operands[1], operands[2])); ++ DONE; ++}) ++ ++(define_split ++ [(set (match_operand:DI 0 "nds32_general_register_operand" "") ++ (match_operand:DI 1 "nds32_general_register_operand" ""))] ++ "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) != NULL ++ || find_regno_note (insn, REG_UNUSED, REGNO (operands[0]) + 1) != NULL" ++ [(set (match_dup 0) (match_dup 1))] ++{ ++ rtx dead_note = find_regno_note (curr_insn, REG_UNUSED, REGNO (operands[0])); ++ HOST_WIDE_INT offset; ++ if (dead_note == NULL_RTX) ++ offset = 0; ++ else ++ offset = 4; ++ operands[0] = simplify_gen_subreg ( ++ SImode, operands[0], ++ DImode, offset); ++ operands[1] = simplify_gen_subreg ( ++ SImode, operands[1], ++ DImode, offset); ++}) +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-pipelines-auxiliary.c gcc-8.2.0/gcc/config/nds32/nds32-pipelines-auxiliary.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-pipelines-auxiliary.c 2018-04-08 11:21:30.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-pipelines-auxiliary.c 2019-01-25 15:38:32.833242671 +0100 +@@ -306,6 +306,19 @@ + return false; + } + ++/* Determine if the latency is occured when the consumer PBSADA_INSN uses the ++ value of DEF_REG in its Rt field. */ ++bool ++pbsada_insn_rt_dep_reg_p (rtx pbsada_insn, rtx def_reg) ++{ ++ rtx pbsada_rt = SET_DEST (PATTERN (pbsada_insn)); ++ ++ if (rtx_equal_p (def_reg, pbsada_rt)) ++ return true; ++ ++ return false; ++} ++ + /* Check if INSN is a movd44 insn consuming DEF_REG. */ + bool + movd44_even_dep_p (rtx_insn *insn, rtx def_reg) +@@ -335,6 +348,103 @@ + return false; + } + ++/* Check if INSN is a wext insn consuming DEF_REG. */ ++bool ++wext_odd_dep_p (rtx insn, rtx def_reg) ++{ ++ rtx shift_rtx = XEXP (SET_SRC (PATTERN (insn)), 0); ++ rtx use_reg = XEXP (shift_rtx, 0); ++ rtx pos_rtx = XEXP (shift_rtx, 1); ++ ++ if (REG_P (pos_rtx) && reg_overlap_p (def_reg, pos_rtx)) ++ return true; ++ ++ if (GET_MODE (def_reg) == DImode) ++ return reg_overlap_p (def_reg, use_reg); ++ ++ gcc_assert (REG_P (def_reg) || GET_CODE (def_reg) == SUBREG); ++ gcc_assert (REG_P (use_reg)); ++ ++ if (REG_P (def_reg)) ++ { ++ if (!TARGET_BIG_ENDIAN) ++ return REGNO (def_reg) == REGNO (use_reg) + 1; ++ else ++ return REGNO (def_reg) == REGNO (use_reg); ++ } ++ ++ if (GET_CODE (def_reg) == SUBREG) ++ { ++ if (!reg_overlap_p (def_reg, use_reg)) ++ return false; ++ ++ if (!TARGET_BIG_ENDIAN) ++ return SUBREG_BYTE (def_reg) == 4; ++ else ++ return SUBREG_BYTE (def_reg) == 0; ++ } ++ ++ return false; ++} ++ ++/* Check if INSN is a bpick insn consuming DEF_REG. */ ++bool ++bpick_ra_rb_dep_p (rtx insn, rtx def_reg) ++{ ++ rtx ior_rtx = SET_SRC (PATTERN (insn)); ++ rtx and1_rtx = XEXP (ior_rtx, 0); ++ rtx and2_rtx = XEXP (ior_rtx, 1); ++ rtx reg1_0 = XEXP (and1_rtx, 0); ++ rtx reg1_1 = XEXP (and1_rtx, 1); ++ rtx reg2_0 = XEXP (and2_rtx, 0); ++ rtx reg2_1 = XEXP (and2_rtx, 1); ++ ++ if (GET_CODE (reg1_0) == NOT) ++ { ++ if (rtx_equal_p (reg1_0, reg2_0)) ++ return reg_overlap_p (def_reg, reg1_1) ++ || reg_overlap_p (def_reg, reg2_1); ++ ++ if (rtx_equal_p (reg1_0, reg2_1)) ++ return reg_overlap_p (def_reg, reg1_1) ++ || reg_overlap_p (def_reg, reg2_0); ++ } ++ ++ if (GET_CODE (reg1_1) == NOT) ++ { ++ if (rtx_equal_p (reg1_1, reg2_0)) ++ return reg_overlap_p (def_reg, reg1_0) ++ || reg_overlap_p (def_reg, reg2_1); ++ ++ if (rtx_equal_p (reg1_1, reg2_1)) ++ return reg_overlap_p (def_reg, reg1_0) ++ || reg_overlap_p (def_reg, reg2_0); ++ } ++ ++ if (GET_CODE (reg2_0) == NOT) ++ { ++ if (rtx_equal_p (reg2_0, reg1_0)) ++ return reg_overlap_p (def_reg, reg2_1) ++ || reg_overlap_p (def_reg, reg1_1); ++ ++ if (rtx_equal_p (reg2_0, reg1_1)) ++ return reg_overlap_p (def_reg, reg2_1) ++ || reg_overlap_p (def_reg, reg1_0); ++ } ++ ++ if (GET_CODE (reg2_1) == NOT) ++ { ++ if (rtx_equal_p (reg2_1, reg1_0)) ++ return reg_overlap_p (def_reg, reg2_0) ++ || reg_overlap_p (def_reg, reg1_1); ++ ++ if (rtx_equal_p (reg2_1, reg1_1)) ++ return reg_overlap_p (def_reg, reg2_0) ++ || reg_overlap_p (def_reg, reg1_0); ++ } ++ ++ gcc_unreachable (); ++} + } // namespace scheduling + } // namespace nds32 + +@@ -375,8 +485,7 @@ + operations in order to write two registers. We have to check the + dependency from the producer to the first micro-operation. */ + case TYPE_DIV: +- if (INSN_CODE (consumer) == CODE_FOR_divmodsi4 +- || INSN_CODE (consumer) == CODE_FOR_udivmodsi4) ++ if (divmod_p (consumer)) + use_rtx = SET_SRC (parallel_element (consumer, 0)); + else + use_rtx = SET_SRC (PATTERN (consumer)); +@@ -506,8 +615,7 @@ + operations in order to write two registers. We have to check the + dependency from the producer to the first micro-operation. */ + case TYPE_DIV: +- if (INSN_CODE (consumer) == CODE_FOR_divmodsi4 +- || INSN_CODE (consumer) == CODE_FOR_udivmodsi4) ++ if (divmod_p (consumer)) + use_rtx = SET_SRC (parallel_element (consumer, 0)); + else + use_rtx = SET_SRC (PATTERN (consumer)); +@@ -606,8 +714,7 @@ + break; + + case TYPE_DIV: +- if (INSN_CODE (consumer) == CODE_FOR_divmodsi4 +- || INSN_CODE (consumer) == CODE_FOR_udivmodsi4) ++ if (divmod_p (consumer)) + use_rtx = SET_SRC (parallel_element (consumer, 0)); + else + use_rtx = SET_SRC (PATTERN (consumer)); +@@ -706,13 +813,175 @@ + We have to check the dependency from the producer to the first + micro-operation. */ + case TYPE_DIV: +- if (INSN_CODE (consumer) == CODE_FOR_divmodsi4 +- || INSN_CODE (consumer) == CODE_FOR_udivmodsi4) ++ if (divmod_p (consumer)) ++ use_rtx = SET_SRC (parallel_element (consumer, 0)); ++ else ++ use_rtx = SET_SRC (PATTERN (consumer)); ++ break; ++ ++ case TYPE_MMU: ++ if (GET_CODE (PATTERN (consumer)) == SET) ++ use_rtx = SET_SRC (PATTERN (consumer)); ++ else ++ return true; ++ break; ++ ++ case TYPE_LOAD: ++ case TYPE_STORE: ++ use_rtx = extract_mem_rtx (consumer); ++ break; ++ ++ case TYPE_LOAD_MULTIPLE: ++ case TYPE_STORE_MULTIPLE: ++ use_rtx = extract_base_reg (consumer); ++ break; ++ ++ case TYPE_BRANCH: ++ use_rtx = PATTERN (consumer); ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ ++ if (reg_overlap_p (def_reg, use_rtx)) ++ return true; ++ ++ return false; ++} ++ ++/* Check the dependency between the producer defining DEF_REG and CONSUMER ++ requiring input operand at EX. */ ++bool ++n10_consumed_by_ex_dep_p (rtx_insn *consumer, rtx def_reg) ++{ ++ rtx use_rtx; ++ ++ switch (get_attr_type (consumer)) ++ { ++ case TYPE_ALU: ++ case TYPE_PBSAD: ++ case TYPE_MUL: ++ case TYPE_DALU: ++ case TYPE_DALU64: ++ case TYPE_DMUL: ++ case TYPE_DPACK: ++ case TYPE_DINSB: ++ case TYPE_DCMP: ++ case TYPE_DCLIP: ++ case TYPE_DALUROUND: ++ use_rtx = SET_SRC (PATTERN (consumer)); ++ break; ++ ++ case TYPE_ALU_SHIFT: ++ use_rtx = extract_shift_reg (consumer); ++ break; ++ ++ case TYPE_PBSADA: ++ return pbsada_insn_ra_rb_dep_reg_p (consumer, def_reg); ++ ++ case TYPE_MAC: ++ case TYPE_DMAC: ++ use_rtx = extract_mac_non_acc_rtx (consumer); ++ break; ++ ++ /* Some special instructions, divmodsi4 and udivmodsi4, produce two ++ results, the quotient and the remainder. */ ++ case TYPE_DIV: ++ if (divmod_p (consumer)) ++ use_rtx = SET_SRC (parallel_element (consumer, 0)); ++ else ++ use_rtx = SET_SRC (PATTERN (consumer)); ++ break; ++ ++ case TYPE_DWEXT: ++ return wext_odd_dep_p (consumer, def_reg); ++ ++ case TYPE_DBPICK: ++ return bpick_ra_rb_dep_p (consumer, def_reg); ++ ++ case TYPE_MMU: ++ if (GET_CODE (PATTERN (consumer)) == SET) ++ use_rtx = SET_SRC (PATTERN (consumer)); ++ else ++ return true; ++ break; ++ ++ case TYPE_LOAD: ++ case TYPE_STORE: ++ use_rtx = extract_mem_rtx (consumer); ++ break; ++ ++ case TYPE_LOAD_MULTIPLE: ++ case TYPE_STORE_MULTIPLE: ++ use_rtx = extract_base_reg (consumer); ++ break; ++ ++ case TYPE_BRANCH: ++ use_rtx = PATTERN (consumer); ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ ++ if (reg_overlap_p (def_reg, use_rtx)) ++ return true; ++ ++ return false; ++} ++ ++/* Check the dependency between the producer defining DEF_REG and CONSUMER ++ requiring input operand at EX. */ ++bool ++gw_consumed_by_ex_dep_p (rtx_insn *consumer, rtx def_reg) ++{ ++ rtx use_rtx; ++ ++ switch (get_attr_type (consumer)) ++ { ++ case TYPE_ALU: ++ case TYPE_PBSAD: ++ case TYPE_MUL: ++ case TYPE_DALU: ++ case TYPE_DALU64: ++ case TYPE_DMUL: ++ case TYPE_DPACK: ++ case TYPE_DINSB: ++ case TYPE_DCMP: ++ case TYPE_DCLIP: ++ case TYPE_DALUROUND: ++ use_rtx = SET_SRC (PATTERN (consumer)); ++ break; ++ ++ case TYPE_ALU_SHIFT: ++ use_rtx = extract_shift_reg (consumer); ++ break; ++ ++ case TYPE_PBSADA: ++ return pbsada_insn_ra_rb_dep_reg_p (consumer, def_reg); ++ ++ case TYPE_MAC: ++ case TYPE_DMAC: ++ use_rtx = extract_mac_non_acc_rtx (consumer); ++ break; ++ ++ /* Some special instructions, divmodsi4 and udivmodsi4, produce two ++ results, the quotient and the remainder. We have to check the ++ dependency from the producer to the first micro-operation. */ ++ case TYPE_DIV: ++ if (divmod_p (consumer)) + use_rtx = SET_SRC (parallel_element (consumer, 0)); + else + use_rtx = SET_SRC (PATTERN (consumer)); + break; + ++ case TYPE_DWEXT: ++ return wext_odd_dep_p (consumer, def_reg); ++ ++ case TYPE_DBPICK: ++ return bpick_ra_rb_dep_p (consumer, def_reg); ++ + case TYPE_MMU: + if (GET_CODE (PATTERN (consumer)) == SET) + use_rtx = SET_SRC (PATTERN (consumer)); +@@ -744,7 +1013,153 @@ + return false; + } + ++/* Check dependencies from any stages to ALU_E1 (E1). This is a helper ++ function of n13_consumed_by_e1_dep_p (). */ ++bool ++n13_alu_e1_insn_dep_reg_p (rtx_insn *alu_e1_insn, rtx def_reg) ++{ ++ rtx unspec_rtx, operand_ra, operand_rb; ++ rtx src_rtx, dst_rtx; ++ ++ switch (INSN_CODE (alu_e1_insn)) ++ { ++ /* BSP and BSE are supported by built-in functions, the corresponding ++ patterns are formed by UNSPEC RTXs. We have to handle them ++ individually. */ ++ case CODE_FOR_unspec_bsp: ++ case CODE_FOR_unspec_bse: ++ unspec_rtx = SET_SRC (parallel_element (alu_e1_insn, 0)); ++ gcc_assert (GET_CODE (unspec_rtx) == UNSPEC); ++ ++ operand_ra = XVECEXP (unspec_rtx, 0, 0); ++ operand_rb = XVECEXP (unspec_rtx, 0, 1); ++ ++ if (rtx_equal_p (def_reg, operand_ra) ++ || rtx_equal_p (def_reg, operand_rb)) ++ return true; ++ ++ return false; ++ ++ /* Unlink general ALU instructions, MOVD44 requires operands at E1. */ ++ case CODE_FOR_move_di: ++ case CODE_FOR_move_df: ++ src_rtx = SET_SRC (PATTERN (alu_e1_insn)); ++ dst_rtx = SET_DEST (PATTERN (alu_e1_insn)); ++ ++ if (REG_P (dst_rtx) && REG_P (src_rtx) ++ && rtx_equal_p (src_rtx, def_reg)) ++ return true; ++ ++ return false; ++ ++ default: ++ return false; ++ } ++} ++ ++/* Check the dependency between the producer defining DEF_REG and CONSUMER ++ requiring input operand at E1. Because the address generation unti is ++ at E1, the address input should be ready at E1. Note that the branch ++ target is also a kind of addresses, so we have to check it. */ ++bool ++n13_consumed_by_e1_dep_p (rtx_insn *consumer, rtx def_reg) ++{ ++ rtx use_rtx; ++ ++ switch (get_attr_type (consumer)) ++ { ++ /* ALU_E1 */ ++ case TYPE_ALU: ++ return n13_alu_e1_insn_dep_reg_p (consumer, def_reg); ++ ++ case TYPE_PBSADA: ++ return pbsada_insn_ra_rb_dep_reg_p (consumer, def_reg); ++ ++ case TYPE_PBSAD: ++ case TYPE_MUL: ++ use_rtx = SET_SRC (PATTERN (consumer)); ++ break; ++ ++ case TYPE_MAC: ++ use_rtx = extract_mac_non_acc_rtx (consumer); ++ break; ++ ++ case TYPE_DIV: ++ if (divmod_p (consumer)) ++ use_rtx = SET_SRC (parallel_element (consumer, 0)); ++ else ++ use_rtx = SET_SRC (PATTERN (consumer)); ++ break; ++ ++ case TYPE_MMU: ++ if (GET_CODE (PATTERN (consumer)) == SET) ++ use_rtx = SET_SRC (PATTERN (consumer)); ++ else ++ return true; ++ break; ++ ++ case TYPE_BRANCH: ++ use_rtx = extract_branch_target_rtx (consumer); ++ break; ++ ++ case TYPE_LOAD: ++ case TYPE_STORE: ++ use_rtx = extract_mem_rtx (consumer); ++ break; ++ ++ case TYPE_LOAD_MULTIPLE: ++ case TYPE_STORE_MULTIPLE: ++ use_rtx = extract_base_reg (consumer); ++ break; ++ ++ default: ++ return false; ++ } ++ ++ if (reg_overlap_p (def_reg, use_rtx)) ++ return true; ++ ++ return false; ++} ++ ++/* Check the dependency between the producer defining DEF_REG and CONSUMER ++ requiring input operand at E2. */ ++bool ++n13_consumed_by_e2_dep_p (rtx_insn *consumer, rtx def_reg) ++{ ++ rtx use_rtx; ++ ++ switch (get_attr_type (consumer)) ++ { ++ case TYPE_ALU: ++ case TYPE_STORE: ++ use_rtx = SET_SRC (PATTERN (consumer)); ++ break; ++ ++ case TYPE_ALU_SHIFT: ++ use_rtx = extract_shift_reg (consumer); ++ break; ++ ++ case TYPE_PBSADA: ++ return pbsada_insn_rt_dep_reg_p (consumer, def_reg); ++ ++ case TYPE_STORE_MULTIPLE: ++ use_rtx = extract_nth_access_rtx (consumer, 0); ++ break; ++ ++ case TYPE_BRANCH: ++ use_rtx = extract_branch_condition_rtx (consumer); ++ break; ++ ++ default: ++ gcc_unreachable(); ++ } ++ ++ if (reg_overlap_p (def_reg, use_rtx)) ++ return true; + ++ return false; ++} + } // anonymous namespace + + /* ------------------------------------------------------------------------ */ +@@ -837,8 +1252,7 @@ + break; + + case TYPE_DIV: +- if (INSN_CODE (producer) == CODE_FOR_divmodsi4 +- || INSN_CODE (producer) == CODE_FOR_udivmodsi4) ++ if (divmod_p (producer)) + def_reg = SET_DEST (parallel_element (producer, 1)); + else + def_reg = SET_DEST (PATTERN (producer)); +@@ -969,8 +1383,7 @@ + break; + + case TYPE_DIV: +- if (INSN_CODE (producer) == CODE_FOR_divmodsi4 +- || INSN_CODE (producer) == CODE_FOR_udivmodsi4) ++ if (divmod_p (producer)) + { + rtx def_reg1 = SET_DEST (parallel_element (producer, 0)); + rtx def_reg2 = SET_DEST (parallel_element (producer, 1)); +@@ -1073,8 +1486,7 @@ + results, the quotient and the remainder. We have to handle them + individually. */ + case TYPE_DIV: +- if (INSN_CODE (producer) == CODE_FOR_divmodsi4 +- || INSN_CODE (producer) == CODE_FOR_udivmodsi4) ++ if (divmod_p (producer)) + { + rtx def_reg1 = SET_DEST (parallel_element (producer, 0)); + rtx def_reg2 = SET_DEST (parallel_element (producer, 1)); +@@ -1132,4 +1544,245 @@ + return n9_3r2w_consumed_by_ex_dep_p (consumer, last_def_reg); + } + ++/* Guard functions for N10 cores. */ ++ ++/* Check dependencies from EX to EX (ADDR_OUT -> ADDR_IN). */ ++bool ++nds32_n10_ex_to_ex_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ gcc_assert (get_attr_type (producer) == TYPE_FLOAD ++ || get_attr_type (producer) == TYPE_FSTORE); ++ gcc_assert (get_attr_type (consumer) == TYPE_FLOAD ++ || get_attr_type (consumer) == TYPE_FSTORE); ++ ++ if (!post_update_insn_p (producer)) ++ return false; ++ ++ return reg_overlap_p (extract_base_reg (producer), ++ extract_mem_rtx (consumer)); ++} ++ ++/* Check dependencies from MM to EX. */ ++bool ++nds32_n10_mm_to_ex_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ rtx def_reg; ++ ++ switch (get_attr_type (producer)) ++ { ++ case TYPE_LOAD: ++ case TYPE_MUL: ++ case TYPE_MAC: ++ case TYPE_DALU64: ++ case TYPE_DMUL: ++ case TYPE_DMAC: ++ case TYPE_DALUROUND: ++ case TYPE_DBPICK: ++ case TYPE_DWEXT: ++ def_reg = SET_DEST (PATTERN (producer)); ++ break; ++ ++ /* Some special instructions, divmodsi4 and udivmodsi4, produce two ++ results, the quotient and the remainder. We have to handle them ++ individually. */ ++ case TYPE_DIV: ++ if (divmod_p (producer)) ++ { ++ rtx def_reg1 = SET_DEST (parallel_element (producer, 0)); ++ rtx def_reg2 = SET_DEST (parallel_element (producer, 1)); ++ ++ return (n10_consumed_by_ex_dep_p (consumer, def_reg1) ++ || n10_consumed_by_ex_dep_p (consumer, def_reg2)); ++ } ++ ++ def_reg = SET_DEST (PATTERN (producer)); ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ ++ return n10_consumed_by_ex_dep_p (consumer, def_reg); ++} ++ ++/* Check dependencies from LMW(N, N) to EX. */ ++bool ++nds32_n10_last_load_to_ex_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ rtx last_def_reg = extract_nth_access_reg (producer, -1); ++ ++ return n10_consumed_by_ex_dep_p (consumer, last_def_reg); ++} ++ ++/* Guard functions for Graywolf cores. */ ++ ++/* Check dependencies from EX to EX (ADDR_OUT -> ADDR_IN). */ ++bool ++nds32_gw_ex_to_ex_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ return nds32_n10_ex_to_ex_p (producer, consumer); ++} ++ ++/* Check dependencies from MM to EX. */ ++bool ++nds32_gw_mm_to_ex_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ rtx def_reg; ++ ++ switch (get_attr_type (producer)) ++ { ++ case TYPE_LOAD: ++ case TYPE_MUL: ++ case TYPE_MAC: ++ case TYPE_DALU64: ++ case TYPE_DMUL: ++ case TYPE_DMAC: ++ case TYPE_DALUROUND: ++ case TYPE_DBPICK: ++ case TYPE_DWEXT: ++ def_reg = SET_DEST (PATTERN (producer)); ++ break; ++ ++ /* Some special instructions, divmodsi4 and udivmodsi4, produce two ++ results, the quotient and the remainder. We have to handle them ++ individually. */ ++ case TYPE_DIV: ++ if (divmod_p (producer)) ++ { ++ rtx def_reg1 = SET_DEST (parallel_element (producer, 0)); ++ rtx def_reg2 = SET_DEST (parallel_element (producer, 1)); ++ ++ return (gw_consumed_by_ex_dep_p (consumer, def_reg1) ++ || gw_consumed_by_ex_dep_p (consumer, def_reg2)); ++ } ++ ++ def_reg = SET_DEST (PATTERN (producer)); ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ ++ return gw_consumed_by_ex_dep_p (consumer, def_reg); ++} ++ ++/* Check dependencies from LMW(N, N) to EX. */ ++bool ++nds32_gw_last_load_to_ex_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ rtx last_def_reg = extract_nth_access_reg (producer, -1); ++ ++ return gw_consumed_by_ex_dep_p (consumer, last_def_reg); ++} ++ ++/* Guard functions for N12/N13 cores. */ ++ ++/* Check dependencies from E2 to E1. */ ++bool ++nds32_n13_e2_to_e1_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ rtx def_reg; ++ ++ switch (get_attr_type (producer)) ++ { ++ /* Only post-update load/store instructions are considered. These ++ instructions produces address output at E2. */ ++ case TYPE_LOAD: ++ case TYPE_STORE: ++ case TYPE_LOAD_MULTIPLE: ++ case TYPE_STORE_MULTIPLE: ++ if (!post_update_insn_p (producer)) ++ return false; ++ ++ def_reg = extract_base_reg (producer); ++ break; ++ ++ case TYPE_ALU: ++ case TYPE_ALU_SHIFT: ++ case TYPE_PBSAD: ++ case TYPE_PBSADA: ++ case TYPE_MUL: ++ case TYPE_MAC: ++ def_reg = SET_DEST (PATTERN (producer)); ++ break; ++ ++ case TYPE_BRANCH: ++ return true; ++ ++ case TYPE_DIV: ++ /* Some special instructions, divmodsi4 and udivmodsi4, produce two ++ results, the quotient and the remainder. We have to handle them ++ individually. */ ++ if (divmod_p (producer)) ++ { ++ rtx def_reg1 = SET_DEST (parallel_element (producer, 0)); ++ rtx def_reg2 = SET_DEST (parallel_element (producer, 1)); ++ ++ return (n13_consumed_by_e1_dep_p (consumer, def_reg1) ++ || n13_consumed_by_e1_dep_p (consumer, def_reg2)); ++ } ++ ++ def_reg = SET_DEST (PATTERN (producer)); ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ ++ return n13_consumed_by_e1_dep_p (consumer, def_reg); ++} ++ ++/* Check dependencies from Load-Store Unit (E3) to E1. */ ++bool ++nds32_n13_load_to_e1_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ rtx def_reg = SET_DEST (PATTERN (producer)); ++ ++ gcc_assert (get_attr_type (producer) == TYPE_LOAD); ++ gcc_assert (REG_P (def_reg) || GET_CODE (def_reg) == SUBREG); ++ ++ return n13_consumed_by_e1_dep_p (consumer, def_reg); ++} ++ ++/* Check dependencies from Load-Store Unit (E3) to E2. */ ++bool ++nds32_n13_load_to_e2_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ rtx def_reg = SET_DEST (PATTERN (producer)); ++ ++ gcc_assert (get_attr_type (producer) == TYPE_LOAD); ++ gcc_assert (REG_P (def_reg) || GET_CODE (def_reg) == SUBREG); ++ ++ return n13_consumed_by_e2_dep_p (consumer, def_reg); ++} ++ ++/* Check dependencies from LMW(N, N) to E1. */ ++bool ++nds32_n13_last_load_to_e1_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ rtx last_def_reg = extract_nth_access_reg (producer, -1); ++ ++ return n13_consumed_by_e1_dep_p (consumer, last_def_reg); ++} ++ ++/* Check dependencies from LMW(N, N) to E2. */ ++bool ++nds32_n13_last_load_to_e2_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ rtx last_def_reg = extract_nth_access_reg (producer, -1); ++ ++ return n13_consumed_by_e2_dep_p (consumer, last_def_reg); ++} ++ ++/* Check dependencies from LMW(N, N-1) to E2. */ ++bool ++nds32_n13_last_two_load_to_e1_p (rtx_insn *producer, rtx_insn *consumer) ++{ ++ rtx last_two_def_reg = extract_nth_access_reg (producer, -2); ++ ++ if (last_two_def_reg == NULL_RTX) ++ return false; ++ ++ return n13_consumed_by_e1_dep_p (consumer, last_two_def_reg); ++} + /* ------------------------------------------------------------------------ */ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-predicates.c gcc-8.2.0/gcc/config/nds32/nds32-predicates.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-predicates.c 2018-05-07 04:22:07.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-predicates.c 2019-01-25 15:41:54.217806220 +0100 +@@ -356,8 +356,8 @@ + } + + /* Function to check if 'bclr' instruction can be used with IVAL. */ +-int +-nds32_can_use_bclr_p (int ival) ++bool ++nds32_can_use_bclr_p (HOST_WIDE_INT ival) + { + int one_bit_count; + unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode); +@@ -373,8 +373,8 @@ + } + + /* Function to check if 'bset' instruction can be used with IVAL. */ +-int +-nds32_can_use_bset_p (int ival) ++bool ++nds32_can_use_bset_p (HOST_WIDE_INT ival) + { + int one_bit_count; + unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode); +@@ -389,8 +389,8 @@ + } + + /* Function to check if 'btgl' instruction can be used with IVAL. */ +-int +-nds32_can_use_btgl_p (int ival) ++bool ++nds32_can_use_btgl_p (HOST_WIDE_INT ival) + { + int one_bit_count; + unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode); +@@ -405,8 +405,8 @@ + } + + /* Function to check if 'bitci' instruction can be used with IVAL. */ +-int +-nds32_can_use_bitci_p (int ival) ++bool ++nds32_can_use_bitci_p (HOST_WIDE_INT ival) + { + /* If we are using V3 ISA, we have 'bitci' instruction. + Try to see if we can present 'andi' semantic with +@@ -518,4 +518,117 @@ + + return val >= lower && val < upper; + } ++ ++bool ++nds32_const_unspec_p (rtx x) ++{ ++ if (GET_CODE (x) == CONST) ++ { ++ x = XEXP (x, 0); ++ ++ if (GET_CODE (x) == PLUS) ++ x = XEXP (x, 0); ++ ++ if (GET_CODE (x) == UNSPEC) ++ { ++ switch (XINT (x, 1)) ++ { ++ case UNSPEC_GOTINIT: ++ case UNSPEC_GOT: ++ case UNSPEC_GOTOFF: ++ case UNSPEC_PLT: ++ case UNSPEC_TLSGD: ++ case UNSPEC_TLSLD: ++ case UNSPEC_TLSIE: ++ case UNSPEC_TLSLE: ++ return false; ++ default: ++ return true; ++ } ++ } ++ } ++ ++ if (GET_CODE (x) == SYMBOL_REF ++ && SYMBOL_REF_TLS_MODEL (x)) ++ return false; ++ ++ return true; ++} ++ ++HOST_WIDE_INT ++const_vector_to_hwint (rtx op) ++{ ++ HOST_WIDE_INT hwint = 0; ++ HOST_WIDE_INT mask; ++ int i; ++ int shift_adv; ++ int shift = 0; ++ int nelem; ++ ++ switch (GET_MODE (op)) ++ { ++ case E_V2HImode: ++ mask = 0xffff; ++ shift_adv = 16; ++ nelem = 2; ++ break; ++ case E_V4QImode: ++ mask = 0xff; ++ shift_adv = 8; ++ nelem = 4; ++ break; ++ default: ++ gcc_unreachable (); ++ } ++ ++ if (TARGET_BIG_ENDIAN) ++ { ++ for (i = 0; i < nelem; ++i) ++ { ++ HOST_WIDE_INT val = XINT (XVECEXP (op, 0, nelem - i - 1), 0); ++ hwint |= (val & mask) << shift; ++ shift = shift + shift_adv; ++ } ++ } ++ else ++ { ++ for (i = 0; i < nelem; ++i) ++ { ++ HOST_WIDE_INT val = XINT (XVECEXP (op, 0, i), 0); ++ hwint |= (val & mask) << shift; ++ shift = shift + shift_adv; ++ } ++ } ++ ++ return hwint; ++} ++ ++bool ++nds32_valid_CVp5_p (rtx op) ++{ ++ HOST_WIDE_INT ival = const_vector_to_hwint (op); ++ return (ival < ((1 << 5) + 16)) && (ival >= (0 + 16)); ++} ++ ++bool ++nds32_valid_CVs5_p (rtx op) ++{ ++ HOST_WIDE_INT ival = const_vector_to_hwint (op); ++ return (ival < (1 << 4)) && (ival >= -(1 << 4)); ++} ++ ++bool ++nds32_valid_CVs2_p (rtx op) ++{ ++ HOST_WIDE_INT ival = const_vector_to_hwint (op); ++ return (ival < (1 << 19)) && (ival >= -(1 << 19)); ++} ++ ++bool ++nds32_valid_CVhi_p (rtx op) ++{ ++ HOST_WIDE_INT ival = const_vector_to_hwint (op); ++ return (ival != 0) && ((ival & 0xfff) == 0); ++} ++ + /* ------------------------------------------------------------------------ */ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-protos.h gcc-8.2.0/gcc/config/nds32/nds32-protos.h +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-protos.h 2018-04-22 11:05:10.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-protos.h 2019-01-25 15:38:32.833242671 +0100 +@@ -69,9 +69,10 @@ + + /* ------------------------------------------------------------------------ */ + +-/* Auxiliary functions for lwm/smw. */ ++/* Auxiliary functions for manipulation DI mode. */ + +-extern bool nds32_valid_smw_lwm_base_p (rtx); ++extern rtx nds32_di_high_part_subreg(rtx); ++extern rtx nds32_di_low_part_subreg(rtx); + + /* Auxiliary functions for expanding rtl used in nds32-multiple.md. */ + +@@ -116,6 +117,20 @@ + extern bool nds32_n9_3r2w_mm_to_ex_p (rtx_insn *, rtx_insn *); + extern bool nds32_n9_last_load_to_ex_p (rtx_insn *, rtx_insn *); + ++extern bool nds32_n10_ex_to_ex_p (rtx_insn *, rtx_insn *); ++extern bool nds32_n10_mm_to_ex_p (rtx_insn *, rtx_insn *); ++extern bool nds32_n10_last_load_to_ex_p (rtx_insn *, rtx_insn *); ++ ++extern bool nds32_gw_ex_to_ex_p (rtx_insn *, rtx_insn *); ++extern bool nds32_gw_mm_to_ex_p (rtx_insn *, rtx_insn *); ++extern bool nds32_gw_last_load_to_ex_p (rtx_insn *, rtx_insn *); ++ ++extern bool nds32_n13_e2_to_e1_p (rtx_insn *, rtx_insn *); ++extern bool nds32_n13_load_to_e1_p (rtx_insn *, rtx_insn *); ++extern bool nds32_n13_load_to_e2_p (rtx_insn *, rtx_insn *); ++extern bool nds32_n13_last_load_to_e1_p (rtx_insn *, rtx_insn *); ++extern bool nds32_n13_last_load_to_e2_p (rtx_insn *, rtx_insn *); ++extern bool nds32_n13_last_two_load_to_e1_p (rtx_insn *, rtx_insn *); + + /* Auxiliary functions for stack operation predicate checking. */ + +@@ -123,24 +138,25 @@ + + /* Auxiliary functions for bit operation detection. */ + +-extern int nds32_can_use_bclr_p (int); +-extern int nds32_can_use_bset_p (int); +-extern int nds32_can_use_btgl_p (int); ++extern bool nds32_can_use_bclr_p (HOST_WIDE_INT); ++extern bool nds32_can_use_bset_p (HOST_WIDE_INT); ++extern bool nds32_can_use_btgl_p (HOST_WIDE_INT); + +-extern int nds32_can_use_bitci_p (int); ++extern bool nds32_can_use_bitci_p (HOST_WIDE_INT); + + extern bool nds32_const_double_range_ok_p (rtx, machine_mode, + HOST_WIDE_INT, HOST_WIDE_INT); + ++extern bool nds32_const_unspec_p (rtx x); ++ + /* Auxiliary function for 'Computing the Length of an Insn'. */ + + extern int nds32_adjust_insn_length (rtx_insn *, int); + + /* Auxiliary functions for FP_AS_GP detection. */ + +-extern int nds32_fp_as_gp_check_available (void); +- + extern bool nds32_symbol_load_store_p (rtx_insn *); ++extern bool nds32_naked_function_p (tree); + + /* Auxiliary functions for jump table generation. */ + +@@ -159,10 +175,50 @@ + extern enum nds32_expand_result_type nds32_expand_movcc (rtx *); + extern void nds32_expand_float_movcc (rtx *); + ++/* Auxiliary functions for expand extv/insv instruction. */ ++ ++extern enum nds32_expand_result_type nds32_expand_extv (rtx *); ++extern enum nds32_expand_result_type nds32_expand_insv (rtx *); ++ ++/* Auxiliary functions for expand PIC instruction. */ ++ ++extern void nds32_expand_pic_move (rtx *); ++ ++/* Auxiliary functions to legitimize PIC address. */ ++ ++extern rtx nds32_legitimize_pic_address (rtx); ++ ++/* Auxiliary functions for expand TLS instruction. */ ++ ++extern void nds32_expand_tls_move (rtx *); ++ ++/* Auxiliary functions to legitimize TLS address. */ ++ ++extern rtx nds32_legitimize_tls_address (rtx); ++ ++/* Auxiliary functions to identify thread-local symbol. */ ++ ++extern bool nds32_tls_referenced_p (rtx); ++ ++/* Auxiliary functions for expand ICT instruction. */ ++ ++extern void nds32_expand_ict_move (rtx *); ++ ++/* Auxiliary functions to legitimize address for indirect-call symbol. */ ++ ++extern rtx nds32_legitimize_ict_address (rtx); ++ ++/* Auxiliary functions to identify indirect-call symbol. */ ++ ++extern bool nds32_indirect_call_referenced_p (rtx); + + /* Auxiliary functions to identify long-call symbol. */ + extern bool nds32_long_call_p (rtx); + ++/* Auxiliary functions to identify SYMBOL_REF and LABEL_REF pattern. */ ++ ++extern bool symbolic_reference_mentioned_p (rtx); ++ + /* Auxiliary functions to identify conditional move comparison operand. */ + + extern int nds32_cond_move_p (rtx); +@@ -185,6 +241,7 @@ + extern const char *nds32_output_float_load(rtx *); + extern const char *nds32_output_float_store(rtx *); + extern const char *nds32_output_smw_single_word (rtx *); ++extern const char *nds32_output_smw_double_word (rtx *); + extern const char *nds32_output_lmw_single_word (rtx *); + extern const char *nds32_output_double (rtx *, bool); + extern const char *nds32_output_cbranchsi4_equality_zero (rtx_insn *, rtx *); +@@ -193,9 +250,12 @@ + rtx *); + extern const char *nds32_output_cbranchsi4_greater_less_zero (rtx_insn *, rtx *); + ++extern const char *nds32_output_unpkd8 (rtx, rtx, rtx, rtx, bool); ++ + extern const char *nds32_output_call (rtx, rtx *, rtx, + const char *, const char *, bool); +- ++extern const char *nds32_output_tls_desc (rtx *); ++extern const char *nds32_output_tls_ie (rtx *); + + /* Auxiliary functions to output stack push/pop instruction. */ + +@@ -203,9 +263,19 @@ + extern const char *nds32_output_stack_pop (rtx); + extern const char *nds32_output_return (void); + ++ ++/* Auxiliary functions to split/output sms pattern. */ ++extern bool nds32_need_split_sms_p (rtx, rtx, rtx, rtx); ++extern const char *nds32_output_sms (rtx, rtx, rtx, rtx); ++extern void nds32_split_sms (rtx, rtx, rtx, rtx, rtx, rtx, rtx); ++ + /* Auxiliary functions to split double word RTX pattern. */ + + extern void nds32_spilt_doubleword (rtx *, bool); ++extern void nds32_split_ashiftdi3 (rtx, rtx, rtx); ++extern void nds32_split_ashiftrtdi3 (rtx, rtx, rtx); ++extern void nds32_split_lshiftrtdi3 (rtx, rtx, rtx); ++extern void nds32_split_rotatertdi3 (rtx, rtx, rtx); + + /* Auxiliary functions to split large constant RTX pattern. */ + +@@ -237,15 +307,29 @@ + extern void nds32_asm_file_start_for_isr (void); + extern void nds32_asm_file_end_for_isr (void); + extern bool nds32_isr_function_p (tree); ++extern bool nds32_isr_function_critical_p (tree); + + /* Auxiliary functions for cost calculation. */ + ++extern void nds32_init_rtx_costs (void); + extern bool nds32_rtx_costs_impl (rtx, machine_mode, int, int, int *, bool); + extern int nds32_address_cost_impl (rtx, machine_mode, addr_space_t, bool); + + /* Auxiliary functions for pre-define marco. */ + extern void nds32_cpu_cpp_builtins(struct cpp_reader *); + ++/* Auxiliary functions for const_vector's constraints. */ ++ ++extern HOST_WIDE_INT const_vector_to_hwint (rtx); ++extern bool nds32_valid_CVp5_p (rtx); ++extern bool nds32_valid_CVs5_p (rtx); ++extern bool nds32_valid_CVs2_p (rtx); ++extern bool nds32_valid_CVhi_p (rtx); ++ ++/* Auxiliary functions for lwm/smw. */ ++ ++extern bool nds32_valid_smw_lwm_base_p (rtx); ++ + extern bool nds32_split_double_word_load_store_p (rtx *,bool); + + namespace nds32 { +@@ -258,11 +342,13 @@ + bool store_single_p (rtx_insn *); + bool load_double_p (rtx_insn *); + bool store_double_p (rtx_insn *); ++bool store_offset_reg_p (rtx_insn *); + bool post_update_insn_p (rtx_insn *); + bool immed_offset_p (rtx); + int find_post_update_rtx (rtx_insn *); + rtx extract_mem_rtx (rtx_insn *); + rtx extract_base_reg (rtx_insn *); ++rtx extract_offset_rtx (rtx_insn *); + + rtx extract_shift_reg (rtx); + +@@ -271,6 +357,8 @@ + + rtx extract_mac_non_acc_rtx (rtx_insn *); + ++bool divmod_p (rtx_insn *); ++ + rtx extract_branch_target_rtx (rtx_insn *); + rtx extract_branch_condition_rtx (rtx_insn *); + } // namespace nds32 +@@ -279,5 +367,6 @@ + + /* Functions for create nds32 specific optimization pass. */ + extern rtl_opt_pass *make_pass_nds32_relax_opt (gcc::context *); ++extern rtl_opt_pass *make_pass_nds32_fp_as_gp (gcc::context *); + + /* ------------------------------------------------------------------------ */ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-relax-opt.c gcc-8.2.0/gcc/config/nds32/nds32-relax-opt.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-relax-opt.c 2018-04-01 12:07:40.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-relax-opt.c 2019-01-25 15:38:32.833242671 +0100 +@@ -52,6 +52,8 @@ + #include "cfgrtl.h" + #include "tree-pass.h" + ++using namespace nds32; ++ + /* This is used to create unique relax hint id value. + The initial value is 0. */ + static int relax_group_id = 0; +@@ -185,6 +187,121 @@ + return false; + } + ++/* Return true if x is const and the referance is ict symbol. */ ++static bool ++nds32_ict_const_p (rtx x) ++{ ++ if (GET_CODE (x) == CONST) ++ { ++ x = XEXP (x, 0); ++ return nds32_indirect_call_referenced_p (x); ++ } ++ return FALSE; ++} ++ ++/* Group the following pattern as relax candidates: ++ ++ GOT: ++ sethi $ra, hi20(sym) ++ ori $ra, $ra, lo12(sym) ++ lw $rb, [$ra + $gp] ++ ++ GOTOFF, TLSLE: ++ sethi $ra, hi20(sym) ++ ori $ra, $ra, lo12(sym) ++ LS $rb, [$ra + $gp] ++ ++ GOTOFF, TLSLE: ++ sethi $ra, hi20(sym) ++ ori $ra, $ra, lo12(sym) ++ add $rb, $ra, $gp($tp) ++ ++ Initial GOT table: ++ sethi $gp,hi20(sym) ++ ori $gp, $gp, lo12(sym) ++ add5.pc $gp */ ++ ++static auto_vec nds32_group_infos; ++/* Group the PIC and TLS relax candidate instructions for linker. */ ++static bool ++nds32_pic_tls_group (rtx_insn *def_insn, ++ enum nds32_relax_insn_type relax_type, ++ int sym_type) ++{ ++ df_ref def_record; ++ df_link *link; ++ rtx_insn *use_insn = NULL; ++ rtx pat, new_pat; ++ def_record = DF_INSN_DEFS (def_insn); ++ for (link = DF_REF_CHAIN (def_record); link; link = link->next) ++ { ++ if (!DF_REF_INSN_INFO (link->ref)) ++ continue; ++ ++ use_insn = DF_REF_INSN (link->ref); ++ ++ /* Skip if define insn and use insn not in the same basic block. */ ++ if (!dominated_by_p (CDI_DOMINATORS, ++ BLOCK_FOR_INSN (use_insn), ++ BLOCK_FOR_INSN (def_insn))) ++ return FALSE; ++ ++ /* Skip if use_insn not active insn. */ ++ if (!active_insn_p (use_insn)) ++ return FALSE; ++ ++ switch (relax_type) ++ { ++ case RELAX_ORI: ++ ++ /* GOTOFF, TLSLE: ++ sethi $ra, hi20(sym) ++ ori $ra, $ra, lo12(sym) ++ add $rb, $ra, $gp($tp) */ ++ if ((sym_type == UNSPEC_TLSLE ++ || sym_type == UNSPEC_GOTOFF) ++ && (recog_memoized (use_insn) == CODE_FOR_addsi3)) ++ { ++ pat = XEXP (PATTERN (use_insn), 1); ++ new_pat = ++ gen_rtx_UNSPEC (SImode, ++ gen_rtvec (2, XEXP (pat, 0), XEXP (pat, 1)), ++ UNSPEC_ADD32); ++ validate_replace_rtx (pat, new_pat, use_insn); ++ nds32_group_infos.safe_push (use_insn); ++ } ++ else if (nds32_plus_reg_load_store_p (use_insn) ++ && !nds32_sp_base_or_plus_load_store_p (use_insn)) ++ nds32_group_infos.safe_push (use_insn); ++ else ++ return FALSE; ++ break; ++ ++ default: ++ return FALSE; ++ } ++ } ++ return TRUE; ++} ++ ++static int ++nds32_pic_tls_symbol_type (rtx x) ++{ ++ x = XEXP (SET_SRC (PATTERN (x)), 1); ++ ++ if (GET_CODE (x) == CONST) ++ { ++ x = XEXP (x, 0); ++ ++ if (GET_CODE (x) == PLUS) ++ x = XEXP (x, 0); ++ ++ return XINT (x, 1); ++ } ++ ++ return XINT (x, 1); ++} ++ + /* Group the relax candidates with group id. */ + static void + nds32_group_insns (rtx sethi) +@@ -193,6 +310,7 @@ + df_link *link; + rtx_insn *use_insn = NULL; + rtx group_id; ++ bool valid; + + def_record = DF_INSN_DEFS (sethi); + +@@ -242,6 +360,132 @@ + /* Insert .relax_* directive. */ + if (active_insn_p (use_insn)) + emit_insn_before (gen_relax_group (group_id), use_insn); ++ ++ /* Find ori ra, ra, unspec(symbol) instruction. */ ++ if (use_insn != NULL ++ && recog_memoized (use_insn) == CODE_FOR_lo_sum ++ && !nds32_const_unspec_p (XEXP (SET_SRC (PATTERN (use_insn)), 1))) ++ { ++ int sym_type = nds32_pic_tls_symbol_type (use_insn); ++ valid = nds32_pic_tls_group (use_insn, RELAX_ORI, sym_type); ++ ++ /* Insert .relax_* directive. */ ++ while (!nds32_group_infos.is_empty ()) ++ { ++ use_insn = nds32_group_infos.pop (); ++ if (valid) ++ emit_insn_before (gen_relax_group (group_id), use_insn); ++ } ++ } ++ } ++ ++ relax_group_id++; ++} ++ ++/* Convert relax group id in rtl. */ ++ ++static void ++nds32_group_tls_insn (rtx insn) ++{ ++ rtx pat = PATTERN (insn); ++ rtx unspec_relax_group = XEXP (XVECEXP (pat, 0, 1), 0); ++ ++ while (GET_CODE (pat) != SET && GET_CODE (pat) == PARALLEL) ++ { ++ pat = XVECEXP (pat, 0, 0); ++ } ++ ++ if (GET_CODE (unspec_relax_group) == UNSPEC ++ && XINT (unspec_relax_group, 1) == UNSPEC_VOLATILE_RELAX_GROUP) ++ { ++ XVECEXP (unspec_relax_group, 0, 0) = GEN_INT (relax_group_id); ++ } ++ ++ relax_group_id++; ++} ++ ++static bool ++nds32_float_reg_load_store_p (rtx_insn *insn) ++{ ++ rtx pat = PATTERN (insn); ++ ++ if (get_attr_type (insn) == TYPE_FLOAD ++ && GET_CODE (pat) == SET ++ && (GET_MODE (XEXP (pat, 0)) == SFmode ++ || GET_MODE (XEXP (pat, 0)) == DFmode) ++ && MEM_P (XEXP (pat, 1))) ++ { ++ rtx addr = XEXP (XEXP (pat, 1), 0); ++ ++ /* [$ra] */ ++ if (REG_P (addr)) ++ return true; ++ /* [$ra + offset] */ ++ if (GET_CODE (addr) == PLUS ++ && REG_P (XEXP (addr, 0)) ++ && CONST_INT_P (XEXP (addr, 1))) ++ return true; ++ } ++ return false; ++} ++ ++ ++/* Group float load-store instructions: ++ la $ra, symbol ++ flsi $rt, [$ra + offset] */ ++ ++static void ++nds32_group_float_insns (rtx insn) ++{ ++ df_ref def_record, use_record; ++ df_link *link; ++ rtx_insn *use_insn = NULL; ++ rtx group_id; ++ ++ def_record = DF_INSN_DEFS (insn); ++ ++ for (link = DF_REF_CHAIN (def_record); link; link = link->next) ++ { ++ if (!DF_REF_INSN_INFO (link->ref)) ++ continue; ++ ++ use_insn = DF_REF_INSN (link->ref); ++ ++ /* Skip if define insn and use insn not in the same basic block. */ ++ if (!dominated_by_p (CDI_DOMINATORS, ++ BLOCK_FOR_INSN (use_insn), ++ BLOCK_FOR_INSN (insn))) ++ return; ++ ++ /* Skip if the low-part used register is from different high-part ++ instructions. */ ++ use_record = DF_INSN_USES (use_insn); ++ if (DF_REF_CHAIN (use_record) && DF_REF_CHAIN (use_record)->next) ++ return; ++ ++ /* Skip if use_insn not active insn. */ ++ if (!active_insn_p (use_insn)) ++ return; ++ ++ if (!nds32_float_reg_load_store_p (use_insn) ++ || find_post_update_rtx (use_insn) != -1) ++ return; ++ } ++ ++ group_id = GEN_INT (relax_group_id); ++ /* Insert .relax_* directive for insn. */ ++ emit_insn_before (gen_relax_group (group_id), insn); ++ ++ /* Scan the use insns and insert the directive. */ ++ for (link = DF_REF_CHAIN (def_record); link; link = link->next) ++ { ++ if (!DF_REF_INSN_INFO (link->ref)) ++ continue; ++ ++ use_insn = DF_REF_INSN (link->ref); ++ ++ /* Insert .relax_* directive. */ ++ emit_insn_before (gen_relax_group (group_id), use_insn); + } + + relax_group_id++; +@@ -271,8 +515,21 @@ + /* Find sethi ra, symbol instruction. */ + if (recog_memoized (insn) == CODE_FOR_sethi + && nds32_symbolic_operand (XEXP (SET_SRC (PATTERN (insn)), 0), +- SImode)) ++ SImode) ++ && !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0))) + nds32_group_insns (insn); ++ else if (recog_memoized (insn) == CODE_FOR_tls_ie) ++ nds32_group_tls_insn (insn); ++ else if (TARGET_FPU_SINGLE ++ && recog_memoized (insn) == CODE_FOR_move_addr ++ && !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0))) ++ { ++ nds32_group_float_insns (insn); ++ } ++ } ++ else if (CALL_P (insn) && recog_memoized (insn) == CODE_FOR_tls_desc) ++ { ++ nds32_group_tls_insn (insn); + } + } + +diff -urN gcc-8.2.0.orig/gcc/config/nds32/nds32-utils.c gcc-8.2.0/gcc/config/nds32/nds32-utils.c +--- gcc-8.2.0.orig/gcc/config/nds32/nds32-utils.c 2018-04-08 10:31:52.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/nds32-utils.c 2019-01-25 15:38:32.833242671 +0100 +@@ -142,6 +142,23 @@ + return true; + } + ++bool ++store_offset_reg_p (rtx_insn *insn) ++{ ++ if (get_attr_type (insn) != TYPE_STORE) ++ return false; ++ ++ rtx offset_rtx = extract_offset_rtx (insn); ++ ++ if (offset_rtx == NULL_RTX) ++ return false; ++ ++ if (REG_P (offset_rtx)) ++ return true; ++ ++ return false; ++} ++ + /* Determine if INSN is a post update insn. */ + bool + post_update_insn_p (rtx_insn *insn) +@@ -316,22 +333,114 @@ + if (REG_P (XEXP (mem_rtx, 0))) + return XEXP (mem_rtx, 0); + ++ /* (mem (lo_sum (reg) (symbol_ref)) */ ++ if (GET_CODE (XEXP (mem_rtx, 0)) == LO_SUM) ++ return XEXP (XEXP (mem_rtx, 0), 0); ++ + plus_rtx = XEXP (mem_rtx, 0); + + if (GET_CODE (plus_rtx) == SYMBOL_REF + || GET_CODE (plus_rtx) == CONST) + return NULL_RTX; + +- gcc_assert (GET_CODE (plus_rtx) == PLUS +- || GET_CODE (plus_rtx) == POST_INC +- || GET_CODE (plus_rtx) == POST_DEC +- || GET_CODE (plus_rtx) == POST_MODIFY); +- gcc_assert (REG_P (XEXP (plus_rtx, 0))); + /* (mem (plus (reg) (const_int))) or ++ (mem (plus (mult (reg) (const_int 4)) (reg))) or + (mem (post_inc (reg))) or + (mem (post_dec (reg))) or + (mem (post_modify (reg) (plus (reg) (reg)))) */ +- return XEXP (plus_rtx, 0); ++ gcc_assert (GET_CODE (plus_rtx) == PLUS ++ || GET_CODE (plus_rtx) == POST_INC ++ || GET_CODE (plus_rtx) == POST_DEC ++ || GET_CODE (plus_rtx) == POST_MODIFY); ++ ++ if (REG_P (XEXP (plus_rtx, 0))) ++ return XEXP (plus_rtx, 0); ++ ++ gcc_assert (REG_P (XEXP (plus_rtx, 1))); ++ return XEXP (plus_rtx, 1); ++} ++ ++/* Extract the offset rtx from load/store insns. The function returns ++ NULL_RTX if offset is absent. */ ++rtx ++extract_offset_rtx (rtx_insn *insn) ++{ ++ rtx mem_rtx; ++ rtx plus_rtx; ++ rtx offset_rtx; ++ ++ /* Find the MEM rtx. The multiple load/store insns doens't have ++ the offset field so we can return NULL_RTX here. */ ++ switch (get_attr_type (insn)) ++ { ++ case TYPE_LOAD_MULTIPLE: ++ case TYPE_STORE_MULTIPLE: ++ return NULL_RTX; ++ ++ case TYPE_LOAD: ++ case TYPE_FLOAD: ++ case TYPE_STORE: ++ case TYPE_FSTORE: ++ mem_rtx = extract_mem_rtx (insn); ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ ++ gcc_assert (MEM_P (mem_rtx)); ++ ++ /* (mem (reg)) */ ++ if (REG_P (XEXP (mem_rtx, 0))) ++ return NULL_RTX; ++ ++ plus_rtx = XEXP (mem_rtx, 0); ++ ++ switch (GET_CODE (plus_rtx)) ++ { ++ case SYMBOL_REF: ++ case CONST: ++ case POST_INC: ++ case POST_DEC: ++ return NULL_RTX; ++ ++ case PLUS: ++ /* (mem (plus (reg) (const_int))) or ++ (mem (plus (mult (reg) (const_int 4)) (reg))) */ ++ if (REG_P (XEXP (plus_rtx, 0))) ++ offset_rtx = XEXP (plus_rtx, 1); ++ else ++ { ++ gcc_assert (REG_P (XEXP (plus_rtx, 1))); ++ offset_rtx = XEXP (plus_rtx, 0); ++ } ++ ++ if (ARITHMETIC_P (offset_rtx)) ++ { ++ gcc_assert (GET_CODE (offset_rtx) == MULT); ++ gcc_assert (REG_P (XEXP (offset_rtx, 0))); ++ offset_rtx = XEXP (offset_rtx, 0); ++ } ++ break; ++ ++ case LO_SUM: ++ /* (mem (lo_sum (reg) (symbol_ref)) */ ++ offset_rtx = XEXP (plus_rtx, 1); ++ break; ++ ++ case POST_MODIFY: ++ /* (mem (post_modify (reg) (plus (reg) (reg / const_int)))) */ ++ gcc_assert (REG_P (XEXP (plus_rtx, 0))); ++ plus_rtx = XEXP (plus_rtx, 1); ++ gcc_assert (GET_CODE (plus_rtx) == PLUS); ++ offset_rtx = XEXP (plus_rtx, 0); ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ ++ return offset_rtx; + } + + /* Extract the register of the shift operand from an ALU_SHIFT rtx. */ +@@ -413,6 +522,7 @@ + switch (get_attr_type (insn)) + { + case TYPE_MAC: ++ case TYPE_DMAC: + if (REG_P (XEXP (exp, 0))) + return XEXP (exp, 1); + else +@@ -423,6 +533,19 @@ + } + } + ++/* Check if the DIV insn needs two write ports. */ ++bool ++divmod_p (rtx_insn *insn) ++{ ++ gcc_assert (get_attr_type (insn) == TYPE_DIV); ++ ++ if (INSN_CODE (insn) == CODE_FOR_divmodsi4 ++ || INSN_CODE (insn) == CODE_FOR_udivmodsi4) ++ return true; ++ ++ return false; ++} ++ + /* Extract the rtx representing the branch target to help recognize + data hazards. */ + rtx +diff -urN gcc-8.2.0.orig/gcc/config/nds32/pipelines.md gcc-8.2.0/gcc/config/nds32/pipelines.md +--- gcc-8.2.0.orig/gcc/config/nds32/pipelines.md 2018-04-08 11:21:30.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/pipelines.md 2019-01-25 15:38:32.833242671 +0100 +@@ -44,6 +44,24 @@ + + + ;; ------------------------------------------------------------------------ ++;; Include N10 pipeline settings. ++;; ------------------------------------------------------------------------ ++(include "nds32-n10.md") ++ ++ ++;; ------------------------------------------------------------------------ ++;; Include Graywolf pipeline settings. ++;; ------------------------------------------------------------------------ ++(include "nds32-graywolf.md") ++ ++ ++;; ------------------------------------------------------------------------ ++;; Include N12/N13 pipeline settings. ++;; ------------------------------------------------------------------------ ++(include "nds32-n13.md") ++ ++ ++;; ------------------------------------------------------------------------ + ;; Define simple pipeline settings. + ;; ------------------------------------------------------------------------ + +diff -urN gcc-8.2.0.orig/gcc/config/nds32/predicates.md gcc-8.2.0/gcc/config/nds32/predicates.md +--- gcc-8.2.0.orig/gcc/config/nds32/predicates.md 2018-04-06 07:51:33.000000000 +0200 ++++ gcc-8.2.0/gcc/config/nds32/predicates.md 2019-01-25 15:38:32.833242671 +0100 +@@ -40,7 +40,15 @@ + (match_code "mult,and,ior,xor")) + + (define_predicate "nds32_symbolic_operand" +- (match_code "const,symbol_ref,label_ref")) ++ (and (match_code "const,symbol_ref,label_ref") ++ (match_test "!(TARGET_ICT_MODEL_LARGE ++ && nds32_indirect_call_referenced_p (op))"))) ++ ++(define_predicate "nds32_nonunspec_symbolic_operand" ++ (and (match_code "const,symbol_ref,label_ref") ++ (match_test "!flag_pic && nds32_const_unspec_p (op) ++ && !(TARGET_ICT_MODEL_LARGE ++ && nds32_indirect_call_referenced_p (op))"))) + + (define_predicate "nds32_reg_constant_operand" + (ior (match_operand 0 "register_operand") +@@ -56,14 +64,51 @@ + (and (match_operand 0 "const_int_operand") + (match_test "satisfies_constraint_Is11 (op)")))) + ++(define_predicate "nds32_imm_0_1_operand" ++ (and (match_operand 0 "const_int_operand") ++ (ior (match_test "satisfies_constraint_Iv00 (op)") ++ (match_test "satisfies_constraint_Iv01 (op)")))) ++ ++(define_predicate "nds32_imm_1_2_operand" ++ (and (match_operand 0 "const_int_operand") ++ (ior (match_test "satisfies_constraint_Iv01 (op)") ++ (match_test "satisfies_constraint_Iv02 (op)")))) ++ ++(define_predicate "nds32_imm_1_2_4_8_operand" ++ (and (match_operand 0 "const_int_operand") ++ (ior (ior (match_test "satisfies_constraint_Iv01 (op)") ++ (match_test "satisfies_constraint_Iv02 (op)")) ++ (ior (match_test "satisfies_constraint_Iv04 (op)") ++ (match_test "satisfies_constraint_Iv08 (op)"))))) ++ ++(define_predicate "nds32_imm2u_operand" ++ (and (match_operand 0 "const_int_operand") ++ (match_test "satisfies_constraint_Iu02 (op)"))) ++ ++(define_predicate "nds32_imm4u_operand" ++ (and (match_operand 0 "const_int_operand") ++ (match_test "satisfies_constraint_Iu04 (op)"))) ++ + (define_predicate "nds32_imm5u_operand" + (and (match_operand 0 "const_int_operand") + (match_test "satisfies_constraint_Iu05 (op)"))) + ++(define_predicate "nds32_imm6u_operand" ++ (and (match_operand 0 "const_int_operand") ++ (match_test "satisfies_constraint_Iu06 (op)"))) ++ ++(define_predicate "nds32_rimm4u_operand" ++ (ior (match_operand 0 "register_operand") ++ (match_operand 0 "nds32_imm4u_operand"))) ++ + (define_predicate "nds32_rimm5u_operand" + (ior (match_operand 0 "register_operand") + (match_operand 0 "nds32_imm5u_operand"))) + ++(define_predicate "nds32_rimm6u_operand" ++ (ior (match_operand 0 "register_operand") ++ (match_operand 0 "nds32_imm6u_operand"))) ++ + (define_predicate "nds32_move_operand" + (and (match_operand 0 "general_operand") + (not (match_code "high,const,symbol_ref,label_ref"))) +@@ -78,6 +123,20 @@ + return true; + }) + ++(define_predicate "nds32_vmove_operand" ++ (and (match_operand 0 "general_operand") ++ (not (match_code "high,const,symbol_ref,label_ref"))) ++{ ++ /* If the constant op does NOT satisfy Is20 nor Ihig, ++ we can not perform move behavior by a single instruction. */ ++ if (GET_CODE (op) == CONST_VECTOR ++ && !satisfies_constraint_CVs2 (op) ++ && !satisfies_constraint_CVhi (op)) ++ return false; ++ ++ return true; ++}) ++ + (define_predicate "nds32_and_operand" + (match_operand 0 "nds32_reg_constant_operand") + { +@@ -127,6 +186,15 @@ + (ior (match_operand 0 "nds32_symbolic_operand") + (match_operand 0 "nds32_general_register_operand"))) + ++(define_predicate "nds32_insv_operand" ++ (match_code "const_int") ++{ ++ return INTVAL (op) == 0 ++ || INTVAL (op) == 8 ++ || INTVAL (op) == 16 ++ || INTVAL (op) == 24; ++}) ++ + (define_predicate "nds32_lmw_smw_base_operand" + (and (match_code "mem") + (match_test "nds32_valid_smw_lwm_base_p (op)"))) +diff -urN gcc-8.2.0.orig/gcc/config/nds32/t-elf gcc-8.2.0/gcc/config/nds32/t-elf +--- gcc-8.2.0.orig/gcc/config/nds32/t-elf 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/t-elf 2019-01-25 15:38:32.833242671 +0100 +@@ -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 ++# . ++ ++# 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 ++ ++# ------------------------------------------------------------------------ +diff -urN gcc-8.2.0.orig/gcc/config/nds32/t-linux gcc-8.2.0/gcc/config/nds32/t-linux +--- gcc-8.2.0.orig/gcc/config/nds32/t-linux 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/config/nds32/t-linux 2019-01-25 15:38:32.833242671 +0100 +@@ -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 ++# . ++ ++# 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 += ++ ++# ------------------------------------------------------------------------ +diff -urN gcc-8.2.0.orig/gcc/config.gcc gcc-8.2.0/gcc/config.gcc +--- gcc-8.2.0.orig/gcc/config.gcc 2018-06-25 21:34:01.000000000 +0200 ++++ gcc-8.2.0/gcc/config.gcc 2019-01-25 15:38:32.821242637 +0100 +@@ -445,7 +445,17 @@ + ;; + nds32*) + cpu_type=nds32 +- extra_headers="nds32_intrinsic.h" ++ extra_headers="nds32_intrinsic.h nds32_isr.h nds32_init.inc" ++ 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" + ;; + nios2-*-*) +@@ -2335,17 +2345,36 @@ + tmake_file="${tmake_file} msp430/t-msp430" + extra_gcc_objs="driver-msp430.o" + ;; +-nds32le-*-*) ++nds32*-*-*) + target_cpu_default="0" + tm_defines="${tm_defines}" +- tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} nds32/nds32_intrinsic.h" +- tmake_file="nds32/t-nds32 nds32/t-mlibs" +- ;; +-nds32be-*-*) +- target_cpu_default="0|MASK_BIG_ENDIAN" +- 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" ++ case ${target} in ++ nds32le*-*-*) ++ ;; ++ nds32be-*-*) ++ target_cpu_default="${target_cpu_default}|MASK_BIG_ENDIAN" ++ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" ++ ;; ++ 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 ++ if test x${with_ext_dsp} = xyes; then ++ tm_defines="${tm_defines} TARGET_DEFAULT_EXT_DSP=1" ++ fi + ;; + nios2-*-*) + tm_file="elfos.h ${tm_file}" +@@ -4318,11 +4347,11 @@ + "") + with_cpu=n9 + ;; +- n6 | n7 | n8 | e8 | s8 | n9) ++ n6 | n7 |n8 | e8 | s8 | n9 | n10 | d10 | n12 | n13 | n15) + # OK + ;; + *) +- echo "Cannot accept --with-cpu=$with_cpu, available values are: n6 n7 n8 e8 s8 n9" 1>&2 ++ echo "Cannot accept --with-cpu=$with_cpu, available values are: n6 n7 n8 e8 s8 n9 n10 d10 n12 n13 n15" 1>&2 + exit 1 + ;; + esac +@@ -4332,15 +4361,30 @@ + "") + # the default library is newlib + with_nds32_lib=newlib ++ tm_defines="${tm_defines} TARGET_DEFAULT_CTOR_DTOR=1" + ;; + newlib) + # OK ++ tm_defines="${tm_defines} TARGET_DEFAULT_CTOR_DTOR=1" + ;; + mculib) + # 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}" ++ ;; ++ 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 + ;; + esac +diff -urN gcc-8.2.0.orig/gcc/configure gcc-8.2.0/gcc/configure +--- gcc-8.2.0.orig/gcc/configure 2018-04-18 11:46:58.000000000 +0200 ++++ gcc-8.2.0/gcc/configure 2019-01-25 15:38:32.837242683 +0100 +@@ -27784,7 +27784,7 @@ + # version to the per-target configury. + case "$cpu_type" in + aarch64 | alpha | arc | arm | avr | bfin | cris | i386 | m32c | m68k \ +- | microblaze | mips | nios2 | pa | riscv | rs6000 | score | sparc | spu \ ++ | microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc | spu \ + | tilegx | tilepro | visium | xstormy16 | xtensa) + insn="nop" + ;; +diff -urN gcc-8.2.0.orig/gcc/configure.ac gcc-8.2.0/gcc/configure.ac +--- gcc-8.2.0.orig/gcc/configure.ac 2018-04-18 11:46:58.000000000 +0200 ++++ gcc-8.2.0/gcc/configure.ac 2019-01-25 15:38:32.837242683 +0100 +@@ -4910,7 +4910,7 @@ + # version to the per-target configury. + case "$cpu_type" in + aarch64 | alpha | arc | arm | avr | bfin | cris | i386 | m32c | m68k \ +- | microblaze | mips | nios2 | pa | riscv | rs6000 | score | sparc | spu \ ++ | microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc | spu \ + | tilegx | tilepro | visium | xstormy16 | xtensa) + insn="nop" + ;; +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.c-torture/execute/20010122-1.c gcc-8.2.0/gcc/testsuite/gcc.c-torture/execute/20010122-1.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.c-torture/execute/20010122-1.c 2015-12-10 20:20:14.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.c-torture/execute/20010122-1.c 2019-01-25 15:38:32.837242683 +0100 +@@ -1,4 +1,5 @@ + /* { dg-skip-if "requires frame pointers" { *-*-* } "-fomit-frame-pointer" "" } */ ++/* { dg-additional-options "-malways-save-lp" { target nds32*-*-* } } */ + /* { dg-require-effective-target return_address } */ + + extern void exit (int); +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.dg/lower-subreg-1.c gcc-8.2.0/gcc/testsuite/gcc.dg/lower-subreg-1.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.dg/lower-subreg-1.c 2017-06-17 17:32:28.000000000 +0200 ++++ gcc-8.2.0/gcc/testsuite/gcc.dg/lower-subreg-1.c 2019-01-25 15:38:32.837242683 +0100 +@@ -1,4 +1,4 @@ +-/* { dg-do compile { target { ! { mips64 || { aarch64*-*-* arm*-*-* ia64-*-* sparc*-*-* spu-*-* tilegx-*-* } } } } } */ ++/* { dg-do compile { target { ! { mips64 || { aarch64*-*-* arm*-*-* ia64-*-* nds32*-*-* sparc*-*-* spu-*-* tilegx-*-* } } } } } */ + /* { dg-options "-O -fdump-rtl-subreg1" } */ + /* { dg-additional-options "-mno-stv" { target ia32 } } */ + /* { dg-skip-if "" { { i?86-*-* x86_64-*-* } && x32 } } */ +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.dg/stack-usage-1.c gcc-8.2.0/gcc/testsuite/gcc.dg/stack-usage-1.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.dg/stack-usage-1.c 2017-06-17 17:32:28.000000000 +0200 ++++ gcc-8.2.0/gcc/testsuite/gcc.dg/stack-usage-1.c 2019-01-25 15:38:32.837242683 +0100 +@@ -2,6 +2,7 @@ + /* { dg-options "-fstack-usage" } */ + /* nvptx doesn't have a reg allocator, and hence no stack usage data. */ + /* { dg-skip-if "" { nvptx-*-* } } */ ++/* { dg-options "-fstack-usage -fno-omit-frame-pointer" { target { nds32*-*-* } } } */ + + /* This is aimed at testing basic support for -fstack-usage in the back-ends. + See the SPARC back-end for example (grep flag_stack_usage_info in sparc.c). +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-isb.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-isb.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-isb.c 2013-12-03 11:58:05.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-isb.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,11 +0,0 @@ +-/* Verify that we generate isb instruction with builtin function. */ +- +-/* { dg-do compile } */ +-/* { dg-options "-O0" } */ +-/* { dg-final { scan-assembler "\\tisb" } } */ +- +-void +-test (void) +-{ +- __builtin_nds32_isb (); +-} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-isync.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-isync.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-isync.c 2013-12-03 11:58:05.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-isync.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,12 +0,0 @@ +-/* Verify that we generate isync instruction with builtin function. */ +- +-/* { dg-do compile } */ +-/* { dg-options "-O0" } */ +-/* { dg-final { scan-assembler "\\tisync" } } */ +- +-void +-test (void) +-{ +- int *addr = (int *) 0x53000000; +- __builtin_nds32_isync (addr); +-} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c 2013-12-03 11:58:05.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,17 +0,0 @@ +-/* Verify that we generate mfsr/mtsr instruction with builtin function. */ +- +-/* { dg-do compile } */ +-/* { dg-options "-O0" } */ +-/* { dg-final { scan-assembler "\\tmfsr" } } */ +-/* { dg-final { scan-assembler "\\tmtsr" } } */ +- +-#include +- +-void +-test (void) +-{ +- int ipsw_value; +- +- ipsw_value = __builtin_nds32_mfsr (__NDS32_REG_IPSW__); +- __builtin_nds32_mtsr (ipsw_value, __NDS32_REG_IPSW__); +-} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c 2013-12-03 11:58:05.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,17 +0,0 @@ +-/* Verify that we generate mfusr/mtusr instruction with builtin function. */ +- +-/* { dg-do compile } */ +-/* { dg-options "-O0" } */ +-/* { dg-final { scan-assembler "\\tmfusr" } } */ +-/* { dg-final { scan-assembler "\\tmtusr" } } */ +- +-#include +- +-void +-test (void) +-{ +- int itype_value; +- +- itype_value = __builtin_nds32_mfusr (__NDS32_REG_ITYPE__); +- __builtin_nds32_mtusr (itype_value, __NDS32_REG_ITYPE__); +-} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-setgie-dis.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-setgie-dis.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-setgie-dis.c 2013-12-03 11:58:05.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-setgie-dis.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,11 +0,0 @@ +-/* Verify that we generate setgie.d instruction with builtin function. */ +- +-/* { dg-do compile } */ +-/* { dg-options "-O0" } */ +-/* { dg-final { scan-assembler "\\tsetgie.d" } } */ +- +-void +-test (void) +-{ +- __builtin_nds32_setgie_dis (); +-} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-setgie-en.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-setgie-en.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-setgie-en.c 2013-12-03 11:58:05.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-setgie-en.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,11 +0,0 @@ +-/* Verify that we generate setgie.e instruction with builtin function. */ +- +-/* { dg-do compile } */ +-/* { dg-options "-O0" } */ +-/* { dg-final { scan-assembler "\\tsetgie.e" } } */ +- +-void +-test (void) +-{ +- __builtin_nds32_setgie_en (); +-} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-setgie_mtsr_mfsr.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-setgie_mtsr_mfsr.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/builtin-setgie_mtsr_mfsr.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/builtin-setgie_mtsr_mfsr.c 2019-01-25 15:38:32.837242683 +0100 +@@ -0,0 +1,36 @@ ++/* This is a test program for checking gie with ++ mtsr/mfsr instruction. */ ++ ++/* { dg-do run } */ ++/* { dg-options "-O0" } */ ++ ++#include ++#include ++ ++int ++main () ++{ ++ unsigned int psw; ++ unsigned int gie; ++ unsigned int pfm_ctl; ++ ++ __nds32__setgie_en (); ++ __nds32__dsb(); /* This is needed for waiting pipeline. */ ++ psw = __nds32__mfsr (NDS32_SR_PSW); ++ ++ gie = psw & 0x00000001; ++ ++ if (gie != 1) ++ abort (); ++ ++ psw = psw & 0xFFFFFFFE; ++ __nds32__mtsr (psw,NDS32_SR_PSW); ++ __nds32__dsb(); /* This is needed for waiting pipeline. */ ++ psw = __nds32__mfsr (NDS32_SR_PSW); ++ gie = psw & 0x00000001; ++ ++ if (gie != 0) ++ abort (); ++ else ++ exit (0); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending.c 2019-01-25 15:38:32.837242683 +0100 +@@ -0,0 +1,10 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O1" } */ ++ ++#include ++ ++void ++main (void) ++{ ++ __nds32__clr_pending_swint (); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending-hw.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending-hw.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending-hw.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-clr-pending-hw.c 2019-01-25 15:38:32.837242683 +0100 +@@ -0,0 +1,16 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O1" } */ ++ ++#include ++ ++void ++main (void) ++{ ++ __nds32__clr_pending_hwint (NDS32_INT_H0); ++ __nds32__clr_pending_hwint (NDS32_INT_H1); ++ __nds32__clr_pending_hwint (NDS32_INT_H2); ++ ++ __nds32__clr_pending_hwint (NDS32_INT_H15); ++ __nds32__clr_pending_hwint (NDS32_INT_H16); ++ __nds32__clr_pending_hwint (NDS32_INT_H31); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-disable.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-disable.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-disable.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-disable.c 2019-01-25 15:38:32.837242683 +0100 +@@ -0,0 +1,13 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O1" } */ ++ ++#include ++ ++void ++main (void) ++{ ++ __nds32__disable_int (NDS32_INT_H15); ++ __nds32__disable_int (NDS32_INT_H16); ++ __nds32__disable_int (NDS32_INT_H31); ++ __nds32__disable_int (NDS32_INT_SWI); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-enable.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-enable.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-enable.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-enable.c 2019-01-25 15:38:32.837242683 +0100 +@@ -0,0 +1,13 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O1" } */ ++ ++#include ++ ++void ++main (void) ++{ ++ __nds32__enable_int (NDS32_INT_H15); ++ __nds32__enable_int (NDS32_INT_H16); ++ __nds32__enable_int (NDS32_INT_H31); ++ __nds32__enable_int (NDS32_INT_SWI); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-get-pending-int.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-get-pending-int.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-get-pending-int.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-get-pending-int.c 2019-01-25 15:38:32.837242683 +0100 +@@ -0,0 +1,14 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O1" } */ ++ ++#include ++ ++int ++main (void) ++{ ++ int a = __nds32__get_pending_int (NDS32_INT_H15); ++ int b = __nds32__get_pending_int (NDS32_INT_SWI); ++ int c = __nds32__get_pending_int (NDS32_INT_H16); ++ ++ return a + b + c; ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-get-trig.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-get-trig.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-get-trig.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-get-trig.c 2019-01-25 15:38:32.837242683 +0100 +@@ -0,0 +1,14 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O1" } */ ++ ++#include ++ ++int ++main (void) ++{ ++ int a = __nds32__get_trig_type (NDS32_INT_H0); ++ int b = __nds32__get_trig_type (NDS32_INT_H15); ++ int c = __nds32__get_trig_type (NDS32_INT_H16); ++ int d = __nds32__get_trig_type (NDS32_INT_H31); ++ return a + b + c + d; ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-isb.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-isb.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-isb.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-isb.c 2019-01-25 15:38:32.837242683 +0100 +@@ -0,0 +1,11 @@ ++/* Verify that we generate isb instruction with builtin function. */ ++ ++/* { dg-do compile } */ ++/* { dg-options "-O0" } */ ++/* { dg-final { scan-assembler "\\tisb" } } */ ++ ++void ++test (void) ++{ ++ __builtin_nds32_isb (); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-isync.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-isync.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-isync.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-isync.c 2019-01-25 15:38:32.841242694 +0100 +@@ -0,0 +1,12 @@ ++/* Verify that we generate isync instruction with builtin function. */ ++ ++/* { dg-do compile } */ ++/* { dg-options "-O0" } */ ++/* { dg-final { scan-assembler "\\tisync" } } */ ++ ++void ++test (void) ++{ ++ int *addr = (int *) 0x53000000; ++ __builtin_nds32_isync (addr); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-mfsr-mtsr.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-mfsr-mtsr.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-mfsr-mtsr.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-mfsr-mtsr.c 2019-01-25 15:38:32.841242694 +0100 +@@ -0,0 +1,17 @@ ++/* Verify that we generate mfsr/mtsr instruction with builtin function. */ ++ ++/* { dg-do compile } */ ++/* { dg-options "-O0" } */ ++/* { dg-final { scan-assembler "\\tmfsr" } } */ ++/* { dg-final { scan-assembler "\\tmtsr" } } */ ++ ++#include ++ ++void ++test (void) ++{ ++ int ipsw_value; ++ ++ ipsw_value = __builtin_nds32_mfsr (__NDS32_REG_IPSW__); ++ __builtin_nds32_mtsr (ipsw_value, __NDS32_REG_IPSW__); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-mfusr-mtusr.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-mfusr-mtusr.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-mfusr-mtusr.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-mfusr-mtusr.c 2019-01-25 15:38:32.841242694 +0100 +@@ -0,0 +1,17 @@ ++/* Verify that we generate mfusr/mtusr instruction with builtin function. */ ++ ++/* { dg-do compile } */ ++/* { dg-options "-O0" } */ ++/* { dg-final { scan-assembler "\\tmfusr" } } */ ++/* { dg-final { scan-assembler "\\tmtusr" } } */ ++ ++#include ++ ++void ++test (void) ++{ ++ int itype_value; ++ ++ itype_value = __builtin_nds32_mfusr (__NDS32_REG_ITYPE__); ++ __builtin_nds32_mtusr (itype_value, __NDS32_REG_ITYPE__); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-dis.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-dis.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-dis.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-dis.c 2019-01-25 15:38:32.841242694 +0100 +@@ -0,0 +1,13 @@ ++/* Verify that we generate setgie.d instruction with builtin function. */ ++ ++/* { dg-do compile } */ ++/* { dg-options "-O0" } */ ++/* { dg-final { scan-assembler "\\tsetgie.d" } } */ ++ ++#include ++ ++void ++test (void) ++{ ++ __nds32__setgie_dis (); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-en.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-en.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-en.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-setgie-en.c 2019-01-25 15:38:32.841242694 +0100 +@@ -0,0 +1,13 @@ ++/* Verify that we generate setgie.e instruction with builtin function. */ ++ ++/* { dg-do compile */ ++/* { dg-options "-O0" } */ ++/* { dg-final { scan-assembler "\\tsetgie.e" } } */ ++ ++#include ++ ++void ++test (void) ++{ ++ __nds32__setgie_en (); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-set-pending.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-set-pending.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-set-pending.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-set-pending.c 2019-01-25 15:38:32.841242694 +0100 +@@ -0,0 +1,10 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O1" } */ ++ ++#include ++ ++int ++main (void) ++{ ++ __nds32__set_pending_swint (); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-edge.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-edge.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-edge.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-edge.c 2019-01-25 15:38:32.841242694 +0100 +@@ -0,0 +1,13 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O1" } */ ++ ++#include ++ ++void ++main (void) ++{ ++ __nds32__set_trig_type_edge (NDS32_INT_H0); ++ __nds32__set_trig_type_edge (NDS32_INT_H15); ++ __nds32__set_trig_type_edge (NDS32_INT_H16); ++ __nds32__set_trig_type_edge (NDS32_INT_H31); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-level.c gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-level.c +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-level.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/compile/builtin-set-trig-level.c 2019-01-25 15:38:32.841242694 +0100 +@@ -0,0 +1,13 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O1" } */ ++ ++#include ++ ++void ++main (void) ++{ ++ __nds32__set_trig_type_level (NDS32_INT_H0); ++ __nds32__set_trig_type_level (NDS32_INT_H15); ++ __nds32__set_trig_type_level (NDS32_INT_H16); ++ __nds32__set_trig_type_level (NDS32_INT_H31); ++} +diff -urN gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/nds32.exp gcc-8.2.0/gcc/testsuite/gcc.target/nds32/nds32.exp +--- gcc-8.2.0.orig/gcc/testsuite/gcc.target/nds32/nds32.exp 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/gcc/testsuite/gcc.target/nds32/nds32.exp 2019-01-25 15:38:32.841242694 +0100 +@@ -38,8 +38,10 @@ + dg-init + + # Main loop. +-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \ ++dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/compile/*.\[cS\]]] \ + "" $DEFAULT_CFLAGS ++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \ ++ "" "" + + # All done. + dg-finish +diff -urN gcc-8.2.0.orig/gcc/testsuite/lib/target-supports.exp gcc-8.2.0/gcc/testsuite/lib/target-supports.exp +--- gcc-8.2.0.orig/gcc/testsuite/lib/target-supports.exp 2018-06-29 00:23:51.000000000 +0200 ++++ gcc-8.2.0/gcc/testsuite/lib/target-supports.exp 2019-01-25 15:38:32.841242694 +0100 +@@ -8783,6 +8783,7 @@ + || [istarget avr*-*-*] + || [istarget crisv32-*-*] || [istarget cris-*-*] + || [istarget mmix-*-*] ++ || [istarget nds32*-*-*] + || [istarget s390*-*-*] + || [istarget powerpc*-*-*] + || [istarget nios2*-*-*] +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/initfini.c gcc-8.2.0/libgcc/config/nds32/initfini.c +--- gcc-8.2.0.orig/libgcc/config/nds32/initfini.c 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/initfini.c 2019-01-25 15:38:32.841242694 +0100 +@@ -25,6 +25,10 @@ + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + ++#include ++/* Need header file for `struct object' type. */ ++#include "../libgcc/unwind-dw2-fde.h" ++ + /* Declare a pointer to void function type. */ + typedef void (*func_ptr) (void); + +@@ -42,11 +46,59 @@ + refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__ + symbol in crtinit.o, where they are defined. */ + +-static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors"))) +- = { (func_ptr) (-1) }; ++static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors"), used)) ++ = { (func_ptr) 0 }; ++ ++static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors"), used)) ++ = { (func_ptr) 0 }; ++ ++ ++#ifdef SUPPORT_UNWINDING_DWARF2 ++/* Preparation of exception handling with dwar2 mechanism registration. */ ++ ++asm ("\n\ ++ .section .eh_frame,\"aw\",@progbits\n\ ++ .global __EH_FRAME_BEGIN__\n\ ++ .type __EH_FRAME_BEGIN__, @object\n\ ++ .align 2\n\ ++__EH_FRAME_BEGIN__:\n\ ++ ! Beginning location of eh_frame section\n\ ++ .previous\n\ ++"); ++ ++extern func_ptr __EH_FRAME_BEGIN__[]; ++ + +-static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors"))) +- = { (func_ptr) (-1) }; ++/* Note that the following two functions are going to be chained into ++ constructor and destructor list, repectively. So these two declarations ++ must be placed after __CTOR_LIST__ and __DTOR_LIST. */ ++extern void __nds32_register_eh(void) __attribute__((constructor, used)); ++extern void __nds32_deregister_eh(void) __attribute__((destructor, used)); ++ ++/* Register the exception handling table as the first constructor. */ ++void ++__nds32_register_eh (void) ++{ ++ static struct object object; ++ if (__register_frame_info) ++ __register_frame_info (__EH_FRAME_BEGIN__, &object); ++} ++ ++/* Unregister the exception handling table as a deconstructor. */ ++void ++__nds32_deregister_eh (void) ++{ ++ static int completed = 0; ++ ++ if (completed) ++ return; ++ ++ if (__deregister_frame_info) ++ __deregister_frame_info (__EH_FRAME_BEGIN__); ++ ++ completed = 1; ++} ++#endif + + /* Run all the global destructors on exit from the program. */ + +@@ -63,7 +115,7 @@ + same particular root executable or shared library file. */ + + static void __do_global_dtors (void) +-asm ("__do_global_dtors") __attribute__ ((section (".text"))); ++asm ("__do_global_dtors") __attribute__ ((section (".text"), used)); + + static void + __do_global_dtors (void) +@@ -116,23 +168,37 @@ + last, these words naturally end up at the very ends of the two lists + contained in these two sections. */ + +-static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors"))) ++static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors"), used)) + = { (func_ptr) 0 }; + +-static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors"))) ++static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors"), used)) + = { (func_ptr) 0 }; + ++#ifdef SUPPORT_UNWINDING_DWARF2 ++/* ZERO terminator in .eh_frame section. */ ++asm ("\n\ ++ .section .eh_frame,\"aw\",@progbits\n\ ++ .global __EH_FRAME_END__\n\ ++ .type __EH_FRAME_END__, @object\n\ ++ .align 2\n\ ++__EH_FRAME_END__:\n\ ++ ! End location of eh_frame section with ZERO terminator\n\ ++ .word 0\n\ ++ .previous\n\ ++"); ++#endif ++ + /* Run all global constructors for the program. + Note that they are run in reverse order. */ + + static void __do_global_ctors (void) +-asm ("__do_global_ctors") __attribute__ ((section (".text"))); ++asm ("__do_global_ctors") __attribute__ ((section (".text"), used)); + + static void + __do_global_ctors (void) + { + func_ptr *p; +- for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--) ++ for (p = __CTOR_END__ - 1; *p; p--) + (*p) (); + } + +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/adj_intr_lvl.inc gcc-8.2.0/libgcc/config/nds32/isr-library/adj_intr_lvl.inc +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/adj_intr_lvl.inc 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/adj_intr_lvl.inc 2019-01-25 15:38:32.841242694 +0100 +@@ -26,13 +26,26 @@ + .macro ADJ_INTR_LVL + #if defined(NDS32_NESTED) /* Nested handler. */ + mfsr $r3, $PSW ++ /* By substracting 1 from $PSW, we can lower PSW.INTL ++ and enable GIE simultaneously. */ + addi $r3, $r3, #-0x1 ++ #if __NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__ ++ ori $r3, $r3, 0x2000 /* Set PSW.AEN(b'13) */ ++ #endif + mtsr $r3, $PSW + #elif defined(NDS32_NESTED_READY) /* Nested ready handler. */ + /* Save ipc and ipsw and lower INT level. */ + mfsr $r3, $PSW + addi $r3, $r3, #-0x2 ++ #if __NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__ ++ ori $r3, $r3, 0x2000 /* Set PSW.AEN(b'13) */ ++ #endif + mtsr $r3, $PSW + #else /* Not nested handler. */ ++ #if __NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__ ++ mfsr $r3, $PSW ++ ori $r3, $r3, 0x2000 /* Set PSW.AEN(b'13) */ ++ mtsr $r3, $PSW ++ #endif + #endif + .endm +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/excp_isr.S gcc-8.2.0/libgcc/config/nds32/isr-library/excp_isr.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/excp_isr.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/excp_isr.S 2019-01-25 15:38:32.841242694 +0100 +@@ -23,6 +23,7 @@ + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + ++#include "save_usr_regs.inc" + #include "save_mac_regs.inc" + #include "save_fpu_regs.inc" + #include "save_fpu_regs_00.inc" +@@ -32,35 +33,33 @@ + #include "save_all.inc" + #include "save_partial.inc" + #include "adj_intr_lvl.inc" +-#include "restore_mac_regs.inc" + #include "restore_fpu_regs_00.inc" + #include "restore_fpu_regs_01.inc" + #include "restore_fpu_regs_02.inc" + #include "restore_fpu_regs_03.inc" + #include "restore_fpu_regs.inc" ++#include "restore_mac_regs.inc" ++#include "restore_usr_regs.inc" + #include "restore_all.inc" + #include "restore_partial.inc" ++ + .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */ + .align 1 +-/* +- First Level Handlers +- 1. First Level Handlers are invokded in vector section via jump instruction +- with specific names for different configurations. +- 2. Naming Format: _nds32_e_SR_NT for exception handlers. +- _nds32_i_SR_NT for interrupt handlers. +- 2.1 All upper case letters are replaced with specific lower case letters encodings. +- 2.2 SR: Saved Registers +- sa: Save All regs (context) +- ps: Partial Save (all caller-saved regs) +- 2.3 NT: Nested Type +- ns: nested +- nn: not nested +- nr: nested ready +-*/ +- +-/* +- This is original 16-byte vector size version. +-*/ ++ ++/* First Level Handlers ++ 1. First Level Handlers are invokded in vector section via jump instruction ++ with specific names for different configurations. ++ 2. Naming Format: _nds32_e_SR_NT for exception handlers. ++ _nds32_i_SR_NT for interrupt handlers. ++ 2.1 All upper case letters are replaced with specific lower case letters encodings. ++ 2.2 SR -- Saved Registers ++ sa: Save All regs (context) ++ ps: Partial Save (all caller-saved regs) ++ 2.3 NT -- Nested Type ++ ns: nested ++ nn: not nested ++ nr: nested ready */ ++ + #ifdef NDS32_SAVE_ALL_REGS + #if defined(NDS32_NESTED) + .globl _nds32_e_sa_ns +@@ -91,21 +90,26 @@ + #endif /* endif for Nest Type */ + #endif /* not NDS32_SAVE_ALL_REGS */ + +-/* +- This is 16-byte vector size version. +- The vector id was restored into $r0 in vector by compiler. +-*/ ++ ++/* For 4-byte vector size version, the vector id is ++ extracted from $ITYPE and is set into $r0 by library. ++ For 16-byte vector size version, the vector id ++ is set into $r0 in vector section by compiler. */ ++ ++/* Save used registers. */ + #ifdef NDS32_SAVE_ALL_REGS + SAVE_ALL + #else + SAVE_PARTIAL + #endif ++ + /* Prepare to call 2nd level handler. */ + la $r2, _nds32_jmptbl_00 + lw $r2, [$r2 + $r0 << #2] + ADJ_INTR_LVL /* Adjust INTR level. $r3 is clobbered. */ + jral $r2 +- /* Restore used registers. */ ++ ++/* Restore used registers. */ + #ifdef NDS32_SAVE_ALL_REGS + RESTORE_ALL + #else +@@ -113,6 +117,7 @@ + #endif + iret + ++ + #ifdef NDS32_SAVE_ALL_REGS + #if defined(NDS32_NESTED) + .size _nds32_e_sa_ns, .-_nds32_e_sa_ns +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/intr_isr.S gcc-8.2.0/libgcc/config/nds32/isr-library/intr_isr.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/intr_isr.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/intr_isr.S 2019-01-25 15:38:32.841242694 +0100 +@@ -23,6 +23,7 @@ + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + ++#include "save_usr_regs.inc" + #include "save_mac_regs.inc" + #include "save_fpu_regs.inc" + #include "save_fpu_regs_00.inc" +@@ -32,35 +33,33 @@ + #include "save_all.inc" + #include "save_partial.inc" + #include "adj_intr_lvl.inc" +-#include "restore_mac_regs.inc" + #include "restore_fpu_regs_00.inc" + #include "restore_fpu_regs_01.inc" + #include "restore_fpu_regs_02.inc" + #include "restore_fpu_regs_03.inc" + #include "restore_fpu_regs.inc" ++#include "restore_mac_regs.inc" ++#include "restore_usr_regs.inc" + #include "restore_all.inc" + #include "restore_partial.inc" ++ + .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */ + .align 1 +-/* +- First Level Handlers +- 1. First Level Handlers are invokded in vector section via jump instruction +- with specific names for different configurations. +- 2. Naming Format: _nds32_e_SR_NT for exception handlers. +- _nds32_i_SR_NT for interrupt handlers. +- 2.1 All upper case letters are replaced with specific lower case letters encodings. +- 2.2 SR: Saved Registers +- sa: Save All regs (context) +- ps: Partial Save (all caller-saved regs) +- 2.3 NT: Nested Type +- ns: nested +- nn: not nested +- nr: nested ready +-*/ +- +-/* +- This is original 16-byte vector size version. +-*/ ++ ++/* First Level Handlers ++ 1. First Level Handlers are invokded in vector section via jump instruction ++ with specific names for different configurations. ++ 2. Naming Format: _nds32_e_SR_NT for exception handlers. ++ _nds32_i_SR_NT for interrupt handlers. ++ 2.1 All upper case letters are replaced with specific lower case letters encodings. ++ 2.2 SR -- Saved Registers ++ sa: Save All regs (context) ++ ps: Partial Save (all caller-saved regs) ++ 2.3 NT -- Nested Type ++ ns: nested ++ nn: not nested ++ nr: nested ready */ ++ + #ifdef NDS32_SAVE_ALL_REGS + #if defined(NDS32_NESTED) + .globl _nds32_i_sa_ns +@@ -91,21 +90,36 @@ + #endif /* endif for Nest Type */ + #endif /* not NDS32_SAVE_ALL_REGS */ + +-/* +- This is 16-byte vector size version. +- The vector id was restored into $r0 in vector by compiler. +-*/ ++ ++/* For 4-byte vector size version, the vector id is ++ extracted from $ITYPE and is set into $r0 by library. ++ For 16-byte vector size version, the vector id ++ is set into $r0 in vector section by compiler. */ ++ ++/* Save used registers first. */ + #ifdef NDS32_SAVE_ALL_REGS + SAVE_ALL + #else + SAVE_PARTIAL + #endif +- /* Prepare to call 2nd level handler. */ ++ ++/* According to vector size, we need to have different implementation. */ ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* Prepare to call 2nd level handler. */ ++ la $r2, _nds32_jmptbl_00 ++ lw $r2, [$r2 + $r0 << #2] ++ addi $r0, $r0, #-9 /* Make interrput vector id zero-based. */ ++ ADJ_INTR_LVL /* Adjust INTR level. $r3 is clobbered. */ ++ jral $r2 ++#else /* not __NDS32_ISR_VECTOR_SIZE_4__ */ ++ /* Prepare to call 2nd level handler. */ + la $r2, _nds32_jmptbl_09 /* For zero-based vcetor id. */ + lw $r2, [$r2 + $r0 << #2] + ADJ_INTR_LVL /* Adjust INTR level. $r3 is clobbered. */ + jral $r2 +- /* Restore used registers. */ ++#endif /* not __NDS32_ISR_VECTOR_SIZE_4__ */ ++ ++/* Restore used registers. */ + #ifdef NDS32_SAVE_ALL_REGS + RESTORE_ALL + #else +@@ -113,6 +127,7 @@ + #endif + iret + ++ + #ifdef NDS32_SAVE_ALL_REGS + #if defined(NDS32_NESTED) + .size _nds32_i_sa_ns, .-_nds32_i_sa_ns +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/reset.S gcc-8.2.0/libgcc/config/nds32/isr-library/reset.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/reset.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/reset.S 2019-01-25 15:38:32.841242694 +0100 +@@ -26,22 +26,18 @@ + .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */ + .align 1 + .weak _SDA_BASE_ /* For reset handler only. */ +- .weak _FP_BASE_ /* For reset handler only. */ + .weak _nds32_init_mem /* User defined memory initialization function. */ + .globl _start + .globl _nds32_reset + .type _nds32_reset, @function + _nds32_reset: + _start: +-#ifdef NDS32_EXT_EX9 +- .no_ex9_begin +-#endif + /* Handle NMI and warm boot if any of them exists. */ + beqz $sp, 1f /* Reset, NMI or warm boot? */ + /* Either NMI or warm boot; save all regs. */ + + /* Preserve registers for context-switching. */ +-#ifdef __NDS32_REDUCED_REGS__ ++#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS + /* For 16-reg mode. */ + smw.adm $r0, [$sp], $r10, #0x0 + smw.adm $r15, [$sp], $r15, #0xf +@@ -49,10 +45,9 @@ + /* For 32-reg mode. */ + smw.adm $r0, [$sp], $r27, #0xf + #endif +-#ifdef NDS32_EXT_IFC ++#if __NDS32_EXT_IFC__ + mfusr $r1, $IFC_LP +- smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep +- stack 8-byte alignment. */ ++ smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep stack 8-byte alignment. */ + #endif + + la $gp, _SDA_BASE_ /* Init GP for small data access. */ +@@ -71,12 +66,11 @@ + bnez $r0, 1f /* If fail to resume, do cold boot. */ + + /* Restore registers for context-switching. */ +-#ifdef NDS32_EXT_IFC +- lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep +- stack 8-byte alignment. */ ++#if __NDS32_EXT_IFC__ ++ lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep stack 8-byte alignment. */ + mtusr $r1, $IFC_LP + #endif +-#ifdef __NDS32_REDUCED_REGS__ ++#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS + /* For 16-reg mode. */ + lmw.bim $r15, [$sp], $r15, #0xf + lmw.bim $r0, [$sp], $r10, #0x0 +@@ -88,6 +82,17 @@ + + + 1: /* Cold boot. */ ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* With vector ID feature for v3 architecture, default vector size is 4-byte. */ ++ /* Set IVB.ESZ = 0 (vector table entry size = 4 bytes) */ ++ mfsr $r0, $IVB ++ li $r1, #0xc000 ++ or $r0, $r0, $r1 ++ xor $r0, $r0, $r1 ++ mtsr $r0, $IVB ++ dsb ++#else ++ /* There is no vector ID feature, so the vector size must be 16-byte. */ + /* Set IVB.ESZ = 1 (vector table entry size = 16 bytes) */ + mfsr $r0, $IVB + li $r1, #0xffff3fff +@@ -95,36 +100,54 @@ + ori $r0, $r0, #0x4000 + mtsr $r0, $IVB + dsb ++#endif + + la $gp, _SDA_BASE_ /* Init $gp. */ +- la $fp, _FP_BASE_ /* Init $fp. */ + la $sp, _stack /* Init $sp. */ +-#ifdef NDS32_EXT_EX9 +-/* +- * Initialize the table base of EX9 instruction +- * ex9 generation needs to disable before the ITB is set +- */ +- mfsr $r0, $MSC_CFG /* Check if HW support of EX9. */ ++ ++#if __NDS32_EXT_EX9__ ++.L_init_itb: ++ /* Initialization for Instruction Table Base (ITB). ++ The symbol _ITB_BASE_ is determined by Linker. ++ Set $ITB only if MSC_CFG.EIT (cr4.b'24) is set. */ ++ mfsr $r0, $MSC_CFG + srli $r0, $r0, 24 + andi $r0, $r0, 0x1 +- beqz $r0, 4f /* Zero means HW does not support EX9. */ +- la $r0, _ITB_BASE_ /* Init $ITB. */ ++ beqz $r0, 4f /* Fall through ? */ ++ la $r0, _ITB_BASE_ + mtusr $r0, $ITB +- .no_ex9_end + 4: + #endif +- la $r15, _nds32_init_mem /* Call DRAM init. _nds32_init_mem +- may written by C language. */ ++ ++#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__ ++.L_init_fpu: ++ /* Initialize FPU ++ Set FUCOP_CTL.CP0EN (fucpr.b'0). */ ++ mfsr $r0, $FUCOP_CTL ++ ori $r0, $r0, 0x1 ++ mtsr $r0, $FUCOP_CTL ++ dsb ++ /* According to [bugzilla #9425], set flush-to-zero mode. ++ That is, set $FPCSR.DNZ(b'12) = 1. */ ++ FMFCSR $r0 ++ ori $r0, $r0, 0x1000 ++ FMTCSR $r0 ++ dsb ++#endif ++ ++ /* Call DRAM init. _nds32_init_mem may written by C language. */ ++ la $r15, _nds32_init_mem + beqz $r15, 6f + jral $r15 + 6: + l.w $r15, _nds32_jmptbl_00 /* Load reset handler. */ + jral $r15 +-/* Reset handler() should never return in a RTOS or non-OS system. +- In case it does return, an exception will be generated. +- This exception will be caught either by default break handler or by EDM. +- Default break handle may just do an infinite loop. +- EDM will notify GDB and GDB will regain control when the ID is 0x7fff. */ ++ ++ /* Reset handler() should never return in a RTOS or non-OS system. ++ In case it does return, an exception will be generated. ++ This exception will be caught either by default break handler or by EDM. ++ Default break handle may just do an infinite loop. ++ EDM will notify GDB and GDB will regain control when the ID is 0x7fff. */ + 5: + break #0x7fff + .size _nds32_reset, .-_nds32_reset +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/restore_all.inc gcc-8.2.0/libgcc/config/nds32/isr-library/restore_all.inc +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/restore_all.inc 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/restore_all.inc 2019-01-25 15:38:32.841242694 +0100 +@@ -31,15 +31,11 @@ + mtsr $r2, $IPSW + RESTORE_FPU_REGS + RESTORE_MAC_REGS +-#ifdef NDS32_EXT_IFC +- lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep +- stack 8-byte alignment. */ +- mtusr $r1, $IFC_LP +-#endif +-#ifdef __NDS32_REDUCED_REGS__ ++ RESTORE_USR_REGS ++#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS + lmw.bim $r0, [$sp], $r10, #0x0 /* Restore all regs. */ + lmw.bim $r15, [$sp], $r15, #0xf +-#else /* not __NDS32_REDUCED_REGS__ */ ++#else + lmw.bim $r0, [$sp], $r27, #0xf /* Restore all regs. */ + #endif + .endm +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/restore_mac_regs.inc gcc-8.2.0/libgcc/config/nds32/isr-library/restore_mac_regs.inc +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/restore_mac_regs.inc 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/restore_mac_regs.inc 2019-01-25 15:38:32.841242694 +0100 +@@ -24,7 +24,7 @@ + . */ + + .macro RESTORE_MAC_REGS +-#ifdef NDS32_DX_REGS ++#if __NDS32_DX_REGS__ + lmw.bim $r1, [$sp], $r4, #0x0 + mtusr $r1, $d0.lo + mtusr $r2, $d0.hi +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/restore_partial.inc gcc-8.2.0/libgcc/config/nds32/isr-library/restore_partial.inc +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/restore_partial.inc 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/restore_partial.inc 2019-01-25 15:38:32.841242694 +0100 +@@ -31,15 +31,11 @@ + mtsr $r1, $IPC /* Set IPC. */ + mtsr $r2, $IPSW /* Set IPSW. */ + #endif +- RESTORE_FPU_REGS +- RESTORE_MAC_REGS +-#ifdef NDS32_EXT_IFC +- lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep +- stack 8-byte alignment. */ +- mtusr $r1, $IFC_LP +-#endif ++ RESTORE_FPU_REGS ++ RESTORE_MAC_REGS ++ RESTORE_USR_REGS + lmw.bim $r0, [$sp], $r5, #0x0 /* Restore all regs. */ +-#ifdef __NDS32_REDUCED_REGS__ ++#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS + lmw.bim $r15, [$sp], $r15, #0x2 + #else + lmw.bim $r15, [$sp], $r27, #0x2 /* Restore all regs. */ +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/restore_usr_regs.inc gcc-8.2.0/libgcc/config/nds32/isr-library/restore_usr_regs.inc +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/restore_usr_regs.inc 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/restore_usr_regs.inc 2019-01-25 15:38:32.841242694 +0100 +@@ -0,0 +1,42 @@ ++/* c-isr library stuff 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. ++ ++ 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 ++ . */ ++ ++.macro RESTORE_USR_REGS ++#if __NDS32_EXT_IFC__ && (__NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__) ++ lmw.bim $r1, [$sp], $r4, #0x0 ++ mtusr $r1, $IFC_LP ++ mtusr $r2, $LB ++ mtusr $r3, $LE ++ mtusr $r4, $LC ++#elif __NDS32_EXT_IFC__ ++ lmw.bim $r1, [$sp], $r2, #0x0 ++ mtusr $r1, $IFC_LP ++#elif __NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__ ++ lmw.bim $r1, [$sp], $r4, #0x0 ++ mtusr $r1, $LB ++ mtusr $r2, $LE ++ mtusr $r3, $LC ++#endif ++.endm +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/save_all.inc gcc-8.2.0/libgcc/config/nds32/isr-library/save_all.inc +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/save_all.inc 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/save_all.inc 2019-01-25 15:38:32.841242694 +0100 +@@ -23,45 +23,42 @@ + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +-.macro SAVE_ALL_4B +-#ifdef __NDS32_REDUCED_REGS__ ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ ++/* If vector size is 4-byte, we have to save registers ++ in the macro implementation. */ ++.macro SAVE_ALL ++#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS + smw.adm $r15, [$sp], $r15, #0xf + smw.adm $r0, [$sp], $r10, #0x0 +-#else /* not __NDS32_REDUCED_REGS__ */ ++#else + smw.adm $r0, [$sp], $r27, #0xf +-#endif /* not __NDS32_REDUCED_REGS__ */ +-#ifdef NDS32_EXT_IFC +- mfusr $r1, $IFC_LP +- smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep +- stack 8-byte alignment. */ + #endif +- SAVE_MAC_REGS +- SAVE_FPU_REGS ++ SAVE_USR_REGS ++ SAVE_MAC_REGS ++ SAVE_FPU_REGS + mfsr $r1, $IPC /* Get IPC. */ + mfsr $r2, $IPSW /* Get IPSW. */ + smw.adm $r1, [$sp], $r2, #0x0 /* Push IPC, IPSW. */ + move $r1, $sp /* $r1 is ptr to NDS32_CONTEXT. */ + mfsr $r0, $ITYPE /* Get VID to $r0. */ + srli $r0, $r0, #5 +-#ifdef __NDS32_ISA_V2__ + andi $r0, $r0, #127 +-#else +- fexti33 $r0, #6 +-#endif + .endm + ++#else /* not __NDS32_ISR_VECTOR_SIZE_4__ */ ++ ++/* If vector size is 16-byte, some works can be done in ++ the vector section generated by compiler, so that we ++ can implement less in the macro. */ + .macro SAVE_ALL +-/* SAVE_REG_TBL code has been moved to +- vector table generated by compiler. */ +-#ifdef NDS32_EXT_IFC +- mfusr $r1, $IFC_LP +- smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep +- stack 8-byte alignment. */ +-#endif +- SAVE_MAC_REGS +- SAVE_FPU_REGS ++ SAVE_USR_REGS ++ SAVE_MAC_REGS ++ SAVE_FPU_REGS + mfsr $r1, $IPC /* Get IPC. */ + mfsr $r2, $IPSW /* Get IPSW. */ + smw.adm $r1, [$sp], $r2, #0x0 /* Push IPC, IPSW. */ + move $r1, $sp /* $r1 is ptr to NDS32_CONTEXT. */ + .endm ++ ++#endif /* not __NDS32_ISR_VECTOR_SIZE_4__ */ +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/save_mac_regs.inc gcc-8.2.0/libgcc/config/nds32/isr-library/save_mac_regs.inc +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/save_mac_regs.inc 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/save_mac_regs.inc 2019-01-25 15:38:32.841242694 +0100 +@@ -24,7 +24,7 @@ + . */ + + .macro SAVE_MAC_REGS +-#ifdef NDS32_DX_REGS ++#if __NDS32_DX_REGS__ + mfusr $r1, $d0.lo + mfusr $r2, $d0.hi + mfusr $r3, $d1.lo +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/save_partial.inc gcc-8.2.0/libgcc/config/nds32/isr-library/save_partial.inc +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/save_partial.inc 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/save_partial.inc 2019-01-25 15:38:32.841242694 +0100 +@@ -23,20 +23,20 @@ + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +-.macro SAVE_PARTIAL_4B +-#ifdef __NDS32_REDUCED_REGS__ ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ ++/* If vector size is 4-byte, we have to save registers ++ in the macro implementation. */ ++.macro SAVE_PARTIAL ++#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS + smw.adm $r15, [$sp], $r15, #0x2 +-#else /* not __NDS32_REDUCED_REGS__ */ ++#else + smw.adm $r15, [$sp], $r27, #0x2 +-#endif /* not __NDS32_REDUCED_REGS__ */ +- smw.adm $r0, [$sp], $r5, #0x0 +-#ifdef NDS32_EXT_IFC +- mfusr $r1, $IFC_LP +- smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep +- stack 8-byte alignment. */ + #endif +- SAVE_MAC_REGS +- SAVE_FPU_REGS ++ smw.adm $r0, [$sp], $r5, #0x0 ++ SAVE_USR_REGS ++ SAVE_MAC_REGS ++ SAVE_FPU_REGS + #if defined(NDS32_NESTED) || defined(NDS32_NESTED_READY) + mfsr $r1, $IPC /* Get IPC. */ + mfsr $r2, $IPSW /* Get IPSW. */ +@@ -44,26 +44,24 @@ + #endif + mfsr $r0, $ITYPE /* Get VID to $r0. */ + srli $r0, $r0, #5 +-#ifdef __NDS32_ISA_V2__ + andi $r0, $r0, #127 +-#else +- fexti33 $r0, #6 +-#endif + .endm + ++#else /* not __NDS32_ISR_VECTOR_SIZE_4__ */ ++ ++/* If vector size is 16-byte, some works can be done in ++ the vector section generated by compiler, so that we ++ can implement less in the macro. */ ++ + .macro SAVE_PARTIAL +-/* SAVE_CALLER_REGS code has been moved to +- vector table generated by compiler. */ +-#ifdef NDS32_EXT_IFC +- mfusr $r1, $IFC_LP +- smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep +- stack 8-byte alignment. */ +-#endif +- SAVE_MAC_REGS +- SAVE_FPU_REGS ++ SAVE_USR_REGS ++ SAVE_MAC_REGS ++ SAVE_FPU_REGS + #if defined(NDS32_NESTED) || defined(NDS32_NESTED_READY) + mfsr $r1, $IPC /* Get IPC. */ + mfsr $r2, $IPSW /* Get IPSW. */ + smw.adm $r1, [$sp], $r2, #0x0 /* Push IPC, IPSW. */ + #endif + .endm ++ ++#endif /* not __NDS32_ISR_VECTOR_SIZE_4__ */ +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/save_usr_regs.inc gcc-8.2.0/libgcc/config/nds32/isr-library/save_usr_regs.inc +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/save_usr_regs.inc 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/save_usr_regs.inc 2019-01-25 15:38:32.841242694 +0100 +@@ -0,0 +1,44 @@ ++/* c-isr library stuff 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. ++ ++ 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 ++ . */ ++ ++.macro SAVE_USR_REGS ++/* Store User Special Registers according to supported ISA extension ++ !!! WATCH OUT !!! Take care of 8-byte alignment issue. */ ++#if __NDS32_EXT_IFC__ && (__NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__) ++ mfusr $r1, $IFC_LP ++ mfusr $r2, $LB ++ mfusr $r3, $LE ++ mfusr $r4, $LC ++ smw.adm $r1, [$sp], $r4, #0x0 /* Save even. Ok! */ ++#elif __NDS32_EXT_IFC__ ++ mfusr $r1, $IFC_LP ++ smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep stack 8-byte aligned. */ ++#elif (__NDS32_EXT_ZOL__ || __NDS32_EXT_DSP__) ++ mfusr $r1, $LB ++ mfusr $r2, $LE ++ mfusr $r3, $LC ++ smw.adm $r1, [$sp], $r4, #0x0 /* Save extra $r4 to keep stack 8-byte aligned. */ ++#endif ++.endm +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid00.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid00.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid00.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid00.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.00, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_00 + .type _nds32_vector_00, @function + _nds32_vector_00: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid01.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid01.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid01.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid01.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.01, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_01 + .type _nds32_vector_01, @function + _nds32_vector_01: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid02.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid02.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid02.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid02.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.02, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_02 + .type _nds32_vector_02, @function + _nds32_vector_02: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid03.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid03.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid03.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid03.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.03, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_03 + .type _nds32_vector_03, @function + _nds32_vector_03: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid04.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid04.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid04.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid04.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.04, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_04 + .type _nds32_vector_04, @function + _nds32_vector_04: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid05.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid05.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid05.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid05.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.05, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_05 + .type _nds32_vector_05, @function + _nds32_vector_05: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid06.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid06.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid06.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid06.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.06, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_06 + .type _nds32_vector_06, @function + _nds32_vector_06: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid07.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid07.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid07.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid07.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.07, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_07 + .type _nds32_vector_07, @function + _nds32_vector_07: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid08.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid08.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid08.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid08.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.08, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_08 + .type _nds32_vector_08, @function + _nds32_vector_08: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid09.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid09.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid09.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid09.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.09, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_09 + .type _nds32_vector_09, @function + _nds32_vector_09: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid10.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid10.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid10.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid10.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.10, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_10 + .type _nds32_vector_10, @function + _nds32_vector_10: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid11.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid11.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid11.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid11.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.11, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_11 + .type _nds32_vector_11, @function + _nds32_vector_11: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid12.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid12.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid12.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid12.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.12, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_12 + .type _nds32_vector_12, @function + _nds32_vector_12: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid13.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid13.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid13.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid13.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.13, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_13 + .type _nds32_vector_13, @function + _nds32_vector_13: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid14.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid14.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid14.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid14.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.14, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_14 + .type _nds32_vector_14, @function + _nds32_vector_14: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid15.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid15.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid15.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid15.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.15, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_15 + .type _nds32_vector_15, @function + _nds32_vector_15: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid16.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid16.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid16.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid16.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.16, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_16 + .type _nds32_vector_16, @function + _nds32_vector_16: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid17.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid17.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid17.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid17.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.17, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_17 + .type _nds32_vector_17, @function + _nds32_vector_17: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid18.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid18.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid18.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid18.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.18, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_18 + .type _nds32_vector_18, @function + _nds32_vector_18: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid19.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid19.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid19.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid19.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.19, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_19 + .type _nds32_vector_19, @function + _nds32_vector_19: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid20.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid20.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid20.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid20.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.20, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_20 + .type _nds32_vector_20, @function + _nds32_vector_20: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid21.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid21.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid21.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid21.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.21, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_21 + .type _nds32_vector_21, @function + _nds32_vector_21: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid22.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid22.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid22.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid22.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.22, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_22 + .type _nds32_vector_22, @function + _nds32_vector_22: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid23.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid23.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid23.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid23.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.23, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_23 + .type _nds32_vector_23, @function + _nds32_vector_23: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid24.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid24.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid24.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid24.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.24, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_24 + .type _nds32_vector_24, @function + _nds32_vector_24: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid25.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid25.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid25.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid25.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.25, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_25 + .type _nds32_vector_25, @function + _nds32_vector_25: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid26.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid26.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid26.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid26.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.26, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_26 + .type _nds32_vector_26, @function + _nds32_vector_26: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid27.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid27.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid27.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid27.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.27, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_27 + .type _nds32_vector_27, @function + _nds32_vector_27: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid28.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid28.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid28.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid28.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.28, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_28 + .type _nds32_vector_28, @function + _nds32_vector_28: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid29.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid29.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid29.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid29.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.29, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_29 + .type _nds32_vector_29, @function + _nds32_vector_29: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid30.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid30.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid30.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid30.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.30, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_30 + .type _nds32_vector_30, @function + _nds32_vector_30: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid31.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid31.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid31.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid31.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.31, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_31 + .type _nds32_vector_31, @function + _nds32_vector_31: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid32.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid32.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid32.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid32.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.32, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_32 + .type _nds32_vector_32, @function + _nds32_vector_32: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid33.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid33.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid33.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid33.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.33, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_33 + .type _nds32_vector_33, @function + _nds32_vector_33: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid34.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid34.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid34.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid34.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.34, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_34 + .type _nds32_vector_34, @function + _nds32_vector_34: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid35.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid35.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid35.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid35.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.35, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_35 + .type _nds32_vector_35, @function + _nds32_vector_35: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid36.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid36.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid36.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid36.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.36, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_36 + .type _nds32_vector_36, @function + _nds32_vector_36: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid37.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid37.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid37.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid37.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.37, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_37 + .type _nds32_vector_37, @function + _nds32_vector_37: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid38.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid38.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid38.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid38.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.38, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_38 + .type _nds32_vector_38, @function + _nds32_vector_38: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid39.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid39.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid39.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid39.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.39, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_39 + .type _nds32_vector_39, @function + _nds32_vector_39: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid40.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid40.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid40.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid40.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.40, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_40 + .type _nds32_vector_40, @function + _nds32_vector_40: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid41.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid41.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid41.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid41.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.41, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_41 + .type _nds32_vector_41, @function + _nds32_vector_41: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid42.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid42.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid42.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid42.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.42, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_42 + .type _nds32_vector_42, @function + _nds32_vector_42: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid43.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid43.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid43.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid43.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.43, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_43 + .type _nds32_vector_43, @function + _nds32_vector_43: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid44.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid44.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid44.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid44.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.44, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_44 + .type _nds32_vector_44, @function + _nds32_vector_44: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid45.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid45.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid45.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid45.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.45, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_45 + .type _nds32_vector_45, @function + _nds32_vector_45: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid46.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid46.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid46.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid46.S 2019-01-25 15:38:32.841242694 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.46, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_46 + .type _nds32_vector_46, @function + _nds32_vector_46: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid47.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid47.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid47.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid47.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.47, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_47 + .type _nds32_vector_47, @function + _nds32_vector_47: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid48.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid48.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid48.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid48.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.48, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_48 + .type _nds32_vector_48, @function + _nds32_vector_48: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid49.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid49.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid49.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid49.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.49, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_49 + .type _nds32_vector_49, @function + _nds32_vector_49: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid50.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid50.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid50.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid50.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.50, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_50 + .type _nds32_vector_50, @function + _nds32_vector_50: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid51.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid51.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid51.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid51.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.51, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_51 + .type _nds32_vector_51, @function + _nds32_vector_51: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid52.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid52.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid52.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid52.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.52, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_52 + .type _nds32_vector_52, @function + _nds32_vector_52: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid53.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid53.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid53.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid53.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.53, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_53 + .type _nds32_vector_53, @function + _nds32_vector_53: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid54.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid54.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid54.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid54.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.54, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_54 + .type _nds32_vector_54, @function + _nds32_vector_54: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid55.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid55.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid55.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid55.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.55, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_55 + .type _nds32_vector_55, @function + _nds32_vector_55: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid56.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid56.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid56.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid56.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.56, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_56 + .type _nds32_vector_56, @function + _nds32_vector_56: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid57.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid57.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid57.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid57.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.57, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_57 + .type _nds32_vector_57, @function + _nds32_vector_57: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid58.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid58.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid58.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid58.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.58, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_58 + .type _nds32_vector_58, @function + _nds32_vector_58: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid59.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid59.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid59.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid59.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.59, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_59 + .type _nds32_vector_59, @function + _nds32_vector_59: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid60.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid60.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid60.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid60.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.60, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_60 + .type _nds32_vector_60, @function + _nds32_vector_60: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid61.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid61.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid61.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid61.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.61, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_61 + .type _nds32_vector_61, @function + _nds32_vector_61: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid62.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid62.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid62.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid62.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.62, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_62 + .type _nds32_vector_62, @function + _nds32_vector_62: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid63.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid63.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid63.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid63.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.63, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_63 + .type _nds32_vector_63, @function + _nds32_vector_63: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid64.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid64.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid64.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid64.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.64, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_64 + .type _nds32_vector_64, @function + _nds32_vector_64: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid65.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid65.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid65.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid65.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.65, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_65 + .type _nds32_vector_65, @function + _nds32_vector_65: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid66.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid66.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid66.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid66.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.66, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_66 + .type _nds32_vector_66, @function + _nds32_vector_66: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid67.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid67.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid67.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid67.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.67, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_67 + .type _nds32_vector_67, @function + _nds32_vector_67: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid68.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid68.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid68.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid68.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.68, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_68 + .type _nds32_vector_68, @function + _nds32_vector_68: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid69.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid69.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid69.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid69.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.69, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_69 + .type _nds32_vector_69, @function + _nds32_vector_69: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid70.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid70.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid70.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid70.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.70, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_70 + .type _nds32_vector_70, @function + _nds32_vector_70: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid71.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid71.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid71.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid71.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.71, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_71 + .type _nds32_vector_71, @function + _nds32_vector_71: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid72.S gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid72.S +--- gcc-8.2.0.orig/libgcc/config/nds32/isr-library/vec_vid72.S 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/isr-library/vec_vid72.S 2019-01-25 15:38:32.845242705 +0100 +@@ -24,8 +24,15 @@ + . */ + + .section .nds32_vector.72, "ax" ++#if __NDS32_ISR_VECTOR_SIZE_4__ ++ /* The vector size is default 4-byte for v3 architecture. */ ++ .vec_size 4 ++ .align 2 ++#else ++ /* The vector size is default 16-byte for other architectures. */ + .vec_size 16 + .align 4 ++#endif + .weak _nds32_vector_72 + .type _nds32_vector_72, @function + _nds32_vector_72: +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/linux-atomic.c gcc-8.2.0/libgcc/config/nds32/linux-atomic.c +--- gcc-8.2.0.orig/libgcc/config/nds32/linux-atomic.c 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/linux-atomic.c 2019-01-25 15:38:32.845242705 +0100 +@@ -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 ++. */ ++ ++/* 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__and_fetch and __sync_fetch_and_ 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) +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/linux-unwind.h gcc-8.2.0/libgcc/config/nds32/linux-unwind.h +--- gcc-8.2.0.orig/libgcc/config/nds32/linux-unwind.h 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/linux-unwind.h 2019-01-25 15:38:32.845242705 +0100 +@@ -0,0 +1,143 @@ ++/* 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 ++ . */ ++ ++#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 ++#include ++#include ++ ++/* Exactly the same layout as the kernel structures, unique names. */ ++ ++/* arch/nds32/kernel/signal.c */ ++struct _rt_sigframe { ++ siginfo_t info; ++ struct ucontext_t uc; ++}; ++ ++#define RT_SIGRETURN 0x8b00f044 ++ ++#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. ++ FIXME: Currently we only handle little endian (EL) case. */ ++ if (pc[0] == RT_SIGRETURN) ++ { ++ /* Using '_sigfame' memory address to locate kernal's sigcontext. ++ The sigcontext structures in arch/nds32/include/asm/sigcontext.h. */ ++ struct _rt_sigframe *rt_; ++ rt_ = context->cfa; ++ sc_ = &rt_->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 +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/t-nds32-glibc gcc-8.2.0/libgcc/config/nds32/t-nds32-glibc +--- gcc-8.2.0.orig/libgcc/config/nds32/t-nds32-glibc 1970-01-01 01:00:00.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/t-nds32-glibc 2019-01-25 15:38:37.357255536 +0100 +@@ -0,0 +1,34 @@ ++# Rules of glibc library makefile of Andes NDS32 cpu for GNU compiler ++# Copyright (C) 2012-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. ++# ++# You should have received a copy of the GNU General Public License ++# along with GCC; see the file COPYING3. If not see ++# . ++ ++# Compiler flags to use when compiling 'libgcc2.c' ++HOST_LIBGCC2_CFLAGS = -O2 -fPIC -fwrapv ++LIB2ADD += $(srcdir)/config/nds32/linux-atomic.c ++ ++#LIB1ASMSRC = nds32/lib1asmsrc-newlib.S ++#LIB1ASMFUNCS = _divsi3 _modsi3 _udivsi3 _umodsi3 ++ ++# List of functions not to build from libgcc2.c. ++#LIB2FUNCS_EXCLUDE = _clzsi2 ++ ++# List of extra C and assembler files(*.S) to add to static libgcc2. ++#LIB2ADD_ST += $(srcdir)/config/nds32/lib2csrc-newlib/_clzsi2.c ++ ++# ------------------------------------------------------------------------ +diff -urN gcc-8.2.0.orig/libgcc/config/nds32/t-nds32-isr gcc-8.2.0/libgcc/config/nds32/t-nds32-isr +--- gcc-8.2.0.orig/libgcc/config/nds32/t-nds32-isr 2018-01-03 11:03:58.000000000 +0100 ++++ gcc-8.2.0/libgcc/config/nds32/t-nds32-isr 2019-01-25 15:38:37.357255536 +0100 +@@ -23,11 +23,11 @@ + # Makfile fragment rules for libnds32_isr.a to support ISR attribute extension + ############################################################################### + +-# basic flags setting ++# Basic flags setting. + ISR_CFLAGS = $(CFLAGS) -c + +-# the object files we would like to create +-LIBNDS32_ISR_16B_OBJS = \ ++# The object files we would like to create. ++LIBNDS32_ISR_VEC_OBJS = \ + vec_vid00.o vec_vid01.o vec_vid02.o vec_vid03.o \ + vec_vid04.o vec_vid05.o vec_vid06.o vec_vid07.o \ + vec_vid08.o vec_vid09.o vec_vid10.o vec_vid11.o \ +@@ -46,40 +46,9 @@ + vec_vid60.o vec_vid61.o vec_vid62.o vec_vid63.o \ + vec_vid64.o vec_vid65.o vec_vid66.o vec_vid67.o \ + vec_vid68.o vec_vid69.o vec_vid70.o vec_vid71.o \ +- vec_vid72.o \ +- excp_isr_ps_nn.o excp_isr_ps_ns.o excp_isr_ps_nr.o \ +- excp_isr_sa_nn.o excp_isr_sa_ns.o excp_isr_sa_nr.o \ +- intr_isr_ps_nn.o intr_isr_ps_ns.o intr_isr_ps_nr.o \ +- intr_isr_sa_nn.o intr_isr_sa_ns.o intr_isr_sa_nr.o \ +- reset.o +- +-LIBNDS32_ISR_4B_OBJS = \ +- vec_vid00_4b.o vec_vid01_4b.o vec_vid02_4b.o vec_vid03_4b.o \ +- vec_vid04_4b.o vec_vid05_4b.o vec_vid06_4b.o vec_vid07_4b.o \ +- vec_vid08_4b.o vec_vid09_4b.o vec_vid10_4b.o vec_vid11_4b.o \ +- vec_vid12_4b.o vec_vid13_4b.o vec_vid14_4b.o vec_vid15_4b.o \ +- vec_vid16_4b.o vec_vid17_4b.o vec_vid18_4b.o vec_vid19_4b.o \ +- vec_vid20_4b.o vec_vid21_4b.o vec_vid22_4b.o vec_vid23_4b.o \ +- vec_vid24_4b.o vec_vid25_4b.o vec_vid26_4b.o vec_vid27_4b.o \ +- vec_vid28_4b.o vec_vid29_4b.o vec_vid30_4b.o vec_vid31_4b.o \ +- vec_vid32_4b.o vec_vid33_4b.o vec_vid34_4b.o vec_vid35_4b.o \ +- vec_vid36_4b.o vec_vid37_4b.o vec_vid38_4b.o vec_vid39_4b.o \ +- vec_vid40_4b.o vec_vid41_4b.o vec_vid42_4b.o vec_vid43_4b.o \ +- vec_vid44_4b.o vec_vid45_4b.o vec_vid46_4b.o vec_vid47_4b.o \ +- vec_vid48_4b.o vec_vid49_4b.o vec_vid50_4b.o vec_vid51_4b.o \ +- vec_vid52_4b.o vec_vid53_4b.o vec_vid54_4b.o vec_vid55_4b.o \ +- vec_vid56_4b.o vec_vid57_4b.o vec_vid58_4b.o vec_vid59_4b.o \ +- vec_vid60_4b.o vec_vid61_4b.o vec_vid62_4b.o vec_vid63_4b.o \ +- vec_vid64_4b.o vec_vid65_4b.o vec_vid66_4b.o vec_vid67_4b.o \ +- vec_vid68_4b.o vec_vid69_4b.o vec_vid70_4b.o vec_vid71_4b.o \ +- vec_vid72_4b.o \ +- excp_isr_ps_nn_4b.o excp_isr_ps_ns_4b.o excp_isr_ps_nr_4b.o \ +- excp_isr_sa_nn_4b.o excp_isr_sa_ns_4b.o excp_isr_sa_nr_4b.o \ +- intr_isr_ps_nn_4b.o intr_isr_ps_ns_4b.o intr_isr_ps_nr_4b.o \ +- intr_isr_sa_nn_4b.o intr_isr_sa_ns_4b.o intr_isr_sa_nr_4b.o \ +- reset_4b.o ++ vec_vid72.o + +-LIBNDS32_ISR_COMMON_OBJS = \ ++LIBNDS32_ISR_JMP_OBJS = \ + jmptbl_vid00.o jmptbl_vid01.o jmptbl_vid02.o jmptbl_vid03.o \ + jmptbl_vid04.o jmptbl_vid05.o jmptbl_vid06.o jmptbl_vid07.o \ + jmptbl_vid08.o jmptbl_vid09.o jmptbl_vid10.o jmptbl_vid11.o \ +@@ -98,29 +67,32 @@ + jmptbl_vid60.o jmptbl_vid61.o jmptbl_vid62.o jmptbl_vid63.o \ + jmptbl_vid64.o jmptbl_vid65.o jmptbl_vid66.o jmptbl_vid67.o \ + jmptbl_vid68.o jmptbl_vid69.o jmptbl_vid70.o jmptbl_vid71.o \ +- jmptbl_vid72.o \ ++ jmptbl_vid72.o ++ ++LIBNDS32_ISR_COMMON_OBJS = \ ++ excp_isr_ps_nn.o excp_isr_ps_ns.o excp_isr_ps_nr.o \ ++ excp_isr_sa_nn.o excp_isr_sa_ns.o excp_isr_sa_nr.o \ ++ intr_isr_ps_nn.o intr_isr_ps_ns.o intr_isr_ps_nr.o \ ++ intr_isr_sa_nn.o intr_isr_sa_ns.o intr_isr_sa_nr.o \ ++ reset.o \ + nmih.o \ + wrh.o + +-LIBNDS32_ISR_COMPLETE_OBJS = $(LIBNDS32_ISR_16B_OBJS) $(LIBNDS32_ISR_4B_OBJS) $(LIBNDS32_ISR_COMMON_OBJS) +- ++LIBNDS32_ISR_COMPLETE_OBJS = $(LIBNDS32_ISR_VEC_OBJS) $(LIBNDS32_ISR_JMP_OBJS) $(LIBNDS32_ISR_COMMON_OBJS) + +-# Build common objects for ISR library +-nmih.o: $(srcdir)/config/nds32/isr-library/nmih.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/nmih.S -o nmih.o + +-wrh.o: $(srcdir)/config/nds32/isr-library/wrh.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/wrh.S -o wrh.o + +-jmptbl_vid%.o: $(srcdir)/config/nds32/isr-library/jmptbl_vid%.S ++# Build vector vid objects for ISR library. ++vec_vid%.o: $(srcdir)/config/nds32/isr-library/vec_vid%.S + $(GCC_FOR_TARGET) $(ISR_CFLAGS) $< -o $@ + + +- +-# Build 16b version objects for ISR library. (no "_4b" postfix string) +-vec_vid%.o: $(srcdir)/config/nds32/isr-library/vec_vid%.S ++# Build jump table objects for ISR library. ++jmptbl_vid%.o: $(srcdir)/config/nds32/isr-library/jmptbl_vid%.S + $(GCC_FOR_TARGET) $(ISR_CFLAGS) $< -o $@ + ++ ++# Build commen objects for ISR library. + excp_isr_ps_nn.o: $(srcdir)/config/nds32/isr-library/excp_isr.S + $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/excp_isr.S -o excp_isr_ps_nn.o + +@@ -160,48 +132,12 @@ + reset.o: $(srcdir)/config/nds32/isr-library/reset.S + $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/reset.S -o reset.o + +-# Build 4b version objects for ISR library. +-vec_vid%_4b.o: $(srcdir)/config/nds32/isr-library/vec_vid%_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $< -o $@ +- +-excp_isr_ps_nn_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_ps_nn_4b.o +- +-excp_isr_ps_ns_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_ps_ns_4b.o +- +-excp_isr_ps_nr_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_ps_nr_4b.o +- +-excp_isr_sa_nn_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_sa_nn_4b.o +- +-excp_isr_sa_ns_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_sa_ns_4b.o +- +-excp_isr_sa_nr_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_sa_nr_4b.o +- +-intr_isr_ps_nn_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_ps_nn_4b.o +- +-intr_isr_ps_ns_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_ps_ns_4b.o +- +-intr_isr_ps_nr_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_ps_nr_4b.o +- +-intr_isr_sa_nn_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_sa_nn_4b.o +- +-intr_isr_sa_ns_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_sa_ns_4b.o ++nmih.o: $(srcdir)/config/nds32/isr-library/nmih.S ++ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/nmih.S -o nmih.o + +-intr_isr_sa_nr_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_sa_nr_4b.o ++wrh.o: $(srcdir)/config/nds32/isr-library/wrh.S ++ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/wrh.S -o wrh.o + +-reset_4b.o: $(srcdir)/config/nds32/isr-library/reset_4b.S +- $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/reset_4b.S -o reset_4b.o + + + # The rule to create libnds32_isr.a file +diff -urN gcc-8.2.0.orig/libgcc/config.host gcc-8.2.0/libgcc/config.host +--- gcc-8.2.0.orig/libgcc/config.host 2018-04-06 22:04:17.000000000 +0200 ++++ gcc-8.2.0/libgcc/config.host 2019-01-25 15:38:32.841242694 +0100 +@@ -974,6 +974,23 @@ + 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" + ;; ++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*) + # Basic makefile fragment and extra_parts for crt stuff. + # We also append c-isr library implementation. diff --git a/util/crossgcc/sum/binutils-2.30.tar.xz.cksum b/util/crossgcc/sum/binutils-2.30.tar.xz.cksum deleted file mode 100644 index 3493413556..0000000000 --- a/util/crossgcc/sum/binutils-2.30.tar.xz.cksum +++ /dev/null @@ -1 +0,0 @@ -574d3b5650413d6ee65195a4f5ecbddc3a38f718 tarballs/binutils-2.30.tar.xz diff --git a/util/crossgcc/sum/binutils-2.31.1.tar.xz.cksum b/util/crossgcc/sum/binutils-2.31.1.tar.xz.cksum new file mode 100644 index 0000000000..6a26c8f2f6 --- /dev/null +++ b/util/crossgcc/sum/binutils-2.31.1.tar.xz.cksum @@ -0,0 +1 @@ +3b031410897fe224412f3a6a1b052402d2fbcc6a tarballs/binutils-2.31.1.tar.xz diff --git a/util/crossgcc/sum/gcc-8.1.0.tar.xz.cksum b/util/crossgcc/sum/gcc-8.1.0.tar.xz.cksum deleted file mode 100644 index d185533514..0000000000 --- a/util/crossgcc/sum/gcc-8.1.0.tar.xz.cksum +++ /dev/null @@ -1 +0,0 @@ -b34031ba9ff3e248b2c62de0825e49a1e0e01998 tarballs/gcc-8.1.0.tar.xz diff --git a/util/crossgcc/sum/gcc-8.2.0.tar.xz.cksum b/util/crossgcc/sum/gcc-8.2.0.tar.xz.cksum new file mode 100644 index 0000000000..1ef301a5d3 --- /dev/null +++ b/util/crossgcc/sum/gcc-8.2.0.tar.xz.cksum @@ -0,0 +1 @@ +19926bdb6c4b58891015929853d41aeff019d400 tarballs/gcc-8.2.0.tar.xz -- cgit v1.2.3