From b1d26f0e9261ec4070e8561406853fe5bddeb27c Mon Sep 17 00:00:00 2001 From: Patrick Georgi Date: Wed, 2 May 2018 17:13:34 +0200 Subject: [PATCH 56/59] util/crossgcc: update to gcc 8.1.0 and binutils 2.30 Also update patches as necessary. Change-Id: I1e8074954d5d7a4eff590abb7439e9be7d3762aa Signed-off-by: Patrick Georgi Reviewed-on: https://review.coreboot.org/25997 Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- util/crossgcc/buildgcc | 10 +- ...ld.patch => binutils-2.30_mips-gold.patch} | 0 .../patches/binutils-2.30_nds32.patch | 25740 ++++++ ...c.patch => binutils-2.30_no-bfd-doc.patch} | 0 .../patches/gcc-6.3.0_ada-raise.patch | 11 - .../patches/gcc-6.3.0_elf_biarch.patch | 87 - .../crossgcc/patches/gcc-6.3.0_memmodel.patch | 416 - .../patches/gcc-6.3.0_nds32_ite.patch | 73397 ---------------- .../crossgcc/patches/gcc-6.3.0_no-p-var.patch | 15 - .../patches/gcc-6.3.0_pointer_integer.patch | 27 - util/crossgcc/patches/gcc-6.3.0_riscv.patch | 10521 --- ...ch => gcc-8.1.0_ada-musl_workaround.patch} | 24 +- .../crossgcc/patches/gcc-8.1.0_armv6s-m.patch | 64 + ...-6.3.0_gnat.patch => gcc-8.1.0_gnat.patch} | 2 +- ....0_libgcc.patch => gcc-8.1.0_libgcc.patch} | 5 +- .../patches/gcc-8.1.0_nds32_ite.patch | 21164 +++++ .../crossgcc/sum/binutils-2.29.1.tar.xz.cksum | 1 - util/crossgcc/sum/binutils-2.30.tar.xz.cksum | 1 + util/crossgcc/sum/gcc-6.3.0.tar.bz2.cksum | 1 - util/crossgcc/sum/gcc-8.1.0.tar.xz.cksum | 1 + 20 files changed, 46993 insertions(+), 84494 deletions(-) rename util/crossgcc/patches/{binutils-2.29.1_mips-gold.patch => binutils-2.30_mips-gold.patch} (100%) create mode 100644 util/crossgcc/patches/binutils-2.30_nds32.patch rename util/crossgcc/patches/{binutils-2.29.1_no-bfd-doc.patch => binutils-2.30_no-bfd-doc.patch} (100%) delete mode 100644 util/crossgcc/patches/gcc-6.3.0_ada-raise.patch delete mode 100644 util/crossgcc/patches/gcc-6.3.0_elf_biarch.patch delete mode 100644 util/crossgcc/patches/gcc-6.3.0_memmodel.patch delete mode 100644 util/crossgcc/patches/gcc-6.3.0_nds32_ite.patch delete mode 100644 util/crossgcc/patches/gcc-6.3.0_no-p-var.patch delete mode 100644 util/crossgcc/patches/gcc-6.3.0_pointer_integer.patch delete mode 100644 util/crossgcc/patches/gcc-6.3.0_riscv.patch rename util/crossgcc/patches/{gcc-6.3.0_ada-musl_workaround.patch => gcc-8.1.0_ada-musl_workaround.patch} (79%) create mode 100644 util/crossgcc/patches/gcc-8.1.0_armv6s-m.patch rename util/crossgcc/patches/{gcc-6.3.0_gnat.patch => gcc-8.1.0_gnat.patch} (89%) rename util/crossgcc/patches/{gcc-6.3.0_libgcc.patch => gcc-8.1.0_libgcc.patch} (92%) create mode 100644 util/crossgcc/patches/gcc-8.1.0_nds32_ite.patch delete mode 100644 util/crossgcc/sum/binutils-2.29.1.tar.xz.cksum create mode 100644 util/crossgcc/sum/binutils-2.30.tar.xz.cksum delete mode 100644 util/crossgcc/sum/gcc-6.3.0.tar.bz2.cksum create mode 100644 util/crossgcc/sum/gcc-8.1.0.tar.xz.cksum diff --git a/util/crossgcc/buildgcc b/util/crossgcc/buildgcc index ef0c4d5d8f..a9d90572cd 100755 --- a/util/crossgcc/buildgcc +++ b/util/crossgcc/buildgcc @@ -18,8 +18,8 @@ cd $(dirname $0) -CROSSGCC_DATE="June 3rd, 2018" -CROSSGCC_VERSION="1.51" +CROSSGCC_DATE="June 11th, 2018" +CROSSGCC_VERSION="1.52" CROSSGCC_COMMIT=$( git describe ) # default settings @@ -38,9 +38,9 @@ THREADS=1 GMP_VERSION=6.1.2 MPFR_VERSION=3.1.5 MPC_VERSION=1.0.3 -GCC_VERSION=6.3.0 +GCC_VERSION=8.1.0 GCC_AUTOCONF_VERSION=2.69 -BINUTILS_VERSION=2.29.1 +BINUTILS_VERSION=2.30 GDB_VERSION=8.0 IASL_VERSION=20180531 PYTHON_VERSION=3.5.1 @@ -57,7 +57,7 @@ CMAKE_VERSION=3.11.3 GMP_ARCHIVE="https://ftpmirror.gnu.org/gmp/gmp-${GMP_VERSION}.tar.xz" MPFR_ARCHIVE="https://ftpmirror.gnu.org/mpfr/mpfr-${MPFR_VERSION}.tar.xz" MPC_ARCHIVE="https://ftpmirror.gnu.org/mpc/mpc-${MPC_VERSION}.tar.gz" -GCC_ARCHIVE="https://ftpmirror.gnu.org/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.bz2" +GCC_ARCHIVE="https://ftpmirror.gnu.org/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.xz" BINUTILS_ARCHIVE="https://ftpmirror.gnu.org/binutils/binutils-${BINUTILS_VERSION}.tar.xz" GDB_ARCHIVE="https://ftpmirror.gnu.org/gdb/gdb-${GDB_VERSION}.tar.xz" IASL_ARCHIVE="https://acpica.org/sites/acpica/files/acpica-unix2-${IASL_VERSION}.tar.gz" diff --git a/util/crossgcc/patches/binutils-2.29.1_mips-gold.patch b/util/crossgcc/patches/binutils-2.30_mips-gold.patch similarity index 100% rename from util/crossgcc/patches/binutils-2.29.1_mips-gold.patch rename to util/crossgcc/patches/binutils-2.30_mips-gold.patch diff --git a/util/crossgcc/patches/binutils-2.30_nds32.patch b/util/crossgcc/patches/binutils-2.30_nds32.patch new file mode 100644 index 0000000000..9608265ad2 --- /dev/null +++ b/util/crossgcc/patches/binutils-2.30_nds32.patch @@ -0,0 +1,25740 @@ +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.29.1_no-bfd-doc.patch b/util/crossgcc/patches/binutils-2.30_no-bfd-doc.patch similarity index 100% rename from util/crossgcc/patches/binutils-2.29.1_no-bfd-doc.patch rename to util/crossgcc/patches/binutils-2.30_no-bfd-doc.patch diff --git a/util/crossgcc/patches/gcc-6.3.0_ada-raise.patch b/util/crossgcc/patches/gcc-6.3.0_ada-raise.patch deleted file mode 100644 index a081957615..0000000000 --- a/util/crossgcc/patches/gcc-6.3.0_ada-raise.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- gcc-6.3.0/gcc/ada/raise.c.orig 2017-06-24 07:06:41.524685169 +0200 -+++ gcc-6.3.0/gcc/ada/raise.c 2017-06-24 07:07:12.945162120 +0200 -@@ -55,7 +55,7 @@ - void - _gnat_builtin_longjmp (void *ptr, int flag ATTRIBUTE_UNUSED) - { -- __builtin_longjmp (ptr, 1); -+ __builtin_longjmp ((void **)ptr, 1); - } - #endif - diff --git a/util/crossgcc/patches/gcc-6.3.0_elf_biarch.patch b/util/crossgcc/patches/gcc-6.3.0_elf_biarch.patch deleted file mode 100644 index 226aed941f..0000000000 --- a/util/crossgcc/patches/gcc-6.3.0_elf_biarch.patch +++ /dev/null @@ -1,87 +0,0 @@ -diff -urN gcc-4.9.2/gcc/config/i386/t-elf64 gcc-4.9.2/gcc/config/i386/t-elf64 ---- gcc-4.9.2/gcc/config/i386/t-elf64 1969-12-31 16:00:00.000000000 -0800 -+++ gcc-6.1.0/gcc/config/i386/t-elf64 2015-06-17 11:20:08.032513005 -0700 -@@ -0,0 +1,38 @@ -+# Copyright (C) 2002-2014 Free Software Foundation, Inc. -+# -+# 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 -+# . -+ -+# On Debian, Ubuntu and other derivative distributions, the 32bit libraries -+# are found in /lib32 and /usr/lib32, /lib64 and /usr/lib64 are symlinks to -+# /lib and /usr/lib, while other distributions install libraries into /lib64 -+# and /usr/lib64. The LSB does not enforce the use of /lib64 and /usr/lib64, -+# it doesn't tell anything about the 32bit libraries on those systems. Set -+# MULTILIB_OSDIRNAMES according to what is found on the target. -+ -+# To support i386, x86-64 and x32 libraries, the directory structrue -+# should be: -+# -+# /lib has i386 libraries. -+# /lib64 has x86-64 libraries. -+# /libx32 has x32 libraries. -+# -+comma=, -+MULTILIB_OPTIONS = $(subst $(comma),/,$(TM_MULTILIB_CONFIG)) -+MULTILIB_DIRNAMES = $(patsubst m%, %, $(subst /, ,$(MULTILIB_OPTIONS))) -+MULTILIB_OSDIRNAMES = m64=../lib64$(call if_multiarch,:x86_64-elf) -+MULTILIB_OSDIRNAMES+= m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:i386-elf) -+MULTILIB_OSDIRNAMES+= mx32=../libx32$(call if_multiarch,:x86_64-elf-x32) -diff -urN gcc-4.9.2/gcc/config.gcc gcc-4.9.2/gcc/config.gcc ---- gcc-4.9.2/gcc/config.gcc 2015-06-17 11:20:57.841008182 -0700 -+++ gcc-6.1.0/gcc/config.gcc 2015-06-17 11:17:24.818890200 -0700 -@@ -1353,6 +1353,30 @@ - ;; - x86_64-*-elf*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h" -+ tmake_file="${tmake_file} i386/t-elf64" -+ x86_multilibs="${with_multilib_list}" -+ if test "$x86_multilibs" = "default"; then -+ case ${with_abi} in -+ x32 | mx32) -+ x86_multilibs="mx32" -+ ;; -+ *) -+ x86_multilibs="m64,m32" -+ ;; -+ esac -+ fi -+ x86_multilibs=`echo $x86_multilibs | sed -e 's/,/ /g'` -+ for x86_multilib in ${x86_multilibs}; do -+ case ${x86_multilib} in -+ m32 | m64 | mx32) -+ TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG},${x86_multilib}" -+ ;; -+ *) -+ echo "--with-multilib-list=${x86_with_multilib} not supported." -+ exit 1 -+ esac -+ done -+ TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's/^,//'` - ;; - i[34567]86-*-rdos*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/rdos.h" ---- gcc-6.1.0/gcc/config/i386/x86-64.h.orig 2015-08-20 17:17:34.555919593 +0200 -+++ gcc-6.1.0/gcc/config/i386/x86-64.h 2015-08-20 17:17:42.615908670 +0200 -@@ -49,7 +49,7 @@ - #define WCHAR_TYPE_SIZE 32 - - #undef ASM_SPEC --#define ASM_SPEC "%{m32:--32} %{m64:--64} %{mx32:--x32}" -+#define ASM_SPEC "%{m16|m32:--32} %{m64:--64} %{mx32:--x32}" - - #undef ASM_OUTPUT_ALIGNED_BSS - #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ diff --git a/util/crossgcc/patches/gcc-6.3.0_memmodel.patch b/util/crossgcc/patches/gcc-6.3.0_memmodel.patch deleted file mode 100644 index 62428c5857..0000000000 --- a/util/crossgcc/patches/gcc-6.3.0_memmodel.patch +++ /dev/null @@ -1,416 +0,0 @@ -commit ea36272bdc2602a690019b9612d23594571d3d2b -Author: thopre01 -Date: Mon Sep 26 17:20:39 2016 +0000 - - 2016-09-26 Thomas Preud'homme - - gcc/ - * tree.h (memmodel_from_int, memmodel_base, is_mm_relaxed, - is_mm_consume, is_mm_acquire, is_mm_release, is_mm_acq_rel, - is_mm_seq_cst, is_mm_sync): Move to ... - * memmodel.h: This. New file. - * builtins.c: Include memmodel.h. - * optabs.c: Likewise. - * tsan.c: Likewise. - * config/aarch64/aarch64.c: Likewise. - * config/alpha/alpha.c: Likewise. - * config/arm/arm.c: Likewise. - * config/i386/i386.c: Likewise. - * config/ia64/ia64.c: Likewise. - * config/mips/mips.c: Likewise. - * config/rs6000/rs6000.c: Likewise. - * config/sparc/sparc.c: Likewise. - * genconditions.c: Include memmodel.h in generated file. - * genemit.c: Likewise. - * genoutput.c: Likewise. - * genpeep.c: Likewise. - * genpreds.c: Likewise. - * genrecog.c: Likewise. - - gcc/c-family/ - * c-common.c: Include memmodel.h. - - git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@240504 138bc75d-0d04-0410-961f-82ee72b054a4 - -diff --git a/gcc/builtins.c b/gcc/builtins.c -index 93cbe15ad3c..04dcf95acd2 100644 ---- a/gcc/builtins.c -+++ b/gcc/builtins.c -@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see - #include "target.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "gimple.h" - #include "predict.h" - #include "tm_p.h" -diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c -index e9f619fd3af..2652259a312 100644 ---- a/gcc/c-family/c-common.c -+++ b/gcc/c-family/c-common.c -@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see - #include "target.h" - #include "function.h" - #include "tree.h" -+#include "memmodel.h" - #include "c-common.h" - #include "gimple-expr.h" - #include "tm_p.h" -diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c -index 6078b163548..c65b826b0cc 100644 ---- a/gcc/config/aarch64/aarch64.c -+++ b/gcc/config/aarch64/aarch64.c -@@ -26,6 +26,7 @@ - #include "target.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "gimple.h" - #include "cfghooks.h" - #include "cfgloop.h" -diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c -index 6d4af04dd7d..d646879e7e8 100644 ---- a/gcc/config/alpha/alpha.c -+++ b/gcc/config/alpha/alpha.c -@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see - #include "target.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "gimple.h" - #include "df.h" - #include "tm_p.h" -diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c -index 619c3291c87..feb54cbc64a 100644 ---- a/gcc/config/arm/arm.c -+++ b/gcc/config/arm/arm.c -@@ -27,6 +27,7 @@ - #include "target.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "cfghooks.h" - #include "df.h" - #include "tm_p.h" -diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c -index 143b905a341..01e2ad8e1b2 100644 ---- a/gcc/config/i386/i386.c -+++ b/gcc/config/i386/i386.c -@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see - #include "backend.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "gimple.h" - #include "cfghooks.h" - #include "cfgloop.h" -diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c -index 5f0bf43a103..573872eb85f 100644 ---- a/gcc/config/ia64/ia64.c -+++ b/gcc/config/ia64/ia64.c -@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see - #include "target.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "cfghooks.h" - #include "df.h" - #include "tm_p.h" -diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c -index 88f4038224a..3586a1001e7 100644 ---- a/gcc/config/mips/mips.c -+++ b/gcc/config/mips/mips.c -@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see - #include "target.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "gimple.h" - #include "cfghooks.h" - #include "df.h" -diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c -index d76f479d9e5..6897b5c260d 100644 ---- a/gcc/config/rs6000/rs6000.c -+++ b/gcc/config/rs6000/rs6000.c -@@ -24,6 +24,7 @@ - #include "backend.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "gimple.h" - #include "cfghooks.h" - #include "cfgloop.h" -diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c -index 5efed3dc52f..5936f96bd80 100644 ---- a/gcc/config/sparc/sparc.c -+++ b/gcc/config/sparc/sparc.c -@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see - #include "target.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "gimple.h" - #include "df.h" - #include "tm_p.h" -diff --git a/gcc/genconditions.c b/gcc/genconditions.c -index e4f45b097cd..d8b0ebba56b 100644 ---- a/gcc/genconditions.c -+++ b/gcc/genconditions.c -@@ -94,6 +94,7 @@ write_header (void) - #include \"resource.h\"\n\ - #include \"diagnostic-core.h\"\n\ - #include \"reload.h\"\n\ -+#include \"memmodel.h\"\n\ - #include \"tm-constrs.h\"\n"); - - if (saw_eh_return) -diff --git a/gcc/genemit.c b/gcc/genemit.c -index 33040aac36d..d5e07a97a6d 100644 ---- a/gcc/genemit.c -+++ b/gcc/genemit.c -@@ -792,6 +792,7 @@ from the machine description file `md'. */\n\n"); - printf ("#include \"reload.h\"\n"); - printf ("#include \"diagnostic-core.h\"\n"); - printf ("#include \"regs.h\"\n"); -+ printf ("#include \"memmodel.h\"\n"); - printf ("#include \"tm-constrs.h\"\n"); - printf ("#include \"ggc.h\"\n"); - printf ("#include \"dumpfile.h\"\n"); -diff --git a/gcc/genoutput.c b/gcc/genoutput.c -index f8c25ac4df0..59092580e49 100644 ---- a/gcc/genoutput.c -+++ b/gcc/genoutput.c -@@ -231,6 +231,7 @@ output_prologue (void) - printf ("#include \"diagnostic-core.h\"\n"); - printf ("#include \"output.h\"\n"); - printf ("#include \"target.h\"\n"); -+ printf ("#include \"memmodel.h\"\n"); - printf ("#include \"tm-constrs.h\"\n"); - } - -diff --git a/gcc/genpeep.c b/gcc/genpeep.c -index 132cdced690..e1997e03e47 100644 ---- a/gcc/genpeep.c -+++ b/gcc/genpeep.c -@@ -373,6 +373,7 @@ from the machine description file `md'. */\n\n"); - printf ("#include \"except.h\"\n"); - printf ("#include \"diagnostic-core.h\"\n"); - printf ("#include \"flags.h\"\n"); -+ printf ("#include \"memmodel.h\"\n"); - printf ("#include \"tm-constrs.h\"\n\n"); - - printf ("extern rtx peep_operand[];\n\n"); -diff --git a/gcc/genpreds.c b/gcc/genpreds.c -index d18ebd2ab5a..6db1b7b0301 100644 ---- a/gcc/genpreds.c -+++ b/gcc/genpreds.c -@@ -1580,6 +1580,7 @@ write_insn_preds_c (void) - #include \"reload.h\"\n\ - #include \"regs.h\"\n\ - #include \"emit-rtl.h\"\n\ -+#include \"memmodel.h\"\n\ - #include \"tm-constrs.h\"\n"); - - FOR_ALL_PREDICATES (p) -diff --git a/gcc/genrecog.c b/gcc/genrecog.c -index 056798c82f7..77861074492 100644 ---- a/gcc/genrecog.c -+++ b/gcc/genrecog.c -@@ -4192,6 +4192,7 @@ write_header (void) - #include \"diagnostic-core.h\"\n\ - #include \"reload.h\"\n\ - #include \"regs.h\"\n\ -+#include \"memmodel.h\"\n\ - #include \"tm-constrs.h\"\n\ - \n"); - -diff --git a/gcc/memmodel.h b/gcc/memmodel.h -new file mode 100644 -index 00000000000..d53eb7bc9d9 ---- /dev/null -+++ b/gcc/memmodel.h -@@ -0,0 +1,86 @@ -+/* Prototypes of memory model helper functions. -+ Copyright (C) 2015-2016 Free Software Foundation, Inc. -+ -+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 -+. */ -+ -+#ifndef GCC_MEMMODEL_H -+#define GCC_MEMMODEL_H -+ -+/* Return the memory model from a host integer. */ -+static inline enum memmodel -+memmodel_from_int (unsigned HOST_WIDE_INT val) -+{ -+ return (enum memmodel) (val & MEMMODEL_MASK); -+} -+ -+/* Return the base memory model from a host integer. */ -+static inline enum memmodel -+memmodel_base (unsigned HOST_WIDE_INT val) -+{ -+ return (enum memmodel) (val & MEMMODEL_BASE_MASK); -+} -+ -+/* Return TRUE if the memory model is RELAXED. */ -+static inline bool -+is_mm_relaxed (enum memmodel model) -+{ -+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_RELAXED; -+} -+ -+/* Return TRUE if the memory model is CONSUME. */ -+static inline bool -+is_mm_consume (enum memmodel model) -+{ -+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_CONSUME; -+} -+ -+/* Return TRUE if the memory model is ACQUIRE. */ -+static inline bool -+is_mm_acquire (enum memmodel model) -+{ -+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_ACQUIRE; -+} -+ -+/* Return TRUE if the memory model is RELEASE. */ -+static inline bool -+is_mm_release (enum memmodel model) -+{ -+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_RELEASE; -+} -+ -+/* Return TRUE if the memory model is ACQ_REL. */ -+static inline bool -+is_mm_acq_rel (enum memmodel model) -+{ -+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_ACQ_REL; -+} -+ -+/* Return TRUE if the memory model is SEQ_CST. */ -+static inline bool -+is_mm_seq_cst (enum memmodel model) -+{ -+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_SEQ_CST; -+} -+ -+/* Return TRUE if the memory model is a SYNC variant. */ -+static inline bool -+is_mm_sync (enum memmodel model) -+{ -+ return (model & MEMMODEL_SYNC); -+} -+ -+#endif /* GCC_MEMMODEL_H */ -diff --git a/gcc/optabs.c b/gcc/optabs.c -index e41747a630f..c5e9b4f8e13 100644 ---- a/gcc/optabs.c -+++ b/gcc/optabs.c -@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see - #include "target.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "predict.h" - #include "tm_p.h" - #include "expmed.h" -diff --git a/gcc/tree.h b/gcc/tree.h -index 0d9ad0198fa..563e6d9e287 100644 ---- a/gcc/tree.h -+++ b/gcc/tree.h -@@ -4675,69 +4675,6 @@ extern void warn_deprecated_use (tree, tree); - extern void cache_integer_cst (tree); - extern const char *combined_fn_name (combined_fn); - --/* Return the memory model from a host integer. */ --static inline enum memmodel --memmodel_from_int (unsigned HOST_WIDE_INT val) --{ -- return (enum memmodel) (val & MEMMODEL_MASK); --} -- --/* Return the base memory model from a host integer. */ --static inline enum memmodel --memmodel_base (unsigned HOST_WIDE_INT val) --{ -- return (enum memmodel) (val & MEMMODEL_BASE_MASK); --} -- --/* Return TRUE if the memory model is RELAXED. */ --static inline bool --is_mm_relaxed (enum memmodel model) --{ -- return (model & MEMMODEL_BASE_MASK) == MEMMODEL_RELAXED; --} -- --/* Return TRUE if the memory model is CONSUME. */ --static inline bool --is_mm_consume (enum memmodel model) --{ -- return (model & MEMMODEL_BASE_MASK) == MEMMODEL_CONSUME; --} -- --/* Return TRUE if the memory model is ACQUIRE. */ --static inline bool --is_mm_acquire (enum memmodel model) --{ -- return (model & MEMMODEL_BASE_MASK) == MEMMODEL_ACQUIRE; --} -- --/* Return TRUE if the memory model is RELEASE. */ --static inline bool --is_mm_release (enum memmodel model) --{ -- return (model & MEMMODEL_BASE_MASK) == MEMMODEL_RELEASE; --} -- --/* Return TRUE if the memory model is ACQ_REL. */ --static inline bool --is_mm_acq_rel (enum memmodel model) --{ -- return (model & MEMMODEL_BASE_MASK) == MEMMODEL_ACQ_REL; --} -- --/* Return TRUE if the memory model is SEQ_CST. */ --static inline bool --is_mm_seq_cst (enum memmodel model) --{ -- return (model & MEMMODEL_BASE_MASK) == MEMMODEL_SEQ_CST; --} -- --/* Return TRUE if the memory model is a SYNC variant. */ --static inline bool --is_mm_sync (enum memmodel model) --{ -- return (model & MEMMODEL_SYNC); --} -- - /* Compare and hash for any structure which begins with a canonical - pointer. Assumes all pointers are interchangeable, which is sort - of already assumed by gcc elsewhere IIRC. */ -diff --git a/gcc/tsan.c b/gcc/tsan.c -index 91dbd41a0b4..cc194749665 100644 ---- a/gcc/tsan.c -+++ b/gcc/tsan.c -@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see - #include "backend.h" - #include "rtl.h" - #include "tree.h" -+#include "memmodel.h" - #include "gimple.h" - #include "tree-pass.h" - #include "ssa.h" diff --git a/util/crossgcc/patches/gcc-6.3.0_nds32_ite.patch b/util/crossgcc/patches/gcc-6.3.0_nds32_ite.patch deleted file mode 100644 index 50e39691b6..0000000000 --- a/util/crossgcc/patches/gcc-6.3.0_nds32_ite.patch +++ /dev/null @@ -1,73397 +0,0 @@ -diff --git a/gcc/common.opt b/gcc/common.opt -index 67048db..e6f8fd3 100644 ---- a/gcc/common.opt -+++ b/gcc/common.opt -@@ -1281,7 +1281,7 @@ ffast-math - Common - - ffat-lto-objects --Common Var(flag_fat_lto_objects) -+Common Var(flag_fat_lto_objects) Init(1) - Output lto objects containing both the intermediate language and binary output. - - ffinite-math-only -diff --git a/gcc/common/config/nds32/nds32-common.c b/gcc/common/config/nds32/nds32-common.c -index fb75956..66ea95c 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,15 +84,69 @@ nds32_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED, - /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ - static const struct default_options nds32_option_optimization_table[] = - { -- /* Enable -fomit-frame-pointer by default at -O1 or higher. */ -- { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, -+#ifdef TARGET_DEFAULT_NO_MATH_ERRNO -+ /* Under some configuration, we would like to use -fno-math-errno by default -+ at all optimization levels for performance and code size consideration. -+ Please check gcc/config.gcc for more implementation details. */ -+ { OPT_LEVELS_ALL, OPT_fmath_errno, NULL, 0 }, -+#endif -+#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 }, -+ /* Enable -mabi-compatible by default at all optimization levels. */ -+ { OPT_LEVELS_ALL, OPT_mabi_compatible, 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 }, -- -- { OPT_LEVELS_NONE, 0, NULL, 0 } -+ { OPT_LEVELS_SIZE, OPT_mv3push, NULL, 1 }, -+ /* Enable -mload-store-opt by default at -Os. */ -+ { OPT_LEVELS_SIZE, OPT_mload_store_opt, NULL, 1 }, -+ /* Enable -mregrename by default at -O1 and above. */ -+ { OPT_LEVELS_1_PLUS, OPT_mregrename, NULL, 1 }, -+ /* Enable -mgcse by default at -O1 and above. */ -+ { OPT_LEVELS_1_PLUS, OPT_mgcse, NULL, 1 }, -+ /* Enable -msign-conversion by default at -O1 and above. */ -+ { OPT_LEVELS_1_PLUS, OPT_msign_conversion, NULL, 1 }, -+ /* Enable -mscalbn-transform by default at -O1 and above. */ -+ { OPT_LEVELS_1_PLUS, OPT_mscalbn_transform, NULL, 1 }, -+ /* Enable -mconst_remeterialization by default at -O1 and above. */ -+ { OPT_LEVELS_1_PLUS, OPT_mconst_remater, NULL, 1 }, -+ /* Enable -mcprop-acc by default at -O1 and above. */ -+ { OPT_LEVELS_1_PLUS, OPT_mcprop_acc, NULL, 1 }, -+#ifdef TARGET_OS_DEFAULT_IFC -+ /* Enable -mifc by default at -Os, but it is useless under V2/V3M ISA. */ -+ { OPT_LEVELS_SIZE, OPT_mifc, NULL, 1 }, -+#endif -+#ifdef TARGET_OS_DEFAULT_EX9 -+ /* Enable -mex9 by default at -Os, but it is useless under V2/V3M ISA. */ -+ { OPT_LEVELS_SIZE, OPT_mex9, NULL, 1 }, -+#endif -+ -+ { OPT_LEVELS_NONE, 0, NULL, 0 } - }; - - /* ------------------------------------------------------------------------ */ -+ -+/* 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. */ - -@@ -95,14 +159,22 @@ static const struct default_options nds32_option_optimization_table[] = - - Other MASK_XXX flags are set individually. - By default we enable -- TARGET_16_BIT : Generate 16/32 bit mixed length instruction. -- TARGET_PERF_EXT : Generate performance extention instrcution. -- TARGET_CMOV : Generate conditional move instruction. */ -+ TARGET_16_BIT : Generate 16/32 bit mixed length instruction. -+ 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 \ - (TARGET_CPU_DEFAULT \ -+ | TARGET_DEFAULT_FPU_ISA \ -+ | TARGET_DEFAULT_FPU_FMA \ - | MASK_16_BIT \ -- | MASK_PERF_EXT \ -+ | MASK_EXT_PERF \ -+ | MASK_EXT_PERF2 \ -+ | MASK_EXT_STRING \ -+ | MASK_HW_ABS \ - | MASK_CMOV) - - #undef TARGET_HANDLE_OPTION -@@ -115,7 +187,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 1d5b23f..367a821 100644 ---- a/gcc/config.gcc -+++ b/gcc/config.gcc -@@ -433,8 +433,28 @@ mips*-*-*) - ;; - nds32*) - cpu_type=nds32 -- extra_headers="nds32_intrinsic.h" -- 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" -+ 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_options="${extra_options} g.opt" -+ extra_objs="nds32-cost.o nds32-intrinsic.o nds32-md-auxiliary.o \ -+ nds32-pipelines-auxiliary.o nds32-predicates.o \ -+ nds32-memory-manipulation.o nds32-fp-as-gp.o \ -+ nds32-load-store-opt.o nds32-soft-fp-comm.o nds32-isr.o \ -+ nds32-regrename.o nds32-gcse.o nds32-relax-opt.o \ -+ nds32-sign-conversion.o \ -+ nds32-scalbn-transform.o nds32-lmwsmw.o \ -+ nds32-reg-utils.o nds32-const-remater.o \ -+ nds32-utils.o nds32-abi-compatible.o \ -+ nds32-cprop-acc.o" - ;; - nios2-*-*) - cpu_type=nios2 -@@ -2265,17 +2285,67 @@ 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}" -- 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}" -- 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 -+ nds32_multilibs="${with_multilib_list}" -+ if test "$nds32_multilibs" = "default"; then -+ nds32_multilibs="" -+ fi -+ nds32_multilibs=`echo $nds32_multilibs | sed -e 's/,/ /g'` -+ for nds32_multilib in ${nds32_multilibs}; do -+ case ${nds32_multilib} in -+ dsp | zol | v3m+ | graywolf ) -+ TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG} ${nds32_multilib}" -+ ;; -+ *) -+ echo "--with-multilib-list=${nds32_multilib} not supported." -+ exit 1 -+ esac -+ done -+ -+ # Handle --enable-default-relax setting. -+ if test x${enable_default_relax} = xyes; then -+ tm_defines="${tm_defines} TARGET_DEFAULT_RELAX=1" -+ fi -+ # Handle --enable-Os-default-ifc setting. -+ if test x${enable_Os_default_ifc} = xyes; then -+ tm_defines="${tm_defines} TARGET_OS_DEFAULT_IFC=1" -+ fi -+ # Handle --enable-Os-default-ex9 setting. -+ if test x${enable_Os_default_ex9} = xyes; then -+ tm_defines="${tm_defines} TARGET_OS_DEFAULT_EX9=1" -+ fi -+ # Handle --with-ext-dsp -+ if test x${with_ext_dsp} = xyes; then -+ tm_defines="${tm_defines} TARGET_DEFAULT_EXT_DSP=1" -+ fi -+ if test x${with_ext_zol} = xyes; then -+ tm_defines="${tm_defines} TARGET_DEFAULT_HWLOOP=1" -+ fi -+ # Handle --with-16bit-ext, and default is on -+ if test x${with_ext_16bit} != xno; then -+ tm_defines="${tm_defines} TARGET_DEFAULT_16BIT=1" -+ fi -+ - ;; - nios2-*-*) - tm_file="elfos.h ${tm_file}" -@@ -4097,15 +4167,51 @@ case "${target}" in - ;; - - nds32*-*-*) -- supported_defaults="arch nds32_lib" -+ supported_defaults="arch cpu nds32_lib float fpu_config memory_model" - - # process --with-arch - case "${with_arch}" in -- "" | v2 | v3 | v3m) -+ "" | v3 | v3j) -+ # OK -+ tm_defines="${tm_defines} TARGET_ARCH_DEFAULT=0" -+ tm_defines="${tm_defines} TARGET_DEFAULT_ISR_VECTOR_SIZE=4" -+ ;; -+ v2 | v2j | v3m) -+ # OK -+ tm_defines="${tm_defines} TARGET_ARCH_DEFAULT=0" -+ tm_defines="${tm_defines} TARGET_DEFAULT_ISR_VECTOR_SIZE=16" -+ ;; -+ v3f) -+ tm_defines="${tm_defines} TARGET_ARCH_DEFAULT=1" -+ tm_defines="${tm_defines} TARGET_DEFAULT_ISR_VECTOR_SIZE=4" -+ ;; -+ v3s) -+ tm_defines="${tm_defines} TARGET_ARCH_DEFAULT=2" -+ tm_defines="${tm_defines} TARGET_DEFAULT_ISR_VECTOR_SIZE=4" -+ ;; -+ *) -+ echo "Cannot accept --with-arch=$with_arch, available values are: v2 v2j v3 v3j v3m v3f v3s" 1>&2 -+ exit 1 -+ ;; -+ esac -+ -+ # process --with-memory-model -+ case "${with_memory_model}" in -+ "" | fast | slow) -+ ;; -+ *) -+ echo "Cannot accept --with-memory-model=$with_memory_model, available values are: fast slow" 1>&2 -+ exit 1 -+ ;; -+ esac -+ -+ # process --with-cpu -+ case "${with_cpu}" in -+ "" | n7 | n8 | e8 | s8 | n9 | n10 | d10 | graywolf | n12 | n13 | panther) - # OK - ;; - *) -- echo "Cannot accept --with-arch=$with_arch, available values are: v2 v3 v3m" 1>&2 -+ echo "Cannot accept --with-cpu=$with_cpu, available values are: n7 n8 e8 s8 n9 n10 d10 graywolf n12 n13 panther" 1>&2 - exit 1 - ;; - esac -@@ -4115,31 +4221,56 @@ 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} TARGET_DEFAULT_TLSDESC_TRAMPOLINE=1" -+ ;; -+ uclibc) - ;; - *) -- echo "Cannot accept --with-nds32-lib=$with_nds32_lib, available values are: newlib mculib" 1>&2 -+ echo "Cannot accept --with-nds32-lib=$with_nds32_lib, available values are: newlib mculib glibc uclibc" 1>&2 -+ exit 1 -+ ;; -+ esac -+ -+ # process --with-float -+ case "${with_float}" in -+ "" | soft | hard) -+ # OK -+ ;; -+ *) -+ echo "Cannot accept --with-float=$with_float, available values are: soft hard" 1>&2 -+ exit 1 -+ ;; -+ esac -+ -+ # process --with-config-fpu -+ case "${with_config_fpu}" in -+ "" | 0 | 1 | 2 | 3) -+ # OK -+ ;; -+ *) -+ echo "Cannot accept --with-config-fpu=$with_config_fpu, available values from 0 to 7" 1>&2 - exit 1 - ;; - esac -- ;; - -- nios2*-*-*) -- supported_defaults="arch" -- case "$with_arch" in -- "" | r1 | r2) -- # OK -- ;; -- *) -- echo "Unknown arch used in --with-arch=$with_arch" 1>&2 -- exit 1 -- ;; -- esac - ;; - - powerpc*-*-* | rs6000-*-*) -@@ -4527,7 +4658,7 @@ case ${target} in - esac - - t= --all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan fp_32 odd_spreg_32 divide llsc mips-plt synci tls" -+all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan fp_32 odd_spreg_32 divide llsc mips-plt synci tls memory_model" - for option in $all_defaults - do - eval "val=\$with_"`echo $option | sed s/-/_/g` -diff --git a/gcc/config/nds32/constants.md b/gcc/config/nds32/constants.md -index bea42ee..6c92412 100644 ---- a/gcc/config/nds32/constants.md -+++ b/gcc/config/nds32/constants.md -@@ -23,25 +23,176 @@ - (define_constants - [(R8_REGNUM 8) - (TA_REGNUM 15) -+ (TP_REGNUM 25) - (FP_REGNUM 28) - (GP_REGNUM 29) - (LP_REGNUM 30) - (SP_REGNUM 31) -+ (LB_REGNUM 98) -+ (LE_REGNUM 99) -+ (LC_REGNUM 100) - ]) - - -+;; The unpec operation index. -+(define_c_enum "unspec_element" [ -+ UNSPEC_COPYSIGN -+ UNSPEC_FCPYNSD -+ UNSPEC_FCPYNSS -+ UNSPEC_FCPYSD -+ UNSPEC_FCPYSS -+ UNSPEC_CLIP -+ UNSPEC_CLIPS -+ UNSPEC_CLO -+ UNSPEC_PBSAD -+ UNSPEC_PBSADA -+ UNSPEC_BSE -+ UNSPEC_BSE_2 -+ UNSPEC_BSP -+ UNSPEC_BSP_2 -+ 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 -+ UNSPEC_LWUP -+ UNSPEC_LBUP -+ UNSPEC_SWUP -+ UNSPEC_SBUP -+ UNSPEC_LMWZB -+ UNSPEC_SMWZB -+ UNSPEC_UALOAD_HW -+ UNSPEC_UALOAD_W -+ UNSPEC_UALOAD_DW -+ 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 -+]) -+ -+ - ;; The unspec_volatile operation index. - (define_c_enum "unspec_volatile_element" [ -- UNSPEC_VOLATILE_FUNC_RETURN -+ UNSPEC_VOLATILE_EH_RETURN - UNSPEC_VOLATILE_ISYNC - UNSPEC_VOLATILE_ISB -+ UNSPEC_VOLATILE_DSB -+ UNSPEC_VOLATILE_MSYNC -+ UNSPEC_VOLATILE_MSYNC_ALL -+ UNSPEC_VOLATILE_MSYNC_STORE - UNSPEC_VOLATILE_MFSR - UNSPEC_VOLATILE_MFUSR - UNSPEC_VOLATILE_MTSR - UNSPEC_VOLATILE_MTUSR - UNSPEC_VOLATILE_SETGIE_EN - UNSPEC_VOLATILE_SETGIE_DIS -+ UNSPEC_VOLATILE_FMFCSR -+ UNSPEC_VOLATILE_FMTCSR -+ UNSPEC_VOLATILE_FMFCFG -+ UNSPEC_VOLATILE_JR_ITOFF -+ UNSPEC_VOLATILE_JR_TOFF -+ UNSPEC_VOLATILE_JRAL_ITON -+ UNSPEC_VOLATILE_JRAL_TON -+ UNSPEC_VOLATILE_RET_ITOFF -+ UNSPEC_VOLATILE_RET_TOFF -+ UNSPEC_VOLATILE_STANDBY_NO_WAKE_GRANT -+ UNSPEC_VOLATILE_STANDBY_WAKE_GRANT -+ UNSPEC_VOLATILE_STANDBY_WAKE_DONE -+ UNSPEC_VOLATILE_TEQZ -+ UNSPEC_VOLATILE_TNEZ -+ UNSPEC_VOLATILE_TRAP -+ UNSPEC_VOLATILE_SETEND_BIG -+ UNSPEC_VOLATILE_SETEND_LITTLE -+ UNSPEC_VOLATILE_BREAK -+ UNSPEC_VOLATILE_SYSCALL -+ UNSPEC_VOLATILE_NOP -+ UNSPEC_VOLATILE_RES_DEP -+ UNSPEC_VOLATILE_DATA_DEP -+ UNSPEC_VOLATILE_LLW -+ UNSPEC_VOLATILE_SCW -+ UNSPEC_VOLATILE_CCTL_L1D_INVALALL -+ UNSPEC_VOLATILE_CCTL_L1D_WBALL_ALVL -+ UNSPEC_VOLATILE_CCTL_L1D_WBALL_ONE_LVL -+ UNSPEC_VOLATILE_CCTL_IDX_WRITE -+ UNSPEC_VOLATILE_CCTL_IDX_READ -+ UNSPEC_VOLATILE_CCTL_VA_WBINVAL_L1 -+ UNSPEC_VOLATILE_CCTL_VA_WBINVAL_LA -+ UNSPEC_VOLATILE_CCTL_IDX_WBINVAL -+ UNSPEC_VOLATILE_CCTL_VA_LCK -+ UNSPEC_VOLATILE_DPREF_QW -+ UNSPEC_VOLATILE_DPREF_HW -+ UNSPEC_VOLATILE_DPREF_W -+ UNSPEC_VOLATILE_DPREF_DW -+ UNSPEC_VOLATILE_TLBOP_TRD -+ UNSPEC_VOLATILE_TLBOP_TWR -+ UNSPEC_VOLATILE_TLBOP_RWR -+ UNSPEC_VOLATILE_TLBOP_RWLK -+ UNSPEC_VOLATILE_TLBOP_UNLK -+ UNSPEC_VOLATILE_TLBOP_PB -+ UNSPEC_VOLATILE_TLBOP_INV -+ UNSPEC_VOLATILE_TLBOP_FLUA -+ UNSPEC_VOLATILE_ENABLE_INT -+ UNSPEC_VOLATILE_DISABLE_INT -+ UNSPEC_VOLATILE_SET_PENDING_SWINT -+ UNSPEC_VOLATILE_CLR_PENDING_SWINT -+ UNSPEC_VOLATILE_CLR_PENDING_HWINT -+ UNSPEC_VOLATILE_GET_ALL_PENDING_INT -+ UNSPEC_VOLATILE_GET_PENDING_INT -+ UNSPEC_VOLATILE_SET_INT_PRIORITY -+ UNSPEC_VOLATILE_GET_INT_PRIORITY -+ UNSPEC_VOLATILE_SET_TRIG_LEVEL -+ UNSPEC_VOLATILE_SET_TRIG_EDGE -+ UNSPEC_VOLATILE_GET_TRIG_TYPE -+ UNSPEC_VOLATILE_RELAX_GROUP -+ UNSPEC_VOLATILE_INNERMOST_LOOP_BEGIN -+ UNSPEC_VOLATILE_INNERMOST_LOOP_END -+ UNSPEC_VOLATILE_OMIT_FP_BEGIN -+ UNSPEC_VOLATILE_OMIT_FP_END - UNSPEC_VOLATILE_POP25_RETURN -+ UNSPEC_VOLATILE_SIGNATURE_BEGIN -+ UNSPEC_VOLATILE_SIGNATURE_END -+ UNSPEC_VOLATILE_NO_HWLOOP -+ UNSPEC_VOLATILE_NO_IFC_BEGIN -+ UNSPEC_VOLATILE_NO_IFC_END -+ UNSPEC_VOLATILE_NO_EX9_BEGIN -+ UNSPEC_VOLATILE_NO_EX9_END -+ UNSPEC_VOLATILE_UNALIGNED_FEATURE -+ UNSPEC_VOLATILE_ENABLE_UNALIGNED -+ UNSPEC_VOLATILE_DISABLE_UNALIGNED -+ UNSPEC_VOLATILE_RDOV -+ UNSPEC_VOLATILE_CLROV -+ UNSPEC_VOLATILE_HWLOOP_LAST_INSN - ]) - - ;; ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/constraints.md b/gcc/config/nds32/constraints.md -index 1f44a1a..8163f46 100644 ---- a/gcc/config/nds32/constraints.md -+++ b/gcc/config/nds32/constraints.md -@@ -25,9 +25,6 @@ - ;; Machine-dependent floating: G H - - --(define_register_constraint "w" "(TARGET_ISA_V3 || TARGET_ISA_V3M) ? LOW_REGS : NO_REGS" -- "LOW register class $r0 ~ $r7 constraint for V3/V3M ISA") -- - (define_register_constraint "l" "LOW_REGS" - "LOW register class $r0 ~ $r7") - -@@ -41,9 +38,59 @@ - (define_register_constraint "t" "R15_TA_REG" - "Temporary Assist register $ta (i.e. $r15)") - -+(define_register_constraint "e" "R8_REG" -+ "Function Entry register $r8)") -+ - (define_register_constraint "k" "STACK_REG" - "Stack register $sp") - -+(define_register_constraint "v" "R5_REG" -+ "Register $r5") -+ -+(define_register_constraint "x" "FRAME_POINTER_REG" -+ "Frame pointer register $fp") -+ -+(define_register_constraint "f" -+ "(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) ? FP_REGS : NO_REGS" -+ "The Floating point registers $fs0 ~ $fs31") -+ -+(define_register_constraint "A" "LOOP_REGS" -+ "Loop register class") -+ -+(define_constraint "Iv00" -+ "Constant value 0" -+ (and (match_code "const_int") -+ (match_test "ival == 0"))) -+ -+(define_constraint "Iv01" -+ "Constant value 1" -+ (and (match_code "const_int") -+ (match_test "ival == 1"))) -+ -+(define_constraint "Iv02" -+ "Constant value 2" -+ (and (match_code "const_int") -+ (match_test "ival == 2"))) -+ -+(define_constraint "Iv04" -+ "Constant value 4" -+ (and (match_code "const_int") -+ (match_test "ival == 4"))) -+ -+(define_constraint "Iv08" -+ "Constant value 8" -+ (and (match_code "const_int") -+ (match_test "ival == 8"))) -+ -+(define_constraint "Iu01" -+ "Unsigned immediate 1-bit value" -+ (and (match_code "const_int") -+ (match_test "ival == 1 || ival == 0"))) -+ -+(define_constraint "Iu02" -+ "Unsigned immediate 2-bit value" -+ (and (match_code "const_int") -+ (match_test "ival < (1 << 2) && ival >= 0"))) - - (define_constraint "Iu03" - "Unsigned immediate 3-bit value" -@@ -65,6 +112,11 @@ - (and (match_code "const_int") - (match_test "ival < (1 << 4) && ival >= -(1 << 4)"))) - -+(define_constraint "Cs05" -+ "Signed immediate 5-bit value" -+ (and (match_code "const_double") -+ (match_test "nds32_const_double_range_ok_p (op, SFmode, -(1 << 4), (1 << 4))"))) -+ - (define_constraint "Iu05" - "Unsigned immediate 5-bit value" - (and (match_code "const_int") -@@ -75,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" -@@ -84,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)"))) -@@ -103,6 +160,11 @@ - (match_test "ival < (1 << 9) && ival >= 0"))) - - -+(define_constraint "Is08" -+ "Signed immediate 8-bit value" -+ (and (match_code "const_int") -+ (match_test "ival < (1 << 7) && ival >= -(1 << 7)"))) -+ - (define_constraint "Is10" - "Signed immediate 10-bit value" - (and (match_code "const_int") -@@ -113,6 +175,10 @@ - (and (match_code "const_int") - (match_test "ival < (1 << 10) && ival >= -(1 << 10)"))) - -+(define_constraint "Is14" -+ "Signed immediate 14-bit value" -+ (and (match_code "const_int") -+ (match_test "ival < (1 << 13) && ival >= -(1 << 13)"))) - - (define_constraint "Is15" - "Signed immediate 15-bit value" -@@ -194,12 +260,21 @@ - (and (match_code "const_int") - (match_test "ival < (1 << 19) && ival >= -(1 << 19)"))) - -+(define_constraint "Cs20" -+ "Signed immediate 20-bit value" -+ (and (match_code "const_double") -+ (match_test "nds32_const_double_range_ok_p (op, SFmode, -(1 << 19), (1 << 19))"))) - - (define_constraint "Ihig" - "The immediate value that can be simply set high 20-bit" - (and (match_code "const_int") - (match_test "(ival != 0) && ((ival & 0xfff) == 0)"))) - -+(define_constraint "Chig" -+ "The immediate value that can be simply set high 20-bit" -+ (and (match_code "high") -+ (match_test "GET_CODE (XEXP (op, 0)) == CONST_DOUBLE"))) -+ - (define_constraint "Izeb" - "The immediate value 0xff" - (and (match_code "const_int") -@@ -213,12 +288,12 @@ - (define_constraint "Ixls" - "The immediate value 0x01" - (and (match_code "const_int") -- (match_test "TARGET_PERF_EXT && (ival == 0x1)"))) -+ (match_test "TARGET_EXT_PERF && (ival == 0x1)"))) - - (define_constraint "Ix11" - "The immediate value 0x7ff" - (and (match_code "const_int") -- (match_test "TARGET_PERF_EXT && (ival == 0x7ff)"))) -+ (match_test "TARGET_EXT_PERF && (ival == 0x7ff)"))) - - (define_constraint "Ibms" - "The immediate value with power of 2" -@@ -232,23 +307,70 @@ - (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" - (and (match_code "mem") -- (match_test "nds32_mem_format (op) == ADDRESS_LO_REG_IMM3U"))) -+ (match_test "nds32_mem_format (op) == ADDRESS_POST_INC_LO_REG_IMM3U -+ || nds32_mem_format (op) == ADDRESS_POST_MODIFY_LO_REG_IMM3U -+ || nds32_mem_format (op) == ADDRESS_LO_REG_IMM3U"))) - - (define_memory_constraint "U45" - "Memory constraint for 45 format" - (and (match_code "mem") - (match_test "(nds32_mem_format (op) == ADDRESS_REG) -- && (GET_MODE (op) == SImode)"))) -+ && ((GET_MODE (op) == SImode) -+ || (GET_MODE (op) == SFmode))"))) -+ -+(define_memory_constraint "Ufe" -+ "Memory constraint for fe format" -+ (and (match_code "mem") -+ (match_test "nds32_mem_format (op) == ADDRESS_R8_IMM7U -+ && (GET_MODE (op) == SImode -+ || GET_MODE (op) == SFmode)"))) - - (define_memory_constraint "U37" - "Memory constraint for 37 format" - (and (match_code "mem") - (match_test "(nds32_mem_format (op) == ADDRESS_SP_IMM7U - || nds32_mem_format (op) == ADDRESS_FP_IMM7U) -- && (GET_MODE (op) == SImode)"))) -+ && (GET_MODE (op) == SImode -+ || GET_MODE (op) == SFmode)"))) -+ -+(define_memory_constraint "Umw" -+ "Memory constraint for lwm/smw" -+ (and (match_code "mem") -+ (match_test "nds32_valid_smw_lwm_base_p (op)"))) -+ -+(define_memory_constraint "Da" -+ "Memory constraint for non-offset loads/stores" -+ (and (match_code "mem") -+ (match_test "REG_P (XEXP (op, 0)) -+ || (GET_CODE (XEXP (op, 0)) == POST_INC)"))) -+ -+(define_memory_constraint "Q" -+ "Memory constraint for no symbol_ref and const" -+ (and (match_code "mem") -+ (match_test "(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) -+ && nds32_float_mem_operand_p (op)"))) - - ;; ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/elf.h b/gcc/config/nds32/elf.h -new file mode 100644 -index 0000000..315dcd8 ---- /dev/null -+++ b/gcc/config/nds32/elf.h -@@ -0,0 +1,83 @@ -+/* Definitions of target machine of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 \ -+ NDS32_IFC_SPEC \ -+ NDS32_EX9_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 ab0f103..6023b9c 100644 ---- a/gcc/config/nds32/iterators.md -+++ b/gcc/config/nds32/iterators.md -@@ -26,30 +26,99 @@ - ;; A list of integer modes that are up to one word long. - (define_mode_iterator QIHISI [QI HI SI]) - -+;; A list of integer modes for one word and double word. -+(define_mode_iterator SIDI [SI DI]) -+ - ;; A list of integer modes that are up to one half-word long. - (define_mode_iterator QIHI [QI HI]) - - ;; A list of the modes that are up to double-word long. - (define_mode_iterator DIDF [DI DF]) - -+;; A list of the modes that are up to one word long vector. -+(define_mode_iterator VQIHI [V4QI V2HI]) -+ -+;; A list of the modes that are up to one word long vector and scalar. -+(define_mode_iterator VSQIHI [V4QI V2HI QI HI]) -+ -+(define_mode_iterator VSQIHIDI [V4QI V2HI QI HI DI]) -+ -+(define_mode_iterator VQIHIDI [V4QI V2HI DI]) -+ -+;; A list of the modes that are up to one word long vector -+;; and scalar for HImode. -+(define_mode_iterator VSHI [V2HI HI]) -+ -+;; A list of the modes that are up to double-word long. -+(define_mode_iterator ANYF [(SF "TARGET_FPU_SINGLE") -+ (DF "TARGET_FPU_DOUBLE")]) - - ;;---------------------------------------------------------------------------- - ;; Mode attributes. - ;;---------------------------------------------------------------------------- - --(define_mode_attr size [(QI "b") (HI "h") (SI "w")]) -+(define_mode_attr size [(QI "b") (HI "h") (SI "w") (SF "s") (DF "d")]) - --(define_mode_attr byte [(QI "1") (HI "2") (SI "4")]) -+(define_mode_attr byte [(QI "1") (HI "2") (SI "4") (V4QI "4") (V2HI "4")]) - -+(define_mode_attr bits [(V4QI "8") (QI "8") (V2HI "16") (HI "16") (DI "64")]) -+ -+(define_mode_attr VELT [(V4QI "QI") (V2HI "HI")]) - - ;;---------------------------------------------------------------------------- - ;; Code iterators. - ;;---------------------------------------------------------------------------- - -+;; 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. - ;;---------------------------------------------------------------------------- - -+;; shifts -+(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 0000000..36ddf2f ---- /dev/null -+++ b/gcc/config/nds32/linux.h -@@ -0,0 +1,78 @@ -+/* Definitions of target machine of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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" -+ -+#ifdef TARGET_DEFAULT_TLSDESC_TRAMPOLINE -+ #define NDS32_TLSDESC_TRAMPOLINE_SPEC \ -+ " %{!mno-tlsdesc-trampoline:--mtlsdesc-trampoline}" -+#else -+ #define NDS32_TLSDESC_TRAMPOLINE_SPEC "" -+#endif -+ -+#define TARGET_OS_CPP_BUILTINS() \ -+ do \ -+ { \ -+ GNU_USER_TARGET_OS_CPP_BUILTINS(); \ -+ } \ -+ while (0) -+ -+#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1" -+ -+/* In the configure stage we may use options --enable-default-relax, -+ --enable-Os-default-ifc and --enable-Os-default-ex9. They effect -+ the default spec of passing --relax, --mifc, and --mex9 to linker. -+ We use NDS32_RELAX_SPEC, NDS32_IFC_SPEC, and NDS32_EX9_SPEC -+ so that we can customize them conveniently. */ -+#define LINK_SPEC \ -+ " %{G*}" \ -+ " %{mbig-endian:-EB} %{mlittle-endian:-EL}" \ -+ " %{shared:-shared} \ -+ %{!shared: \ -+ %{!static: \ -+ %{rdynamic:-export-dynamic} \ -+ -dynamic-linker " GNU_USER_DYNAMIC_LINKER "} \ -+ %{static:-static}}" \ -+ NDS32_RELAX_SPEC \ -+ NDS32_IFC_SPEC \ -+ NDS32_EX9_SPEC \ -+ NDS32_TLSDESC_TRAMPOLINE_SPEC -+ -+#define LINK_PIE_SPEC "%{pie:%{!fno-pie:%{!fno-PIE:%{!static:-pie}}}} " -+ -+ -+/* 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-abi-compatible.c b/gcc/config/nds32/nds32-abi-compatible.c -new file mode 100644 -index 0000000..f2ed006 ---- /dev/null -+++ b/gcc/config/nds32/nds32-abi-compatible.c -@@ -0,0 +1,315 @@ -+/* A Gimple-level pass of Andes NDS32 cpu for GNU compiler. -+ This pass collects the usage of float-point. -+ -+ Copyright (C) 2012-2016 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 -+. */ -+ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "hash-set.h" -+#include "machmode.h" -+#include "vec.h" -+#include "double-int.h" -+#include "input.h" -+#include "alias.h" -+#include "symtab.h" -+#include "wide-int.h" -+#include "inchash.h" -+#include "tree.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "rtl.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload (). */ -+#include "flags.h" -+#include "input.h" -+#include "function.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "dominance.h" -+#include "cfg.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "predict.h" -+#include "basic-block.h" -+#include "bitmap.h" -+#include "df.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function (). */ -+#include "ggc.h" -+#include "tree-pass.h" -+#include "tree-ssa-alias.h" -+#include "fold-const.h" -+#include "gimple-expr.h" -+#include "is-a.h" -+#include "gimple.h" -+#include "gimplify.h" -+#include "gimple-iterator.h" -+#include "gimplify-me.h" -+#include "gimple-ssa.h" -+#include "ipa-ref.h" -+#include "lto-streamer.h" -+#include "cgraph.h" -+#include "tree-cfg.h" -+#include "tree-phinodes.h" -+#include "stringpool.h" -+#include "tree-ssanames.h" -+#include "tree-pass.h" -+#include "gimple-pretty-print.h" -+#include "gimple-walk.h" -+ -+/* Indicate the translation unit whether including floating-point arithmetic -+ or not. */ -+bool nds32_include_fp_arith = false; -+ -+/* Return true if the return type and argument types of current function -+ pass the insepction. Furthermore, the global value NDS32_INCLUDE_FP_ARITH -+ is modified. */ -+ -+static bool -+nds32_acd_func_rtn_args_check (tree fn_decl) -+{ -+ tree fn_type = TREE_TYPE (fn_decl); -+ function_args_iterator iter; -+ tree arg_type = NULL_TREE; -+ tree rtn_type = NULL_TREE; -+ unsigned argno = 1; -+ -+ gcc_assert (fn_type); -+ -+ rtn_type = TREE_TYPE (fn_type); -+ if (dump_file) -+ { -+ fprintf (dump_file, -+ " Check the return & arguments for function %s\n" -+ " Prototype:", -+ fndecl_name (fn_decl)); -+ print_generic_decl (dump_file, fn_decl, 0); -+ fprintf (dump_file, "\n"); -+ } -+ -+ /* Check the return type. */ -+ if (FLOAT_TYPE_P (rtn_type) -+ || RECORD_OR_UNION_TYPE_P (rtn_type)) -+ { -+ if (dump_file) -+ fprintf (dump_file, " ! Return type is FP or record/union type\n"); -+ nds32_include_fp_arith = true; -+ -+ return false; -+ } -+ -+ /* Check if the function has a variable argument list. */ -+ if (stdarg_p (fn_type)) -+ { -+ if (dump_file) -+ fprintf (dump_file, " ! Has variable argument list (i.e. ,...)\n"); -+ nds32_include_fp_arith = true; -+ -+ return false; -+ } -+ -+ /* Check the arguments. */ -+ FOREACH_FUNCTION_ARGS (fn_type, arg_type, iter) -+ { -+ if (arg_type == void_type_node) -+ break; -+ -+ if (FLOAT_TYPE_P (arg_type) -+ || RECORD_OR_UNION_TYPE_P (arg_type)) -+ { -+ if (dump_file) -+ fprintf (dump_file, -+ " ! No.%d argument is FP or record/union type\n", -+ argno); -+ nds32_include_fp_arith = true; -+ -+ return false; -+ } -+ argno++; -+ } -+ -+ if (dump_file) -+ fprintf (dump_file, -+ " >> Pass the inspection of return & arguments type\n"); -+ -+ return true; -+} -+ -+/* Helper for nds32_abi_compatible. Return *TP if it is a floating-point -+ -related operand. */ -+ -+static tree -+nds32_acd_walk_op_fn (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) -+{ -+ tree t = *tp; -+ -+ if (t && TREE_TYPE (t) -+ && (FLOAT_TYPE_P (TREE_TYPE (t)) -+ || TREE_CODE (t) == REAL_CST -+ || TREE_CODE (t) == COMPLEX_CST -+ || TREE_CODE (t) == FLOAT_EXPR -+ || TREE_CODE (t) == REALPART_EXPR)) -+ { -+ *walk_subtrees = 0; -+ return t; -+ } -+ -+ return NULL_TREE; -+} -+ -+/* Helper for nds32_abi_compatible. Return non-NULL tree and set -+ *HANDLED_OPS_P to true if *GSI_P is an ASM stmt. */ -+ -+static tree -+nds32_acd_walk_stmt_fn (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, -+ struct walk_stmt_info *wi ATTRIBUTE_UNUSED) -+{ -+ gimple *stmt = gsi_stmt (*gsi_p); -+ -+ switch (gimple_code (stmt)) -+ { -+ case GIMPLE_DEBUG: -+ *handled_ops_p = true; -+ break; -+ -+ case GIMPLE_ASM: -+ *handled_ops_p = true; -+ return (tree) -1; -+ break; -+ -+ case GIMPLE_CALL: -+ { -+ tree call_decl = gimple_call_fndecl (stmt); -+ if (!call_decl -+ || !nds32_acd_func_rtn_args_check (call_decl)) -+ { -+ *handled_ops_p = true; -+ return call_decl; -+ } -+ } -+ break; -+ -+ default: -+ break; -+ } -+ -+ return NULL_TREE; -+} -+ -+/* This function is the entry of ABI compatible detection pass. */ -+ -+static int -+nds32_abi_compatible (void) -+{ -+ basic_block bb; -+ struct walk_stmt_info wi; -+ -+ memset (&wi, 0, sizeof (wi)); -+ -+ if (!nds32_acd_func_rtn_args_check (current_function_decl)) -+ return 0; -+ -+ if (dump_file) -+ fprintf (dump_file, "Check function body %s\n", -+ function_name (cfun)); -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ gimple *ret; -+ gimple_seq seq = bb_seq (bb); -+ -+ ret = walk_gimple_seq (seq, -+ nds32_acd_walk_stmt_fn, -+ nds32_acd_walk_op_fn, -+ &wi); -+ if (ret != NULL) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, " ! NO PASS: "); -+ print_gimple_stmt (dump_file, ret, 0, TDF_SLIM|TDF_RAW); -+ } -+ nds32_include_fp_arith = true; -+ break; -+ } -+ } -+ -+ if (dump_file) -+ if (!nds32_include_fp_arith) -+ fprintf (dump_file, -+ " >> Pass the inspection of FP operand for function body\n"); -+ -+ return 0; -+} -+ -+static bool -+gate_nds32_abi_compatible (void) -+{ -+ return flag_nds32_abi_compatible -+ && !nds32_include_fp_arith; -+} -+ -+const pass_data pass_data_nds32_abi_compatible = -+{ -+ GIMPLE_PASS, /* type */ -+ "abi_compatible", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ ( PROP_cfg | PROP_ssa ), /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ 0, /* todo_flags_finish */ -+}; -+ -+class pass_nds32_abi_compatible : public gimple_opt_pass -+{ -+public: -+ pass_nds32_abi_compatible (gcc::context *ctxt) -+ : gimple_opt_pass (pass_data_nds32_abi_compatible, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { return gate_nds32_abi_compatible (); } -+ unsigned int execute (function *) { return nds32_abi_compatible (); } -+}; -+ -+gimple_opt_pass * -+make_pass_nds32_abi_compatible (gcc::context *ctxt) -+{ -+ return new pass_nds32_abi_compatible (ctxt); -+} -diff --git a/gcc/config/nds32/nds32-const-remater.c b/gcc/config/nds32/nds32-const-remater.c -new file mode 100644 -index 0000000..760e567 ---- /dev/null -+++ b/gcc/config/nds32/nds32-const-remater.c -@@ -0,0 +1,461 @@ -+/* Global CSE pass of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+/* ------------------------------------------------------------------------ */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "backend.h" -+#include "tree.h" -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" -+#include "cpplib.h" -+#include "params.h" -+#include "tree-pass.h" -+#include "dbgcnt.h" -+#include "df.h" -+#include "tm-constrs.h" -+ -+/* ------------------------------------------------------------------------ */ -+ -+typedef struct reg_avail_info -+{ -+ rtx insn; -+ unsigned int uint; -+ unsigned int regno; -+} reg_avail_info_t; -+ -+ -+static void find_common_const (void); -+static bool try_rematerialize (rtx_insn *, unsigned int, -+ auto_vec *); -+static void clean_reg_avail_info (rtx ,const_rtx, void *); -+static rtx get_const (rtx); -+static bool addsi3_format_p (rtx); -+ -+/* Search the register records. */ -+static bool -+try_rematerialize (rtx_insn *insn, unsigned int uint_r, -+ auto_vec *reg_avail_infos) -+{ -+ unsigned int i, uint_i, cl_i, cl_r, ct_i, ct_r; -+ rtx pat, src, dest, new_insn; -+ bool done = FALSE; -+ df_ref df_rec; -+ df_link *link; -+ -+ cl_r = __builtin_clz (uint_r); -+ ct_r = __builtin_ctz (uint_r); -+ for (i = 0; i < reg_avail_infos->length (); ++i) -+ { -+ if ((*reg_avail_infos)[i].uint != uint_r) -+ { -+ uint_i = (*reg_avail_infos)[i].uint; -+ if (dump_file) -+ fprintf (dump_file, "Try rematerialize %08x with const %08x\n", -+ uint_r, uint_i); -+ cl_i = __builtin_clz (uint_i); -+ ct_i = __builtin_ctz (uint_i); -+ src = SET_DEST (PATTERN ((*reg_avail_infos)[i].insn)); -+ dest = SET_DEST (PATTERN (insn)); -+ -+ if (cl_r > cl_i -+ && (uint_i >> (cl_r - cl_i)) == uint_r) -+ { -+ /* Right shift logical. */ -+ pat = gen_rtx_LSHIFTRT (SImode, src, GEN_INT (cl_r - cl_i)); -+ done = TRUE; -+ if (dump_file) -+ fprintf (dump_file, -+ "Rematerialize %08x with const %08x by l>> %d\n", -+ uint_r, uint_i, (cl_r - cl_i)); -+ } -+ else if (ct_i >= ct_r -+ && ((int) uint_i >> (ct_i - ct_r)) == (int) uint_r) -+ { -+ /* Right shift arithmetic. */ -+ pat = gen_rtx_ASHIFTRT (SImode, src, GEN_INT (ct_i - ct_r)); -+ done = TRUE; -+ if (dump_file) -+ fprintf (dump_file, -+ "Rematerialize %08x with const %08x by a>> %d\n", -+ uint_r, uint_i, (cl_r - cl_i)); -+ } -+ else if (ct_r > ct_i -+ && (uint_i << (ct_r - ct_i)) == uint_r) -+ { -+ /* Left shift. */ -+ pat = gen_rtx_ASHIFT (SImode, src, GEN_INT (ct_r - ct_i)); -+ done = TRUE; -+ if (dump_file) -+ fprintf (dump_file, -+ "Rematerialize %08x with const %08x by << %d\n", -+ uint_r, uint_i, (ct_r - ct_i)); -+ } -+ else if (TARGET_EXT_PERF && __builtin_popcount (uint_r ^ uint_i) == 1) -+ { -+ unsigned int val = uint_r ^ uint_i; -+ if ((uint_r & (uint_r ^ uint_i)) != 0) -+ { -+ if (val > (1 << 5)) -+ { -+ /* Bit set. */ -+ pat = gen_rtx_IOR (SImode, src, GEN_INT (val)); -+ done = TRUE; -+ if (dump_file) -+ fprintf (dump_file, -+ "Rematerialize %08x with const %08x by | %08x\n", -+ uint_r, uint_i, uint_r ^ uint_i); -+ } -+ else -+ { -+ /* Transform to plus if immediate can fit addi45. */ -+ pat = gen_rtx_PLUS (SImode, src, GEN_INT (val)); -+ done = TRUE; -+ if (dump_file) -+ fprintf (dump_file, -+ "Rematerialize %08x with const %08x by | %08x\n", -+ uint_r, uint_i, uint_r ^ uint_i); -+ } -+ } -+ else -+ { -+ if (val > (1 << 5)) -+ { -+ /* Bit clear. */ -+ pat = gen_rtx_AND (SImode, src, GEN_INT (~(uint_r ^ uint_i))); -+ done = TRUE; -+ if (dump_file) -+ fprintf (dump_file, -+ "Rematerialize %08x with const %08x by & %08x\n", -+ uint_r, uint_i, ~(uint_r ^ uint_i)); -+ } -+ else -+ { -+ /* Transform to plus if immediate can fit subi45. */ -+ pat = gen_rtx_PLUS (SImode, src, GEN_INT ((int) -val)); -+ done = TRUE; -+ if (dump_file) -+ fprintf (dump_file, -+ "Rematerialize %08x with const %08x by | %08x\n", -+ uint_r, uint_i, uint_r ^ uint_i); -+ } -+ } -+ } -+ else if ((uint_r > uint_i ? uint_r - uint_i -+ : uint_i - uint_r) < 0x4000) -+ { -+ /* Check insn_info existence because the instruction -+ maybe be deleted.*/ -+ if (DF_INSN_INFO_GET ((*reg_avail_infos)[i].insn)) -+ { -+ df_rec = DF_INSN_DEFS ((*reg_avail_infos)[i].insn); -+ link = DF_REF_CHAIN (df_rec); -+ -+ /* Do not use the dead instruction. */ -+ /* Do not use the original matched sethi. */ -+ if (!link) -+ continue; -+ for (link = DF_REF_CHAIN (df_rec); link; link = link->next) -+ { -+ if (DF_REF_REGNO (link->ref) == 0 -+ || !DF_REF_INSN_INFO (link->ref) -+ || DF_REF_INSN (link->ref) == insn) -+ break; -+ } -+ if (link) -+ continue; -+ } -+ -+ /* Add. */ -+ if (uint_r > uint_i) -+ { -+ pat = gen_rtx_PLUS (SImode, src, GEN_INT (uint_r - uint_i)); -+ done = TRUE; -+ } -+ else -+ { -+ pat = gen_rtx_PLUS (SImode, src, GEN_INT ((HOST_WIDE_INT) -+ uint_r - uint_i)); -+ done = TRUE; -+ } -+ } -+ -+ if (done) -+ { -+ /* Emit the new instruction. */ -+ new_insn = gen_move_insn (dest, pat); -+ emit_insn_before (new_insn, insn); -+ set_dst_reg_note (new_insn, REG_EQUAL, GEN_INT (uint_r), dest); -+ return TRUE; -+ } -+ } -+ } -+ return FALSE; -+} -+ -+/* Clean the reg_avail_info value. */ -+static void -+clean_reg_avail_info (rtx dest, const_rtx setter ATTRIBUTE_UNUSED, -+ void *data) -+{ -+ unsigned int i; -+ auto_vec *reg_avail_infos = -+ (auto_vec *) data; -+ -+ if (GET_CODE (dest) == SUBREG) -+ dest = SUBREG_REG (dest); -+ -+ if (REG_P (dest)) -+ for (i = 0; i < reg_avail_infos->length (); ++i) -+ if ((*reg_avail_infos)[i].regno == REGNO (dest) -+ || (GET_MODE_SIZE (GET_MODE (dest)) == 8 -+ && (*reg_avail_infos)[i].regno == REGNO (dest) + 1)) -+ reg_avail_infos->unordered_remove (i--); -+} -+ -+/* Return the const if the setting value is a constant integer. */ -+static rtx -+get_const (rtx insn) -+{ -+ rtx note; -+ -+ if (GET_CODE (PATTERN (insn)) != SET -+ || !REG_P (SET_DEST (PATTERN (insn))) -+ || GET_MODE (SET_DEST (PATTERN (insn))) != SImode) -+ return NULL_RTX; -+ -+ /* Constant move instruction. */ -+ if (CONST_INT_P (XEXP (PATTERN (insn), 1))) -+ return XEXP (PATTERN (insn), 1); -+ -+ note = find_reg_note (insn, REG_EQUAL, NULL_RTX); -+ if (!note) -+ note = find_reg_note (insn, REG_EQUIV, NULL_RTX); -+ -+ if (note && CONST_INT_P (XEXP (note, 0))) -+ return XEXP (note, 0); -+ -+ return NULL_RTX; -+} -+ -+/* Return true if the instruction is addi format. */ -+static bool -+addsi3_format_p (rtx insn) -+{ -+ if (GET_CODE (XEXP (PATTERN (insn), 1)) == PLUS -+ && GET_CODE (XEXP (XEXP (PATTERN (insn), 1), 1)) == CONST_INT) -+ return TRUE; -+ -+ return FALSE; -+} -+ -+/* Return true if the instruction is sethi format. */ -+static bool -+sethi_format_p (rtx insn) -+{ -+ if (GET_CODE (PATTERN (insn)) == SET -+ && GET_CODE (XEXP (PATTERN (insn), 1)) == CONST_INT -+ && satisfies_constraint_Ihig (XEXP (PATTERN (insn), 1))) -+ return TRUE; -+ return FALSE; -+} -+ -+/* Return true if the register definition only be used by insn. */ -+static bool -+use_only_p (rtx insn) -+{ -+ rtx def_insn; -+ df_ref rec; -+ df_link *link; -+ rec = DF_INSN_USES (insn); -+ link = DF_REF_CHAIN (rec); -+ -+ if (!link -+ || DF_REF_REGNO (link->ref) == 0 -+ || !DF_REF_INSN_INFO (link->ref)) -+ return FALSE; -+ -+ def_insn = DF_REF_INSN (link->ref); -+ -+ if (!sethi_format_p (def_insn)) -+ return FALSE; -+ -+ rec = DF_INSN_DEFS (def_insn); -+ link = DF_REF_CHAIN (rec); -+ -+ if (!link -+ || link->next -+ || DF_REF_REGNO (link->ref) == 0 -+ || !DF_REF_INSN_INFO (link->ref)) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+/* Traverse instructions in each basic block, and save the value of -+ setting constant instructions. */ -+static void -+find_common_const (void) -+{ -+ basic_block bb; -+ unsigned int i; -+ -+ /* Save register constant value. */ -+ auto_vec reg_avail_infos; -+ reg_avail_info_t reg_avail_info; -+ -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ rtx_insn *insn; -+ rtx dest, cst; -+ -+ /* Clear the vector. */ -+ while (!reg_avail_infos.is_empty ()) -+ reg_avail_infos.pop (); -+ -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (!NONDEBUG_INSN_P (insn)) -+ continue; -+ -+ if (CALL_P (insn)) -+ { -+ /* Clean hard register. */ -+ for (i = 0; i < reg_avail_infos.length ();) -+ { -+ if (HARD_REGISTER_NUM_P (reg_avail_infos[i].regno) -+ && call_used_regs[reg_avail_infos[i].regno]) -+ reg_avail_infos.unordered_remove (i); -+ else -+ ++i; -+ } -+ } -+ -+ cst = get_const (insn); -+ if (cst == NULL_RTX) -+ { -+ note_stores (PATTERN (insn), clean_reg_avail_info, -+ ®_avail_infos); -+ continue; -+ } -+ -+ dest = SET_DEST (PATTERN (insn)); -+ -+ if (addsi3_format_p (insn) -+ && use_only_p (insn) -+ && try_rematerialize (insn, XUINT (cst, 0), ®_avail_infos)) -+ { -+ delete_insn (insn); -+ df_insn_rescan_all (); -+ } -+ -+ note_stores (PATTERN (insn), clean_reg_avail_info, ®_avail_infos); -+ reg_avail_info.insn = insn; -+ reg_avail_info.uint = XUINT (cst, 0); -+ reg_avail_info.regno = REGNO (dest); -+ if (dump_file) -+ fprintf (dump_file, "Find const %08x on %u\n", -+ reg_avail_info.uint, reg_avail_info.regno); -+ reg_avail_infos.safe_push (reg_avail_info); -+ } -+ } -+} -+ -+static unsigned int -+nds32_const_remater_opt (void) -+{ -+ df_chain_add_problem (DF_DU_CHAIN + DF_UD_CHAIN); -+ df_note_add_problem (); -+ df_insn_rescan_all (); -+ df_analyze (); -+ -+ find_common_const (); -+ -+ df_insn_rescan_all (); -+ return 0; -+} -+ -+const pass_data pass_data_nds32_const_remater_opt = -+{ -+ RTL_PASS, /* type */ -+ "const_remater_opt", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ 0, /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_df_finish, /* todo_flags_finish */ -+}; -+ -+class pass_nds32_const_remater_opt : public rtl_opt_pass -+{ -+public: -+ pass_nds32_const_remater_opt (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_const_remater_opt, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { return flag_nds32_const_remater_opt; } -+ unsigned int execute (function *) { return nds32_const_remater_opt (); } -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_const_remater_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_const_remater_opt (ctxt); -+} -+ -+/* ------------------------------------------------------------------------ */ -diff --git a/gcc/config/nds32/nds32-cost.c b/gcc/config/nds32/nds32-cost.c -index e6a29fc..881d086 100644 ---- a/gcc/config/nds32/nds32-cost.c -+++ b/gcc/config/nds32/nds32-cost.c -@@ -24,73 +24,447 @@ - #include "system.h" - #include "coretypes.h" - #include "backend.h" --#include "target.h" --#include "rtl.h" - #include "tree.h" --#include "tm_p.h" --#include "optabs.h" /* For GEN_FCN. */ -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" - #include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" - #include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.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; -+ enum 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 */ -+ if (TARGET_PIPELINE_PANTHER) -+ *total = COSTS_N_INSNS (1); -+ else -+ *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 */ -+ if (TARGET_PIPELINE_PANTHER) -+ *total = COSTS_N_INSNS (1); -+ else -+ *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) -+ { -+ /* ALU_SHIFT */ -+ if (TARGET_PIPELINE_PANTHER) -+ *total = COSTS_N_INSNS (1); -+ else -+ *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) -+ { -+ /* ALU_SHIFT */ -+ if (TARGET_PIPELINE_PANTHER) -+ *total = COSTS_N_INSNS (1); -+ else -+ *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) -+ { -+ /* ALU_SHIFT */ -+ if (TARGET_PIPELINE_PANTHER) -+ *total = COSTS_N_INSNS (1); -+ else -+ *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) -+ { -+ /* ALU_SHIFT */ -+ if (TARGET_PIPELINE_PANTHER) -+ *total = COSTS_N_INSNS (1); -+ else -+ *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; - --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. */ -@@ -98,7 +472,7 @@ size_cost: - { - case SET: - /* For 'SET' rtx, we need to return false -- so that it can recursively calculate costs. */ -+ so that it can recursively calculate costs. */ - return false; - - case USE: -@@ -108,92 +482,169 @@ size_cost: - - case CONST_INT: - /* All instructions involving constant operation -- need to be considered for cost evaluation. */ -+ need to be considered for cost evaluation. */ - if (outer_code == SET) - { - /* (set X imm5s), use movi55, 2-byte cost. - (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); - --performance_cost: -- /* This is section for performance cost model. */ -+ default: -+ break; -+ } - -- /* FALLTHRU, currently we use same cost model as size_cost. */ -+ return COSTS_N_INSNS (4); - --size_cost: -- /* This is section for size cost model. */ -+} -+ -+int nds32_address_cost_speed_fwprop (rtx address) -+{ -+ rtx plus0, plus1; -+ enum rtx_code code; -+ -+ code = GET_CODE (address); - - switch (code) - { -@@ -201,18 +652,18 @@ size_cost: - case POST_INC: - case POST_DEC: - /* We encourage that rtx contains -- POST_MODIFY/POST_INC/POST_DEC behavior. */ -+ 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 (1); -+ 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 (1); -+ Have it 4-byte cost. */ -+ return COSTS_N_INSNS (2); - - case REG: - /* Simply return 4-byte costs. */ -@@ -220,21 +671,25 @@ size_cost: - - 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. */ -+ 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_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); -@@ -246,4 +701,84 @@ size_cost: - 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, -+ enum 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-cprop-acc.c b/gcc/config/nds32/nds32-cprop-acc.c -new file mode 100644 -index 0000000..0852095 ---- /dev/null -+++ b/gcc/config/nds32/nds32-cprop-acc.c -@@ -0,0 +1,845 @@ -+/* Copy propagation on hard registers for accumulate style instruction. -+ Copyright (C) 2000-2014 Free Software Foundation, Inc. -+ -+ 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 -+ . */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "rtl.h" -+#include "tm_p.h" -+#include "insn-config.h" -+#include "regs.h" -+#include "addresses.h" -+#include "predict.h" -+#include "basic-block.h" -+#include "reload.h" -+#include "hash-set.h" -+#include "dominance.h" -+#include "cfg.h" -+#include "function.h" -+#include "recog.h" -+#include "cfgrtl.h" -+#include "flags.h" -+#include "diagnostic-core.h" -+#include "obstack.h" -+#include "tree-pass.h" -+#include "bitmap.h" -+#include "df.h" -+#include "output.h" -+#include "emit-rtl.h" -+#include -+ -+/* For each move instruction, we have a two-dimensional vector that record -+ what insns need to replace the operands when the move instruction is -+ propagated. */ -+ -+typedef std::vector insn_list; -+ -+/* Function called by note_uses to replace used subexpressions. */ -+ -+struct replace_src_operands_data -+{ -+ rtx dst_reg; -+ rtx src_reg; -+ unsigned int old_regno; -+ unsigned int new_regno; -+ rtx_insn *insn; -+}; -+ -+/* Return true if a mode change from ORIG to NEW is allowed for REGNO. -+ Adapted from mode_change_ok in regcprop. */ -+ -+static bool -+nds32_mode_change_ok (enum machine_mode orig_mode, enum machine_mode new_mode, -+ unsigned int regno ATTRIBUTE_UNUSED) -+{ -+ if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode)) -+ return false; -+ -+#ifdef CANNOT_CHANGE_MODE_CLASS -+ return !REG_CANNOT_CHANGE_MODE_P (regno, orig_mode, new_mode); -+#endif -+ -+ return true; -+} -+ -+/* Register REGNO was originally set in ORIG_MODE. It - or a copy of it - -+ was copied in COPY_MODE to COPY_REGNO, and then COPY_REGNO was accessed -+ in NEW_MODE. -+ Return a NEW_MODE rtx for REGNO if that's OK, otherwise return NULL_RTX. -+ Adapted from maybe_mode_change in regcprop. */ -+ -+static rtx -+nds32_mode_change_reg (enum machine_mode orig_mode, enum machine_mode copy_mode, -+ enum machine_mode new_mode, unsigned int regno, -+ unsigned int copy_regno ATTRIBUTE_UNUSED) -+{ -+ if (GET_MODE_SIZE (copy_mode) < GET_MODE_SIZE (orig_mode) -+ && GET_MODE_SIZE (copy_mode) < GET_MODE_SIZE (new_mode)) -+ return NULL_RTX; -+ -+ if (orig_mode == new_mode) -+ return gen_raw_REG (new_mode, regno); -+ else if (nds32_mode_change_ok (orig_mode, new_mode, regno)) -+ { -+ int copy_nregs = hard_regno_nregs[copy_regno][copy_mode]; -+ int use_nregs = hard_regno_nregs[copy_regno][new_mode]; -+ int copy_offset -+ = GET_MODE_SIZE (copy_mode) / copy_nregs * (copy_nregs - use_nregs); -+ int offset -+ = GET_MODE_SIZE (orig_mode) - GET_MODE_SIZE (new_mode) - copy_offset; -+ int byteoffset = offset % UNITS_PER_WORD; -+ int wordoffset = offset - byteoffset; -+ -+ offset = ((WORDS_BIG_ENDIAN ? wordoffset : 0) -+ + (BYTES_BIG_ENDIAN ? byteoffset : 0)); -+ regno += subreg_regno_offset (regno, orig_mode, offset, new_mode); -+ if (HARD_REGNO_MODE_OK (regno, new_mode)) -+ return gen_raw_REG (new_mode, regno); -+ } -+ return NULL_RTX; -+} -+ -+/* Return true if INSN is a register-based move instruction, false -+ otherwise. */ -+ -+static bool -+nds32_is_reg_mov_p (rtx_insn *insn) -+{ -+ rtx pat = PATTERN (insn); -+ -+ if (GET_CODE (pat) != SET) -+ return false; -+ -+ rtx src_reg = SET_SRC (pat); -+ rtx dst_reg = SET_DEST (pat); -+ -+ if (REG_P (dst_reg) && REG_P (src_reg) && can_copy_p (GET_MODE (dst_reg))) -+ return true; -+ else -+ return false; -+} -+ -+ -+/* Return accumulated register if INSN is an accumulate style instruction, -+ otherwise return NULL_RTX. */ -+ -+static rtx -+nds32_is_acc_insn_p (rtx_insn *insn) -+{ -+ int i; -+ const operand_alternative *op_alt; -+ rtx pat; -+ -+ if (get_attr_length (insn) != 4) -+ return NULL_RTX; -+ -+ pat = PATTERN (insn); -+ if (GET_CODE (pat) != SET) -+ return NULL_RTX; -+ -+ /* Try to get the insn data from recog_data. */ -+ recog_memoized (insn); -+ extract_constrain_insn (insn); -+ /* Transform the constraint strings into a more usable form, -+ recog_op_alt. */ -+ preprocess_constraints (insn); -+ op_alt = which_op_alt (); -+ -+ /* Check all operands whether the output operand is identical to -+ another input operand */ -+ for (i = 0; i < recog_data.n_operands; ++i) -+ { -+ int matches = op_alt[i].matches; -+ int matched = op_alt[i].matched; -+ if ((matches >= 0 -+ && (recog_data.operand_type[i] != OP_IN -+ || recog_data.operand_type[matches] != OP_IN)) -+ || (matched >= 0 -+ && (recog_data.operand_type[i] != OP_IN -+ || recog_data.operand_type[matched] != OP_IN))) -+ return recog_data.operand[i]; -+ } -+ -+ return NULL_RTX; -+} -+ -+/* Finds the reference corresponding to the definition of register whose -+ register number is REGNO in INSN. DF is the dataflow object. -+ Adapted from df_find_def in df-core. */ -+ -+static df_ref -+nds32_df_find_regno_def (rtx_insn *insn, unsigned int regno) -+{ -+ df_ref def; -+ -+ FOR_EACH_INSN_DEF (def, insn) -+ if (DF_REF_REGNO (def) == regno) -+ return def; -+ -+ return NULL; -+ } -+ -+/* Return true if the REG in INSN is only defined by one insn whose uid -+ is DEF_UID, otherwise return false. */ -+ -+static bool -+nds32_is_single_def_p (rtx_insn *insn, rtx reg, unsigned int def_uid) -+{ -+ df_ref use; -+ -+ FOR_EACH_INSN_USE (use, insn) -+ { -+ df_link *link; -+ unsigned int uid; -+ -+ if (DF_REF_REGNO (use) >= REGNO (reg) -+ && DF_REF_REGNO (use) < END_REGNO (reg)) -+ { -+ link = DF_REF_CHAIN (use); -+ if (link->next -+ || DF_REF_IS_ARTIFICIAL (link->ref)) -+ return false; -+ -+ uid = DF_REF_INSN_UID (link->ref); -+ if (uid != def_uid) -+ return false; -+ } -+ } -+ -+ return true; -+} -+ -+/* Return true if there is no definition of REG on any path from the insn -+ whose uid is FROM_UID (called FROM) to insn TO, otherwise return false. -+ This function collects the reaching definitions bitmap at insn TO, and -+ check if all uses of REG in insn FROM can reach insn TO. */ -+ -+static bool -+nds32_no_define_reg_p (rtx to, rtx reg, unsigned int from_uid) -+{ -+ basic_block bb = BLOCK_FOR_INSN (to); -+ struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (bb); -+ bitmap_head rd_local; -+ bool result = true; -+ rtx_insn *insn; -+ df_ref use; -+ df_insn_info *insn_info; -+ -+ bitmap_initialize (&rd_local, &bitmap_default_obstack); -+ bitmap_copy (&rd_local, &bb_info->in); -+ df_rd_simulate_artificial_defs_at_top (bb, &rd_local); -+ -+ for (insn = BB_HEAD (bb); insn != to; insn = NEXT_INSN (insn)) -+ if (INSN_P (insn)) -+ df_rd_simulate_one_insn (bb, insn, &rd_local); -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "scan reach define:"); -+ print_rtl_single (dump_file, to); -+ -+ fprintf (dump_file, "bb rd in:\n"); -+ dump_bitmap (dump_file, &bb_info->in); -+ -+ fprintf (dump_file, "reach def:\n"); -+ dump_bitmap (dump_file, &rd_local); -+ } -+ -+ insn_info = DF_INSN_UID_GET (from_uid); -+ FOR_EACH_INSN_INFO_USE (use, insn_info) -+ { -+ df_link *link; -+ -+ if (DF_REF_REGNO (use) >= REGNO (reg) -+ && DF_REF_REGNO (use) < END_REGNO (reg)) -+ for (link = DF_REF_CHAIN (use); link; link = link->next) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "use ID %d\n", DF_REF_ID (link->ref)); -+ if (DF_REF_IS_ARTIFICIAL (link->ref)) -+ fprintf (dump_file, "use ref is artificial\n"); -+ else -+ { -+ fprintf (dump_file, "use from insn:"); -+ print_rtl_single (dump_file, DF_REF_INSN (link->ref)); -+ } -+ } -+ result &= -+ (bitmap_bit_p (&rd_local, DF_REF_ID (link->ref))) -+ ? true -+ : false; -+ } -+ } -+ -+ bitmap_clear (&rd_local); -+ return result; -+} -+ -+/* Return true if the value held by REG is no longer needed before INSN -+ (i.e. REG is dead before INSN), otherwise return false. */ -+ -+static bool -+nds32_is_dead_reg_p (rtx_insn *insn, rtx reg) -+{ -+ basic_block bb = BLOCK_FOR_INSN (insn); -+ bitmap live = BITMAP_ALLOC (®_obstack); -+ bool result = true; -+ rtx_insn *i; -+ unsigned int rn; -+ -+ bitmap_copy (live, DF_LR_IN (bb)); -+ df_simulate_initialize_forwards (bb, live); -+ -+ for (i = BB_HEAD (bb); i != insn; i = NEXT_INSN (i)) -+ df_simulate_one_insn_forwards (bb, i, live); -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "scan live regs:"); -+ print_rtl_single (dump_file, insn); -+ -+ fprintf (dump_file, "bb lr in:\n"); -+ dump_bitmap (dump_file, DF_LR_IN (bb)); -+ -+ fprintf (dump_file, "live:\n"); -+ dump_bitmap (dump_file, live); -+ } -+ -+ for (rn = REGNO (reg); rn < END_REGNO (reg); ++rn) -+ result &= (bitmap_bit_p (live, rn)) ? false : true; -+ -+ BITMAP_FREE (live); -+ return result; -+} -+ -+/* Return true if START can do propagation. Notice START maybe a move -+ instruction or an accumulate style instruction. -+ MOV_UID is the uid of beginning move instruction that is only used by -+ function nds32_no_define_reg_p. -+ DST_REG & SRC_REG is the SET_DEST and SET_SRC of a move instruction that -+ maybe real or unreal, respectively. -+ INDEX indicates what number sequence is currently considered rank as -+ consecutive hard registers. Simultaneously, INDEX is the index of row in -+ INSN_LISTS. */ -+ -+static bool -+nds32_can_cprop_acc_1 (rtx_insn *start, unsigned int mov_uid, -+ rtx dst_reg, rtx src_reg, -+ unsigned int index, -+ std::vector &insn_lists) -+{ -+ unsigned int lead_regno = REGNO (dst_reg) + index; -+ unsigned int new_regno = REGNO (src_reg) + index; -+ df_ref def_rec; -+ df_link *link; -+ -+ def_rec = nds32_df_find_regno_def (start, lead_regno); -+ gcc_assert (def_rec); -+ -+ for (link = DF_REF_CHAIN (def_rec); link; link = link->next) -+ { -+ rtx *use_loc; -+ unsigned int use_regno; -+ enum machine_mode use_mode; -+ rtx_insn *use_insn; -+ rtx acc_reg, new_src; -+ -+ if (DF_REF_IS_ARTIFICIAL (link->ref)) -+ return false; -+ -+ use_loc = DF_REF_LOC (link->ref); -+ gcc_assert (use_loc && REG_P (*use_loc)); -+ -+ use_regno = REGNO (*use_loc); -+ /* Do not propagate when any insns use register that regno is -+ smaller than DST_REG. */ -+ if (use_regno < REGNO (dst_reg)) -+ return false; -+ -+ /* This status should be handled by previous call. */ -+ if (use_regno < lead_regno) -+ continue; -+ -+ /* Do not propagate because not all of the pieces of the copy came -+ from DST_REG. */ -+ if (END_REGNO (*use_loc) > END_REGNO (dst_reg)) -+ return false; -+ -+ use_insn = DF_REF_INSN (link->ref); -+ /* Do not propagate since call-used registers can't be replaced. */ -+ if (CALL_P (use_insn)) -+ return false; -+ -+ /* Do not replace in asms intentionally referencing hard registers. */ -+ if (asm_noperands (PATTERN (use_insn)) >= 0 -+ && use_regno == ORIGINAL_REGNO (*use_loc)) -+ return false; -+ -+ /* Do not propagate when the register is defined by more than one -+ instruction. */ -+ if (!nds32_is_single_def_p (use_insn, *use_loc, INSN_UID (start))) -+ return false; -+ -+ use_mode = GET_MODE (*use_loc); -+ new_src = nds32_mode_change_reg (GET_MODE (src_reg), -+ GET_MODE (dst_reg), -+ use_mode, -+ new_regno, -+ use_regno); -+ /* Do not propagate if we can't generate a new register with new mode. */ -+ if (!new_src) -+ return false; -+ -+ /* Can not replace DST_REG with SRC_REG when SRC_REG is redefined between -+ START and use insn of START. */ -+ if (!nds32_no_define_reg_p (use_insn, new_src, mov_uid)) -+ return false; -+ -+ acc_reg = nds32_is_acc_insn_p (use_insn); -+ /* Handle the accumulate style instruction that accumulate register -+ may be replaced. -+ Also handle the AUTO_INC register that is another form of accumulated -+ register. */ -+ if ((acc_reg && rtx_equal_p (acc_reg, *use_loc)) -+ || FIND_REG_INC_NOTE (use_insn, *use_loc)) -+ { -+ unsigned int i, use_nregs; -+ -+ /* ACC_REG can't be replaced since the SRC_REG can't be -+ overwritten. */ -+ if (!nds32_is_dead_reg_p (use_insn, new_src)) -+ return false; -+ -+ /* Once we confirm that ACC_REG can be replaced, the unreal move -+ instruction is generated. For example: -+ mov r0, r1 mov r0, r1 -+ cmovn r0, r2, r3 -> cmovn r1, r2, r3 -+ mov r0, r1 -+ If the unreal move instruction can do propagation, the ACC_REG -+ can be replaced. We check it in a recursive way. */ -+ use_nregs = hard_regno_nregs [use_regno][(int) use_mode]; -+ for (i = 0; i < use_nregs; ++i) -+ if (!nds32_can_cprop_acc_1 (use_insn, mov_uid, -+ *use_loc, new_src, -+ i, insn_lists)) -+ return false; -+ } -+ insn_lists[index].push_back (use_insn); -+ } -+ -+ return true; -+} -+ -+/* Return true if MOV can do propagation, otherwise return false. -+ INSN_LISTS is used to record what insns need to replace the operands. */ -+ -+static bool -+nds32_can_cprop_acc (rtx_insn *mov, std::vector &insn_lists) -+{ -+ rtx dst_reg = SET_DEST (PATTERN (mov)); -+ rtx src_reg = SET_SRC (PATTERN (mov)); -+ unsigned int dst_regno = REGNO (dst_reg); -+ enum machine_mode dst_mode = GET_MODE (dst_reg); -+ unsigned int dst_nregs = hard_regno_nregs[dst_regno][(int) dst_mode]; -+ unsigned int index; -+ -+ insn_lists.resize (dst_nregs); -+ for (index = 0; index < dst_nregs; ++index) -+ if (!nds32_can_cprop_acc_1 (mov, INSN_UID (mov), -+ dst_reg, src_reg, -+ index, insn_lists)) -+ return false; -+ -+ return true; -+} -+ -+/* Replace every occurrence of OLD_REGNO in LOC with NEW_REGNO. LOC maybe a -+ part of INSN. -+ DST_REG & SRC_REG are used by function nds32_mode_change_reg. -+ Mark each change with validate_change passing INSN. */ -+ -+static void -+nds32_replace_partial_operands (rtx *loc, rtx dst_reg, rtx src_reg, -+ unsigned int old_regno, unsigned int new_regno, -+ rtx_insn *insn) -+{ -+ int i, j; -+ rtx x = *loc; -+ enum rtx_code code; -+ const char *fmt; -+ -+ if (!x) -+ return; -+ -+ code = GET_CODE (x); -+ fmt = GET_RTX_FORMAT (code); -+ -+ if (REG_P (x) && REGNO (x) == old_regno) -+ { -+ rtx new_reg = nds32_mode_change_reg (GET_MODE (src_reg), -+ GET_MODE (dst_reg), -+ GET_MODE (x), -+ new_regno, -+ old_regno); -+ -+ gcc_assert (new_reg); -+ -+ ORIGINAL_REGNO (new_reg) = ORIGINAL_REGNO (x); -+ REG_ATTRS (new_reg) = REG_ATTRS (x); -+ REG_POINTER (new_reg) = REG_POINTER (x); -+ -+ /* ??? unshare or not? */ -+ validate_change (insn, loc, new_reg, 1); -+ return; -+ } -+ -+ /* Call ourself recursively to perform the replacements. */ -+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) -+ { -+ if (fmt[i] == 'e') -+ nds32_replace_partial_operands (&XEXP (x, i), dst_reg, src_reg, -+ old_regno, new_regno, insn); -+ else if (fmt[i] == 'E') /* ??? how about V? */ -+ for (j = XVECLEN (x, i) - 1; j >= 0; j--) -+ nds32_replace_partial_operands (&XVECEXP (x, i, j), dst_reg, src_reg, -+ old_regno, new_regno, insn); -+ } -+} -+ -+/* Try replacing every occurrence of OLD_REGNO in INSN with NEW_REGNO. */ -+ -+static void -+nds32_replace_all_operands (rtx dst_reg, rtx src_reg, -+ unsigned int old_regno, unsigned int new_regno, -+ rtx_insn *insn) -+{ -+ nds32_replace_partial_operands (&PATTERN (insn), dst_reg, src_reg, -+ old_regno, new_regno, insn); -+} -+ -+/* Called via note_uses in function nds32_replace_src_operands, for all used -+ rtx do replacement. */ -+ -+static void -+nds32_replace_src_operands_1 (rtx *loc, void *data) -+{ -+ struct replace_src_operands_data *d -+ = (struct replace_src_operands_data *) data; -+ -+ nds32_replace_partial_operands (loc, d->dst_reg, d->src_reg, -+ d->old_regno, d->new_regno, d->insn); -+} -+ -+/* Try replacing every occurrence of OLD_REGNO in INSN with NEW_REGNO, -+ avoiding SET_DESTs. */ -+ -+static void -+nds32_replace_src_operands (rtx dst_reg, rtx src_reg, -+ unsigned int old_regno, unsigned int new_regno, -+ rtx_insn *insn) -+{ -+ struct replace_src_operands_data d -+ = {dst_reg, src_reg, old_regno, new_regno, insn}; -+ -+ note_uses (&PATTERN (insn), nds32_replace_src_operands_1, &d); -+} -+ -+/* Try replacing every occurrence of SRC_REG (include its consecutive hard -+ registers) in each insn of INSN_LISTS with DST_REG. */ -+ -+static bool -+nds32_try_replace_operands (rtx dst_reg, rtx src_reg, -+ std::vector &insn_lists) -+{ -+ unsigned int i; -+ std::vector::iterator ritr; -+ unsigned int old_regno, new_regno; -+ -+ old_regno = REGNO (dst_reg); -+ new_regno = REGNO (src_reg); -+ -+ for (i = 0; i < insn_lists.size (); ++i, ++old_regno, ++new_regno) -+ for (ritr = insn_lists[i].begin (); ritr != insn_lists[i].end (); ++ritr) -+ { -+ rtx_insn *insn = *ritr; -+ rtx acc_reg; -+ -+ acc_reg = nds32_is_acc_insn_p (insn); -+ if (acc_reg && REGNO (acc_reg) == old_regno) -+ { -+ /* Replace OP_OUT & OP_INOUT */ -+ nds32_replace_all_operands (dst_reg, src_reg, -+ old_regno, new_regno, insn); -+ -+ } -+ else -+ { -+ /* Replace OP_IN */ -+ nds32_replace_src_operands (dst_reg, src_reg, -+ old_regno, new_regno, insn); -+ } -+ } -+ -+ if (!apply_change_group ()) -+ return false; -+ else -+ { -+ df_analyze (); -+ return true; -+ } -+} -+ -+/* Check if each move instruction in WORK_LIST can do propagation, and -+ then try to replace operands if necessary. */ -+ -+static int -+nds32_do_cprop_acc (auto_vec &work_list) -+{ -+ int n_replace = 0; -+ int i; -+ rtx_insn *mov; -+ std::vector insn_lists; -+ -+ FOR_EACH_VEC_ELT (work_list, i, mov) -+ { -+ if (nds32_can_cprop_acc (mov, insn_lists)) -+ { -+ if (dump_file) -+ fprintf (dump_file, "\n [CPROP_ACC] insn %d will be cprop. \n", -+ INSN_UID (mov)); -+ -+ if (nds32_try_replace_operands (SET_DEST (PATTERN (mov)), -+ SET_SRC (PATTERN (mov)), -+ insn_lists)) -+ n_replace++; -+ } -+ insn_lists.clear (); -+ } -+ -+ return n_replace; -+} -+ -+/* Return true if MOV meets the conditions of propagation about move -+ instruction, otherwise return false. */ -+ -+static bool -+nds32_is_target_mov_p (rtx mov) -+{ -+ rtx dst = SET_DEST (PATTERN (mov)); -+ rtx src = SET_SRC (PATTERN (mov)); -+ unsigned int dst_regno, src_regno; -+ unsigned int dst_nregs, src_nregs; -+ bool dst_is_general, src_is_general; -+ -+ gcc_assert (REG_P (dst) && REG_P (src)); -+ -+ dst_regno = REGNO (dst); -+ src_regno = REGNO (src); -+ dst_nregs = hard_regno_nregs[dst_regno][GET_MODE (dst)]; -+ src_nregs = hard_regno_nregs[src_regno][GET_MODE (src)]; -+ -+ /* Do not propagate to the stack pointer, as that can leave memory accesses -+ with no scheduling dependency on the stack update. -+ Adapted from regcprop. */ -+ if (dst_regno == STACK_POINTER_REGNUM) -+ return false; -+ -+ /* Likewise with the frame pointer, if we're using one. -+ Adapted from regcprop. */ -+ if (frame_pointer_needed && dst_regno == HARD_FRAME_POINTER_REGNUM) -+ return false; -+ -+ /* Do not propagate to fixed or global registers, patterns can be relying -+ to see particular fixed register or users can expect the chosen global -+ register in asm. -+ Adapted from regcprop. */ -+ if (fixed_regs[dst_regno] || global_regs[dst_regno]) -+ return false; -+ -+ /* Make sure the all consecutive registers of SET_DEST are only defined by -+ SET_SRC. */ -+ if (dst_nregs > src_nregs) -+ return false; -+ -+ /* Narrowing on big endian will result in the invalid transformation. */ -+ if (dst_nregs < src_nregs -+ && (GET_MODE_SIZE (GET_MODE (src)) > UNITS_PER_WORD -+ ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN)) -+ return false; -+ -+ dst_is_general = in_hard_reg_set_p (reg_class_contents[GENERAL_REGS], -+ GET_MODE (dst), REGNO (dst)); -+ src_is_general = in_hard_reg_set_p (reg_class_contents[GENERAL_REGS], -+ GET_MODE (src), REGNO (src)); -+ /* Make sure the register class of SET_DEST & SET_SRC are the same. */ -+ if (dst_is_general ^ src_is_general) -+ return false; -+ -+ return true; -+} -+ -+/* Collect the move instructions that are the uses of accumulated register -+ in WORK_LIST */ -+ -+static void -+nds32_cprop_acc_find_target_mov (auto_vec &work_list) -+{ -+ basic_block bb; -+ rtx_insn *insn; -+ rtx acc_reg; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ FOR_BB_INSNS (bb, insn) -+ if (INSN_P (insn)) -+ { -+ acc_reg = nds32_is_acc_insn_p (insn); -+ if (acc_reg) -+ { -+ unsigned int acc_regno; -+ enum machine_mode acc_mode; -+ df_ref use; -+ df_link *link; -+ rtx_insn *def_insn; -+ -+ if (!single_set (insn) || !REG_P (acc_reg)) -+ continue; -+ -+ acc_regno = REGNO (acc_reg); -+ /* Don't replace in asms intentionally referencing hard regs. */ -+ if (asm_noperands (PATTERN (insn)) >= 0 -+ && acc_regno == ORIGINAL_REGNO (acc_reg)) -+ continue; -+ -+ if (dump_file) -+ fprintf (dump_file, -+ "\n [CPROP_ACC] " -+ "RTL_UID %d is an exchangeable ACC insn. \n", -+ INSN_UID (insn)); -+ -+ use = df_find_use (insn, acc_reg); -+ gcc_assert (use); -+ link = DF_REF_CHAIN (use); -+ -+ if (link->next -+ || DF_REF_IS_ARTIFICIAL (link->ref)) -+ continue; -+ -+ acc_mode = GET_MODE (acc_reg); -+ def_insn = DF_REF_INSN (link->ref); -+ if (nds32_is_reg_mov_p (def_insn)) -+ { -+ rtx *loc = DF_REF_LOC (link->ref); -+ enum machine_mode loc_mode = GET_MODE (*loc); -+ -+ /* If the move instruction can't define whole accumulated -+ register, the replacement is invalid. */ -+ if (loc_mode != acc_mode) -+ if (hard_regno_nregs[acc_regno][acc_mode] -+ > hard_regno_nregs[acc_regno][loc_mode]) -+ continue; -+ -+ if (nds32_is_target_mov_p (def_insn)) -+ work_list.safe_push (def_insn); -+ } -+ } -+ } -+} -+ -+/* Main entry point for the forward copy propagation optimization for -+ accumulate style instruction. */ -+ -+static int -+nds32_cprop_acc_opt (void) -+{ -+ df_chain_add_problem (DF_DU_CHAIN + DF_UD_CHAIN); -+ df_note_add_problem (); -+ df_set_flags (DF_RD_PRUNE_DEAD_DEFS); -+ df_insn_rescan_all (); -+ df_analyze (); -+ -+ auto_vec work_list; -+ -+ nds32_cprop_acc_find_target_mov (work_list); -+ if (work_list.is_empty()) -+ { -+ if (dump_file) -+ fprintf (dump_file, "\n [CPROP_ACC] The work_list is empty. \n"); -+ return 0; -+ } -+ -+ if (dump_file) -+ { -+ int i; -+ rtx_insn *mov; -+ -+ fprintf (dump_file, "\n [CPROP_ACC] The content of work_list:"); -+ FOR_EACH_VEC_ELT (work_list, i, mov) -+ fprintf (dump_file, " %d", INSN_UID (mov)); -+ fprintf (dump_file, "\n"); -+ } -+ -+ compute_bb_for_insn (); -+ -+ int n_replace = nds32_do_cprop_acc (work_list); -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "\n [CPROP_ACC] Result: "); -+ if (n_replace == 0) -+ fprintf (dump_file, "No move can do cprop. \n"); -+ else -+ fprintf (dump_file, "Do cprop for %d move. \n", n_replace); -+ } -+ -+ work_list.release (); -+ return 1; -+} -+ -+const pass_data pass_data_nds32_cprop_acc_opt = -+{ -+ RTL_PASS, /* type */ -+ "cprop_acc", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ 0, /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_df_finish, /* todo_flags_finish */ -+}; -+ -+class pass_nds32_cprop_acc_opt : public rtl_opt_pass -+{ -+public: -+ pass_nds32_cprop_acc_opt (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_cprop_acc_opt, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { return optimize > 0 && flag_nds32_cprop_acc; } -+ unsigned int execute (function *) { return nds32_cprop_acc_opt (); } -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_cprop_acc_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_cprop_acc_opt (ctxt); -+} -diff --git a/gcc/config/nds32/nds32-doubleword.md b/gcc/config/nds32/nds32-doubleword.md -index 23a9f25..7c9dfb9 100644 ---- a/gcc/config/nds32/nds32-doubleword.md -+++ b/gcc/config/nds32/nds32-doubleword.md -@@ -23,7 +23,8 @@ - ;; Move DImode/DFmode instructions. - ;; ------------------------------------------------------------- - -- -+;; Do *NOT* try to split DI/DFmode before reload since LRA seem -+;; still buggy for such behavior at least at gcc 4.8.2... - (define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] -@@ -46,149 +47,100 @@ - - - (define_insn "move_" -- [(set (match_operand:DIDF 0 "nonimmediate_operand" "=r, r, r, m") -- (match_operand:DIDF 1 "general_operand" " r, i, m, r"))] -- "" -+ [(set (match_operand:DIDF 0 "nonimmediate_operand" "=r, r, r, r, Da, m, f, Q, f, *r, *f") -+ (match_operand:DIDF 1 "general_operand" " r, i, Da, m, r, r, Q, f, f, *f, *r"))] -+ "register_operand(operands[0], mode) -+ || register_operand(operands[1], mode)" - { -- rtx addr; -- rtx otherops[5]; -- - switch (which_alternative) - { - case 0: - return "movd44\t%0, %1"; -- - case 1: - /* reg <- const_int, we ask gcc to split instruction. */ - return "#"; -- - case 2: -- /* Refer to nds32_legitimate_address_p() in nds32.c, -- we only allow "reg", "symbol_ref", "const", and "reg + const_int" -- as address rtx for DImode/DFmode memory access. */ -- addr = XEXP (operands[1], 0); -- -- otherops[0] = gen_rtx_REG (SImode, REGNO (operands[0])); -- otherops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); -- otherops[2] = addr; -- -- if (REG_P (addr)) -- { -- /* (reg) <- (mem (reg)) */ -- output_asm_insn ("lmw.bi\t%0, [%2], %1, 0", otherops); -- } -- else if (GET_CODE (addr) == PLUS) -- { -- /* (reg) <- (mem (plus (reg) (const_int))) */ -- rtx op0 = XEXP (addr, 0); -- rtx op1 = XEXP (addr, 1); -- -- if (REG_P (op0)) -- { -- otherops[2] = op0; -- otherops[3] = op1; -- otherops[4] = gen_int_mode (INTVAL (op1) + 4, SImode); -- } -- else -- { -- otherops[2] = op1; -- otherops[3] = op0; -- otherops[4] = gen_int_mode (INTVAL (op0) + 4, SImode); -- } -- -- /* To avoid base overwrite when REGNO(%0) == REGNO(%2). */ -- if (REGNO (otherops[0]) != REGNO (otherops[2])) -- { -- output_asm_insn ("lwi\t%0, [%2 + (%3)]", otherops); -- output_asm_insn ("lwi\t%1, [%2 + (%4)]", otherops); -- } -- else -- { -- output_asm_insn ("lwi\t%1, [%2 + (%4)]", otherops); -- output_asm_insn ("lwi\t%0,[ %2 + (%3)]", otherops); -- } -- } -- else -- { -- /* (reg) <- (mem (symbol_ref ...)) -- (reg) <- (mem (const ...)) */ -- output_asm_insn ("lwi.gp\t%0, [ + %2]", otherops); -- output_asm_insn ("lwi.gp\t%1, [ + %2 + 4]", otherops); -- } -- -- /* We have already used output_asm_insn() by ourself, -- so return an empty string. */ -- return ""; -- -+ /* The memory format is (mem (reg)), -+ we can generate 'lmw.bi' instruction. */ -+ return nds32_output_double (operands, true); - case 3: -- /* Refer to nds32_legitimate_address_p() in nds32.c, -- we only allow "reg", "symbol_ref", "const", and "reg + const_int" -- as address rtx for DImode/DFmode memory access. */ -- addr = XEXP (operands[0], 0); -- -- otherops[0] = gen_rtx_REG (SImode, REGNO (operands[1])); -- otherops[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); -- otherops[2] = addr; -- -- if (REG_P (addr)) -- { -- /* (mem (reg)) <- (reg) */ -- output_asm_insn ("smw.bi\t%0, [%2], %1, 0", otherops); -- } -- else if (GET_CODE (addr) == PLUS) -- { -- /* (mem (plus (reg) (const_int))) <- (reg) */ -- rtx op0 = XEXP (addr, 0); -- rtx op1 = XEXP (addr, 1); -- -- if (REG_P (op0)) -- { -- otherops[2] = op0; -- otherops[3] = op1; -- otherops[4] = gen_int_mode (INTVAL (op1) + 4, SImode); -- } -- else -- { -- otherops[2] = op1; -- otherops[3] = op0; -- otherops[4] = gen_int_mode (INTVAL (op0) + 4, SImode); -- } -- -- /* To avoid base overwrite when REGNO(%0) == REGNO(%2). */ -- if (REGNO (otherops[0]) != REGNO (otherops[2])) -- { -- output_asm_insn ("swi\t%0, [%2 + (%3)]", otherops); -- output_asm_insn ("swi\t%1, [%2 + (%4)]", otherops); -- } -- else -- { -- output_asm_insn ("swi\t%1, [%2 + (%4)]", otherops); -- output_asm_insn ("swi\t%0, [%2 + (%3)]", otherops); -- } -- } -- else -- { -- /* (mem (symbol_ref ...)) <- (reg) -- (mem (const ...)) <- (reg) */ -- output_asm_insn ("swi.gp\t%0, [ + %2]", otherops); -- output_asm_insn ("swi.gp\t%1, [ + %2 + 4]", otherops); -- } -- -- /* We have already used output_asm_insn() by ourself, -- so return an empty string. */ -- return ""; -- -+ /* 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" "move,move,move,move") -- (set_attr "length" " 4, 16, 8, 8")]) -+ [(set_attr "type" "alu,alu,load,load,store,store,fload,fstore,fcpy,fmfdr,fmtdr") -+ (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")]) -+ -+;; 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))] - { -@@ -207,7 +159,12 @@ - /* Actually we would like to create move behavior by ourself. - So that movsi expander could have chance to split large constant. */ - emit_move_insn (operands[2], operands[3]); -- emit_move_insn (operands[4], operands[5]); -+ -+ unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode); -+ if ((UINTVAL (operands[3]) & mask) == (UINTVAL (operands[5]) & mask)) -+ emit_move_insn (operands[4], operands[2]); -+ else -+ emit_move_insn (operands[4], operands[5]); - DONE; - }) - -@@ -217,7 +174,9 @@ - [(set (match_operand:DIDF 0 "register_operand" "") - (match_operand:DIDF 1 "register_operand" ""))] - "reload_completed -- && (TARGET_ISA_V2 || !TARGET_16_BIT)" -+ && (TARGET_ISA_V2 || !TARGET_16_BIT) -+ && NDS32_IS_GPR_REGNUM (REGNO (operands[0])) -+ && NDS32_IS_GPR_REGNUM (REGNO (operands[1]))" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 2) (match_dup 3))] - { -@@ -239,6 +198,28 @@ - } - }) - -+(define_split -+ [(set (match_operand:DIDF 0 "nds32_general_register_operand" "") -+ (match_operand:DIDF 1 "memory_operand" ""))] -+ "reload_completed -+ && nds32_split_double_word_load_store_p (operands, true)" -+ [(set (match_dup 2) (match_dup 3)) -+ (set (match_dup 4) (match_dup 5))] -+{ -+ nds32_spilt_doubleword (operands, true); -+}) -+ -+(define_split -+ [(set (match_operand:DIDF 0 "memory_operand" "") -+ (match_operand:DIDF 1 "nds32_general_register_operand" ""))] -+ "reload_completed -+ && nds32_split_double_word_load_store_p (operands, false)" -+ [(set (match_dup 2) (match_dup 3)) -+ (set (match_dup 4) (match_dup 5))] -+{ -+ nds32_spilt_doubleword (operands, false); -+}) -+ - ;; ------------------------------------------------------------- - ;; Boolean DImode instructions. - ;; ------------------------------------------------------------- -diff --git a/gcc/config/nds32/nds32-dspext.md b/gcc/config/nds32/nds32-dspext.md -new file mode 100644 -index 0000000..6ec2137 ---- /dev/null -+++ b/gcc/config/nds32/nds32-dspext.md -@@ -0,0 +1,5280 @@ -+;; Machine description of Andes NDS32 cpu for GNU compiler -+;; Copyright (C) 2012-2016 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, A") -+ (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, r"))] -+ "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); -+ case 22: -+ return "mtusr\t%1, %0"; -+ 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,alu") -+ (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, 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, v1")]) -+ -+(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_se (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_se (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_se (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_se (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:HI 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-e8.md b/gcc/config/nds32/nds32-e8.md -new file mode 100644 -index 0000000..1f24b5c ---- /dev/null -+++ b/gcc/config/nds32/nds32-e8.md -@@ -0,0 +1,329 @@ -+;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler -+;; Copyright (C) 2012-2016 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 E8 pipeline settings. -+;; ------------------------------------------------------------------------ -+ -+(define_automaton "nds32_e8_machine") -+ -+;; ------------------------------------------------------------------------ -+;; Pipeline Stages -+;; ------------------------------------------------------------------------ -+;; IF - Instruction Fetch -+;; II - Instruction Issue / Address Generation -+;; EX - Instruction Execution -+;; EXD - Psuedo Stage / Load Data Completion -+ -+(define_cpu_unit "e8_ii" "nds32_e8_machine") -+(define_cpu_unit "e8_ex" "nds32_e8_machine") -+ -+(define_insn_reservation "nds_e8_unknown" 1 -+ (and (eq_attr "type" "unknown") -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, e8_ex") -+ -+(define_insn_reservation "nds_e8_misc" 1 -+ (and (eq_attr "type" "misc") -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, e8_ex") -+ -+(define_insn_reservation "nds_e8_alu" 1 -+ (and (eq_attr "type" "alu") -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, e8_ex") -+ -+(define_insn_reservation "nds_e8_load" 1 -+ (and (match_test "nds32::load_single_p (insn)") -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, e8_ex") -+ -+(define_insn_reservation "nds_e8_store" 1 -+ (and (match_test "nds32::store_single_p (insn)") -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, e8_ex") -+ -+(define_insn_reservation "nds_e8_load_multiple_1" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, e8_ex") -+ -+(define_insn_reservation "nds_e8_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" "e8")) -+ "e8_ii, e8_ii+e8_ex, e8_ex") -+ -+(define_insn_reservation "nds_e8_load_multiple_3" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*2, e8_ex") -+ -+(define_insn_reservation "nds_e8_load_multiple_4" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*3, e8_ex") -+ -+(define_insn_reservation "nds_e8_load_multiple_5" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*4, e8_ex") -+ -+(define_insn_reservation "nds_e8_load_multiple_6" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "6")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*5, e8_ex") -+ -+(define_insn_reservation "nds_e8_load_multiple_7" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*6, e8_ex") -+ -+(define_insn_reservation "nds_e8_load_multiple_8" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*7, e8_ex") -+ -+(define_insn_reservation "nds_e8_load_multiple_12" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*11, e8_ex") -+ -+(define_insn_reservation "nds_e8_store_multiple_1" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, e8_ex") -+ -+(define_insn_reservation "nds_e8_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" "e8")) -+ "e8_ii, e8_ii+e8_ex, e8_ex") -+ -+(define_insn_reservation "nds_e8_store_multiple_3" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*2, e8_ex") -+ -+(define_insn_reservation "nds_e8_store_multiple_4" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*3, e8_ex") -+ -+(define_insn_reservation "nds_e8_store_multiple_5" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*4, e8_ex") -+ -+(define_insn_reservation "nds_e8_store_multiple_6" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "6")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*5, e8_ex") -+ -+(define_insn_reservation "nds_e8_store_multiple_7" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*6, e8_ex") -+ -+(define_insn_reservation "nds_e8_store_multiple_8" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*7, e8_ex") -+ -+(define_insn_reservation "nds_e8_store_multiple_12" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*11, e8_ex") -+ -+(define_insn_reservation "nds_e8_mul_fast" 1 -+ (and (match_test "nds32_mul_config != MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "e8"))) -+ "e8_ii, e8_ex") -+ -+(define_insn_reservation "nds_e8_mul_slow" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "e8"))) -+ "e8_ii, e8_ex*16") -+ -+(define_insn_reservation "nds_e8_mac_fast" 1 -+ (and (match_test "nds32_mul_config != MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "e8"))) -+ "e8_ii, e8_ii+e8_ex, e8_ex") -+ -+(define_insn_reservation "nds_e8_mac_slow" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "e8"))) -+ "e8_ii, (e8_ii+e8_ex)*16, e8_ex") -+ -+(define_insn_reservation "nds_e8_div" 1 -+ (and (eq_attr "type" "div") -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, (e8_ii+e8_ex)*36, e8_ex") -+ -+(define_insn_reservation "nds_e8_branch" 1 -+ (and (eq_attr "type" "branch") -+ (eq_attr "pipeline_model" "e8")) -+ "e8_ii, e8_ex") -+ -+;; ------------------------------------------------------------------------ -+;; Comment Notations and Bypass Rules -+;; ------------------------------------------------------------------------ -+;; Producers (LHS) -+;; LD -+;; Load data from the memory and produce the loaded data. The result is -+;; ready at EXD. -+;; 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 EXD. -+;; ADDR_OUT -+;; Most load/store instructions can produce an address output if updating -+;; the base register is required. The result is ready at EX, which is -+;; produced by ALU. -+;; ALU, MOVD44, MUL, MAC -+;; The result is ready at EX. -+;; DIV_Rs -+;; A division instruction saves the quotient result to Rt and saves the -+;; remainder result to Rs. The instruction is separated into two micro- -+;; operations. The first micro-operation writes to Rt, and the seconde -+;; one writes to Rs. Each of the results is ready at EX. -+;; -+;; Consumers (RHS) -+;; ALU, MUL, DIV -+;; Require operands at EX. -+;; ADDR_IN_MOP(N) -+;; N denotes the address input is required by the N-th micro-operation. -+;; Such operand is required at II. -+;; ST -+;; A store instruction requires its data at EX. -+;; SMW(N, M) -+;; There are N micro-operations within an instruction that stores multiple -+;; words. Each M-th micro-operation requires its data at EX. -+;; BR_COND -+;; If a branch instruction is conditional, its input data is required at EX. -+ -+;; LD -> ADDR_IN_MOP(1) -+(define_bypass 2 -+ "nds_e8_load" -+ "nds_e8_branch,\ -+ nds_e8_load, nds_e8_store,\ -+ nds_e8_load_multiple_1,nds_e8_load_multiple_2, nds_e8_load_multiple_3,\ -+ nds_e8_load_multiple_4,nds_e8_load_multiple_5, nds_e8_load_multiple_6,\ -+ nds_e8_load_multiple_7,nds_e8_load_multiple_8, nds_e8_load_multiple_12,\ -+ nds_e8_store_multiple_1,nds_e8_store_multiple_2, nds_e8_store_multiple_3,\ -+ nds_e8_store_multiple_4,nds_e8_store_multiple_5, nds_e8_store_multiple_6,\ -+ nds_e8_store_multiple_7,nds_e8_store_multiple_8, nds_e8_store_multiple_12" -+ "nds32_e8_load_to_ii_p" -+) -+ -+;; LD -> ALU, MUL, MAC, DIV, BR_COND, ST, SMW(N, 1) -+(define_bypass 2 -+ "nds_e8_load" -+ "nds_e8_alu, -+ nds_e8_mul_fast, nds_e8_mul_slow,\ -+ nds_e8_mac_fast, nds_e8_mac_slow,\ -+ nds_e8_div,\ -+ nds_e8_branch,\ -+ nds_e8_store,\ -+ nds_e8_store_multiple_1,nds_e8_store_multiple_2, nds_e8_store_multiple_3,\ -+ nds_e8_store_multiple_4,nds_e8_store_multiple_5, nds_e8_store_multiple_6,\ -+ nds_e8_store_multiple_7,nds_e8_store_multiple_8, nds_e8_store_multiple_12" -+ "nds32_e8_load_to_ex_p" -+) -+ -+;; ALU, MOVD44, MUL, MAC, DIV_Rs, LD_bi, ADDR_OUT -> ADDR_IN_MOP(1) -+(define_bypass 2 -+ "nds_e8_alu, -+ nds_e8_mul_fast, nds_e8_mul_slow,\ -+ nds_e8_mac_fast, nds_e8_mac_slow,\ -+ nds_e8_div,\ -+ nds_e8_load, nds_e8_store,\ -+ nds_e8_load_multiple_1,nds_e8_load_multiple_2, nds_e8_load_multiple_3,\ -+ nds_e8_load_multiple_4,nds_e8_load_multiple_5, nds_e8_load_multiple_6,\ -+ nds_e8_load_multiple_7,nds_e8_load_multiple_8, nds_e8_load_multiple_12,\ -+ nds_e8_store_multiple_1,nds_e8_store_multiple_2, nds_e8_store_multiple_3,\ -+ nds_e8_store_multiple_4,nds_e8_store_multiple_5, nds_e8_store_multiple_6,\ -+ nds_e8_store_multiple_7,nds_e8_store_multiple_8, nds_e8_store_multiple_12" -+ "nds_e8_branch,\ -+ nds_e8_load, nds_e8_store,\ -+ nds_e8_load_multiple_1,nds_e8_load_multiple_2, nds_e8_load_multiple_3,\ -+ nds_e8_load_multiple_4,nds_e8_load_multiple_5, nds_e8_load_multiple_6,\ -+ nds_e8_load_multiple_7,nds_e8_load_multiple_8, nds_e8_load_multiple_12,\ -+ nds_e8_store_multiple_1,nds_e8_store_multiple_2, nds_e8_store_multiple_3,\ -+ nds_e8_store_multiple_4,nds_e8_store_multiple_5, nds_e8_store_multiple_6,\ -+ nds_e8_store_multiple_7,nds_e8_store_multiple_8, nds_e8_store_multiple_12" -+ "nds32_e8_ex_to_ii_p" -+) -+ -+;; LMW(N, N) -> ADDR_IN_MOP(1) -+(define_bypass 2 -+ "nds_e8_load_multiple_1,nds_e8_load_multiple_2, nds_e8_load_multiple_3,\ -+ nds_e8_load_multiple_4,nds_e8_load_multiple_5, nds_e8_load_multiple_6,\ -+ nds_e8_load_multiple_7,nds_e8_load_multiple_8, nds_e8_load_multiple_12" -+ "nds_e8_branch,\ -+ nds_e8_load, nds_e8_store,\ -+ nds_e8_load_multiple_1,nds_e8_load_multiple_2, nds_e8_load_multiple_3,\ -+ nds_e8_load_multiple_4,nds_e8_load_multiple_5, nds_e8_load_multiple_6,\ -+ nds_e8_load_multiple_7,nds_e8_load_multiple_8, nds_e8_load_multiple_12,\ -+ nds_e8_store_multiple_1,nds_e8_store_multiple_2, nds_e8_store_multiple_3,\ -+ nds_e8_store_multiple_4,nds_e8_store_multiple_5, nds_e8_store_multiple_6,\ -+ nds_e8_store_multiple_7,nds_e8_store_multiple_8, nds_e8_store_multiple_12" -+ "nds32_e8_last_load_to_ii_p" -+) -+ -+;; LMW(N, N) -> ALU, MUL, MAC, DIV, BR_COND, ST, SMW(N, 1) -+(define_bypass 2 -+ "nds_e8_load_multiple_1,nds_e8_load_multiple_2, nds_e8_load_multiple_3,\ -+ nds_e8_load_multiple_4,nds_e8_load_multiple_5, nds_e8_load_multiple_6,\ -+ nds_e8_load_multiple_7,nds_e8_load_multiple_8, nds_e8_load_multiple_12" -+ "nds_e8_alu, -+ nds_e8_mul_fast, nds_e8_mul_slow,\ -+ nds_e8_mac_fast, nds_e8_mac_slow,\ -+ nds_e8_div,\ -+ nds_e8_branch,\ -+ nds_e8_store,\ -+ nds_e8_store_multiple_1,nds_e8_store_multiple_2, nds_e8_store_multiple_3,\ -+ nds_e8_store_multiple_4,nds_e8_store_multiple_5, nds_e8_store_multiple_6,\ -+ nds_e8_store_multiple_7,nds_e8_store_multiple_8, nds_e8_store_multiple_12" -+ "nds32_e8_last_load_to_ex_p" -+) -diff --git a/gcc/config/nds32/nds32-elf.opt b/gcc/config/nds32/nds32-elf.opt -new file mode 100644 -index 0000000..afe6aad ---- /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 f8b2738..6525915 100644 ---- a/gcc/config/nds32/nds32-fp-as-gp.c -+++ b/gcc/config/nds32/nds32-fp-as-gp.c -@@ -1,4 +1,4 @@ --/* The fp-as-gp pass of Andes NDS32 cpu for GNU compiler -+/* fp-as-gp pass of Andes NDS32 cpu for GNU compiler - Copyright (C) 2012-2016 Free Software Foundation, Inc. - Contributed by Andes Technology Corporation. - -@@ -24,19 +24,280 @@ - #include "system.h" - #include "coretypes.h" - #include "backend.h" -+#include "tree.h" -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" -+#include "ira.h" -+#include "ira-int.h" -+#include "tree-pass.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 -new file mode 100644 -index 0000000..11eabd5 ---- /dev/null -+++ b/gcc/config/nds32/nds32-fpu.md -@@ -0,0 +1,503 @@ -+;; Machine description of Andes NDS32 cpu for GNU compiler -+;; Copyright (C) 2012-2016 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 -+;; . -+ -+;;SFmode moves -+ -+(define_expand "movsf" -+ [(set (match_operand:SF 0 "general_operand" "") -+ (match_operand:SF 1 "general_operand" ""))] -+ "" -+{ -+ /* Need to force register if mem <- !reg. */ -+ if (MEM_P (operands[0]) && !REG_P (operands[1])) -+ operands[1] = force_reg (SFmode, operands[1]); -+ if (CONST_DOUBLE_P (operands[1]) -+ && !satisfies_constraint_Cs20 (operands[1])) -+ { -+ const REAL_VALUE_TYPE *r; -+ unsigned long l; -+ -+ r = CONST_DOUBLE_REAL_VALUE (operands[1]); -+ REAL_VALUE_TO_TARGET_SINGLE (*r, l); -+ -+ emit_move_insn (operands[0], gen_rtx_HIGH (SFmode, operands[1])); -+ -+ if ((l & 0xFFF) != 0) -+ emit_insn (gen_movsf_lo (operands[0], operands[0], operands[1])); -+ DONE; -+ } -+}) -+ -+(define_insn "movsf_lo" -+ [(set (match_operand:SF 0 "register_operand" "=r") -+ (lo_sum:SF (match_operand:SF 1 "register_operand" "r") -+ (match_operand:SF 2 "immediate_operand" "i")))] -+ "" -+ "ori\t%0, %1, lo12(%2)" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*movsf" -+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r, r, U45, U33, U37, U45, m, l, l, l, d, r, f, *f, *r, f, Q, r, r, r") -+ (match_operand:SF 1 "general_operand" " r, r, l, l, l, d, r, U45, U33, U37, U45, m, f, *r, *f, Q, f,Cs05,Cs20, Chig"))] -+ "(register_operand(operands[0], SFmode) -+ || register_operand(operands[1], SFmode))" -+{ -+ 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, 4); -+ case 6: -+ return nds32_output_32bit_store (operands, 4); -+ case 7: -+ case 8: -+ case 9: -+ case 10: -+ return nds32_output_16bit_load (operands, 4); -+ case 11: -+ return nds32_output_32bit_load (operands, 4); -+ case 12: -+ if (TARGET_FPU_SINGLE) -+ return "fcpyss\t%0, %1, %1"; -+ else -+ return "#"; -+ case 13: -+ return "fmtsr\t%1, %0"; -+ case 14: -+ return "fmfsr\t%0, %1"; -+ case 15: -+ return nds32_output_float_load (operands); -+ case 16: -+ return nds32_output_float_store (operands); -+ case 17: -+ return "movi55\t%0, %1"; -+ case 18: -+ return "movi\t%0, %1"; -+ case 19: -+ return "sethi\t%0, %1"; -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "alu,alu,store,store,store,store,store,load,load,load,load,load,fcpy,fmtsr,fmfsr,fload,fstore,alu,alu,alu") -+ (set_attr "length" " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 2, 4, 4") -+ (set_attr "feature" " v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu, v1, v1, v1")]) -+ -+;; Conditional Move Instructions -+ -+(define_expand "movcc" -+ [(set (match_operand:ANYF 0 "register_operand" "") -+ (if_then_else:ANYF (match_operand 1 "nds32_float_comparison_operator" "") -+ (match_operand:ANYF 2 "register_operand" "") -+ (match_operand:ANYF 3 "register_operand" "")))] -+ "" -+{ -+ if (nds32_cond_move_p (operands[1])) -+ { -+ /* Operands[1] condition code is UNORDERED or ORDERED, and -+ sub-operands[1] MODE isn't SFmode or SFmode, return FAIL -+ for gcc, because we don't using slt compare instruction -+ to generate UNORDERED and ORDERED condition. */ -+ FAIL; -+ } -+ else -+ nds32_expand_float_movcc (operands); -+}) -+ -+(define_insn "fcmov_eq" -+ [(set (match_operand:ANYF 0 "register_operand" "=f, f") -+ (if_then_else:ANYF (eq (match_operand:SI 1 "register_operand" "f, f") -+ (const_int 0)) -+ (match_operand:ANYF 2 "register_operand" "f, 0") -+ (match_operand:ANYF 3 "register_operand" "0, f")))] -+ "" -+ "@ -+ fcmovz\t%0,%2,%1 -+ fcmovn\t%0,%3,%1" -+ [(set_attr "type" "fcmov") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "fcmov_ne" -+ [(set (match_operand:ANYF 0 "register_operand" "=f, f") -+ (if_then_else:ANYF (ne (match_operand:SI 1 "register_operand" "f, f") -+ (const_int 0)) -+ (match_operand:ANYF 2 "register_operand" "f, 0") -+ (match_operand:ANYF 3 "register_operand" "0, f")))] -+ "" -+ "@ -+ fcmovn\t%0,%2,%1 -+ fcmovz\t%0,%3,%1" -+ [(set_attr "type" "fcmov") -+ (set_attr "length" "4")] -+) -+ -+;; Arithmetic instructions. -+ -+(define_insn "add3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (plus:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "" -+ "fadd\t %0, %1, %2" -+ [(set_attr "type" "falu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "sub3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (minus:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "" -+ "fsub\t %0, %1, %2" -+ [(set_attr "type" "falu") -+ (set_attr "length" "4")] -+) -+ -+;; Multiplication insns. -+ -+(define_insn "mul3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "" -+ "fmul\t %0, %1, %2" -+ [(set_attr "type" "fmul") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "fma4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (fma:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f") -+ (match_operand:ANYF 3 "register_operand" "0")))] -+ "TARGET_EXT_FPU_FMA" -+ "fmadd\t%0, %1, %2" -+ [(set_attr "type" "fmac") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "fnma4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) -+ (match_operand:ANYF 2 "register_operand" "f") -+ (match_operand:ANYF 3 "register_operand" "0")))] -+ "TARGET_EXT_FPU_FMA" -+ "fmsub\t%0, %1, %2" -+ [(set_attr "type" "fmac") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "fms4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (fma:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f") -+ (neg:ANYF (match_operand:ANYF 3 "register_operand" "0"))))] -+ "TARGET_EXT_FPU_FMA" -+ "fnmsub\t%0, %1, %2" -+ [(set_attr "type" "fmac") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "fnms4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) -+ (match_operand:ANYF 2 "register_operand" "f") -+ (neg:ANYF (match_operand:ANYF 3 "register_operand" "0"))))] -+ "TARGET_EXT_FPU_FMA" -+ "fnmadd\t%0, %1, %2" -+ [(set_attr "type" "fmac") -+ (set_attr "length" "4")] -+) -+ -+;; Div Instructions. -+ -+(define_insn "div3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (div:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "" -+ "fdiv\t %0, %1, %2" -+ [(set_attr "type" "fdiv") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "sqrt2" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))] -+ "" -+ "fsqrt\t %0, %1" -+ [(set_attr "type" "fsqrt") -+ (set_attr "length" "4")] -+) -+ -+;; Conditional Branch patterns -+ -+(define_expand "cstore4" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operator:SI 1 "nds32_float_comparison_operator" -+ [(match_operand:ANYF 2 "register_operand" "") -+ (match_operand:ANYF 3 "register_operand" "")]))] -+ "" -+{ -+ nds32_expand_float_cstore (operands); -+ DONE; -+}) -+ -+(define_expand "cbranch4" -+ [(set (pc) -+ (if_then_else (match_operator 0 "nds32_float_comparison_operator" -+ [(match_operand:ANYF 1 "register_operand" "") -+ (match_operand:ANYF 2 "register_operand" "")]) -+ (label_ref (match_operand 3 "" "")) -+ (pc)))] -+ "" -+{ -+ nds32_expand_float_cbranch (operands); -+ DONE; -+}) -+ -+;; Copysign Instructions. -+ -+(define_insn "copysignsf3" -+ [(set (match_operand:SF 0 "register_operand" "=f") -+ (unspec:SF [(match_operand:SF 1 "register_operand" "f") -+ (match_operand:SF 2 "register_operand" "f")] -+ UNSPEC_COPYSIGN))] -+ "TARGET_FPU_SINGLE" -+ "fcpyss\t%0,%1,%2" -+ [(set_attr "type" "fcpy") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "copysigndf3" -+ [(set (match_operand:DF 0 "register_operand" "=f") -+ (unspec:DF [(match_operand:DF 1 "register_operand" "f") -+ (match_operand:DF 2 "register_operand" "f")] -+ UNSPEC_COPYSIGN))] -+ "TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE" -+ "fcpysd\t%0,%1,%2" -+ [(set_attr "type" "fcpy") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*ncopysign3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (neg:ANYF (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")] -+ UNSPEC_COPYSIGN)))] -+ "" -+ "fcpyns\t%0,%1,%2" -+ [(set_attr "type" "fcpy") -+ (set_attr "length" "4")] -+) -+ -+;; Absolute Instructions -+ -+(define_insn "abssf2" -+ [(set (match_operand:SF 0 "register_operand" "=f, r") -+ (abs:SF (match_operand:SF 1 "register_operand" "f, r")))] -+ "TARGET_FPU_SINGLE || TARGET_EXT_PERF" -+ "@ -+ fabss\t%0, %1 -+ bclr\t%0, %1, 31" -+ [(set_attr "type" "fabs,alu") -+ (set_attr "length" "4") -+ (set_attr "feature" "fpu,pe1")] -+) -+ -+(define_insn "absdf2" -+ [(set (match_operand:DF 0 "register_operand" "=f") -+ (abs:DF (match_operand:DF 1 "register_operand" "f")))] -+ "TARGET_FPU_DOUBLE" -+ "fabsd\t%0, %1" -+ [(set_attr "type" "fabs") -+ (set_attr "length" "4")] -+) -+ -+;; Negation Instructions -+ -+(define_insn "*negsf2" -+ [(set (match_operand:SF 0 "register_operand" "=f, r") -+ (neg:SF (match_operand:SF 1 "register_operand" "f, r")))] -+ "TARGET_FPU_SINGLE || TARGET_EXT_PERF" -+ "@ -+ fcpynss\t%0, %1, %1 -+ btgl\t%0, %1, 31" -+ [(set_attr "type" "fcpy,alu") -+ (set_attr "length" "4") -+ (set_attr "feature" "fpu,pe1")] -+) -+ -+(define_insn "*negdf2" -+ [(set (match_operand:DF 0 "register_operand" "=f") -+ (neg:DF (match_operand:DF 1 "register_operand" "f")))] -+ "TARGET_FPU_DOUBLE" -+ "fcpynsd\t%0, %1, %1" -+ [(set_attr "type" "fcpy") -+ (set_attr "length" "4")] -+) -+ -+;; Data Format Conversion Instructions -+ -+(define_insn "floatunssi2" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (unsigned_float:ANYF (match_operand:SI 1 "register_operand" "f")))] -+ "" -+ "fui2\t %0, %1" -+ [(set_attr "type" "falu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "floatsi2" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (float:ANYF (match_operand:SI 1 "register_operand" "f")))] -+ "" -+ "fsi2\t %0, %1" -+ [(set_attr "type" "falu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "fixuns_truncsi2" -+ [(set (match_operand:SI 0 "register_operand" "=f") -+ (unsigned_fix:SI (fix:ANYF (match_operand:ANYF 1 "register_operand" "f"))))] -+ "" -+ "f2ui.z\t %0, %1" -+ [(set_attr "type" "falu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "fix_truncsi2" -+ [(set (match_operand:SI 0 "register_operand" "=f") -+ (fix:SI (fix:ANYF (match_operand:ANYF 1 "register_operand" "f"))))] -+ "" -+ "f2si.z\t %0, %1" -+ [(set_attr "type" "falu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "extendsfdf2" -+ [(set (match_operand:DF 0 "register_operand" "=f") -+ (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] -+ "TARGET_FPU_SINGLE && TARGET_FPU_DOUBLE" -+ "fs2d\t%0, %1" -+ [(set_attr "type" "falu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "truncdfsf2" -+ [(set (match_operand:SF 0 "register_operand" "=f") -+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] -+ "TARGET_FPU_SINGLE && TARGET_FPU_DOUBLE" -+ "fd2s\t%0, %1" -+ [(set_attr "type" "falu") -+ (set_attr "length" "4")] -+) -+ -+;; Compare Instructions -+ -+(define_insn "cmp_eq" -+ [(set (match_operand:SI 0 "register_operand" "=f") -+ (eq:SI (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "" -+ { -+ if (NDS32_EXT_FPU_DOT_E) -+ return "fcmpeq.e %0, %1, %2"; -+ else -+ return "fcmpeq\t%0, %1, %2"; -+ } -+ [(set_attr "type" "fcmp") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "cmp_lt" -+ [(set (match_operand:SI 0 "register_operand" "=f") -+ (lt:SI (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "" -+{ -+ if (NDS32_EXT_FPU_DOT_E) -+ return "fcmplt.e %0, %1, %2"; -+ else -+ return "fcmplt\t%0, %1, %2"; -+} -+ [(set_attr "type" "fcmp") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "cmp_le" -+ [(set (match_operand:SI 0 "register_operand" "=f") -+ (le:SI (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "" -+{ -+ if (NDS32_EXT_FPU_DOT_E) -+ return "fcmple.e %0, %1, %2"; -+ else -+ return "fcmple\t%0, %1, %2"; -+} -+ [(set_attr "type" "fcmp") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "cmp_un" -+ [(set (match_operand:SI 0 "register_operand" "=f") -+ (unordered:SI (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "" -+{ -+ if (NDS32_EXT_FPU_DOT_E) -+ return "fcmpun.e %0, %1, %2"; -+ else -+ return "fcmpun\t%0, %1, %2"; -+} -+ [(set_attr "type" "fcmp") -+ (set_attr "length" "4")] -+) -+ -+(define_split -+ [(set (match_operand:SF 0 "register_operand" "") -+ (match_operand:SF 1 "register_operand" ""))] -+ "!TARGET_FPU_SINGLE -+ && NDS32_IS_FPR_REGNUM (REGNO (operands[0])) -+ && NDS32_IS_FPR_REGNUM (REGNO (operands[1]))" -+ [(set (match_dup 2) (match_dup 1)) -+ (set (match_dup 0) (match_dup 2))] -+{ -+ operands[2] = gen_rtx_REG (SFmode, TA_REGNUM); -+}) -+ -+(define_split -+ [(set (match_operand:SF 0 "register_operand" "") -+ (match_operand:SF 1 "const_double_operand" ""))] -+ "!satisfies_constraint_Cs20 (operands[1]) -+ && !satisfies_constraint_Chig (operands[1])" -+ [(set (match_dup 0) (high:SF (match_dup 1))) -+ (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))]) -+;; ---------------------------------------------------------------------------- -diff --git a/gcc/config/nds32/nds32-gcse.c b/gcc/config/nds32/nds32-gcse.c -new file mode 100644 -index 0000000..301981d ---- /dev/null -+++ b/gcc/config/nds32/nds32-gcse.c -@@ -0,0 +1,670 @@ -+/* Global CSE pass of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+/* ------------------------------------------------------------------------ */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "backend.h" -+#include "tree.h" -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" -+#include "cpplib.h" -+#include "params.h" -+#include "tree-pass.h" -+#include "dbgcnt.h" -+#include "df.h" -+#include "reload.h" -+ -+/* ------------------------------------------------------------------------ */ -+ -+struct expr -+{ -+ /* The expression. */ -+ rtx expr; -+ -+ /* The same hash for this entry. */ -+ hashval_t hash; -+ -+ struct occr *antic_occr; -+ /* The number of antic_occr. */ -+ unsigned int count; -+}; -+ -+struct occr -+{ -+ /* Next occurrence of this expression. */ -+ struct occr *next; -+ /* The insn that computes the expression. */ -+ rtx_insn *insn; -+ /* Nonzero if this [anticipatable] occurrence has been deleted. */ -+ char deleted_p; -+}; -+ -+struct reg_avail_info -+{ -+ basic_block last_bb; -+ int first_set; -+ int first_use; -+}; -+ -+/* Hashtable helpers. */ -+ -+struct expr_hasher : nofree_ptr_hash -+{ -+ static inline hashval_t hash (const expr *); -+ static inline bool equal (const expr *, const expr *); -+}; -+ -+/* Callback for hashtab. -+ Return the hash value for expression EXP. We don't actually hash -+ here, we just return the cached hash value. */ -+ -+inline hashval_t -+expr_hasher::hash (const expr *exp) -+{ -+ return exp->hash; -+} -+ -+/* Callback for hashtab. -+ Return nonzero if exp1 is equivalent to exp2. */ -+ -+inline bool -+expr_hasher::equal (const expr *exp1, const expr *exp2) -+{ -+ int equiv_p = exp_equiv_p (exp1->expr, exp2->expr, 0, true); -+ -+ gcc_assert (!equiv_p || exp1->hash == exp2->hash); -+ return equiv_p; -+} -+ -+static hashval_t -+hash_expr (rtx x, int *do_not_record_p) -+{ -+ *do_not_record_p = 0; -+ return hash_rtx (x, GET_MODE (x), do_not_record_p, -+ NULL, /*have_reg_qty=*/false); -+} -+ -+ -+/* Helpers for memory allocation/freeing. */ -+static void alloc_mem (void); -+static void free_mem (void); -+static void compute_hash_table (void); -+/* Scan the pattern of INSN and add an entry to the hash TABLE. -+ After reload we are interested in loads/stores only. */ -+static void hash_scan_set (rtx_insn *); -+static void insert_expr_in_table (rtx, rtx_insn *); -+static void dump_hash_table (FILE *); -+ -+static struct obstack expr_obstack; -+/* The table itself. */ -+static hash_table *expr_table; -+static struct reg_avail_info *reg_avail_info; -+static sbitmap *hoist_vbein; -+static sbitmap *hoist_vbeout; -+ -+/* Allocate memory for the CUID mapping array and register/memory -+ tracking tables. */ -+ -+static void -+alloc_mem (void) -+{ -+ /* Allocate the available expressions hash table. We don't want to -+ make the hash table too small, but unnecessarily making it too large -+ also doesn't help. The i/4 is a gcse.c relic, and seems like a -+ reasonable choice. */ -+ expr_table = new hash_table (MAX (get_max_insn_count () / 4, -+ 13)); -+ -+ /* We allocate everything on obstacks because we often can roll back -+ the whole obstack to some point. Freeing obstacks is very fast. */ -+ gcc_obstack_init (&expr_obstack); -+} -+ -+/* Free memory allocated by alloc_mem. */ -+ -+static void -+free_mem (void) -+{ -+ delete expr_table; -+ expr_table = NULL; -+ -+ obstack_free (&expr_obstack, NULL); -+} -+ -+ -+/* Dump all expressions and occurrences that are currently in the -+ expression hash table to FILE. */ -+ -+/* This helper is called via htab_traverse. */ -+int -+nds32_dump_expr_hash_table_entry (expr **slot, FILE *file) -+{ -+ struct expr *exprs = *slot; -+ struct occr *occr; -+ -+ fprintf (file, "expr: "); -+ print_rtl (file, exprs->expr); -+ fprintf (file,"\nhashcode: %u\n", exprs->hash); -+ fprintf (file,"list of occurrences:\n"); -+ occr = exprs->antic_occr; -+ while (occr) -+ { -+ rtx_insn *insn = occr->insn; -+ print_rtl_single (file, insn); -+ fprintf (file, "\n"); -+ occr = occr->next; -+ } -+ fprintf (file, "\n"); -+ return 1; -+} -+ -+static void -+dump_hash_table (FILE *file) -+{ -+ fprintf (file, "\n\nexpression hash table\n"); -+ fprintf (file, "size %ld, %ld elements, %f collision/search ratio\n", -+ (long) expr_table->size (), -+ (long) expr_table->elements (), -+ expr_table->collisions ()); -+ if (expr_table->elements () > 0) -+ { -+ fprintf (file, "\n\ntable entries:\n"); -+ expr_table->traverse (file); -+ } -+ fprintf (file, "\n"); -+} -+ -+/* Insert expression X in INSN in the hash TABLE. -+ If it is already present, record it as the last occurrence in INSN's -+ basic block. */ -+ -+static void -+insert_expr_in_table (rtx x, rtx_insn *insn) -+{ -+ int do_not_record_p; -+ hashval_t hash; -+ struct expr *cur_expr, **slot; -+ struct occr *antic_occr, *last_occr = NULL; -+ -+ hash = hash_expr (x, &do_not_record_p); -+ -+ /* Do not insert expression in the table if it contains volatile operands, -+ or if hash_expr determines the expression is something we don't want -+ to or can't handle. */ -+ if (do_not_record_p) -+ return; -+ -+ /* We anticipate that redundant expressions are rare, so for convenience -+ allocate a new hash table element here already and set its fields. -+ If we don't do this, we need a hack with a static struct expr. Anyway, -+ obstack_free is really fast and one more obstack_alloc doesn't hurt if -+ we're going to see more expressions later on. */ -+ cur_expr = (struct expr *) obstack_alloc (&expr_obstack, -+ sizeof (struct expr)); -+ cur_expr->expr = x; -+ cur_expr->hash = hash; -+ cur_expr->antic_occr = NULL; -+ -+ slot = expr_table->find_slot_with_hash (cur_expr, hash, INSERT); -+ -+ if (! (*slot)) -+ /* The expression isn't found, so insert it. */ -+ *slot = cur_expr; -+ else -+ { -+ /* The expression is already in the table, so roll back the -+ obstack and use the existing table entry. */ -+ obstack_free (&expr_obstack, cur_expr); -+ cur_expr = *slot; -+ } -+ -+ /* Search for another occurrence in the same basic block. */ -+ antic_occr = cur_expr->antic_occr; -+ cur_expr->count++; -+ while (antic_occr -+ && BLOCK_FOR_INSN (antic_occr->insn) != BLOCK_FOR_INSN (insn)) -+ { -+ /* If an occurrence isn't found, save a pointer to the end of -+ the list. */ -+ last_occr = antic_occr; -+ antic_occr = antic_occr->next; -+ } -+ -+ if (antic_occr) -+ /* Found another instance of the expression in the same basic block. -+ Prefer this occurrence to the currently recorded one. We want -+ the last one in the block and the block is scanned from start -+ to end. */ -+ antic_occr->insn = insn; -+ else -+ { -+ /* First occurrence of this expression in this basic block. */ -+ antic_occr = (struct occr *) obstack_alloc (&expr_obstack, -+ sizeof (struct occr)); -+ -+ /* First occurrence of this expression in any block? */ -+ if (cur_expr->antic_occr == NULL) -+ cur_expr->antic_occr = antic_occr; -+ else -+ last_occr->next = antic_occr; -+ -+ antic_occr->insn = insn; -+ antic_occr->next = NULL; -+ antic_occr->deleted_p = 0; -+ } -+} -+ -+/* Check whether this instruction is supported format. */ -+ -+static void -+hash_scan_set (rtx_insn *insn) -+{ -+ rtx pat = PATTERN (insn); -+ rtx src = SET_SRC (pat); -+ rtx dest = SET_DEST (pat); -+ int regno; -+ struct reg_avail_info *info; -+ -+ /* Don't mess with jumps and nops. */ -+ if (JUMP_P (insn) || set_noop_p (pat)) -+ return; -+ -+ /* TODO: support more format. */ -+ -+ /* Only consider locally anticipatable intructions currently. */ -+ if (REG_P (dest) && REGNO (dest) <= SP_REGNUM) -+ { -+ regno = REGNO (dest); -+ info = ®_avail_info[regno]; -+ -+ if (BLOCK_FOR_INSN (insn) == info->last_bb -+ && info->first_set == DF_INSN_LUID (insn) -+ && info->first_use >= info->first_set) -+ { -+ /* Only support immediate input currently because -+ this is bugzilla case. */ -+ if (CONST_INT_P (src) || CONST_DOUBLE_P (src)) -+ insert_expr_in_table (PATTERN (insn), insn); -+ } -+ } -+} -+ -+/* Record register first use information for REGNO in INSN. -+ -+ first_use records the first place in the block where the register -+ is used and is used to compute "anticipatability". -+ -+ last_bb records the block for which first_use is valid, -+ as a quick test to invalidate them. */ -+ -+static void -+record_first_reg_use_info (rtx_insn *insn, int regno) -+{ -+ struct reg_avail_info *info = ®_avail_info[regno]; -+ int luid = DF_INSN_LUID (insn); -+ -+ if (info->last_bb != BLOCK_FOR_INSN (insn)) -+ { -+ info->last_bb = BLOCK_FOR_INSN (insn); -+ info->first_use = luid; -+ /* Set the value to record the using is former than setting. */ -+ info->first_set = luid + 1; -+ } -+} -+ -+/* Called from compute_hash_table via note_stores to handle one -+ SET or CLOBBER in an insn. DATA is really the instruction in which -+ the SET is taking place. */ -+ -+static void -+record_first_use_info (rtx *dest, void *data) -+{ -+ rtx_insn *last_set_insn = static_cast (data); -+ int i, j; -+ enum rtx_code code; -+ const char *fmt; -+ rtx x = *dest; -+ -+ if (x == 0) -+ return; -+ -+ code = GET_CODE (x); -+ if (REG_P (x) && REGNO (x) <= SP_REGNUM) -+ { -+ record_first_reg_use_info (last_set_insn, REGNO (x)); -+ /* DF and DI mode may use two registers. */ -+ if (GET_MODE_SIZE (GET_MODE (x)) == 8) -+ record_first_reg_use_info (last_set_insn, REGNO (x) + 1); -+ } -+ -+ for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--) -+ { -+ if (fmt[i] == 'e') -+ record_first_use_info (&XEXP (x, i), data); -+ else if (fmt[i] == 'E') -+ for (j = 0; j < XVECLEN (x, i); j++) -+ record_first_use_info (&XVECEXP (x, i, j), data); -+ } -+} -+ -+/* Record register first/block set information for REGNO in INSN. -+ -+ first_set records the first place in the block where the register -+ is set and is used to compute "anticipatability". -+ -+ last_bb records the block for which first_set is valid, -+ as a quick test to invalidate them. */ -+ -+static void -+record_first_reg_set_info (rtx_insn *insn, int regno) -+{ -+ struct reg_avail_info *info = ®_avail_info[regno]; -+ int luid = DF_INSN_LUID (insn); -+ -+ if (info->last_bb != BLOCK_FOR_INSN (insn)) -+ { -+ info->last_bb = BLOCK_FOR_INSN (insn); -+ info->first_set = luid; -+ /* Set the value to record the using is later than setting. */ -+ info->first_use = luid + 1; -+ } -+} -+ -+/* Called from compute_hash_table via note_stores to handle one -+ SET or CLOBBER in an insn. DATA is really the instruction in which -+ the SET is taking place. */ -+ -+static void -+record_first_set_info (rtx dest, const_rtx setter ATTRIBUTE_UNUSED, void *data) -+{ -+ rtx_insn *last_set_insn = static_cast (data); -+ -+ if (GET_CODE (dest) == SUBREG) -+ dest = SUBREG_REG (dest); -+ -+ if (REG_P (dest) && REGNO (dest) <= SP_REGNUM) -+ { -+ record_first_reg_set_info (last_set_insn, REGNO (dest)); -+ if (GET_MODE_SIZE (GET_MODE (dest)) == 8) -+ record_first_reg_set_info (last_set_insn, REGNO (dest) + 1); -+ } -+} -+ -+/* Build hash table for supported format instructions. -+ Only consider if the instruction is anticipatable in the basic block here. -+ We postpone the def-use check until hoisting. */ -+ -+static void -+compute_hash_table (void) -+{ -+ basic_block bb; -+ int i; -+ -+ /* We only take care hard registers. */ -+ reg_avail_info = -+ (struct reg_avail_info *) xmalloc (sizeof (struct reg_avail_info) * -+ (SP_REGNUM + 1)); -+ -+ for (i = 0; i < 32; i++) -+ reg_avail_info[i].last_bb = NULL; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ rtx_insn *insn; -+ -+ /* Do not hoist instrucion from block which has more -+ than one predecessor. */ -+ if (EDGE_COUNT (bb->preds) > 1) -+ continue; -+ -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (!NONDEBUG_INSN_P (insn)) -+ continue; -+ -+ /* Construct a caller save register barrier. We cannot hoist the -+ instruction over a function call which sets caller save -+ registers. */ -+ if (CALL_P (insn)) -+ { -+ for (i = 0; i <= SP_REGNUM; i++) -+ if (call_used_regs[i]) -+ record_first_reg_use_info (insn, i); -+ } -+ -+ note_uses (&PATTERN (insn), record_first_use_info, insn); -+ note_stores (PATTERN (insn), record_first_set_info, insn); -+ } -+ -+ /* Build the hash table. */ -+ FOR_BB_INSNS (bb, insn) -+ if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == SET) -+ hash_scan_set (insn); -+ } -+} -+ -+/* Hoist instructions in this slot if possible. */ -+int -+nds32_find_gcse_expr_table (expr **slot, void *data ATTRIBUTE_UNUSED) -+{ -+ struct expr *exprs = *slot; -+ struct occr *occr; -+ rtx_insn *insn = NULL; -+ rtx_insn *last_insn; -+ basic_block bb; -+ edge e; -+ unsigned ix; -+ unsigned emit_done; -+ unsigned cover, regno; -+ df_ref use; -+ enum machine_mode mode; -+ -+ if (exprs->count < 2) -+ return 1; -+ -+ bitmap_vector_clear (hoist_vbeout, last_basic_block_for_fn (cfun)); -+ bitmap_vector_clear (hoist_vbein, last_basic_block_for_fn (cfun)); -+ -+ /* Set the bit for this slot. */ -+ occr = exprs->antic_occr; -+ while (occr) -+ { -+ insn = occr->insn; -+ bb = BLOCK_FOR_INSN (insn); -+ if (!occr->deleted_p) -+ bitmap_set_bit (hoist_vbein[bb->index], 0); -+ occr = occr->next; -+ } -+ -+ /* Try to hoist code for each basic block. */ -+ FOR_EACH_BB_REVERSE_FN (bb, cfun) -+ { -+ if (bb->next_bb != EXIT_BLOCK_PTR_FOR_FN (cfun)) -+ bitmap_intersection_of_succs (hoist_vbeout[bb->index], hoist_vbein, bb); -+ -+ if (bitmap_bit_p (hoist_vbeout[bb->index], 0) -+ && EDGE_COUNT (bb->succs) > 1) -+ { -+ emit_done = 0; -+ cover = FALSE; -+ for (e = NULL, ix = 0; ix < EDGE_COUNT (bb->succs); ix++) -+ { -+ e = EDGE_SUCC (bb, ix); -+ if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun)) -+ continue; -+ occr = exprs->antic_occr; -+ while (occr) -+ { -+ insn = occr->insn; -+ if (!occr->deleted_p && e->dest == BLOCK_FOR_INSN (insn)) -+ break; -+ occr = occr->next; -+ } -+ -+ gcc_assert (insn != NULL); -+ -+ if (!emit_done) -+ { -+ last_insn = BB_END (bb); -+ /* Check the defined register is not used by the last -+ instruction of the previos block.*/ -+ regno = REGNO (SET_DEST (PATTERN (insn))); -+ mode = GET_MODE (SET_DEST (PATTERN (insn))); -+ FOR_EACH_INSN_USE (use, last_insn) -+ { -+ if (DF_REF_REGNO (use) == regno -+ || regno_clobbered_p (regno, last_insn, mode, 2)) -+ { -+ cover = TRUE; -+ break; -+ } -+ } -+ -+ /* TODO: support more format. */ -+ if (cover) -+ break; -+ else if (JUMP_P (last_insn)) -+ { -+ emit_insn_before_noloc (PATTERN (insn), last_insn, bb); -+ emit_done = TRUE; -+ } -+ else -+ break; -+ } -+ -+ if (emit_done) -+ { -+ delete_insn (insn); -+ occr->deleted_p = TRUE; -+ } -+ } -+ } -+ } -+ return 1; -+} -+ -+static int -+hoist_code (void) -+{ -+ hoist_vbein = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), 1); -+ hoist_vbeout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), 1); -+ -+ expr_table->traverse (NULL); -+ -+ sbitmap_vector_free (hoist_vbein); -+ sbitmap_vector_free (hoist_vbeout); -+ -+ return 0; -+} -+ -+ -+static unsigned int -+nds32_gcse_opt (void) -+{ -+ -+ if (n_basic_blocks_for_fn (cfun) <= NUM_FIXED_BLOCKS + 1) -+ return 0; -+ /* Allocate memory for this pass. -+ Also computes and initializes the insns' CUIDs. */ -+ alloc_mem (); -+ -+ df_chain_add_problem (DF_DU_CHAIN); -+ df_insn_rescan_all (); -+ df_analyze (); -+ -+ compute_hash_table (); -+ -+ if (dump_file) -+ dump_hash_table (dump_file); -+ -+ hoist_code (); -+ -+ df_insn_rescan_all (); -+ free_mem (); -+ return 0; -+} -+ -+const pass_data pass_data_nds32_gcse_opt = -+{ -+ RTL_PASS, /* type */ -+ "gcse_opt", /* 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_gcse_opt : public rtl_opt_pass -+{ -+public: -+ pass_nds32_gcse_opt (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_gcse_opt, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { return TARGET_GCSE_OPT; } -+ unsigned int execute (function *) { return nds32_gcse_opt (); } -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_gcse_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_gcse_opt (ctxt); -+} -+ -+/* ------------------------------------------------------------------------ */ -diff --git a/gcc/config/nds32/nds32-graywolf.md b/gcc/config/nds32/nds32-graywolf.md -new file mode 100644 -index 0000000..f9ddbd8 ---- /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-2016 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 fabf262..7547fb1 100644 ---- a/gcc/config/nds32/nds32-intrinsic.c -+++ b/gcc/config/nds32/nds32-intrinsic.c -@@ -24,210 +24,1867 @@ - #include "system.h" - #include "coretypes.h" - #include "backend.h" --#include "target.h" --#include "rtl.h" - #include "tree.h" --#include "optabs.h" /* For GEN_FCN. */ --#include "diagnostic-core.h" -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" - #include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" - #include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" - #include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" - - /* ------------------------------------------------------------------------ */ - --/* Function to expand builtin function for -- '[(unspec_volatile [(reg)])]'. */ -+/* Read the requested argument from the EXP given by INDEX. -+ Return the value as an rtx. */ -+static rtx -+nds32_read_argument (tree exp, unsigned int index) -+{ -+ return expand_normal (CALL_EXPR_ARG (exp, index)); -+} -+ -+/* Return a legitimate rtx for instruction ICODE's return value. Use TARGET -+ if it's not null, has the right mode, and satisfies operand 0's -+ predicate. */ -+static rtx -+nds32_legitimize_target (enum insn_code icode, rtx target) -+{ -+ enum machine_mode mode = insn_data[icode].operand[0].mode; -+ -+ if (! target -+ || GET_MODE (target) != mode -+ || ! (*insn_data[icode].operand[0].predicate) (target, mode)) -+ return gen_reg_rtx (mode); -+ else -+ return target; -+} -+ -+/* Given that ARG is being passed as operand OPNUM to instruction ICODE, -+ check whether ARG satisfies the operand's constraints. If it doesn't, -+ copy ARG to a temporary register and return that. Otherwise return ARG -+ itself. */ - static rtx --nds32_expand_builtin_null_ftype_reg (enum insn_code icode, -- tree exp, rtx target) -+nds32_legitimize_argument (enum insn_code icode, int opnum, rtx arg) -+{ -+ enum machine_mode mode = insn_data[icode].operand[opnum].mode; -+ -+ if ((*insn_data[icode].operand[opnum].predicate) (arg, mode)) -+ return arg; -+ else if (VECTOR_MODE_P (mode) && CONST_INT_P (arg)) -+ { -+ /* Handle CONST_INT covert to CONST_VECTOR. */ -+ int nunits = GET_MODE_NUNITS (mode); -+ int i, shift = 0; -+ rtvec v = rtvec_alloc (nunits); -+ int val = INTVAL (arg); -+ enum machine_mode val_mode = (mode == V4QImode) ? QImode : HImode; -+ int shift_acc = (val_mode == QImode) ? 8 : 16; -+ int mask = (val_mode == QImode) ? 0xff : 0xffff; -+ int tmp_val = val; -+ -+ if (TARGET_BIG_ENDIAN) -+ for (i = 0; i < nunits; i++) -+ { -+ tmp_val = (val >> shift) & mask; -+ RTVEC_ELT (v, nunits - i - 1) = gen_int_mode (tmp_val, val_mode); -+ shift += shift_acc; -+ } -+ else -+ for (i = 0; i < nunits; i++) -+ { -+ tmp_val = (val >> shift) & mask; -+ RTVEC_ELT (v, i) = gen_int_mode (tmp_val, val_mode); -+ shift += shift_acc; -+ } -+ -+ return copy_to_mode_reg (mode, gen_rtx_CONST_VECTOR (mode, v)); -+ } -+ else -+ { -+ rtx tmp_rtx = gen_reg_rtx (mode); -+ convert_move (tmp_rtx, arg, false); -+ return tmp_rtx; -+ } -+} -+ -+/* Return true if OPVAL can be used for operand OPNUM of instruction ICODE. -+ The instruction should require a constant operand of some sort. The -+ function prints an error if OPVAL is not valid. */ -+static int -+nds32_check_constant_argument (enum insn_code icode, int opnum, rtx opval, -+ const char *name) - { -- /* Mapping: -- ops[0] <--> value0 <--> arg0 */ -- struct expand_operand ops[1]; -- tree arg0; -- rtx value0; -+ if (GET_CODE (opval) != CONST_INT) -+ { -+ error ("invalid argument to built-in function %s", name); -+ return false; -+ } -+ if (! (*insn_data[icode].operand[opnum].predicate) (opval, VOIDmode)) -+ { -+ error ("constant argument out of range for %s", name); -+ -+ return false; -+ } -+ return true; -+} - -- /* Grab the incoming arguments and extract its rtx. */ -- arg0 = CALL_EXPR_ARG (exp, 0); -- value0 = expand_normal (arg0); -+/* Expand builtins that return target. */ -+static rtx -+nds32_expand_noarg_builtin (enum insn_code icode, rtx target) -+{ -+ rtx pat; - -- /* Create operands. */ -- create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0))); -+ target = nds32_legitimize_target (icode, target); - -- /* Emit new instruction. */ -- if (!maybe_expand_insn (icode, 1, ops)) -- error ("invalid argument to built-in function"); -+ /* Emit and return the new instruction. */ -+ pat = GEN_FCN (icode) (target); -+ if (! pat) -+ return NULL_RTX; - -+ emit_insn (pat); - return target; - } - --/* Function to expand builtin function for -- '[(set (reg) (unspec_volatile [(imm)]))]'. */ -+/* Expand builtins that take one operand. */ - static rtx --nds32_expand_builtin_reg_ftype_imm (enum insn_code icode, -- tree exp, rtx target) -+nds32_expand_unop_builtin (enum insn_code icode, tree exp, rtx target, -+ bool return_p) - { -- /* Mapping: -- ops[0] <--> target <--> exp -- ops[1] <--> value0 <--> arg0 */ -- struct expand_operand ops[2]; -- tree arg0; -- rtx value0; -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ int op0_num = return_p ? 1 : 0; -+ -+ if (return_p) -+ target = nds32_legitimize_target (icode, target); - -- /* Grab the incoming arguments and extract its rtx. */ -- arg0 = CALL_EXPR_ARG (exp, 0); -- value0 = expand_normal (arg0); -+ op0 = nds32_legitimize_argument (icode, op0_num, op0); - -- /* Create operands. */ -- create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp))); -- create_input_operand (&ops[1], value0, TYPE_MODE (TREE_TYPE (arg0))); -+ /* Emit and return the new instruction. */ -+ if (return_p) -+ pat = GEN_FCN (icode) (target, op0); -+ else -+ pat = GEN_FCN (icode) (op0); - -- /* Emit new instruction. */ -- if (!maybe_expand_insn (icode, 2, ops)) -- error ("invalid argument to built-in function"); -+ if (! pat) -+ return NULL_RTX; - -+ emit_insn (pat); - return target; - } - --/* Function to expand builtin function for -- '[(unspec_volatile [(reg) (imm)])]' pattern. */ -+/* Expand builtins that take one operands and the first is immediate. */ - static rtx --nds32_expand_builtin_null_ftype_reg_imm (enum insn_code icode, -- tree exp, rtx target) --{ -- /* Mapping: -- ops[0] <--> value0 <--> arg0 -- ops[1] <--> value1 <--> arg1 */ -- struct expand_operand ops[2]; -- tree arg0, arg1; -- rtx value0, value1; -- -- /* Grab the incoming arguments and extract its rtx. */ -- arg0 = CALL_EXPR_ARG (exp, 0); -- arg1 = CALL_EXPR_ARG (exp, 1); -- value0 = expand_normal (arg0); -- value1 = expand_normal (arg1); -- -- /* Create operands. */ -- create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0))); -- create_input_operand (&ops[1], value1, TYPE_MODE (TREE_TYPE (arg1))); -- -- /* Emit new instruction. */ -- if (!maybe_expand_insn (icode, 2, ops)) -- error ("invalid argument to built-in function"); -+nds32_expand_unopimm_builtin (enum insn_code icode, tree exp, rtx target, -+ bool return_p, const char *name) -+{ -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ int op0_num = return_p ? 1 : 0; -+ -+ if (return_p) -+ target = nds32_legitimize_target (icode, target); -+ -+ if (!nds32_check_constant_argument (icode, op0_num, op0, name)) -+ return NULL_RTX; -+ -+ op0 = nds32_legitimize_argument (icode, op0_num, op0); - -+ /* Emit and return the new instruction. */ -+ if (return_p) -+ pat = GEN_FCN (icode) (target, op0); -+ else -+ pat = GEN_FCN (icode) (op0); -+ -+ if (! pat) -+ return NULL_RTX; -+ -+ emit_insn (pat); - return target; - } - --/* ------------------------------------------------------------------------ */ -+/* Expand builtins that take two operands. */ -+static rtx -+nds32_expand_binop_builtin (enum insn_code icode, tree exp, rtx target, -+ bool return_p) -+{ -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ rtx op1 = nds32_read_argument (exp, 1); -+ int op0_num = return_p ? 1 : 0; -+ int op1_num = return_p ? 2 : 1; - --void --nds32_init_builtins_impl (void) -+ if (return_p) -+ target = nds32_legitimize_target (icode, target); -+ -+ op0 = nds32_legitimize_argument (icode, op0_num, op0); -+ op1 = nds32_legitimize_argument (icode, op1_num, op1); -+ -+ /* Emit and return the new instruction. */ -+ if (return_p) -+ pat = GEN_FCN (icode) (target, op0, op1); -+ else -+ pat = GEN_FCN (icode) (op0, op1); -+ -+ if (! pat) -+ return NULL_RTX; -+ -+ emit_insn (pat); -+ return target; -+} -+ -+/* Expand builtins that take two operands and the second is immediate. */ -+static rtx -+nds32_expand_binopimm_builtin (enum insn_code icode, tree exp, rtx target, -+ bool return_p, const char *name) - { -- tree pointer_type_node = build_pointer_type (integer_type_node); -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ rtx op1 = nds32_read_argument (exp, 1); -+ int op0_num = return_p ? 1 : 0; -+ int op1_num = return_p ? 2 : 1; - -- tree void_ftype_void = build_function_type (void_type_node, -- void_list_node); -+ if (return_p) -+ target = nds32_legitimize_target (icode, target); - -- tree void_ftype_pint = build_function_type_list (void_type_node, -- pointer_type_node, -- NULL_TREE); -+ if (!nds32_check_constant_argument (icode, op1_num, op1, name)) -+ return NULL_RTX; - -- tree int_ftype_int = build_function_type_list (integer_type_node, -- integer_type_node, -- NULL_TREE); -+ op0 = nds32_legitimize_argument (icode, op0_num, op0); -+ op1 = nds32_legitimize_argument (icode, op1_num, op1); - -- tree void_ftype_int_int = build_function_type_list (void_type_node, -- integer_type_node, -- integer_type_node, -- NULL_TREE); -+ /* Emit and return the new instruction. */ -+ if (return_p) -+ pat = GEN_FCN (icode) (target, op0, op1); -+ else -+ pat = GEN_FCN (icode) (op0, op1); - -- /* Cache. */ -- add_builtin_function ("__builtin_nds32_isync", void_ftype_pint, -- NDS32_BUILTIN_ISYNC, -- BUILT_IN_MD, NULL, NULL_TREE); -- add_builtin_function ("__builtin_nds32_isb", void_ftype_void, -- NDS32_BUILTIN_ISB, -- BUILT_IN_MD, NULL, NULL_TREE); -+ if (! pat) -+ return NULL_RTX; - -- /* Register Transfer. */ -- add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int, -- NDS32_BUILTIN_MFSR, -- BUILT_IN_MD, NULL, NULL_TREE); -- add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int, -- NDS32_BUILTIN_MFUSR, -- BUILT_IN_MD, NULL, NULL_TREE); -- add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int, -- NDS32_BUILTIN_MTSR, -- BUILT_IN_MD, NULL, NULL_TREE); -- add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int, -- NDS32_BUILTIN_MTUSR, -- BUILT_IN_MD, NULL, NULL_TREE); -+ emit_insn (pat); -+ return target; -+} - -- /* Interrupt. */ -- add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void, -- NDS32_BUILTIN_SETGIE_EN, -- BUILT_IN_MD, NULL, NULL_TREE); -- add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void, -- NDS32_BUILTIN_SETGIE_DIS, -- BUILT_IN_MD, NULL, NULL_TREE); -+/* Expand builtins that take three operands. */ -+static rtx -+nds32_expand_triop_builtin (enum insn_code icode, tree exp, rtx target, -+ bool return_p) -+{ -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ rtx op1 = nds32_read_argument (exp, 1); -+ rtx op2 = nds32_read_argument (exp, 2); -+ int op0_num = return_p ? 1 : 0; -+ int op1_num = return_p ? 2 : 1; -+ int op2_num = return_p ? 3 : 2; -+ -+ if (return_p) -+ target = nds32_legitimize_target (icode, target); -+ -+ op0 = nds32_legitimize_argument (icode, op0_num, op0); -+ op1 = nds32_legitimize_argument (icode, op1_num, op1); -+ op2 = nds32_legitimize_argument (icode, op2_num, op2); -+ -+ /* Emit and return the new instruction. */ -+ if (return_p) -+ pat = GEN_FCN (icode) (target, op0, op1, op2); -+ else -+ pat = GEN_FCN (icode) (op0, op1, op2); -+ -+ if (! pat) -+ return NULL_RTX; -+ -+ emit_insn (pat); -+ return target; -+} -+ -+/* Expand builtins that take three operands and the third is immediate. */ -+static rtx -+nds32_expand_triopimm_builtin (enum insn_code icode, tree exp, rtx target, -+ bool return_p, const char *name) -+{ -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ rtx op1 = nds32_read_argument (exp, 1); -+ rtx op2 = nds32_read_argument (exp, 2); -+ int op0_num = return_p ? 1 : 0; -+ int op1_num = return_p ? 2 : 1; -+ int op2_num = return_p ? 3 : 2; -+ -+ if (return_p) -+ target = nds32_legitimize_target (icode, target); -+ -+ if (!nds32_check_constant_argument (icode, op2_num, op2, name)) -+ return NULL_RTX; -+ -+ op0 = nds32_legitimize_argument (icode, op0_num, op0); -+ op1 = nds32_legitimize_argument (icode, op1_num, op1); -+ op2 = nds32_legitimize_argument (icode, op2_num, op2); -+ -+ /* Emit and return the new instruction. */ -+ if (return_p) -+ pat = GEN_FCN (icode) (target, op0, op1, op2); -+ else -+ pat = GEN_FCN (icode) (op0, op1, op2); -+ -+ if (! pat) -+ return NULL_RTX; -+ -+ emit_insn (pat); -+ return target; -+} -+ -+/* Expand builtins for load. */ -+static rtx -+nds32_expand_builtin_load (enum insn_code icode, tree exp, rtx target) -+{ -+ /* Load address format is [$ra + $rb], -+ but input arguments not enough, -+ so we need another temp register as $rb. -+ Generating assembly code: -+ movi $temp, 0 -+ llw $rt, [$ra + $temp] */ -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ rtx addr_helper = gen_reg_rtx (insn_data[icode].operand[1].mode); -+ -+ target = nds32_legitimize_target (icode, target); -+ op0 = nds32_legitimize_argument (icode, 1, op0); -+ -+ /* Emit and return the new instruction. */ -+ pat = GEN_FCN (icode) (target, op0, addr_helper); -+ if (!pat) -+ return NULL_RTX; -+ -+ emit_move_insn (addr_helper, GEN_INT (0)); -+ emit_insn (pat); -+ return target; -+} -+ -+/* Expand builtins for store. */ -+static rtx -+nds32_expand_builtin_store (enum insn_code icode, tree exp, rtx target) -+{ -+ /* Store address format is [$ra + $rb], -+ but input arguments not enough, -+ so we need another temp register as $rb. -+ Generating assembly code: -+ movi $temp, 0 -+ store $rt, [$ra + $temp] */ -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ rtx op1 = nds32_read_argument (exp, 1); -+ rtx addr_helper = gen_reg_rtx (insn_data[icode].operand[1].mode); -+ -+ op0 = nds32_legitimize_argument (icode, 0, op0); -+ op1 = nds32_legitimize_argument (icode, 2, op1); -+ -+ /* Emit and return the new instruction. */ -+ pat = GEN_FCN (icode) (op0, addr_helper, op1); -+ if (! pat) -+ return NULL_RTX; -+ -+ emit_move_insn (addr_helper, GEN_INT (0)); -+ emit_insn (pat); -+ return target; -+} -+ -+/* Expand cctl builtins. */ -+static rtx -+nds32_expand_cctl_builtin (enum insn_code icode, tree exp, rtx target, -+ bool return_p, const char *name) -+{ -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ rtx op1 = nds32_read_argument (exp, 1); -+ int op0_num = return_p ? 1 : 0; -+ int op1_num = return_p ? 2 : 1; -+ -+ if (return_p) -+ target = nds32_legitimize_target (icode, target); -+ -+ if (!nds32_check_constant_argument (icode, op0_num, op0, name)) -+ return NULL_RTX; -+ -+ op0 = nds32_legitimize_argument (icode, op0_num, op0); -+ op1 = nds32_legitimize_argument (icode, op1_num, op1); -+ -+ /* Emit and return the new instruction. */ -+ if (icode == CODE_FOR_cctl_idx_write) -+ { -+ /* cctl_idx_write is three argument, -+ so create operand2 for cctl_idx_write pattern. */ -+ rtx op2 = nds32_read_argument (exp, 2); -+ op2 = nds32_legitimize_argument (icode, 2, op2); -+ pat = GEN_FCN (icode) (op0, op1, op2); -+ } -+ else if (return_p) -+ pat = GEN_FCN (icode) (target, op0, op1); -+ else -+ pat = GEN_FCN (icode) (op0, op1); -+ -+ if (! pat) -+ return NULL_RTX; -+ -+ emit_insn (pat); -+ return target; -+} -+ -+/* Expand scw builtins. */ -+static rtx -+nds32_expand_scw_builtin (enum insn_code icode, tree exp, rtx target) -+{ -+ /* SCW address format is [$ra + $rb], but input arguments not enough, -+ so we need another temp register as $rb. -+ Generating assembly code: -+ movi $temp, 0 -+ scw $rt, [$ra + $temp] */ -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ rtx op1 = nds32_read_argument (exp, 1); -+ rtx addr_helper = gen_reg_rtx (insn_data[icode].operand[1].mode); -+ -+ target = nds32_legitimize_target (icode, target); -+ op0 = nds32_legitimize_argument (icode, 1, op0); -+ op1 = nds32_legitimize_argument (icode, 2, op1); -+ -+ /* Emit and return the new instruction. */ -+ pat = GEN_FCN (icode) (target, op0, addr_helper, target); -+ -+ if (!pat) -+ return NULL_RTX; -+ -+ emit_move_insn (addr_helper, GEN_INT (0)); -+ emit_move_insn (target, op1); -+ emit_insn (pat); -+ return target; - } - -+/* Expand set int priority builtins. */ -+static rtx -+nds32_expand_priority_builtin (enum insn_code icode, tree exp, rtx target, -+ const char *name) -+{ -+ rtx pat; -+ rtx op0 = nds32_read_argument (exp, 0); -+ rtx op1 = nds32_read_argument (exp, 1); -+ -+ /* set_int_priority intrinsic function that two arguments are immediate, -+ so check whether auguments are immedite. */ -+ -+ if (!nds32_check_constant_argument (icode, 0, op0, name)) -+ return NULL_RTX; -+ -+ if (!nds32_check_constant_argument (icode, 1, op1, name)) -+ return NULL_RTX; -+ -+ op0 = nds32_legitimize_argument (icode, 0, op0); -+ op1 = nds32_legitimize_argument (icode, 1, op1); -+ -+ /* Emit and return the new instruction. */ -+ pat = GEN_FCN (icode) (op0, op1); -+ -+ if (! pat) -+ return NULL_RTX; -+ -+ emit_insn (pat); -+ return target; -+} -+ -+struct builtin_description -+{ -+ const enum insn_code icode; -+ const char *name; -+ enum nds32_builtins code; -+ bool return_p; -+}; -+ -+#define NDS32_BUILTIN(code, string, builtin) \ -+ { CODE_FOR_##code, "__nds32__" string, \ -+ NDS32_BUILTIN_##builtin, true }, -+ -+#define NDS32_NO_TARGET_BUILTIN(code, string, builtin) \ -+ { CODE_FOR_##code, "__nds32__" string, \ -+ NDS32_BUILTIN_##builtin, false }, -+ -+/* Intrinsics that no argument, and that return value. */ -+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", -+ GET_ALL_PENDING_INT) -+ NDS32_BUILTIN(unspec_unaligned_feature, "unaligned_feature", -+ UNALIGNED_FEATURE) -+ NDS32_NO_TARGET_BUILTIN(unspec_enable_unaligned, "enable_unaligned", -+ ENABLE_UNALIGNED) -+ NDS32_NO_TARGET_BUILTIN(unspec_disable_unaligned, "disable_unaligned", -+ DISABLE_UNALIGNED) -+}; -+ -+/* Intrinsics that take just one argument. */ -+static struct builtin_description bdesc_1arg[] = -+{ -+ NDS32_BUILTIN(unspec_ssabssi2, "abs", ABS) -+ NDS32_BUILTIN(clzsi2, "clz", CLZ) -+ NDS32_BUILTIN(unspec_clo, "clo", CLO) -+ NDS32_BUILTIN(unspec_wsbh, "wsbh", WSBH) -+ NDS32_BUILTIN(unspec_tlbop_pb, "tlbop_pb",TLBOP_PB) -+ NDS32_BUILTIN(unaligned_load_hw, "unaligned_load_hw", UALOAD_HW) -+ NDS32_BUILTIN(unaligned_loadsi, "unaligned_load_w", UALOAD_W) -+ NDS32_BUILTIN(unaligned_loaddi, "unaligned_load_dw", UALOAD_DW) -+ NDS32_NO_TARGET_BUILTIN(unspec_volatile_isync, "isync", ISYNC) -+ NDS32_NO_TARGET_BUILTIN(unspec_fmtcsr, "fmtcsr", FMTCSR) -+ NDS32_NO_TARGET_BUILTIN(unspec_jr_itoff, "jr_itoff", JR_ITOFF) -+ NDS32_NO_TARGET_BUILTIN(unspec_jr_toff, "jr_toff", JR_TOFF) -+ NDS32_NO_TARGET_BUILTIN(unspec_jral_ton, "jral_ton", JRAL_TON) -+ NDS32_NO_TARGET_BUILTIN(unspec_ret_toff, "ret_toff", RET_TOFF) -+ NDS32_NO_TARGET_BUILTIN(unspec_jral_iton, "jral_iton",JRAL_ITON) -+ NDS32_NO_TARGET_BUILTIN(unspec_tlbop_trd, "tlbop_trd", TLBOP_TRD) -+ NDS32_NO_TARGET_BUILTIN(unspec_tlbop_twr, "tlbop_twr", TLBOP_TWR) -+ NDS32_NO_TARGET_BUILTIN(unspec_tlbop_rwr, "tlbop_rwr", TLBOP_RWR) -+ NDS32_NO_TARGET_BUILTIN(unspec_tlbop_rwlk, "tlbop_rwlk", TLBOP_RWLK) -+ NDS32_NO_TARGET_BUILTIN(unspec_tlbop_unlk, "tlbop_unlk", TLBOP_UNLK) -+ NDS32_NO_TARGET_BUILTIN(unspec_tlbop_inv, "tlbop_inv", TLBOP_INV) -+ 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. */ -+static struct builtin_description bdesc_1argimm[] = -+{ -+ NDS32_BUILTIN(unspec_volatile_mfsr, "mfsr", MFSR) -+ NDS32_BUILTIN(unspec_volatile_mfusr, "mfsr", MFUSR) -+ NDS32_BUILTIN(unspec_get_pending_int, "get_pending_int", GET_PENDING_INT) -+ NDS32_BUILTIN(unspec_get_int_priority, "get_int_priority", GET_INT_PRIORITY) -+ NDS32_NO_TARGET_BUILTIN(unspec_trap, "trap", TRAP) -+ NDS32_NO_TARGET_BUILTIN(unspec_break, "break", BREAK) -+ NDS32_NO_TARGET_BUILTIN(unspec_syscall, "syscall", SYSCALL) -+ NDS32_NO_TARGET_BUILTIN(unspec_enable_int, "enable_int", ENABLE_INT) -+ NDS32_NO_TARGET_BUILTIN(unspec_disable_int, "disable_int", DISABLE_INT) -+ NDS32_NO_TARGET_BUILTIN(unspec_clr_pending_hwint, "clr_pending_hwint", -+ CLR_PENDING_HWINT) -+ NDS32_NO_TARGET_BUILTIN(unspec_set_trig_level, "set_trig_level", -+ SET_TRIG_LEVEL) -+ NDS32_NO_TARGET_BUILTIN(unspec_set_trig_edge, "set_trig_edge", -+ SET_TRIG_EDGE) -+ NDS32_BUILTIN(unspec_get_trig_type, "get_trig_type", GET_TRIG_TYPE) -+}; -+ -+/* Intrinsics that take two arguments. */ -+static struct builtin_description bdesc_2arg[] = -+{ -+ NDS32_BUILTIN(unspec_fcpynss, "fcpynss", FCPYNSS) -+ NDS32_BUILTIN(unspec_fcpyss, "fcpyss", FCPYSS) -+ NDS32_BUILTIN(unspec_fcpynsd, "fcpynsd", FCPYNSD) -+ NDS32_BUILTIN(unspec_fcpysd, "fcpysd", FCPYSD) -+ NDS32_BUILTIN(unspec_ave, "ave", AVE) -+ NDS32_BUILTIN(unspec_pbsad, "pbsad", PBSAD) -+ 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) -+ NDS32_NO_TARGET_BUILTIN(mtsr_isb, "mtsr_isb", MTSR_ISB) -+ NDS32_NO_TARGET_BUILTIN(mtsr_dsb, "mtsr_dsb", MTSR_DSB) -+ NDS32_NO_TARGET_BUILTIN(unspec_volatile_mtsr, "mtsr", MTSR) -+ NDS32_NO_TARGET_BUILTIN(unspec_volatile_mtusr, "mtusr", MTUSR) -+ 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. */ -+static struct builtin_description bdesc_2argimm[] = -+{ -+ NDS32_BUILTIN(unspec_bclr, "bclr", BCLR) -+ NDS32_BUILTIN(unspec_bset, "bset", BSET) -+ NDS32_BUILTIN(unspec_btgl, "btgl", BTGL) -+ NDS32_BUILTIN(unspec_btst, "btst", BTST) -+ NDS32_BUILTIN(unspec_clip, "clip", CLIP) -+ 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. */ -+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. */ -+static struct builtin_description bdesc_3argimm[] = -+{ -+ NDS32_NO_TARGET_BUILTIN(prefetch_qw, "prefetch_qw", DPREF_QW) -+ 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. */ -+static struct builtin_description bdesc_load[] = -+{ -+ NDS32_BUILTIN(unspec_volatile_llw, "llw", LLW) -+ NDS32_BUILTIN(unspec_lwup, "lwup", LWUP) -+ NDS32_BUILTIN(unspec_lbup, "lbup", LBUP) -+}; -+ -+/* Intrinsics that store a value. */ -+static struct builtin_description bdesc_store[] = -+{ -+ NDS32_BUILTIN(unspec_swup, "swup", SWUP) -+ NDS32_BUILTIN(unspec_sbup, "sbup", SBUP) -+}; -+ -+static struct builtin_description bdesc_cctl[] = -+{ -+ NDS32_BUILTIN(cctl_idx_read, "cctl_idx_read", CCTL_IDX_READ) -+ NDS32_NO_TARGET_BUILTIN(cctl_idx_write, "cctl_idx_write", CCTL_IDX_WRITE) -+ NDS32_NO_TARGET_BUILTIN(cctl_va_lck, "cctl_va_lck", CCTL_VA_LCK) -+ NDS32_NO_TARGET_BUILTIN(cctl_idx_wbinval, -+ "cctl_idx_wbinval", CCTL_IDX_WBINVAL) -+ NDS32_NO_TARGET_BUILTIN(cctl_va_wbinval_l1, -+ "cctl_va_wbinval_l1", CCTL_VA_WBINVAL_L1) -+ NDS32_NO_TARGET_BUILTIN(cctl_va_wbinval_la, -+ "cctl_va_wbinval_la", CCTL_VA_WBINVAL_LA) -+}; - - rtx - nds32_expand_builtin_impl (tree exp, - rtx target, - rtx subtarget ATTRIBUTE_UNUSED, -- machine_mode mode ATTRIBUTE_UNUSED, -+ enum machine_mode mode ATTRIBUTE_UNUSED, - int ignore ATTRIBUTE_UNUSED) - { - tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); -+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl); -+ 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. */ -+ case NDS32_BUILTIN_FMFCFG: -+ case NDS32_BUILTIN_FMFCSR: -+ case NDS32_BUILTIN_FMTCSR: -+ case NDS32_BUILTIN_FCPYNSS: -+ case NDS32_BUILTIN_FCPYSS: -+ /* Both v3s and v3f toolchains define TARGET_FPU_SINGLE. */ -+ if (!TARGET_FPU_SINGLE) -+ { -+ error ("this builtin function is only available " -+ "on the v3s or v3f toolchain"); -+ return NULL_RTX; -+ } -+ break; -+ -+ /* FPU Register Transfer. */ -+ case NDS32_BUILTIN_FCPYNSD: -+ case NDS32_BUILTIN_FCPYSD: -+ /* Only v3f toolchain defines TARGET_FPU_DOUBLE. */ -+ if (!TARGET_FPU_DOUBLE) -+ { -+ error ("this builtin function is only available " -+ "on the v3f toolchain"); -+ return NULL_RTX; -+ } -+ break; -+ -+ /* Load and Store */ -+ case NDS32_BUILTIN_LLW: -+ case NDS32_BUILTIN_LWUP: -+ case NDS32_BUILTIN_LBUP: -+ case NDS32_BUILTIN_SCW: -+ case NDS32_BUILTIN_SWUP: -+ case NDS32_BUILTIN_SBUP: -+ if (TARGET_ISA_V3M) -+ { -+ error ("this builtin function not support " -+ "on the v3m toolchain"); -+ return NULL_RTX; -+ } -+ break; -+ -+ /* Performance Extension */ -+ case NDS32_BUILTIN_ABS: -+ case NDS32_BUILTIN_AVE: -+ case NDS32_BUILTIN_BCLR: -+ case NDS32_BUILTIN_BSET: -+ case NDS32_BUILTIN_BTGL: -+ case NDS32_BUILTIN_BTST: -+ case NDS32_BUILTIN_CLIP: -+ case NDS32_BUILTIN_CLIPS: -+ case NDS32_BUILTIN_CLZ: -+ case NDS32_BUILTIN_CLO: -+ if (!TARGET_EXT_PERF) -+ { -+ error ("don't support performance extension instructions"); -+ return NULL_RTX; -+ } -+ break; -+ -+ /* Performance Extension 2 */ -+ case NDS32_BUILTIN_PBSAD: -+ case NDS32_BUILTIN_PBSADA: -+ case NDS32_BUILTIN_BSE: -+ case NDS32_BUILTIN_BSP: -+ if (!TARGET_EXT_PERF2) -+ { -+ error ("don't support performance extension " -+ "version 2 instructions"); -+ return NULL_RTX; -+ } -+ break; - -- int fcode = DECL_FUNCTION_CODE (fndecl); -+ /* String Extension */ -+ case NDS32_BUILTIN_FFB: -+ case NDS32_BUILTIN_FFMISM: -+ case NDS32_BUILTIN_FLMISM: -+ if (!TARGET_EXT_STRING) -+ { -+ error ("don't support string extension instructions"); -+ return NULL_RTX; -+ } -+ break; - -+ default: -+ break; -+ } -+ -+ /* Since there are no result and operands, we can simply emit this rtx. */ - switch (fcode) - { -- /* Cache. */ -- case NDS32_BUILTIN_ISYNC: -- return nds32_expand_builtin_null_ftype_reg -- (CODE_FOR_unspec_volatile_isync, exp, target); - case NDS32_BUILTIN_ISB: -- /* Since there are no result and operands for isb instruciton, -- we can simply emit this rtx. */ - emit_insn (gen_unspec_volatile_isb ()); - return target; -- -- /* Register Transfer. */ -- case NDS32_BUILTIN_MFSR: -- return nds32_expand_builtin_reg_ftype_imm -- (CODE_FOR_unspec_volatile_mfsr, exp, target); -- case NDS32_BUILTIN_MFUSR: -- return nds32_expand_builtin_reg_ftype_imm -- (CODE_FOR_unspec_volatile_mfusr, exp, target); -- case NDS32_BUILTIN_MTSR: -- return nds32_expand_builtin_null_ftype_reg_imm -- (CODE_FOR_unspec_volatile_mtsr, exp, target); -- case NDS32_BUILTIN_MTUSR: -- return nds32_expand_builtin_null_ftype_reg_imm -- (CODE_FOR_unspec_volatile_mtusr, exp, target); -- -- /* Interrupt. */ -+ case NDS32_BUILTIN_DSB: -+ emit_insn (gen_unspec_dsb ()); -+ return target; -+ case NDS32_BUILTIN_MSYNC_ALL: -+ emit_insn (gen_unspec_msync_all ()); -+ return target; -+ case NDS32_BUILTIN_MSYNC_STORE: -+ emit_insn (gen_unspec_msync_store ()); -+ return target; - case NDS32_BUILTIN_SETGIE_EN: -- /* Since there are no result and operands for setgie.e instruciton, -- we can simply emit this rtx. */ - emit_insn (gen_unspec_volatile_setgie_en ()); -+ emit_insn (gen_unspec_dsb ()); - return target; - case NDS32_BUILTIN_SETGIE_DIS: -- /* Since there are no result and operands for setgie.d instruciton, -- we can simply emit this rtx. */ - emit_insn (gen_unspec_volatile_setgie_dis ()); -+ emit_insn (gen_unspec_dsb ()); -+ return target; -+ case NDS32_BUILTIN_GIE_DIS: -+ emit_insn (gen_unspec_volatile_setgie_dis ()); -+ emit_insn (gen_unspec_dsb ()); -+ return target; -+ case NDS32_BUILTIN_GIE_EN: -+ emit_insn (gen_unspec_volatile_setgie_en ()); -+ emit_insn (gen_unspec_dsb ()); -+ return target; -+ case NDS32_BUILTIN_SET_PENDING_SWINT: -+ emit_insn (gen_unspec_set_pending_swint ()); -+ return target; -+ case NDS32_BUILTIN_CLR_PENDING_SWINT: -+ emit_insn (gen_unspec_clr_pending_swint ()); -+ return target; -+ case NDS32_BUILTIN_CCTL_L1D_INVALALL: -+ emit_insn (gen_cctl_l1d_invalall()); -+ return target; -+ case NDS32_BUILTIN_CCTL_L1D_WBALL_ALVL: -+ emit_insn (gen_cctl_l1d_wball_alvl()); -+ return target; -+ 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; -+ case NDS32_BUILTIN_STANDBY_WAKE_GRANT: -+ emit_insn (gen_unspec_standby_wake_grant ()); -+ return target; -+ case NDS32_BUILTIN_STANDBY_WAKE_DONE: -+ emit_insn (gen_unspec_standby_wait_done ()); -+ return target; -+ case NDS32_BUILTIN_SETEND_BIG: -+ emit_insn (gen_unspec_setend_big ()); -+ return target; -+ case NDS32_BUILTIN_SETEND_LITTLE: -+ emit_insn (gen_unspec_setend_little ()); -+ return target; -+ case NDS32_BUILTIN_NOP: -+ emit_insn (gen_unspec_nop ()); -+ return target; -+ case NDS32_BUILTIN_SCHE_BARRIER: -+ emit_insn (gen_blockage ()); -+ return target; -+ case NDS32_BUILTIN_TLBOP_FLUA: -+ emit_insn (gen_unspec_tlbop_flua ()); -+ return target; -+ /* Instruction sequence protection */ -+ case NDS32_BUILTIN_SIGNATURE_BEGIN: -+ emit_insn (gen_unspec_signature_begin ()); -+ return target; -+ case NDS32_BUILTIN_SIGNATURE_END: -+ emit_insn (gen_unspec_signature_end ()); -+ return target; -+ case NDS32_BUILTIN_SCW: -+ return nds32_expand_scw_builtin (CODE_FOR_unspec_volatile_scw, -+ exp, target); -+ case NDS32_BUILTIN_SET_INT_PRIORITY: -+ return nds32_expand_priority_builtin (CODE_FOR_unspec_set_int_priority, -+ exp, target, -+ "__nds32__set_int_priority"); -+ case NDS32_BUILTIN_NO_HWLOOP: -+ emit_insn (gen_no_hwloop ()); - return target; -- - default: -- gcc_unreachable (); -+ break; - } - -+ /* Expand groups of builtins. */ -+ for (i = 0, d = bdesc_noarg; i < ARRAY_SIZE (bdesc_noarg); i++, d++) -+ if (d->code == fcode) -+ return nds32_expand_noarg_builtin (d->icode, target); -+ -+ for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++) -+ if (d->code == fcode) -+ return nds32_expand_unop_builtin (d->icode, exp, target, d->return_p); -+ -+ for (i = 0, d = bdesc_1argimm; i < ARRAY_SIZE (bdesc_1argimm); i++, d++) -+ if (d->code == fcode) -+ return nds32_expand_unopimm_builtin (d->icode, exp, target, -+ d->return_p, d->name); -+ -+ for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) -+ if (d->code == fcode) -+ return nds32_expand_binop_builtin (d->icode, exp, target, d->return_p); -+ -+ for (i = 0, d = bdesc_2argimm; i < ARRAY_SIZE (bdesc_2argimm); i++, d++) -+ if (d->code == fcode) -+ return nds32_expand_binopimm_builtin (d->icode, exp, target, -+ d->return_p, d->name); -+ -+ for (i = 0, d = bdesc_3arg; i < ARRAY_SIZE (bdesc_3arg); i++, d++) -+ if (d->code == fcode) -+ return nds32_expand_triop_builtin (d->icode, exp, target, d->return_p); -+ -+ for (i = 0, d = bdesc_3argimm; i < ARRAY_SIZE (bdesc_3argimm); i++, d++) -+ if (d->code == fcode) -+ return nds32_expand_triopimm_builtin (d->icode, exp, target, -+ d->return_p, d->name); -+ -+ for (i = 0, d = bdesc_load; i < ARRAY_SIZE (bdesc_load); i++, d++) -+ if (d->code == fcode) -+ return nds32_expand_builtin_load (d->icode, exp, target); -+ -+ for (i = 0, d = bdesc_store; i < ARRAY_SIZE (bdesc_store); i++, d++) -+ if (d->code == fcode) -+ return nds32_expand_builtin_store (d->icode, exp, target); -+ -+ for (i = 0, d = bdesc_cctl; i < ARRAY_SIZE (bdesc_cctl); i++, d++) -+ if (d->code == fcode) -+ return nds32_expand_cctl_builtin (d->icode, exp, target, -+ d->return_p, d->name); -+ - return NULL_RTX; - } - -+static GTY(()) tree nds32_builtin_decls[NDS32_BUILTIN_COUNT]; -+ -+/* Return the NDS32 builtin for CODE. */ -+tree -+nds32_builtin_decl_impl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) -+{ -+ if (code >= NDS32_BUILTIN_COUNT) -+ return error_mark_node; -+ -+ return nds32_builtin_decls[code]; -+} -+ -+void -+nds32_init_builtins_impl (void) -+{ -+#define ADD_NDS32_BUILTIN0(NAME, RET_TYPE, CODE) \ -+ nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] = \ -+ add_builtin_function ("__builtin_nds32_" NAME, \ -+ build_function_type_list (RET_TYPE##_type_node, \ -+ NULL_TREE), \ -+ NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE) -+ -+#define ADD_NDS32_BUILTIN1(NAME, RET_TYPE, ARG_TYPE, CODE) \ -+ nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] = \ -+ add_builtin_function ("__builtin_nds32_" NAME, \ -+ build_function_type_list (RET_TYPE##_type_node, \ -+ ARG_TYPE##_type_node, \ -+ NULL_TREE), \ -+ NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE) -+ -+#define ADD_NDS32_BUILTIN2(NAME, RET_TYPE, ARG_TYPE1, ARG_TYPE2, CODE) \ -+ nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] = \ -+ add_builtin_function ("__builtin_nds32_" NAME, \ -+ build_function_type_list (RET_TYPE##_type_node, \ -+ ARG_TYPE1##_type_node,\ -+ ARG_TYPE2##_type_node,\ -+ NULL_TREE), \ -+ NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE) -+ -+#define ADD_NDS32_BUILTIN3(NAME, RET_TYPE, ARG_TYPE1, ARG_TYPE2, ARG_TYPE3, CODE) \ -+ nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] = \ -+ add_builtin_function ("__builtin_nds32_" NAME, \ -+ build_function_type_list (RET_TYPE##_type_node, \ -+ ARG_TYPE1##_type_node,\ -+ ARG_TYPE2##_type_node,\ -+ ARG_TYPE3##_type_node,\ -+ NULL_TREE), \ -+ 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); -+ ADD_NDS32_BUILTIN0 ("isb", void, ISB); -+ ADD_NDS32_BUILTIN0 ("dsb", void, DSB); -+ ADD_NDS32_BUILTIN0 ("msync_all", void, MSYNC_ALL); -+ ADD_NDS32_BUILTIN0 ("msync_store", void, MSYNC_STORE); -+ -+ /* Register Transfer. */ -+ ADD_NDS32_BUILTIN1 ("mfsr", unsigned, integer, MFSR); -+ ADD_NDS32_BUILTIN1 ("mfusr", unsigned, integer, MFUSR); -+ ADD_NDS32_BUILTIN2 ("mtsr", void, unsigned, integer, MTSR); -+ ADD_NDS32_BUILTIN2 ("mtsr_isb", void, unsigned, integer, MTSR_ISB); -+ ADD_NDS32_BUILTIN2 ("mtsr_dsb", void, unsigned, integer, MTSR_DSB); -+ ADD_NDS32_BUILTIN2 ("mtusr", void, unsigned, integer, MTUSR); -+ -+ /* FPU Register Transfer. */ -+ ADD_NDS32_BUILTIN0 ("fmfcsr", unsigned, FMFCSR); -+ ADD_NDS32_BUILTIN1 ("fmtcsr", void, unsigned, FMTCSR); -+ ADD_NDS32_BUILTIN0 ("fmfcfg", unsigned, FMFCFG); -+ ADD_NDS32_BUILTIN2 ("fcpyss", float, float, float, FCPYSS); -+ ADD_NDS32_BUILTIN2 ("fcpynss", float, float, float, FCPYNSS); -+ ADD_NDS32_BUILTIN2 ("fcpysd", double, double, double, FCPYSD); -+ ADD_NDS32_BUILTIN2 ("fcpynsd", double, double, double, FCPYNSD); -+ -+ /* Interrupt. */ -+ ADD_NDS32_BUILTIN0 ("setgie_en", void, SETGIE_EN); -+ ADD_NDS32_BUILTIN0 ("setgie_dis", void, SETGIE_DIS); -+ ADD_NDS32_BUILTIN0 ("gie_en", void, GIE_EN); -+ ADD_NDS32_BUILTIN0 ("gie_dis", void, GIE_DIS); -+ ADD_NDS32_BUILTIN1 ("enable_int", void, integer, ENABLE_INT); -+ ADD_NDS32_BUILTIN1 ("disable_int", void, integer, DISABLE_INT); -+ ADD_NDS32_BUILTIN0 ("set_pending_swint", void, SET_PENDING_SWINT); -+ ADD_NDS32_BUILTIN0 ("clr_pending_swint", void, CLR_PENDING_SWINT); -+ ADD_NDS32_BUILTIN0 ("get_all_pending_int", unsigned, GET_ALL_PENDING_INT); -+ ADD_NDS32_BUILTIN1 ("get_pending_int", unsigned, integer, GET_PENDING_INT); -+ ADD_NDS32_BUILTIN1 ("get_int_priority", unsigned, integer, GET_INT_PRIORITY); -+ ADD_NDS32_BUILTIN2 ("set_int_priority", void, integer, integer, -+ SET_INT_PRIORITY); -+ ADD_NDS32_BUILTIN1 ("clr_pending_hwint", void, integer, CLR_PENDING_HWINT); -+ ADD_NDS32_BUILTIN1 ("set_trig_level", void, integer, SET_TRIG_LEVEL); -+ ADD_NDS32_BUILTIN1 ("set_trig_edge", void, integer, SET_TRIG_EDGE); -+ ADD_NDS32_BUILTIN1 ("get_trig_type", unsigned, integer, GET_TRIG_TYPE); -+ -+ /* Load and Store */ -+ ADD_NDS32_BUILTIN1 ("llw", unsigned, ptr_uint, LLW); -+ ADD_NDS32_BUILTIN1 ("lwup", unsigned, ptr_uint, LWUP); -+ ADD_NDS32_BUILTIN1 ("lbup", char, ptr_uchar, LBUP); -+ ADD_NDS32_BUILTIN2 ("scw", unsigned, ptr_uint, unsigned, SCW); -+ ADD_NDS32_BUILTIN2 ("swup", void, ptr_uint, unsigned, SWUP); -+ ADD_NDS32_BUILTIN2 ("sbup", void, ptr_uchar, char, SBUP); -+ -+ /* CCTL */ -+ ADD_NDS32_BUILTIN0 ("cctl_l1d_invalall", void, CCTL_L1D_INVALALL); -+ ADD_NDS32_BUILTIN0 ("cctl_l1d_wball_alvl", void, CCTL_L1D_WBALL_ALVL); -+ ADD_NDS32_BUILTIN0 ("cctl_l1d_wball_one_lvl", void, CCTL_L1D_WBALL_ONE_LVL); -+ ADD_NDS32_BUILTIN2 ("cctl_va_lck", void, integer, ptr_uint, CCTL_VA_LCK); -+ ADD_NDS32_BUILTIN2 ("cctl_idx_wbinval", void, integer, unsigned, -+ CCTL_IDX_WBINVAL); -+ ADD_NDS32_BUILTIN2 ("cctl_va_wbinval_l1", void, integer, ptr_uint, -+ CCTL_VA_WBINVAL_L1); -+ ADD_NDS32_BUILTIN2 ("cctl_va_wbinval_la", void, integer, ptr_uint, -+ CCTL_VA_WBINVAL_LA); -+ ADD_NDS32_BUILTIN2 ("cctl_idx_read", unsigned, integer, unsigned, -+ CCTL_IDX_READ); -+ ADD_NDS32_BUILTIN3 ("cctl_idx_write", void, integer, unsigned, unsigned, -+ CCTL_IDX_WRITE); -+ -+ /* PREFETCH */ -+ ADD_NDS32_BUILTIN3 ("dpref_qw", void, ptr_uchar, unsigned, integer, DPREF_QW); -+ ADD_NDS32_BUILTIN3 ("dpref_hw", void, ptr_ushort, unsigned, integer, -+ DPREF_HW); -+ ADD_NDS32_BUILTIN3 ("dpref_w", void, ptr_uint, unsigned, integer, DPREF_W); -+ ADD_NDS32_BUILTIN3 ("dpref_dw", void, ptr_ulong, unsigned, integer, DPREF_DW); -+ -+ /* Performance Extension */ -+ ADD_NDS32_BUILTIN1 ("pe_abs", integer, integer, ABS); -+ ADD_NDS32_BUILTIN2 ("pe_ave", integer, integer, integer, AVE); -+ ADD_NDS32_BUILTIN2 ("pe_bclr", unsigned, unsigned, unsigned, BCLR); -+ ADD_NDS32_BUILTIN2 ("pe_bset", unsigned, unsigned, unsigned, BSET); -+ ADD_NDS32_BUILTIN2 ("pe_btgl", unsigned, unsigned, unsigned, BTGL); -+ ADD_NDS32_BUILTIN2 ("pe_btst", unsigned, unsigned, unsigned, BTST); -+ ADD_NDS32_BUILTIN2 ("pe_clip", unsigned, integer, unsigned, CLIP); -+ ADD_NDS32_BUILTIN2 ("pe_clips", integer, integer, unsigned, CLIPS); -+ ADD_NDS32_BUILTIN1 ("pe_clz", unsigned, unsigned, CLZ); -+ ADD_NDS32_BUILTIN1 ("pe_clo", unsigned, unsigned, CLO); -+ -+ /* Performance Extension 2 */ -+ ADD_NDS32_BUILTIN3 ("pe2_bse", void, ptr_uint, unsigned, ptr_uint, BSE); -+ ADD_NDS32_BUILTIN3 ("pe2_bsp", void, ptr_uint, unsigned, ptr_uint, BSP); -+ ADD_NDS32_BUILTIN2 ("pe2_pbsad", unsigned, unsigned, unsigned, PBSAD); -+ ADD_NDS32_BUILTIN3 ("pe2_pbsada", unsigned, unsigned, unsigned, unsigned, -+ PBSADA); -+ -+ /* String Extension */ -+ ADD_NDS32_BUILTIN2 ("se_ffb", integer, unsigned, unsigned, FFB); -+ 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); -+ -+ /* Swap */ -+ ADD_NDS32_BUILTIN1 ("wsbh", unsigned, unsigned, WSBH); -+ -+ /* System */ -+ ADD_NDS32_BUILTIN2 ("svs", unsigned, integer, integer, SVS); -+ ADD_NDS32_BUILTIN2 ("sva", unsigned, integer, integer, SVA); -+ ADD_NDS32_BUILTIN1 ("jr_itoff", void, unsigned, JR_ITOFF); -+ ADD_NDS32_BUILTIN1 ("jr_toff", void, unsigned, JR_TOFF); -+ ADD_NDS32_BUILTIN1 ("jral_iton", void, unsigned, JRAL_ITON); -+ ADD_NDS32_BUILTIN1 ("jral_ton", void, unsigned, JRAL_TON); -+ ADD_NDS32_BUILTIN1 ("ret_itoff", void, unsigned, RET_ITOFF); -+ ADD_NDS32_BUILTIN1 ("ret_toff", void, unsigned, RET_TOFF); -+ ADD_NDS32_BUILTIN0 ("standby_no_wake_grant", void, STANDBY_NO_WAKE_GRANT); -+ ADD_NDS32_BUILTIN0 ("standby_wake_grant", void, STANDBY_WAKE_GRANT); -+ ADD_NDS32_BUILTIN0 ("standby_wait_done", void, STANDBY_WAKE_DONE); -+ ADD_NDS32_BUILTIN1 ("break", void, unsigned, BREAK); -+ ADD_NDS32_BUILTIN1 ("syscall", void, unsigned, SYSCALL); -+ ADD_NDS32_BUILTIN0 ("nop", void, NOP); -+ ADD_NDS32_BUILTIN0 ("get_current_sp", unsigned, GET_CURRENT_SP); -+ ADD_NDS32_BUILTIN1 ("set_current_sp", void, unsigned, SET_CURRENT_SP); -+ ADD_NDS32_BUILTIN2 ("teqz", void, unsigned, unsigned, TEQZ); -+ ADD_NDS32_BUILTIN2 ("tnez", void, unsigned, unsigned, TNEZ); -+ ADD_NDS32_BUILTIN1 ("trap", void, unsigned, TRAP); -+ ADD_NDS32_BUILTIN0 ("return_address", unsigned, RETURN_ADDRESS); -+ ADD_NDS32_BUILTIN0 ("setend_big", void, SETEND_BIG); -+ ADD_NDS32_BUILTIN0 ("setend_little", void, SETEND_LITTLE); -+ -+ /* Schedule Barrier */ -+ ADD_NDS32_BUILTIN0 ("schedule_barrier", void, SCHE_BARRIER); -+ -+ /* TLBOP */ -+ ADD_NDS32_BUILTIN1 ("tlbop_trd", void, unsigned, TLBOP_TRD); -+ ADD_NDS32_BUILTIN1 ("tlbop_twr", void, unsigned, TLBOP_TWR); -+ ADD_NDS32_BUILTIN1 ("tlbop_rwr", void, unsigned, TLBOP_RWR); -+ ADD_NDS32_BUILTIN1 ("tlbop_rwlk", void, unsigned, TLBOP_RWLK); -+ ADD_NDS32_BUILTIN1 ("tlbop_unlk", void, unsigned, TLBOP_UNLK); -+ ADD_NDS32_BUILTIN1 ("tlbop_pb", unsigned, unsigned, TLBOP_PB); -+ ADD_NDS32_BUILTIN1 ("tlbop_inv", void, unsigned, TLBOP_INV); -+ ADD_NDS32_BUILTIN0 ("tlbop_flua", void, TLBOP_FLUA); -+ -+ /* Unaligned Load/Store */ -+ ADD_NDS32_BUILTIN1 ("unaligned_load_hw", short_unsigned, ptr_ushort, -+ UALOAD_HW); -+ ADD_NDS32_BUILTIN1 ("unaligned_load_w", unsigned, ptr_uint, UALOAD_W); -+ ADD_NDS32_BUILTIN1 ("unaligned_load_dw", long_long_unsigned, ptr_ulong, -+ UALOAD_DW); -+ ADD_NDS32_BUILTIN2 ("unaligned_store_hw", void, ptr_ushort, short_unsigned, -+ UASTORE_HW); -+ ADD_NDS32_BUILTIN2 ("unaligned_store_w", void, ptr_uint, unsigned, UASTORE_W); -+ ADD_NDS32_BUILTIN2 ("unaligned_store_dw", void, ptr_ulong, long_long_unsigned, -+ UASTORE_DW); -+ ADD_NDS32_BUILTIN0 ("unaligned_feature", unsigned, UNALIGNED_FEATURE); -+ ADD_NDS32_BUILTIN0 ("enable_unaligned", void, ENABLE_UNALIGNED); -+ ADD_NDS32_BUILTIN0 ("disable_unaligned", void, DISABLE_UNALIGNED); -+ -+ /* Instruction sequence protection */ -+ ADD_NDS32_BUILTIN0 ("signature_begin", void, SIGNATURE_BEGIN); -+ ADD_NDS32_BUILTIN0 ("signature_end", void, SIGNATURE_END); -+ -+ /* 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); -+ -+ /* The builtin turn off hwloop optimization. */ -+ ADD_NDS32_BUILTIN0 ("no_ext_zol", void, NO_HWLOOP); -+ -+ /* 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 53876c5..6f8b3eb 100644 ---- a/gcc/config/nds32/nds32-intrinsic.md -+++ b/gcc/config/nds32/nds32-intrinsic.md -@@ -40,6 +40,26 @@ - (set_attr "length" "4")] - ) - -+(define_expand "mtsr_isb" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "immediate_operand" ""))] -+ "" -+{ -+ emit_insn (gen_unspec_volatile_mtsr (operands[0], operands[1])); -+ emit_insn (gen_unspec_volatile_isb()); -+ DONE; -+}) -+ -+(define_expand "mtsr_dsb" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "immediate_operand" ""))] -+ "" -+{ -+ emit_insn (gen_unspec_volatile_mtsr (operands[0], operands[1])); -+ emit_insn (gen_unspec_dsb()); -+ DONE; -+}) -+ - (define_insn "unspec_volatile_mtsr" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTSR)] -@@ -58,6 +78,74 @@ - (set_attr "length" "4")] - ) - -+;; FPU Register Transfer. -+ -+(define_insn "unspec_fcpynsd" -+ [(set (match_operand:DF 0 "register_operand" "=f") -+ (unspec:DF [(match_operand:DF 1 "register_operand" "f") -+ (match_operand:DF 2 "register_operand" "f")] UNSPEC_FCPYNSD))] -+ "" -+ "fcpynsd\t%0, %1, %2" -+ [(set_attr "type" "misc") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_fcpynss" -+ [(set (match_operand:SF 0 "register_operand" "=f") -+ (unspec:SF [(match_operand:SF 1 "register_operand" "f") -+ (match_operand:SF 2 "register_operand" "f")] UNSPEC_FCPYNSS))] -+ "" -+ "fcpynss\t%0, %1, %2" -+ [(set_attr "type" "misc") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_fcpysd" -+ [(set (match_operand:DF 0 "register_operand" "=f") -+ (unspec:DF [(match_operand:DF 1 "register_operand" "f") -+ (match_operand:DF 2 "register_operand" "f")] UNSPEC_FCPYSD))] -+ "" -+ "fcpysd\t%0, %1, %2" -+ [(set_attr "type" "misc") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_fcpyss" -+ [(set (match_operand:SF 0 "register_operand" "=f") -+ (unspec:SF [(match_operand:SF 1 "register_operand" "f") -+ (match_operand:SF 2 "register_operand" "f")] UNSPEC_FCPYSS))] -+ "" -+ "fcpyss\t%0, %1, %2" -+ [(set_attr "type" "misc") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_fmfcsr" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_FMFCSR))] -+ "" -+ "fmfcsr\t%0" -+ [(set_attr "type" "misc") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_fmtcsr" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_FMTCSR)] -+ "" -+ "fmtcsr\t%0" -+ [(set_attr "type" "misc") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_fmfcfg" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_FMFCFG))] -+ "" -+ "fmfcfg\t%0" -+ [(set_attr "type" "misc") -+ (set_attr "length" "4")] -+) -+ - ;; ------------------------------------------------------------------------ - - ;; Interrupt Instructions. -@@ -76,6 +164,445 @@ - [(set_attr "type" "misc")] - ) - -+(define_expand "unspec_enable_int" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_ENABLE_INT)] -+ "" -+{ -+ rtx system_reg; -+ rtx temp_reg = gen_reg_rtx (SImode); -+ -+ /* Set system register form nds32_intrinsic_register_names[]. */ -+ if ((INTVAL (operands[0]) >= NDS32_INT_H16) -+ && (INTVAL (operands[0]) <= NDS32_INT_H31)) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_MASK2__); -+ operands[0] = GEN_INT (1 << (INTVAL (operands[0]))); -+ } -+ else if ((INTVAL (operands[0]) >= NDS32_INT_H32) -+ && (INTVAL (operands[0]) <= NDS32_INT_H63)) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_MASK3__); -+ operands[0] = GEN_INT (1 << (INTVAL (operands[0]) - 32)); -+ } -+ else -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_MASK__); -+ -+ if (INTVAL (operands[0]) == NDS32_INT_SWI) -+ operands[0] = GEN_INT (1 << 16); -+ else if ((INTVAL (operands[0]) >= NDS32_INT_ALZ) -+ && (INTVAL (operands[0]) <= NDS32_INT_DSSIM)) -+ operands[0] = GEN_INT (1 << (INTVAL (operands[0]) - 4)); -+ else -+ operands[0] = GEN_INT (1 << (INTVAL (operands[0]))); -+ } -+ -+ emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); -+ emit_insn (gen_iorsi3 (temp_reg, temp_reg, operands[0])); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ DONE; -+}) -+ -+(define_expand "unspec_disable_int" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_DISABLE_INT)] -+ "" -+{ -+ rtx system_reg; -+ rtx temp_reg = gen_reg_rtx (SImode); -+ -+ /* Set system register form nds32_intrinsic_register_names[]. */ -+ if ((INTVAL (operands[0]) >= NDS32_INT_H16) -+ && (INTVAL (operands[0]) <= NDS32_INT_H31)) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_MASK2__); -+ operands[0] = GEN_INT (~(1 << INTVAL (operands[0]))); -+ } -+ else if ((INTVAL (operands[0]) >= NDS32_INT_H32) -+ && (INTVAL (operands[0]) <= NDS32_INT_H63)) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_MASK3__); -+ operands[0] = GEN_INT (~(1 << (INTVAL (operands[0]) - 32))); -+ } -+ else -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_MASK__); -+ -+ if (INTVAL (operands[0]) == NDS32_INT_SWI) -+ operands[0] = GEN_INT (~(1 << 16)); -+ else if ((INTVAL (operands[0]) >= NDS32_INT_ALZ) -+ && (INTVAL (operands[0]) <= NDS32_INT_DSSIM)) -+ operands[0] = GEN_INT (~(1 << (INTVAL (operands[0]) - 4))); -+ else -+ operands[0] = GEN_INT (~(1 << INTVAL (operands[0]))); -+ } -+ -+ emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); -+ emit_insn (gen_andsi3 (temp_reg, temp_reg, operands[0])); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ DONE; -+}) -+ -+(define_expand "unspec_set_pending_swint" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SET_PENDING_SWINT)] -+ "" -+{ -+ /* Get $INT_PEND system register form nds32_intrinsic_register_names[] */ -+ rtx system_reg = GEN_INT (__NDS32_REG_INT_PEND__); -+ rtx temp_reg = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); -+ emit_insn (gen_iorsi3 (temp_reg, temp_reg, GEN_INT (65536))); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ DONE; -+}) -+ -+(define_expand "unspec_clr_pending_swint" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CLR_PENDING_SWINT)] -+ "" -+{ -+ /* Get $INT_PEND system register form nds32_intrinsic_register_names[] */ -+ rtx system_reg = GEN_INT (__NDS32_REG_INT_PEND__); -+ rtx temp_reg = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); -+ emit_insn (gen_andsi3 (temp_reg, temp_reg, GEN_INT (~(1 << 16)))); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ DONE; -+}) -+ -+(define_expand "unspec_clr_pending_hwint" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_CLR_PENDING_HWINT)] -+ "" -+{ -+ rtx system_reg = NULL_RTX; -+ rtx temp_reg = gen_reg_rtx (SImode); -+ rtx clr_hwint; -+ unsigned offset = 0; -+ -+ /* Set system register form nds32_intrinsic_register_names[]. */ -+ if ((INTVAL (operands[0]) >= NDS32_INT_H0) -+ && (INTVAL (operands[0]) <= NDS32_INT_H15)) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PEND__); -+ } -+ else if ((INTVAL (operands[0]) >= NDS32_INT_H16) -+ && (INTVAL (operands[0]) <= NDS32_INT_H31)) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PEND2__); -+ } -+ else if ((INTVAL (operands[0]) >= NDS32_INT_H32) -+ && (INTVAL (operands[0]) <= NDS32_INT_H63)) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PEND3__); -+ offset = 32; -+ } -+ else -+ error ("__nds32__clr_pending_hwint not support NDS32_INT_SWI," -+ " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); -+ -+ /* $INT_PEND type is write one clear. */ -+ clr_hwint = GEN_INT (1 << (INTVAL (operands[0]) - offset)); -+ -+ if (system_reg != NULL_RTX) -+ { -+ emit_move_insn (temp_reg, clr_hwint); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ } -+ DONE; -+}) -+ -+(define_expand "unspec_get_all_pending_int" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_GET_ALL_PENDING_INT))] -+ "" -+{ -+ rtx system_reg = GEN_INT (__NDS32_REG_INT_PEND__); -+ emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ DONE; -+}) -+ -+(define_expand "unspec_get_pending_int" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_GET_PENDING_INT))] -+ "" -+{ -+ rtx system_reg = NULL_RTX; -+ -+ /* Set system register form nds32_intrinsic_register_names[]. */ -+ if ((INTVAL (operands[1]) >= NDS32_INT_H0) -+ && (INTVAL (operands[1]) <= NDS32_INT_H15)) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PEND__); -+ operands[2] = GEN_INT (31 - INTVAL (operands[1])); -+ } -+ else if (INTVAL (operands[1]) == NDS32_INT_SWI) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PEND__); -+ operands[2] = GEN_INT (15); -+ } -+ else if ((INTVAL (operands[1]) >= NDS32_INT_H16) -+ && (INTVAL (operands[1]) <= NDS32_INT_H31)) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PEND2__); -+ operands[2] = GEN_INT (31 - INTVAL (operands[1])); -+ } -+ else if ((INTVAL (operands[1]) >= NDS32_INT_H32) -+ && (INTVAL (operands[1]) <= NDS32_INT_H63)) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PEND3__); -+ operands[2] = GEN_INT (31 - (INTVAL (operands[1]) - 32)); -+ } -+ else -+ error ("get_pending_int not support NDS32_INT_ALZ," -+ " NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); -+ -+ /* mfsr op0, sytem_reg */ -+ if (system_reg != NULL_RTX) -+ { -+ emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); -+ emit_insn (gen_ashlsi3 (operands[0], operands[0], operands[2])); -+ emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (31))); -+ emit_insn (gen_unspec_dsb ()); -+ } -+ DONE; -+}) -+ -+(define_expand "unspec_set_int_priority" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "") -+ (match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_SET_INT_PRIORITY)] -+ "" -+{ -+ rtx system_reg = NULL_RTX; -+ rtx priority = NULL_RTX; -+ rtx mask = NULL_RTX; -+ rtx temp_reg = gen_reg_rtx (SImode); -+ rtx mask_reg = gen_reg_rtx (SImode); -+ rtx set_reg = gen_reg_rtx (SImode); -+ unsigned offset = 0; -+ -+ /* Get system register form nds32_intrinsic_register_names[]. */ -+ if (INTVAL (operands[0]) <= NDS32_INT_H15) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PRI__); -+ offset = 0; -+ } -+ else if (INTVAL (operands[0]) >= NDS32_INT_H16 -+ && INTVAL (operands[0]) <= NDS32_INT_H31) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PRI2__); -+ /* The $INT_PRI2 first bit correspond to H16, so need -+ subtract 16. */ -+ offset = 16; -+ } -+ else if (INTVAL (operands[0]) >= NDS32_INT_H32 -+ && INTVAL (operands[0]) <= NDS32_INT_H47) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PRI3__); -+ /* The $INT_PRI3 first bit correspond to H32, so need -+ subtract 32. */ -+ offset = 32; -+ } -+ else if (INTVAL (operands[0]) >= NDS32_INT_H48 -+ && INTVAL (operands[0]) <= NDS32_INT_H63) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PRI4__); -+ /* The $INT_PRI3 first bit correspond to H48, so need -+ subtract 48. */ -+ offset = 48; -+ } -+ else -+ error ("set_int_priority not support NDS32_INT_SWI," -+ " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); -+ -+ mask = GEN_INT (~(3 << 2 * (INTVAL (operands[0]) - offset))); -+ priority = GEN_INT ((int) (INTVAL (operands[1]) -+ << ((INTVAL (operands[0]) - offset) * 2))); -+ -+ if (system_reg != NULL_RTX) -+ { -+ emit_move_insn (mask_reg, mask); -+ emit_move_insn (set_reg, priority); -+ emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); -+ emit_insn (gen_andsi3 (temp_reg, temp_reg, mask_reg)); -+ emit_insn (gen_iorsi3 (temp_reg, temp_reg, set_reg)); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ } -+ DONE; -+}) -+ -+(define_expand "unspec_get_int_priority" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_GET_INT_PRIORITY))] -+ "" -+{ -+ rtx system_reg = NULL_RTX; -+ rtx priority = NULL_RTX; -+ unsigned offset = 0; -+ -+ /* Get system register form nds32_intrinsic_register_names[] */ -+ if (INTVAL (operands[1]) <= NDS32_INT_H15) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PRI__); -+ offset = 0; -+ } -+ else if (INTVAL (operands[1]) >= NDS32_INT_H16 -+ && INTVAL (operands[1]) <= NDS32_INT_H31) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PRI2__); -+ /* The $INT_PRI2 first bit correspond to H16, so need -+ subtract 16. */ -+ offset = 16; -+ } -+ else if (INTVAL (operands[1]) >= NDS32_INT_H32 -+ && INTVAL (operands[1]) <= NDS32_INT_H47) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PRI3__); -+ /* The $INT_PRI3 first bit correspond to H32, so need -+ subtract 32. */ -+ offset = 32; -+ } -+ else if (INTVAL (operands[1]) >= NDS32_INT_H48 -+ && INTVAL (operands[1]) <= NDS32_INT_H63) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_PRI4__); -+ /* The $INT_PRI4 first bit correspond to H48, so need -+ subtract 48. */ -+ offset = 48; -+ } -+ else -+ error ("set_int_priority not support NDS32_INT_SWI," -+ " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); -+ -+ priority = GEN_INT (31 - 2 * (INTVAL (operands[1]) - offset)); -+ -+ if (system_reg != NULL_RTX) -+ { -+ emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); -+ emit_insn (gen_ashlsi3 (operands[0], operands[0], priority)); -+ emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (30))); -+ emit_insn (gen_unspec_dsb ()); -+ } -+ DONE; -+}) -+ -+(define_expand "unspec_set_trig_level" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_SET_TRIG_LEVEL)] -+ "" -+{ -+ rtx system_reg = NULL_RTX; -+ rtx temp_reg = gen_reg_rtx (SImode); -+ rtx set_level; -+ unsigned offset = 0; -+ -+ if (INTVAL (operands[0]) >= NDS32_INT_H0 -+ && INTVAL (operands[0]) <= NDS32_INT_H31) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER__); -+ offset = 0; -+ } -+ else if (INTVAL (operands[0]) >= NDS32_INT_H32 -+ && INTVAL (operands[0]) <= NDS32_INT_H63) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER2__); -+ offset = 32; -+ } -+ else -+ error ("__nds32__set_trig_type_level not support NDS32_INT_SWI," -+ " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); -+ -+ if (system_reg != NULL_RTX) -+ { -+ /* TRIGGER register, 0 mean level triggered and 1 mean edge triggered. */ -+ set_level = GEN_INT (~(1 << (INTVAL (operands[0]) - offset))); -+ -+ emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); -+ emit_insn (gen_andsi3 (temp_reg, temp_reg, set_level)); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ } -+ DONE; -+}) -+ -+(define_expand "unspec_set_trig_edge" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_SET_TRIG_EDGE)] -+ "" -+{ -+ rtx system_reg = NULL_RTX; -+ rtx temp_reg = gen_reg_rtx (SImode); -+ rtx set_level; -+ unsigned offset = 0; -+ -+ if (INTVAL (operands[0]) >= NDS32_INT_H0 -+ && INTVAL (operands[0]) <= NDS32_INT_H31) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER__); -+ offset = 0; -+ } -+ else if (INTVAL (operands[0]) >= NDS32_INT_H32 -+ && INTVAL (operands[0]) <= NDS32_INT_H63) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER2__); -+ offset = 32; -+ } -+ else -+ error ("__nds32__set_trig_type_edge not support NDS32_INT_SWI," -+ " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); -+ -+ if (system_reg != NULL_RTX) -+ { -+ /* TRIGGER register, 0 mean level triggered and 1 mean edge triggered. */ -+ set_level = GEN_INT ((1 << (INTVAL (operands[0]) - offset))); -+ -+ emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); -+ emit_insn (gen_iorsi3 (temp_reg, temp_reg, set_level)); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ } -+ DONE; -+}) -+ -+(define_expand "unspec_get_trig_type" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_GET_TRIG_TYPE))] -+ "" -+{ -+ rtx system_reg = NULL_RTX; -+ rtx trig_type; -+ unsigned offset = 0; -+ -+ if (INTVAL (operands[1]) >= NDS32_INT_H0 -+ && INTVAL (operands[1]) <= NDS32_INT_H31) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER__); -+ offset = 0; -+ } -+ else if (INTVAL (operands[1]) >= NDS32_INT_H32 -+ && INTVAL (operands[1]) <= NDS32_INT_H63) -+ { -+ system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER2__); -+ offset = 32; -+ } -+ else -+ error ("__nds32__get_trig_type not support NDS32_INT_SWI," -+ " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM"); -+ -+ if (system_reg != NULL_RTX) -+ { -+ trig_type = GEN_INT (31 - (INTVAL (operands[1]) - offset)); -+ -+ emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); -+ emit_insn (gen_ashlsi3 (operands[0], operands[0], trig_type)); -+ emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (31))); -+ emit_insn (gen_unspec_dsb ()); -+ } -+ DONE; -+}) -+ - ;; ------------------------------------------------------------------------ - - ;; Cache Synchronization Instructions -@@ -84,7 +611,7 @@ - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_ISYNC)] - "" - "isync\t%0" -- [(set_attr "type" "misc")] -+ [(set_attr "type" "mmu")] - ) - - (define_insn "unspec_volatile_isb" -@@ -94,4 +621,1077 @@ - [(set_attr "type" "misc")] - ) - -+(define_insn "unspec_dsb" -+ [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_DSB)] -+ "" -+ "dsb" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_msync" -+ [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_MSYNC)] -+ "" -+ "msync\t%0" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_msync_all" -+ [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_MSYNC_ALL)] -+ "" -+ "msync\tall" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_msync_store" -+ [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_MSYNC_STORE)] -+ "" -+ "msync\tstore" -+ [(set_attr "type" "misc")] -+) -+ -+;; Load and Store -+ -+(define_insn "unspec_volatile_llw" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")))] UNSPEC_VOLATILE_LLW))] -+ "" -+ "llw\t%0, [%1 + %2]" -+ [(set_attr "length" "4")] -+) -+ -+(define_insn "unspec_lwup" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")))] UNSPEC_LWUP))] -+ "" -+ "lwup\t%0, [%1 + %2]" -+ [(set_attr "length" "4")] -+) -+ -+(define_insn "unspec_lbup" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")))] UNSPEC_LBUP))] -+ "" -+ "lbup\t%0, [%1 + %2]" -+ [(set_attr "length" "4")] -+) -+ -+(define_insn "unspec_volatile_scw" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r"))) -+ (match_operand:SI 3 "register_operand" "0")] UNSPEC_VOLATILE_SCW))] -+ "" -+ "scw\t%0, [%1 + %2]" -+ [(set_attr "length" "4")] -+) -+ -+(define_insn "unspec_swup" -+ [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r") -+ (match_operand:SI 1 "register_operand" "r"))) -+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")] UNSPEC_SWUP))] -+ "" -+ "swup\t%2, [%0 + %1]" -+ [(set_attr "length" "4")] -+) -+ -+(define_insn "unspec_sbup" -+ [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r") -+ (match_operand:SI 1 "register_operand" "r"))) -+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")] UNSPEC_SBUP))] -+ "" -+ "sbup\t%2, [%0 + %1]" -+ [(set_attr "length" "4")] -+) -+ -+;; CCTL -+ -+(define_insn "cctl_l1d_invalall" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CCTL_L1D_INVALALL)] -+ "" -+ "cctl\tL1D_INVALALL" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "cctl_l1d_wball_alvl" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CCTL_L1D_WBALL_ALVL)] -+ "" -+ "cctl\tL1D_WBALL, alevel" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "cctl_l1d_wball_one_lvl" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CCTL_L1D_WBALL_ONE_LVL)] -+ "" -+ "cctl\tL1D_WBALL, 1level" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "cctl_idx_read" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i") -+ (match_operand:SI 2 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_IDX_READ))] -+ "" -+ "cctl\t%0, %2, %X1" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "cctl_idx_write" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i") -+ (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_IDX_WRITE)] -+ "" -+ "cctl\t%1, %2, %W0" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "cctl_va_wbinval_l1" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i") -+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_VA_WBINVAL_L1)] -+ "" -+ "cctl\t%1, %U0, 1level" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "cctl_va_wbinval_la" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i") -+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_VA_WBINVAL_LA)] -+ "" -+ "cctl\t%1, %U0, alevel" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "cctl_idx_wbinval" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i") -+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_IDX_WBINVAL)] -+ "" -+ "cctl\t%1, %T0" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "cctl_va_lck" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i") -+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_VA_LCK)] -+ "" -+ "cctl\t%1, %R0" -+ [(set_attr "type" "mmu")] -+) -+ -+;;PREFETCH -+ -+(define_insn "prefetch_qw" -+ [(unspec_volatile:QI [(match_operand:SI 0 "register_operand" "r") -+ (match_operand:SI 1 "nonmemory_operand" "r") -+ (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_DPREF_QW)] -+ "" -+ "dpref\t%Z2, [%0 + %1]" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "prefetch_hw" -+ [(unspec_volatile:HI [(match_operand:SI 0 "register_operand" "r") -+ (match_operand:SI 1 "nonmemory_operand" "r") -+ (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_DPREF_HW)] -+ "" -+ "dpref\t%Z2, [%0 + (%1<<1)]" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "prefetch_w" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" " r, r") -+ (match_operand:SI 1 "nonmemory_operand" "Is15, r") -+ (match_operand:SI 2 "immediate_operand" " i, i")] UNSPEC_VOLATILE_DPREF_W)] -+ "" -+ "@ -+ dprefi.w\t%Z2, [%0 + %1] -+ dpref\t%Z2, [%0 + (%1<<2)]" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "prefetch_dw" -+ [(unspec_volatile:DI [(match_operand:SI 0 "register_operand" " r, r") -+ (match_operand:SI 1 "nonmemory_operand" "Is15, r") -+ (match_operand:SI 2 "immediate_operand" " i, i")] UNSPEC_VOLATILE_DPREF_DW)] -+ "" -+ "@ -+ dprefi.d\t%Z2, [%0 + %1] -+ dpref\t%Z2, [%0 + (%1<<3)]" -+ [(set_attr "type" "misc")] -+) -+ -+;; Performance Extension -+ -+(define_expand "unspec_ave" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "register_operand" "")] -+ "" -+{ -+ emit_insn (gen_ave (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_expand "unspec_bclr" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "immediate_operand" "")] -+ "" -+{ -+ unsigned HOST_WIDE_INT val = ~(1u << UINTVAL (operands[2])); -+ emit_insn (gen_andsi3 (operands[0], operands[1], gen_int_mode (val, SImode))); -+ DONE; -+}) -+ -+(define_expand "unspec_bset" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "immediate_operand" "")] -+ "" -+{ -+ unsigned HOST_WIDE_INT val = 1u << UINTVAL (operands[2]); -+ emit_insn (gen_iorsi3 (operands[0], operands[1], gen_int_mode (val, SImode))); -+ DONE; -+}) -+ -+(define_expand "unspec_btgl" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "immediate_operand" "")] -+ "" -+{ -+ unsigned HOST_WIDE_INT val = 1u << UINTVAL (operands[2]); -+ emit_insn (gen_xorsi3 (operands[0], operands[1], gen_int_mode (val, SImode))); -+ DONE; -+}) -+ -+(define_expand "unspec_btst" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "immediate_operand" "")] -+ "" -+{ -+ emit_insn (gen_btst (operands[0], operands[1], operands[2])); -+ DONE; -+}) -+ -+(define_insn "unspec_clip" -+ [(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))] -+ "" -+ "clip\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_clips" -+ [(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))] -+ "" -+ "clips\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_clo" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_CLO))] -+ "" -+ "clo\t%0, %1" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_ssabssi2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (ss_abs:SI (match_operand:SI 1 "register_operand" "r")))] -+ "" -+ "abs\t%0, %1" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+;; Performance extension 2 -+ -+(define_insn "unspec_pbsad" -+ [(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_PBSAD))] -+ "" -+ "pbsad\t%0, %1, %2" -+ [(set_attr "type" "pbsad") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_pbsada" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "0") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "r")] UNSPEC_PBSADA))] -+ "" -+ "pbsada\t%0, %2, %3" -+ [(set_attr "type" "pbsada") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "bse" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "register_operand" "")] -+ "" -+ { -+ rtx temp0 = gen_reg_rtx (SImode); -+ rtx temp2 = gen_reg_rtx (SImode); -+ -+ emit_move_insn (temp0, gen_rtx_MEM (Pmode, operands[0])); -+ emit_move_insn (temp2, gen_rtx_MEM (Pmode, operands[2])); -+ emit_insn (gen_unspec_bse (temp0, operands[1], temp2, temp0, temp2)); -+ emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), temp0); -+ emit_move_insn (gen_rtx_MEM (Pmode, operands[2]), temp2); -+ DONE; -+ } -+) -+ -+(define_insn "unspec_bse" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "0")] UNSPEC_BSE)) -+ (set (match_operand:SI 4 "register_operand" "=2") -+ (unspec:SI [(match_dup 1) -+ (match_dup 2) -+ (match_dup 0)] UNSPEC_BSE_2))] -+ "" -+ "bse\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "bsp" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "register_operand" "")] -+ "" -+ { -+ rtx temp0 = gen_reg_rtx (SImode); -+ rtx temp2 = gen_reg_rtx (SImode); -+ -+ emit_move_insn (temp0, gen_rtx_MEM (Pmode, operands[0])); -+ emit_move_insn (temp2, gen_rtx_MEM (Pmode, operands[2])); -+ emit_insn (gen_unspec_bsp (temp0, operands[1], temp2, temp0, temp2)); -+ emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), temp0); -+ emit_move_insn (gen_rtx_MEM (Pmode, operands[2]), temp2); -+ DONE; -+ } -+) -+ -+(define_insn "unspec_bsp" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r") -+ (match_operand:SI 3 "register_operand" "0")] UNSPEC_BSP)) -+ (set (match_operand:SI 4 "register_operand" "=2") -+ (unspec:SI [(match_dup 1) -+ (match_dup 2) -+ (match_dup 0)] UNSPEC_BSP_2))] -+ "" -+ "bsp\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+;; String Extension -+ -+(define_insn "unspec_ffb" -+ [(set (match_operand:SI 0 "register_operand" "=r, r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r, r") -+ (match_operand:SI 2 "nonmemory_operand" "Iu08, r")] UNSPEC_FFB))] -+ "" -+ "@ -+ ffbi\t%0, %1, %2 -+ ffb\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_ffmism" -+ [(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_FFMISM))] -+ "" -+ "ffmism\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_flmism" -+ [(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_FLMISM))] -+ "" -+ "flmism\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (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 [(plus:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")) -+ (const_int 15)] UNSPEC_CLIPS))] -+ "" -+ "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 [(minus:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")) -+ (const_int 15)] UNSPEC_CLIPS))] -+ "" -+ "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" -+ [(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_SVA))] -+ "" -+ "sva\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_svs" -+ [(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_SVS))] -+ "" -+ "svs\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "unspec_jr_itoff" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JR_ITOFF)] -+ "" -+ "jr.itoff\t%0" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_jr_toff" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JR_TOFF)] -+ "" -+ "jr.toff\t%0" -+ [(set_attr "type" "branch")] -+) -+ -+(define_insn "unspec_jral_iton" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JRAL_ITON)] -+ "" -+ "jral.iton\t%0" -+ [(set_attr "type" "branch")] -+) -+ -+(define_insn "unspec_jral_ton" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JRAL_TON)] -+ "" -+ "jral.ton\t%0" -+ [(set_attr "type" "branch")] -+) -+ -+(define_insn "unspec_ret_itoff" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_RET_ITOFF)] -+ "" -+ "ret.itoff\t%0" -+ [(set_attr "type" "branch")] -+) -+ -+(define_insn "unspec_ret_toff" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_RET_TOFF)] -+ "" -+ "ret.toff\t%0" -+ [(set_attr "type" "branch")] -+) -+ -+(define_insn "unspec_standby_no_wake_grant" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_STANDBY_NO_WAKE_GRANT)] -+ "" -+ "standby\tno_wake_grant" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_standby_wake_grant" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_STANDBY_WAKE_GRANT)] -+ "" -+ "standby\twake_grant" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_standby_wait_done" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_STANDBY_WAKE_DONE)] -+ "" -+ "standby\twait_done" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_teqz" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") -+ (match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_TEQZ)] -+ "" -+ "teqz\t%0, %1" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_tnez" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") -+ (match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_TNEZ)] -+ "" -+ "tnez\t%0, %1" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_trap" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_TRAP)] -+ "" -+ "trap\t%0" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_setend_big" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETEND_BIG)] -+ "" -+ "setend.b" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_setend_little" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETEND_LITTLE)] -+ "" -+ "setend.l" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_break" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_BREAK)] -+ "" -+ "break\t%0" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_syscall" -+ [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_SYSCALL)] -+ "" -+ "syscall\t%0" -+ [(set_attr "type" "misc")] -+) -+ -+(define_insn "unspec_nop" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_NOP)] -+ "" -+ "nop" -+ [(set_attr "type" "misc")] -+) -+ -+(define_expand "unspec_get_current_sp" -+ [(match_operand:SI 0 "register_operand" "")] -+ "" -+{ -+ emit_move_insn (operands[0], gen_rtx_REG (SImode, SP_REGNUM)); -+ DONE; -+}) -+ -+(define_expand "unspec_set_current_sp" -+ [(match_operand:SI 0 "register_operand" "")] -+ "" -+{ -+ emit_move_insn (gen_rtx_REG (SImode, SP_REGNUM), operands[0]); -+ DONE; -+}) -+ -+(define_expand "unspec_return_address" -+ [(match_operand:SI 0 "register_operand" "")] -+ "" -+{ -+ emit_move_insn (operands[0], gen_rtx_REG (SImode, LP_REGNUM)); -+ DONE; -+}) -+ -+(define_insn "unspec_signature_begin" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SIGNATURE_BEGIN)] -+ "" -+ "isps" -+ [(set_attr "length" "4")] -+) -+ -+(define_insn "unspec_signature_end" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SIGNATURE_END)] -+ "" -+ "! -----\;.signature_end\;j8 2\;! -----" -+ [(set_attr "length" "2")] -+) -+ -+;; Swap -+ -+(define_insn "unspec_wsbh" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_WSBH))] -+ "" -+ "wsbh\t%0, %1" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")] -+) -+ -+;; TLBOP Intrinsic -+ -+(define_insn "unspec_tlbop_trd" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_TRD)] -+ "" -+ "tlbop\t%0, TRD" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "unspec_tlbop_twr" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_TWR)] -+ "" -+ "tlbop\t%0, TWR" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "unspec_tlbop_rwr" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_RWR)] -+ "" -+ "tlbop\t%0, RWR" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "unspec_tlbop_rwlk" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_RWLK)] -+ "" -+ "tlbop\t%0, RWLK" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "unspec_tlbop_unlk" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_UNLK)] -+ "" -+ "tlbop\t%0, UNLK" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "unspec_tlbop_pb" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_PB))] -+ "" -+ "tlbop\t%0, %1, PB" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "unspec_tlbop_inv" -+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_INV)] -+ "" -+ "tlbop\t%0, INV" -+ [(set_attr "type" "mmu")] -+) -+ -+(define_insn "unspec_tlbop_flua" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_TLBOP_FLUA)] -+ "" -+ "tlbop\tFLUA" -+ [(set_attr "type" "mmu")] -+) -+ -+;;Unaligned Load/Store -+ -+(define_expand "unaligned_load_hw" -+ [(set (match_operand:HI 0 "register_operand" "") -+ (unspec:HI [(mem:HI (match_operand:SI 1 "register_operand" ""))] UNSPEC_UALOAD_HW))] -+ "" -+{ -+ operands[0] = simplify_gen_subreg (SImode, operands[0], -+ GET_MODE (operands[0]), 0); -+ if (TARGET_ISA_V3M) -+ { -+ nds32_expand_unaligned_load (operands, HImode); -+ } -+ else -+ { -+ emit_insn (gen_unaligned_load_w (operands[0], -+ gen_rtx_MEM (SImode, operands[1]))); -+ -+ if (WORDS_BIG_ENDIAN) -+ emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT(16))); -+ else -+ emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (0xffff))); -+ } -+ -+ DONE; -+}) -+ -+(define_expand "unaligned_loadsi" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_W))] -+ "" -+{ -+ if (flag_unaligned_access) -+ { -+ rtx mem = gen_rtx_MEM (SImode, operands[1]); -+ emit_move_insn (operands[0], mem); -+ } -+ else -+ { -+ if (TARGET_ISA_V3M) -+ nds32_expand_unaligned_load (operands, SImode); -+ else -+ emit_insn (gen_unaligned_load_w (operands[0], -+ gen_rtx_MEM (SImode, (operands[1])))); -+ } -+ DONE; -+}) -+ -+(define_insn "unaligned_load_w" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (unspec:SI [(match_operand:SI 1 "nds32_lmw_smw_base_operand" " Umw")] UNSPEC_UALOAD_W))] -+ "" -+{ -+ return nds32_output_lmw_single_word (operands); -+} -+ [(set_attr "type" "load") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "unaligned_loaddi" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (unspec:DI [(mem:DI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_DW))] -+ "" -+{ -+ if (TARGET_ISA_V3M) -+ { -+ nds32_expand_unaligned_load (operands, DImode); -+ } -+ else -+ emit_insn (gen_unaligned_load_dw (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_insn "unaligned_load_dw" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (unspec:DI [(mem:DI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_DW))] -+ "" -+{ -+ rtx otherops[3]; -+ otherops[0] = gen_rtx_REG (SImode, REGNO (operands[0])); -+ otherops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); -+ otherops[2] = operands[1]; -+ -+ output_asm_insn ("lmw.bi\t%0, [%2], %1, 0", otherops); -+ return ""; -+} -+ [(set_attr "type" "load") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "unaligned_store_hw" -+ [(set (mem:SI (match_operand:SI 0 "register_operand" "")) -+ (unspec:HI [(match_operand:HI 1 "register_operand" "")] UNSPEC_UASTORE_HW))] -+ "" -+{ -+ operands[1] = simplify_gen_subreg (SImode, operands[1], -+ GET_MODE (operands[1]), 0); -+ nds32_expand_unaligned_store (operands, HImode); -+ DONE; -+}) -+ -+(define_expand "unaligned_storesi" -+ [(set (mem:SI (match_operand:SI 0 "register_operand" "r")) -+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_UASTORE_W))] -+ "" -+{ -+ if (flag_unaligned_access) -+ { -+ rtx mem = gen_rtx_MEM (SImode, operands[0]); -+ emit_move_insn (mem, operands[1]); -+ } -+ else -+ { -+ if (TARGET_ISA_V3M) -+ nds32_expand_unaligned_store (operands, SImode); -+ else -+ emit_insn (gen_unaligned_store_w (gen_rtx_MEM (SImode, operands[0]), -+ operands[1])); -+ } -+ DONE; -+}) -+ -+(define_insn "unaligned_store_w" -+ [(set (match_operand:SI 0 "nds32_lmw_smw_base_operand" "=Umw") -+ (unspec:SI [(match_operand:SI 1 "register_operand" " r")] UNSPEC_UASTORE_W))] -+ "" -+{ -+ return nds32_output_smw_single_word (operands); -+} -+ [(set_attr "type" "store") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "unaligned_storedi" -+ [(set (mem:DI (match_operand:SI 0 "register_operand" "r")) -+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_UASTORE_DW))] -+ "" -+{ -+ if (TARGET_ISA_V3M) -+ nds32_expand_unaligned_store (operands, DImode); -+ else -+ emit_insn (gen_unaligned_store_dw (gen_rtx_MEM (DImode, operands[0]), -+ operands[1])); -+ DONE; -+}) -+ -+(define_insn "unaligned_store_dw" -+ [(set (match_operand:DI 0 "nds32_lmw_smw_base_operand" "=Umw") -+ (unspec:DI [(match_operand:DI 1 "register_operand" " r")] UNSPEC_UASTORE_DW))] -+ "" -+{ -+ return nds32_output_smw_double_word (operands); -+} -+ [(set_attr "type" "store") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "unspec_unaligned_feature" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_UNALIGNED_FEATURE))] -+ "" -+{ -+ /* Get $MMU_CTL system register form nds32_intrinsic_register_names[] */ -+ rtx system_reg = GEN_INT (__NDS32_REG_MMU_CTL__); -+ rtx temp_reg = gen_reg_rtx (SImode); -+ rtx temp2_reg = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); -+ emit_move_insn (temp_reg, operands[0]); -+ emit_move_insn (temp2_reg, GEN_INT (0x800 << 12)); -+ emit_insn (gen_iorsi3 (operands[0], operands[0], temp2_reg)); -+ emit_insn (gen_unspec_volatile_mtsr (operands[0], system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ -+ emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg)); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ -+ emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (8))); -+ emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (31))); -+ DONE; -+}) -+ -+(define_expand "unspec_enable_unaligned" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_UNALIGNED_FEATURE)] -+ "" -+{ -+ /* Get $MMU_CTL system register form nds32_intrinsic_register_names[] */ -+ rtx system_reg = GEN_INT (__NDS32_REG_MMU_CTL__); -+ rtx temp_reg = gen_reg_rtx (SImode); -+ rtx temp2_reg = gen_reg_rtx (SImode); -+ emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); -+ emit_move_insn (temp2_reg, GEN_INT (0x800 << 12)); -+ emit_insn (gen_iorsi3 (temp_reg, temp_reg, temp2_reg)); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ DONE; -+}) -+ -+(define_expand "unspec_disable_unaligned" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_UNALIGNED_FEATURE)] -+ "" -+{ -+ /* Get $MMU_CTL system register form nds32_intrinsic_register_names[] */ -+ rtx system_reg = GEN_INT (__NDS32_REG_MMU_CTL__); -+ rtx temp_reg = gen_reg_rtx (SImode); -+ rtx temp2_reg = gen_reg_rtx (SImode); -+ emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg)); -+ emit_move_insn (temp2_reg, GEN_INT (0x800 << 12)); -+ emit_insn (gen_one_cmplsi2 (temp2_reg, temp2_reg)); -+ emit_insn (gen_andsi3 (temp_reg, temp_reg, temp2_reg)); -+ emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg)); -+ emit_insn (gen_unspec_dsb ()); -+ 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")] -+) -+ -+(define_expand "no_hwloop" -+ [(const_int 0)] -+ "" -+{ -+ if (NDS32_HW_LOOP_P ()) -+ emit_insn (gen_unspec_no_hwloop ()); -+ else -+ emit_insn (gen_nop ()); -+ -+ DONE; -+}) -+ -+(define_insn "unspec_no_hwloop" -+ [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_NO_HWLOOP)] -+ "" -+ "" -+ [(set_attr "type" "misc")] -+) - ;; ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/nds32-isr.c b/gcc/config/nds32/nds32-isr.c -index 79be27e..be82609 100644 ---- a/gcc/config/nds32/nds32-isr.c -+++ b/gcc/config/nds32/nds32-isr.c -@@ -24,11 +24,41 @@ - #include "system.h" - #include "coretypes.h" - #include "backend.h" --#include "target.h" --#include "rtl.h" - #include "tree.h" --#include "diagnostic-core.h" -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" - #include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" - - /* ------------------------------------------------------------------------ */ - -@@ -39,7 +69,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 -@@ -75,6 +358,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); -@@ -95,7 +387,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]; -@@ -143,46 +434,63 @@ 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 -- is needed in vector section. */ -+ Hardware $VID support is necessary and only one instruction -+ is needed in vector section. */ - fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n", - first_level_handler_name); - } - else - { - /* This block is for 16-byte vector size. -- There is NO hardware $VID so that we need several instructions -- such as pushing GPRs and preparing software vid at vector section. -- For pushing GPRs, there are four variations for -- 16-byte vector content and we have to handle each combination. -- For preparing software vid, note that the vid need to -- be substracted vector_number_offset. */ -+ There is NO hardware $VID so that we need several instructions -+ such as pushing GPRs and preparing software vid at vector section. -+ For pushing GPRs, there are four variations for -+ 16-byte vector content and we have to handle each combination. -+ For preparing software vid, note that the vid need to -+ be substracted vector_number_offset. */ - if (TARGET_REDUCED_REGS) - { - if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL) -@@ -235,13 +543,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"); - -@@ -257,7 +563,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"); -@@ -271,9 +577,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, -@@ -319,12 +625,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. */ -@@ -343,8 +649,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 -@@ -358,6 +666,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. -@@ -369,15 +688,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); -@@ -387,6 +712,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) -@@ -413,6 +795,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) -@@ -432,6 +817,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); -@@ -447,12 +834,12 @@ nds32_construct_isr_vectors_information (tree func_attrs, - nds32_isr_vectors[0].category = NDS32_ISR_RESET; - - /* Prepare id_list and identify id value so that -- we can set total number of vectors. */ -+ we can set total number of vectors. */ - id_list = TREE_VALUE (reset); - id = TREE_VALUE (id_list); - - /* The total vectors = interrupt + exception numbers + reset. -- There are 8 exception and 1 reset in nds32 architecture. */ -+ There are 8 exception and 1 reset in nds32 architecture. */ - nds32_isr_vectors[0].total_n_vectors = TREE_INT_CST_LOW (id) + 8 + 1; - strcpy (nds32_isr_vectors[0].func_name, func_name); - -@@ -488,7 +875,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) - { -@@ -501,15 +887,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; - -@@ -543,6 +928,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"); -@@ -576,4 +963,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 0000000..75ccd76 ---- /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-lmwsmw.c b/gcc/config/nds32/nds32-lmwsmw.c -new file mode 100644 -index 0000000..e3b66bf ---- /dev/null -+++ b/gcc/config/nds32/nds32-lmwsmw.c -@@ -0,0 +1,1998 @@ -+ -+/* lmwsmw pass of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+/* ------------------------------------------------------------------------ */ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "hash-set.h" -+#include "machmode.h" -+#include "vec.h" -+#include "double-int.h" -+#include "input.h" -+#include "alias.h" -+#include "symtab.h" -+#include "wide-int.h" -+#include "inchash.h" -+#include "tree.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "rtl.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "input.h" -+#include "function.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "dominance.h" -+#include "cfg.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "predict.h" -+#include "basic-block.h" -+#include "bitmap.h" -+#include "df.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "ggc.h" -+#include "tree-pass.h" -+#include "target-globals.h" -+#include "ira.h" -+#include "ira-int.h" -+#include "regrename.h" -+#include "nds32-load-store-opt.h" -+#include "nds32-reg-utils.h" -+#include -+#include -+#include -+ -+#define NDS32_GPR_NUM 32 -+ -+static int -+compare_order (const void *a, const void *b) -+{ -+ const load_store_info_t *fp1 = (const load_store_info_t *) a; -+ const load_store_info_t *fp2 = (const load_store_info_t *) b; -+ const load_store_info_t f1 = *fp1; -+ const load_store_info_t f2 = *fp2; -+ -+ return f1.order < f2.order ? -1 : 1; -+} -+ -+static int -+compare_offset (const void *a, const void *b) -+{ -+ const load_store_info_t *fp1 = (const load_store_info_t *) a; -+ const load_store_info_t *fp2 = (const load_store_info_t *) b; -+ const load_store_info_t f1 = *fp1; -+ const load_store_info_t f2 = *fp2; -+ -+ return f1.offset < f2.offset ? -1 : 1; -+} -+ -+static bool -+compare_amount(available_reg_info_t a, available_reg_info_t b) -+{ -+ return a.amount > b.amount; -+} -+ -+static bool -+nds32_load_store_reg_plus_offset (rtx_insn *insn, load_store_info_t *load_store_info) -+{ -+ rtx pattern, mem, reg, base_reg, addr; -+ HOST_WIDE_INT offset; -+ bool load_p; -+ enum nds32_memory_post_type post_type = NDS32_NONE; -+ -+ pattern = PATTERN (insn); -+ mem = NULL_RTX; -+ reg = NULL_RTX; -+ base_reg = NULL_RTX; -+ offset = 0; -+ load_p = false; -+ -+ if (GET_CODE (pattern) != SET) -+ return false; -+ -+ if (MEM_P (SET_SRC (pattern))) -+ { -+ mem = SET_SRC (pattern); -+ reg = SET_DEST (pattern); -+ load_p = true; -+ } -+ -+ if (MEM_P (SET_DEST (pattern))) -+ { -+ mem = SET_DEST (pattern); -+ reg = SET_SRC (pattern); -+ load_p = false; -+ } -+ -+ if (mem == NULL_RTX || reg == NULL_RTX || !REG_P (reg)) -+ return false; -+ -+ /* The FPU ISA has not load-store-multiple instruction. */ -+ if (!NDS32_IS_GPR_REGNUM (REGNO (reg))) -+ return false; -+ -+ if (MEM_VOLATILE_P (mem)) -+ return false; -+ -+ if (GET_MODE (reg) != SImode) -+ return false; -+ -+ gcc_assert (REG_P (reg)); -+ -+ addr = XEXP (mem, 0); -+ -+ /* We only care about [reg] and [reg+const]. */ -+ if (REG_P (addr)) -+ { -+ base_reg = addr; -+ offset = 0; -+ } -+ else if (GET_CODE (addr) == PLUS -+ && CONST_INT_P (XEXP (addr, 1))) -+ { -+ base_reg = XEXP (addr, 0); -+ offset = INTVAL (XEXP (addr, 1)); -+ if (!REG_P (base_reg)) -+ return false; -+ } -+ else if (GET_CODE (addr) == POST_INC) -+ { -+ base_reg = XEXP (addr, 0); -+ offset = 0; -+ post_type = NDS32_POST_INC; -+ } -+ else if (GET_CODE (addr) == POST_DEC) -+ { -+ base_reg = XEXP (addr, 0); -+ offset = 0; -+ post_type = NDS32_POST_DEC; -+ } -+ else -+ return false; -+ -+ if ((REGNO (base_reg) > NDS32_LAST_GPR_REGNUM) -+ && (REGNO (base_reg) < FIRST_PSEUDO_REGISTER)) -+ return false; -+ -+ if (load_store_info) -+ { -+ load_store_info->load_p = load_p; -+ load_store_info->offset = offset; -+ load_store_info->reg = reg; -+ load_store_info->base_reg = base_reg; -+ load_store_info->insn = insn; -+ load_store_info->mem = mem; -+ load_store_info->post_type = post_type; -+ } -+ -+ return true; -+} -+ -+static bool -+nds32_insn_alias_p (rtx memref, rtx x) -+{ -+ rtx mem; -+ -+ if (GET_CODE (x) == PARALLEL) -+ { -+ int i, j; -+ -+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) -+ { -+ for (j = XVECLEN (x, i) - 1; j >= 0; j--) -+ if (nds32_insn_alias_p (memref, XVECEXP (x, i, j))) -+ return true; -+ } -+ -+ return false; -+ } -+ -+ if (GET_CODE (x) != SET) -+ return true; -+ -+ if (MEM_P (SET_SRC (x))) -+ mem = SET_SRC (x); -+ else if (MEM_P (SET_DEST (x))) -+ mem = SET_DEST (x); -+ else -+ return false; -+ -+ if (may_alias_p (memref, mem)) -+ return true; -+ else -+ return false; -+} -+ -+static void -+nds32_emit_multiple_insn (load_store_infos_t *multiple_insn, -+ rtx base_reg, rtx place, bool update_p) -+{ -+ unsigned int i; -+ unsigned int num_use_regs = multiple_insn->length (); -+ int par_index = 0; -+ int offset = 0; -+ bool load_p = (*multiple_insn)[0].load_p; -+ -+ rtx reg; -+ rtx mem; -+ rtx push_rtx; -+ rtx update_offset; -+ rtx parallel_insn; -+ -+ /* In addition to used registers, -+ we need one more space for (set base base-x) rtx. */ -+ if (update_p) -+ num_use_regs++; -+ -+ parallel_insn = gen_rtx_PARALLEL (VOIDmode, -+ rtvec_alloc (num_use_regs)); -+ -+ /* Set update insn. */ -+ if (update_p) -+ { -+ update_offset = GEN_INT (multiple_insn->length () * 4); -+ push_rtx = gen_addsi3 (base_reg, base_reg, update_offset); -+ XVECEXP (parallel_insn, 0, par_index) = push_rtx; -+ par_index++; -+ } -+ -+ /* Create (set mem regX) from start_reg to end_reg. */ -+ for (i = 0; i < multiple_insn->length (); ++i) -+ { -+ reg = (*multiple_insn)[i].reg; -+ mem = gen_frame_mem (SImode, plus_constant (Pmode, -+ base_reg, -+ offset)); -+ MEM_COPY_ATTRIBUTES (mem, (*multiple_insn)[i].mem); -+ -+ if (load_p) -+ push_rtx = gen_rtx_SET (reg, mem); -+ else -+ push_rtx = gen_rtx_SET (mem, reg); -+ -+ XVECEXP (parallel_insn, 0, par_index) = push_rtx; -+ offset = offset + 4; -+ par_index++; -+ } -+ -+ emit_insn_before (parallel_insn, place); -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "lmw/smw instruction:\n"); -+ print_rtl_single (dump_file, parallel_insn); -+ } -+} -+ -+static void -+nds32_emit_add_insn (load_store_info_t insn, rtx base_reg, -+ rtx place, bool add_p) -+{ -+ rtx add_insn; -+ HOST_WIDE_INT offset = insn.offset; -+ if (!add_p) -+ offset = -offset; -+ -+ add_insn = gen_addsi3 (base_reg, insn.base_reg, GEN_INT (offset)); -+ emit_insn_before (add_insn, place); -+} -+ -+/* Get the instruction of same ID. */ -+static void -+nds32_fetch_group_insn (load_store_infos_t *src, -+ load_store_infos_t *dst, int id) -+{ -+ unsigned int i = 0; -+ -+ while (i < src->length ()) -+ { -+ if (id == (*src)[i].group) -+ { -+ dst->safe_push ((*src)[i]); -+ src->ordered_remove (i); -+ i = 0; -+ } -+ else -+ i++; -+ } -+} -+ -+/* Check registers are not used and defined. */ -+static rtx -+nds32_lmwsmw_insert_place (load_store_infos_t *insn_set) -+{ -+ unsigned int i, position; -+ bool combine_p; -+ rtx_insn *insn; -+ auto_vec temp_set; -+ -+ for (i = 0; i < insn_set->length (); i++) -+ temp_set.safe_push ((*insn_set)[i]); -+ -+ /* Check registers are not used and defined -+ between first instruction and last instruction, -+ and find insert lmw/smw instruction place. -+ example: -+ lwi $r0, [$r2 + 4] -+ lwi $r1, [$r2 + 8] -+ -+ Check $r0 and $r1 are not used and defined. */ -+ temp_set.qsort (compare_order); -+ -+ for (position = 0; position < temp_set.length (); ++position) -+ { -+ combine_p = true; -+ -+ /* Check instruction form first instruction to position. */ -+ for (i = 0; i < position; i++) -+ { -+ for (insn = NEXT_INSN (temp_set[i].insn); -+ insn != temp_set[position].insn; -+ insn = NEXT_INSN (insn)) -+ { -+ if (!NONDEBUG_INSN_P (insn)) -+ continue; -+ if (df_reg_used (insn, temp_set[i].reg) -+ || df_reg_defined (insn, temp_set[i].reg)) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Fail:register has modify\n"); -+ fprintf (dump_file, "insn uid:%d, reg: r%d,\n", -+ INSN_UID (temp_set[position].insn), -+ REGNO (temp_set[position].reg)); -+ fprintf (dump_file, "Modify instruction:\n"); -+ print_rtl_single (dump_file, insn); -+ } -+ combine_p = false; -+ break; -+ } -+ } -+ } -+ -+ /* Check instruction form position to last instruction. */ -+ for (i = position + 1; i < temp_set.length (); i++) -+ { -+ for (insn = temp_set[position].insn; -+ insn != temp_set[i].insn; -+ insn = NEXT_INSN (insn)) -+ { -+ if (!NONDEBUG_INSN_P (insn)) -+ continue; -+ if (df_reg_used (insn, temp_set[i].reg) -+ || df_reg_defined (insn, temp_set[i].reg)) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Fail:register has modify\n"); -+ fprintf (dump_file, "insn uid:%d, reg: r%d,\n", -+ INSN_UID (temp_set[position].insn), -+ REGNO (temp_set[position].reg)); -+ fprintf (dump_file, "Modify instruction:\n"); -+ print_rtl_single (dump_file, insn); -+ } -+ combine_p = false; -+ break; -+ } -+ } -+ } -+ -+ if (combine_p) -+ return temp_set[position].insn; -+ } -+ -+ return NULL_RTX; -+} -+ -+/* Check registers are not used and defined. */ -+static bool -+nds32_base_reg_safe_p (load_store_infos_t *insn_set) -+{ -+ unsigned int i; -+ rtx_insn *insn; -+ auto_vec temp_set; -+ -+ /* We will change 'insn_set' element order, -+ to avoid change order using 'temp_set'. */ -+ for (i = 0; i < insn_set->length (); i++) -+ temp_set.safe_push ((*insn_set)[i]); -+ -+ /* We want to combine load and store instructions, -+ need to check base register is not used and defined -+ between first insn and last insn. -+ example: -+ lwi $r0, [$r3 + 4] -+ ... <- check here -+ lwi $r1, [$r3 + 8] -+ ... <- check here -+ lwi $r2, [$r3 + 12] -+ -+ Check $r3 is not used and defined, -+ between first insn and last insn. */ -+ -+ /* Scan instruction from top to bottom, -+ so need to sort by order. */ -+ temp_set.qsort (compare_order); -+ -+ for (i = 0; i < temp_set.length () - 1; ++i) -+ { -+ for (insn = NEXT_INSN (temp_set[i].insn); -+ insn != temp_set[i + 1].insn; -+ insn = NEXT_INSN (insn)) -+ { -+ if (!NONDEBUG_INSN_P (insn)) -+ continue; -+ -+ if (nds32_insn_alias_p (temp_set[0].mem, PATTERN (insn))) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Memory alias:\n"); -+ print_rtl_single (dump_file, insn); -+ } -+ return false; -+ } -+ -+ if (temp_set[0].load_p) -+ { -+ if (df_reg_defined (insn, temp_set[0].base_reg)) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Fail: base register has modify\n"); -+ fprintf (dump_file, "insn uid:%d, base reg: r%d,\n", -+ INSN_UID (temp_set[i].insn), -+ REGNO (temp_set[i].reg)); -+ fprintf (dump_file, "Modify instruction:\n"); -+ print_rtl_single (dump_file, insn); -+ } -+ return false; -+ } -+ } -+ else -+ { -+ if (df_reg_used (insn, temp_set[0].base_reg)) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Fail: base register has modify\n"); -+ fprintf (dump_file, "insn uid:%d, base reg: r%d,\n", -+ INSN_UID (temp_set[i].insn), -+ REGNO (temp_set[i].reg)); -+ fprintf (dump_file, "Modify instruction:\n"); -+ print_rtl_single (dump_file, insn); -+ } -+ return false; -+ } -+ } -+ } -+ } -+ return true; -+} -+ -+static bool -+nds32_gain_size_p (load_store_infos_t *insn, bool new_base_p) -+{ -+ unsigned int i, new_cost = 4, old_cost = 0; -+ rtx reg; -+ rtx base_reg = (*insn)[0].base_reg; -+ HOST_WIDE_INT offset; -+ -+ for (i = 0; i < insn->length (); ++i) -+ { -+ reg = (*insn)[i].reg; -+ offset = (*insn)[i].offset; -+ -+ if (in_reg_class_p (reg, LOW_REGS)) -+ { -+ /* lwi37.sp/swi37.sp/lwi37/swi37 */ -+ if ((REGNO (base_reg) == SP_REGNUM -+ || REGNO (base_reg) == FP_REGNUM) -+ && (offset >= 0 && offset < 512 && (offset % 4 == 0))) -+ old_cost += 2; -+ /* lwi333/swi333 */ -+ else if (in_reg_class_p (base_reg, LOW_REGS) -+ && (offset >= 0 && offset < 32 && (offset % 4 == 0))) -+ old_cost += 2; -+ else -+ old_cost += 4; -+ } -+ else -+ { -+ /* lwi450/swi450 */ -+ if (in_reg_class_p (reg, MIDDLE_REGS) -+ && offset == 0) -+ old_cost += 2; -+ else -+ old_cost += 4; -+ } -+ } -+ -+ offset = (*insn)[0].offset; -+ if (offset != 0) -+ { -+ /* addi333 */ -+ if (in_reg_class_p (base_reg, LOW_REGS) -+ && satisfies_constraint_Iu05 (GEN_INT (offset))) -+ new_cost += 2; -+ /* addi45 */ -+ else if (in_reg_class_p (base_reg, MIDDLE_REGS) -+ && satisfies_constraint_Iu05 (GEN_INT (offset))) -+ new_cost += 2; -+ else -+ new_cost += 4; -+ -+ /* subri */ -+ if (!new_base_p) -+ new_cost += 4; -+ } -+ -+ if (dump_file) -+ fprintf (dump_file, "Code size compare: old code size is %d," -+ " new code size is %d\n", old_cost, new_cost); -+ -+ return new_cost < old_cost; -+} -+ -+static bool -+nds32_gain_speed_p (load_store_infos_t *insn, bool new_base_p) -+{ -+ unsigned int new_cost = 0, old_cost = insn->length (); -+ -+ if (TARGET_PIPELINE_GRAYWOLF) -+ { -+ new_cost = insn->length () / 2 + insn->length () % 2; -+ -+ if ((*insn)[0].offset != 0) -+ { -+ /* Need addi instruction. */ -+ new_cost += 1; -+ -+ /* Need subri instruction. */ -+ if (!new_base_p) -+ new_cost += 1; -+ } -+ } -+ else -+ { -+ if ((*insn)[0].offset != 0) -+ return false; -+ } -+ -+ return new_cost < old_cost; -+} -+ -+/* Check instructions can combine into a mulitple-instruction. */ -+static bool -+nds32_combine_multiple_p (load_store_infos_t *insn_set, bool new_base_p) -+{ -+ unsigned int i; -+ auto_vec temp_set; -+ -+ /* We will change 'insn_set' element order, -+ to avoid change order using 'temp_set'. */ -+ for (i = 0; i < insn_set->length (); i++) -+ temp_set.safe_push ((*insn_set)[i]); -+ -+ /* Check start offset need to sort by offset. */ -+ temp_set.qsort (compare_offset); -+ -+ /* The lmw/smw pattern, need two or more instructions. */ -+ if (temp_set.length () < 2) -+ return false; -+ -+ /* The lmw/smw pattern, only allow combine 25 instruction. */ -+ if (temp_set.length () > 25) -+ return false; -+ -+ if (TARGET_LMWSMW_OPT_SIZE -+ || (TARGET_LMWSMW_OPT_AUTO && optimize_size)) -+ { -+ /* Compare original instructions with multiple instruction, -+ when mupltiple instruction is small than original instructions -+ then combine it. */ -+ if (!nds32_gain_size_p (&temp_set, new_base_p)) -+ return false; -+ } -+ else if (TARGET_LMWSMW_OPT_SPEED -+ || (TARGET_LMWSMW_OPT_AUTO && !optimize_size)) -+ { -+ /* The start offset is not zero, we need add a instrucion -+ to handle offset, it is not worth on -O3, -O2 level. */ -+ if (!nds32_gain_speed_p (&temp_set, new_base_p)) -+ return false; -+ } -+ -+ /* Base register is not equal register, when offset is not zero. */ -+ if (temp_set[0].offset != 0) -+ for (i = 0; i < temp_set.length (); ++i) -+ { -+ if (REGNO (temp_set[i].reg) -+ == REGNO (temp_set[0].base_reg)) -+ return false; -+ } -+ -+ /* Don't combine, when start offset is greater then Is15, -+ because need extra register. */ -+ if (!satisfies_constraint_Is15 (GEN_INT (temp_set[0].offset))) -+ return false; -+ -+ return true; -+} -+ -+static bool -+nds32_use_bim_p (load_store_infos_t *insn_set, -+ load_store_infos_t *ref_set) -+{ -+ rtx_insn *insn; -+ bool combine_p = true; -+ -+ /* Generate .bim form, need offset is continuous. */ -+ if (insn_set->last ().offset != ((*ref_set)[0].offset - 4)) -+ return false; -+ -+ /* Reject 'insn_set' instructions bottom -+ of the 'ref_set' instructions. */ -+ if ((*insn_set)[0].group > (*ref_set)[0].group) -+ return false; -+ -+ /* Scan instruction from top to bottom, -+ so need to sort by order. */ -+ insn_set->qsort (compare_order); -+ ref_set->qsort (compare_order); -+ -+ /* We want to combine .bim form instruction, -+ so need to check base register is not used and defined -+ between multiple-insn and next mulitple-insn. -+ example: -+ lmw.bim $r0, [$r2], $r1 -+ ... <- check here -+ lmw.bi $r3, [$r2], $r4 -+ -+ Use .bim form need to check $r2 is not used and defined, -+ between lmw.bim and lmw.bi. */ -+ for (insn = NEXT_INSN (insn_set->last ().insn); -+ insn != (*ref_set)[0].insn; -+ insn = NEXT_INSN (insn)) -+ { -+ if (!NONDEBUG_INSN_P (insn)) -+ continue; -+ -+ if (nds32_insn_alias_p ((*insn_set)[0].mem, PATTERN (insn))) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Have memory instruction:\n"); -+ print_rtl_single (dump_file, insn); -+ } -+ combine_p = false; -+ break; -+ } -+ -+ if (df_reg_used (insn, (*insn_set)[0].base_reg) -+ || df_reg_defined (insn, (*insn_set)[0].base_reg)) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Use .bi form: Base reg is" -+ " used or defined between multiple-insn" -+ " and next multiple-insn\n"); -+ fprintf (dump_file, "Base register: r%d,\n", -+ REGNO ((*insn_set)[0].base_reg)); -+ fprintf (dump_file, "use or def instruction:\n"); -+ print_rtl_single (dump_file, insn); -+ } -+ combine_p = false; -+ break; -+ } -+ } -+ -+ /* Restore element order. */ -+ insn_set->qsort (compare_offset); -+ ref_set->qsort (compare_offset); -+ -+ if (combine_p) -+ return true; -+ else -+ return false; -+} -+ -+static void -+nds32_merge_overlapping_regs (HARD_REG_SET *pset, struct du_head *head) -+{ -+ bitmap_iterator bi; -+ unsigned i; -+ IOR_HARD_REG_SET (*pset, head->hard_conflicts); -+ EXECUTE_IF_SET_IN_BITMAP (&head->conflicts, 0, i, bi) -+ { -+ du_head_p other = regrename_chain_from_id (i); -+ unsigned j = other->nregs; -+ gcc_assert (other != head); -+ while (j-- > 0) -+ SET_HARD_REG_BIT (*pset, other->regno + j); -+ } -+} -+ -+/* Check if NEW_REG can be the candidate register to rename for -+ REG in THIS_HEAD chain. THIS_UNAVAILABLE is a set of unavailable hard -+ registers. */ -+static bool -+nds32_check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg, -+ struct du_head *this_head, HARD_REG_SET this_unavailable) -+{ -+ enum machine_mode mode = GET_MODE (*this_head->first->loc); -+ int nregs = hard_regno_nregs[new_reg][mode]; -+ int i; -+ struct du_chain *tmp; -+ -+ for (i = nregs - 1; i >= 0; --i) -+ if (TEST_HARD_REG_BIT (this_unavailable, new_reg + i) -+ || fixed_regs[new_reg + i] -+ || global_regs[new_reg + i] -+ /* Can't use regs which aren't saved by the prologue. */ -+ || (! df_regs_ever_live_p (new_reg + i) -+ && ! call_used_regs[new_reg + i]) -+#ifdef LEAF_REGISTERS -+ /* We can't use a non-leaf register if we're in a -+ leaf function. */ -+ || (crtl->is_leaf -+ && !LEAF_REGISTERS[new_reg + i]) -+#endif -+#ifdef HARD_REGNO_RENAME_OK -+ || ! HARD_REGNO_RENAME_OK (reg + i, new_reg + i) -+#endif -+ ) -+ return false; -+ -+ /* See whether it accepts all modes that occur in -+ definition and uses. */ -+ for (tmp = this_head->first; tmp; tmp = tmp->next_use) -+ if ((! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc)) -+ && ! DEBUG_INSN_P (tmp->insn)) -+ || (this_head->need_caller_save_reg -+ && ! (HARD_REGNO_CALL_PART_CLOBBERED -+ (reg, GET_MODE (*tmp->loc))) -+ && (HARD_REGNO_CALL_PART_CLOBBERED -+ (new_reg, GET_MODE (*tmp->loc))))) -+ return false; -+ -+ return true; -+} -+ -+static int -+nds32_find_best_rename_reg (du_head_p this_head, int new_reg, int old_reg) -+{ -+ HARD_REG_SET unavailable; -+ int best_new_reg = old_reg; -+ -+ COMPL_HARD_REG_SET (unavailable, reg_class_contents[GENERAL_REGS]); -+ CLEAR_HARD_REG_BIT (unavailable, this_head->regno); -+ -+ /* Further narrow the set of registers we can use for renaming. -+ If the chain needs a call-saved register, mark the call-used -+ registers as unavailable. */ -+ if (this_head->need_caller_save_reg) -+ IOR_HARD_REG_SET (unavailable, call_used_reg_set); -+ -+ /* Mark registers that overlap this chain's lifetime as unavailable. */ -+ nds32_merge_overlapping_regs (&unavailable, this_head); -+ -+ if (nds32_check_new_reg_p (old_reg, new_reg, this_head, unavailable)) -+ best_new_reg = new_reg; -+ -+ return best_new_reg; -+} -+ -+static bool -+nds32_try_rename_reg (rtx_insn *insn, unsigned op_pos, unsigned best_reg) -+{ -+ insn_rr_info *info; -+ du_head_p op_chain; -+ unsigned oldreg, newreg; -+ -+ info = &insn_rr[INSN_UID (insn)]; -+ -+ if (info->op_info == NULL) -+ return false; -+ -+ if (info->op_info[op_pos].n_chains == 0) -+ return false; -+ -+ op_chain = regrename_chain_from_id (info->op_info[op_pos].heads[0]->id); -+ -+ if (op_chain->cannot_rename) -+ return false; -+ -+ oldreg = op_chain->regno; -+ newreg = nds32_find_best_rename_reg (op_chain, best_reg, oldreg); -+ -+ if (newreg == oldreg) -+ return false; -+ -+ return true; -+} -+ -+/* Grouping consecutive registers. */ -+static void -+nds32_group_available_reg (HARD_REG_SET *available_regset, enum reg_class clazz, -+ std::vector *available_group) -+{ -+ hard_reg_set_iterator hrsi; -+ unsigned regno, pre_regno = 0; -+ unsigned count = 0; -+ available_reg_info_t reg_info; -+ std::vector::iterator it; -+ -+ if (!available_group->empty ()) -+ available_group->clear (); -+ -+ /* Find available register form $r16 to $r31. */ -+ EXECUTE_IF_SET_IN_HARD_REG_SET (reg_class_contents[clazz], 2, regno, hrsi) -+ { -+ /* Caller-save register or callee-save register but it's ever live. */ -+ if (TEST_HARD_REG_BIT (*available_regset, regno) -+ && (call_used_regs[regno] || df_regs_ever_live_p (regno))) -+ { -+ if (pre_regno == 0 -+ || (pre_regno + 1) == regno) -+ count++; -+ } -+ else -+ { -+ if (count >= 2) -+ { -+ reg_info.amount = count; -+ reg_info.end = pre_regno; -+ reg_info.start = pre_regno - count + 1; -+ available_group->push_back (reg_info); -+ } -+ count = 0; -+ } -+ pre_regno = regno; -+ } -+ -+ sort (available_group->begin(), available_group->end(), compare_amount); -+ -+ if (dump_file) -+ { -+ for (it = available_group->begin(); -+ it != available_group->end(); ++it) -+ fprintf (dump_file, -+ "available amount = %d start = %d " -+ "end = %d \n", it->amount, it->start, -+ it->end); -+ } -+} -+ -+/* Try to rename insn's register in order. */ -+static void -+nds32_find_reg (load_store_infos_t *insn, load_store_infos_t *rename_insn, -+ HARD_REG_SET *available_regset) -+{ -+ int can_rename_number; -+ unsigned i, regno, amount; -+ unsigned op_pos = (*insn)[0].load_p ? 0 : 1; -+ auto_vec temp_set; -+ std::vector available_group; -+ std::vector::iterator it; -+ auto_vec down_set, up_set; -+ unsigned int down_num = 0, up_num = 0; -+ long offset; -+ int m; -+ -+ /* We will change 'insn' element order, -+ to avoid change order using 'temp_set'. */ -+ for (i = 0; i < insn->length (); i++) -+ temp_set.safe_push ((*insn)[i]); -+ -+ if (temp_set[0].post_type == NDS32_NONE) -+ temp_set.qsort (compare_offset); -+ -+ nds32_group_available_reg (available_regset, GENERAL_REGS, &available_group); -+ -+ /* Check rename register form top insn to bottom insn, -+ and avoid using fp, sp, lp, gp registers. */ -+ regno = REGNO (temp_set[0].reg); -+ can_rename_number = regno + temp_set.length () - 1; -+ offset = temp_set[0].offset; -+ -+ if (can_rename_number < FP_REGNUM) -+ for (i = 1; i < temp_set.length (); ++i) -+ { -+ /* Find this case: -+ lwi $r0, [$r2 + 4] -+ lwi $r3, [$r2 + 8] -+ -+ Rename $r3 to $r1. */ -+ down_num++; -+ if ((regno + i) != REGNO (temp_set[i].reg)) -+ { -+ if (nds32_try_rename_reg (temp_set[i].insn, op_pos, regno + i)) -+ { -+ /* Store in temparary set. */ -+ down_set.safe_push (temp_set[i]); -+ down_set.last ().new_reg = regno + i; -+ } -+ else -+ /* Stop when the register sequence is broken. */ -+ break; -+ } -+ } -+ -+ /* Check rename register form bottom insn to top insn, -+ and avoid using fp, sp, lp, gp registers. */ -+ regno = REGNO (temp_set.last ().reg); -+ can_rename_number = regno - temp_set.length () + 1; -+ -+ if (can_rename_number > 0 && regno < FP_REGNUM) -+ for (i = temp_set.length () - 1; i > 0; --i) -+ { -+ /* Find this case: -+ lwi $r1, [$r2 + 4] -+ lwi $r4, [$r2 + 8] -+ -+ Rename $r1 to $r3. */ -+ up_num++; -+ if ((regno - i) != REGNO (temp_set[i - 1].reg)) -+ { -+ if (nds32_try_rename_reg (temp_set[i - 1].insn, op_pos, regno - i)) -+ { -+ /* Store in rename_insn. */ -+ up_set.safe_push (temp_set[i - 1]); -+ up_set.last ().new_reg = regno - i; -+ } -+ else -+ /* Stop when the register sequence is broken. */ -+ break; -+ } -+ } -+ -+ /* Rename for the longest sequence. */ -+ /* The overhead of zero offset instruction is lowest, so try it first. */ -+ if ((offset == 0 || down_num >= up_num) && !down_set.is_empty ()) -+ { -+ for (m = down_set.length () - 1; m >= 0; --m) -+ { -+ regno = REGNO (down_set[m].reg); -+ CLEAR_HARD_REG_BIT (*available_regset, regno); -+ rename_insn->safe_push (down_set[m]); -+ } -+ nds32_group_available_reg (available_regset, GENERAL_REGS, -+ &available_group); -+ return; -+ } -+ else if (up_num >= down_num && !up_set.is_empty ()) -+ { -+ for (m = up_set.length () - 1; m >= 0; --m) -+ { -+ regno = REGNO (up_set[m].reg); -+ CLEAR_HARD_REG_BIT (*available_regset, regno); -+ rename_insn->safe_push (up_set[m]); -+ } -+ nds32_group_available_reg (available_regset, GENERAL_REGS, -+ &available_group); -+ return; -+ } -+ /* Check whether it is empty, We will use available table. */ -+ else if (available_group.empty ()) -+ return; -+ -+ amount = available_group.begin ()->amount; -+ /* Using the minimum number, as the rename amount. */ -+ if (amount > temp_set.length ()) -+ amount = temp_set.length (); -+ -+ /* Using most available register number to rename. */ -+ regno = available_group.begin ()->start; -+ for (i = 0; i < amount; ++i) -+ { -+ if (nds32_try_rename_reg (temp_set[i].insn, op_pos, regno)) -+ { -+ rename_insn->safe_push (temp_set[i]); -+ rename_insn->last ().new_reg = regno; -+ CLEAR_HARD_REG_BIT (*available_regset, regno); -+ regno++; -+ } -+ else -+ /* Stop when the register sequence is broken. */ -+ break; -+ } -+ -+ /* Check length here because the whole sequence entries -+ have to be renamed. */ -+ if (rename_insn->length () > 1) -+ { -+ /* Update available table. */ -+ nds32_group_available_reg (available_regset, GENERAL_REGS, -+ &available_group); -+ return; -+ } -+ -+ /* Using all available register to rename each insn. */ -+ for (i = 0; i < (temp_set.length () - 1); i += 2) -+ { -+ for (it = available_group.begin(); -+ it != available_group.end(); ++it) -+ { -+ bool change_p = false; -+ unsigned int j; -+ regno = it->start; -+ -+ /* Once replaced two instructions. */ -+ for (j = regno; j < (it->end + 1); j += 2) -+ { -+ if (nds32_try_rename_reg (temp_set[i].insn, op_pos, regno) -+ && nds32_try_rename_reg (temp_set[i + 1].insn, -+ op_pos, regno + 1)) -+ { -+ rename_insn->safe_push (temp_set[i]); -+ rename_insn->last ().new_reg = regno; -+ CLEAR_HARD_REG_BIT (*available_regset, regno); -+ -+ rename_insn->safe_push (temp_set[i + 1]); -+ rename_insn->last ().new_reg = regno + 1; -+ CLEAR_HARD_REG_BIT (*available_regset, regno + 1); -+ change_p = true; -+ break; -+ } -+ } -+ -+ if (change_p) -+ { -+ nds32_group_available_reg (available_regset, GENERAL_REGS, -+ &available_group); -+ break; -+ } -+ } -+ } -+} -+ -+static void -+nds32_rename_reg (rtx_insn *insn, unsigned op_pos, unsigned newreg) -+{ -+ insn_rr_info *info; -+ du_head_p op_chain; -+ -+ info = &insn_rr[INSN_UID (insn)]; -+ op_chain = regrename_chain_from_id (info->op_info[op_pos].heads[0]->id); -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "Try to rename operand %d to %d:\n", -+ op_pos, newreg); -+ print_rtl_single (dump_file, insn); -+ } -+ -+ regrename_do_replace (op_chain, newreg); -+ -+ if (dump_file) -+ { -+ print_rtl_single (dump_file, insn); -+ } -+} -+ -+/* Combine mutilple load/store insn into a lmw/smw insn. */ -+static void -+nds32_combine_bi_insn (load_store_infos_t *load_store_info) -+{ -+ auto_vec candidate_set, bi_set; -+ unsigned int i, j, regno; -+ -+ bool load_insn_p; -+ enum nds32_memory_post_type post_type; -+ -+ for (i = 0; i < load_store_info->length (); ++i) -+ { -+ /* Recording instruction order of priority and initinal place. */ -+ (*load_store_info)[i].order = i; -+ (*load_store_info)[i].place = false; -+ candidate_set.safe_push ((*load_store_info)[i]); -+ } -+ -+ for (i = 0; i < candidate_set.length (); ++i) -+ { -+ load_insn_p = candidate_set[i].load_p; -+ post_type = candidate_set[i].post_type; -+ regno = REGNO (candidate_set[i].reg); -+ -+ for (j = i + 1; j < candidate_set.length (); ++j) -+ { -+ if ((post_type == candidate_set[j].post_type) -+ && (load_insn_p == candidate_set[j].load_p) -+ && ((regno + 1) == REGNO (candidate_set[j].reg))) -+ { -+ bi_set.safe_push (candidate_set[i]); -+ bi_set.safe_push (candidate_set[j]); -+ -+ if (nds32_combine_multiple_p (&bi_set, false) -+ && nds32_base_reg_safe_p (&bi_set) -+ && nds32_lmwsmw_insert_place (&bi_set) != NULL_RTX) -+ { -+ rtx place = nds32_lmwsmw_insert_place (&bi_set); -+ rtx base_reg = bi_set[0].base_reg; -+ -+ nds32_emit_multiple_insn (&bi_set, base_reg, place, true); -+ delete_insn (bi_set[i].insn); -+ delete_insn (bi_set[j].insn); -+ candidate_set.ordered_remove (j); -+ bi_set.block_remove (0, bi_set.length ()); -+ break; -+ } -+ -+ bi_set.block_remove (0, bi_set.length ()); -+ } -+ } -+ } -+} -+ -+/* Combine mutilple load/store insn into a lmw/smw insn. */ -+static void -+nds32_combine_load_store_insn (load_store_infos_t *load_store_info, -+ HARD_REG_SET *available_regset) -+{ -+ auto_vec candidate_set, main_set, temp_set; -+ auto_vec first_set, second_set; -+ HOST_WIDE_INT current_offset, last_offset = 0, add_offset = 0; -+ unsigned int i, j, regno; -+ int group_num = 0, group_id; -+ bool load_insn_p; -+ bool new_base_p = false; -+ bool prev_bim_p = false; -+ bool inc_p = true, dec_p = true; -+ rtx new_base_reg = NULL_RTX; -+ rtx base_reg = (*load_store_info)[0].base_reg; -+ rtx place; -+ unsigned new_base_regnum; -+ -+ /* Get available register to add offset for first instruction. */ -+ new_base_regnum = find_available_reg (available_regset, GENERAL_REGS); -+ if (new_base_regnum != INVALID_REGNUM) -+ { -+ CLEAR_HARD_REG_BIT (*available_regset, new_base_regnum); -+ new_base_reg = gen_rtx_REG (Pmode, new_base_regnum); -+ /* Copy attribute form base register to new base register. */ -+ ORIGINAL_REGNO (new_base_reg) = -+ ORIGINAL_REGNO ((*load_store_info)[0].base_reg); -+ REG_ATTRS (new_base_reg) = REG_ATTRS ((*load_store_info)[0].base_reg); -+ new_base_p = true; -+ -+ if (dump_file) -+ fprintf (dump_file, "Have new base register: %d\n", new_base_regnum); -+ } -+ -+ /* Recording instruction order of priority and initinal place. */ -+ for (i = 0; i < load_store_info->length (); ++i) -+ { -+ (*load_store_info)[i].order = i; -+ (*load_store_info)[i].place = false; -+ } -+ -+ /* Fetch first instruction information from 'load_store_info', -+ we will use first instruction as base, to search next instruction. */ -+ candidate_set.safe_push ((*load_store_info)[0]); -+ /* Set offset, regno, load_p state from candidate_set. */ -+ current_offset = candidate_set[0].offset; -+ regno = REGNO (candidate_set[0].reg); -+ load_insn_p = candidate_set[0].load_p; -+ /* Set first instruction group ID, -+ the group ID mark instruction for the same group. */ -+ candidate_set[0].group = group_num; -+ -+ /* Search instructions can be combined to a lmw/smw instruction. */ -+ for (i = 1; i < load_store_info->length (); ++i) -+ { -+ /* Collecting register number and offset is increase, -+ for example: -+ -+ lwi $r0, [$r22 + 4] <- base instruction -+ lwi $r1, [$r22 + 8] <- collect object -+ -+ The collect object (regno + 1), (offset + 4) -+ from base instruction. */ -+ if ((current_offset == (*load_store_info)[i].offset - 4) -+ && ((regno + 1) == REGNO ((*load_store_info)[i].reg)) -+ && (load_insn_p == (*load_store_info)[i].load_p) -+ && inc_p) -+ { -+ /* Give instruction group ID. */ -+ (*load_store_info)[i].group = group_num; -+ /* Save instruction. */ -+ candidate_set.safe_push ((*load_store_info)[i]); -+ /* Update state, next register number and offset. */ -+ regno = REGNO ((*load_store_info)[i].reg); -+ current_offset += 4; -+ /* Close decrease type, search increase type. */ -+ dec_p = false; -+ } -+ /* Collecting register number and offset is decrease, -+ for example: -+ -+ lwi $r2, [$r22 + 8] <- base instruction -+ lwi $r1, [$r22 + 4] <- collect object -+ -+ The collect object (regno - 1), (offset - 4) -+ from base instruction. */ -+ else if ((current_offset == (*load_store_info)[i].offset + 4) -+ && ((regno - 1) == REGNO ((*load_store_info)[i].reg)) -+ && (load_insn_p == (*load_store_info)[i].load_p) -+ && dec_p) -+ { -+ /* Give instruction group ID. */ -+ (*load_store_info)[i].group = group_num; -+ /* Save instruction. */ -+ candidate_set.safe_push ((*load_store_info)[i]); -+ -+ /* Update state, next register number and offset. */ -+ regno = REGNO ((*load_store_info)[i].reg); -+ current_offset -= 4; -+ /* Close increase type, search decrease type. */ -+ inc_p = false; -+ } -+ else -+ { -+ inc_p = true; -+ dec_p = true; -+ } -+ -+ /* Instructions collect is complete. */ -+ if ((inc_p && dec_p) -+ || (i + 1) == load_store_info->length ()) -+ { -+ /* Filter candidate instructions. */ -+ if (nds32_combine_multiple_p (&candidate_set, new_base_p) -+ && nds32_base_reg_safe_p (&candidate_set) -+ && nds32_lmwsmw_insert_place (&candidate_set) != NULL_RTX) -+ { -+ /* Store candidate instructions to 'main_set'. */ -+ for (j = 0; j < candidate_set.length (); j++) -+ main_set.safe_push (candidate_set[j]); -+ } -+ -+ /* Scan to the last instruction, it is complete. */ -+ if ((i + 1) == load_store_info->length ()) -+ break; -+ -+ /* Clean candidate_set sequence. */ -+ candidate_set.block_remove (0, candidate_set.length ()); -+ /* Reinitialize first instruction infomation -+ to search next instruction. */ -+ candidate_set.safe_push ((*load_store_info)[i]); -+ /* Update group number for next sequence. */ -+ group_num ++; -+ /* Set offset, regno, load_p state from candidate_set. */ -+ current_offset = candidate_set.last ().offset; -+ regno = REGNO (candidate_set.last ().reg); -+ load_insn_p = candidate_set.last ().load_p; -+ candidate_set.last ().group = group_num; -+ } -+ else if (!nds32_base_reg_safe_p (&candidate_set) -+ || nds32_lmwsmw_insert_place (&candidate_set) == NULL_RTX) -+ { -+ /* Check collect instruction for each instruction, -+ we store (n - 1) instructions in group, and -+ last instruction make next group First instruction. */ -+ for (j = 0; j < (candidate_set.length () - 1); j++) -+ temp_set.safe_push (candidate_set[j]); -+ -+ /* Store candidate instructions to 'main_set'. */ -+ if (nds32_combine_multiple_p (&temp_set, new_base_p)) -+ { -+ for (j = 0; j < (temp_set.length ()); j++) -+ main_set.safe_push (temp_set[j]); -+ } -+ -+ /* Clean temp_set sequence. */ -+ temp_set.block_remove (0, temp_set.length ()); -+ /* Clean candidate_set sequence. */ -+ candidate_set.block_remove (0, (candidate_set.length () - 1)); -+ /* Update group number for next sequence. */ -+ group_num ++; -+ /* Set offset, regno, load_p state from candidate_set. */ -+ current_offset = candidate_set.last ().offset; -+ regno = REGNO (candidate_set.last ().reg); -+ load_insn_p = candidate_set.last ().load_p; -+ candidate_set.last ().group = group_num; -+ /* Reset it for search increase and decrease type. */ -+ inc_p = true; -+ dec_p = true; -+ } -+ } -+ -+ if (dump_file) -+ { -+ if (!main_set.is_empty ()) -+ fprintf (dump_file,"Do lmwsmw instructions:\n"); -+ for (i = 0; i < main_set.length (); ++i) -+ { -+ fprintf (dump_file, -+ "regno = %d base_regno = %d " -+ "offset = " HOST_WIDE_INT_PRINT_DEC " " -+ "load_p = %d UID = %u group = %d," -+ " order = %d, place = %d\n", -+ REGNO (main_set[i].reg), -+ REGNO (main_set[i].base_reg), -+ main_set[i].offset, -+ main_set[i].load_p, -+ INSN_UID (main_set[i].insn), -+ main_set[i].group, -+ main_set[i].order, -+ main_set[i].place); -+ } -+ } -+ -+ /* Fetch first group instruction from main_set. */ -+ if (!main_set.is_empty ()) -+ { -+ /* Sort main_set by offset. */ -+ main_set.qsort (compare_offset); -+ -+ group_id = main_set[0].group; -+ nds32_fetch_group_insn (&main_set, &first_set, group_id); -+ last_offset = first_set.last ().offset; -+ } -+ -+ /* Main loop for emit lmw/smw instrucion. */ -+ while (!main_set.is_empty ()) -+ { -+ /* Get second group ID. */ -+ group_id = main_set[0].group; -+ for (i = 0; i < main_set.length (); ++i) -+ { -+ /* Prefer get consecutive offset form -+ first group to second group */ -+ if ((last_offset + 4) == main_set[i].offset) -+ { -+ group_id = main_set[i].group; -+ break; -+ } -+ } -+ -+ /* Fetch second instrucion group. */ -+ nds32_fetch_group_insn (&main_set, &second_set, group_id); -+ /* Get lmw/smw insert place. */ -+ place = nds32_lmwsmw_insert_place (&first_set); -+ -+ /* Adjust address offset, because lmw/smw instruction -+ only allow offset is zero. -+ example: -+ lwi $r0, [$r3 + 4] -+ lwi $r1, [$r3 + 8] -+ lwi $r2, [$r3 + 12] -+ -+ combine into -+ -+ addi $r3, $r3, 4 -+ lwm.bi(m) $r0, [$r3], $r2 -+ -+ Need addi instrucion to handle offset. */ -+ if (first_set[0].offset != 0 && !prev_bim_p) -+ { -+ if (dump_file) -+ fprintf (dump_file, "Use addi insn handle offset: " -+ "" HOST_WIDE_INT_PRINT_DEC "\n", -+ first_set[0].offset); -+ /* Use available register to process offset, -+ and don't recovey base register value. */ -+ if (new_base_p) -+ { -+ base_reg = new_base_reg; -+ add_offset = 0; -+ CLEAR_HARD_REG_BIT (*available_regset, new_base_regnum); -+ } -+ else -+ add_offset = first_set[0].offset; -+ -+ nds32_emit_add_insn (first_set[0], base_reg, place, true); -+ } -+ -+ if (nds32_use_bim_p (&first_set, &second_set)) -+ { -+ if (dump_file) -+ fprintf (dump_file, "Generate BIM form.\n"); -+ -+ nds32_emit_multiple_insn (&first_set, base_reg, place, true); -+ -+ /* Update status, for next instruction sequence. -+ The add_offset need add 4, because the instruction -+ is post increase. */ -+ add_offset = first_set.last ().offset + 4; -+ prev_bim_p = true; -+ } -+ else -+ { -+ if (dump_file) -+ fprintf (dump_file, "Generate BI form.\n"); -+ -+ nds32_emit_multiple_insn (&first_set, base_reg, place, false); -+ -+ if (add_offset != 0) -+ { -+ if (dump_file) -+ fprintf (dump_file, "Use addi insn handle -offset: " -+ "" HOST_WIDE_INT_PRINT_DEC "\n", -+ add_offset); -+ -+ nds32_emit_add_insn (first_set[0], base_reg, place, false); -+ add_offset = 0; -+ } -+ prev_bim_p = false; -+ -+ /* Recovey base register for next instruction sequence. */ -+ if (REGNO (base_reg) != REGNO (first_set[0].base_reg)) -+ base_reg = first_set[0].base_reg; -+ } -+ -+ /* Delete insn, replace by lmw/smw instruction. */ -+ for (i = 0; i < first_set.length (); ++i) -+ delete_insn (first_set[i].insn); -+ -+ /* Clean first_set for store next instruction group. */ -+ first_set.block_remove (0, first_set.length ()); -+ /* Store next instruction group. */ -+ for (i = 0; i < second_set.length (); ++i) -+ first_set.safe_insert (i, second_set[i]); -+ -+ /* Clean second_set. */ -+ second_set.block_remove (0, second_set.length ()); -+ -+ /* Update last_offset for search next group. */ -+ last_offset = first_set.last ().offset; -+ } -+ -+ /* Processing the last instruction group. */ -+ if (!first_set.is_empty ()) -+ { -+ /* Get lmw/smw insert place. */ -+ place = nds32_lmwsmw_insert_place (&first_set); -+ -+ if (first_set[0].offset != 0 && !prev_bim_p) -+ { -+ if (dump_file) -+ fprintf (dump_file, "Use addi insn handle offset: " -+ "" HOST_WIDE_INT_PRINT_DEC "\n", -+ first_set[0].offset); -+ -+ if (new_base_p) -+ { -+ base_reg = new_base_reg; -+ add_offset = 0; -+ } -+ else -+ add_offset = first_set[0].offset; -+ -+ nds32_emit_add_insn (first_set[0], base_reg, place, true); -+ } -+ -+ if (dump_file) -+ fprintf (dump_file, "Generate BI form.\n"); -+ -+ nds32_emit_multiple_insn (&first_set, base_reg, place, false); -+ -+ if (add_offset != 0) -+ { -+ if (dump_file) -+ fprintf (dump_file, "Use addi insn handle -offset: " -+ "" HOST_WIDE_INT_PRINT_DEC "\n", -+ -add_offset); -+ -+ nds32_emit_add_insn (first_set[0], base_reg, place, false); -+ } -+ -+ /* Delete insn, replace by lmw/smw instruction. */ -+ for (i = 0; i < first_set.length (); ++i) -+ delete_insn (first_set[i].insn); -+ } -+} -+ -+/* Combine mutilple load/store insn into a lmw/smw insn. */ -+static void -+nds32_rename_bi_insn (load_store_infos_t *load_store_info, -+ HARD_REG_SET *available_regset) -+{ -+ auto_vec candidate_set, bi_set, replace_set; -+ unsigned int i, j; -+ -+ bool load_insn_p; -+ enum nds32_memory_post_type post_type; -+ -+ for (i = 0; i < load_store_info->length (); ++i) -+ { -+ /* Recording instruction order of priority and initinal place. */ -+ (*load_store_info)[i].order = i; -+ (*load_store_info)[i].place = false; -+ candidate_set.safe_push ((*load_store_info)[i]); -+ } -+ -+ for (i = 0; i < candidate_set.length (); ++i) -+ { -+ load_insn_p = candidate_set[i].load_p; -+ post_type = candidate_set[i].post_type; -+ -+ for (j = i + 1; j < candidate_set.length (); ++j) -+ { -+ if ((post_type == candidate_set[j].post_type) -+ && (load_insn_p == candidate_set[j].load_p)) -+ { -+ bi_set.safe_push (candidate_set[i]); -+ bi_set.safe_push (candidate_set[j]); -+ -+ if (nds32_combine_multiple_p (&bi_set, false) -+ && nds32_base_reg_safe_p (&bi_set) -+ && nds32_lmwsmw_insert_place (&bi_set) != NULL_RTX) -+ { -+ nds32_find_reg (&bi_set, &replace_set, available_regset); -+ -+ if (!replace_set.is_empty ()) -+ { -+ unsigned k; -+ unsigned op_pos = replace_set[0].load_p ? 0 : 1; -+ -+ /* Do rename register. */ -+ for (k = 0; k < replace_set.length (); ++k) -+ nds32_rename_reg (replace_set[k].insn, op_pos, -+ replace_set[k].new_reg); -+ -+ replace_set.block_remove (0, replace_set.length ()); -+ } -+ -+ candidate_set.ordered_remove (j); -+ bi_set.block_remove (0, bi_set.length ()); -+ break; -+ } -+ -+ bi_set.block_remove (0, bi_set.length ()); -+ } -+ } -+ } -+} -+ -+/* Rename register, can be combined mutilple load/store insn. */ -+static void -+nds32_rename_load_store_reg (load_store_infos_t *load_store_info, -+ HARD_REG_SET *available_regset) -+{ -+ auto_vec rename_set, temp_set, replace_set; -+ HOST_WIDE_INT current_offset; -+ unsigned int i, j; -+ bool load_insn_p; -+ bool inc_p = true, dec_p = true; -+ -+ /* Recording instruction order of priority and initinal place. */ -+ for (i = 0; i < load_store_info->length (); ++i) -+ { -+ (*load_store_info)[i].order = i; -+ (*load_store_info)[i].place = false; -+ } -+ -+ /* Fetch first instruction information from 'load_store_info', -+ we will use first instruction as base, to search next instruction. */ -+ rename_set.safe_push ((*load_store_info)[0]); -+ /* Set offset, load_p state from rename_set. */ -+ current_offset = rename_set[0].offset; -+ load_insn_p = rename_set[0].load_p; -+ -+ /* Search instructions can be combined to a lmw/smw instruction. */ -+ for (i = 1; i < load_store_info->length (); ++i) -+ { -+ /* Collecting offset is increase, for example: -+ -+ lwi pseudo_reg, [$r22 + 4] <- base instruction -+ lwi pseudo_reg, [$r22 + 8] <- collect object -+ -+ The collect object (offset + 4) from base instruction. */ -+ if ((current_offset == (*load_store_info)[i].offset - 4) -+ && (load_insn_p == (*load_store_info)[i].load_p) -+ && inc_p) -+ { -+ /* Save instruction. */ -+ rename_set.safe_push ((*load_store_info)[i]); -+ /* Update offset. */ -+ current_offset += 4; -+ /* Close decrease type, search increase type. */ -+ dec_p = false; -+ } -+ /* Collecting offset is decrease, for example: -+ -+ lwi pseudo_reg, [$r22 + 8] <- base instruction -+ lwi pseudo_reg, [$r22 + 4] <- collect object -+ -+ The collect object (offset - 4) from base instruction. */ -+ else if ((current_offset == (*load_store_info)[i].offset + 4) -+ && (load_insn_p == (*load_store_info)[i].load_p) -+ && dec_p) -+ { -+ /* Save instruction. */ -+ rename_set.safe_push ((*load_store_info)[i]); -+ -+ /* Update offset. */ -+ current_offset -= 4; -+ /* Close increase type, search decrease type. */ -+ inc_p = false; -+ } -+ else -+ { -+ inc_p = true; -+ dec_p = true; -+ } -+ -+ /* Instructions collect is completed. */ -+ if ((inc_p && dec_p) -+ || (i + 1) == load_store_info->length ()) -+ { -+ /* Check whether the rename register. */ -+ if (nds32_combine_multiple_p (&rename_set, false) -+ && nds32_base_reg_safe_p (&rename_set) -+ && nds32_lmwsmw_insert_place (&rename_set) != NULL_RTX) -+ { -+ /* Find can rename instruction, and store in 'replace_set'. */ -+ nds32_find_reg (&rename_set, &replace_set, available_regset); -+ -+ if (!replace_set.is_empty ()) -+ { -+ unsigned op_pos = replace_set[0].load_p ? 0 : 1; -+ -+ /* Do rename register. */ -+ for (j = 0; j < replace_set.length (); ++j) -+ nds32_rename_reg (replace_set[j].insn, op_pos, -+ replace_set[j].new_reg); -+ -+ replace_set.block_remove (0, replace_set.length ()); -+ } -+ } -+ -+ /* Scan to the last instruction, it is complete. */ -+ if ((i + 1) == load_store_info->length ()) -+ break; -+ -+ /* Clean rename_set sequence. */ -+ rename_set.block_remove (0, rename_set.length ()); -+ /* Reinitialize first instruction infomation -+ to search next instruction. */ -+ rename_set.safe_push ((*load_store_info)[i]); -+ /* Set offset, load_p state from rename_set. */ -+ current_offset = rename_set.last ().offset; -+ load_insn_p = rename_set.last ().load_p; -+ } -+ else if (!nds32_base_reg_safe_p (&rename_set) -+ || nds32_lmwsmw_insert_place (&rename_set) == NULL_RTX) -+ { -+ /* Check collect instruction for each instruction, -+ we store (n - 1) instructions in group, and -+ last instruction as the first instruction of the next group. */ -+ for (j = 0; j < (rename_set.length () - 1); j++) -+ temp_set.safe_push (rename_set[j]); -+ -+ if (nds32_combine_multiple_p (&temp_set, false)) -+ { -+ /* Find can rename instruction, and store in 'replace_set'. */ -+ nds32_find_reg (&temp_set, &replace_set, available_regset); -+ -+ if (!replace_set.is_empty ()) -+ { -+ unsigned op_pos = replace_set[0].load_p ? 0 : 1; -+ -+ /* Do rename register. */ -+ for (j = 0; j < replace_set.length (); ++j) -+ nds32_rename_reg (replace_set[j].insn, op_pos, -+ replace_set[j].new_reg); -+ -+ replace_set.block_remove (0, replace_set.length ()); -+ } -+ } -+ -+ /* Clean temp_set sequence. */ -+ temp_set.block_remove (0, temp_set.length ()); -+ /* Clean rename_set sequence. */ -+ rename_set.block_remove (0, (rename_set.length () - 1)); -+ /* Set offset, regno, load_p state from rename_set. */ -+ current_offset = rename_set.last ().offset; -+ load_insn_p = rename_set.last ().load_p; -+ /* Reset it for search increase and decrease type. */ -+ inc_p = true; -+ dec_p = true; -+ } -+ } -+} -+ -+static void -+nds32_do_lmwsmw_opt (basic_block bb, bool rename_p) -+{ -+ rtx_insn *insn; -+ HARD_REG_SET available_regset; -+ load_store_info_t load_store_info; -+ auto_vec load_store_infos[NDS32_GPR_NUM]; -+ auto_vec plus_infos[NDS32_GPR_NUM]; -+ auto_vec post_infos[NDS32_GPR_NUM]; -+ int i; -+ unsigned j; -+ unsigned regno; -+ unsigned polluting; -+ df_ref def; -+ /* Dirty mean a register is define again after -+ first load/store instruction. -+ For example: -+ -+ lwi $r2, [$r3 + #0x100] -+ mov $r3, $r4 ! $r3 is dirty after this instruction. -+ lwi $r1, [$r3 + #0x120] ! so this load can't chain with prev load. -+ */ -+ bool dirty[NDS32_GPR_NUM]; -+ -+ if (dump_file) -+ fprintf (dump_file, "scan bb %d\n", bb->index); -+ -+ for (i = 0; i < NDS32_GPR_NUM; ++i) -+ dirty[i] = false; -+ -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (!INSN_P (insn)) -+ continue; -+ -+ polluting = INVALID_REGNUM; -+ -+ /* Set def reg is dirty if chain is not empty. */ -+ FOR_EACH_INSN_USE (def, insn) -+ { -+ regno = DF_REF_REGNO (def); -+ -+ if (!NDS32_IS_GPR_REGNUM (regno)) -+ continue; -+ -+ if (!load_store_infos[regno].is_empty ()) -+ { -+ /* Set pulluting here because the source register -+ may be the same one. */ -+ if (dirty[regno] == false) -+ polluting = regno; -+ -+ dirty[regno] = true; -+ } -+ } -+ -+ /* Set all caller-save register is dirty if chain is not empty. */ -+ if (CALL_P (insn)) -+ { -+ for (i = 0; i < NDS32_GPR_NUM; ++i) -+ { -+ if (call_used_regs[i] && !load_store_infos[i].is_empty ()) -+ dirty[i] = true; -+ } -+ } -+ -+ if (nds32_load_store_reg_plus_offset (insn, &load_store_info)) -+ { -+ regno = REGNO (load_store_info.base_reg); -+ gcc_assert (NDS32_IS_GPR_REGNUM (regno)); -+ -+ /* Don't add to chain if this reg is dirty. */ -+ if (dirty[regno] && polluting != regno) -+ break; -+ -+ /* If the register is first time to be used and be polluted -+ right away, we don't push it. */ -+ if (regno == REGNO (load_store_info.reg) && load_store_info.load_p -+ && dirty[regno] == false) -+ continue; -+ -+ load_store_infos[regno].safe_push (load_store_info); -+ } -+ } -+ -+ for (i = 0; i < NDS32_GPR_NUM; ++i) -+ { -+ for (j = 0; j < load_store_infos[i].length (); ++j) -+ { -+ if (load_store_infos[i][j].post_type == NDS32_NONE) -+ plus_infos[i].safe_push (load_store_infos[i][j]); -+ else -+ post_infos[i].safe_push (load_store_infos[i][j]); -+ } -+ } -+ -+ for (i = 0; i < NDS32_GPR_NUM; ++i) -+ { -+ if (load_store_infos[i].length () <= 1) -+ { -+ if (dump_file && load_store_infos[i].length () == 1) -+ fprintf (dump_file, -+ "Skip Chain for $r%d since chain size only 1\n", -+ i); -+ continue; -+ } -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, -+ "Chain for $r%d: (size = %u)\n", -+ i, load_store_infos[i].length ()); -+ -+ for (j = 0; j < load_store_infos[i].length (); ++j) -+ { -+ fprintf (dump_file, -+ "regno = %d base_regno = %d " -+ "offset = " HOST_WIDE_INT_PRINT_DEC " " -+ "load_p = %d UID = %u place = %d\n", -+ REGNO (load_store_infos[i][j].reg), -+ REGNO (load_store_infos[i][j].base_reg), -+ load_store_infos[i][j].offset, -+ load_store_infos[i][j].load_p, -+ INSN_UID (load_store_infos[i][j].insn), -+ load_store_infos[i][j].place); -+ } -+ } -+ -+ nds32_get_available_reg_set (bb, -+ load_store_infos[i][0].insn, -+ load_store_infos[i].last ().insn, -+ &available_regset); -+ if (dump_file) -+ print_hard_reg_set (dump_file, "", available_regset); -+ -+ /* If rename_p is true, then do rename register of load/store -+ instruction. Otherwise combination of a multiple load/sotre -+ a multiple load/store instruction. */ -+ if (rename_p) -+ { -+ if (plus_infos[i].length () > 1) -+ nds32_rename_load_store_reg (&plus_infos[i], &available_regset); -+ if (post_infos[i].length () > 1) -+ nds32_rename_bi_insn (&post_infos[i], &available_regset); -+ } -+ else -+ { -+ if (plus_infos[i].length () > 1) -+ nds32_combine_load_store_insn (&plus_infos[i], &available_regset); -+ if (post_infos[i].length () > 1) -+ nds32_combine_bi_insn (&post_infos[i]); -+ } -+ } -+} -+ -+static void -+nds32_lmwsmw_opt (bool rename_p) -+{ -+ basic_block bb; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ nds32_do_lmwsmw_opt (bb, rename_p); -+} -+ -+/* Implement rename register for load and store instruction. */ -+static unsigned int -+rest_of_handle_rename_lmwsmw_opt (void) -+{ -+ init_alias_analysis (); -+ -+ df_set_flags (DF_LR_RUN_DCE); -+ df_note_add_problem (); -+ df_analyze (); -+ df_set_flags (DF_DEFER_INSN_RESCAN); -+ -+ regrename_init (true); -+ regrename_analyze (NULL); -+ -+ nds32_lmwsmw_opt (true); -+ -+ regrename_finish (); -+ -+ /* We are finished with alias. */ -+ end_alias_analysis (); -+ return 1; -+} -+ -+/* Implement generate lmw and smw instruction. */ -+static unsigned int -+rest_of_handle_gen_lmwsmw_opt (void) -+{ -+ init_alias_analysis (); -+ -+ df_note_add_problem (); -+ df_analyze (); -+ nds32_lmwsmw_opt (false); -+ -+ /* We are finished with alias. */ -+ end_alias_analysis (); -+ return 1; -+} -+ -+ -+const pass_data pass_data_nds32_rename_lmwsmw_opt = -+{ -+ RTL_PASS, /* type */ -+ "rename_lmwsmw_opt", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ 0, /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_df_finish, /* todo_flags_finish */ -+}; -+ -+class pass_nds32_rename_lmwsmw_opt : public rtl_opt_pass -+{ -+public: -+ pass_nds32_rename_lmwsmw_opt (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_rename_lmwsmw_opt, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { return flag_nds32_lmwsmw_opt; } -+ unsigned int execute (function *) { return rest_of_handle_rename_lmwsmw_opt (); } -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_rename_lmwsmw_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_rename_lmwsmw_opt (ctxt); -+} -+ -+const pass_data pass_data_nds32_gen_lmwsmw_opt = -+{ -+ RTL_PASS, /* type */ -+ "gen_lmwsmw_opt", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ 0, /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_df_finish, /* todo_flags_finish */ -+}; -+ -+class pass_nds32_gen_lmwsmw_opt : public rtl_opt_pass -+{ -+public: -+ pass_nds32_gen_lmwsmw_opt (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_gen_lmwsmw_opt, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { return flag_nds32_lmwsmw_opt; } -+ unsigned int execute (function *) { return rest_of_handle_gen_lmwsmw_opt (); } -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_gen_lmwsmw_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_gen_lmwsmw_opt (ctxt); -+} -diff --git a/gcc/config/nds32/nds32-load-store-opt.c b/gcc/config/nds32/nds32-load-store-opt.c -new file mode 100644 -index 0000000..9e5161e ---- /dev/null -+++ b/gcc/config/nds32/nds32-load-store-opt.c -@@ -0,0 +1,721 @@ -+/* load-store-opt pass of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "backend.h" -+#include "tree.h" -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" -+#include "cpplib.h" -+#include "params.h" -+#include "tree-pass.h" -+#include "target-globals.h" -+#include "nds32-load-store-opt.h" -+#include "nds32-reg-utils.h" -+#include -+ -+#define NDS32_GPR_NUM 32 -+ -+static new_base_reg_info_t gen_new_base (rtx, -+ offset_info_t, -+ unsigned, -+ HOST_WIDE_INT, -+ HOST_WIDE_INT); -+ -+static const load_store_optimize_pass *load_store_optimizes[] = -+{ -+ /* allow_regclass, new_base_regclass, -+ offset_lower_bound, offset_upper_bound, -+ load_only_p, name */ -+ new load_store_optimize_pass ( -+ LOW_REGS, LOW_REGS, -+ 0, (32-4), -+ false, "lswi333"), -+ new load_store_optimize_pass ( -+ LOW_REGS, FRAME_POINTER_REG, -+ 0, (512-4), -+ false, "lswi37"), -+ new load_store_optimize_pass ( -+ MIDDLE_REGS, GENERAL_REGS, -+ 0, 0, -+ false, "lswi450"), -+ new load_store_optimize_pass ( -+ MIDDLE_REGS, R8_REG, -+ -128, -4, -+ true, "lwi45fe") -+}; -+ -+static const int N_LOAD_STORE_OPT_TYPE = sizeof (load_store_optimizes) -+ / sizeof (load_store_optimize_pass*); -+ -+load_store_optimize_pass -+::load_store_optimize_pass (enum reg_class allow_regclass, -+ enum reg_class new_base_regclass, -+ HOST_WIDE_INT offset_lower_bound, -+ HOST_WIDE_INT offset_upper_bound, -+ bool load_only_p, -+ const char *name) -+ : m_allow_regclass (allow_regclass), -+ m_new_base_regclass (new_base_regclass), -+ m_offset_lower_bound (offset_lower_bound), -+ m_offset_upper_bound (offset_upper_bound), -+ m_load_only_p (load_only_p), -+ m_name (name) -+{ -+ gcc_assert (offset_lower_bound <= offset_upper_bound); -+} -+ -+int -+load_store_optimize_pass::calc_gain (HARD_REG_SET *available_regset, -+ offset_info_t offset_info, -+ load_store_infos_t *load_store_info) const -+{ -+ int extra_cost = 0; -+ int gain = 0; -+ unsigned i; -+ unsigned chain_size; -+ unsigned new_base_regnum; -+ HOST_WIDE_INT allow_range = m_offset_upper_bound - m_offset_lower_bound; -+ new_base_regnum = find_available_reg (available_regset, m_new_base_regclass); -+ chain_size = load_store_info->length (); -+ -+ if (new_base_regnum == INVALID_REGNUM) -+ { -+ if (dump_file) -+ fprintf (dump_file, -+ "%s have no avariable register, so give up try %s\n", -+ reg_class_names[m_new_base_regclass], -+ m_name); -+ return 0; -+ } -+ else if (dump_file) -+ fprintf (dump_file, -+ "%s is avariable, get %s, try %s, chain size = %u\n", -+ reg_class_names[m_new_base_regclass], -+ reg_names[new_base_regnum], -+ m_name, -+ chain_size); -+ -+ HOST_WIDE_INT range = offset_info.max_offset - offset_info.min_offset; -+ -+ if (range > allow_range) -+ { -+ /* TODO: We can perform load-store opt for only part of load store. */ -+ if (dump_file) -+ fprintf (dump_file, -+ "range is too large for %s" -+ " (range = " HOST_WIDE_INT_PRINT_DEC ", " -+ "allow_range = " HOST_WIDE_INT_PRINT_DEC ")\n", -+ m_name, range, allow_range); -+ return 0; -+ } -+ -+ if (offset_info.min_offset >= m_offset_lower_bound -+ && offset_info.max_offset <= m_offset_upper_bound) -+ { -+ /* mov55. */ -+ extra_cost = 2; -+ } -+ else -+ { -+ if (satisfies_constraint_Is15 (GEN_INT (offset_info.min_offset -+ - m_offset_lower_bound))) -+ { -+ /* add. */ -+ extra_cost = 4; -+ } -+ else -+ { -+ /* TODO: Try m_offset_upper_bound instead of m_offset_lower_bound -+ again. */ -+ /* add45 + movi. */ -+ if (satisfies_constraint_Is20 (GEN_INT (offset_info.min_offset -+ - m_offset_lower_bound))) -+ extra_cost = 6; -+ else -+ return -1; /* Give up if this constant is too large. */ -+ } -+ } -+ -+ for (i = 0; i < chain_size; ++i) -+ { -+ if (m_load_only_p && !(*load_store_info)[i].load_p) -+ continue; -+ -+ if (in_reg_class_p ((*load_store_info)[i].reg, m_allow_regclass)) -+ gain += 2; -+ } -+ -+ if (dump_file) -+ fprintf (dump_file, -+ "%s: gain = %d extra_cost = %d\n", -+ m_name, gain, extra_cost); -+ -+ return gain - extra_cost; -+} -+ -+ -+void -+load_store_optimize_pass::do_optimize ( -+ HARD_REG_SET *available_regset, -+ offset_info_t offset_info, -+ load_store_infos_t *load_store_info) const -+{ -+ new_base_reg_info_t new_base_reg_info; -+ rtx load_store_insn; -+ unsigned new_base_regnum; -+ -+ new_base_regnum = find_available_reg (available_regset, m_new_base_regclass); -+ gcc_assert (new_base_regnum != INVALID_REGNUM); -+ -+ new_base_reg_info = -+ gen_new_base ((*load_store_info)[0].base_reg, -+ offset_info, -+ new_base_regnum, -+ m_offset_lower_bound, m_offset_upper_bound); -+ unsigned i; -+ rtx insn; -+ insn = emit_insn_before (new_base_reg_info.set_insns[0], -+ (*load_store_info)[0].insn); -+ if (new_base_reg_info.n_set_insns > 1) -+ { -+ gcc_assert (new_base_reg_info.n_set_insns == 2); -+ emit_insn_before (new_base_reg_info.set_insns[1], insn); -+ } -+ -+ for (i = 0; i < load_store_info->length (); ++i) -+ { -+ if (m_load_only_p && !(*load_store_info)[i].load_p) -+ continue; -+ -+ if (!in_reg_class_p ((*load_store_info)[i].reg, m_allow_regclass)) -+ continue; -+ -+ HOST_WIDE_INT offset = (*load_store_info)[i].offset; -+ -+ if (new_base_reg_info.need_adjust_offset_p) -+ offset = offset + new_base_reg_info.adjust_offset; -+ -+ load_store_insn = -+ gen_reg_plus_imm_load_store ((*load_store_info)[i].reg, -+ new_base_reg_info.reg, -+ offset, -+ (*load_store_info)[i].load_p, -+ (*load_store_info)[i].mem); -+ -+ emit_insn_before (load_store_insn, (*load_store_info)[i].insn); -+ -+ delete_insn ((*load_store_info)[i].insn); -+ } -+ -+ /* Recompute it CFG, to update BB_END() instruction. */ -+ compute_bb_for_insn (); -+} -+ -+static new_base_reg_info_t -+gen_new_base (rtx original_base_reg, -+ offset_info_t offset_info, -+ unsigned new_base_regno, -+ HOST_WIDE_INT offset_lower, -+ HOST_WIDE_INT offset_upper) -+{ -+ new_base_reg_info_t new_base_reg_info; -+ -+ /* Use gen_raw_REG instead of gen_rtx_REG to prevent break the reg -+ info for global one. -+ For example, gen_rtx_REG will return frame_pointer_rtx immediate -+ instead of create new rtx for gen_raw_REG (Pmode, FP_REGNUM). */ -+ new_base_reg_info.reg = gen_raw_REG (Pmode, new_base_regno); -+ -+ /* Setup register info. */ -+ ORIGINAL_REGNO (new_base_reg_info.reg) = ORIGINAL_REGNO (original_base_reg); -+ REG_ATTRS (new_base_reg_info.reg) = REG_ATTRS (original_base_reg); -+ -+ if (offset_info.max_offset <= offset_upper -+ && offset_info.min_offset >= offset_lower) -+ { -+ new_base_reg_info.set_insns[0] = gen_movsi (new_base_reg_info.reg, -+ original_base_reg); -+ new_base_reg_info.n_set_insns = 1; -+ new_base_reg_info.need_adjust_offset_p = false; -+ new_base_reg_info.adjust_offset = 0; -+ } -+ else -+ { -+ /* For example: -+ lwi45.fe allow -4 ~ -128 range: -+ offset_lower = #-4 -+ offset_upper = #-128 -+ -+ lwi $r2, [$r12 + #10] -+ -> -+ addi $r8, $r12, #14 ! $r8 = $r12 + #10 - offset_lower -+ ! = $r12 + #10 - #-4 -+ ! = $r12 + #14 -+ lwi45.fe $r2, [$r8 - #4] ! [$r8 - #4] -+ ! = [$r12 + #14 - #4] -+ ! = [$r12 + #10] -+ */ -+ new_base_reg_info.adjust_offset = -+ -(offset_info.min_offset - offset_lower); -+ -+ rtx offset = GEN_INT (-new_base_reg_info.adjust_offset); -+ -+ -+ if (satisfies_constraint_Is15 (offset)) -+ { -+ new_base_reg_info.set_insns[0] = -+ gen_addsi3(new_base_reg_info.reg, -+ original_base_reg, -+ offset); -+ -+ new_base_reg_info.n_set_insns = 1; -+ } -+ else -+ { -+ if (!satisfies_constraint_Is20 (offset)) -+ gcc_unreachable (); -+ -+ new_base_reg_info.set_insns[1] = -+ gen_rtx_SET (new_base_reg_info.reg, -+ GEN_INT (-new_base_reg_info.adjust_offset)); -+ -+ new_base_reg_info.set_insns[0] = -+ gen_addsi3 (new_base_reg_info.reg, -+ new_base_reg_info.reg, -+ original_base_reg); -+ -+ new_base_reg_info.n_set_insns = 2; -+ } -+ -+ new_base_reg_info.need_adjust_offset_p = true; -+ } -+ -+ return new_base_reg_info; -+} -+ -+static bool -+nds32_4byte_load_store_reg_plus_offset ( -+ rtx_insn *insn, -+ load_store_info_t *load_store_info) -+{ -+ if (!INSN_P (insn)) -+ return false; -+ -+ rtx pattern = PATTERN (insn); -+ rtx mem = NULL_RTX; -+ rtx reg = NULL_RTX; -+ rtx base_reg = NULL_RTX; -+ rtx addr; -+ HOST_WIDE_INT offset = 0; -+ bool load_p = false; -+ -+ if (GET_CODE (pattern) != SET) -+ return false; -+ -+ if (MEM_P (SET_SRC (pattern))) -+ { -+ mem = SET_SRC (pattern); -+ reg = SET_DEST (pattern); -+ load_p = true; -+ } -+ -+ if (MEM_P (SET_DEST (pattern))) -+ { -+ mem = SET_DEST (pattern); -+ reg = SET_SRC (pattern); -+ load_p = false; -+ } -+ -+ if (mem == NULL_RTX || reg == NULL_RTX || !REG_P (reg)) -+ return false; -+ -+ gcc_assert (REG_P (reg)); -+ -+ addr = XEXP (mem, 0); -+ -+ /* We only care about [reg] and [reg+const]. */ -+ if (REG_P (addr)) -+ { -+ base_reg = addr; -+ offset = 0; -+ } -+ else if (GET_CODE (addr) == PLUS -+ && CONST_INT_P (XEXP (addr, 1))) -+ { -+ base_reg = XEXP (addr, 0); -+ offset = INTVAL (XEXP (addr, 1)); -+ if (!REG_P (base_reg)) -+ return false; -+ } -+ else -+ return false; -+ -+ /* At least need MIDDLE_REGS. */ -+ if (!in_reg_class_p (reg, MIDDLE_REGS)) -+ return false; -+ -+ /* lwi450/swi450 */ -+ if (offset == 0) -+ return false; -+ -+ if (in_reg_class_p (reg, LOW_REGS)) -+ { -+ /* lwi37.sp/swi37.sp/lwi37/swi37 */ -+ if ((REGNO (base_reg) == SP_REGNUM -+ || REGNO (base_reg) == FP_REGNUM) -+ && (offset >= 0 && offset < 512 && (offset % 4 == 0))) -+ return false; -+ -+ /* lwi333/swi333 */ -+ if (in_reg_class_p (base_reg, LOW_REGS) -+ && (offset >= 0 && offset < 32 && (offset % 4 == 0))) -+ return false; -+ } -+ -+ if (load_store_info) -+ { -+ load_store_info->load_p = load_p; -+ load_store_info->offset = offset; -+ load_store_info->reg = reg; -+ load_store_info->base_reg = base_reg; -+ load_store_info->insn = insn; -+ load_store_info->mem = mem; -+ } -+ -+ if (GET_MODE (reg) != SImode) -+ return false; -+ -+ return true; -+} -+ -+static bool -+nds32_4byte_load_store_reg_plus_offset_p (rtx_insn *insn) -+{ -+ return nds32_4byte_load_store_reg_plus_offset (insn, NULL); -+} -+ -+static bool -+nds32_load_store_opt_profitable_p (basic_block bb) -+{ -+ int candidate = 0; -+ int threshold = 2; -+ rtx_insn *insn; -+ -+ if (dump_file) -+ fprintf (dump_file, "scan bb %d\n", bb->index); -+ -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (nds32_4byte_load_store_reg_plus_offset_p (insn)) -+ candidate++; -+ } -+ -+ if (dump_file) -+ fprintf (dump_file, " candidate = %d\n", candidate); -+ -+ return candidate >= threshold; -+} -+ -+static offset_info_t -+nds32_get_offset_info (auto_vec *load_store_info) -+{ -+ unsigned i; -+ std::set offsets; -+ offset_info_t offset_info; -+ offset_info.max_offset = 0; -+ offset_info.min_offset = 0; -+ offset_info.num_offset = 0; -+ -+ if (load_store_info->length () == 0) -+ return offset_info; -+ -+ offset_info.max_offset = (*load_store_info)[0].offset; -+ offset_info.min_offset = (*load_store_info)[0].offset; -+ offsets.insert ((*load_store_info)[0].offset); -+ -+ for (i = 1; i < load_store_info->length (); i++) -+ { -+ HOST_WIDE_INT offset = (*load_store_info)[i].offset; -+ offset_info.max_offset = MAX (offset_info.max_offset, offset); -+ offset_info.min_offset = MIN (offset_info.min_offset, offset); -+ offsets.insert (offset); -+ } -+ -+ offset_info.num_offset = offsets.size (); -+ -+ return offset_info; -+} -+ -+static void -+nds32_do_load_store_opt (basic_block bb) -+{ -+ rtx_insn *insn; -+ load_store_info_t load_store_info; -+ auto_vec load_store_infos[NDS32_GPR_NUM]; -+ HARD_REG_SET available_regset; -+ int i; -+ unsigned j; -+ unsigned regno; -+ unsigned polluting; -+ df_ref def; -+ /* Dirty mean a register is define again after -+ first load/store instruction. -+ For example: -+ -+ lwi $r2, [$r3 + #0x100] -+ mov $r3, $r4 ! $r3 is dirty after this instruction. -+ lwi $r1, [$r3 + #0x120] ! so this load can't chain with prev load. -+ */ -+ bool dirty[NDS32_GPR_NUM]; -+ -+ if (dump_file) -+ fprintf (dump_file, "try load store opt for bb %d\n", bb->index); -+ -+ for (i = 0; i < NDS32_GPR_NUM; ++i) -+ dirty[i] = false; -+ -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (!INSN_P (insn)) -+ continue; -+ -+ polluting = INVALID_REGNUM; -+ -+ /* Set def reg is dirty if chain is not empty. */ -+ FOR_EACH_INSN_DEF (def, insn) -+ { -+ regno = DF_REF_REGNO (def); -+ -+ if (!NDS32_IS_GPR_REGNUM (regno)) -+ continue; -+ -+ if (!load_store_infos[regno].is_empty ()) -+ { -+ /* Set pulluting here because the source register -+ may be the same one. */ -+ if (dirty[regno] == false) -+ polluting = regno; -+ -+ dirty[regno] = true; -+ } -+ } -+ -+ /* Set all caller-save register is dirty if chain is not empty. */ -+ if (CALL_P (insn)) -+ { -+ for (i = 0; i < NDS32_GPR_NUM; ++i) -+ { -+ if (call_used_regs[i] && !load_store_infos[i].is_empty ()) -+ dirty[i] = true; -+ } -+ } -+ -+ if (nds32_4byte_load_store_reg_plus_offset (insn, &load_store_info)) -+ { -+ regno = REGNO (load_store_info.base_reg); -+ gcc_assert (NDS32_IS_GPR_REGNUM (regno)); -+ -+ /* Don't add to chain if this reg is dirty. */ -+ if (dirty[regno] && polluting != regno) -+ break; -+ -+ /* If the register is first time to be used and be polluted -+ right away, we don't push it. */ -+ if (regno == REGNO (load_store_info.reg) && load_store_info.load_p -+ && dirty[regno] == false) -+ continue; -+ -+ load_store_infos[regno].safe_push (load_store_info); -+ } -+ } -+ for (i = 0; i < NDS32_GPR_NUM; ++i) -+ { -+ if (load_store_infos[i].length () <= 1) -+ { -+ if (dump_file && load_store_infos[i].length () == 1) -+ fprintf (dump_file, -+ "Skip Chain for $r%d since chain size only 1\n", -+ i); -+ continue; -+ } -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, -+ "Chain for $r%d: (size = %u)\n", -+ i, load_store_infos[i].length ()); -+ -+ for (j = 0; j < load_store_infos[i].length (); ++j) -+ { -+ fprintf (dump_file, -+ "regno = %d base_regno = %d " -+ "offset = " HOST_WIDE_INT_PRINT_DEC " " -+ "load_p = %d UID = %u\n", -+ REGNO (load_store_infos[i][j].reg), -+ REGNO (load_store_infos[i][j].base_reg), -+ load_store_infos[i][j].offset, -+ load_store_infos[i][j].load_p, -+ INSN_UID (load_store_infos[i][j].insn)); -+ } -+ } -+ -+ nds32_get_available_reg_set (bb, -+ load_store_infos[i][0].insn, -+ load_store_infos[i].last ().insn, -+ &available_regset); -+ -+ if (dump_file) -+ { -+ print_hard_reg_set (dump_file, "", available_regset); -+ } -+ -+ offset_info_t offset_info = nds32_get_offset_info (&load_store_infos[i]); -+ if (dump_file) -+ { -+ fprintf (dump_file, -+ "max offset = " HOST_WIDE_INT_PRINT_DEC "\n" -+ "min offset = " HOST_WIDE_INT_PRINT_DEC "\n" -+ "num offset = %d\n", -+ offset_info.max_offset, -+ offset_info.min_offset, -+ offset_info.num_offset); -+ } -+ -+ int gain; -+ int best_gain = 0; -+ const load_store_optimize_pass *best_load_store_optimize_pass = NULL; -+ -+ for (j = 0; j < N_LOAD_STORE_OPT_TYPE; ++j) -+ { -+ gain = load_store_optimizes[j]->calc_gain (&available_regset, -+ offset_info, -+ &load_store_infos[i]); -+ -+ if (dump_file) -+ fprintf (dump_file, "%s gain = %d\n", -+ load_store_optimizes[j]->name (), gain); -+ -+ if (gain > best_gain) -+ { -+ best_gain = gain; -+ best_load_store_optimize_pass = load_store_optimizes[j]; -+ } -+ } -+ -+ if (best_load_store_optimize_pass) -+ { -+ if (dump_file) -+ fprintf (dump_file, "%s is most profit, optimize it!\n", -+ best_load_store_optimize_pass->name ()); -+ -+ best_load_store_optimize_pass->do_optimize (&available_regset, -+ offset_info, -+ &load_store_infos[i]); -+ -+ df_insn_rescan_all (); -+ } -+ -+ } -+} -+ -+static unsigned int -+nds32_load_store_opt (void) -+{ -+ basic_block bb; -+ -+ df_set_flags (DF_LR_RUN_DCE); -+ df_note_add_problem (); -+ df_analyze (); -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ if (nds32_load_store_opt_profitable_p (bb)) -+ nds32_do_load_store_opt (bb); -+ } -+ -+ return 1; -+} -+ -+const pass_data pass_data_nds32_load_store_opt = -+{ -+ RTL_PASS, /* type */ -+ "load_store_opt", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ 0, /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_df_finish, /* todo_flags_finish */ -+}; -+ -+class pass_nds32_load_store_opt : public rtl_opt_pass -+{ -+public: -+ pass_nds32_load_store_opt (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_load_store_opt, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { return TARGET_16_BIT && TARGET_LOAD_STORE_OPT; } -+ unsigned int execute (function *) { return nds32_load_store_opt (); } -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_load_store_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_load_store_opt (ctxt); -+} -diff --git a/gcc/config/nds32/nds32-load-store-opt.h b/gcc/config/nds32/nds32-load-store-opt.h -new file mode 100644 -index 0000000..f94b56a ---- /dev/null -+++ b/gcc/config/nds32/nds32-load-store-opt.h -@@ -0,0 +1,117 @@ -+/* Prototypes for load-store-opt of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+#ifndef NDS32_LOAD_STORE_OPT_H -+#define NDS32_LOAD_STORE_OPT_H -+ -+/* Define the type of a set of hard registers. */ -+ -+enum nds32_memory_post_type -+{ -+ NDS32_NONE, -+ NDS32_POST_INC, -+ NDS32_POST_DEC -+}; -+ -+typedef struct { -+ rtx reg; -+ rtx base_reg; -+ rtx offset; -+ HOST_WIDE_INT shift; -+ bool load_p; -+ rtx insn; -+} rr_load_store_info_t; -+ -+typedef struct { -+ rtx reg; -+ rtx base_reg; -+ HOST_WIDE_INT offset; -+ bool load_p; -+ rtx_insn *insn; -+ rtx mem; -+ int new_reg; -+ int order; -+ int group; -+ bool place; -+ enum nds32_memory_post_type post_type; -+} load_store_info_t; -+ -+typedef struct { -+ HOST_WIDE_INT max_offset; -+ HOST_WIDE_INT min_offset; -+ /* How many different offset. */ -+ int num_offset; -+} offset_info_t; -+ -+typedef struct { -+ rtx set_insns[2]; -+ int n_set_insns; -+ rtx reg; -+ bool need_adjust_offset_p; -+ HOST_WIDE_INT adjust_offset; -+} new_base_reg_info_t; -+ -+typedef struct { -+ unsigned int amount; -+ unsigned int start; -+ unsigned int end; -+} available_reg_info_t; -+ -+typedef auto_vec load_store_infos_t; -+ -+class load_store_optimize_pass -+{ -+public: -+ load_store_optimize_pass (enum reg_class, -+ enum reg_class, -+ HOST_WIDE_INT, -+ HOST_WIDE_INT, -+ bool, -+ const char *); -+ const char *name () const { return m_name; }; -+ int calc_gain (HARD_REG_SET *, -+ offset_info_t, -+ load_store_infos_t *) const; -+ void do_optimize (HARD_REG_SET *, -+ offset_info_t, -+ load_store_infos_t *) const; -+private: -+ enum reg_class m_allow_regclass; -+ enum reg_class m_new_base_regclass; -+ HOST_WIDE_INT m_offset_lower_bound; -+ HOST_WIDE_INT m_offset_upper_bound; -+ bool m_load_only_p; -+ const char *m_name; -+}; -+ -+static inline rtx -+gen_reg_plus_imm_load_store (rtx reg, rtx base_reg, -+ HOST_WIDE_INT offset, bool load_p, rtx oldmem) -+{ -+ rtx addr = plus_constant(Pmode, base_reg, offset); -+ rtx mem = gen_rtx_MEM (SImode, addr); -+ MEM_COPY_ATTRIBUTES (mem, oldmem); -+ if (load_p) -+ return gen_movsi (reg, mem); -+ else -+ return gen_movsi (mem, reg); -+} -+ -+#endif /* ! NDS32_LOAD_STORE_OPT_H */ -diff --git a/gcc/config/nds32/nds32-md-auxiliary.c b/gcc/config/nds32/nds32-md-auxiliary.c -index def8eda..3881df7 100644 ---- a/gcc/config/nds32/nds32-md-auxiliary.c -+++ b/gcc/config/nds32/nds32-md-auxiliary.c -@@ -25,17 +25,74 @@ - #include "system.h" - #include "coretypes.h" - #include "backend.h" --#include "target.h" --#include "rtl.h" - #include "tree.h" --#include "tm_p.h" --#include "optabs.h" /* For GEN_FCN. */ --#include "recog.h" -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" - #include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" - #include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* This file is divided into three parts: -+ -+ PART 1: Auxiliary static function definitions. -+ -+ PART 2: Auxiliary function for expand RTL pattern. -+ -+ PART 3: Auxiliary function for output asm template. */ - - /* ------------------------------------------------------------------------ */ - -+/* PART 1: Auxiliary static function definitions. */ -+ -+static int -+nds32_regno_to_enable4 (unsigned regno) -+{ -+ switch (regno) -+ { -+ case 28: /* $r28/fp */ -+ return 0x8; -+ case 29: /* $r29/gp */ -+ return 0x4; -+ case 30: /* $r30/lp */ -+ return 0x2; -+ case 31: /* $r31/sp */ -+ return 0x1; -+ default: -+ gcc_unreachable (); -+ } -+} -+ - /* A helper function to return character based on byte size. */ - static char - nds32_byte_to_size (int byte) -@@ -54,796 +111,3825 @@ nds32_byte_to_size (int byte) - } - } - --/* A helper function to return memory format. */ --enum nds32_16bit_address_type --nds32_mem_format (rtx op) -+static int -+nds32_inverse_cond_code (int code) - { -- machine_mode mode_test; -- int val; -- int regno; -- -- if (!TARGET_16_BIT) -- return ADDRESS_NOT_16BIT_FORMAT; -- -- mode_test = GET_MODE (op); -- -- op = XEXP (op, 0); -+ switch (code) -+ { -+ case NE: -+ return EQ; -+ case EQ: -+ return NE; -+ case GT: -+ return LE; -+ case LE: -+ return GT; -+ case GE: -+ return LT; -+ case LT: -+ return GE; -+ default: -+ gcc_unreachable (); -+ } -+} - -- /* 45 format. */ -- if (GET_CODE (op) == REG && (mode_test == SImode)) -- return ADDRESS_REG; -+static const char * -+nds32_cond_code_str (int code) -+{ -+ switch (code) -+ { -+ case NE: -+ return "ne"; -+ case EQ: -+ return "eq"; -+ case GT: -+ return "gt"; -+ case LE: -+ return "le"; -+ case GE: -+ return "ge"; -+ case LT: -+ return "lt"; -+ default: -+ gcc_unreachable (); -+ } -+} - -- /* 333 format for QI/HImode. */ -- if (GET_CODE (op) == REG && (REGNO (op) < R8_REGNUM)) -- return ADDRESS_LO_REG_IMM3U; -+static void -+output_cond_branch (int code, const char *suffix, bool r5_p, -+ bool long_jump_p, rtx *operands) -+{ -+ char pattern[256]; -+ const char *cond_code; -+ bool align_p = NDS32_ALIGN_P (); -+ const char *align = align_p ? "\t.align\t2\n" : ""; - -- /* post_inc 333 format. */ -- if ((GET_CODE (op) == POST_INC) && (mode_test == SImode)) -+ if (r5_p && REGNO (operands[2]) == 5 && TARGET_16_BIT) - { -- regno = REGNO(XEXP (op, 0)); -- -- if (regno < 8) -- return ADDRESS_POST_INC_LO_REG_IMM3U; -+ /* This is special case for beqs38 and bnes38, -+ second operand 2 can't be $r5 and it's almost meanless, -+ however it may occur after copy propgation. */ -+ if (code == EQ) -+ { -+ /* $r5 == $r5 always taken! */ -+ if (long_jump_p) -+ snprintf (pattern, sizeof (pattern), -+ "j\t%%3"); -+ else -+ snprintf (pattern, sizeof (pattern), -+ "j8\t%%3"); -+ } -+ else -+ /* Don't output anything since $r5 != $r5 never taken! */ -+ pattern[0] = '\0'; - } -- -- /* post_inc 333 format. */ -- if ((GET_CODE (op) == POST_MODIFY) -- && (mode_test == SImode) -- && (REG_P (XEXP (XEXP (op, 1), 0))) -- && (CONST_INT_P (XEXP (XEXP (op, 1), 1)))) -+ else if (long_jump_p) - { -- regno = REGNO (XEXP (XEXP (op, 1), 0)); -- val = INTVAL (XEXP (XEXP (op, 1), 1)); -- if (regno < 8 && val < 32) -- return ADDRESS_POST_INC_LO_REG_IMM3U; -+ int inverse_code = nds32_inverse_cond_code (code); -+ cond_code = nds32_cond_code_str (inverse_code); -+ -+ /* b $r0, $r1, .L0 -+ => -+ b $r0, $r1, .LCB0 -+ j .L0 -+ .LCB0: -+ -+ or -+ -+ b $r0, $r1, .L0 -+ => -+ b $r0, $r1, .LCB0 -+ j .L0 -+ .LCB0: -+ */ -+ if (r5_p && TARGET_16_BIT) -+ { -+ snprintf (pattern, sizeof (pattern), -+ "b%ss38\t %%2, .LCB%%=\n\tj\t%%3\n%s.LCB%%=:", -+ cond_code, align); -+ } -+ else -+ { -+ snprintf (pattern, sizeof (pattern), -+ "b%s%s\t%%1, %%2, .LCB%%=\n\tj\t%%3\n%s.LCB%%=:", -+ cond_code, suffix, align); -+ } - } -- -- if ((GET_CODE (op) == PLUS) -- && (GET_CODE (XEXP (op, 0)) == REG) -- && (GET_CODE (XEXP (op, 1)) == CONST_INT)) -+ else - { -- val = INTVAL (XEXP (op, 1)); -- -- regno = REGNO(XEXP (op, 0)); -- -- if (regno > 7 -- && regno != SP_REGNUM -- && regno != FP_REGNUM) -- return ADDRESS_NOT_16BIT_FORMAT; -- -- switch (mode_test) -+ cond_code = nds32_cond_code_str (code); -+ if (r5_p && TARGET_16_BIT) - { -- case QImode: -- /* 333 format. */ -- if (val >= 0 && val < 8 && regno < 8) -- return ADDRESS_LO_REG_IMM3U; -- break; -- -- case HImode: -- /* 333 format. */ -- if (val >= 0 && val < 16 && (val % 2 == 0) && regno < 8) -- return ADDRESS_LO_REG_IMM3U; -- break; -- -- case SImode: -- case SFmode: -- case DFmode: -- /* fp imply 37 format. */ -- if ((regno == FP_REGNUM) && -- (val >= 0 && val < 512 && (val % 4 == 0))) -- return ADDRESS_FP_IMM7U; -- /* sp imply 37 format. */ -- else if ((regno == SP_REGNUM) && -- (val >= 0 && val < 512 && (val % 4 == 0))) -- return ADDRESS_SP_IMM7U; -- /* 333 format. */ -- else if (val >= 0 && val < 32 && (val % 4 == 0) && regno < 8) -- return ADDRESS_LO_REG_IMM3U; -- break; -- -- default: -- break; -+ /* bs38 $r1, .L0 */ -+ snprintf (pattern, sizeof (pattern), -+ "b%ss38\t %%2, %%3", cond_code); -+ } -+ else -+ { -+ /* b $r0, $r1, .L0 */ -+ snprintf (pattern, sizeof (pattern), -+ "b%s%s\t%%1, %%2, %%3", cond_code, suffix); - } - } - -- return ADDRESS_NOT_16BIT_FORMAT; -+ output_asm_insn (pattern, operands); - } - --/* Output 16-bit store. */ --const char * --nds32_output_16bit_store (rtx *operands, int byte) -+static void -+output_cond_branch_compare_zero (int code, const char *suffix, -+ bool long_jump_p, rtx *operands, -+ bool ta_implied_p) - { -- char pattern[100]; -- char size; -- rtx code = XEXP (operands[0], 0); -- -- size = nds32_byte_to_size (byte); -+ char pattern[256]; -+ const char *cond_code; -+ bool align_p = NDS32_ALIGN_P (); -+ const char *align = align_p ? "\t.align\t2\n" : ""; -+ if (long_jump_p) -+ { -+ int inverse_code = nds32_inverse_cond_code (code); -+ cond_code = nds32_cond_code_str (inverse_code); - -- switch (nds32_mem_format (operands[0])) -+ if (ta_implied_p && TARGET_16_BIT) -+ { -+ /* bz .L0 -+ => -+ bz .LCB0 -+ j .L0 -+ .LCB0: -+ */ -+ snprintf (pattern, sizeof (pattern), -+ "b%sz%s\t.LCB%%=\n\tj\t%%2\n%s.LCB%%=:", -+ cond_code, suffix, align); -+ } -+ else -+ { -+ /* bz $r0, .L0 -+ => -+ bz $r0, .LCB0 -+ j .L0 -+ .LCB0: -+ */ -+ snprintf (pattern, sizeof (pattern), -+ "b%sz%s\t%%1, .LCB%%=\n\tj\t%%2\n%s.LCB%%=:", -+ cond_code, suffix, align); -+ } -+ } -+ else - { -- case ADDRESS_REG: -- operands[0] = code; -- output_asm_insn ("swi450\t%1, [%0]", operands); -- break; -- case ADDRESS_LO_REG_IMM3U: -- snprintf (pattern, sizeof (pattern), "s%ci333\t%%1, %%0", size); -- output_asm_insn (pattern, operands); -- break; -- case ADDRESS_POST_INC_LO_REG_IMM3U: -- snprintf (pattern, sizeof (pattern), "s%ci333.bi\t%%1, %%0", size); -- output_asm_insn (pattern, operands); -- break; -- case ADDRESS_FP_IMM7U: -- output_asm_insn ("swi37\t%1, %0", operands); -- break; -- case ADDRESS_SP_IMM7U: -- /* Get immediate value and set back to operands[1]. */ -- operands[0] = XEXP (code, 1); -- output_asm_insn ("swi37.sp\t%1, [ + (%0)]", operands); -- break; -- default: -- break; -+ cond_code = nds32_cond_code_str (code); -+ if (ta_implied_p && TARGET_16_BIT) -+ { -+ /* bz .L0 */ -+ snprintf (pattern, sizeof (pattern), -+ "b%sz%s\t%%2", cond_code, suffix); -+ } -+ else -+ { -+ /* bz $r0, .L0 */ -+ snprintf (pattern, sizeof (pattern), -+ "b%sz%s\t%%1, %%2", cond_code, suffix); -+ } - } - -- return ""; -+ output_asm_insn (pattern, operands); - } - --/* Output 16-bit load. */ --const char * --nds32_output_16bit_load (rtx *operands, int byte) -+static void -+nds32_split_shiftrtdi3 (rtx dst, rtx src, rtx shiftamount, bool logic_shift_p) - { -- char pattern[100]; -- unsigned char size; -- rtx code = XEXP (operands[1], 0); -+ rtx src_high_part; -+ rtx dst_high_part, dst_low_part; - -- size = nds32_byte_to_size (byte); -+ 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); - -- switch (nds32_mem_format (operands[1])) -+ if (CONST_INT_P (shiftamount)) - { -- case ADDRESS_REG: -- operands[1] = code; -- output_asm_insn ("lwi450\t%0, [%1]", operands); -- break; -- case ADDRESS_LO_REG_IMM3U: -- snprintf (pattern, sizeof (pattern), "l%ci333\t%%0, %%1", size); -- output_asm_insn (pattern, operands); -- break; -- case ADDRESS_POST_INC_LO_REG_IMM3U: -- snprintf (pattern, sizeof (pattern), "l%ci333.bi\t%%0, %%1", size); -- output_asm_insn (pattern, operands); -- break; -- case ADDRESS_FP_IMM7U: -- output_asm_insn ("lwi37\t%0, %1", operands); -- break; -- case ADDRESS_SP_IMM7U: -- /* Get immediate value and set back to operands[0]. */ -- operands[1] = XEXP (code, 1); -- output_asm_insn ("lwi37.sp\t%0, [ + (%1)]", operands); -- break; -- default: -- break; -+ 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))); -+ } - -- return ""; -+ 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)); -+ } - } - --/* Output 32-bit store. */ --const char * --nds32_output_32bit_store (rtx *operands, int byte) --{ -- char pattern[100]; -- unsigned char size; -- rtx code = XEXP (operands[0], 0); -+/* ------------------------------------------------------------------------ */ - -- size = nds32_byte_to_size (byte); -+/* PART 2: Auxiliary function for expand RTL pattern. */ - -- switch (GET_CODE (code)) -+enum nds32_expand_result_type -+nds32_expand_cbranch (rtx *operands) -+{ -+ rtx tmp_reg; -+ enum rtx_code code; -+ -+ code = GET_CODE (operands[0]); -+ -+ /* If operands[2] is (const_int 0), -+ we can use beqz,bnez,bgtz,bgez,bltz,or blez instructions. -+ So we have gcc generate original template rtx. */ -+ if (GET_CODE (operands[2]) == CONST_INT) -+ if (INTVAL (operands[2]) == 0) -+ if ((code != GTU) -+ && (code != GEU) -+ && (code != LTU) -+ && (code != LEU)) -+ return EXPAND_CREATE_TEMPLATE; -+ -+ /* For other comparison, NDS32 ISA only has slt (Set-on-Less-Than) -+ behavior for the comparison, we might need to generate other -+ rtx patterns to achieve same semantic. */ -+ switch (code) - { -- case REG: -- /* (mem (reg X)) -- => access location by using register, -- use "sbi / shi / swi" */ -- snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size); -- break; -- -- case SYMBOL_REF: -- case CONST: -- /* (mem (symbol_ref X)) -- (mem (const (...))) -- => access global variables, -- use "sbi.gp / shi.gp / swi.gp" */ -- operands[0] = XEXP (operands[0], 0); -- snprintf (pattern, sizeof (pattern), "s%ci.gp\t%%1, [ + %%0]", size); -- break; -+ case GT: -+ case GTU: -+ if (GET_CODE (operands[2]) == CONST_INT) -+ { -+ /* GT reg_A, const_int => !(LT reg_A, const_int + 1) */ -+ if (optimize_size || optimize == 0) -+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -+ else -+ tmp_reg = gen_reg_rtx (SImode); -+ -+ /* We want to plus 1 into the integer value -+ of operands[2] to create 'slt' instruction. -+ This caculation is performed on the host machine, -+ which may be 64-bit integer. -+ So the meaning of caculation result may be -+ different from the 32-bit nds32 target. -+ -+ For example: -+ 0x7fffffff + 0x1 -> 0x80000000, -+ this value is POSITIVE on 64-bit machine, -+ but the expected value on 32-bit nds32 target -+ should be NEGATIVE value. -+ -+ Hence, instead of using GEN_INT(), we use gen_int_mode() to -+ explicitly create SImode constant rtx. */ -+ enum rtx_code cmp_code; -+ -+ rtx plus1 = gen_int_mode (INTVAL (operands[2]) + 1, SImode); -+ if (satisfies_constraint_Is15 (plus1)) -+ { -+ operands[2] = plus1; -+ cmp_code = EQ; -+ if (code == GT) -+ { -+ /* GT, use slts instruction */ -+ emit_insn ( -+ gen_slts_compare (tmp_reg, operands[1], operands[2])); -+ } -+ else -+ { -+ /* GTU, use slt instruction */ -+ emit_insn ( -+ gen_slt_compare (tmp_reg, operands[1], operands[2])); -+ } -+ } -+ else -+ { -+ cmp_code = NE; -+ if (code == GT) -+ { -+ /* GT, use slts instruction */ -+ emit_insn ( -+ gen_slts_compare (tmp_reg, operands[2], operands[1])); -+ } -+ else -+ { -+ /* GTU, use slt instruction */ -+ emit_insn ( -+ gen_slt_compare (tmp_reg, operands[2], operands[1])); -+ } -+ } -+ -+ PUT_CODE (operands[0], cmp_code); -+ operands[1] = tmp_reg; -+ operands[2] = const0_rtx; -+ emit_insn (gen_cbranchsi4 (operands[0], operands[1], -+ operands[2], operands[3])); -+ -+ return EXPAND_DONE; -+ } -+ else -+ { -+ /* GT reg_A, reg_B => LT reg_B, reg_A */ -+ if (optimize_size || optimize == 0) -+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -+ else -+ tmp_reg = gen_reg_rtx (SImode); -+ -+ if (code == GT) -+ { -+ /* GT, use slts instruction */ -+ emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1])); -+ } -+ else -+ { -+ /* GTU, use slt instruction */ -+ emit_insn (gen_slt_compare (tmp_reg, operands[2], operands[1])); -+ } -+ -+ PUT_CODE (operands[0], NE); -+ operands[1] = tmp_reg; -+ operands[2] = const0_rtx; -+ emit_insn (gen_cbranchsi4 (operands[0], operands[1], -+ operands[2], operands[3])); -+ -+ return EXPAND_DONE; -+ } - -- case POST_INC: -- /* (mem (post_inc reg)) -- => access location by using register which will be post increment, -- use "sbi.bi / shi.bi / swi.bi" */ -- snprintf (pattern, sizeof (pattern), -- "s%ci.bi\t%%1, %%0, %d", size, byte); -- break; -+ case GE: -+ case GEU: -+ /* GE reg_A, reg_B => !(LT reg_A, reg_B) */ -+ /* GE reg_A, const_int => !(LT reg_A, const_int) */ -+ if (optimize_size || optimize == 0) -+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -+ else -+ tmp_reg = gen_reg_rtx (SImode); - -- case POST_DEC: -- /* (mem (post_dec reg)) -- => access location by using register which will be post decrement, -- use "sbi.bi / shi.bi / swi.bi" */ -- snprintf (pattern, sizeof (pattern), -- "s%ci.bi\t%%1, %%0, -%d", size, byte); -- break; -+ if (code == GE) -+ { -+ /* GE, use slts instruction */ -+ emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2])); -+ } -+ else -+ { -+ /* GEU, use slt instruction */ -+ emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2])); -+ } - -- case POST_MODIFY: -- switch (GET_CODE (XEXP (XEXP (code, 1), 1))) -+ PUT_CODE (operands[0], EQ); -+ operands[1] = tmp_reg; -+ operands[2] = const0_rtx; -+ emit_insn (gen_cbranchsi4 (operands[0], operands[1], -+ operands[2], operands[3])); -+ -+ return EXPAND_DONE; -+ -+ case LT: -+ case LTU: -+ /* LT reg_A, reg_B => LT reg_A, reg_B */ -+ /* LT reg_A, const_int => LT reg_A, const_int */ -+ if (optimize_size || optimize == 0) -+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -+ else -+ tmp_reg = gen_reg_rtx (SImode); -+ -+ if (code == LT) - { -- case REG: -- case SUBREG: -- /* (mem (post_modify (reg) (plus (reg) (reg)))) -- => access location by using register which will be -- post modified with reg, -- use "sb.bi/ sh.bi / sw.bi" */ -- snprintf (pattern, sizeof (pattern), "s%c.bi\t%%1, %%0", size); -- break; -- case CONST_INT: -- /* (mem (post_modify (reg) (plus (reg) (const_int)))) -- => access location by using register which will be -- post modified with const_int, -- use "sbi.bi/ shi.bi / swi.bi" */ -- snprintf (pattern, sizeof (pattern), "s%ci.bi\t%%1, %%0", size); -- break; -- default: -- abort (); -+ /* LT, use slts instruction */ -+ emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2])); -+ } -+ else -+ { -+ /* LTU, use slt instruction */ -+ emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2])); - } -- break; - -- case PLUS: -- switch (GET_CODE (XEXP (code, 1))) -+ PUT_CODE (operands[0], NE); -+ operands[1] = tmp_reg; -+ operands[2] = const0_rtx; -+ emit_insn (gen_cbranchsi4 (operands[0], operands[1], -+ operands[2], operands[3])); -+ -+ return EXPAND_DONE; -+ -+ case LE: -+ case LEU: -+ if (GET_CODE (operands[2]) == CONST_INT) - { -- case REG: -- case SUBREG: -- /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg)) -- => access location by adding two registers, -- use "sb / sh / sw" */ -- snprintf (pattern, sizeof (pattern), "s%c\t%%1, %%0", size); -- break; -- case CONST_INT: -- /* (mem (plus reg const_int)) -- => access location by adding one register with const_int, -- use "sbi / shi / swi" */ -- snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size); -- break; -- default: -- abort (); -+ /* LE reg_A, const_int => LT reg_A, const_int + 1 */ -+ if (optimize_size || optimize == 0) -+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -+ else -+ tmp_reg = gen_reg_rtx (SImode); -+ -+ enum rtx_code cmp_code; -+ /* Note that (le:SI X INT_MAX) is not the same as (lt:SI X INT_MIN). -+ We better have an assert here in case GCC does not properly -+ optimize it away. The INT_MAX here is 0x7fffffff for target. */ -+ rtx plus1 = gen_int_mode (INTVAL (operands[2]) + 1, SImode); -+ if (satisfies_constraint_Is15 (plus1)) -+ { -+ operands[2] = plus1; -+ cmp_code = NE; -+ if (code == LE) -+ { -+ /* LE, use slts instruction */ -+ emit_insn ( -+ gen_slts_compare (tmp_reg, operands[1], operands[2])); -+ } -+ else -+ { -+ /* LEU, use slt instruction */ -+ emit_insn ( -+ gen_slt_compare (tmp_reg, operands[1], operands[2])); -+ } -+ } -+ else -+ { -+ cmp_code = EQ; -+ if (code == LE) -+ { -+ /* LE, use slts instruction */ -+ emit_insn ( -+ gen_slts_compare (tmp_reg, operands[2], operands[1])); -+ } -+ else -+ { -+ /* LEU, use slt instruction */ -+ emit_insn ( -+ gen_slt_compare (tmp_reg, operands[2], operands[1])); -+ } -+ } -+ -+ PUT_CODE (operands[0], cmp_code); -+ operands[1] = tmp_reg; -+ operands[2] = const0_rtx; -+ emit_insn (gen_cbranchsi4 (operands[0], operands[1], -+ operands[2], operands[3])); -+ -+ return EXPAND_DONE; -+ } -+ else -+ { -+ /* LE reg_A, reg_B => !(LT reg_B, reg_A) */ -+ if (optimize_size || optimize == 0) -+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -+ else -+ tmp_reg = gen_reg_rtx (SImode); -+ -+ if (code == LE) -+ { -+ /* LE, use slts instruction */ -+ emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1])); -+ } -+ else -+ { -+ /* LEU, use slt instruction */ -+ emit_insn (gen_slt_compare (tmp_reg, operands[2], operands[1])); -+ } -+ -+ PUT_CODE (operands[0], EQ); -+ operands[1] = tmp_reg; -+ operands[2] = const0_rtx; -+ emit_insn (gen_cbranchsi4 (operands[0], operands[1], -+ operands[2], operands[3])); -+ -+ return EXPAND_DONE; - } -- break; - -- case LO_SUM: -- operands[2] = XEXP (code, 1); -- operands[0] = XEXP (code, 0); -- snprintf (pattern, sizeof (pattern), -- "s%ci\t%%1, [%%0 + lo12(%%2)]", size); -- break; -+ case EQ: -+ case NE: -+ /* NDS32 ISA has various form for eq/ne behavior no matter -+ what kind of the operand is. -+ So just generate original template rtx. */ -+ -+ /* Put operands[2] into register if operands[2] is a large -+ const_int or ISAv2. */ -+ if (GET_CODE (operands[2]) == CONST_INT -+ && (!satisfies_constraint_Is11 (operands[2]) -+ || TARGET_ISA_V2)) -+ operands[2] = force_reg (SImode, operands[2]); -+ -+ return EXPAND_CREATE_TEMPLATE; - - default: -- abort (); -+ return EXPAND_FAIL; - } -- -- output_asm_insn (pattern, operands); -- return ""; - } - --/* Output 32-bit load. */ --const char * --nds32_output_32bit_load (rtx *operands, int byte) -+enum nds32_expand_result_type -+nds32_expand_cstore (rtx *operands) - { -- char pattern[100]; -- unsigned char size; -- rtx code; -- -- code = XEXP (operands[1], 0); -+ rtx tmp_reg; -+ enum rtx_code code; - -- size = nds32_byte_to_size (byte); -+ code = GET_CODE (operands[1]); - -- switch (GET_CODE (code)) -+ switch (code) - { -- case REG: -- /* (mem (reg X)) -- => access location by using register, -- use "lbi / lhi / lwi" */ -- snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size); -- break; -- -- case SYMBOL_REF: -- case CONST: -- /* (mem (symbol_ref X)) -- (mem (const (...))) -- => access global variables, -- use "lbi.gp / lhi.gp / lwi.gp" */ -- operands[1] = XEXP (operands[1], 0); -- snprintf (pattern, sizeof (pattern), "l%ci.gp\t%%0, [ + %%1]", size); -- break; -+ case EQ: -+ case NE: -+ if (GET_CODE (operands[3]) == CONST_INT) -+ { -+ /* reg_R = (reg_A == const_int_B) -+ --> xori reg_C, reg_A, const_int_B -+ slti reg_R, reg_C, const_int_1 -+ reg_R = (reg_A != const_int_B) -+ --> xori reg_C, reg_A, const_int_B -+ slti reg_R, const_int0, reg_C */ -+ tmp_reg = gen_reg_rtx (SImode); -+ -+ /* If the integer value is not in the range of imm15s, -+ we need to force register first because our addsi3 pattern -+ only accept nds32_rimm15s_operand predicate. */ -+ rtx new_imm = gen_int_mode (-INTVAL (operands[3]), SImode); -+ if (satisfies_constraint_Is15 (new_imm)) -+ emit_insn (gen_addsi3 (tmp_reg, operands[2], new_imm)); -+ else -+ { -+ if (!(satisfies_constraint_Iu15 (operands[3]) -+ || (TARGET_EXT_PERF -+ && satisfies_constraint_It15 (operands[3])))) -+ operands[3] = force_reg (SImode, operands[3]); -+ emit_insn (gen_xorsi3 (tmp_reg, operands[2], operands[3])); -+ } -+ -+ if (code == EQ) -+ emit_insn (gen_slt_eq0 (operands[0], tmp_reg)); -+ else -+ emit_insn (gen_slt_compare (operands[0], const0_rtx, tmp_reg)); -+ -+ return EXPAND_DONE; -+ } -+ else -+ { -+ /* reg_R = (reg_A == reg_B) -+ --> xor reg_C, reg_A, reg_B -+ slti reg_R, reg_C, const_int_1 -+ reg_R = (reg_A != reg_B) -+ --> xor reg_C, reg_A, reg_B -+ slti reg_R, const_int0, reg_C */ -+ tmp_reg = gen_reg_rtx (SImode); -+ emit_insn (gen_xorsi3 (tmp_reg, operands[2], operands[3])); -+ if (code == EQ) -+ emit_insn (gen_slt_eq0 (operands[0], tmp_reg)); -+ else -+ emit_insn (gen_slt_compare (operands[0], const0_rtx, tmp_reg)); -+ -+ return EXPAND_DONE; -+ } -+ case GT: -+ case GTU: -+ /* reg_R = (reg_A > reg_B) --> slt reg_R, reg_B, reg_A */ -+ /* reg_R = (reg_A > const_int_B) --> slt reg_R, const_int_B, reg_A */ -+ if (code == GT) -+ { -+ /* GT, use slts instruction */ -+ emit_insn (gen_slts_compare (operands[0], operands[3], operands[2])); -+ } -+ else -+ { -+ /* GTU, use slt instruction */ -+ emit_insn (gen_slt_compare (operands[0], operands[3], operands[2])); -+ } - -- case POST_INC: -- /* (mem (post_inc reg)) -- => access location by using register which will be post increment, -- use "lbi.bi / lhi.bi / lwi.bi" */ -- snprintf (pattern, sizeof (pattern), -- "l%ci.bi\t%%0, %%1, %d", size, byte); -- break; -+ return EXPAND_DONE; - -- case POST_DEC: -- /* (mem (post_dec reg)) -- => access location by using register which will be post decrement, -- use "lbi.bi / lhi.bi / lwi.bi" */ -- snprintf (pattern, sizeof (pattern), -- "l%ci.bi\t%%0, %%1, -%d", size, byte); -- break; -+ case GE: -+ case GEU: -+ if (GET_CODE (operands[3]) == CONST_INT) -+ { -+ /* reg_R = (reg_A >= const_int_B) -+ --> movi reg_C, const_int_B - 1 -+ slt reg_R, reg_C, reg_A */ -+ tmp_reg = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_movsi (tmp_reg, -+ gen_int_mode (INTVAL (operands[3]) - 1, -+ SImode))); -+ if (code == GE) -+ { -+ /* GE, use slts instruction */ -+ emit_insn (gen_slts_compare (operands[0], tmp_reg, operands[2])); -+ } -+ else -+ { -+ /* GEU, use slt instruction */ -+ emit_insn (gen_slt_compare (operands[0], tmp_reg, operands[2])); -+ } -+ -+ return EXPAND_DONE; -+ } -+ else -+ { -+ /* reg_R = (reg_A >= reg_B) -+ --> slt reg_R, reg_A, reg_B -+ xori reg_R, reg_R, const_int_1 */ -+ if (code == GE) -+ { -+ /* GE, use slts instruction */ -+ emit_insn (gen_slts_compare (operands[0], -+ operands[2], operands[3])); -+ } -+ else -+ { -+ /* GEU, use slt instruction */ -+ emit_insn (gen_slt_compare (operands[0], -+ operands[2], operands[3])); -+ } -+ -+ /* perform 'not' behavior */ -+ emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx)); -+ -+ return EXPAND_DONE; -+ } - -- case POST_MODIFY: -- switch (GET_CODE (XEXP (XEXP (code, 1), 1))) -+ case LT: -+ case LTU: -+ /* reg_R = (reg_A < reg_B) --> slt reg_R, reg_A, reg_B */ -+ /* reg_R = (reg_A < const_int_B) --> slt reg_R, reg_A, const_int_B */ -+ if (code == LT) - { -- case REG: -- case SUBREG: -- /* (mem (post_modify (reg) (plus (reg) (reg)))) -- => access location by using register which will be -- post modified with reg, -- use "lb.bi/ lh.bi / lw.bi" */ -- snprintf (pattern, sizeof (pattern), "l%c.bi\t%%0, %%1", size); -- break; -- case CONST_INT: -- /* (mem (post_modify (reg) (plus (reg) (const_int)))) -- => access location by using register which will be -- post modified with const_int, -- use "lbi.bi/ lhi.bi / lwi.bi" */ -- snprintf (pattern, sizeof (pattern), "l%ci.bi\t%%0, %%1", size); -- break; -- default: -- abort (); -+ /* LT, use slts instruction */ -+ emit_insn (gen_slts_compare (operands[0], operands[2], operands[3])); -+ } -+ else -+ { -+ /* LTU, use slt instruction */ -+ emit_insn (gen_slt_compare (operands[0], operands[2], operands[3])); - } -- break; - -- case PLUS: -- switch (GET_CODE (XEXP (code, 1))) -+ return EXPAND_DONE; -+ -+ case LE: -+ case LEU: -+ if (GET_CODE (operands[3]) == CONST_INT) - { -- case REG: -- case SUBREG: -- /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg)) -- use "lb / lh / lw" */ -- snprintf (pattern, sizeof (pattern), "l%c\t%%0, %%1", size); -- break; -- case CONST_INT: -- /* (mem (plus reg const_int)) -- => access location by adding one register with const_int, -- use "lbi / lhi / lwi" */ -- snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size); -- break; -- default: -- abort (); -+ /* reg_R = (reg_A <= const_int_B) -+ --> movi reg_C, const_int_B + 1 -+ slt reg_R, reg_A, reg_C */ -+ tmp_reg = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_movsi (tmp_reg, -+ gen_int_mode (INTVAL (operands[3]) + 1, -+ SImode))); -+ if (code == LE) -+ { -+ /* LE, use slts instruction */ -+ emit_insn (gen_slts_compare (operands[0], operands[2], tmp_reg)); -+ } -+ else -+ { -+ /* LEU, use slt instruction */ -+ emit_insn (gen_slt_compare (operands[0], operands[2], tmp_reg)); -+ } -+ -+ return EXPAND_DONE; -+ } -+ else -+ { -+ /* reg_R = (reg_A <= reg_B) --> slt reg_R, reg_B, reg_A -+ xori reg_R, reg_R, const_int_1 */ -+ if (code == LE) -+ { -+ /* LE, use slts instruction */ -+ emit_insn (gen_slts_compare (operands[0], -+ operands[3], operands[2])); -+ } -+ else -+ { -+ /* LEU, use slt instruction */ -+ emit_insn (gen_slt_compare (operands[0], -+ operands[3], operands[2])); -+ } -+ -+ /* perform 'not' behavior */ -+ emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx)); -+ -+ return EXPAND_DONE; - } -- break; - -- case LO_SUM: -- operands[2] = XEXP (code, 1); -- operands[1] = XEXP (code, 0); -- snprintf (pattern, sizeof (pattern), -- "l%ci\t%%0, [%%1 + lo12(%%2)]", size); -- break; - - default: -- abort (); -+ gcc_unreachable (); - } -- -- output_asm_insn (pattern, operands); -- return ""; - } - --/* Output 32-bit load with signed extension. */ --const char * --nds32_output_32bit_load_s (rtx *operands, int byte) -+void -+nds32_expand_float_cbranch (rtx *operands) - { -- char pattern[100]; -- unsigned char size; -- rtx code; -+ enum rtx_code code = GET_CODE (operands[0]); -+ enum rtx_code new_code = code; -+ rtx cmp_op0 = operands[1]; -+ rtx cmp_op1 = operands[2]; -+ rtx tmp_reg; -+ rtx tmp; - -- code = XEXP (operands[1], 0); -+ int reverse = 0; - -- size = nds32_byte_to_size (byte); -+ /* Main Goal: Use compare instruction + branch instruction. - -- switch (GET_CODE (code)) -+ For example: -+ GT, GE: swap condition and swap operands and generate -+ compare instruction(LT, LE) + branch not equal instruction. -+ -+ UNORDERED, LT, LE, EQ: no need to change and generate -+ compare instruction(UNORDERED, LT, LE, EQ) + branch not equal instruction. -+ -+ ORDERED, NE: reverse condition and generate -+ compare instruction(EQ) + branch equal instruction. */ -+ -+ switch (code) - { -- case REG: -- /* (mem (reg X)) -- => access location by using register, -- use "lbsi / lhsi" */ -- snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size); -+ case GT: -+ case GE: -+ tmp = cmp_op0; -+ cmp_op0 = cmp_op1; -+ cmp_op1 = tmp; -+ new_code = swap_condition (new_code); - break; -- -- case SYMBOL_REF: -- case CONST: -- /* (mem (symbol_ref X)) -- (mem (const (...))) -- => access global variables, -- use "lbsi.gp / lhsi.gp" */ -- operands[1] = XEXP (operands[1], 0); -- snprintf (pattern, sizeof (pattern), "l%csi.gp\t%%0, [ + %%1]", size); -+ case UNORDERED: -+ case LT: -+ case LE: -+ case EQ: - break; -- -- case POST_INC: -- /* (mem (post_inc reg)) -- => access location by using register which will be post increment, -- use "lbsi.bi / lhsi.bi" */ -- snprintf (pattern, sizeof (pattern), -- "l%csi.bi\t%%0, %%1, %d", size, byte); -+ case ORDERED: -+ case NE: -+ new_code = reverse_condition (new_code); -+ reverse = 1; -+ break; -+ case UNGT: -+ case UNGE: -+ new_code = reverse_condition_maybe_unordered (new_code); -+ reverse = 1; - break; -+ case UNLT: -+ case UNLE: -+ new_code = reverse_condition_maybe_unordered (new_code); -+ tmp = cmp_op0; -+ cmp_op0 = cmp_op1; -+ cmp_op1 = tmp; -+ new_code = swap_condition (new_code); -+ reverse = 1; -+ break; -+ default: -+ return; -+ } - -- case POST_DEC: -- /* (mem (post_dec reg)) -- => access location by using register which will be post decrement, -- use "lbsi.bi / lhsi.bi" */ -- snprintf (pattern, sizeof (pattern), -- "l%csi.bi\t%%0, %%1, -%d", size, byte); -+ tmp_reg = gen_reg_rtx (SImode); -+ emit_insn (gen_rtx_SET (tmp_reg, -+ gen_rtx_fmt_ee (new_code, SImode, -+ cmp_op0, cmp_op1))); -+ -+ PUT_CODE (operands[0], reverse ? EQ : NE); -+ emit_insn (gen_cbranchsi4 (operands[0], tmp_reg, -+ const0_rtx, operands[3])); -+} -+ -+void -+nds32_expand_float_cstore (rtx *operands) -+{ -+ enum rtx_code code = GET_CODE (operands[1]); -+ enum rtx_code new_code = code; -+ enum machine_mode mode = GET_MODE (operands[2]); -+ -+ rtx cmp_op0 = operands[2]; -+ rtx cmp_op1 = operands[3]; -+ rtx tmp; -+ -+ /* Main Goal: Use compare instruction to store value. -+ -+ For example: -+ GT, GE: swap condition and swap operands. -+ reg_R = (reg_A > reg_B) --> fcmplt reg_R, reg_B, reg_A -+ reg_R = (reg_A >= reg_B) --> fcmple reg_R, reg_B, reg_A -+ -+ LT, LE, EQ: no need to change, it is already LT, LE, EQ. -+ reg_R = (reg_A < reg_B) --> fcmplt reg_R, reg_A, reg_B -+ reg_R = (reg_A <= reg_B) --> fcmple reg_R, reg_A, reg_B -+ reg_R = (reg_A == reg_B) --> fcmpeq reg_R, reg_A, reg_B -+ -+ ORDERED: reverse condition and using xor insturction to achieve 'ORDERED'. -+ reg_R = (reg_A != reg_B) --> fcmpun reg_R, reg_A, reg_B -+ xor reg_R, reg_R, const1_rtx -+ -+ NE: reverse condition and using xor insturction to achieve 'NE'. -+ reg_R = (reg_A != reg_B) --> fcmpeq reg_R, reg_A, reg_B -+ xor reg_R, reg_R, const1_rtx */ -+ switch (code) -+ { -+ case GT: -+ case GE: -+ tmp = cmp_op0; -+ cmp_op0 = cmp_op1; -+ cmp_op1 =tmp; -+ new_code = swap_condition (new_code); - break; -+ case UNORDERED: -+ case LT: -+ case LE: -+ case EQ: -+ break; -+ case ORDERED: -+ if (mode == SFmode) -+ emit_insn (gen_cmpsf_un (operands[0], cmp_op0, cmp_op1)); -+ else -+ emit_insn (gen_cmpdf_un (operands[0], cmp_op0, cmp_op1)); - -- case POST_MODIFY: -- switch (GET_CODE (XEXP (XEXP (code, 1), 1))) -+ emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx)); -+ return; -+ case NE: -+ if (mode == SFmode) -+ emit_insn (gen_cmpsf_eq (operands[0], cmp_op0, cmp_op1)); -+ else -+ emit_insn (gen_cmpdf_eq (operands[0], cmp_op0, cmp_op1)); -+ -+ emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx)); -+ return; -+ default: -+ return; -+ } -+ -+ emit_insn (gen_rtx_SET (operands[0], -+ gen_rtx_fmt_ee (new_code, SImode, -+ cmp_op0, cmp_op1))); -+} -+ -+enum nds32_expand_result_type -+nds32_expand_movcc (rtx *operands) -+{ -+ enum rtx_code code = GET_CODE (operands[1]); -+ enum rtx_code new_code = code; -+ enum machine_mode cmp0_mode = GET_MODE (XEXP (operands[1], 0)); -+ rtx cmp_op0 = XEXP (operands[1], 0); -+ rtx cmp_op1 = XEXP (operands[1], 1); -+ rtx tmp; -+ -+ if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) -+ && XEXP (operands[1], 1) == const0_rtx) -+ { -+ /* If the operands[1] rtx is already (eq X 0) or (ne X 0), -+ we have gcc generate original template rtx. */ -+ return EXPAND_CREATE_TEMPLATE; -+ } -+ else if ((TARGET_FPU_SINGLE && cmp0_mode == SFmode) -+ || (TARGET_FPU_DOUBLE && cmp0_mode == DFmode)) -+ { -+ nds32_expand_float_movcc (operands); -+ } -+ else -+ { -+ /* Since there is only 'slt'(Set when Less Than) instruction for -+ comparison in Andes ISA, the major strategy we use here is to -+ convert conditional move into 'LT + EQ' or 'LT + NE' rtx combination. -+ We design constraints properly so that the reload phase will assist -+ to make one source operand to use same register as result operand. -+ Then we can use cmovz/cmovn to catch the other source operand -+ which has different register. */ -+ int reverse = 0; -+ -+ /* Main Goal: Use 'LT + EQ' or 'LT + NE' to target "then" part -+ Strategy : Reverse condition and swap comparison operands -+ -+ For example: -+ -+ a <= b ? P : Q (LE or LEU) -+ --> a > b ? Q : P (reverse condition) -+ --> b < a ? Q : P (swap comparison operands to achieve 'LT/LTU') -+ -+ a >= b ? P : Q (GE or GEU) -+ --> a < b ? Q : P (reverse condition to achieve 'LT/LTU') -+ -+ a < b ? P : Q (LT or LTU) -+ --> (NO NEED TO CHANGE, it is already 'LT/LTU') -+ -+ a > b ? P : Q (GT or GTU) -+ --> b < a ? P : Q (swap comparison operands to achieve 'LT/LTU') */ -+ switch (code) - { -- case REG: -- case SUBREG: -- /* (mem (post_modify (reg) (plus (reg) (reg)))) -- => access location by using register which will be -- post modified with reg, -- use "lbs.bi/ lhs.bi" */ -- snprintf (pattern, sizeof (pattern), "l%cs.bi\t%%0, %%1", size); -+ case GE: case GEU: case LE: case LEU: -+ new_code = reverse_condition (code); -+ reverse = 1; - break; -- case CONST_INT: -- /* (mem (post_modify (reg) (plus (reg) (const_int)))) -- => access location by using register which will be -- post modified with const_int, -- use "lbsi.bi/ lhsi.bi" */ -- snprintf (pattern, sizeof (pattern), "l%csi.bi\t%%0, %%1", size); -+ case EQ: -+ case NE: -+ /* no need to reverse condition */ - break; - default: -- abort (); -+ return EXPAND_FAIL; - } -- break; - -- case PLUS: -- switch (GET_CODE (XEXP (code, 1))) -+ /* For '>' comparison operator, we swap operands -+ so that we can have 'LT/LTU' operator. */ -+ if (new_code == GT || new_code == GTU) - { -- case REG: -- case SUBREG: -- /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg)) -- use "lbs / lhs" */ -- snprintf (pattern, sizeof (pattern), "l%cs\t%%0, %%1", size); -+ tmp = cmp_op0; -+ cmp_op0 = cmp_op1; -+ cmp_op1 = tmp; -+ -+ new_code = swap_condition (new_code); -+ } -+ -+ /* Use a temporary register to store slt/slts result. */ -+ tmp = gen_reg_rtx (SImode); -+ -+ if (new_code == EQ || new_code == NE) -+ { -+ emit_insn (gen_xorsi3 (tmp, cmp_op0, cmp_op1)); -+ /* tmp == 0 if cmp_op0 == cmp_op1. */ -+ operands[1] = gen_rtx_fmt_ee (new_code, VOIDmode, tmp, const0_rtx); -+ } -+ else -+ { -+ /* This emit_insn will create corresponding 'slt/slts' -+ insturction. */ -+ if (new_code == LT) -+ emit_insn (gen_slts_compare (tmp, cmp_op0, cmp_op1)); -+ else if (new_code == LTU) -+ emit_insn (gen_slt_compare (tmp, cmp_op0, cmp_op1)); -+ else -+ gcc_unreachable (); -+ -+ /* Change comparison semantic into (eq X 0) or (ne X 0) behavior -+ so that cmovz or cmovn will be matched later. -+ -+ For reverse condition cases, we want to create a semantic that: -+ (eq X 0) --> pick up "else" part -+ For normal cases, we want to create a semantic that: -+ (ne X 0) --> pick up "then" part -+ -+ Later we will have cmovz/cmovn instruction pattern to -+ match corresponding behavior and output instruction. */ -+ operands[1] = gen_rtx_fmt_ee (reverse ? EQ : NE, -+ VOIDmode, tmp, const0_rtx); -+ } -+ } -+ return EXPAND_CREATE_TEMPLATE; -+} -+ -+void -+nds32_expand_float_movcc (rtx *operands) -+{ -+ if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) -+ && GET_MODE (XEXP (operands[1], 0)) == SImode -+ && XEXP (operands[1], 1) == const0_rtx) -+ { -+ /* If the operands[1] rtx is already (eq X 0) or (ne X 0), -+ we have gcc generate original template rtx. */ -+ return; -+ } -+ else -+ { -+ enum rtx_code code = GET_CODE (operands[1]); -+ enum rtx_code new_code = code; -+ enum machine_mode cmp0_mode = GET_MODE (XEXP (operands[1], 0)); -+ enum machine_mode cmp1_mode = GET_MODE (XEXP (operands[1], 1)); -+ rtx cmp_op0 = XEXP (operands[1], 0); -+ rtx cmp_op1 = XEXP (operands[1], 1); -+ rtx tmp; -+ -+ /* Compare instruction Operations: (cmp_op0 condition cmp_op1) ? 1 : 0, -+ when result is 1, and 'reverse' be set 1 for fcmovzs instructuin. */ -+ int reverse = 0; -+ -+ /* Main Goal: Use cmpare instruction + conditional move instruction. -+ Strategy : swap condition and swap comparison operands. -+ -+ For example: -+ a > b ? P : Q (GT) -+ --> a < b ? Q : P (swap condition) -+ --> b < a ? Q : P (swap comparison operands to achieve 'GT') -+ -+ a >= b ? P : Q (GE) -+ --> a <= b ? Q : P (swap condition) -+ --> b <= a ? Q : P (swap comparison operands to achieve 'GE') -+ -+ a < b ? P : Q (LT) -+ --> (NO NEED TO CHANGE, it is already 'LT') -+ -+ a >= b ? P : Q (LE) -+ --> (NO NEED TO CHANGE, it is already 'LE') -+ -+ a == b ? P : Q (EQ) -+ --> (NO NEED TO CHANGE, it is already 'EQ') */ -+ -+ switch (code) -+ { -+ case GT: -+ case GE: -+ tmp = cmp_op0; -+ cmp_op0 = cmp_op1; -+ cmp_op1 =tmp; -+ new_code = swap_condition (new_code); - break; -- case CONST_INT: -- /* (mem (plus reg const_int)) -- => access location by adding one register with const_int, -- use "lbsi / lhsi" */ -- snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size); -+ case UNORDERED: -+ case LT: -+ case LE: -+ case EQ: -+ break; -+ case ORDERED: -+ case NE: -+ reverse = 1; -+ new_code = reverse_condition (new_code); -+ break; -+ case UNGT: -+ case UNGE: -+ new_code = reverse_condition_maybe_unordered (new_code); -+ reverse = 1; -+ break; -+ case UNLT: -+ case UNLE: -+ new_code = reverse_condition_maybe_unordered (new_code); -+ tmp = cmp_op0; -+ cmp_op0 = cmp_op1; -+ cmp_op1 = tmp; -+ new_code = swap_condition (new_code); -+ reverse = 1; - break; - default: -- abort (); -+ return; - } -- break; - -- case LO_SUM: -- operands[2] = XEXP (code, 1); -- operands[1] = XEXP (code, 0); -- snprintf (pattern, sizeof (pattern), -- "l%csi\t%%0, [%%1 + lo12(%%2)]", size); -- break; -+ /* Use a temporary register to store fcmpxxs result. */ -+ tmp = gen_reg_rtx (SImode); -+ -+ /* Create float compare instruction for SFmode and DFmode, -+ other MODE using cstoresi create compare instruction. */ -+ if ((cmp0_mode == DFmode || cmp0_mode == SFmode) -+ && (cmp1_mode == DFmode || cmp1_mode == SFmode)) -+ { -+ /* This emit_insn create corresponding float compare instruction */ -+ emit_insn (gen_rtx_SET (tmp, -+ gen_rtx_fmt_ee (new_code, SImode, -+ cmp_op0, cmp_op1))); -+ } -+ else -+ { -+ /* This emit_insn using cstoresi create corresponding -+ compare instruction */ -+ PUT_CODE (operands[1], new_code); -+ emit_insn (gen_cstoresi4 (tmp, operands[1], -+ cmp_op0, cmp_op1)); -+ } -+ /* operands[1] crete corresponding condition move instruction -+ for fcmovzs and fcmovns. */ -+ operands[1] = gen_rtx_fmt_ee (reverse ? EQ : NE, -+ VOIDmode, tmp, const0_rtx); -+ } -+} -+ -+void -+nds32_emit_push_fpr_callee_saved (int base_offset) -+{ -+ rtx fpu_insn; -+ rtx reg, mem; -+ unsigned int regno = cfun->machine->callee_saved_first_fpr_regno; -+ unsigned int last_fpr = cfun->machine->callee_saved_last_fpr_regno; -+ -+ while (regno <= last_fpr) -+ { -+ /* Handling two registers, using fsdi instruction. */ -+ reg = gen_rtx_REG (DFmode, regno); -+ mem = gen_frame_mem (DFmode, plus_constant (Pmode, -+ stack_pointer_rtx, -+ base_offset)); -+ base_offset += 8; -+ regno += 2; -+ fpu_insn = emit_move_insn (mem, reg); -+ RTX_FRAME_RELATED_P (fpu_insn) = 1; -+ } -+} -+ -+void -+nds32_emit_pop_fpr_callee_saved (int gpr_padding_size) -+{ -+ rtx fpu_insn; -+ rtx reg, mem, addr; -+ rtx dwarf, adjust_sp_rtx; -+ unsigned int regno = cfun->machine->callee_saved_first_fpr_regno; -+ unsigned int last_fpr = cfun->machine->callee_saved_last_fpr_regno; -+ int padding = 0; -+ -+ while (regno <= last_fpr) -+ { -+ /* Handling two registers, using fldi.bi instruction. */ -+ if ((regno + 1) >= last_fpr) -+ padding = gpr_padding_size; -+ -+ reg = gen_rtx_REG (DFmode, (regno)); -+ addr = gen_rtx_POST_MODIFY (Pmode, stack_pointer_rtx, -+ gen_rtx_PLUS (Pmode, stack_pointer_rtx, -+ GEN_INT (8 + padding))); -+ mem = gen_frame_mem (DFmode, addr); -+ regno += 2; -+ fpu_insn = emit_move_insn (reg, mem); -+ -+ adjust_sp_rtx = -+ gen_rtx_SET (stack_pointer_rtx, -+ plus_constant (Pmode, stack_pointer_rtx, -+ 8 + padding)); -+ -+ dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, NULL_RTX); -+ /* Tell gcc we adjust SP in this insn. */ -+ dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, copy_rtx (adjust_sp_rtx), -+ dwarf); -+ RTX_FRAME_RELATED_P (fpu_insn) = 1; -+ REG_NOTES (fpu_insn) = dwarf; -+ } -+} -+ -+void -+nds32_emit_v3pop_fpr_callee_saved (int base) -+{ -+ int fpu_base_addr = base; -+ int regno; -+ rtx fpu_insn; -+ rtx reg, mem; -+ rtx dwarf; -+ -+ regno = cfun->machine->callee_saved_first_fpr_regno; -+ while (regno <= cfun->machine->callee_saved_last_fpr_regno) -+ { -+ /* Handling two registers, using fldi instruction. */ -+ reg = gen_rtx_REG (DFmode, regno); -+ mem = gen_frame_mem (DFmode, plus_constant (Pmode, -+ stack_pointer_rtx, -+ fpu_base_addr)); -+ fpu_base_addr += 8; -+ regno += 2; -+ fpu_insn = emit_move_insn (reg, mem); -+ dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, NULL_RTX); -+ RTX_FRAME_RELATED_P (fpu_insn) = 1; -+ REG_NOTES (fpu_insn) = dwarf; -+ } -+} -+ -+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; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* PART 3: Auxiliary function for output asm template. */ -+ -+/* 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) -+{ -+ enum 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 QImode: -+ output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands); -+ break; -+ case HImode: -+ output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands); -+ break; -+ case SImode: -+ output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); -+ break; - default: -- abort (); -+ gcc_unreachable (); - } - -- output_asm_insn (pattern, operands); -- return ""; -+ /* 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 output stack push operation. -- We need to deal with normal stack push multiple or stack v3push. */ -+/* Function to generate normal jump table. */ - const char * --nds32_output_stack_push (rtx par_rtx) -+nds32_output_casesi (rtx *operands) - { -- /* A string pattern for output_asm_insn(). */ -- char pattern[100]; -- /* The operands array which will be used in output_asm_insn(). */ -- rtx operands[3]; -- /* Pick up varargs first regno and last regno for further use. */ -- int rb_va_args = cfun->machine->va_args_first_regno; -- int re_va_args = cfun->machine->va_args_last_regno; -- int last_argument_regno = NDS32_FIRST_GPR_REGNUM -- + NDS32_MAX_GPR_REGS_FOR_ARGS -- - 1; -- /* Pick up callee-saved first regno and last regno for further use. */ -- int rb_callee_saved = cfun->machine->callee_saved_first_gpr_regno; -- int re_callee_saved = cfun->machine->callee_saved_last_gpr_regno; -+ /* 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); - -- /* First we need to check if we are pushing argument registers not used -- for the named arguments. If so, we have to create 'smw.adm' (push.s) -- instruction. */ -- if (reg_mentioned_p (gen_rtx_REG (SImode, last_argument_regno), par_rtx)) -+ /* 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) -+{ -+ enum machine_mode mode_test; -+ int val; -+ int regno; -+ -+ if (!TARGET_16_BIT) -+ return ADDRESS_NOT_16BIT_FORMAT; -+ -+ mode_test = GET_MODE (op); -+ -+ op = XEXP (op, 0); -+ -+ /* 45 format. */ -+ if (GET_CODE (op) == REG -+ && ((mode_test == SImode) || (mode_test == SFmode))) -+ return ADDRESS_REG; -+ -+ /* 333 format for QI/HImode. */ -+ if (GET_CODE (op) == REG && (REGNO (op) < R8_REGNUM)) -+ return ADDRESS_LO_REG_IMM3U; -+ -+ /* post_inc 333 format. */ -+ if ((GET_CODE (op) == POST_INC) -+ && ((mode_test == SImode) || (mode_test == SFmode))) - { -- /* Set operands[0] and operands[1]. */ -- operands[0] = gen_rtx_REG (SImode, rb_va_args); -- operands[1] = gen_rtx_REG (SImode, re_va_args); -- /* Create assembly code pattern: "Rb, Re, { }". */ -- snprintf (pattern, sizeof (pattern), "push.s\t%s", "%0, %1, { }"); -- /* We use output_asm_insn() to output assembly code by ourself. */ -- output_asm_insn (pattern, operands); -- return ""; -+ regno = REGNO(XEXP (op, 0)); -+ -+ if (regno < 8) -+ return ADDRESS_POST_INC_LO_REG_IMM3U; -+ } -+ -+ /* post_inc 333 format. */ -+ if ((GET_CODE (op) == POST_MODIFY) -+ && ((mode_test == SImode) || (mode_test == SFmode)) -+ && (REG_P (XEXP (XEXP (op, 1), 0))) -+ && (CONST_INT_P (XEXP (XEXP (op, 1), 1)))) -+ { -+ regno = REGNO (XEXP (XEXP (op, 1), 0)); -+ val = INTVAL (XEXP (XEXP (op, 1), 1)); -+ if (regno < 8 && val > 0 && val < 32) -+ return ADDRESS_POST_MODIFY_LO_REG_IMM3U; - } - -- /* If we step here, we are going to do v3push or multiple push operation. */ -+ if ((GET_CODE (op) == PLUS) -+ && (GET_CODE (XEXP (op, 0)) == REG) -+ && (GET_CODE (XEXP (op, 1)) == CONST_INT)) -+ { -+ val = INTVAL (XEXP (op, 1)); -+ -+ regno = REGNO(XEXP (op, 0)); -+ -+ if (regno > 8 -+ && regno != SP_REGNUM -+ && regno != FP_REGNUM) -+ return ADDRESS_NOT_16BIT_FORMAT; -+ -+ switch (mode_test) -+ { -+ case QImode: -+ /* 333 format. */ -+ if (val >= 0 && val < 8 && regno < 8) -+ return ADDRESS_LO_REG_IMM3U; -+ break; -+ -+ case HImode: -+ /* 333 format. */ -+ if (val >= 0 && val < 16 && (val % 2 == 0) && regno < 8) -+ return ADDRESS_LO_REG_IMM3U; -+ break; -+ -+ case SImode: -+ case SFmode: -+ case DFmode: -+ /* r8 imply fe format. */ -+ if ((regno == 8) && -+ (val >= -128 && val <= -4 && (val % 4 == 0))) -+ return ADDRESS_R8_IMM7U; -+ /* fp imply 37 format. */ -+ if ((regno == FP_REGNUM) && -+ (val >= 0 && val < 512 && (val % 4 == 0))) -+ return ADDRESS_FP_IMM7U; -+ /* sp imply 37 format. */ -+ else if ((regno == SP_REGNUM) && -+ (val >= 0 && val < 512 && (val % 4 == 0))) -+ return ADDRESS_SP_IMM7U; -+ /* 333 format. */ -+ else if (val >= 0 && val < 32 && (val % 4 == 0) && regno < 8) -+ return ADDRESS_LO_REG_IMM3U; -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ return ADDRESS_NOT_16BIT_FORMAT; -+} -+ -+/* Output 16-bit store. */ -+const char * -+nds32_output_16bit_store (rtx *operands, int byte) -+{ -+ char pattern[100]; -+ char size; -+ rtx code = XEXP (operands[0], 0); -+ -+ size = nds32_byte_to_size (byte); -+ -+ switch (nds32_mem_format (operands[0])) -+ { -+ case ADDRESS_REG: -+ operands[0] = code; -+ output_asm_insn ("swi450\t%1, [%0]", operands); -+ break; -+ case ADDRESS_LO_REG_IMM3U: -+ snprintf (pattern, sizeof (pattern), "s%ci333\t%%1, %%0", size); -+ output_asm_insn (pattern, operands); -+ break; -+ case ADDRESS_POST_INC_LO_REG_IMM3U: -+ snprintf (pattern, sizeof (pattern), "swi333.bi\t%%1, %%0, 4"); -+ output_asm_insn (pattern, operands); -+ break; -+ case ADDRESS_POST_MODIFY_LO_REG_IMM3U: -+ snprintf (pattern, sizeof (pattern), "swi333.bi\t%%1, %%0"); -+ output_asm_insn (pattern, operands); -+ break; -+ case ADDRESS_FP_IMM7U: -+ output_asm_insn ("swi37\t%1, %0", operands); -+ break; -+ case ADDRESS_SP_IMM7U: -+ /* Get immediate value and set back to operands[1]. */ -+ operands[0] = XEXP (code, 1); -+ output_asm_insn ("swi37.sp\t%1, [ + (%0)]", operands); -+ break; -+ default: -+ break; -+ } -+ -+ return ""; -+} -+ -+/* Output 16-bit load. */ -+const char * -+nds32_output_16bit_load (rtx *operands, int byte) -+{ -+ char pattern[100]; -+ unsigned char size; -+ rtx code = XEXP (operands[1], 0); -+ -+ size = nds32_byte_to_size (byte); -+ -+ switch (nds32_mem_format (operands[1])) -+ { -+ case ADDRESS_REG: -+ operands[1] = code; -+ output_asm_insn ("lwi450\t%0, [%1]", operands); -+ break; -+ case ADDRESS_LO_REG_IMM3U: -+ snprintf (pattern, sizeof (pattern), "l%ci333\t%%0, %%1", size); -+ output_asm_insn (pattern, operands); -+ break; -+ case ADDRESS_POST_INC_LO_REG_IMM3U: -+ snprintf (pattern, sizeof (pattern), "lwi333.bi\t%%0, %%1, 4"); -+ output_asm_insn (pattern, operands); -+ break; -+ case ADDRESS_POST_MODIFY_LO_REG_IMM3U: -+ snprintf (pattern, sizeof (pattern), "lwi333.bi\t%%0, %%1"); -+ output_asm_insn (pattern, operands); -+ break; -+ case ADDRESS_R8_IMM7U: -+ output_asm_insn ("lwi45.fe\t%0, %e1", operands); -+ break; -+ case ADDRESS_FP_IMM7U: -+ output_asm_insn ("lwi37\t%0, %1", operands); -+ break; -+ case ADDRESS_SP_IMM7U: -+ /* Get immediate value and set back to operands[0]. */ -+ operands[1] = XEXP (code, 1); -+ output_asm_insn ("lwi37.sp\t%0, [ + (%1)]", operands); -+ break; -+ default: -+ break; -+ } -+ -+ return ""; -+} -+ -+/* Output 32-bit store. */ -+const char * -+nds32_output_32bit_store (rtx *operands, int byte) -+{ -+ char pattern[100]; -+ unsigned char size; -+ rtx code = XEXP (operands[0], 0); -+ -+ size = nds32_byte_to_size (byte); -+ -+ switch (GET_CODE (code)) -+ { -+ case REG: -+ /* (mem (reg X)) -+ => access location by using register, -+ use "sbi / shi / swi" */ -+ snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size); -+ break; -+ -+ case SYMBOL_REF: -+ case CONST: -+ /* (mem (symbol_ref X)) -+ (mem (const (...))) -+ => access global variables, -+ use "sbi.gp / shi.gp / swi.gp" */ -+ operands[0] = XEXP (operands[0], 0); -+ snprintf (pattern, sizeof (pattern), "s%ci.gp\t%%1, [ + %%0]", size); -+ break; -+ -+ case POST_INC: -+ /* (mem (post_inc reg)) -+ => access location by using register which will be post increment, -+ use "sbi.bi / shi.bi / swi.bi" */ -+ snprintf (pattern, sizeof (pattern), -+ "s%ci.bi\t%%1, %%0, %d", size, byte); -+ break; -+ -+ case POST_DEC: -+ /* (mem (post_dec reg)) -+ => access location by using register which will be post decrement, -+ use "sbi.bi / shi.bi / swi.bi" */ -+ snprintf (pattern, sizeof (pattern), -+ "s%ci.bi\t%%1, %%0, -%d", size, byte); -+ break; -+ -+ case POST_MODIFY: -+ switch (GET_CODE (XEXP (XEXP (code, 1), 1))) -+ { -+ case REG: -+ case SUBREG: -+ /* (mem (post_modify (reg) (plus (reg) (reg)))) -+ => access location by using register which will be -+ post modified with reg, -+ use "sb.bi/ sh.bi / sw.bi" */ -+ snprintf (pattern, sizeof (pattern), "s%c.bi\t%%1, %%0", size); -+ break; -+ case CONST_INT: -+ /* (mem (post_modify (reg) (plus (reg) (const_int)))) -+ => access location by using register which will be -+ post modified with const_int, -+ use "sbi.bi/ shi.bi / swi.bi" */ -+ snprintf (pattern, sizeof (pattern), "s%ci.bi\t%%1, %%0", size); -+ break; -+ default: -+ abort (); -+ } -+ break; -+ -+ case PLUS: -+ switch (GET_CODE (XEXP (code, 1))) -+ { -+ case REG: -+ case SUBREG: -+ /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg)) -+ => access location by adding two registers, -+ use "sb / sh / sw" */ -+ snprintf (pattern, sizeof (pattern), "s%c\t%%1, %%0", size); -+ break; -+ case CONST_INT: -+ /* (mem (plus reg const_int)) -+ => access location by adding one register with const_int, -+ use "sbi / shi / swi" */ -+ snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size); -+ break; -+ default: -+ abort (); -+ } -+ break; -+ -+ case LO_SUM: -+ operands[2] = XEXP (code, 1); -+ operands[0] = XEXP (code, 0); -+ snprintf (pattern, sizeof (pattern), -+ "s%ci\t%%1, [%%0 + lo12(%%2)]", size); -+ break; -+ -+ default: -+ abort (); -+ } -+ -+ output_asm_insn (pattern, operands); -+ return ""; -+} -+ -+/* Output 32-bit load. */ -+const char * -+nds32_output_32bit_load (rtx *operands, int byte) -+{ -+ char pattern[100]; -+ unsigned char size; -+ rtx code; -+ -+ code = XEXP (operands[1], 0); -+ -+ size = nds32_byte_to_size (byte); -+ -+ switch (GET_CODE (code)) -+ { -+ case REG: -+ /* (mem (reg X)) -+ => access location by using register, -+ use "lbi / lhi / lwi" */ -+ snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size); -+ break; -+ -+ case SYMBOL_REF: -+ case CONST: -+ /* (mem (symbol_ref X)) -+ (mem (const (...))) -+ => access global variables, -+ use "lbi.gp / lhi.gp / lwi.gp" */ -+ operands[1] = XEXP (operands[1], 0); -+ snprintf (pattern, sizeof (pattern), "l%ci.gp\t%%0, [ + %%1]", size); -+ break; -+ -+ case POST_INC: -+ /* (mem (post_inc reg)) -+ => access location by using register which will be post increment, -+ use "lbi.bi / lhi.bi / lwi.bi" */ -+ snprintf (pattern, sizeof (pattern), -+ "l%ci.bi\t%%0, %%1, %d", size, byte); -+ break; -+ -+ case POST_DEC: -+ /* (mem (post_dec reg)) -+ => access location by using register which will be post decrement, -+ use "lbi.bi / lhi.bi / lwi.bi" */ -+ snprintf (pattern, sizeof (pattern), -+ "l%ci.bi\t%%0, %%1, -%d", size, byte); -+ break; -+ -+ case POST_MODIFY: -+ switch (GET_CODE (XEXP (XEXP (code, 1), 1))) -+ { -+ case REG: -+ case SUBREG: -+ /* (mem (post_modify (reg) (plus (reg) (reg)))) -+ => access location by using register which will be -+ post modified with reg, -+ use "lb.bi/ lh.bi / lw.bi" */ -+ snprintf (pattern, sizeof (pattern), "l%c.bi\t%%0, %%1", size); -+ break; -+ case CONST_INT: -+ /* (mem (post_modify (reg) (plus (reg) (const_int)))) -+ => access location by using register which will be -+ post modified with const_int, -+ use "lbi.bi/ lhi.bi / lwi.bi" */ -+ snprintf (pattern, sizeof (pattern), "l%ci.bi\t%%0, %%1", size); -+ break; -+ default: -+ abort (); -+ } -+ break; -+ -+ case PLUS: -+ switch (GET_CODE (XEXP (code, 1))) -+ { -+ case REG: -+ case SUBREG: -+ /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg)) -+ use "lb / lh / lw" */ -+ snprintf (pattern, sizeof (pattern), "l%c\t%%0, %%1", size); -+ break; -+ case CONST_INT: -+ /* (mem (plus reg const_int)) -+ => access location by adding one register with const_int, -+ use "lbi / lhi / lwi" */ -+ snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size); -+ break; -+ default: -+ abort (); -+ } -+ break; -+ -+ case LO_SUM: -+ operands[2] = XEXP (code, 1); -+ operands[1] = XEXP (code, 0); -+ snprintf (pattern, sizeof (pattern), -+ "l%ci\t%%0, [%%1 + lo12(%%2)]", size); -+ break; -+ -+ default: -+ abort (); -+ } -+ -+ output_asm_insn (pattern, operands); -+ return ""; -+} -+ -+/* Output 32-bit load with signed extension. */ -+const char * -+nds32_output_32bit_load_se (rtx *operands, int byte) -+{ -+ char pattern[100]; -+ unsigned char size; -+ rtx code; -+ -+ code = XEXP (operands[1], 0); -+ -+ size = nds32_byte_to_size (byte); -+ -+ switch (GET_CODE (code)) -+ { -+ case REG: -+ /* (mem (reg X)) -+ => access location by using register, -+ use "lbsi / lhsi" */ -+ snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size); -+ break; -+ -+ case SYMBOL_REF: -+ case CONST: -+ /* (mem (symbol_ref X)) -+ (mem (const (...))) -+ => access global variables, -+ use "lbsi.gp / lhsi.gp" */ -+ operands[1] = XEXP (operands[1], 0); -+ snprintf (pattern, sizeof (pattern), "l%csi.gp\t%%0, [ + %%1]", size); -+ break; -+ -+ case POST_INC: -+ /* (mem (post_inc reg)) -+ => access location by using register which will be post increment, -+ use "lbsi.bi / lhsi.bi" */ -+ snprintf (pattern, sizeof (pattern), -+ "l%csi.bi\t%%0, %%1, %d", size, byte); -+ break; -+ -+ case POST_DEC: -+ /* (mem (post_dec reg)) -+ => access location by using register which will be post decrement, -+ use "lbsi.bi / lhsi.bi" */ -+ snprintf (pattern, sizeof (pattern), -+ "l%csi.bi\t%%0, %%1, -%d", size, byte); -+ break; -+ -+ case POST_MODIFY: -+ switch (GET_CODE (XEXP (XEXP (code, 1), 1))) -+ { -+ case REG: -+ case SUBREG: -+ /* (mem (post_modify (reg) (plus (reg) (reg)))) -+ => access location by using register which will be -+ post modified with reg, -+ use "lbs.bi/ lhs.bi" */ -+ snprintf (pattern, sizeof (pattern), "l%cs.bi\t%%0, %%1", size); -+ break; -+ case CONST_INT: -+ /* (mem (post_modify (reg) (plus (reg) (const_int)))) -+ => access location by using register which will be -+ post modified with const_int, -+ use "lbsi.bi/ lhsi.bi" */ -+ snprintf (pattern, sizeof (pattern), "l%csi.bi\t%%0, %%1", size); -+ break; -+ default: -+ abort (); -+ } -+ break; -+ -+ case PLUS: -+ switch (GET_CODE (XEXP (code, 1))) -+ { -+ case REG: -+ case SUBREG: -+ /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg)) -+ use "lbs / lhs" */ -+ snprintf (pattern, sizeof (pattern), "l%cs\t%%0, %%1", size); -+ break; -+ case CONST_INT: -+ /* (mem (plus reg const_int)) -+ => access location by adding one register with const_int, -+ use "lbsi / lhsi" */ -+ snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size); -+ break; -+ default: -+ abort (); -+ } -+ break; -+ -+ case LO_SUM: -+ operands[2] = XEXP (code, 1); -+ operands[1] = XEXP (code, 0); -+ snprintf (pattern, sizeof (pattern), -+ "l%csi\t%%0, [%%1 + lo12(%%2)]", size); -+ break; -+ -+ default: -+ abort (); -+ } -+ -+ output_asm_insn (pattern, operands); -+ return ""; -+} -+ -+/* Function to output stack push operation. -+ We need to deal with normal stack push multiple or stack v3push. */ -+const char * -+nds32_output_stack_push (rtx par_rtx) -+{ -+ /* A string pattern for output_asm_insn(). */ -+ char pattern[100]; -+ /* The operands array which will be used in output_asm_insn(). */ -+ rtx operands[3]; -+ /* Pick up varargs first regno and last regno for further use. */ -+ int rb_va_args = cfun->machine->va_args_first_regno; -+ int re_va_args = cfun->machine->va_args_last_regno; -+ int last_argument_regno = NDS32_FIRST_GPR_REGNUM -+ + NDS32_MAX_GPR_REGS_FOR_ARGS -+ - 1; -+ /* Pick up first and last eh data regno for further use. */ -+ int rb_eh_data = cfun->machine->eh_return_data_first_regno; -+ int re_eh_data = cfun->machine->eh_return_data_last_regno; -+ int first_eh_data_regno = EH_RETURN_DATA_REGNO (0); -+ /* Pick up callee-saved first regno and last regno for further use. */ -+ int rb_callee_saved = cfun->machine->callee_saved_first_gpr_regno; -+ int re_callee_saved = cfun->machine->callee_saved_last_gpr_regno; -+ -+ /* First we need to check if we are pushing argument registers not used -+ for the named arguments. If so, we have to create 'smw.adm' (push.s) -+ instruction. */ -+ if (reg_mentioned_p (gen_rtx_REG (SImode, last_argument_regno), par_rtx)) -+ { -+ /* Set operands[0] and operands[1]. */ -+ operands[0] = gen_rtx_REG (SImode, rb_va_args); -+ operands[1] = gen_rtx_REG (SImode, re_va_args); -+ /* Create assembly code pattern: "Rb, Re, { }". */ -+ snprintf (pattern, sizeof (pattern), "push.s\t%s", "%0, %1, { }"); -+ /* We use output_asm_insn() to output assembly code by ourself. */ -+ output_asm_insn (pattern, operands); -+ return ""; -+ } -+ -+ /* If last_argument_regno is not mentioned in par_rtx, we can confirm that -+ we do not need to push argument registers for variadic function. -+ But we still need to check if we need to push exception handling -+ data registers. */ -+ if (reg_mentioned_p (gen_rtx_REG (SImode, first_eh_data_regno), par_rtx)) -+ { -+ /* Set operands[0] and operands[1]. */ -+ operands[0] = gen_rtx_REG (SImode, rb_eh_data); -+ operands[1] = gen_rtx_REG (SImode, re_eh_data); -+ /* Create assembly code pattern: "Rb, Re, { }". */ -+ snprintf (pattern, sizeof (pattern), "push.s\t%s", "%0, %1, { }"); -+ /* We use output_asm_insn() to output assembly code by ourself. */ -+ output_asm_insn (pattern, operands); -+ return ""; -+ } -+ -+ /* If we step here, we are going to do v3push or multiple push operation. */ -+ -+ /* Refer to nds32.h, where we comment when push25/pop25 are available. */ -+ if (NDS32_V3PUSH_AVAILABLE_P) -+ { -+ /* For stack v3push: -+ operands[0]: Re -+ operands[1]: imm8u */ -+ -+ /* This variable is to check if 'push25 Re,imm8u' is available. */ -+ int sp_adjust; -+ -+ /* Set operands[0]. */ -+ operands[0] = gen_rtx_REG (SImode, re_callee_saved); -+ -+ /* Check if we can generate 'push25 Re,imm8u', -+ otherwise, generate 'push25 Re,0'. */ -+ sp_adjust = cfun->machine->local_size -+ + cfun->machine->out_args_size -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) -+ && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)) -+ operands[1] = GEN_INT (sp_adjust); -+ else -+ { -+ /* Allocate callee saved fpr space. */ -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ sp_adjust = cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ operands[1] = GEN_INT (sp_adjust); -+ } -+ else -+ { -+ operands[1] = GEN_INT (0); -+ } -+ } -+ -+ /* Create assembly code pattern. */ -+ snprintf (pattern, sizeof (pattern), "push25\t%%0, %%1"); -+ } -+ else -+ { -+ /* For normal stack push multiple: -+ operands[0]: Rb -+ operands[1]: Re -+ operands[2]: En4 */ -+ -+ /* This variable is used to check if we only need to generate En4 field. -+ As long as Rb==Re=SP_REGNUM, we set this variable to 1. */ -+ int push_en4_only_p = 0; -+ -+ /* Set operands[0] and operands[1]. */ -+ operands[0] = gen_rtx_REG (SImode, rb_callee_saved); -+ operands[1] = gen_rtx_REG (SImode, re_callee_saved); -+ -+ /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */ -+ if (!cfun->machine->fp_size -+ && !cfun->machine->gp_size -+ && !cfun->machine->lp_size -+ && REGNO (operands[0]) == SP_REGNUM -+ && REGNO (operands[1]) == SP_REGNUM) -+ { -+ /* No need to generate instruction. */ -+ return ""; -+ } -+ else -+ { -+ /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */ -+ if (REGNO (operands[0]) == SP_REGNUM -+ && REGNO (operands[1]) == SP_REGNUM) -+ push_en4_only_p = 1; -+ -+ /* Create assembly code pattern. -+ We need to handle the form: "Rb, Re, { $fp $gp $lp }". */ -+ snprintf (pattern, sizeof (pattern), -+ "push.s\t%s{%s%s%s }", -+ push_en4_only_p ? "" : "%0, %1, ", -+ cfun->machine->fp_size ? " $fp" : "", -+ cfun->machine->gp_size ? " $gp" : "", -+ cfun->machine->lp_size ? " $lp" : ""); -+ } -+ } -+ -+ /* We use output_asm_insn() to output assembly code by ourself. */ -+ output_asm_insn (pattern, operands); -+ return ""; -+} -+ -+/* Function to output stack pop operation. -+ We need to deal with normal stack pop multiple or stack v3pop. */ -+const char * -+nds32_output_stack_pop (rtx par_rtx ATTRIBUTE_UNUSED) -+{ -+ /* A string pattern for output_asm_insn(). */ -+ char pattern[100]; -+ /* The operands array which will be used in output_asm_insn(). */ -+ rtx operands[3]; -+ /* Pick up first and last eh data regno for further use. */ -+ int rb_eh_data = cfun->machine->eh_return_data_first_regno; -+ int re_eh_data = cfun->machine->eh_return_data_last_regno; -+ int first_eh_data_regno = EH_RETURN_DATA_REGNO (0); -+ /* Pick up callee-saved first regno and last regno for further use. */ -+ int rb_callee_saved = cfun->machine->callee_saved_first_gpr_regno; -+ int re_callee_saved = cfun->machine->callee_saved_last_gpr_regno; -+ -+ /* We need to check if we need to push exception handling -+ data registers. */ -+ if (reg_mentioned_p (gen_rtx_REG (SImode, first_eh_data_regno), par_rtx)) -+ { -+ /* Set operands[0] and operands[1]. */ -+ operands[0] = gen_rtx_REG (SImode, rb_eh_data); -+ operands[1] = gen_rtx_REG (SImode, re_eh_data); -+ /* Create assembly code pattern: "Rb, Re, { }". */ -+ snprintf (pattern, sizeof (pattern), "pop.s\t%s", "%0, %1, { }"); -+ /* We use output_asm_insn() to output assembly code by ourself. */ -+ output_asm_insn (pattern, operands); -+ return ""; -+ } -+ -+ /* If we step here, we are going to do v3pop or multiple pop operation. */ -+ -+ /* Refer to nds32.h, where we comment when push25/pop25 are available. */ -+ if (NDS32_V3PUSH_AVAILABLE_P) -+ { -+ /* For stack v3pop: -+ operands[0]: Re -+ operands[1]: imm8u */ -+ -+ /* This variable is to check if 'pop25 Re,imm8u' is available. */ -+ int sp_adjust; -+ -+ /* Set operands[0]. */ -+ operands[0] = gen_rtx_REG (SImode, re_callee_saved); -+ -+ /* Check if we can generate 'pop25 Re,imm8u', -+ otherwise, generate 'pop25 Re,0'. -+ We have to consider alloca issue as well. -+ If the function does call alloca(), the stack pointer is not fixed. -+ In that case, we cannot use 'pop25 Re,imm8u' directly. -+ We have to caculate stack pointer from frame pointer -+ and then use 'pop25 Re,0'. */ -+ sp_adjust = cfun->machine->local_size -+ + cfun->machine->out_args_size -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) -+ && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust) -+ && !cfun->calls_alloca) -+ operands[1] = GEN_INT (sp_adjust); -+ else -+ { -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ /* If has fpr need to restore, the $sp on callee saved fpr -+ position, so we need to consider gpr pading bytes and -+ callee saved fpr size. */ -+ sp_adjust = cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ operands[1] = GEN_INT (sp_adjust); -+ } -+ else -+ { -+ operands[1] = GEN_INT (0); -+ } -+ } -+ -+ /* Create assembly code pattern. */ -+ snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1"); -+ } -+ else -+ { -+ /* For normal stack pop multiple: -+ operands[0]: Rb -+ operands[1]: Re -+ operands[2]: En4 */ -+ -+ /* This variable is used to check if we only need to generate En4 field. -+ As long as Rb==Re=SP_REGNUM, we set this variable to 1. */ -+ int pop_en4_only_p = 0; -+ -+ /* Set operands[0] and operands[1]. */ -+ operands[0] = gen_rtx_REG (SImode, rb_callee_saved); -+ operands[1] = gen_rtx_REG (SImode, re_callee_saved); -+ -+ /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */ -+ if (!cfun->machine->fp_size -+ && !cfun->machine->gp_size -+ && !cfun->machine->lp_size -+ && REGNO (operands[0]) == SP_REGNUM -+ && REGNO (operands[1]) == SP_REGNUM) -+ { -+ /* No need to generate instruction. */ -+ return ""; -+ } -+ else -+ { -+ /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */ -+ if (REGNO (operands[0]) == SP_REGNUM -+ && REGNO (operands[1]) == SP_REGNUM) -+ pop_en4_only_p = 1; -+ -+ /* Create assembly code pattern. -+ We need to handle the form: "Rb, Re, { $fp $gp $lp }". */ -+ snprintf (pattern, sizeof (pattern), -+ "pop.s\t%s{%s%s%s }", -+ pop_en4_only_p ? "" : "%0, %1, ", -+ cfun->machine->fp_size ? " $fp" : "", -+ cfun->machine->gp_size ? " $gp" : "", -+ cfun->machine->lp_size ? " $lp" : ""); -+ } -+ } -+ -+ /* We use output_asm_insn() to output assembly code by ourself. */ -+ output_asm_insn (pattern, operands); -+ return ""; -+} -+ -+/* Function to output return operation. */ -+const char * -+nds32_output_return (void) -+{ -+ /* A string pattern for output_asm_insn(). */ -+ char pattern[100]; -+ /* The operands array which will be used in output_asm_insn(). */ -+ rtx operands[2]; -+ /* For stack v3pop: -+ operands[0]: Re -+ operands[1]: imm8u */ -+ int re_callee_saved = cfun->machine->callee_saved_last_gpr_regno; -+ int sp_adjust; -+ -+ /* Set operands[0]. */ -+ operands[0] = gen_rtx_REG (SImode, re_callee_saved); -+ -+ /* Check if we can generate 'pop25 Re,imm8u', -+ otherwise, generate 'pop25 Re,0'. -+ We have to consider alloca issue as well. -+ If the function does call alloca(), the stack pointer is not fixed. -+ In that case, we cannot use 'pop25 Re,imm8u' directly. -+ We have to caculate stack pointer from frame pointer -+ and then use 'pop25 Re,0'. */ -+ sp_adjust = cfun->machine->local_size -+ + cfun->machine->out_args_size -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) -+ && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust) -+ && !cfun->calls_alloca) -+ operands[1] = GEN_INT (sp_adjust); -+ else -+ operands[1] = GEN_INT (0); -+ -+ /* Create assembly code pattern. */ -+ snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1"); -+ /* We use output_asm_insn() to output assembly code by ourself. */ -+ output_asm_insn (pattern, operands); -+ return ""; -+} -+ -+ -+/* output a float load instruction */ -+const char * -+nds32_output_float_load (rtx *operands) -+{ -+ char buff[100]; -+ const char *pattern; -+ rtx addr, addr_op0, addr_op1; -+ int dp = GET_MODE_SIZE (GET_MODE (operands[0])) == 8; -+ addr = XEXP (operands[1], 0); -+ switch (GET_CODE (addr)) -+ { -+ case REG: -+ pattern = "fl%ci\t%%0, %%1"; -+ break; -+ -+ case PLUS: -+ addr_op0 = XEXP (addr, 0); -+ addr_op1 = XEXP (addr, 1); -+ -+ if (REG_P (addr_op0) && REG_P (addr_op1)) -+ pattern = "fl%c\t%%0, %%1"; -+ else if (REG_P (addr_op0) && CONST_INT_P (addr_op1)) -+ pattern = "fl%ci\t%%0, %%1"; -+ else if (GET_CODE (addr_op0) == MULT && REG_P (addr_op1) -+ && REG_P (XEXP (addr_op0, 0)) -+ && CONST_INT_P (XEXP (addr_op0, 1))) -+ pattern = "fl%c\t%%0, %%1"; -+ else -+ gcc_unreachable (); -+ break; -+ -+ case POST_MODIFY: -+ addr_op0 = XEXP (addr, 0); -+ addr_op1 = XEXP (addr, 1); -+ -+ if (REG_P (addr_op0) && GET_CODE (addr_op1) == PLUS -+ && REG_P (XEXP (addr_op1, 1))) -+ pattern = "fl%c.bi\t%%0, %%1"; -+ else if (REG_P (addr_op0) && GET_CODE (addr_op1) == PLUS -+ && CONST_INT_P (XEXP (addr_op1, 1))) -+ pattern = "fl%ci.bi\t%%0, %%1"; -+ else -+ gcc_unreachable (); -+ break; -+ -+ case POST_INC: -+ if (REG_P (XEXP (addr, 0))) -+ { -+ if (dp) -+ pattern = "fl%ci.bi\t%%0, %%1, 8"; -+ else -+ pattern = "fl%ci.bi\t%%0, %%1, 4"; -+ } -+ else -+ gcc_unreachable (); -+ break; -+ -+ case POST_DEC: -+ if (REG_P (XEXP (addr, 0))) -+ { -+ if (dp) -+ pattern = "fl%ci.bi\t%%0, %%1, -8"; -+ else -+ pattern = "fl%ci.bi\t%%0, %%1, -4"; -+ } -+ else -+ gcc_unreachable (); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ sprintf (buff, pattern, dp ? 'd' : 's'); -+ output_asm_insn (buff, operands); -+ return ""; -+} -+ -+/* output a float store instruction */ -+const char * -+nds32_output_float_store (rtx *operands) -+{ -+ char buff[100]; -+ const char *pattern; -+ rtx addr, addr_op0, addr_op1; -+ int dp = GET_MODE_SIZE (GET_MODE (operands[0])) == 8; -+ addr = XEXP (operands[0], 0); -+ switch (GET_CODE (addr)) -+ { -+ case REG: -+ pattern = "fs%ci\t%%1, %%0"; -+ break; -+ -+ case PLUS: -+ addr_op0 = XEXP (addr, 0); -+ addr_op1 = XEXP (addr, 1); -+ -+ if (REG_P (addr_op0) && REG_P (addr_op1)) -+ pattern = "fs%c\t%%1, %%0"; -+ else if (REG_P (addr_op0) && CONST_INT_P (addr_op1)) -+ pattern = "fs%ci\t%%1, %%0"; -+ else if (GET_CODE (addr_op0) == MULT && REG_P (addr_op1) -+ && REG_P (XEXP (addr_op0, 0)) -+ && CONST_INT_P (XEXP (addr_op0, 1))) -+ pattern = "fs%c\t%%1, %%0"; -+ else -+ gcc_unreachable (); -+ break; -+ -+ case POST_MODIFY: -+ addr_op0 = XEXP (addr, 0); -+ addr_op1 = XEXP (addr, 1); -+ -+ if (REG_P (addr_op0) && GET_CODE (addr_op1) == PLUS -+ && REG_P (XEXP (addr_op1, 1))) -+ pattern = "fs%c.bi\t%%1, %%0"; -+ else if (REG_P (addr_op0) && GET_CODE (addr_op1) == PLUS -+ && CONST_INT_P (XEXP (addr_op1, 1))) -+ pattern = "fs%ci.bi\t%%1, %%0"; -+ else -+ gcc_unreachable (); -+ break; -+ -+ case POST_INC: -+ if (REG_P (XEXP (addr, 0))) -+ { -+ if (dp) -+ pattern = "fs%ci.bi\t%%1, %%0, 8"; -+ else -+ pattern = "fs%ci.bi\t%%1, %%0, 4"; -+ } -+ else -+ gcc_unreachable (); -+ break; -+ -+ case POST_DEC: -+ if (REG_P (XEXP (addr, 0))) -+ { -+ if (dp) -+ pattern = "fs%ci.bi\t%%1, %%0, -8"; -+ else -+ pattern = "fs%ci.bi\t%%1, %%0, -4"; -+ } -+ else -+ gcc_unreachable (); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ sprintf (buff, pattern, dp ? 'd' : 's'); -+ output_asm_insn (buff, operands); -+ return ""; -+} -+ -+const char * -+nds32_output_smw_single_word (rtx *operands) -+{ -+ char buff[100]; -+ unsigned regno; -+ int enable4; -+ bool update_base_p; -+ rtx base_addr = operands[0]; -+ rtx base_reg; -+ rtx otherops[2]; -+ -+ if (REG_P (XEXP (base_addr, 0))) -+ { -+ update_base_p = false; -+ base_reg = XEXP (base_addr, 0); -+ } -+ else -+ { -+ update_base_p = true; -+ base_reg = XEXP (XEXP (base_addr, 0), 0); -+ } -+ -+ const char *update_base = update_base_p ? "m" : ""; -+ -+ regno = REGNO (operands[1]); -+ -+ otherops[0] = base_reg; -+ otherops[1] = operands[1]; -+ -+ if (regno >= 28) -+ { -+ enable4 = nds32_regno_to_enable4 (regno); -+ sprintf (buff, "smw.bi%s\t$sp, [%%0], $sp, %x", update_base, enable4); -+ } -+ else -+ { -+ sprintf (buff, "smw.bi%s\t%%1, [%%0], %%1", update_base); -+ } -+ output_asm_insn (buff, otherops); -+ return ""; -+} -+ -+const char * -+nds32_output_smw_double_word (rtx *operands) -+{ -+ char buff[100]; -+ unsigned regno; -+ int enable4; -+ bool update_base_p; -+ rtx base_addr = operands[0]; -+ rtx base_reg; -+ rtx otherops[3]; -+ -+ if (REG_P (XEXP (base_addr, 0))) -+ { -+ update_base_p = false; -+ base_reg = XEXP (base_addr, 0); -+ } -+ else -+ { -+ update_base_p = true; -+ base_reg = XEXP (XEXP (base_addr, 0), 0); -+ } -+ -+ const char *update_base = update_base_p ? "m" : ""; -+ -+ regno = REGNO (operands[1]); -+ -+ 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) -+ | 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], %%2", update_base); -+ } -+ output_asm_insn (buff, otherops); -+ return ""; -+} -+ -+ -+const char * -+nds32_output_lmw_single_word (rtx *operands) -+{ -+ char buff[100]; -+ unsigned regno; -+ bool update_base_p; -+ int enable4; -+ rtx base_addr = operands[1]; -+ rtx base_reg; -+ rtx otherops[2]; -+ -+ if (REG_P (XEXP (base_addr, 0))) -+ { -+ update_base_p = false; -+ base_reg = XEXP (base_addr, 0); -+ } -+ else -+ { -+ update_base_p = true; -+ base_reg = XEXP (XEXP (base_addr, 0), 0); -+ } -+ -+ const char *update_base = update_base_p ? "m" : ""; -+ -+ regno = REGNO (operands[0]); -+ -+ otherops[0] = operands[0]; -+ otherops[1] = base_reg; -+ -+ if (regno >= 28) -+ { -+ enable4 = nds32_regno_to_enable4 (regno); -+ sprintf (buff, "lmw.bi%s\t$sp, [%%1], $sp, %x", update_base, enable4); -+ } -+ else -+ { -+ sprintf (buff, "lmw.bi%s\t%%0, [%%1], %%0", update_base); -+ } -+ output_asm_insn (buff, otherops); -+ return ""; -+} -+ -+void -+nds32_expand_unaligned_load (rtx *operands, enum machine_mode mode) -+{ -+ /* Initial memory offset. */ -+ int offset = WORDS_BIG_ENDIAN ? GET_MODE_SIZE (mode) - 1 : 0; -+ int offset_adj = WORDS_BIG_ENDIAN ? -1 : 1; -+ /* Initial register shift byte. */ -+ int shift = 0; -+ /* The first load byte instruction is not the same. */ -+ int width = GET_MODE_SIZE (mode) - 1; -+ rtx mem[2]; -+ rtx reg[2]; -+ rtx sub_reg; -+ rtx temp_reg, temp_sub_reg; -+ int num_reg; -+ -+ /* Generating a series of load byte instructions. -+ The first load byte instructions and other -+ load byte instructions are not the same. like: -+ First: -+ lbi reg0, [mem] -+ zeh reg0, reg0 -+ Second: -+ lbi temp_reg, [mem + offset] -+ sll temp_reg, (8 * shift) -+ ior reg0, temp_reg -+ -+ lbi temp_reg, [mem + (offset + 1)] -+ sll temp_reg, (8 * (shift + 1)) -+ ior reg0, temp_reg */ -+ -+ temp_reg = gen_reg_rtx (SImode); -+ temp_sub_reg = gen_lowpart (QImode, temp_reg); -+ -+ if (mode == DImode) -+ { -+ /* Load doubleword, we need two registers to access. */ -+ 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 -+ { -+ 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--) -+ { -+ sub_reg = gen_lowpart (QImode, reg[0]); -+ mem[0] = gen_rtx_MEM (QImode, plus_constant (Pmode, operands[1], offset)); -+ -+ /* Generating the first part instructions. -+ lbi reg0, [mem] -+ zeh reg0, reg0 */ -+ emit_move_insn (sub_reg, mem[0]); -+ emit_insn (gen_zero_extendqisi2 (reg[0], sub_reg)); -+ -+ while (width > 0) -+ { -+ offset = offset + offset_adj; -+ shift++; -+ width--; -+ -+ mem[1] = gen_rtx_MEM (QImode, plus_constant (Pmode, -+ operands[1], -+ offset)); -+ /* Generating the second part instructions. -+ lbi temp_reg, [mem + offset] -+ sll temp_reg, (8 * shift) -+ ior reg0, temp_reg */ -+ emit_move_insn (temp_sub_reg, mem[1]); -+ emit_insn (gen_ashlsi3 (temp_reg, temp_reg, -+ GEN_INT (shift * 8))); -+ emit_insn (gen_iorsi3 (reg[0], reg[0], temp_reg)); -+ } -+ -+ if (mode == DImode) -+ { -+ /* Using the second register to load memory information. */ -+ reg[0] = reg[1]; -+ shift = 0; -+ width = GET_MODE_SIZE (SImode) - 1; -+ offset = offset + offset_adj; -+ } -+ } -+ if (VECTOR_MODE_P (mode)) -+ convert_move (operands[0], reg[0], false); -+} -+ -+void -+nds32_expand_unaligned_store (rtx *operands, enum machine_mode mode) -+{ -+ /* Initial memory offset. */ -+ int offset = WORDS_BIG_ENDIAN ? GET_MODE_SIZE (mode) - 1 : 0; -+ int offset_adj = WORDS_BIG_ENDIAN ? -1 : 1; -+ /* Initial register shift byte. */ -+ int shift = 0; -+ /* The first load byte instruction is not the same. */ -+ int width = GET_MODE_SIZE (mode) - 1; -+ rtx mem[2]; -+ rtx reg[2]; -+ rtx sub_reg; -+ rtx temp_reg, temp_sub_reg; -+ int num_reg; -+ -+ /* Generating a series of store byte instructions. -+ The first store byte instructions and other -+ load byte instructions are not the same. like: -+ First: -+ sbi reg0, [mem + 0] -+ Second: -+ srli temp_reg, reg0, (8 * shift) -+ sbi temp_reg, [mem + offset] */ -+ -+ temp_reg = gen_reg_rtx (SImode); -+ temp_sub_reg = gen_lowpart (QImode, temp_reg); -+ -+ if (mode == DImode) -+ { -+ /* Load doubleword, we need two registers to access. */ -+ 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 -+ { -+ 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--) -+ { -+ sub_reg = gen_lowpart (QImode, reg[0]); -+ mem[0] = gen_rtx_MEM (QImode, plus_constant (Pmode, operands[0], offset)); -+ -+ /* Generating the first part instructions. -+ sbi reg0, [mem + 0] */ -+ emit_move_insn (mem[0], sub_reg); -+ -+ while (width > 0) -+ { -+ offset = offset + offset_adj; -+ shift++; -+ width--; -+ -+ mem[1] = gen_rtx_MEM (QImode, plus_constant (Pmode, -+ operands[0], -+ offset)); -+ /* Generating the second part instructions. -+ srli temp_reg, reg0, (8 * shift) -+ sbi temp_reg, [mem + offset] */ -+ emit_insn (gen_lshrsi3 (temp_reg, reg[0], -+ GEN_INT (shift * 8))); -+ emit_move_insn (mem[1], temp_sub_reg); -+ } -+ -+ if (mode == DImode) -+ { -+ /* Using the second register to load memory information. */ -+ reg[0] = reg[1]; -+ shift = 0; -+ width = GET_MODE_SIZE (SImode) - 1; -+ offset = offset + offset_adj; -+ } -+ } -+} -+ -+/* Using multiple load/store instruction to output doubleword instruction. */ -+const char * -+nds32_output_double (rtx *operands, bool load_p) -+{ -+ char pattern[100]; -+ int reg = load_p ? 0 : 1; -+ int mem = load_p ? 1 : 0; -+ rtx otherops[3]; -+ rtx addr = XEXP (operands[mem], 0); -+ -+ otherops[0] = gen_rtx_REG (SImode, REGNO (operands[reg])); -+ otherops[1] = gen_rtx_REG (SImode, REGNO (operands[reg]) + 1); -+ -+ if (GET_CODE (addr) == POST_INC) -+ { -+ /* (mem (post_inc (reg))) */ -+ otherops[2] = XEXP (addr, 0); -+ snprintf (pattern, sizeof (pattern), -+ "%cmw.bim\t%%0, [%%2], %%1, 0", load_p ? 'l' : 's'); -+ } -+ else -+ { -+ /* (mem (reg)) */ -+ otherops[2] = addr; -+ snprintf (pattern, sizeof (pattern), -+ "%cmw.bi\t%%0, [%%2], %%1, 0", load_p ? 'l' : 's'); -+ -+ } -+ -+ output_asm_insn (pattern, otherops); -+ return ""; -+} -+ -+const char * -+nds32_output_cbranchsi4_equality_zero (rtx_insn *insn, rtx *operands) -+{ -+ enum rtx_code code; -+ bool long_jump_p = false; -+ -+ code = GET_CODE (operands[0]); -+ -+ /* This zero-comparison conditional branch has two forms: -+ 32-bit instruction => beqz/bnez imm16s << 1 -+ 16-bit instruction => beqzs8/bnezs8/beqz38/bnez38 imm8s << 1 -+ -+ For 32-bit case, -+ we assume it is always reachable. (but check range -65500 ~ 65500) -+ -+ For 16-bit case, -+ it must satisfy { 255 >= (label - pc) >= -256 } condition. -+ However, since the $pc for nds32 is at the beginning of the instruction, -+ we should leave some length space for current insn. -+ So we use range -250 ~ 250. */ -+ -+ switch (get_attr_length (insn)) -+ { -+ case 8: -+ long_jump_p = true; -+ /* fall through */ -+ case 2: -+ if (which_alternative == 0) -+ { -+ /* constraint: t */ -+ /* bzs8 .L0 -+ or -+ bzs8 .LCB0 -+ j .L0 -+ .LCB0: -+ */ -+ output_cond_branch_compare_zero (code, "s8", long_jump_p, -+ operands, true); -+ return ""; -+ } -+ else if (which_alternative == 1) -+ { -+ /* constraint: l */ -+ /* bz38 $r0, .L0 -+ or -+ bz38 $r0, .LCB0 -+ j .L0 -+ .LCB0: -+ */ -+ output_cond_branch_compare_zero (code, "38", long_jump_p, -+ operands, false); -+ return ""; -+ } -+ else -+ { -+ /* constraint: r */ -+ /* For which_alternative==2, it should not be here. */ -+ gcc_unreachable (); -+ } -+ case 10: -+ /* including constraints: t, l, and r */ -+ long_jump_p = true; -+ /* fall through */ -+ case 4: -+ /* including constraints: t, l, and r */ -+ output_cond_branch_compare_zero (code, "", long_jump_p, operands, false); -+ return ""; -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+const char * -+nds32_output_cbranchsi4_equality_reg (rtx_insn *insn, rtx *operands) -+{ -+ enum rtx_code code; -+ bool long_jump_p, r5_p; -+ int insn_length; -+ -+ insn_length = get_attr_length (insn); -+ -+ long_jump_p = (insn_length == 10 || insn_length == 8) ? true : false; -+ r5_p = (insn_length == 2 || insn_length == 8) ? true : false; -+ -+ code = GET_CODE (operands[0]); -+ -+ /* This register-comparison conditional branch has one form: -+ 32-bit instruction => beq/bne imm14s << 1 -+ -+ For 32-bit case, -+ we assume it is always reachable. (but check range -16350 ~ 16350). */ -+ -+ switch (code) -+ { -+ case EQ: -+ case NE: -+ output_cond_branch (code, "", r5_p, long_jump_p, operands); -+ return ""; -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+const char * -+nds32_output_cbranchsi4_equality_reg_or_const_int (rtx_insn *insn, -+ rtx *operands) -+{ -+ enum rtx_code code; -+ bool long_jump_p, r5_p; -+ int insn_length; -+ -+ insn_length = get_attr_length (insn); -+ -+ long_jump_p = (insn_length == 10 || insn_length == 8) ? true : false; -+ r5_p = (insn_length == 2 || insn_length == 8) ? true : false; -+ -+ code = GET_CODE (operands[0]); -+ -+ /* This register-comparison conditional branch has one form: -+ 32-bit instruction => beq/bne imm14s << 1 -+ 32-bit instruction => beqc/bnec imm8s << 1 -+ -+ For 32-bit case, we assume it is always reachable. -+ (but check range -16350 ~ 16350 and -250 ~ 250). */ -+ -+ switch (code) -+ { -+ case EQ: -+ case NE: -+ if (which_alternative == 2) -+ { -+ /* r, Is11 */ -+ /* bc */ -+ output_cond_branch (code, "c", r5_p, long_jump_p, operands); -+ } -+ else -+ { -+ /* r, r */ -+ /* v, r */ -+ output_cond_branch (code, "", r5_p, long_jump_p, operands); -+ } -+ return ""; -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+const char * -+nds32_output_cbranchsi4_greater_less_zero (rtx_insn *insn, rtx *operands) -+{ -+ enum rtx_code code; -+ bool long_jump_p; -+ int insn_length; -+ -+ insn_length = get_attr_length (insn); -+ -+ gcc_assert (insn_length == 4 || insn_length == 10); -+ -+ long_jump_p = (insn_length == 10) ? true : false; -+ -+ code = GET_CODE (operands[0]); -+ -+ /* This zero-greater-less-comparison conditional branch has one form: -+ 32-bit instruction => bgtz/bgez/bltz/blez imm16s << 1 -+ -+ For 32-bit case, we assume it is always reachable. -+ (but check range -65500 ~ 65500). */ -+ -+ switch (code) -+ { -+ case GT: -+ case GE: -+ case LT: -+ case LE: -+ output_cond_branch_compare_zero (code, "", long_jump_p, operands, false); -+ break; -+ default: -+ gcc_unreachable (); -+ } -+ 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 -+nds32_symbol_binds_local_p (const_rtx x) -+{ -+ return (SYMBOL_REF_DECL (x) -+ ? targetm.binds_local_p (SYMBOL_REF_DECL (x)) -+ : SYMBOL_REF_LOCAL_P (x)); -+} -+ -+const char * -+nds32_output_call (rtx insn, rtx *operands, rtx symbol, const char *long_call, -+ const char *call, bool align_p) -+{ -+ char pattern[100]; -+ bool noreturn_p; -+ -+ 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"); -+ -+ noreturn_p = find_reg_note (insn, REG_NORETURN, NULL_RTX) != NULL_RTX; -+ -+ if (noreturn_p) -+ { -+ if (TARGET_16_BIT) -+ strcat (pattern, "\n\tnop16"); -+ else -+ strcat (pattern, "\n\tnop"); -+ } -+ -+ output_asm_insn (pattern, operands); -+ 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) -+{ -+ int reg = load_p ? 0 : 1; -+ int mem = load_p ? 1 : 0; -+ rtx reg_rtx = load_p ? operands[0] : operands[1]; -+ rtx mem_rtx = load_p ? operands[1] : operands[0]; -+ rtx low_part[2], high_part[2]; -+ rtx sub_mem = XEXP (mem_rtx, 0); -+ -+ /* Generate low_part and high_part register pattern. -+ i.e. register pattern like: -+ (reg:DI) -> (subreg:SI (reg:DI)) -+ (subreg:SI (reg:DI)) */ -+ low_part[reg] = simplify_gen_subreg (SImode, reg_rtx, GET_MODE (reg_rtx), 0); -+ high_part[reg] = simplify_gen_subreg (SImode, reg_rtx, GET_MODE (reg_rtx), 4); -+ -+ /* Generate low_part and high_part memory pattern. -+ Memory format is (post_dec) will generate: -+ low_part: lwi.bi reg, [mem], 4 -+ high_part: lwi.bi reg, [mem], -12 */ -+ if (GET_CODE (sub_mem) == POST_DEC) -+ { -+ /* memory format is (post_dec (reg)), -+ so that extract (reg) from the (post_dec (reg)) pattern. */ -+ sub_mem = XEXP (sub_mem, 0); -+ -+ /* 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)))); -+ } -+ else if (GET_CODE (sub_mem) == POST_MODIFY) -+ { -+ /* Memory format is (post_modify (reg) (plus (reg) (const))), -+ so that extract (reg) from the post_modify pattern. */ -+ rtx post_mem = XEXP (sub_mem, 0); -+ -+ /* Extract (const) from the (post_modify (reg) (plus (reg) (const))) -+ pattern. */ -+ -+ rtx plus_op = XEXP (sub_mem, 1); -+ rtx post_val = XEXP (plus_op, 1); -+ -+ /* 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)); -+ } -+ else -+ { -+ /* memory format: (symbol_ref), (const), (reg + const_int). */ -+ low_part[mem] = adjust_address (mem_rtx, SImode, 0); -+ high_part[mem] = adjust_address (mem_rtx, SImode, 4); -+ } -+ -+ /* After reload completed, we have dependent issue by low part register and -+ higt part memory. i.e. we cannot split a sequence -+ like: -+ load $r0, [%r1] -+ spilt to -+ lw $r0, [%r0] -+ lwi $r1, [%r0 + 4] -+ swap position -+ lwi $r1, [%r0 + 4] -+ lw $r0, [%r0] -+ For store instruction we don't have a problem. -+ -+ When memory format is [post_modify], we need to emit high part instruction, -+ before low part instruction. -+ expamle: -+ load $r0, [%r2], post_val -+ spilt to -+ load $r1, [%r2 + 4] -+ load $r0, [$r2], post_val. */ -+ if ((load_p && reg_overlap_mentioned_p (low_part[0], high_part[1])) -+ || GET_CODE (sub_mem) == POST_MODIFY) -+ { -+ operands[2] = high_part[0]; -+ operands[3] = high_part[1]; -+ operands[4] = low_part[0]; -+ operands[5] = low_part[1]; -+ } -+ else -+ { -+ operands[2] = low_part[0]; -+ operands[3] = low_part[1]; -+ operands[4] = high_part[0]; -+ operands[5] = high_part[1]; -+ } -+} -+ -+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; - -- /* 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)) -+ 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--) - { -- /* For stack v3push: -- operands[0]: Re -- operands[1]: imm8u */ -+ if (fmt[i] == 'E') -+ { -+ int j; - -- /* This variable is to check if 'push25 Re,imm8u' is available. */ -- int sp_adjust; -+ for (j = XVECLEN (op, i) - 1; j >= 0; j--) -+ if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) -+ return true; -+ } - -- /* Set operands[0]. */ -- operands[0] = gen_rtx_REG (SImode, re_callee_saved); -+ else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i))) -+ return true; -+ } - -- /* Check if we can generate 'push25 Re,imm8u', -- otherwise, generate 'push25 Re,0'. */ -- sp_adjust = cfun->machine->local_size -- + cfun->machine->out_args_size -- + cfun->machine->callee_saved_area_gpr_padding_bytes; -- if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) -- && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)) -- operands[1] = GEN_INT (sp_adjust); -- else -- operands[1] = GEN_INT (0); -+ return false; -+} - -- /* Create assembly code pattern. */ -- snprintf (pattern, sizeof (pattern), "push25\t%%0, %%1"); -- } -- else -- { -- /* For normal stack push multiple: -- operands[0]: Rb -- operands[1]: Re -- operands[2]: En4 */ -+/* Expand PIC code for @GOTOFF and @GOT. - -- /* This variable is used to check if we only need to generate En4 field. -- As long as Rb==Re=SP_REGNUM, we set this variable to 1. */ -- int push_en4_only_p = 0; -+ Example for @GOTOFF: - -- /* Set operands[0] and operands[1]. */ -- operands[0] = gen_rtx_REG (SImode, rb_callee_saved); -- operands[1] = gen_rtx_REG (SImode, re_callee_saved); -+ la $r0, symbol@GOTOFF -+ -> sethi $ta, hi20(symbol@GOTOFF) -+ ori $ta, $ta, lo12(symbol@GOTOFF) -+ add $r0, $ta, $gp - -- /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */ -- if (!cfun->machine->fp_size -- && !cfun->machine->gp_size -- && !cfun->machine->lp_size -- && REGNO (operands[0]) == SP_REGNUM -- && REGNO (operands[1]) == SP_REGNUM) -+ 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) - { -- /* No need to generate instruction. */ -- return ""; -+ 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 - { -- /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */ -- if (REGNO (operands[0]) == SP_REGNUM -- && REGNO (operands[1]) == SP_REGNUM) -- push_en4_only_p = 1; -- -- /* Create assembly code pattern. -- We need to handle the form: "Rb, Re, { $fp $gp $lp }". */ -- snprintf (pattern, sizeof (pattern), -- "push.s\t%s{%s%s%s }", -- push_en4_only_p ? "" : "%0, %1, ", -- cfun->machine->fp_size ? " $fp" : "", -- cfun->machine->gp_size ? " $gp" : "", -- cfun->machine->lp_size ? " $lp" : ""); -+ /* Don't handle this pattern. */ -+ debug_rtx (x); -+ gcc_unreachable (); - } - } -+ return x; -+} - -- /* We use output_asm_insn() to output assembly code by ourself. */ -- output_asm_insn (pattern, operands); -- return ""; -+void -+nds32_expand_pic_move (rtx *operands) -+{ -+ rtx src; -+ -+ src = nds32_legitimize_pic_address (operands[1]); -+ emit_move_insn (operands[0], src); - } - --/* Function to output stack pop operation. -- We need to deal with normal stack pop multiple or stack v3pop. */ --const char * --nds32_output_stack_pop (rtx par_rtx ATTRIBUTE_UNUSED) -+/* 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) - { -- /* A string pattern for output_asm_insn(). */ -- char pattern[100]; -- /* The operands array which will be used in output_asm_insn(). */ -- rtx operands[3]; -- /* Pick up callee-saved first regno and last regno for further use. */ -- int rb_callee_saved = cfun->machine->callee_saved_first_gpr_regno; -- int re_callee_saved = cfun->machine->callee_saved_last_gpr_regno; -+ 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)); - -- /* If we step here, we are going to do v3pop or multiple pop operation. */ -+ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, symbol), UNSPEC_ICT); -+ addr = gen_rtx_CONST (SImode, addr); -+ emit_insn (gen_sethi (reg, addr)); - -- /* 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)) -- { -- /* For stack v3pop: -- operands[0]: Re -- operands[1]: imm8u */ -+ x = gen_const_mem (SImode, gen_rtx_LO_SUM (Pmode, reg, addr)); - -- /* This variable is to check if 'pop25 Re,imm8u' is available. */ -- int sp_adjust; -+ return x; -+} - -- /* Set operands[0]. */ -- operands[0] = gen_rtx_REG (SImode, re_callee_saved); -+void -+nds32_expand_ict_move (rtx *operands) -+{ -+ rtx src = operands[1]; - -- /* Check if we can generate 'pop25 Re,imm8u', -- otherwise, generate 'pop25 Re,0'. -- We have to consider alloca issue as well. -- If the function does call alloca(), the stack pointer is not fixed. -- In that case, we cannot use 'pop25 Re,imm8u' directly. -- We have to caculate stack pointer from frame pointer -- and then use 'pop25 Re,0'. */ -- sp_adjust = cfun->machine->local_size -- + cfun->machine->out_args_size -- + cfun->machine->callee_saved_area_gpr_padding_bytes; -- if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) -- && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust) -- && !cfun->calls_alloca) -- operands[1] = GEN_INT (sp_adjust); -- else -- operands[1] = GEN_INT (0); -+ src = nds32_legitimize_ict_address (src); - -- /* Create assembly code pattern. */ -- snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1"); -+ 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) -+{ -+ if (nds32_indirect_call_referenced_p (symbol)) -+ return TARGET_ICT_MODEL_LARGE; - else -- { -- /* For normal stack pop multiple: -- operands[0]: Rb -- operands[1]: Re -- operands[2]: En4 */ -+ return TARGET_CMODEL_LARGE; -+} - -- /* This variable is used to check if we only need to generate En4 field. -- As long as Rb==Re=SP_REGNUM, we set this variable to 1. */ -- int pop_en4_only_p = 0; -+/* Return true if X contains a thread-local symbol. */ -+bool -+nds32_tls_referenced_p (rtx x) -+{ -+ if (!targetm.have_tls) -+ return false; - -- /* Set operands[0] and operands[1]. */ -- operands[0] = gen_rtx_REG (SImode, rb_callee_saved); -- operands[1] = gen_rtx_REG (SImode, re_callee_saved); -+ if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS) -+ x = XEXP (XEXP (x, 0), 0); - -- /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */ -- if (!cfun->machine->fp_size -- && !cfun->machine->gp_size -- && !cfun->machine->lp_size -- && REGNO (operands[0]) == SP_REGNUM -- && REGNO (operands[1]) == SP_REGNUM) -- { -- /* No need to generate instruction. */ -- return ""; -- } -- else -- { -- /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */ -- if (REGNO (operands[0]) == SP_REGNUM -- && REGNO (operands[1]) == SP_REGNUM) -- pop_en4_only_p = 1; -+ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x)) -+ return true; - -- /* Create assembly code pattern. -- We need to handle the form: "Rb, Re, { $fp $gp $lp }". */ -- snprintf (pattern, sizeof (pattern), -- "pop.s\t%s{%s%s%s }", -- pop_en4_only_p ? "" : "%0, %1, ", -- cfun->machine->fp_size ? " $fp" : "", -- cfun->machine->gp_size ? " $gp" : "", -- cfun->machine->lp_size ? " $lp" : ""); -+ 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); - } - } - -- /* We use output_asm_insn() to output assembly code by ourself. */ -- output_asm_insn (pattern, operands); -- return ""; -+ return x; - } - --/* Function to generate PC relative jump table. -- Refer to nds32.md for more details. -+void -+nds32_expand_tls_move (rtx *operands) -+{ -+ rtx src = operands[1]; -+ rtx base, addend; - -- The following is the sample for the case that diff value -- can be presented in '.short' size. -+ if (CONSTANT_P (src)) -+ split_const (src, &base, &addend); - -- addi $r1, $r1, -(case_lower_bound) -- slti $ta, $r1, (case_number) -- beqz $ta, .L_skip_label -+ 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]); -+ } -+ } - -- 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 -+ emit_move_insn (operands[0], src); -+} - -- ! 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) -+void -+nds32_expand_constant (enum machine_mode mode, HOST_WIDE_INT val, -+ rtx target, rtx source) - { -- machine_mode mode; -- rtx diff_vec; -+ rtx temp = gen_reg_rtx (mode); -+ int clear_sign_bit_copies = 0; -+ int clear_zero_bit_copies = 0; -+ unsigned HOST_WIDE_INT remainder = val & 0xffffffffUL; -+ -+ /* Count number of leading zeros. */ -+ clear_sign_bit_copies = __builtin_clz (remainder); -+ /* Count number of trailing zeros. */ -+ clear_zero_bit_copies = __builtin_ctz (remainder); -+ -+ HOST_WIDE_INT sign_shift_mask = ((0xffffffffUL -+ << (32 - clear_sign_bit_copies)) -+ & 0xffffffffUL); -+ HOST_WIDE_INT zero_shift_mask = (1 << clear_zero_bit_copies) - 1; -+ -+ if (clear_sign_bit_copies > 0 && clear_sign_bit_copies < 17 -+ && (remainder | sign_shift_mask) == 0xffffffffUL) -+ { -+ /* Transfer AND to two shifts, example: -+ a = b & 0x7fffffff => (b << 1) >> 1 */ -+ rtx shift = GEN_INT (clear_sign_bit_copies); - -- diff_vec = PATTERN (NEXT_INSN (as_a (operands[1]))); -+ emit_insn (gen_ashlsi3 (temp, source, shift)); -+ emit_insn (gen_lshrsi3 (target, temp, shift)); -+ } -+ else if (clear_zero_bit_copies > 0 && clear_sign_bit_copies < 17 -+ && (remainder | zero_shift_mask) == 0xffffffffUL) -+ { -+ /* Transfer AND to two shifts, example: -+ a = b & 0xfff00000 => (b >> 20) << 20 */ -+ rtx shift = GEN_INT (clear_zero_bit_copies); - -- gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); -+ emit_insn (gen_lshrsi3 (temp, source, shift)); -+ emit_insn (gen_ashlsi3 (target, temp, shift)); -+ } -+ else -+ { -+ emit_move_insn (temp, GEN_INT (val)); -+ emit_move_insn (target, gen_rtx_fmt_ee (AND, mode, source, temp)); -+ } -+} - -- /* Step C: "t <-- operands[1]". */ -- output_asm_insn ("la\t$ta, %l1", operands); -+/* Auxiliary functions for lwm/smw. */ -+bool -+nds32_valid_smw_lwm_base_p (rtx op) -+{ -+ rtx base_addr; - -- /* Get the mode of each element in the difference vector. */ -- mode = GET_MODE (diff_vec); -+ if (!MEM_P (op)) -+ return false; - -- /* 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) -+ base_addr = XEXP (op, 0); -+ -+ if (REG_P (base_addr)) -+ return true; -+ else - { -- case QImode: -- output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands); -- break; -- case HImode: -- output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands); -- break; -- case SImode: -- output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); -- break; -- default: -- gcc_unreachable (); -+ if (GET_CODE (base_addr) == POST_INC -+ && REG_P (XEXP (base_addr, 0))) -+ return true; - } - -- /* 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); -+ return false; -+} - -- /* Step F: jump to target with register t. */ -- if (TARGET_16_BIT) -- return "jr5\t$ta"; -- else -- return "jr\t$ta"; -+/* 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); - } - --/* Function to generate normal jump table. */ --const char * --nds32_output_casesi (rtx *operands) -+rtx nds32_di_low_part_subreg(rtx reg) - { -- /* Step C: "t <-- operands[1]". */ -- output_asm_insn ("la\t$ta, %l1", operands); -+ unsigned low_part_offset = subreg_lowpart_offset (SImode, DImode); - -- /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */ -- output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); -+ return simplify_gen_subreg ( -+ SImode, reg, -+ DImode, low_part_offset); -+} - -- /* 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"; -+/* 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 -- return "jr\t%2"; -+ 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 4c26dcc..c46ac8f 100644 ---- a/gcc/config/nds32/nds32-memory-manipulation.c -+++ b/gcc/config/nds32/nds32-memory-manipulation.c -@@ -25,28 +25,1255 @@ - #include "system.h" - #include "coretypes.h" - #include "backend.h" --#include "target.h" -+#include "tree.h" - #include "rtl.h" --#include "emit-rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" - #include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* This file is divided into six parts: -+ -+ PART 1: Auxiliary static function definitions. -+ -+ PART 2: Auxiliary function for expand movmem pattern. -+ -+ PART 3: Auxiliary function for expand setmem pattern. -+ -+ PART 4: Auxiliary function for expand movstr pattern. -+ -+ PART 5: Auxiliary function for expand strlen pattern. -+ -+ PART 6: Auxiliary function for expand load_multiple/store_multiple -+ pattern. */ -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* PART 1: Auxiliary static function definitions. */ -+ -+static void -+nds32_emit_load_store (rtx reg, rtx mem, -+ enum machine_mode mode, -+ int offset, bool load_p) -+{ -+ rtx new_mem; -+ new_mem = adjust_address (mem, mode, offset); -+ if (load_p) -+ emit_move_insn (reg, new_mem); -+ else -+ emit_move_insn (new_mem, reg); -+} -+ -+static void -+nds32_emit_post_inc_load_store (rtx reg, rtx base_reg, -+ enum machine_mode mode, -+ bool load_p) -+{ -+ gcc_assert (GET_MODE (reg) == mode); -+ gcc_assert (GET_MODE (base_reg) == Pmode); -+ -+ /* Do not gen (set (reg) (mem (post_inc (reg)))) directly here since it may -+ not recognize by gcc, so let gcc combine it at auto_inc_dec pass. */ -+ if (load_p) -+ emit_move_insn (reg, -+ gen_rtx_MEM (mode, -+ base_reg)); -+ else -+ emit_move_insn (gen_rtx_MEM (mode, -+ base_reg), -+ reg); -+ -+ emit_move_insn (base_reg, -+ plus_constant(Pmode, base_reg, GET_MODE_SIZE (mode))); -+} -+ -+static void -+nds32_emit_mem_move (rtx src, rtx dst, -+ enum machine_mode mode, -+ int addr_offset) -+{ -+ gcc_assert (MEM_P (src) && MEM_P (dst)); -+ rtx tmp_reg = gen_reg_rtx (mode); -+ nds32_emit_load_store (tmp_reg, src, mode, -+ addr_offset, /* load_p */ true); -+ nds32_emit_load_store (tmp_reg, dst, mode, -+ addr_offset, /* load_p */ false); -+} -+ -+static void -+nds32_emit_mem_move_block (int base_regno, int count, -+ rtx *dst_base_reg, rtx *dst_mem, -+ rtx *src_base_reg, rtx *src_mem, -+ bool update_base_reg_p) -+{ -+ rtx new_base_reg; -+ -+ emit_insn (nds32_expand_load_multiple (base_regno, count, -+ *src_base_reg, *src_mem, -+ update_base_reg_p, &new_base_reg)); -+ if (update_base_reg_p) -+ { -+ *src_base_reg = new_base_reg; -+ *src_mem = gen_rtx_MEM (SImode, *src_base_reg); -+ } -+ -+ emit_insn (nds32_expand_store_multiple (base_regno, count, -+ *dst_base_reg, *dst_mem, -+ update_base_reg_p, &new_base_reg)); -+ -+ if (update_base_reg_p) -+ { -+ *dst_base_reg = new_base_reg; -+ *dst_mem = gen_rtx_MEM (SImode, *dst_base_reg); -+ } -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* PART 2: Auxiliary function for expand movmem pattern. */ -+ -+static bool -+nds32_expand_movmemsi_loop_unknown_size (rtx dstmem, rtx srcmem, -+ rtx size, -+ rtx alignment, bool use_zol_p) -+{ -+ /* Emit loop version of movmem. -+ -+ andi $size_least_3_bit, $size, #~7 -+ add $dst_end, $dst, $size -+ move $dst_itr, $dst -+ move $src_itr, $src -+ beqz $size_least_3_bit, .Lbyte_mode_entry ! Not large enough. -+ add $double_word_end, $dst, $size_least_3_bit -+ -+ .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 -+ -+ .Lbyte_mode_entry: -+ beq $dst_itr, $dst_end, .Lend_label -+ .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 -+ .Lend_label: -+ */ -+ 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 size_least_3_bit; -+ rtx double_word_end = NULL; -+ rtx double_word_mode_loop, byte_mode_entry, byte_mode_loop, end_label; -+ rtx tmp; -+ rtx mask_least_3_bit; -+ int start_regno; -+ bool align_to_4_bytes = (INTVAL (alignment) & 3) == 0; -+ int hwloop_id = cfun->machine->hwloop_group_id; -+ -+ 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); -+ mask_least_3_bit = GEN_INT (~7); -+ -+ double_word_mode_loop = gen_label_rtx (); -+ byte_mode_entry = gen_label_rtx (); -+ byte_mode_loop = gen_label_rtx (); -+ end_label = 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)); -+ /* andi $size_least_3_bit, $size, #~7 */ -+ size_least_3_bit = expand_binop (SImode, and_optab, size, mask_least_3_bit, -+ NULL_RTX, 0, OPTAB_WIDEN); -+ /* 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); -+ -+ /* beqz $size_least_3_bit, .Lbyte_mode_entry ! Not large enough. */ -+ emit_cmp_and_jump_insns (size_least_3_bit, const0_rtx, EQ, NULL, -+ SImode, 1, byte_mode_entry); -+ if (TARGET_HWLOOP && use_zol_p) -+ { -+ rtx start_label = gen_rtx_LABEL_REF (Pmode, double_word_mode_loop); -+ /* We use multiple-load/store instruction once to process 8-bytes, -+ division 8-bytes for one cycle, generate -+ srli $size_least_3_bit, size_least_3_bit, 3. */ -+ emit_insn (gen_lshrsi3 (size_least_3_bit, size_least_3_bit, GEN_INT (3))); -+ /* mtlbi .Ldouble_word_mode_loop */ -+ emit_insn (gen_mtlbi_hint (start_label, GEN_INT (hwloop_id))); -+ emit_insn (gen_init_lc (size_least_3_bit, GEN_INT (hwloop_id))); -+ emit_insn (gen_no_hwloop ()); -+ } -+ else -+ { -+ /* add $double_word_end, $dst, $size_least_3_bit */ -+ double_word_end = expand_binop (Pmode, add_optab, -+ dst_base_reg, size_least_3_bit, -+ NULL_RTX, 0, OPTAB_WIDEN); -+ } -+ -+ /* .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); -+ -+ if (TARGET_HWLOOP && use_zol_p) -+ { -+ rtx start_label = gen_rtx_LABEL_REF (Pmode, double_word_mode_loop); -+ /* Hwloop pseduo instrtion to handle CFG. */ -+ rtx cfg_insn = emit_jump_insn (gen_hwloop_cfg (GEN_INT (hwloop_id), -+ start_label)); -+ JUMP_LABEL (cfg_insn) = double_word_mode_loop; -+ cfun->machine->hwloop_group_id++; -+ } -+ else -+ { -+ /* ! Not readch upper bound. Loop. -+ bne $double_word_end, $dst_itr, .Ldouble_word_mode_loop */ -+ emit_cmp_and_jump_insns (double_word_end, dst_itr, NE, NULL, -+ Pmode, 1, double_word_mode_loop); -+ } -+ -+ /* .Lbyte_mode_entry: */ -+ emit_label (byte_mode_entry); -+ -+ /* beq $dst_itr, $dst_end, .Lend_label */ -+ emit_cmp_and_jump_insns (dst_itr, dst_end, EQ, NULL, -+ Pmode, 1, end_label); -+ /* .Lbyte_mode_loop: */ -+ emit_label (byte_mode_loop); -+ -+ emit_insn (gen_no_hwloop ()); -+ /* 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); -+ -+ /* .Lend_label: */ -+ emit_label (end_label); -+ -+ return true; -+} -+ -+static bool -+nds32_expand_movmemsi_loop_known_size (rtx dstmem, rtx srcmem, -+ rtx size, rtx 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; -+ int hwloop_id = cfun->machine->hwloop_group_id; -+ 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); -+ -+ emit_insn (gen_no_hwloop ()); -+ /* 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 */ -+ -+ if (TARGET_HWLOOP) -+ { -+ rtx start_label = gen_rtx_LABEL_REF (Pmode, double_word_mode_loop); -+ -+ rtx loop_count_reg = gen_reg_rtx (Pmode); -+ /* movi $loop_count_reg, total_bytes / 8 */ -+ emit_move_insn (loop_count_reg, GEN_INT (total_bytes / 8)); -+ /* mtlbi .Ldouble_word_mode_loop */ -+ emit_insn (gen_mtlbi_hint (start_label, GEN_INT (hwloop_id))); -+ /* mtusr $loop_count_reg, LC */ -+ emit_insn (gen_init_lc (loop_count_reg, GEN_INT (hwloop_id))); -+ emit_insn (gen_no_hwloop ()); -+ } -+ else -+ { -+ /* 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); -+ -+ if (TARGET_HWLOOP) -+ { -+ rtx start_label = gen_rtx_LABEL_REF (Pmode, double_word_mode_loop); -+ /* Hwloop pseduo instrtion to handle CFG. */ -+ rtx cfg_insn = emit_jump_insn (gen_hwloop_cfg (GEN_INT (hwloop_id), -+ start_label)); -+ JUMP_LABEL (cfg_insn) = double_word_mode_loop; -+ cfun->machine->hwloop_group_id++; -+ } -+ else -+ { -+ /* ! 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, -+ true); -+ } -+ -+ return true; -+} -+ -+static bool -+nds32_expand_movmemsi_loop (rtx dstmem, rtx srcmem, -+ rtx size, rtx alignment) -+{ -+ if (CONST_INT_P (size)) -+ return nds32_expand_movmemsi_loop_known_size (dstmem, srcmem, -+ size, alignment); -+ else -+ return nds32_expand_movmemsi_loop_unknown_size (dstmem, srcmem, -+ size, alignment, false); -+} -+ -+static bool -+nds32_expand_movmemsi_unroll (rtx dstmem, rtx srcmem, -+ rtx total_bytes, rtx alignment) -+{ -+ rtx dst_base_reg, src_base_reg; -+ rtx tmp_reg; -+ int maximum_bytes; -+ int maximum_bytes_per_inst; -+ int maximum_regs; -+ int start_regno; -+ int i, inst_num; -+ HOST_WIDE_INT remain_bytes, remain_words; -+ bool align_to_4_bytes = (INTVAL (alignment) & 3) == 0; -+ bool align_to_2_bytes = (INTVAL (alignment) & 1) == 0; -+ -+ /* Because reduced-set regsiters has few registers -+ (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' -+ cannot be used for register allocation), -+ using 8 registers (32 bytes) for moving memory block -+ may easily consume all of them. -+ It makes register allocation/spilling hard to work. -+ So we only allow maximum=4 registers (16 bytes) for -+ moving memory block under reduced-set registers. */ -+ if (TARGET_REDUCED_REGS) -+ { -+ maximum_regs = 4; -+ maximum_bytes = 64; -+ start_regno = 2; -+ } -+ else -+ { -+ if (TARGET_LINUX_ABI) -+ { -+ /* $r25 is $tp so we use up to 8 registers if using Linux ABI. */ -+ maximum_regs = 8; -+ maximum_bytes = 160; -+ start_regno = 16; -+ } -+ else -+ { -+ maximum_regs = 10; -+ maximum_bytes = 160; -+ start_regno = 16; -+ } -+ } -+ maximum_bytes_per_inst = maximum_regs * UNITS_PER_WORD; -+ -+ /* 1. Total_bytes is integer for sure. -+ 2. Alignment is integer for sure. -+ 3. Maximum 4 or 10 registers and up to 4 instructions, -+ 4 * 4 * 4 = 64 bytes, 8 * 4 * 10 = 160 bytes. -+ 4. The dstmem cannot be volatile memory access. -+ 5. The srcmem cannot be volatile memory access. -+ 6. Known shared alignment not align to 4 byte in v3m since lmw/smw *NOT* -+ support unalign access with v3m configure. */ -+ if (GET_CODE (total_bytes) != CONST_INT -+ || GET_CODE (alignment) != CONST_INT -+ || INTVAL (total_bytes) > maximum_bytes -+ || MEM_VOLATILE_P (dstmem) -+ || MEM_VOLATILE_P (srcmem) -+ || (TARGET_ISA_V3M && !align_to_4_bytes)) -+ return false; -+ -+ dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0)); -+ src_base_reg = copy_to_mode_reg (SImode, XEXP (srcmem, 0)); -+ remain_bytes = INTVAL (total_bytes); -+ -+ /* Do not update base address for last lmw/smw pair. */ -+ inst_num = ((INTVAL (total_bytes) + (maximum_bytes_per_inst - 1)) -+ / maximum_bytes_per_inst) - 1; -+ -+ for (i = 0; i < inst_num; i++) -+ { -+ nds32_emit_mem_move_block (start_regno, maximum_regs, -+ &dst_base_reg, &dstmem, -+ &src_base_reg, &srcmem, -+ true); -+ } -+ remain_bytes -= maximum_bytes_per_inst * inst_num; -+ -+ remain_words = remain_bytes / UNITS_PER_WORD; -+ remain_bytes = remain_bytes - (remain_words * UNITS_PER_WORD); -+ -+ if (remain_words != 0) -+ { -+ if (remain_bytes != 0) -+ nds32_emit_mem_move_block (start_regno, remain_words, -+ &dst_base_reg, &dstmem, -+ &src_base_reg, &srcmem, -+ true); -+ else -+ { -+ /* Do not update address if no further byte to move. */ -+ if (remain_words == 1) -+ { -+ /* emit move instruction if align to 4 byte and only 1 -+ word to move. */ -+ if (align_to_4_bytes) -+ nds32_emit_mem_move (srcmem, dstmem, SImode, 0); -+ else -+ { -+ tmp_reg = gen_reg_rtx (SImode); -+ emit_insn ( -+ gen_unaligned_load_w (tmp_reg, -+ gen_rtx_MEM (SImode, src_base_reg))); -+ emit_insn ( -+ gen_unaligned_store_w (gen_rtx_MEM (SImode, dst_base_reg), -+ tmp_reg)); -+ } -+ } -+ else -+ nds32_emit_mem_move_block (start_regno, remain_words, -+ &dst_base_reg, &dstmem, -+ &src_base_reg, &srcmem, -+ false); -+ } -+ } -+ -+ switch (remain_bytes) -+ { -+ case 3: -+ case 2: -+ { -+ if (align_to_2_bytes) -+ nds32_emit_mem_move (srcmem, dstmem, HImode, 0); -+ else -+ { -+ nds32_emit_mem_move (srcmem, dstmem, QImode, 0); -+ nds32_emit_mem_move (srcmem, dstmem, QImode, 1); -+ } -+ -+ if (remain_bytes == 3) -+ nds32_emit_mem_move (srcmem, dstmem, QImode, 2); -+ break; -+ } -+ case 1: -+ nds32_emit_mem_move (srcmem, dstmem, QImode, 0); -+ break; -+ case 0: -+ break; -+ default: -+ gcc_unreachable (); -+ } -+ -+ /* Successfully create patterns, return true. */ -+ return true; -+} -+ -+/* Function to move block memory content by -+ using load_multiple and store_multiple. -+ This is auxiliary extern function to help create rtx template. -+ Check nds32-multiple.md file for the patterns. */ -+bool -+nds32_expand_movmemsi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment) -+{ -+ if (nds32_expand_movmemsi_unroll (dstmem, srcmem, total_bytes, alignment)) -+ return true; -+ -+ if (!optimize_size && optimize > 2) -+ return nds32_expand_movmemsi_loop (dstmem, srcmem, total_bytes, alignment); -+ -+ return false; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* PART 3: Auxiliary function for expand setmem pattern. */ -+ -+static rtx -+nds32_gen_dup_4_byte_to_word_value_aux (rtx value, rtx value4word) -+{ -+ gcc_assert (GET_MODE (value) == QImode || CONST_INT_P (value)); -+ -+ if (CONST_INT_P (value)) -+ { -+ unsigned HOST_WIDE_INT val = UINTVAL (value) & GET_MODE_MASK(QImode); -+ rtx new_val = gen_int_mode (val | (val << 8) -+ | (val << 16) | (val << 24), SImode); -+ /* Just calculate at here if it's constant value. */ -+ emit_move_insn (value4word, new_val); -+ } -+ else -+ { -+ 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 -+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 (); -+ rtx byte_mode_size = gen_reg_rtx (SImode); -+ rtx byte_mode_size_tmp = gen_reg_rtx (SImode); -+ rtx word_mode_end = gen_reg_rtx (SImode); -+ rtx size_for_word = gen_reg_rtx (SImode); -+ -+ /* and $size_for_word, $size, #~0x7 */ -+ size_for_word = expand_binop (SImode, and_optab, size, -+ gen_int_mode (~0x7, SImode), -+ NULL_RTX, 0, OPTAB_WIDEN); -+ -+ emit_move_insn (byte_mode_size, size); -+ -+ /* beqz $size_for_word, .Lbyte_mode_entry */ -+ emit_cmp_and_jump_insns (size_for_word, const0_rtx, EQ, NULL, -+ SImode, 1, word_mode_end_label); -+ /* add $word_mode_end, $dst, $size_for_word */ -+ word_mode_end = expand_binop (Pmode, add_optab, itr, size_for_word, -+ NULL_RTX, 0, OPTAB_WIDEN); -+ -+ /* 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); -+ -+ /* .Lword_mode: */ -+ emit_label (word_mode_label); -+ /* ! 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_dw (itr, -+ itr, -+ value)); -+ emit_cmp_and_jump_insns (word_mode_end, itr, NE, NULL, -+ Pmode, 1, word_mode_label); -+ -+ emit_label (word_mode_end_label); -+ -+ return byte_mode_size; -+} -+ -+static rtx -+emit_setmem_byte_loop (rtx itr, rtx size, rtx value, bool need_end) -+{ -+ rtx end = gen_reg_rtx (Pmode); -+ rtx byte_mode_label = gen_label_rtx (); -+ rtx end_label = gen_label_rtx (); -+ -+ value = force_reg (QImode, value); -+ -+ if (need_end) -+ end = expand_binop (Pmode, add_optab, itr, size, -+ NULL_RTX, 0, OPTAB_WIDEN); -+ /* beqz $byte_mode_size, .Lend -+ add $byte_mode_end, $dst_itr, $byte_mode_size */ -+ emit_cmp_and_jump_insns (size, const0_rtx, EQ, NULL, -+ SImode, 1, end_label); -+ -+ if (!need_end) -+ end = expand_binop (Pmode, add_optab, itr, size, -+ NULL_RTX, 0, OPTAB_WIDEN); -+ -+ /* .Lbyte_mode: */ -+ emit_label (byte_mode_label); -+ -+ emit_insn (gen_no_hwloop ()); -+ /* ! byte-mode set loop -+ sbi.bi $value, [$dst_itr] ,1 -+ bne $byte_mode_end, $dst_itr, .Lbyte_mode */ -+ nds32_emit_post_inc_load_store (value, itr, QImode, false); -+ -+ emit_cmp_and_jump_insns (end, itr, NE, NULL, -+ Pmode, 1, byte_mode_label); -+ /* .Lend: */ -+ emit_label (end_label); -+ -+ if (need_end) -+ return end; -+ else -+ return NULL_RTX; -+} -+ -+static bool -+nds32_expand_setmem_loop (rtx dstmem, rtx size, rtx value) -+{ -+ rtx value4doubleword; -+ rtx value4byte; -+ rtx dst; -+ rtx byte_mode_size; -+ -+ /* Emit loop version of setmem. -+ memset: -+ ! prepare word -+ andi $tmp1, $val, 0xff ! $tmp1 <- 0x000000ab -+ slli $tmp2, $tmp1, 8 ! $tmp2 <- 0x0000ab00 -+ or $tmp3, $val, $tmp2 ! $tmp3 <- 0x0000abab -+ slli $tmp4, $tmp3, 16 ! $tmp4 <- 0xabab0000 -+ or $val4word, $tmp3, $tmp4 ! $value4word <- 0xabababab -+ -+ and $size_for_word, $size, #-4 -+ beqz $size_for_word, .Lword_mode_end -+ -+ add $word_mode_end, $dst, $size_for_word -+ andi $byte_mode_size, $size, 3 -+ -+ .Lword_mode: -+ ! word-mode set loop -+ smw.bim $value4word, [$dst], $value4word, 0 -+ bne $word_mode_end, $dst, .Lword_mode -+ -+ .Lword_mode_end: -+ beqz $byte_mode_size, .Lend -+ add $byte_mode_end, $dst, $byte_mode_size -+ -+ .Lbyte_mode: -+ ! byte-mode set loop -+ sbi.bi $value4word, [$dst] ,1 -+ bne $byte_mode_end, $dst, .Lbyte_mode -+ .Lend: */ -+ -+ dst = copy_to_mode_reg (SImode, XEXP (dstmem, 0)); -+ -+ /* ! 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 */ -+ value4doubleword = nds32_gen_dup_8_byte_to_double_word_value (value); -+ -+ /* and $size_for_word, $size, #-4 -+ beqz $size_for_word, .Lword_mode_end -+ -+ add $word_mode_end, $dst, $size_for_word -+ andi $byte_mode_size, $size, 3 -+ -+ .Lword_mode: -+ ! word-mode set loop -+ smw.bim $value4word, [$dst], $value4word, 0 -+ bne $word_mode_end, $dst, .Lword_mode -+ .Lword_mode_end: */ -+ byte_mode_size = emit_setmem_doubleword_loop (dst, size, value4doubleword); -+ -+ /* beqz $byte_mode_size, .Lend -+ add $byte_mode_end, $dst, $byte_mode_size -+ -+ .Lbyte_mode: -+ ! byte-mode set loop -+ sbi.bi $value, [$dst] ,1 -+ bne $byte_mode_end, $dst, .Lbyte_mode -+ .Lend: */ -+ -+ value4byte = simplify_gen_subreg (QImode, value4doubleword, DImode, -+ subreg_lowpart_offset (QImode, DImode)); -+ -+ emit_setmem_byte_loop (dst, byte_mode_size, value4byte, false); -+ -+ return true; -+} -+ -+static bool -+nds32_expand_setmem_loop_v3m (rtx dstmem, rtx size, rtx value) -+{ -+ rtx base_reg = copy_to_mode_reg (Pmode, XEXP (dstmem, 0)); -+ rtx need_align_bytes = gen_reg_rtx (SImode); -+ rtx last_2_bit = gen_reg_rtx (SImode); -+ rtx byte_loop_base = gen_reg_rtx (SImode); -+ rtx byte_loop_size = gen_reg_rtx (SImode); -+ rtx remain_size = gen_reg_rtx (SImode); -+ rtx new_base_reg; -+ rtx value4byte, value4doubleword; -+ rtx byte_mode_size; -+ rtx last_byte_loop_label = gen_label_rtx (); -+ -+ size = force_reg (SImode, size); -+ -+ 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); -+ -+ /* Jump to last byte loop if size is less than 16. */ -+ emit_cmp_and_jump_insns (size, gen_int_mode (16, SImode), LE, NULL, -+ SImode, 1, last_byte_loop_label); -+ -+ /* Make sure align to 4 byte first since v3m can't unalign access. */ -+ emit_insn (gen_andsi3 (last_2_bit, -+ base_reg, -+ gen_int_mode (0x3, SImode))); -+ -+ emit_insn (gen_subsi3 (need_align_bytes, -+ gen_int_mode (4, SImode), -+ last_2_bit)); -+ -+ /* Align to 4 byte. */ -+ new_base_reg = emit_setmem_byte_loop (base_reg, -+ need_align_bytes, -+ value4byte, -+ true); -+ -+ /* Calculate remain size. */ -+ emit_insn (gen_subsi3 (remain_size, size, need_align_bytes)); -+ -+ /* Set memory word by word. */ -+ 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); -+ -+ emit_label (last_byte_loop_label); -+ -+ /* And set memory for remain bytes. */ -+ emit_setmem_byte_loop (byte_loop_base, byte_loop_size, value4byte, false); -+ return true; -+} -+ -+static bool -+nds32_expand_setmem_unroll (rtx dstmem, rtx size, rtx value, -+ rtx align ATTRIBUTE_UNUSED, -+ rtx expected_align ATTRIBUTE_UNUSED, -+ rtx expected_size ATTRIBUTE_UNUSED) -+{ -+ unsigned maximum_regs, maximum_bytes, start_regno, regno; -+ rtx value4word; -+ rtx dst_base_reg, new_base_reg; -+ unsigned HOST_WIDE_INT remain_bytes, remain_words, prepare_regs, fill_per_smw; -+ unsigned HOST_WIDE_INT real_size; -+ -+ if (TARGET_REDUCED_REGS) -+ { -+ maximum_regs = 4; -+ maximum_bytes = 64; -+ start_regno = 2; -+ } -+ else -+ { -+ maximum_regs = 8; -+ maximum_bytes = 128; -+ start_regno = 16; -+ } -+ -+ real_size = UINTVAL (size) & GET_MODE_MASK(SImode); -+ -+ if (!(CONST_INT_P (size) && real_size <= maximum_bytes)) -+ return false; -+ -+ remain_bytes = real_size; -+ -+ gcc_assert (GET_MODE (value) == QImode || CONST_INT_P (value)); -+ -+ value4word = nds32_gen_dup_4_byte_to_word_value (value); -+ -+ prepare_regs = remain_bytes / UNITS_PER_WORD; -+ -+ dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0)); -+ -+ if (prepare_regs > maximum_regs) -+ prepare_regs = maximum_regs; -+ -+ fill_per_smw = prepare_regs * UNITS_PER_WORD; -+ -+ regno = start_regno; -+ switch (prepare_regs) -+ { -+ case 2: -+ default: -+ { -+ rtx reg0 = gen_rtx_REG (SImode, regno); -+ rtx reg1 = gen_rtx_REG (SImode, regno+1); -+ unsigned last_regno = start_regno + prepare_regs - 1; -+ -+ emit_move_insn (reg0, value4word); -+ emit_move_insn (reg1, value4word); -+ rtx regd = gen_rtx_REG (DImode, regno); -+ regno += 2; -+ -+ /* Try to utilize movd44! */ -+ while (regno <= last_regno) -+ { -+ if ((regno + 1) <=last_regno) -+ { -+ rtx reg = gen_rtx_REG (DImode, regno); -+ emit_move_insn (reg, regd); -+ regno += 2; -+ } -+ else -+ { -+ rtx reg = gen_rtx_REG (SImode, regno); -+ emit_move_insn (reg, reg0); -+ regno += 1; -+ } -+ } -+ break; -+ } -+ case 1: -+ { -+ rtx reg = gen_rtx_REG (SImode, regno++); -+ emit_move_insn (reg, value4word); -+ } -+ break; -+ case 0: -+ break; -+ } -+ -+ if (fill_per_smw) -+ for (;remain_bytes >= fill_per_smw;remain_bytes -= fill_per_smw) -+ { -+ emit_insn (nds32_expand_store_multiple (start_regno, prepare_regs, -+ dst_base_reg, dstmem, -+ true, &new_base_reg)); -+ dst_base_reg = new_base_reg; -+ dstmem = gen_rtx_MEM (SImode, dst_base_reg); -+ } -+ -+ remain_words = remain_bytes / UNITS_PER_WORD; -+ -+ if (remain_words) -+ { -+ emit_insn (nds32_expand_store_multiple (start_regno, remain_words, -+ dst_base_reg, dstmem, -+ true, &new_base_reg)); -+ dst_base_reg = new_base_reg; -+ dstmem = gen_rtx_MEM (SImode, dst_base_reg); -+ } -+ -+ remain_bytes = remain_bytes - (remain_words * UNITS_PER_WORD); -+ -+ if (remain_bytes) -+ { -+ value = simplify_gen_subreg (QImode, value4word, SImode, -+ subreg_lowpart_offset(QImode, SImode)); -+ int offset = 0; -+ for (;remain_bytes;--remain_bytes, ++offset) -+ { -+ nds32_emit_load_store (value, dstmem, QImode, offset, false); -+ } -+ } -+ -+ return true; -+} -+ -+bool -+nds32_expand_setmem (rtx dstmem, rtx size, rtx value, rtx align, -+ rtx expected_align, -+ rtx expected_size) -+{ -+ bool align_to_4_bytes = (INTVAL (align) & 3) == 0; -+ -+ /* Only expand at O3 */ -+ if (optimize_size || optimize < 3) -+ return false; -+ -+ if (TARGET_ISA_V3M && !align_to_4_bytes) -+ return nds32_expand_setmem_loop_v3m (dstmem, size, value); -+ -+ if (nds32_expand_setmem_unroll (dstmem, size, value, -+ align, expected_align, expected_size)) -+ return true; -+ -+ return nds32_expand_setmem_loop (dstmem, size, value); -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* PART 4: Auxiliary function for expand movstr pattern. */ -+ -+bool -+nds32_expand_movstr (rtx dst_end_ptr, -+ rtx dstmem, -+ rtx srcmem) -+{ -+ rtx tmp; -+ rtx dst_base_reg, src_base_reg; -+ rtx new_dst_base_reg, new_src_base_reg; -+ rtx last_non_null_char_ptr; -+ rtx ffbi_result; -+ rtx loop_label; -+ -+ if (optimize_size || optimize < 3) -+ return false; -+ -+ tmp = gen_reg_rtx (SImode); -+ ffbi_result = gen_reg_rtx (Pmode); -+ new_dst_base_reg = gen_reg_rtx (Pmode); -+ new_src_base_reg = gen_reg_rtx (Pmode); -+ dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0)); -+ src_base_reg = copy_to_mode_reg (SImode, XEXP (srcmem, 0)); -+ loop_label = gen_label_rtx (); -+ -+ emit_label (loop_label); -+ emit_insn (gen_lmwzb (new_src_base_reg, src_base_reg, tmp)); -+ emit_insn (gen_smwzb (new_dst_base_reg, dst_base_reg, tmp)); -+ emit_insn (gen_unspec_ffb (ffbi_result, tmp, const0_rtx)); -+ -+ emit_move_insn (src_base_reg, new_src_base_reg); -+ emit_move_insn (dst_base_reg, new_dst_base_reg); -+ -+ emit_cmp_and_jump_insns (ffbi_result, const0_rtx, EQ, NULL, -+ SImode, 1, loop_label); -+ -+ last_non_null_char_ptr = expand_binop (Pmode, add_optab, dst_base_reg, -+ ffbi_result, NULL_RTX, 0, OPTAB_WIDEN); -+ -+ emit_move_insn (dst_end_ptr, last_non_null_char_ptr); -+ -+ return true; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* PART 5: Auxiliary function for expand strlen pattern. */ -+ -+bool -+nds32_expand_strlen (rtx result, rtx str, -+ rtx target_char, rtx align ATTRIBUTE_UNUSED) -+{ -+ rtx base_reg, backup_base_reg; -+ rtx ffb_result; -+ rtx target_char_ptr, length; -+ rtx loop_label, tmp; -+ -+ if (optimize_size || optimize < 3) -+ return false; -+ -+ gcc_assert (MEM_P (str)); -+ gcc_assert (CONST_INT_P (target_char) || REG_P (target_char)); -+ -+ base_reg = copy_to_mode_reg (SImode, XEXP (str, 0)); -+ loop_label = gen_label_rtx (); -+ -+ ffb_result = gen_reg_rtx (Pmode); -+ tmp = gen_reg_rtx (SImode); -+ backup_base_reg = gen_reg_rtx (SImode); -+ -+ /* Emit loop version of strlen. -+ move $backup_base, $base -+ .Lloop: -+ lmw.bim $tmp, [$base], $tmp, 0 -+ ffb $ffb_result, $tmp, $target_char ! is there $target_char? -+ beqz $ffb_result, .Lloop -+ add $last_char_ptr, $base, $ffb_result -+ sub $length, $last_char_ptr, $backup_base */ -+ -+ /* move $backup_base, $base */ -+ emit_move_insn (backup_base_reg, base_reg); -+ -+ /* .Lloop: */ -+ emit_label (loop_label); -+ /* lmw.bim $tmp, [$base], $tmp, 0 */ -+ emit_insn (gen_unaligned_load_update_base_w (base_reg, tmp, base_reg)); -+ -+ /* ffb $ffb_result, $tmp, $target_char ! is there $target_char? */ -+ emit_insn (gen_unspec_ffb (ffb_result, tmp, target_char)); -+ -+ /* beqz $ffb_result, .Lloop */ -+ emit_cmp_and_jump_insns (ffb_result, const0_rtx, EQ, NULL, -+ SImode, 1, loop_label); -+ -+ /* add $target_char_ptr, $base, $ffb_result */ -+ target_char_ptr = expand_binop (Pmode, add_optab, base_reg, -+ ffb_result, NULL_RTX, 0, OPTAB_WIDEN); -+ -+ /* sub $length, $target_char_ptr, $backup_base */ -+ length = expand_binop (Pmode, sub_optab, target_char_ptr, -+ backup_base_reg, NULL_RTX, 0, OPTAB_WIDEN); -+ -+ emit_move_insn (result, length); -+ -+ return true; -+} - - /* ------------------------------------------------------------------------ */ - -+/* PART 6: Auxiliary function for expand load_multiple/store_multiple -+ pattern. */ -+ - /* Functions to expand load_multiple and store_multiple. - They are auxiliary extern functions to help create rtx template. - Check nds32-multiple.md file for the patterns. */ - rtx - nds32_expand_load_multiple (int base_regno, int count, -- rtx base_addr, rtx basemem) -+ rtx base_addr, rtx basemem, -+ bool update_base_reg_p, -+ rtx *update_base_reg) - { - int par_index; - int offset; -+ int start_idx; - rtx result; - rtx new_addr, mem, reg; - -+ /* Generate a unaligned load to prevent load instruction pull out from -+ parallel, and then it will generate lwi, and lose unaligned acces */ -+ if (count == 1) -+ { -+ reg = gen_rtx_REG (SImode, base_regno); -+ if (update_base_reg_p) -+ { -+ *update_base_reg = gen_reg_rtx (SImode); -+ return gen_unaligned_load_update_base_w (*update_base_reg, reg, base_addr); -+ } -+ else -+ return gen_unaligned_load_w (reg, gen_rtx_MEM (SImode, base_addr)); -+ } -+ - /* Create the pattern that is presented in nds32-multiple.md. */ -+ if (update_base_reg_p) -+ { -+ result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 1)); -+ start_idx = 1; -+ } -+ else -+ { -+ result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); -+ start_idx = 0; -+ } -+ -+ if (update_base_reg_p) -+ { -+ offset = count * 4; -+ new_addr = plus_constant (Pmode, base_addr, offset); -+ *update_base_reg = gen_reg_rtx (SImode); - -- result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); -+ XVECEXP (result, 0, 0) = gen_rtx_SET (*update_base_reg, new_addr); -+ } - - for (par_index = 0; par_index < count; par_index++) - { -@@ -57,7 +1284,7 @@ nds32_expand_load_multiple (int base_regno, int count, - new_addr, offset); - reg = gen_rtx_REG (SImode, base_regno + par_index); - -- XVECEXP (result, 0, par_index) = gen_rtx_SET (reg, mem); -+ XVECEXP (result, 0, (par_index + start_idx)) = gen_rtx_SET (reg, mem); - } - - return result; -@@ -65,16 +1292,49 @@ nds32_expand_load_multiple (int base_regno, int count, - - rtx - nds32_expand_store_multiple (int base_regno, int count, -- rtx base_addr, rtx basemem) -+ rtx base_addr, rtx basemem, -+ bool update_base_reg_p, -+ rtx *update_base_reg) - { - int par_index; - int offset; -+ int start_idx; - rtx result; - rtx new_addr, mem, reg; - -+ if (count == 1) -+ { -+ reg = gen_rtx_REG (SImode, base_regno); -+ if (update_base_reg_p) -+ { -+ *update_base_reg = gen_reg_rtx (SImode); -+ return gen_unaligned_store_update_base_w (*update_base_reg, base_addr, reg); -+ } -+ else -+ return gen_unaligned_store_w (gen_rtx_MEM (SImode, base_addr), reg); -+ } -+ - /* Create the pattern that is presented in nds32-multiple.md. */ - -- result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); -+ if (update_base_reg_p) -+ { -+ result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 1)); -+ start_idx = 1; -+ } -+ else -+ { -+ result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); -+ start_idx = 0; -+ } -+ -+ if (update_base_reg_p) -+ { -+ offset = count * 4; -+ new_addr = plus_constant (Pmode, base_addr, offset); -+ *update_base_reg = gen_reg_rtx (SImode); -+ -+ XVECEXP (result, 0, 0) = gen_rtx_SET (*update_base_reg, new_addr); -+ } - - for (par_index = 0; par_index < count; par_index++) - { -@@ -85,58 +1345,11 @@ nds32_expand_store_multiple (int base_regno, int count, - new_addr, offset); - reg = gen_rtx_REG (SImode, base_regno + par_index); - -- XVECEXP (result, 0, par_index) = gen_rtx_SET (mem, reg); -+ XVECEXP (result, 0, par_index + start_idx) = gen_rtx_SET (mem, reg); - } - -- return result; --} -- --/* Function to move block memory content by -- using load_multiple and store_multiple. -- This is auxiliary extern function to help create rtx template. -- Check nds32-multiple.md file for the patterns. */ --int --nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment) --{ -- HOST_WIDE_INT in_words, out_words; -- rtx dst_base_reg, src_base_reg; -- int maximum_bytes; -- -- /* Because reduced-set regsiters has few registers -- (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' -- cannot be used for register allocation), -- using 8 registers (32 bytes) for moving memory block -- may easily consume all of them. -- It makes register allocation/spilling hard to work. -- So we only allow maximum=4 registers (16 bytes) for -- moving memory block under reduced-set registers. */ -- if (TARGET_REDUCED_REGS) -- maximum_bytes = 16; -- else -- maximum_bytes = 32; -- -- /* 1. Total_bytes is integer for sure. -- 2. Alignment is integer for sure. -- 3. Maximum 4 or 8 registers, 4 * 4 = 16 bytes, 8 * 4 = 32 bytes. -- 4. Requires (n * 4) block size. -- 5. Requires 4-byte alignment. */ -- if (GET_CODE (total_bytes) != CONST_INT -- || GET_CODE (alignment) != CONST_INT -- || INTVAL (total_bytes) > maximum_bytes -- || INTVAL (total_bytes) & 3 -- || INTVAL (alignment) & 3) -- return 0; - -- dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0)); -- src_base_reg = copy_to_mode_reg (SImode, XEXP (srcmem, 0)); -- -- out_words = in_words = INTVAL (total_bytes) / UNITS_PER_WORD; -- -- emit_insn (nds32_expand_load_multiple (0, in_words, src_base_reg, srcmem)); -- emit_insn (nds32_expand_store_multiple (0, out_words, dst_base_reg, dstmem)); -- -- /* Successfully create patterns, return 1. */ -- return 1; -+ return result; - } - - /* ------------------------------------------------------------------------ */ -diff --git a/gcc/config/nds32/nds32-modes.def b/gcc/config/nds32/nds32-modes.def -index f2d0e6c..7a6f953 100644 ---- a/gcc/config/nds32/nds32-modes.def -+++ b/gcc/config/nds32/nds32-modes.def -@@ -18,4 +18,6 @@ - along with GCC; see the file COPYING3. If not see - . */ - --/* So far, there is no need to define any modes for nds32 target. */ -+/* Vector modes. */ -+VECTOR_MODES (INT, 4); /* V4QI V2HI */ -+VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */ -diff --git a/gcc/config/nds32/nds32-multiple.md b/gcc/config/nds32/nds32-multiple.md -index babc7f2..500a1c6 100644 ---- a/gcc/config/nds32/nds32-multiple.md -+++ b/gcc/config/nds32/nds32-multiple.md -@@ -49,17 +49,19 @@ - otherwise we have to FAIL this rtx generation: - 1. The number of consecutive registers must be integer. - 2. Maximum 4 or 8 registers for lmw.bi instruction -- (based on this nds32-multiple.md design). -+ (based on this nds32-multiple.md design). - 3. Minimum 2 registers for lmw.bi instruction -- (based on this nds32-multiple.md design). -+ (based on this nds32-multiple.md design). - 4. operands[0] must be register for sure. - 5. operands[1] must be memory for sure. -- 6. Do not cross $r15 register because it is not allocatable. */ -+ 6. operands[1] is not volatile memory access. -+ 7. Do not cross $r15 register because it is not allocatable. */ - if (GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) > maximum - || INTVAL (operands[2]) < 2 - || GET_CODE (operands[0]) != REG - || GET_CODE (operands[1]) != MEM -+ || MEM_VOLATILE_P (operands[1]) - || REGNO (operands[0]) + INTVAL (operands[2]) > TA_REGNUM) - FAIL; - -@@ -69,12 +71,943 @@ - INTVAL (operands[2]), - force_reg (SImode, - XEXP (operands[1], 0)), -- operands[1]); -+ operands[1], -+ false, NULL); - }) - - ;; Ordinary Load Multiple. -+(define_insn "*lmw_bim_si25" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 100))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 60)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 64)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 68)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 72)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 76)))) -+ (set (match_operand:SI 23 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 80)))) -+ (set (match_operand:SI 24 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 84)))) -+ (set (match_operand:SI 25 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 88)))) -+ (set (match_operand:SI 26 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 92)))) -+ (set (match_operand:SI 27 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 96))))])] -+ "(XVECLEN (operands[0], 0) == 26)" -+ "lmw.bim\t%3, [%1], %27, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "25") -+ (set_attr "length" "4")] -+) - --(define_insn "*lmwsi8" -+(define_insn "*lmw_bim_si24" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 96))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 60)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 64)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 68)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 72)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 76)))) -+ (set (match_operand:SI 23 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 80)))) -+ (set (match_operand:SI 24 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 84)))) -+ (set (match_operand:SI 25 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 88)))) -+ (set (match_operand:SI 26 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 92))))])] -+ "(XVECLEN (operands[0], 0) == 25)" -+ "lmw.bim\t%3, [%1], %26, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "24") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si23" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 92))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 60)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 64)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 68)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 72)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 76)))) -+ (set (match_operand:SI 23 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 80)))) -+ (set (match_operand:SI 24 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 84)))) -+ (set (match_operand:SI 25 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 88))))])] -+ "(XVECLEN (operands[0], 0) == 24)" -+ "lmw.bim\t%3, [%1], %25, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "23") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si22" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 88))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 60)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 64)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 68)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 72)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 76)))) -+ (set (match_operand:SI 23 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 80)))) -+ (set (match_operand:SI 24 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 84))))])] -+ "(XVECLEN (operands[0], 0) == 23)" -+ "lmw.bim\t%3, [%1], %24, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "22") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si21" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 84))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 60)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 64)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 68)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 72)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 76)))) -+ (set (match_operand:SI 23 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 80))))])] -+ "(XVECLEN (operands[0], 0) == 22)" -+ "lmw.bim\t%3, [%1], %23, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "21") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si20" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 80))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 60)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 64)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 68)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 72)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 76))))])] -+ "(XVECLEN (operands[0], 0) == 21)" -+ "lmw.bim\t%3, [%1], %22, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "20") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si19" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 76))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 60)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 64)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 68)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 72))))])] -+ "(XVECLEN (operands[0], 0) == 20)" -+ "lmw.bim\t%3, [%1], %21, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "19") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si18" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 72))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 60)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 64)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 68))))])] -+ "(XVECLEN (operands[0], 0) == 19)" -+ "lmw.bim\t%3, [%1], %20, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "18") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si17" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 68))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 60)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 64))))])] -+ "(XVECLEN (operands[0], 0) == 18)" -+ "lmw.bim\t%3, [%1], %19, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "17") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si16" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 64))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 60))))])] -+ "(XVECLEN (operands[0], 0) == 17)" -+ "lmw.bim\t%3, [%1], %18, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "16") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si15" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 60))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 56))))])] -+ "(XVECLEN (operands[0], 0) == 16)" -+ "lmw.bim\t%3, [%1], %17, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "15") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si14" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 56))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 52))))])] -+ "(XVECLEN (operands[0], 0) == 15)" -+ "lmw.bim\t%3, [%1], %16, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "14") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si13" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 52))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 48))))])] -+ "(XVECLEN (operands[0], 0) == 14)" -+ "lmw.bim\t%3, [%1], %15, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "13") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si12" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 48))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 44))))])] -+ "(XVECLEN (operands[0], 0) == 13)" -+ "lmw.bim\t%3, [%1], %14, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "12") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si11" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 44))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 40))))])] -+ "(XVECLEN (operands[0], 0) == 12)" -+ "lmw.bim\t%3, [%1], %13, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "11") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si10" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 40))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 36))))])] -+ "(XVECLEN (operands[0], 0) == 11)" -+ "lmw.bim\t%3, [%1], %12, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "10") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si9" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 36))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 32))))])] -+ "(XVECLEN (operands[0], 0) == 10)" -+ "lmw.bim\t%3, [%1], %11, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "9") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si8" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 32))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 28))))])] -+ "(XVECLEN (operands[0], 0) == 9)" -+ "lmw.bim\t%3, [%1], %10, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "8") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si7" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 28))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 24))))])] -+ "(XVECLEN (operands[0], 0) == 8)" -+ "lmw.bim\t%3, [%1], %9, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "7") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si6" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 24))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 20))))])] -+ "(XVECLEN (operands[0], 0) == 7)" -+ "lmw.bim\t%3, [%1], %8, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "6") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si5" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 20))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 16))))])] -+ "(XVECLEN (operands[0], 0) == 6)" -+ "lmw.bim\t%3, [%1], %7, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "5") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si4" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 16))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))])] -+ "(XVECLEN (operands[0], 0) == 5)" -+ "lmw.bim\t%3, [%1], %6, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "4") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si3" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 12))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))])] -+ "(XVECLEN (operands[0], 0) == 4)" -+ "lmw.bim\t%3, [%1], %5, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "3") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmw_bim_si2" -+ [(match_parallel 0 "nds32_load_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 8))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (match_dup 2))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))])] -+ "(XVECLEN (operands[0], 0) == 3)" -+ "lmw.bim\t%3, [%1], %4, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "2") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "unaligned_load_update_base_w" -+ [(parallel [(set (match_operand:SI 0 "register_operand" "") -+ (plus:SI (match_operand:SI 2 "register_operand" "") (const_int 4))) -+ (set (match_operand:SI 1 "register_operand" "") -+ (unspec:SI [(mem:SI (match_dup 2))] UNSPEC_UALOAD_W))])] -+ "" -+{ -+ /* DO NOT emit unaligned_load_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_load_w (operands[1], gen_rtx_MEM (SImode, operands[2]))); -+ emit_insn (gen_addsi3 (operands[0], operands[2], gen_int_mode (4, Pmode))); -+ DONE; -+} -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "1") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi25" - [(match_parallel 0 "nds32_load_multiple_operation" - [(set (match_operand:SI 2 "register_operand" "") - (mem:SI (match_operand:SI 1 "register_operand" "r"))) -@@ -91,14 +1024,49 @@ - (set (match_operand:SI 8 "register_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 24)))) - (set (match_operand:SI 9 "register_operand" "") -- (mem:SI (plus:SI (match_dup 1) (const_int 28))))])] -- "(XVECLEN (operands[0], 0) == 8)" -- "lmw.bi\t%2, [%1], %9, 0x0" -- [(set_attr "type" "load") -- (set_attr "length" "4")] -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 60)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 64)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 68)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 72)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 76)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 80)))) -+ (set (match_operand:SI 23 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 84)))) -+ (set (match_operand:SI 24 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 88)))) -+ (set (match_operand:SI 25 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 92)))) -+ (set (match_operand:SI 26 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 96))))])] -+ "(XVECLEN (operands[0], 0) == 25)" -+ "lmw.bi\t%2, [%1], %26, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "25") -+ (set_attr "length" "4")] - ) - --(define_insn "*lmwsi7" -+(define_insn "*lmwsi24" - [(match_parallel 0 "nds32_load_multiple_operation" - [(set (match_operand:SI 2 "register_operand" "") - (mem:SI (match_operand:SI 1 "register_operand" "r"))) -@@ -113,14 +1081,49 @@ - (set (match_operand:SI 7 "register_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 20)))) - (set (match_operand:SI 8 "register_operand" "") -- (mem:SI (plus:SI (match_dup 1) (const_int 24))))])] -- "(XVECLEN (operands[0], 0) == 7)" -- "lmw.bi\t%2, [%1], %8, 0x0" -- [(set_attr "type" "load") -- (set_attr "length" "4")] -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 60)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 64)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 68)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 72)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 76)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 80)))) -+ (set (match_operand:SI 23 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 84)))) -+ (set (match_operand:SI 24 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 88)))) -+ (set (match_operand:SI 25 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 92))))])] -+ "(XVECLEN (operands[0], 0) == 24)" -+ "lmw.bi\t%2, [%1], %25, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "24") -+ (set_attr "length" "4")] - ) - --(define_insn "*lmwsi6" -+(define_insn "*lmwsi23" - [(match_parallel 0 "nds32_load_multiple_operation" - [(set (match_operand:SI 2 "register_operand" "") - (mem:SI (match_operand:SI 1 "register_operand" "r"))) -@@ -133,14 +1136,49 @@ - (set (match_operand:SI 6 "register_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 16)))) - (set (match_operand:SI 7 "register_operand" "") -- (mem:SI (plus:SI (match_dup 1) (const_int 20))))])] -- "(XVECLEN (operands[0], 0) == 6)" -- "lmw.bi\t%2, [%1], %7, 0x0" -- [(set_attr "type" "load") -- (set_attr "length" "4")] -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 60)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 64)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 68)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 72)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 76)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 80)))) -+ (set (match_operand:SI 23 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 84)))) -+ (set (match_operand:SI 24 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 88))))])] -+ "(XVECLEN (operands[0], 0) == 23)" -+ "lmw.bi\t%2, [%1], %24, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "23") -+ (set_attr "length" "4")] - ) - --(define_insn "*lmwsi5" -+(define_insn "*lmwsi22" - [(match_parallel 0 "nds32_load_multiple_operation" - [(set (match_operand:SI 2 "register_operand" "") - (mem:SI (match_operand:SI 1 "register_operand" "r"))) -@@ -151,110 +1189,2430 @@ - (set (match_operand:SI 5 "register_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 12)))) - (set (match_operand:SI 6 "register_operand" "") -- (mem:SI (plus:SI (match_dup 1) (const_int 16))))])] -- "(XVECLEN (operands[0], 0) == 5)" -- "lmw.bi\t%2, [%1], %6, 0x0" -- [(set_attr "type" "load") -- (set_attr "length" "4")] -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 60)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 64)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 68)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 72)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 76)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 80)))) -+ (set (match_operand:SI 23 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 84))))])] -+ "(XVECLEN (operands[0], 0) == 22)" -+ "lmw.bi\t%2, [%1], %23, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "22") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi21" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 60)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 64)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 68)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 72)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 76)))) -+ (set (match_operand:SI 22 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 80))))])] -+ "(XVECLEN (operands[0], 0) == 21)" -+ "lmw.bi\t%2, [%1], %22, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "21") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi20" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 60)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 64)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 68)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 72)))) -+ (set (match_operand:SI 21 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 76))))])] -+ "(XVECLEN (operands[0], 0) == 20)" -+ "lmw.bi\t%2, [%1], %21, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "20") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi19" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 60)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 64)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 68)))) -+ (set (match_operand:SI 20 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 72))))])] -+ "(XVECLEN (operands[0], 0) == 19)" -+ "lmw.bi\t%2, [%1], %20, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "19") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi18" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 60)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 64)))) -+ (set (match_operand:SI 19 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 68))))])] -+ "(XVECLEN (operands[0], 0) == 18)" -+ "lmw.bi\t%2, [%1], %19, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "18") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi17" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 60)))) -+ (set (match_operand:SI 18 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 64))))])] -+ "(XVECLEN (operands[0], 0) == 17)" -+ "lmw.bi\t%2, [%1], %18, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "17") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi16" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56)))) -+ (set (match_operand:SI 17 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 60))))])] -+ "(XVECLEN (operands[0], 0) == 16)" -+ "lmw.bi\t%2, [%1], %17, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "16") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi15" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52)))) -+ (set (match_operand:SI 16 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 56))))])] -+ "(XVECLEN (operands[0], 0) == 15)" -+ "lmw.bi\t%2, [%1], %16, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "15") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi14" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48)))) -+ (set (match_operand:SI 15 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 52))))])] -+ "(XVECLEN (operands[0], 0) == 14)" -+ "lmw.bi\t%2, [%1], %15, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "14") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi13" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44)))) -+ (set (match_operand:SI 14 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 48))))])] -+ "(XVECLEN (operands[0], 0) == 13)" -+ "lmw.bi\t%2, [%1], %14, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "13") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi12" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40)))) -+ (set (match_operand:SI 13 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 44))))])] -+ "(XVECLEN (operands[0], 0) == 12)" -+ "lmw.bi\t%2, [%1], %13, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "12") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi11" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36)))) -+ (set (match_operand:SI 12 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 40))))])] -+ "(XVECLEN (operands[0], 0) == 11)" -+ "lmw.bi\t%2, [%1], %12, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "11") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi10" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32)))) -+ (set (match_operand:SI 11 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 36))))])] -+ "(XVECLEN (operands[0], 0) == 10)" -+ "lmw.bi\t%2, [%1], %11, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "10") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi9" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28)))) -+ (set (match_operand:SI 10 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 32))))])] -+ "(XVECLEN (operands[0], 0) == 9)" -+ "lmw.bi\t%2, [%1], %10, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "9") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi8" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24)))) -+ (set (match_operand:SI 9 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 28))))])] -+ "(XVECLEN (operands[0], 0) == 8)" -+ "lmw.bi\t%2, [%1], %9, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "8") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi7" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20)))) -+ (set (match_operand:SI 8 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 24))))])] -+ "(XVECLEN (operands[0], 0) == 7)" -+ "lmw.bi\t%2, [%1], %8, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "7") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi6" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16)))) -+ (set (match_operand:SI 7 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 20))))])] -+ "(XVECLEN (operands[0], 0) == 6)" -+ "lmw.bi\t%2, [%1], %7, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "6") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi5" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12)))) -+ (set (match_operand:SI 6 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 16))))])] -+ "(XVECLEN (operands[0], 0) == 5)" -+ "lmw.bi\t%2, [%1], %6, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "5") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi4" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -+ (set (match_operand:SI 5 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 12))))])] -+ "(XVECLEN (operands[0], 0) == 4)" -+ "lmw.bi\t%2, [%1], %5, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "4") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi3" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -+ (set (match_operand:SI 4 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 8))))])] -+ "(XVECLEN (operands[0], 0) == 3)" -+ "lmw.bi\t%2, [%1], %4, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "3") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*lmwsi2" -+ [(match_parallel 0 "nds32_load_multiple_operation" -+ [(set (match_operand:SI 2 "register_operand" "") -+ (mem:SI (match_operand:SI 1 "register_operand" "r"))) -+ (set (match_operand:SI 3 "register_operand" "") -+ (mem:SI (plus:SI (match_dup 1) (const_int 4))))])] -+ "(XVECLEN (operands[0], 0) == 2)" -+ "lmw.bi\t%2, [%1], %3, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "2") -+ (set_attr "length" "4")] -+) -+ -+;; Store Multiple Insns. -+;; -+;; operands[0] is the first memory location. -+;; operands[1] is the first of the consecutive registers. -+;; operands[2] is the number of consecutive registers. -+ -+(define_expand "store_multiple" -+ [(match_par_dup 3 [(set (match_operand:SI 0 "" "") -+ (match_operand:SI 1 "" "")) -+ (use (match_operand:SI 2 "" ""))])] -+ "" -+{ -+ int maximum; -+ -+ /* Because reduced-set regsiters has few registers -+ (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' cannot -+ be used for register allocation), -+ using 8 registers for store_multiple may easily consume all of them. -+ It makes register allocation/spilling hard to work. -+ So we only allow maximum=4 registers for store_multiple -+ under reduced-set registers. */ -+ if (TARGET_REDUCED_REGS) -+ maximum = 4; -+ else -+ maximum = 8; -+ -+ /* Here are the conditions that must be all passed, -+ otherwise we have to FAIL this rtx generation: -+ 1. The number of consecutive registers must be integer. -+ 2. Maximum 4 or 8 registers for smw.bi instruction -+ (based on this nds32-multiple.md design). -+ 3. Minimum 2 registers for smw.bi instruction -+ (based on this nds32-multiple.md design). -+ 4. operands[0] must be memory for sure. -+ 5. operands[1] must be register for sure. -+ 6. operands[0] is not volatile memory access. -+ 7. Do not cross $r15 register because it is not allocatable. */ -+ if (GET_CODE (operands[2]) != CONST_INT -+ || INTVAL (operands[2]) > maximum -+ || INTVAL (operands[2]) < 2 -+ || GET_CODE (operands[0]) != MEM -+ || GET_CODE (operands[1]) != REG -+ || MEM_VOLATILE_P (operands[0]) -+ || REGNO (operands[1]) + INTVAL (operands[2]) > TA_REGNUM) -+ FAIL; -+ -+ /* For (mem addr), we force_reg on addr here, -+ so that nds32_expand_store_multiple can easily use it. */ -+ operands[3] = nds32_expand_store_multiple (REGNO (operands[1]), -+ INTVAL (operands[2]), -+ force_reg (SImode, -+ XEXP (operands[0], 0)), -+ operands[0], -+ false, NULL); -+}) -+ -+;; Ordinary Store Multiple. -+(define_insn "*stm_bim_si25" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 100))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 60))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 64))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 68))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 72))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 76))) -+ (match_operand:SI 22 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 80))) -+ (match_operand:SI 23 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 84))) -+ (match_operand:SI 24 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 88))) -+ (match_operand:SI 25 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 92))) -+ (match_operand:SI 26 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 96))) -+ (match_operand:SI 27 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 26)" -+ "smw.bim\t%3, [%1], %27, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "25") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si24" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 96))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 60))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 64))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 68))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 72))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 76))) -+ (match_operand:SI 22 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 80))) -+ (match_operand:SI 23 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 84))) -+ (match_operand:SI 24 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 88))) -+ (match_operand:SI 25 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 92))) -+ (match_operand:SI 26 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 25)" -+ "smw.bim\t%3, [%1], %26, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "24") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si23" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 92))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 60))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 64))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 68))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 72))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 76))) -+ (match_operand:SI 22 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 80))) -+ (match_operand:SI 23 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 84))) -+ (match_operand:SI 24 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 88))) -+ (match_operand:SI 25 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 24)" -+ "smw.bim\t%3, [%1], %25, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "23") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si22" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 88))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 60))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 64))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 68))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 72))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 76))) -+ (match_operand:SI 22 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 80))) -+ (match_operand:SI 23 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 84))) -+ (match_operand:SI 24 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 23)" -+ "smw.bim\t%3, [%1], %24, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "22") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si21" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 84))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 60))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 64))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 68))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 72))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 76))) -+ (match_operand:SI 22 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 80))) -+ (match_operand:SI 23 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 22)" -+ "smw.bim\t%3, [%1], %23, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "21") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si20" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 80))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 60))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 64))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 68))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 72))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 76))) -+ (match_operand:SI 22 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 21)" -+ "smw.bim\t%3, [%1], %22, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "20") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si19" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 76))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 60))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 64))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 68))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 72))) -+ (match_operand:SI 21 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 20)" -+ "smw.bim\t%3, [%1], %21, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "19") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si18" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 72))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 60))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 64))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 68))) -+ (match_operand:SI 20 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 19)" -+ "smw.bim\t%3, [%1], %20, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "18") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si17" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 68))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 60))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 64))) -+ (match_operand:SI 19 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 18)" -+ "smw.bim\t%3, [%1], %19, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "17") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si16" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 64))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 60))) -+ (match_operand:SI 18 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 17)" -+ "smw.bim\t%3, [%1], %18, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "16") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si15" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 60))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 56))) -+ (match_operand:SI 17 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 16)" -+ "smw.bim\t%3, [%1], %17, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "15") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si14" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 56))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 52))) -+ (match_operand:SI 16 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 15)" -+ "smw.bim\t%3, [%1], %16, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "14") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si13" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 52))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 48))) -+ (match_operand:SI 15 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 14)" -+ "smw.bim\t%3, [%1], %15, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "13") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si12" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 48))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 44))) -+ (match_operand:SI 14 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 13)" -+ "smw.bim\t%3, [%1], %14, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "12") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si11" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 44))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 40))) -+ (match_operand:SI 13 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 12)" -+ "smw.bim\t%3, [%1], %13, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "11") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si10" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 40))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 36))) -+ (match_operand:SI 12 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 11)" -+ "smw.bim\t%3, [%1], %12, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "10") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si9" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 36))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 32))) -+ (match_operand:SI 11 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 10)" -+ "smw.bim\t%3, [%1], %11, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "9") -+ (set_attr "length" "4")] -+) -+ -+ -+(define_insn "*stm_bim_si8" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 32))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 28))) -+ (match_operand:SI 10 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 9)" -+ "smw.bim\t%3, [%1], %10, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "8") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si7" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 28))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 24))) -+ (match_operand:SI 9 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 8)" -+ "smw.bim\t%3, [%1], %9, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "7") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si6" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 24))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 20))) -+ (match_operand:SI 8 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 7)" -+ "smw.bim\t%3, [%1], %8, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "6") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si5" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 20))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16))) -+ (match_operand:SI 7 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 6)" -+ "smw.bim\t%3, [%1], %7, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "5") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si4" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 16))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) -+ (match_operand:SI 6 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 5)" -+ "smw.bim\t%3, [%1], %6, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "4") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si3" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 12))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) -+ (match_operand:SI 5 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 4)" -+ "smw.bim\t%3, [%1], %5, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "3") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stm_bim_si2" -+ [(match_parallel 0 "nds32_store_multiple_and_update_address_operation" -+ [(set (match_operand:SI 1 "register_operand" "=r") -+ (plus:SI (match_operand:SI 2 "register_operand" "1") (const_int 8))) -+ (set (mem:SI (match_dup 2)) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) -+ (match_operand:SI 4 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 3)" -+ "smw.bim\t%3, [%1], %4, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "2") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "unaligned_store_update_base_w" -+ [(parallel [(set (match_operand:SI 0 "register_operand" "=r") -+ (plus:SI (match_operand:SI 1 "register_operand" "0") (const_int 4))) -+ (set (mem:SI (match_dup 1)) -+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")] UNSPEC_UASTORE_W))])] -+ "" -+{ -+ /* 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_w (gen_rtx_MEM (SImode, operands[1]), operands[2])); -+ emit_insn (gen_addsi3 (operands[0], operands[1], gen_int_mode (4, Pmode))); -+ DONE; -+} -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "1") -+ (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")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 60))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 64))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 68))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 72))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 76))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 80))) -+ (match_operand:SI 22 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 84))) -+ (match_operand:SI 23 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 88))) -+ (match_operand:SI 24 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 92))) -+ (match_operand:SI 25 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 96))) -+ (match_operand:SI 26 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 25)" -+ "smw.bi\t%2, [%1], %26, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "25") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stmsi24" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 60))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 64))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 68))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 72))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 76))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 80))) -+ (match_operand:SI 22 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 84))) -+ (match_operand:SI 23 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 88))) -+ (match_operand:SI 24 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 92))) -+ (match_operand:SI 25 "register_operand" "")) -+])] -+ "(XVECLEN (operands[0], 0) == 24)" -+ "smw.bi\t%2, [%1], %25, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "24") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stmsi23" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 60))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 64))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 68))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 72))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 76))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 80))) -+ (match_operand:SI 22 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 84))) -+ (match_operand:SI 23 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 88))) -+ (match_operand:SI 24 "register_operand" "")) -+])] -+ "(XVECLEN (operands[0], 0) == 23)" -+ "smw.bi\t%2, [%1], %24, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "23") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stmsi22" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 60))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 64))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 68))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 72))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 76))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 80))) -+ (match_operand:SI 22 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 84))) -+ (match_operand:SI 23 "register_operand" "")) -+])] -+ "(XVECLEN (operands[0], 0) == 22)" -+ "smw.bi\t%2, [%1], %23, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "22") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stmsi21" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 60))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 64))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 68))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 72))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 76))) -+ (match_operand:SI 21 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 80))) -+ (match_operand:SI 22 "register_operand" "")) -+])] -+ "(XVECLEN (operands[0], 0) == 21)" -+ "smw.bi\t%2, [%1], %22, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "21") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stmsi20" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 60))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 64))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 68))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 72))) -+ (match_operand:SI 20 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 76))) -+ (match_operand:SI 21 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 20)" -+ "smw.bi\t%2, [%1], %21, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "20") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stmsi19" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 60))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 64))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 68))) -+ (match_operand:SI 19 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 72))) -+ (match_operand:SI 20 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 19)" -+ "smw.bi\t%2, [%1], %20, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "19") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "*stmsi18" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 60))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 64))) -+ (match_operand:SI 18 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 68))) -+ (match_operand:SI 19 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 18)" -+ "smw.bi\t%2, [%1], %19, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "18") -+ (set_attr "length" "4")] - ) - --(define_insn "*lmwsi4" -- [(match_parallel 0 "nds32_load_multiple_operation" -- [(set (match_operand:SI 2 "register_operand" "") -- (mem:SI (match_operand:SI 1 "register_operand" "r"))) -- (set (match_operand:SI 3 "register_operand" "") -- (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -- (set (match_operand:SI 4 "register_operand" "") -- (mem:SI (plus:SI (match_dup 1) (const_int 8)))) -- (set (match_operand:SI 5 "register_operand" "") -- (mem:SI (plus:SI (match_dup 1) (const_int 12))))])] -- "(XVECLEN (operands[0], 0) == 4)" -- "lmw.bi\t%2, [%1], %5, 0x0" -- [(set_attr "type" "load") -- (set_attr "length" "4")] -+(define_insn "*stmsi17" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 60))) -+ (match_operand:SI 17 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 64))) -+ (match_operand:SI 18 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 17)" -+ "smw.bi\t%2, [%1], %18, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "17") -+ (set_attr "length" "4")] - ) - --(define_insn "*lmwsi3" -- [(match_parallel 0 "nds32_load_multiple_operation" -- [(set (match_operand:SI 2 "register_operand" "") -- (mem:SI (match_operand:SI 1 "register_operand" "r"))) -- (set (match_operand:SI 3 "register_operand" "") -- (mem:SI (plus:SI (match_dup 1) (const_int 4)))) -- (set (match_operand:SI 4 "register_operand" "") -- (mem:SI (plus:SI (match_dup 1) (const_int 8))))])] -- "(XVECLEN (operands[0], 0) == 3)" -- "lmw.bi\t%2, [%1], %4, 0x0" -- [(set_attr "type" "load") -- (set_attr "length" "4")] -+(define_insn "*stmsi16" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 60))) -+ (match_operand:SI 17 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 16)" -+ "smw.bi\t%2, [%1], %17, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "16") -+ (set_attr "length" "4")] - ) - --(define_insn "*lmwsi2" -- [(match_parallel 0 "nds32_load_multiple_operation" -- [(set (match_operand:SI 2 "register_operand" "") -- (mem:SI (match_operand:SI 1 "register_operand" "r"))) -- (set (match_operand:SI 3 "register_operand" "") -- (mem:SI (plus:SI (match_dup 1) (const_int 4))))])] -- "(XVECLEN (operands[0], 0) == 2)" -- "lmw.bi\t%2, [%1], %3, 0x0" -- [(set_attr "type" "load") -- (set_attr "length" "4")] -+(define_insn "*stmsi15" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 56))) -+ (match_operand:SI 16 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 15)" -+ "smw.bi\t%2, [%1], %16, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "15") -+ (set_attr "length" "4")] - ) - -+(define_insn "*stmsi14" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 52))) -+ (match_operand:SI 15 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 14)" -+ "smw.bi\t%2, [%1], %15, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "14") -+ (set_attr "length" "4")] -+) - --;; Store Multiple Insns. --;; --;; operands[0] is the first memory location. --;; opernads[1] is the first of the consecutive registers. --;; operands[2] is the number of consecutive registers. -- --(define_expand "store_multiple" -- [(match_par_dup 3 [(set (match_operand:SI 0 "" "") -- (match_operand:SI 1 "" "")) -- (use (match_operand:SI 2 "" ""))])] -- "" --{ -- int maximum; -+(define_insn "*stmsi13" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 48))) -+ (match_operand:SI 14 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 13)" -+ "smw.bi\t%2, [%1], %14, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "13") -+ (set_attr "length" "4")] -+) - -- /* Because reduced-set regsiters has few registers -- (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' cannot -- be used for register allocation), -- using 8 registers for store_multiple may easily consume all of them. -- It makes register allocation/spilling hard to work. -- So we only allow maximum=4 registers for store_multiple -- under reduced-set registers. */ -- if (TARGET_REDUCED_REGS) -- maximum = 4; -- else -- maximum = 8; -+(define_insn "*stmsi12" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) -+ (match_operand:SI 13 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 12)" -+ "smw.bi\t%2, [%1], %13, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "12") -+ (set_attr "length" "4")] -+) - -- /* Here are the conditions that must be all passed, -- otherwise we have to FAIL this rtx generation: -- 1. The number of consecutive registers must be integer. -- 2. Maximum 4 or 8 registers for smw.bi instruction -- (based on this nds32-multiple.md design). -- 3. Minimum 2 registers for smw.bi instruction -- (based on this nds32-multiple.md design). -- 4. operands[0] must be memory for sure. -- 5. operands[1] must be register for sure. -- 6. Do not cross $r15 register because it is not allocatable. */ -- if (GET_CODE (operands[2]) != CONST_INT -- || INTVAL (operands[2]) > maximum -- || INTVAL (operands[2]) < 2 -- || GET_CODE (operands[0]) != MEM -- || GET_CODE (operands[1]) != REG -- || REGNO (operands[1]) + INTVAL (operands[2]) > TA_REGNUM) -- FAIL; -+(define_insn "*stmsi11" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) -+ (match_operand:SI 12 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 11)" -+ "smw.bi\t%2, [%1], %12, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "11") -+ (set_attr "length" "4")] -+) - -- /* For (mem addr), we force_reg on addr here, -- so that nds32_expand_store_multiple can easily use it. */ -- operands[3] = nds32_expand_store_multiple (REGNO (operands[1]), -- INTVAL (operands[2]), -- force_reg (SImode, -- XEXP (operands[0], 0)), -- operands[0]); --}) -+(define_insn "*stmsi10" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) -+ (match_operand:SI 11 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 10)" -+ "smw.bi\t%2, [%1], %11, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "10") -+ (set_attr "length" "4")] -+) - --;; Ordinary Store Multiple. -+(define_insn "*stmsi9" -+ [(match_parallel 0 "nds32_store_multiple_operation" -+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) -+ (match_operand:SI 2 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) -+ (match_operand:SI 3 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) -+ (match_operand:SI 4 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) -+ (match_operand:SI 5 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) -+ (match_operand:SI 6 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) -+ (match_operand:SI 7 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) -+ (match_operand:SI 8 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) -+ (match_operand:SI 9 "register_operand" "")) -+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) -+ (match_operand:SI 10 "register_operand" ""))])] -+ "(XVECLEN (operands[0], 0) == 9)" -+ "smw.bi\t%2, [%1], %10, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "9") -+ (set_attr "length" "4")] -+) - - (define_insn "*stmsi8" - [(match_parallel 0 "nds32_store_multiple_operation" -@@ -276,8 +3634,9 @@ - (match_operand:SI 9 "register_operand" ""))])] - "(XVECLEN (operands[0], 0) == 8)" - "smw.bi\t%2, [%1], %9, 0x0" -- [(set_attr "type" "store") -- (set_attr "length" "4")] -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "8") -+ (set_attr "length" "4")] - ) - - (define_insn "*stmsi7" -@@ -298,8 +3657,9 @@ - (match_operand:SI 8 "register_operand" ""))])] - "(XVECLEN (operands[0], 0) == 7)" - "smw.bi\t%2, [%1], %8, 0x0" -- [(set_attr "type" "store") -- (set_attr "length" "4")] -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "7") -+ (set_attr "length" "4")] - ) - - (define_insn "*stmsi6" -@@ -318,8 +3678,9 @@ - (match_operand:SI 7 "register_operand" ""))])] - "(XVECLEN (operands[0], 0) == 6)" - "smw.bi\t%2, [%1], %7, 0x0" -- [(set_attr "type" "store") -- (set_attr "length" "4")] -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "6") -+ (set_attr "length" "4")] - ) - - (define_insn "*stmsi5" -@@ -336,8 +3697,9 @@ - (match_operand:SI 6 "register_operand" ""))])] - "(XVECLEN (operands[0], 0) == 5)" - "smw.bi\t%2, [%1], %6, 0x0" -- [(set_attr "type" "store") -- (set_attr "length" "4")] -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "5") -+ (set_attr "length" "4")] - ) - - (define_insn "*stmsi4" -@@ -352,8 +3714,9 @@ - (match_operand:SI 5 "register_operand" ""))])] - "(XVECLEN (operands[0], 0) == 4)" - "smw.bi\t%2, [%1], %5, 0x0" -- [(set_attr "type" "store") -- (set_attr "length" "4")] -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "4") -+ (set_attr "length" "4")] - ) - - (define_insn "*stmsi3" -@@ -366,8 +3729,9 @@ - (match_operand:SI 4 "register_operand" ""))])] - "(XVECLEN (operands[0], 0) == 3)" - "smw.bi\t%2, [%1], %4, 0x0" -- [(set_attr "type" "store") -- (set_attr "length" "4")] -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "3") -+ (set_attr "length" "4")] - ) - - (define_insn "*stmsi2" -@@ -378,8 +3742,9 @@ - (match_operand:SI 3 "register_operand" ""))])] - "(XVECLEN (operands[0], 0) == 2)" - "smw.bi\t%2, [%1], %3, 0x0" -- [(set_attr "type" "store") -- (set_attr "length" "4")] -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "2") -+ (set_attr "length" "4")] - ) - - ;; Move a block of memory if it is word aligned and MORE than 2 words long. -@@ -391,14 +3756,14 @@ - ;; operands[2] is the number of bytes to move. - ;; operands[3] is the known shared alignment. - --(define_expand "movmemqi" -+(define_expand "movmemsi" - [(match_operand:BLK 0 "general_operand" "") - (match_operand:BLK 1 "general_operand" "") -- (match_operand:SI 2 "const_int_operand" "") -+ (match_operand:SI 2 "nds32_reg_constant_operand" "") - (match_operand:SI 3 "const_int_operand" "")] - "" - { -- if (nds32_expand_movmemqi (operands[0], -+ if (nds32_expand_movmemsi (operands[0], - operands[1], - operands[2], - operands[3])) -@@ -408,3 +3773,75 @@ - }) - - ;; ------------------------------------------------------------------------ -+ -+(define_insn "lmwzb" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (plus:SI (match_operand:SI 1 "register_operand" "0") (const_int 4))) -+ (set (match_operand:SI 2 "register_operand" "=r") -+ (unspec:SI [(mem:SI (match_dup 1))] UNSPEC_LMWZB))] -+ "" -+ "lmwzb.bm\t%2, [%1], %2, 0x0" -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "1") -+ (set_attr "length" "4")] -+) -+ -+(define_insn "smwzb" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (plus:SI (match_operand:SI 1 "register_operand" "0") (const_int 4))) -+ (set (mem:SI (match_dup 1)) -+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")] UNSPEC_SMWZB))] -+ "" -+ "smwzb.bm\t%2, [%1], %2, 0x0" -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "1") -+ (set_attr "length" "4")] -+) -+ -+(define_expand "movstr" -+ [(match_operand:SI 0 "register_operand" "") -+ (match_operand:BLK 1 "memory_operand" "") -+ (match_operand:BLK 2 "memory_operand" "")] -+ "TARGET_EXT_STRING && TARGET_INLINE_STRCPY" -+{ -+ if (nds32_expand_movstr (operands[0], -+ operands[1], -+ operands[2])) -+ DONE; -+ -+ FAIL; -+}) -+ -+(define_expand "strlensi" -+ [(match_operand:SI 0 "register_operand") -+ (match_operand:BLK 1 "memory_operand") -+ (match_operand:QI 2 "nds32_reg_constant_operand") -+ (match_operand 3 "const_int_operand")] -+ "TARGET_EXT_STRING" -+{ -+ if (nds32_expand_strlen (operands[0], operands[1], operands[2], operands[3])) -+ DONE; -+ -+ FAIL; -+}) -+ -+(define_expand "setmemsi" -+ [(use (match_operand:BLK 0 "memory_operand")) -+ (use (match_operand:SI 1 "nds32_reg_constant_operand")) -+ (use (match_operand:QI 2 "nonmemory_operand")) -+ (use (match_operand 3 "const_int_operand")) -+ (use (match_operand:SI 4 "const_int_operand")) -+ (use (match_operand:SI 5 "const_int_operand"))] -+ "" -+{ -+ if (nds32_expand_setmem (operands[0], operands[1], -+ operands[2], operands[3], -+ operands[4], operands[5])) -+ DONE; -+ -+ FAIL; -+}) -+ -+ -+ -+;; ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/nds32-n10.md b/gcc/config/nds32/nds32-n10.md -new file mode 100644 -index 0000000..7261608 ---- /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-2016 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 0000000..622480d ---- /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-2016 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-n7.md b/gcc/config/nds32/nds32-n7.md -new file mode 100644 -index 0000000..ff788ce ---- /dev/null -+++ b/gcc/config/nds32/nds32-n7.md -@@ -0,0 +1,298 @@ -+;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler -+;; Copyright (C) 2012-2016 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 N8 pipeline settings. -+;; ------------------------------------------------------------------------ -+ -+(define_automaton "nds32_n7_machine") -+ -+;; ------------------------------------------------------------------------ -+;; Pipeline Stages -+;; ------------------------------------------------------------------------ -+;; IF - Instruction Fetch -+;; Instruction Alignment -+;; Instruction Pre-decode -+;; II - Instruction Issue -+;; Instruction Decode -+;; Register File Access -+;; Instruction Execution -+;; Interrupt Handling -+;; EXD - Psuedo Stage -+;; Load Data Completion -+ -+(define_cpu_unit "n7_ii" "nds32_n7_machine") -+ -+(define_insn_reservation "nds_n7_unknown" 1 -+ (and (eq_attr "type" "unknown") -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii") -+ -+(define_insn_reservation "nds_n7_misc" 1 -+ (and (eq_attr "type" "misc") -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii") -+ -+(define_insn_reservation "nds_n7_alu" 1 -+ (and (eq_attr "type" "alu") -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii") -+ -+(define_insn_reservation "nds_n7_load" 1 -+ (and (match_test "nds32::load_single_p (insn)") -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii") -+ -+(define_insn_reservation "nds_n7_store" 1 -+ (and (match_test "nds32::store_single_p (insn)") -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii") -+ -+(define_insn_reservation "nds_n7_load_multiple_1" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii") -+ -+(define_insn_reservation "nds_n7_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" "n7")) -+ "n7_ii*2") -+ -+(define_insn_reservation "nds_n7_load_multiple_3" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*3") -+ -+(define_insn_reservation "nds_n7_load_multiple_4" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*4") -+ -+(define_insn_reservation "nds_n7_load_multiple_5" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*5") -+ -+(define_insn_reservation "nds_n7_load_multiple_6" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "6")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*6") -+ -+(define_insn_reservation "nds_n7_load_multiple_7" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*7") -+ -+(define_insn_reservation "nds_n7_load_multiple_8" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*8") -+ -+(define_insn_reservation "nds_n7_load_multiple_12" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*12") -+ -+(define_insn_reservation "nds_n7_store_multiple_1" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii") -+ -+(define_insn_reservation "nds_n7_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" "n7")) -+ "n7_ii*2") -+ -+(define_insn_reservation "nds_n7_store_multiple_3" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*3") -+ -+(define_insn_reservation "nds_n7_store_multiple_4" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*4") -+ -+(define_insn_reservation "nds_n7_store_multiple_5" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*5") -+ -+(define_insn_reservation "nds_n7_store_multiple_6" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "6")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*6") -+ -+(define_insn_reservation "nds_n7_store_multiple_7" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*7") -+ -+(define_insn_reservation "nds_n7_store_multiple_8" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*8") -+ -+(define_insn_reservation "nds_n7_store_multiple_12" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*12") -+ -+(define_insn_reservation "nds_n7_mul_fast" 1 -+ (and (match_test "nds32_mul_config != MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n7"))) -+ "n7_ii") -+ -+(define_insn_reservation "nds_n7_mul_slow" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n7"))) -+ "n7_ii*17") -+ -+(define_insn_reservation "nds_n7_mac_fast" 1 -+ (and (match_test "nds32_mul_config != MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n7"))) -+ "n7_ii*2") -+ -+(define_insn_reservation "nds_n7_mac_slow" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n7"))) -+ "n7_ii*18") -+ -+(define_insn_reservation "nds_n7_div" 1 -+ (and (eq_attr "type" "div") -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii*37") -+ -+(define_insn_reservation "nds_n7_branch" 1 -+ (and (eq_attr "type" "branch") -+ (eq_attr "pipeline_model" "n7")) -+ "n7_ii") -+ -+;; ------------------------------------------------------------------------ -+;; Comment Notations and Bypass Rules -+;; ------------------------------------------------------------------------ -+;; Producers (LHS) -+;; LD_!bi -+;; Load data from the memory (without updating the base register) and -+;; produce the loaded data. The result is ready at EXD. -+;; 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 EXD. If the base register should be -+;; updated, an extra micro-operation is inserted to the sequence, and the -+;; result is ready at II. -+;; -+;; Consumers (RHS) -+;; ALU, MUL, DIV -+;; Require operands at II. -+;; MOVD44_E -+;; A double-word move instruction needs two micro-operations because the -+;; reigster ports is 2R1W. The first micro-operation writes an even number -+;; register, and the second micro-operation writes an odd number register. -+;; Each input operand is required at II for each micro-operation. The letter -+;; 'E' stands for even. -+;; MAC_RaRb -+;; A MAC instruction is separated into two micro-operations. The first -+;; micro-operation does the multiplication, which requires operands Ra -+;; and Rb at II. The second micro-options does the accumulation, which -+;; requires the operand Rt at II. -+;; ADDR_IN_MOP(N) -+;; Because the reigster port is 2R1W, some load/store instructions are -+;; separated into many micro-operations. N denotes the address input is -+;; required by the N-th micro-operation. Such operand is required at II. -+;; ST_bi -+;; A post-increment store instruction requires its data at II. -+;; ST_!bi_RI -+;; A store instruction with an immediate offset requires its data at II. -+;; If the offset field is a register (ST_!bi_RR), the instruction will be -+;; separated into two micro-operations, and the second one requires the -+;; input operand at II in order to store it to the memory. -+;; SMW(N, M) -+;; There are N micro-operations within an instruction that stores multiple -+;; words. Each M-th micro-operation requires its data at II. If the base -+;; register should be updated, an extra micro-operation is inserted to the -+;; sequence. -+;; BR_COND -+;; If a branch instruction is conditional, its input data is required at II. -+ -+;; LD_!bi -+;; -> ALU, MOVD44_E, MUL, MAC_RaRb, DIV, BR, ADDR_IN_MOP(1), ST_bi, ST_!bi_RI, SMW(N, 1) -+(define_bypass 2 -+ "nds_n7_load" -+ "nds_n7_alu,\ -+ nds_n7_mul_fast, nds_n7_mul_slow,\ -+ nds_n7_mac_fast, nds_n7_mac_slow,\ -+ nds_n7_div,\ -+ nds_n7_branch,\ -+ nds_n7_load, nds_n7_store,\ -+ nds_n7_load_multiple_1,nds_n7_load_multiple_2, nds_n7_load_multiple_3,\ -+ nds_n7_load_multiple_4,nds_n7_load_multiple_5, nds_n7_load_multiple_6,\ -+ nds_n7_load_multiple_7,nds_n7_load_multiple_8, nds_n7_load_multiple_12,\ -+ nds_n7_store_multiple_1,nds_n7_store_multiple_2, nds_n7_store_multiple_3,\ -+ nds_n7_store_multiple_4,nds_n7_store_multiple_5, nds_n7_store_multiple_6,\ -+ nds_n7_store_multiple_7,nds_n7_store_multiple_8, nds_n7_store_multiple_12" -+ "nds32_n7_load_to_ii_p" -+) -+ -+;; LMW(N, N) -+;; -> ALU, MOVD44_E, MUL, MAC_RaRb, DIV, BR, AADR_IN_MOP(1), ST_bi, ST_!bi_RI, SMW(N, 1) -+(define_bypass 2 -+ "nds_n7_load_multiple_1,nds_n7_load_multiple_2, nds_n7_load_multiple_3,\ -+ nds_n7_load_multiple_4,nds_n7_load_multiple_5, nds_n7_load_multiple_6,\ -+ nds_n7_load_multiple_7,nds_n7_load_multiple_8, nds_n7_load_multiple_12" -+ "nds_n7_alu,\ -+ nds_n7_mul_fast, nds_n7_mul_slow,\ -+ nds_n7_mac_fast, nds_n7_mac_slow,\ -+ nds_n7_div,\ -+ nds_n7_branch,\ -+ nds_n7_load, nds_n7_store,\ -+ nds_n7_load_multiple_1,nds_n7_load_multiple_2, nds_n7_load_multiple_3,\ -+ nds_n7_load_multiple_4,nds_n7_load_multiple_5, nds_n7_load_multiple_6,\ -+ nds_n7_load_multiple_7,nds_n7_load_multiple_8, nds_n7_load_multiple_12,\ -+ nds_n7_store_multiple_1,nds_n7_store_multiple_2, nds_n7_store_multiple_3,\ -+ nds_n7_store_multiple_4,nds_n7_store_multiple_5, nds_n7_store_multiple_6,\ -+ nds_n7_store_multiple_7,nds_n7_store_multiple_8, nds_n7_store_multiple_12" -+ "nds32_n7_last_load_to_ii_p" -+) -diff --git a/gcc/config/nds32/nds32-n8.md b/gcc/config/nds32/nds32-n8.md -new file mode 100644 -index 0000000..c3db9cd ---- /dev/null -+++ b/gcc/config/nds32/nds32-n8.md -@@ -0,0 +1,389 @@ -+;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler -+;; Copyright (C) 2012-2016 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 N8 pipeline settings. -+;; ------------------------------------------------------------------------ -+ -+(define_automaton "nds32_n8_machine") -+ -+;; ------------------------------------------------------------------------ -+;; Pipeline Stages -+;; ------------------------------------------------------------------------ -+;; IF - Instruction Fetch -+;; II - Instruction Issue / Address Generation -+;; EX - Instruction Execution -+;; EXD - Psuedo Stage / Load Data Completion -+ -+(define_cpu_unit "n8_ii" "nds32_n8_machine") -+(define_cpu_unit "n8_ex" "nds32_n8_machine") -+ -+(define_insn_reservation "nds_n8_unknown" 1 -+ (and (eq_attr "type" "unknown") -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, n8_ex") -+ -+(define_insn_reservation "nds_n8_misc" 1 -+ (and (eq_attr "type" "misc") -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, n8_ex") -+ -+(define_insn_reservation "nds_n8_alu" 1 -+ (and (eq_attr "type" "alu") -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, n8_ex") -+ -+(define_insn_reservation "nds_n8_load" 1 -+ (and (match_test "nds32::load_single_p (insn)") -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, n8_ex") -+ -+(define_insn_reservation "nds_n8_store" 1 -+ (and (match_test "nds32::store_single_p (insn)") -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, n8_ex") -+ -+(define_insn_reservation "nds_n8_load_multiple_1" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, n8_ex") -+ -+(define_insn_reservation "nds_n8_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" "n8")) -+ "n8_ii, n8_ii+n8_ex, n8_ex") -+ -+(define_insn_reservation "nds_n8_load_multiple_3" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*2, n8_ex") -+ -+(define_insn_reservation "nds_n8_load_multiple_4" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*3, n8_ex") -+ -+(define_insn_reservation "nds_n8_load_multiple_5" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*4, n8_ex") -+ -+(define_insn_reservation "nds_n8_load_multiple_6" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "6")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*5, n8_ex") -+ -+(define_insn_reservation "nds_n8_load_multiple_7" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*6, n8_ex") -+ -+(define_insn_reservation "nds_n8_load_multiple_8" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*7, n8_ex") -+ -+(define_insn_reservation "nds_n8_load_multiple_12" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*11, n8_ex") -+ -+(define_insn_reservation "nds_n8_store_multiple_1" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, n8_ex") -+ -+(define_insn_reservation "nds_n8_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" "n8")) -+ "n8_ii, n8_ii+n8_ex, n8_ex") -+ -+(define_insn_reservation "nds_n8_store_multiple_3" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*2, n8_ex") -+ -+(define_insn_reservation "nds_n8_store_multiple_4" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*3, n8_ex") -+ -+(define_insn_reservation "nds_n8_store_multiple_5" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*4, n8_ex") -+ -+(define_insn_reservation "nds_n8_store_multiple_6" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "6")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*5, n8_ex") -+ -+(define_insn_reservation "nds_n8_store_multiple_7" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*6, n8_ex") -+ -+(define_insn_reservation "nds_n8_store_multiple_8" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*7, n8_ex") -+ -+(define_insn_reservation "nds_n8_store_multiple_12" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*11, n8_ex") -+ -+(define_insn_reservation "nds_n8_mul_fast" 1 -+ (and (match_test "nds32_mul_config != MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n8"))) -+ "n8_ii, n8_ex") -+ -+(define_insn_reservation "nds_n8_mul_slow" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n8"))) -+ "n8_ii, n8_ex*16") -+ -+(define_insn_reservation "nds_n8_mac_fast" 1 -+ (and (match_test "nds32_mul_config != MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n8"))) -+ "n8_ii, n8_ii+n8_ex, n8_ex") -+ -+(define_insn_reservation "nds_n8_mac_slow" 1 -+ (and (match_test "nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n8"))) -+ "n8_ii, (n8_ii+n8_ex)*16, n8_ex") -+ -+(define_insn_reservation "nds_n8_div" 1 -+ (and (eq_attr "type" "div") -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, (n8_ii+n8_ex)*36, n8_ex") -+ -+(define_insn_reservation "nds_n8_branch" 1 -+ (and (eq_attr "type" "branch") -+ (eq_attr "pipeline_model" "n8")) -+ "n8_ii, n8_ex") -+ -+;; ------------------------------------------------------------------------ -+;; Comment Notations and Bypass Rules -+;; ------------------------------------------------------------------------ -+;; Producers (LHS) -+;; LD_!bi -+;; Load data from the memory (without updating the base register) and -+;; produce the loaded data. The result is ready at EXD. -+;; LD_bi -+;; Load data from the memory (with updating the base register) and -+;; produce the loaded data. The result is ready at EXD. Because the -+;; register port is 2R1W, two micro-operations are required in order -+;; to write two registers. The base register is updated by the second -+;; micro-operation and the result is ready at EX. -+;; 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 EXD. If the base register should be -+;; updated, an extra micro-operation is inserted to the sequence, and the -+;; result is ready at EX. -+;; ADDR_OUT -+;; Most load/store instructions can produce an address output if updating -+;; the base register is required. The result is ready at EX, which is -+;; produced by ALU. -+;; ALU, MUL, MAC -+;; The result is ready at EX. -+;; MOVD44_O -+;; A double-word move instruction needs to write registers twice. Because -+;; the register port is 2R1W, two micro-operations are required. The even -+;; number reigster is updated by the first one, and the odd number register -+;; is updated by the second one. Each of the results is ready at EX. -+;; The letter 'O' stands for odd. -+;; DIV_Rs -+;; A division instruction saves the quotient result to Rt and saves the -+;; remainder result to Rs. It requires two micro-operations because the -+;; register port is 2R1W. The first micro-operation writes to Rt, and -+;; the seconde one writes to Rs. Each of the results is ready at EX. -+;; -+;; Consumers (RHS) -+;; ALU, MUL, DIV -+;; Require operands at EX. -+;; MOVD44_E -+;; The letter 'E' stands for even, which is accessed by the first micro- -+;; operation and a movd44 instruction. The operand is required at EX. -+;; MAC_RaRb -+;; A MAC instruction is separated into two micro-operations. The first -+;; micro-operation does the multiplication, which requires operands Ra -+;; and Rb at EX. The second micro-options does the accumulation, which -+;; requires the operand Rt at EX. -+;; ADDR_IN_MOP(N) -+;; Because the reigster port is 2R1W, some load/store instructions are -+;; separated into many micro-operations. N denotes the address input is -+;; required by the N-th micro-operation. Such operand is required at II. -+;; ST_bi -+;; A post-increment store instruction requires its data at EX. -+;; ST_!bi_RI -+;; A store instruction with an immediate offset requires its data at EX. -+;; If the offset field is a register (ST_!bi_RR), the instruction will be -+;; separated into two micro-operations, and the second one requires the -+;; input operand at EX in order to store it to the memory. -+;; SMW(N, M) -+;; There are N micro-operations within an instruction that stores multiple -+;; words. Each M-th micro-operation requires its data at EX. If the base -+;; register should be updated, an extra micro-operation is inserted to the -+;; sequence. -+;; BR_COND -+;; If a branch instruction is conditional, its input data is required at EX. -+ -+;; LD_!bi -> ADDR_IN_MOP(1) -+(define_bypass 3 -+ "nds_n8_load" -+ "nds_n8_branch,\ -+ nds_n8_load, nds_n8_store,\ -+ nds_n8_load_multiple_1,nds_n8_load_multiple_2, nds_n8_load_multiple_3,\ -+ nds_n8_load_multiple_4,nds_n8_load_multiple_5, nds_n8_load_multiple_6,\ -+ nds_n8_load_multiple_7,nds_n8_load_multiple_8, nds_n8_load_multiple_12,\ -+ nds_n8_store_multiple_1,nds_n8_store_multiple_2, nds_n8_store_multiple_3,\ -+ nds_n8_store_multiple_4,nds_n8_store_multiple_5, nds_n8_store_multiple_6,\ -+ nds_n8_store_multiple_7,nds_n8_store_multiple_8, nds_n8_store_multiple_12" -+ "nds32_n8_load_to_ii_p" -+) -+ -+;; LMW(N, N) -> ADDR_IN_MOP(1) -+(define_bypass 3 -+ "nds_n8_load_multiple_1,nds_n8_load_multiple_2, nds_n8_load_multiple_3,\ -+ nds_n8_load_multiple_4,nds_n8_load_multiple_5, nds_n8_load_multiple_6,\ -+ nds_n8_load_multiple_7,nds_n8_load_multiple_8, nds_n8_load_multiple_12" -+ "nds_n8_branch,\ -+ nds_n8_load, nds_n8_store,\ -+ nds_n8_load_multiple_1,nds_n8_load_multiple_2, nds_n8_load_multiple_3,\ -+ nds_n8_load_multiple_4,nds_n8_load_multiple_5, nds_n8_load_multiple_6,\ -+ nds_n8_load_multiple_7,nds_n8_load_multiple_8, nds_n8_load_multiple_12,\ -+ nds_n8_store_multiple_1,nds_n8_store_multiple_2, nds_n8_store_multiple_3,\ -+ nds_n8_store_multiple_4,nds_n8_store_multiple_5, nds_n8_store_multiple_6,\ -+ nds_n8_store_multiple_7,nds_n8_store_multiple_8, nds_n8_store_multiple_12" -+ "nds32_n8_last_load_to_ii_p" -+) -+ -+;; LMW(N, N - 1) -> ADDR_IN_MOP(1) -+(define_bypass 2 -+ "nds_n8_load_multiple_1,nds_n8_load_multiple_2, nds_n8_load_multiple_3,\ -+ nds_n8_load_multiple_4,nds_n8_load_multiple_5, nds_n8_load_multiple_6,\ -+ nds_n8_load_multiple_7,nds_n8_load_multiple_8, nds_n8_load_multiple_12" -+ "nds_n8_branch,\ -+ nds_n8_load, nds_n8_store,\ -+ nds_n8_load_multiple_1,nds_n8_load_multiple_2, nds_n8_load_multiple_3,\ -+ nds_n8_load_multiple_4,nds_n8_load_multiple_5, nds_n8_load_multiple_6,\ -+ nds_n8_load_multiple_7,nds_n8_load_multiple_8, nds_n8_load_multiple_12,\ -+ nds_n8_store_multiple_1,nds_n8_store_multiple_2, nds_n8_store_multiple_3,\ -+ nds_n8_store_multiple_4,nds_n8_store_multiple_5, nds_n8_store_multiple_6,\ -+ nds_n8_store_multiple_7,nds_n8_store_multiple_8, nds_n8_store_multiple_12" -+ "nds32_n8_last_load_two_to_ii_p" -+) -+ -+;; LD_bi -> ADDR_IN_MOP(1) -+(define_bypass 2 -+ "nds_n8_load" -+ "nds_n8_branch,\ -+ nds_n8_load, nds_n8_store,\ -+ nds_n8_load_multiple_1,nds_n8_load_multiple_2, nds_n8_load_multiple_3,\ -+ nds_n8_load_multiple_4,nds_n8_load_multiple_5, nds_n8_load_multiple_6,\ -+ nds_n8_load_multiple_7,nds_n8_load_multiple_8, nds_n8_load_multiple_12,\ -+ nds_n8_store_multiple_1,nds_n8_store_multiple_2, nds_n8_store_multiple_3,\ -+ nds_n8_store_multiple_4,nds_n8_store_multiple_5, nds_n8_store_multiple_6,\ -+ nds_n8_store_multiple_7,nds_n8_store_multiple_8, nds_n8_store_multiple_12" -+ "nds32_n8_load_bi_to_ii_p" -+) -+ -+;; LD_!bi -> ALU, MOVD44_E, MUL, MAC_RaRb, DIV, BR_COND, ST_bi, ST_!bi_RI, SMW(N, 1) -+(define_bypass 2 -+ "nds_n8_load" -+ "nds_n8_alu, -+ nds_n8_mul_fast, nds_n8_mul_slow,\ -+ nds_n8_mac_fast, nds_n8_mac_slow,\ -+ nds_n8_div,\ -+ nds_n8_branch,\ -+ nds_n8_store,\ -+ nds_n8_store_multiple_1,nds_n8_store_multiple_2, nds_n8_store_multiple_3,\ -+ nds_n8_store_multiple_4,nds_n8_store_multiple_5, nds_n8_store_multiple_6,\ -+ nds_n8_store_multiple_7,nds_n8_store_multiple_8, nds_n8_store_multiple_12" -+ "nds32_n8_load_to_ex_p" -+) -+ -+;; ALU, MOVD44_O, MUL, MAC, DIV_Rs, LD_bi, ADDR_OUT -> ADDR_IN_MOP(1) -+(define_bypass 2 -+ "nds_n8_alu, -+ nds_n8_mul_fast, nds_n8_mul_slow,\ -+ nds_n8_mac_fast, nds_n8_mac_slow,\ -+ nds_n8_div,\ -+ nds_n8_load, nds_n8_store,\ -+ nds_n8_load_multiple_1,nds_n8_load_multiple_2, nds_n8_load_multiple_3,\ -+ nds_n8_load_multiple_4,nds_n8_load_multiple_5, nds_n8_load_multiple_6,\ -+ nds_n8_load_multiple_7,nds_n8_load_multiple_8, nds_n8_load_multiple_12,\ -+ nds_n8_store_multiple_1,nds_n8_store_multiple_2, nds_n8_store_multiple_3,\ -+ nds_n8_store_multiple_4,nds_n8_store_multiple_5, nds_n8_store_multiple_6,\ -+ nds_n8_store_multiple_7,nds_n8_store_multiple_8, nds_n8_store_multiple_12" -+ "nds_n8_branch,\ -+ nds_n8_load, nds_n8_store,\ -+ nds_n8_load_multiple_1,nds_n8_load_multiple_2, nds_n8_load_multiple_3,\ -+ nds_n8_load_multiple_4,nds_n8_load_multiple_5, nds_n8_load_multiple_6,\ -+ nds_n8_load_multiple_7,nds_n8_load_multiple_8, nds_n8_load_multiple_12,\ -+ nds_n8_store_multiple_1,nds_n8_store_multiple_2, nds_n8_store_multiple_3,\ -+ nds_n8_store_multiple_4,nds_n8_store_multiple_5, nds_n8_store_multiple_6,\ -+ nds_n8_store_multiple_7,nds_n8_store_multiple_8, nds_n8_store_multiple_12" -+ "nds32_n8_ex_to_ii_p" -+) -+ -+;; LMW(N, N) -> ALU, MOVD44_E, MUL, MAC_RaRb, DIV, BR_COND, ST_bi, ST_!bi_RI, SMW(N, 1) -+(define_bypass 2 -+ "nds_n8_load_multiple_1,nds_n8_load_multiple_2, nds_n8_load_multiple_3,\ -+ nds_n8_load_multiple_4,nds_n8_load_multiple_5, nds_n8_load_multiple_6,\ -+ nds_n8_load_multiple_7,nds_n8_load_multiple_8, nds_n8_load_multiple_12" -+ "nds_n8_alu, -+ nds_n8_mul_fast, nds_n8_mul_slow,\ -+ nds_n8_mac_fast, nds_n8_mac_slow,\ -+ nds_n8_div,\ -+ nds_n8_branch,\ -+ nds_n8_store,\ -+ nds_n8_store_multiple_1,nds_n8_store_multiple_2, nds_n8_store_multiple_3,\ -+ nds_n8_store_multiple_4,nds_n8_store_multiple_5, nds_n8_store_multiple_6,\ -+ nds_n8_store_multiple_7,nds_n8_store_multiple_8, nds_n8_store_multiple_12" -+ "nds32_n8_last_load_to_ex_p" -+) -diff --git a/gcc/config/nds32/nds32-n9-2r1w.md b/gcc/config/nds32/nds32-n9-2r1w.md -new file mode 100644 -index 0000000..d0db953 ---- /dev/null -+++ b/gcc/config/nds32/nds32-n9-2r1w.md -@@ -0,0 +1,362 @@ -+;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler -+;; Copyright (C) 2012-2016 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 N9 2R1W pipeline settings. -+;; ------------------------------------------------------------------------ -+ -+(define_automaton "nds32_n9_2r1w_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 "n9_2r1w_ii" "nds32_n9_2r1w_machine") -+(define_cpu_unit "n9_2r1w_ex" "nds32_n9_2r1w_machine") -+(define_cpu_unit "n9_2r1w_mm" "nds32_n9_2r1w_machine") -+(define_cpu_unit "n9_2r1w_wb" "nds32_n9_2r1w_machine") -+ -+(define_insn_reservation "nds_n9_2r1w_unknown" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "type" "unknown") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_misc" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "type" "misc") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_mmu" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "type" "mmu") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_alu" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "type" "alu") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_alu_shift" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "type" "alu_shift") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ex+n9_2r1w_mm, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_pbsad" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "type" "pbsad") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex*3, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_pbsada" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "type" "pbsada") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex*3, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_load" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (match_test "nds32::load_single_p (insn)") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_store" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (match_test "nds32::store_single_p (insn)") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_load_multiple_1" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "1")))) -+ "n9_2r1w_ii, n9_2r1w_ex, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_load_multiple_2" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (ior (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "2")) -+ (match_test "nds32::load_double_p (insn)")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ex+n9_2r1w_mm, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_load_multiple_3" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "3")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_load_multiple_4" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "4")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_load_multiple_5" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "5")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, (n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb)*2, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_load_multiple_6" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "6")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, (n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb)*3, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_load_multiple_7" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "7")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, (n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb)*4, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_load_multiple_8" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "8")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, (n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb)*5, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_load_multiple_12" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "12")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, (n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb)*9, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_store_multiple_1" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "1")))) -+ "n9_2r1w_ii, n9_2r1w_ex, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_store_multiple_2" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (ior (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "2")) -+ (match_test "nds32::store_double_p (insn)")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ex+n9_2r1w_mm, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_store_multiple_3" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "3")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_store_multiple_4" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "4")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_store_multiple_5" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "5")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, (n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb)*2, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_store_multiple_6" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "6")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, (n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb)*3, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_store_multiple_7" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "7")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, (n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb)*4, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_store_multiple_8" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "8")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, (n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb)*5, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_store_multiple_12" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "12")))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm, (n9_2r1w_ii+n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb)*9, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_mul_fast" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W && nds32_mul_config != MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_mul_slow" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W && nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex*17, n9_2r1w_mm, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_mac_fast" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W && nds32_mul_config != MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ii+n9_2r1w_ex, n9_2r1w_ex+n9_2r1w_mm, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_mac_slow" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W && nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, (n9_2r1w_ii+n9_2r1w_ex)*17, n9_2r1w_ex+n9_2r1w_mm, n9_2r1w_ex+n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_div" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "type" "div") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, (n9_2r1w_ii+n9_2r1w_ex)*34, n9_2r1w_ex+n9_2r1w_mm, n9_2r1w_mm+n9_2r1w_wb, n9_2r1w_wb") -+ -+(define_insn_reservation "nds_n9_2r1w_branch" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_2R1W") -+ (and (eq_attr "type" "branch") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_2r1w_ii, n9_2r1w_ex, n9_2r1w_mm, n9_2r1w_wb") -+ -+;; ------------------------------------------------------------------------ -+;; Comment Notations and Bypass Rules -+;; ------------------------------------------------------------------------ -+;; Producers (LHS) -+;; LD_!bi -+;; Load data from the memory (without updating the base register) and -+;; produce the loaded data. The result is ready at MM. Because the register -+;; port is 2R1W, two micro-operations are required if the base register -+;; should be updated. In this case, the base register is updated by the -+;; second micro-operation, and the updated result is ready at EX. -+;; 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. If the base register should be -+;; updated, an extra micro-operation is apppended to the end of the -+;; sequence, and the result is ready at EX. -+;; 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, 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. -+;; MOVD44_E -+;; A double-word move instruction needs two micro-operations because the -+;; reigster ports is 2R1W. The first micro-operation writes an even number -+;; register, and the second micro-operation writes an odd number register. -+;; Each input operand is required at EX for each micro-operation. MOVD44_E -+;; stands for the first micro-operation. -+;; MAC_RaRb, M2R -+;; MAC instructions do multiplication at EX and do accumulation at MM, but -+;; MAC instructions which operate on general purpose registers always -+;; require operands at EX because MM stage cannot be forwarded in 2R1W mode. -+;; ADDR_IN -+;; If an instruction requires an address as its input operand, the address -+;; is required at EX. -+;; ST_bi -+;; A post-increment store instruction requires its data at EX because MM -+;; cannot be forwarded in 2R1W mode. -+;; ST_!bi_RI -+;; A store instruction with an immediate offset requires its data at EX -+;; because MM cannot be forwarded in 2R1W mode. If the offset field is a -+;; register (ST_!bi_RR), the instruction will be separated into two micro- -+;; operations, and the second one requires the input operand at EX in order -+;; to store it to the memory. -+;; 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. -+ -+;; LD_!bi, MUL, MAC -+;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44_E, MUL, MAC_RaRb, M2R, DIV, ADDR_IN_!bi, ADDR_IN_bi_Ra, ST_bi, ST_!bi_RI, BR, MMU -+(define_bypass 2 -+ "nds_n9_2r1w_load,\ -+ nds_n9_2r1w_mul_fast, nds_n9_2r1w_mul_slow,\ -+ nds_n9_2r1w_mac_fast, nds_n9_2r1w_mac_slow" -+ "nds_n9_2r1w_alu, nds_n9_2r1w_alu_shift,\ -+ nds_n9_2r1w_pbsad, nds_n9_2r1w_pbsada,\ -+ nds_n9_2r1w_mul_fast, nds_n9_2r1w_mul_slow,\ -+ nds_n9_2r1w_mac_fast, nds_n9_2r1w_mac_slow,\ -+ nds_n9_2r1w_branch,\ -+ nds_n9_2r1w_div,\ -+ nds_n9_2r1w_load,nds_n9_2r1w_store,\ -+ nds_n9_2r1w_load_multiple_1,nds_n9_2r1w_load_multiple_2, nds_n9_2r1w_load_multiple_3,\ -+ nds_n9_2r1w_load_multiple_4,nds_n9_2r1w_load_multiple_5, nds_n9_2r1w_load_multiple_6,\ -+ nds_n9_2r1w_load_multiple_7,nds_n9_2r1w_load_multiple_8, nds_n9_2r1w_load_multiple_12,\ -+ nds_n9_2r1w_store_multiple_1,nds_n9_2r1w_store_multiple_2, nds_n9_2r1w_store_multiple_3,\ -+ nds_n9_2r1w_store_multiple_4,nds_n9_2r1w_store_multiple_5, nds_n9_2r1w_store_multiple_6,\ -+ nds_n9_2r1w_store_multiple_7,nds_n9_2r1w_store_multiple_8, nds_n9_2r1w_store_multiple_12,\ -+ nds_n9_2r1w_mmu" -+ "nds32_n9_2r1w_mm_to_ex_p" -+) -+ -+;; LMW(N, N) -+;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44_E, MUL, MAC_RaRb, M2R, DIV, ADDR_IN_!bi, ADDR_IN_bi_Ra, ST_bi, ST_!bi_RI, BR, MMU -+(define_bypass 2 -+ "nds_n9_2r1w_load_multiple_1,nds_n9_2r1w_load_multiple_2, nds_n9_2r1w_load_multiple_3,\ -+ nds_n9_2r1w_load_multiple_4,nds_n9_2r1w_load_multiple_5, nds_n9_2r1w_load_multiple_6,\ -+ nds_n9_2r1w_load_multiple_7,nds_n9_2r1w_load_multiple_8, nds_n9_2r1w_load_multiple_12" -+ "nds_n9_2r1w_alu, nds_n9_2r1w_alu_shift,\ -+ nds_n9_2r1w_pbsad, nds_n9_2r1w_pbsada,\ -+ nds_n9_2r1w_mul_fast, nds_n9_2r1w_mul_slow,\ -+ nds_n9_2r1w_mac_fast, nds_n9_2r1w_mac_slow,\ -+ nds_n9_2r1w_branch,\ -+ nds_n9_2r1w_div,\ -+ nds_n9_2r1w_load,nds_n9_2r1w_store,\ -+ nds_n9_2r1w_load_multiple_1,nds_n9_2r1w_load_multiple_2, nds_n9_2r1w_load_multiple_3,\ -+ nds_n9_2r1w_load_multiple_4,nds_n9_2r1w_load_multiple_5, nds_n9_2r1w_load_multiple_6,\ -+ nds_n9_2r1w_load_multiple_7,nds_n9_2r1w_load_multiple_8, nds_n9_2r1w_load_multiple_12,\ -+ nds_n9_2r1w_store_multiple_1,nds_n9_2r1w_store_multiple_2, nds_n9_2r1w_store_multiple_3,\ -+ nds_n9_2r1w_store_multiple_4,nds_n9_2r1w_store_multiple_5, nds_n9_2r1w_store_multiple_6,\ -+ nds_n9_2r1w_store_multiple_7,nds_n9_2r1w_store_multiple_8, nds_n9_2r1w_store_multiple_12,\ -+ nds_n9_2r1w_mmu" -+ "nds32_n9_last_load_to_ex_p" -+) -diff --git a/gcc/config/nds32/nds32-n9-3r2w.md b/gcc/config/nds32/nds32-n9-3r2w.md -new file mode 100644 -index 0000000..7849c72 ---- /dev/null -+++ b/gcc/config/nds32/nds32-n9-3r2w.md -@@ -0,0 +1,357 @@ -+;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler -+;; Copyright (C) 2012-2016 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 N9 3R2W pipeline settings. -+;; ------------------------------------------------------------------------ -+ -+(define_automaton "nds32_n9_3r2w_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 "n9_3r2w_ii" "nds32_n9_3r2w_machine") -+(define_cpu_unit "n9_3r2w_ex" "nds32_n9_3r2w_machine") -+(define_cpu_unit "n9_3r2w_mm" "nds32_n9_3r2w_machine") -+(define_cpu_unit "n9_3r2w_wb" "nds32_n9_3r2w_machine") -+ -+(define_insn_reservation "nds_n9_3r2w_unknown" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "type" "unknown") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_misc" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "type" "misc") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_mmu" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "type" "mmu") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_alu" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "type" "alu") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_alu_shift" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "type" "alu_shift") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ex+n9_3r2w_mm, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_pbsad" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "type" "pbsad") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex*3, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_pbsada" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "type" "pbsada") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex*3, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_load" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (match_test "nds32::load_single_p (insn)") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_store" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (match_test "nds32::store_single_p (insn)") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_load_multiple_1" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "1")))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_load_multiple_2" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (ior (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "2")) -+ (match_test "nds32::load_double_p (insn)")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ex+n9_3r2w_mm, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_load_multiple_3" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "3")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_load_multiple_4" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "4")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_load_multiple_5" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "5")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, (n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb)*2, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_load_multiple_6" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "6")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, (n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb)*3, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_load_multiple_7" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "7")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, (n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb)*4, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_load_multiple_8" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "8")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, (n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb)*5, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_load_multiple_12" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "12")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, (n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb)*9, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_store_multiple_1" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "1")))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_store_multiple_2" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (ior (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "2")) -+ (match_test "nds32::store_double_p (insn)")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ex+n9_3r2w_mm, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_store_multiple_3" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "3")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_store_multiple_4" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "4")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_store_multiple_5" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "5")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, (n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb)*2, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_store_multiple_6" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "6")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, (n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb)*3, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_store_multiple_7" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "7")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, (n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb)*4, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_store_multiple_8" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "8")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, (n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb)*5, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_store_multiple_12" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "pipeline_model" "n9") -+ (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "12")))) -+ "n9_3r2w_ii, n9_3r2w_ii+n9_3r2w_ex, n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm, (n9_3r2w_ii+n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb)*9, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_mm+n9_3r2w_wb, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_mul_fast1" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W && nds32_mul_config == MUL_TYPE_FAST_1") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_mul_fast2" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W && nds32_mul_config == MUL_TYPE_FAST_2") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex*2, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_mul_slow" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W && nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex*17, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_mac_fast1" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W && nds32_mul_config == MUL_TYPE_FAST_1") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_mac_fast2" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W && nds32_mul_config == MUL_TYPE_FAST_2") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex*2, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_mac_slow" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W && nds32_mul_config == MUL_TYPE_SLOW") -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex*17, n9_3r2w_ex+n9_3r2w_mm, n9_3r2w_ex+n9_3r2w_mm+n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_div" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "type" "div") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex*34, n9_3r2w_mm, n9_3r2w_wb") -+ -+(define_insn_reservation "nds_n9_3r2w_branch" 1 -+ (and (match_test "nds32_register_ports_config == REG_PORT_3R2W") -+ (and (eq_attr "type" "branch") -+ (eq_attr "pipeline_model" "n9"))) -+ "n9_3r2w_ii, n9_3r2w_ex, n9_3r2w_mm, n9_3r2w_wb") -+ -+;; ------------------------------------------------------------------------ -+;; 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. -+ -+;; LD, MUL, MAC, DIV -+;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44, MUL, MAC_RaRb, DIV, ADDR_IN, BR, MMU -+(define_bypass 2 -+ "nds_n9_3r2w_load,\ -+ nds_n9_3r2w_mul_fast1, nds_n9_3r2w_mul_fast2, nds_n9_3r2w_mul_slow,\ -+ nds_n9_3r2w_mac_fast1, nds_n9_3r2w_mac_fast2, nds_n9_3r2w_mac_slow,\ -+ nds_n9_3r2w_div" -+ "nds_n9_3r2w_alu, nds_n9_3r2w_alu_shift,\ -+ nds_n9_3r2w_pbsad, nds_n9_3r2w_pbsada,\ -+ nds_n9_3r2w_mul_fast1, nds_n9_3r2w_mul_fast2, nds_n9_3r2w_mul_slow,\ -+ nds_n9_3r2w_mac_fast1, nds_n9_3r2w_mac_fast2, nds_n9_3r2w_mac_slow,\ -+ nds_n9_3r2w_branch,\ -+ nds_n9_3r2w_div,\ -+ nds_n9_3r2w_load,nds_n9_3r2w_store,\ -+ nds_n9_3r2w_load_multiple_1,nds_n9_3r2w_load_multiple_2, nds_n9_3r2w_load_multiple_3,\ -+ nds_n9_3r2w_load_multiple_4,nds_n9_3r2w_load_multiple_5, nds_n9_3r2w_load_multiple_6,\ -+ nds_n9_3r2w_load_multiple_7,nds_n9_3r2w_load_multiple_8, nds_n9_3r2w_load_multiple_12,\ -+ nds_n9_3r2w_store_multiple_1,nds_n9_3r2w_store_multiple_2, nds_n9_3r2w_store_multiple_3,\ -+ nds_n9_3r2w_store_multiple_4,nds_n9_3r2w_store_multiple_5, nds_n9_3r2w_store_multiple_6,\ -+ nds_n9_3r2w_store_multiple_7,nds_n9_3r2w_store_multiple_8, nds_n9_3r2w_store_multiple_12,\ -+ nds_n9_3r2w_mmu" -+ "nds32_n9_3r2w_mm_to_ex_p" -+) -+ -+;; LMW(N, N) -+;; -> ALU, ALU_SHIFT_Rb, PBSAD, PBSADA_RaRb, MOVD44, MUL, MAC_RaRb, DIV, ADDR_IN, BR, MMU -+(define_bypass 2 -+ "nds_n9_3r2w_load_multiple_1,nds_n9_3r2w_load_multiple_2, nds_n9_3r2w_load_multiple_3,\ -+ nds_n9_3r2w_load_multiple_4,nds_n9_3r2w_load_multiple_5, nds_n9_3r2w_load_multiple_6,\ -+ nds_n9_3r2w_load_multiple_7,nds_n9_3r2w_load_multiple_8, nds_n9_3r2w_load_multiple_12" -+ "nds_n9_3r2w_alu, nds_n9_3r2w_alu_shift,\ -+ nds_n9_3r2w_pbsad, nds_n9_3r2w_pbsada,\ -+ nds_n9_3r2w_mul_fast1, nds_n9_3r2w_mul_fast2, nds_n9_3r2w_mul_slow,\ -+ nds_n9_3r2w_mac_fast1, nds_n9_3r2w_mac_fast2, nds_n9_3r2w_mac_slow,\ -+ nds_n9_3r2w_branch,\ -+ nds_n9_3r2w_div,\ -+ nds_n9_3r2w_load,nds_n9_3r2w_store,\ -+ nds_n9_3r2w_load_multiple_1,nds_n9_3r2w_load_multiple_2, nds_n9_3r2w_load_multiple_3,\ -+ nds_n9_3r2w_load_multiple_4,nds_n9_3r2w_load_multiple_5, nds_n9_3r2w_load_multiple_6,\ -+ nds_n9_3r2w_load_multiple_7,nds_n9_3r2w_load_multiple_8, nds_n9_3r2w_load_multiple_12,\ -+ nds_n9_3r2w_store_multiple_1,nds_n9_3r2w_store_multiple_2, nds_n9_3r2w_store_multiple_3,\ -+ nds_n9_3r2w_store_multiple_4,nds_n9_3r2w_store_multiple_5, nds_n9_3r2w_store_multiple_6,\ -+ nds_n9_3r2w_store_multiple_7,nds_n9_3r2w_store_multiple_8, nds_n9_3r2w_store_multiple_12,\ -+ nds_n9_3r2w_mmu" -+ "nds32_n9_last_load_to_ex_p" -+) -diff --git a/gcc/config/nds32/nds32-opts.h b/gcc/config/nds32/nds32-opts.h -index 25c4081..e4017bb 100644 ---- a/gcc/config/nds32/nds32-opts.h -+++ b/gcc/config/nds32/nds32-opts.h -@@ -22,14 +22,42 @@ - #define NDS32_OPTS_H - - #define NDS32_DEFAULT_CACHE_BLOCK_SIZE 16 --#define NDS32_DEFAULT_ISR_VECTOR_SIZE (TARGET_ISA_V3 ? 4 : 16) -+#define NDS32_DEFAULT_ISR_VECTOR_SIZE TARGET_DEFAULT_ISR_VECTOR_SIZE - - /* The various ANDES ISA. */ - enum nds32_arch_type - { - ARCH_V2, -+ ARCH_V2J, - ARCH_V3, -- ARCH_V3M -+ ARCH_V3J, -+ ARCH_V3M, -+ ARCH_V3M_PLUS, -+ ARCH_V3F, -+ ARCH_V3S -+}; -+ -+/* The various ANDES CPU. */ -+enum nds32_cpu_type -+{ -+ CPU_N6, -+ CPU_N7, -+ CPU_N8, -+ CPU_E8, -+ CPU_N9, -+ CPU_N10, -+ CPU_GRAYWOLF, -+ CPU_N12, -+ CPU_N13, -+ CPU_PANTHER, -+ CPU_SIMPLE -+}; -+ -+/* The code model defines the address generation strategy. */ -+enum nds32_memory_model_type -+{ -+ MEMORY_MODEL_SLOW, -+ MEMORY_MODEL_FAST - }; - - /* The code model defines the address generation strategy. */ -@@ -40,4 +68,56 @@ 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 -+{ -+ MUL_TYPE_FAST_1, -+ MUL_TYPE_FAST_2, -+ MUL_TYPE_SLOW -+}; -+ -+/* Register ports configuration. */ -+enum nds32_register_ports -+{ -+ REG_PORT_3R2W, -+ REG_PORT_2R1W -+}; -+ -+/* Which ABI to use. */ -+enum abi_type -+{ -+ NDS32_ABI_V2, -+ NDS32_ABI_V2_FP_PLUS -+}; -+ -+/* The various FPU number of registers. */ -+enum float_reg_number -+{ -+ NDS32_CONFIG_FPU_0, -+ NDS32_CONFIG_FPU_1, -+ NDS32_CONFIG_FPU_2, -+ NDS32_CONFIG_FPU_3, -+ NDS32_CONFIG_FPU_4, -+ NDS32_CONFIG_FPU_5, -+ NDS32_CONFIG_FPU_6, -+ NDS32_CONFIG_FPU_7 -+}; -+ -+/* Do lmwsmw opt model. */ -+enum lmwsmw_cost_type -+{ -+ LMWSMW_OPT_SIZE, -+ LMWSMW_OPT_SPEED, -+ LMWSMW_OPT_ALL, -+ LMWSMW_OPT_AUTO -+}; -+ - #endif -diff --git a/gcc/config/nds32/nds32-panther.md b/gcc/config/nds32/nds32-panther.md -new file mode 100644 -index 0000000..d45de1c ---- /dev/null -+++ b/gcc/config/nds32/nds32-panther.md -@@ -0,0 +1,446 @@ -+;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler -+;; Copyright (C) 2012-2016 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 Panther pipeline settings. -+;; ------------------------------------------------------------------------ -+ -+(define_automaton "nds32_pn_machine") -+ -+(define_cpu_unit "pn_i3_0" "nds32_pn_machine") -+(define_cpu_unit "pn_i3_1" "nds32_pn_machine") -+(define_cpu_unit "pn_e1_p0" "nds32_pn_machine") -+(define_cpu_unit "pn_e2_p0" "nds32_pn_machine") -+(define_cpu_unit "pn_e3_p0" "nds32_pn_machine") -+(define_cpu_unit "pn_e4_p0" "nds32_pn_machine") -+(define_cpu_unit "pn_wb_p0" "nds32_pn_machine") -+(define_cpu_unit "pn_e1_p1" "nds32_pn_machine") -+(define_cpu_unit "pn_e2_p1" "nds32_pn_machine") -+(define_cpu_unit "pn_e3_p1" "nds32_pn_machine") -+(define_cpu_unit "pn_e4_p1" "nds32_pn_machine") -+(define_cpu_unit "pn_wb_p1" "nds32_pn_machine") -+(define_cpu_unit "pn_e1_p2" "nds32_pn_machine") -+(define_cpu_unit "pn_e2_p2" "nds32_pn_machine") -+(define_cpu_unit "pn_e3_p2" "nds32_pn_machine") -+(define_cpu_unit "pn_e4_p2" "nds32_pn_machine") -+(define_cpu_unit "pn_wb_p2" "nds32_pn_machine") -+ -+(define_reservation "pn_i3" "pn_i3_0 | pn_i3_1") -+(define_reservation "pn_e1" "pn_e1_p0 | pn_e1_p1") -+(define_reservation "pn_e2" "pn_e2_p0 | pn_e2_p1") -+(define_reservation "pn_e3" "pn_e3_p0 | pn_e3_p1") -+(define_reservation "pn_e4" "pn_e4_p0 | pn_e4_p1") -+(define_reservation "pn_wb" "pn_wb_p0 | pn_wb_p1") -+ -+(define_insn_reservation "nds_pn_unknown" 1 -+ (and (eq_attr "type" "unknown") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1, pn_e2, pn_e3, pn_e4, pn_wb") -+ -+(define_insn_reservation "nds_pn_misc" 1 -+ (and (eq_attr "type" "misc") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1, pn_e2, pn_e3, pn_e4, pn_wb") -+ -+(define_insn_reservation "nds_pn_mmu" 1 -+ (and (eq_attr "type" "mmu") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1, pn_e2, pn_e3, pn_e4, pn_wb") -+ -+(define_insn_reservation "nds_pn_movd44" 1 -+ (and (and (and (eq_attr "type" "alu") -+ (eq_attr "subtype" "simple")) -+ (match_test "nds32::movd44_insn_p (insn)")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p1, pn_e2_p1, pn_e3_p1, pn_e4_p1, pn_wb_p1") -+ -+(define_insn_reservation "nds_pn_alu" 1 -+ (and (and (and (eq_attr "type" "alu") -+ (eq_attr "subtype" "simple")) -+ (match_test "!nds32::movd44_insn_p (insn)")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1, pn_e2, pn_e3, pn_e4, pn_wb") -+ -+(define_insn_reservation "nds_pn_shift" 1 -+ (and (and (eq_attr "type" "alu") -+ (eq_attr "subtype" "shift")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1, pn_e2, pn_e3, pn_e4, pn_wb") -+ -+(define_insn_reservation "nds_pn_alu_shift" 1 -+ (and (eq_attr "type" "alu_shift") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1, pn_e2, pn_e3, pn_e4, pn_wb") -+ -+(define_insn_reservation "nds_pn_pbsad" 1 -+ (and (eq_attr "type" "pbsad") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1, pn_e2, pn_e3*2, pn_e4, pn_wb") -+ -+(define_insn_reservation "nds_pn_pbsada" 1 -+ (and (eq_attr "type" "pbsada") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1, pn_e2, pn_e3*3, pn_e4, pn_wb") -+ -+(define_insn_reservation "nds_pn_load_full_word" 1 -+ (and (match_test "nds32::load_full_word_p (insn)") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_load_partial_word" 1 -+ (and (match_test "nds32::load_partial_word_p (insn)") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_store" 1 -+ (and (match_test "nds32::store_single_p (insn)") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_load_multiple_1" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_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" "panther")) -+ "pn_i3, pn_e1_p2*2, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_load_multiple_3" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*3, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_load_multiple_4" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*4, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_load_multiple_5" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*5, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_load_multiple_6" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*6, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_load_multiple_7" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*7, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_load_multiple_8" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*8, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_load_multiple_12" 1 -+ (and (and (eq_attr "type" "load_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*12, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_store_multiple_1" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "1")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_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" "panther")) -+ "pn_i3, pn_e1_p2*2, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_store_multiple_3" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "3")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*3, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_store_multiple_4" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "4")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*4, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_store_multiple_5" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*5, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_store_multiple_6" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "5")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*6, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_store_multiple_7" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "7")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*7, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_store_multiple_8" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "8")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*8, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_store_multiple_12" 1 -+ (and (and (eq_attr "type" "store_multiple") -+ (eq_attr "combo" "12")) -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p2*12, pn_e2_p2, pn_e3_p2, pn_e4_p2, pn_wb_p2") -+ -+(define_insn_reservation "nds_pn_mul" 1 -+ (and (eq_attr "type" "mul") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p1, pn_e2_p1, pn_e3_p1, pn_e4_p1, pn_wb_p1") -+ -+(define_insn_reservation "nds_pn_mac" 1 -+ (and (eq_attr "type" "mac") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p1, pn_e2_p1, pn_e3_p1, pn_e4_p1, pn_wb_p1") -+ -+;; The cycles consumed in E4 stage is 32 - CLZ(abs(Ra)) + 2, -+;; so the worst case is 34. -+(define_insn_reservation "nds_pn_div" 1 -+ (and (eq_attr "type" "div") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p1, pn_e2_p1, pn_e3_p1, pn_e4_p1*34, pn_wb_p1") -+ -+(define_insn_reservation "nds_pn_branch" 1 -+ (and (eq_attr "type" "branch") -+ (eq_attr "pipeline_model" "panther")) -+ "pn_i3, pn_e1_p0, pn_e2_p0, pn_e3_p0, pn_e4_p0, pn_wb_p0") -+ -+;; SHIFT -> ADDR_IN -+(define_bypass 2 -+ "nds_pn_shift" -+ "nds_pn_load_full_word, nds_pn_load_partial_word, nds_pn_store,\ -+ nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds32_pn_e2_to_e1_p" -+) -+ -+;; ALU, MOVD44 -> ADDR_IN -+(define_bypass 3 -+ "nds_pn_alu, nds_pn_movd44" -+ "nds_pn_load_full_word, nds_pn_load_partial_word, nds_pn_store,\ -+ nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds32_pn_e3_to_e1_p" -+) -+ -+;; ALU, MOVD44 -> SHIFT, MUL, MAC_RaRb -+(define_bypass 2 -+ "nds_pn_alu, nds_pn_movd44" -+ "nds_pn_shift, nds_pn_mul, nds_pn_mac" -+ "nds32_pn_e3_to_e2_p" -+) -+ -+;; MUL, MAC, DIV, LW, ADDR_OUT -> ADDR_IN -+(define_bypass 4 -+ "nds_pn_mul, nds_pn_mac, nds_pn_div,\ -+ nds_pn_load_full_word, nds_pn_load_partial_word, nds_pn_store,\ -+ nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds_pn_load_full_word, nds_pn_load_partial_word, nds_pn_store,\ -+ nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds32_pn_e4_to_e1_p" -+) -+ -+;; MUL, MAC, DIV, LW, ADDR_OUT -> SHIFT, MUL, MAC_RaRb -+(define_bypass 3 -+ "nds_pn_mul, nds_pn_mac, nds_pn_div,\ -+ nds_pn_load_full_word, nds_pn_load_partial_word, nds_pn_store,\ -+ nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds_pn_shift, nds_pn_mul, nds_pn_mac" -+ "nds32_pn_e4_to_e2_p" -+) -+ -+;; MUL, MAC, DIV, LW, ADDR_OUT -> ALU, MOVD44, BR_COND, ST, SMW(N, 1) -+(define_bypass 2 -+ "nds_pn_mul, nds_pn_mac, nds_pn_div,\ -+ nds_pn_load_full_word, nds_pn_load_partial_word, nds_pn_store,\ -+ nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds_pn_alu, nds_pn_movd44, nds_pn_branch,\ -+ nds_pn_store,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds32_pn_e4_to_e3_p" -+) -+ -+;; LH, LB -> ADDR_IN -+(define_bypass 5 -+ "nds_pn_load_partial_word" -+ "nds_pn_load_full_word, nds_pn_load_partial_word, nds_pn_store,\ -+ nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds32_pn_wb_to_e1_p" -+) -+ -+;; LH, LB -> SHIFT, MUL, MAC_RaRb -+(define_bypass 4 -+ "nds_pn_load_partial_word" -+ "nds_pn_shift, nds_pn_mul, nds_pn_mac" -+ "nds32_pn_wb_to_e2_p" -+) -+ -+;; LH, LB -> ALU, MOVD44, BR_COND, ST, SMW(N, 1) -+(define_bypass 3 -+ "nds_pn_load_partial_word" -+ "nds_pn_alu, nds_pn_movd44, nds_pn_branch,\ -+ nds_pn_store,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds32_pn_wb_to_e3_p" -+) -+ -+;; LH, LB -> DIV -+(define_bypass 2 -+ "nds_pn_load_partial_word" -+ "nds_pn_div" -+ "nds32_pn_wb_to_e4_p" -+) -+ -+;; LMW(N, N) -> ADDR_IN -+(define_bypass 4 -+ "nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12" -+ "nds_pn_load_full_word, nds_pn_load_partial_word, nds_pn_store,\ -+ nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds32_pn_last_load_to_e1_p" -+) -+ -+;; LMW(N, N) -> SHIFT, MUL, MAC_RaRb -+(define_bypass 3 -+ "nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12" -+ "nds_pn_shift, nds_pn_mul, nds_pn_mac" -+ "nds32_pn_last_load_to_e2_p" -+) -+ -+;; LMW(N, N - 1) -> ADDR_IN -+(define_bypass 3 -+ "nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12" -+ "nds_pn_load_full_word, nds_pn_load_partial_word, nds_pn_store,\ -+ nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds32_pn_last_two_load_to_e1_p" -+) -+ -+;; LMW(N, N - 2) -> ADDR_IN -+(define_bypass 2 -+ "nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12" -+ "nds_pn_load_full_word, nds_pn_load_partial_word, nds_pn_store,\ -+ nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds32_pn_last_three_load_to_e1_p" -+) -+ -+;; LMW(N, N - 1) -> SHIFT, MUL, MAC_RaRb -+(define_bypass 2 -+ "nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12" -+ "nds_pn_shift, nds_pn_mul, nds_pn_mac" -+ "nds32_pn_last_two_load_to_e2_p" -+) -+ -+;; LMW(N, N) -> ALU, MOVD44, BR_COND -+(define_bypass 2 -+ "nds_pn_load_multiple_1, nds_pn_load_multiple_2, nds_pn_load_multiple_3,\ -+ nds_pn_load_multiple_4, nds_pn_load_multiple_5, nds_pn_load_multiple_6,\ -+ nds_pn_load_multiple_7, nds_pn_load_multiple_8, nds_pn_load_multiple_12" -+ "nds_pn_alu, nds_pn_movd44, nds_pn_branch,\ -+ nds_pn_store,\ -+ nds_pn_store_multiple_1, nds_pn_store_multiple_2, nds_pn_store_multiple_3,\ -+ nds_pn_store_multiple_4, nds_pn_store_multiple_5, nds_pn_store_multiple_6,\ -+ nds_pn_store_multiple_7, nds_pn_store_multiple_8, nds_pn_store_multiple_12" -+ "nds32_pn_last_load_to_e3_p" -+) -diff --git a/gcc/config/nds32/nds32-peephole2.md b/gcc/config/nds32/nds32-peephole2.md -index 07e3a2b..bb47385 100644 ---- a/gcc/config/nds32/nds32-peephole2.md -+++ b/gcc/config/nds32/nds32-peephole2.md -@@ -19,6 +19,197 @@ - ;; . - - --;; Use define_peephole2 to handle possible target-specific optimization. -+;; Use define_split, define_peephole, and define_peephole2 to -+;; handle possible target-specific optimization in this file. - - ;; ------------------------------------------------------------------------ -+;; 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])); -+ }) -+ -+;; Merge two flsi to fldi. -+(define_peephole2 -+ [(set (match_operand:SF 0 "float_even_register_operand" "") -+ (match_operand:SF 1 "memory_operand" "")) -+ (set (match_operand:SF 2 "float_odd_register_operand" "") -+ (match_operand:SF 3 "memory_operand" ""))] -+ "REGNO (operands[0]) == REGNO (operands[2]) - 1 -+ && nds32_memory_merge_peep_p (operands[3], operands[1])" -+ [(set (match_dup 0) (match_dup 1))] -+{ -+ operands[1] = widen_memory_access (operands[3], DFmode, 0); -+ operands[0] = gen_rtx_REG (DFmode, REGNO (operands[0])); -+}) -+ -+(define_peephole2 -+ [(set (match_operand:SF 0 "float_odd_register_operand" "") -+ (match_operand:SF 1 "memory_operand" "")) -+ (set (match_operand:SF 2 "float_even_register_operand" "") -+ (match_operand:SF 3 "memory_operand" ""))] -+ "REGNO (operands[2]) == REGNO (operands[0]) - 1 -+ && nds32_memory_merge_peep_p (operands[1], operands[3])" -+ [(set (match_dup 0) (match_dup 1))] -+{ -+ operands[1] = widen_memory_access (operands[1], DFmode, 0); -+ operands[0] = gen_rtx_REG (DFmode, REGNO (operands[2])); -+}) -+ -+;; Merge two fssi to fsdi. -+(define_peephole2 -+ [(set (match_operand:SF 0 "memory_operand" "") -+ (match_operand:SF 1 "float_even_register_operand" "")) -+ (set (match_operand:SF 2 "memory_operand" "") -+ (match_operand:SF 3 "float_odd_register_operand" ""))] -+ "REGNO (operands[1]) == REGNO (operands[3]) - 1 -+ && nds32_memory_merge_peep_p (operands[2], operands[0])" -+ [(set (match_dup 0) (match_dup 1))] -+{ -+ operands[0] = widen_memory_access (operands[2], DFmode, 0); -+ operands[1] = gen_rtx_REG (DFmode, REGNO (operands[1])); -+}) -+ -+(define_peephole2 -+ [(set (match_operand:SF 0 "memory_operand" "") -+ (match_operand:SF 1 "float_odd_register_operand" "")) -+ (set (match_operand:SF 2 "memory_operand" "") -+ (match_operand:SF 3 "float_even_register_operand" ""))] -+ "REGNO (operands[3]) == REGNO (operands[1]) - 1 -+ && nds32_memory_merge_peep_p (operands[0], operands[2])" -+ [(set (match_dup 0) (match_dup 1))] -+{ -+ operands[0] = widen_memory_access (operands[0], DFmode, 0); -+ operands[1] = 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 a396fff..903a2ed 100644 ---- a/gcc/config/nds32/nds32-pipelines-auxiliary.c -+++ b/gcc/config/nds32/nds32-pipelines-auxiliary.c -@@ -21,14 +21,2638 @@ - - /* ------------------------------------------------------------------------ */ - -+#include - #include "config.h" - #include "system.h" - #include "coretypes.h" - #include "backend.h" -+#include "tree.h" -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" -+#include "tree-pass.h" - - /* ------------------------------------------------------------------------ */ - --/* This file is prepared for future implementation of precise -- pipeline description for nds32 target. */ -+namespace nds32 { -+namespace scheduling { -+ -+/* Classify the memory access direction. It's unknown if the offset register -+ is not a constant value. */ -+enum memory_access_direction -+{ -+ MEM_ACCESS_DIR_POS, -+ MEM_ACCESS_DIR_NEG, -+ MEM_ACCESS_DIR_UNKNOWN -+}; -+ -+/* This class provides some wrappers of the DFA scheduler. Due to the design -+ drawback of the DFA scheduler, creating two instances at the same time is -+ now allowed. Use the loosest relationship such as 'dependency' instead of -+ 'aggregation' or 'composition' can minimize this issue. */ -+class pipeline_simulator -+{ -+public: -+ pipeline_simulator (); -+ ~pipeline_simulator (); -+ -+ void advance_cycle (int cycles = 1); -+ int query_latency (rtx_insn *producer, rtx_insn *consumer) const; -+ int issue_insn (rtx_insn *insn); -+ int force_issue_insn (rtx_insn *insn); -+ -+private: -+ static int gcc_dfa_initialized_; -+ state_t state_; -+}; -+ -+/* Insert pseudo NOPs so that we can see stall cycles caused by structural or -+ data hazards in the assembly code. The design of this class is similar to -+ the 'template method' pattern, but we don't need to maintain multiple -+ customized algorithms at the same time. Hence this class has no virtual -+ functions providing further customizations. */ -+class stall_inserter -+{ -+private: -+ enum dep_type { RES_DEP, DATA_DEP }; -+ -+public: -+ void insert_stalls (); -+ -+private: -+ static rtx emit_pseudo_nop_before (rtx_insn *insn, int cycles, enum dep_type type); -+ -+ void insert_structural_hazard_stalls (); -+ void insert_data_hazard_stalls (); -+ void emit_pseudo_nops_for_data_hazards (rtx_insn *insn, -+ pipeline_simulator &simulator); -+}; -+ -+class pass_nds32_print_stalls : public rtl_opt_pass -+{ -+public: -+ pass_nds32_print_stalls (gcc::context *ctxt); -+ -+ bool gate (function *); -+ unsigned int execute (function *); -+}; -+ -+int pipeline_simulator::gcc_dfa_initialized_ = 0; -+ -+const pass_data pass_data_nds32_print_stalls = -+{ -+ RTL_PASS, /* type */ -+ "print_stalls", /* 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 */ -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_print_stalls (gcc::context *ctxt) -+{ -+ return new pass_nds32_print_stalls (ctxt); -+} -+ -+/* A safe wrapper to the function reg_overlap_mentioned_p (). */ -+bool -+reg_overlap_p (rtx x, rtx in) -+{ -+ if (x == NULL_RTX || in == NULL_RTX) -+ return false; -+ -+ return static_cast (reg_overlap_mentioned_p (x, in)); -+} -+ -+/* Calculate the cycle distance between two insns in pipeline view. -+ Hence each insn can be treated as one cycle. -+ TODO: multi-cycle insns should be handled -+ specially, but we haven't done it here. */ -+int -+cycle_distance (rtx_insn *from, rtx_insn *to) -+{ -+ int count = 1; -+ -+ for (from = NEXT_INSN (from); from && from != to; from = NEXT_INSN (from)) -+ { -+ if (!insn_executable_p (from)) -+ continue; -+ -+ if (insn_pseudo_nop_p (from)) -+ count += INTVAL (XVECEXP (PATTERN (from), 0, 0)); -+ else -+ ++count; -+ } -+ -+ return count; -+} -+ -+/* Determine the memory access direction of a load/store insn. */ -+memory_access_direction -+determine_access_direction (rtx_insn *insn) -+{ -+ int post_update_rtx_index; -+ rtx plus_rtx; -+ rtx mem_rtx; -+ rtx offset_rtx; -+ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD_MULTIPLE: -+ gcc_assert (parallel_elements (insn) >= 2); -+ -+ post_update_rtx_index = find_post_update_rtx (insn); -+ if (post_update_rtx_index != -1) -+ plus_rtx = SET_SRC (parallel_element (insn, post_update_rtx_index)); -+ else -+ { -+ /* (parallel -+ [(set (reg) (mem (reg))) : index 0 -+ (set (reg) (mem (plus (reg) (...)))) : index 1 -+ ...]) */ -+ mem_rtx = SET_SRC (parallel_element (insn, 1)); -+ if (GET_CODE (mem_rtx) == UNSPEC) -+ mem_rtx = XVECEXP (mem_rtx, 0, 0); -+ gcc_assert (MEM_P (mem_rtx)); -+ plus_rtx = XEXP (mem_rtx, 0); -+ } -+ break; -+ -+ case TYPE_STORE_MULTIPLE: -+ gcc_assert (parallel_elements (insn) >= 2); -+ -+ post_update_rtx_index = find_post_update_rtx (insn); -+ if (post_update_rtx_index != -1) -+ plus_rtx = SET_SRC (parallel_element (insn, post_update_rtx_index)); -+ else -+ { -+ /* (parallel -+ [(set (mem (reg)) (reg)) : index 0 -+ (set (mem (plus (reg) (...))) (reg)) : index 1 -+ ...]) */ -+ mem_rtx = SET_DEST (parallel_element (insn, 1)); -+ if (GET_CODE (mem_rtx) == UNSPEC) -+ mem_rtx = XVECEXP (mem_rtx, 0, 0); -+ gcc_assert (MEM_P (mem_rtx)); -+ plus_rtx = XEXP (mem_rtx, 0); -+ } -+ break; -+ -+ case TYPE_LOAD: -+ case TYPE_STORE: -+ mem_rtx = extract_mem_rtx (insn); -+ -+ switch (GET_CODE (XEXP (mem_rtx, 0))) -+ { -+ case POST_INC: -+ /* (mem (post_inc (...))) */ -+ return MEM_ACCESS_DIR_POS; -+ -+ case POST_DEC: -+ /* (mem (post_dec (...))) */ -+ return MEM_ACCESS_DIR_NEG; -+ -+ case PLUS: -+ /* (mem (plus (reg) (...))) */ -+ plus_rtx = XEXP (mem_rtx, 0); -+ break; -+ -+ case POST_MODIFY: -+ /* (mem (post_modify (reg) (plus (reg) (...)))) */ -+ plus_rtx = XEXP (XEXP (mem_rtx, 0), 1); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ gcc_assert (GET_CODE (plus_rtx) == PLUS); -+ -+ offset_rtx = XEXP (plus_rtx, 1); -+ if (GET_CODE (offset_rtx) == CONST_INT) -+ { -+ if (INTVAL (offset_rtx) < 0) -+ return MEM_ACCESS_DIR_NEG; -+ else -+ return MEM_ACCESS_DIR_POS; -+ } -+ -+ return MEM_ACCESS_DIR_UNKNOWN; -+} -+ -+/* Return the nth load/store operation in the real micro-operation -+ accessing order. */ -+rtx -+extract_nth_access_rtx (rtx_insn *insn, int n) -+{ -+ int n_elems = parallel_elements (insn); -+ int post_update_rtx_index = find_post_update_rtx (insn); -+ memory_access_direction direction = determine_access_direction (insn); -+ -+ gcc_assert (direction != MEM_ACCESS_DIR_UNKNOWN); -+ -+ /* Reverse the order if the direction negative. */ -+ if (direction == MEM_ACCESS_DIR_NEG) -+ n = -1 * n - 1; -+ -+ if (post_update_rtx_index != -1) -+ { -+ if (n >= 0 && post_update_rtx_index <= n) -+ ++n; -+ else if (n < 0 && post_update_rtx_index >= n + n_elems) -+ --n; -+ } -+ -+ return parallel_element (insn, n); -+} -+ -+/* Returns the register operated by the nth load/store operation in the real -+ micro-operation accessing order. This function assumes INSN must be a -+ multiple-word load/store insn. */ -+rtx -+extract_nth_lmsw_access_reg (rtx_insn *insn, int n) -+{ -+ rtx nth_rtx = extract_nth_access_rtx (insn, n); -+ -+ if (nth_rtx == NULL_RTX) -+ return NULL_RTX; -+ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD_MULTIPLE: -+ return SET_DEST (nth_rtx); -+ -+ case TYPE_STORE_MULTIPLE: -+ return SET_SRC (nth_rtx); -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+/* Returns the register operated by the nth load/store operation in the real -+ micro-operation accessing order. This function assumes INSN must be a -+ double-word load/store insn. */ -+rtx -+extract_nth_ls2_access_reg (rtx_insn *insn, int n) -+{ -+ rtx reg; -+ enum machine_mode mode; -+ -+ if (post_update_insn_p (insn)) -+ { -+ memory_access_direction direction = determine_access_direction (insn); -+ gcc_assert (direction != MEM_ACCESS_DIR_UNKNOWN); -+ -+ /* Reverse the order if the direction negative. */ -+ if (direction == MEM_ACCESS_DIR_NEG) -+ n = -1 * n - 1; -+ } -+ -+ /* Handle the out-of-range case. */ -+ if (n < -2 || n > 1) -+ return NULL_RTX; -+ -+ /* Convert the index to a positive one. */ -+ if (n < 0) -+ n = 2 + n; -+ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD: -+ reg = SET_DEST (PATTERN (insn)); -+ break; -+ -+ case TYPE_STORE: -+ reg = SET_SRC (PATTERN (insn)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ gcc_assert (REG_P (reg) || GET_CODE (reg) == SUBREG); -+ -+ switch (GET_MODE (reg)) -+ { -+ case DImode: -+ mode = SImode; -+ break; -+ -+ case DFmode: -+ mode = SFmode; -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ if (n == 0) -+ return gen_lowpart (mode, reg); -+ else -+ return gen_highpart (mode, reg); -+} -+ -+/* Returns the register operated by the nth load/store operation in the real -+ micro-operation accessing order. */ -+rtx -+extract_nth_access_reg (rtx_insn *insn, int index) -+{ -+ switch (GET_CODE (PATTERN (insn))) -+ { -+ case PARALLEL: -+ return extract_nth_lmsw_access_reg (insn, index); -+ -+ case SET: -+ return extract_nth_ls2_access_reg (insn, index); -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+/* Determine if the latency is occured when the consumer PBSADA_INSN uses the -+ value of DEF_REG in its Ra or Rb fields. */ -+bool -+pbsada_insn_ra_rb_dep_reg_p (rtx pbsada_insn, rtx def_reg) -+{ -+ rtx unspec_rtx = SET_SRC (PATTERN (pbsada_insn)); -+ gcc_assert (GET_CODE (unspec_rtx) == UNSPEC); -+ -+ rtx pbsada_ra = XVECEXP (unspec_rtx, 0, 0); -+ rtx pbsada_rb = XVECEXP (unspec_rtx, 0, 1); -+ -+ if (rtx_equal_p (def_reg, pbsada_ra) -+ || rtx_equal_p (def_reg, pbsada_rb)) -+ return true; -+ -+ 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) -+{ -+ if (!movd44_insn_p (insn)) -+ return false; -+ -+ rtx use_rtx = SET_SRC (PATTERN (insn)); -+ -+ if (REG_P (def_reg)) -+ { -+ return rtx_equal_p (def_reg, use_rtx); -+ } -+ else if (GET_CODE (def_reg) == SUBREG -+ && GET_MODE (def_reg) == SImode -+ && rtx_equal_p (SUBREG_REG (def_reg), use_rtx)) -+ { -+ if (TARGET_BIG_ENDIAN && SUBREG_BYTE (def_reg) == 4) -+ return true; -+ -+ if (!TARGET_BIG_ENDIAN && SUBREG_BYTE (def_reg) == 0) -+ return true; -+ -+ return false; -+ } -+ -+ 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 (); -+} -+ -+pipeline_simulator::pipeline_simulator () -+{ -+ /* The design of dfa_start () operates on static global variables and -+ allocates memory space without checking whether the function is called -+ twice or not. We add some guards in order to protect it from abusing. */ -+ if (!gcc_dfa_initialized_++) -+ dfa_start (); -+ -+ state_ = xmalloc (state_size()); -+ state_reset (state_); -+} -+ -+pipeline_simulator::~pipeline_simulator () -+{ -+ /* The design of dfa_finish () operates on a static global variable and -+ deallocates memory space without checking whether the function is called -+ twice or not. We add some guards in order to protect it from abusing. */ -+ free (state_); -+ -+ gcc_assert(gcc_dfa_initialized_ > 0); -+ if (!--gcc_dfa_initialized_) -+ dfa_finish (); -+} -+ -+void -+pipeline_simulator::advance_cycle (int cycles) -+{ -+ gcc_assert (cycles > 0); -+ -+ /* The second argument was 'NULL', but we found the expression is directly -+ written in insn-automata.c: -+ if (insn == 0) -+ insn_code = DFA__ADVANCE_CYCLE; -+ Hence we change it to '0' in order to make it consistent. */ -+ while (cycles--) -+ state_transition (state_, 0); -+} -+ -+/* A wrapper of insn_latency () provided by the insn-attr.h in the object tree. -+ See that file for more information. */ -+int -+pipeline_simulator::query_latency (rtx_insn *producer, rtx_insn *consumer) const -+{ -+ return insn_latency (producer, consumer); -+} -+ -+/* Return 0 or negative if we can issue INSN at the current cycle. Otherwise, -+ return a postive value indicates how many cycles we have to wait. The -+ interface is consistent with state_transition () provided by insn-attr.h -+ in the object directory. See that file for more information. */ -+int -+pipeline_simulator::issue_insn (rtx_insn *insn) -+{ -+ int stalls; -+ -+ /* Skip cycles specified by pseudo NOPs. */ -+ if (insn_pseudo_nop_p (insn)) -+ { -+ int nop_stalls = INTVAL (XVECEXP (PATTERN (insn), 0, 0)); -+ -+ gcc_assert (nop_stalls > 0); -+ advance_cycle (nop_stalls); -+ stalls = -1; -+ } -+ else -+ { -+ stalls = state_transition (state_, insn); -+ -+ /* All targets are single-issue, so we advance one cycle once after -+ an insn has been issued successfully. */ -+ if (stalls <= 0) -+ advance_cycle (); -+ } -+ -+ return stalls; -+} -+ -+/* This function is similar to issue_insn (), but it advances cycles until INSN -+ can be issued successfully. If INSN can be issued at the current cycle, the -+ return value will be 0 or negaitive. Otherwise, the function will return -+ the cycles it has been skipped. */ -+int -+pipeline_simulator::force_issue_insn (rtx_insn *insn) -+{ -+ int stalls; -+ -+ stalls = issue_insn (insn); -+ -+ /* Skip cycles until we can issue the insn. */ -+ if (stalls > 0) -+ { -+ advance_cycle (stalls); -+ issue_insn (insn); -+ } -+ -+ return stalls; -+} -+ -+/* The main flow of the class STALL_INSERTER. We insert NOPs for structural -+ hazards because self-stalled instructions also consume the delay cycles -+ caused by data hazards. */ -+void -+stall_inserter::insert_stalls () -+{ -+ compute_bb_for_insn_safe (); -+ -+ insert_structural_hazard_stalls (); -+ insert_data_hazard_stalls (); -+ -+ /* We have to call the following two functions again after we inserting -+ some insns after it has been invoked. Otherwise, an assert expression -+ in final () will be triggered and cause to an internal compiler error. */ -+ init_insn_lengths (); -+ shorten_branches (get_insns ()); -+ -+ free_bb_for_insn (); -+} -+ -+/* A helper function inserting NOPs. CYCLES indicates how many cycles the NOP -+ insn consumes. TYPE indicates what type of the NOP insn we want to insert; -+ now there are two types available: RES_DEP and DATA_DEP. */ -+rtx -+stall_inserter::emit_pseudo_nop_before ( -+ rtx_insn *insn, int cycles, enum dep_type type) -+{ -+ rtx nop_pattern; -+ rtx_insn *nop_insn; -+ int recog; -+ -+ switch (type) -+ { -+ case RES_DEP: -+ nop_pattern = gen_nop_res_dep (GEN_INT (cycles)); -+ break; -+ case DATA_DEP: -+ nop_pattern = gen_nop_data_dep (GEN_INT (cycles)); -+ break; -+ default: -+ gcc_unreachable (); -+ } -+ -+ nop_insn = emit_insn_before (nop_pattern, insn); -+ recog = recog_memoized (nop_insn); -+ gcc_assert(recog != -1); -+ -+ return nop_insn; -+} -+ -+void -+stall_inserter::insert_structural_hazard_stalls () -+{ -+ pipeline_simulator simulator; -+ rtx_insn *insn; -+ -+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) -+ { -+ if (!insn_executable_p (insn)) continue; -+ -+ int stalls = simulator.force_issue_insn (insn); -+ -+ if (stalls > 0) -+ emit_pseudo_nop_before (insn, stalls, RES_DEP); -+ } -+} -+ -+void -+stall_inserter::insert_data_hazard_stalls () -+{ -+ pipeline_simulator simulator; -+ rtx_insn *insn; -+ -+ /* Calling to df_insn_rescan_all here is required in order to avoid crash -+ when some special options are specified by users, such as -+ -O0 -fschedule-insns2. */ -+ df_chain_add_problem (DF_DU_CHAIN); -+ df_insn_rescan_all (); -+ df_analyze (); -+ -+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) -+ { -+ if (!insn_executable_p (insn)) continue; -+ -+ simulator.force_issue_insn (insn); -+ emit_pseudo_nops_for_data_hazards (insn, simulator); -+ } -+ -+ /* We must call df_finish_pass manually because it should be invoked before -+ BB information is destroyed. Hence we cannot set the TODO_df_finish flag -+ to the pass manager. */ -+ df_insn_rescan_all (); -+ df_finish_pass (false); -+} -+ -+/* Traverse all insns using the results produced by INSN and ask SIMULATOR -+ how many delay cycles between them. If there are some delay cycles, insert -+ corresponding NOP insns there. */ -+void -+stall_inserter::emit_pseudo_nops_for_data_hazards ( -+ rtx_insn *insn, pipeline_simulator &simulator) -+{ -+ df_ref def; -+ df_link *link; -+ std::set processed_insns; -+ -+ FOR_EACH_INSN_DEF (def, insn) -+ { -+ for (link = DF_REF_CHAIN (def); link; link = link->next) -+ { -+ if (!DF_REF_INSN_INFO (link->ref)) -+ continue; -+ -+ rtx_insn *use_insn = DF_REF_INSN (link->ref); -+ -+ if (!insn_executable_p (use_insn) -+ || processed_insns.count (use_insn)) -+ continue; -+ -+ int stalls = simulator.query_latency (insn, use_insn); -+ int distance = cycle_distance (insn, use_insn); -+ -+ if (stalls > distance) -+ { -+ stalls -= distance; -+ emit_pseudo_nop_before (use_insn, stalls, DATA_DEP); -+ processed_insns.insert (use_insn); -+ } -+ } -+ } -+} -+ -+pass_nds32_print_stalls::pass_nds32_print_stalls (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_print_stalls, ctxt) -+{ -+} -+ -+bool pass_nds32_print_stalls::gate (function *) -+{ -+ return TARGET_PRINT_STALLS; -+} -+ -+unsigned int -+pass_nds32_print_stalls::execute (function *) -+{ -+ stall_inserter inserter; -+ -+ inserter.insert_stalls (); -+ return 0; -+} -+ -+} // namespace scheduling -+} // namespace nds32 -+ -+/* ------------------------------------------------------------------------ */ -+ -+using namespace nds32; -+using namespace nds32::scheduling; -+ -+namespace { // anonymous namespace -+ -+/* Check the dependency between the producer defining DEF_REG and CONSUMER -+ requiring input operand at II. */ -+bool -+n7_consumed_by_ii_dep_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ /* MOVD44_E */ -+ case TYPE_ALU: -+ if (movd44_even_dep_p (consumer, def_reg)) -+ return true; -+ -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_MUL: -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_MAC: -+ use_rtx = extract_mac_non_acc_rtx (consumer); -+ break; -+ -+ /* Some special instructions, divmodsi4 and udivmodsi4, produce two -+ results, the quotient and the remainder. It requires two micro- -+ 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 (divmod_p (consumer)) -+ use_rtx = SET_SRC (parallel_element (consumer, 0)); -+ else -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_LOAD: -+ /* ADDR_IN_bi_Ra, ADDR_IN_!bi */ -+ if (post_update_insn_p (consumer)) -+ use_rtx = extract_base_reg (consumer); -+ else -+ use_rtx = extract_mem_rtx (consumer); -+ break; -+ -+ case TYPE_STORE: -+ /* ADDR_IN_bi_Ra, ADDR_IN_!bi */ -+ if (post_update_insn_p (consumer)) -+ use_rtx = extract_base_reg (consumer); -+ else -+ use_rtx = extract_mem_rtx (consumer); -+ -+ if (reg_overlap_p (def_reg, use_rtx)) -+ return true; -+ -+ /* ST_bi, ST_!bi_RI */ -+ if (!post_update_insn_p (consumer) -+ && !immed_offset_p (extract_mem_rtx (consumer))) -+ return false; -+ -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_LOAD_MULTIPLE: -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ case TYPE_STORE_MULTIPLE: -+ /* ADDR_IN */ -+ use_rtx = extract_base_reg (consumer); -+ if (reg_overlap_p (def_reg, use_rtx)) -+ return true; -+ -+ /* SMW (N, 1) */ -+ use_rtx = extract_nth_access_rtx (consumer, 0); -+ 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 AG (II). */ -+bool -+n8_consumed_by_addr_in_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ case TYPE_BRANCH: -+ use_rtx = extract_branch_target_rtx (consumer); -+ break; -+ -+ case TYPE_LOAD: -+ if (load_single_p (consumer)) -+ use_rtx = extract_mem_rtx (consumer); -+ else -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ case TYPE_STORE: -+ if (store_single_p (consumer) -+ && (!post_update_insn_p (consumer) -+ || immed_offset_p (extract_mem_rtx (consumer)))) -+ use_rtx = extract_mem_rtx (consumer); -+ else -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ case TYPE_LOAD_MULTIPLE: -+ case TYPE_STORE_MULTIPLE: -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return reg_overlap_p (def_reg, use_rtx); -+} -+ -+/* Check the dependency between the producer defining DEF_REG and CONSUMER -+ requiring input operand at EX. */ -+bool -+n8_consumed_by_ex_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ case TYPE_ALU: -+ if (movd44_even_dep_p (consumer, def_reg)) -+ return true; -+ -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_MUL: -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_MAC: -+ use_rtx = extract_mac_non_acc_rtx (consumer); -+ break; -+ -+ /* Some special instructions, divmodsi4 and udivmodsi4, produce two -+ results, the quotient and the remainder. It requires two micro- -+ 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 (divmod_p (consumer)) -+ use_rtx = SET_SRC (parallel_element (consumer, 0)); -+ else -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_BRANCH: -+ use_rtx = extract_branch_condition_rtx (consumer); -+ break; -+ -+ case TYPE_STORE: -+ /* exclude ST_!bi_RR */ -+ if (!post_update_insn_p (consumer) -+ && !immed_offset_p (extract_mem_rtx (consumer))) -+ return false; -+ -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_STORE_MULTIPLE: -+ use_rtx = extract_nth_access_rtx (consumer, 0); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return reg_overlap_p (def_reg, use_rtx); -+} -+ -+/* Check the dependency between the producer defining DEF_REG and CONSUMER -+ requiring input operand at AG (II). */ -+bool -+e8_consumed_by_addr_in_p (rtx_insn *consumer, rtx def_reg) -+{ -+ return n8_consumed_by_addr_in_p (consumer, def_reg); -+} -+ -+/* Check the dependency between the producer defining DEF_REG and CONSUMER -+ requiring input operand at EX. */ -+bool -+e8_consumed_by_ex_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_MUL: -+ case TYPE_MAC: -+ case TYPE_DIV: -+ case TYPE_BRANCH: -+ case TYPE_STORE_MULTIPLE: -+ return n8_consumed_by_ex_p (consumer, def_reg); -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return reg_overlap_p (def_reg, use_rtx); -+} -+ -+/* Check the dependency between the producer defining DEF_REG and CONSUMER -+ requiring input operand at EX. */ -+bool -+n9_2r1w_consumed_by_ex_dep_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ case TYPE_ALU: -+ if (movd44_even_dep_p (consumer, def_reg)) -+ return true; -+ -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_PBSAD: -+ case TYPE_MUL: -+ 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: -+ use_rtx = PATTERN (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_LOAD: -+ /* ADDR_IN_bi_Ra, ADDR_IN_!bi */ -+ if (post_update_insn_p (consumer)) -+ use_rtx = extract_base_reg (consumer); -+ else -+ use_rtx = extract_mem_rtx (consumer); -+ break; -+ -+ case TYPE_STORE: -+ /* ADDR_IN_bi_Ra, ADDR_IN_!bi */ -+ if (post_update_insn_p (consumer)) -+ use_rtx = extract_base_reg (consumer); -+ else -+ use_rtx = extract_mem_rtx (consumer); -+ -+ if (reg_overlap_p (def_reg, use_rtx)) -+ return true; -+ -+ /* exclude ST_!bi_RR */ -+ if (!post_update_insn_p (consumer) -+ && !immed_offset_p (extract_mem_rtx (consumer))) -+ return false; -+ -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_LOAD_MULTIPLE: -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ case TYPE_STORE_MULTIPLE: -+ /* ADDR_IN */ -+ use_rtx = extract_base_reg (consumer); -+ if (reg_overlap_p (def_reg, use_rtx)) -+ return true; -+ -+ /* SMW (N, 1) */ -+ use_rtx = extract_nth_access_rtx (consumer, 0); -+ 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 -+n9_3r2w_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: -+ 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: -+ use_rtx = extract_mac_non_acc_rtx (consumer); -+ break; -+ -+ /* Some special instructions, divmodsi4 and udivmodsi4, produce two -+ results, the quotient and the remainder. In 2R1W configuration, -+ it requires two micro-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 (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)); -+ 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; -+} -+ -+/* Check the dependency between the producer defining DEF_REG and CONSUMER -+ requiring input operand at AG (E1). */ -+bool -+pn_consumed_by_e1_dep_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ case TYPE_LOAD: -+ if (load_single_p (consumer)) -+ use_rtx = extract_mem_rtx (consumer); -+ else -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ case TYPE_STORE: -+ if (store_single_p (consumer) -+ && (!post_update_insn_p (consumer) -+ || immed_offset_p (extract_mem_rtx (consumer)))) -+ use_rtx = extract_mem_rtx (consumer); -+ else -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ case TYPE_LOAD_MULTIPLE: -+ case TYPE_STORE_MULTIPLE: -+ use_rtx = extract_base_reg (consumer); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return reg_overlap_p (def_reg, use_rtx); -+} -+ -+bool -+pn_consumed_by_e2_dep_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ case TYPE_ALU: -+ if (get_attr_subtype (consumer) != SUBTYPE_SHIFT) -+ return false; -+ case TYPE_PBSAD: -+ case TYPE_PBSADA: -+ case TYPE_MUL: -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_MAC: -+ use_rtx = extract_mac_non_acc_rtx (consumer); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return reg_overlap_p (def_reg, use_rtx); -+} -+ -+bool -+pn_consumed_by_e3_dep_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ case TYPE_ALU: -+ if (get_attr_subtype (consumer) == SUBTYPE_SHIFT) -+ return false; -+ case TYPE_PBSAD: -+ case TYPE_PBSADA: -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_BRANCH: -+ return (reg_overlap_p (def_reg, extract_branch_target_rtx (consumer)) -+ || reg_overlap_p (def_reg, -+ extract_branch_condition_rtx (consumer))); -+ break; -+ -+ case TYPE_STORE: -+ use_rtx = SET_SRC (PATTERN (consumer)); -+ break; -+ -+ case TYPE_STORE_MULTIPLE: -+ use_rtx = extract_nth_access_rtx (consumer, 0); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return reg_overlap_p (def_reg, use_rtx); -+} -+ -+bool -+pn_consumed_by_e4_dep_p (rtx_insn *consumer, rtx def_reg) -+{ -+ rtx use_rtx; -+ -+ switch (get_attr_type (consumer)) -+ { -+ case TYPE_MAC: -+ use_rtx = SET_DEST (PATTERN (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; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return reg_overlap_p (def_reg, use_rtx); -+} -+ -+} // anonymous namespace -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* Guard functions for N7 core. */ -+ -+bool -+nds32_n7_load_to_ii_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ if (post_update_insn_p (producer)) -+ return false; -+ -+ rtx def_reg = SET_DEST (PATTERN (producer)); -+ -+ return n7_consumed_by_ii_dep_p (consumer, def_reg); -+} -+ -+bool -+nds32_n7_last_load_to_ii_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ /* If PRODUCER is a post-update LMW insn, the last micro-operation updates -+ the base register and the result is ready in II stage, so we don't need -+ to handle that case in this guard function and the corresponding bypass -+ rule. */ -+ if (post_update_insn_p (producer)) -+ return false; -+ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ if (last_def_reg == NULL_RTX) -+ return false; -+ -+ gcc_assert (REG_P (last_def_reg) || GET_CODE (last_def_reg) == SUBREG); -+ -+ return n7_consumed_by_ii_dep_p (consumer, last_def_reg); -+} -+ -+/* Guard functions for N8 core. */ -+ -+bool -+nds32_n8_load_to_ii_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ if (post_update_insn_p (producer)) -+ return false; -+ -+ rtx def_reg = SET_DEST (PATTERN (producer)); -+ -+ return n8_consumed_by_addr_in_p (consumer, def_reg); -+} -+ -+bool -+nds32_n8_load_bi_to_ii_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ if (!post_update_insn_p (producer)) -+ return false; -+ -+ rtx def_reg = SET_DEST (PATTERN (producer)); -+ -+ return n8_consumed_by_addr_in_p (consumer, def_reg); -+} -+ -+bool -+nds32_n8_load_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ if (post_update_insn_p (producer)) -+ return false; -+ -+ rtx def_reg = SET_DEST (PATTERN (producer)); -+ -+ return n8_consumed_by_ex_p (consumer, def_reg); -+} -+ -+bool -+nds32_n8_ex_to_ii_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_ALU: -+ if (movd44_insn_p (producer)) -+ def_reg = extract_movd44_odd_reg (producer); -+ else -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ case TYPE_MUL: -+ case TYPE_MAC: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ case TYPE_DIV: -+ if (divmod_p (producer)) -+ def_reg = SET_DEST (parallel_element (producer, 1)); -+ else -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ 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; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return n8_consumed_by_addr_in_p (consumer, def_reg); -+} -+ -+bool -+nds32_n8_last_load_to_ii_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ /* If PRODUCER is a post-update LMW insn, the last micro-operation updates -+ the base register and the result is ready in EX stage, so we don't need -+ to handle that case in this guard function and the corresponding bypass -+ rule. */ -+ if (post_update_insn_p (producer)) -+ return false; -+ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ if (last_def_reg == NULL_RTX) -+ return false; -+ -+ gcc_assert (REG_P (last_def_reg) || GET_CODE (last_def_reg) == SUBREG); -+ -+ return n8_consumed_by_addr_in_p (consumer, last_def_reg); -+} -+ -+bool -+nds32_n8_last_load_two_to_ii_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ int index = -2; -+ -+ /* If PRODUCER is a post-update insn, there is an additional one micro- -+ operation inserted in the end, so the last memory access operation should -+ be handled by this guard function and the corresponding bypass rule. */ -+ if (post_update_insn_p (producer)) -+ index = -1; -+ -+ rtx last_two_def_reg = extract_nth_access_reg (producer, index); -+ -+ if (last_two_def_reg == NULL_RTX) -+ return false; -+ -+ gcc_assert (REG_P (last_two_def_reg) -+ || GET_CODE (last_two_def_reg) == SUBREG); -+ -+ return n8_consumed_by_addr_in_p (consumer, last_two_def_reg); -+} -+ -+bool -+nds32_n8_last_load_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ /* If PRODUCER is a post-update LMW insn, the last micro-operation updates -+ the base register and the result is ready in EX stage, so we don't need -+ to handle that case in this guard function and the corresponding bypass -+ rule. */ -+ if (post_update_insn_p (producer)) -+ return false; -+ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ if (last_def_reg == NULL_RTX) -+ return false; -+ -+ gcc_assert (REG_P (last_def_reg) || GET_CODE (last_def_reg) == SUBREG); -+ -+ return n8_consumed_by_ex_p (consumer, last_def_reg); -+} -+ -+/* Guard functions for E8 cores. */ -+ -+bool -+nds32_e8_load_to_ii_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg = SET_DEST (PATTERN (producer)); -+ -+ return e8_consumed_by_addr_in_p (consumer, def_reg); -+} -+ -+bool -+nds32_e8_load_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg = SET_DEST (PATTERN (producer)); -+ -+ return e8_consumed_by_ex_p (consumer, def_reg); -+} -+ -+bool -+nds32_e8_ex_to_ii_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_ALU: -+ /* No data hazards if AGEN's input is produced by MOVI or SETHI. */ -+ if (GET_CODE (PATTERN (producer)) == SET) -+ { -+ rtx dest = SET_DEST (PATTERN (producer)); -+ rtx src = SET_SRC (PATTERN (producer)); -+ -+ if ((REG_P (dest) || GET_CODE (dest) == SUBREG) -+ && (GET_CODE (src) == CONST_INT || GET_CODE (src) == HIGH)) -+ return false; -+ } -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ case TYPE_MUL: -+ case TYPE_MAC: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ 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 (e8_consumed_by_addr_in_p (consumer, def_reg1) -+ || e8_consumed_by_addr_in_p (consumer, def_reg2)); -+ } -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ 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; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return e8_consumed_by_addr_in_p (consumer, def_reg); -+} -+ -+bool -+nds32_e8_last_load_to_ii_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ if (last_def_reg == NULL_RTX) -+ return false; -+ -+ gcc_assert (REG_P (last_def_reg) || GET_CODE (last_def_reg) == SUBREG); -+ -+ return e8_consumed_by_addr_in_p (consumer, last_def_reg); -+} -+ -+bool -+nds32_e8_last_load_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ if (last_def_reg == NULL_RTX) -+ return false; -+ -+ gcc_assert (REG_P (last_def_reg) || GET_CODE (last_def_reg) == SUBREG); -+ -+ return e8_consumed_by_ex_p (consumer, last_def_reg); -+} -+ -+/* Guard functions for N9 cores. */ -+ -+/* Check dependencies from MM to EX. */ -+bool -+nds32_n9_2r1w_mm_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ /* LD_!bi */ -+ case TYPE_LOAD: -+ if (post_update_insn_p (producer)) -+ return false; -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ case TYPE_MUL: -+ case TYPE_MAC: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return n9_2r1w_consumed_by_ex_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from MM to EX. */ -+bool -+nds32_n9_3r2w_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: -+ 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 (n9_3r2w_consumed_by_ex_dep_p (consumer, def_reg1) -+ || n9_3r2w_consumed_by_ex_dep_p (consumer, def_reg2)); -+ } -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return n9_3r2w_consumed_by_ex_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from LMW(N, N) to EX. */ -+bool -+nds32_n9_last_load_to_ex_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ if (nds32_register_ports_config == REG_PORT_2R1W) -+ { -+ /* The base-update micro operation occupies the last cycle. */ -+ if (post_update_insn_p (producer)) -+ return false; -+ -+ /* When the base register is in the list of a load multiple insn and the -+ access order of the base register is not the last one, we need an -+ additional micro operation to commit the load result to the base -+ register -- we can treat the base register as the last defined -+ register. */ -+ size_t i; -+ size_t n_elems = parallel_elements (producer); -+ rtx base_reg = extract_base_reg (producer); -+ -+ for (i = 0; i < n_elems; ++i) -+ { -+ rtx load_rtx = extract_nth_access_rtx (producer, i); -+ rtx list_element = SET_DEST (load_rtx); -+ -+ if (rtx_equal_p (base_reg, list_element) && i != n_elems - 1) -+ { -+ last_def_reg = base_reg; -+ break; -+ } -+ } -+ -+ return n9_2r1w_consumed_by_ex_dep_p (consumer, last_def_reg); -+ } -+ else -+ 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); -+} -+ -+/* Guard functions for Panther cores. */ -+ -+/* Check dependencies from E2 to E1. */ -+bool -+nds32_pn_e2_to_e1_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_ALU: -+ gcc_assert (get_attr_subtype (producer) == SUBTYPE_SHIFT); -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return pn_consumed_by_e1_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from E3 to E1. */ -+bool -+nds32_pn_e3_to_e1_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_ALU: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return pn_consumed_by_e1_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from E3 to E2. */ -+bool -+nds32_pn_e3_to_e2_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_ALU: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return pn_consumed_by_e2_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from E4 to E1. */ -+bool -+nds32_pn_e4_to_e1_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_MUL: -+ case TYPE_MAC: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ 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 (pn_consumed_by_e1_dep_p (consumer, def_reg1) -+ || pn_consumed_by_e1_dep_p (consumer, def_reg2)); -+ } -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ case TYPE_LOAD: -+ if (post_update_insn_p (producer) -+ && pn_consumed_by_e1_dep_p (consumer, extract_base_reg (producer))) -+ return true; -+ -+ if (!load_full_word_p (producer)) -+ return false; -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ 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; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return pn_consumed_by_e1_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from E4 to E2. */ -+bool -+nds32_pn_e4_to_e2_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_MUL: -+ case TYPE_MAC: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ 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 (pn_consumed_by_e2_dep_p (consumer, def_reg1) -+ || pn_consumed_by_e2_dep_p (consumer, def_reg2)); -+ } -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ case TYPE_LOAD: -+ if (post_update_insn_p (producer) -+ && pn_consumed_by_e2_dep_p (consumer, extract_base_reg (producer))) -+ return true; -+ -+ if (!load_full_word_p (producer)) -+ return false; -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ 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; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return pn_consumed_by_e2_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from E4 to E3. */ -+bool -+nds32_pn_e4_to_e3_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_MUL: -+ case TYPE_MAC: -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ 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 (pn_consumed_by_e3_dep_p (consumer, def_reg1) -+ || pn_consumed_by_e3_dep_p (consumer, def_reg2)); -+ } -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ case TYPE_LOAD: -+ if (post_update_insn_p (producer) -+ && pn_consumed_by_e3_dep_p (consumer, extract_base_reg (producer))) -+ return true; -+ -+ if (load_partial_word_p (producer)) -+ return false; -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ 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; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return pn_consumed_by_e3_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from WB to E1. */ -+bool -+nds32_pn_wb_to_e1_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_LOAD: -+ if (!load_partial_word_p (producer)) -+ return false; -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return pn_consumed_by_e1_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from WB to E2. */ -+bool -+nds32_pn_wb_to_e2_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_LOAD: -+ if (!load_partial_word_p (producer)) -+ return false; -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return pn_consumed_by_e2_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from WB to E3. */ -+bool -+nds32_pn_wb_to_e3_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_LOAD: -+ if (!load_partial_word_p (producer)) -+ return false; -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return pn_consumed_by_e3_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from WB to E4. */ -+bool -+nds32_pn_wb_to_e4_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx def_reg; -+ -+ switch (get_attr_type (producer)) -+ { -+ case TYPE_LOAD: -+ if (!load_partial_word_p (producer)) -+ return false; -+ -+ def_reg = SET_DEST (PATTERN (producer)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return pn_consumed_by_e4_dep_p (consumer, def_reg); -+} -+ -+/* Check dependencies from LMW(N, N) to E1. */ -+bool -+nds32_pn_last_load_to_e1_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ return pn_consumed_by_e1_dep_p (consumer, last_def_reg); -+} -+ -+/* Check dependencies from LMW(N, N) to E2. */ -+bool -+nds32_pn_last_load_to_e2_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ return pn_consumed_by_e2_dep_p (consumer, last_def_reg); -+} -+ -+/* Check dependencies from LMW(N, N) to E3. */ -+bool -+nds32_pn_last_load_to_e3_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_def_reg = extract_nth_access_reg (producer, -1); -+ -+ return pn_consumed_by_e3_dep_p (consumer, last_def_reg); -+} -+ -+/* Check dependencies from LMW(N, N - 1) to E1. */ -+bool -+nds32_pn_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 pn_consumed_by_e1_dep_p (consumer, last_two_def_reg); -+} -+ -+/* Check dependencies from LMW(N, N - 1) to E2. */ -+bool -+nds32_pn_last_two_load_to_e2_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 pn_consumed_by_e2_dep_p (consumer, last_two_def_reg); -+} -+ -+/* Check dependencies from LMW(N, N - 2) to E1. */ -+bool -+nds32_pn_last_three_load_to_e1_p (rtx_insn *producer, rtx_insn *consumer) -+{ -+ rtx last_three_def_reg = extract_nth_access_reg (producer, -3); -+ -+ if (last_three_def_reg == NULL_RTX) -+ return false; -+ -+ return pn_consumed_by_e1_dep_p (consumer, last_three_def_reg); -+} - - /* ------------------------------------------------------------------------ */ -diff --git a/gcc/config/nds32/nds32-predicates.c b/gcc/config/nds32/nds32-predicates.c -index 361d001..b45d3e6 100644 ---- a/gcc/config/nds32/nds32-predicates.c -+++ b/gcc/config/nds32/nds32-predicates.c -@@ -24,14 +24,41 @@ - #include "system.h" - #include "coretypes.h" - #include "backend.h" --#include "target.h" --#include "rtl.h" - #include "tree.h" --#include "tm_p.h" --#include "optabs.h" /* For GEN_FCN. */ -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" - #include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" - #include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" - #include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" - - /* ------------------------------------------------------------------------ */ - -@@ -98,21 +125,33 @@ nds32_consecutive_registers_load_store_p (rtx op, - We have to extract reg and mem of every element and - check if the information is valid for multiple load/store operation. */ - bool --nds32_valid_multiple_load_store (rtx op, bool load_p) -+nds32_valid_multiple_load_store_p (rtx op, bool load_p, bool bim_p) - { - int count; - int first_elt_regno; -+ int update_base_elt_idx; -+ int offset; - rtx elt; -+ rtx update_base; - -- /* Get the counts of elements in the parallel rtx. */ -- count = XVECLEN (op, 0); -- /* Pick up the first element. */ -- elt = XVECEXP (op, 0, 0); -+ /* Get the counts of elements in the parallel rtx. -+ Last one is update base register if bim_p. -+ and pick up the first element. */ -+ if (bim_p) -+ { -+ count = XVECLEN (op, 0) - 1; -+ elt = XVECEXP (op, 0, 1); -+ } -+ else -+ { -+ count = XVECLEN (op, 0); -+ elt = XVECEXP (op, 0, 0); -+ } - - /* Perform some quick check for the first element in the parallel rtx. */ - if (GET_CODE (elt) != SET - || count <= 1 -- || count > 8) -+ || count > 25) - return false; - - /* Pick up regno of first element for further detail checking. -@@ -138,11 +177,29 @@ nds32_valid_multiple_load_store (rtx op, bool load_p) - Refer to nds32-multiple.md for more information - about following checking. - The starting element of parallel rtx is index 0. */ -- if (!nds32_consecutive_registers_load_store_p (op, load_p, 0, -+ if (!nds32_consecutive_registers_load_store_p (op, load_p, bim_p ? 1 : 0, - first_elt_regno, - count)) - return false; - -+ if (bim_p) -+ { -+ update_base_elt_idx = 0; -+ update_base = XVECEXP (op, 0, update_base_elt_idx); -+ if (!REG_P (SET_DEST (update_base))) -+ return false; -+ if (GET_CODE (SET_SRC (update_base)) != PLUS) -+ return false; -+ else -+ { -+ offset = count * UNITS_PER_WORD; -+ elt = XEXP (SET_SRC (update_base), 1); -+ if (GET_CODE (elt) != CONST_INT -+ || (INTVAL (elt) != offset)) -+ return false; -+ } -+ } -+ - /* Pass all test, this is a valid rtx. */ - return true; - } -@@ -174,47 +231,47 @@ nds32_valid_stack_push_pop_p (rtx op, bool push_p) - { - elt = XVECEXP (op, 0, index); - if (GET_CODE (elt) != SET) -- return false; -+ return false; - } - - /* For push operation, the parallel rtx looks like: - (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32))) -- (reg:SI Rb)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) -- (reg:SI Rb+1)) -- ... -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) -- (reg:SI Re)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) -- (reg:SI FP_REGNUM)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) -- (reg:SI GP_REGNUM)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) -- (reg:SI LP_REGNUM)) -- (set (reg:SI SP_REGNUM) -- (plus (reg:SI SP_REGNUM) (const_int -32)))]) -+ (reg:SI Rb)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) -+ (reg:SI Rb+1)) -+ ... -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) -+ (reg:SI Re)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) -+ (reg:SI FP_REGNUM)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) -+ (reg:SI GP_REGNUM)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) -+ (reg:SI LP_REGNUM)) -+ (set (reg:SI SP_REGNUM) -+ (plus (reg:SI SP_REGNUM) (const_int -32)))]) - - For pop operation, the parallel rtx looks like: - (parallel [(set (reg:SI Rb) -- (mem (reg:SI SP_REGNUM))) -- (set (reg:SI Rb+1) -- (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) -- ... -- (set (reg:SI Re) -- (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) -- (set (reg:SI FP_REGNUM) -- (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) -- (set (reg:SI GP_REGNUM) -- (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) -- (set (reg:SI LP_REGNUM) -- (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) -- (set (reg:SI SP_REGNUM) -- (plus (reg:SI SP_REGNUM) (const_int 32)))]) */ -+ (mem (reg:SI SP_REGNUM))) -+ (set (reg:SI Rb+1) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) -+ ... -+ (set (reg:SI Re) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) -+ (set (reg:SI FP_REGNUM) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) -+ (set (reg:SI GP_REGNUM) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) -+ (set (reg:SI LP_REGNUM) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) -+ (set (reg:SI SP_REGNUM) -+ (plus (reg:SI SP_REGNUM) (const_int 32)))]) */ - - /* 1. Consecutive registers push/pop operations. -- We need to calculate how many registers should be consecutive. -- The $sp adjustment rtx, $fp push rtx, $gp push rtx, -- and $lp push rtx are excluded. */ -+ We need to calculate how many registers should be consecutive. -+ The $sp adjustment rtx, $fp push rtx, $gp push rtx, -+ and $lp push rtx are excluded. */ - - /* Detect whether we have $fp, $gp, or $lp in the parallel rtx. */ - save_fp = reg_mentioned_p (gen_rtx_REG (SImode, FP_REGNUM), op); -@@ -238,19 +295,19 @@ nds32_valid_stack_push_pop_p (rtx op, bool push_p) - first_regno = REGNO (elt_reg); - - /* The 'push' operation is a kind of store operation. -- The 'pop' operation is a kind of load operation. -- Pass corresponding false/true as second argument (bool load_p). -- The par_index is supposed to start with index 0. */ -+ The 'pop' operation is a kind of load operation. -+ Pass corresponding false/true as second argument (bool load_p). -+ The par_index is supposed to start with index 0. */ - if (!nds32_consecutive_registers_load_store_p (op, - !push_p ? true : false, - 0, - first_regno, - rest_count)) -- return false; -+ return false; - } - - /* 2. Valid $fp/$gp/$lp push/pop operations. -- Remember to set start index for checking them. */ -+ Remember to set start index for checking them. */ - - /* The rest_count is the start index for checking $fp/$gp/$lp. */ - index = rest_count; -@@ -269,9 +326,9 @@ nds32_valid_stack_push_pop_p (rtx op, bool push_p) - index++; - - if (GET_CODE (elt_mem) != MEM -- || GET_CODE (elt_reg) != REG -- || REGNO (elt_reg) != FP_REGNUM) -- return false; -+ || GET_CODE (elt_reg) != REG -+ || REGNO (elt_reg) != FP_REGNUM) -+ return false; - } - if (save_gp) - { -@@ -281,9 +338,9 @@ nds32_valid_stack_push_pop_p (rtx op, bool push_p) - index++; - - if (GET_CODE (elt_mem) != MEM -- || GET_CODE (elt_reg) != REG -- || REGNO (elt_reg) != GP_REGNUM) -- return false; -+ || GET_CODE (elt_reg) != REG -+ || REGNO (elt_reg) != GP_REGNUM) -+ return false; - } - if (save_lp) - { -@@ -293,16 +350,16 @@ nds32_valid_stack_push_pop_p (rtx op, bool push_p) - index++; - - if (GET_CODE (elt_mem) != MEM -- || GET_CODE (elt_reg) != REG -- || REGNO (elt_reg) != LP_REGNUM) -- return false; -+ || GET_CODE (elt_reg) != REG -+ || REGNO (elt_reg) != LP_REGNUM) -+ return false; - } - - /* 3. The last element must be stack adjustment rtx. -- Its form of rtx should be: -- (set (reg:SI SP_REGNUM) -- (plus (reg:SI SP_REGNUM) (const_int X))) -- The X could be positive or negative value. */ -+ Its form of rtx should be: -+ (set (reg:SI SP_REGNUM) -+ (plus (reg:SI SP_REGNUM) (const_int X))) -+ The X could be positive or negative value. */ - - /* Pick up the last element. */ - elt = XVECEXP (op, 0, total_count - 1); -@@ -322,54 +379,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_PERF_EXT && (one_bit_count == 1)); -+ 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_PERF_EXT && (one_bit_count == 1)); -+ 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_PERF_EXT && (one_bit_count == 1)); -+ 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 -@@ -381,4 +441,286 @@ nds32_can_use_bitci_p (int ival) - && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode))); - } - -+/* Return true if is load/store with SYMBOL_REF addressing mode -+ and memory mode is SImode. */ -+bool -+nds32_symbol_load_store_p (rtx_insn *insn) -+{ -+ rtx mem_src = NULL_RTX; -+ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD: -+ mem_src = SET_SRC (PATTERN (insn)); -+ break; -+ case TYPE_STORE: -+ mem_src = SET_DEST (PATTERN (insn)); -+ break; -+ default: -+ break; -+ } -+ -+ /* Find load/store insn with addressing mode is SYMBOL_REF. */ -+ if (mem_src != NULL_RTX) -+ { -+ if ((GET_CODE (mem_src) == ZERO_EXTEND) -+ || (GET_CODE (mem_src) == SIGN_EXTEND)) -+ mem_src = XEXP (mem_src, 0); -+ -+ if ((GET_CODE (XEXP (mem_src, 0)) == SYMBOL_REF) -+ || (GET_CODE (XEXP (mem_src, 0)) == LO_SUM)) -+ return true; -+ } -+ -+ return false; -+} -+ -+/* Vaild memory operand for floating-point loads and stores */ -+bool -+nds32_float_mem_operand_p (rtx op) -+{ -+ enum machine_mode mode = GET_MODE (op); -+ rtx addr = XEXP (op, 0); -+ -+ /* Not support [symbol] [const] memory */ -+ if (GET_CODE (addr) == SYMBOL_REF -+ || GET_CODE (addr) == CONST -+ || GET_CODE (addr) == LO_SUM) -+ return false; -+ -+ if (GET_CODE (addr) == PLUS) -+ { -+ if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF) -+ return false; -+ -+ /* Restrict const range: (imm12s << 2) */ -+ if (GET_CODE (XEXP (addr, 1)) == CONST_INT) -+ { -+ if ((mode == SImode || mode == SFmode) -+ && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (XEXP (addr, 1))) -+ && !satisfies_constraint_Is14 ( XEXP(addr, 1))) -+ return false; -+ -+ if ((mode == DImode || mode == DFmode) -+ && NDS32_DOUBLE_WORD_ALIGN_P (INTVAL (XEXP (addr, 1))) -+ && !satisfies_constraint_Is14 (XEXP (addr, 1))) -+ return false; -+ } -+ } -+ -+ return true; -+} -+ -+int -+nds32_cond_move_p (rtx cmp_rtx) -+{ -+ enum machine_mode cmp0_mode = GET_MODE (XEXP (cmp_rtx, 0)); -+ enum machine_mode cmp1_mode = GET_MODE (XEXP (cmp_rtx, 1)); -+ enum rtx_code cond = GET_CODE (cmp_rtx); -+ -+ if ((cmp0_mode == DFmode || cmp0_mode == SFmode) -+ && (cmp1_mode == DFmode || cmp1_mode == SFmode) -+ && (cond == ORDERED || cond == UNORDERED)) -+ return true; -+ return false; -+} -+ -+/* Return true if the addresses in mem1 and mem2 are suitable for use in -+ an fldi or fsdi instruction. -+ -+ This can only happen when addr1 and addr2, the addresses in mem1 -+ and mem2, are consecutive memory locations (addr1 + 4 == addr2). -+ addr1 must also be aligned on a 64-bit boundary. */ -+bool -+nds32_memory_merge_peep_p (rtx mem1, rtx mem2) -+{ -+ rtx addr1, addr2; -+ unsigned int reg1; -+ HOST_WIDE_INT offset1; -+ -+ /* The mems cannot be volatile. */ -+ if (MEM_VOLATILE_P (mem1) || MEM_VOLATILE_P (mem2)) -+ return false; -+ -+ /* MEM1 should be aligned on a 64-bit boundary. */ -+ if (MEM_ALIGN (mem1) < 64) -+ return false; -+ -+ addr1 = XEXP (mem1, 0); -+ addr2 = XEXP (mem2, 0); -+ -+ /* Extract a register number and offset (if used) from the first addr. */ -+ if (GET_CODE (addr1) == PLUS) -+ { -+ if (GET_CODE (XEXP (addr1, 0)) != REG) -+ return false; -+ else -+ { -+ reg1 = REGNO (XEXP (addr1, 0)); -+ if (GET_CODE (XEXP (addr1, 1)) != CONST_INT) -+ return false; -+ -+ offset1 = INTVAL (XEXP (addr1, 1)); -+ } -+ } -+ else if (GET_CODE (addr1) != REG) -+ return false; -+ else -+ { -+ reg1 = REGNO (addr1); -+ /* This was a simple (mem (reg)) expression. Offset is 0. */ -+ offset1 = 0; -+ } -+ /* Make sure the second address is a (mem (plus (reg) (const_int). */ -+ if (GET_CODE (addr2) != PLUS) -+ return false; -+ -+ if (GET_CODE (XEXP (addr2, 0)) != REG -+ || GET_CODE (XEXP (addr2, 1)) != CONST_INT) -+ return false; -+ -+ if (reg1 != REGNO (XEXP (addr2, 0))) -+ return false; -+ -+ /* The first offset must be evenly divisible by 8 to ensure the -+ address is 64 bit aligned. */ -+ if (offset1 % 8 != 0) -+ return false; -+ -+ /* The offset for the second addr must be 4 more than the first addr. */ -+ if (INTVAL (XEXP (addr2, 1)) != offset1 + 4) -+ return false; -+ -+ return true; -+} -+ -+bool -+nds32_const_double_range_ok_p (rtx op, enum machine_mode mode, -+ HOST_WIDE_INT lower, HOST_WIDE_INT upper) -+{ -+ if (GET_CODE (op) != CONST_DOUBLE -+ || GET_MODE (op) != mode) -+ return false; -+ -+ const REAL_VALUE_TYPE *rv; -+ long val; -+ -+ rv = CONST_DOUBLE_REAL_VALUE (op); -+ REAL_VALUE_TO_TARGET_SINGLE (*rv, val); -+ -+ 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 V2HImode: -+ mask = 0xffff; -+ shift_adv = 16; -+ nelem = 2; -+ break; -+ case 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 d66749d..19e69e3 100644 ---- a/gcc/config/nds32/nds32-protos.h -+++ b/gcc/config/nds32/nds32-protos.h -@@ -28,10 +28,14 @@ extern void nds32_init_expanders (void); - - /* Register Usage. */ - -+/* -- Order of Allocation of Registers. */ -+extern void nds32_adjust_reg_alloc_order (void); -+ - /* -- How Values Fit in Registers. */ - --extern int nds32_hard_regno_nregs (int, machine_mode); --extern int nds32_hard_regno_mode_ok (int, machine_mode); -+extern int nds32_hard_regno_nregs (int, enum machine_mode); -+extern int nds32_hard_regno_mode_ok (int, enum machine_mode); -+extern int nds32_modes_tieable_p (enum machine_mode, enum machine_mode); - - - /* Register Classes. */ -@@ -43,6 +47,7 @@ extern enum reg_class nds32_regno_reg_class (int); - - /* -- Basic Stack Layout. */ - -+extern rtx nds32_dynamic_chain_address (rtx); - extern rtx nds32_return_addr_rtx (int, rtx); - - /* -- Eliminating Frame Pointer and Arg Pointer. */ -@@ -61,22 +66,88 @@ extern void nds32_expand_prologue (void); - extern void nds32_expand_epilogue (bool); - extern void nds32_expand_prologue_v3push (void); - extern void nds32_expand_epilogue_v3pop (bool); -+extern void nds32_emit_push_fpr_callee_saved (int); -+extern void nds32_emit_pop_fpr_callee_saved (int); -+extern void nds32_emit_v3pop_fpr_callee_saved (int); -+ -+/* Controlling Debugging Information Format. */ -+ -+extern unsigned int nds32_dbx_register_number (unsigned int); - - /* ------------------------------------------------------------------------ */ - --/* Auxiliary functions for auxiliary macros in nds32.h. */ -+/* Auxiliary functions for manipulation DI mode. */ - --extern bool nds32_ls_333_p (rtx, rtx, rtx, machine_mode); -+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. */ - --extern rtx nds32_expand_load_multiple (int, int, rtx, rtx); --extern rtx nds32_expand_store_multiple (int, int, rtx, rtx); --extern int nds32_expand_movmemqi (rtx, rtx, rtx, rtx); -+extern rtx nds32_expand_load_multiple (int, int, rtx, rtx, bool, rtx *); -+extern rtx nds32_expand_store_multiple (int, int, rtx, rtx, bool, rtx *); -+extern bool nds32_expand_movmemsi (rtx, rtx, rtx, rtx); -+extern bool nds32_expand_setmem (rtx, rtx, rtx, rtx, rtx, rtx); -+extern bool nds32_expand_movstr (rtx, rtx, rtx); -+extern bool nds32_expand_strlen (rtx, rtx, rtx, rtx); - - /* Auxiliary functions for multiple load/store predicate checking. */ - --extern bool nds32_valid_multiple_load_store (rtx, bool); -+extern bool nds32_valid_multiple_load_store_p (rtx, bool, bool); -+ -+/* Auxiliary functions for guard function checking in pipelines.md. */ -+ -+extern bool nds32_n7_load_to_ii_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n7_last_load_to_ii_p (rtx_insn *, rtx_insn *); -+ -+extern bool nds32_n8_load_to_ii_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n8_load_bi_to_ii_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n8_load_to_ex_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n8_ex_to_ii_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n8_last_load_to_ii_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n8_last_load_two_to_ii_p (rtx_insn *, rtx_insn *); -+extern bool nds32_n8_last_load_to_ex_p (rtx_insn *, rtx_insn *); -+ -+extern bool nds32_e8_load_to_ii_p (rtx_insn *, rtx_insn *); -+extern bool nds32_e8_load_to_ex_p (rtx_insn *, rtx_insn *); -+extern bool nds32_e8_ex_to_ii_p (rtx_insn *, rtx_insn *); -+extern bool nds32_e8_last_load_to_ii_p (rtx_insn *, rtx_insn *); -+extern bool nds32_e8_last_load_to_ex_p (rtx_insn *, rtx_insn *); -+ -+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 *); -+ -+extern bool nds32_pn_e2_to_e1_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_e3_to_e1_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_e3_to_e2_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_e4_to_e1_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_e4_to_e2_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_e4_to_e3_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_wb_to_e1_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_wb_to_e2_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_wb_to_e3_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_wb_to_e4_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_last_load_to_e1_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_last_load_to_e2_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_last_load_to_e3_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_last_two_load_to_e1_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_last_two_load_to_e2_p (rtx_insn *, rtx_insn *); -+extern bool nds32_pn_last_three_load_to_e1_p (rtx_insn *, rtx_insn *); - - /* Auxiliary functions for stack operation predicate checking. */ - -@@ -84,55 +155,176 @@ 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); - --/* Auxiliary function for 'Computing the Length of an Insn'. */ -+extern bool nds32_const_double_range_ok_p (rtx, enum machine_mode, -+ HOST_WIDE_INT, HOST_WIDE_INT); - --extern int nds32_adjust_insn_length (rtx_insn *, int); -+extern bool nds32_const_unspec_p (rtx x); - - /* 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. */ - - extern const char *nds32_output_casesi_pc_relative (rtx *); - extern const char *nds32_output_casesi (rtx *); - -+/* Auxiliary functions for conditional branch generation. */ -+ -+extern enum nds32_expand_result_type nds32_expand_cbranch (rtx *); -+extern enum nds32_expand_result_type nds32_expand_cstore (rtx *); -+extern void nds32_expand_float_cbranch (rtx *); -+extern void nds32_expand_float_cstore (rtx *); -+ -+/* Auxiliary functions for conditional move generation. */ -+ -+extern enum nds32_expand_result_type nds32_expand_movcc (rtx *); -+extern void nds32_expand_float_movcc (rtx *); -+ -+/* Auxiliary functions for expand unalign load instruction. */ -+ -+extern void nds32_expand_unaligned_load (rtx *, enum machine_mode); -+ -+/* 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 unalign store instruction. */ -+ -+extern void nds32_expand_unaligned_store (rtx *, enum machine_mode); -+ -+/* 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); -+ -+/* Auxiliary functions to identify address for peephole2 merge instruction. */ -+ -+extern bool nds32_memory_merge_peep_p (rtx, rtx); -+ - /* Auxiliary functions to identify 16 bit addresing mode. */ - - extern enum nds32_16bit_address_type nds32_mem_format (rtx); - -+/* Auxiliary functions to identify floating-point addresing mode. */ -+ -+extern bool nds32_float_mem_operand_p (rtx); -+ - /* Auxiliary functions to output assembly code. */ - - extern const char *nds32_output_16bit_store (rtx *, int); - extern const char *nds32_output_16bit_load (rtx *, int); - extern const char *nds32_output_32bit_store (rtx *, int); - extern const char *nds32_output_32bit_load (rtx *, int); --extern const char *nds32_output_32bit_load_s (rtx *, int); -+extern const char *nds32_output_32bit_load_se (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 *); -+extern const char *nds32_output_cbranchsi4_equality_reg (rtx_insn *, rtx *); -+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. */ - - 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. */ -+ -+extern void nds32_expand_constant (enum machine_mode, -+ HOST_WIDE_INT, rtx, rtx); - - /* Auxiliary functions to check using return with null epilogue. */ - - extern int nds32_can_use_return_insn (void); -+extern enum machine_mode nds32_case_vector_shorten_mode (int, int, rtx); - - /* Auxiliary functions to decide output alignment or not. */ - - extern int nds32_target_alignment (rtx); -+extern unsigned int nds32_data_alignment (tree, unsigned int); -+extern unsigned int nds32_constant_alignment (tree, unsigned int); -+extern unsigned int nds32_local_alignment (tree, unsigned int); - - /* Auxiliary functions to expand builtin functions. */ - - extern void nds32_init_builtins_impl (void); - extern rtx nds32_expand_builtin_impl (tree, rtx, rtx, -- machine_mode, int); -+ enum machine_mode, int); -+extern tree nds32_builtin_decl_impl (unsigned, bool); - - /* Auxiliary functions for ISR implementation. */ - -@@ -141,10 +333,86 @@ 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); -+extern int nds32_address_cost_impl (rtx, enum machine_mode, addr_space_t, bool); -+extern struct register_pass_info insert_pass_fp_as_gp; -+ -+extern int nds32_adjust_insn_length (rtx_insn *, int); -+ -+/* 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); -+ -+/* Auxiliary functions for register rename pass. */ -+extern reg_class_t nds32_preferred_rename_class_impl (reg_class_t); -+ -+extern bool nds32_split_double_word_load_store_p (rtx *,bool); -+ -+namespace nds32 { -+ -+extern rtx extract_pattern_from_insn (rtx); -+ -+size_t parallel_elements (rtx); -+rtx parallel_element (rtx, int); -+ -+bool insn_pseudo_nop_p (rtx_insn *); -+bool insn_executable_p (rtx_insn *); -+rtx_insn *prev_executable_insn (rtx_insn *); -+rtx_insn *next_executable_insn (rtx_insn *); -+rtx_insn *prev_executable_insn_local (rtx_insn *); -+rtx_insn *next_executable_insn_local (rtx_insn *); -+bool insn_deleted_p (rtx_insn *); -+ -+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 load_full_word_p (rtx_insn *); -+bool load_partial_word_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_insn *); -+ -+bool movd44_insn_p (rtx_insn *); -+rtx extract_movd44_even_reg (rtx_insn *); -+rtx extract_movd44_odd_reg (rtx_insn *); -+ -+rtx extract_mac_acc_rtx (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 *); -+ -+void compute_bb_for_insn_safe (); -+ -+void exchange_insns (rtx_insn *, rtx_insn *); -+ -+} // namespace nds32 -+ -+extern bool nds32_include_fp_arith; - - /* ------------------------------------------------------------------------ */ -diff --git a/gcc/config/nds32/nds32-reg-utils.c b/gcc/config/nds32/nds32-reg-utils.c -new file mode 100644 -index 0000000..1fd8a83 ---- /dev/null -+++ b/gcc/config/nds32/nds32-reg-utils.c -@@ -0,0 +1,190 @@ -+ -+/* lmwsmw pass of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+/* ------------------------------------------------------------------------ */ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "hash-set.h" -+#include "machmode.h" -+#include "vec.h" -+#include "double-int.h" -+#include "input.h" -+#include "alias.h" -+#include "symtab.h" -+#include "wide-int.h" -+#include "inchash.h" -+#include "tree.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "rtl.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "input.h" -+#include "function.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "dominance.h" -+#include "cfg.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "predict.h" -+#include "basic-block.h" -+#include "bitmap.h" -+#include "df.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "ggc.h" -+#include "tree-pass.h" -+#include "target-globals.h" -+#include "ira.h" -+#include "ira-int.h" -+#include "nds32-reg-utils.h" -+ -+#define NDS32_GPR_NUM 32 -+ -+static bool debug_live_reg = false; -+ -+void -+nds32_live_regs (basic_block bb, rtx_insn *first, rtx_insn *last, bitmap *live) -+{ -+ df_ref def; -+ rtx_insn *insn; -+ bitmap_copy (*live, DF_LR_IN (bb)); -+ df_simulate_initialize_forwards (bb, *live); -+ rtx_insn *first_insn = BB_HEAD (bb); -+ -+ for (insn = first_insn; insn != first; insn = NEXT_INSN (insn)) -+ df_simulate_one_insn_forwards (bb, insn, *live); -+ -+ if (dump_file && debug_live_reg) -+ { -+ fprintf (dump_file, "scan live regs:\nfrom:\n"); -+ print_rtl_single (dump_file, first); -+ -+ fprintf (dump_file, "to:\n"); -+ print_rtl_single (dump_file, last); -+ -+ fprintf (dump_file, "bb lr in:\n"); -+ dump_bitmap (dump_file, DF_LR_IN (bb)); -+ -+ fprintf (dump_file, "init:\n"); -+ dump_bitmap (dump_file, *live); -+ } -+ -+ for (insn = first; insn != last; insn = NEXT_INSN (insn)) -+ { -+ if (!INSN_P (insn)) -+ continue; -+ -+ FOR_EACH_INSN_DEF (def, insn) -+ bitmap_set_bit (*live, DF_REF_REGNO (def)); -+ -+ if (dump_file && debug_live_reg) -+ { -+ fprintf (dump_file, "scaning:\n"); -+ print_rtl_single (dump_file, insn); -+ dump_bitmap (dump_file, *live); -+ } -+ } -+ -+ gcc_assert (INSN_P (insn)); -+ -+ FOR_EACH_INSN_DEF (def, insn) -+ bitmap_set_bit (*live, DF_REF_REGNO (def)); -+ -+ if (dump_file && debug_live_reg) -+ { -+ fprintf (dump_file, "scaning:\n"); -+ print_rtl_single (dump_file, last); -+ dump_bitmap (dump_file, *live); -+ } -+} -+ -+void -+print_hard_reg_set (FILE *file, const char *prefix, HARD_REG_SET set) -+{ -+ int i; -+ bool first = true; -+ fprintf (file, "%s{ ", prefix); -+ -+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) -+ { -+ if (TEST_HARD_REG_BIT (set, i)) -+ { -+ if (first) -+ { -+ fprintf (file, "%s", reg_names[i]); -+ first = false; -+ } -+ else -+ fprintf (file, ", %s", reg_names[i]); -+ } -+ } -+ fprintf (file, "}\n"); -+} -+ -+void -+nds32_get_available_reg_set (basic_block bb, -+ rtx_insn *first, -+ rtx_insn *last, -+ HARD_REG_SET *available_regset) -+{ -+ bitmap live; -+ HARD_REG_SET live_regset; -+ unsigned i; -+ live = BITMAP_ALLOC (®_obstack); -+ -+ nds32_live_regs (bb, first, last, &live); -+ -+ REG_SET_TO_HARD_REG_SET (live_regset, live); -+ -+ /* Reverse available_regset. */ -+ COMPL_HARD_REG_SET (*available_regset, live_regset); -+ -+ /* We only care $r0-$r31, so mask $r0-$r31. */ -+ AND_HARD_REG_SET (*available_regset, reg_class_contents[GENERAL_REGS]); -+ -+ /* Fixed register also not available. */ -+ for (i = NDS32_FIRST_GPR_REGNUM; i <= NDS32_LAST_GPR_REGNUM; ++i) -+ { -+ if (fixed_regs[i]) -+ CLEAR_HARD_REG_BIT (*available_regset, i); -+ } -+ -+ BITMAP_FREE (live); -+} -diff --git a/gcc/config/nds32/nds32-reg-utils.h b/gcc/config/nds32/nds32-reg-utils.h -new file mode 100644 -index 0000000..16c23a3 ---- /dev/null -+++ b/gcc/config/nds32/nds32-reg-utils.h -@@ -0,0 +1,61 @@ -+/* Prototypes for load-store-opt of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+#ifndef NDS32_REG_UTILS_OPT_H -+#define NDS32_REG_UTILS_OPT_H -+ -+/* Auxiliary functions for register usage analysis. */ -+extern void nds32_live_regs (basic_block, rtx_insn *, rtx_insn *, bitmap *); -+extern void print_hard_reg_set (FILE *, const char *, HARD_REG_SET); -+extern void nds32_get_available_reg_set (basic_block, rtx_insn *, -+ rtx_insn *, HARD_REG_SET *); -+ -+static inline bool -+in_reg_class_p (unsigned regno, enum reg_class clazz) -+{ -+ return TEST_HARD_REG_BIT (reg_class_contents[clazz], regno); -+} -+ -+static inline bool -+in_reg_class_p (rtx reg, enum reg_class clazz) -+{ -+ gcc_assert (REG_P (reg)); -+ return in_reg_class_p (REGNO (reg), clazz); -+} -+ -+static inline unsigned -+find_available_reg (HARD_REG_SET *available_regset, enum reg_class clazz) -+{ -+ hard_reg_set_iterator hrsi; -+ unsigned regno; -+ EXECUTE_IF_SET_IN_HARD_REG_SET (reg_class_contents[clazz], 0, regno, hrsi) -+ { -+ /* Caller-save register or callee-save register but it's ever live. */ -+ if (TEST_HARD_REG_BIT (*available_regset, regno) -+ && (call_used_regs[regno] || df_regs_ever_live_p (regno))) -+ return regno; -+ } -+ -+ return INVALID_REGNUM; -+} -+ -+ -+ -+#endif -diff --git a/gcc/config/nds32/nds32-regrename.c b/gcc/config/nds32/nds32-regrename.c -new file mode 100644 -index 0000000..0875722 ---- /dev/null -+++ b/gcc/config/nds32/nds32-regrename.c -@@ -0,0 +1,389 @@ -+/* Register rename pass of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "backend.h" -+#include "tree.h" -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" -+#include "cpplib.h" -+#include "params.h" -+#include "tree-pass.h" -+#include "regrename.h" -+ -+static reg_class_t current_preferred_rename_class = NO_REGS; -+ -+reg_class_t -+nds32_preferred_rename_class_impl (reg_class_t rclass) -+{ -+ if (rclass == GENERAL_REGS) -+ return current_preferred_rename_class; -+ else -+ return NO_REGS; -+} -+ -+static void -+print_hard_reg_set (FILE *file, HARD_REG_SET set) -+{ -+ int i; -+ -+ fprintf (file, "{ "); -+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) -+ { -+ if (TEST_HARD_REG_BIT (set, i)) -+ fprintf (file, "%d ", i); -+ } -+ fprintf (file, "}\n"); -+} -+ -+void -+dump_hard_reg_set (FILE *file, HARD_REG_SET set) -+{ -+ print_hard_reg_set (file, set); -+} -+ -+static bool -+in_reg_class_p (unsigned regno, enum reg_class clazz) -+{ -+ return TEST_HARD_REG_BIT (reg_class_contents[clazz], regno); -+} -+ -+static unsigned -+try_find_best_rename_reg (du_head_p op_chain, reg_class_t preferred_class) -+{ -+ HARD_REG_SET unavailable; -+ unsigned new_reg; -+ current_preferred_rename_class = preferred_class; -+ -+ COMPL_HARD_REG_SET (unavailable, reg_class_contents[preferred_class]); -+ CLEAR_HARD_REG_BIT (unavailable, op_chain->regno); -+ -+ new_reg = find_rename_reg (op_chain, GENERAL_REGS, -+ &unavailable, op_chain->regno, false); -+ -+ current_preferred_rename_class = NO_REGS; -+ return new_reg; -+} -+ -+static bool -+try_rename_operand_to (rtx insn, unsigned op_pos, -+ reg_class_t preferred_rename_class) -+{ -+ insn_rr_info *info; -+ du_head_p op_chain; -+ unsigned newreg; -+ unsigned oldreg; -+ -+ info = &insn_rr[INSN_UID (insn)]; -+ -+ if (info->op_info == NULL) -+ return false; -+ -+ if (info->op_info[op_pos].n_chains == 0) -+ return false; -+ -+ op_chain = regrename_chain_from_id (info->op_info[op_pos].heads[0]->id); -+ -+ if (op_chain->cannot_rename) -+ return false; -+ -+ /* Already use preferred class, so do nothing. */ -+ if (TEST_HARD_REG_BIT (reg_class_contents[preferred_rename_class], -+ op_chain->regno)) -+ return false; -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "Try to rename operand %d to %s:\n", -+ op_pos, reg_class_names[preferred_rename_class]); -+ print_rtl_single (dump_file, insn); -+ } -+ -+ oldreg = op_chain->regno; -+ newreg = try_find_best_rename_reg (op_chain, preferred_rename_class); -+ -+ if (newreg == oldreg) -+ return false; -+ -+ regrename_do_replace (op_chain, newreg); -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "Rename operand %d to %s is Done:\n", -+ op_pos, reg_class_names[preferred_rename_class]); -+ print_rtl_single (dump_file, insn); -+ } -+ return true; -+} -+ -+static bool -+rename_slt_profitlable (rtx insn) -+{ -+ rtx pattern; -+ pattern = PATTERN (insn); -+ rtx src = SET_SRC (pattern); -+ rtx op0 = XEXP (src, 0); -+ rtx op1 = XEXP (src, 0); -+ -+ insn_rr_info *info; -+ du_head_p op_chain; -+ int op_pos = 0; -+ -+ info = &insn_rr[INSN_UID (insn)]; -+ -+ if (info->op_info == NULL) -+ return false; -+ -+ if (info->op_info[op_pos].n_chains == 0) -+ return false; -+ -+ op_chain = regrename_chain_from_id (info->op_info[op_pos].heads[0]->id); -+ -+ if (in_reg_class_p (op_chain->regno, R15_TA_REG)) -+ return false; -+ -+ /* slt[s]45 need second operand in MIDDLE_REGS class. */ -+ if (!REG_P (op0) || !in_reg_class_p (REGNO (op0), MIDDLE_REGS)) -+ return false; -+ -+ /* slt[s]i45 only allow 5 bit unsigned integer. */ -+ if (REG_P (op1) -+ || (CONST_INT_P (op1) && satisfies_constraint_Iu05 (op1))) -+ return true; -+ -+ return false; -+} -+ -+static bool -+rename_cbranch_eq0_low_reg_profitlable (rtx insn) -+{ -+ insn_rr_info *info; -+ du_head_p op_chain; -+ int op_pos = 1; -+ -+ info = &insn_rr[INSN_UID (insn)]; -+ -+ if (info->op_info == NULL) -+ return false; -+ -+ if (info->op_info[op_pos].n_chains == 0) -+ return false; -+ -+ op_chain = regrename_chain_from_id (info->op_info[op_pos].heads[0]->id); -+ -+ if (in_reg_class_p (op_chain->regno, LOW_REGS)) -+ return false; -+ -+ return true; -+} -+ -+ -+static bool -+rename_cbranch_eq0_r15_profitlable (rtx insn) -+{ -+ rtx pattern; -+ pattern = PATTERN (insn); -+ rtx if_then_else = SET_SRC (pattern); -+ rtx cond = XEXP (if_then_else, 0); -+ rtx op0 = XEXP (cond, 0); -+ -+ insn_rr_info *info; -+ du_head_p op_chain; -+ int op_pos = 1; -+ -+ info = &insn_rr[INSN_UID (insn)]; -+ -+ if (info->op_info == NULL) -+ return false; -+ -+ if (info->op_info[op_pos].n_chains == 0) -+ return false; -+ -+ op_chain = regrename_chain_from_id (info->op_info[op_pos].heads[0]->id); -+ -+ if (in_reg_class_p (op_chain->regno, R15_TA_REG)) -+ return false; -+ -+ /* LOW_REGS or R15_TA_REG both are 2-byte instruction. */ -+ if (REG_P (op0) && in_reg_class_p (REGNO (op0), LOW_REGS)) -+ return false; -+ -+ return true; -+} -+ -+static bool -+rename_cbranch_eq_reg_profitlable (rtx insn) -+{ -+ rtx pattern; -+ pattern = PATTERN (insn); -+ rtx if_then_else = SET_SRC (pattern); -+ rtx cond = XEXP (if_then_else, 0); -+ rtx op1 = XEXP (cond, 1); -+ -+ insn_rr_info *info; -+ du_head_p op_chain; -+ int op_pos = 1; -+ -+ info = &insn_rr[INSN_UID (insn)]; -+ -+ if (info->op_info == NULL) -+ return false; -+ -+ if (info->op_info[op_pos].n_chains == 0) -+ return false; -+ -+ op_chain = regrename_chain_from_id (info->op_info[op_pos].heads[0]->id); -+ -+ if (in_reg_class_p (op_chain->regno, R5_REG)) -+ return false; -+ -+ if (REG_P (op1) && in_reg_class_p (REGNO (op1), LOW_REGS)) -+ return true; -+ else -+ return false; -+} -+ -+static void -+do_regrename () -+{ -+ basic_block bb; -+ rtx_insn *insn; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (!INSN_P (insn)) -+ continue; -+ -+ switch (recog_memoized (insn)) -+ { -+ case CODE_FOR_slts_compare_impl: -+ case CODE_FOR_slt_compare_impl: -+ /* Try to rename operand 0 to $r15 if profitable. */ -+ if (rename_slt_profitlable (insn)) -+ try_rename_operand_to (insn, 0, R15_TA_REG); -+ break; -+ case CODE_FOR_slt_eq0: -+ /* Try to rename operand 0 to $r15. */ -+ if (rename_slt_profitlable (insn)) -+ try_rename_operand_to (insn, 0, R15_TA_REG); -+ break; -+ case CODE_FOR_cbranchsi4_equality_zero: -+ /* Try to rename operand 1 to $r15. */ -+ if (rename_cbranch_eq0_r15_profitlable (insn)) -+ if (!try_rename_operand_to (insn, 1, R15_TA_REG)) -+ if (rename_cbranch_eq0_low_reg_profitlable (insn)) -+ try_rename_operand_to (insn, 1, LOW_REGS); -+ break; -+ case CODE_FOR_cbranchsi4_equality_reg: -+ case CODE_FOR_cbranchsi4_equality_reg_or_const_int: -+ /* Try to rename operand 1 to $r5. */ -+ if (rename_cbranch_eq_reg_profitlable (insn)) -+ try_rename_operand_to (insn, 1, R5_REG); -+ break; -+ } -+ } -+ } -+} -+ -+static unsigned int -+nds32_regrename (void) -+{ -+ df_set_flags (DF_LR_RUN_DCE); -+ df_note_add_problem (); -+ df_analyze (); -+ df_set_flags (DF_DEFER_INSN_RESCAN); -+ -+ regrename_init (true); -+ -+ regrename_analyze (NULL); -+ -+ do_regrename (); -+ -+ regrename_finish (); -+ return 1; -+} -+ -+const pass_data pass_data_nds32_regrename = -+{ -+ RTL_PASS, /* type */ -+ "nds32-regrename", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ 0, /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_df_finish, /* todo_flags_finish */ -+}; -+ -+class pass_nds32_regrename_opt : public rtl_opt_pass -+{ -+public: -+ pass_nds32_regrename_opt (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_regrename, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { return TARGET_16_BIT && TARGET_REGRENAME_OPT; } -+ unsigned int execute (function *) { return nds32_regrename (); } -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_regrename_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_regrename_opt (ctxt); -+} -diff --git a/gcc/config/nds32/nds32-relax-opt.c b/gcc/config/nds32/nds32-relax-opt.c -new file mode 100644 -index 0000000..0919af6 ---- /dev/null -+++ b/gcc/config/nds32/nds32-relax-opt.c -@@ -0,0 +1,612 @@ -+/* relax-opt pass of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "hash-set.h" -+#include "machmode.h" -+#include "vec.h" -+#include "double-int.h" -+#include "input.h" -+#include "alias.h" -+#include "symtab.h" -+#include "wide-int.h" -+#include "inchash.h" -+#include "tree.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "rtl.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload (). */ -+#include "flags.h" -+#include "input.h" -+#include "function.h" -+#include "emit-rtl.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "dominance.h" -+#include "cfg.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "predict.h" -+#include "basic-block.h" -+#include "bitmap.h" -+#include "df.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function (). */ -+#include "ggc.h" -+#include "tree-pass.h" -+#include "target-globals.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; -+ -+/* Group the following pattern as relax candidates: -+ -+ 1. sethi $ra, hi20(sym) -+ ori $ra, $ra, lo12(sym) -+ ==> -+ addi.gp $ra, sym -+ -+ 2. sethi $ra, hi20(sym) -+ lwi $rb, [$ra + lo12(sym)] -+ ==> -+ lwi.gp $rb, [(sym)] -+ -+ 3. sethi $ra, hi20(sym) -+ ori $ra, $ra, lo12(sym) -+ lwi $rb, [$ra] -+ swi $rc, [$ra] -+ ==> -+ lwi37 $rb, [(sym)] -+ swi37 $rc, [(sym)] */ -+ -+/* Return true if is load/store with REG addressing mode -+ and memory mode is SImode. */ -+static bool -+nds32_reg_base_load_store_p (rtx_insn *insn) -+{ -+ rtx mem_src = NULL_RTX; -+ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD: -+ mem_src = SET_SRC (PATTERN (insn)); -+ break; -+ case TYPE_STORE: -+ mem_src = SET_DEST (PATTERN (insn)); -+ break; -+ default: -+ break; -+ } -+ -+ /* Find load/store insn with addressing mode is REG. */ -+ if (mem_src != NULL_RTX) -+ { -+ if ((GET_CODE (mem_src) == ZERO_EXTEND) -+ || (GET_CODE (mem_src) == SIGN_EXTEND)) -+ mem_src = XEXP (mem_src, 0); -+ -+ if (GET_CODE (XEXP (mem_src, 0)) == REG) -+ return true; -+ } -+ -+ return false; -+} -+ -+/* Return true if insn is a sp/fp base or sp/fp plus load-store instruction. */ -+ -+static bool -+nds32_sp_base_or_plus_load_store_p (rtx_insn *insn) -+{ -+ rtx mem_src = NULL_RTX; -+ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD: -+ mem_src = SET_SRC (PATTERN (insn)); -+ break; -+ case TYPE_STORE: -+ mem_src = SET_DEST (PATTERN (insn)); -+ break; -+ default: -+ break; -+ } -+ /* Find load/store insn with addressing mode is REG. */ -+ if (mem_src != NULL_RTX) -+ { -+ if ((GET_CODE (mem_src) == ZERO_EXTEND) -+ || (GET_CODE (mem_src) == SIGN_EXTEND)) -+ mem_src = XEXP (mem_src, 0); -+ -+ if ((GET_CODE (XEXP (mem_src, 0)) == PLUS)) -+ mem_src = XEXP (mem_src, 0); -+ -+ if (REG_P (XEXP (mem_src, 0)) -+ && ((frame_pointer_needed -+ && REGNO (XEXP (mem_src, 0)) == FP_REGNUM) -+ || REGNO (XEXP (mem_src, 0)) == SP_REGNUM)) -+ return true; -+ } -+ -+ return false; -+} -+ -+/* Return true if is load with [REG + REG/CONST_INT] addressing mode. */ -+static bool -+nds32_plus_reg_load_store_p (rtx_insn *insn) -+{ -+ rtx mem_src = NULL_RTX; -+ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD: -+ mem_src = SET_SRC (PATTERN (insn)); -+ break; -+ case TYPE_STORE: -+ mem_src = SET_DEST (PATTERN (insn)); -+ break; -+ default: -+ break; -+ } -+ -+ /* Find load/store insn with addressing mode is [REG + REG/CONST]. */ -+ if (mem_src != NULL_RTX) -+ { -+ if ((GET_CODE (mem_src) == ZERO_EXTEND) -+ || (GET_CODE (mem_src) == SIGN_EXTEND)) -+ mem_src = XEXP (mem_src, 0); -+ -+ if ((GET_CODE (XEXP (mem_src, 0)) == PLUS)) -+ mem_src = XEXP (mem_src, 0); -+ else -+ return false; -+ -+ if (GET_CODE (XEXP (mem_src, 0)) == REG) -+ return true; -+ -+ } -+ -+ return false; -+} -+ -+/* Return true if ins is hwloop last instruction. */ -+static bool -+nds32_hwloop_last_insn_p (rtx_insn *insn) -+{ -+ if (recog_memoized (insn) == CODE_FOR_hwloop_last_insn) -+ return true; -+ -+ 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) -+{ -+ df_ref def_record, use_record; -+ df_link *link; -+ rtx_insn *use_insn = NULL; -+ rtx group_id; -+ bool valid; -+ -+ def_record = DF_INSN_DEFS (sethi); -+ -+ 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 (sethi))) -+ 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; -+ -+ /* Initial use_insn_type. */ -+ if (!(recog_memoized (use_insn) == CODE_FOR_lo_sum -+ || nds32_symbol_load_store_p (use_insn) -+ || (nds32_reg_base_load_store_p (use_insn) -+ &&!nds32_sp_base_or_plus_load_store_p (use_insn)))) -+ return; -+ } -+ -+ group_id = GEN_INT (relax_group_id); -+ /* Insert .relax_* directive for sethi. */ -+ emit_insn_before (gen_relax_group (group_id), sethi); -+ -+ /* 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. */ -+ 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++; -+} -+ -+/* Group the relax candidate instructions for linker. */ -+static void -+nds32_relax_group (void) -+{ -+ rtx_insn *insn; -+ -+ compute_bb_for_insn (); -+ -+ df_chain_add_problem (DF_DU_CHAIN | DF_UD_CHAIN); -+ df_insn_rescan_all (); -+ df_analyze (); -+ df_set_flags (DF_DEFER_INSN_RESCAN); -+ calculate_dominance_info (CDI_DOMINATORS); -+ -+ insn = get_insns (); -+ gcc_assert (NOTE_P (insn)); -+ -+ for (insn = next_active_insn (insn); insn; insn = next_active_insn (insn)) -+ { -+ if (NONJUMP_INSN_P (insn)) -+ { -+ /* Find sethi ra, symbol instruction. */ -+ if (recog_memoized (insn) == CODE_FOR_sethi -+ && nds32_symbolic_operand (XEXP (SET_SRC (PATTERN (insn)), 0), -+ SImode) -+ && !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0)) -+ && !nds32_hwloop_last_insn_p (next_active_insn (insn))) -+ -+ 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_hwloop_last_insn_p (next_active_insn (insn))) -+ { -+ nds32_group_float_insns (insn); -+ } -+ } -+ else if (CALL_P (insn) && recog_memoized (insn) == CODE_FOR_tls_desc) -+ { -+ nds32_group_tls_insn (insn); -+ } -+ } -+ -+ /* We must call df_finish_pass manually because it should be invoked before -+ BB information is destroyed. Hence we cannot set the TODO_df_finish flag -+ to the pass manager. */ -+ df_insn_rescan_all (); -+ df_finish_pass (false); -+ free_dominance_info (CDI_DOMINATORS); -+} -+ -+static unsigned int -+nds32_relax_opt (void) -+{ -+ if (TARGET_RELAX_HINT) -+ nds32_relax_group (); -+ return 1; -+} -+ -+const pass_data pass_data_nds32_relax_opt = -+{ -+ RTL_PASS, /* type */ -+ "relax_opt", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ 0, /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_df_finish, /* todo_flags_finish */ -+}; -+ -+class pass_nds32_relax_opt : public rtl_opt_pass -+{ -+public: -+ pass_nds32_relax_opt (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_relax_opt, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { return TARGET_RELAX_HINT; } -+ unsigned int execute (function *) { return nds32_relax_opt (); } -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_relax_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_relax_opt (ctxt); -+} -diff --git a/gcc/config/nds32/nds32-scalbn-transform.c b/gcc/config/nds32/nds32-scalbn-transform.c -new file mode 100644 -index 0000000..fba7c6f ---- /dev/null -+++ b/gcc/config/nds32/nds32-scalbn-transform.c -@@ -0,0 +1,364 @@ -+/* A Gimple-level pass of Andes NDS32 cpu for GNU compiler. -+ This pass transforms the multiplications whose multiplier is a -+ power of 2. -+ -+ Copyright (C) 2012-2016 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 -+. */ -+ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "hash-set.h" -+#include "machmode.h" -+#include "vec.h" -+#include "double-int.h" -+#include "input.h" -+#include "alias.h" -+#include "symtab.h" -+#include "wide-int.h" -+#include "inchash.h" -+#include "tree.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "rtl.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload (). */ -+#include "flags.h" -+#include "input.h" -+#include "function.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "dominance.h" -+#include "cfg.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "predict.h" -+#include "basic-block.h" -+#include "bitmap.h" -+#include "df.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function (). */ -+#include "ggc.h" -+#include "tree-pass.h" -+#include "tree-ssa-alias.h" -+#include "fold-const.h" -+#include "gimple-expr.h" -+#include "is-a.h" -+#include "gimple.h" -+#include "gimplify.h" -+#include "gimple-iterator.h" -+#include "gimplify-me.h" -+#include "gimple-ssa.h" -+#include "ipa-ref.h" -+#include "lto-streamer.h" -+#include "cgraph.h" -+#include "tree-cfg.h" -+#include "tree-phinodes.h" -+#include "stringpool.h" -+#include "tree-ssanames.h" -+#include "tree-pass.h" -+#include "gimple-pretty-print.h" -+#include "gimple-fold.h" -+ -+ -+/* Return true if the current function name is scalbn/scalbnf, or its alias -+ includes scalbn/scalbnf, otherwise return false. */ -+ -+static bool -+nds32_is_scalbn_alias_func_p (void) -+{ -+ int i; -+ struct ipa_ref *ref; -+ struct cgraph_node *cfun_node; -+ -+ if (!strcmp (function_name (cfun), "scalbn") -+ || !strcmp (function_name (cfun), "scalbnf")) -+ return true; -+ -+ cfun_node = cgraph_node::get (current_function_decl); -+ -+ if (!cfun_node) -+ return false; -+ -+ for (i = 0; cfun_node->iterate_referring (i, ref); i++) -+ if (ref->use == IPA_REF_ALIAS) -+ { -+ struct cgraph_node *alias = dyn_cast (ref->referring); -+ if (!strcmp (alias->asm_name (), "scalbn") -+ || !strcmp (alias->asm_name (), "scalbnf")) -+ return true; -+ } -+ -+ return false; -+} -+ -+/* Return true if value of tree node RT is power of 2. */ -+ -+static bool -+nds32_real_ispow2_p (tree rt) -+{ -+ if (TREE_CODE (rt) != REAL_CST) -+ return false; -+ -+ if (TREE_REAL_CST_PTR (rt)->cl != rvc_normal) -+ return false; -+ -+ int i; -+ for (i = 0; i < SIGSZ-1; ++i) -+ if (TREE_REAL_CST_PTR (rt)->sig[i] != 0) -+ return false; -+ if (TREE_REAL_CST_PTR (rt)->sig[SIGSZ-1] != SIG_MSB) -+ return false; -+ -+ return true; -+} -+ -+/* Return the exponent of tree node RT in base 2. */ -+ -+static int -+nds32_real_pow2exp (tree rt) -+{ -+ return REAL_EXP (TREE_REAL_CST_PTR (rt)) - 1; -+} -+ -+/* Return true if GS is the target of scalbn transform. */ -+ -+static bool -+nds32_scalbn_transform_target_p (gimple *gs) -+{ -+ if (is_gimple_assign (gs)) -+ if ((gimple_assign_rhs_code (gs) == MULT_EXPR) -+ && (TREE_CODE (TREE_TYPE (gimple_assign_rhs1 (gs))) == REAL_TYPE) -+ && nds32_real_ispow2_p (gimple_assign_rhs2 (gs))) -+ return true; -+ return false; -+} -+ -+/* Do scalbn transform for a GIMPLE statement GS. -+ -+ When the multiplier of GIMPLE statement GS is a positive number, -+ GS will be transform to one gimple_call statement and one -+ gimple_assign statement as follows: -+ A = B * 128.0 -> temp = BUILT_IN_SCALBN (B, 7) -+ A = temp -+ -+ When the multiplier is a negative number, the multiplier will be -+ conversed the sign first since BUILT_IN_SCALBN can't handle -+ negative multiplier. The example is shown below: -+ A = B * -128.0 -> temp = BUILT_IN_SCALBN (B, 7) -+ A = -temp -+*/ -+ -+static void -+nds32_do_scalbn_transform (gimple *gs) -+{ -+ tree mult_cand = gimple_assign_rhs1 (gs); /* Multiplicand */ -+ tree mult_er = gimple_assign_rhs2 (gs); /* Multiplier */ -+ bool is_neg = false; -+ -+ /* Choose the function by type of arg. */ -+ enum built_in_function fn_name; -+ tree type = TREE_TYPE (mult_cand); -+ if (TYPE_MAIN_VARIANT (type) == double_type_node) -+ fn_name = BUILT_IN_SCALBN; -+ else if (TYPE_MAIN_VARIANT (type) == float_type_node) -+ fn_name = BUILT_IN_SCALBNF; -+ /* Do not transform long double to scalbnl since some c library don't provide -+ it if target don't have real long double type -+ else if (TYPE_MAIN_VARIANT (type) == long_double_type_node) -+ fn_name = BUILT_IN_SCALBNL; -+ */ -+ else -+ return; -+ -+ /* Converse the sign of negative number. */ -+ if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (mult_er))) -+ { -+ is_neg = true; -+ mult_er = build_real (TREE_TYPE (mult_er), -+ real_value_negate (&TREE_REAL_CST (mult_er))); -+ } -+ -+ /* Set function name for building gimple_call. */ -+ tree fndecl = builtin_decl_explicit (fn_name); -+ -+ /* Set last arg for building gimple_call. */ -+ tree exp = build_int_cst (integer_type_node, -+ nds32_real_pow2exp (mult_er)); -+ -+ /* Build a new temp ssa. */ -+ tree temp_call_ssa = make_ssa_name (TREE_TYPE (gimple_assign_lhs (gs)), NULL); -+ -+ /* Build gimple_call stmt to replace GS. */ -+ gimple *call_stmt = gimple_build_call (fndecl, -+ 2, -+ mult_cand, -+ exp); -+ gimple_call_set_lhs (call_stmt, temp_call_ssa); -+ -+ enum tree_code subcode = NOP_EXPR; -+ /* Handle negative value. */ -+ if (is_neg) -+ subcode = NEGATE_EXPR; -+ -+ /* Build gimple_assign for return value or change the sign. */ -+ gimple *assign_stmt = -+ gimple_build_assign (gimple_assign_lhs (gs), -+ subcode, -+ gimple_call_lhs (call_stmt)); -+ -+ /* Replace gimple_assign GS by new gimple_call. */ -+ gimple_stmt_iterator gsi = gsi_for_stmt (gs); -+ update_stmt (call_stmt); -+ gsi_insert_before (&gsi, call_stmt, GSI_NEW_STMT); -+ -+ /* Insert the gimple_assign after the scalbn call. */ -+ update_stmt (assign_stmt); -+ gsi_next (&gsi); -+ gsi_replace (&gsi, assign_stmt, false); -+} -+ -+/* Do scalbn transform for each basic block BB. */ -+ -+static int -+nds32_scalbn_transform_basic_block (basic_block bb) -+{ -+ gimple_stmt_iterator gsi; -+ int transform_number = 0; -+ -+ if (dump_file) -+ fprintf (dump_file, -+ "\n;; Transforming the multiplication for basic block %d\n", -+ bb->index); -+ -+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) -+ { -+ gimple *stmt = gsi_stmt (gsi); -+ -+ if (nds32_scalbn_transform_target_p (stmt)) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, -+ "* The multiplier of stmt %d is transforming.\n", -+ gimple_uid (stmt)); -+ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM|TDF_RAW); -+ } -+ nds32_do_scalbn_transform (stmt); -+ transform_number++; -+ } -+ } -+ -+ return transform_number; -+} -+ -+/* This function is the entry of scalbn transform pass. */ -+ -+static int -+nds32_scalbn_transform_opt (void) -+{ -+ basic_block bb; -+ int total_transform_number = 0; -+ -+ /* Ignore current and builtin function name are the same. */ -+ if (nds32_is_scalbn_alias_func_p ()) -+ { -+ if (dump_file) -+ fprintf (dump_file, -+ "* Ignore function %s. " -+ "Transform it will cause infinite loop.\n", -+ function_name (cfun)); -+ return 0; -+ } -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ total_transform_number += nds32_scalbn_transform_basic_block (bb); -+ } -+ -+ if (dump_file) -+ { -+ if (total_transform_number > 0) -+ fprintf (dump_file, -+ "\n;; Transform %d multiplication stmt in function %s\n", -+ total_transform_number, -+ current_function_name ()); -+ else -+ fprintf (dump_file, -+ "\n;; No multiplication stmt is transformed in function %s\n", -+ current_function_name ()); -+ } -+ -+ return 1; -+} -+ -+static bool -+gate_nds32_scalbn_transform (void) -+{ -+ return flag_nds32_scalbn_transform -+ && !TARGET_FPU_SINGLE -+ && !flag_no_builtin; -+} -+ -+const pass_data pass_data_nds32_scalbn_transform_opt = -+{ -+ GIMPLE_PASS, /* type */ -+ "scalbn_transform", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ ( PROP_cfg | PROP_ssa ), /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_update_ssa, /* todo_flags_finish */ -+}; -+ -+class pass_nds32_scalbn_transform_opt : public gimple_opt_pass -+{ -+public: -+ pass_nds32_scalbn_transform_opt (gcc::context *ctxt) -+ : gimple_opt_pass (pass_data_nds32_scalbn_transform_opt, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { return gate_nds32_scalbn_transform (); } -+ unsigned int execute (function *) { return nds32_scalbn_transform_opt (); } -+}; -+ -+gimple_opt_pass * -+make_pass_nds32_scalbn_transform_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_scalbn_transform_opt (ctxt); -+} -diff --git a/gcc/config/nds32/nds32-sign-conversion.c b/gcc/config/nds32/nds32-sign-conversion.c -new file mode 100644 -index 0000000..74eefba ---- /dev/null -+++ b/gcc/config/nds32/nds32-sign-conversion.c -@@ -0,0 +1,218 @@ -+/* A Gimple-level pass of Andes NDS32 cpu for GNU compiler that -+ converse the sign of constant operand when the FPU do not be -+ accessed. -+ -+ Copyright (C) 2012-2016 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 -+. */ -+ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "hash-set.h" -+#include "machmode.h" -+#include "vec.h" -+#include "double-int.h" -+#include "input.h" -+#include "alias.h" -+#include "symtab.h" -+#include "wide-int.h" -+#include "inchash.h" -+#include "tree.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "rtl.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload (). */ -+#include "flags.h" -+#include "input.h" -+#include "function.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "dominance.h" -+#include "cfg.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "predict.h" -+#include "basic-block.h" -+#include "bitmap.h" -+#include "df.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function (). */ -+#include "ggc.h" -+#include "tree-pass.h" -+#include "tree-ssa-alias.h" -+#include "fold-const.h" -+#include "gimple-expr.h" -+#include "is-a.h" -+#include "gimple.h" -+#include "gimplify.h" -+#include "gimple-iterator.h" -+#include "gimplify-me.h" -+#include "gimple-ssa.h" -+#include "ipa-ref.h" -+#include "lto-streamer.h" -+#include "cgraph.h" -+#include "tree-cfg.h" -+#include "tree-phinodes.h" -+#include "stringpool.h" -+#include "tree-ssanames.h" -+#include "tree-pass.h" -+#include "gimple-pretty-print.h" -+#include "gimple-fold.h" -+ -+/* Return true if GS is the target of sign conversion. */ -+ -+static bool -+nds32_sign_conversion_target_p (gimple *gs) -+{ -+ if (is_gimple_assign (gs)) -+ if ((gimple_assign_rhs_code (gs) == MINUS_EXPR) -+ && (TREE_CODE (gimple_assign_rhs2 (gs)) == REAL_CST)) -+ return true; -+ return false; -+} -+ -+/* Do sign conversion for a GIMPLE statement GS. */ -+ -+static void -+nds32_do_sign_conversion (gimple *gs) -+{ -+ /* Rewrite the rhs operand. */ -+ enum tree_code op_code = gimple_assign_rhs_code (gs); -+ op_code = PLUS_EXPR; -+ gimple_assign_set_rhs_code (gs, op_code); -+ /* Rewrite the constant value. */ -+ tree rhs2 = gimple_assign_rhs2 (gs); -+ rhs2 = build_real (TREE_TYPE (rhs2), -+ real_value_negate (&TREE_REAL_CST (rhs2))); -+ gimple_assign_set_rhs2 (gs, rhs2); -+ /* When the statement is modified, please mark this statement is modified. */ -+ update_stmt (gs); -+} -+ -+/* Do sign conversion for each basic block BB. */ -+ -+static int -+nds32_sign_conversion_basic_block (basic_block bb) -+{ -+ gimple_stmt_iterator gsi; -+ int converse_number = 0; -+ -+ if (dump_file) -+ fprintf (dump_file, -+ "\n;; Conversing the sign of gimple stmts for basic block %d\n", -+ bb->index); -+ -+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) -+ { -+ gimple *stmt = gsi_stmt (gsi); -+ -+ if (nds32_sign_conversion_target_p (stmt)) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "* The sign of stmt %d is conversing.\n", -+ gimple_uid (stmt)); -+ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM|TDF_RAW); -+ } -+ nds32_do_sign_conversion (stmt); -+ converse_number++; -+ } -+ } -+ -+ return converse_number; -+} -+ -+/* This function is the entry of sign conversion pass. */ -+ -+static int -+nds32_sign_conversion_opt (void) -+{ -+ basic_block bb; -+ int total_converse_number = 0; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ total_converse_number += nds32_sign_conversion_basic_block (bb); -+ } -+ -+ if (dump_file) -+ { -+ if (total_converse_number > 0) -+ fprintf (dump_file, "\n;; Converse %d stmts in function %s\n", -+ total_converse_number, -+ current_function_name ()); -+ else -+ fprintf (dump_file, -+ "\n;; No sign of stmt is conversed in function %s\n", -+ current_function_name ()); -+ } -+ -+ return 1; -+} -+ -+const pass_data pass_data_nds32_sign_conversion_opt = -+{ -+ GIMPLE_PASS, /* type */ -+ "sign_conversion", /* name */ -+ OPTGROUP_NONE, /* optinfo_flags */ -+ TV_MACH_DEP, /* tv_id */ -+ ( PROP_cfg | PROP_ssa ), /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_update_ssa, /* todo_flags_finish */ -+}; -+ -+class pass_nds32_sign_conversion_opt : public gimple_opt_pass -+{ -+public: -+ pass_nds32_sign_conversion_opt (gcc::context *ctxt) -+ : gimple_opt_pass (pass_data_nds32_sign_conversion_opt, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) -+ { -+ return flag_nds32_sign_conversion && !TARGET_FPU_SINGLE; -+ } -+ unsigned int execute (function *) { return nds32_sign_conversion_opt (); } -+}; -+ -+gimple_opt_pass * -+make_pass_nds32_sign_conversion_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_sign_conversion_opt (ctxt); -+} -diff --git a/gcc/config/nds32/nds32-soft-fp-comm.c b/gcc/config/nds32/nds32-soft-fp-comm.c -new file mode 100644 -index 0000000..98ba3d5 ---- /dev/null -+++ b/gcc/config/nds32/nds32-soft-fp-comm.c -@@ -0,0 +1,205 @@ -+/* Operand commutative for soft floating point arithmetic pass -+ of Andes NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "backend.h" -+#include "tree.h" -+#include "rtl.h" -+#include "df.h" -+#include "alias.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ -+#include "builtins.h" -+#include "cpplib.h" -+#include "params.h" -+#include "tree-pass.h" -+ -+#define SF_ARG0_REGNO 0 -+#define SF_ARG1_REGNO 1 -+ -+#define DF_ARG0_REGNO 0 -+#define DF_ARG1_REGNO 2 -+ -+static int -+nds32_soft_fp_arith_comm_opt (void) -+{ -+ basic_block bb; -+ rtx_insn *insn; -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (!CALL_P (insn)) -+ continue; -+ -+ rtx pat = PATTERN (insn); -+ rtx call_rtx = XVECEXP (pat, 0, 0); -+ -+ if (GET_CODE (call_rtx) == SET) -+ call_rtx = SET_SRC (call_rtx); -+ -+ rtx func_mem = XEXP (call_rtx, 0); -+ rtx symbol = XEXP (func_mem, 0); -+ -+ if (GET_CODE (symbol) != SYMBOL_REF) -+ continue; -+ -+ const char *func_name = XSTR (symbol, 0); -+ bool df_p; -+ if (((strcmp("__mulsf3", func_name) == 0) -+ || (strcmp("__addsf3", func_name) == 0))) -+ df_p = false; -+ else if (((strcmp("__muldf3", func_name) == 0) -+ || (strcmp("__adddf3", func_name) == 0))) -+ df_p = true; -+ else -+ continue; -+ -+ rtx_insn *prev_insn = insn; -+ rtx_insn *arg0_insn = NULL; -+ rtx_insn *arg1_insn = NULL; -+ unsigned arg0_regno = df_p ? DF_ARG0_REGNO : SF_ARG0_REGNO; -+ unsigned arg1_regno = df_p ? DF_ARG1_REGNO : SF_ARG1_REGNO; -+ enum machine_mode mode = df_p ? DFmode : SFmode; -+ while ((prev_insn = PREV_INSN (prev_insn)) && prev_insn) -+ { -+ if (arg0_insn != NULL && arg1_insn != NULL) -+ break; -+ -+ if (BLOCK_FOR_INSN (prev_insn) != BLOCK_FOR_INSN (insn)) -+ break; -+ -+ if (!NONJUMP_INSN_P (prev_insn)) -+ break; -+ -+ if (!INSN_P (prev_insn)) -+ continue; -+ -+ rtx set = PATTERN (prev_insn); -+ -+ if (GET_CODE (set) != SET) -+ continue; -+ -+ rtx dst_reg = SET_DEST (set); -+ -+ if (!REG_P (dst_reg)) -+ break; -+ -+ unsigned regno = REGNO (dst_reg); -+ -+ if (regno == arg0_regno) -+ { -+ arg0_insn = prev_insn; -+ continue; -+ } -+ else if (regno == arg1_regno) -+ { -+ arg1_insn = prev_insn; -+ continue; -+ } -+ break; -+ } -+ if (arg0_insn == NULL || arg1_insn == NULL) -+ continue; -+ -+ rtx arg0_src = SET_SRC (PATTERN (arg0_insn)); -+ rtx arg1_src = SET_SRC (PATTERN (arg1_insn)); -+ -+ if ((REG_P (arg0_src) -+ && GET_MODE (arg0_src) == mode -+ && REGNO (arg0_src) == arg1_regno) -+ || (REG_P (arg1_src) -+ && GET_MODE (arg1_src) == mode -+ && REGNO (arg1_src) == arg0_regno)) -+ { -+ /* Swap operand! */ -+ rtx tmp = SET_DEST (PATTERN (arg0_insn)); -+ SET_DEST (PATTERN (arg0_insn)) = SET_DEST (PATTERN (arg1_insn)); -+ SET_DEST (PATTERN (arg1_insn)) = tmp; -+ } -+ } -+ } -+ return 1; -+} -+ -+const pass_data pass_data_nds32_soft_fp_arith_comm_opt = -+{ -+ RTL_PASS, /* type */ -+ "soft_fp_arith_comm", /* 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_soft_fp_arith_comm_opt : public rtl_opt_pass -+{ -+public: -+ pass_nds32_soft_fp_arith_comm_opt (gcc::context *ctxt) -+ : rtl_opt_pass (pass_data_nds32_soft_fp_arith_comm_opt, ctxt) -+ {} -+ -+ /* opt_pass methods: */ -+ bool gate (function *) { -+ return TARGET_SOFT_FP_ARITH_COMM && !TARGET_FPU_SINGLE; -+ } -+ unsigned int execute (function *) { return nds32_soft_fp_arith_comm_opt (); } -+}; -+ -+rtl_opt_pass * -+make_pass_nds32_soft_fp_arith_comm_opt (gcc::context *ctxt) -+{ -+ return new pass_nds32_soft_fp_arith_comm_opt (ctxt); -+} -diff --git a/gcc/config/nds32/nds32-utils.c b/gcc/config/nds32/nds32-utils.c -new file mode 100644 -index 0000000..3b16738 ---- /dev/null -+++ b/gcc/config/nds32/nds32-utils.c -@@ -0,0 +1,923 @@ -+/* Auxiliary functions for pipeline descriptions pattern of Andes -+ NDS32 cpu for GNU compiler -+ Copyright (C) 2012-2016 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 -+ . */ -+ -+/* ------------------------------------------------------------------------ */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "hash-set.h" -+#include "machmode.h" -+#include "vec.h" -+#include "double-int.h" -+#include "input.h" -+#include "alias.h" -+#include "symtab.h" -+#include "wide-int.h" -+#include "inchash.h" -+#include "tree.h" -+#include "stor-layout.h" -+#include "varasm.h" -+#include "calls.h" -+#include "rtl.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" -+#include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "input.h" -+#include "function.h" -+#include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "dominance.h" -+#include "cfg.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "predict.h" -+#include "basic-block.h" -+#include "nds32-protos.h" -+ -+namespace nds32 { -+ -+/* Get the rtx in the PATTERN field of an insn. If INSN is not an insn, -+ the funciton doesn't change anything and returns it directly. */ -+rtx -+extract_pattern_from_insn (rtx insn) -+{ -+ if (INSN_P (insn)) -+ return PATTERN (insn); -+ -+ return insn; -+} -+ -+/* Get the number of elements in a parallel rtx. */ -+size_t -+parallel_elements (rtx parallel_rtx) -+{ -+ parallel_rtx = extract_pattern_from_insn (parallel_rtx); -+ gcc_assert (GET_CODE (parallel_rtx) == PARALLEL); -+ -+ return XVECLEN (parallel_rtx, 0); -+} -+ -+/* Extract an rtx from a parallel rtx with index NTH. If NTH is a negative -+ value, the function returns the last NTH rtx. */ -+rtx -+parallel_element (rtx parallel_rtx, int nth) -+{ -+ parallel_rtx = extract_pattern_from_insn (parallel_rtx); -+ gcc_assert (GET_CODE (parallel_rtx) == PARALLEL); -+ -+ int len = parallel_elements (parallel_rtx); -+ -+ if (nth >= 0) -+ { -+ if (nth >= len) -+ return NULL_RTX; -+ -+ return XVECEXP (parallel_rtx, 0, nth); -+ } -+ else -+ { -+ if (len + nth < 0) -+ return NULL_RTX; -+ -+ return XVECEXP (parallel_rtx, 0, len + nth); -+ } -+} -+ -+/* Return true if an insn is a pseudo NOP that is not a real instruction -+ occupying a real cycle and space of the text section. */ -+bool -+insn_pseudo_nop_p (rtx_insn *insn) -+{ -+ if (INSN_CODE (insn) == CODE_FOR_nop_data_dep -+ || INSN_CODE (insn) == CODE_FOR_nop_res_dep) -+ return true; -+ -+ return false; -+} -+ -+/* Indicate whether an insn is a real insn which occupy at least one cycle -+ or not. The determination cannot be target-independent because some targets -+ use UNSPEC or UNSPEC_VOLATILE insns to represent real instructions. */ -+bool -+insn_executable_p (rtx_insn *insn) -+{ -+ if (!INSN_P (insn)) -+ return false; -+ -+ if (insn_pseudo_nop_p (insn)) -+ return true; -+ -+ if (get_attr_length (insn) == 0) -+ return false; -+ -+ switch (GET_CODE (PATTERN (insn))) -+ { -+ case CONST_INT: -+ case USE: -+ case CLOBBER: -+ case ADDR_VEC: -+ case ADDR_DIFF_VEC: -+ case UNSPEC: -+ case UNSPEC_VOLATILE: -+ return false; -+ -+ default: -+ return true; -+ } -+ -+ return true; -+} -+ -+/* Find the previous executable insn. */ -+rtx_insn * -+prev_executable_insn (rtx_insn *insn) -+{ -+ insn = PREV_INSN (insn); -+ while (insn && !insn_executable_p (insn)) -+ insn = PREV_INSN (insn); -+ -+ return insn; -+} -+ -+/* Find the next executable insn. */ -+rtx_insn * -+next_executable_insn (rtx_insn *insn) -+{ -+ insn = NEXT_INSN (insn); -+ while (insn && !insn_executable_p (insn)) -+ insn = NEXT_INSN (insn); -+ -+ return insn; -+} -+ -+/* Find the previous executable insn in the current basic block. */ -+rtx_insn * -+prev_executable_insn_local (rtx_insn *insn) -+{ -+ insn = PREV_INSN (insn); -+ while (insn && !insn_executable_p (insn)) -+ { -+ if(LABEL_P (insn) || JUMP_P (insn) || CALL_P (insn)) -+ return NULL; -+ -+ insn = PREV_INSN (insn); -+ } -+ -+ return insn; -+} -+ -+/* Find the next executable insn in the current basic block. */ -+rtx_insn * -+next_executable_insn_local (rtx_insn *insn) -+{ -+ insn = NEXT_INSN (insn); -+ while (insn && !insn_executable_p (insn)) -+ { -+ if(LABEL_P (insn) || JUMP_P (insn) || CALL_P (insn)) -+ return NULL; -+ -+ insn = NEXT_INSN (insn); -+ } -+ -+ return insn; -+} -+ -+/* Return true if an insn is marked as deleted. */ -+bool -+insn_deleted_p (rtx_insn *insn) -+{ -+ if (insn->deleted ()) -+ return true; -+ -+ if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED) -+ return true; -+ -+ return false; -+} -+ -+/* Functions to determine whether INSN is single-word, double-word -+ or partial-word load/store insn. */ -+ -+bool -+load_single_p (rtx_insn *insn) -+{ -+ if (get_attr_type (insn) != TYPE_LOAD) -+ return false; -+ -+ if (INSN_CODE (insn) == CODE_FOR_move_di || -+ INSN_CODE (insn) == CODE_FOR_move_df) -+ return false; -+ -+ return true; -+} -+ -+bool -+store_single_p (rtx_insn *insn) -+{ -+ if (get_attr_type (insn) != TYPE_STORE) -+ return false; -+ -+ if (INSN_CODE (insn) == CODE_FOR_move_di || -+ INSN_CODE (insn) == CODE_FOR_move_df) -+ return false; -+ -+ return true; -+} -+ -+bool -+load_double_p (rtx_insn *insn) -+{ -+ if (get_attr_type (insn) != TYPE_LOAD) -+ return false; -+ -+ if (INSN_CODE (insn) != CODE_FOR_move_di && -+ INSN_CODE (insn) != CODE_FOR_move_df) -+ return false; -+ -+ return true; -+} -+ -+bool -+store_double_p (rtx_insn *insn) -+{ -+ if (get_attr_type (insn) != TYPE_STORE) -+ return false; -+ -+ if (INSN_CODE (insn) != CODE_FOR_move_di && -+ INSN_CODE (insn) != CODE_FOR_move_df) -+ return false; -+ -+ 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; -+} -+ -+bool -+load_full_word_p (rtx_insn *insn) -+{ -+ if (!nds32::load_single_p (insn)) -+ return false; -+ -+ if (GET_MODE (SET_SRC (PATTERN (insn))) == SImode) -+ return true; -+ -+ return false; -+} -+ -+bool -+load_partial_word_p (rtx_insn *insn) -+{ -+ if (!nds32::load_single_p (insn)) -+ return false; -+ -+ if (GET_MODE (SET_SRC (PATTERN (insn))) == HImode -+ || GET_MODE (SET_SRC (PATTERN (insn))) == QImode) -+ return true; -+ -+ return false; -+} -+ -+/* Determine if INSN is a post update insn. */ -+bool -+post_update_insn_p (rtx_insn *insn) -+{ -+ if (find_post_update_rtx (insn) == -1) -+ return false; -+ else -+ return true; -+} -+ -+/* Check if the address of MEM_RTX consists of a base register and an -+ immediate offset. */ -+bool -+immed_offset_p (rtx mem_rtx) -+{ -+ gcc_assert (MEM_P (mem_rtx)); -+ -+ rtx addr_rtx = XEXP (mem_rtx, 0); -+ -+ /* (mem (reg)) is equivalent to (mem (plus (reg) (const_int 0))) */ -+ if (REG_P (addr_rtx)) -+ return true; -+ -+ /* (mem (plus (reg) (const_int))) */ -+ if (GET_CODE (addr_rtx) == PLUS -+ && GET_CODE (XEXP (addr_rtx, 1)) == CONST_INT) -+ return true; -+ -+ return false; -+} -+ -+/* Find the post update rtx in INSN. If INSN is a load/store multiple insn, -+ the function returns the vector index of its parallel part. If INSN is a -+ single load/store insn, the function returns 0. If INSN is not a post- -+ update insn, the function returns -1. */ -+int -+find_post_update_rtx (rtx_insn *insn) -+{ -+ rtx mem_rtx; -+ int i, len; -+ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD_MULTIPLE: -+ case TYPE_STORE_MULTIPLE: -+ /* Find a pattern in a parallel rtx: -+ (set (reg) (plus (reg) (const_int))) */ -+ len = parallel_elements (insn); -+ for (i = 0; i < len; ++i) -+ { -+ rtx curr_insn = parallel_element (insn, i); -+ -+ if (GET_CODE (curr_insn) == SET -+ && REG_P (SET_DEST (curr_insn)) -+ && GET_CODE (SET_SRC (curr_insn)) == PLUS) -+ return i; -+ } -+ return -1; -+ -+ case TYPE_LOAD: -+ case TYPE_FLOAD: -+ case TYPE_STORE: -+ case TYPE_FSTORE: -+ mem_rtx = extract_mem_rtx (insn); -+ /* (mem (post_inc (reg))) */ -+ switch (GET_CODE (XEXP (mem_rtx, 0))) -+ { -+ case POST_INC: -+ case POST_DEC: -+ case POST_MODIFY: -+ return 0; -+ -+ default: -+ return -1; -+ } -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+/* Extract the MEM rtx from a load/store insn. */ -+rtx -+extract_mem_rtx (rtx_insn *insn) -+{ -+ rtx body = PATTERN (insn); -+ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD: -+ case TYPE_FLOAD: -+ if (MEM_P (SET_SRC (body))) -+ return SET_SRC (body); -+ -+ /* unaligned address: (unspec [(mem)]) */ -+ if (GET_CODE (SET_SRC (body)) == UNSPEC) -+ { -+ gcc_assert (MEM_P (XVECEXP (SET_SRC (body), 0, 0))); -+ return XVECEXP (SET_SRC (body), 0, 0); -+ } -+ -+ /* (sign_extend (mem)) */ -+ gcc_assert (MEM_P (XEXP (SET_SRC (body), 0))); -+ return XEXP (SET_SRC (body), 0); -+ -+ case TYPE_STORE: -+ case TYPE_FSTORE: -+ if (MEM_P (SET_DEST (body))) -+ return SET_DEST (body); -+ -+ /* unaligned address: (unspec [(mem)]) */ -+ if (GET_CODE (SET_DEST (body)) == UNSPEC) -+ { -+ gcc_assert (MEM_P (XVECEXP (SET_DEST (body), 0, 0))); -+ return XVECEXP (SET_DEST (body), 0, 0); -+ } -+ -+ /* (sign_extend (mem)) */ -+ gcc_assert (MEM_P (XEXP (SET_DEST (body), 0))); -+ return XEXP (SET_DEST (body), 0); -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+/* Extract the base register from load/store insns. The function returns -+ NULL_RTX if the address is not consist of any registers. */ -+rtx -+extract_base_reg (rtx_insn *insn) -+{ -+ int post_update_rtx_index; -+ rtx mem_rtx; -+ rtx plus_rtx; -+ -+ /* Find the MEM rtx. If we can find an insn updating the base register, -+ the base register will be returned directly. */ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_LOAD_MULTIPLE: -+ post_update_rtx_index = find_post_update_rtx (insn); -+ -+ if (post_update_rtx_index != -1) -+ return SET_DEST (parallel_element (insn, post_update_rtx_index)); -+ -+ mem_rtx = SET_SRC (parallel_element (insn, 0)); -+ break; -+ -+ case TYPE_STORE_MULTIPLE: -+ post_update_rtx_index = find_post_update_rtx (insn); -+ -+ if (post_update_rtx_index != -1) -+ return SET_DEST (parallel_element (insn, post_update_rtx_index)); -+ -+ mem_rtx = SET_DEST (parallel_element (insn, 0)); -+ break; -+ -+ 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 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; -+ -+ /* (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)))) */ -+ 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. */ -+rtx -+extract_shift_reg (rtx_insn *insn) -+{ -+ rtx alu_shift_rtx = extract_pattern_from_insn (insn); -+ -+ rtx alu_rtx = SET_SRC (alu_shift_rtx); -+ rtx shift_rtx; -+ -+ /* Various forms of ALU_SHIFT can be made by the combiner. -+ See the difference between add_slli and sub_slli in nds32.md. */ -+ if (REG_P (XEXP (alu_rtx, 0))) -+ shift_rtx = XEXP (alu_rtx, 1); -+ else -+ shift_rtx = XEXP (alu_rtx, 0); -+ -+ return XEXP (shift_rtx, 0); -+} -+ -+/* Check if INSN is a movd44 insn. */ -+bool -+movd44_insn_p (rtx_insn *insn) -+{ -+ if (get_attr_type (insn) == TYPE_ALU -+ && (INSN_CODE (insn) == CODE_FOR_move_di -+ || INSN_CODE (insn) == CODE_FOR_move_df)) -+ { -+ rtx body = PATTERN (insn); -+ gcc_assert (GET_CODE (body) == SET); -+ -+ rtx src = SET_SRC (body); -+ rtx dest = SET_DEST (body); -+ -+ if ((REG_P (src) || GET_CODE (src) == SUBREG) -+ && (REG_P (dest) || GET_CODE (dest) == SUBREG)) -+ return true; -+ -+ return false; -+ } -+ -+ return false; -+} -+ -+/* Extract the first result (even reg) of a movd44 insn. */ -+rtx -+extract_movd44_even_reg (rtx_insn *insn) -+{ -+ gcc_assert (movd44_insn_p (insn)); -+ -+ rtx def_reg = SET_DEST (PATTERN (insn)); -+ enum machine_mode mode; -+ -+ gcc_assert (REG_P (def_reg) || GET_CODE (def_reg) == SUBREG); -+ switch (GET_MODE (def_reg)) -+ { -+ case DImode: -+ mode = SImode; -+ break; -+ -+ case DFmode: -+ mode = SFmode; -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return gen_lowpart (mode, def_reg); -+} -+ -+/* Extract the second result (odd reg) of a movd44 insn. */ -+rtx -+extract_movd44_odd_reg (rtx_insn *insn) -+{ -+ gcc_assert (movd44_insn_p (insn)); -+ -+ rtx def_reg = SET_DEST (PATTERN (insn)); -+ enum machine_mode mode; -+ -+ gcc_assert (REG_P (def_reg) || GET_CODE (def_reg) == SUBREG); -+ switch (GET_MODE (def_reg)) -+ { -+ case DImode: -+ mode = SImode; -+ break; -+ -+ case DFmode: -+ mode = SFmode; -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return gen_highpart (mode, def_reg); -+} -+ -+/* Extract the rtx representing the accumulation operand of a MAC insn. */ -+rtx -+extract_mac_acc_rtx (rtx_insn *insn) -+{ -+ return SET_DEST (PATTERN (insn)); -+} -+ -+/* Extract the rtx representing non-accumulation operands of a MAC insn. */ -+rtx -+extract_mac_non_acc_rtx (rtx_insn *insn) -+{ -+ rtx exp = SET_SRC (PATTERN (insn)); -+ -+ switch (get_attr_type (insn)) -+ { -+ case TYPE_MAC: -+ case TYPE_DMAC: -+ if (REG_P (XEXP (exp, 0))) -+ return XEXP (exp, 1); -+ else -+ return XEXP (exp, 0); -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+/* 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 -+extract_branch_target_rtx (rtx_insn *insn) -+{ -+ gcc_assert (CALL_P (insn) || JUMP_P (insn)); -+ -+ rtx body = PATTERN (insn); -+ -+ if (GET_CODE (body) == SET) -+ { -+ /* RTXs in IF_THEN_ELSE are branch conditions. */ -+ if (GET_CODE (SET_SRC (body)) == IF_THEN_ELSE) -+ return NULL_RTX; -+ -+ return SET_SRC (body); -+ } -+ -+ if (GET_CODE (body) == CALL) -+ return XEXP (body, 0); -+ -+ if (GET_CODE (body) == PARALLEL) -+ { -+ rtx first_rtx = parallel_element (body, 0); -+ -+ if (GET_CODE (first_rtx) == SET) -+ return SET_SRC (first_rtx); -+ -+ if (GET_CODE (first_rtx) == CALL) -+ return XEXP (first_rtx, 0); -+ } -+ -+ /* Handle special cases of bltzal, bgezal and jralnez. */ -+ if (GET_CODE (body) == COND_EXEC) -+ { -+ rtx addr_rtx = XEXP (body, 1); -+ -+ if (GET_CODE (addr_rtx) == SET) -+ return SET_SRC (addr_rtx); -+ -+ if (GET_CODE (addr_rtx) == PARALLEL) -+ { -+ rtx first_rtx = parallel_element (addr_rtx, 0); -+ -+ if (GET_CODE (first_rtx) == SET) -+ { -+ rtx call_rtx = SET_SRC (first_rtx); -+ gcc_assert (GET_CODE (call_rtx) == CALL); -+ -+ return XEXP (call_rtx, 0); -+ } -+ -+ if (GET_CODE (first_rtx) == CALL) -+ return XEXP (first_rtx, 0); -+ } -+ } -+ -+ gcc_unreachable (); -+} -+ -+/* Extract the rtx representing the branch condition to help recognize -+ data hazards. */ -+rtx -+extract_branch_condition_rtx (rtx_insn *insn) -+{ -+ gcc_assert (CALL_P (insn) || JUMP_P (insn)); -+ -+ rtx body = PATTERN (insn); -+ -+ if (GET_CODE (body) == SET) -+ { -+ rtx if_then_else_rtx = SET_SRC (body); -+ -+ if (GET_CODE (if_then_else_rtx) == IF_THEN_ELSE) -+ return XEXP (if_then_else_rtx, 0); -+ -+ return NULL_RTX; -+ } -+ -+ if (GET_CODE (body) == COND_EXEC) -+ return XEXP (body, 0); -+ -+ return NULL_RTX; -+} -+ -+/* Building the CFG in later back end passes cannot call compute_bb_for_insn () -+ directly because calling to BLOCK_FOR_INSN (insn) when some insns have been -+ deleted can cause a segmentation fault. Use this function to rebuild the CFG -+ can avoid such issues. */ -+void -+compute_bb_for_insn_safe () -+{ -+ basic_block bb; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ rtx_insn *insn, *next_insn, *last_insn; -+ bool after_last_insn = false; -+ -+ /* Find the last non-deleted insn. */ -+ for (last_insn = BB_END (bb); -+ PREV_INSN (last_insn) && insn_deleted_p (last_insn); -+ last_insn = PREV_INSN (last_insn)); -+ -+ /* Bind each insn to its BB and adjust BB_END (bb). */ -+ for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn)) -+ { -+ BLOCK_FOR_INSN (insn) = bb; -+ -+ if (insn == last_insn) -+ after_last_insn = true; -+ -+ next_insn = NEXT_INSN (insn); -+ -+ if (after_last_insn -+ && (!next_insn -+ || LABEL_P (next_insn) -+ || NOTE_INSN_BASIC_BLOCK_P (next_insn))) -+ { -+ BB_END (bb) = insn; -+ break; -+ } -+ } -+ } -+} -+ -+/* Exchange insns positions. */ -+void -+exchange_insns (rtx_insn *insn1, rtx_insn *insn2) -+{ -+ if (INSN_UID (insn1) == INSN_UID (insn2)) -+ return; -+ -+ rtx_insn *insn1_from = insn1; -+ rtx_insn *insn1_to = insn1; -+ rtx_insn *insn2_from = insn2; -+ rtx_insn *insn2_to = insn2; -+ -+ if (PREV_INSN (insn1) -+ && INSN_CODE (PREV_INSN (insn1)) == CODE_FOR_relax_group) -+ insn1_from = PREV_INSN (insn1); -+ -+ if (PREV_INSN (insn2) -+ && INSN_CODE (PREV_INSN (insn2)) == CODE_FOR_relax_group) -+ insn2_from = PREV_INSN (insn2); -+ -+ if (GET_MODE (insn1) == TImode && GET_MODE (insn2) == VOIDmode) -+ { -+ PUT_MODE (insn1, VOIDmode); -+ PUT_MODE (insn2, TImode); -+ } -+ else if (GET_MODE (insn1) == VOIDmode && GET_MODE (insn2) == TImode) -+ { -+ PUT_MODE (insn1, TImode); -+ PUT_MODE (insn2, VOIDmode); -+ } -+ -+ if (PREV_INSN (insn1_from)) -+ { -+ rtx_insn *insn1_prev = PREV_INSN (insn1_from); -+ -+ reorder_insns (insn1_from, insn1_to, insn2); -+ reorder_insns (insn2_from, insn2_to, insn1_prev); -+ -+ return; -+ } -+ -+ gcc_assert (PREV_INSN (insn2_from)); -+ -+ rtx_insn *insn2_prev = PREV_INSN (insn2_from); -+ -+ reorder_insns (insn2_from, insn2_to, insn1); -+ reorder_insns (insn1_from, insn1_to, insn2_prev); -+ -+ return; -+} -+ -+} // namespace nds32 -diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c -index c47c122..5f5e668 100644 ---- a/gcc/config/nds32/nds32.c -+++ b/gcc/config/nds32/nds32.c -@@ -24,48 +24,103 @@ - #include "system.h" - #include "coretypes.h" - #include "backend.h" --#include "target.h" --#include "rtl.h" - #include "tree.h" -+#include "rtl.h" - #include "df.h" --#include "tm_p.h" --#include "optabs.h" /* For GEN_FCN. */ --#include "regs.h" --#include "emit-rtl.h" --#include "recog.h" --#include "diagnostic-core.h" -+#include "alias.h" -+#include "stringpool.h" - #include "stor-layout.h" - #include "varasm.h" - #include "calls.h" -+#include "regs.h" -+#include "insn-config.h" /* Required by recog.h. */ -+#include "conditions.h" - #include "output.h" -+#include "insn-attr.h" /* For DFA state_t. */ -+#include "insn-codes.h" /* For CODE_FOR_xxx. */ -+#include "reload.h" /* For push_reload(). */ -+#include "flags.h" -+#include "insn-config.h" -+#include "expmed.h" -+#include "dojump.h" - #include "explow.h" -+#include "emit-rtl.h" -+#include "stmt.h" - #include "expr.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "tm_p.h" - #include "tm-constrs.h" -+#include "optabs.h" /* For GEN_FCN. */ -+#include "target.h" -+#include "langhooks.h" /* For add_builtin_function(). */ - #include "builtins.h" -+#include "cpplib.h" -+#include "params.h" -+#include "tree-pass.h" -+#include "cfgloop.h" -+#include "cfghooks.h" -+#include "hw-doloop.h" -+#include "context.h" -+#include "sched-int.h" - - /* This file should be included last. */ - #include "target-def.h" - - /* ------------------------------------------------------------------------ */ - --/* This file is divided into five parts: -+/* This file is divided into six parts: - -- PART 1: Auxiliary static variable definitions and -- target hook static variable definitions. -+ PART 1: Auxiliary external function and variable declarations. - -- PART 2: Auxiliary static function definitions. -+ PART 2: Auxiliary static variable definitions and -+ target hook static variable definitions. - -- PART 3: Implement target hook stuff definitions. -+ PART 3: Auxiliary static function definitions. - -- PART 4: Implemet extern function definitions, -- the prototype is in nds32-protos.h. -+ PART 4: Implement target hook stuff definitions. - -- PART 5: Initialize target hook structure and definitions. */ -+ PART 5: Implemet extern function definitions, -+ the prototype is in nds32-protos.h. -+ -+ PART 6: Initialize target hook structure and definitions. */ -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* PART 1: Auxiliary function and variable declarations. */ -+ -+namespace nds32 { -+namespace scheduling { -+ -+rtl_opt_pass *make_pass_nds32_print_stalls (gcc::context *); -+ -+} // namespace scheduling -+} // namespace nds32 -+ -+rtl_opt_pass *make_pass_nds32_fp_as_gp (gcc::context *); -+rtl_opt_pass *make_pass_nds32_load_store_opt (gcc::context *); -+rtl_opt_pass *make_pass_nds32_soft_fp_arith_comm_opt(gcc::context *); -+rtl_opt_pass *make_pass_nds32_regrename_opt (gcc::context *); -+rtl_opt_pass *make_pass_nds32_gcse_opt (gcc::context *); -+rtl_opt_pass *make_pass_nds32_relax_opt (gcc::context *); -+rtl_opt_pass *make_pass_nds32_rename_lmwsmw_opt (gcc::context *); -+rtl_opt_pass *make_pass_nds32_gen_lmwsmw_opt (gcc::context *); -+rtl_opt_pass *make_pass_nds32_const_remater_opt (gcc::context *); -+rtl_opt_pass *make_pass_nds32_cprop_acc_opt (gcc::context *); -+ -+gimple_opt_pass *make_pass_nds32_sign_conversion_opt (gcc::context *); -+gimple_opt_pass *make_pass_nds32_scalbn_transform_opt (gcc::context *); -+gimple_opt_pass *make_pass_nds32_abi_compatible (gcc::context *); - - /* ------------------------------------------------------------------------ */ - --/* PART 1: Auxiliary static variable definitions and -- target hook static variable definitions. */ -+/* PART 2: Auxiliary static variable definitions and -+ target hook static variable definitions. */ - - /* Define intrinsic register names. - Please refer to nds32_intrinsic.h file, the index is corresponding to -@@ -73,14 +128,217 @@ - NOTE that the base value starting from 1024. */ - static const char * const nds32_intrinsic_register_names[] = - { -- "$PSW", "$IPSW", "$ITYPE", "$IPC" -+ "$CPU_VER", -+ "$ICM_CFG", -+ "$DCM_CFG", -+ "$MMU_CFG", -+ "$MSC_CFG", -+ "$MSC_CFG2", -+ "$CORE_ID", -+ "$FUCOP_EXIST", -+ -+ "$PSW", -+ "$IPSW", -+ "$P_IPSW", -+ "$IVB", -+ "$EVA", -+ "$P_EVA", -+ "$ITYPE", -+ "$P_ITYPE", -+ -+ "$MERR", -+ "$IPC", -+ "$P_IPC", -+ "$OIPC", -+ "$P_P0", -+ "$P_P1", -+ -+ "$INT_MASK", -+ "$INT_MASK2", -+ "$INT_MASK3", -+ "$INT_PEND", -+ "$INT_PEND2", -+ "$INT_PEND3", -+ "$SP_USR", -+ "$SP_PRIV", -+ "$INT_PRI", -+ "$INT_PRI2", -+ "$INT_PRI3", -+ "$INT_PRI4", -+ "$INT_CTRL", -+ "$INT_TRIGGER", -+ "$INT_TRIGGER2", -+ "$INT_GPR_PUSH_DIS", -+ -+ "$MMU_CTL", -+ "$L1_PPTB", -+ "$TLB_VPN", -+ "$TLB_DATA", -+ "$TLB_MISC", -+ "$VLPT_IDX", -+ "$ILMB", -+ "$DLMB", -+ -+ "$CACHE_CTL", -+ "$HSMP_SADDR", -+ "$HSMP_EADDR", -+ "$SDZ_CTL", -+ "$N12MISC_CTL", -+ "$MISC_CTL", -+ "$ECC_MISC", -+ -+ "$BPC0", -+ "$BPC1", -+ "$BPC2", -+ "$BPC3", -+ "$BPC4", -+ "$BPC5", -+ "$BPC6", -+ "$BPC7", -+ -+ "$BPA0", -+ "$BPA1", -+ "$BPA2", -+ "$BPA3", -+ "$BPA4", -+ "$BPA5", -+ "$BPA6", -+ "$BPA7", -+ -+ "$BPAM0", -+ "$BPAM1", -+ "$BPAM2", -+ "$BPAM3", -+ "$BPAM4", -+ "$BPAM5", -+ "$BPAM6", -+ "$BPAM7", -+ -+ "$BPV0", -+ "$BPV1", -+ "$BPV2", -+ "$BPV3", -+ "$BPV4", -+ "$BPV5", -+ "$BPV6", -+ "$BPV7", -+ -+ "$BPCID0", -+ "$BPCID1", -+ "$BPCID2", -+ "$BPCID3", -+ "$BPCID4", -+ "$BPCID5", -+ "$BPCID6", -+ "$BPCID7", -+ -+ "$EDM_CFG", -+ "$EDMSW", -+ "$EDM_CTL", -+ "$EDM_DTR", -+ "$BPMTC", -+ "$DIMBR", -+ -+ "$TECR0", -+ "$TECR1", -+ "$PFMC0", -+ "$PFMC1", -+ "$PFMC2", -+ "$PFM_CTL", -+ "$PFT_CTL", -+ "$HSP_CTL", -+ "$SP_BOUND", -+ "$SP_BOUND_PRIV", -+ "$SP_BASE", -+ "$SP_BASE_PRIV", -+ "$FUCOP_CTL", -+ "$PRUSR_ACC_CTL", -+ -+ "$DMA_CFG", -+ "$DMA_GCSW", -+ "$DMA_CHNSEL", -+ "$DMA_ACT", -+ "$DMA_SETUP", -+ "$DMA_ISADDR", -+ "$DMA_ESADDR", -+ "$DMA_TCNT", -+ "$DMA_STATUS", -+ "$DMA_2DSET", -+ "$DMA_2DSCTL", -+ "$DMA_RCNT", -+ "$DMA_HSTATUS", -+ -+ "$PC", -+ "$SP_USR1", -+ "$SP_USR2", -+ "$SP_USR3", -+ "$SP_PRIV1", -+ "$SP_PRIV2", -+ "$SP_PRIV3", -+ "$BG_REGION", -+ "$SFCR", -+ "$SIGN", -+ "$ISIGN", -+ "$P_ISIGN", -+ "$IFC_LP", -+ "$ITB" -+}; -+ -+/* Define instrinsic cctl names. */ -+static const char * const nds32_cctl_names[] = -+{ -+ "L1D_VA_FILLCK", -+ "L1D_VA_ULCK", -+ "L1I_VA_FILLCK", -+ "L1I_VA_ULCK", -+ -+ "L1D_IX_WBINVAL", -+ "L1D_IX_INVAL", -+ "L1D_IX_WB", -+ "L1I_IX_INVAL", -+ -+ "L1D_VA_INVAL", -+ "L1D_VA_WB", -+ "L1D_VA_WBINVAL", -+ "L1I_VA_INVAL", -+ -+ "L1D_IX_RTAG", -+ "L1D_IX_RWD", -+ "L1I_IX_RTAG", -+ "L1I_IX_RWD", -+ -+ "L1D_IX_WTAG", -+ "L1D_IX_WWD", -+ "L1I_IX_WTAG", -+ "L1I_IX_WWD" -+}; -+ -+static const char * const nds32_dpref_names[] = -+{ -+ "SRD", -+ "MRD", -+ "SWR", -+ "MWR", -+ "PTE", -+ "CLWR" -+}; -+ -+/* Defining register allocation order for performance. -+ We want to allocate callee-saved registers after others. -+ It may be used by nds32_adjust_reg_alloc_order(). */ -+static const int nds32_reg_alloc_order_for_speed[] = -+{ -+ 0, 1, 2, 3, 4, 5, 16, 17, -+ 18, 19, 20, 21, 22, 23, 24, 25, -+ 26, 27, 6, 7, 8, 9, 10, 11, -+ 12, 13, 14, 15 - }; - - /* Defining target-specific uses of __attribute__. */ - static const struct attribute_spec nds32_attribute_table[] = - { - /* Syntax: { name, min_len, max_len, decl_required, type_required, -- function_type_required, handler, affects_type_identity } */ -+ function_type_required, handler, affects_type_identity } */ - - /* The interrupt vid: [0-63]+ (actual vector number starts from 9 to 72). */ - { "interrupt", 1, 64, false, false, false, NULL, false }, -@@ -93,6 +351,7 @@ static const struct attribute_spec nds32_attribute_table[] = - { "nested", 0, 0, false, false, false, NULL, false }, - { "not_nested", 0, 0, false, false, false, NULL, false }, - { "nested_ready", 0, 0, false, false, false, NULL, false }, -+ { "critical", 0, 0, false, false, false, NULL, false }, - - /* The attributes describing isr register save scheme. */ - { "save_all", 0, 0, false, false, false, NULL, false }, -@@ -102,17 +361,32 @@ static const struct attribute_spec nds32_attribute_table[] = - { "nmi", 1, 1, false, false, false, NULL, false }, - { "warm", 1, 1, false, false, false, NULL, false }, - -+ /* The attributes describing isr security level. */ -+ { "secure", 1, 1, false, false, false, NULL, false }, -+ - /* The attribute telling no prologue/epilogue. */ - { "naked", 0, 0, false, false, false, NULL, false }, - -+ /* The attribute is used to set signature. */ -+ { "signature", 0, 0, false, false, false, NULL, false }, -+ -+ /* The attribute is used to tell this function to be ROM patch. */ -+ { "indirect_call",0, 0, false, false, false, NULL, false }, -+ -+ /* FOR BACKWARD COMPATIBILITY, -+ this attribute also tells no prologue/epilogue. */ -+ { "no_prologue", 0, 0, false, false, false, NULL, false }, -+ -+ /* The attribute turn off hwloop optimization. */ -+ { "no_ext_zol", 0, 0, false, false, false, NULL, false}, -+ - /* The last attribute spec is set to be NULL. */ - { NULL, 0, 0, false, false, false, NULL, false } - }; - -- - /* ------------------------------------------------------------------------ */ - --/* PART 2: Auxiliary static function definitions. */ -+/* PART 3: Auxiliary static function definitions. */ - - /* Function to save and restore machine-specific function data. */ - static struct machine_function * -@@ -121,12 +395,24 @@ nds32_init_machine_status (void) - struct machine_function *machine; - machine = ggc_cleared_alloc (); - -+ /* Initially assume this function does not use __builtin_eh_return. */ -+ machine->use_eh_return_p = 0; -+ - /* Initially assume this function needs prologue/epilogue. */ - machine->naked_p = 0; - - /* Initially assume this function does NOT use fp_as_gp optimization. */ - machine->fp_as_gp_p = 0; - -+ /* 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; -+ -+ /* Initially this function hwloop group ID number. */ -+ machine->hwloop_group_id = 0; - return machine; - } - -@@ -137,23 +423,63 @@ nds32_compute_stack_frame (void) - { - int r; - int block_size; -+ bool v3pushpop_p; - - /* Because nds32_compute_stack_frame() will be called from different place, - everytime we enter this function, we have to assume this function - 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. */ -+ if (crtl->calls_eh_return) -+ { -+ frame_pointer_needed = 1; -+ -+ /* We need to mark eh data registers that need to be saved -+ in the stack. */ -+ cfun->machine->eh_return_data_first_regno = EH_RETURN_DATA_REGNO (0); -+ for (r = 0; EH_RETURN_DATA_REGNO (r) != INVALID_REGNUM; r++) -+ cfun->machine->eh_return_data_last_regno = r; -+ -+ cfun->machine->eh_return_data_regs_size -+ = 4 * (cfun->machine->eh_return_data_last_regno -+ - cfun->machine->eh_return_data_first_regno -+ + 1); -+ cfun->machine->use_eh_return_p = 1; -+ } -+ else -+ { -+ /* Assigning SP_REGNUM to eh_first_regno and eh_last_regno means we -+ do not need to handle __builtin_eh_return case in this function. */ -+ cfun->machine->eh_return_data_first_regno = SP_REGNUM; -+ cfun->machine->eh_return_data_last_regno = SP_REGNUM; -+ -+ cfun->machine->eh_return_data_regs_size = 0; -+ cfun->machine->use_eh_return_p = 0; -+ } -+ - /* Get variadic arguments size to prepare pretend arguments and - we will push them into stack at prologue by ourself. */ - cfun->machine->va_args_size = crtl->args.pretend_args_size; - if (cfun->machine->va_args_size != 0) - { - cfun->machine->va_args_first_regno -- = NDS32_GPR_ARG_FIRST_REGNUM -- + NDS32_MAX_GPR_REGS_FOR_ARGS -- - (crtl->args.pretend_args_size / UNITS_PER_WORD); -+ = NDS32_GPR_ARG_FIRST_REGNUM -+ + NDS32_MAX_GPR_REGS_FOR_ARGS -+ - (crtl->args.pretend_args_size / UNITS_PER_WORD); - cfun->machine->va_args_last_regno -- = NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS - 1; -+ = NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS - 1; - } - else - { -@@ -183,11 +509,13 @@ 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. */ -- cfun->machine->lp_size = (df_regs_ever_live_p (LP_REGNUM)) ? 4 : 0; -+ cfun->machine->lp_size -+ = (flag_always_save_lp || df_regs_ever_live_p (LP_REGNUM)) ? 4 : 0; - - /* Initially there is no padding bytes. */ - cfun->machine->callee_saved_area_gpr_padding_bytes = 0; -@@ -196,6 +524,10 @@ nds32_compute_stack_frame (void) - cfun->machine->callee_saved_gpr_regs_size = 0; - cfun->machine->callee_saved_first_gpr_regno = SP_REGNUM; - cfun->machine->callee_saved_last_gpr_regno = SP_REGNUM; -+ cfun->machine->callee_saved_fpr_regs_size = 0; -+ cfun->machine->callee_saved_first_fpr_regno = SP_REGNUM; -+ cfun->machine->callee_saved_last_fpr_regno = SP_REGNUM; -+ - /* Currently, there is no need to check $r28~$r31 - because we will save them in another way. */ - for (r = 0; r < 28; r++) -@@ -213,43 +545,77 @@ nds32_compute_stack_frame (void) - } - } - -+ /* Recording fpu callee-saved register. */ -+ if (TARGET_HARD_FLOAT) -+ { -+ for (r = NDS32_FIRST_FPR_REGNUM; r < NDS32_LAST_FPR_REGNUM; r++) -+ { -+ if (NDS32_REQUIRED_CALLEE_SAVED_P (r)) -+ { -+ /* Mark the first required callee-saved register. */ -+ if (cfun->machine->callee_saved_first_fpr_regno == SP_REGNUM) -+ { -+ /* Make first callee-saved number is even, -+ bacause we use doubleword access, and this way -+ promise 8-byte alignemt. */ -+ if (!NDS32_FPR_REGNO_OK_FOR_DOUBLE (r)) -+ cfun->machine->callee_saved_first_fpr_regno = r - 1; -+ else -+ cfun->machine->callee_saved_first_fpr_regno = r; -+ } -+ cfun->machine->callee_saved_last_fpr_regno = r; -+ } -+ } -+ -+ /* Make last callee-saved register number is odd, -+ we hope callee-saved register is even. */ -+ int last_fpr = cfun->machine->callee_saved_last_fpr_regno; -+ if (NDS32_FPR_REGNO_OK_FOR_DOUBLE (last_fpr)) -+ cfun->machine->callee_saved_last_fpr_regno++; -+ } -+ - /* 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, - we can set this function 'naked_p' as well: - condition 1: first_regno == last_regno == SP_REGNUM, -- which means we do not have to save -- any callee-saved registers. -+ which means we do not have to save -+ any callee-saved registers. - condition 2: Both $lp and $fp are NOT live in this function, -- which means we do not need to save them and there -- is no outgoing size. -+ which means we do not need to save them and there -+ 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)) -+ we do not need to adjust $sp. */ -+ 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 -- callee-saved, local size, and outgoing size. -- The varargs space and ret instruction may still present in -- the prologue/epilogue expanding. */ -+ Note that in nds32 port, the 'naked_p = 1' JUST means there is no -+ callee-saved, local size, and outgoing size. -+ The varargs space and ret instruction may still present in -+ the prologue/epilogue expanding. */ - cfun->machine->naked_p = 1; - - /* No need to save $fp, $gp, and $lp. -- We should set these value to be zero -- so that nds32_initial_elimination_offset() can work properly. */ -+ We should set these value to be zero -+ so that nds32_initial_elimination_offset() can work properly. */ - cfun->machine->fp_size = 0; - cfun->machine->gp_size = 0; - cfun->machine->lp_size = 0; - - /* If stack usage computation is required, -- we need to provide the static stack size. */ -+ we need to provide the static stack size. */ - if (flag_stack_usage_info) - current_function_static_stack_size = 0; - -@@ -257,6 +623,8 @@ nds32_compute_stack_frame (void) - return; - } - -+ v3pushpop_p = NDS32_V3PUSH_AVAILABLE_P; -+ - /* Adjustment for v3push instructions: - If we are using v3push (push25/pop25) instructions, - we need to make sure Rb is $r6 and Re is -@@ -264,16 +632,14 @@ nds32_compute_stack_frame (void) - Some results above will be discarded and recomputed. - Note that it is only available under V3/V3M ISA and we - DO NOT setup following stuff for isr or variadic function. */ -- if (TARGET_V3PUSH -- && !nds32_isr_function_p (current_function_decl) -- && (cfun->machine->va_args_size == 0)) -+ if (v3pushpop_p) - { - /* Recompute: -- cfun->machine->fp_size -- cfun->machine->gp_size -- cfun->machine->lp_size -- cfun->machine->callee_saved_regs_first_regno -- cfun->machine->callee_saved_regs_last_regno */ -+ cfun->machine->fp_size -+ cfun->machine->gp_size -+ cfun->machine->lp_size -+ cfun->machine->callee_saved_first_gpr_regno -+ cfun->machine->callee_saved_last_gpr_regno */ - - /* For v3push instructions, $fp, $gp, and $lp are always saved. */ - cfun->machine->fp_size = 4; -@@ -316,11 +682,46 @@ nds32_compute_stack_frame (void) - } - } - -- /* We have correctly set callee_saved_regs_first_regno -- and callee_saved_regs_last_regno. -- Initially, the callee_saved_regs_size is supposed to be 0. -- As long as callee_saved_regs_last_regno is not SP_REGNUM, -- we can update callee_saved_regs_size with new size. */ -+ int sp_adjust = cfun->machine->local_size -+ + cfun->machine->out_args_size -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ -+ if (!v3pushpop_p -+ && nds32_memory_model_option == MEMORY_MODEL_FAST -+ && sp_adjust == 0 -+ && !frame_pointer_needed) -+ { -+ block_size = cfun->machine->fp_size -+ + cfun->machine->gp_size -+ + cfun->machine->lp_size -+ + (4 * (cfun->machine->callee_saved_last_gpr_regno -+ - cfun->machine->callee_saved_first_gpr_regno -+ + 1)); -+ -+ if (!NDS32_DOUBLE_WORD_ALIGN_P (block_size)) -+ { -+ /* $r14 is last callee save register. */ -+ if (cfun->machine->callee_saved_last_gpr_regno -+ < NDS32_LAST_CALLEE_SAVE_GPR_REGNUM) -+ { -+ cfun->machine->callee_saved_last_gpr_regno++; -+ } -+ else if (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM) -+ { -+ cfun->machine->callee_saved_first_gpr_regno -+ = NDS32_FIRST_CALLEE_SAVE_GPR_REGNUM; -+ cfun->machine->callee_saved_last_gpr_regno -+ = NDS32_FIRST_CALLEE_SAVE_GPR_REGNUM; -+ } -+ } -+ } -+ -+ /* We have correctly set callee_saved_first_gpr_regno -+ and callee_saved_last_gpr_regno. -+ Initially, the callee_saved_gpr_regs_size is supposed to be 0. -+ As long as callee_saved_last_gpr_regno is not SP_REGNUM, -+ we can update callee_saved_gpr_regs_size with new size. */ - if (cfun->machine->callee_saved_last_gpr_regno != SP_REGNUM) - { - /* Compute pushed size of callee-saved registers. */ -@@ -330,10 +731,22 @@ nds32_compute_stack_frame (void) - + 1); - } - -+ if (TARGET_HARD_FLOAT) -+ { -+ /* Compute size of callee svaed floating-point registers. */ -+ if (cfun->machine->callee_saved_last_fpr_regno != SP_REGNUM) -+ { -+ cfun->machine->callee_saved_fpr_regs_size -+ = 4 * (cfun->machine->callee_saved_last_fpr_regno -+ - cfun->machine->callee_saved_first_fpr_regno -+ + 1); -+ } -+ } -+ - /* Important: We need to make sure that -- (fp_size + gp_size + lp_size + callee_saved_regs_size) -- is 8-byte alignment. -- If it is not, calculate the padding bytes. */ -+ (fp_size + gp_size + lp_size + callee_saved_gpr_regs_size) -+ is 8-byte alignment. -+ If it is not, calculate the padding bytes. */ - block_size = cfun->machine->fp_size - + cfun->machine->gp_size - + cfun->machine->lp_size -@@ -361,14 +774,15 @@ nds32_compute_stack_frame (void) - "push registers to memory", - "adjust stack pointer". */ - static void --nds32_emit_stack_push_multiple (rtx Rb, rtx Re, rtx En4, bool vaarg_p) -+nds32_emit_stack_push_multiple (unsigned Rb, unsigned Re, -+ bool save_fp_p, bool save_gp_p, bool save_lp_p, -+ bool vaarg_p) - { -- int regno; -+ unsigned regno; - int extra_count; - int num_use_regs; - int par_index; - int offset; -- int save_fp, save_gp, save_lp; - - rtx reg; - rtx mem; -@@ -381,39 +795,34 @@ nds32_emit_stack_push_multiple (rtx Rb, rtx Re, rtx En4, bool vaarg_p) - necessary information for data analysis, - so we create a parallel rtx like this: - (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32))) -- (reg:SI Rb)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) -- (reg:SI Rb+1)) -- ... -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) -- (reg:SI Re)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) -- (reg:SI FP_REGNUM)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) -- (reg:SI GP_REGNUM)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) -- (reg:SI LP_REGNUM)) -- (set (reg:SI SP_REGNUM) -- (plus (reg:SI SP_REGNUM) (const_int -32)))]) */ -- -- /* Determine whether we need to save $fp, $gp, or $lp. */ -- save_fp = INTVAL (En4) & 0x8; -- save_gp = INTVAL (En4) & 0x4; -- save_lp = INTVAL (En4) & 0x2; -+ (reg:SI Rb)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) -+ (reg:SI Rb+1)) -+ ... -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) -+ (reg:SI Re)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) -+ (reg:SI FP_REGNUM)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) -+ (reg:SI GP_REGNUM)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) -+ (reg:SI LP_REGNUM)) -+ (set (reg:SI SP_REGNUM) -+ (plus (reg:SI SP_REGNUM) (const_int -32)))]) */ - - /* Calculate the number of registers that will be pushed. */ - extra_count = 0; -- if (save_fp) -+ if (save_fp_p) - extra_count++; -- if (save_gp) -+ if (save_gp_p) - extra_count++; -- if (save_lp) -+ if (save_lp_p) - extra_count++; - /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */ -- if (REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM) -+ if (Rb == SP_REGNUM && Re == SP_REGNUM) - num_use_regs = extra_count; - else -- num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + extra_count; -+ num_use_regs = Re - Rb + 1 + extra_count; - - /* In addition to used registers, - we need one more space for (set sp sp-x) rtx. */ -@@ -425,10 +834,10 @@ nds32_emit_stack_push_multiple (rtx Rb, rtx Re, rtx En4, bool vaarg_p) - offset = -(num_use_regs * 4); - - /* Create (set mem regX) from Rb, Rb+1 up to Re. */ -- for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++) -+ for (regno = Rb; regno <= Re; regno++) - { - /* Rb and Re may be SP_REGNUM. -- We need to break this loop immediately. */ -+ We need to break this loop immediately. */ - if (regno == SP_REGNUM) - break; - -@@ -444,7 +853,7 @@ nds32_emit_stack_push_multiple (rtx Rb, rtx Re, rtx En4, bool vaarg_p) - } - - /* Create (set mem fp), (set mem gp), and (set mem lp) if necessary. */ -- if (save_fp) -+ if (save_fp_p) - { - reg = gen_rtx_REG (SImode, FP_REGNUM); - mem = gen_frame_mem (SImode, plus_constant (Pmode, -@@ -456,7 +865,7 @@ nds32_emit_stack_push_multiple (rtx Rb, rtx Re, rtx En4, bool vaarg_p) - offset = offset + 4; - par_index++; - } -- if (save_gp) -+ if (save_gp_p) - { - reg = gen_rtx_REG (SImode, GP_REGNUM); - mem = gen_frame_mem (SImode, plus_constant (Pmode, -@@ -468,7 +877,7 @@ nds32_emit_stack_push_multiple (rtx Rb, rtx Re, rtx En4, bool vaarg_p) - offset = offset + 4; - par_index++; - } -- if (save_lp) -+ if (save_lp_p) - { - reg = gen_rtx_REG (SImode, LP_REGNUM); - mem = gen_frame_mem (SImode, plus_constant (Pmode, -@@ -514,14 +923,14 @@ nds32_emit_stack_push_multiple (rtx Rb, rtx Re, rtx En4, bool vaarg_p) - "pop registers from memory", - "adjust stack pointer". */ - static void --nds32_emit_stack_pop_multiple (rtx Rb, rtx Re, rtx En4) -+nds32_emit_stack_pop_multiple (unsigned Rb, unsigned Re, -+ bool save_fp_p, bool save_gp_p, bool save_lp_p) - { -- int regno; -+ unsigned regno; - int extra_count; - int num_use_regs; - int par_index; - int offset; -- int save_fp, save_gp, save_lp; - - rtx reg; - rtx mem; -@@ -534,39 +943,34 @@ nds32_emit_stack_pop_multiple (rtx Rb, rtx Re, rtx En4) - necessary information for data analysis, - so we create a parallel rtx like this: - (parallel [(set (reg:SI Rb) -- (mem (reg:SI SP_REGNUM))) -- (set (reg:SI Rb+1) -- (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) -- ... -- (set (reg:SI Re) -- (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) -- (set (reg:SI FP_REGNUM) -- (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) -- (set (reg:SI GP_REGNUM) -- (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) -- (set (reg:SI LP_REGNUM) -- (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) -- (set (reg:SI SP_REGNUM) -- (plus (reg:SI SP_REGNUM) (const_int 32)))]) */ -- -- /* Determine whether we need to restore $fp, $gp, or $lp. */ -- save_fp = INTVAL (En4) & 0x8; -- save_gp = INTVAL (En4) & 0x4; -- save_lp = INTVAL (En4) & 0x2; -+ (mem (reg:SI SP_REGNUM))) -+ (set (reg:SI Rb+1) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) -+ ... -+ (set (reg:SI Re) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) -+ (set (reg:SI FP_REGNUM) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) -+ (set (reg:SI GP_REGNUM) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) -+ (set (reg:SI LP_REGNUM) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) -+ (set (reg:SI SP_REGNUM) -+ (plus (reg:SI SP_REGNUM) (const_int 32)))]) */ - - /* Calculate the number of registers that will be poped. */ - extra_count = 0; -- if (save_fp) -+ if (save_fp_p) - extra_count++; -- if (save_gp) -+ if (save_gp_p) - extra_count++; -- if (save_lp) -+ if (save_lp_p) - extra_count++; - /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */ -- if (REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM) -+ if (Rb == SP_REGNUM && Re == SP_REGNUM) - num_use_regs = extra_count; - else -- num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + extra_count; -+ num_use_regs = Re - Rb + 1 + extra_count; - - /* In addition to used registers, - we need one more space for (set sp sp+x) rtx. */ -@@ -578,10 +982,10 @@ nds32_emit_stack_pop_multiple (rtx Rb, rtx Re, rtx En4) - offset = 0; - - /* Create (set regX mem) from Rb, Rb+1 up to Re. */ -- for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++) -+ for (regno = Rb; regno <= Re; regno++) - { - /* Rb and Re may be SP_REGNUM. -- We need to break this loop immediately. */ -+ We need to break this loop immediately. */ - if (regno == SP_REGNUM) - break; - -@@ -599,7 +1003,7 @@ nds32_emit_stack_pop_multiple (rtx Rb, rtx Re, rtx En4) - } - - /* Create (set fp mem), (set gp mem), and (set lp mem) if necessary. */ -- if (save_fp) -+ if (save_fp_p) - { - reg = gen_rtx_REG (SImode, FP_REGNUM); - mem = gen_frame_mem (SImode, plus_constant (Pmode, -@@ -613,7 +1017,7 @@ nds32_emit_stack_pop_multiple (rtx Rb, rtx Re, rtx En4) - - dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf); - } -- if (save_gp) -+ if (save_gp_p) - { - reg = gen_rtx_REG (SImode, GP_REGNUM); - mem = gen_frame_mem (SImode, plus_constant (Pmode, -@@ -627,7 +1031,7 @@ nds32_emit_stack_pop_multiple (rtx Rb, rtx Re, rtx En4) - - dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf); - } -- if (save_lp) -+ if (save_lp_p) - { - reg = gen_rtx_REG (SImode, LP_REGNUM); - mem = gen_frame_mem (SImode, plus_constant (Pmode, -@@ -670,12 +1074,11 @@ nds32_emit_stack_pop_multiple (rtx Rb, rtx Re, rtx En4) - "push registers to memory", - "adjust stack pointer". */ - static void --nds32_emit_stack_v3push (rtx Rb, -- rtx Re, -- rtx En4 ATTRIBUTE_UNUSED, -- rtx imm8u) -+nds32_emit_stack_v3push (unsigned Rb, -+ unsigned Re, -+ unsigned imm8u) - { -- int regno; -+ unsigned regno; - int num_use_regs; - int par_index; - int offset; -@@ -690,27 +1093,27 @@ nds32_emit_stack_v3push (rtx Rb, - necessary information for data analysis, - so we create a parallel rtx like this: - (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32))) -- (reg:SI Rb)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) -- (reg:SI Rb+1)) -- ... -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) -- (reg:SI Re)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) -- (reg:SI FP_REGNUM)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) -- (reg:SI GP_REGNUM)) -- (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) -- (reg:SI LP_REGNUM)) -- (set (reg:SI SP_REGNUM) -- (plus (reg:SI SP_REGNUM) (const_int -32-imm8u)))]) */ -+ (reg:SI Rb)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) -+ (reg:SI Rb+1)) -+ ... -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) -+ (reg:SI Re)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) -+ (reg:SI FP_REGNUM)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) -+ (reg:SI GP_REGNUM)) -+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) -+ (reg:SI LP_REGNUM)) -+ (set (reg:SI SP_REGNUM) -+ (plus (reg:SI SP_REGNUM) (const_int -32-imm8u)))]) */ - - /* Calculate the number of registers that will be pushed. - Since $fp, $gp, and $lp is always pushed with v3push instruction, - we need to count these three registers. - Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14. - So there is no need to worry about Rb=Re=SP_REGNUM case. */ -- num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + 3; -+ num_use_regs = Re - Rb + 1 + 3; - - /* In addition to used registers, - we need one more space for (set sp sp-x-imm8u) rtx. */ -@@ -724,7 +1127,7 @@ nds32_emit_stack_v3push (rtx Rb, - /* Create (set mem regX) from Rb, Rb+1 up to Re. - Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14. - So there is no need to worry about Rb=Re=SP_REGNUM case. */ -- for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++) -+ for (regno = Rb; regno <= Re; regno++) - { - reg = gen_rtx_REG (SImode, regno); - mem = gen_frame_mem (SImode, plus_constant (Pmode, -@@ -776,7 +1179,7 @@ nds32_emit_stack_v3push (rtx Rb, - = gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, - stack_pointer_rtx, -- offset - INTVAL (imm8u))); -+ offset - imm8u)); - XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx; - RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1; - -@@ -794,12 +1197,11 @@ nds32_emit_stack_v3push (rtx Rb, - "pop registers from memory", - "adjust stack pointer". */ - static void --nds32_emit_stack_v3pop (rtx Rb, -- rtx Re, -- rtx En4 ATTRIBUTE_UNUSED, -- rtx imm8u) -+nds32_emit_stack_v3pop (unsigned Rb, -+ unsigned Re, -+ unsigned imm8u) - { -- int regno; -+ unsigned regno; - int num_use_regs; - int par_index; - int offset; -@@ -815,27 +1217,27 @@ nds32_emit_stack_v3pop (rtx Rb, - necessary information for data analysis, - so we create a parallel rtx like this: - (parallel [(set (reg:SI Rb) -- (mem (reg:SI SP_REGNUM))) -- (set (reg:SI Rb+1) -- (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) -- ... -- (set (reg:SI Re) -- (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) -- (set (reg:SI FP_REGNUM) -- (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) -- (set (reg:SI GP_REGNUM) -- (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) -- (set (reg:SI LP_REGNUM) -- (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) -- (set (reg:SI SP_REGNUM) -- (plus (reg:SI SP_REGNUM) (const_int 32+imm8u)))]) */ -+ (mem (reg:SI SP_REGNUM))) -+ (set (reg:SI Rb+1) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) -+ ... -+ (set (reg:SI Re) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) -+ (set (reg:SI FP_REGNUM) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) -+ (set (reg:SI GP_REGNUM) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) -+ (set (reg:SI LP_REGNUM) -+ (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) -+ (set (reg:SI SP_REGNUM) -+ (plus (reg:SI SP_REGNUM) (const_int 32+imm8u)))]) */ - - /* Calculate the number of registers that will be poped. - Since $fp, $gp, and $lp is always poped with v3pop instruction, - we need to count these three registers. - Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14. - So there is no need to worry about Rb=Re=SP_REGNUM case. */ -- num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + 3; -+ num_use_regs = Re - Rb + 1 + 3; - - /* In addition to used registers, - we need one more space for (set sp sp+x+imm8u) rtx. */ -@@ -849,7 +1251,7 @@ nds32_emit_stack_v3pop (rtx Rb, - /* Create (set regX mem) from Rb, Rb+1 up to Re. - Under v3pop, Rb is $r6, while Re is $r6, $r8, $r10, or $r14. - So there is no need to worry about Rb=Re=SP_REGNUM case. */ -- for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++) -+ for (regno = Rb; regno <= Re; regno++) - { - reg = gen_rtx_REG (SImode, regno); - mem = gen_frame_mem (SImode, plus_constant (Pmode, -@@ -907,11 +1309,24 @@ nds32_emit_stack_v3pop (rtx Rb, - = gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, - stack_pointer_rtx, -- offset + INTVAL (imm8u))); -+ offset + imm8u)); - XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx; - -- /* Tell gcc we adjust SP in this insn. */ -- dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, copy_rtx (adjust_sp_rtx), dwarf); -+ if (frame_pointer_needed) -+ { -+ /* (expr_list:REG_CFA_DEF_CFA (plus:SI (reg/f:SI $sp) -+ (const_int 0)) -+ mean reset frame pointer to $sp and reset to offset 0. */ -+ rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, -+ const0_rtx); -+ dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); -+ } -+ else -+ { -+ /* Tell gcc we adjust SP in this insn. */ -+ dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, -+ copy_rtx (adjust_sp_rtx), dwarf); -+ } - - parallel_insn = emit_insn (parallel_insn); - -@@ -924,6 +1339,32 @@ nds32_emit_stack_v3pop (rtx 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. - -@@ -933,79 +1374,70 @@ nds32_emit_stack_v3pop (rtx Rb, - the adjustment value is not able to be fit in the 'addi' instruction. - One solution is to move value into a register - and then use 'add' instruction. -- In practice, we use TA_REGNUM ($r15) to accomplish this purpose. -- Also, we need to return zero for sp adjustment so that -- proglogue/epilogue knows there is no need to create 'addi' instruction. */ --static int --nds32_force_addi_stack_int (int full_value) -+ In practice, we use TA_REGNUM ($r15) to accomplish this purpose. */ -+static void -+nds32_emit_adjust_frame (rtx to_reg, rtx from_reg, int adjust_value) - { -- int adjust_value; -- - rtx tmp_reg; -- rtx sp_adjust_insn; -+ rtx frame_adjust_insn; -+ rtx adjust_value_rtx = GEN_INT (adjust_value); - -- if (!satisfies_constraint_Is15 (GEN_INT (full_value))) -+ if (adjust_value == 0) -+ return; -+ -+ if (!satisfies_constraint_Is15 (adjust_value_rtx)) - { - /* The value is not able to fit in single addi instruction. -- Create more instructions of moving value into a register -- and then add stack pointer with it. */ -+ Create more instructions of moving value into a register -+ and then add stack pointer with it. */ - - /* $r15 is going to be temporary register to hold the value. */ - tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); - - /* Create one more instruction to move value -- into the temporary register. */ -- emit_move_insn (tmp_reg, GEN_INT (full_value)); -+ into the temporary register. */ -+ emit_move_insn (tmp_reg, adjust_value_rtx); - - /* Create new 'add' rtx. */ -- sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, -- stack_pointer_rtx, -- tmp_reg); -+ frame_adjust_insn = gen_addsi3 (to_reg, -+ from_reg, -+ tmp_reg); - /* Emit rtx into insn list and receive its transformed insn rtx. */ -- sp_adjust_insn = emit_insn (sp_adjust_insn); -- -- /* At prologue, we need to tell GCC that this is frame related insn, -- so that we can consider this instruction to output debug information. -- If full_value is NEGATIVE, it means this function -- is invoked by expand_prologue. */ -- if (full_value < 0) -- { -- /* Because (tmp_reg <- full_value) may be split into two -- rtl patterns, we can not set its RTX_FRAME_RELATED_P. -- We need to construct another (sp <- sp + full_value) -- and then insert it into sp_adjust_insn's reg note to -- represent a frame related expression. -- GCC knows how to refer it and output debug information. */ -- -- rtx plus_rtx; -- rtx set_rtx; -+ frame_adjust_insn = emit_insn (frame_adjust_insn); - -- plus_rtx = plus_constant (Pmode, stack_pointer_rtx, full_value); -- set_rtx = gen_rtx_SET (stack_pointer_rtx, plus_rtx); -- add_reg_note (sp_adjust_insn, REG_FRAME_RELATED_EXPR, set_rtx); -+ /* Because (tmp_reg <- full_value) may be split into two -+ rtl patterns, we can not set its RTX_FRAME_RELATED_P. -+ We need to construct another (sp <- sp + full_value) -+ and then insert it into sp_adjust_insn's reg note to -+ represent a frame related expression. -+ GCC knows how to refer it and output debug information. */ - -- RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; -- } -+ rtx plus_rtx; -+ rtx set_rtx; - -- /* We have used alternative way to adjust stack pointer value. -- Return zero so that prologue/epilogue -- will not generate other instructions. */ -- return 0; -+ plus_rtx = plus_constant (Pmode, from_reg, adjust_value); -+ set_rtx = gen_rtx_SET (to_reg, plus_rtx); -+ add_reg_note (frame_adjust_insn, REG_FRAME_RELATED_EXPR, set_rtx); - } - else - { -- /* The value is able to fit in addi instruction. -- However, remember to make it to be positive value -- because we want to return 'adjustment' result. */ -- adjust_value = (full_value < 0) ? (-full_value) : (full_value); -- -- return adjust_value; -+ /* Generate sp adjustment instruction if and only if sp_adjust != 0. */ -+ frame_adjust_insn = gen_addsi3 (to_reg, -+ from_reg, -+ adjust_value_rtx); -+ /* Emit rtx into instructions list and receive INSN rtx form. */ -+ frame_adjust_insn = emit_insn (frame_adjust_insn); - } -+ -+ /* The insn rtx 'sp_adjust_insn' will change frame layout. -+ We need to use RTX_FRAME_RELATED_P so that GCC is able to -+ generate CFI (Call Frame Information) stuff. */ -+ RTX_FRAME_RELATED_P (frame_adjust_insn) = 1; - } - - /* Return true if MODE/TYPE need double word alignment. */ - static bool --nds32_needs_double_word_align (machine_mode mode, const_tree type) -+nds32_needs_double_word_align (enum machine_mode mode, const_tree type) - { - unsigned int align; - -@@ -1015,18 +1447,25 @@ nds32_needs_double_word_align (machine_mode mode, const_tree type) - return (align > PARM_BOUNDARY); - } - --/* 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 check if 'X' is a valid address register. -@@ -1035,7 +1474,7 @@ nds32_naked_function_p (tree func) - - STRICT : true - => We are in reload pass or after reload pass. -- The register number should be strictly limited in general registers. -+ The register number should be strictly limited in general registers. - - STRICT : false - => Before reload pass, we are free to use any register number. */ -@@ -1058,10 +1497,10 @@ nds32_address_register_rtx_p (rtx x, bool strict) - /* Function that check if 'INDEX' is valid to be a index rtx for address. - - OUTER_MODE : Machine mode of outer address rtx. -- INDEX : Check if this rtx is valid to be a index for address. -+ INDEX : Check if this rtx is valid to be a index for address. - STRICT : If it is true, we are in reload pass or after reload pass. */ - static bool --nds32_legitimate_index_p (machine_mode outer_mode, -+nds32_legitimate_index_p (enum machine_mode outer_mode, - rtx index, - bool strict) - { -@@ -1074,7 +1513,7 @@ nds32_legitimate_index_p (machine_mode outer_mode, - case REG: - regno = REGNO (index); - /* If we are in reload pass or after reload pass, -- we need to limit it to general register. */ -+ we need to limit it to general register. */ - if (strict) - return REGNO_OK_FOR_INDEX_P (regno); - else -@@ -1082,45 +1521,73 @@ nds32_legitimate_index_p (machine_mode outer_mode, - - case CONST_INT: - /* The alignment of the integer value is determined by 'outer_mode'. */ -- if (GET_MODE_SIZE (outer_mode) == 1) -+ switch (GET_MODE_SIZE (outer_mode)) - { -+ case 1: - /* Further check if the value is legal for the 'outer_mode'. */ -- if (!satisfies_constraint_Is15 (index)) -- return false; -+ if (satisfies_constraint_Is15 (index)) -+ return true; -+ break; - -- /* Pass all test, the value is valid, return true. */ -- return true; -- } -- if (GET_MODE_SIZE (outer_mode) == 2 -- && NDS32_HALF_WORD_ALIGN_P (INTVAL (index))) -- { -+ case 2: - /* Further check if the value is legal for the 'outer_mode'. */ -- if (!satisfies_constraint_Is16 (index)) -- return false; -+ if (satisfies_constraint_Is16 (index)) -+ { -+ /* If it is not under strictly aligned situation, -+ we can return true without checking alignment. */ -+ if (!cfun->machine->strict_aligned_p) -+ return true; -+ /* Make sure address is half word alignment. */ -+ else if (NDS32_HALF_WORD_ALIGN_P (INTVAL (index))) -+ return true; -+ } -+ break; - -- /* Pass all test, the value is valid, return true. */ -- return true; -- } -- if (GET_MODE_SIZE (outer_mode) == 4 -- && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index))) -- { -+ case 4: - /* Further check if the value is legal for the 'outer_mode'. */ -- if (!satisfies_constraint_Is17 (index)) -- return false; -+ if (satisfies_constraint_Is17 (index)) -+ { -+ if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)) -+ { -+ if (!satisfies_constraint_Is14 (index)) -+ return false; -+ } -+ -+ /* If it is not under strictly aligned situation, -+ we can return true without checking alignment. */ -+ if (!cfun->machine->strict_aligned_p) -+ return true; -+ /* Make sure address is word alignment. */ -+ else if (NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index))) -+ return true; -+ } -+ break; - -- /* Pass all test, the value is valid, return true. */ -- return true; -- } -- if (GET_MODE_SIZE (outer_mode) == 8 -- && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index))) -- { -- /* Further check if the value is legal for the 'outer_mode'. */ -- if (!satisfies_constraint_Is17 (gen_int_mode (INTVAL (index) + 4, -- SImode))) -- return false; -+ case 8: -+ if (satisfies_constraint_Is17 (gen_int_mode (INTVAL (index) + 4, -+ SImode))) -+ { -+ if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)) -+ { -+ if (!satisfies_constraint_Is14 (index)) -+ return false; -+ } -+ -+ /* If it is not under strictly aligned situation, -+ we can return true without checking alignment. */ -+ if (!cfun->machine->strict_aligned_p) -+ return true; -+ /* Make sure address is word alignment. -+ Currently we do not have 64-bit load/store yet, -+ so we will use two 32-bit load/store instructions to do -+ memory access and they are single word alignment. */ -+ else if (NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index))) -+ return true; -+ } -+ break; - -- /* Pass all test, the value is valid, return true. */ -- return true; -+ default: -+ return false; - } - - return false; -@@ -1134,9 +1601,10 @@ nds32_legitimate_index_p (machine_mode outer_mode, - int multiplier; - multiplier = INTVAL (op1); - -- /* We only allow (mult reg const_int_1) -- or (mult reg const_int_2) or (mult reg const_int_4). */ -- if (multiplier != 1 && multiplier != 2 && multiplier != 4) -+ /* We only allow (mult reg const_int_1), (mult reg const_int_2), -+ (mult reg const_int_4) or (mult reg const_int_8). */ -+ if (multiplier != 1 && multiplier != 2 -+ && multiplier != 4 && multiplier != 8) - return false; - - regno = REGNO (op0); -@@ -1161,8 +1629,9 @@ nds32_legitimate_index_p (machine_mode outer_mode, - sv = INTVAL (op1); - - /* We only allow (ashift reg const_int_0) -- or (ashift reg const_int_1) or (ashift reg const_int_2). */ -- if (sv != 0 && sv != 1 && sv !=2) -+ or (ashift reg const_int_1) or (ashift reg const_int_2) or -+ (ashift reg const_int_3). */ -+ if (sv != 0 && sv != 1 && sv !=2 && sv != 3) - return false; - - regno = REGNO (op0); -@@ -1181,18 +1650,302 @@ nds32_legitimate_index_p (machine_mode outer_mode, - } - } - -+static void -+nds32_insert_innermost_loop (void) -+{ -+ struct loop *loop; -+ basic_block *bbs, bb; -+ -+ compute_bb_for_insn (); -+ /* initial loop structure */ -+ loop_optimizer_init (AVOID_CFG_MODIFICATIONS); -+ -+ /* Scan all inner most loops. */ -+ FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST) -+ { -+ bbs = get_loop_body (loop); -+ bb = *bbs; -+ free (bbs); -+ -+ emit_insn_before (gen_innermost_loop_begin (), -+ BB_HEAD (bb)); -+ -+ /* Find the final basic block in the loop. */ -+ while (bb) -+ { -+ if (bb->next_bb == NULL) -+ break; -+ -+ if (bb->next_bb->loop_father != loop) -+ break; -+ -+ bb = bb->next_bb; -+ } -+ -+ emit_insn_before (gen_innermost_loop_end (), -+ BB_END (bb)); -+ } -+ -+ /* release loop structre */ -+ loop_optimizer_finalize (); -+} -+ -+/* Insert isps for function with signature attribute. */ -+static void -+nds32_insert_isps (void) -+{ -+ rtx_insn *insn; -+ unsigned first = 0; -+ -+ if (!lookup_attribute ("signature", DECL_ATTRIBUTES (current_function_decl))) -+ return; -+ -+ insn = get_insns (); -+ while (insn) -+ { -+ /* In order to ensure protect whole function, emit the first -+ isps here rather than in prologue.*/ -+ if (!first && INSN_P (insn)) -+ { -+ emit_insn_before (gen_unspec_signature_begin (), insn); -+ first = 1; -+ } -+ -+ if (LABEL_P (insn) || CALL_P (insn) || any_condjump_p (insn) -+ || (INSN_P (insn) && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE -+ && (XINT (PATTERN (insn), 1) == UNSPEC_VOLATILE_SYSCALL -+ || XINT (PATTERN (insn), 1) == UNSPEC_VOLATILE_TRAP -+ || XINT (PATTERN (insn), 1) == UNSPEC_VOLATILE_TEQZ -+ || XINT (PATTERN (insn), 1) == UNSPEC_VOLATILE_TNEZ))) -+ { -+ emit_insn_after (gen_unspec_signature_begin (), insn); -+ } -+ insn = NEXT_INSN (insn); -+ } -+} -+ -+static void -+nds32_register_pass ( -+ rtl_opt_pass *(*make_pass_func) (gcc::context *), -+ enum pass_positioning_ops pass_pos, -+ const char *ref_pass_name) -+{ -+ opt_pass *new_opt_pass = make_pass_func (g); -+ -+ struct register_pass_info insert_pass = -+ { -+ new_opt_pass, /* pass */ -+ ref_pass_name, /* reference_pass_name */ -+ 1, /* ref_pass_instance_number */ -+ pass_pos /* po_op */ -+ }; -+ -+ register_pass (&insert_pass); -+} -+ -+static void -+nds32_register_pass ( -+ gimple_opt_pass *(*make_pass_func) (gcc::context *), -+ enum pass_positioning_ops pass_pos, -+ const char *ref_pass_name) -+{ -+ opt_pass *new_opt_pass = make_pass_func (g); -+ -+ struct register_pass_info insert_pass = -+ { -+ new_opt_pass, /* pass */ -+ ref_pass_name, /* reference_pass_name */ -+ 1, /* ref_pass_instance_number */ -+ pass_pos /* po_op */ -+ }; -+ -+ register_pass (&insert_pass); -+} -+ -+/* This function is called from nds32_option_override (). -+ All new passes should be registered here. */ -+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, -+ "mach"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_load_store_opt, -+ PASS_POS_INSERT_AFTER, -+ "mach"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_soft_fp_arith_comm_opt, -+ PASS_POS_INSERT_BEFORE, -+ "mach"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_regrename_opt, -+ PASS_POS_INSERT_AFTER, -+ "mach"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_gcse_opt, -+ PASS_POS_INSERT_BEFORE, -+ "cprop_hardreg"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_cprop_acc_opt, -+ PASS_POS_INSERT_AFTER, -+ "cprop_hardreg"); -+ -+ nds32_register_pass ( -+ make_pass_cprop_hardreg, -+ PASS_POS_INSERT_AFTER, -+ "mach"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_rename_lmwsmw_opt, -+ PASS_POS_INSERT_AFTER, -+ "jump2"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_gen_lmwsmw_opt, -+ PASS_POS_INSERT_BEFORE, -+ "peephole2"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_const_remater_opt, -+ PASS_POS_INSERT_BEFORE, -+ "ira"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_scalbn_transform_opt, -+ PASS_POS_INSERT_AFTER, -+ "optimized"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_sign_conversion_opt, -+ PASS_POS_INSERT_BEFORE, -+ "optimized"); -+ -+ nds32_register_pass ( -+ make_pass_nds32_abi_compatible, -+ PASS_POS_INSERT_BEFORE, -+ "optimized"); -+ -+ nds32_register_pass ( -+ nds32::scheduling::make_pass_nds32_print_stalls, -+ PASS_POS_INSERT_BEFORE, -+ "final"); -+} -+ - /* ------------------------------------------------------------------------ */ - --/* PART 3: Implement target hook stuff definitions. */ -+/* PART 4: Implement target hook stuff definitions. */ -+ -+ -+/* Computing the Length of an Insn. -+ Modifies the length assigned to instruction INSN. -+ LEN is the initially computed length of the insn. */ -+int -+nds32_adjust_insn_length (rtx_insn *insn, int length) -+{ -+ int adjust_value = 0; -+ switch (recog_memoized (insn)) -+ { -+ case CODE_FOR_call_internal: -+ case CODE_FOR_call_value_internal: -+ { -+ if (NDS32_ALIGN_P ()) -+ { -+ rtx_insn *next_insn = next_active_insn (insn); -+ if (next_insn && get_attr_length (next_insn) != 2) -+ adjust_value += 2; -+ } -+ /* We need insert a nop after a noretun function call -+ to prevent software breakpoint corrupt the next function. */ -+ if (find_reg_note (insn, REG_NORETURN, NULL_RTX)) -+ { -+ if (TARGET_16_BIT) -+ adjust_value += 2; -+ else -+ adjust_value += 4; -+ } -+ } -+ return length + adjust_value; -+ -+ default: -+ return length; -+ } -+} -+ -+/* Storage Layout. */ -+ -+/* This function will be called just before expansion into rtl. */ -+static void -+nds32_expand_to_rtl_hook (void) -+{ -+ /* We need to set strictly aligned situation. -+ After that, the memory address checking in nds32_legitimate_address_p() -+ will take alignment offset into consideration so that it will not create -+ unaligned [base + offset] access during the rtl optimization. */ -+ cfun->machine->strict_aligned_p = 1; -+} -+ -+ -+/* Register Usage. */ -+ -+static void -+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; -+ regno <= NDS32_LAST_FPR_REGNUM; regno++) -+ { -+ fixed_regs[regno] = 0; -+ if (regno < NDS32_FIRST_FPR_REGNUM + NDS32_MAX_FPR_REGS_FOR_ARGS) -+ call_used_regs[regno] = 1; -+ else if (regno >= NDS32_FIRST_FPR_REGNUM + 22 -+ && regno < NDS32_FIRST_FPR_REGNUM + 48) -+ call_used_regs[regno] = 1; -+ else -+ call_used_regs[regno] = 0; -+ } -+ } -+ else if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) -+ { -+ for (regno = NDS32_FIRST_FPR_REGNUM; -+ regno <= NDS32_LAST_FPR_REGNUM; -+ regno++) -+ fixed_regs[regno] = 0; -+ } -+} -+ - - /* Register Classes. */ - -+static reg_class_t -+nds32_preferred_rename_class (reg_class_t rclass) -+{ -+ return nds32_preferred_rename_class_impl (rclass); -+} -+ - static unsigned char - nds32_class_max_nregs (reg_class_t rclass ATTRIBUTE_UNUSED, -- machine_mode mode) -+ enum machine_mode mode) - { - /* Return the maximum number of consecutive registers -- needed to represent "mode" in a register of "rclass". */ -+ needed to represent MODE in a register of RCLASS. */ - return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD); - } - -@@ -1200,9 +1953,24 @@ static int - nds32_register_priority (int hard_regno) - { - /* Encourage to use r0-r7 for LRA when optimize for size. */ -- if (optimize_size && hard_regno < 8) -- return 4; -- return 3; -+ if (optimize_size) -+ { -+ if (hard_regno < 8) -+ return 4; -+ else if (hard_regno < 16) -+ return 3; -+ else if (hard_regno < 28) -+ return 2; -+ else -+ return 1; -+ } -+ else -+ { -+ if (hard_regno > 27) -+ return 1; -+ else -+ return 4; -+ } - } - - -@@ -1222,8 +1990,8 @@ nds32_register_priority (int hard_regno) - 2. return address - 3. callee-saved registers - 4. (we will calculte in nds32_compute_stack_frame() -- and save it at -- cfun->machine->callee_saved_area_padding_bytes) -+ and save it at -+ cfun->machine->callee_saved_area_padding_bytes) - - [Block B] - 1. local variables -@@ -1241,29 +2009,29 @@ nds32_register_priority (int hard_regno) - By applying the basic frame/stack/argument pointers concept, - the layout of a stack frame shoule be like this: - -- | | -+ | | - old stack pointer -> ---- -- | | \ -- | | saved arguments for -- | | vararg functions -- | | / -+ | | \ -+ | | saved arguments for -+ | | vararg functions -+ | | / - hard frame pointer -> -- - & argument pointer | | \ -- | | previous hardware frame pointer -- | | return address -- | | callee-saved registers -- | | / -- frame pointer -> -- -- | | \ -- | | local variables -- | | and incoming arguments -- | | / -- -- -- | | \ -- | | outgoing -- | | arguments -- | | / -- stack pointer -> ---- -+ | | previous hardware frame pointer -+ | | return address -+ | | callee-saved registers -+ | | / -+ frame pointer -> -- -+ | | \ -+ | | local variables -+ | | and incoming arguments -+ | | / -+ -- -+ | | \ -+ | | outgoing -+ | | arguments -+ | | / -+ stack pointer -> ---- - - $SFP and $AP are used to represent frame pointer and arguments pointer, - which will be both eliminated as hard frame pointer. */ -@@ -1291,7 +2059,7 @@ nds32_can_eliminate (const int from_reg, const int to_reg) - /* -- Passing Arguments in Registers. */ - - static rtx --nds32_function_arg (cumulative_args_t ca, machine_mode mode, -+nds32_function_arg (cumulative_args_t ca, enum machine_mode mode, - const_tree type, bool named) - { - unsigned int regno; -@@ -1306,7 +2074,7 @@ nds32_function_arg (cumulative_args_t ca, machine_mode mode, - if (!named) - { - /* If we are under hard float abi, we have arguments passed on the -- stack and all situation can be handled by GCC itself. */ -+ stack and all situation can be handled by GCC itself. */ - if (TARGET_HARD_FLOAT) - return NULL_RTX; - -@@ -1320,7 +2088,7 @@ nds32_function_arg (cumulative_args_t ca, machine_mode mode, - } - - /* No register available, return NULL_RTX. -- The compiler will use stack to pass argument instead. */ -+ The compiler will use stack to pass argument instead. */ - return NULL_RTX; - } - -@@ -1329,14 +2097,34 @@ nds32_function_arg (cumulative_args_t ca, machine_mode mode, - are different. */ - if (TARGET_HARD_FLOAT) - { -- /* Currently we have not implemented hard float yet. */ -- gcc_unreachable (); -+ /* For TARGET_HARD_FLOAT calling convention, we use GPR and FPR -+ to pass argument. We have to further check TYPE and MODE so -+ that we can determine which kind of register we shall use. */ -+ -+ /* Note that we need to pass argument entirely in registers under -+ hard float abi. */ -+ if (GET_MODE_CLASS (mode) == MODE_FLOAT -+ && NDS32_ARG_ENTIRE_IN_FPR_REG_P (cum->fpr_offset, mode, type)) -+ { -+ /* Pick up the next available FPR register number. */ -+ regno -+ = NDS32_AVAILABLE_REGNUM_FOR_FPR_ARG (cum->fpr_offset, mode, type); -+ return gen_rtx_REG (mode, regno); -+ } -+ else if (GET_MODE_CLASS (mode) != MODE_FLOAT -+ && NDS32_ARG_ENTIRE_IN_GPR_REG_P (cum->gpr_offset, mode, type)) -+ { -+ /* Pick up the next available GPR register number. */ -+ regno -+ = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type); -+ return gen_rtx_REG (mode, regno); -+ } - } - else - { - /* For !TARGET_HARD_FLOAT calling convention, we always use GPR to pass -- argument. Since we allow to pass argument partially in registers, -- we can just return it if there are still registers available. */ -+ argument. Since we allow to pass argument partially in registers, -+ we can just return it if there are still registers available. */ - if (NDS32_ARG_PARTIAL_IN_GPR_REG_P (cum->gpr_offset, mode, type)) - { - /* Pick up the next available register number. */ -@@ -1353,7 +2141,7 @@ nds32_function_arg (cumulative_args_t ca, machine_mode mode, - } - - static bool --nds32_must_pass_in_stack (machine_mode mode, const_tree type) -+nds32_must_pass_in_stack (enum machine_mode mode, const_tree type) - { - /* Return true if a type must be passed in memory. - If it is NOT using hard float abi, small aggregates can be -@@ -1366,7 +2154,7 @@ nds32_must_pass_in_stack (machine_mode mode, const_tree type) - } - - static int --nds32_arg_partial_bytes (cumulative_args_t ca, machine_mode mode, -+nds32_arg_partial_bytes (cumulative_args_t ca, enum machine_mode mode, - tree type, bool named ATTRIBUTE_UNUSED) - { - /* Returns the number of bytes at the beginning of an argument that -@@ -1400,7 +2188,7 @@ nds32_arg_partial_bytes (cumulative_args_t ca, machine_mode mode, - remaining_reg_count - = NDS32_MAX_GPR_REGS_FOR_ARGS - - (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type) -- - NDS32_GPR_ARG_FIRST_REGNUM); -+ - NDS32_GPR_ARG_FIRST_REGNUM); - - /* Note that we have to return the nubmer of bytes, not registers count. */ - if (needed_reg_count > remaining_reg_count) -@@ -1410,26 +2198,23 @@ nds32_arg_partial_bytes (cumulative_args_t ca, machine_mode mode, - } - - static void --nds32_function_arg_advance (cumulative_args_t ca, machine_mode mode, -+nds32_function_arg_advance (cumulative_args_t ca, enum machine_mode mode, - const_tree type, bool named) - { -- machine_mode sub_mode; - CUMULATIVE_ARGS *cum = get_cumulative_args (ca); - - if (named) - { - /* We need to further check TYPE and MODE so that we can determine -- which kind of register we shall advance. */ -- if (type && TREE_CODE (type) == COMPLEX_TYPE) -- sub_mode = TYPE_MODE (TREE_TYPE (type)); -- else -- sub_mode = mode; -+ which kind of register we shall advance. */ - - /* Under hard float abi, we may advance FPR registers. */ -- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (sub_mode) == MODE_FLOAT) -+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) - { -- /* Currently we have not implemented hard float yet. */ -- gcc_unreachable (); -+ cum->fpr_offset -+ = NDS32_AVAILABLE_REGNUM_FOR_FPR_ARG (cum->fpr_offset, mode, type) -+ - NDS32_FPR_ARG_FIRST_REGNUM -+ + NDS32_NEED_N_REGS_FOR_ARG (mode, type); - } - else - { -@@ -1442,9 +2227,9 @@ nds32_function_arg_advance (cumulative_args_t ca, machine_mode mode, - else - { - /* If this nameless argument is NOT under TARGET_HARD_FLOAT, -- we can advance next register as well so that caller is -- able to pass arguments in registers and callee must be -- in charge of pushing all of them into stack. */ -+ we can advance next register as well so that caller is -+ able to pass arguments in registers and callee must be -+ in charge of pushing all of them into stack. */ - if (!TARGET_HARD_FLOAT) - { - cum->gpr_offset -@@ -1456,13 +2241,23 @@ nds32_function_arg_advance (cumulative_args_t ca, machine_mode mode, - } - - static unsigned int --nds32_function_arg_boundary (machine_mode mode, const_tree type) -+nds32_function_arg_boundary (enum machine_mode mode, const_tree type) - { - return (nds32_needs_double_word_align (mode, type) - ? NDS32_DOUBLE_WORD_ALIGNMENT - : PARM_BOUNDARY); - } - -+bool -+nds32_vector_mode_supported_p (enum machine_mode mode) -+{ -+ if (mode == V4QImode -+ || mode == V2HImode) -+ return NDS32_EXT_DSP_P (); -+ -+ return false; -+} -+ - /* -- How Scalar Function Values Are Returned. */ - - static rtx -@@ -1470,28 +2265,68 @@ nds32_function_value (const_tree ret_type, - const_tree fn_decl_or_type ATTRIBUTE_UNUSED, - bool outgoing ATTRIBUTE_UNUSED) - { -- machine_mode mode; -+ enum machine_mode mode; - int unsignedp; - - mode = TYPE_MODE (ret_type); - unsignedp = TYPE_UNSIGNED (ret_type); - -- mode = promote_mode (ret_type, mode, &unsignedp); -+ if (INTEGRAL_TYPE_P (ret_type)) -+ mode = promote_mode (ret_type, mode, &unsignedp); - -- return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM); -+ if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode)) -+ return gen_rtx_REG (mode, NDS32_FPR_RET_FIRST_REGNUM); -+ else -+ return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM); - } - - static rtx --nds32_libcall_value (machine_mode mode, -+nds32_libcall_value (enum machine_mode mode, - const_rtx fun ATTRIBUTE_UNUSED) - { -+ if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode)) -+ return gen_rtx_REG (mode, NDS32_FPR_RET_FIRST_REGNUM); -+ - return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM); - } - - static bool - nds32_function_value_regno_p (const unsigned int regno) - { -- return (regno == NDS32_GPR_RET_FIRST_REGNUM); -+ if (regno == NDS32_GPR_RET_FIRST_REGNUM -+ || (TARGET_HARD_FLOAT -+ && regno == NDS32_FPR_RET_FIRST_REGNUM)) -+ return true; -+ -+ return false; -+} -+ -+/* -- How Large Values Are Returned. */ -+ -+static bool -+nds32_return_in_memory (const_tree type, -+ const_tree fntype ATTRIBUTE_UNUSED) -+{ -+ /* Note that int_size_in_bytes can return -1 if the size can vary -+ or is larger than an integer. */ -+ HOST_WIDE_INT size = int_size_in_bytes (type); -+ -+ /* For COMPLEX_TYPE, if the total size cannot be hold within two registers, -+ the return value is supposed to be in memory. We need to be aware of -+ that the size may be -1. */ -+ if (TREE_CODE (type) == COMPLEX_TYPE) -+ if (size < 0 || size > 2 * UNITS_PER_WORD) -+ return true; -+ -+ /* If it is BLKmode and the total size cannot be hold within two registers, -+ the return value is supposed to be in memory. We need to be aware of -+ that the size may be -1. */ -+ if (TYPE_MODE (type) == BLKmode) -+ if (size < 0 || size > 2 * UNITS_PER_WORD) -+ return true; -+ -+ /* For other cases, having result in memory is unnecessary. */ -+ return false; - } - - /* -- Function Entry and Exit. */ -@@ -1522,7 +2357,7 @@ nds32_asm_function_prologue (FILE *file, - /* Use df_regs_ever_live_p() to detect if the register - is ever used in the current function. */ - fprintf (file, "\t! registers ever_live: "); -- for (r = 0; r < 32; r++) -+ for (r = 0; r < 65; r++) - { - if (df_regs_ever_live_p (r)) - fprintf (file, "%s, ", reg_names[r]); -@@ -1554,6 +2389,10 @@ nds32_asm_function_prologue (FILE *file, - attrs = TREE_CHAIN (attrs); - } - fputc ('\n', file); -+ -+ /* If there is any critical isr in this file, disable linker ifc. */ -+ if (nds32_isr_function_critical_p (current_function_decl)) -+ fprintf (file, "\t.no_relax ifc\n"); - } - - /* After rtl prologue has been expanded, this function is used. */ -@@ -1561,56 +2400,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"); - } - -@@ -1638,41 +2433,104 @@ 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))) - { -- fprintf (file, "\taddi\t$r%d, $r%d, %ld\n", -+ fprintf (file, "\taddi\t$r%d, $r%d, " HOST_WIDE_INT_PRINT_DEC "\n", - this_regno, this_regno, delta); - } - else if (satisfies_constraint_Is20 (GEN_INT (delta))) - { -- fprintf (file, "\tmovi\t$ta, %ld\n", delta); -+ fprintf (file, "\tmovi\t$ta, " HOST_WIDE_INT_PRINT_DEC "\n", delta); - fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno); - } - else - { -- fprintf (file, "\tsethi\t$ta, hi20(%ld)\n", delta); -- fprintf (file, "\tori\t$ta, $ta, lo12(%ld)\n", delta); -+ fprintf (file, -+ "\tsethi\t$ta, hi20(" HOST_WIDE_INT_PRINT_DEC ")\n", -+ delta); -+ fprintf (file, -+ "\tori\t$ta, $ta, lo12(" HOST_WIDE_INT_PRINT_DEC ")\n", -+ delta); - fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno); - } - } - -- 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 (); - } - - /* -- Permitting tail calls. */ - -+/* Return true if it is ok to do sibling call optimization. */ -+static bool -+nds32_function_ok_for_sibcall (tree decl, -+ tree exp ATTRIBUTE_UNUSED) -+{ -+ /* The DECL is NULL if it is an indirect call. */ -+ -+ /* 1. Do not apply sibling call if -mv3push is enabled, -+ because pop25 instruction also represents return behavior. -+ 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. -+ 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. -+ 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 -+ && !flag_pic); -+} -+ - /* Determine whether we need to enable warning for function return check. */ - static bool - nds32_warn_func_return (tree decl) - { --/* Naked functions are implemented entirely in assembly, including the -- return sequence, so suppress warnings about this. */ -+ /* Naked functions are implemented entirely in assembly, including the -+ return sequence, so suppress warnings about this. */ - return !nds32_naked_function_p (decl); - } - -@@ -1681,7 +2539,7 @@ nds32_warn_func_return (tree decl) - - static void - nds32_setup_incoming_varargs (cumulative_args_t ca, -- machine_mode mode, -+ enum machine_mode mode, - tree type, - int *pretend_args_size, - int second_time ATTRIBUTE_UNUSED) -@@ -1795,7 +2653,7 @@ nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) - sorry ("a nested function is not supported for reduced registers"); - - /* STEP 1: Copy trampoline code template into stack, -- fill up essential data into stack. */ -+ fill up essential data into stack. */ - - /* Extract nested function address rtx. */ - fnaddr = XEXP (DECL_RTL (fndecl), 0); -@@ -1831,8 +2689,8 @@ nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) - && (tramp_align_in_bytes % nds32_cache_block_size) == 0) - { - /* Under this condition, the starting address of trampoline -- must be aligned to the starting address of each cache block -- and we do not have to worry about cross-boundary issue. */ -+ must be aligned to the starting address of each cache block -+ and we do not have to worry about cross-boundary issue. */ - for (i = 0; - i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1) - / nds32_cache_block_size; -@@ -1847,10 +2705,10 @@ nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) - else if (TRAMPOLINE_SIZE > nds32_cache_block_size) - { - /* The starting address of trampoline code -- may not be aligned to the cache block, -- so the trampoline code may be across two cache block. -- We need to sync the last element, which is 4-byte size, -- of trampoline template. */ -+ may not be aligned to the cache block, -+ so the trampoline code may be across two cache block. -+ We need to sync the last element, which is 4-byte size, -+ of trampoline template. */ - for (i = 0; - i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1) - / nds32_cache_block_size; -@@ -1871,16 +2729,16 @@ nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) - else - { - /* This is the simplest case. -- Because TRAMPOLINE_SIZE is less than or -- equal to nds32_cache_block_size, -- we can just sync start address and -- the last element of trampoline code. */ -+ Because TRAMPOLINE_SIZE is less than or -+ equal to nds32_cache_block_size, -+ we can just sync start address and -+ the last element of trampoline code. */ - - /* Sync starting address of tampoline code. */ - emit_move_insn (tmp_reg, sync_cache_addr); - emit_insn (isync_insn); - /* Sync the last element, which is 4-byte size, -- of trampoline template. */ -+ of trampoline template. */ - emit_move_insn (tmp_reg, - plus_constant (Pmode, sync_cache_addr, - TRAMPOLINE_SIZE - 4)); -@@ -1896,11 +2754,52 @@ nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) - /* Addressing Modes. */ - - static bool --nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) -+nds32_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) - { -+ if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) -+ { -+ /* When using floating-point instructions, -+ we don't allow 'addr' to be [symbol_ref], [CONST] pattern. */ -+ if ((mode == DFmode || mode == SFmode) -+ && (GET_CODE (x) == SYMBOL_REF -+ || GET_CODE(x) == CONST)) -+ return false; -+ -+ /* Allow [post_modify] addressing mode, when using FPU instructions. */ -+ if (GET_CODE (x) == POST_MODIFY -+ && mode == DFmode) -+ { -+ if (GET_CODE (XEXP (x, 0)) == REG -+ && GET_CODE (XEXP (x, 1)) == PLUS) -+ { -+ rtx plus_op = XEXP (x, 1); -+ rtx op0 = XEXP (plus_op, 0); -+ rtx op1 = XEXP (plus_op, 1); -+ -+ if (nds32_address_register_rtx_p (op0, strict) -+ && CONST_INT_P (op1)) -+ { -+ if (satisfies_constraint_Is14 (op1)) -+ { -+ /* If it is not under strictly aligned situation, -+ we can return true without checking alignment. */ -+ if (!cfun->machine->strict_aligned_p) -+ return true; -+ /* Make sure address is word alignment. -+ Currently we do not have 64-bit load/store yet, -+ so we will use two 32-bit load/store instructions to do -+ memory access and they are single word alignment. */ -+ else if (NDS32_SINGLE_WORD_ALIGN_P (INTVAL (op1))) -+ return true; -+ } -+ } -+ } -+ } -+ } -+ - /* For (mem:DI addr) or (mem:DF addr) case, - we only allow 'addr' to be [reg], [symbol_ref], -- [const], or [reg + const_int] pattern. */ -+ [const], or [reg + const_int] pattern. */ - if (mode == DImode || mode == DFmode) - { - /* Allow [Reg + const_int] addressing mode. */ -@@ -1910,13 +2809,19 @@ nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) - && nds32_legitimate_index_p (mode, XEXP (x, 1), strict) - && CONST_INT_P (XEXP (x, 1))) - return true; -- - else if (nds32_address_register_rtx_p (XEXP (x, 1), strict) - && nds32_legitimate_index_p (mode, XEXP (x, 0), strict) - && CONST_INT_P (XEXP (x, 0))) - return true; - } - -+ /* Allow [post_inc] and [post_dec] addressing mode. */ -+ if (GET_CODE (x) == POST_INC || GET_CODE (x) == POST_DEC) -+ { -+ if (nds32_address_register_rtx_p (XEXP (x, 0), strict)) -+ return true; -+ } -+ - /* Now check [reg], [symbol_ref], and [const]. */ - if (GET_CODE (x) != REG - && GET_CODE (x) != SYMBOL_REF -@@ -1933,18 +2838,26 @@ 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. */ -+ during or after LRA/reload phase. */ - if (TARGET_CMODEL_LARGE - && (reload_completed - || reload_in_progress - || lra_in_progress)) - return false; - /* If -mcmodel=medium and the symbol references to rodata section, -- the 'symbol_ref' is not a valid address during or after -- LRA/reload phase. */ -+ 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)) -@@ -1954,7 +2867,7 @@ nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) - - case CONST: - /* (mem (const (...))) -- => [ + const_addr ], where const_addr = symbol_ref + const_int */ -+ => [ + const_addr ], where const_addr = symbol_ref + const_int */ - if (GET_CODE (XEXP (x, 0)) == PLUS) - { - rtx plus_op = XEXP (x, 0); -@@ -1965,17 +2878,21 @@ nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) - if (GET_CODE (op0) == SYMBOL_REF && CONST_INT_P (op1)) - { - /* Now we see the [ + const_addr ] pattern, but we need -- some further checking. */ -+ some further checking. */ -+ -+ if (flag_pic) -+ return false; -+ - /* If -mcmodel=large, the 'const_addr' is not a valid address -- during or after LRA/reload phase. */ -+ during or after LRA/reload phase. */ - if (TARGET_CMODEL_LARGE - && (reload_completed - || reload_in_progress - || lra_in_progress)) - return false; - /* If -mcmodel=medium and the symbol references to rodata section, -- the 'const_addr' is not a valid address during or after -- LRA/reload phase. */ -+ the 'const_addr' is not a valid address during or after -+ LRA/reload phase. */ - if (TARGET_CMODEL_MEDIUM - && NDS32_SYMBOL_REF_RODATA_P (op0) - && (reload_completed -@@ -1993,9 +2910,9 @@ nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) - - case POST_MODIFY: - /* (mem (post_modify (reg) (plus (reg) (reg)))) -- => [Ra], Rb */ -+ => [Ra], Rb */ - /* (mem (post_modify (reg) (plus (reg) (const_int)))) -- => [Ra], const_int */ -+ => [Ra], const_int */ - if (GET_CODE (XEXP (x, 0)) == REG - && GET_CODE (XEXP (x, 1)) == PLUS) - { -@@ -2018,7 +2935,7 @@ nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) - /* (mem (post_inc reg)) => [Ra], 1/2/4 */ - /* (mem (post_dec reg)) => [Ra], -1/-2/-4 */ - /* The 1/2/4 or -1/-2/-4 have been displayed in nds32.md. -- We only need to deal with register Ra. */ -+ We only need to deal with register Ra. */ - if (nds32_address_register_rtx_p (XEXP (x, 0), strict)) - return true; - else -@@ -2026,11 +2943,11 @@ nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict) - - case PLUS: - /* (mem (plus reg const_int)) -- => [Ra + imm] */ -+ => [Ra + imm] */ - /* (mem (plus reg reg)) -- => [Ra + Rb] */ -+ => [Ra + Rb] */ - /* (mem (plus (mult reg const_int) reg)) -- => [Ra + Rb << sv] */ -+ => [Ra + Rb << sv] */ - if (nds32_address_register_rtx_p (XEXP (x, 0), strict) - && nds32_legitimate_index_p (mode, XEXP (x, 1), strict)) - return true; -@@ -2042,39 +2959,292 @@ 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, -+ enum 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 (enum 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 enum machine_mode -+nds32_vectorize_preferred_simd_mode (enum machine_mode mode) -+{ -+ if (!NDS32_EXT_DSP_P ()) -+ return word_mode; -+ -+ switch (mode) -+ { -+ case QImode: -+ return V4QImode; -+ case HImode: -+ return V2HImode; -+ default: -+ return word_mode; -+ } -+} - -+static bool -+nds32_cannot_force_const_mem (enum 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; -+} -+ -+ -+/* Condition Code Status. */ -+ -+/* -- Representation of condition codes using registers. */ -+ -+static void -+nds32_canonicalize_comparison (int *code, -+ rtx *op0 ATTRIBUTE_UNUSED, -+ rtx *op1, -+ bool op0_preserve_value ATTRIBUTE_UNUSED) -+{ -+ /* When the instruction combination pass tries to combine a comparison insn -+ with its previous insns, it also transforms the operator in order to -+ minimize its constant field. For example, it tries to transform a -+ comparison insn from -+ (set (reg:SI 54) -+ (ltu:SI (reg:SI 52) -+ (const_int 10 [0xa]))) -+ to -+ (set (reg:SI 54) -+ (leu:SI (reg:SI 52) -+ (const_int 9 [0x9]))) -+ -+ However, the nds32 target only provides instructions supporting the LTU -+ operation directly, and the implementation of the pattern "cbranchsi4" -+ only expands the LTU form. In order to handle the non-LTU operations -+ generated from passes other than the RTL expansion pass, we have to -+ implement this hook to revert those changes. Since we only expand the LTU -+ operator in the RTL expansion pass, we might only need to handle the LEU -+ case, unless we find other optimization passes perform more aggressive -+ transformations. */ -+ -+ if (*code == LEU && CONST_INT_P (*op1)) -+ { -+ *op1 = gen_int_mode (INTVAL (*op1) + 1, SImode); -+ *code = LTU; -+ } - } - - - /* Describing Relative Costs of Operations. */ - - static int --nds32_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED, -+nds32_register_move_cost (enum machine_mode mode, - reg_class_t from, - reg_class_t to) - { -- if (from == HIGH_REGS || to == HIGH_REGS) -- return 6; -+ /* 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; -+ } -+ } - -- return 2; -+ if ((from == FP_REGS && to != FP_REGS) -+ || (from != FP_REGS && to == FP_REGS)) -+ return 3; -+ else if (from == HIGH_REGS || to == HIGH_REGS) -+ return optimize_size ? 6 : 2; -+ else -+ return 2; - } - - static int --nds32_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED, -+nds32_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, - reg_class_t rclass ATTRIBUTE_UNUSED, - bool in ATTRIBUTE_UNUSED) - { -- return 8; -+ /* Memory access is only need 1 cycle in our low-end processor, -+ however memory access is most 4-byte instruction, -+ so let it 8 for optimize_size, otherwise be 2. */ -+ if (nds32_memory_model_option == MEMORY_MODEL_FAST) -+ return optimize_size ? 8 : 4; -+ else -+ return 8; - } - - /* This target hook describes the relative costs of RTL expressions. -@@ -2094,7 +3264,7 @@ nds32_rtx_costs (rtx x, - - static int - nds32_address_cost (rtx address, -- machine_mode mode, -+ enum machine_mode mode, - addr_space_t as, - bool speed) - { -@@ -2102,6 +3272,55 @@ nds32_address_cost (rtx address, - } - - -+/* Adjusting the Instruction Scheduler. */ -+ -+static int -+nds32_sched_issue_rate (void) -+{ -+ switch (nds32_cpu_option) -+ { -+ case CPU_GRAYWOLF: -+ case CPU_PANTHER: -+ return 2; -+ -+ default: -+ return 1; -+ } -+} -+ -+static int -+nds32_sched_adjust_cost (rtx_insn *insn ATTRIBUTE_UNUSED, rtx link, rtx_insn *dep ATTRIBUTE_UNUSED, int cost) -+{ -+ if (REG_NOTE_KIND (link) == REG_DEP_ANTI -+ || REG_NOTE_KIND (link) == REG_DEP_OUTPUT) -+ { -+ if (nds32_sched_issue_rate () > 1) -+ return 1; -+ -+ return 0; -+ } -+ -+ return cost; -+} -+ -+static void -+nds32_set_sched_flags (spec_info_t spec_info ATTRIBUTE_UNUSED) -+{ -+ if (!flag_reorg_out_of_order -+ || nds32_sched_issue_rate () < 2) -+ return; -+ -+ unsigned int *flags = &(current_sched_info->flags); -+ -+ // Disallow the sheculder to find inc/mem pairs and break dependencies by -+ // duplication address computations. Otherwise, after doing so, the -+ // scheduler will treat that the two insns can be issued at the same cycle -+ // so that the later insn isn't marked as TImode. It will result in a wrong -+ // behavior for out-of-order reorganization. -+ *flags |= DONT_BREAK_DEPENDENCIES; -+} -+ -+ - /* Dividing the Output into Sections (Texts, Data, . . . ). */ - - /* If references to a symbol or a constant must be treated differently -@@ -2150,17 +3369,56 @@ 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"); -- fprintf (asm_out_file, "\t.abi_2\n"); -+ if (TARGET_HARD_FLOAT) -+ fprintf (asm_out_file, "\t.abi_2fp_plus\n"); -+ else -+ fprintf (asm_out_file, "\t.abi_2\n"); - - /* 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); -+ -+ /* 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"); -+ } -+ /* If user enables '-mifc', we should emit relaxation directive -+ to tell linker that this file is allowed to do ifc optimization. */ -+ if (TARGET_IFC) -+ { -+ fprintf (asm_out_file, "\t! This relaxation directive is required " -+ "to do ifc link time optimization\n"); -+ fprintf (asm_out_file, "\t.relax\tifc\n"); -+ } -+ /* If user enables '-mex9', we should emit relaxation directive -+ to tell linker that this file is allowed to do ex9 optimization. */ -+ if (TARGET_EX9) -+ { -+ fprintf (asm_out_file, "\t! This relaxation directive is required " -+ "to do ex9 link time optimization\n"); -+ fprintf (asm_out_file, "\t.relax\tex9\n"); -+ } - - fprintf (asm_out_file, "\t! ------------------------------------\n"); - -@@ -2171,6 +3429,53 @@ 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_PANTHER: -+ fprintf (asm_out_file, "\t! Pipeline model\t: %s\n", "Panther"); -+ 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) -@@ -2181,6 +3486,15 @@ nds32_asm_file_start (void) - fprintf (asm_out_file, "\t! Endian setting\t: %s\n", - ((TARGET_BIG_ENDIAN) ? "big-endian" - : "little-endian")); -+ fprintf (asm_out_file, "\t! Use SP floating-point instruction\t: %s\n", -+ ((TARGET_FPU_SINGLE) ? "Yes" -+ : "No")); -+ fprintf (asm_out_file, "\t! Use DP floating-point instruction\t: %s\n", -+ ((TARGET_FPU_DOUBLE) ? "Yes" -+ : "No")); -+ fprintf (asm_out_file, "\t! ABI version\t\t: %s\n", -+ ((TARGET_HARD_FLOAT) ? "ABI2FP+" -+ : "ABI2")); - - fprintf (asm_out_file, "\t! ------------------------------------\n"); - -@@ -2188,8 +3502,14 @@ nds32_asm_file_start (void) - ((TARGET_CMOV) ? "Yes" - : "No")); - fprintf (asm_out_file, "\t! Use performance extension\t: %s\n", -- ((TARGET_PERF_EXT) ? "Yes" -+ ((TARGET_EXT_PERF) ? "Yes" - : "No")); -+ fprintf (asm_out_file, "\t! Use performance extension 2\t: %s\n", -+ ((TARGET_EXT_PERF2) ? "Yes" -+ : "No")); -+ fprintf (asm_out_file, "\t! Use string extension\t\t: %s\n", -+ ((TARGET_EXT_STRING) ? "Yes" -+ : "No")); - - fprintf (asm_out_file, "\t! ------------------------------------\n"); - -@@ -2203,10 +3523,18 @@ nds32_asm_file_start (void) - ((TARGET_REDUCED_REGS) ? "Yes" - : "No")); - -+ fprintf (asm_out_file, "\t! Support unaligned access\t\t: %s\n", -+ (flag_unaligned_access ? "Yes" -+ : "No")); -+ - fprintf (asm_out_file, "\t! ------------------------------------\n"); - - if (optimize_size) - fprintf (asm_out_file, "\t! Optimization level\t: -Os\n"); -+ else if (optimize_fast) -+ fprintf (asm_out_file, "\t! Optimization level\t: -Ofast\n"); -+ else if (optimize_debug) -+ fprintf (asm_out_file, "\t! Optimization level\t: -Og\n"); - else - fprintf (asm_out_file, "\t! Optimization level\t: -O%d\n", optimize); - -@@ -2225,9 +3553,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 -@@ -2243,7 +3627,15 @@ nds32_asm_globalize_label (FILE *stream, const char *name) - static void - nds32_print_operand (FILE *stream, rtx x, int code) - { -- int op_value; -+ 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; -+ -+ if (CONST_INT_P (x)) -+ op_value = INTVAL (x); - - switch (code) - { -@@ -2251,29 +3643,82 @@ nds32_print_operand (FILE *stream, rtx x, int code) - /* Do nothing special. */ - break; - -- case 'V': -- /* 'x' is supposed to be CONST_INT, get the value. */ -+ case 'b': -+ /* Use exact_log2() to search the 0-bit position. */ - gcc_assert (CONST_INT_P (x)); -- op_value = INTVAL (x); -+ zero_position = exact_log2 (~UINTVAL (x) & GET_MODE_MASK (SImode)); -+ gcc_assert (zero_position != -1); -+ fprintf (stream, HOST_WIDE_INT_PRINT_DEC, zero_position); - -- /* According to the Andes architecture, -- the system/user register index range is 0 ~ 1023. -- In order to avoid conflict between user-specified-integer value -- and enum-specified-register value, -- the 'enum nds32_intrinsic_registers' value -- in nds32_intrinsic.h starts from 1024. */ -- if (op_value < 1024 && op_value >= 0) -- { -- /* If user gives integer value directly (0~1023), -- we just print out the value. */ -- fprintf (stream, "%d", op_value); -- } -- else if (op_value < 0 -- || op_value >= ((int) ARRAY_SIZE (nds32_intrinsic_register_names) -- + 1024)) -- { -- /* The enum index value for array size is out of range. */ -- error ("intrinsic register index is out of range"); -+ /* No need to handle following process, so return immediately. */ -+ return; -+ -+ case 'e': -+ gcc_assert (MEM_P (x) -+ && GET_CODE (XEXP (x, 0)) == PLUS -+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT); -+ fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (XEXP (XEXP (x, 0), 1))); -+ -+ /* 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)); -+ one_position = exact_log2 (UINTVAL (x) & GET_MODE_MASK (SImode)); -+ gcc_assert (one_position != -1); -+ fprintf (stream, HOST_WIDE_INT_PRINT_DEC, one_position); -+ -+ /* No need to handle following process, so return immediately. */ -+ return; -+ -+ case 'L': -+ /* X is supposed to be REG rtx. */ -+ gcc_assert (REG_P (x)); -+ /* Claim that we are going to pick LSB part of X. */ -+ pick_lsb_p = true; -+ break; -+ -+ case 'H': -+ /* X is supposed to be REG rtx. */ -+ gcc_assert (REG_P (x)); -+ /* Claim that we are going to pick MSB part of X. */ -+ pick_msb_p = true; -+ break; -+ -+ case 'V': -+ /* X is supposed to be CONST_INT, get the value. */ -+ gcc_assert (CONST_INT_P (x)); -+ -+ /* According to the Andes architecture, -+ the system/user register index range is 0 ~ 1023. -+ In order to avoid conflict between user-specified-integer value -+ and enum-specified-register value, -+ the 'enum nds32_intrinsic_registers' value -+ in nds32_intrinsic.h starts from 1024. */ -+ if (op_value < 1024 && op_value >= 0) -+ { -+ /* If user gives integer value directly (0~1023), -+ we just print out the value. */ -+ fprintf (stream, HOST_WIDE_INT_PRINT_DEC, op_value); -+ } -+ else if (op_value < 0 -+ || op_value >= ((int) ARRAY_SIZE (nds32_intrinsic_register_names) -+ + 1024)) -+ { -+ /* The enum index value for array size is out of range. */ -+ error ("intrinsic register index is out of range"); - } - else - { -@@ -2286,6 +3731,45 @@ nds32_print_operand (FILE *stream, rtx x, int code) - /* No need to handle following process, so return immediately. */ - return; - -+ case 'R': /* cctl valck */ -+ /* Note the cctl divide to 5 group and share the same name table. */ -+ if (op_value < 0 || op_value > 4) -+ error ("CCTL intrinsic function subtype out of range!"); -+ fprintf (stream, "%s", nds32_cctl_names[op_value]); -+ return; -+ -+ case 'T': /* cctl idxwbinv */ -+ /* Note the cctl divide to 5 group and share the same name table. */ -+ if (op_value < 0 || op_value > 4) -+ error ("CCTL intrinsic function subtype out of range!"); -+ fprintf (stream, "%s", nds32_cctl_names[op_value + 4]); -+ return; -+ -+ case 'U': /* cctl vawbinv */ -+ /* Note the cctl divide to 5 group and share the same name table. */ -+ if (op_value < 0 || op_value > 4) -+ error ("CCTL intrinsic function subtype out of range!"); -+ fprintf (stream, "%s", nds32_cctl_names[op_value + 8]); -+ return; -+ -+ case 'X': /* cctl idxread */ -+ /* Note the cctl divide to 5 group and share the same name table. */ -+ if (op_value < 0 || op_value > 4) -+ error ("CCTL intrinsic function subtype out of range!"); -+ fprintf (stream, "%s", nds32_cctl_names[op_value + 12]); -+ return; -+ -+ case 'W': /* cctl idxwitre */ -+ /* Note the cctl divide to 5 group and share the same name table. */ -+ if (op_value < 0 || op_value > 4) -+ error ("CCTL intrinsic function subtype out of range!"); -+ fprintf (stream, "%s", nds32_cctl_names[op_value + 16]); -+ return; -+ -+ case 'Z': /* dpref */ -+ fprintf (stream, "%s", nds32_dpref_names[op_value]); -+ return; -+ - default : - /* Unknown flag. */ - output_operand_lossage ("invalid operand output code"); -@@ -2295,35 +3779,113 @@ 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: -+ /* Print a Double-precision register name. */ -+ if ((GET_MODE (x) == DImode || GET_MODE (x) == DFmode) -+ && NDS32_IS_FPR_REGNUM (REGNO (x))) -+ { -+ regno = REGNO (x); -+ if (!NDS32_FPR_REGNO_OK_FOR_DOUBLE (regno)) -+ { -+ output_operand_lossage ("invalid operand for code '%c'", code); -+ break; -+ } -+ fprintf (stream, "$fd%d", (regno - NDS32_FIRST_FPR_REGNUM) >> 1); -+ break; -+ } -+ -+ /* Print LSB or MSB part of register pair if the -+ constraint modifier 'L' or 'H' is specified. */ -+ if ((GET_MODE (x) == DImode || GET_MODE (x) == DFmode) -+ && NDS32_IS_GPR_REGNUM (REGNO (x))) -+ { -+ if ((pick_lsb_p && WORDS_BIG_ENDIAN) -+ || (pick_msb_p && !WORDS_BIG_ENDIAN)) -+ { -+ /* If we would like to print out LSB register under big-endian, -+ or print out MSB register under little-endian, we need to -+ increase register number. */ -+ regno = REGNO (x); -+ regno++; -+ fputs (reg_names[regno], stream); -+ break; -+ } -+ } -+ - /* Forbid using static chain register ($r16) -- on reduced-set registers configuration. */ -+ on reduced-set registers configuration. */ - if (TARGET_REDUCED_REGS - && REGNO (x) == STATIC_CHAIN_REGNUM) - sorry ("a nested function is not supported for reduced registers"); - - /* Normal cases, print out register name. */ -- fputs (reg_names[REGNO (x)], stream); -+ regno = REGNO (x); -+ fputs (reg_names[regno], stream); - break; - - case MEM: - output_address (GET_MODE (x), XEXP (x, 0)); - break; - -+ case HIGH: -+ if (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE) -+ { -+ const REAL_VALUE_TYPE *rv; -+ long val; -+ gcc_assert (GET_MODE (x) == SFmode); -+ -+ rv = CONST_DOUBLE_REAL_VALUE (XEXP (x, 0)); -+ REAL_VALUE_TO_TARGET_SINGLE (*rv, val); -+ -+ fprintf (stream, "hi20(0x%lx)", val); -+ } -+ else -+ gcc_unreachable (); -+ break; -+ -+ case CONST_DOUBLE: -+ const REAL_VALUE_TYPE *rv; -+ long val; -+ gcc_assert (GET_MODE (x) == SFmode); -+ -+ rv = CONST_DOUBLE_REAL_VALUE (x); -+ REAL_VALUE_TO_TARGET_SINGLE (*rv, val); -+ -+ fprintf (stream, "0x%lx", val); -+ break; -+ - case CODE_LABEL: - case CONST_INT: - case CONST: - 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, -- so we use gcc_unreachable() to stop it. */ -+ We want to see what CODE could appear, -+ so we use gcc_unreachable() to stop it. */ - debug_rtx (x); - gcc_unreachable (); - break; -@@ -2331,7 +3893,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; - -@@ -2346,15 +3910,25 @@ 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. */ -+ on reduced-set registers configuration. */ - if (TARGET_REDUCED_REGS - && REGNO (x) == STATIC_CHAIN_REGNUM) - sorry ("a nested function is not supported for reduced registers"); - - /* [Ra] */ -- fprintf (stream, "[%s]", reg_names[REGNO (x)]); -+ fprintf (stream, "[%s + 0]", reg_names[REGNO (x)]); - break; - - case PLUS: -@@ -2362,13 +3936,13 @@ nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) - op1 = XEXP (x, 1); - - /* Checking op0, forbid using static chain register ($r16) -- on reduced-set registers configuration. */ -+ on reduced-set registers configuration. */ - if (TARGET_REDUCED_REGS - && REG_P (op0) - && REGNO (op0) == STATIC_CHAIN_REGNUM) - sorry ("a nested function is not supported for reduced registers"); - /* Checking op1, forbid using static chain register ($r16) -- on reduced-set registers configuration. */ -+ on reduced-set registers configuration. */ - if (TARGET_REDUCED_REGS - && REG_P (op1) - && REGNO (op1) == STATIC_CHAIN_REGNUM) -@@ -2377,8 +3951,8 @@ nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) - if (REG_P (op0) && CONST_INT_P (op1)) - { - /* [Ra + imm] */ -- fprintf (stream, "[%s + (%d)]", -- reg_names[REGNO (op0)], (int)INTVAL (op1)); -+ fprintf (stream, "[%s + (" HOST_WIDE_INT_PRINT_DEC ")]", -+ reg_names[REGNO (op0)], INTVAL (op1)); - } - else if (REG_P (op0) && REG_P (op1)) - { -@@ -2391,8 +3965,8 @@ nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) - /* [Ra + Rb << sv] - From observation, the pattern looks like: - (plus:SI (mult:SI (reg:SI 58) -- (const_int 4 [0x4])) -- (reg/f:SI 57)) */ -+ (const_int 4 [0x4])) -+ (reg/f:SI 57)) */ - int sv; - - /* We need to set sv to output shift value. */ -@@ -2402,6 +3976,8 @@ nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) - sv = 1; - else if (INTVAL (XEXP (op0, 1)) == 4) - sv = 2; -+ else if (INTVAL (XEXP (op0, 1)) == 8) -+ sv = 3; - else - gcc_unreachable (); - -@@ -2410,6 +3986,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. */ -@@ -2421,20 +4011,20 @@ nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) - - case POST_MODIFY: - /* (post_modify (regA) (plus (regA) (regB))) -- (post_modify (regA) (plus (regA) (const_int))) -- We would like to extract -- regA and regB (or const_int) from plus rtx. */ -+ (post_modify (regA) (plus (regA) (const_int))) -+ We would like to extract -+ regA and regB (or const_int) from plus rtx. */ - op0 = XEXP (XEXP (x, 1), 0); - op1 = XEXP (XEXP (x, 1), 1); - - /* Checking op0, forbid using static chain register ($r16) -- on reduced-set registers configuration. */ -+ on reduced-set registers configuration. */ - if (TARGET_REDUCED_REGS - && REG_P (op0) - && REGNO (op0) == STATIC_CHAIN_REGNUM) - sorry ("a nested function is not supported for reduced registers"); - /* Checking op1, forbid using static chain register ($r16) -- on reduced-set registers configuration. */ -+ on reduced-set registers configuration. */ - if (TARGET_REDUCED_REGS - && REG_P (op1) - && REGNO (op1) == STATIC_CHAIN_REGNUM) -@@ -2449,8 +4039,8 @@ nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) - else if (REG_P (op0) && CONST_INT_P (op1)) - { - /* [Ra], imm */ -- fprintf (stream, "[%s], %d", -- reg_names[REGNO (op0)], (int)INTVAL (op1)); -+ fprintf (stream, "[%s], " HOST_WIDE_INT_PRINT_DEC, -+ reg_names[REGNO (op0)], INTVAL (op1)); - } - else - { -@@ -2466,7 +4056,7 @@ nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) - op0 = XEXP (x, 0); - - /* Checking op0, forbid using static chain register ($r16) -- on reduced-set registers configuration. */ -+ on reduced-set registers configuration. */ - if (TARGET_REDUCED_REGS - && REG_P (op0) - && REGNO (op0) == STATIC_CHAIN_REGNUM) -@@ -2490,14 +4080,92 @@ nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x) - - default : - /* Generally, output_addr_const () is able to handle most cases. -- We want to see what CODE could appear, -- so we use gcc_unreachable() to stop it. */ -+ We want to see what CODE could appear, -+ so we use gcc_unreachable() to stop it. */ - debug_rtx (x); - gcc_unreachable (); - break; - } - } - -+/* -- Assembler Commands for Exception Regions. */ -+ -+static rtx -+nds32_dwarf_register_span (rtx reg) -+{ -+ rtx dwarf_high, dwarf_low; -+ rtx dwarf_single; -+ enum machine_mode mode; -+ int regno; -+ -+ mode = GET_MODE (reg); -+ regno = REGNO (reg); -+ -+ /* We need to adjust dwarf register information for floating-point registers -+ rather than using default register number mapping. */ -+ if (regno >= NDS32_FIRST_FPR_REGNUM -+ && regno <= NDS32_LAST_FPR_REGNUM) -+ { -+ if (mode == DFmode || mode == SCmode) -+ { -+ /* By default, GCC maps increasing register numbers to increasing -+ memory locations, but paired FPRs in NDS32 target are always -+ big-endian, i.e.: -+ -+ fd0 : fs0 fs1 -+ (MSB) (LSB) -+ -+ We must return parallel rtx to represent such layout. */ -+ dwarf_high = gen_rtx_REG (word_mode, regno); -+ dwarf_low = gen_rtx_REG (word_mode, regno + 1); -+ return gen_rtx_PARALLEL (VOIDmode, -+ gen_rtvec (2, dwarf_low, dwarf_high)); -+ } -+ else if (mode == DCmode) -+ { -+ rtx dwarf_high_re = gen_rtx_REG (word_mode, regno); -+ rtx dwarf_low_re = gen_rtx_REG (word_mode, regno + 1); -+ rtx dwarf_high_im = gen_rtx_REG (word_mode, regno); -+ rtx dwarf_low_im = gen_rtx_REG (word_mode, regno + 1); -+ return gen_rtx_PARALLEL (VOIDmode, -+ gen_rtvec (4, dwarf_low_re, dwarf_high_re, -+ dwarf_high_im, dwarf_low_im)); -+ } -+ else if (mode == SFmode || mode == SImode) -+ { -+ /* Create new dwarf information with adjusted register number. */ -+ dwarf_single = gen_rtx_REG (word_mode, regno); -+ return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, dwarf_single)); -+ } -+ else -+ { -+ /* We should not be here. */ -+ gcc_unreachable (); -+ } -+ } -+ -+ return NULL_RTX; -+} -+ -+/* Map internal gcc register numbers to DWARF2 register numbers. */ -+ -+unsigned int -+nds32_dbx_register_number (unsigned int regno) -+{ -+ /* The nds32 port in GDB maintains a mapping between dwarf register -+ number and displayed register name. For backward compatibility to -+ previous toolchain, currently our gdb still has four registers -+ (d0.l, d0.h, d1.l, and d1.h) between GPR and FPR while compiler -+ does not count those four registers in its register number table. -+ So we have to add 4 on its register number and then create new -+ dwarf information. Hopefully we can discard such workaround -+ in the future. */ -+ if (NDS32_IS_FPR_REGNUM (regno)) -+ return regno + 4; -+ -+ return regno; -+} -+ - - /* Defining target-specific uses of __attribute__. */ - -@@ -2526,6 +4194,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. -@@ -2543,14 +4232,46 @@ nds32_insert_attributes (tree decl, tree *attributes) - nds32_check_isr_attrs_conflict (decl, func_attrs); - - /* Now we are starting to check valid id value -- for interrupt/exception/reset. -- Note that we ONLY check its validity here. -- To construct isr vector information, it is still performed -- by nds32_construct_isr_vectors_information(). */ -+ for interrupt/exception/reset. -+ Note that we ONLY check its validity here. -+ To construct isr vector information, it is still performed -+ by nds32_construct_isr_vectors_information(). */ - intr = lookup_attribute ("interrupt", func_attrs); - 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. */ -@@ -2576,8 +4297,8 @@ nds32_insert_attributes (tree decl, tree *attributes) - id = TREE_VALUE (id_list); - /* Issue error if it is not a valid integer value. */ - if (TREE_CODE (id) != INTEGER_CST -- || wi::ltu_p (id, lower_bound) -- || wi::gtu_p (id, upper_bound)) -+ || TREE_INT_CST_LOW (id) < lower_bound -+ || TREE_INT_CST_LOW (id) > upper_bound) - error ("invalid id value for interrupt/exception attribute"); - - /* Advance to next id. */ -@@ -2604,8 +4325,8 @@ nds32_insert_attributes (tree decl, tree *attributes) - - /* 3. Check valid integer value for reset. */ - if (TREE_CODE (id) != INTEGER_CST -- || wi::ltu_p (id, lower_bound) -- || wi::gtu_p (id, upper_bound)) -+ || TREE_INT_CST_LOW (id) < lower_bound -+ || TREE_INT_CST_LOW (id) > upper_bound) - error ("invalid id value for reset attribute"); - - /* 4. Check valid function for nmi/warm. */ -@@ -2667,17 +4388,40 @@ nds32_option_override (void) - { - /* Under V2 ISA, we need to strictly disable TARGET_V3PUSH. */ - target_flags &= ~MASK_V3PUSH; -+ /* Under V2 ISA, we need to strictly disable TARGET_IFC. */ -+ target_flags &= ~MASK_IFC; -+ /* Under V2 ISA, we need to strictly disable TARGET_EX9. */ -+ target_flags &= ~MASK_EX9; -+ /* If this is ARCH_V2J, we need to enable TARGET_REDUCED_REGS. */ -+ if (nds32_arch_option == ARCH_V2J) -+ target_flags |= MASK_REDUCED_REGS; - } - 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) - { - /* Under V3M ISA, we need to strictly enable TARGET_REDUCED_REGS. */ - target_flags |= MASK_REDUCED_REGS; -- /* Under V3M ISA, we need to strictly disable TARGET_PERF_EXT. */ -- target_flags &= ~MASK_PERF_EXT; -+ if (nds32_arch_option != ARCH_V3M_PLUS) -+ { -+ /* Under V3M ISA, we need to strictly disable TARGET_IFC. */ -+ target_flags &= ~MASK_IFC; -+ /* Under V3M ISA, we need to strictly disable TARGET_EX9. */ -+ target_flags &= ~MASK_EX9; -+ } -+ /* Under V3M ISA, we need to strictly disable TARGET_EXT_PERF. */ -+ target_flags &= ~MASK_EXT_PERF; -+ /* Under V3M ISA, we need to strictly disable TARGET_EXT_PERF2. */ -+ 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: -@@ -2688,48 +4432,568 @@ nds32_option_override (void) - int r; - - /* Prevent register allocator from -- choosing it as doing register allocation. */ -+ choosing it as doing register allocation. */ - for (r = 11; r <= 14; r++) - fixed_regs[r] = call_used_regs[r] = 1; - for (r = 16; r <= 27; r++) - 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. */ - target_flags &= ~MASK_V3PUSH; - } - -- /* Currently, we don't support PIC code generation yet. */ -- if (flag_pic) -- sorry ("not support -fpic"); -+ if (TARGET_HARD_FLOAT && !(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)) -+ { -+ if (nds32_arch_option == ARCH_V3S || nds32_arch_option == ARCH_V3F) -+ error ("Disable FPU ISA, " -+ "the ABI option must be enable '-mfloat-abi=soft'"); -+ else -+ error ("'-mabi=2fp+' option only support when FPU available, " -+ "must be enable '-mext-fpu-sp' or '-mext-fpu-dp'"); -+ } -+ -+ nds32_register_passes (); -+ -+ nds32_init_rtx_costs (); - } - - - /* Miscellaneous Parameters. */ - -+static rtx_insn * -+nds32_md_asm_adjust (vec &outputs ATTRIBUTE_UNUSED, -+ vec &inputs 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); -+ return NULL; -+} -+/* Insert end_label and check loop body whether is empty. */ -+static bool -+nds32_hwloop_insert_end_label (rtx loop_id, rtx end_label) -+{ -+ rtx_insn *insn = NULL; -+ basic_block bb; -+ rtx cfg_id; -+ rtx_insn *last_insn; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (NOTE_P (insn)) -+ continue; -+ -+ if (recog_memoized (insn) == CODE_FOR_hwloop_cfg -+ && INSN_P (insn)) -+ { -+ cfg_id = XVECEXP (XVECEXP (PATTERN (insn), 0, 5), 0, 0); -+ if (cfg_id == loop_id) -+ { -+ for (last_insn = PREV_INSN (insn); last_insn != BB_HEAD (bb); -+ last_insn = PREV_INSN (last_insn)) -+ { -+ if (NONDEBUG_INSN_P (last_insn)) -+ { -+ emit_label_before (end_label, last_insn); -+ if (TARGET_IFC) -+ { -+ /* The last_insn don't do ifcall. */ -+ emit_insn_before (gen_no_ifc_begin (), last_insn); -+ emit_insn_after (gen_no_ifc_end (), last_insn); -+ } -+ if (TARGET_EX9) -+ { -+ /* The last_insn don't do ex9. */ -+ emit_insn_before (gen_no_ex9_begin (), last_insn); -+ emit_insn_after (gen_no_ex9_end (), last_insn); -+ } -+ /* Record last instruction for identify in relax pass. */ -+ emit_insn_after (gen_hwloop_last_insn (), last_insn); -+ return true; -+ } -+ } -+ -+ if (NOTE_INSN_BASIC_BLOCK_P (last_insn)) -+ { -+ rtx_insn *nop = emit_insn_before (gen_unspec_nop (), -+ last_insn); -+ emit_label_before (end_label, nop); -+ if (TARGET_IFC) -+ { -+ /* The last_insn don't do ifcall. */ -+ emit_insn_before (gen_no_ifc_begin (), last_insn); -+ emit_insn_after (gen_no_ifc_end (), last_insn); -+ } -+ if (TARGET_EX9) -+ { -+ /* The last_insn don't do ex9. */ -+ emit_insn_before (gen_no_ex9_begin (), last_insn); -+ emit_insn_after (gen_no_ex9_end (), last_insn); -+ } -+ return true; -+ } -+ } -+ } -+ } -+ } -+ -+ if (insn != NULL) -+ delete_insn (insn); -+ return false; -+} -+ -+static void -+nds32_hwloop_remove (rtx loop_id) -+{ -+ rtx_insn *insn; -+ rtx le_id; -+ basic_block bb; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (NOTE_P (insn)) -+ continue; -+ -+ if (recog_memoized (insn) == CODE_FOR_init_lc -+ && INSN_P (insn)) -+ { -+ le_id = XVECEXP (XVECEXP (PATTERN (insn), 0, 1), 0, 0); -+ if (loop_id == le_id) -+ { -+ delete_insn (insn); -+ return; -+ } -+ } -+ } -+ } -+} -+ -+/* Insert isb instruction for hwloop. */ -+static void -+nds32_hwloop_insert_isb (rtx loop_id) -+{ -+ rtx_insn *insn; -+ rtx le_id; -+ basic_block bb; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (NOTE_P (insn)) -+ continue; -+ -+ if (recog_memoized (insn) == CODE_FOR_init_lc -+ && INSN_P (insn)) -+ { -+ le_id = XVECEXP (XVECEXP (PATTERN (insn), 0, 1), 0, 0); -+ if (loop_id == le_id) -+ { -+ emit_insn_after (gen_unspec_volatile_isb (), insn); -+ return; -+ } -+ } -+ } -+ } -+} -+/* Insert mtlei instruction for hwloop. */ -+static void -+nds32_hwloop_insert_init_end () -+{ -+ rtx_insn *insn; -+ basic_block bb; -+ rtx loop_id, end_label; -+ bool hwloop_p; -+ -+ FOR_EACH_BB_FN (bb, cfun) -+ { -+ FOR_BB_INSNS (bb, insn) -+ { -+ if (NOTE_P (insn)) -+ continue; -+ -+ if (recog_memoized (insn) == CODE_FOR_mtlbi_hint -+ && INSN_P (insn)) -+ { -+ end_label = gen_label_rtx (); -+ loop_id = XVECEXP (XVECEXP (PATTERN (insn), 0, 1), 0, 0); -+ hwloop_p = nds32_hwloop_insert_end_label (loop_id, end_label); -+ -+ if (!hwloop_p) -+ { -+ delete_insn (insn); -+ nds32_hwloop_remove (loop_id); -+ } -+ else -+ { -+ emit_insn_after (gen_mtlei (gen_rtx_LABEL_REF (Pmode, end_label)), insn); -+ nds32_hwloop_insert_isb (loop_id); -+ } -+ } -+ } -+ } -+} -+ -+/* Reorganize insns issued at the same cycle in out of order. */ -+static void -+nds32_reorg_out_of_order () -+{ -+ using namespace nds32; -+ -+ // The function is controoled by -mreorg-out-of-order and the issue rate. -+ if (!flag_reorg_out_of_order -+ || nds32_sched_issue_rate () < 2) -+ return; -+ -+ // We only move load insns up at this moment. -+ rtx_insn *insn; -+ -+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) -+ { -+ if (!insn_executable_p (insn) -+ || GET_MODE (insn) != TImode -+ || get_attr_type (insn) == TYPE_STORE_MULTIPLE -+ || get_attr_type (insn) == TYPE_LOAD_MULTIPLE -+ || get_attr_type (insn) == TYPE_LOAD -+ || get_attr_type (insn) == TYPE_FLOAD -+ || get_attr_type (insn) == TYPE_STORE -+ || get_attr_type (insn) == TYPE_FSTORE) -+ continue; -+ -+ rtx_insn *load_insn = insn; -+ -+ while ((load_insn = next_executable_insn_local (load_insn))) -+ { -+ if (GET_MODE (load_insn) == TImode) -+ { -+ load_insn = NULL; -+ break; -+ } -+ -+ if ((get_attr_type (load_insn) == TYPE_LOAD -+ || get_attr_type (load_insn) == TYPE_FLOAD) -+ && get_attr_length (load_insn) < 4) -+ break; -+ } -+ -+ if (load_insn == NULL_RTX) -+ continue; -+ -+ exchange_insns (insn, load_insn); -+ } -+} -+ -+/* Perform machine-dependent processing. */ -+static void -+nds32_machine_dependent_reorg (void) -+{ -+ /* We are freeing block_for_insn in the toplev to keep compatibility -+ with old MDEP_REORGS that are not CFG based. Recompute it -+ now. */ -+ compute_bb_for_insn (); -+ -+ nds32_reorg_out_of_order (); -+ -+ if (TARGET_HWLOOP) -+ nds32_hwloop_insert_init_end (); -+ -+ if (flag_var_tracking) -+ { -+ df_analyze (); -+ timevar_push (TV_VAR_TRACKING); -+ variable_tracking_main (); -+ timevar_pop (TV_VAR_TRACKING); -+ df_finish_pass (false); -+ } -+ -+ /* Use -minnermost-loop to enable, -+ need more testing to verify result. */ -+ if (TARGET_INNERMOST_LOOP) -+ nds32_insert_innermost_loop (); -+ -+ nds32_insert_isps (); -+} -+ - static void - nds32_init_builtins (void) - { - nds32_init_builtins_impl (); - } - -+static tree -+nds32_builtin_decl (unsigned code, bool initialize_p) -+{ -+ /* Implement in nds32-intrinsic.c. */ -+ return nds32_builtin_decl_impl (code, initialize_p); -+} -+ - static rtx - nds32_expand_builtin (tree exp, - rtx target, - rtx subtarget, -- machine_mode mode, -+ enum machine_mode mode, - int ignore) - { -+ /* Implement in nds32-intrinsic.c. */ - return nds32_expand_builtin_impl (exp, target, subtarget, mode, ignore); - } - -+static bool -+nds32_have_conditional_execution (void) -+{ -+ /* Lie to gcc that we have conditional execution for change optimization flow -+ in if-conversion, LRA and scheduling phase. -+ In our experiment result show that cand reduce about 2% code size with very -+ minor performance degradation in average. */ -+ return optimize_size; -+} -+ -+/* Implement TARGET_INIT_LIBFUNCS. */ -+static void -+nds32_init_libfuncs (void) -+{ -+ if (TARGET_LINUX_ABI) -+ init_sync_libfuncs (UNITS_PER_WORD); -+} -+ -+/* Implement TARGET_CAN_USE_DOLOOP_P. */ -+static bool -+nds32_can_use_doloop_p (const widest_int &, const widest_int &iterations_max, -+ unsigned int, bool entered_at_top) -+{ -+ /* Using hwloop must be entered from the top. */ -+ if (!entered_at_top) -+ return false; -+ -+ if (lookup_attribute ("no_ext_zol", DECL_ATTRIBUTES (current_function_decl))) -+ return false; -+ -+ /* Initial hardware loops too costly, so we must avoid to -+ generate a hardware loops when loop count less then 8. */ -+ if (!NDS32_HW_LOOP_P () -+ || iterations_max.ulow() < 8) -+ return false; -+ return true; -+} -+ -+/* NULL if INSN insn is valid within a low-overhead loop. -+ Otherwise return why doloop cannot be applied. */ -+static const char * -+nds32_invalid_within_doloop (const rtx_insn *insn) -+{ -+ if (CALL_P (insn)) -+ return "Function call in the loop."; -+ else if (INSN_CODE (insn) == CODE_FOR_pop25return -+ || INSN_CODE (insn) == CODE_FOR_return_internal) -+ return "Simple return in the loop."; -+ else if (INSN_CODE (insn) == CODE_FOR_unspec_no_hwloop) -+ return "no_hwloop hint in the loop"; -+ -+ return NULL; -+} - - /* ------------------------------------------------------------------------ */ - --/* PART 4: Implemet extern function definitions, -- the prototype is in nds32-protos.h. */ -+/* PART 5: Implemet extern function definitions, -+ the prototype is in nds32-protos.h. */ -+ -+/* Run-time Target Specification. */ -+ -+void -+nds32_cpu_cpp_builtins(struct cpp_reader *pfile) -+{ -+#define builtin_define(TXT) cpp_define (pfile, TXT) -+#define builtin_assert(TXT) cpp_assert (pfile, TXT) -+ 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 -+ builtin_define ("__NDS32_ABI_2__"); -+ -+ if (TARGET_ISA_V2) -+ builtin_define ("__NDS32_ISA_V2__"); -+ if (TARGET_ISA_V3) -+ builtin_define ("__NDS32_ISA_V3__"); -+ if (TARGET_ISA_V3M) -+ builtin_define ("__NDS32_ISA_V3M__"); -+ -+ if (TARGET_FPU_SINGLE) -+ builtin_define ("__NDS32_EXT_FPU_SP__"); -+ if (TARGET_FPU_DOUBLE) -+ builtin_define ("__NDS32_EXT_FPU_DP__"); -+ -+ if (TARGET_EXT_FPU_FMA) -+ builtin_define ("__NDS32_EXT_FPU_FMA__"); -+ if (NDS32_EXT_FPU_DOT_E) -+ builtin_define ("__NDS32_EXT_FPU_DOT_E__"); -+ if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) -+ { -+ switch (nds32_fp_regnum) -+ { -+ case 0: -+ case 4: -+ builtin_define ("__NDS32_EXT_FPU_CONFIG_0__"); -+ break; -+ case 1: -+ case 5: -+ builtin_define ("__NDS32_EXT_FPU_CONFIG_1__"); -+ break; -+ case 2: -+ case 6: -+ builtin_define ("__NDS32_EXT_FPU_CONFIG_2__"); -+ break; -+ case 3: -+ case 7: -+ builtin_define ("__NDS32_EXT_FPU_CONFIG_3__"); -+ break; -+ default: -+ abort (); -+ } -+ } -+ -+ if (TARGET_BIG_ENDIAN) -+ builtin_define ("__NDS32_EB__"); -+ else -+ builtin_define ("__NDS32_EL__"); -+ -+ if (TARGET_REDUCED_REGS) -+ builtin_define ("__NDS32_REDUCED_REGS__"); -+ if (TARGET_CMOV) -+ builtin_define ("__NDS32_CMOV__"); -+ if (TARGET_EXT_PERF) -+ builtin_define ("__NDS32_EXT_PERF__"); -+ if (TARGET_EXT_PERF2) -+ builtin_define ("__NDS32_EXT_PERF2__"); -+ if (TARGET_EXT_STRING) -+ builtin_define ("__NDS32_EXT_STRING__"); -+ if (TARGET_16_BIT) -+ builtin_define ("__NDS32_16_BIT__"); -+ if (TARGET_GP_DIRECT) -+ builtin_define ("__NDS32_GP_DIRECT__"); -+ if (TARGET_VH) -+ builtin_define ("__NDS32_VH__"); -+ if (NDS32_EXT_DSP_P ()) -+ builtin_define ("__NDS32_EXT_DSP__"); -+ if (NDS32_HW_LOOP_P ()) -+ builtin_define ("__NDS32_EXT_ZOL__"); -+ -+ /* Extra builtin macros. */ -+ if (TARGET_ISA_V3 || TARGET_ISA_V3M_PLUS) -+ builtin_define ("__NDS32_EXT_IFC__"); -+ if (TARGET_ISA_V3 || TARGET_ISA_V3M_PLUS) -+ builtin_define ("__NDS32_EXT_EX9__"); -+ if (TARGET_BIG_ENDIAN) -+ builtin_define ("__big_endian__"); -+ -+ builtin_assert ("cpu=nds32"); -+ builtin_assert ("machine=nds32"); -+ -+ /* FOR BACKWARD COMPATIBILITY. */ -+ if (TARGET_ISA_V2) -+ builtin_define ("__NDS32_BASELINE_V2__"); -+ if (TARGET_ISA_V3) -+ builtin_define ("__NDS32_BASELINE_V3__"); -+ if (TARGET_ISA_V3M) -+ builtin_define ("__NDS32_BASELINE_V3M__"); -+ if (TARGET_REDUCED_REGS) -+ builtin_define ("__NDS32_REDUCE_REGS__"); -+ -+ if (TARGET_ISA_V2) -+ builtin_define ("NDS32_BASELINE_V2"); -+ if (TARGET_ISA_V3) -+ builtin_define ("NDS32_BASELINE_V3"); -+ if (TARGET_ISA_V3M) -+ builtin_define ("NDS32_BASELINE_V3M"); -+ if (TARGET_REDUCED_REGS) -+ builtin_define ("NDS32_REDUCE_REGS"); -+ if (TARGET_FPU_SINGLE) -+ builtin_define ("NDS32_EXT_FPU_SP"); -+ if (TARGET_FPU_DOUBLE) -+ builtin_define ("NDS32_EXT_FPU_DP"); -+ if (TARGET_EXT_PERF) -+ builtin_define ("NDS32_EXT_PERF"); -+ if (TARGET_EXT_PERF2) -+ builtin_define ("NDS32_EXT_PERF2"); -+ if (TARGET_EXT_STRING) -+ builtin_define ("NDS32_EXT_STRING"); -+ if (TARGET_ISA_V3) -+ builtin_define ("NDS32_EXT_IFC"); -+ if (TARGET_ISA_V3) -+ builtin_define ("NDS32_EXT_EX9"); -+ -+ if (TARGET_HARD_FLOAT) -+ builtin_define ("NDS32_ABI_2FP_PLUS"); -+ else -+ builtin_define ("NDS32_ABI_2"); -+ -+ if (TARGET_BIG_ENDIAN) -+ builtin_define ("NDS32_EB"); -+ else -+ builtin_define ("NDS32_EL"); -+ -+ if (TARGET_ISA_V2) -+ builtin_define ("__NDS32_BASELINE_V2"); -+ if (TARGET_ISA_V3) -+ builtin_define ("__NDS32_BASELINE_V3"); -+ if (TARGET_ISA_V3M) -+ builtin_define ("__NDS32_BASELINE_V3M"); -+ if (TARGET_REDUCED_REGS) -+ builtin_define ("__NDS32_REDUCE_REGS"); -+ if (TARGET_FPU_SINGLE) -+ builtin_define ("__NDS32_EXT_FPU_SP"); -+ if (TARGET_FPU_DOUBLE) -+ builtin_define ("__NDS32_EXT_FPU_DP"); -+ if (TARGET_EXT_PERF) -+ builtin_define ("__NDS32_EXT_PERF"); -+ if (TARGET_EXT_PERF2) -+ builtin_define ("__NDS32_EXT_PERF2"); -+ if (TARGET_EXT_STRING) -+ builtin_define ("__NDS32_EXT_STRING"); -+ if (TARGET_ISA_V3) -+ builtin_define ("__NDS32_EXT_IFC"); -+ -+ if (TARGET_ISA_V3) -+ builtin_define ("__NDS32_EXT_EX9"); -+ -+ if (TARGET_HARD_FLOAT) -+ builtin_define ("__NDS32_ABI_2FP_PLUS"); -+ else -+ builtin_define ("__NDS32_ABI_2"); -+ -+ if (TARGET_BIG_ENDIAN) -+ builtin_define ("__NDS32_EB"); -+ else -+ builtin_define ("__NDS32_EL"); -+#undef builtin_define -+#undef builtin_assert -+} -+ - - /* Defining Data Structures for Per-function Information. */ - -@@ -2743,26 +5007,80 @@ nds32_init_expanders (void) - - /* Register Usage. */ - -+/* -- Order of Allocation of Registers. */ -+ -+void -+nds32_adjust_reg_alloc_order (void) -+{ -+ const int nds32_reg_alloc_order[] = REG_ALLOC_ORDER; -+ -+ /* Copy the default register allocation order, which is designed -+ to optimize for code size. */ -+ memcpy(reg_alloc_order, nds32_reg_alloc_order, sizeof (reg_alloc_order)); -+ -+ /* Adjust few register allocation order when optimizing for speed. */ -+ if (!optimize_size) -+ { -+ memcpy (reg_alloc_order, nds32_reg_alloc_order_for_speed, -+ sizeof (nds32_reg_alloc_order_for_speed)); -+ } -+} -+ - /* -- How Values Fit in Registers. */ - - int - nds32_hard_regno_nregs (int regno ATTRIBUTE_UNUSED, -- machine_mode mode) -+ enum machine_mode mode) - { - return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD); - } - - int --nds32_hard_regno_mode_ok (int regno, machine_mode mode) -+nds32_hard_regno_mode_ok (int regno, enum machine_mode mode) - { -+ if (regno > FIRST_PSEUDO_REGISTER) -+ return true; -+ -+ if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) && NDS32_IS_FPR_REGNUM (regno)) -+ { -+ if (NDS32_IS_EXT_FPR_REGNUM(regno)) -+ return (NDS32_FPR_REGNO_OK_FOR_DOUBLE(regno) && (mode == DFmode)); -+ else if (mode == SFmode || mode == SImode) -+ return NDS32_FPR_REGNO_OK_FOR_SINGLE (regno); -+ else if (mode == DFmode) -+ return NDS32_FPR_REGNO_OK_FOR_DOUBLE (regno); -+ -+ return false; -+ } -+ - /* Restrict double-word quantities to even register pairs. */ -- if (HARD_REGNO_NREGS (regno, mode) == 1 -- || !((regno) & 1)) -- return 1; -+ if (regno <= NDS32_LAST_GPR_REGNUM) -+ return (HARD_REGNO_NREGS (regno, mode) == 1 -+ || !((regno) & 1)); - -- return 0; -+ return false; - } - -+int -+nds32_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2) -+{ -+ if ((GET_MODE_CLASS (mode1) == MODE_INT -+ && GET_MODE_CLASS (mode2) == MODE_INT) -+ && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD -+ && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD) -+ return true; -+ -+ if (GET_MODE_SIZE (mode1) == GET_MODE_SIZE (mode2)) -+ { -+ if ((TARGET_FPU_SINGLE && !TARGET_FPU_DOUBLE) -+ && (mode1 == DFmode || mode2 == DFmode)) -+ return false; -+ else -+ return true; -+ } -+ -+ return false; -+} - - /* Register Classes. */ - -@@ -2784,7 +5102,16 @@ nds32_regno_reg_class (int regno) - else if (regno >= 20 && regno <= 31) - return HIGH_REGS; - else if (regno == 32 || regno == 33) -- return FRAME_REGS; -+ { -+ /* $SFP and $AP is FRAME_REGS in fact, However prevent IRA don't -+ know how to allocate register for $SFP and $AP, just tell IRA they -+ are GENERAL_REGS, and ARM do this hack too. */ -+ return GENERAL_REGS; -+ } -+ else if (regno >= 34 && regno <= 97) -+ return FP_REGS; -+ else if (regno >= 98 && regno <= 100) -+ return LOOP_REGS; - else - return NO_REGS; - } -@@ -2795,14 +5122,39 @@ nds32_regno_reg_class (int regno) - /* -- Basic Stack Layout. */ - - rtx -+nds32_dynamic_chain_address (rtx frameaddr) -+{ -+ if (TARGET_V3PUSH) -+ { -+ /* If -mv3push is specified, we push $fp, $gp, and $lp into stack. -+ We can access dynamic chain address from stack by [$fp - 12]. */ -+ return plus_constant (Pmode, frameaddr, -12); -+ } -+ else -+ { -+ /* For general case we push $fp and $lp into stack at prologue. -+ We can access dynamic chain address from stack by [$fp - 8]. */ -+ return plus_constant (Pmode, frameaddr, -8); -+ } -+} -+ -+rtx - nds32_return_addr_rtx (int count, -- rtx frameaddr ATTRIBUTE_UNUSED) -+ rtx frameaddr) - { -- /* There is no way to determine the return address -- if frameaddr is the frame that has 'count' steps -- up from current frame. */ -+ int offset; -+ rtx addr; -+ - if (count != 0) -- return NULL_RTX; -+ { -+ /* In nds32 ABI design, we can expect that $lp is always available -+ from stack by [$fp - 4] location. */ -+ offset = -4; -+ addr = plus_constant (Pmode, frameaddr, offset); -+ addr = memory_address (Pmode, addr); -+ -+ return gen_rtx_MEM (Pmode, addr); -+ } - - /* If count == 0, it means we are at current frame, - the return address is $r30 ($lp). */ -@@ -2821,15 +5173,18 @@ nds32_initial_elimination_offset (unsigned int from_reg, unsigned int to_reg) - nds32_compute_stack_frame (); - - /* Remember to consider -- cfun->machine->callee_saved_area_padding_bytes -+ cfun->machine->callee_saved_area_gpr_padding_bytes and -+ cfun->machine->eh_return_data_regs_size - when calculating offset. */ - if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM) - { - offset = (cfun->machine->fp_size -- + cfun->machine->gp_size -+ + cfun->machine->gp_size - + cfun->machine->lp_size - + cfun->machine->callee_saved_gpr_regs_size - + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size -+ + cfun->machine->eh_return_data_regs_size - + cfun->machine->local_size - + cfun->machine->out_args_size); - } -@@ -2850,7 +5205,9 @@ nds32_initial_elimination_offset (unsigned int from_reg, unsigned int to_reg) - + cfun->machine->gp_size - + cfun->machine->lp_size - + cfun->machine->callee_saved_gpr_regs_size -- + cfun->machine->callee_saved_area_gpr_padding_bytes); -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size -+ + cfun->machine->eh_return_data_regs_size); - } - else - { -@@ -2869,10 +5226,11 @@ nds32_init_cumulative_args (CUMULATIVE_ARGS *cum, - tree fndecl ATTRIBUTE_UNUSED, - int n_named_args ATTRIBUTE_UNUSED) - { -- /* Initial available registers -- (in offset, corresponding to NDS32_GPR_ARG_FIRST_REGNUM) -+ /* Initial available registers. The values are offset against -+ NDS32_GPR_ARG_FIRST_REGNUM and NDS32_FPR_ARG_FIRST_REGNUM - for passing arguments. */ - cum->gpr_offset = 0; -+ cum->fpr_offset = 0; - } - - /* -- Function Entry and Exit. */ -@@ -2883,125 +5241,178 @@ nds32_expand_prologue (void) - { - int fp_adjust; - int sp_adjust; -- int en4_const; -- -- rtx Rb, Re; -- rtx fp_adjust_insn, sp_adjust_insn; -+ unsigned Rb, Re; - - /* Compute and setup stack frame size. - 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) - { -- Rb = gen_rtx_REG (SImode, cfun->machine->va_args_first_regno); -- Re = gen_rtx_REG (SImode, cfun->machine->va_args_last_regno); -- /* No need to push $fp, $gp, or $lp, so use GEN_INT(0). */ -- nds32_emit_stack_push_multiple (Rb, Re, GEN_INT (0), true); -+ Rb = cfun->machine->va_args_first_regno; -+ Re = cfun->machine->va_args_last_regno; -+ /* No need to push $fp, $gp, or $lp. */ -+ nds32_emit_stack_push_multiple (Rb, Re, false, false, false, true); - - /* We may also need to adjust stack pointer for padding bytes -- because varargs may cause $sp not 8-byte aligned. */ -+ because varargs may cause $sp not 8-byte aligned. */ - if (cfun->machine->va_args_area_padding_bytes) - { - /* Generate sp adjustment instruction. */ - sp_adjust = cfun->machine->va_args_area_padding_bytes; -- sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (-1 * sp_adjust)); - -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- sp_adjust_insn = emit_insn (sp_adjust_insn); -- -- /* The insn rtx 'sp_adjust_insn' will change frame layout. -- We need to use RTX_FRAME_RELATED_P so that GCC is able to -- generate CFI (Call Frame Information) stuff. */ -- RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ -1 * sp_adjust); - } - } - - /* 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. */ -- Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_first_gpr_regno); -- Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_last_gpr_regno); -- -- /* nds32_emit_stack_push_multiple(first_regno, last_regno), -- the pattern 'stack_push_multiple' is implemented in nds32.md. -- For En4 field, we have to calculate its constant value. -- Refer to Andes ISA for more information. */ -- en4_const = 0; -- if (cfun->machine->fp_size) -- en4_const += 8; -- if (cfun->machine->gp_size) -- en4_const += 4; -- if (cfun->machine->lp_size) -- en4_const += 2; -+ Rb = cfun->machine->callee_saved_first_gpr_regno; -+ Re = cfun->machine->callee_saved_last_gpr_regno; - - /* If $fp, $gp, $lp, and all callee-save registers are NOT required - to be saved, we don't have to create multiple push instruction. - Otherwise, a multiple push instruction is needed. */ -- if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0)) -+ if (!(Rb == SP_REGNUM && Re == SP_REGNUM -+ && cfun->machine->fp_size == 0 -+ && cfun->machine->gp_size == 0 -+ && cfun->machine->lp_size == 0)) - { - /* Create multiple push instruction rtx. */ -- nds32_emit_stack_push_multiple (Rb, Re, GEN_INT (en4_const), false); -+ nds32_emit_stack_push_multiple ( -+ Rb, Re, -+ cfun->machine->fp_size, cfun->machine->gp_size, cfun->machine->lp_size, -+ false); -+ } -+ -+ /* Save eh data registers. */ -+ if (cfun->machine->use_eh_return_p) -+ { -+ Rb = cfun->machine->eh_return_data_first_regno; -+ Re = cfun->machine->eh_return_data_last_regno; -+ -+ /* No need to push $fp, $gp, or $lp. -+ Also, this is not variadic arguments push. */ -+ nds32_emit_stack_push_multiple (Rb, Re, false, false, false, false); - } - -- /* Check frame_pointer_needed to see -- if we shall emit fp adjustment instruction. */ -- if (frame_pointer_needed) -- { -- /* adjust $fp = $sp + ($fp size) + ($gp size) + ($lp size) -- + (4 * callee-saved-registers) -- Note: No need to adjust -- cfun->machine->callee_saved_area_padding_bytes, -- because, at this point, stack pointer is just -- at the position after push instruction. */ -- fp_adjust = cfun->machine->fp_size -- + cfun->machine->gp_size -- + cfun->machine->lp_size -- + cfun->machine->callee_saved_gpr_regs_size; -- fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx, -+ /* Check frame_pointer_needed to see -+ if we shall emit fp adjustment instruction. */ -+ if (frame_pointer_needed) -+ { -+ /* adjust $fp = $sp + ($fp size) + ($gp size) + ($lp size) -+ + (4 * callee-saved-registers) -+ + (4 * exception-handling-data-registers) -+ Note: No need to adjust -+ cfun->machine->callee_saved_area_gpr_padding_bytes, -+ because, at this point, stack pointer is just -+ at the position after push instruction. */ -+ fp_adjust = cfun->machine->fp_size -+ + cfun->machine->gp_size -+ + cfun->machine->lp_size -+ + cfun->machine->callee_saved_gpr_regs_size -+ + cfun->machine->eh_return_data_regs_size; -+ -+ nds32_emit_adjust_frame (hard_frame_pointer_rtx, -+ stack_pointer_rtx, -+ fp_adjust); -+ } -+ -+ /* Save fpu registers. */ -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ /* When $sp moved to bottom of stack, we need to check whether -+ the range of offset in the FPU instruction. */ -+ int fpr_offset = cfun->machine->local_size -+ + cfun->machine->out_args_size -+ + cfun->machine->callee_saved_fpr_regs_size; -+ -+ /* Check FPU instruction offset imm14s. */ -+ if (!satisfies_constraint_Is14 (GEN_INT (fpr_offset))) -+ { -+ int fpr_space = cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ -+ /* Save fpu registers, need to allocate stack space -+ for fpu callee registers. And now $sp position -+ on callee saved fpr registers. */ -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ -1 * fpr_space); -+ -+ /* Emit fpu store instruction, using [$sp + offset] store -+ fpu registers. */ -+ nds32_emit_push_fpr_callee_saved (0); -+ -+ /* Adjust $sp = $sp - local_size - out_args_size. */ -+ sp_adjust = cfun->machine->local_size -+ + cfun->machine->out_args_size; -+ -+ /* Allocate stack space for local size and out args size. */ -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ -1 * sp_adjust); -+ } -+ else -+ { -+ /* Offset range in Is14, so $sp moved to bottom of stack. */ -+ -+ /* Adjust $sp = $sp - local_size - out_args_size -+ - callee_saved_area_gpr_padding_bytes -+ - callee_saved_fpr_regs_size. */ -+ sp_adjust = cfun->machine->local_size -+ + cfun->machine->out_args_size -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ -+ nds32_emit_adjust_frame (stack_pointer_rtx, - stack_pointer_rtx, -- GEN_INT (fp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- fp_adjust_insn = emit_insn (fp_adjust_insn); -+ -1 * sp_adjust); - -- /* The insn rtx 'fp_adjust_insn' will change frame layout. */ -- RTX_FRAME_RELATED_P (fp_adjust_insn) = 1; -+ /* Emit fpu store instruction, using [$sp + offset] store -+ fpu registers. */ -+ int fpr_position = cfun->machine->out_args_size -+ + cfun->machine->local_size; -+ nds32_emit_push_fpr_callee_saved (fpr_position); -+ } - } -- -- /* Adjust $sp = $sp - local_size - out_args_size -- - callee_saved_area_padding_bytes. */ -- sp_adjust = cfun->machine->local_size -- + cfun->machine->out_args_size -- + cfun->machine->callee_saved_area_gpr_padding_bytes; -- /* sp_adjust value may be out of range of the addi instruction, -- create alternative add behavior with TA_REGNUM if necessary, -- using NEGATIVE value to tell that we are decreasing address. */ -- sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust); -- if (sp_adjust) -+ else - { -- /* Generate sp adjustment instruction if and only if sp_adjust != 0. */ -- sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (-1 * sp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- sp_adjust_insn = emit_insn (sp_adjust_insn); -+ /* Adjust $sp = $sp - local_size - out_args_size -+ - callee_saved_area_gpr_padding_bytes. */ -+ sp_adjust = cfun->machine->local_size -+ + cfun->machine->out_args_size -+ + cfun->machine->callee_saved_area_gpr_padding_bytes; - -- /* The insn rtx 'sp_adjust_insn' will change frame layout. -- We need to use RTX_FRAME_RELATED_P so that GCC is able to -- generate CFI (Call Frame Information) stuff. */ -- RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; -+ /* sp_adjust value may be out of range of the addi instruction, -+ create alternative add behavior with TA_REGNUM if necessary, -+ using NEGATIVE value to tell that we are decreasing address. */ -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ -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. */ -@@ -3009,18 +5420,17 @@ void - nds32_expand_epilogue (bool sibcall_p) - { - int sp_adjust; -- int en4_const; -- -- rtx Rb, Re; -- rtx sp_adjust_insn; -+ unsigned Rb, Re; - - /* Compute and setup stack frame size. - 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. -@@ -3029,110 +5439,156 @@ nds32_expand_epilogue (bool sibcall_p) - if (cfun->machine->naked_p) - { - /* If this is a variadic function, we do not have to restore argument -- registers but need to adjust stack pointer back to previous stack -- frame location before return. */ -+ registers but need to adjust stack pointer back to previous stack -+ frame location before return. */ - if (cfun->machine->va_args_size != 0) - { - /* Generate sp adjustment instruction. - We need to consider padding bytes here. */ - sp_adjust = cfun->machine->va_args_size - + cfun->machine->va_args_area_padding_bytes; -- sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (sp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- sp_adjust_insn = emit_insn (sp_adjust_insn); - -- /* The insn rtx 'sp_adjust_insn' will change frame layout. -- We need to use RTX_FRAME_RELATED_P so that GCC is able to -- generate CFI (Call Frame Information) stuff. */ -- RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ sp_adjust); - } - - /* 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; - } - - if (frame_pointer_needed) - { -- /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size) -- - (4 * callee-saved-registers) -- Note: No need to adjust -- cfun->machine->callee_saved_area_padding_bytes, -- because we want to adjust stack pointer -- to the position for pop instruction. */ -- sp_adjust = cfun->machine->fp_size -- + cfun->machine->gp_size -- + cfun->machine->lp_size -- + cfun->machine->callee_saved_gpr_regs_size; -- sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, -+ /* Restore fpu registers. */ -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ int gpr_padding = cfun->machine->callee_saved_area_gpr_padding_bytes; -+ -+ /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size) -+ - (4 * callee-saved-registers) -+ - (4 * exception-handling-data-registers) -+ - (4 * callee-saved-gpr-registers padding byte) -+ - (4 * callee-saved-fpr-registers) -+ Note: we want to adjust stack pointer -+ to the position for callee-saved fpr register, -+ And restore fpu register use .bi instruction to adjust $sp -+ from callee-saved fpr register to pop instruction. */ -+ sp_adjust = cfun->machine->fp_size -+ + cfun->machine->gp_size -+ + cfun->machine->lp_size -+ + cfun->machine->callee_saved_gpr_regs_size -+ + cfun->machine->eh_return_data_regs_size -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ -+ nds32_emit_adjust_frame (stack_pointer_rtx, - hard_frame_pointer_rtx, -- GEN_INT (-1 * sp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- sp_adjust_insn = emit_insn (sp_adjust_insn); -+ -1 * sp_adjust); -+ -+ /* Emit fpu load instruction, using .bi instruction -+ load fpu registers. */ -+ nds32_emit_pop_fpr_callee_saved (gpr_padding); -+ } -+ else -+ { -+ /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size) -+ - (4 * callee-saved-registers) -+ - (4 * exception-handling-data-registers) -+ Note: No need to adjust -+ cfun->machine->callee_saved_area_gpr_padding_bytes, -+ because we want to adjust stack pointer -+ to the position for pop instruction. */ -+ sp_adjust = cfun->machine->fp_size -+ + cfun->machine->gp_size -+ + cfun->machine->lp_size -+ + cfun->machine->callee_saved_gpr_regs_size -+ + cfun->machine->eh_return_data_regs_size; - -- /* The insn rtx 'sp_adjust_insn' will change frame layout. */ -- RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ hard_frame_pointer_rtx, -+ -1 * sp_adjust); -+ } - } - else - { -- /* If frame pointer is NOT needed, -- we cannot calculate the sp adjustment from frame pointer. -- Instead, we calculate the adjustment by local_size, -- out_args_size, and callee_saved_area_padding_bytes. -- Notice that such sp adjustment value may be out of range, -- so we have to deal with it as well. */ -+ /* Restore fpu registers. */ -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ int gpr_padding = cfun->machine->callee_saved_area_gpr_padding_bytes; - -- /* Adjust $sp = $sp + local_size + out_args_size -- + callee_saved_area_padding_bytes. */ -- sp_adjust = cfun->machine->local_size -- + cfun->machine->out_args_size -- + cfun->machine->callee_saved_area_gpr_padding_bytes; -- /* sp_adjust value may be out of range of the addi instruction, -- create alternative add behavior with TA_REGNUM if necessary, -- using POSITIVE value to tell that we are increasing address. */ -- sp_adjust = nds32_force_addi_stack_int (sp_adjust); -- if (sp_adjust) -- { -- /* Generate sp adjustment instruction -- if and only if sp_adjust != 0. */ -- sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (sp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- sp_adjust_insn = emit_insn (sp_adjust_insn); -+ /* Adjust $sp = $sp + local_size + out_args_size. */ -+ sp_adjust = cfun->machine->local_size -+ + cfun->machine->out_args_size; - -- /* The insn rtx 'sp_adjust_insn' will change frame layout. */ -- RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ sp_adjust); -+ -+ /* Emit fpu load instruction, using .bi instruction -+ load fpu registers, and adjust $sp from callee-saved fpr register -+ to callee-saved gpr register. */ -+ nds32_emit_pop_fpr_callee_saved (gpr_padding); -+ } -+ else -+ { -+ /* If frame pointer is NOT needed, -+ we cannot calculate the sp adjustment from frame pointer. -+ Instead, we calculate the adjustment by local_size, -+ out_args_size, and callee_saved_area_gpr_padding_bytes. -+ Notice that such sp adjustment value may be out of range, -+ so we have to deal with it as well. */ -+ -+ /* Adjust $sp = $sp + local_size + out_args_size -+ + callee_saved_area_gpr_padding_bytes. */ -+ sp_adjust = cfun->machine->local_size -+ + cfun->machine->out_args_size -+ + cfun->machine->callee_saved_area_gpr_padding_bytes; -+ -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ sp_adjust); - } - } - -+ /* Restore eh data registers. */ -+ if (cfun->machine->use_eh_return_p) -+ { -+ Rb = cfun->machine->eh_return_data_first_regno; -+ Re = cfun->machine->eh_return_data_last_regno; -+ -+ /* No need to pop $fp, $gp, or $lp. */ -+ nds32_emit_stack_pop_multiple (Rb, Re, false, false, false); -+ } -+ - /* Get callee_first_regno and callee_last_regno. */ -- Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_first_gpr_regno); -- Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_last_gpr_regno); -- -- /* nds32_emit_stack_pop_multiple(first_regno, last_regno), -- the pattern 'stack_pop_multiple' is implementad in nds32.md. -- For En4 field, we have to calculate its constant value. -- Refer to Andes ISA for more information. */ -- en4_const = 0; -- if (cfun->machine->fp_size) -- en4_const += 8; -- if (cfun->machine->gp_size) -- en4_const += 4; -- if (cfun->machine->lp_size) -- en4_const += 2; -+ Rb = cfun->machine->callee_saved_first_gpr_regno; -+ Re = cfun->machine->callee_saved_last_gpr_regno; - - /* If $fp, $gp, $lp, and all callee-save registers are NOT required - to be saved, we don't have to create multiple pop instruction. - Otherwise, a multiple pop instruction is needed. */ -- if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0)) -+ if (!(Rb == SP_REGNUM && Re == SP_REGNUM -+ && cfun->machine->fp_size == 0 -+ && cfun->machine->gp_size == 0 -+ && cfun->machine->lp_size == 0)) - { - /* Create multiple pop instruction rtx. */ -- nds32_emit_stack_pop_multiple (Rb, Re, GEN_INT (en4_const)); -+ nds32_emit_stack_pop_multiple ( -+ Rb, Re, -+ cfun->machine->fp_size, cfun->machine->gp_size, cfun->machine->lp_size); - } - - /* If this is a variadic function, we do not have to restore argument -@@ -3141,19 +5597,49 @@ nds32_expand_epilogue (bool sibcall_p) - if (cfun->machine->va_args_size != 0) - { - /* Generate sp adjustment instruction. -- We need to consider padding bytes here. */ -+ We need to consider padding bytes here. */ - sp_adjust = cfun->machine->va_args_size - + cfun->machine->va_args_area_padding_bytes; -- sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (sp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- sp_adjust_insn = emit_insn (sp_adjust_insn); - -- /* The insn rtx 'sp_adjust_insn' will change frame layout. -- We need to use RTX_FRAME_RELATED_P so that GCC is able to -- generate CFI (Call Frame Information) stuff. */ -- RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ sp_adjust); -+ } -+ -+ /* If this function uses __builtin_eh_return, make stack adjustment -+ for exception handler. */ -+ if (cfun->machine->use_eh_return_p) -+ { -+ /* We need to unwind the stack by the offset computed by -+ EH_RETURN_STACKADJ_RTX. However, at this point the CFA is -+ based on SP. Ideally we would update the SP and define the -+ CFA along the lines of: -+ -+ SP = SP + EH_RETURN_STACKADJ_RTX -+ (regnote CFA = SP - EH_RETURN_STACKADJ_RTX) -+ -+ However the dwarf emitter only understands a constant -+ register offset. -+ -+ The solution chosen here is to use the otherwise $ta ($r15) -+ as a temporary register to hold the current SP value. The -+ CFA is described using $ta then SP is modified. */ -+ -+ rtx ta_reg; -+ rtx insn; -+ -+ ta_reg = gen_rtx_REG (SImode, TA_REGNUM); -+ -+ insn = emit_move_insn (ta_reg, stack_pointer_rtx); -+ add_reg_note (insn, REG_CFA_DEF_CFA, ta_reg); -+ RTX_FRAME_RELATED_P (insn) = 1; -+ -+ emit_insn (gen_addsi3 (stack_pointer_rtx, -+ stack_pointer_rtx, -+ EH_RETURN_STACKADJ_RTX)); -+ -+ /* Ensure the assignment to $ta does not get optimized away. */ -+ emit_use (ta_reg); - } - - /* Generate return instruction. */ -@@ -3167,28 +5653,35 @@ nds32_expand_prologue_v3push (void) - { - int fp_adjust; - int sp_adjust; -- -- rtx Rb, Re; -- rtx fp_adjust_insn, sp_adjust_insn; -+ int fpr_space = 0; -+ unsigned Rb, Re; - - /* Compute and setup stack frame size. - The result will be in cfun->machine. */ - nds32_compute_stack_frame (); - -+ 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. */ -- Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_first_gpr_regno); -- Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_last_gpr_regno); -+ Rb = cfun->machine->callee_saved_first_gpr_regno; -+ Re = cfun->machine->callee_saved_last_gpr_regno; - - /* Calculate sp_adjust first to test if 'push25 Re,imm8u' is available, - where imm8u has to be 8-byte alignment. */ - sp_adjust = cfun->machine->local_size - + cfun->machine->out_args_size -- + cfun->machine->callee_saved_area_gpr_padding_bytes; -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; - - if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) - && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)) -@@ -3196,94 +5689,118 @@ nds32_expand_prologue_v3push (void) - /* We can use 'push25 Re,imm8u'. */ - - /* nds32_emit_stack_v3push(last_regno, sp_adjust), -- the pattern 'stack_v3push' is implemented in nds32.md. -- The (const_int 14) means v3push always push { $fp $gp $lp }. */ -- nds32_emit_stack_v3push (Rb, Re, -- GEN_INT (14), GEN_INT (sp_adjust)); -+ the pattern 'stack_v3push' is implemented in nds32.md. */ -+ nds32_emit_stack_v3push (Rb, Re, sp_adjust); -+ -+ /* Save fpu registers. */ -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ /* Calculate fpr position. */ -+ int fpr_position = cfun->machine->local_size -+ + cfun->machine->out_args_size; -+ /* Emit fpu store instruction, using [$sp + offset] store -+ fpu registers. */ -+ nds32_emit_push_fpr_callee_saved (fpr_position); -+ } - - /* Check frame_pointer_needed to see -- if we shall emit fp adjustment instruction. */ -+ if we shall emit fp adjustment instruction. */ - if (frame_pointer_needed) - { - /* adjust $fp = $sp + 4 ($fp size) -- + 4 ($gp size) -- + 4 ($lp size) -- + (4 * n) (callee-saved registers) -- + sp_adjust ('push25 Re,imm8u') -+ + 4 ($gp size) -+ + 4 ($lp size) -+ + (4 * n) (callee-saved registers) -+ + sp_adjust ('push25 Re,imm8u') - Note: Since we use 'push25 Re,imm8u', -- the position of stack pointer is further -- changed after push instruction. -- Hence, we need to take sp_adjust value -- into consideration. */ -+ the position of stack pointer is further -+ changed after push instruction. -+ Hence, we need to take sp_adjust value -+ into consideration. */ - fp_adjust = cfun->machine->fp_size - + cfun->machine->gp_size - + cfun->machine->lp_size - + cfun->machine->callee_saved_gpr_regs_size - + sp_adjust; -- fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (fp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- fp_adjust_insn = emit_insn (fp_adjust_insn); -+ -+ nds32_emit_adjust_frame (hard_frame_pointer_rtx, -+ stack_pointer_rtx, -+ fp_adjust); - } - } - else - { -- /* We have to use 'push25 Re,0' and -- expand one more instruction to adjust $sp later. */ -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ /* Calculate fpr space. */ -+ fpr_space = cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ -+ /* We have to use 'push25 Re, fpr_space', to pre-allocate -+ callee saved fpr registers space. */ -+ nds32_emit_stack_v3push (Rb, Re, fpr_space); -+ nds32_emit_push_fpr_callee_saved (0); -+ } -+ else -+ { -+ /* We have to use 'push25 Re,0' and -+ expand one more instruction to adjust $sp later. */ - -- /* nds32_emit_stack_v3push(last_regno, sp_adjust), -- the pattern 'stack_v3push' is implemented in nds32.md. -- The (const_int 14) means v3push always push { $fp $gp $lp }. */ -- nds32_emit_stack_v3push (Rb, Re, -- GEN_INT (14), GEN_INT (0)); -+ /* nds32_emit_stack_v3push(last_regno, sp_adjust), -+ the pattern 'stack_v3push' is implemented in nds32.md. */ -+ nds32_emit_stack_v3push (Rb, Re, 0); -+ } - - /* Check frame_pointer_needed to see -- if we shall emit fp adjustment instruction. */ -+ if we shall emit fp adjustment instruction. */ - if (frame_pointer_needed) - { - /* adjust $fp = $sp + 4 ($fp size) -- + 4 ($gp size) -- + 4 ($lp size) -- + (4 * n) (callee-saved registers) -+ + 4 ($gp size) -+ + 4 ($lp size) -+ + (4 * n) (callee-saved registers) - Note: Since we use 'push25 Re,0', -- the stack pointer is just at the position -- after push instruction. -- No need to take sp_adjust into consideration. */ -+ the stack pointer is just at the position -+ after push instruction. -+ No need to take sp_adjust into consideration. */ - fp_adjust = cfun->machine->fp_size - + cfun->machine->gp_size - + cfun->machine->lp_size - + cfun->machine->callee_saved_gpr_regs_size; -- fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (fp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- fp_adjust_insn = emit_insn (fp_adjust_insn); -- } - -- /* Because we use 'push25 Re,0', -- we need to expand one more instruction to adjust $sp. -- However, sp_adjust value may be out of range of the addi instruction, -- create alternative add behavior with TA_REGNUM if necessary, -- using NEGATIVE value to tell that we are decreasing address. */ -- sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust); -- if (sp_adjust) -- { -- /* Generate sp adjustment instruction -- if and only if sp_adjust != 0. */ -- sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (-1 * sp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- sp_adjust_insn = emit_insn (sp_adjust_insn); -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ /* We use 'push25 Re, fpr_space', the $sp is -+ on callee saved fpr position, so need to consider -+ fpr space. */ -+ fp_adjust = fp_adjust + fpr_space; -+ } -+ -+ nds32_emit_adjust_frame (hard_frame_pointer_rtx, -+ stack_pointer_rtx, -+ fp_adjust); -+ } - -- /* The insn rtx 'sp_adjust_insn' will change frame layout. -- We need to use RTX_FRAME_RELATED_P so that GCC is able to -- generate CFI (Call Frame Information) stuff. */ -- RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ /* We use 'push25 Re, fpr_space', -+ the $sp is on callee saved fpr position, -+ no need to consider fpr space. */ -+ sp_adjust = sp_adjust - fpr_space; - } -+ -+ /* Because we use 'push25 Re,0', -+ we need to expand one more instruction to adjust $sp. -+ using NEGATIVE value to tell that we are decreasing address. */ -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ -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 ()); -@@ -3294,9 +5811,7 @@ void - nds32_expand_epilogue_v3pop (bool sibcall_p) - { - int sp_adjust; -- -- rtx Rb, Re; -- rtx sp_adjust_insn; -+ unsigned Rb, Re; - - /* Compute and setup stack frame size. - The result will be in cfun->machine. */ -@@ -3311,21 +5826,32 @@ 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; - } - - /* Get callee_first_regno and callee_last_regno. */ -- Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_first_gpr_regno); -- Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_last_gpr_regno); -+ Rb = cfun->machine->callee_saved_first_gpr_regno; -+ Re = cfun->machine->callee_saved_last_gpr_regno; - - /* Calculate sp_adjust first to test if 'pop25 Re,imm8u' is available, - where imm8u has to be 8-byte alignment. */ - sp_adjust = cfun->machine->local_size - + cfun->machine->out_args_size -- + cfun->machine->callee_saved_area_gpr_padding_bytes; -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; - - /* We have to consider alloca issue as well. - If the function does call alloca(), the stack pointer is not fixed. -@@ -3338,38 +5864,65 @@ nds32_expand_epilogue_v3pop (bool sibcall_p) - && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust) - && !cfun->calls_alloca) - { -+ /* Restore fpu registers. */ -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ int fpr_position = cfun->machine->local_size -+ + cfun->machine->out_args_size; -+ /* Emit fpu load instruction, using [$sp + offset] restore -+ fpu registers. */ -+ nds32_emit_v3pop_fpr_callee_saved (fpr_position); -+ } -+ - /* We can use 'pop25 Re,imm8u'. */ - - /* nds32_emit_stack_v3pop(last_regno, sp_adjust), -- the pattern 'stack_v3pop' is implementad in nds32.md. -- The (const_int 14) means v3pop always pop { $fp $gp $lp }. */ -- nds32_emit_stack_v3pop (Rb, Re, -- GEN_INT (14), GEN_INT (sp_adjust)); -+ the pattern 'stack_v3pop' is implementad in nds32.md. */ -+ nds32_emit_stack_v3pop (Rb, Re, sp_adjust); - } - else - { - /* We have to use 'pop25 Re,0', and prior to it, -- we must expand one more instruction to adjust $sp. */ -+ we must expand one more instruction to adjust $sp. */ - - if (frame_pointer_needed) - { - /* adjust $sp = $fp - 4 ($fp size) -- - 4 ($gp size) -- - 4 ($lp size) -- - (4 * n) (callee-saved registers) -+ - 4 ($gp size) -+ - 4 ($lp size) -+ - (4 * n) (callee-saved registers) - Note: No need to adjust -- cfun->machine->callee_saved_area_padding_bytes, -- because we want to adjust stack pointer -- to the position for pop instruction. */ -+ cfun->machine->callee_saved_area_gpr_padding_bytes, -+ because we want to adjust stack pointer -+ to the position for pop instruction. */ - sp_adjust = cfun->machine->fp_size - + cfun->machine->gp_size - + cfun->machine->lp_size - + cfun->machine->callee_saved_gpr_regs_size; -- sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, -+ -+ /* Restore fpu registers. */ -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ /* Set $sp to callee saved fpr position, we need to restore -+ fpr registers. */ -+ sp_adjust = sp_adjust -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ hard_frame_pointer_rtx, -+ -1 * sp_adjust); -+ -+ /* Emit fpu load instruction, using [$sp + offset] restore -+ fpu registers. */ -+ nds32_emit_v3pop_fpr_callee_saved (0); -+ } -+ else -+ { -+ nds32_emit_adjust_frame (stack_pointer_rtx, - hard_frame_pointer_rtx, -- GEN_INT (-1 * sp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- sp_adjust_insn = emit_insn (sp_adjust_insn); -+ -1 * sp_adjust); -+ } - } - else - { -@@ -3381,33 +5934,57 @@ nds32_expand_epilogue_v3pop (bool sibcall_p) - so we have to deal with it as well. */ - - /* Adjust $sp = $sp + local_size + out_args_size -- + callee_saved_area_padding_bytes. */ -+ + callee_saved_area_gpr_padding_bytes -+ + callee_saved_fpr_regs_size. */ - sp_adjust = cfun->machine->local_size - + cfun->machine->out_args_size -- + cfun->machine->callee_saved_area_gpr_padding_bytes; -- /* sp_adjust value may be out of range of the addi instruction, -- create alternative add behavior with TA_REGNUM if necessary, -- using POSITIVE value to tell that we are increasing address. */ -- sp_adjust = nds32_force_addi_stack_int (sp_adjust); -- if (sp_adjust) -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ -+ /* Restore fpu registers. */ -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ /* Set $sp to callee saved fpr position, we need to restore -+ fpr registers. */ -+ sp_adjust = sp_adjust -+ - cfun->machine->callee_saved_area_gpr_padding_bytes -+ - cfun->machine->callee_saved_fpr_regs_size; -+ -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ sp_adjust); -+ -+ /* Emit fpu load instruction, using [$sp + offset] restore -+ fpu registers. */ -+ nds32_emit_v3pop_fpr_callee_saved (0); -+ } -+ else - { -- /* Generate sp adjustment instruction -- if and only if sp_adjust != 0. */ -- sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (sp_adjust)); -- /* Emit rtx into instructions list and receive INSN rtx form. */ -- sp_adjust_insn = emit_insn (sp_adjust_insn); -+ /* sp_adjust value may be out of range of the addi instruction, -+ create alternative add behavior with TA_REGNUM if necessary, -+ using POSITIVE value to tell that we are increasing -+ address. */ -+ nds32_emit_adjust_frame (stack_pointer_rtx, -+ stack_pointer_rtx, -+ sp_adjust); - } - } - -- /* nds32_emit_stack_v3pop(last_regno, sp_adjust), -- the pattern 'stack_v3pop' is implementad in nds32.md. */ -- /* The (const_int 14) means v3pop always pop { $fp $gp $lp }. */ -- nds32_emit_stack_v3pop (Rb, Re, -- GEN_INT (14), GEN_INT (0)); -+ if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM) -+ { -+ /* We have fpr need to restore, so $sp is set on callee saved fpr -+ position. And we use 'pop25 Re, fpr_space' to adjust $sp. */ -+ int fpr_space = cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size; -+ nds32_emit_stack_v3pop (Rb, Re, fpr_space); -+ } -+ else -+ { -+ /* nds32_emit_stack_v3pop(last_regno, sp_adjust), -+ the pattern 'stack_v3pop' is implementad in nds32.md. */ -+ nds32_emit_stack_v3pop (Rb, Re, 0); -+ } - } -- - /* Generate return instruction. */ - emit_jump_insn (gen_pop25return ()); - } -@@ -3418,97 +5995,179 @@ nds32_expand_epilogue_v3pop (bool sibcall_p) - int - nds32_can_use_return_insn (void) - { -+ int sp_adjust; -+ - /* Prior to reloading, we can't tell how many registers must be saved. - Thus we can not determine whether this function has null epilogue. */ - 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 -+ + cfun->machine->callee_saved_fpr_regs_size; -+ if (!cfun->machine->fp_as_gp_p -+ && satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) -+ && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust) -+ && !cfun->calls_alloca -+ && NDS32_V3PUSH_AVAILABLE_P -+ && !(TARGET_HARD_FLOAT -+ && (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM))) -+ return 1; -+ - /* If no stack was created, two conditions must be satisfied: - 1. This is a naked function. -- So there is no callee-saved, local size, or outgoing size. -+ So there is no callee-saved, local size, or outgoing size. - 2. This is NOT a variadic function. -- So there is no pushing arguement registers into the stack. */ -- return (cfun->machine->naked_p && (cfun->machine->va_args_size == 0)); -+ So there is no pushing arguement registers into the stack. */ -+ return ((cfun->machine->naked_p && (cfun->machine->va_args_size == 0))); - } - --/* ------------------------------------------------------------------------ */ -- --/* Function to test 333-form for load/store instructions. -- This is auxiliary extern function for auxiliary macro in nds32.h. -- Because it is a little complicated, we use function instead of macro. */ --bool --nds32_ls_333_p (rtx rt, rtx ra, rtx imm, machine_mode mode) -+enum machine_mode -+nds32_case_vector_shorten_mode (int min_offset, int max_offset, -+ rtx body ATTRIBUTE_UNUSED) - { -- if (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS -- && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS) -+ if (min_offset < 0 || max_offset >= 0x2000) -+ return SImode; -+ else - { -- if (GET_MODE_SIZE (mode) == 4) -- return satisfies_constraint_Iu05 (imm); -- -- if (GET_MODE_SIZE (mode) == 2) -- return satisfies_constraint_Iu04 (imm); -- -- if (GET_MODE_SIZE (mode) == 1) -- return satisfies_constraint_Iu03 (imm); -+ /* The jump table maybe need to 2 byte alignment, -+ so reserved 1 byte for check max_offset. */ -+ if (max_offset >= 0xff) -+ return HImode; -+ else -+ return QImode; - } -+} -+ -+static bool -+nds32_cannot_copy_insn_p (rtx_insn *insn) -+{ -+ /* The hwloop_cfg insn cannot be copied. */ -+ if (recog_memoized (insn) == CODE_FOR_hwloop_cfg) -+ return true; - - return false; - } - -- --/* Computing the Length of an Insn. -- Modifies the length assigned to instruction INSN. -- LEN is the initially computed length of the insn. */ -+/* Return alignment for the label. */ - int --nds32_adjust_insn_length (rtx_insn *insn, int length) -+nds32_target_alignment (rtx label) - { -- rtx src, dst; -+ rtx_insn *insn; - -- switch (recog_memoized (insn)) -+ if (!NDS32_ALIGN_P ()) -+ return 0; -+ -+ insn = next_active_insn (label); -+ -+ /* Always align to 4 byte when first instruction after label is jump -+ instruction since length for that might changed, so let's always align -+ it for make sure we don't lose any perfomance here. */ -+ if (insn == 0 -+ || (get_attr_length (insn) == 2 -+ && !JUMP_P (insn) && !CALL_P (insn))) -+ return 0; -+ else -+ return 2; -+} -+ -+/* Return alignment for data. */ -+unsigned int -+nds32_data_alignment (tree data, -+ unsigned int basic_align) -+{ -+ if ((basic_align < BITS_PER_WORD) -+ && (TREE_CODE (data) == ARRAY_TYPE -+ || TREE_CODE (data) == UNION_TYPE -+ || TREE_CODE (data) == RECORD_TYPE)) -+ return BITS_PER_WORD; -+ else -+ return basic_align; -+} -+ -+/* Return alignment for constant value. */ -+unsigned int -+nds32_constant_alignment (tree constant, -+ unsigned int basic_align) -+{ -+ /* Make string literal and constant for constructor to word align. */ -+ if (((TREE_CODE (constant) == STRING_CST -+ || TREE_CODE (constant) == CONSTRUCTOR -+ || TREE_CODE (constant) == UNION_TYPE -+ || TREE_CODE (constant) == RECORD_TYPE -+ || TREE_CODE (constant) == ARRAY_TYPE) -+ && basic_align < BITS_PER_WORD)) -+ return BITS_PER_WORD; -+ else -+ return basic_align; -+} -+ -+/* Return alignment for local variable. */ -+unsigned int -+nds32_local_alignment (tree local ATTRIBUTE_UNUSED, -+ unsigned int basic_align) -+{ -+ bool at_least_align_to_word = false; -+ /* Make local array, struct and union at least align to word for make -+ sure it can unroll memcpy when initialize by constant. */ -+ switch (TREE_CODE (local)) - { -- case CODE_FOR_move_df: -- case CODE_FOR_move_di: -- /* Adjust length of movd44 to 2. */ -- src = XEXP (PATTERN (insn), 1); -- dst = XEXP (PATTERN (insn), 0); -- -- if (REG_P (src) -- && REG_P (dst) -- && (REGNO (src) % 2) == 0 -- && (REGNO (dst) % 2) == 0) -- length = 2; -+ case ARRAY_TYPE: -+ case RECORD_TYPE: -+ case UNION_TYPE: -+ at_least_align_to_word = true; - break; -- - default: -+ at_least_align_to_word = false; - break; - } -- -- return length; -+ if (at_least_align_to_word -+ && (basic_align < BITS_PER_WORD)) -+ return BITS_PER_WORD; -+ else -+ return basic_align; - } - -- --/* Return align 2 (log base 2) if the next instruction of LABEL is 4 byte. */ --int --nds32_target_alignment (rtx label) -+bool -+nds32_split_double_word_load_store_p(rtx *operands, bool load_p) - { -- rtx_insn *insn; -+ rtx mem = load_p ? operands[1] : operands[0]; -+ /* Do split at split2 if -O0 or schedule 2 not enable. */ -+ if (optimize == 0 || !flag_schedule_insns_after_reload) -+ return !satisfies_constraint_Da (mem) || MEM_VOLATILE_P (mem); - -- if (optimize_size) -- return 0; -+ /* Split double word load store after copy propgation. */ -+ if (current_pass == NULL) -+ return false; - -- insn = next_active_insn (label); -+ const char *pass_name = current_pass->name; -+ if (pass_name && ((strcmp (pass_name, "split4") == 0) -+ || (strcmp (pass_name, "split5") == 0))) -+ return !satisfies_constraint_Da (mem) || MEM_VOLATILE_P (mem); - -- if (insn == 0) -- return 0; -- else if ((get_attr_length (insn) % 4) == 0) -- return 2; -+ return false; -+} -+ -+static bool -+nds32_use_blocks_for_constant_p (enum machine_mode mode, -+ const_rtx x ATTRIBUTE_UNUSED) -+{ -+ if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) -+ && (mode == DFmode || mode == SFmode)) -+ return true; - else -- return 0; -+ return false; - } - - /* ------------------------------------------------------------------------ */ - --/* PART 5: Initialize target hook structure and definitions. */ -+/* PART 6: Initialize target hook structure and definitions. */ - - /* Controlling the Compilation Driver. */ - -@@ -3525,6 +6184,9 @@ nds32_target_alignment (rtx label) - #define TARGET_PROMOTE_FUNCTION_MODE \ - default_promote_function_mode_always_promote - -+#undef TARGET_EXPAND_TO_RTL_HOOK -+#define TARGET_EXPAND_TO_RTL_HOOK nds32_expand_to_rtl_hook -+ - - /* Layout of Source Language Data Types. */ - -@@ -3533,6 +6195,9 @@ nds32_target_alignment (rtx label) - - /* -- Basic Characteristics of Registers. */ - -+#undef TARGET_CONDITIONAL_REGISTER_USAGE -+#define TARGET_CONDITIONAL_REGISTER_USAGE nds32_conditional_register_usage -+ - /* -- Order of Allocation of Registers. */ - - /* -- How Values Fit in Registers. */ -@@ -3544,6 +6209,9 @@ nds32_target_alignment (rtx label) - - /* Register Classes. */ - -+#undef TARGET_PREFERRED_RENAME_CLASS -+#define TARGET_PREFERRED_RENAME_CLASS nds32_preferred_rename_class -+ - #undef TARGET_CLASS_MAX_NREGS - #define TARGET_CLASS_MAX_NREGS nds32_class_max_nregs - -@@ -3591,6 +6259,9 @@ nds32_target_alignment (rtx label) - #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 -@@ -3604,6 +6275,9 @@ nds32_target_alignment (rtx label) - - /* -- How Large Values Are Returned. */ - -+#undef TARGET_RETURN_IN_MEMORY -+#define TARGET_RETURN_IN_MEMORY nds32_return_in_memory -+ - /* -- Caller-Saves Register Allocation. */ - - /* -- Function Entry and Exit. */ -@@ -3630,6 +6304,9 @@ nds32_target_alignment (rtx label) - - /* -- Permitting tail calls. */ - -+#undef TARGET_FUNCTION_OK_FOR_SIBCALL -+#define TARGET_FUNCTION_OK_FOR_SIBCALL nds32_function_ok_for_sibcall -+ - #undef TARGET_WARN_FUNC_RETURN - #define TARGET_WARN_FUNC_RETURN nds32_warn_func_return - -@@ -3662,6 +6339,21 @@ nds32_target_alignment (rtx label) - #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. */ - -@@ -3672,6 +6364,9 @@ nds32_target_alignment (rtx label) - - /* -- Representation of condition codes using registers. */ - -+#undef TARGET_CANONICALIZE_COMPARISON -+#define TARGET_CANONICALIZE_COMPARISON nds32_canonicalize_comparison -+ - /* -- Macros to control conditional execution. */ - - -@@ -3692,6 +6387,15 @@ nds32_target_alignment (rtx label) - - /* Adjusting the Instruction Scheduler. */ - -+#undef TARGET_SCHED_ISSUE_RATE -+#define TARGET_SCHED_ISSUE_RATE nds32_sched_issue_rate -+ -+#undef TARGET_SCHED_ADJUST_COST -+#define TARGET_SCHED_ADJUST_COST nds32_sched_adjust_cost -+ -+#undef TARGET_SCHED_SET_SCHED_FLAGS -+#define TARGET_SCHED_SET_SCHED_FLAGS nds32_set_sched_flags -+ - - /* Dividing the Output into Sections (Texts, Data, . . . ). */ - -@@ -3719,6 +6423,9 @@ nds32_target_alignment (rtx label) - #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. */ -@@ -3741,6 +6448,9 @@ nds32_target_alignment (rtx label) - - /* -- Assembler Commands for Exception Regions. */ - -+#undef TARGET_DWARF_REGISTER_SPAN -+#define TARGET_DWARF_REGISTER_SPAN nds32_dwarf_register_span -+ - /* -- Assembler Commands for Alignment. */ - - -@@ -3756,6 +6466,11 @@ nds32_target_alignment (rtx label) - - /* -- Macros for SDB and DWARF Output. */ - -+/* Variable tracking should be run after all optimizations which -+ change order of insns. It also needs a valid CFG. */ -+#undef TARGET_DELAY_VARTRACK -+#define TARGET_DELAY_VARTRACK true -+ - /* -- Macros for VMS Debug Format. */ - - -@@ -3785,6 +6500,9 @@ nds32_target_alignment (rtx label) - - /* Emulating TLS. */ - -+#undef TARGET_HAVE_TLS -+#define TARGET_HAVE_TLS TARGET_LINUX_ABI -+ - - /* Defining coprocessor specifics for MIPS targets. */ - -@@ -3800,12 +6518,43 @@ nds32_target_alignment (rtx label) - - /* Miscellaneous Parameters. */ - -+#undef TARGET_MD_ASM_ADJUST -+#define TARGET_MD_ASM_ADJUST nds32_md_asm_adjust -+ -+#undef TARGET_MACHINE_DEPENDENT_REORG -+#define TARGET_MACHINE_DEPENDENT_REORG nds32_machine_dependent_reorg -+ - #undef TARGET_INIT_BUILTINS - #define TARGET_INIT_BUILTINS nds32_init_builtins - -+#undef TARGET_BUILTIN_DECL -+#define TARGET_BUILTIN_DECL nds32_builtin_decl -+ - #undef TARGET_EXPAND_BUILTIN - #define TARGET_EXPAND_BUILTIN nds32_expand_builtin - -+#undef TARGET_HAVE_CONDITIONAL_EXECUTION -+#define TARGET_HAVE_CONDITIONAL_EXECUTION nds32_have_conditional_execution -+ -+#undef TARGET_INIT_LIBFUNCS -+#define TARGET_INIT_LIBFUNCS nds32_init_libfuncs -+ -+#undef TARGET_CAN_USE_DOLOOP_P -+#define TARGET_CAN_USE_DOLOOP_P nds32_can_use_doloop_p -+ -+#undef TARGET_INVALID_WITHIN_DOLOOP -+#define TARGET_INVALID_WITHIN_DOLOOP nds32_invalid_within_doloop -+ -+#undef TARGET_CANNOT_COPY_INSN_P -+#define TARGET_CANNOT_COPY_INSN_P nds32_cannot_copy_insn_p -+ -+#undef TARGET_MIN_ANCHOR_OFFSET -+#define TARGET_MIN_ANCHOR_OFFSET -((long long int) 1 << 14) -+#undef TARGET_MAX_ANCHOR_OFFSET -+#define TARGET_MAX_ANCHOR_OFFSET (((long long int) 1 << 14) - 1) -+#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 eb4558c..a3e07cd 100644 ---- a/gcc/config/nds32/nds32.h -+++ b/gcc/config/nds32/nds32.h -@@ -24,6 +24,9 @@ - /* The following are auxiliary macros or structure declarations - that are used all over the nds32.c and nds32.h. */ - -+#define ADJUST_INSN_LENGTH(INSN, LENGTH) \ -+ (LENGTH = nds32_adjust_insn_length (INSN, LENGTH)) -+ - /* Use SYMBOL_FLAG_MACH_DEP to define our own symbol_ref flag. - It is used in nds32_encode_section_info() to store flag in symbol_ref - in case the symbol should be placed in .rodata section. -@@ -33,68 +36,23 @@ - #define NDS32_SYMBOL_REF_RODATA_P(x) \ - ((SYMBOL_REF_FLAGS (x) & NDS32_SYMBOL_FLAG_RODATA) != 0) - --/* Computing the Length of an Insn. */ --#define ADJUST_INSN_LENGTH(INSN, LENGTH) \ -- (LENGTH = nds32_adjust_insn_length (INSN, LENGTH)) -+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 -+}; - --/* Check instruction LS-37-FP-implied form. -- Note: actually its immediate range is imm9u -- since it is used for lwi37/swi37 instructions. */ --#define NDS32_LS_37_FP_P(rt, ra, imm) \ -- (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ -- && REGNO (ra) == FP_REGNUM \ -- && satisfies_constraint_Iu09 (imm)) -- --/* Check instruction LS-37-SP-implied form. -- Note: actually its immediate range is imm9u -- since it is used for lwi37/swi37 instructions. */ --#define NDS32_LS_37_SP_P(rt, ra, imm) \ -- (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ -- && REGNO (ra) == SP_REGNUM \ -- && satisfies_constraint_Iu09 (imm)) -- -- --/* Check load/store instruction form : Rt3, Ra3, imm3u. */ --#define NDS32_LS_333_P(rt, ra, imm, mode) nds32_ls_333_p (rt, ra, imm, mode) -- --/* Check load/store instruction form : Rt4, Ra5, const_int_0. -- Note: no need to check ra because Ra5 means it covers all registers. */ --#define NDS32_LS_450_P(rt, ra, imm) \ -- ((imm == const0_rtx) \ -- && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ -- || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS)) -- --/* Check instruction RRI-333-form. */ --#define NDS32_RRI_333_P(rt, ra, imm) \ -- (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ -- && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS \ -- && satisfies_constraint_Iu03 (imm)) -- --/* Check instruction RI-45-form. */ --#define NDS32_RI_45_P(rt, ra, imm) \ -- (REGNO (rt) == REGNO (ra) \ -- && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ -- || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS) \ -- && satisfies_constraint_Iu05 (imm)) -- -- --/* Check instruction RR-33-form. */ --#define NDS32_RR_33_P(rt, ra) \ -- (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ -- && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS) -- --/* Check instruction RRR-333-form. */ --#define NDS32_RRR_333_P(rt, ra, rb) \ -- (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ -- && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS \ -- && REGNO_REG_CLASS (REGNO (rb)) == LOW_REGS) -- --/* Check instruction RR-45-form. -- Note: no need to check rb because Rb5 means it covers all registers. */ --#define NDS32_RR_45_P(rt, ra, rb) \ -- (REGNO (rt) == REGNO (ra) \ -- && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ -- || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS)) -+/* Classifies expand result for expand helper function. */ -+enum nds32_expand_result_type -+{ -+ EXPAND_DONE, -+ EXPAND_FAIL, -+ EXPAND_CREATE_TEMPLATE -+}; - - /* Classifies address type to distinguish 16-bit/32-bit format. */ - enum nds32_16bit_address_type -@@ -105,6 +63,10 @@ enum nds32_16bit_address_type - ADDRESS_LO_REG_IMM3U, - /* post_inc [lo_reg + imm3u]: 333 format address. */ - ADDRESS_POST_INC_LO_REG_IMM3U, -+ /* post_modify [lo_reg + imm3u]: 333 format address. */ -+ ADDRESS_POST_MODIFY_LO_REG_IMM3U, -+ /* [$r8 + imm7u]: r8 imply address. */ -+ ADDRESS_R8_IMM7U, - /* [$fp + imm7u]: fp imply address. */ - ADDRESS_FP_IMM7U, - /* [$sp + imm7u]: sp imply address. */ -@@ -113,23 +75,67 @@ enum nds32_16bit_address_type - ADDRESS_NOT_16BIT_FORMAT - }; - -- - /* ------------------------------------------------------------------------ */ - - /* Define maximum numbers of registers for passing arguments. */ - #define NDS32_MAX_GPR_REGS_FOR_ARGS 6 -+#define NDS32_MAX_FPR_REGS_FOR_ARGS 6 - - /* Define the register number for first argument. */ - #define NDS32_GPR_ARG_FIRST_REGNUM 0 -+#define NDS32_FPR_ARG_FIRST_REGNUM 34 - - /* Define the register number for return value. */ - #define NDS32_GPR_RET_FIRST_REGNUM 0 -+#define NDS32_FPR_RET_FIRST_REGNUM 34 - - /* Define the first integer register number. */ - #define NDS32_FIRST_GPR_REGNUM 0 - /* Define the last integer register number. */ - #define NDS32_LAST_GPR_REGNUM 31 - -+#define NDS32_FIRST_CALLEE_SAVE_GPR_REGNUM 6 -+#define NDS32_LAST_CALLEE_SAVE_GPR_REGNUM \ -+ (TARGET_REDUCED_REGS ? 10 : 14) -+ -+/* Define the floating-point number of registers. */ -+#define NDS32_FLOAT_REGISTER_NUMBER \ -+ (((nds32_fp_regnum == NDS32_CONFIG_FPU_0) \ -+ || (nds32_fp_regnum == NDS32_CONFIG_FPU_4)) ? 8 \ -+ : ((nds32_fp_regnum == NDS32_CONFIG_FPU_1) \ -+ || (nds32_fp_regnum == NDS32_CONFIG_FPU_5)) ? 16 \ -+ : ((nds32_fp_regnum == NDS32_CONFIG_FPU_2) \ -+ || (nds32_fp_regnum == NDS32_CONFIG_FPU_6)) ? 32 \ -+ : ((nds32_fp_regnum == NDS32_CONFIG_FPU_3) \ -+ || (nds32_fp_regnum == NDS32_CONFIG_FPU_7)) ? 64 \ -+ : 32) -+ -+#define NDS32_EXT_FPU_DOT_E (nds32_fp_regnum >= 4) -+ -+/* Define the first floating-point register number. */ -+#define NDS32_FIRST_FPR_REGNUM 34 -+/* Define the last floating-point register number. */ -+#define NDS32_LAST_FPR_REGNUM \ -+ (NDS32_FIRST_FPR_REGNUM + NDS32_FLOAT_REGISTER_NUMBER - 1) -+ -+ -+#define NDS32_IS_EXT_FPR_REGNUM(regno) \ -+ (((regno) >= NDS32_FIRST_FPR_REGNUM + 32) \ -+ && ((regno) < NDS32_FIRST_FPR_REGNUM + 64)) -+ -+#define NDS32_IS_FPR_REGNUM(regno) \ -+ (((regno) >= NDS32_FIRST_FPR_REGNUM) \ -+ && ((regno) <= NDS32_LAST_FPR_REGNUM)) -+ -+#define NDS32_FPR_REGNO_OK_FOR_SINGLE(regno) \ -+ ((regno) <= NDS32_LAST_FPR_REGNUM) -+ -+#define NDS32_FPR_REGNO_OK_FOR_DOUBLE(regno) \ -+ ((((regno) - NDS32_FIRST_FPR_REGNUM) & 1) == 0) -+ -+#define NDS32_IS_GPR_REGNUM(regno) \ -+ (((regno) <= NDS32_LAST_GPR_REGNUM)) -+ - /* Define double word alignment bits. */ - #define NDS32_DOUBLE_WORD_ALIGNMENT 64 - -@@ -138,6 +144,16 @@ enum nds32_16bit_address_type - #define NDS32_SINGLE_WORD_ALIGN_P(value) (((value) & 0x03) == 0) - #define NDS32_DOUBLE_WORD_ALIGN_P(value) (((value) & 0x07) == 0) - -+/* Determine whether we would like to have code generation strictly aligned. -+ We set it strictly aligned when -malways-align is enabled. -+ Check gcc/common/config/nds32/nds32-common.c for the optimizations that -+ apply -malways-align. */ -+#define NDS32_ALIGN_P() (TARGET_ALWAYS_ALIGN) -+ -+#define NDS32_HW_LOOP_P() (TARGET_HWLOOP && !TARGET_FORCE_NO_HWLOOP) -+ -+#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) \ -@@ -159,21 +175,28 @@ enum nds32_16bit_address_type - /* This macro is used to return the register number for passing argument. - We need to obey the following rules: - 1. If it is required MORE THAN one register, -- we need to further check if it really needs to be -- aligned on double words. -- a) If double word alignment is necessary, -- the register number must be even value. -- b) Otherwise, the register number can be odd or even value. -+ we need to further check if it really needs to be -+ aligned on double words. -+ a) If double word alignment is necessary, -+ the register number must be even value. -+ b) Otherwise, the register number can be odd or even value. - 2. If it is required ONLY one register, -- the register number can be odd or even value. */ --#define NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG(reg_offset, mode, type) \ -- ((NDS32_NEED_N_REGS_FOR_ARG (mode, type) > 1) \ -- ? ((NDS32_MODE_TYPE_ALIGN (mode, type) > PARM_BOUNDARY) \ -- ? (((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM + 1) & ~1) \ -- : ((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM)) \ -+ the register number can be odd or even value. */ -+#define NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG(reg_offset, mode, type) \ -+ ((NDS32_NEED_N_REGS_FOR_ARG (mode, type) > 1) \ -+ ? ((NDS32_MODE_TYPE_ALIGN (mode, type) > PARM_BOUNDARY) \ -+ ? (((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM + 1) & ~1) \ -+ : ((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM)) \ - : ((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM)) - --/* This macro is to check if there are still available registers -+#define NDS32_AVAILABLE_REGNUM_FOR_FPR_ARG(reg_offset, mode, type) \ -+ ((NDS32_NEED_N_REGS_FOR_ARG (mode, type) > 1) \ -+ ? ((NDS32_MODE_TYPE_ALIGN (mode, type) > PARM_BOUNDARY) \ -+ ? (((reg_offset) + NDS32_FPR_ARG_FIRST_REGNUM + 1) & ~1) \ -+ : ((reg_offset) + NDS32_FPR_ARG_FIRST_REGNUM)) \ -+ : ((reg_offset) + NDS32_FPR_ARG_FIRST_REGNUM)) -+ -+/* These two macros are to check if there are still available registers - for passing argument, which must be entirely in registers. */ - #define NDS32_ARG_ENTIRE_IN_GPR_REG_P(reg_offset, mode, type) \ - ((NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (reg_offset, mode, type) \ -@@ -181,13 +204,23 @@ enum nds32_16bit_address_type - <= (NDS32_GPR_ARG_FIRST_REGNUM \ - + NDS32_MAX_GPR_REGS_FOR_ARGS)) - --/* This macro is to check if there are still available registers -+#define NDS32_ARG_ENTIRE_IN_FPR_REG_P(reg_offset, mode, type) \ -+ ((NDS32_AVAILABLE_REGNUM_FOR_FPR_ARG (reg_offset, mode, type) \ -+ + NDS32_NEED_N_REGS_FOR_ARG (mode, type)) \ -+ <= (NDS32_FPR_ARG_FIRST_REGNUM \ -+ + NDS32_MAX_FPR_REGS_FOR_ARGS)) -+ -+/* These two macros are to check if there are still available registers - for passing argument, either entirely in registers or partially - in registers. */ - #define NDS32_ARG_PARTIAL_IN_GPR_REG_P(reg_offset, mode, type) \ - (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (reg_offset, mode, type) \ - < NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS) - -+#define NDS32_ARG_PARTIAL_IN_FPR_REG_P(reg_offset, mode, type) \ -+ (NDS32_AVAILABLE_REGNUM_FOR_FPR_ARG (reg_offset, mode, type) \ -+ < NDS32_FPR_ARG_FIRST_REGNUM + NDS32_MAX_FPR_REGS_FOR_ARGS) -+ - /* This macro is to check if the register is required to be saved on stack. - If call_used_regs[regno] == 0, regno is the callee-saved register. - If df_regs_ever_live_p(regno) == true, it is used in the current function. -@@ -196,6 +229,19 @@ enum nds32_16bit_address_type - #define NDS32_REQUIRED_CALLEE_SAVED_P(regno) \ - ((!call_used_regs[regno]) && (df_regs_ever_live_p (regno))) - -+/* This macro is to check if the push25/pop25 are available to be used -+ for code generation. Because pop25 also performs return behavior, -+ the instructions may not be available for some cases. -+ If we want to use push25/pop25, all the following conditions must -+ be satisfied: -+ 1. TARGET_V3PUSH is set. -+ 2. Current function is not an ISR function. -+ 3. Current function is not a variadic function.*/ -+#define NDS32_V3PUSH_AVAILABLE_P \ -+ (TARGET_V3PUSH \ -+ && !nds32_isr_function_p (current_function_decl) \ -+ && (cfun->machine->va_args_size == 0)) -+ - /* ------------------------------------------------------------------------ */ - - /* A C structure for machine-specific, per-function data. -@@ -222,6 +268,10 @@ struct GTY(()) machine_function - callee-saved registers. */ - int callee_saved_gpr_regs_size; - -+ /* Number of bytes on the stack for saving floating-point -+ callee-saved registers. */ -+ int callee_saved_fpr_regs_size; -+ - /* The padding bytes in callee-saved area may be required. */ - int callee_saved_area_gpr_padding_bytes; - -@@ -230,26 +280,57 @@ struct GTY(()) machine_function - /* The last required general purpose callee-saved register. */ - int callee_saved_last_gpr_regno; - -+ /* The first required floating-point callee-saved register. */ -+ int callee_saved_first_fpr_regno; -+ /* The last required floating-point callee-saved register. */ -+ int callee_saved_last_fpr_regno; -+ - /* The padding bytes in varargs area may be required. */ - int va_args_area_padding_bytes; -- - /* The first required register that should be saved on stack for va_args. */ - int va_args_first_regno; - /* The last required register that should be saved on stack for va_args. */ - int va_args_last_regno; - -+ /* Number of bytes on the stack for saving exception handling registers. */ -+ int eh_return_data_regs_size; -+ /* The first register of passing exception handling information. */ -+ int eh_return_data_first_regno; -+ /* The last register of passing exception handling information. */ -+ int eh_return_data_last_regno; -+ -+ /* Indicate that whether this function -+ calls __builtin_eh_return. */ -+ int use_eh_return_p; -+ - /* Indicate that whether this function needs - prologue/epilogue code generation. */ - int naked_p; - /* Indicate that whether this function - uses fp_as_gp optimization. */ - int fp_as_gp_p; -+ /* Indicate that whether this function is under strictly aligned -+ situation for legitimate address checking. This flag informs -+ nds32_legitimate_address_p() how to treat offset alignment: -+ 1. The IVOPT phase needs to detect available range for memory access, -+ such as checking [base + 32767] ~ [base + (-32768)]. -+ For this case we do not want address to be strictly aligned. -+ 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; -+ /* Record hwloop group, use in reorg pass. */ -+ int hwloop_group_id; - }; - - /* A C structure that contains the arguments information. */ - typedef struct - { - unsigned int gpr_offset; -+ unsigned int fpr_offset; - } nds32_cumulative_args; - - /* ------------------------------------------------------------------------ */ -@@ -288,7 +369,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. -@@ -316,6 +398,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. -@@ -340,19 +429,477 @@ enum nds32_builtins - { - NDS32_BUILTIN_ISYNC, - NDS32_BUILTIN_ISB, -+ NDS32_BUILTIN_DSB, -+ NDS32_BUILTIN_MSYNC_ALL, -+ NDS32_BUILTIN_MSYNC_STORE, - NDS32_BUILTIN_MFSR, - NDS32_BUILTIN_MFUSR, - NDS32_BUILTIN_MTSR, -+ NDS32_BUILTIN_MTSR_ISB, -+ NDS32_BUILTIN_MTSR_DSB, - NDS32_BUILTIN_MTUSR, - NDS32_BUILTIN_SETGIE_EN, -- NDS32_BUILTIN_SETGIE_DIS -+ NDS32_BUILTIN_SETGIE_DIS, -+ NDS32_BUILTIN_FMFCFG, -+ NDS32_BUILTIN_FMFCSR, -+ NDS32_BUILTIN_FMTCSR, -+ NDS32_BUILTIN_FCPYNSS, -+ NDS32_BUILTIN_FCPYSS, -+ NDS32_BUILTIN_FCPYNSD, -+ NDS32_BUILTIN_FCPYSD, -+ NDS32_BUILTIN_FABSS, -+ NDS32_BUILTIN_FABSD, -+ NDS32_BUILTIN_FSQRTS, -+ NDS32_BUILTIN_FSQRTD, -+ NDS32_BUILTIN_ABS, -+ NDS32_BUILTIN_AVE, -+ NDS32_BUILTIN_BCLR, -+ NDS32_BUILTIN_BSET, -+ NDS32_BUILTIN_BTGL, -+ NDS32_BUILTIN_BTST, -+ NDS32_BUILTIN_CLIP, -+ NDS32_BUILTIN_CLIPS, -+ NDS32_BUILTIN_CLZ, -+ NDS32_BUILTIN_CLO, -+ NDS32_BUILTIN_MAX, -+ NDS32_BUILTIN_MIN, -+ NDS32_BUILTIN_PBSAD, -+ NDS32_BUILTIN_PBSADA, -+ NDS32_BUILTIN_BSE, -+ NDS32_BUILTIN_BSP, -+ 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, -+ NDS32_BUILTIN_WSBH, -+ NDS32_BUILTIN_JR_ITOFF, -+ NDS32_BUILTIN_JR_TOFF, -+ NDS32_BUILTIN_JRAL_ITON, -+ NDS32_BUILTIN_JRAL_TON, -+ NDS32_BUILTIN_RET_ITOFF, -+ NDS32_BUILTIN_RET_TOFF, -+ NDS32_BUILTIN_STANDBY_NO_WAKE_GRANT, -+ NDS32_BUILTIN_STANDBY_WAKE_GRANT, -+ NDS32_BUILTIN_STANDBY_WAKE_DONE, -+ NDS32_BUILTIN_TEQZ, -+ NDS32_BUILTIN_TNEZ, -+ NDS32_BUILTIN_TRAP, -+ NDS32_BUILTIN_SETEND_BIG, -+ NDS32_BUILTIN_SETEND_LITTLE, -+ NDS32_BUILTIN_SYSCALL, -+ NDS32_BUILTIN_BREAK, -+ NDS32_BUILTIN_NOP, -+ NDS32_BUILTIN_SCHE_BARRIER, -+ NDS32_BUILTIN_GET_CURRENT_SP, -+ NDS32_BUILTIN_SET_CURRENT_SP, -+ NDS32_BUILTIN_RETURN_ADDRESS, -+ NDS32_BUILTIN_LLW, -+ NDS32_BUILTIN_LWUP, -+ NDS32_BUILTIN_LBUP, -+ NDS32_BUILTIN_SCW, -+ NDS32_BUILTIN_SWUP, -+ NDS32_BUILTIN_SBUP, -+ NDS32_BUILTIN_CCTL_VA_LCK, -+ NDS32_BUILTIN_CCTL_IDX_WBINVAL, -+ NDS32_BUILTIN_CCTL_VA_WBINVAL_L1, -+ NDS32_BUILTIN_CCTL_VA_WBINVAL_LA, -+ NDS32_BUILTIN_CCTL_IDX_READ, -+ NDS32_BUILTIN_CCTL_IDX_WRITE, -+ NDS32_BUILTIN_CCTL_L1D_INVALALL, -+ NDS32_BUILTIN_CCTL_L1D_WBALL_ALVL, -+ NDS32_BUILTIN_CCTL_L1D_WBALL_ONE_LVL, -+ NDS32_BUILTIN_DPREF_QW, -+ NDS32_BUILTIN_DPREF_HW, -+ NDS32_BUILTIN_DPREF_W, -+ NDS32_BUILTIN_DPREF_DW, -+ NDS32_BUILTIN_TLBOP_TRD, -+ NDS32_BUILTIN_TLBOP_TWR, -+ NDS32_BUILTIN_TLBOP_RWR, -+ NDS32_BUILTIN_TLBOP_RWLK, -+ NDS32_BUILTIN_TLBOP_UNLK, -+ NDS32_BUILTIN_TLBOP_PB, -+ NDS32_BUILTIN_TLBOP_INV, -+ NDS32_BUILTIN_TLBOP_FLUA, -+ NDS32_BUILTIN_UALOAD_HW, -+ NDS32_BUILTIN_UALOAD_W, -+ NDS32_BUILTIN_UALOAD_DW, -+ NDS32_BUILTIN_UASTORE_HW, -+ NDS32_BUILTIN_UASTORE_W, -+ NDS32_BUILTIN_UASTORE_DW, -+ NDS32_BUILTIN_GIE_DIS, -+ NDS32_BUILTIN_GIE_EN, -+ NDS32_BUILTIN_ENABLE_INT, -+ NDS32_BUILTIN_DISABLE_INT, -+ NDS32_BUILTIN_SET_PENDING_SWINT, -+ NDS32_BUILTIN_CLR_PENDING_SWINT, -+ NDS32_BUILTIN_CLR_PENDING_HWINT, -+ NDS32_BUILTIN_GET_ALL_PENDING_INT, -+ NDS32_BUILTIN_GET_PENDING_INT, -+ NDS32_BUILTIN_SET_INT_PRIORITY, -+ NDS32_BUILTIN_GET_INT_PRIORITY, -+ NDS32_BUILTIN_SET_TRIG_LEVEL, -+ NDS32_BUILTIN_SET_TRIG_EDGE, -+ NDS32_BUILTIN_GET_TRIG_TYPE, -+ NDS32_BUILTIN_SIGNATURE_BEGIN, -+ NDS32_BUILTIN_SIGNATURE_END, -+ 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_NO_HWLOOP, -+ NDS32_BUILTIN_UNALIGNED_FEATURE, -+ NDS32_BUILTIN_ENABLE_UNALIGNED, -+ NDS32_BUILTIN_DISABLE_UNALIGNED, -+ NDS32_BUILTIN_COUNT - }; - - /* ------------------------------------------------------------------------ */ - --#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2) --#define TARGET_ISA_V3 (nds32_arch_option == ARCH_V3) --#define TARGET_ISA_V3M (nds32_arch_option == ARCH_V3M) -+#define TARGET_ISR_VECTOR_SIZE_4_BYTE \ -+ (nds32_isr_vector_size == 4) -+ -+#define TARGET_ISA_V2 \ -+ (nds32_arch_option == ARCH_V2 || nds32_arch_option == ARCH_V2J) -+#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 || \ -+ nds32_arch_option == ARCH_V3M_PLUS) -+ -+#define TARGET_ISA_V3M_PLUS \ -+ (nds32_arch_option == ARCH_V3M_PLUS) -+ -+#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_PANTHER \ -+ (nds32_cpu_option == CPU_PANTHER) -+#define TARGET_PIPELINE_SIMPLE \ -+ (nds32_cpu_option == CPU_SIMPLE) - - #define TARGET_CMODEL_SMALL \ - (nds32_cmodel_option == CMODEL_SMALL) -@@ -361,55 +908,153 @@ 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 \ - (nds32_cmodel_option == CMODEL_SMALL\ - || nds32_cmodel_option == CMODEL_MEDIUM) - --#define TARGET_SOFT_FLOAT 1 --#define TARGET_HARD_FLOAT 0 -+/* There are three kinds of mul configurations: -+ 1-cycle fast mul, 2-cycle fast mul, and slow mul operation. */ -+#define TARGET_MUL_FAST_1 \ -+ (nds32_mul_config == MUL_TYPE_FAST_1) -+#define TARGET_MUL_FAST_2 \ -+ (nds32_mul_config == MUL_TYPE_FAST_2) -+#define TARGET_MUL_SLOW \ -+ (nds32_mul_config == MUL_TYPE_SLOW) -+ -+/* Run-time Target Specification. */ -+#define TARGET_SOFT_FLOAT (nds32_abi == NDS32_ABI_V2) -+/* Use hardware floating point calling convention. */ -+#define TARGET_HARD_FLOAT (nds32_abi == NDS32_ABI_V2_FP_PLUS) -+ -+/* 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 == 1 -+# define TARGET_DEFAULT_ABI NDS32_ABI_V2_FP_PLUS -+# define TARGET_DEFAULT_FPU_ISA MASK_FPU_DOUBLE | MASK_FPU_SINGLE -+# define TARGET_DEFAULT_FPU_FMA 0 -+#else -+# if TARGET_ARCH_DEFAULT == 2 -+# define TARGET_DEFAULT_ABI NDS32_ABI_V2_FP_PLUS -+# define TARGET_DEFAULT_FPU_ISA MASK_FPU_SINGLE -+# define TARGET_DEFAULT_FPU_FMA 0 -+# else -+# define TARGET_DEFAULT_ABI NDS32_ABI_V2 -+# define TARGET_DEFAULT_FPU_ISA 0 -+# define TARGET_DEFAULT_FPU_FMA 0 -+# endif -+#endif -+ -+#define TARGET_CONFIG_FPU_DEFAULT NDS32_CONFIG_FPU_2 -+ -+#define TARGET_LMWSMW_OPT_AUTO \ -+ (flag_lmwsmw_cost == LMWSMW_OPT_AUTO) -+ -+#define TARGET_LMWSMW_OPT_SIZE \ -+ (flag_lmwsmw_cost == LMWSMW_OPT_SIZE) -+ -+#define TARGET_LMWSMW_OPT_SPEED \ -+ (flag_lmwsmw_cost == LMWSMW_OPT_SPEED) -+ -+#define TARGET_LMWSMW_OPT_ALL \ -+ (flag_lmwsmw_cost == LMWSMW_OPT_ALL) -+ -+/* ------------------------------------------------------------------------ */ -+ -+#ifdef TARGET_DEFAULT_RELAX -+# define NDS32_RELAX_SPEC " %{!mno-relax:--relax}" -+#else -+# define NDS32_RELAX_SPEC " %{mrelax:--relax}" -+#endif -+ -+#ifdef TARGET_OS_DEFAULT_IFC -+# define NDS32_IFC_SPEC " %{Os3|Os|mifc:%{!mno-ifc:--mifc}}" -+#else -+# define NDS32_IFC_SPEC " %{mifc:--mifc}" -+#endif -+#define NDS32_IFC_V3M_PLUS_SPEC " %{march=v3m+:%{Os3|Os|mifc:%{!mno-ifc:-mifc}}}" -+ -+#ifdef TARGET_OS_DEFAULT_EX9 -+# define NDS32_EX9_SPEC " %{Os3|Os|mex9:%{!mno-ex9:--mex9}}" -+#else -+# define NDS32_EX9_SPEC " %{mex9:--mex9}" -+#endif -+#define NDS32_EX9_V3M_PLUS_SPEC " %{march=v3m+:%{Os3|Os|mex9:%{!mno-ex9:-mex9}}}" -+ -+#ifdef TARGET_DEFAULT_EXT_DSP -+# define NDS32_EXT_DSP_SPEC " %{!mno-ext-dsp:-mext-dsp}" -+#else -+# define NDS32_EXT_DSP_SPEC "" -+#endif -+ -+#ifdef TARGET_DEFAULT_HWLOOP -+# define NDS32_HWLOOP_SPEC " %{!mno-ext-zol:-mext-zol}" -+#else -+# define NDS32_HWLOOP_SPEC "" -+#endif -+ -+#ifdef TARGET_DEFAULT_16BIT -+# define NDS32_16BIT_SPEC " %{!mno-16-bit:%{!mno-16bit:-m16bit}}" -+#else -+# define NDS32_16BIT_SPEC " %{!m16-bit:%{!m16bit:-mno-16bit}}" -+#endif - - /* ------------------------------------------------------------------------ */ - - /* Controlling the Compilation Driver. */ - -+#define DRIVER_SELF_SPECS \ -+ " %{mno-16bit|mno-16-bit:-mno-ifc -mno-ex9}" \ -+ NDS32_IFC_V3M_PLUS_SPEC \ -+ NDS32_EX9_V3M_PLUS_SPEC \ -+ NDS32_16BIT_SPEC -+ - #define OPTION_DEFAULT_SPECS \ -- {"arch", "%{!march=*:-march=%(VALUE)}" } -+ {"arch", " %{!march=*:-march=%(VALUE)}" \ -+ " %{march=v3f:%{!mfloat-abi=*:-mfloat-abi=hard}" \ -+ " %{!mno-ext-fpu-sp:%{!mext-fpu-sp:-mext-fpu-sp}}" \ -+ " %{!mno-ext-fpu-dp:%{!mext-fpu-dp:-mext-fpu-dp}}}" \ -+ " %{march=v3s:%{!mfloat-abi=*:-mfloat-abi=hard}" \ -+ " %{!mno-ext-fpu-sp:%{!mext-fpu-sp:-mext-fpu-sp}}}" }, \ -+ {"cpu", "%{!mcpu=*:-mcpu=%(VALUE)}" }, \ -+ {"memory_model", "%{!mmemory-model=*:-mmemory-model=%(VALUE)}"}, \ -+ {"float", "%{!mfloat-abi=*:-mfloat-abi=%(VALUE)}" } - - #define CC1_SPEC \ -- "" -+ " %{Os1:-Os -mno-ifc -mno-ex9;" \ -+ "Os2:-Os -minnermost-loop;" \ -+ "Os3:-Os}" \ -+ " %{ffast-math:%{!mno-soft-fp-arith-comm:-msoft-fp-arith-comm}}" \ -+ NDS32_EXT_DSP_SPEC \ -+ NDS32_HWLOOP_SPEC - - #define ASM_SPEC \ -- " %{mbig-endian:-EB} %{mlittle-endian:-EL}" -- --/* 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}" -+ " %{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}" \ -+ " %{mno-ext-fpu-mac:-mno-mac}" \ -+ " %{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}" \ -+ " %{mext-dsp:-mdsp-ext}" \ -+ " %{mext-zol:-mzol-ext}" \ -+ " %{O|O1|O2|O3|Ofast:-O1;:-Os}" - - /* The TARGET_BIG_ENDIAN_DEFAULT is defined if we - configure gcc with --target=nds32be-* setting. -@@ -422,7 +1067,11 @@ enum nds32_builtins - - /* 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=medium" -+#endif - - #define MULTILIB_DEFAULTS \ - { NDS32_ENDIAN_DEFAULT, NDS32_CMODEL_DEFAULT } -@@ -430,34 +1079,8 @@ enum nds32_builtins - - /* Run-time Target Specification. */ - --#define TARGET_CPU_CPP_BUILTINS() \ -- do \ -- { \ -- builtin_define ("__nds32__"); \ -- \ -- if (TARGET_ISA_V2) \ -- builtin_define ("__NDS32_ISA_V2__"); \ -- if (TARGET_ISA_V3) \ -- builtin_define ("__NDS32_ISA_V3__"); \ -- if (TARGET_ISA_V3M) \ -- builtin_define ("__NDS32_ISA_V3M__"); \ -- \ -- if (TARGET_BIG_ENDIAN) \ -- builtin_define ("__big_endian__"); \ -- if (TARGET_REDUCED_REGS) \ -- builtin_define ("__NDS32_REDUCED_REGS__"); \ -- if (TARGET_CMOV) \ -- builtin_define ("__NDS32_CMOV__"); \ -- if (TARGET_PERF_EXT) \ -- builtin_define ("__NDS32_PERF_EXT__"); \ -- if (TARGET_16_BIT) \ -- builtin_define ("__NDS32_16_BIT__"); \ -- if (TARGET_GP_DIRECT) \ -- builtin_define ("__NDS32_GP_DIRECT__"); \ -- \ -- builtin_assert ("cpu=nds32"); \ -- builtin_assert ("machine=nds32"); \ -- } while (0) -+#define TARGET_CPU_CPP_BUILTINS() \ -+ nds32_cpu_cpp_builtins (pfile) - - - /* Defining Data Structures for Per-function Information. */ -@@ -487,10 +1110,20 @@ enum nds32_builtins - - #define STACK_BOUNDARY 64 - --#define FUNCTION_BOUNDARY 32 -+#define FUNCTION_BOUNDARY \ -+ ((NDS32_ALIGN_P () || TARGET_ALIGN_FUNCTION) ? (TARGET_PIPELINE_PANTHER ? 64 : 32) : 16) - - #define BIGGEST_ALIGNMENT 64 - -+#define DATA_ALIGNMENT(constant, basic_align) \ -+ nds32_data_alignment (constant, basic_align) -+ -+#define CONSTANT_ALIGNMENT(constant, basic_align) \ -+ nds32_constant_alignment (constant, basic_align) -+ -+#define LOCAL_ALIGNMENT(type, basic_align) \ -+ nds32_local_alignment (type, basic_align) -+ - #define EMPTY_FIELD_BOUNDARY 32 - - #define STRUCTURE_SIZE_BOUNDARY 8 -@@ -515,8 +1148,8 @@ enum nds32_builtins - - #define SIZE_TYPE "long unsigned int" - #define PTRDIFF_TYPE "long int" --#define WCHAR_TYPE "short unsigned int" --#define WCHAR_TYPE_SIZE 16 -+#define WCHAR_TYPE "unsigned int" -+#define WCHAR_TYPE_SIZE 32 - - - /* Register Usage. */ -@@ -526,7 +1159,7 @@ enum nds32_builtins - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. */ --#define FIRST_PSEUDO_REGISTER 34 -+#define FIRST_PSEUDO_REGISTER 101 - - /* An initializer that says which registers are used for fixed - purposes all throughout the compiled code and are therefore -@@ -537,24 +1170,38 @@ enum nds32_builtins - $r30 : $lp - $r31 : $sp - -- caller-save registers: $r0 ~ $r5, $r16 ~ $r23 -- callee-save registers: $r6 ~ $r10, $r11 ~ $r14 -+ caller-save registers: $r0 ~ $r5, $r16 ~ $r23, $fs0 ~ $fs5, $fs22 ~ $fs47 -+ callee-save registers: $r6 ~ $r10, $r11 ~ $r14, $fs6 ~ $fs21, $fs48 ~ $fs63 - - reserved for assembler : $r15 - reserved for other use : $r24, $r25, $r26, $r27 */ --#define FIXED_REGISTERS \ --{ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \ -- 0, 0, 0, 0, 0, 0, 0, 0, \ -- /* r8 r9 r10 r11 r12 r13 r14 r15 */ \ -- 0, 0, 0, 0, 0, 0, 0, 1, \ -- /* r16 r17 r18 r19 r20 r21 r22 r23 */ \ -- 0, 0, 0, 0, 0, 0, 0, 0, \ -- /* r24 r25 r26 r27 r28 r29 r30 r31 */ \ -- 1, 1, 1, 1, 0, 1, 0, 1, \ -- /* ARG_POINTER:32 */ \ -- 1, \ -- /* FRAME_POINTER:33 */ \ -- 1 \ -+#define FIXED_REGISTERS \ -+{ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \ -+ 0, 0, 0, 0, 0, 0, 0, 0, \ -+ /* r8 r9 r10 r11 r12 r13 r14 r15 */ \ -+ 0, 0, 0, 0, 0, 0, 0, 0, \ -+ /* r16 r17 r18 r19 r20 r21 r22 r23 */ \ -+ 0, 0, 0, 0, 0, 0, 0, 0, \ -+ /* r24 r25 r26 r27 r28 r29 r30 r31 */ \ -+ 0, 0, 1, 1, 0, 1, 0, 1, \ -+ /* AP FP fs0 fs1 fs2 fs3 fs4 fs5 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fs6 fs7 fs8 fs9 fs10 fs11 fs12 fs13 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fs14 fs15 fs16 fs17 fs18 fs19 fs20 fs21 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fs22 fs23 fs24 fs25 fs26 fs27 fs28 fs29 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fs30 fs31 fd16 fd17 fd18 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fd19 fd20 fd21 fd22 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fd23 fd24 fd25 fd26 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fd27 fd28 fd29 fd30 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fd31 LB LE LC */ \ -+ 1, 1, 1, 1, 1 \ - } - - /* Identifies the registers that are not available for -@@ -563,35 +1210,59 @@ enum nds32_builtins - - 0 : callee-save registers - 1 : caller-save registers */ --#define CALL_USED_REGISTERS \ --{ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \ -- 1, 1, 1, 1, 1, 1, 0, 0, \ -- /* r8 r9 r10 r11 r12 r13 r14 r15 */ \ -- 0, 0, 0, 0, 0, 0, 0, 1, \ -- /* r16 r17 r18 r19 r20 r21 r22 r23 */ \ -- 1, 1, 1, 1, 1, 1, 1, 1, \ -- /* r24 r25 r26 r27 r28 r29 r30 r31 */ \ -- 1, 1, 1, 1, 0, 1, 0, 1, \ -- /* ARG_POINTER:32 */ \ -- 1, \ -- /* FRAME_POINTER:33 */ \ -- 1 \ -+#define CALL_USED_REGISTERS \ -+{ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \ -+ 1, 1, 1, 1, 1, 1, 0, 0, \ -+ /* r8 r9 r10 r11 r12 r13 r14 r15 */ \ -+ 0, 0, 0, 0, 0, 0, 0, 1, \ -+ /* r16 r17 r18 r19 r20 r21 r22 r23 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* r24 r25 r26 r27 r28 r29 r30 r31 */ \ -+ 1, 1, 1, 1, 0, 1, 0, 1, \ -+ /* AP FP fs0 fs1 fs2 fs3 fs4 fs5 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fs6 fs7 fs8 fs9 fs10 fs11 fs12 fs13 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fs14 fs15 fs16 fs17 fs18 fs19 fs20 fs21 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fs22 fs23 fs24 fs25 fs26 fs27 fs28 fs29 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fs30 fs31 fd16 fd17 fd18 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fd19 fd20 fd21 fd22 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fd23 fd24 fd25 fd26 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fd27 fd28 fd29 fd30 */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, \ -+ /* fd31 LB LE LC */ \ -+ 1, 1, 1, 1, 1 \ - } - - /* In nds32 target, we have three levels of registers: - LOW_COST_REGS : $r0 ~ $r7 - MIDDLE_COST_REGS : $r8 ~ $r11, $r16 ~ $r19 - HIGH_COST_REGS : $r12 ~ $r14, $r20 ~ $r31 */ --#define REG_ALLOC_ORDER \ --{ \ -- 0, 1, 2, 3, 4, 5, 6, 7, \ -- 8, 9, 10, 11, 16, 17, 18, 19, \ -- 12, 13, 14, 15, 20, 21, 22, 23, \ -- 24, 25, 26, 27, 28, 29, 30, 31, \ -- 32, \ -- 33 \ -+#define REG_ALLOC_ORDER \ -+{ 0, 1, 2, 3, 4, 5, 6, 7, \ -+ 16, 17, 18, 19, 9, 10, 11, 12, \ -+ 13, 14, 8, 15, 20, 21, 22, 23, \ -+ 24, 25, 26, 27, 28, 29, 30, 31, \ -+ 32, 33, 34, 35, 36, 37, 38, 39, \ -+ 40, 41, 42, 43, 44, 45, 46, 47, \ -+ 48, 49, 50, 51, 52, 53, 54, 55, \ -+ 56, 57, 58, 59, 60, 61, 62, 63, \ -+ 64, 65, 66, 67, 68, 69, 70, 71, \ -+ 72, 73, 74, 75, 76, 77, 78, 79, \ -+ 80, 81, 82, 83, 84, 85, 86, 87, \ -+ 88, 89, 90, 91, 92, 93, 94, 95, \ -+ 96, 97, 98, 99, 100, \ - } - -+/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order -+ to be rearranged based on optimizing for speed or size. */ -+#define ADJUST_REG_ALLOC_ORDER nds32_adjust_reg_alloc_order () -+ - /* Tell IRA to use the order we define rather than messing it up with its - own cost calculations. */ - #define HONOR_REG_ALLOC_ORDER optimize_size -@@ -609,11 +1280,7 @@ enum nds32_builtins - Define this macro to return nonzero in as many cases as possible - since doing so will allow GCC to perform better register allocation. - We can use general registers to tie QI/HI/SI modes together. */ --#define MODES_TIEABLE_P(mode1, mode2) \ -- (GET_MODE_CLASS (mode1) == MODE_INT \ -- && GET_MODE_CLASS (mode2) == MODE_INT \ -- && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD \ -- && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD) -+#define MODES_TIEABLE_P(mode1, mode2) nds32_modes_tieable_p (mode1, mode2) - - - /* Register Classes. */ -@@ -628,13 +1295,18 @@ enum nds32_builtins - enum reg_class - { - NO_REGS, -+ R5_REG, -+ R8_REG, - R15_TA_REG, - STACK_REG, -+ FRAME_POINTER_REG, - LOW_REGS, - MIDDLE_REGS, - HIGH_REGS, - GENERAL_REGS, - FRAME_REGS, -+ FP_REGS, -+ LOOP_REGS, - ALL_REGS, - LIM_REG_CLASSES - }; -@@ -644,27 +1316,50 @@ enum reg_class - #define REG_CLASS_NAMES \ - { \ - "NO_REGS", \ -+ "R5_REG", \ -+ "R8_REG", \ - "R15_TA_REG", \ - "STACK_REG", \ -+ "FRAME_POINTER_REG", \ - "LOW_REGS", \ - "MIDDLE_REGS", \ - "HIGH_REGS", \ - "GENERAL_REGS", \ - "FRAME_REGS", \ -+ "FP_REGS", \ -+ "LOOP_REGS", \ - "ALL_REGS" \ - } - - #define REG_CLASS_CONTENTS \ --{ \ -- {0x00000000, 0x00000000}, /* NO_REGS : */ \ -- {0x00008000, 0x00000000}, /* R15_TA_REG : 15 */ \ -- {0x80000000, 0x00000000}, /* STACK_REG : 31 */ \ -- {0x000000ff, 0x00000000}, /* LOW_REGS : 0-7 */ \ -- {0x000f0fff, 0x00000000}, /* MIDDLE_REGS : 0-11, 16-19 */ \ -- {0xfff07000, 0x00000000}, /* HIGH_REGS : 12-14, 20-31 */ \ -- {0xffffffff, 0x00000000}, /* GENERAL_REGS: 0-31 */ \ -- {0x00000000, 0x00000003}, /* FRAME_REGS : 32, 33 */ \ -- {0xffffffff, 0x00000003} /* ALL_REGS : 0-31, 32, 33 */ \ -+{ /* NO_REGS */ \ -+ {0x00000000, 0x00000000, 0x00000000, 0x00000000}, \ -+ /* R5_REG : 5 */ \ -+ {0x00000020, 0x00000000, 0x00000000, 0x00000000}, \ -+ /* R8_REG : 8 */ \ -+ {0x00000100, 0x00000000, 0x00000000, 0x00000000}, \ -+ /* R15_TA_REG : 15 */ \ -+ {0x00008000, 0x00000000, 0x00000000, 0x00000000}, \ -+ /* STACK_REG : 31 */ \ -+ {0x80000000, 0x00000000, 0x00000000, 0x00000000}, \ -+ /* FRAME_POINTER_REG : 28 */ \ -+ {0x10000000, 0x00000000, 0x00000000, 0x00000000}, \ -+ /* LOW_REGS : 0-7 */ \ -+ {0x000000ff, 0x00000000, 0x00000000, 0x00000000}, \ -+ /* MIDDLE_REGS : 0-11, 16-19 */ \ -+ {0x000f0fff, 0x00000000, 0x00000000, 0x00000000}, \ -+ /* HIGH_REGS : 12-14, 20-31 */ \ -+ {0xfff07000, 0x00000000, 0x00000000, 0x00000000}, \ -+ /* GENERAL_REGS : 0-31 */ \ -+ {0xffffffff, 0x00000000, 0x00000000, 0x00000000}, \ -+ /* FRAME_REGS : 32, 33 */ \ -+ {0x00000000, 0x00000003, 0x00000000, 0x00000000}, \ -+ /* FP_REGS : 34-98 */ \ -+ {0x00000000, 0xfffffffc, 0xffffffff, 0x00000003}, \ -+ /* LOOP_REGS 99-101 */ \ -+ {0x00000000, 0x00000000, 0x00000000, 0x0000001c}, \ -+ /* ALL_REGS : 0-101 */ \ -+ {0xffffffff, 0xffffffff, 0xffffffff, 0x0000001f} \ - } - - #define REGNO_REG_CLASS(regno) nds32_regno_reg_class (regno) -@@ -672,13 +1367,18 @@ enum reg_class - #define BASE_REG_CLASS GENERAL_REGS - #define INDEX_REG_CLASS GENERAL_REGS - -+#define TEST_REGNO(R, TEST, VALUE) \ -+ ((R TEST VALUE) || ((unsigned) reg_renumber[R] TEST VALUE)) -+ - /* Return nonzero if it is suitable for use as a - base register in operand addresses. - So far, we return nonzero only if "num" is a hard reg - of the suitable class or a pseudo register which is - allocated to a suitable hard reg. */ - #define REGNO_OK_FOR_BASE_P(num) \ -- ((num) < 32 || (unsigned) reg_renumber[num] < 32) -+ (TEST_REGNO (num, <, 32) \ -+ || TEST_REGNO (num, ==, FRAME_POINTER_REGNUM) \ -+ || TEST_REGNO (num, ==, ARG_POINTER_REGNUM)) - - /* Return nonzero if it is suitable for use as a - index register in operand addresses. -@@ -688,7 +1388,15 @@ enum reg_class - The difference between an index register and a base register is that - the index register may be scaled. */ - #define REGNO_OK_FOR_INDEX_P(num) \ -- ((num) < 32 || (unsigned) reg_renumber[num] < 32) -+ (TEST_REGNO (num, <, 32) \ -+ || TEST_REGNO (num, ==, FRAME_POINTER_REGNUM) \ -+ || TEST_REGNO (num, ==, ARG_POINTER_REGNUM)) -+ -+/* Don't spill double-precision register to two singal-precision registers */ -+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ -+ ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) \ -+ && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ -+ ? reg_classes_intersect_p (CLASS, FP_REGS) : 0) - - - /* Obsolete Macros for Defining Constraints. */ -@@ -707,6 +1415,11 @@ enum reg_class - #define FIRST_PARM_OFFSET(fundecl) \ - (NDS32_DOUBLE_WORD_ALIGN_P (crtl->args.pretend_args_size) ? 0 : 4) - -+/* A C expression whose value is RTL representing the address in a stack frame -+ where the pointer to the caller's frame is stored. */ -+#define DYNAMIC_CHAIN_ADDRESS(frameaddr) \ -+ nds32_dynamic_chain_address (frameaddr) -+ - #define RETURN_ADDR_RTX(count, frameaddr) \ - nds32_return_addr_rtx (count, frameaddr) - -@@ -718,6 +1431,15 @@ enum reg_class - #define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LP_REGNUM) - #define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LP_REGNUM) - -+/* Use $r0 $r1 to pass exception handling information. */ -+#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? (N) : INVALID_REGNUM) -+/* The register $r2 that represents a location in which to store a stack -+ adjustment to be applied before function return. -+ This is used to unwind the stack to an exception handler's call frame. */ -+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 2) -+ -+#define DBX_REGISTER_NUMBER(REGNO) nds32_dbx_register_number (REGNO) -+ - #define STACK_POINTER_REGNUM SP_REGNUM - - #define FRAME_POINTER_REGNUM 33 -@@ -746,12 +1468,11 @@ enum reg_class - #define INIT_CUMULATIVE_ARGS(cum, fntype, libname, fndecl, n_named_args) \ - nds32_init_cumulative_args (&cum, fntype, libname, fndecl, n_named_args) - --/* The REGNO is an unsigned integer but NDS32_GPR_ARG_FIRST_REGNUM may be 0. -- We better cast REGNO into signed integer so that we can avoid -- 'comparison of unsigned expression >= 0 is always true' warning. */ --#define FUNCTION_ARG_REGNO_P(regno) \ -- (((int) regno - NDS32_GPR_ARG_FIRST_REGNUM >= 0) \ -- && ((int) regno - NDS32_GPR_ARG_FIRST_REGNUM < NDS32_MAX_GPR_REGS_FOR_ARGS)) -+#define FUNCTION_ARG_REGNO_P(regno) \ -+ (IN_RANGE ((regno), NDS32_FIRST_GPR_REGNUM, NDS32_MAX_GPR_REGS_FOR_ARGS - 1) \ -+ || ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) \ -+ && IN_RANGE ((regno), NDS32_FPR_ARG_FIRST_REGNUM, \ -+ NDS32_FIRST_FPR_REGNUM + NDS32_MAX_FPR_REGS_FOR_ARGS - 1))) - - #define DEFAULT_PCC_STRUCT_RETURN 0 - -@@ -763,7 +1484,15 @@ enum reg_class - #define EXIT_IGNORE_STACK 1 - - #define FUNCTION_PROFILER(file, labelno) \ -- fprintf (file, "/* profiler %d */", (labelno)) -+ fprintf (file, "/* profiler %d */\n", (labelno)) -+ -+#define PROFILE_HOOK(LABEL) \ -+ { \ -+ rtx fun, lp; \ -+ lp = get_hard_reg_initial_val (Pmode, LP_REGNUM); \ -+ fun = gen_rtx_SYMBOL_REF (Pmode, "_mcount"); \ -+ emit_library_call (fun, LCT_NORMAL, VOIDmode, 1, lp, Pmode); \ -+ } - - - /* Implementing the Varargs Macros. */ -@@ -780,13 +1509,13 @@ enum reg_class - The trampoline code for nds32 target must contains following parts: - - 1. instructions (4 * 4 = 16 bytes): -- get $pc first -- load chain_value to static chain register via $pc -- load nested function address to $r15 via $pc -- jump to desired nested function via $r15 -+ get $pc first -+ load chain_value to static chain register via $pc -+ load nested function address to $r15 via $pc -+ jump to desired nested function via $r15 - 2. data (4 * 2 = 8 bytes): -- chain_value -- nested function address -+ chain_value -+ nested function address - - Please check nds32.c implementation for more information. */ - #define TRAMPOLINE_SIZE 24 -@@ -811,9 +1540,22 @@ enum reg_class - /* We have "LW.bi Rt, [Ra], Rb" instruction form. */ - #define HAVE_POST_MODIFY_REG 1 - --#define CONSTANT_ADDRESS_P(x) (CONSTANT_P (x) && GET_CODE (x) != CONST_DOUBLE) -+#define USE_LOAD_POST_INCREMENT(mode) \ -+ (GET_MODE_SIZE (mode) <= GET_MODE_SIZE(DImode)) -+#define USE_LOAD_POST_DECREMENT(mode) \ -+ (GET_MODE_SIZE (mode) <= GET_MODE_SIZE(DImode)) -+#define USE_STORE_POST_DECREMENT(mode) USE_LOAD_POST_DECREMENT(mode) -+#define USE_STORE_POST_INCREMENT(mode) USE_LOAD_POST_INCREMENT(mode) -+ -+#define CONSTANT_ADDRESS_P(x) \ -+ (CONSTANT_P (x) && memory_address_p (GET_MODE (x), x)) - --#define MAX_REGS_PER_ADDRESS 2 -+/* CONST_DOUBLE is legal without TARGET_FPU in legitimate_constant_p. -+ Therefore, let it be a legal PIC operand and split it later.*/ -+#define LEGITIMATE_PIC_OPERAND_P(x) \ -+ (GET_CODE (x) != CONST_DOUBLE || !(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)) -+ -+#define MAX_REGS_PER_ADDRESS 3 - - - /* Anchored Addresses. */ -@@ -827,7 +1569,11 @@ enum reg_class - /* A C expression for the cost of a branch instruction. - A value of 1 is the default; - other values are interpreted relative to that. */ --#define BRANCH_COST(speed_p, predictable_p) ((speed_p) ? 2 : 0) -+#define BRANCH_COST(speed_p, predictable_p) ((speed_p) ? 2 : 1) -+ -+/* Override BRANCH_COST heuristic which empirically produces worse -+ performance for removing short circuiting from the logical ops. */ -+#define LOGICAL_OP_NON_SHORT_CIRCUIT 0 - - #define SLOW_BYTE_ACCESS 1 - -@@ -857,12 +1603,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" - -@@ -877,14 +1628,77 @@ enum reg_class - - #define LOCAL_LABEL_PREFIX "." - --#define REGISTER_NAMES \ --{ \ -- "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", \ -+#define REGISTER_NAMES \ -+{ "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", \ - "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$ta", \ - "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", \ - "$r24", "$r25", "$r26", "$r27", "$fp", "$gp", "$lp", "$sp", \ -- "$AP", \ -- "$SFP" \ -+ "$AP", "$SFP", "$fs0", "$fs1", "$fs2", "$fs3", "$fs4", "$fs5", \ -+ "$fs6", "$fs7", "$fs8", "$fs9", "$fs10","$fs11","$fs12","$fs13",\ -+ "$fs14","$fs15","$fs16","$fs17","$fs18","$fs19","$fs20","$fs21",\ -+ "$fs22","$fs23","$fs24","$fs25","$fs26","$fs27","$fs28","$fs29",\ -+ "$fs30","$fs31","$fs32","$fs33","$fs34","$fs35","$fs36","$fs37",\ -+ "$fs38","$fs39","$fs40","$fs41","$fs42","$fs43","$fs44","$fs45",\ -+ "$fs46","$fs47","$fs48","$fs49","$fs50","$fs51","$fs52","$fs53",\ -+ "$fs54","$fs55","$fs56","$fs57","$fs58","$fs59","$fs60","$fs61",\ -+ "$fs62","$fs63", "LB", "LE", "LC" \ -+} -+ -+#define ADDITIONAL_REGISTER_NAMES \ -+{ \ -+ {"$r15", 15}, \ -+ {"$r28", 28}, {"$r29", 29}, {"$r30", 30}, {"$r31", 31}, \ -+ {"$a0", 0}, {"$a1", 1}, {"$a2", 2}, \ -+ {"$a3", 3}, {"$a4", 4}, {"$a5", 5}, \ -+ {"$s0", 6}, {"$s1", 7}, {"$s2", 8}, {"$s3", 9}, \ -+ {"$s4", 10}, {"$s5", 11}, {"$s6", 12}, {"$s7", 13}, \ -+ {"$s8", 14}, \ -+ {"$t0", 16}, {"$t1", 17}, {"$t2", 18}, {"$t3", 19}, \ -+ {"$t4", 20}, {"$t5", 21}, {"$t6", 22}, {"$t7", 23}, \ -+ {"$t8", 24}, {"$t9", 25}, \ -+ {"$p0", 26}, {"$p1", 27}, \ -+ {"$h0", 0}, {"$h1", 1}, {"$h2", 2}, {"$h3", 3}, \ -+ {"$h4", 4}, {"$h5", 5}, {"$h6", 6}, {"$h7", 7}, \ -+ {"$h8", 8}, {"$h9", 9}, {"$h10", 10}, {"$h11", 11}, \ -+ {"$h12", 16}, {"$h13", 17}, {"$h14", 18}, {"$h15", 19}, \ -+ {"$o0", 0}, {"$o1", 1}, {"$o2", 2}, {"$o3", 3}, \ -+ {"$o4", 4}, {"$o5", 5}, {"$o6", 6}, {"$o7", 7}, \ -+} -+ -+#define OVERLAPPING_REGISTER_NAMES \ -+{ \ -+ {"$fd0", NDS32_FIRST_FPR_REGNUM + 0, 2}, \ -+ {"$fd1", NDS32_FIRST_FPR_REGNUM + 2, 2}, \ -+ {"$fd2", NDS32_FIRST_FPR_REGNUM + 4, 2}, \ -+ {"$fd3", NDS32_FIRST_FPR_REGNUM + 6, 2}, \ -+ {"$fd4", NDS32_FIRST_FPR_REGNUM + 8, 2}, \ -+ {"$fd5", NDS32_FIRST_FPR_REGNUM + 10, 2}, \ -+ {"$fd6", NDS32_FIRST_FPR_REGNUM + 12, 2}, \ -+ {"$fd7", NDS32_FIRST_FPR_REGNUM + 14, 2}, \ -+ {"$fd8", NDS32_FIRST_FPR_REGNUM + 16, 2}, \ -+ {"$fd9", NDS32_FIRST_FPR_REGNUM + 18, 2}, \ -+ {"$fd10", NDS32_FIRST_FPR_REGNUM + 20, 2}, \ -+ {"$fd11", NDS32_FIRST_FPR_REGNUM + 22, 2}, \ -+ {"$fd12", NDS32_FIRST_FPR_REGNUM + 24, 2}, \ -+ {"$fd13", NDS32_FIRST_FPR_REGNUM + 26, 2}, \ -+ {"$fd14", NDS32_FIRST_FPR_REGNUM + 28, 2}, \ -+ {"$fd15", NDS32_FIRST_FPR_REGNUM + 30, 2}, \ -+ {"$fd16", NDS32_FIRST_FPR_REGNUM + 32, 2}, \ -+ {"$fd17", NDS32_FIRST_FPR_REGNUM + 34, 2}, \ -+ {"$fd18", NDS32_FIRST_FPR_REGNUM + 36, 2}, \ -+ {"$fd19", NDS32_FIRST_FPR_REGNUM + 38, 2}, \ -+ {"$fd20", NDS32_FIRST_FPR_REGNUM + 40, 2}, \ -+ {"$fd21", NDS32_FIRST_FPR_REGNUM + 42, 2}, \ -+ {"$fd22", NDS32_FIRST_FPR_REGNUM + 44, 2}, \ -+ {"$fd23", NDS32_FIRST_FPR_REGNUM + 46, 2}, \ -+ {"$fd24", NDS32_FIRST_FPR_REGNUM + 48, 2}, \ -+ {"$fd25", NDS32_FIRST_FPR_REGNUM + 50, 2}, \ -+ {"$fd26", NDS32_FIRST_FPR_REGNUM + 52, 2}, \ -+ {"$fd27", NDS32_FIRST_FPR_REGNUM + 54, 2}, \ -+ {"$fd28", NDS32_FIRST_FPR_REGNUM + 56, 2}, \ -+ {"$fd29", NDS32_FIRST_FPR_REGNUM + 58, 2}, \ -+ {"$fd30", NDS32_FIRST_FPR_REGNUM + 60, 2}, \ -+ {"$fd31", NDS32_FIRST_FPR_REGNUM + 62, 2}, \ - } - - /* Output normal jump table entry. */ -@@ -896,19 +1710,19 @@ enum reg_class - do \ - { \ - switch (GET_MODE (body)) \ -- { \ -- case QImode: \ -- asm_fprintf (stream, "\t.byte\t.L%d-.L%d\n", value, rel); \ -- break; \ -- case HImode: \ -- asm_fprintf (stream, "\t.short\t.L%d-.L%d\n", value, rel); \ -- break; \ -- case SImode: \ -- asm_fprintf (stream, "\t.word\t.L%d-.L%d\n", value, rel); \ -- break; \ -- default: \ -- gcc_unreachable(); \ -- } \ -+ { \ -+ case QImode: \ -+ asm_fprintf (stream, "\t.byte\t.L%d-.L%d\n", value, rel); \ -+ break; \ -+ case HImode: \ -+ asm_fprintf (stream, "\t.short\t.L%d-.L%d\n", value, rel); \ -+ break; \ -+ case SImode: \ -+ asm_fprintf (stream, "\t.word\t.L%d-.L%d\n", value, rel); \ -+ break; \ -+ default: \ -+ gcc_unreachable(); \ -+ } \ - } while (0) - - /* We have to undef it first because elfos.h formerly define it -@@ -925,10 +1739,10 @@ enum reg_class - do \ - { \ - /* Because our jump table is in text section, \ -- we need to make sure 2-byte alignment after \ -- the jump table for instructions fetch. */ \ -+ we need to make sure 2-byte alignment after \ -+ the jump table for instructions fetch. */ \ - if (GET_MODE (PATTERN (table)) == QImode) \ -- ASM_OUTPUT_ALIGN (stream, 1); \ -+ ASM_OUTPUT_ALIGN (stream, 1); \ - asm_fprintf (stream, "\t! Jump Table End\n"); \ - } while (0) - -@@ -992,9 +1806,7 @@ enum reg_class - /* Return the preferred mode for and addr_diff_vec when the mininum - and maximum offset are known. */ - #define CASE_VECTOR_SHORTEN_MODE(min_offset, max_offset, body) \ -- ((min_offset < 0 || max_offset >= 0x2000 ) ? SImode \ -- : (max_offset >= 100) ? HImode \ -- : QImode) -+ nds32_case_vector_shorten_mode (min_offset, max_offset, body) - - /* Generate pc relative jump table when -fpic or -Os. */ - #define CASE_VECTOR_PC_RELATIVE (flag_pic || optimize_size) -@@ -1027,6 +1839,11 @@ enum reg_class - when the condition is true. */ - #define STORE_FLAG_VALUE 1 - -+/* A C expression that indicates whether the architecture defines a value for -+ clz or ctz with a zero operand. In nds32 clz for 0 result 32 is defined -+ in ISA spec */ -+#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1) -+ - /* An alias for the machine mode for pointers. */ - #define Pmode SImode - -diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md -index 5cdd8b2..557c466 100644 ---- a/gcc/config/nds32/nds32.md -+++ b/gcc/config/nds32/nds32.md -@@ -46,58 +46,144 @@ - ;; Include DImode/DFmode operations. - (include "nds32-doubleword.md") - -+;; Include floating-point patterns. -+(include "nds32-fpu.md") -+ - ;; Include peephole patterns. - (include "nds32-peephole2.md") - - -+;; ------------------------------------------------------------------------ -+ -+;; CPU pipeline model. -+(define_attr "pipeline_model" "n7,n8,e8,n9,n10,graywolf,n13,panther,simple" -+ (const -+ (cond [(match_test "nds32_cpu_option == CPU_N7") (const_string "n7") -+ (match_test "nds32_cpu_option == CPU_N6 || nds32_cpu_option == CPU_N8") (const_string "n8") -+ (match_test "nds32_cpu_option == CPU_E8") (const_string "e8") -+ (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_PANTHER") (const_string "panther") -+ (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,move,load,store,alu,compare,branch,call,misc" -+ "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,\ -+ dalu,dalu64,daluround,dcmp,dclip,dmul,dmac,dinsb,dpack,dbpick,dwext" - (const_string "unknown")) - -+;; Insn sub-type -+(define_attr "subtype" -+ "simple,shift,saturation" -+ (const_string "simple")) - - ;; Length, in bytes, default is 4-bytes. - (define_attr "length" "" (const_int 4)) - -+;; Indicate the amount of micro instructions. -+(define_attr "combo" -+ "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25" -+ (const_string "1")) -+ -+;; Insn in which feature set, it is used to enable/disable insn alternatives. -+;; v1 : Baseline Instructions -+;; v2 : Baseline Version 2 Instructions -+;; v3m : Baseline Version 3m Instructions -+;; v3 : Baseline Version 3 Instructions -+;; pe1 : Performance Extension Instructions -+;; pe2 : Performance Extension Version 2 Instructions -+;; se : String Extension instructions -+(define_attr "feature" -+ "v1,v2,v3m,v3,pe1,pe2,se,fpu" -+ (const_string "v1")) - - ;; Enabled, which is used to enable/disable insn alternatives. - ;; Note that we use length and TARGET_16_BIT here as criteria. --;; If the instruction pattern already check TARGET_16_BIT to --;; determine the length by itself, its enabled attribute should be --;; always 1 to avoid the conflict with the settings here. --(define_attr "enabled" "" -- (cond [(and (eq_attr "length" "2") -- (match_test "!TARGET_16_BIT")) -- (const_int 0)] -- (const_int 1))) -+;; If the instruction pattern already check TARGET_16_BIT to determine -+;; the length by itself, its enabled attribute should be customized to -+;; avoid the conflict between length attribute and this default setting. -+(define_attr "enabled" "no,yes" -+ (if_then_else -+ (and (eq_attr "length" "2") -+ (match_test "!TARGET_16_BIT")) -+ (const_string "no") -+ (cond [(eq_attr "feature" "v1") (const_string "yes") -+ (eq_attr "feature" "v2") (if_then_else (match_test "TARGET_ISA_V2 || TARGET_ISA_V3 || TARGET_ISA_V3M") -+ (const_string "yes") -+ (const_string "no")) -+ (eq_attr "feature" "v3") (if_then_else (match_test "TARGET_ISA_V3") -+ (const_string "yes") -+ (const_string "no")) -+ (eq_attr "feature" "v3m") (if_then_else (match_test "TARGET_ISA_V3 || TARGET_ISA_V3M") -+ (const_string "yes") -+ (const_string "no")) -+ (eq_attr "feature" "pe1") (if_then_else (match_test "TARGET_EXT_PERF") -+ (const_string "yes") -+ (const_string "no")) -+ (eq_attr "feature" "pe2") (if_then_else (match_test "TARGET_EXT_PERF2") -+ (const_string "yes") -+ (const_string "no")) -+ (eq_attr "feature" "se") (if_then_else (match_test "TARGET_EXT_STRING") -+ (const_string "yes") -+ (const_string "no")) -+ (eq_attr "feature" "fpu") (if_then_else (match_test "TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE") -+ (const_string "yes") -+ (const_string "no"))] -+ (const_string "yes")))) - - - ;; ---------------------------------------------------------------------------- - -+(include "nds32-dspext.md") - - ;; Move instructions. - - ;; For QImode and HImode, the immediate value can be fit in imm20s. - ;; So there is no need to split rtx for QI and HI patterns. - --(define_expand "movqi" -- [(set (match_operand:QI 0 "general_operand" "") -- (match_operand:QI 1 "general_operand" ""))] -+(define_expand "mov" -+ [(set (match_operand:QIHI 0 "general_operand" "") -+ (match_operand:QIHI 1 "general_operand" ""))] - "" - { - /* Need to force register if mem <- !reg. */ - if (MEM_P (operands[0]) && !REG_P (operands[1])) -- operands[1] = force_reg (QImode, operands[1]); -+ operands[1] = force_reg (mode, operands[1]); -+ -+ if (MEM_P (operands[1]) && optimize > 0) -+ { -+ rtx reg = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_zero_extendsi2 (reg, operands[1])); -+ operands[1] = gen_lowpart (mode, reg); -+ } - }) - --(define_expand "movhi" -- [(set (match_operand:HI 0 "general_operand" "") -- (match_operand:HI 1 "general_operand" ""))] -+(define_expand "movmisalign" -+ [(set (match_operand:SIDI 0 "general_operand" "") -+ (match_operand:SIDI 1 "general_operand" ""))] - "" - { -- /* Need to force register if mem <- !reg. */ -+ rtx addr; - if (MEM_P (operands[0]) && !REG_P (operands[1])) -- operands[1] = force_reg (HImode, 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 "movsi" -@@ -130,12 +216,33 @@ - low12_int)); - DONE; - } -+ -+ if (REG_P (operands[0]) && 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" -- [(set (match_operand:QIHISI 0 "nonimmediate_operand" "=r, r, U45, U33, U37, U45, m, l, l, l, d, r, d, r, r, r") -- (match_operand:QIHISI 1 "nds32_move_operand" " r, r, l, l, l, d, r, U45, U33, U37, U45, m, Ip05, Is05, Is20, Ihig"))] -- "" -+ [(set (match_operand:QIHISI 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, A") -+ (match_operand:QIHISI 1 "nds32_move_operand" " r, r, l, l, l, d, r,U45,U33,U37,U45,Ufe, m,Ip05, Is05, Is20, Ihig, *f, r, *f, Q, *f, r"))] -+ "register_operand(operands[0], mode) -+ || register_operand(operands[1], mode)" - { - switch (which_alternative) - { -@@ -154,37 +261,54 @@ - case 8: - case 9: - case 10: -- return nds32_output_16bit_load (operands, ); - case 11: -- return nds32_output_32bit_load (operands, ); -+ return nds32_output_16bit_load (operands, ); - case 12: -- return "movpi45\t%0, %1"; -+ return nds32_output_32bit_load (operands, ); - case 13: -- return "movi55\t%0, %1"; -+ return "movpi45\t%0, %1"; - case 14: -- return "movi\t%0, %1"; -+ 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); -+ case 22: -+ return "mtusr\t%1, %0"; - default: - gcc_unreachable (); - } - } -- [(set_attr "type" "alu,alu,store,store,store,store,store,load,load,load,load,load,alu,alu,alu,alu") -- (set_attr "length" " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 4, 2, 2, 4, 4")]) -+ [(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,alu") -+ (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, 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, v1")]) - - - ;; 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"))] -+(define_insn "move_addr" -+ [(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" "move") -+ [(set_attr "type" "alu") - (set_attr "length" "8")]) - - --(define_insn "*sethi" -+(define_insn "sethi" - [(set (match_operand:SI 0 "register_operand" "=r") - (high:SI (match_operand:SI 1 "nds32_symbolic_operand" " i")))] - "" -@@ -193,7 +317,7 @@ - (set_attr "length" "4")]) - - --(define_insn "*lo_sum" -+(define_insn "lo_sum" - [(set (match_operand:SI 0 "register_operand" "=r") - (lo_sum:SI (match_operand:SI 1 "register_operand" " r") - (match_operand:SI 2 "nds32_symbolic_operand" " i")))] -@@ -208,8 +332,8 @@ - ;; Zero extension instructions. - - (define_insn "zero_extendsi2" -- [(set (match_operand:SI 0 "register_operand" "=l, r, l, *r") -- (zero_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, U33, m")))] -+ [(set (match_operand:SI 0 "register_operand" "=l, r, l, *r") -+ (zero_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r,U33, m")))] - "" - { - switch (which_alternative) -@@ -245,7 +369,7 @@ - case 1: - return "se\t%0, %1"; - case 2: -- return nds32_output_32bit_load_s (operands, ); -+ return nds32_output_32bit_load_se (operands, ); - - default: - gcc_unreachable (); -@@ -256,25 +380,70 @@ - - - ;; ---------------------------------------------------------------------------- -+(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 "add3" -- [(set (match_operand:QIHISI 0 "register_operand" "= d, l, d, l, d, l, k, l, r, r") -- (plus:QIHISI (match_operand:QIHISI 1 "register_operand" "% 0, l, 0, l, 0, l, 0, k, r, r") -- (match_operand:QIHISI 2 "nds32_rimm15s_operand" " In05, In03, Iu05, Iu03, r, l, Is10, Iu06, Is15, r")))] -+(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")))] - "" - { - switch (which_alternative) - { - case 0: - /* addi Rt4,Rt4,-x ==> subi45 Rt4,x -- where 0 <= x <= 31 */ -+ where 0 <= x <= 31 */ - operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode); - return "subi45\t%0, %2"; - case 1: - /* addi Rt3,Ra3,-x ==> subi333 Rt3,Ra3,x -- where 0 <= x <= 7 */ -+ where 0 <= x <= 7 */ - operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode); - return "subi333\t%0, %1, %2"; - case 2: -@@ -298,19 +467,20 @@ - gcc_unreachable (); - } - } -- [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu") -- (set_attr "length" " 2, 2, 2, 2, 2, 2, 2, 2, 4, 4")]) -- --(define_insn "sub3" -- [(set (match_operand:QIHISI 0 "register_operand" "=d, l, r, r") -- (minus:QIHISI (match_operand:QIHISI 1 "nds32_rimm15s_operand" " 0, l, Is15, r") -- (match_operand:QIHISI 2 "register_operand" " r, l, r, r")))] -+ [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu") -+ (set_attr "length" " 2, 2, 2, 2, 2, 2, 2, 2, 4, 4") -+ (set_attr "feature" " v1, v1, v1, v1, v1, v1, v2, v1, v1, v1")]) -+ -+(define_insn "subsi3" -+ [(set (match_operand:SI 0 "register_operand" "=d, l, r, r") -+ (minus:SI (match_operand:SI 1 "nds32_rimm15s_operand" " 0, l, Is15, r") -+ (match_operand:SI 2 "register_operand" " r, l, r, r")))] - "" - "@ -- sub45\t%0, %2 -- sub333\t%0, %1, %2 -- subri\t%0, %2, %1 -- sub\t%0, %1, %2" -+ sub45\t%0, %2 -+ sub333\t%0, %1, %2 -+ subri\t%0, %2, %1 -+ sub\t%0, %1, %2" - [(set_attr "type" "alu,alu,alu,alu") - (set_attr "length" " 2, 2, 4, 4")]) - -@@ -320,10 +490,10 @@ - ;; and needs to ensure it is exact_log2 value. - (define_insn "*add_slli" - [(set (match_operand:SI 0 "register_operand" "=r") -- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r") -+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r") - (match_operand:SI 2 "immediate_operand" " i")) - (match_operand:SI 3 "register_operand" " r")))] -- "TARGET_ISA_V3 -+ "TARGET_ISA_V3 && (TARGET_PIPELINE_PANTHER || optimize_size) - && (exact_log2 (INTVAL (operands[2])) != -1) - && (exact_log2 (INTVAL (operands[2])) <= 31)" - { -@@ -333,18 +503,20 @@ - - return "add_slli\t%0, %3, %1, %2"; - } -- [(set_attr "type" "alu") -- (set_attr "length" "4")]) -+ [(set_attr "type" "alu_shift") -+ (set_attr "combo" "2") -+ (set_attr "length" "4")]) - - (define_insn "*add_srli" -- [(set (match_operand:SI 0 "register_operand" "= r") -- (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "immediate_operand" " Iu05")) -- (match_operand:SI 3 "register_operand" " r")))] -- "TARGET_ISA_V3" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) -+ (match_operand:SI 3 "register_operand" " r")))] -+ "TARGET_ISA_V3 && (TARGET_PIPELINE_PANTHER || optimize_size)" - "add_srli\t%0, %3, %1, %2" -- [(set_attr "type" "alu") -- (set_attr "length" "4")]) -+ [(set_attr "type" "alu_shift") -+ (set_attr "combo" "2") -+ (set_attr "length" "4")]) - - - ;; GCC intends to simplify (minus (reg) (ashift ...)) -@@ -355,7 +527,7 @@ - (minus:SI (match_operand:SI 1 "register_operand" " r") - (mult:SI (match_operand:SI 2 "register_operand" " r") - (match_operand:SI 3 "immediate_operand" " i"))))] -- "TARGET_ISA_V3 -+ "TARGET_ISA_V3 && (TARGET_PIPELINE_PANTHER || optimize_size) - && (exact_log2 (INTVAL (operands[3])) != -1) - && (exact_log2 (INTVAL (operands[3])) <= 31)" - { -@@ -365,32 +537,35 @@ - - return "sub_slli\t%0, %1, %2, %3"; - } -- [(set_attr "type" "alu") -- (set_attr "length" "4")]) -+ [(set_attr "type" "alu_shift") -+ (set_attr "combo" "2") -+ (set_attr "length" "4")]) - - (define_insn "*sub_srli" -- [(set (match_operand:SI 0 "register_operand" "= r") -- (minus:SI (match_operand:SI 1 "register_operand" " r") -- (lshiftrt:SI (match_operand:SI 2 "register_operand" " r") -- (match_operand:SI 3 "immediate_operand" " Iu05"))))] -- "TARGET_ISA_V3" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (minus:SI (match_operand:SI 1 "register_operand" " r") -+ (lshiftrt:SI (match_operand:SI 2 "register_operand" " r") -+ (match_operand:SI 3 "nds32_imm5u_operand" " Iu05"))))] -+ "TARGET_ISA_V3 && (TARGET_PIPELINE_PANTHER || optimize_size)" - "sub_srli\t%0, %1, %2, %3" -- [(set_attr "type" "alu") -- (set_attr "length" "4")]) -+ [(set_attr "type" "alu_shift") -+ (set_attr "combo" "2") -+ (set_attr "length" "4")]) - - - ;; Multiplication instructions. - - (define_insn "mulsi3" -- [(set (match_operand:SI 0 "register_operand" "=w, r") -+ [(set (match_operand:SI 0 "register_operand" "=l, r") - (mult:SI (match_operand:SI 1 "register_operand" "%0, r") -- (match_operand:SI 2 "register_operand" " w, r")))] -+ (match_operand:SI 2 "register_operand" " l, r")))] - "" - "@ -- mul33\t%0, %2 -- mul\t%0, %1, %2" -- [(set_attr "type" "alu,alu") -- (set_attr "length" " 2, 4")]) -+ mul33\t%0, %2 -+ mul\t%0, %1, %2" -+ [(set_attr "type" "mul,mul") -+ (set_attr "length" " 2, 4") -+ (set_attr "feature" "v3m, v1")]) - - (define_insn "mulsidi3" - [(set (match_operand:DI 0 "register_operand" "=r") -@@ -398,7 +573,7 @@ - (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))))] - "TARGET_ISA_V2 || TARGET_ISA_V3" - "mulsr64\t%0, %1, %2" -- [(set_attr "type" "alu") -+ [(set_attr "type" "mul") - (set_attr "length" "4")]) - - (define_insn "umulsidi3" -@@ -407,7 +582,7 @@ - (zero_extend:DI (match_operand:SI 2 "register_operand" " r"))))] - "TARGET_ISA_V2 || TARGET_ISA_V3" - "mulr64\t%0, %1, %2" -- [(set_attr "type" "alu") -+ [(set_attr "type" "mul") - (set_attr "length" "4")]) - - -@@ -415,32 +590,32 @@ - - (define_insn "*maddr32_0" - [(set (match_operand:SI 0 "register_operand" "=r") -- (plus:SI (match_operand:SI 3 "register_operand" " 0") -- (mult:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "register_operand" " r"))))] -+ (plus:SI (match_operand:SI 3 "register_operand" " 0") -+ (mult:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "register_operand" " r"))))] - "" - "maddr32\t%0, %1, %2" -- [(set_attr "type" "alu") -+ [(set_attr "type" "mac") - (set_attr "length" "4")]) - - (define_insn "*maddr32_1" - [(set (match_operand:SI 0 "register_operand" "=r") -- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "register_operand" " r")) -- (match_operand:SI 3 "register_operand" " 0")))] -+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "register_operand" " r")) -+ (match_operand:SI 3 "register_operand" " 0")))] - "" - "maddr32\t%0, %1, %2" -- [(set_attr "type" "alu") -+ [(set_attr "type" "mac") - (set_attr "length" "4")]) - - (define_insn "*msubr32" - [(set (match_operand:SI 0 "register_operand" "=r") -- (minus:SI (match_operand:SI 3 "register_operand" " 0") -- (mult:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "register_operand" " r"))))] -+ (minus:SI (match_operand:SI 3 "register_operand" " 0") -+ (mult:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "register_operand" " r"))))] - "" - "msubr32\t%0, %1, %2" -- [(set_attr "type" "alu") -+ [(set_attr "type" "mac") - (set_attr "length" "4")]) - - -@@ -448,26 +623,46 @@ - - (define_insn "divmodsi4" - [(set (match_operand:SI 0 "register_operand" "=r") -- (div:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "register_operand" " r"))) -+ (div:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "register_operand" " r"))) - (set (match_operand:SI 3 "register_operand" "=r") -- (mod:SI (match_dup 1) (match_dup 2)))] -+ (mod:SI (match_dup 1) (match_dup 2)))] - "" - "divsr\t%0, %3, %1, %2" -- [(set_attr "type" "alu") -+ [(set_attr "type" "div") - (set_attr "length" "4")]) - - (define_insn "udivmodsi4" - [(set (match_operand:SI 0 "register_operand" "=r") -- (udiv:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "register_operand" " r"))) -+ (udiv:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "register_operand" " r"))) - (set (match_operand:SI 3 "register_operand" "=r") -- (umod:SI (match_dup 1) (match_dup 2)))] -+ (umod:SI (match_dup 1) (match_dup 2)))] - "" - "divr\t%0, %3, %1, %2" -- [(set_attr "type" "alu") -+ [(set_attr "type" "div") -+ (set_attr "length" "4")]) -+ -+;; divsr/divr will keep quotient only when quotient and remainder is the same -+;; register in our ISA spec, it's can reduce 1 register presure if we don't -+;; want remainder. -+(define_insn "divsi4" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (div:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "register_operand" " r")))] -+ "" -+ "divsr\t%0, %0, %1, %2" -+ [(set_attr "type" "div") - (set_attr "length" "4")]) - -+(define_insn "udivsi4" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (udiv:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "register_operand" " r")))] -+ "" -+ "divr\t%0, %0, %1, %2" -+ [(set_attr "type" "div") -+ (set_attr "length" "4")]) - - ;; ---------------------------------------------------------------------------- - -@@ -488,14 +683,28 @@ - (set_attr "length" "4")] - ) - --(define_insn "andsi3" -- [(set (match_operand:SI 0 "register_operand" "=w, r, l, l, l, l, l, l, r, r, r, r, r") -- (and:SI (match_operand:SI 1 "register_operand" "%0, r, l, l, l, l, 0, 0, r, r, r, r, r") -- (match_operand:SI 2 "general_operand" " w, r, Izeb, Izeh, Ixls, Ix11, Ibms, Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))] -+(define_expand "andsi3" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (and:SI (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "nds32_reg_constant_operand" "")))] -+ "" -+{ -+ if (CONST_INT_P (operands[2]) -+ && !nds32_and_operand (operands[2], SImode)) -+ { -+ nds32_expand_constant (SImode, INTVAL (operands[2]), -+ operands[0], operands[1]); -+ DONE; -+ } -+}) -+ -+(define_insn "*andsi3" -+ [(set (match_operand:SI 0 "register_operand" "=l, r, l, l, l, l, l, l, r, r, r, r, r") -+ (and:SI (match_operand:SI 1 "register_operand" "%0, r, l, l, l, l, 0, 0, r, r, r, r, r") -+ (match_operand:SI 2 "nds32_and_operand" " l, r,Izeb,Izeh,Ixls,Ix11,Ibms,Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))] - "" - { - HOST_WIDE_INT mask = INTVAL (operands[2]); -- int zero_position; - - /* 16-bit andi instructions: - andi Rt3,Ra3,0xff -> zeb33 Rt3,Ra3 -@@ -520,8 +729,7 @@ - case 5: - return "x11b33\t%0, %1"; - case 6: -- operands[2] = GEN_INT (floor_log2 (mask)); -- return "bmski33\t%0, %2"; -+ return "bmski33\t%0, %B2"; - case 7: - operands[2] = GEN_INT (floor_log2 (mask + 1) - 1); - return "fexti33\t%0, %2"; -@@ -535,47 +743,35 @@ - operands[2] = GEN_INT (~mask); - return "bitci\t%0, %1, %2"; - case 12: -- /* If we reach this alternative, -- it must pass the nds32_can_use_bclr_p() test, -- so that we can guarantee there is only one 0-bit -- within the immediate value. */ -- for (zero_position = 31; zero_position >= 0; zero_position--) -- { -- if ((INTVAL (operands[2]) & (1 << zero_position)) == 0) -- { -- /* Found the 0-bit position. */ -- operands[2] = GEN_INT (zero_position); -- break; -- } -- } -- return "bclr\t%0, %1, %2"; -+ return "bclr\t%0, %1, %b2"; - - default: - gcc_unreachable (); - } - } -- [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu") -- (set_attr "length" " 2, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4")]) -+ [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu") -+ (set_attr "length" " 2, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4") -+ (set_attr "feature" "v3m, v1, v1, v1, v1, v1,v3m,v3m, v1, v1, v1, v3,pe1")]) - - (define_insn "*and_slli" -- [(set (match_operand:SI 0 "register_operand" "= r") -- (and:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "immediate_operand" " Iu05")) -- (match_operand:SI 3 "register_operand" " r")))] -- "TARGET_ISA_V3" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (and:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) -+ (match_operand:SI 3 "register_operand" " r")))] -+ "TARGET_ISA_V3 && (TARGET_PIPELINE_PANTHER || optimize_size)" - "and_slli\t%0, %3, %1, %2" -- [(set_attr "type" "alu") -- (set_attr "length" "4")]) -+ [(set_attr "type" "alu_shift") -+ (set_attr "length" "4")]) - - (define_insn "*and_srli" -- [(set (match_operand:SI 0 "register_operand" "= r") -- (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "immediate_operand" " Iu05")) -- (match_operand:SI 3 "register_operand" " r")))] -- "TARGET_ISA_V3" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) -+ (match_operand:SI 3 "register_operand" " r")))] -+ "TARGET_ISA_V3 && (TARGET_PIPELINE_PANTHER || optimize_size)" - "and_srli\t%0, %3, %1, %2" -- [(set_attr "type" "alu") -- (set_attr "length" "4")]) -+ [(set_attr "type" "alu_shift") -+ (set_attr "length" "4")]) - - - ;; ---------------------------------------------------------------------------- -@@ -584,58 +780,50 @@ - - ;; For V3/V3M ISA, we have 'or33' instruction. - ;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2. --(define_insn "iorsi3" -- [(set (match_operand:SI 0 "register_operand" "=w, r, r, r") -- (ior:SI (match_operand:SI 1 "register_operand" "%0, r, r, r") -- (match_operand:SI 2 "general_operand" " w, r, Iu15, Ie15")))] -+ -+(define_expand "iorsi3" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (ior:SI (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "general_operand" "")))] - "" - { -- int one_position; -- -- switch (which_alternative) -- { -- case 0: -- return "or33\t%0, %2"; -- case 1: -- return "or\t%0, %1, %2"; -- case 2: -- return "ori\t%0, %1, %2"; -- case 3: -- /* If we reach this alternative, -- it must pass the nds32_can_use_bset_p() test, -- so that we can guarantee there is only one 1-bit -- within the immediate value. */ -- /* Use exact_log2() to search the 1-bit position. */ -- one_position = exact_log2 (INTVAL (operands[2])); -- operands[2] = GEN_INT (one_position); -- return "bset\t%0, %1, %2"; -+ if (!nds32_ior_operand (operands[2], SImode)) -+ operands[2] = force_reg (SImode, operands[2]); -+}) - -- default: -- gcc_unreachable (); -- } --} -- [(set_attr "type" "alu,alu,alu,alu") -- (set_attr "length" " 2, 4, 4, 4")]) -+(define_insn "*iorsi3" -+ [(set (match_operand:SI 0 "register_operand" "=l, r, r, r") -+ (ior:SI (match_operand:SI 1 "register_operand" "%0, r, r, r") -+ (match_operand:SI 2 "nds32_ior_operand" " l, r, Iu15, Ie15")))] -+ "" -+ "@ -+ or33\t%0, %2 -+ or\t%0, %1, %2 -+ ori\t%0, %1, %2 -+ bset\t%0, %1, %B2" -+ [(set_attr "type" "alu,alu,alu,alu") -+ (set_attr "length" " 2, 4, 4, 4") -+ (set_attr "feature" "v3m, v1, v1,pe1")]) - - (define_insn "*or_slli" -- [(set (match_operand:SI 0 "register_operand" "= r") -- (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "immediate_operand" " Iu05")) -- (match_operand:SI 3 "register_operand" " r")))] -- "TARGET_ISA_V3" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) -+ (match_operand:SI 3 "register_operand" " r")))] -+ "TARGET_ISA_V3 && (TARGET_PIPELINE_PANTHER || optimize_size)" - "or_slli\t%0, %3, %1, %2" -- [(set_attr "type" "alu") -- (set_attr "length" "4")]) -+ [(set_attr "type" "alu_shift") -+ (set_attr "length" "4")]) - - (define_insn "*or_srli" -- [(set (match_operand:SI 0 "register_operand" "= r") -- (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "immediate_operand" " Iu05")) -- (match_operand:SI 3 "register_operand" " r")))] -- "TARGET_ISA_V3" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) -+ (match_operand:SI 3 "register_operand" " r")))] -+ "TARGET_ISA_V3 && (TARGET_PIPELINE_PANTHER || optimize_size)" - "or_srli\t%0, %3, %1, %2" -- [(set_attr "type" "alu") -- (set_attr "length" "4")]) -+ [(set_attr "type" "alu_shift") -+ (set_attr "length" "4")]) - - - ;; ---------------------------------------------------------------------------- -@@ -644,71 +832,64 @@ - - ;; For V3/V3M ISA, we have 'xor33' instruction. - ;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2. --(define_insn "xorsi3" -- [(set (match_operand:SI 0 "register_operand" "=w, r, r, r") -- (xor:SI (match_operand:SI 1 "register_operand" "%0, r, r, r") -- (match_operand:SI 2 "general_operand" " w, r, Iu15, It15")))] -+ -+(define_expand "xorsi3" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (xor:SI (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "general_operand" "")))] - "" - { -- int one_position; -- -- switch (which_alternative) -- { -- case 0: -- return "xor33\t%0, %2"; -- case 1: -- return "xor\t%0, %1, %2"; -- case 2: -- return "xori\t%0, %1, %2"; -- case 3: -- /* If we reach this alternative, -- it must pass the nds32_can_use_btgl_p() test, -- so that we can guarantee there is only one 1-bit -- within the immediate value. */ -- /* Use exact_log2() to search the 1-bit position. */ -- one_position = exact_log2 (INTVAL (operands[2])); -- operands[2] = GEN_INT (one_position); -- return "btgl\t%0, %1, %2"; -+ if (!nds32_xor_operand (operands[2], SImode)) -+ operands[2] = force_reg (SImode, operands[2]); -+}) - -- default: -- gcc_unreachable (); -- } --} -- [(set_attr "type" "alu,alu,alu,alu") -- (set_attr "length" " 2, 4, 4, 4")]) -+(define_insn "*xorsi3" -+ [(set (match_operand:SI 0 "register_operand" "=l, r, r, r") -+ (xor:SI (match_operand:SI 1 "register_operand" "%0, r, r, r") -+ (match_operand:SI 2 "nds32_xor_operand" " l, r, Iu15, It15")))] -+ "" -+ "@ -+ xor33\t%0, %2 -+ xor\t%0, %1, %2 -+ xori\t%0, %1, %2 -+ btgl\t%0, %1, %B2" -+ [(set_attr "type" "alu,alu,alu,alu") -+ (set_attr "length" " 2, 4, 4, 4") -+ (set_attr "feature" "v3m, v1, v1,pe1")]) - - (define_insn "*xor_slli" - [(set (match_operand:SI 0 "register_operand" "= r") - (xor:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "immediate_operand" " Iu05")) -+ (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) - (match_operand:SI 3 "register_operand" " r")))] -- "TARGET_ISA_V3" -+ "TARGET_ISA_V3 && (TARGET_PIPELINE_PANTHER || optimize_size)" - "xor_slli\t%0, %3, %1, %2" -- [(set_attr "type" "alu") -- (set_attr "length" "4")]) -+ [(set_attr "type" "alu_shift") -+ (set_attr "length" "4")]) - - (define_insn "*xor_srli" -- [(set (match_operand:SI 0 "register_operand" "= r") -- (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") -- (match_operand:SI 2 "immediate_operand" " Iu05")) -- (match_operand:SI 3 "register_operand" " r")))] -- "TARGET_ISA_V3" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") -+ (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) -+ (match_operand:SI 3 "register_operand" " r")))] -+ "TARGET_ISA_V3 && (TARGET_PIPELINE_PANTHER || optimize_size)" - "xor_srli\t%0, %3, %1, %2" -- [(set_attr "type" "alu") -- (set_attr "length" "4")]) -+ [(set_attr "type" "alu_shift") -+ (set_attr "length" "4")]) - - ;; Rotate Right Instructions. - --(define_insn "rotrsi3" -- [(set (match_operand:SI 0 "register_operand" "= r, r") -- (rotatert:SI (match_operand:SI 1 "register_operand" " r, r") -- (match_operand:SI 2 "nonmemory_operand" " Iu05, r")))] -+(define_insn "*rotrsi3" -+ [(set (match_operand:SI 0 "register_operand" "= r, r") -+ (rotatert:SI (match_operand:SI 1 "register_operand" " r, r") -+ (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r")))] - "" - "@ -- rotri\t%0, %1, %2 -- rotr\t%0, %1, %2" -- [(set_attr "type" "alu,alu") -- (set_attr "length" " 4, 4")]) -+ rotri\t%0, %1, %2 -+ rotr\t%0, %1, %2" -+ [(set_attr "type" " alu, alu") -+ (set_attr "subtype" "shift,shift") -+ (set_attr "length" " 4, 4")]) - - - ;; ---------------------------------------------------------------------------- -@@ -720,14 +901,95 @@ - ;; And for V2 ISA, there is NO 'neg33' instruction. - ;; The only option is to use 'subri A,B,0' (its semantic is 'A = 0 - B'). - (define_insn "negsi2" -- [(set (match_operand:SI 0 "register_operand" "=w, r") -- (neg:SI (match_operand:SI 1 "register_operand" " w, r")))] -+ [(set (match_operand:SI 0 "register_operand" "=l, r") -+ (neg:SI (match_operand:SI 1 "register_operand" " l, r")))] - "" - "@ - neg33\t%0, %1 - subri\t%0, %1, 0" -- [(set_attr "type" "alu,alu") -- (set_attr "length" " 2, 4")]) -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4") -+ (set_attr "feature" "v3m, v1")]) -+ -+(define_expand "negsf2" -+ [(set (match_operand:SF 0 "register_operand" "") -+ (neg:SF (match_operand:SF 1 "register_operand" "")))] -+ "" -+{ -+ if (!TARGET_FPU_SINGLE && !TARGET_EXT_PERF) -+ { -+ rtx new_dst = simplify_gen_subreg (SImode, operands[0], SFmode, 0); -+ rtx new_src = simplify_gen_subreg (SImode, operands[1], SFmode, 0); -+ -+ emit_insn (gen_xorsi3 (new_dst, -+ new_src, -+ gen_int_mode (0x80000000, SImode))); -+ -+ DONE; -+ } -+}) -+ -+(define_expand "negdf2" -+ [(set (match_operand:DF 0 "register_operand" "") -+ (neg:DF (match_operand:DF 1 "register_operand" "")))] -+ "" -+{ -+}) -+ -+(define_insn_and_split "soft_negdf2" -+ [(set (match_operand:DF 0 "register_operand" "") -+ (neg:DF (match_operand:DF 1 "register_operand" "")))] -+ "!TARGET_FPU_DOUBLE" -+ "#" -+ "!TARGET_FPU_DOUBLE" -+ [(const_int 1)] -+{ -+ rtx src = operands[1]; -+ rtx dst = operands[0]; -+ rtx ori_dst = operands[0]; -+ -+ bool need_extra_move_for_dst_p; -+ /* FPU register can't change mode to SI directly, so we need create a -+ tmp register to handle it, and FPU register can't do `xor` or btgl. */ -+ if (HARD_REGISTER_P (src) -+ && TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (src))) -+ { -+ rtx tmp = gen_reg_rtx (DFmode); -+ emit_move_insn (tmp, src); -+ src = tmp; -+ } -+ -+ if (HARD_REGISTER_P (dst) -+ && TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (dst))) -+ { -+ need_extra_move_for_dst_p = true; -+ rtx tmp = gen_reg_rtx (DFmode); -+ dst = tmp; -+ } -+ -+ rtx dst_high_part = simplify_gen_subreg ( -+ SImode, dst, -+ DFmode, subreg_highpart_offset (SImode, DFmode)); -+ rtx dst_low_part = simplify_gen_subreg ( -+ SImode, dst, -+ DFmode, subreg_lowpart_offset (SImode, DFmode)); -+ rtx src_high_part = simplify_gen_subreg ( -+ SImode, src, -+ DFmode, subreg_highpart_offset (SImode, DFmode)); -+ rtx src_low_part = simplify_gen_subreg ( -+ SImode, src, -+ DFmode, subreg_lowpart_offset (SImode, DFmode)); -+ -+ emit_insn (gen_xorsi3 (dst_high_part, -+ src_high_part, -+ gen_int_mode (0x80000000, SImode))); -+ emit_move_insn (dst_low_part, src_low_part); -+ -+ if (need_extra_move_for_dst_p) -+ emit_move_insn (ori_dst, dst); -+ -+ DONE; -+}) - - - ;; ---------------------------------------------------------------------------- -@@ -737,55 +999,72 @@ - ;; For V3/V3M ISA, we have 'not33' instruction. - ;; So we can identify 'not Rt3,Ra3' case and set its length to be 2. - (define_insn "one_cmplsi2" -- [(set (match_operand:SI 0 "register_operand" "=w, r") -- (not:SI (match_operand:SI 1 "register_operand" " w, r")))] -+ [(set (match_operand:SI 0 "register_operand" "=l, r") -+ (not:SI (match_operand:SI 1 "register_operand" " l, r")))] - "" - "@ - not33\t%0, %1 - nor\t%0, %1, %1" -- [(set_attr "type" "alu,alu") -- (set_attr "length" " 2, 4")]) -+ [(set_attr "type" "alu,alu") -+ (set_attr "length" " 2, 4") -+ (set_attr "feature" "v3m, v1")]) - - - ;; ---------------------------------------------------------------------------- - - ;; Shift instructions. - --(define_insn "ashlsi3" -- [(set (match_operand:SI 0 "register_operand" "= l, r, r") -- (ashift:SI (match_operand:SI 1 "register_operand" " l, r, r") -- (match_operand:SI 2 "nonmemory_operand" " Iu03, Iu05, r")))] -+(define_expand "si3" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (shift_rotate:SI (match_operand:SI 1 "register_operand" "") -+ (match_operand:SI 2 "nds32_rimm5u_operand" "")))] - "" -- "@ -- slli333\t%0, %1, %2 -- slli\t%0, %1, %2 -- sll\t%0, %1, %2" -- [(set_attr "type" "alu,alu,alu") -- (set_attr "length" " 2, 4, 4")]) -+{ -+ if (operands[2] == const0_rtx) -+ { -+ emit_move_insn (operands[0], operands[1]); -+ DONE; -+ } -+}) - --(define_insn "ashrsi3" -- [(set (match_operand:SI 0 "register_operand" "= d, r, r") -- (ashiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") -- (match_operand:SI 2 "nonmemory_operand" " Iu05, Iu05, r")))] -+(define_insn "*ashlsi3" -+ [(set (match_operand:SI 0 "register_operand" "= l, r, r") -+ (ashift:SI (match_operand:SI 1 "register_operand" " l, r, r") -+ (match_operand:SI 2 "nds32_rimm5u_operand" " Iu03, Iu05, r")))] - "" - "@ -- srai45\t%0, %2 -- srai\t%0, %1, %2 -- sra\t%0, %1, %2" -- [(set_attr "type" "alu,alu,alu") -- (set_attr "length" " 2, 4, 4")]) -- --(define_insn "lshrsi3" -- [(set (match_operand:SI 0 "register_operand" "= d, r, r") -- (lshiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") -- (match_operand:SI 2 "nonmemory_operand" " Iu05, Iu05, r")))] -+ slli333\t%0, %1, %2 -+ slli\t%0, %1, %2 -+ sll\t%0, %1, %2" -+ [(set_attr "type" " alu, alu, alu") -+ (set_attr "subtype" "shift,shift,shift") -+ (set_attr "length" " 2, 4, 4")]) -+ -+(define_insn "*ashrsi3" -+ [(set (match_operand:SI 0 "register_operand" "= d, r, r") -+ (ashiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") -+ (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))] -+ "" -+ "@ -+ srai45\t%0, %2 -+ srai\t%0, %1, %2 -+ sra\t%0, %1, %2" -+ [(set_attr "type" " alu, alu, alu") -+ (set_attr "subtype" "shift,shift,shift") -+ (set_attr "length" " 2, 4, 4")]) -+ -+(define_insn "*lshrsi3" -+ [(set (match_operand:SI 0 "register_operand" "= d, r, r") -+ (lshiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") -+ (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))] - "" - "@ -- srli45\t%0, %2 -- srli\t%0, %1, %2 -- srl\t%0, %1, %2" -- [(set_attr "type" "alu,alu,alu") -- (set_attr "length" " 2, 4, 4")]) -+ srli45\t%0, %2 -+ srli\t%0, %1, %2 -+ srl\t%0, %1, %2" -+ [(set_attr "type" " alu, alu, alu") -+ (set_attr "subtype" "shift,shift,shift") -+ (set_attr "length" " 2, 4, 4")]) - - - ;; ---------------------------------------------------------------------------- -@@ -794,148 +1073,65 @@ - ;; Conditional Move patterns - ;; ---------------------------------------------------------------------------- - --(define_expand "movsicc" -- [(set (match_operand:SI 0 "register_operand" "") -- (if_then_else:SI (match_operand 1 "comparison_operator" "") -- (match_operand:SI 2 "register_operand" "") -- (match_operand:SI 3 "register_operand" "")))] -- "TARGET_CMOV" -+(define_expand "movcc" -+ [(set (match_operand:QIHISI 0 "register_operand" "") -+ (if_then_else:QIHISI (match_operand 1 "nds32_movecc_comparison_operator" "") -+ (match_operand:QIHISI 2 "register_operand" "") -+ (match_operand:QIHISI 3 "register_operand" "")))] -+ "TARGET_CMOV && !optimize_size" - { -- if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) -- && GET_MODE (XEXP (operands[1], 0)) == SImode -- && XEXP (operands[1], 1) == const0_rtx) -- { -- /* If the operands[1] rtx is already (eq X 0) or (ne X 0), -- we have gcc generate original template rtx. */ -- goto create_template; -- } -- else -+ enum nds32_expand_result_type result = nds32_expand_movcc (operands); -+ switch (result) - { -- /* Since there is only 'slt'(Set when Less Than) instruction for -- comparison in Andes ISA, the major strategy we use here is to -- convert conditional move into 'LT + EQ' or 'LT + NE' rtx combination. -- We design constraints properly so that the reload phase will assist -- to make one source operand to use same register as result operand. -- Then we can use cmovz/cmovn to catch the other source operand -- which has different register. */ -- enum rtx_code code = GET_CODE (operands[1]); -- enum rtx_code new_code = code; -- rtx cmp_op0 = XEXP (operands[1], 0); -- rtx cmp_op1 = XEXP (operands[1], 1); -- rtx tmp; -- int reverse = 0; -- -- /* Main Goal: Use 'LT + EQ' or 'LT + NE' to target "then" part -- Strategy : Reverse condition and swap comparison operands -- -- For example: -- -- a <= b ? P : Q (LE or LEU) -- --> a > b ? Q : P (reverse condition) -- --> b < a ? Q : P (swap comparison operands to achieve 'LT/LTU') -- -- a >= b ? P : Q (GE or GEU) -- --> a < b ? Q : P (reverse condition to achieve 'LT/LTU') -- -- a < b ? P : Q (LT or LTU) -- --> (NO NEED TO CHANGE, it is already 'LT/LTU') -- -- a > b ? P : Q (GT or GTU) -- --> b < a ? P : Q (swap comparison operands to achieve 'LT/LTU') */ -- switch (code) -- { -- case NE: -- /* (a != b ? P : Q) -- can be expressed as -- (a == b ? Q : P) -- so, fall through to reverse condition */ -- case GE: case GEU: case LE: case LEU: -- new_code = reverse_condition (code); -- reverse = 1; -- break; -- case EQ: case GT: case GTU: case LT: case LTU: -- /* no need to reverse condition */ -- break; -- default: -- FAIL; -- } -- -- /* For '>' comparison operator, we swap operands -- so that we can have 'LT/LTU' operator. */ -- if (new_code == GT || new_code == GTU) -- { -- tmp = cmp_op0; -- cmp_op0 = cmp_op1; -- cmp_op1 = tmp; -- -- new_code = swap_condition (new_code); -- } -- -- /* Use a temporary register to store slt/slts result. */ -- tmp = gen_reg_rtx (SImode); -- -- /* Split EQ and NE because we don't have direct comparison of EQ and NE. -- If we don't split it, the conditional move transformation will fail -- when producing (SET A (EQ B C)) or (SET A (NE B C)). */ -- if (new_code == EQ) -- { -- emit_insn (gen_xorsi3 (tmp, cmp_op0, cmp_op1)); -- emit_insn (gen_slt_compare (tmp, tmp, GEN_INT (1))); -- } -- else if (new_code == NE) -- { -- emit_insn (gen_xorsi3 (tmp, cmp_op0, cmp_op1)); -- emit_insn (gen_slt_compare (tmp, GEN_INT (0), tmp)); -- } -- else -- /* This emit_insn will create corresponding 'slt/slts' insturction. */ -- emit_insn (gen_rtx_SET (tmp, gen_rtx_fmt_ee (new_code, SImode, -- cmp_op0, cmp_op1))); -- -- /* Change comparison semantic into (eq X 0) or (ne X 0) behavior -- so that cmovz or cmovn will be matched later. -- -- For reverse condition cases, we want to create a semantic that: -- (eq X 0) --> pick up "else" part -- For normal cases, we want to create a semantic that: -- (ne X 0) --> pick up "then" part -- -- Later we will have cmovz/cmovn instruction pattern to -- match corresponding behavior and output instruction. */ -- operands[1] = gen_rtx_fmt_ee (reverse ? EQ : NE, -- VOIDmode, tmp, const0_rtx); -+ case EXPAND_DONE: -+ DONE; -+ break; -+ case EXPAND_FAIL: -+ FAIL; -+ break; -+ case EXPAND_CREATE_TEMPLATE: -+ break; -+ default: -+ gcc_unreachable (); - } -- --create_template: -- do {} while(0); /* dummy line */ - }) - --(define_insn "cmovz" -- [(set (match_operand:SI 0 "register_operand" "=r, r") -- (if_then_else:SI (eq (match_operand:SI 1 "register_operand" " r, r") -+(define_insn "cmovz" -+ [(set (match_operand:QIHISI 0 "register_operand" "=r, r") -+ (if_then_else:QIHISI (eq (match_operand:SI 1 "register_operand" " r, r") - (const_int 0)) -- (match_operand:SI 2 "register_operand" " r, 0") -- (match_operand:SI 3 "register_operand" " 0, r")))] -+ (match_operand:QIHISI 2 "register_operand" " r, 0") -+ (match_operand:QIHISI 3 "register_operand" " 0, r")))] - "TARGET_CMOV" - "@ - cmovz\t%0, %2, %1 - cmovn\t%0, %3, %1" -- [(set_attr "type" "move") -+ [(set_attr "type" "alu") - (set_attr "length" "4")]) - --(define_insn "cmovn" -- [(set (match_operand:SI 0 "register_operand" "=r, r") -- (if_then_else:SI (ne (match_operand:SI 1 "register_operand" " r, r") -+(define_insn "cmovn" -+ [(set (match_operand:QIHISI 0 "register_operand" "=r, r") -+ (if_then_else:QIHISI (ne (match_operand:SI 1 "register_operand" " r, r") - (const_int 0)) -- (match_operand:SI 2 "register_operand" " r, 0") -- (match_operand:SI 3 "register_operand" " 0, r")))] -+ (match_operand:QIHISI 2 "register_operand" " r, 0") -+ (match_operand:QIHISI 3 "register_operand" " 0, r")))] - "TARGET_CMOV" - "@ - cmovn\t%0, %2, %1 - cmovz\t%0, %3, %1" -- [(set_attr "type" "move") -+ [(set_attr "type" "alu") - (set_attr "length" "4")]) - -+;; A hotfix to help RTL combiner to merge a cmovn insn and a zero_extend insn. -+;; It should be removed once after we change the expansion form of the cmovn. -+(define_insn "*cmovn_simplified_" -+ [(set (match_operand:QIHISI 0 "register_operand" "=r") -+ (if_then_else:QIHISI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:QIHISI 2 "register_operand" "r") -+ (match_operand:QIHISI 3 "register_operand" "0")))] -+ "" -+ "cmovn\t%0, %2, %1" -+ [(set_attr "type" "alu")]) - - ;; ---------------------------------------------------------------------------- - ;; Conditional Branch patterns -@@ -950,573 +1146,188 @@ create_template: - (pc)))] - "" - { -- rtx tmp_reg; -- enum rtx_code code; -- -- code = GET_CODE (operands[0]); -- -- /* If operands[2] is (const_int 0), -- we can use beqz,bnez,bgtz,bgez,bltz,or blez instructions. -- So we have gcc generate original template rtx. */ -- if (GET_CODE (operands[2]) == CONST_INT) -- if (INTVAL (operands[2]) == 0) -- if ((code != GTU) -- && (code != GEU) -- && (code != LTU) -- && (code != LEU)) -- goto create_template; -- -- /* For other comparison, NDS32 ISA only has slt (Set-on-Less-Than) -- behavior for the comparison, we might need to generate other -- rtx patterns to achieve same semantic. */ -- switch (code) -+ enum nds32_expand_result_type result = nds32_expand_cbranch (operands); -+ switch (result) - { -- case GT: -- case GTU: -- if (GET_CODE (operands[2]) == CONST_INT) -- { -- /* GT reg_A, const_int => !(LT reg_A, const_int + 1) */ -- tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -- -- /* We want to plus 1 into the integer value -- of operands[2] to create 'slt' instruction. -- This caculation is performed on the host machine, -- which may be 64-bit integer. -- So the meaning of caculation result may be -- different from the 32-bit nds32 target. -- -- For example: -- 0x7fffffff + 0x1 -> 0x80000000, -- this value is POSITIVE on 64-bit machine, -- but the expected value on 32-bit nds32 target -- should be NEGATIVE value. -- -- Hence, instead of using GEN_INT(), we use gen_int_mode() to -- explicitly create SImode constant rtx. */ -- operands[2] = gen_int_mode (INTVAL (operands[2]) + 1, SImode); -- -- if (code == GT) -- { -- /* GT, use slts instruction */ -- emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2])); -- } -- else -- { -- /* GTU, use slt instruction */ -- emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2])); -- } -- -- PUT_CODE (operands[0], EQ); -- operands[1] = tmp_reg; -- operands[2] = const0_rtx; -- emit_insn (gen_cbranchsi4 (operands[0], operands[1], -- operands[2], operands[3])); -- -- DONE; -- } -- else -- { -- /* GT reg_A, reg_B => LT reg_B, reg_A */ -- tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -- -- if (code == GT) -- { -- /* GT, use slts instruction */ -- emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1])); -- } -- else -- { -- /* GTU, use slt instruction */ -- emit_insn (gen_slt_compare (tmp_reg, operands[2], operands[1])); -- } -- -- PUT_CODE (operands[0], NE); -- operands[1] = tmp_reg; -- operands[2] = const0_rtx; -- emit_insn (gen_cbranchsi4 (operands[0], operands[1], -- operands[2], operands[3])); -- -- DONE; -- } -- -- case GE: -- case GEU: -- /* GE reg_A, reg_B => !(LT reg_A, reg_B) */ -- /* GE reg_A, const_int => !(LT reg_A, const_int) */ -- tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -- -- if (code == GE) -- { -- /* GE, use slts instruction */ -- emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2])); -- } -- else -- { -- /* GEU, use slt instruction */ -- emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2])); -- } -- -- PUT_CODE (operands[0], EQ); -- operands[1] = tmp_reg; -- operands[2] = const0_rtx; -- emit_insn (gen_cbranchsi4 (operands[0], operands[1], -- operands[2], operands[3])); -- -+ case EXPAND_DONE: - DONE; -- -- case LT: -- case LTU: -- /* LT reg_A, reg_B => LT reg_A, reg_B */ -- /* LT reg_A, const_int => LT reg_A, const_int */ -- tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -- -- if (code == LT) -- { -- /* LT, use slts instruction */ -- emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2])); -- } -- else -- { -- /* LTU, use slt instruction */ -- emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2])); -- } -- -- PUT_CODE (operands[0], NE); -- operands[1] = tmp_reg; -- operands[2] = const0_rtx; -- emit_insn (gen_cbranchsi4 (operands[0], operands[1], -- operands[2], operands[3])); -- -- DONE; -- -- case LE: -- case LEU: -- if (GET_CODE (operands[2]) == CONST_INT) -- { -- /* LE reg_A, const_int => LT reg_A, const_int + 1 */ -- tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -- -- /* Note that (le:SI X INT_MAX) is not the same as (lt:SI X INT_MIN). -- We better have an assert here in case GCC does not properly -- optimize it away. The INT_MAX here is 0x7fffffff for target. */ -- gcc_assert (code != LE || INTVAL (operands[2]) != 0x7fffffff); -- operands[2] = gen_int_mode (INTVAL (operands[2]) + 1, SImode); -- -- if (code == LE) -- { -- /* LE, use slts instruction */ -- emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2])); -- } -- else -- { -- /* LEU, use slt instruction */ -- emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2])); -- } -- -- PUT_CODE (operands[0], NE); -- operands[1] = tmp_reg; -- operands[2] = const0_rtx; -- emit_insn (gen_cbranchsi4 (operands[0], operands[1], -- operands[2], operands[3])); -- -- DONE; -- } -- else -- { -- /* LE reg_A, reg_B => !(LT reg_B, reg_A) */ -- tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); -- -- if (code == LE) -- { -- /* LE, use slts instruction */ -- emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1])); -- } -- else -- { -- /* LEU, use slt instruction */ -- emit_insn (gen_slt_compare (tmp_reg, operands[2], operands[1])); -- } -- -- PUT_CODE (operands[0], EQ); -- operands[1] = tmp_reg; -- operands[2] = const0_rtx; -- emit_insn (gen_cbranchsi4 (operands[0], operands[1], -- operands[2], operands[3])); -- -- DONE; -- } -- -- case EQ: -- case NE: -- /* NDS32 ISA has various form for eq/ne behavior no matter -- what kind of the operand is. -- So just generate original template rtx. */ -- goto create_template; -- -- default: -+ break; -+ case EXPAND_FAIL: - FAIL; -+ break; -+ case EXPAND_CREATE_TEMPLATE: -+ break; -+ default: -+ gcc_unreachable (); - } -- --create_template: -- do {} while(0); /* dummy line */ - }) - - --(define_insn "*cbranchsi4_equality_zero" -+(define_insn "cbranchsi4_equality_zero" - [(set (pc) - (if_then_else (match_operator 0 "nds32_equality_comparison_operator" -- [(match_operand:SI 1 "register_operand" "t, l, r") -+ [(match_operand:SI 1 "register_operand" "t,l, r") - (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - { -- enum rtx_code code; -- -- code = GET_CODE (operands[0]); -- -- /* This zero-comparison conditional branch has two forms: -- 32-bit instruction => beqz/bnez imm16s << 1 -- 16-bit instruction => beqzs8/bnezs8/beqz38/bnez38 imm8s << 1 -- -- For 32-bit case, -- we assume it is always reachable. (but check range -65500 ~ 65500) -- -- For 16-bit case, -- it must satisfy { 255 >= (label - pc) >= -256 } condition. -- However, since the $pc for nds32 is at the beginning of the instruction, -- we should leave some length space for current insn. -- So we use range -250 ~ 250. */ -- -- switch (get_attr_length (insn)) -- { -- case 2: -- if (which_alternative == 0) -- { -- /* constraint: t */ -- return (code == EQ) ? "beqzs8\t%2" : "bnezs8\t%2"; -- } -- else if (which_alternative == 1) -- { -- /* constraint: l */ -- return (code == EQ) ? "beqz38\t%1, %2" : "bnez38\t%1, %2"; -- } -- else -- { -- /* constraint: r */ -- /* For which_alternative==2, it should not be here. */ -- gcc_unreachable (); -- } -- case 4: -- /* including constraints: t, l, and r */ -- return (code == EQ) ? "beqz\t%1, %2" : "bnez\t%1, %2"; -- case 6: -- if (which_alternative == 0) -- { -- /* constraint: t */ -- if (code == EQ) -- { -- /* beqzs8 .L0 -- => -- bnezs8 .LCB0 -- j .L0 -- .LCB0: -- */ -- return "bnezs8\t.LCB%=\;j\t%2\n.LCB%=:"; -- } -- else -- { -- /* bnezs8 .L0 -- => -- beqzs8 .LCB0 -- j .L0 -- .LCB0: -- */ -- return "beqzs8\t.LCB%=\;j\t%2\n.LCB%=:"; -- } -- } -- else if (which_alternative == 1) -- { -- /* constraint: l */ -- if (code == EQ) -- { -- /* beqz38 $r0, .L0 -- => -- bnez38 $r0, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "bnez38\t%1, .LCB%=\;j\t%2\n.LCB%=:"; -- } -- else -- { -- /* bnez38 $r0, .L0 -- => -- beqz38 $r0, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "beqz38\t%1, .LCB%=\;j\t%2\n.LCB%=:"; -- } -- } -- else -- { -- /* constraint: r */ -- /* For which_alternative==2, it should not be here. */ -- gcc_unreachable (); -- } -- case 8: -- /* constraint: t, l, r. */ -- if (code == EQ) -- { -- /* beqz $r8, .L0 -- => -- bnez $r8, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "bnez\t%1, .LCB%=\;j\t%2\n.LCB%=:"; -- } -- else -- { -- /* bnez $r8, .L0 -- => -- beqz $r8, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "beqz\t%1, .LCB%=\;j\t%2\n.LCB%=:"; -- } -- default: -- gcc_unreachable (); -- } -+ return nds32_output_cbranchsi4_equality_zero (insn, operands); - } - [(set_attr "type" "branch") -- (set_attr "enabled" "1") -+ (set_attr_alternative "enabled" -+ [ -+ ;; Alternative 0 -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_string "yes") -+ (const_string "no")) -+ ;; Alternative 1 -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_string "yes") -+ (const_string "no")) -+ ;; Alternative 2 -+ (const_string "yes") -+ ]) - (set_attr_alternative "length" - [ - ;; Alternative 0 -- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250)) -- (le (minus (match_dup 2) (pc)) (const_int 250))) -- (if_then_else (match_test "TARGET_16_BIT") -- (const_int 2) -- (const_int 4)) -- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) -- (le (minus (match_dup 2) (pc)) (const_int 65500))) -- (const_int 4) -+ (if_then_else (match_test "!CROSSING_JUMP_P (insn)") -+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250)) -+ (le (minus (match_dup 2) (pc)) (const_int 250))) - (if_then_else (match_test "TARGET_16_BIT") -- (const_int 6) -- (const_int 8)))) -+ (const_int 2) -+ (const_int 4)) -+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) -+ (le (minus (match_dup 2) (pc)) (const_int 65500))) -+ (const_int 4) -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_int 8) -+ (const_int 10)))) -+ (const_int 10)) - ;; Alternative 1 -- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250)) -- (le (minus (match_dup 2) (pc)) (const_int 250))) -- (if_then_else (match_test "TARGET_16_BIT") -- (const_int 2) -- (const_int 4)) -+ (if_then_else (match_test "!CROSSING_JUMP_P (insn)") -+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250)) -+ (le (minus (match_dup 2) (pc)) (const_int 250))) -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_int 2) -+ (const_int 4)) -+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) -+ (le (minus (match_dup 2) (pc)) (const_int 65500))) -+ (const_int 4) -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_int 8) -+ (const_int 10)))) -+ (const_int 10)) -+ ;; Alternative 2 -+ (if_then_else (match_test "!CROSSING_JUMP_P (insn)") - (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) - (le (minus (match_dup 2) (pc)) (const_int 65500))) - (const_int 4) -- (if_then_else (match_test "TARGET_16_BIT") -- (const_int 6) -- (const_int 8)))) -- ;; Alternative 2 -- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) -- (le (minus (match_dup 2) (pc)) (const_int 65500))) -- (const_int 4) -- (const_int 8)) -+ (const_int 10)) -+ (const_int 10)) - ])]) - - - ;; This pattern is dedicated to V2 ISA, - ;; because V2 DOES NOT HAVE beqc/bnec instruction. --(define_insn "*cbranchsi4_equality_reg" -+(define_insn "cbranchsi4_equality_reg" - [(set (pc) - (if_then_else (match_operator 0 "nds32_equality_comparison_operator" -- [(match_operand:SI 1 "register_operand" "r") -- (match_operand:SI 2 "nds32_reg_constant_operand" "r")]) -+ [(match_operand:SI 1 "register_operand" "v, r") -+ (match_operand:SI 2 "register_operand" "l, r")]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "TARGET_ISA_V2" - { -- enum rtx_code code; -- -- code = GET_CODE (operands[0]); -- -- /* This register-comparison conditional branch has one form: -- 32-bit instruction => beq/bne imm14s << 1 -- -- For 32-bit case, -- we assume it is always reachable. (but check range -16350 ~ 16350). */ -- -- switch (code) -- { -- case EQ: -- /* r, r */ -- switch (get_attr_length (insn)) -- { -- case 4: -- return "beq\t%1, %2, %3"; -- case 8: -- /* beq $r0, $r1, .L0 -- => -- bne $r0, $r1, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "bne\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; -- default: -- gcc_unreachable (); -- } -- -- case NE: -- /* r, r */ -- switch (get_attr_length (insn)) -- { -- case 4: -- return "bne\t%1, %2, %3"; -- case 8: -- /* bne $r0, $r1, .L0 -- => -- beq $r0, $r1, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "beq\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; -- default: -- gcc_unreachable (); -- } -- -- default: -- gcc_unreachable (); -- } -+ return nds32_output_cbranchsi4_equality_reg (insn, operands); - } - [(set_attr "type" "branch") -- (set (attr "length") -- (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350)) -- (le (minus (match_dup 3) (pc)) (const_int 16350))) -- (const_int 4) -- (const_int 8)))]) -+ (set_attr_alternative "enabled" -+ [ -+ ;; Alternative 0 -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_string "yes") -+ (const_string "no")) -+ ;; Alternative 1 -+ (const_string "yes") -+ ]) -+ (set_attr_alternative "length" -+ [ -+ ;; Alternative 0 -+ (if_then_else (match_test "!CROSSING_JUMP_P (insn)") -+ (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250)) -+ (le (minus (match_dup 3) (pc)) (const_int 250))) -+ (const_int 2) -+ (if_then_else (and (ge (minus (match_dup 3) (pc)) -+ (const_int -16350)) -+ (le (minus (match_dup 3) (pc)) -+ (const_int 16350))) -+ (const_int 4) -+ (const_int 8))) -+ (const_int 8)) -+ ;; Alternative 1 -+ (if_then_else (match_test "!CROSSING_JUMP_P (insn)") -+ (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350)) -+ (le (minus (match_dup 3) (pc)) (const_int 16350))) -+ (const_int 4) -+ (const_int 10)) -+ (const_int 10)) -+ ])]) - - - ;; This pattern is dedicated to V3/V3M, - ;; because V3/V3M DO HAVE beqc/bnec instruction. --(define_insn "*cbranchsi4_equality_reg_or_const_int" -+(define_insn "cbranchsi4_equality_reg_or_const_int" - [(set (pc) - (if_then_else (match_operator 0 "nds32_equality_comparison_operator" -- [(match_operand:SI 1 "register_operand" "r, r") -- (match_operand:SI 2 "nds32_reg_constant_operand" "r, Is11")]) -+ [(match_operand:SI 1 "register_operand" "v, r, r") -+ (match_operand:SI 2 "nds32_rimm11s_operand" "l, r, Is11")]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "TARGET_ISA_V3 || TARGET_ISA_V3M" - { -- enum rtx_code code; -- -- code = GET_CODE (operands[0]); -- -- /* This register-comparison conditional branch has one form: -- 32-bit instruction => beq/bne imm14s << 1 -- 32-bit instruction => beqc/bnec imm8s << 1 -- -- For 32-bit case, we assume it is always reachable. -- (but check range -16350 ~ 16350 and -250 ~ 250). */ -- -- switch (code) -- { -- case EQ: -- if (which_alternative == 0) -- { -- /* r, r */ -- switch (get_attr_length (insn)) -- { -- case 4: -- return "beq\t%1, %2, %3"; -- case 8: -- /* beq $r0, $r1, .L0 -- => -- bne $r0, $r1, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "bne\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; -- default: -- gcc_unreachable (); -- } -- } -- else -- { -- /* r, Is11 */ -- switch (get_attr_length (insn)) -- { -- case 4: -- return "beqc\t%1, %2, %3"; -- case 8: -- /* beqc $r0, constant, .L0 -- => -- bnec $r0, constant, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "bnec\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; -- default: -- gcc_unreachable (); -- } -- } -- case NE: -- if (which_alternative == 0) -- { -- /* r, r */ -- switch (get_attr_length (insn)) -- { -- case 4: -- return "bne\t%1, %2, %3"; -- case 8: -- /* bne $r0, $r1, .L0 -- => -- beq $r0, $r1, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "beq\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; -- default: -- gcc_unreachable (); -- } -- } -- else -- { -- /* r, Is11 */ -- switch (get_attr_length (insn)) -- { -- case 4: -- return "bnec\t%1, %2, %3"; -- case 8: -- /* bnec $r0, constant, .L0 -- => -- beqc $r0, constant, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "beqc\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; -- default: -- gcc_unreachable (); -- } -- } -- default: -- gcc_unreachable (); -- } -+ return nds32_output_cbranchsi4_equality_reg_or_const_int (insn, operands); - } - [(set_attr "type" "branch") -+ (set_attr_alternative "enabled" -+ [ -+ ;; Alternative 0 -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_string "yes") -+ (const_string "no")) -+ ;; Alternative 1 -+ (const_string "yes") -+ ;; Alternative 2 -+ (const_string "yes") -+ ]) - (set_attr_alternative "length" - [ - ;; Alternative 0 -- (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350)) -- (le (minus (match_dup 3) (pc)) (const_int 16350))) -- (const_int 4) -- (const_int 8)) -+ (if_then_else (match_test "!CROSSING_JUMP_P (insn)") -+ (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250)) -+ (le (minus (match_dup 3) (pc)) (const_int 250))) -+ (const_int 2) -+ (if_then_else (and (ge (minus (match_dup 3) (pc)) -+ (const_int -16350)) -+ (le (minus (match_dup 3) (pc)) -+ (const_int 16350))) -+ (const_int 4) -+ (const_int 8))) -+ (const_int 8)) - ;; Alternative 1 -- (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250)) -- (le (minus (match_dup 3) (pc)) (const_int 250))) -- (const_int 4) -- (const_int 8)) -+ (if_then_else (match_test "!CROSSING_JUMP_P (insn)") -+ (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350)) -+ (le (minus (match_dup 3) (pc)) (const_int 16350))) -+ (const_int 4) -+ (const_int 10)) -+ (const_int 10)) -+ ;; Alternative 2 -+ (if_then_else (match_test "!CROSSING_JUMP_P (insn)") -+ (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250)) -+ (le (minus (match_dup 3) (pc)) (const_int 250))) -+ (const_int 4) -+ (const_int 10)) -+ (const_int 10)) - ])]) - - -@@ -1529,80 +1340,16 @@ create_template: - (pc)))] - "" - { -- enum rtx_code code; -- -- code = GET_CODE (operands[0]); -- -- /* This zero-greater-less-comparison conditional branch has one form: -- 32-bit instruction => bgtz/bgez/bltz/blez imm16s << 1 -- -- For 32-bit case, we assume it is always reachable. -- (but check range -65500 ~ 65500). */ -- -- if (get_attr_length (insn) == 8) -- { -- /* The branch target is too far to simply use one -- bgtz/bgez/bltz/blez instruction. -- We need to reverse condition and use 'j' to jump to the target. */ -- switch (code) -- { -- case GT: -- /* bgtz $r8, .L0 -- => -- blez $r8, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "blez\t%1, .LCB%=\;j\t%2\n.LCB%=:"; -- case GE: -- /* bgez $r8, .L0 -- => -- bltz $r8, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "bltz\t%1, .LCB%=\;j\t%2\n.LCB%=:"; -- case LT: -- /* bltz $r8, .L0 -- => -- bgez $r8, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "bgez\t%1, .LCB%=\;j\t%2\n.LCB%=:"; -- case LE: -- /* blez $r8, .L0 -- => -- bgtz $r8, .LCB0 -- j .L0 -- .LCB0: -- */ -- return "bgtz\t%1, .LCB%=\;j\t%2\n.LCB%=:"; -- default: -- gcc_unreachable (); -- } -- } -- -- switch (code) -- { -- case GT: -- return "bgtz\t%1, %2"; -- case GE: -- return "bgez\t%1, %2"; -- case LT: -- return "bltz\t%1, %2"; -- case LE: -- return "blez\t%1, %2"; -- default: -- gcc_unreachable (); -- } -+ return nds32_output_cbranchsi4_greater_less_zero (insn, operands); - } - [(set_attr "type" "branch") - (set (attr "length") -- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) -- (le (minus (match_dup 2) (pc)) (const_int 65500))) -- (const_int 4) -- (const_int 8)))]) -+ (if_then_else (match_test "!CROSSING_JUMP_P (insn)") -+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) -+ (le (minus (match_dup 2) (pc)) (const_int 65500))) -+ (const_int 4) -+ (const_int 10)) -+ (const_int 10)))]) - - - (define_expand "cstoresi4" -@@ -1612,237 +1359,85 @@ create_template: - (match_operand:SI 3 "nonmemory_operand" "")]))] - "" - { -- rtx tmp_reg; -- enum rtx_code code; -- -- code = GET_CODE (operands[1]); -- -- switch (code) -+ enum nds32_expand_result_type result = nds32_expand_cstore (operands); -+ switch (result) - { -- case EQ: -- if (GET_CODE (operands[3]) == CONST_INT) -- { -- /* reg_R = (reg_A == const_int_B) -- --> addi reg_C, reg_A, -const_int_B -- slti reg_R, reg_C, const_int_1 */ -- tmp_reg = gen_reg_rtx (SImode); -- operands[3] = gen_int_mode (-INTVAL (operands[3]), SImode); -- /* If the integer value is not in the range of imm15s, -- we need to force register first because our addsi3 pattern -- only accept nds32_rimm15s_operand predicate. */ -- if (!satisfies_constraint_Is15 (operands[3])) -- operands[3] = force_reg (SImode, operands[3]); -- emit_insn (gen_addsi3 (tmp_reg, operands[2], operands[3])); -- emit_insn (gen_slt_compare (operands[0], tmp_reg, const1_rtx)); -- -- DONE; -- } -- else -- { -- /* reg_R = (reg_A == reg_B) -- --> xor reg_C, reg_A, reg_B -- slti reg_R, reg_C, const_int_1 */ -- tmp_reg = gen_reg_rtx (SImode); -- emit_insn (gen_xorsi3 (tmp_reg, operands[2], operands[3])); -- emit_insn (gen_slt_compare (operands[0], tmp_reg, const1_rtx)); -- -- DONE; -- } -- -- case NE: -- if (GET_CODE (operands[3]) == CONST_INT) -- { -- /* reg_R = (reg_A != const_int_B) -- --> addi reg_C, reg_A, -const_int_B -- slti reg_R, const_int_0, reg_C */ -- tmp_reg = gen_reg_rtx (SImode); -- operands[3] = gen_int_mode (-INTVAL (operands[3]), SImode); -- /* If the integer value is not in the range of imm15s, -- we need to force register first because our addsi3 pattern -- only accept nds32_rimm15s_operand predicate. */ -- if (!satisfies_constraint_Is15 (operands[3])) -- operands[3] = force_reg (SImode, operands[3]); -- emit_insn (gen_addsi3 (tmp_reg, operands[2], operands[3])); -- emit_insn (gen_slt_compare (operands[0], const0_rtx, tmp_reg)); -- -- DONE; -- } -- else -- { -- /* reg_R = (reg_A != reg_B) -- --> xor reg_C, reg_A, reg_B -- slti reg_R, const_int_0, reg_C */ -- tmp_reg = gen_reg_rtx (SImode); -- emit_insn (gen_xorsi3 (tmp_reg, operands[2], operands[3])); -- emit_insn (gen_slt_compare (operands[0], const0_rtx, tmp_reg)); -- -- DONE; -- } -- -- case GT: -- case GTU: -- /* reg_R = (reg_A > reg_B) --> slt reg_R, reg_B, reg_A */ -- /* reg_R = (reg_A > const_int_B) --> slt reg_R, const_int_B, reg_A */ -- if (code == GT) -- { -- /* GT, use slts instruction */ -- emit_insn (gen_slts_compare (operands[0], operands[3], operands[2])); -- } -- else -- { -- /* GTU, use slt instruction */ -- emit_insn (gen_slt_compare (operands[0], operands[3], operands[2])); -- } -- -+ case EXPAND_DONE: - DONE; -- -- case GE: -- case GEU: -- if (GET_CODE (operands[3]) == CONST_INT) -- { -- /* reg_R = (reg_A >= const_int_B) -- --> movi reg_C, const_int_B - 1 -- slt reg_R, reg_C, reg_A */ -- tmp_reg = gen_reg_rtx (SImode); -- -- emit_insn (gen_movsi (tmp_reg, -- gen_int_mode (INTVAL (operands[3]) - 1, -- SImode))); -- if (code == GE) -- { -- /* GE, use slts instruction */ -- emit_insn (gen_slts_compare (operands[0], tmp_reg, operands[2])); -- } -- else -- { -- /* GEU, use slt instruction */ -- emit_insn (gen_slt_compare (operands[0], tmp_reg, operands[2])); -- } -- -- DONE; -- } -- else -- { -- /* reg_R = (reg_A >= reg_B) -- --> slt reg_R, reg_A, reg_B -- xori reg_R, reg_R, const_int_1 */ -- if (code == GE) -- { -- /* GE, use slts instruction */ -- emit_insn (gen_slts_compare (operands[0], -- operands[2], operands[3])); -- } -- else -- { -- /* GEU, use slt instruction */ -- emit_insn (gen_slt_compare (operands[0], -- operands[2], operands[3])); -- } -- -- /* perform 'not' behavior */ -- emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx)); -- -- DONE; -- } -- -- case LT: -- case LTU: -- /* reg_R = (reg_A < reg_B) --> slt reg_R, reg_A, reg_B */ -- /* reg_R = (reg_A < const_int_B) --> slt reg_R, reg_A, const_int_B */ -- if (code == LT) -- { -- /* LT, use slts instruction */ -- emit_insn (gen_slts_compare (operands[0], operands[2], operands[3])); -- } -- else -- { -- /* LTU, use slt instruction */ -- emit_insn (gen_slt_compare (operands[0], operands[2], operands[3])); -- } -- -- DONE; -- -- case LE: -- case LEU: -- if (GET_CODE (operands[3]) == CONST_INT) -- { -- /* reg_R = (reg_A <= const_int_B) -- --> movi reg_C, const_int_B + 1 -- slt reg_R, reg_A, reg_C */ -- tmp_reg = gen_reg_rtx (SImode); -- -- emit_insn (gen_movsi (tmp_reg, -- gen_int_mode (INTVAL (operands[3]) + 1, -- SImode))); -- if (code == LE) -- { -- /* LE, use slts instruction */ -- emit_insn (gen_slts_compare (operands[0], operands[2], tmp_reg)); -- } -- else -- { -- /* LEU, use slt instruction */ -- emit_insn (gen_slt_compare (operands[0], operands[2], tmp_reg)); -- } -- -- DONE; -- } -- else -- { -- /* reg_R = (reg_A <= reg_B) --> slt reg_R, reg_B, reg_A -- xori reg_R, reg_R, const_int_1 */ -- if (code == LE) -- { -- /* LE, use slts instruction */ -- emit_insn (gen_slts_compare (operands[0], -- operands[3], operands[2])); -- } -- else -- { -- /* LEU, use slt instruction */ -- emit_insn (gen_slt_compare (operands[0], -- operands[3], operands[2])); -- } -- -- /* perform 'not' behavior */ -- emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx)); -- -- DONE; -- } -- -- -+ break; -+ case EXPAND_FAIL: -+ FAIL; -+ break; -+ case EXPAND_CREATE_TEMPLATE: -+ break; - default: - gcc_unreachable (); - } - }) - - --(define_insn "slts_compare" -- [(set (match_operand:SI 0 "register_operand" "=t, t, r, r") -- (lt:SI (match_operand:SI 1 "nonmemory_operand" " d, d, r, r") -- (match_operand:SI 2 "nonmemory_operand" " r, Iu05, r, Is15")))] -+(define_expand "slts_compare" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (lt:SI (match_operand:SI 1 "general_operand" "") -+ (match_operand:SI 2 "general_operand" "")))] -+ "" -+{ -+ if (!REG_P (operands[1])) -+ operands[1] = force_reg (SImode, operands[1]); -+ -+ if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2])) -+ operands[2] = force_reg (SImode, operands[2]); -+}) -+ -+(define_insn "slts_compare_impl" -+ [(set (match_operand:SI 0 "register_operand" "=t, t, r, r") -+ (lt:SI (match_operand:SI 1 "register_operand" " d, d, r, r") -+ (match_operand:SI 2 "nds32_rimm15s_operand" " r,Iu05, r, Is15")))] - "" - "@ - slts45\t%1, %2 - sltsi45\t%1, %2 - slts\t%0, %1, %2 - sltsi\t%0, %1, %2" -- [(set_attr "type" "compare,compare,compare,compare") -- (set_attr "length" " 2, 2, 4, 4")]) -+ [(set_attr "type" "alu, alu, alu, alu") -+ (set_attr "length" " 2, 2, 4, 4")]) -+ -+(define_insn "slt_eq0" -+ [(set (match_operand:SI 0 "register_operand" "=t, r") -+ (eq:SI (match_operand:SI 1 "register_operand" " d, r") -+ (const_int 0)))] -+ "" -+ "@ -+ slti45\t%1, 1 -+ slti\t%0, %1, 1" -+ [(set_attr "type" "alu, alu") -+ (set_attr "length" " 2, 4")]) -+ -+(define_expand "slt_compare" -+ [(set (match_operand:SI 0 "register_operand" "") -+ (ltu:SI (match_operand:SI 1 "general_operand" "") -+ (match_operand:SI 2 "general_operand" "")))] -+ "" -+{ -+ if (!REG_P (operands[1])) -+ operands[1] = force_reg (SImode, operands[1]); - --(define_insn "slt_compare" -- [(set (match_operand:SI 0 "register_operand" "=t, t, r, r") -- (ltu:SI (match_operand:SI 1 "nonmemory_operand" " d, d, r, r") -- (match_operand:SI 2 "nonmemory_operand" " r, Iu05, r, Is15")))] -+ if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2])) -+ operands[2] = force_reg (SImode, operands[2]); -+}) -+ -+(define_insn "slt_compare_impl" -+ [(set (match_operand:SI 0 "register_operand" "=t, t, r, r") -+ (ltu:SI (match_operand:SI 1 "register_operand" " d, d, r, r") -+ (match_operand:SI 2 "nds32_rimm15s_operand" " r,Iu05, r, Is15")))] - "" - "@ - slt45\t%1, %2 - slti45\t%1, %2 - slt\t%0, %1, %2 - slti\t%0, %1, %2" -- [(set_attr "type" "compare,compare,compare,compare") -- (set_attr "length" " 2, 2, 4, 4")]) -- -+ [(set_attr "type" "alu, alu, alu, alu") -+ (set_attr "length" " 2, 2, 4, 4")]) - - ;; ---------------------------------------------------------------------------- - -@@ -1874,12 +1469,14 @@ create_template: - } - } - [(set_attr "type" "branch") -- (set_attr "enabled" "1") -+ (set_attr "enabled" "yes") - (set (attr "length") -- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250)) -- (le (minus (match_dup 0) (pc)) (const_int 250))) -- (if_then_else (match_test "TARGET_16_BIT") -- (const_int 2) -+ (if_then_else (match_test "!CROSSING_JUMP_P (insn)") -+ (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250)) -+ (le (minus (match_dup 0) (pc)) (const_int 250))) -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_int 2) -+ (const_int 4)) - (const_int 4)) - (const_int 4)))]) - -@@ -1887,14 +1484,27 @@ create_template: - [(set (pc) (match_operand:SI 0 "register_operand" "r, r"))] - "" - "@ -- jr5\t%0 -- jr\t%0" -+ jr5\t%0 -+ jr\t%0" - [(set_attr "type" "branch,branch") - (set_attr "length" " 2, 4")]) - -+(define_insn "*cond_indirect_jump" -+ [(cond_exec (ne (match_operand:SI 0 "register_operand" "r") -+ (const_int 0)) -+ (set (pc) (match_operand:SI 1 "register_operand" "0")))] -+ "" -+ "jrnez\t%0" -+ [(set_attr "type" "branch") -+ (set_attr "length" "4")]) -+ -+;; ---------------------------------------------------------------------------- -+ -+;; Normal call patterns. -+ - ;; Subroutine call instruction returning no value. - ;; operands[0]: It should be a mem RTX whose address is --;; the address of the function. -+;; the the address of the function. - ;; operands[1]: It is the number of bytes of arguments pushed as a const_int. - ;; operands[2]: It is the number of registers used as operands. - -@@ -1904,39 +1514,114 @@ create_template: - (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_register" -- [(parallel [(call (mem (match_operand:SI 0 "register_operand" "r, r")) -- (match_operand 1)) -- (clobber (reg:SI LP_REGNUM)) -- (clobber (reg:SI TA_REGNUM))])] -- "" -- "@ -- jral5\t%0 -- jral\t%0" -- [(set_attr "type" "branch,branch") -- (set_attr "length" " 2, 4")]) -- --(define_insn "*call_immediate" -- [(parallel [(call (mem (match_operand:SI 0 "immediate_operand" "i")) -+(define_insn "call_internal" -+ [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i")) - (match_operand 1)) - (clobber (reg:SI LP_REGNUM)) - (clobber (reg:SI TA_REGNUM))])] - "" - { -- if (TARGET_CMODEL_LARGE) -- return "bal\t%0"; -- else -- return "jal\t%0"; -+ rtx_insn *next_insn = next_active_insn (insn); -+ bool align_p = (!(next_insn && get_attr_length (next_insn) == 2)) -+ && NDS32_ALIGN_P (); -+ switch (which_alternative) -+ { -+ case 0: -+ if (TARGET_16_BIT) -+ { -+ if (align_p) -+ return "jral5\t%0\;.align 2"; -+ else -+ return "jral5\t%0"; -+ } -+ else -+ { -+ if (align_p) -+ return "jral\t%0\;.align 2"; -+ else -+ return "jral\t%0"; -+ } -+ case 1: -+ return nds32_output_call (insn, operands, operands[0], -+ "bal\t%0", "jal\t%0", align_p); -+ default: -+ gcc_unreachable (); -+ } - } -- [(set_attr "type" "branch") -- (set (attr "length") -- (if_then_else (match_test "TARGET_CMODEL_LARGE") -- (const_int 12) -- (const_int 4)))]) -+ [(set_attr "enabled" "yes") -+ (set_attr "type" "branch") -+ (set_attr_alternative "length" -+ [ -+ ;; Alternative 0 -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_int 2) -+ (const_int 4)) -+ ;; Alternative 1 -+ (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))) -+ ])] -+) - -+(define_insn "*cond_call_register" -+ [(cond_exec (ne (match_operand:SI 0 "register_operand" "r") -+ (const_int 0)) -+ (parallel [(call (mem (match_operand:SI 1 "register_operand" "0")) -+ (match_operand 2)) -+ (clobber (reg:SI LP_REGNUM)) -+ (clobber (reg:SI TA_REGNUM))]))] -+ "TARGET_ISA_V3" -+ "jralnez\t%0" -+ [(set_attr "type" "branch") -+ (set_attr "length" "4")]) -+ -+(define_insn "*cond_call_immediate" -+ [(cond_exec (match_operator 0 "nds32_conditional_call_comparison_operator" -+ [(match_operand:SI 1 "register_operand" "r") -+ (const_int 0)]) -+ (parallel [(call (mem (match_operand:SI 2 "nds32_symbolic_operand" "i")) -+ (match_operand 3)) -+ (clobber (reg:SI LP_REGNUM)) -+ (clobber (reg:SI TA_REGNUM))]))] -+ "!flag_pic && !TARGET_CMODEL_LARGE -+ && nds32_indirect_call_referenced_p (operands[2])" -+{ -+ switch (GET_CODE (operands[0])) -+ { -+ case LT: -+ return "bltzal\t%1, %2"; -+ case GE: -+ return "bgezal\t%1, %2"; -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "type" "branch") -+ (set_attr "length" "4")]) - - ;; Subroutine call instruction returning a value. - ;; operands[0]: It is the hard regiser in which the value is returned. -@@ -1951,49 +1636,152 @@ create_template: - (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_register" -+(define_insn "call_value_internal" - [(parallel [(set (match_operand 0) -- (call (mem (match_operand:SI 1 "register_operand" "r, r")) -+ (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i")) - (match_operand 2))) - (clobber (reg:SI LP_REGNUM)) - (clobber (reg:SI TA_REGNUM))])] - "" -- "@ -- jral5\t%1 -- jral\t%1" -- [(set_attr "type" "branch,branch") -- (set_attr "length" " 2, 4")]) -- --(define_insn "*call_value_immediate" -- [(parallel [(set (match_operand 0) -- (call (mem (match_operand:SI 1 "immediate_operand" "i")) -- (match_operand 2))) -- (clobber (reg:SI LP_REGNUM)) -- (clobber (reg:SI TA_REGNUM))])] -- "" - { -- if (TARGET_CMODEL_LARGE) -- return "bal\t%1"; -- else -- return "jal\t%1"; -+ rtx_insn *next_insn = next_active_insn (insn); -+ bool align_p = (!(next_insn && get_attr_length (next_insn) == 2)) -+ && NDS32_ALIGN_P (); -+ switch (which_alternative) -+ { -+ case 0: -+ if (TARGET_16_BIT) -+ { -+ if (align_p) -+ return "jral5\t%1\;.align 2"; -+ else -+ return "jral5\t%1"; -+ } -+ else -+ { -+ if (align_p) -+ return "jral\t%1\;.align 2"; -+ else -+ return "jral\t%1"; -+ } -+ case 1: -+ return nds32_output_call (insn, operands, operands[1], -+ "bal\t%1", "jal\t%1", align_p); -+ default: -+ gcc_unreachable (); -+ } -+} -+ [(set_attr "enabled" "yes") -+ (set_attr "type" "branch") -+ (set_attr_alternative "length" -+ [ -+ ;; Alternative 0 -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_int 2) -+ (const_int 4)) -+ ;; Alternative 1 -+ (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))) -+ ])] -+) -+ -+(define_insn "*cond_call_value_register" -+ [(cond_exec (ne (match_operand:SI 0 "register_operand" "r") -+ (const_int 0)) -+ (parallel [(set (match_operand 1) -+ (call (mem (match_operand:SI 2 "register_operand" "0")) -+ (match_operand 3))) -+ (clobber (reg:SI LP_REGNUM)) -+ (clobber (reg:SI TA_REGNUM))]))] -+ "TARGET_ISA_V3" -+ "jralnez\t%0" -+ [(set_attr "type" "branch") -+ (set_attr "length" "4")]) -+ -+(define_insn "*cond_call_value_immediate" -+ [(cond_exec (match_operator 0 "nds32_conditional_call_comparison_operator" -+ [(match_operand:SI 1 "register_operand" "r") -+ (const_int 0)]) -+ (parallel [(set (match_operand 2) -+ (call (mem (match_operand:SI 3 "nds32_symbolic_operand" "i")) -+ (match_operand 4))) -+ (clobber (reg:SI LP_REGNUM)) -+ (clobber (reg:SI TA_REGNUM))]))] -+ "!flag_pic && !TARGET_CMODEL_LARGE -+ && nds32_indirect_call_referenced_p (operands[3])" -+{ -+ switch (GET_CODE (operands[0])) -+ { -+ case LT: -+ return "bltzal\t%1, %3"; -+ case GE: -+ return "bgezal\t%1, %3"; -+ default: -+ gcc_unreachable (); -+ } - } - [(set_attr "type" "branch") -- (set (attr "length") -- (if_then_else (match_test "TARGET_CMODEL_LARGE") -- (const_int 12) -- (const_int 4)))]) -+ (set_attr "length" "4")]) -+ -+;; Call subroutine returning any type. -+ -+(define_expand "untyped_call" -+ [(parallel [(call (match_operand 0 "" "") -+ (const_int 0)) -+ (match_operand 1 "" "") -+ (match_operand 2 "" "")])] -+ "" -+{ -+ int i; -+ -+ emit_call_insn (gen_call (operands[0], const0_rtx)); -+ -+ for (i = 0; i < XVECLEN (operands[2], 0); i++) -+ { -+ rtx set = XVECEXP (operands[2], 0, i); -+ emit_move_insn (SET_DEST (set), SET_SRC (set)); -+ } - -+ /* The optimizer does not know that the call sets the function value -+ registers we stored in the result block. We avoid problems by -+ claiming that all hard registers are used and clobbered at this -+ point. */ -+ emit_insn (gen_blockage ()); -+ DONE; -+}) - - ;; ---------------------------------------------------------------------------- - - ;; The sibcall patterns. - - ;; sibcall --;; sibcall_register --;; sibcall_immediate -+;; sibcall_internal - - (define_expand "sibcall" - [(parallel [(call (match_operand 0 "memory_operand" "") -@@ -2001,41 +1789,60 @@ create_template: - (clobber (reg:SI TA_REGNUM)) - (return)])] - "" -- "" --) -- --(define_insn "*sibcall_register" -- [(parallel [(call (mem (match_operand:SI 0 "register_operand" "r, r")) -- (match_operand 1)) -- (clobber (reg:SI TA_REGNUM)) -- (return)])] -- "" -- "@ -- jr5\t%0 -- jr\t%0" -- [(set_attr "type" "branch,branch") -- (set_attr "length" " 2, 4")]) -+{ -+ 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_immediate" -- [(parallel [(call (mem (match_operand:SI 0 "immediate_operand" "i")) -+(define_insn "sibcall_internal" -+ [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i")) - (match_operand 1)) - (clobber (reg:SI TA_REGNUM)) - (return)])] - "" - { -- if (TARGET_CMODEL_LARGE) -- return "b\t%0"; -- else -- return "j\t%0"; -+ switch (which_alternative) -+ { -+ case 0: -+ if (TARGET_16_BIT) -+ return "jr5\t%0"; -+ else -+ return "jr\t%0"; -+ case 1: -+ if (nds32_long_call_p (operands[0])) -+ return "b\t%0"; -+ else -+ return "j\t%0"; -+ default: -+ gcc_unreachable (); -+ } - } -- [(set_attr "type" "branch") -- (set (attr "length") -- (if_then_else (match_test "TARGET_CMODEL_LARGE") -- (const_int 12) -- (const_int 4)))]) -+ [(set_attr "enabled" "yes") -+ (set_attr "type" "branch") -+ (set_attr_alternative "length" -+ [ -+ ;; Alternative 0 -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_int 2) -+ (const_int 4)) -+ ;; Alternative 1 -+ (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))) -+ ])] -+) - - ;; sibcall_value --;; sibcall_value_register -+;; sibcall_value_internal - ;; sibcall_value_immediate - - (define_expand "sibcall_value" -@@ -2045,73 +1852,106 @@ create_template: - (clobber (reg:SI TA_REGNUM)) - (return)])] - "" -- "" --) -- --(define_insn "*sibcall_value_register" -- [(parallel [(set (match_operand 0) -- (call (mem (match_operand:SI 1 "register_operand" "r, r")) -- (match_operand 2))) -- (clobber (reg:SI TA_REGNUM)) -- (return)])] -- "" -- "@ -- jr5\t%1 -- jr\t%1" -- [(set_attr "type" "branch,branch") -- (set_attr "length" " 2, 4")]) -+{ -+ 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_immediate" -+(define_insn "sibcall_value_internal" - [(parallel [(set (match_operand 0) -- (call (mem (match_operand:SI 1 "immediate_operand" "i")) -+ (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i")) - (match_operand 2))) - (clobber (reg:SI TA_REGNUM)) - (return)])] - "" - { -- if (TARGET_CMODEL_LARGE) -- return "b\t%1"; -- else -- return "j\t%1"; -+ switch (which_alternative) -+ { -+ case 0: -+ if (TARGET_16_BIT) -+ return "jr5\t%1"; -+ else -+ return "jr\t%1"; -+ case 1: -+ if (nds32_long_call_p (operands[1])) -+ return "b\t%1"; -+ else -+ return "j\t%1"; -+ default: -+ gcc_unreachable (); -+ } - } -- [(set_attr "type" "branch") -- (set (attr "length") -- (if_then_else (match_test "TARGET_CMODEL_LARGE") -- (const_int 12) -- (const_int 4)))]) -- -+ [(set_attr "enabled" "yes") -+ (set_attr "type" "branch") -+ (set_attr_alternative "length" -+ [ -+ ;; Alternative 0 -+ (if_then_else (match_test "TARGET_16_BIT") -+ (const_int 2) -+ (const_int 4)) -+ ;; Alternative 1 -+ (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))) -+ ])] -+) - - ;; ---------------------------------------------------------------------------- - --;; prologue and epilogue. -+;; The prologue and epilogue. - - (define_expand "prologue" [(const_int 0)] - "" - { - /* Note that only under V3/V3M ISA, we could use v3push prologue. -- In addition, we do not want to use v3push for isr function -- and variadic function. */ -- if (TARGET_V3PUSH -- && !nds32_isr_function_p (current_function_decl) -- && (cfun->machine->va_args_size == 0)) -+ In addition, we need to check if v3push is indeed available. */ -+ if (NDS32_V3PUSH_AVAILABLE_P) - 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 do not want to use v3pop for isr function -- and variadic function. */ -- if (TARGET_V3PUSH -- && !nds32_isr_function_p (current_function_decl) -- && (cfun->machine->va_args_size == 0)) -+ In addition, we need to check if v3push is indeed available. */ -+ if (NDS32_V3PUSH_AVAILABLE_P) - nds32_expand_epilogue_v3pop (false); - else - nds32_expand_epilogue (false); -+ - DONE; - }) - -@@ -2121,15 +1961,11 @@ create_template: - /* Pass true to indicate that this is sibcall epilogue and - exit from a function without the final branch back to the - calling function. */ -- if (TARGET_V3PUSH && !nds32_isr_function_p (current_function_decl)) -- nds32_expand_epilogue_v3pop (true); -- else -- nds32_expand_epilogue (true); -+ nds32_expand_epilogue (true); - - DONE; - }) - -- - ;; nop instruction. - - (define_insn "nop" -@@ -2142,7 +1978,7 @@ create_template: - return "nop"; - } - [(set_attr "type" "misc") -- (set_attr "enabled" "1") -+ (set_attr "enabled" "yes") - (set (attr "length") - (if_then_else (match_test "TARGET_16_BIT") - (const_int 2) -@@ -2166,12 +2002,11 @@ create_template: - { - return nds32_output_stack_push (operands[0]); - } -- [(set_attr "type" "misc") -- (set_attr "enabled" "1") -+ [(set_attr "type" "store_multiple") -+ (set_attr "combo" "12") -+ (set_attr "enabled" "yes") - (set (attr "length") -- (if_then_else (match_test "TARGET_V3PUSH -- && !nds32_isr_function_p (cfun->decl) -- && (cfun->machine->va_args_size == 0)") -+ (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P") - (const_int 2) - (const_int 4)))]) - -@@ -2188,12 +2023,11 @@ create_template: - { - return nds32_output_stack_pop (operands[0]); - } -- [(set_attr "type" "misc") -- (set_attr "enabled" "1") -+ [(set_attr "type" "load_multiple") -+ (set_attr "combo" "12") -+ (set_attr "enabled" "yes") - (set (attr "length") -- (if_then_else (match_test "TARGET_V3PUSH -- && !nds32_isr_function_p (cfun->decl) -- && (cfun->machine->va_args_size == 0)") -+ (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P") - (const_int 2) - (const_int 4)))]) - -@@ -2205,34 +2039,64 @@ create_template: - ;; Use this pattern to expand a return instruction - ;; with simple_return rtx if no epilogue is required. - (define_expand "return" -- [(simple_return)] -+ [(parallel [(return) -+ (clobber (reg:SI FP_REGNUM))])] - "nds32_can_use_return_insn ()" -- "" --) -+{ -+ /* Emit as the simple return. */ -+ if (!cfun->machine->fp_as_gp_p -+ && cfun->machine->naked_p -+ && (cfun->machine->va_args_size == 0)) -+ { -+ emit_jump_insn (gen_return_internal ()); -+ DONE; -+ } -+}) - - ;; 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" - "" - ) - -+(define_insn "*nds32_return" -+ [(parallel [(return) -+ (clobber (reg:SI FP_REGNUM))])] -+ "" -+{ -+ return nds32_output_return (); -+} -+ [(set_attr "type" "branch") -+ (set_attr "enabled" "yes") -+ (set_attr "length" "4")]) -+ - (define_insn "return_internal" - [(simple_return)] - "" - { -+ if (nds32_isr_function_critical_p (current_function_decl)) -+ return "iret"; -+ - if (TARGET_16_BIT) - return "ret5"; - else - return "ret"; - } - [(set_attr "type" "branch") -- (set_attr "enabled" "1") -+ (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))))]) - - - ;; ---------------------------------------------------------------------------- -@@ -2267,6 +2131,7 @@ create_template: - { - rtx add_tmp; - rtx reg, test; -+ rtx tmp_reg; - - /* Step A: "k <-- (plus (operands[0]) (-operands[1]))". */ - if (operands[1] != const0_rtx) -@@ -2275,8 +2140,8 @@ create_template: - add_tmp = gen_int_mode (-INTVAL (operands[1]), SImode); - - /* If the integer value is not in the range of imm15s, -- we need to force register first because our addsi3 pattern -- only accept nds32_rimm15s_operand predicate. */ -+ we need to force register first because our addsi3 pattern -+ only accept nds32_rimm15s_operand predicate. */ - add_tmp = force_reg (SImode, add_tmp); - - emit_insn (gen_addsi3 (reg, operands[0], add_tmp)); -@@ -2288,11 +2153,14 @@ create_template: - emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], - operands[4])); - -- operands[5] = gen_reg_rtx (SImode); -- /* Step C, D, E, and F, using another temporary register operands[5]. */ -+ 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], -- operands[5])); -+ tmp_reg)); - DONE; - }) - -@@ -2328,17 +2196,34 @@ create_template: - else - return nds32_output_casesi (operands); - } -- [(set_attr "length" "20") -- (set_attr "type" "alu")]) -+ [(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")))] -- "TARGET_PERF_EXT" -+ "TARGET_EXT_PERF" - "clz\t%0, %1" - [(set_attr "type" "alu") - (set_attr "length" "4")]) -@@ -2347,34 +2232,212 @@ create_template: - [(set (match_operand:SI 0 "register_operand" "=r") - (smax:SI (match_operand:SI 1 "register_operand" " r") - (match_operand:SI 2 "register_operand" " r")))] -- "TARGET_PERF_EXT" -+ "TARGET_EXT_PERF" - "max\t%0, %1, %2" - [(set_attr "type" "alu") - (set_attr "length" "4")]) - -+(define_expand "uminqi3" -+ [(set (match_operand:QI 0 "register_operand" "") -+ (umin:QI (match_operand:QI 1 "register_operand" "") -+ (match_operand:QI 2 "register_operand" "")))] -+ "TARGET_EXT_PERF" -+{ -+ rtx tmpop[3]; -+ tmpop[0] = gen_reg_rtx (SImode); -+ tmpop[1] = gen_reg_rtx (SImode); -+ tmpop[2] = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_zero_extendqisi2 (tmpop[1], operands[1])); -+ emit_insn (gen_zero_extendqisi2 (tmpop[2], operands[2])); -+ emit_insn (gen_sminsi3 (tmpop[0], tmpop[1], tmpop[2])); -+ convert_move (operands[0], tmpop[0], false); -+ DONE; -+}) -+ -+(define_expand "sminqi3" -+ [(set (match_operand:QI 0 "register_operand" "") -+ (smin:QI (match_operand:QI 1 "register_operand" "") -+ (match_operand:QI 2 "register_operand" "")))] -+ "TARGET_EXT_PERF" -+{ -+ rtx tmpop[3]; -+ tmpop[0] = gen_reg_rtx (SImode); -+ tmpop[1] = gen_reg_rtx (SImode); -+ tmpop[2] = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_extendqisi2 (tmpop[1], operands[1])); -+ emit_insn (gen_extendqisi2 (tmpop[2], operands[2])); -+ emit_insn (gen_sminsi3 (tmpop[0], tmpop[1], tmpop[2])); -+ convert_move (operands[0], tmpop[0], false); -+ DONE; -+}) -+ -+(define_expand "uminhi3" -+ [(set (match_operand:HI 0 "register_operand" "") -+ (umin:HI (match_operand:HI 1 "register_operand" "") -+ (match_operand:HI 2 "register_operand" "")))] -+ "TARGET_EXT_PERF" -+{ -+ rtx tmpop[3]; -+ tmpop[0] = gen_reg_rtx (SImode); -+ tmpop[1] = gen_reg_rtx (SImode); -+ tmpop[2] = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_zero_extendhisi2 (tmpop[1], operands[1])); -+ emit_insn (gen_zero_extendhisi2 (tmpop[2], operands[2])); -+ emit_insn (gen_sminsi3 (tmpop[0], tmpop[1], tmpop[2])); -+ convert_move (operands[0], tmpop[0], false); -+ DONE; -+}) -+ -+(define_expand "sminhi3" -+ [(set (match_operand:HI 0 "register_operand" "") -+ (smin:HI (match_operand:HI 1 "register_operand" "") -+ (match_operand:HI 2 "register_operand" "")))] -+ "TARGET_EXT_PERF" -+{ -+ rtx tmpop[3]; -+ tmpop[0] = gen_reg_rtx (SImode); -+ tmpop[1] = gen_reg_rtx (SImode); -+ tmpop[2] = gen_reg_rtx (SImode); -+ -+ emit_insn (gen_extendhisi2 (tmpop[1], operands[1])); -+ emit_insn (gen_extendhisi2 (tmpop[2], operands[2])); -+ emit_insn (gen_sminsi3 (tmpop[0], tmpop[1], tmpop[2])); -+ convert_move (operands[0], tmpop[0], false); -+ DONE; -+}) -+ - (define_insn "sminsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (smin:SI (match_operand:SI 1 "register_operand" " r") - (match_operand:SI 2 "register_operand" " r")))] -- "TARGET_PERF_EXT" -+ "TARGET_EXT_PERF" - "min\t%0, %1, %2" - [(set_attr "type" "alu") - (set_attr "length" "4")]) - --(define_insn "*btst" -- [(set (match_operand:SI 0 "register_operand" "= r") -- (zero_extract:SI (match_operand:SI 1 "register_operand" " r") -+(define_insn "btst" -+ [(set (match_operand:SI 0 "register_operand" "= r") -+ (zero_extract:SI (match_operand:SI 1 "register_operand" " r") - (const_int 1) -- (match_operand:SI 2 "immediate_operand" " Iu05")))] -- "TARGET_PERF_EXT" -+ (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")))] -+ "TARGET_EXT_PERF" - "btst\t%0, %1, %2" - [(set_attr "type" "alu") - (set_attr "length" "4")]) - -+(define_insn "ave" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (ashiftrt:DI -+ (plus:DI -+ (plus:DI -+ (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) -+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))) -+ (const_int 1)) -+ (const_int 1))))] -+ "TARGET_EXT_PERF" -+ "ave\t%0, %1, %2" -+ [(set_attr "type" "alu") -+ (set_attr "length" "4")]) -+ - ;; ---------------------------------------------------------------------------- - - ;; Pseudo NOPs - -+;; Structural hazards NOP -+(define_insn "nop_res_dep" -+ [(unspec [(match_operand 0 "const_int_operand" "i")] UNSPEC_VOLATILE_RES_DEP)] -+ "" -+ "! structural dependency (%0 cycles)" -+ [(set_attr "length" "0")] -+) -+ -+;; Data hazards NOP -+(define_insn "nop_data_dep" -+ [(unspec [(match_operand 0 "const_int_operand" "i")] UNSPEC_VOLATILE_DATA_DEP)] -+ "" -+ "! data dependency (%0 cycles)" -+ [(set_attr "length" "0")] -+) -+ -+(define_insn "relax_group" -+ [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)] -+ "" -+ ".relax_hint %0" -+ [(set_attr "length" "0")] -+) -+ -+(define_insn "innermost_loop_begin" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_INNERMOST_LOOP_BEGIN)] -+ "" -+ ".innermost_loop_begin" -+ [(set_attr "length" "0")] -+) -+ -+(define_insn "innermost_loop_end" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_INNERMOST_LOOP_END)] -+ "" -+ ".innermost_loop_end" -+ [(set_attr "length" "0")] -+) -+ -+(define_insn "no_ifc_begin" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_NO_IFC_BEGIN)] -+ "" -+ ".no_ifc_begin" -+ [(set_attr "length" "0")] -+) -+ -+(define_insn "no_ifc_end" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_NO_IFC_END)] -+ "" -+ ".no_ifc_end" -+ [(set_attr "length" "0")] -+) -+ -+(define_insn "no_ex9_begin" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_NO_EX9_BEGIN)] -+ "" -+ ".no_ex9_begin" -+ [(set_attr "length" "0")] -+) -+ -+(define_insn "no_ex9_end" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_NO_EX9_END)] -+ "" -+ ".no_ex9_end" -+ [(set_attr "length" "0")] -+) -+ -+(define_insn "hwloop_last_insn" -+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_HWLOOP_LAST_INSN)] -+ "" -+ "" -+ [(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)] -@@ -2383,4 +2446,262 @@ create_template: - [(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")] -+) -+ -+;; Hardware loop -+ -+; operand 0 is the loop count pseudo register -+; operand 1 is the label to jump to at the top of the loop -+(define_expand "doloop_end" -+ [(parallel [(set (pc) (if_then_else -+ (ne (match_operand:SI 0 "" "") -+ (const_int 1)) -+ (label_ref (match_operand 1 "" "")) -+ (pc))) -+ (set (match_dup 0) -+ (plus:SI (match_dup 0) -+ (const_int -1))) -+ (unspec [(const_int 0)] UNSPEC_LOOP_END) -+ (clobber (match_dup 2))])] ; match_scratch -+ "NDS32_HW_LOOP_P ()" -+{ -+ /* The loop optimizer doesn't check the predicates... */ -+ if (GET_MODE (operands[0]) != SImode) -+ FAIL; -+ operands[2] = gen_rtx_SCRATCH (SImode); -+}) -+ -+(define_insn "loop_end" -+ [(set (pc) -+ (if_then_else (ne (match_operand:SI 3 "nonimmediate_operand" "0, 0, *r, 0") -+ (const_int 1)) -+ (label_ref (match_operand 1 "" "")) -+ (pc))) -+ (set (match_operand:SI 0 "nonimmediate_operand" "=r, m, m, *f") -+ (plus:SI (match_dup 3) -+ (const_int -1))) -+ (unspec [(const_int 0)] UNSPEC_LOOP_END) -+ (clobber (match_scratch:SI 2 "=X, &r, &r, &r"))] -+ "NDS32_HW_LOOP_P ()" -+ "#" -+ [(set_attr "length" "12, 12, 12, 12")]) -+ -+(define_split -+ [(set (pc) -+ (if_then_else (ne (match_operand:SI 3 "nonimmediate_operand" "") -+ (const_int 1)) -+ (label_ref (match_operand 1 "" "")) -+ (pc))) -+ (set (match_operand:SI 0 "fpu_reg_or_memory_operand" "") -+ (plus:SI (match_dup 3) -+ (const_int -1))) -+ (unspec [(const_int 0)] UNSPEC_LOOP_END) -+ (clobber (match_scratch:SI 2 ""))] -+ "NDS32_HW_LOOP_P ()" -+ [(set (match_dup 2) (plus:SI (match_dup 3) (const_int -1))) -+ (set (match_dup 0) (match_dup 2)) -+ (set (pc) -+ (if_then_else (ne (match_dup 2) (const_int 0)) -+ (label_ref (match_dup 1)) -+ (pc)))] -+{ -+ if (fpu_reg_or_memory_operand (operands[3], SImode)) -+ { -+ emit_move_insn (operands[2], operands[3]); -+ operands[3] = operands[2]; -+ } -+}) -+ -+(define_insn "mtlbi_hint" -+ [(set (reg:SI LB_REGNUM) -+ (match_operand:SI 0 "nds32_label_operand" "i")) -+ (unspec [(match_operand 1 "const_int_operand" "i")] UNSPEC_LOOP_END)] -+ "NDS32_HW_LOOP_P ()" -+ "mtlbi\t%0" -+ [(set_attr "length" "4")]) -+ -+(define_insn "mtlbi" -+ [(set (reg:SI LB_REGNUM) -+ (match_operand:SI 0 "nds32_label_operand" "i"))] -+ "NDS32_HW_LOOP_P ()" -+ "mtlbi\t%0" -+ [(set_attr "length" "4")]) -+ -+(define_insn "mtlei" -+ [(set (reg:SI LE_REGNUM) -+ (match_operand:SI 0 "nds32_label_operand" "i"))] -+ "NDS32_HW_LOOP_P ()" -+ "mtlei\t%0" -+ [(set_attr "length" "4")]) -+ -+(define_insn "init_lc" -+ [(set (reg:SI LC_REGNUM) -+ (match_operand:SI 0 "register_operand" "r")) -+ (unspec [(match_operand 1 "const_int_operand" "i")] UNSPEC_LOOP_END)] -+ "NDS32_HW_LOOP_P ()" -+ "mtusr\t%0, LC" -+ [(set_attr "length" "4")]) -+ -+; After replace hwloop, use this is pattern to get right CFG -+(define_insn "hwloop_cfg" -+ [(set (pc) -+ (if_then_else (ne (reg:SI LC_REGNUM) -+ (const_int 1)) -+ (match_operand:SI 1 "nds32_label_operand" "i") -+ (pc))) -+ (set (reg:SI LC_REGNUM) -+ (plus:SI (reg:SI LC_REGNUM) -+ (const_int -1))) -+ (use (reg:SI LB_REGNUM)) -+ (use (reg:SI LE_REGNUM)) -+ (use (reg:SI LC_REGNUM)) -+ (unspec [(match_operand 0 "const_int_operand" "i")] UNSPEC_LOOP_END)] -+ "TARGET_HWLOOP" -+ "" -+ [(set_attr "length" "0")]) -+;; ---------------------------------------------------------------------------- -+ -+;; Patterns for exception handling -+ -+(define_expand "eh_return" -+ [(use (match_operand 0 "general_operand"))] -+ "" -+{ -+ emit_insn (gen_nds32_eh_return (operands[0])); -+ DONE; -+}) -+ -+(define_insn_and_split "nds32_eh_return" -+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_EH_RETURN)] -+ "" -+ "#" -+ "reload_completed" -+ [(const_int 0)] -+{ -+ rtx place; -+ rtx addr; -+ -+ /* The operands[0] is the handler address. We need to assign it -+ to return address rtx so that we can jump to exception handler -+ when returning from current function. */ -+ -+ if (cfun->machine->lp_size == 0) -+ { -+ /* If $lp is not saved in the stack frame, we can take $lp directly. */ -+ place = gen_rtx_REG (SImode, LP_REGNUM); -+ } -+ else -+ { -+ /* Otherwise, we need to locate the stack slot of return address. -+ The return address is generally saved in [$fp-4] location. -+ However, DSE (dead store elimination) does not detect an alias -+ between [$fp-x] and [$sp+y]. This can result in a store to save -+ $lp introduced by builtin_eh_return() being incorrectly deleted -+ if it is based on $fp. The solution we take here is to compute -+ the offset relative to stack pointer and then use $sp to access -+ location so that the alias can be detected. -+ FIXME: What if the immediate value "offset" is too large to be -+ fit in a single addi instruction? */ -+ HOST_WIDE_INT offset; -+ -+ offset = (cfun->machine->fp_size -+ + cfun->machine->gp_size -+ + cfun->machine->lp_size -+ + cfun->machine->callee_saved_gpr_regs_size -+ + cfun->machine->callee_saved_area_gpr_padding_bytes -+ + cfun->machine->callee_saved_fpr_regs_size -+ + cfun->machine->eh_return_data_regs_size -+ + cfun->machine->local_size -+ + cfun->machine->out_args_size); -+ -+ addr = plus_constant (Pmode, stack_pointer_rtx, offset - 4); -+ place = gen_frame_mem (SImode, addr); -+ } -+ -+ emit_move_insn (place, operands[0]); -+ DONE; -+}) -+ -+;; ---------------------------------------------------------------------------- -+ -+;; 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 938136f..a70ced9 100644 ---- a/gcc/config/nds32/nds32.opt -+++ b/gcc/config/nds32/nds32.opt -@@ -21,14 +21,67 @@ - HeaderInclude - config/nds32/nds32-opts.h - --mbig-endian --Target Report RejectNegative Negative(mlittle-endian) Mask(BIG_ENDIAN) -+; --------------------------------------------------------------- -+; The following options are designed for aliasing and compatibility options. -+ -+EB -+Target RejectNegative Alias(mbig-endian) - Generate code in big-endian mode. - --mlittle-endian --Target Report RejectNegative Negative(mbig-endian) InverseMask(BIG_ENDIAN) -+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. -+ -+m16bit -+Target Undocumented Alias(m16-bit) -+Generate 16-bit instructions. -+ -+mcrt-arg=yes -+Target Undocumented Alias(mcrt-arg) -+Obsolete option. Users SHOULD NOT use this option in the command line. -+ -+mreduce-regs -+Target Undocumented Alias(mreduced-regs) -+Use reduced-set registers for register allocation. -+ -+mcache-line-size= -+Target RejectNegative Joined UInteger Undocumented Alias(mcache-block-size=) -+Alias of -mcache-block-size= -+ -+; --------------------------------------------------------------- -+ -+mabi= -+Target RejectNegative Joined Enum(abi_type) Var(nds32_abi) Init(TARGET_DEFAULT_ABI) -+Specify which ABI type to generate code for: 2, 2fp+. -+ -+Enum -+Name(abi_type) Type(enum abi_type) -+Known ABIs (for use with the -mabi= option): -+ -+EnumValue -+Enum(abi_type) String(2) Value(NDS32_ABI_V2) -+ -+EnumValue -+Enum(abi_type) String(2fp+) Value(NDS32_ABI_V2_FP_PLUS) -+ -+mfloat-abi=soft -+Target RejectNegative Alias(mabi=, 2) -+Specify use soft floating point ABI which mean alias to -mabi=2. -+ -+mfloat-abi=hard -+Target RejectNegative Alias(mabi=, 2fp+) -+Specify use soft floating point ABI which mean alias to -mabi=2fp+. -+ -+; --------------------------------------------------------------- -+ - mreduced-regs - Target Report RejectNegative Negative(mfull-regs) Mask(REDUCED_REGS) - Use reduced-set registers for register allocation. -@@ -37,14 +90,148 @@ mfull-regs - Target Report RejectNegative Negative(mreduced-regs) InverseMask(REDUCED_REGS) - Use full-set registers for register allocation. - -+; --------------------------------------------------------------- -+ -+Os1 -+Target -+Optimize for size level 1. This option will disable IFC and EX9 to prevent performance drop. -+ -+Os2 -+Target -+Optimize for size level 2. This option will disable IFC and EX9 for innermost loop to prevent performance drop. -+ -+Os3 -+Target -+Optimize for size level 3 which mean don't care performance. -+ -+malways-align -+Target Mask(ALWAYS_ALIGN) -+Always align function entry, jump target and return address. -+ -+malign-functions -+Target Mask(ALIGN_FUNCTION) -+Align function entry to 4 byte. -+ -+mbig-endian -+Target Undocumented RejectNegative Negative(mlittle-endian) Mask(BIG_ENDIAN) -+Generate code in big-endian mode. -+ -+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'. -+ -+minline-strcpy -+Target Undocumented Mask(INLINE_STRCPY) -+Inlining strcpy function. -+ -+mload-store-opt -+Target Mask(LOAD_STORE_OPT) -+Enable load store optimization. -+ -+mregrename -+Target Mask(REGRENAME_OPT) -+Enable target dependent register rename optimization. -+ -+mgcse -+Target Mask(GCSE_OPT) -+Enable target dependent global CSE optimization. -+ -+mconst-remater -+Target Var(flag_nds32_const_remater_opt) -+Enable target dependent constant remeterialization optimization. -+ -+msoft-fp-arith-comm -+Target Mask(SOFT_FP_ARITH_COMM) -+Enable operand commutative for soft floating point arithmetic optimization. -+ -+msign-conversion -+Target Var(flag_nds32_sign_conversion) -+Enable the sign conversion in Gimple level. -+ -+mscalbn-transform -+Target Var(flag_nds32_scalbn_transform) -+Enable the scalbn transform in Gimple level. -+ -+mlmwsmw-opt -+Target Var(flag_nds32_lmwsmw_opt) -+Enable the load/store multiple optimization. -+ -+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) -+ -+mlmwsmw-cost= -+Target RejectNegative Joined Enum(lmwsmw_cost_type) Var(flag_lmwsmw_cost) Init(LMWSMW_OPT_AUTO) -+Specify the load/store insn generate to lmw/smw. -+ -+Enum -+Name(lmwsmw_cost_type) Type(enum lmwsmw_cost_type) -+Known lmwsmw cost type (for use with the -mlmwsmw-cost= option): -+ -+EnumValue -+Enum(lmwsmw_cost_type) String(size) Value(LMWSMW_OPT_SIZE) -+ -+EnumValue -+Enum(lmwsmw_cost_type) String(speed) Value(LMWSMW_OPT_SPEED) -+ -+EnumValue -+Enum(lmwsmw_cost_type) String(all) Value(LMWSMW_OPT_ALL) -+ -+EnumValue -+Enum(lmwsmw_cost_type) String(auto) Value(LMWSMW_OPT_AUTO) -+ -+mabi-compatible -+Target Var(flag_nds32_abi_compatible) -+Enable the ABI compatible detection. -+ -+mcprop-acc -+Target Var(flag_nds32_cprop_acc) -+Enable the copy propagation for accumulate style instructions. -+ -+; --------------------------------------------------------------- -+ - mcmov - Target Report Mask(CMOV) - Generate conditional move instructions. - --mperf-ext --Target Report Mask(PERF_EXT) -+mhw-abs -+Target Report Mask(HW_ABS) -+Generate hardware abs instructions. -+ -+mext-perf -+Target Report Mask(EXT_PERF) - Generate performance extension instructions. - -+mext-perf2 -+Target Report Mask(EXT_PERF2) -+Generate performance extension version 2 instructions. -+ -+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. -@@ -53,10 +240,22 @@ m16-bit - Target Report Mask(16_BIT) - Generate 16-bit instructions. - -+mrelax-hint -+Target Report Mask(RELAX_HINT) -+Insert relax hint for linker to do relaxation. -+ -+mvh -+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) -+Target RejectNegative Joined UInteger Var(nds32_isr_vector_size) Init(NDS32_DEFAULT_ISR_VECTOR_SIZE) Condition(!TARGET_LINUX_ABI) - 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. -@@ -73,32 +272,418 @@ EnumValue - Enum(nds32_arch_type) String(v2) Value(ARCH_V2) - - EnumValue -+Enum(nds32_arch_type) String(v2j) Value(ARCH_V2J) -+ -+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) - --mcmodel= --Target RejectNegative Joined Enum(nds32_cmodel_type) Var(nds32_cmodel_option) Init(CMODEL_MEDIUM) --Specify the address generation strategy for code model. -+EnumValue -+Enum(nds32_arch_type) String(v3m+) Value(ARCH_V3M_PLUS) -+ -+EnumValue -+Enum(nds32_arch_type) String(v3f) Value(ARCH_V3F) -+ -+EnumValue -+Enum(nds32_arch_type) String(v3s) Value(ARCH_V3S) -+ -+mcpu= -+Target RejectNegative Joined Enum(nds32_cpu_type) Var(nds32_cpu_option) Init(CPU_N9) -+Specify the cpu for pipeline model. - - Enum --Name(nds32_cmodel_type) Type(enum nds32_cmodel_type) --Known cmodel types (for use with the -mcmodel= option): -+Name(nds32_cpu_type) Type(enum nds32_cpu_type) -+Known cpu types (for use with the -mcpu= option): -+ -+EnumValue -+Enum(nds32_cpu_type) String(n6) Value(CPU_N6) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n650) Value(CPU_N6) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n7) Value(CPU_N7) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n705) Value(CPU_N7) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n8) Value(CPU_N8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n801) Value(CPU_N8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(sn8) Value(CPU_N8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(sn801) Value(CPU_N8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(s8) Value(CPU_N8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(s801) Value(CPU_N8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(e8) Value(CPU_E8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(e801) Value(CPU_E8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n820) Value(CPU_E8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(s830) Value(CPU_E8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(e830) Value(CPU_E8) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n9) Value(CPU_N9) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n903) Value(CPU_N9) -+ -+EnumValue -+Enum(nds32_cpu_type) String(n903a) Value(CPU_N9) -+ -+EnumValue -+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_cmodel_type) String(small) Value(CMODEL_SMALL) -+Enum(nds32_cpu_type) String(n1068) Value(CPU_N10) - - EnumValue --Enum(nds32_cmodel_type) String(medium) Value(CMODEL_MEDIUM) -+Enum(nds32_cpu_type) String(n1068a) Value(CPU_N10) - - EnumValue --Enum(nds32_cmodel_type) String(large) Value(CMODEL_LARGE) -+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) Undocumented String(panther) Value(CPU_PANTHER) -+ -+EnumValue -+Enum(nds32_cpu_type) Undocumented String(simple) Value(CPU_SIMPLE) -+ -+mcpu=n15 -+Target RejectNegative Undocumented Alias(mcpu=, graywolf) -+Alias for multi-lib work. -+ -+mcpu=n15f -+Target RejectNegative Undocumented Alias(mcpu=, graywolf) -+Alias for multi-lib work. -+ -+mcpu=n15s -+Target RejectNegative Undocumented Alias(mcpu=, graywolf) -+Alias for multi-lib work. -+ -+mcpu=d15 -+Target RejectNegative Undocumented Alias(mcpu=, graywolf) -+Alias for multi-lib work. -+ -+mcpu=d15s -+Target RejectNegative Undocumented Alias(mcpu=, graywolf) -+Alias for multi-lib work. -+ -+mcpu=d15f -+Target RejectNegative Undocumented Alias(mcpu=, graywolf) -+Alias for multi-lib work. -+ -+mgraywolf -+Target RejectNegative Undocumented Alias(mcpu=, graywolf) -+This alias is only for gcc parallel test. -+ -+mv3m+ -+Target RejectNegative Undocumented Alias(march=, v3m+) -+This alias is only for gcc parallel test. -+ -+mmemory-model= -+Target RejectNegative Joined Enum(nds32_memory_model_type) Var(nds32_memory_model_option) Init(MEMORY_MODEL_FAST) -+Specify the memory model, fast or slow memory. -+ -+Enum -+Name(nds32_memory_model_type) Type(enum nds32_memory_model_type) -+ -+EnumValue -+Enum(nds32_memory_model_type) String(slow) Value(MEMORY_MODEL_SLOW) -+ -+EnumValue -+Enum(nds32_memory_model_type) String(fast) Value(MEMORY_MODEL_FAST) -+ -+mconfig-fpu= -+Target RejectNegative Joined Enum(float_reg_number) Var(nds32_fp_regnum) Init(TARGET_CONFIG_FPU_DEFAULT) -+Specify a fpu configuration value from 0 to 7; 0-3 is as FPU spec says, and 4-7 is corresponding to 0-3. -+ -+Enum -+Name(float_reg_number) Type(enum float_reg_number) -+Known floating-point number of registers (for use with the -mconfig-fpu= option): -+ -+EnumValue -+Enum(float_reg_number) String(0) Value(NDS32_CONFIG_FPU_0) -+ -+EnumValue -+Enum(float_reg_number) String(1) Value(NDS32_CONFIG_FPU_1) -+ -+EnumValue -+Enum(float_reg_number) String(2) Value(NDS32_CONFIG_FPU_2) -+ -+EnumValue -+Enum(float_reg_number) String(3) Value(NDS32_CONFIG_FPU_3) -+ -+EnumValue -+Enum(float_reg_number) String(4) Value(NDS32_CONFIG_FPU_4) -+ -+EnumValue -+Enum(float_reg_number) String(5) Value(NDS32_CONFIG_FPU_5) -+ -+EnumValue -+Enum(float_reg_number) String(6) Value(NDS32_CONFIG_FPU_6) -+ -+EnumValue -+Enum(float_reg_number) String(7) Value(NDS32_CONFIG_FPU_7) -+ -+mconfig-mul= -+Target RejectNegative Joined Enum(nds32_mul_type) Var(nds32_mul_config) Init(MUL_TYPE_FAST_1) -+Specify configuration of instruction mul: fast1, fast2 or slow. The default is fast1. -+ -+Enum -+Name(nds32_mul_type) Type(enum nds32_mul_type) -+ -+EnumValue -+Enum(nds32_mul_type) String(fast) Value(MUL_TYPE_FAST_1) -+ -+EnumValue -+Enum(nds32_mul_type) String(fast1) Value(MUL_TYPE_FAST_1) -+ -+EnumValue -+Enum(nds32_mul_type) String(fast2) Value(MUL_TYPE_FAST_2) -+ -+EnumValue -+Enum(nds32_mul_type) String(slow) Value(MUL_TYPE_SLOW) -+ -+mconfig-register-ports= -+Target RejectNegative Joined Enum(nds32_register_ports) Var(nds32_register_ports_config) Init(REG_PORT_3R2W) -+Specify how many read/write ports for n9/n10 cores. The value should be 3r2w or 2r1w. -+ -+Enum -+Name(nds32_register_ports) Type(enum nds32_register_ports) -+ -+EnumValue -+Enum(nds32_register_ports) String(3r2w) Value(REG_PORT_3R2W) -+ -+EnumValue -+Enum(nds32_register_ports) String(2r1w) Value(REG_PORT_2R1W) -+ -+mreorg-out-of-order -+Target Report Var(flag_reorg_out_of_order) Init(0) -+Allow out-of-order reorganization for multiple issue micro-architectures. -+ -+mifc -+Target Report Mask(IFC) -+Use special directives to guide linker doing ifc optimization. -+ -+mex9 -+Target Report Mask(EX9) -+Use special directives to guide linker doing ex9 optimization. -+ -+mprint-stall-cycles -+Target Report Mask(PRINT_STALLS) -+Print stall cycles due to structural or data dependencies. It should be used with the option '-S'. -+Note that stall cycles are determined by the compiler's pipeline model and it may not be precise. - - mctor-dtor - Target Report - Enable constructor/destructor feature. - -+mcrt-arg -+Target Report -+Enable argc/argv passed by simulator. -+ - mrelax - Target Report - Guide linker to relax instructions. -+ -+minnermost-loop -+Target Report Mask(INNERMOST_LOOP) -+Insert the innermost loop directive. -+ -+mext-fpu-fma -+Target Report Mask(EXT_FPU_FMA) -+Generate floating-point multiply-accumulation instructions. -+ -+mext-fpu-sp -+Target Report Mask(FPU_SINGLE) -+Generate single-precision floating-point instructions. -+ -+mext-fpu-dp -+Target Report Mask(FPU_DOUBLE) -+Generate double-precision floating-point instructions. -+ -+mext-zol -+Target Report Mask(HWLOOP) -+Insert the hardware loop directive. -+ -+mforce-no-ext-zol -+Target Undocumented Report Mask(FORCE_NO_HWLOOP) -+Force disable hardware loop, even use -mext-zol. -+ -+mforce-no-ext-dsp -+Target Undocumented Report Mask(FORCE_NO_EXT_DSP) -+Force disable hardware loop, even use -mext-dsp. -+ -+mforce-memcpy-zol -+Target Report Var(flag_force_memcpy_zol) Init(0) -+Force enable hardware loop in memcpy function. -+ -+msched-prolog-epilog -+Target Var(flag_sched_prolog_epilog) Init(1) -+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. -+ -+munaligned-access -+Target Report Var(flag_unaligned_access) Init(0) -+Enable unaligned word and halfword accesses to packed data. -+ -+; --------------------------------------------------------------- -+; The following options are designed for compatibility issue. -+; Hopefully these obsolete options will be removed one day. -+ -+mg -+Target Undocumented Warn(%qs is deprecated and has no effect) -+Obsolete option. Users SHOULD NOT use this option in the command line. -+ -+mdx-regs -+Target Undocumented Warn(%qs is deprecated and has no effect) -+Obsolete option. Users SHOULD NOT use this option in the command line. -+ -+mexpand-isr -+Target Undocumented Warn(%qs is deprecated and has no effect) -+Obsolete option. Users SHOULD NOT use this option in the command line. -+ -+mcrt-cpp=yes -+Target Undocumented Warn(%qs is deprecated and has no effect, use -mctor-dtor instead) -+Obsolete option. Users SHOULD NOT use this option in the command line. -+ -+mcrt-exit=yes -+Target Undocumented Warn(%qs is deprecated and has no effect, use -mctor-dtor instead) -+Obsolete option. Users SHOULD NOT use this option in the command line. -+ -+mlib= -+Target RejectNegative Joined Undocumented Warn(%qs is deprecated and has no effect) -+Obsolete option. Users SHOULD NOT use this option in the command line. -+ -+; --------------------------------------------------------------- -+; The following options are designed for compatibility issue. -+; Hopefully these obsolete options will be removed one day. -+ -+mace -+Target RejectNegative -+Compile with Andes ACE. -+ -+mace-s2s= -+Target Joined RejectNegative -+Argument for pass to Andes's ACE source-to-source translator. -+ -+ -+; --------------------------------------------------------------- -diff --git a/gcc/config/nds32/nds32_init.inc b/gcc/config/nds32/nds32_init.inc -new file mode 100644 -index 0000000..1084ad0 ---- /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 3e868dc..fef727b 100644 ---- a/gcc/config/nds32/nds32_intrinsic.h -+++ b/gcc/config/nds32/nds32_intrinsic.h -@@ -26,12 +26,1383 @@ - #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 - { -- __NDS32_REG_PSW__ = 1024, -+ __NDS32_REG_CPU_VER__ = 1024, -+ __NDS32_REG_ICM_CFG__, -+ __NDS32_REG_DCM_CFG__, -+ __NDS32_REG_MMU_CFG__, -+ __NDS32_REG_MSC_CFG__, -+ __NDS32_REG_MSC_CFG2__, -+ __NDS32_REG_CORE_ID__, -+ __NDS32_REG_FUCOP_EXIST__, -+ -+ __NDS32_REG_PSW__, - __NDS32_REG_IPSW__, -+ __NDS32_REG_P_IPSW__, -+ __NDS32_REG_IVB__, -+ __NDS32_REG_EVA__, -+ __NDS32_REG_P_EVA__, - __NDS32_REG_ITYPE__, -- __NDS32_REG_IPC__ -+ __NDS32_REG_P_ITYPE__, -+ -+ __NDS32_REG_MERR__, -+ __NDS32_REG_IPC__, -+ __NDS32_REG_P_IPC__, -+ __NDS32_REG_OIPC__, -+ __NDS32_REG_P_P0__, -+ __NDS32_REG_P_P1__, -+ -+ __NDS32_REG_INT_MASK__, -+ __NDS32_REG_INT_MASK2__, -+ __NDS32_REG_INT_MASK3__, -+ __NDS32_REG_INT_PEND__, -+ __NDS32_REG_INT_PEND2__, -+ __NDS32_REG_INT_PEND3__, -+ __NDS32_REG_SP_USR__, -+ __NDS32_REG_SP_PRIV__, -+ __NDS32_REG_INT_PRI__, -+ __NDS32_REG_INT_PRI2__, -+ __NDS32_REG_INT_PRI3__, -+ __NDS32_REG_INT_PRI4__, -+ __NDS32_REG_INT_CTRL__, -+ __NDS32_REG_INT_TRIGGER__, -+ __NDS32_REG_INT_TRIGGER2__, -+ __NDS32_REG_INT_GPR_PUSH_DIS__, -+ -+ __NDS32_REG_MMU_CTL__, -+ __NDS32_REG_L1_PPTB__, -+ __NDS32_REG_TLB_VPN__, -+ __NDS32_REG_TLB_DATA__, -+ __NDS32_REG_TLB_MISC__, -+ __NDS32_REG_VLPT_IDX__, -+ __NDS32_REG_ILMB__, -+ __NDS32_REG_DLMB__, -+ -+ __NDS32_REG_CACHE_CTL__, -+ __NDS32_REG_HSMP_SADDR__, -+ __NDS32_REG_HSMP_EADDR__, -+ __NDS32_REG_SDZ_CTL__, -+ __NDS32_REG_N12MISC_CTL__, -+ __NDS32_REG_MISC_CTL__, -+ __NDS32_REG_ECC_MISC__, -+ -+ __NDS32_REG_BPC0__, -+ __NDS32_REG_BPC1__, -+ __NDS32_REG_BPC2__, -+ __NDS32_REG_BPC3__, -+ __NDS32_REG_BPC4__, -+ __NDS32_REG_BPC5__, -+ __NDS32_REG_BPC6__, -+ __NDS32_REG_BPC7__, -+ -+ __NDS32_REG_BPA0__, -+ __NDS32_REG_BPA1__, -+ __NDS32_REG_BPA2__, -+ __NDS32_REG_BPA3__, -+ __NDS32_REG_BPA4__, -+ __NDS32_REG_BPA5__, -+ __NDS32_REG_BPA6__, -+ __NDS32_REG_BPA7__, -+ -+ __NDS32_REG_BPAM0__, -+ __NDS32_REG_BPAM1__, -+ __NDS32_REG_BPAM2__, -+ __NDS32_REG_BPAM3__, -+ __NDS32_REG_BPAM4__, -+ __NDS32_REG_BPAM5__, -+ __NDS32_REG_BPAM6__, -+ __NDS32_REG_BPAM7__, -+ -+ __NDS32_REG_BPV0__, -+ __NDS32_REG_BPV1__, -+ __NDS32_REG_BPV2__, -+ __NDS32_REG_BPV3__, -+ __NDS32_REG_BPV4__, -+ __NDS32_REG_BPV5__, -+ __NDS32_REG_BPV6__, -+ __NDS32_REG_BPV7__, -+ -+ __NDS32_REG_BPCID0__, -+ __NDS32_REG_BPCID1__, -+ __NDS32_REG_BPCID2__, -+ __NDS32_REG_BPCID3__, -+ __NDS32_REG_BPCID4__, -+ __NDS32_REG_BPCID5__, -+ __NDS32_REG_BPCID6__, -+ __NDS32_REG_BPCID7__, -+ -+ __NDS32_REG_EDM_CFG__, -+ __NDS32_REG_EDMSW__, -+ __NDS32_REG_EDM_CTL__, -+ __NDS32_REG_EDM_DTR__, -+ __NDS32_REG_BPMTC__, -+ __NDS32_REG_DIMBR__, -+ -+ __NDS32_REG_TECR0__, -+ __NDS32_REG_TECR1__, -+ __NDS32_REG_PFMC0__, -+ __NDS32_REG_PFMC1__, -+ __NDS32_REG_PFMC2__, -+ __NDS32_REG_PFM_CTL__, -+ __NDS32_REG_PFT_CTL__, -+ __NDS32_REG_HSP_CTL__, -+ __NDS32_REG_SP_BOUND__, -+ __NDS32_REG_SP_BOUND_PRIV__, -+ __NDS32_REG_SP_BASE__, -+ __NDS32_REG_SP_BASE_PRIV__, -+ __NDS32_REG_FUCOP_CTL__, -+ __NDS32_REG_PRUSR_ACC_CTL__, -+ -+ __NDS32_REG_DMA_CFG__, -+ __NDS32_REG_DMA_GCSW__, -+ __NDS32_REG_DMA_CHNSEL__, -+ __NDS32_REG_DMA_ACT__, -+ __NDS32_REG_DMA_SETUP__, -+ __NDS32_REG_DMA_ISADDR__, -+ __NDS32_REG_DMA_ESADDR__, -+ __NDS32_REG_DMA_TCNT__, -+ __NDS32_REG_DMA_STATUS__, -+ __NDS32_REG_DMA_2DSET__, -+ __NDS32_REG_DMA_2DSCTL__, -+ __NDS32_REG_DMA_RCNT__, -+ __NDS32_REG_DMA_HSTATUS__, -+ -+ __NDS32_REG_PC__, -+ __NDS32_REG_SP_USR1__, -+ __NDS32_REG_SP_USR2__, -+ __NDS32_REG_SP_USR3__, -+ __NDS32_REG_SP_PRIV1__, -+ __NDS32_REG_SP_PRIV2__, -+ __NDS32_REG_SP_PRIV3__, -+ __NDS32_REG_BG_REGION__, -+ __NDS32_REG_SFCR__, -+ __NDS32_REG_SIGN__, -+ __NDS32_REG_ISIGN__, -+ __NDS32_REG_P_ISIGN__, -+ __NDS32_REG_IFC_LP__, -+ __NDS32_REG_ITB__ - }; - -+/* The cctl subtype for intrinsic. */ -+enum nds32_cctl_valck -+{ -+ __NDS32_CCTL_L1D_VA_FILLCK__, -+ __NDS32_CCTL_L1D_VA_ULCK__, -+ __NDS32_CCTL_L1I_VA_FILLCK__, -+ __NDS32_CCTL_L1I_VA_ULCK__ -+}; -+ -+enum nds32_cctl_idxwbinv -+{ -+ __NDS32_CCTL_L1D_IX_WBINVAL__, -+ __NDS32_CCTL_L1D_IX_INVAL__, -+ __NDS32_CCTL_L1D_IX_WB__, -+ __NDS32_CCTL_L1I_IX_INVAL__ -+}; -+ -+enum nds32_cctl_vawbinv -+{ -+ __NDS32_CCTL_L1D_VA_INVAL__, -+ __NDS32_CCTL_L1D_VA_WB__, -+ __NDS32_CCTL_L1D_VA_WBINVAL__, -+ __NDS32_CCTL_L1I_VA_INVAL__ -+}; -+ -+enum nds32_cctl_idxread -+{ -+ __NDS32_CCTL_L1D_IX_RTAG__, -+ __NDS32_CCTL_L1D_IX_RWD__, -+ __NDS32_CCTL_L1I_IX_RTAG__, -+ __NDS32_CCTL_L1I_IX_RWD__ -+}; -+ -+enum nds32_cctl_idxwrite -+{ -+ __NDS32_CCTL_L1D_IX_WTAG__, -+ __NDS32_CCTL_L1D_IX_WWD__, -+ __NDS32_CCTL_L1I_IX_WTAG__, -+ __NDS32_CCTL_L1I_IX_WWD__ -+}; -+ -+enum nds32_dpref -+{ -+ __NDS32_DPREF_SRD__, -+ __NDS32_DPREF_MRD__, -+ __NDS32_DPREF_SWR__, -+ __NDS32_DPREF_MWR__, -+ __NDS32_DPREF_PTE__, -+ __NDS32_DPREF_CLWR__ -+}; -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* Define interrupt number for intrinsic function. */ -+#define NDS32_INT_H0 0 -+#define NDS32_INT_H1 1 -+#define NDS32_INT_H2 2 -+#define NDS32_INT_H3 3 -+#define NDS32_INT_H4 4 -+#define NDS32_INT_H5 5 -+#define NDS32_INT_H6 6 -+#define NDS32_INT_H7 7 -+#define NDS32_INT_H8 8 -+#define NDS32_INT_H9 9 -+#define NDS32_INT_H10 10 -+#define NDS32_INT_H11 11 -+#define NDS32_INT_H12 12 -+#define NDS32_INT_H13 13 -+#define NDS32_INT_H14 14 -+#define NDS32_INT_H15 15 -+#define NDS32_INT_H16 16 -+#define NDS32_INT_H17 17 -+#define NDS32_INT_H18 18 -+#define NDS32_INT_H19 19 -+#define NDS32_INT_H20 20 -+#define NDS32_INT_H21 21 -+#define NDS32_INT_H22 22 -+#define NDS32_INT_H23 23 -+#define NDS32_INT_H24 24 -+#define NDS32_INT_H25 25 -+#define NDS32_INT_H26 26 -+#define NDS32_INT_H27 27 -+#define NDS32_INT_H28 28 -+#define NDS32_INT_H29 29 -+#define NDS32_INT_H30 30 -+#define NDS32_INT_H31 31 -+#define NDS32_INT_H32 32 -+#define NDS32_INT_H33 33 -+#define NDS32_INT_H34 34 -+#define NDS32_INT_H35 35 -+#define NDS32_INT_H36 36 -+#define NDS32_INT_H37 37 -+#define NDS32_INT_H38 38 -+#define NDS32_INT_H39 39 -+#define NDS32_INT_H40 40 -+#define NDS32_INT_H41 41 -+#define NDS32_INT_H42 42 -+#define NDS32_INT_H43 43 -+#define NDS32_INT_H44 44 -+#define NDS32_INT_H45 45 -+#define NDS32_INT_H46 46 -+#define NDS32_INT_H47 47 -+#define NDS32_INT_H48 48 -+#define NDS32_INT_H49 49 -+#define NDS32_INT_H50 50 -+#define NDS32_INT_H51 51 -+#define NDS32_INT_H52 52 -+#define NDS32_INT_H53 53 -+#define NDS32_INT_H54 54 -+#define NDS32_INT_H55 55 -+#define NDS32_INT_H56 56 -+#define NDS32_INT_H57 57 -+#define NDS32_INT_H58 58 -+#define NDS32_INT_H59 59 -+#define NDS32_INT_H60 60 -+#define NDS32_INT_H61 61 -+#define NDS32_INT_H62 62 -+#define NDS32_INT_H63 63 -+#define NDS32_INT_SWI 64 -+#define NDS32_INT_ALZ 65 -+#define NDS32_INT_IDIVZE 66 -+#define NDS32_INT_DSSIM 67 -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* Define intrinsic register name macro for compatibility. */ -+#define NDS32_SR_CPU_VER __NDS32_REG_CPU_VER__ -+#define NDS32_SR_ICM_CFG __NDS32_REG_ICM_CFG__ -+#define NDS32_SR_DCM_CFG __NDS32_REG_DCM_CFG__ -+#define NDS32_SR_MMU_CFG __NDS32_REG_MMU_CFG__ -+#define NDS32_SR_MSC_CFG __NDS32_REG_MSC_CFG__ -+#define NDS32_SR_MSC_CFG2 __NDS32_REG_MSC_CFG2__ -+#define NDS32_SR_CORE_ID __NDS32_REG_CORE_ID__ -+#define NDS32_SR_FUCOP_EXIST __NDS32_REG_FUCOP_EXIST__ -+#define NDS32_SR_PSW __NDS32_REG_PSW__ -+#define NDS32_SR_IPSW __NDS32_REG_IPSW__ -+#define NDS32_SR_P_IPSW __NDS32_REG_P_IPSW__ -+#define NDS32_SR_IVB __NDS32_REG_IVB__ -+#define NDS32_SR_EVA __NDS32_REG_EVA__ -+#define NDS32_SR_P_EVA __NDS32_REG_P_EVA__ -+#define NDS32_SR_ITYPE __NDS32_REG_ITYPE__ -+#define NDS32_SR_P_ITYPE __NDS32_REG_P_ITYPE__ -+#define NDS32_SR_MERR __NDS32_REG_MERR__ -+#define NDS32_SR_IPC __NDS32_REG_IPC__ -+#define NDS32_SR_P_IPC __NDS32_REG_P_IPC__ -+#define NDS32_SR_OIPC __NDS32_REG_OIPC__ -+#define NDS32_SR_P_P0 __NDS32_REG_P_P0__ -+#define NDS32_SR_P_P1 __NDS32_REG_P_P1__ -+#define NDS32_SR_INT_MASK __NDS32_REG_INT_MASK__ -+#define NDS32_SR_INT_MASK2 __NDS32_REG_INT_MASK2__ -+#define NDS32_SR_INT_MASK3 __NDS32_REG_INT_MASK3__ -+#define NDS32_SR_INT_PEND __NDS32_REG_INT_PEND__ -+#define NDS32_SR_INT_PEND2 __NDS32_REG_INT_PEND2__ -+#define NDS32_SR_INT_PEND3 __NDS32_REG_INT_PEND3__ -+#define NDS32_SR_SP_USR __NDS32_REG_SP_USR__ -+#define NDS32_SR_SP_PRIV __NDS32_REG_SP_PRIV__ -+#define NDS32_SR_INT_PRI __NDS32_REG_INT_PRI__ -+#define NDS32_SR_INT_PRI2 __NDS32_REG_INT_PRI2__ -+#define NDS32_SR_INT_PRI3 __NDS32_REG_INT_PRI3__ -+#define NDS32_SR_INT_PRI4 __NDS32_REG_INT_PRI4__ -+#define NDS32_SR_INT_CTRL __NDS32_REG_INT_CTRL__ -+#define NDS32_SR_INT_TRIGGER __NDS32_REG_INT_TRIGGER__ -+#define NDS32_SR_INT_TRIGGER2 __NDS32_REG_INT_TRIGGER2__ -+#define NDS32_SR_INT_GPR_PUSH_DIS __NDS32_REG_INT_GPR_PUSH_DIS__ -+#define NDS32_SR_MMU_CTL __NDS32_REG_MMU_CTL__ -+#define NDS32_SR_L1_PPTB __NDS32_REG_L1_PPTB__ -+#define NDS32_SR_TLB_VPN __NDS32_REG_TLB_VPN__ -+#define NDS32_SR_TLB_DATA __NDS32_REG_TLB_DATA__ -+#define NDS32_SR_TLB_MISC __NDS32_REG_TLB_MISC__ -+#define NDS32_SR_VLPT_IDX __NDS32_REG_VLPT_IDX__ -+#define NDS32_SR_ILMB __NDS32_REG_ILMB__ -+#define NDS32_SR_DLMB __NDS32_REG_DLMB__ -+#define NDS32_SR_CACHE_CTL __NDS32_REG_CACHE_CTL__ -+#define NDS32_SR_HSMP_SADDR __NDS32_REG_HSMP_SADDR__ -+#define NDS32_SR_HSMP_EADDR __NDS32_REG_HSMP_EADDR__ -+#define NDS32_SR_SDZ_CTL __NDS32_REG_SDZ_CTL__ -+#define NDS32_SR_N12MISC_CTL __NDS32_REG_N12MISC_CTL__ -+#define NDS32_SR_MISC_CTL __NDS32_REG_MISC_CTL__ -+#define NDS32_SR_ECC_MISC __NDS32_REG_ECC_MISC__ -+#define NDS32_SR_BPC0 __NDS32_REG_BPC0__ -+#define NDS32_SR_BPC1 __NDS32_REG_BPC1__ -+#define NDS32_SR_BPC2 __NDS32_REG_BPC2__ -+#define NDS32_SR_BPC3 __NDS32_REG_BPC3__ -+#define NDS32_SR_BPC4 __NDS32_REG_BPC4__ -+#define NDS32_SR_BPC5 __NDS32_REG_BPC5__ -+#define NDS32_SR_BPC6 __NDS32_REG_BPC6__ -+#define NDS32_SR_BPC7 __NDS32_REG_BPC7__ -+#define NDS32_SR_BPA0 __NDS32_REG_BPA0__ -+#define NDS32_SR_BPA1 __NDS32_REG_BPA1__ -+#define NDS32_SR_BPA2 __NDS32_REG_BPA2__ -+#define NDS32_SR_BPA3 __NDS32_REG_BPA3__ -+#define NDS32_SR_BPA4 __NDS32_REG_BPA4__ -+#define NDS32_SR_BPA5 __NDS32_REG_BPA5__ -+#define NDS32_SR_BPA6 __NDS32_REG_BPA6__ -+#define NDS32_SR_BPA7 __NDS32_REG_BPA7__ -+#define NDS32_SR_BPAM0 __NDS32_REG_BPAM0__ -+#define NDS32_SR_BPAM1 __NDS32_REG_BPAM1__ -+#define NDS32_SR_BPAM2 __NDS32_REG_BPAM2__ -+#define NDS32_SR_BPAM3 __NDS32_REG_BPAM3__ -+#define NDS32_SR_BPAM4 __NDS32_REG_BPAM4__ -+#define NDS32_SR_BPAM5 __NDS32_REG_BPAM5__ -+#define NDS32_SR_BPAM6 __NDS32_REG_BPAM6__ -+#define NDS32_SR_BPAM7 __NDS32_REG_BPAM7__ -+#define NDS32_SR_BPV0 __NDS32_REG_BPV0__ -+#define NDS32_SR_BPV1 __NDS32_REG_BPV1__ -+#define NDS32_SR_BPV2 __NDS32_REG_BPV2__ -+#define NDS32_SR_BPV3 __NDS32_REG_BPV3__ -+#define NDS32_SR_BPV4 __NDS32_REG_BPV4__ -+#define NDS32_SR_BPV5 __NDS32_REG_BPV5__ -+#define NDS32_SR_BPV6 __NDS32_REG_BPV6__ -+#define NDS32_SR_BPV7 __NDS32_REG_BPV7__ -+#define NDS32_SR_BPCID0 __NDS32_REG_BPCID0__ -+#define NDS32_SR_BPCID1 __NDS32_REG_BPCID1__ -+#define NDS32_SR_BPCID2 __NDS32_REG_BPCID2__ -+#define NDS32_SR_BPCID3 __NDS32_REG_BPCID3__ -+#define NDS32_SR_BPCID4 __NDS32_REG_BPCID4__ -+#define NDS32_SR_BPCID5 __NDS32_REG_BPCID5__ -+#define NDS32_SR_BPCID6 __NDS32_REG_BPCID6__ -+#define NDS32_SR_BPCID7 __NDS32_REG_BPCID7__ -+#define NDS32_SR_EDM_CFG __NDS32_REG_EDM_CFG__ -+#define NDS32_SR_EDMSW __NDS32_REG_EDMSW__ -+#define NDS32_SR_EDM_CTL __NDS32_REG_EDM_CTL__ -+#define NDS32_SR_EDM_DTR __NDS32_REG_EDM_DTR__ -+#define NDS32_SR_BPMTC __NDS32_REG_BPMTC__ -+#define NDS32_SR_DIMBR __NDS32_REG_DIMBR__ -+#define NDS32_SR_TECR0 __NDS32_REG_TECR0__ -+#define NDS32_SR_TECR1 __NDS32_REG_TECR1__ -+#define NDS32_SR_PFMC0 __NDS32_REG_PFMC0__ -+#define NDS32_SR_PFMC1 __NDS32_REG_PFMC1__ -+#define NDS32_SR_PFMC2 __NDS32_REG_PFMC2__ -+#define NDS32_SR_PFM_CTL __NDS32_REG_PFM_CTL__ -+#define NDS32_SR_HSP_CTL __NDS32_REG_HSP_CTL__ -+#define NDS32_SR_SP_BOUND __NDS32_REG_SP_BOUND__ -+#define NDS32_SR_SP_BOUND_PRIV __NDS32_REG_SP_BOUND_PRIV__ -+#define NDS32_SR_SP_BASE __NDS32_REG_SP_BASE__ -+#define NDS32_SR_SP_BASE_PRIV __NDS32_REG_SP_BASE_PRIV__ -+#define NDS32_SR_FUCOP_CTL __NDS32_REG_FUCOP_CTL__ -+#define NDS32_SR_PRUSR_ACC_CTL __NDS32_REG_PRUSR_ACC_CTL__ -+#define NDS32_SR_DMA_CFG __NDS32_REG_DMA_CFG__ -+#define NDS32_SR_DMA_GCSW __NDS32_REG_DMA_GCSW__ -+#define NDS32_SR_DMA_CHNSEL __NDS32_REG_DMA_CHNSEL__ -+#define NDS32_SR_DMA_ACT __NDS32_REG_DMA_ACT__ -+#define NDS32_SR_DMA_SETUP __NDS32_REG_DMA_SETUP__ -+#define NDS32_SR_DMA_ISADDR __NDS32_REG_DMA_ISADDR__ -+#define NDS32_SR_DMA_ESADDR __NDS32_REG_DMA_ESADDR__ -+#define NDS32_SR_DMA_TCNT __NDS32_REG_DMA_TCNT__ -+#define NDS32_SR_DMA_STATUS __NDS32_REG_DMA_STATUS__ -+#define NDS32_SR_DMA_2DSET __NDS32_REG_DMA_2DSET__ -+#define NDS32_SR_DMA_2DSCTL __NDS32_REG_DMA_2DSCTL__ -+#define NDS32_SR_DMA_RCNT __NDS32_REG_DMA_RCNT__ -+#define NDS32_SR_DMA_HSTATUS __NDS32_REG_DMA_HSTATUS__ -+#define NDS32_SR_SP_USR1 __NDS32_REG_SP_USR1__ -+#define NDS32_SR_SP_USR2 __NDS32_REG_SP_USR2__ -+#define NDS32_SR_SP_USR3 __NDS32_REG_SP_USR3__ -+#define NDS32_SR_SP_PRIV1 __NDS32_REG_SP_PRIV1__ -+#define NDS32_SR_SP_PRIV2 __NDS32_REG_SP_PRIV2__ -+#define NDS32_SR_SP_PRIV3 __NDS32_REG_SP_PRIV3__ -+#define NDS32_SR_BG_REGION __NDS32_REG_BG_REGION__ -+#define NDS32_SR_SFCR __NDS32_REG_SFCR__ -+#define NDS32_SR_SIGN __NDS32_REG_SIGN__ -+#define NDS32_SR_ISIGN __NDS32_REG_ISIGN__ -+#define NDS32_SR_P_ISIGN __NDS32_REG_P_ISIGN__ -+ -+#define NDS32_USR_PC __NDS32_REG_PC__ -+#define NDS32_USR_DMA_CFG __NDS32_REG_DMA_CFG__ -+#define NDS32_USR_DMA_GCSW __NDS32_REG_DMA_GCSW__ -+#define NDS32_USR_DMA_CHNSEL __NDS32_REG_DMA_CHNSEL__ -+#define NDS32_USR_DMA_ACT __NDS32_REG_DMA_ACT__ -+#define NDS32_USR_DMA_SETUP __NDS32_REG_DMA_SETUP__ -+#define NDS32_USR_DMA_ISADDR __NDS32_REG_DMA_ISADDR__ -+#define NDS32_USR_DMA_ESADDR __NDS32_REG_DMA_ESADDR__ -+#define NDS32_USR_DMA_TCNT __NDS32_REG_DMA_TCNT__ -+#define NDS32_USR_DMA_STATUS __NDS32_REG_DMA_STATUS__ -+#define NDS32_USR_DMA_2DSET __NDS32_REG_DMA_2DSET__ -+#define NDS32_USR_DMA_2DSCTL __NDS32_REG_DMA_2DSCTL__ -+#define NDS32_USR_PFMC0 __NDS32_REG_PFMC0__ -+#define NDS32_USR_PFMC1 __NDS32_REG_PFMC1__ -+#define NDS32_USR_PFMC2 __NDS32_REG_PFMC2__ -+#define NDS32_USR_PFM_CTL __NDS32_REG_PFM_CTL__ -+#define NDS32_USR_IFC_LP __NDS32_REG_IFC_LP__ -+#define NDS32_USR_ITB __NDS32_REG_ITB__ -+ -+#define NDS32_CCTL_L1D_VA_FILLCK __NDS32_CCTL_L1D_VA_FILLCK__ -+#define NDS32_CCTL_L1D_VA_ULCK __NDS32_CCTL_L1D_VA_ULCK__ -+#define NDS32_CCTL_L1I_VA_FILLCK __NDS32_CCTL_L1I_VA_FILLCK__ -+#define NDS32_CCTL_L1I_VA_ULCK __NDS32_CCTL_L1I_VA_ULCK__ -+ -+#define NDS32_CCTL_L1D_IX_WBINVAL __NDS32_CCTL_L1D_IX_WBINVAL__ -+#define NDS32_CCTL_L1D_IX_INVAL __NDS32_CCTL_L1D_IX_INVAL__ -+#define NDS32_CCTL_L1D_IX_WB __NDS32_CCTL_L1D_IX_WB__ -+#define NDS32_CCTL_L1I_IX_INVAL __NDS32_CCTL_L1I_IX_INVAL__ -+ -+#define NDS32_CCTL_L1D_VA_INVAL __NDS32_CCTL_L1D_VA_INVAL__ -+#define NDS32_CCTL_L1D_VA_WB __NDS32_CCTL_L1D_VA_WB__ -+#define NDS32_CCTL_L1D_VA_WBINVAL __NDS32_CCTL_L1D_VA_WBINVAL__ -+#define NDS32_CCTL_L1I_VA_INVAL __NDS32_CCTL_L1I_VA_INVAL__ -+ -+#define NDS32_CCTL_L1D_IX_RTAG __NDS32_CCTL_L1D_IX_RTAG__ -+#define NDS32_CCTL_L1D_IX_RWD __NDS32_CCTL_L1D_IX_RWD__ -+#define NDS32_CCTL_L1I_IX_RTAG __NDS32_CCTL_L1I_IX_RTAG__ -+#define NDS32_CCTL_L1I_IX_RWD __NDS32_CCTL_L1I_IX_RWD__ -+ -+#define NDS32_CCTL_L1D_IX_WTAG __NDS32_CCTL_L1D_IX_WTAG__ -+#define NDS32_CCTL_L1D_IX_WWD __NDS32_CCTL_L1D_IX_WWD__ -+#define NDS32_CCTL_L1I_IX_WTAG __NDS32_CCTL_L1I_IX_WTAG__ -+#define NDS32_CCTL_L1I_IX_WWD __NDS32_CCTL_L1I_IX_WWD__ -+ -+#define NDS32_DPREF_SRD __NDS32_DPREF_SRD__ -+#define NDS32_DPREF_MRD __NDS32_DPREF_MRD__ -+#define NDS32_DPREF_SWR __NDS32_DPREF_SWR__ -+#define NDS32_DPREF_MWR __NDS32_DPREF_MWR__ -+#define NDS32_DPREF_PTE __NDS32_DPREF_PTE__ -+#define NDS32_DPREF_CLWR __NDS32_DPREF_CLWR__ -+ -+/* ------------------------------------------------------------------------ */ -+ -+/* Define user friendly macro. */ -+#define SIGNATURE_BEGIN __nds32__signature_begin () -+#define SIGNATURE_END __nds32__signature_end () -+ -+/* Map __nds32__xxx() to __builtin_xxx() functions for compatibility. */ -+#define __nds32__llw(a) \ -+ (__builtin_nds32_llw ((a))) -+#define __nds32__lwup(a) \ -+ (__builtin_nds32_lwup ((a))) -+#define __nds32__lbup(a) \ -+ (__builtin_nds32_lbup ((a))) -+#define __nds32__scw(a, b) \ -+ (__builtin_nds32_scw ((a), (b))) -+#define __nds32__swup(a, b) \ -+ (__builtin_nds32_swup ((a), (b))) -+#define __nds32__sbup(a, b) \ -+ (__builtin_nds32_sbup ((a), (b))) -+ -+#define __nds32__mfsr(srname) \ -+ (__builtin_nds32_mfsr ((srname))) -+#define __nds32__mfusr(usrname) \ -+ (__builtin_nds32_mfusr ((usrname))) -+#define __nds32__mtsr(val, srname) \ -+ (__builtin_nds32_mtsr ((val), (srname))) -+#define __nds32__mtsr_isb(val, srname) \ -+ (__builtin_nds32_mtsr_isb ((val), (srname))) -+#define __nds32__mtsr_dsb(val, srname) \ -+ (__builtin_nds32_mtsr_dsb ((val), (srname))) -+#define __nds32__mtusr(val, usrname) \ -+ (__builtin_nds32_mtusr ((val), (usrname))) -+ -+#define __nds32__break(swid) \ -+ (__builtin_nds32_break(swid)) -+#define __nds32__cctlva_lck(subtype, va) \ -+ (__builtin_nds32_cctl_va_lck ((subtype), (va))) -+#define __nds32__cctlidx_wbinval(subtype, idx) \ -+ (__builtin_nds32_cctl_idx_wbinval ((subtype), (idx))) -+#define __nds32__cctlva_wbinval_alvl(subtype, va) \ -+ (__builtin_nds32_cctl_va_wbinval_la ((subtype), (va))) -+#define __nds32__cctlva_wbinval_one_lvl(subtype, va) \ -+ (__builtin_nds32_cctl_va_wbinval_l1 ((subtype), (va))) -+#define __nds32__cctlidx_read(subtype, idx) \ -+ (__builtin_nds32_cctl_idx_read ((subtype), (idx))) -+#define __nds32__cctlidx_write(subtype, b, idxw) \ -+ (__builtin_nds32_cctl_idx_write ((subtype), (b), (idxw))) -+#define __nds32__cctl_l1d_invalall() \ -+ (__builtin_nds32_cctl_l1d_invalall()) -+#define __nds32__cctl_l1d_wball_alvl() \ -+ (__builtin_nds32_cctl_l1d_wball_alvl()) -+#define __nds32__cctl_l1d_wball_one_lvl() \ -+ (__builtin_nds32_cctl_l1d_wball_one_lvl()) -+ -+#define __nds32__dsb() \ -+ (__builtin_nds32_dsb()) -+#define __nds32__isb() \ -+ (__builtin_nds32_isb()) -+#define __nds32__msync_store() \ -+ (__builtin_nds32_msync_store()) -+#define __nds32__msync_all() \ -+ (__builtin_nds32_msync_all()) -+#define __nds32__nop() \ -+ (__builtin_nds32_nop()) -+ -+#define __nds32__standby_wait_done() \ -+ (__builtin_nds32_standby_wait_done()) -+#define __nds32__standby_no_wake_grant() \ -+ (__builtin_nds32_standby_no_wake_grant()) -+#define __nds32__standby_wake_grant() \ -+ (__builtin_nds32_standby_wake_grant()) -+#define __nds32__schedule_barrier() \ -+ (__builtin_nds32_schedule_barrier()) -+#define __nds32__setend_big() \ -+ (__builtin_nds32_setend_big()) -+#define __nds32__setend_little() \ -+ (__builtin_nds32_setend_little()) -+#define __nds32__setgie_en() \ -+ (__builtin_nds32_setgie_en()) -+#define __nds32__setgie_dis() \ -+ (__builtin_nds32_setgie_dis()) -+ -+#define __nds32__jr_itoff(a) \ -+ (__builtin_nds32_jr_itoff ((a))) -+#define __nds32__jr_toff(a) \ -+ (__builtin_nds32_jr_toff ((a))) -+#define __nds32__jral_iton(a) \ -+ (__builtin_nds32_jral_iton ((a))) -+#define __nds32__jral_ton(a) \ -+ (__builtin_nds32_jral_ton ((a))) -+#define __nds32__ret_itoff(a) \ -+ (__builtin_nds32_ret_itoff ((a))) -+#define __nds32__ret_toff(a) \ -+ (__builtin_nds32_ret_toff ((a))) -+#define __nds32__svs(a, b) \ -+ (__builtin_nds32_svs ((a), (b))) -+#define __nds32__sva(a, b) \ -+ (__builtin_nds32_sva ((a), (b))) -+#define __nds32__dpref_qw(a, b, subtype) \ -+ (__builtin_nds32_dpref_qw ((a), (b), (subtype))) -+#define __nds32__dpref_hw(a, b, subtype) \ -+ (__builtin_nds32_dpref_hw ((a), (b), (subtype))) -+#define __nds32__dpref_w(a, b, subtype) \ -+ (__builtin_nds32_dpref_w ((a), (b), (subtype))) -+#define __nds32__dpref_dw(a, b, subtype) \ -+ (__builtin_nds32_dpref_dw ((a), (b), (subtype))) -+ -+#define __nds32__teqz(a, swid) \ -+ (__builtin_nds32_teqz ((a), (swid))) -+#define __nds32__tnez(a, swid) \ -+ ( __builtin_nds32_tnez ((a), (swid))) -+#define __nds32__trap(swid) \ -+ (__builtin_nds32_trap ((swid))) -+#define __nds32__isync(a) \ -+ (__builtin_nds32_isync ((a))) -+#define __nds32__rotr(val, ror) \ -+ (__builtin_nds32_rotr ((val), (ror))) -+#define __nds32__wsbh(a) \ -+ (__builtin_nds32_wsbh ((a))) -+#define __nds32__syscall(a) \ -+ (__builtin_nds32_syscall ((a))) -+#define __nds32__return_address() \ -+ (__builtin_nds32_return_address()) -+#define __nds32__get_current_sp() \ -+ (__builtin_nds32_get_current_sp()) -+#define __nds32__set_current_sp(a) \ -+ (__builtin_nds32_set_current_sp ((a))) -+#define __nds32__abs(a) \ -+ (__builtin_nds32_pe_abs ((a))) -+#define __nds32__ave(a, b) \ -+ (__builtin_nds32_pe_ave ((a), (b))) -+#define __nds32__bclr(a, pos) \ -+ (__builtin_nds32_pe_bclr ((a), (pos))) -+#define __nds32__bset(a, pos) \ -+ (__builtin_nds32_pe_bset ((a), (pos))) -+#define __nds32__btgl(a, pos) \ -+ (__builtin_nds32_pe_btgl ((a), (pos))) -+#define __nds32__btst(a, pos) \ -+ (__builtin_nds32_pe_btst ((a), (pos))) -+ -+#define __nds32__clip(a, imm) \ -+ (__builtin_nds32_pe_clip ((a), (imm))) -+#define __nds32__clips(a, imm) \ -+ (__builtin_nds32_pe_clips ((a), (imm))) -+#define __nds32__clz(a) \ -+ (__builtin_nds32_pe_clz ((a))) -+#define __nds32__clo(a) \ -+ (__builtin_nds32_pe_clo ((a))) -+#define __nds32__bse(r, a, b) \ -+ (__builtin_nds32_pe2_bse ((r), (a), (b))) -+#define __nds32__bsp(r, a, b) \ -+ (__builtin_nds32_pe2_bsp ((r), (a), (b))) -+#define __nds32__pbsad(a, b) \ -+ (__builtin_nds32_pe2_pbsad ((a), (b))) -+#define __nds32__pbsada(acc, a, b) \ -+ (__builtin_nds32_pe2_pbsada ((acc), (a), (b))) -+ -+#define __nds32__ffb(a, b) \ -+ (__builtin_nds32_se_ffb ((a), (b))) -+#define __nds32__ffmism(a, b) \ -+ (__builtin_nds32_se_ffmism ((a), (b))) -+#define __nds32__flmism(a, b) \ -+ (__builtin_nds32_se_flmism ((a), (b))) -+#define __nds32__fcpynsd(a, b) \ -+ (__builtin_nds32_fcpynsd ((a), (b))) -+#define __nds32__fcpynss(a, b) \ -+ (__builtin_nds32_fcpynss ((a), (b))) -+#define __nds32__fcpysd(a, b) \ -+ (__builtin_nds32_fcpysd ((a), (b))) -+#define __nds32__fcpyss(a, b) \ -+ (__builtin_nds32_fcpyss ((a), (b))) -+#define __nds32__fmfcsr() \ -+ (__builtin_nds32_fmfcsr()) -+#define __nds32__fmtcsr(fpcsr) \ -+ (__builtin_nds32_fmtcsr ((fpcsr))) -+#define __nds32__fmfcfg() \ -+ (__builtin_nds32_fmfcfg()) -+ -+#define __nds32__tlbop_trd(a) \ -+ (__builtin_nds32_tlbop_trd ((a))) -+#define __nds32__tlbop_twr(a) \ -+ (__builtin_nds32_tlbop_twr ((a))) -+#define __nds32__tlbop_rwr(a) \ -+ (__builtin_nds32_tlbop_rwr ((a))) -+#define __nds32__tlbop_rwlk(a) \ -+ (__builtin_nds32_tlbop_rwlk ((a))) -+#define __nds32__tlbop_unlk(a) \ -+ (__builtin_nds32_tlbop_unlk ((a))) -+#define __nds32__tlbop_pb(a) \ -+ (__builtin_nds32_tlbop_pb ((a))) -+#define __nds32__tlbop_inv(a) \ -+ (__builtin_nds32_tlbop_inv ((a))) -+#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() \ -+ (__builtin_nds32_gie_en()) -+#define __nds32__enable_int(a) \ -+ (__builtin_nds32_enable_int ((a))) -+#define __nds32__disable_int(a) \ -+ (__builtin_nds32_disable_int ((a))) -+#define __nds32__set_pending_swint() \ -+ (__builtin_nds32_set_pending_swint()) -+#define __nds32__clr_pending_swint() \ -+ (__builtin_nds32_clr_pending_swint()) -+#define __nds32__clr_pending_hwint(a) \ -+ (__builtin_nds32_clr_pending_hwint(a)) -+#define __nds32__get_all_pending_int() \ -+ (__builtin_nds32_get_all_pending_int()) -+#define __nds32__get_pending_int(a) \ -+ (__builtin_nds32_get_pending_int ((a))) -+#define __nds32__set_int_priority(a, b) \ -+ (__builtin_nds32_set_int_priority ((a), (b))) -+#define __nds32__get_int_priority(a) \ -+ (__builtin_nds32_get_int_priority ((a))) -+#define __nds32__set_trig_type_level(a) \ -+ (__builtin_nds32_set_trig_level(a)) -+#define __nds32__set_trig_type_edge(a) \ -+ (__builtin_nds32_set_trig_edge(a)) -+#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__signature_begin() \ -+ (__builtin_nds32_signature_begin ()) -+#define __nds32__signature_end() \ -+ (__builtin_nds32_signature_end ()) -+ -+#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__no_ext_zol() \ -+ (__builtin_nds32_no_ext_zol()) -+ -+#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 0000000..6fabd3e ---- /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-2016 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 f7e2fa8..6cd854d 100644 ---- a/gcc/config/nds32/pipelines.md -+++ b/gcc/config/nds32/pipelines.md -@@ -18,12 +18,65 @@ - ;; along with GCC; see the file COPYING3. If not see - ;; . - --(define_automaton "nds32_machine") -+;; ------------------------------------------------------------------------ -+;; Include N7 pipeline settings. -+;; ------------------------------------------------------------------------ -+(include "nds32-n7.md") -+ -+ -+;; ------------------------------------------------------------------------ -+;; Include N8 pipeline settings. -+;; ------------------------------------------------------------------------ -+(include "nds32-n8.md") -+ -+ -+;; ------------------------------------------------------------------------ -+;; Include E8 pipeline settings. -+;; ------------------------------------------------------------------------ -+(include "nds32-e8.md") -+ -+ -+;; ------------------------------------------------------------------------ -+;; Include N9/N10 pipeline settings. -+;; ------------------------------------------------------------------------ -+(include "nds32-n9-3r2w.md") -+(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") -+ -+ -+;; ------------------------------------------------------------------------ -+;; Include Panther pipeline settings. -+;; ------------------------------------------------------------------------ -+(include "nds32-panther.md") -+ -+ -+;; ------------------------------------------------------------------------ -+;; Define simple pipeline settings. -+;; ------------------------------------------------------------------------ -+ -+(define_automaton "nds32_simple_machine") - --(define_cpu_unit "general_unit" "nds32_machine") -+(define_cpu_unit "simple_unit" "nds32_simple_machine") - - (define_insn_reservation "simple_insn" 1 -- (eq_attr "type" "unknown,load,store,move,alu,compare,branch,call,misc") -- "general_unit") -+ (eq_attr "pipeline_model" "simple") -+ "simple_unit") - - ;; ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/predicates.md b/gcc/config/nds32/predicates.md -index 05a039d..71a3615 100644 ---- a/gcc/config/nds32/predicates.md -+++ b/gcc/config/nds32/predicates.md -@@ -24,25 +24,93 @@ - (define_predicate "nds32_greater_less_comparison_operator" - (match_code "gt,ge,lt,le")) - -+(define_predicate "nds32_float_comparison_operator" -+ (match_code "eq,ne,le,lt,ge,gt,ordered,unordered,ungt,unge,unlt,unle")) -+ -+(define_predicate "nds32_movecc_comparison_operator" -+ (match_code "eq,ne,le,leu,ge,geu")) -+ - (define_special_predicate "nds32_logical_binary_operator" - (match_code "and,ior,xor")) - -+(define_special_predicate "nds32_conditional_call_comparison_operator" -+ (match_code "lt,ge")) -+ -+(define_special_predicate "nds32_have_33_inst_operator" -+ (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_label_operand" -+ (match_code "label_ref")) - - (define_predicate "nds32_reg_constant_operand" -- (ior (match_operand 0 "register_operand") -- (match_operand 0 "const_int_operand"))) -+ (match_code "reg,const_int")) - - (define_predicate "nds32_rimm15s_operand" - (ior (match_operand 0 "register_operand") - (and (match_operand 0 "const_int_operand") - (match_test "satisfies_constraint_Is15 (op)")))) - -+(define_predicate "nds32_rimm11s_operand" -+ (ior (match_operand 0 "register_operand") -+ (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"))) -@@ -57,12 +125,121 @@ - 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_code "reg,const_int") -+{ -+ return (REG_P (op) && GET_MODE (op) == mode) -+ || satisfies_constraint_Izeb (op) -+ || satisfies_constraint_Izeh (op) -+ || satisfies_constraint_Ixls (op) -+ || satisfies_constraint_Ix11 (op) -+ || satisfies_constraint_Ibms (op) -+ || satisfies_constraint_Ifex (op) -+ || satisfies_constraint_Iu15 (op) -+ || satisfies_constraint_Ii15 (op) -+ || satisfies_constraint_Ic15 (op); -+}) -+ -+(define_predicate "nds32_ior_operand" -+ (match_code "reg,const_int") -+{ -+ return (REG_P (op) && GET_MODE (op) == mode) -+ || satisfies_constraint_Iu15 (op) -+ || satisfies_constraint_Ie15 (op); -+}) -+ -+(define_predicate "nds32_xor_operand" -+ (match_code "reg,const_int") -+{ -+ return (REG_P (op) && GET_MODE (op) == mode) -+ || GET_CODE (op) == SUBREG -+ || satisfies_constraint_Iu15 (op) -+ || satisfies_constraint_It15 (op); -+}) -+ -+(define_predicate "nds32_general_register_operand" -+ (match_code "reg,subreg") -+{ -+ if (GET_CODE (op) == SUBREG) -+ op = SUBREG_REG (op); -+ -+ return (REG_P (op) -+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER -+ || REGNO (op) <= NDS32_LAST_GPR_REGNUM)); -+}) -+ -+(define_predicate "nds32_fpu_register_operand" -+ (match_code "reg,subreg") -+{ -+ if (GET_CODE (op) == SUBREG) -+ op = SUBREG_REG (op); -+ -+ return (REG_P (op) -+ && NDS32_IS_FPR_REGNUM (REGNO (op))); -+}) -+ -+(define_predicate "fpu_reg_or_memory_operand" -+ (ior (match_operand 0 "nds32_fpu_register_operand") -+ (match_operand 0 "memory_operand"))) -+ -+(define_predicate "nds32_call_address_operand" -+ (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)"))) -+ -+(define_predicate "float_even_register_operand" -+ (and (match_code "reg") -+ (and (match_test "REGNO (op) >= NDS32_FIRST_FPR_REGNUM") -+ (match_test "REGNO (op) <= NDS32_LAST_FPR_REGNUM") -+ (match_test "(REGNO (op) & 1) == 0")))) -+ -+(define_predicate "float_odd_register_operand" -+ (and (match_code "reg") -+ (and (match_test "REGNO (op) >= NDS32_FIRST_FPR_REGNUM") -+ (match_test "REGNO (op) <= NDS32_LAST_FPR_REGNUM") -+ (match_test "(REGNO (op) & 1) != 0")))) -+ - (define_special_predicate "nds32_load_multiple_operation" - (match_code "parallel") - { - /* To verify 'load' operation, pass 'true' for the second argument. - See the implementation in nds32.c for details. */ -- return nds32_valid_multiple_load_store (op, true); -+ return nds32_valid_multiple_load_store_p (op, true, false); -+}) -+ -+(define_special_predicate "nds32_load_multiple_and_update_address_operation" -+ (match_code "parallel") -+{ -+ /* To verify 'load' operation, pass 'true' for the second argument. -+ to verify 'update address' operation, pass 'true' for the third argument -+ See the implementation in nds32.c for details. */ -+ return nds32_valid_multiple_load_store_p (op, true, true); - }) - - (define_special_predicate "nds32_store_multiple_operation" -@@ -70,7 +247,16 @@ - { - /* To verify 'store' operation, pass 'false' for the second argument. - See the implementation in nds32.c for details. */ -- return nds32_valid_multiple_load_store (op, false); -+ return nds32_valid_multiple_load_store_p (op, false, false); -+}) -+ -+(define_special_predicate "nds32_store_multiple_and_update_address_operation" -+ (match_code "parallel") -+{ -+ /* To verify 'store' operation, pass 'false' for the second argument, -+ to verify 'update address' operation, pass 'true' for the third argument -+ See the implementation in nds32.c for details. */ -+ return nds32_valid_multiple_load_store_p (op, false, true); - }) - - (define_special_predicate "nds32_stack_push_operation" -diff --git a/gcc/config/nds32/t-elf b/gcc/config/nds32/t-elf -new file mode 100644 -index 0000000..a63a310 ---- /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-2016 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-mlibs b/gcc/config/nds32/t-linux -similarity index 94% -rename from gcc/config/nds32/t-mlibs -rename to gcc/config/nds32/t-linux -index 5cb13f7..a4d8ab3 100644 ---- a/gcc/config/nds32/t-mlibs -+++ b/gcc/config/nds32/t-linux -@@ -21,6 +21,6 @@ - # 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 -+MULTILIB_OPTIONS += - - # ------------------------------------------------------------------------ -diff --git a/gcc/config/nds32/t-nds32 b/gcc/config/nds32/t-nds32 -index cf3aea6..e34b844 100644 ---- a/gcc/config/nds32/t-nds32 -+++ b/gcc/config/nds32/t-nds32 -@@ -1,51 +1,294 @@ --# General rules that all nds32/ targets must have. -+# Dependency rules rule of Andes NDS32 cpu for GNU compiler - # Copyright (C) 2012-2016 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 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. -+# 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 - # . - --nds32-cost.o: $(srcdir)/config/nds32/nds32-cost.c -- $(COMPILE) $< -- $(POSTCOMPILE) - --nds32-intrinsic.o: $(srcdir)/config/nds32/nds32-intrinsic.c -- $(COMPILE) $< -- $(POSTCOMPILE) -+nds32-md-auxiliary.o: $(srcdir)/config/nds32/nds32-md-auxiliary.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-md-auxiliary.c - --nds32-isr.o: $(srcdir)/config/nds32/nds32-isr.c -- $(COMPILE) $< -- $(POSTCOMPILE) -+nds32-memory-manipulation.o: $(srcdir)/config/nds32/nds32-memory-manipulation.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-memory-manipulation.c - --nds32-md-auxiliary.o: $(srcdir)/config/nds32/nds32-md-auxiliary.c -- $(COMPILE) $< -- $(POSTCOMPILE) -+nds32-predicates.o: $(srcdir)/config/nds32/nds32-predicates.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-predicates.c - --nds32-pipelines-auxiliary.o: $(srcdir)/config/nds32/nds32-pipelines-auxiliary.c -- $(COMPILE) $< -- $(POSTCOMPILE) -+nds32-intrinsic.o: $(srcdir)/config/nds32/nds32-intrinsic.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-intrinsic.c - --nds32-predicates.o: $(srcdir)/config/nds32/nds32-predicates.c -- $(COMPILE) $< -- $(POSTCOMPILE) -+nds32-pipelines-auxiliary.o: \ -+ $(srcdir)/config/nds32/nds32-pipelines-auxiliary.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-pipelines-auxiliary.c - --nds32-memory-manipulation.o: $(srcdir)/config/nds32/nds32-memory-manipulation.c -- $(COMPILE) $< -- $(POSTCOMPILE) -+nds32-isr.o: \ -+ $(srcdir)/config/nds32/nds32-isr.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-isr.c - --nds32-fp-as-gp.o: $(srcdir)/config/nds32/nds32-fp-as-gp.c -- $(COMPILE) $< -- $(POSTCOMPILE) -+nds32-cost.o: \ -+ $(srcdir)/config/nds32/nds32-cost.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-cost.c -+ -+nds32-fp-as-gp.o: \ -+ $(srcdir)/config/nds32/nds32-fp-as-gp.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-fp-as-gp.c -+ -+nds32-load-store-opt.o: \ -+ $(srcdir)/config/nds32/nds32-load-store-opt.c \ -+ $(srcdir)/config/nds32/nds32-load-store-opt.h \ -+ $(srcdir)/config/nds32/nds32-reg-utils.h \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-load-store-opt.c -+ -+nds32-soft-fp-comm.o: \ -+ $(srcdir)/config/nds32/nds32-soft-fp-comm.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-soft-fp-comm.c -+ -+nds32-regrename.o: \ -+ $(srcdir)/config/nds32/nds32-regrename.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-regrename.c -+ -+nds32-gcse.o: \ -+ $(srcdir)/config/nds32/nds32-gcse.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-gcse.c -+ -+nds32-relax-opt.o: \ -+ $(srcdir)/config/nds32/nds32-relax-opt.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-relax-opt.c -+ -+nds32-cprop-acc.o: \ -+ $(srcdir)/config/nds32/nds32-cprop-acc.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-cprop-acc.c -+ -+nds32-sign-conversion.o: \ -+ $(srcdir)/config/nds32/nds32-sign-conversion.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(GIMPLE_H) $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-sign-conversion.c -+ -+nds32-scalbn-transform.o: \ -+ $(srcdir)/config/nds32/nds32-scalbn-transform.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(GIMPLE_H) $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-scalbn-transform.c -+ -+nds32-abi-compatible.o: \ -+ $(srcdir)/config/nds32/nds32-abi-compatible.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(GIMPLE_H) $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-abi-compatible.c -+ -+nds32-lmwsmw.o: \ -+ $(srcdir)/config/nds32/nds32-lmwsmw.c \ -+ $(srcdir)/config/nds32/nds32-load-store-opt.h \ -+ $(srcdir)/config/nds32/nds32-reg-utils.h \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-lmwsmw.c -+ -+nds32-reg-utils.o: \ -+ $(srcdir)/config/nds32/nds32-reg-utils.c \ -+ $(srcdir)/config/nds32/nds32-reg-utils.h \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-reg-utils.c -+ -+nds32-const-remater.o: \ -+ $(srcdir)/config/nds32/nds32-const-remater.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-const-remater.c -+ -+nds32-utils.o: \ -+ $(srcdir)/config/nds32/nds32-utils.c \ -+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ -+ $(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \ -+ insn-config.h conditions.h output.h dumpfile.h \ -+ $(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \ -+ $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \ -+ $(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \ -+ $(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \ -+ intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/nds32/nds32-utils.c -diff --git a/gcc/configure b/gcc/configure -index 954673c..ca21885 100755 ---- a/gcc/configure -+++ b/gcc/configure -@@ -27327,7 +27327,7 @@ esac - # version to the per-target configury. - case "$cpu_type" in - aarch64 | alpha | arm | avr | bfin | cris | i386 | m32c | m68k | microblaze \ -- | mips | nios2 | pa | rs6000 | score | sparc | spu | tilegx | tilepro \ -+ | mips | nds32 | nios2 | pa | rs6000 | score | sparc | spu | tilegx | tilepro \ - | visium | xstormy16 | xtensa) - insn="nop" - ;; -diff --git a/gcc/configure.ac b/gcc/configure.ac -index 4c65d44..d7a5efc 100644 ---- a/gcc/configure.ac -+++ b/gcc/configure.ac -@@ -4667,7 +4667,7 @@ esac - # version to the per-target configury. - case "$cpu_type" in - aarch64 | alpha | arm | avr | bfin | cris | i386 | m32c | m68k | microblaze \ -- | mips | nios2 | pa | rs6000 | score | sparc | spu | tilegx | tilepro \ -+ | mips | nds32 | nios2 | pa | rs6000 | score | sparc | spu | tilegx | tilepro \ - | visium | xstormy16 | xtensa) - insn="nop" - ;; -diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi -index ee2715d..37fa3b5 100644 ---- a/gcc/doc/extend.texi -+++ b/gcc/doc/extend.texi -@@ -13587,38 +13587,33 @@ builtin is exact. - - These built-in functions are available for the NDS32 target: - --@deftypefn {Built-in Function} void __builtin_nds32_isync (int *@var{addr}) -+@table @code -+@item void __builtin_nds32_isync (int *@var{addr}) - Insert an ISYNC instruction into the instruction stream where - @var{addr} is an instruction address for serialization. --@end deftypefn - --@deftypefn {Built-in Function} void __builtin_nds32_isb (void) -+@item void __builtin_nds32_isb (void) - Insert an ISB instruction into the instruction stream. --@end deftypefn - --@deftypefn {Built-in Function} int __builtin_nds32_mfsr (int @var{sr}) -+@item int __builtin_nds32_mfsr (int @var{sr}) - Return the content of a system register which is mapped by @var{sr}. --@end deftypefn - --@deftypefn {Built-in Function} int __builtin_nds32_mfusr (int @var{usr}) -+@item int __builtin_nds32_mfusr (int @var{usr}) - Return the content of a user space register which is mapped by @var{usr}. --@end deftypefn - --@deftypefn {Built-in Function} void __builtin_nds32_mtsr (int @var{value}, int @var{sr}) -+@item void __builtin_nds32_mtsr (int @var{value}, int @var{sr}) - Move the @var{value} to a system register which is mapped by @var{sr}. --@end deftypefn - --@deftypefn {Built-in Function} void __builtin_nds32_mtusr (int @var{value}, int @var{usr}) -+@item void __builtin_nds32_mtusr (int @var{value}, int @var{usr}) - Move the @var{value} to a user space register which is mapped by @var{usr}. --@end deftypefn - --@deftypefn {Built-in Function} void __builtin_nds32_setgie_en (void) -+@item void __builtin_nds32_setgie_en (void) - Enable global interrupt. --@end deftypefn - --@deftypefn {Built-in Function} void __builtin_nds32_setgie_dis (void) -+@item void __builtin_nds32_setgie_dis (void) - Disable global interrupt. --@end deftypefn -+ -+@end table - - @node picoChip Built-in Functions - @subsection picoChip Built-in Functions -diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi -index b60b53a..fc23722 100644 ---- a/gcc/doc/install.texi -+++ b/gcc/doc/install.texi -@@ -2109,7 +2109,7 @@ supported since version 4.7.2 and is the default in 4.8.0 and newer. - - @item --with-nds32-lib=@var{library} - Specifies that @var{library} setting is used for building @file{libgcc.a}. --Currently, the valid @var{library} is @samp{newlib} or @samp{mculib}. -+Currently, the valid @var{library} are 'newlib' or 'mculib'. - This option is only supported for the NDS32 target. - - @item --with-build-time-tools=@var{dir} -diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi -index 2ed9285..75e0042 100644 ---- a/gcc/doc/invoke.texi -+++ b/gcc/doc/invoke.texi -@@ -904,13 +904,19 @@ Objective-C and Objective-C++ Dialects}. - -mreduced-regs -mfull-regs @gol - -mcmov -mno-cmov @gol - -mperf-ext -mno-perf-ext @gol -+-mperf2-ext -mno-perf2-ext @gol -+-mstring-ext -mno-string-ext @gol - -mv3push -mno-v3push @gol - -m16bit -mno-16bit @gol -+-mgp-direct -mno-gp-direct @gol - -misr-vector-size=@var{num} @gol - -mcache-block-size=@var{num} @gol - -march=@var{arch} @gol ---mcmodel=@var{code-model} @gol ---mctor-dtor -mrelax} -+-mcpu=@var{cpu} @gol -+-mmemory-model=@var{cpu} @gol -+-mconfig-register-ports=@var{ports} @gol -+-mforce-fp-as-gp -mforbid-fp-as-gp @gol -+-mex9 -mctor-dtor -mrelax} - - @emph{Nios II Options} - @gccoptlist{-G @var{num} -mgpopt=@var{option} -mgpopt -mno-gpopt @gol -@@ -5006,7 +5012,7 @@ example, warn if an unsigned variable is compared against zero with - @opindex Wbad-function-cast - @opindex Wno-bad-function-cast - Warn when a function call is cast to a non-matching type. --For example, warn if a call to a function returning an integer type -+For example, warn if a call to a function returning an integer type - is cast to a pointer type. - - @item -Wc90-c99-compat @r{(C and Objective-C only)} -@@ -19089,6 +19095,22 @@ Generate performance extension instructions. - @opindex mno-perf-ext - Do not generate performance extension instructions. - -+@item -mperf2-ext -+@opindex mperf2-ext -+Generate performance extension version 2 instructions. -+ -+@item -mno-perf2-ext -+@opindex mno-perf2-ext -+Do not generate performance extension version 2 instructions. -+ -+@item -mstring-ext -+@opindex mstring-ext -+Generate string extension instructions. -+ -+@item -mno-string-ext -+@opindex mno-string-ext -+Do not generate string extension instructions. -+ - @item -mv3push - @opindex mv3push - Generate v3 push25/pop25 instructions. -@@ -19105,6 +19127,14 @@ Generate 16-bit instructions. - @opindex mno-16-bit - Do not generate 16-bit instructions. - -+@item -mgp-direct -+@opindex mgp-direct -+Generate GP base instructions directly. -+ -+@item -mno-gp-direct -+@opindex mno-gp-direct -+Do no generate GP base instructions directly. -+ - @item -misr-vector-size=@var{num} - @opindex misr-vector-size - Specify the size of each interrupt vector, which must be 4 or 16. -@@ -19118,20 +19148,33 @@ which must be a power of 2 between 4 and 512. - @opindex march - Specify the name of the target architecture. - --@item -mcmodel=@var{code-model} --@opindex mcmodel --Set the code model to one of --@table @asis --@item @samp{small} --All the data and read-only data segments must be within 512KB addressing space. --The text segment must be within 16MB addressing space. --@item @samp{medium} --The data segment must be within 512KB while the read-only data segment can be --within 4GB addressing space. The text segment should be still within 16MB --addressing space. --@item @samp{large} --All the text and data segments can be within 4GB addressing space. --@end table -+@item -mcpu=@var{cpu} -+@opindex mcpu -+Specify the cpu for pipeline model. -+ -+@item -mmemory-model=@var{cpu} -+@opindex mmemory-model -+Specify fast or slow memory model. -+ -+@item -mconfig-register-ports=@var{ports} -+@opindex mconfig-register-ports -+Specify how many read/write ports for n9/n10 cores. -+The value should be 3r2w or 2r1w. -+ -+@item -mforce-fp-as-gp -+@opindex mforce-fp-as-gp -+Prevent $fp being allocated during register allocation so that compiler -+is able to force performing fp-as-gp optimization. -+ -+@item -mforbid-fp-as-gp -+@opindex mforbid-fp-as-gp -+Forbid using $fp to access static and global variables. -+This option strictly forbids fp-as-gp optimization -+regardless of @option{-mforce-fp-as-gp}. -+ -+@item -mex9 -+@opindex mex9 -+Use special directives to guide linker doing ex9 optimization. - - @item -mctor-dtor - @opindex mctor-dtor -@@ -19159,55 +19202,15 @@ Put global and static objects less than or equal to @var{num} bytes - into the small data or BSS sections instead of the normal data or BSS - sections. The default value of @var{num} is 8. - --@item -mgpopt=@var{option} - @item -mgpopt - @itemx -mno-gpopt - @opindex mgpopt - @opindex mno-gpopt --Generate (do not generate) GP-relative accesses. The following --@var{option} names are recognized: -- --@table @samp -- --@item none --Do not generate GP-relative accesses. -- --@item local --Generate GP-relative accesses for small data objects that are not --external, weak, or uninitialized common symbols. --Also use GP-relative addressing for objects that --have been explicitly placed in a small data section via a @code{section} --attribute. -- --@item global --As for @samp{local}, but also generate GP-relative accesses for --small data objects that are external, weak, or common. If you use this option, --you must ensure that all parts of your program (including libraries) are --compiled with the same @option{-G} setting. -- --@item data --Generate GP-relative accesses for all data objects in the program. If you --use this option, the entire data and BSS segments --of your program must fit in 64K of memory and you must use an appropriate --linker script to allocate them within the addressable range of the --global pointer. -- --@item all --Generate GP-relative addresses for function pointers as well as data --pointers. If you use this option, the entire text, data, and BSS segments --of your program must fit in 64K of memory and you must use an appropriate --linker script to allocate them within the addressable range of the --global pointer. -- --@end table -- --@option{-mgpopt} is equivalent to @option{-mgpopt=local}, and --@option{-mno-gpopt} is equivalent to @option{-mgpopt=none}. -- --The default is @option{-mgpopt} except when @option{-fpic} or --@option{-fPIC} is specified to generate position-independent code. --Note that the Nios II ABI does not permit GP-relative accesses from --shared libraries. -+Generate (do not generate) GP-relative accesses for objects in the -+small data or BSS sections. The default is @option{-mgpopt} except -+when @option{-fpic} or @option{-fPIC} is specified to generate -+position-independent code. Note that the Nios II ABI does not permit -+GP-relative accesses from shared libraries. - - You may need to specify @option{-mno-gpopt} explicitly when building - programs that include large amounts of small data, including large -diff --git a/gcc/gcc.c b/gcc/gcc.c -index 0f042b0..5c43f33 100644 ---- a/gcc/gcc.c -+++ b/gcc/gcc.c -@@ -1288,7 +1288,7 @@ static const struct compiler default_compilers[] = - {".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0}, - {".go", "#Go", 0, 1, 0}, - /* Next come the entries for C. */ -- {".c", "@c", 0, 0, 1}, -+ {".c", "@nds32_c", 0, 0, 1}, - {"@c", - /* cc1 has an integrated ISO C preprocessor. We should invoke the - external preprocessor if -save-temps is given. */ -@@ -1303,6 +1303,38 @@ static const struct compiler default_compilers[] = - %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\ - cc1 %(cpp_unique_options) %(cc1_options)}}}\ - %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 1}, -+ {"@nds32_c", -+ /* cc1 has an integrated ISO C preprocessor. We should invoke the -+ external preprocessor if -save-temps is given. */ -+ "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\ -+ %{mace:\ -+ %{!E:%{!M:%{!MM:\ -+ %{traditional:\ -+%eGNU C no longer supports -traditional without -E}\ -+ %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ -+ %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\ -+ cs2 %{mace-s2s*} %{save-temps*:%b.i} %{!save-temps*:%g.i} \ -+ -o %{save-temps*:%b.ace.i} %{!save-temps*:%g.ace.i} --\n\ -+ cc1 -fpreprocessed %{save-temps*:%b.ace.i} %{!save-temps*:%g.ace.i} \ -+ %(cc1_options)}\ -+ %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\ -+ %(trad_capable_cpp) %(cpp_options) -o %u.i\n}}}\ -+ %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\ -+ cs2 %{mace-s2s*} %U.i -o %u.ace.i --\n}}}\ -+ %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\ -+ cc1 -fpreprocessed %U.ace.i %(cc1_options)}}}\ -+ %{!fsyntax-only:%(invoke_as)}}}}}\ -+ %{!mace:\ -+ %{!E:%{!M:%{!MM:\ -+ %{traditional:\ -+%eGNU C no longer supports -traditional without -E}\ -+ %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ -+ %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\ -+ cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \ -+ %(cc1_options)}\ -+ %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\ -+ cc1 %(cpp_unique_options) %(cc1_options)}}}\ -+ %{!fsyntax-only:%(invoke_as)}}}}}", 0, 0, 1}, - {"-", - "%{!E:%e-E or -x required when input is from standard input}\ - %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0, 0, 0}, -diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c -index 4d26e2f..60f934c 100644 ---- a/gcc/loop-unroll.c -+++ b/gcc/loop-unroll.c -@@ -1132,7 +1132,9 @@ decide_unroll_stupid (struct loop *loop, int flags) - of mispredicts. - TODO: this heuristic needs tunning; call inside the loop body - is also relatively good reason to not unroll. */ -- if (num_loop_branches (loop) > 1) -+ unsigned branch_count = PARAM_VALUE (PARAM_MAX_LOOP_UNROLL_BRANCH); -+ -+ if (num_loop_branches (loop) > branch_count) - { - if (dump_file) - fprintf (dump_file, ";; Not unrolling, contains branches\n"); -diff --git a/gcc/opt-read.awk b/gcc/opt-read.awk -index b304ccb..2e6e8df 100644 ---- a/gcc/opt-read.awk -+++ b/gcc/opt-read.awk -@@ -99,6 +99,7 @@ BEGIN { - val_flags = "0" - val_flags = val_flags \ - test_flag("Canonical", props, "| CL_ENUM_CANONICAL") \ -+ test_flag("Undocumented", props, "| CL_UNDOCUMENTED") \ - test_flag("DriverOnly", props, "| CL_ENUM_DRIVER_ONLY") - enum_data[enum_name] = enum_data[enum_name] \ - " { " quote string quote ", " value ", " val_flags \ -diff --git a/gcc/opts.c b/gcc/opts.c -index 0f9431a..da75332 100644 ---- a/gcc/opts.c -+++ b/gcc/opts.c -@@ -1271,6 +1271,10 @@ print_filtered_help (unsigned int include_flags, - { - unsigned int len = strlen (cl_enums[i].values[j].arg); - -+ /* Skip the undocument enum value */ -+ if (cl_enums[i].values[j].flags & CL_UNDOCUMENTED) -+ continue; -+ - if (pos > 4 && pos + 1 + len <= columns) - { - printf (" %s", cl_enums[i].values[j].arg); -diff --git a/gcc/params.def b/gcc/params.def -index dbff305..44847b3 100644 ---- a/gcc/params.def -+++ b/gcc/params.def -@@ -297,6 +297,11 @@ DEFPARAM(PARAM_MAX_UNROLL_TIMES, - "max-unroll-times", - "The maximum number of unrollings of a single loop.", - 8, 0, 0) -+/* Maximum number of loop unroll loop branch count. */ -+DEFPARAM (PARAM_MAX_LOOP_UNROLL_BRANCH, -+ "max-unroll-loop-branch", -+ "Maximum number of loop branch count", -+ 1, 1, 20) - /* The maximum number of insns of a peeled loop. */ - DEFPARAM(PARAM_MAX_PEELED_INSNS, - "max-peeled-insns", -diff --git a/gcc/testsuite/g++.dg/init/array15.C b/gcc/testsuite/g++.dg/init/array15.C -index 17160d0..280fe69 100644 ---- a/gcc/testsuite/g++.dg/init/array15.C -+++ b/gcc/testsuite/g++.dg/init/array15.C -@@ -1,4 +1,6 @@ - // { dg-do run } -+// { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } -+// { dg-options "-mcmodel=large" { target nds32*-*-elf* } } - - // Copyright (C) 2004 Free Software Foundation, Inc. - // Contributed by Nathan Sidwell 8 Dec 2004 -diff --git a/gcc/testsuite/g++.dg/init/array16.C b/gcc/testsuite/g++.dg/init/array16.C -index 188d1a8..83c0d47 100644 ---- a/gcc/testsuite/g++.dg/init/array16.C -+++ b/gcc/testsuite/g++.dg/init/array16.C -@@ -2,6 +2,7 @@ - // have "compile" for some targets and "run" for others. - // { dg-do run { target { ! mmix-*-* } } } - // { dg-options "-mstructure-size-boundary=8" { target arm*-*-* } } -+// { dg-skip-if "" { nds32_gp_direct } } - - // Copyright (C) 2004 Free Software Foundation, Inc. - // Contributed by Nathan Sidwell 8 Dec 2004 -diff --git a/gcc/testsuite/g++.dg/torture/type-generic-1.C b/gcc/testsuite/g++.dg/torture/type-generic-1.C -index 4d82592..5ae789c 100644 ---- a/gcc/testsuite/g++.dg/torture/type-generic-1.C -+++ b/gcc/testsuite/g++.dg/torture/type-generic-1.C -@@ -4,6 +4,7 @@ - /* { dg-do run } */ - /* { dg-add-options ieee } */ - /* { dg-skip-if "No Inf/NaN support" { spu-*-* } } */ -+/* { dg-skip-if "No Denormmalized support" { nds32_ext_fpu } } */ - - #include "../../gcc.dg/tg-tests.h" - -diff --git a/gcc/testsuite/gcc.c-torture/compile/limits-fndefn.c b/gcc/testsuite/gcc.c-torture/compile/limits-fndefn.c -index 228c5d9..d2d3e51 100644 ---- a/gcc/testsuite/gcc.c-torture/compile/limits-fndefn.c -+++ b/gcc/testsuite/gcc.c-torture/compile/limits-fndefn.c -@@ -1,4 +1,5 @@ - /* { dg-skip-if "too complex for avr" { avr-*-* } { "*" } { "" } } */ -+/* { dg-skip-if "lto may cause internal compiler error on cygwin with gcc-4.9" { nds32*-*-* } { "*" } { "" } } */ - /* { dg-skip-if "ptxas times out" { nvptx-*-* } { "*" } { "" } } */ - /* { dg-timeout-factor 4.0 } */ - #define LIM1(x) x##0, x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8, x##9, -diff --git a/gcc/testsuite/gcc.c-torture/execute/20010122-1.c b/gcc/testsuite/gcc.c-torture/execute/20010122-1.c -index 4eeb8c7..6cd02bc 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.c-torture/execute/920501-8.x b/gcc/testsuite/gcc.c-torture/execute/920501-8.x -new file mode 100644 -index 0000000..96f05bc ---- /dev/null -+++ b/gcc/testsuite/gcc.c-torture/execute/920501-8.x -@@ -0,0 +1,11 @@ -+# Please see Andes Bugzilla #11005 for the details. -+if { [istarget "nds32*-*-*"] } { -+ # The nds32 mculib toolchains require -+ # "-u_printf_float" and "-u_scanf_float" options -+ # to fully support printf and scanf functionality. -+ # These options are supposed to be harmless to newlib toolchain. -+ set additional_flags "-u_printf_float -u_scanf_float" -+} -+ -+return 0 -+ -diff --git a/gcc/testsuite/gcc.c-torture/execute/930513-1.x b/gcc/testsuite/gcc.c-torture/execute/930513-1.x -new file mode 100644 -index 0000000..96f05bc ---- /dev/null -+++ b/gcc/testsuite/gcc.c-torture/execute/930513-1.x -@@ -0,0 +1,11 @@ -+# Please see Andes Bugzilla #11005 for the details. -+if { [istarget "nds32*-*-*"] } { -+ # The nds32 mculib toolchains require -+ # "-u_printf_float" and "-u_scanf_float" options -+ # to fully support printf and scanf functionality. -+ # These options are supposed to be harmless to newlib toolchain. -+ set additional_flags "-u_printf_float -u_scanf_float" -+} -+ -+return 0 -+ -diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/ieee.exp b/gcc/testsuite/gcc.c-torture/execute/ieee/ieee.exp -index 009984e..19cfcca 100644 ---- a/gcc/testsuite/gcc.c-torture/execute/ieee/ieee.exp -+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/ieee.exp -@@ -30,6 +30,10 @@ load_lib c-torture.exp - # Disable tests on machines with no hardware support for IEEE arithmetic. - if { [istarget "vax-*-*"] || [ istarget "powerpc-*-*spe"] || [istarget "pdp11-*-*"] } { return } - -+# Since we cannot use dg-skip-if or dg-require-effective-target for individual -+# test case under ieee category, we disable all ieee tests on nds32 fpu toolchains. -+if { [istarget "nds32*-*-*"] && [check_effective_target_nds32_ext_fpu] } { return } -+ - if $tracelevel then { - strace $tracelevel - } -diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60822.c b/gcc/testsuite/gcc.c-torture/execute/pr60822.c -index dcd2447..a305df3 100644 ---- a/gcc/testsuite/gcc.c-torture/execute/pr60822.c -+++ b/gcc/testsuite/gcc.c-torture/execute/pr60822.c -@@ -1,4 +1,5 @@ - /* { dg-require-effective-target int32plus } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - struct X { - char fill0[800000]; - int a; -diff --git a/gcc/testsuite/gcc.c-torture/execute/struct-ret-1.x b/gcc/testsuite/gcc.c-torture/execute/struct-ret-1.x -new file mode 100644 -index 0000000..96f05bc ---- /dev/null -+++ b/gcc/testsuite/gcc.c-torture/execute/struct-ret-1.x -@@ -0,0 +1,11 @@ -+# Please see Andes Bugzilla #11005 for the details. -+if { [istarget "nds32*-*-*"] } { -+ # The nds32 mculib toolchains require -+ # "-u_printf_float" and "-u_scanf_float" options -+ # to fully support printf and scanf functionality. -+ # These options are supposed to be harmless to newlib toolchain. -+ set additional_flags "-u_printf_float -u_scanf_float" -+} -+ -+return 0 -+ -diff --git a/gcc/testsuite/gcc.dg/constructor-1.c b/gcc/testsuite/gcc.dg/constructor-1.c -index 73e9fc3..827987e 100644 ---- a/gcc/testsuite/gcc.dg/constructor-1.c -+++ b/gcc/testsuite/gcc.dg/constructor-1.c -@@ -1,6 +1,7 @@ - /* { dg-do run } */ - /* { dg-options "-O2" } */ - /* { dg-skip-if "" { ! global_constructor } { "*" } { "" } } */ -+/* { dg-options "-O2 -mctor-dtor" { target { nds32*-*-* } } } */ - - /* The ipa-split pass pulls the body of the if(!x) block - into a separate function to make foo a better inlining -diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-0.c b/gcc/testsuite/gcc.dg/graphite/interchange-0.c -index d56be46..b83535c 100644 ---- a/gcc/testsuite/gcc.dg/graphite/interchange-0.c -+++ b/gcc/testsuite/gcc.dg/graphite/interchange-0.c -@@ -1,4 +1,5 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - #define DEBUG 0 - -diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-1.c b/gcc/testsuite/gcc.dg/graphite/interchange-1.c -index b65d486..2d77f0e 100644 ---- a/gcc/testsuite/gcc.dg/graphite/interchange-1.c -+++ b/gcc/testsuite/gcc.dg/graphite/interchange-1.c -@@ -1,4 +1,6 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - /* Formerly known as ltrans-1.c */ - -diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-10.c b/gcc/testsuite/gcc.dg/graphite/interchange-10.c -index a955644..2021de2 100644 ---- a/gcc/testsuite/gcc.dg/graphite/interchange-10.c -+++ b/gcc/testsuite/gcc.dg/graphite/interchange-10.c -@@ -1,4 +1,6 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - #define DEBUG 0 - #if DEBUG -diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-11.c b/gcc/testsuite/gcc.dg/graphite/interchange-11.c -index 6102822..5abb316 100644 ---- a/gcc/testsuite/gcc.dg/graphite/interchange-11.c -+++ b/gcc/testsuite/gcc.dg/graphite/interchange-11.c -@@ -1,4 +1,6 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - #define DEBUG 0 - #if DEBUG -diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-15.c b/gcc/testsuite/gcc.dg/graphite/interchange-15.c -index 7410f29..1f71f06 100644 ---- a/gcc/testsuite/gcc.dg/graphite/interchange-15.c -+++ b/gcc/testsuite/gcc.dg/graphite/interchange-15.c -@@ -1,4 +1,6 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - #define DEBUG 0 - #if DEBUG -diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-2.c b/gcc/testsuite/gcc.dg/graphite/interchange-2.c -index 936ee00..0041649 100644 ---- a/gcc/testsuite/gcc.dg/graphite/interchange-2.c -+++ b/gcc/testsuite/gcc.dg/graphite/interchange-2.c -@@ -1,4 +1,6 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - /* Formerly known as ltrans-2.c */ - -diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-3.c b/gcc/testsuite/gcc.dg/graphite/interchange-3.c -index 4aec824..6635529 100644 ---- a/gcc/testsuite/gcc.dg/graphite/interchange-3.c -+++ b/gcc/testsuite/gcc.dg/graphite/interchange-3.c -@@ -1,4 +1,6 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - /* Formerly known as ltrans-3.c */ - -diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-4.c b/gcc/testsuite/gcc.dg/graphite/interchange-4.c -index 463ecb5..359f0ac 100644 ---- a/gcc/testsuite/gcc.dg/graphite/interchange-4.c -+++ b/gcc/testsuite/gcc.dg/graphite/interchange-4.c -@@ -1,4 +1,6 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - /* Formerly known as ltrans-4.c */ - -diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-5.c b/gcc/testsuite/gcc.dg/graphite/interchange-5.c -index e5aaa64..892257e 100644 ---- a/gcc/testsuite/gcc.dg/graphite/interchange-5.c -+++ b/gcc/testsuite/gcc.dg/graphite/interchange-5.c -@@ -1,4 +1,5 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - /* Formerly known as ltrans-5.c */ - -diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c b/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c -index c6543ec..51c6ee5 100644 ---- a/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c -+++ b/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c -@@ -1,4 +1,6 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - #define DEBUG 0 - #if DEBUG -diff --git a/gcc/testsuite/gcc.dg/graphite/pr46185.c b/gcc/testsuite/gcc.dg/graphite/pr46185.c -index 36d46a4..738c9a8 100644 ---- a/gcc/testsuite/gcc.dg/graphite/pr46185.c -+++ b/gcc/testsuite/gcc.dg/graphite/pr46185.c -@@ -1,5 +1,7 @@ - /* { dg-do run } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ - /* { dg-options "-O2 -floop-interchange -ffast-math -fno-ipa-cp" } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - #define DEBUG 0 - #if DEBUG -diff --git a/gcc/testsuite/gcc.dg/graphite/uns-interchange-15.c b/gcc/testsuite/gcc.dg/graphite/uns-interchange-15.c -index fe2669f..dd77aa3 100644 ---- a/gcc/testsuite/gcc.dg/graphite/uns-interchange-15.c -+++ b/gcc/testsuite/gcc.dg/graphite/uns-interchange-15.c -@@ -1,4 +1,6 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - #define DEBUG 0 - #if DEBUG -diff --git a/gcc/testsuite/gcc.dg/graphite/uns-interchange-mvt.c b/gcc/testsuite/gcc.dg/graphite/uns-interchange-mvt.c -index 211c9ab..c7defb4 100644 ---- a/gcc/testsuite/gcc.dg/graphite/uns-interchange-mvt.c -+++ b/gcc/testsuite/gcc.dg/graphite/uns-interchange-mvt.c -@@ -1,4 +1,6 @@ - /* { dg-require-effective-target size32plus } */ -+/* { dg-require-effective-target nds32_full_addr_space { target nds32*-*-elf* } } */ -+/* { dg-additional-options "-mcmodel=large" { target nds32*-*-elf* } } */ - - #define DEBUG 0 - #if DEBUG -diff --git a/gcc/testsuite/gcc.dg/initpri1.c b/gcc/testsuite/gcc.dg/initpri1.c -index 794ea2b..10b3a24 100644 ---- a/gcc/testsuite/gcc.dg/initpri1.c -+++ b/gcc/testsuite/gcc.dg/initpri1.c -@@ -1,4 +1,5 @@ - /* { dg-do run { target init_priority } } */ -+/* { dg-options "-mctor-dtor" { target { nds32*-*-* } } } */ - - extern void abort (); - -diff --git a/gcc/testsuite/gcc.dg/initpri2.c b/gcc/testsuite/gcc.dg/initpri2.c -index fa9fda0..1418411 100644 ---- a/gcc/testsuite/gcc.dg/initpri2.c -+++ b/gcc/testsuite/gcc.dg/initpri2.c -@@ -1,4 +1,5 @@ - /* { dg-do compile { target init_priority } } */ -+/* { dg-options "-mctor-dtor" { target { nds32*-*-* } } } */ - - /* Priorities must be in the range [0, 65535]. */ - void c1() -diff --git a/gcc/testsuite/gcc.dg/initpri3.c b/gcc/testsuite/gcc.dg/initpri3.c -index 1633da0..e1b8cf6 100644 ---- a/gcc/testsuite/gcc.dg/initpri3.c -+++ b/gcc/testsuite/gcc.dg/initpri3.c -@@ -1,6 +1,7 @@ - /* { dg-do run { target init_priority } } */ - /* { dg-require-effective-target lto } */ - /* { dg-options "-flto -O3" } */ -+/* { dg-options "-flto -O3 -mctor-dtor" { target { nds32*-*-* } } } */ - - extern void abort (); - -diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c -index 4db904b..2290d8b 100644 ---- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c -+++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c -@@ -1,5 +1,6 @@ - /* { dg-do run } */ - /* { dg-options "-O2 -fipa-sra -fdump-tree-eipa_sra-details" } */ -+/* { dg-additional-options "-u_printf_float -u_scanf_float" { target nds32*-*-* } } */ - - struct bovid - { -diff --git a/gcc/testsuite/gcc.dg/lower-subreg-1.c b/gcc/testsuite/gcc.dg/lower-subreg-1.c -index 47057fe..25439b1 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-*-* sparc*-*-* spu-*-* tilegx-*-* nds32*-*-* } } } } } */ - /* { 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/pr28796-2.c b/gcc/testsuite/gcc.dg/pr28796-2.c -index f56a5d4..fff71bc 100644 ---- a/gcc/testsuite/gcc.dg/pr28796-2.c -+++ b/gcc/testsuite/gcc.dg/pr28796-2.c -@@ -2,6 +2,7 @@ - /* { dg-options "-O2 -funsafe-math-optimizations -fno-finite-math-only -DUNSAFE" } */ - /* { dg-add-options ieee } */ - /* { dg-skip-if "No Inf/NaN support" { spu-*-* } } */ -+/* { dg-skip-if "No Denormmalized support" { nds32_ext_fpu } } */ - - #include "tg-tests.h" - -diff --git a/gcc/testsuite/gcc.dg/sibcall-10.c b/gcc/testsuite/gcc.dg/sibcall-10.c -index d98b43a..bb0e24c 100644 ---- a/gcc/testsuite/gcc.dg/sibcall-10.c -+++ b/gcc/testsuite/gcc.dg/sibcall-10.c -@@ -5,7 +5,7 @@ - Copyright (C) 2002 Free Software Foundation Inc. - Contributed by Hans-Peter Nilsson */ - --/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ -+/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ - /* -mlongcall disables sibcall patterns. */ - /* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */ - /* { dg-options "-O2 -foptimize-sibling-calls" } */ -diff --git a/gcc/testsuite/gcc.dg/sibcall-3.c b/gcc/testsuite/gcc.dg/sibcall-3.c -index eafe8dd..f188a18 100644 ---- a/gcc/testsuite/gcc.dg/sibcall-3.c -+++ b/gcc/testsuite/gcc.dg/sibcall-3.c -@@ -5,7 +5,7 @@ - Copyright (C) 2002 Free Software Foundation Inc. - Contributed by Hans-Peter Nilsson */ - --/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ -+/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ - /* -mlongcall disables sibcall patterns. */ - /* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */ - /* { dg-options "-O2 -foptimize-sibling-calls" } */ -diff --git a/gcc/testsuite/gcc.dg/sibcall-4.c b/gcc/testsuite/gcc.dg/sibcall-4.c -index 1e039c6..a8c844a 100644 ---- a/gcc/testsuite/gcc.dg/sibcall-4.c -+++ b/gcc/testsuite/gcc.dg/sibcall-4.c -@@ -5,7 +5,7 @@ - Copyright (C) 2002 Free Software Foundation Inc. - Contributed by Hans-Peter Nilsson */ - --/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ -+/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ - /* -mlongcall disables sibcall patterns. */ - /* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */ - /* { dg-options "-O2 -foptimize-sibling-calls" } */ -diff --git a/gcc/testsuite/gcc.dg/sibcall-9.c b/gcc/testsuite/gcc.dg/sibcall-9.c -index 34e7053..71c3251 100644 ---- a/gcc/testsuite/gcc.dg/sibcall-9.c -+++ b/gcc/testsuite/gcc.dg/sibcall-9.c -@@ -5,7 +5,7 @@ - Copyright (C) 2002 Free Software Foundation Inc. - Contributed by Hans-Peter Nilsson */ - --/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nds32*-*-* nvptx-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ -+/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nvptx-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ - /* -mlongcall disables sibcall patterns. */ - /* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */ - /* { dg-options "-O2 -foptimize-sibling-calls" } */ -diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c -index 7864c6a..c768ca2 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.dg/torture/type-generic-1.c b/gcc/testsuite/gcc.dg/torture/type-generic-1.c -index 3897818..6815e8b 100644 ---- a/gcc/testsuite/gcc.dg/torture/type-generic-1.c -+++ b/gcc/testsuite/gcc.dg/torture/type-generic-1.c -@@ -3,6 +3,7 @@ - - /* { dg-do run } */ - /* { dg-skip-if "No Inf/NaN support" { spu-*-* } } */ -+/* { dg-skip-if "No Denormmalized support" { nds32_ext_fpu } } */ - /* { dg-options "-DUNSAFE" { target tic6x*-*-* visium-*-* } } */ - /* { dg-add-options ieee } */ - -diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c -index 1a4bfe6..78c948a 100644 ---- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c -+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c -@@ -25,4 +25,4 @@ foo () - but the loop reads only one element at a time, and DOM cannot resolve these. - The same happens on powerpc depending on the SIMD support available. */ - --/* { dg-final { scan-tree-dump "return 28;" "optimized" { xfail { { alpha*-*-* hppa*64*-*-* powerpc64*-*-* } || { sparc*-*-* && lp64 } } } } } */ -+/* { dg-final { scan-tree-dump "return 28;" "optimized" { xfail { { alpha*-*-* hppa*64*-*-* powerpc64*-*-* nds32*-*-*} || { sparc*-*-* && lp64 } } } } } */ -diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp88.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp88.c -index f70b311..8a1081c 100644 ---- a/gcc/testsuite/gcc.dg/tree-ssa/vrp88.c -+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp88.c -@@ -33,6 +33,6 @@ bitmap_single_bit_set_p (const_bitmap a) - } - - /* Verify that VRP simplified an "if" statement. */ --/* { dg-final { scan-tree-dump "Folded into: if.*" "vrp1"} } */ -+/* { dg-final { scan-tree-dump "Folded into: if.*" "vrp1" { xfail *-*-* } } } */ - - -diff --git a/gcc/testsuite/gcc.target/nds32/basic-main.c b/gcc/testsuite/gcc.target/nds32/basic-main.c -index 6fdbc35..7341fb5 100644 ---- a/gcc/testsuite/gcc.target/nds32/basic-main.c -+++ b/gcc/testsuite/gcc.target/nds32/basic-main.c -@@ -1,9 +1,10 @@ - /* This is a basic main function test program. */ - --/* { dg-do run } */ --/* { dg-options "-O0" } */ -+/* { dg-do run } */ -+/* { dg-options "-O0" } */ - --int main(void) -+int -+main (void) - { - return 0; - } -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE1-abs.c b/gcc/testsuite/gcc.target/nds32/builtin-PE1-abs.c -new file mode 100644 -index 0000000..8cadcfd ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE1-abs.c -@@ -0,0 +1,20 @@ -+/* This is a test program for abs instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ int a = -4; -+ int abs = __nds32__abs (a); -+ -+ if (abs != 4) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE1-ave.c b/gcc/testsuite/gcc.target/nds32/builtin-PE1-ave.c -new file mode 100644 -index 0000000..d2c87db ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE1-ave.c -@@ -0,0 +1,21 @@ -+/* This is a test program for ave instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ int a = 4; -+ int b = 2; -+ int ave = __nds32__ave (a, b); -+ -+ if (ave != 3) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE1-bclr.c b/gcc/testsuite/gcc.target/nds32/builtin-PE1-bclr.c -new file mode 100644 -index 0000000..0e6c1e0 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE1-bclr.c -@@ -0,0 +1,20 @@ -+/* This is a test program for bclr instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ int a = 1; -+ int c = __nds32__bclr (a, 0); -+ -+ if (c != 0) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE1-bset.c b/gcc/testsuite/gcc.target/nds32/builtin-PE1-bset.c -new file mode 100644 -index 0000000..1bd8513 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE1-bset.c -@@ -0,0 +1,20 @@ -+/* This is a test program for bset instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ int c = 0; -+ c = __nds32__bset (c, 0); -+ -+ if (c != 1) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE1-btgl.c b/gcc/testsuite/gcc.target/nds32/builtin-PE1-btgl.c -new file mode 100644 -index 0000000..a1dbc00 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE1-btgl.c -@@ -0,0 +1,20 @@ -+/* This is a test program for btgl instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ int a = 1; -+ int c = __nds32__btgl (1, 0); -+ -+ if (c != 0) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE1-btst.c b/gcc/testsuite/gcc.target/nds32/builtin-PE1-btst.c -new file mode 100644 -index 0000000..c001f94 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE1-btst.c -@@ -0,0 +1,20 @@ -+/* This is a test program for btst instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ int c = 1; -+ c = __nds32__btst (c, 0); -+ -+ if (c != 1) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE1-clip.c b/gcc/testsuite/gcc.target/nds32/builtin-PE1-clip.c -new file mode 100644 -index 0000000..d63b298 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE1-clip.c -@@ -0,0 +1,20 @@ -+/* This is a test program for clip instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ int c = 33; -+ c = __nds32__clip (c, 5); -+ -+ if (c != 31) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE1-clips.c b/gcc/testsuite/gcc.target/nds32/builtin-PE1-clips.c -new file mode 100644 -index 0000000..3e3f663 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE1-clips.c -@@ -0,0 +1,20 @@ -+/* This is a test program for clips instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ int a = -33; -+ int c = __nds32__clips (a, 5); -+ -+ if (c != -32) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE1-clo.c b/gcc/testsuite/gcc.target/nds32/builtin-PE1-clo.c -new file mode 100644 -index 0000000..d672a33 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE1-clo.c -@@ -0,0 +1,20 @@ -+/* This is a test program for clo instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ int c = 0xFFFF0000; -+ c = __nds32__clo (c); -+ -+ if (c != 16) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE1-clz.c b/gcc/testsuite/gcc.target/nds32/builtin-PE1-clz.c -new file mode 100644 -index 0000000..17e6318 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE1-clz.c -@@ -0,0 +1,20 @@ -+/* This is a test program for clz instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ int c = 0x0000FFFF; -+ c = __nds32__clz (c); -+ -+ if (c != 16) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE2-bse.c b/gcc/testsuite/gcc.target/nds32/builtin-PE2-bse.c -new file mode 100644 -index 0000000..c769fea ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE2-bse.c -@@ -0,0 +1,28 @@ -+/* This is a test program for bse instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf2 } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int a = 0xF0F0F0F0; -+ unsigned int b = 0x00000300; -+ unsigned int r = 0; -+ -+ unsigned int verify_b = 0x00000300; -+ unsigned int verify_r = 0; -+ -+ __nds32__bse (&r, a, &b); -+ a = 0xF0F0F0F0; -+ asm volatile ("bse %0, %2, %1": "+&r" (verify_r), "+&r" (verify_b) : "r" (a)); -+ -+ if ((verify_b == b) && (verify_r == r)) -+ exit (0); -+ else -+ abort (); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE2-bsp.c b/gcc/testsuite/gcc.target/nds32/builtin-PE2-bsp.c -new file mode 100644 -index 0000000..d798719 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE2-bsp.c -@@ -0,0 +1,26 @@ -+/* This is a test program for bsp instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf2 } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int a = 0x0000000F; -+ unsigned int b = 0x00000300; -+ unsigned int r = 0; -+ unsigned int verify_b = 0x00000300; -+ unsigned int verify_r = 0; -+ -+ __nds32__bsp (&r, a, &b); -+ asm volatile ("bsp %0, %2, %1": "+&r" (verify_r), "+&r" (verify_b) : "r" (a)); -+ -+ if ((verify_b == b) && (verify_r == r)) -+ exit (0); -+ else -+ abort (); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE2-pbsad.c b/gcc/testsuite/gcc.target/nds32/builtin-PE2-pbsad.c -new file mode 100644 -index 0000000..bc4fe42 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE2-pbsad.c -@@ -0,0 +1,21 @@ -+/* This is a test program for pbsad instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf2 } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int a = 0x09070605; -+ unsigned int b = 0x04020301; -+ unsigned int r = __nds32__pbsad (a, b); -+ -+ if (r != 17) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-PE2-pbsada.c b/gcc/testsuite/gcc.target/nds32/builtin-PE2-pbsada.c -new file mode 100644 -index 0000000..6ed1b08 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-PE2-pbsada.c -@@ -0,0 +1,23 @@ -+/* This is a test program for pbsada instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_perf2 } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int a = 0x09070605; -+ unsigned int b = 0x04020301; -+ unsigned int r = 1; -+ -+ r = __nds32__pbsada(r, a, b); -+ -+ if (r != 18) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-add16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-add16.c -new file mode 100644 -index 0000000..0eec324 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-add16.c -@@ -0,0 +1,49 @@ -+/* This is a test program for add16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int add16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__add16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_uadd16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_uadd16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_sadd16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_sadd16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = add16 (0x0001f000, 0x00011000); -+ uint16x2_t v_ua = v_uadd16 ((uint16x2_t) {0xf000, 0xf000}, -+ (uint16x2_t) {0x1000, 0x2000}); -+ int16x2_t v_sa = v_sadd16 ((int16x2_t) {0xf777, 0xf111}, -+ (int16x2_t) {0x1000, 0x2000}); -+ -+ if (a != 0x00020000) -+ abort (); -+ else if (v_ua[0] != 0x0000 -+ || v_ua[1] != 0x1000) -+ abort (); -+ else if (v_sa[0] != 0x0777 -+ || v_sa[1] != 0x1111) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-add64.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-add64.c -new file mode 100644 -index 0000000..b761b7f ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-add64.c -@@ -0,0 +1,36 @@ -+/* This is a test program for add64 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long sadd64 (long long ra, long long rb) -+{ -+ return __nds32__sadd64 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+unsigned long long uadd64 (unsigned long long ra, unsigned long long rb) -+{ -+ return __nds32__uadd64 (ra, rb); -+} -+ -+int -+main () -+{ -+ long long sa = sadd64 (0x1122334400000000ll, 0x55667788ll); -+ unsigned long long ua = uadd64 (0xffff00000000ull, 0x55667788ull); -+ -+ if (sa != 0x1122334455667788ll) -+ abort (); -+ else if (ua != 0xffff55667788ull) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-add8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-add8.c -new file mode 100644 -index 0000000..77e686c ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-add8.c -@@ -0,0 +1,53 @@ -+/* This is a test program for add8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int add8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__add8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_uadd8 (uint8x4_t ra, uint8x4_t rb) -+{ -+ return __nds32__v_uadd8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int8x4_t v_sadd8 (int8x4_t ra, int8x4_t rb) -+{ -+ return __nds32__v_sadd8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = add8 (0x11223344, 0x55667788); -+ uint8x4_t v_ua = v_uadd8 ((uint8x4_t) {0xff, 0xee, 0xdd, 0xcc}, -+ (uint8x4_t) {0x1, 0xee, 0xdd, 0xcc}); -+ int8x4_t v_sa = v_sadd8 ((int8x4_t) {0x80, 0x7f, 0xbb, 0xaa}, -+ (int8x4_t) {0x80, 0x7f, 0xbb, 0xaa}); -+ -+ if (a != 0x6688aacc) -+ abort (); -+ else if (v_ua[0] != 0 -+ || v_ua[1] != 0xdc -+ || v_ua[2] != 0xba -+ || v_ua[3] != 0x98) -+ abort (); -+ else if (v_sa[0] != 0 -+ || v_sa[1] != (char) 0xfe -+ || v_sa[2] != 0x76 -+ || v_sa[3] != 0x54) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-bitrev.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-bitrev.c -new file mode 100644 -index 0000000..2c8c297 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-bitrev.c -@@ -0,0 +1,27 @@ -+/* This is a test program for bitrev instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int bitrev (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__bitrev (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = bitrev (0xd, 1); -+ -+ if (a != 0x2) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-bpick.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-bpick.c -new file mode 100644 -index 0000000..78893cb ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-bpick.c -@@ -0,0 +1,27 @@ -+/* This is a test program for bpick instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int bpick (unsigned int ra, unsigned int rb, unsigned int rc) -+{ -+ return __nds32__bpick (ra, rb, rc); -+} -+ -+int -+main () -+{ -+ unsigned int a = bpick (0x11223344, 0x11332244, 0); -+ -+ if (a != 0x11332244) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-cmpeq16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-cmpeq16.c -new file mode 100644 -index 0000000..c37abf4 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-cmpeq16.c -@@ -0,0 +1,49 @@ -+/* This is a test program for cmpeq16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int cmpeq16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__cmpeq16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_scmpeq16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_scmpeq16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_ucmpeq16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_ucmpeq16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = cmpeq16 (0xffff0000, 0xffff0001); -+ uint16x2_t v_sa = v_scmpeq16 ((int16x2_t) {0x7fff, 0x8000}, -+ (int16x2_t) {0x8000, 0x8000}); -+ uint16x2_t v_ua = v_ucmpeq16 ((uint16x2_t) {0x7fff, 0x8000}, -+ (uint16x2_t) {0x8000, 0x8000}); -+ -+ if (a != 0xffff0000) -+ abort (); -+ else if (v_sa[0] != 0 -+ || v_sa[1] != 0xffff) -+ abort (); -+ else if (v_ua[0] != 0 -+ || v_ua[1] != 0xffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-cmpeq8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-cmpeq8.c -new file mode 100644 -index 0000000..a692dac ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-cmpeq8.c -@@ -0,0 +1,53 @@ -+/* This is a test program for cmpeq8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int cmpeq8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__cmpeq8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_scmpeq8 (int8x4_t ra, int8x4_t rb) -+{ -+ return __nds32__v_scmpeq8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_ucmpeq8 (uint8x4_t ra, uint8x4_t rb) -+{ -+ return __nds32__v_ucmpeq8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = cmpeq8 (0xffff0000, 0xffff0101); -+ uint8x4_t v_sa = v_scmpeq8 ((int8x4_t) { 0x7f, 0x7f, 0x01, 0x01}, -+ (int8x4_t) { 0x7f, 0x7f, 0x00, 0x00}); -+ uint8x4_t v_ua = v_ucmpeq8 ((uint8x4_t) { 0x7f, 0x7f, 0x01, 0x01}, -+ (uint8x4_t) { 0x7f, 0x7f, 0x00, 0x00}); -+ -+ if (a != 0xffff0000) -+ abort (); -+ else if (v_sa[0] != 0xff -+ || v_sa[1] != 0xff -+ || v_sa[2] != 0 -+ || v_sa[3] != 0) -+ abort (); -+ else if (v_ua[0] != 0xff -+ || v_ua[1] != 0xff -+ || v_ua[2] != 0 -+ || v_ua[3] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-cras16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-cras16.c -new file mode 100644 -index 0000000..7d6da46 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-cras16.c -@@ -0,0 +1,58 @@ -+/* This is a test program for cras16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int cras16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__cras16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_ucras16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_ucras16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_scras16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_scras16 (ra, rb); -+} -+ -+int -+main () -+{ -+ -+#ifdef __NDS32_EL__ -+ uint16x2_t v_ua_p = {1, 0}; -+ int16x2_t v_sa_p = {0x1000, 0x111}; -+#else -+ uint16x2_t v_ua_p = {0x2469, 0xe000}; -+ int16x2_t v_sa_p = {0x3000, 0xe111}; -+#endif -+ -+ unsigned int a = cras16 (0x0001f000, 0x0001f000); -+ uint16x2_t v_ua = v_ucras16 ((uint16x2_t) {0x1235, 0xf000}, -+ (uint16x2_t) {0x1000, 0x1234}); -+ int16x2_t v_sa = v_scras16 ((int16x2_t) {0x2000, 0xf111}, -+ (int16x2_t) {0x1000, 0x1000}); -+ -+ if (a != 0xf001efff) -+ abort (); -+ else if (v_ua[0] != v_ua_p[0] -+ || v_ua[1] != v_ua_p[1]) -+ abort (); -+ else if (v_sa[0] != v_sa_p[0] -+ || v_sa[1] != v_sa_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-crsa16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-crsa16.c -new file mode 100644 -index 0000000..de99c3a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-crsa16.c -@@ -0,0 +1,57 @@ -+/* This is a test program for crsa16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int crsa16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__crsa16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_ucrsa16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_ucrsa16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_scrsa16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_scrsa16 (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ uint16x2_t v_ua_p = {0x2469, 0xe000}; -+ int16x2_t v_sa_p = {0x3000, 0x110}; -+#else -+ uint16x2_t v_ua_p = {1, 0}; -+ int16x2_t v_sa_p = {0x1000, 0x112}; -+#endif -+ -+ unsigned int a = crsa16 (0x0001f000, 0x0001f000); -+ uint16x2_t v_ua = v_ucrsa16 ((uint16x2_t) {0x1235, 0xf000}, -+ (uint16x2_t) {0x1000, 0x1234}); -+ int16x2_t v_sa = v_scrsa16 ((int16x2_t) {0x2000, 0x0111}, -+ (int16x2_t) {0x0001, 0x1000}); -+ -+ if (a != 0x1001f001) -+ abort (); -+ else if (v_ua[0] != v_ua_p[0] -+ || v_ua[1] != v_ua_p[1]) -+ abort (); -+ else if (v_sa[0] != v_sa_p[0] -+ || v_sa[1] != v_sa_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-insb.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-insb.c -new file mode 100644 -index 0000000..ebd0348 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-insb.c -@@ -0,0 +1,27 @@ -+/* This is a test program for insb instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int insb (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__insb (ra, rb, 1); -+} -+ -+int -+main () -+{ -+ unsigned int a = insb (0x11220044, 0x33); -+ -+ if (a != 0x11223344) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-pkbb16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-pkbb16.c -new file mode 100644 -index 0000000..23d92e9 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-pkbb16.c -@@ -0,0 +1,44 @@ -+/* This is a test program for pkbb16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int pkbb16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__pkbb16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_pkbb16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_pkbb16 (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ uint16x2_t va_p = {0xcccc, 0xaaaa}; -+#else -+ uint16x2_t va_p = {0xbbbb, 0xdddd}; -+#endif -+ -+ unsigned int a = pkbb16 (0x11223344, 0x55667788); -+ uint16x2_t va = v_pkbb16 ((uint16x2_t) {0xaaaa, 0xbbbb}, -+ (uint16x2_t) {0xcccc, 0xdddd}); -+ -+ if (a != 0x33447788) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-pkbt16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-pkbt16.c -new file mode 100644 -index 0000000..6c34420 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-pkbt16.c -@@ -0,0 +1,44 @@ -+/* This is a test program for pkbt16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int pkbt16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__pkbt16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_pkbt16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_pkbt16 (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ uint16x2_t va_p = {0xdddd, 0xaaaa}; -+#else -+ uint16x2_t va_p = {0xbbbb, 0xcccc}; -+#endif -+ -+ unsigned int a = pkbt16 (0x11223344, 0x55667788); -+ uint16x2_t va = v_pkbt16 ((uint16x2_t) {0xaaaa, 0xbbbb}, -+ (uint16x2_t) {0xcccc, 0xdddd}); -+ -+ if (a != 0x33445566) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-pktb16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-pktb16.c -new file mode 100644 -index 0000000..0aab5df ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-pktb16.c -@@ -0,0 +1,44 @@ -+/* This is a test program for pktb16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int pktb16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__pktb16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_pktb16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_pktb16 (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ uint16x2_t va_p = {0xcccc, 0xbbbb}; -+#else -+ uint16x2_t va_p = {0xaaaa, 0xdddd}; -+#endif -+ -+ unsigned int a = pktb16 (0x11223344, 0x55667788); -+ uint16x2_t va = v_pktb16 ((uint16x2_t) {0xaaaa, 0xbbbb}, -+ (uint16x2_t) {0xcccc, 0xdddd}); -+ -+ if (a != 0x11227788) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-pktt16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-pktt16.c -new file mode 100644 -index 0000000..745cde5 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-pktt16.c -@@ -0,0 +1,44 @@ -+/* This is a test program for pktt16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int pktt16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__pktt16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_pktt16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_pktt16 (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ uint16x2_t va_p = {0xdddd, 0xbbbb}; -+#else -+ uint16x2_t va_p = {0xaaaa, 0xcccc}; -+#endif -+ -+ unsigned int a = pktt16 (0x11223344, 0x55667788); -+ uint16x2_t va = v_pktt16 ((uint16x2_t) {0xaaaa, 0xbbbb}, -+ (uint16x2_t) {0xcccc, 0xdddd}); -+ -+ if (a != 0x11225566) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-radd16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-radd16.c -new file mode 100644 -index 0000000..5271b41 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-radd16.c -@@ -0,0 +1,38 @@ -+/* This is a test program for radd16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int radd16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__radd16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_radd16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_radd16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = radd16 (0x7fff7fff, 0x7fff7fff); -+ int16x2_t va = v_radd16 ((int16x2_t) {0x8000, 0x4000}, -+ (int16x2_t) {0x8000, 0x8000}); -+ -+ if (a != 0x7fff7fff) -+ abort (); -+ else if (va[0] != (short) 0x8000 -+ || va[1] != (short) 0xe000) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-radd64.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-radd64.c -new file mode 100644 -index 0000000..3e82ff5 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-radd64.c -@@ -0,0 +1,27 @@ -+/* This is a test program for radd64 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long radd64 (long long ra, long long rb) -+{ -+ return __nds32__radd64 (ra, rb); -+} -+ -+int -+main () -+{ -+ long long a = radd64 (0xf000000000000000ll, 0xf000000000000000ll); -+ -+ if (a != 0xf000000000000000ll) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-radd8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-radd8.c -new file mode 100644 -index 0000000..10735a1 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-radd8.c -@@ -0,0 +1,40 @@ -+/* This is a test program for radd8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int radd8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__radd8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int8x4_t v_radd8 (int8x4_t ra, int8x4_t rb) -+{ -+ return __nds32__v_radd8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = radd8 (0x11223344, 0x55667788); -+ int8x4_t va = v_radd8 ((int8x4_t) {0x7f, 0x80, 0x80, 0xaa}, -+ (int8x4_t) {0x7f, 0x80, 0x40, 0xaa}); -+ -+ if (a != 0x334455e6) -+ abort (); -+ else if (va[0] != 0x7f -+ || va[1] != (char) 0x80 -+ || va[2] != (char) 0xe0 -+ || va[3] != (char) 0xaa) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-raddw.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-raddw.c -new file mode 100644 -index 0000000..190a477 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-raddw.c -@@ -0,0 +1,27 @@ -+/* This is a test program for raddw instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int raddw (int ra, int rb) -+{ -+ return __nds32__raddw (ra, rb); -+} -+ -+int -+main () -+{ -+ int a = raddw (0x80000000, 0x80000000); -+ -+ if (a != 0x80000000) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-rcras16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rcras16.c -new file mode 100644 -index 0000000..2a2288a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rcras16.c -@@ -0,0 +1,44 @@ -+/* This is a test program for rcras16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int rcras16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__rcras16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_rcras16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_rcras16 (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int16x2_t va_p = {0x7fff, 0x8000}; -+#else -+ int16x2_t va_p = {0xffff, 0}; -+#endif -+ -+ unsigned int a = rcras16 (0x0fff0000, 0x00000fff); -+ int16x2_t va = v_rcras16 ((int16x2_t) {0x7fff, 0x8000}, -+ (int16x2_t) {0x8000, 0x8000}); -+ -+ if (a != 0x0fff0000) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-rcrsa16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rcrsa16.c -new file mode 100644 -index 0000000..ebcc0f6 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rcrsa16.c -@@ -0,0 +1,44 @@ -+/* This is a test program for rcrsa16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int rcrsa16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__rcrsa16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_rcrsa16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_rcrsa16 (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int16x2_t va_p = {0x8000, 0x8000}; -+#else -+ int16x2_t va_p = {0, 0xffff}; -+#endif -+ -+ unsigned int a = rcrsa16 (0x7fff7fff, 0x7fff8000); -+ int16x2_t va = v_rcrsa16 ((int16x2_t) {0x8000, 0x8000}, -+ (int16x2_t) {0x7fff, 0x8000}); -+ -+ if (a != 0x7fff7fff) -+ abort (); -+ else if (va[0] != va_p [0] -+ || va[1] != va_p [1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsub16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsub16.c -new file mode 100644 -index 0000000..f9fcc86 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsub16.c -@@ -0,0 +1,38 @@ -+/* This is a test program for rsub16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int rsub16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__rsub16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_rsub16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_rsub16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = rsub16 (0x7fff7fff, 0x80008000); -+ int16x2_t va = v_rsub16 ((int16x2_t) {0x8000, 0x8000}, -+ (int16x2_t) {0x7fff, 0x4000}); -+ -+ if (a != 0x7fff7fff) -+ abort (); -+ else if (va[0] != (short) 0x8000 -+ || va[1] != (short) 0xa000) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsub64.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsub64.c -new file mode 100644 -index 0000000..227eba7 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsub64.c -@@ -0,0 +1,27 @@ -+/* This is a test program for rsub64 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long rsub64 (long long ra, long long rb) -+{ -+ return __nds32__rsub64 (ra, rb); -+} -+ -+int -+main () -+{ -+ long long a = rsub64 (0xe, 0xf); -+ -+ if (a != 0xffffffffffffffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsub8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsub8.c -new file mode 100644 -index 0000000..0f1dddc ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsub8.c -@@ -0,0 +1,40 @@ -+/* This is a test program for rsub8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int rsub8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__rsub8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int8x4_t v_rsub8 (int8x4_t ra, int8x4_t rb) -+{ -+ return __nds32__v_rsub8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = rsub8 (0x55667788, 0x11223344); -+ int8x4_t va = v_rsub8 ((int8x4_t) {0x7f, 0x80, 0x80, 0xaa}, -+ (int8x4_t) {0x80, 0x7f, 0x40, 0xaa}); -+ -+ if (a != 0x222222a2) -+ abort (); -+ else if (va[0] != 0x7f -+ || va[1] != (char) 0x80 -+ || va[2] != (char) 0xa0 -+ || va[3] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsubw.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsubw.c -new file mode 100644 -index 0000000..b70a229 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-rsubw.c -@@ -0,0 +1,27 @@ -+/* This is a test program for rsubw instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int rsubw (int ra, int rb) -+{ -+ return __nds32__rsubw (ra, rb); -+} -+ -+int -+main () -+{ -+ int a = rsubw (0x80000000, 0x7fffffff); -+ -+ if (a != 0x80000000) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmple16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmple16.c -new file mode 100644 -index 0000000..95251d6 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmple16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for scmple16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int scmple16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__scmple16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_scmple16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_scmple16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = scmple16 (0xfffe0001, 0xffff0000); -+ uint16x2_t va = v_scmple16 ((int16x2_t) {0x7fff, 0x7ffe}, -+ (int16x2_t) {0x7ffe, 0x7fff}); -+ if (a != 0xffff0000) -+ abort (); -+ else if (va[0] != 0 -+ || va[1] != 0xffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmple8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmple8.c -new file mode 100644 -index 0000000..6c0033d ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmple8.c -@@ -0,0 +1,40 @@ -+/* This is a test program for scmple8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int scmple8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__scmple8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_scmple8 (int8x4_t ra, int8x4_t rb) -+{ -+ return __nds32__v_scmple8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = scmple8 (0xfefe0101, 0xffff0000); -+ uint8x4_t va = v_scmple8 ((int8x4_t) {0x7e, 0x7e, 0x01, 0x01}, -+ (int8x4_t) {0x7f, 0x7f, 0x00, 0x00}); -+ -+ if (a != 0xffff0000) -+ abort (); -+ else if (va[0] != 0xff -+ || va[1] != 0xff -+ || va[2] != 0 -+ || va[3] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmplt16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmplt16.c -new file mode 100644 -index 0000000..5797711 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmplt16.c -@@ -0,0 +1,38 @@ -+/* This is a test program for scmplt16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int scmplt16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__scmplt16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_scmplt16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_scmplt16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = scmplt16 (0xfffe0001, 0xffff0000); -+ uint16x2_t va = v_scmplt16 ((int16x2_t) {0x7fff, 0x7ffe}, -+ (int16x2_t) {0x7ffe, 0x7fff}); -+ -+ if (a != 0xffff0000) -+ abort (); -+ else if (va[0] != 0 -+ || va[1] != 0xffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmplt8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmplt8.c -new file mode 100644 -index 0000000..3e52006 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-scmplt8.c -@@ -0,0 +1,40 @@ -+/* This is a test program for scmplt8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int scmplt8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__scmplt8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_scmplt8 (int8x4_t ra, int8x4_t rb) -+{ -+ return __nds32__v_scmplt8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = scmplt8 (0xfefe0101, 0xffff0000); -+ uint8x4_t va = v_scmplt8 ((int8x4_t) {0x7e, 0x7e, 0x01, 0x01}, -+ (int8x4_t) {0x7f, 0x7f, 0x00, 0x00}); -+ -+ if (a != 0xffff0000) -+ abort (); -+ else if (va[0] != 0xff -+ || va[1] != 0xff -+ || va[2] != 0 -+ || va[3] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sll16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sll16.c -new file mode 100644 -index 0000000..5ab9506 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sll16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for sll16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int sll16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__sll16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_sll16 (uint16x2_t ra, unsigned int rb) -+{ -+ return __nds32__v_sll16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = sll16 (0x0f00f000, 4); -+ uint16x2_t va = v_sll16 ((uint16x2_t) {0x7fff, 0x8000}, 4); -+ -+ if (a != 0xf0000000) -+ abort (); -+ else if (va[0] != 0xfff0 -+ || va[1] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smal.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smal.c -new file mode 100644 -index 0000000..f7e54b7 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smal.c -@@ -0,0 +1,36 @@ -+/* This is a test program for smal instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smal (long long ra, unsigned int rb) -+{ -+ return __nds32__smal (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smal (long long ra, int16x2_t rb) -+{ -+ return __nds32__v_smal (ra, rb); -+} -+ -+int -+main () -+{ -+ long long a = smal (0xfffff0000ll, 0x0001ffff); -+ long long va = v_smal (0xffffff0000ll, -+ (int16x2_t) {0x0002, 0xffff}); -+ if (a != 0xffffeffffll) -+ abort (); -+ else if (va != 0xfffffefffell) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalbb.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalbb.c -new file mode 100644 -index 0000000..c39a889 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalbb.c -@@ -0,0 +1,45 @@ -+/* This is a test program for smalbb instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smalbb (long long t, unsigned int a, unsigned int b) -+{ -+ return __nds32__smalbb (t, a, b); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smalbb (long long t, int16x2_t a, int16x2_t b) -+{ -+ return __nds32__v_smalbb (t, a, b); -+} -+ -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ long long a_p = 0x12345679075ca9d3ll; -+ long long va_p = 0x12345679075ca9d3ll; -+#else -+ long long a_p = 0x12345679075ca9d3ll; -+ long long va_p = 0x12345678ffffffffll; -+#endif -+ -+ long long a = smalbb (0x12345678ffffffffll,0x00006789, 0x00001234); -+ long long va = v_smalbb (0x12345678ffffffffll, (int16x2_t) {0x6789, 0}, -+ (int16x2_t) {0x1234, 0}); -+ if (a != a_p) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalbt.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalbt.c -new file mode 100644 -index 0000000..06577fd ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalbt.c -@@ -0,0 +1,45 @@ -+/* This is a test program for smalbt instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smalbt (long long t, unsigned int a, unsigned int b) -+{ -+ return __nds32__smalbt (t, a, b); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smalbt (long long t, int16x2_t a, int16x2_t b) -+{ -+ return __nds32__v_smalbt (t, a, b); -+} -+ -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ long long a_p = 0x12345679075ca9d3ll; -+ long long va_p = 0x12345679075ca9d3ll; -+#else -+ long long a_p = 0x12345679075ca9d3ll; -+ long long va_p = 0x12345678ffffffffll; -+#endif -+ -+ long long a = smalbt (0x12345678ffffffffll, 0x00006789, 0x12340000); -+ long long va = v_smalbt (0x12345678ffffffffll, (int16x2_t) {0x6789, 0}, -+ (int16x2_t) {0, 0x1234}); -+ if (a != a_p) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalda.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalda.c -new file mode 100644 -index 0000000..33b4b3f ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalda.c -@@ -0,0 +1,38 @@ -+/* This is a test program for smalda instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smalda (long long t, unsigned int a, unsigned int b) -+{ -+ return __nds32__smalda (t, a, b); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smalda (long long t, int16x2_t a, int16x2_t b) -+{ -+ return __nds32__v_smalda (t, a, b); -+} -+ -+ -+int -+main () -+{ -+ long long a = smalda (0x12345678ffffffffll, 0x67890000, 0x12340000); -+ long long va = v_smalda (0x12345678ffffffffll, (int16x2_t) {0, 0x6789}, -+ (int16x2_t) {0, 0x1234}); -+ -+ if (a != 0x12345679075CA9D3ll) -+ abort (); -+ else if (va != 0x12345679075CA9D3ll) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smaldrs.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smaldrs.c -new file mode 100644 -index 0000000..48255b1 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smaldrs.c -@@ -0,0 +1,46 @@ -+/* This is a test program for smaldrs instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smaldrs (long long t, unsigned int a, unsigned int b) -+{ -+ return __nds32__smaldrs (t, a, b); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smaldrs (long long t, int16x2_t a, int16x2_t b) -+{ -+ return __nds32__v_smaldrs (t, a, b); -+} -+ -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ long long a_p = 0x12345678ffffaaaall; -+ long long va_p = 0x12345678ffffaaaall; -+#else -+ long long a_p = 0x12345678ffffaaaall; -+ long long va_p = 0x1234567900005554ll; -+#endif -+ -+ long long a = smaldrs (0x12345678ffffffffll, 0x67890001, 0x00011234); -+ long long va = v_smaldrs (0x12345678ffffffffll, (int16x2_t) {0x0001, 0x6789}, -+ (int16x2_t) {0x1234, 0x0001}); -+ -+ if (a != a_p) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalds.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalds.c -new file mode 100644 -index 0000000..5a89ea6 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalds.c -@@ -0,0 +1,46 @@ -+/* This is a test program for smalds instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smalds (long long t, unsigned int a, unsigned int b) -+{ -+ return __nds32__smalds (t, a, b); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smalds (long long t, int16x2_t a, int16x2_t b) -+{ -+ return __nds32__v_smalds (t, a, b); -+} -+ -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ long long a_p = 0x12345678ffffaaaall; -+ long long va_p = 0x12345678ffffaaaall; -+#else -+ long long a_p = 0x12345678ffffaaaall; -+ long long va_p = 0x1234567900005554ll; -+#endif -+ -+ long long a = smalds (0x12345678ffffffffll, 0x12340001, 0x00016789); -+ long long va = v_smalds (0x12345678ffffffffll, (int16x2_t) {0x0001, 0x1234}, -+ (int16x2_t) {0x6789, 0x0001}); -+ -+ if (a != a_p) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smaltt.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smaltt.c -new file mode 100644 -index 0000000..709607a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smaltt.c -@@ -0,0 +1,46 @@ -+/* This is a test program for smaltt instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smaltt (long long t, unsigned int a, unsigned int b) -+{ -+ return __nds32__smaltt (t, a, b); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smaltt (long long t, int16x2_t a, int16x2_t b) -+{ -+ return __nds32__v_smaltt (t, a, b); -+} -+ -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ long long a_p = 0x12345679075ca9d3ll; -+ long long va_p = 0x12345679075ca9d3ll; -+#else -+ long long a_p = 0x12345679075ca9d3ll; -+ long long va_p = 0x12345678ffffffffll; -+#endif -+ -+ long long a = smaltt (0x12345678ffffffffll, 0x67890000, 0x12340000); -+ long long va = v_smaltt (0x12345678ffffffffll, (int16x2_t) {0, 0x6789}, -+ (int16x2_t) {0, 0x1234}); -+ -+ if (a != a_p) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalxda.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalxda.c -new file mode 100644 -index 0000000..0f90250 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalxda.c -@@ -0,0 +1,38 @@ -+/* This is a test program for smalxda instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smalxda (long long t, unsigned int a, unsigned int b) -+{ -+ return __nds32__smalxda (t, a, b); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smalxda (long long t, int16x2_t a, int16x2_t b) -+{ -+ return __nds32__v_smalxda (t, a, b); -+} -+ -+ -+int -+main () -+{ -+ long long a = smalxda (0x12345678ffffffffll, 0x67890000, 0x00001234); -+ long long va = v_smalxda (0x12345678ffffffffll, (int16x2_t) {0, 0x6789}, -+ (int16x2_t) {0x1234, 0}); -+ -+ if (a != 0x12345679075CA9D3) -+ abort (); -+ else if (va != 0x12345679075CA9D3) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalxds.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalxds.c -new file mode 100644 -index 0000000..ee2e098 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smalxds.c -@@ -0,0 +1,46 @@ -+/* This is a test program for smalxds instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smalxds (long long t, unsigned int a, unsigned int b) -+{ -+ return __nds32__smalxds (t, a, b); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smalxds (long long t, int16x2_t a, int16x2_t b) -+{ -+ return __nds32__v_smalxds (t, a, b); -+} -+ -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ long long a_p = 0x12345678ffffaaaall; -+ long long va_p = 0x12345678ffffaaaall; -+#else -+ long long a_p = 0x12345678ffffaaaall; -+ long long va_p = 0x1234567900005554ll; -+#endif -+ -+ long long a = smalxds (0x12345678ffffffffll, 0x12340001, 0x67890001); -+ long long va = v_smalxds (0x12345678ffffffffll, (int16x2_t) {0x0001, 0x1234}, -+ (int16x2_t) {0x0001, 0x6789}); -+ -+ if (a != a_p) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smar64.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smar64.c -new file mode 100644 -index 0000000..59c6f1f ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smar64.c -@@ -0,0 +1,27 @@ -+/* This is a test program for smar64 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smar64 (long long t, int a, int b) -+{ -+ return __nds32__smar64 (t, a, b); -+} -+ -+int -+main () -+{ -+ long long a = smar64 (0xf000000000000000ll, 0x12345678, 0x23); -+ -+ if (a != 0xf00000027d27d268ll) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smax16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smax16.c -new file mode 100644 -index 0000000..72bf957 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smax16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for smax16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int smax16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smax16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_smax16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smax16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = smax16 (0xfffe0001, 0xffff0000); -+ int16x2_t va = v_smax16 ((int16x2_t) {0x7fff, 0}, -+ (int16x2_t) {0x7ffe, 1}); -+ if (a != 0xffff0001) -+ abort (); -+ else if (va[0] != 0x7fff -+ || va[1] != 1) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smax8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smax8.c -new file mode 100644 -index 0000000..128bf19 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smax8.c -@@ -0,0 +1,41 @@ -+/* This is a test program for smax8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int smax8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smax8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int8x4_t v_smax8 (int8x4_t ra, int8x4_t rb) -+{ -+ return __nds32__v_smax8 (ra, rb); -+} -+ -+ -+int -+main () -+{ -+ unsigned int a = smax8 (0xffff0000, 0xfefe0001); -+ int8x4_t va = v_smax8 ((int8x4_t) {0x7f, 0x7f, 0x01, 0x01}, -+ (int8x4_t) {0x7e, 0x7e, 0x00, 0x00}); -+ -+ if (a != 0xffff0001) -+ abort (); -+ else if (va[0] != 0x7f -+ || va[1] != 0x7f -+ || va[2] != 1 -+ || va[3] != 1) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smbb.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smbb.c -new file mode 100644 -index 0000000..25759bd ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smbb.c -@@ -0,0 +1,44 @@ -+/* This is a test program for smbb instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smbb (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smbb (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int v_smbb (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smbb (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int va_p = 1; -+#else -+ int va_p = 2; -+#endif -+ -+ int a = smbb (0x80000002, 0x80000001); -+ -+ int va = v_smbb ((int16x2_t) {0xffff, 0x0002}, -+ (int16x2_t) {0xffff, 0x0001}); -+ -+ if (a != 2) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smbt.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smbt.c -new file mode 100644 -index 0000000..7ed2c22 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smbt.c -@@ -0,0 +1,44 @@ -+/* This is a test program for smbt instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smbt (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smbt (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int v_smbt (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smbt (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int va_p = 0xffffffff; -+#else -+ int va_p = 0xfffffffe; -+#endif -+ -+ int a = smbt (0x80000002, 0x80000001); -+ -+ int va = v_smbt ((int16x2_t) {0xffff, 0x0002}, -+ (int16x2_t) {0xffff, 0x0001}); -+ -+ if (a != 0xffff0000) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smdrs.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smdrs.c -new file mode 100644 -index 0000000..4224b04 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smdrs.c -@@ -0,0 +1,43 @@ -+/* This is a test program for smdrs instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smdrs (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smdrs (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int v_smdrs (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smdrs (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int va_p = 0xffffffff; -+#else -+ int va_p = 1; -+#endif -+ -+ int a = smdrs (0x80000002, 0x80000001); -+ int va = v_smdrs ((int16x2_t) {0xffff, 0x0002}, -+ (int16x2_t) {0xffff, 0x0001}); -+ -+ if (a != 0xc0000002) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smds.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smds.c -new file mode 100644 -index 0000000..9875efb ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smds.c -@@ -0,0 +1,43 @@ -+/* This is a test program for smds instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smds (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smds (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int v_smds (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smds (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int va_p = 1; -+#else -+ int va_p = 0xffffffff; -+#endif -+ -+ int a = smds (0x80000002, 0x80000001); -+ int va = v_smds ((int16x2_t) {0xffff, 0x0002}, -+ (int16x2_t) {0xffff, 0x0001}); -+ -+ if (a != 0x3ffffffe) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smin16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smin16.c -new file mode 100644 -index 0000000..60deb4b ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smin16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for smin16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int smin16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smin16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_smin16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smin16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = smin16 (0xfffe0001, 0xffff0000); -+ int16x2_t v_sa = v_smin16 ((int16x2_t) {0x7fff, 0}, -+ (int16x2_t) {0x7ffe, 1}); -+ if (a != 0xfffe0000) -+ abort (); -+ else if (v_sa[0] != 0x7ffe -+ || v_sa[1] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmul.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmul.c -new file mode 100644 -index 0000000..5735efa ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmul.c -@@ -0,0 +1,27 @@ -+/* This is a test program for smmul instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smmul (int ra, int rb) -+{ -+ return __nds32__smmul (ra, rb); -+} -+ -+int -+main () -+{ -+ int a = smmul (0x80000000, 0x80000000); -+ -+ if (a != 0x40000000) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmulu.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmulu.c -new file mode 100644 -index 0000000..fbe0b15 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmulu.c -@@ -0,0 +1,27 @@ -+/* This is a test program for smmul.u instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smmul_u (int ra, int rb) -+{ -+ return __nds32__smmul_u (ra, rb); -+} -+ -+int -+main () -+{ -+ int a = smmul_u (0x80000002, 0x80000001); -+ -+ if (a != 0x3fffffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwb.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwb.c -new file mode 100644 -index 0000000..9160b9a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwb.c -@@ -0,0 +1,43 @@ -+/* This is a test program for smmwb instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smmwb (int ra, unsigned int rb) -+{ -+ return __nds32__smmwb (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int v_smmwb (int ra, int16x2_t rb) -+{ -+ return __nds32__v_smmwb (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int va_p = 0; -+#else -+ int va_p = 0xffffffff; -+#endif -+ -+ int a = smmwb (0x80000002, 0x80000001); -+ -+ int va = v_smmwb (0xffff0002, (int16x2_t) {0xffff, 0x0001}); -+ -+ if (a != 0xffff8000) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwbu.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwbu.c -new file mode 100644 -index 0000000..46ebed2 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwbu.c -@@ -0,0 +1,43 @@ -+/* This is a test program for smmwb.u instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smmwb_u (int ra, unsigned int rb) -+{ -+ return __nds32__smmwb_u (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int v_smmwb_u (int ra, int16x2_t rb) -+{ -+ return __nds32__v_smmwb_u (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int va_p = 1; -+#else -+ int va_p = 0xffffffff; -+#endif -+ -+ int a = smmwb_u (0x80000002, 0x80000001); -+ -+ int va = v_smmwb_u (0xffff0002, (int16x2_t) {0xffff, 0x0001}); -+ -+ if (a != 0xffff8000) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwt.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwt.c -new file mode 100644 -index 0000000..45d4792 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwt.c -@@ -0,0 +1,43 @@ -+/* This is a test program for smmwt instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smmwt (int ra, unsigned int rb) -+{ -+ return __nds32__smmwt (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int v_smmwt (int ra, int16x2_t rb) -+{ -+ return __nds32__v_smmwt (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int va_p = 0xffffffff; -+#else -+ int va_p = 0; -+#endif -+ -+ int a = smmwt (0x80000002, 0x80000001); -+ -+ int va = v_smmwt (0xffff0002, (int16x2_t) {0xffff, 0x0001}); -+ -+ if (a != 0x3fffffff) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwtu.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwtu.c -new file mode 100644 -index 0000000..3b4b487 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smmwtu.c -@@ -0,0 +1,43 @@ -+/* This is a test program for smmwt.u instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smmwt_u (int ra, unsigned int rb) -+{ -+ return __nds32__smmwt_u (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int v_smmwt_u (int ra, int16x2_t rb) -+{ -+ return __nds32__v_smmwt_u (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int va_p = 0xffffffff; -+#else -+ int va_p = 1; -+#endif -+ -+ int a = smmwt_u (0x80000002, 0x80000001); -+ -+ int va = v_smmwt_u (0xffff0002, (int16x2_t) {0xffff, 0x0001}); -+ -+ if (a != 0x3fffffff) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smslda.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smslda.c -new file mode 100644 -index 0000000..be2ac27 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smslda.c -@@ -0,0 +1,37 @@ -+/* This is a test program for smslda instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smslda (long long rt, unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smslda (rt, ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smslda (long long rt, int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smslda (rt, ra, rb); -+} -+ -+int -+main () -+{ -+ long long a = smslda (0xff0000000000ll, 0xffffffff, 0x2); -+ long long va = v_smslda (0x100000000ll, -+ (int16x2_t) {0xf000, 0}, (int16x2_t) {0, 3}); -+ -+ if (a != 0xff0000000002ll) -+ abort (); -+ else if (va != 0x100000000ll) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smslxda.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smslxda.c -new file mode 100644 -index 0000000..f276a2e ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smslxda.c -@@ -0,0 +1,37 @@ -+/* This is a test program for smslxda instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smslxda (long long rt, unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smslxda (rt, ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+long long v_smslxda (long long rt, int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smslxda (rt, ra, rb); -+} -+ -+int -+main () -+{ -+ long long a = smslxda (0xff0000000000ll, 0xffffffff, 0x2); -+ long long va = v_smslxda (0x100000000ll, -+ (int16x2_t) {0xf000, 0}, (int16x2_t) {0, 3}); -+ -+ if (a != 0xff0000000002ll) -+ abort (); -+ else if (va != 0x100003000ll) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smsr64.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smsr64.c -new file mode 100644 -index 0000000..64a84e9 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smsr64.c -@@ -0,0 +1,27 @@ -+/* This is a test program for smsr64 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long smsr64 (long long t, int a, int b) -+{ -+ return __nds32__smsr64 (t, a, b); -+} -+ -+int -+main () -+{ -+ long long a = smsr64 (0x5000000300000000ll, 0x12345678, 0x23); -+ -+ if (a != 0x5000000082D82D98ll) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smtt.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smtt.c -new file mode 100644 -index 0000000..bfb30f2 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smtt.c -@@ -0,0 +1,44 @@ -+/* This is a test program for smtt instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smtt (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smtt (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int v_smtt (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smtt (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int va_p = 2; -+#else -+ int va_p = 1; -+#endif -+ -+ int a = smtt (0x80000002, 0x80000001); -+ -+ int va = v_smtt ((int16x2_t) {0xffff, 0x0002}, -+ (int16x2_t) {0xffff, 0x0001}); -+ -+ if (a != 0x40000000) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smul16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smul16.c -new file mode 100644 -index 0000000..bb3fad4 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smul16.c -@@ -0,0 +1,38 @@ -+/* This is a test program for smul16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned long long smul16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smul16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int32x2_t v_smul16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smul16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned long long a = smul16 (0xffff0000, 0x0001ffff); -+ int32x2_t va = v_smul16 ((int16x2_t) {0xffff, 0}, -+ (int16x2_t) {0x0001, 0xffff}); -+ -+ if (a != 0xffffffff00000000) -+ abort (); -+ else if (va[0] != 0xffffffff -+ || va[1] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smulx16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smulx16.c -new file mode 100644 -index 0000000..0e65a2a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smulx16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for smulx16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned long long smulx16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smulx16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int32x2_t v_smulx16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smulx16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned long long a = smulx16 (0xffff0000, 0xffff0001); -+ int32x2_t va = v_smulx16 ((int16x2_t) {0xffff, 0xffff}, -+ (int16x2_t) {1, 0}); -+ if (a != 0xffffffff00000000) -+ abort (); -+ else if (va[0] != 0 -+ || va[1] != 0xffffffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-smxds.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smxds.c -new file mode 100644 -index 0000000..e429aa3 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-smxds.c -@@ -0,0 +1,45 @@ -+/* This is a test program for smxds instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int smxds (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__smxds (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int v_smxds (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_smxds (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int a_p = 0x8000; -+ int va_p = 0xffffffff; -+#else -+ int a_p = 0x8000; -+ int va_p = 1; -+#endif -+ -+ int a = smxds (0x80000002, 0x80000001); -+ int va = v_smxds ((int16x2_t) {0xffff, 0x0002}, -+ (int16x2_t) {0xffff, 0x0001}); -+ -+ if (a != a_p) -+ abort (); -+ else if (va != va_p) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sra16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sra16.c -new file mode 100644 -index 0000000..7d85032 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sra16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for sra16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int sra16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__sra16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_sra16 (int16x2_t ra, unsigned int rb) -+{ -+ return __nds32__v_sra16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = sra16 (0x0ffff000, 4); -+ int16x2_t va = v_sra16 ((int16x2_t) {0x7fff, 0x8000}, 4); -+ -+ if (a != 0x00ffff00) -+ abort (); -+ else if (va[0] != 0x7ff -+ || va[1] != (short) 0xf800) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sra16u.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sra16u.c -new file mode 100644 -index 0000000..5bc127c ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sra16u.c -@@ -0,0 +1,37 @@ -+/* This is a test program for sra16.u instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int sra16u (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__sra16_u (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_sra16u (int16x2_t ra, unsigned int rb) -+{ -+ return __nds32__v_sra16_u (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = sra16u (0x0ffff000, 4); -+ int16x2_t va = v_sra16u ((int16x2_t) {0x7fff, 0x8000}, 4); -+ -+ if (a != 0x100ff00) -+ abort (); -+ else if (va[0] != 0x800 -+ || va[1] != (short) 0xf800) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-srai16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srai16.c -new file mode 100644 -index 0000000..f3c6e16 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srai16.c -@@ -0,0 +1,39 @@ -+/* This is a test program for srai16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int srai16 (unsigned int ra) -+{ -+ return __nds32__sra16 (ra, 4); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_srai16 (int16x2_t ra) -+{ -+ return __nds32__v_sra16 (ra, 4); -+} -+ -+int -+main () -+{ -+ unsigned int a = srai16 (0x0ffff000); -+ -+ int16x2_t aa; -+ int16x2_t va = v_srai16 ((int16x2_t) {0x7fff, 0x8000}); -+ -+ if (a != 0x00ffff00) -+ abort (); -+ else if (va[0] != 0x7ff -+ || va[1] != (short) 0xf800) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-srai16u.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srai16u.c -new file mode 100644 -index 0000000..380bd2e ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srai16u.c -@@ -0,0 +1,37 @@ -+/* This is a test program for srai16.u instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int srai16u (unsigned int ra) -+{ -+ return __nds32__sra16_u (ra, 4); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_srai16u (int16x2_t ra) -+{ -+ return __nds32__v_sra16_u (ra, 4); -+} -+ -+int -+main () -+{ -+ unsigned int a = srai16u (0x0ffff000); -+ int16x2_t va = v_srai16u ((int16x2_t) {0x7fff, 0x8000}); -+ -+ if (a != 0x100ff00) -+ abort (); -+ else if (va[0] != 0x800 -+ || va[1] != (short) 0xf800) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sraiu.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sraiu.c -new file mode 100644 -index 0000000..4090762 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sraiu.c -@@ -0,0 +1,27 @@ -+/* This is a test program for srai.u instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int sraiu (int ra) -+{ -+ return __nds32__sra_u (ra, 8); -+} -+ -+int -+main () -+{ -+ int a = sraiu (0xf00ff); -+ -+ if (a != 0xf01) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-srau.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srau.c -new file mode 100644 -index 0000000..e3a3137 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srau.c -@@ -0,0 +1,27 @@ -+/* This is a test program for sra.u instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+int srau (int ra, unsigned int rb) -+{ -+ return __nds32__sra_u (ra, rb); -+} -+ -+int -+main () -+{ -+ int a = srau (0xf00ff, 8); -+ -+ if (a != 0xf01) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-srl16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srl16.c -new file mode 100644 -index 0000000..8aa9c59 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srl16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for srl16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int srl16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__srl16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_srl16 (uint16x2_t ra, unsigned int rb) -+{ -+ return __nds32__v_srl16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = srl16 (0x0f00f000, 4); -+ uint16x2_t va = v_srl16 ((uint16x2_t) {0x7fff, 0x8000}, 4); -+ -+ if (a != 0xf00f00) -+ abort (); -+ else if (va[0] != 0x7ff -+ || va[1] != 0x0800) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-srl16u.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srl16u.c -new file mode 100644 -index 0000000..3f4ac5b ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srl16u.c -@@ -0,0 +1,37 @@ -+/* This is a test program for srl16.u instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int srl16_u (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__srl16_u (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_srl16_u (uint16x2_t ra, unsigned int rb) -+{ -+ return __nds32__v_srl16_u (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = srl16_u (0x0f00f000, 4); -+ uint16x2_t va = v_srl16_u ((uint16x2_t) {0x7fff, 0x8000}, 4); -+ -+ if (a != 0xf00f00) -+ abort (); -+ else if (va[0] != 0x800 -+ || va[1] != 0x800) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-srli16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srli16.c -new file mode 100644 -index 0000000..200bf8c ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srli16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for srli16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int srli16 (unsigned int ra) -+{ -+ return __nds32__srl16 (ra, 4); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_srli16 (uint16x2_t ra) -+{ -+ return __nds32__v_srl16 (ra, 4); -+} -+ -+int -+main () -+{ -+ unsigned int a = srli16 (0x0f00f000); -+ uint16x2_t va = v_srli16 ((uint16x2_t) {0x7fff, 0x8000}); -+ -+ if (a != 0xf00f00) -+ abort (); -+ else if (va[0] != 0x7ff -+ || va[1] != 0x0800) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-srli16u.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srli16u.c -new file mode 100644 -index 0000000..808319b ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-srli16u.c -@@ -0,0 +1,37 @@ -+/* This is a test program for sril16.u instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int srli16_u (unsigned int ra) -+{ -+ return __nds32__srl16_u (ra, 4); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_srli16_u (uint16x2_t ra) -+{ -+ return __nds32__v_srl16_u (ra, 4); -+} -+ -+int -+main () -+{ -+ unsigned int a = srli16_u (0x0f00f000); -+ uint16x2_t va = v_srli16_u ((uint16x2_t) {0x7fff, 0x8000}); -+ -+ if (a != 0xf00f00) -+ abort (); -+ else if (va[0] != 0x800 -+ || va[1] != 0x800) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sub16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sub16.c -new file mode 100644 -index 0000000..eff5f92 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sub16.c -@@ -0,0 +1,49 @@ -+/* This is a test program for sub16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int sub16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__sub16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_usub16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_usub16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_ssub16 (int16x2_t ra, int16x2_t rb) -+{ -+ return __nds32__v_ssub16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = sub16 (0x00010000, 0x00010001); -+ uint16x2_t v_ua = v_usub16 ((uint16x2_t) {0x1000, 0x0001}, -+ (uint16x2_t) {0xf000, 0x0000}); -+ int16x2_t v_sa = v_ssub16 ((int16x2_t) {0x7777, 0x2111}, -+ (int16x2_t) {0x1000, 0x2000}); -+ -+ if (a != 0x0000ffff) -+ abort (); -+ else if (v_ua[0] != 0x2000 -+ || v_ua[1] != 0x0001) -+ abort (); -+ else if (v_sa[0] != 0x6777 -+ || v_sa[1] != 0x0111) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sub64.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sub64.c -new file mode 100644 -index 0000000..efdd879 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sub64.c -@@ -0,0 +1,36 @@ -+/* This is a test program for sub64 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+long long ssub64 (long long ra, long long rb) -+{ -+ return __nds32__ssub64 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+unsigned long long usub64 (unsigned long long ra, unsigned long long rb) -+{ -+ return __nds32__usub64 (ra, rb); -+} -+ -+int -+main () -+{ -+ long long sa = ssub64 (0x100000000ll, 0xffffffffll); -+ unsigned long long ua = usub64 (0xf00000000ull, 0x1111ull); -+ -+ if (sa != 1ll) -+ abort (); -+ else if (ua != 0xeffffeeefull) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sub8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sub8.c -new file mode 100644 -index 0000000..b21f8a5 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sub8.c -@@ -0,0 +1,53 @@ -+/* This is a test program for sub8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int sub8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__sub8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_usub8 (uint8x4_t ra, uint8x4_t rb) -+{ -+ return __nds32__v_usub8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+int8x4_t v_ssub8 (int8x4_t ra, int8x4_t rb) -+{ -+ return __nds32__v_ssub8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = sub8 (0x55667788, 0x11223344); -+ uint8x4_t v_ua = v_usub8 ((uint8x4_t) {0xff, 0xee, 0xee, 0xcc}, -+ (uint8x4_t) {0x1, 0xee, 0xdd, 0xdd}); -+ int8x4_t v_sa = v_ssub8 ((int8x4_t) {0x81, 0x0, 0xdd, 0xaa}, -+ (int8x4_t) {0x80, 0x1, 0xcc, 0xaa}); -+ -+ if (a != 0x44444444) -+ abort (); -+ else if (v_ua[0] != 0xfe -+ || v_ua[1] != 0 -+ || v_ua[2] != 0x11 -+ || v_ua[3] != 0xef) -+ abort (); -+ else if (v_sa[0] != 1 -+ || v_sa[1] != (char) 0xff -+ || v_sa[2] != 0x11 -+ || v_sa[3] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd810.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd810.c -new file mode 100644 -index 0000000..29fff3a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd810.c -@@ -0,0 +1,43 @@ -+/* This is a test program for sunpkd810 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int sunpkd810 (unsigned int a) -+{ -+ return __nds32__sunpkd810 (a); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_sunpkd810 (int8x4_t a) -+{ -+ return __nds32__v_sunpkd810 (a); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int16x2_t va_p = {0xfff8, 0x56}; -+#else -+ int16x2_t va_p = {0, 0}; -+#endif -+ -+ unsigned int a = sunpkd810 (0x000056f8); -+ int16x2_t va = v_sunpkd810 ((int8x4_t) {0xf8, 0x56, 0, 0}); -+ -+ if (a != 0x0056fff8) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd820.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd820.c -new file mode 100644 -index 0000000..43f969a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd820.c -@@ -0,0 +1,43 @@ -+/* This is a test program for sunpkd820 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int sunpkd820 (unsigned int a) -+{ -+ return __nds32__sunpkd820 (a); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_sunpkd820 (int8x4_t a) -+{ -+ return __nds32__v_sunpkd820 (a); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int16x2_t va_p = {0xfff8, 0x34}; -+#else -+ int16x2_t va_p = {0, 0}; -+#endif -+ -+ unsigned int a = sunpkd820 (0x003400f8); -+ int16x2_t va = v_sunpkd820 ((int8x4_t) {0xf8, 0, 0x34, 0}); -+ -+ if (a != 0x0034fff8) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd830.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd830.c -new file mode 100644 -index 0000000..76540b5 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd830.c -@@ -0,0 +1,37 @@ -+/* This is a test program for sunpkd830 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int sunpkd830 (unsigned int a) -+{ -+ return __nds32__sunpkd830 (a); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_sunpkd830 (int8x4_t a) -+{ -+ return __nds32__v_sunpkd830 (a); -+} -+ -+int -+main () -+{ -+ unsigned int a = sunpkd830 (0x120000f8); -+ int16x2_t va = v_sunpkd830 ((int8x4_t) {0xf8, 0x00, 0, 0x12}); -+ -+ if (a != 0x0012fff8) -+ abort (); -+ else if (va[0] != (short) 0xfff8 -+ || va[1] != 0x0012) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd831.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd831.c -new file mode 100644 -index 0000000..05149e6 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-sunpkd831.c -@@ -0,0 +1,43 @@ -+/* This is a test program for sunpkd831 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int sunpkd831 (unsigned int a) -+{ -+ return __nds32__sunpkd831 (a); -+} -+ -+static __attribute__ ((noinline)) -+int16x2_t v_sunpkd831 (int8x4_t a) -+{ -+ return __nds32__v_sunpkd831 (a); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int16x2_t va_p = {0xfff8, 0x12}; -+#else -+ int16x2_t va_p = {0, 0}; -+#endif -+ -+ unsigned int a = sunpkd831 (0x1200f800); -+ int16x2_t va = v_sunpkd831 ((int8x4_t) {0, 0xf8, 0, 0x12}); -+ -+ if (a != 0x0012fff8) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmple16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmple16.c -new file mode 100644 -index 0000000..17b5344 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmple16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for ucmple16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int ucmple16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__ucmple16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_ucmple16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_ucmple16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = ucmple16 (0xfffe0001, 0xffff0000); -+ uint16x2_t va = v_ucmple16 ((uint16x2_t) {0x7fff, 0x7ffe}, -+ (uint16x2_t) {0x7ffe, 0x7fff}); -+ if (a != 0xffff0000) -+ abort (); -+ else if (va[0] != 0 -+ || va[1] != 0xffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmple8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmple8.c -new file mode 100644 -index 0000000..561b500 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmple8.c -@@ -0,0 +1,40 @@ -+/* This is a test program for ucmple8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int ucmple8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__ucmple8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_ucmple8 (uint8x4_t ra, uint8x4_t rb) -+{ -+ return __nds32__v_ucmple8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = ucmple8 (0xfefe0101, 0xffff0000); -+ uint8x4_t va = v_ucmple8 ((uint8x4_t) {0x7e, 0x7e, 0x01, 0x01}, -+ (uint8x4_t) {0x7f, 0x7f, 0x00, 0x00}); -+ -+ if (a != 0xffff0000) -+ abort (); -+ else if (va[0] != 0xff -+ || va[1] != 0xff -+ || va[2] != 0 -+ || va[3] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmplt16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmplt16.c -new file mode 100644 -index 0000000..820ce1e ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmplt16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for ucmplt16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int ucmplt16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__ucmplt16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_ucmplt16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_ucmplt16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = ucmplt16 (0xfffe0001, 0xffff0000); -+ uint16x2_t va = v_ucmplt16 ((uint16x2_t) {0x7fff, 0x7ffe}, -+ (uint16x2_t) {0x7ffe, 0x7fff}); -+ if (a != 0xffff0000) -+ abort (); -+ else if (va[0] != 0 -+ || va[1] != 0xffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmplt8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmplt8.c -new file mode 100644 -index 0000000..8001586 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ucmplt8.c -@@ -0,0 +1,40 @@ -+/* This is a test program for ucmplt8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int ucmplt8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__ucmplt8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_ucmplt8 (uint8x4_t ra, uint8x4_t rb) -+{ -+ return __nds32__v_ucmplt8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = ucmplt8 (0xfefe0101, 0xffff0000); -+ uint8x4_t va = v_ucmplt8 ((uint8x4_t) {0x7e, 0x7e, 0x01, 0x01}, -+ (uint8x4_t) {0x7f, 0x7f, 0x00, 0x00}); -+ -+ if (a != 0xffff0000) -+ abort (); -+ else if (va[0] != 0xff -+ || va[1] != 0xff -+ || va[2] != 0 -+ || va[3] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-umar64.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umar64.c -new file mode 100644 -index 0000000..ac32ae1 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umar64.c -@@ -0,0 +1,27 @@ -+/* This is a test program for umar64 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned long long umar64 (unsigned long long t,unsigned int a,unsigned int b) -+{ -+ return __nds32__umar64 (t, a, b); -+} -+ -+int -+main () -+{ -+ unsigned long long a = umar64 (0xf000000000000000ull, 0x12345678, 0x23); -+ -+ if (a != 0xf00000027d27d268ull) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-umax16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umax16.c -new file mode 100644 -index 0000000..99a43d2 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umax16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for umax16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int umax16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__umax16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_umax16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_umax16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = umax16 (0xfffe0001, 0xffff0000); -+ uint16x2_t va = v_umax16 ((uint16x2_t) {0xffff, 0}, -+ (uint16x2_t) {0xfffe, 1}); -+ if (a != 0xffff0001) -+ abort (); -+ else if (va[0] != 0xffff -+ || va[1] != 1) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-umax8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umax8.c -new file mode 100644 -index 0000000..23904b2 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umax8.c -@@ -0,0 +1,41 @@ -+/* This is a test program for umax8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int umax8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__umax8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_umax8 (uint8x4_t ra, uint8x4_t rb) -+{ -+ return __nds32__v_umax8 (ra, rb); -+} -+ -+ -+int -+main () -+{ -+ unsigned int a = umax8 (0xffff0000, 0xfffe0001); -+ uint8x4_t va = v_umax8 ((uint8x4_t) {0xff, 0xff, 0x01, 0x01}, -+ (uint8x4_t) {0xfe, 0xfe, 0x00, 0x00}); -+ -+ if (a != 0xffff0001) -+ abort (); -+ else if (va[0] != 0xff -+ || va[1] != 0xff -+ || va[2] != 1 -+ || va[3] != 1) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-umin16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umin16.c -new file mode 100644 -index 0000000..eec7058 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umin16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for umin16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int umin16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__umin16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_umin16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_umin16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = umin16 (0xfffe0001, 0xffff0000); -+ uint16x2_t va = v_umin16 ((uint16x2_t) {0x7fff, 0}, -+ (uint16x2_t) {0x7ffe, 1}); -+ if (a != 0xfffe0000) -+ abort (); -+ else if (va[0] != 0x7ffe -+ || va[1] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-umsr64.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umsr64.c -new file mode 100644 -index 0000000..3fb20bf ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umsr64.c -@@ -0,0 +1,27 @@ -+/* This is a test program for umsr64 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned long long umsr64 (unsigned long long t, unsigned int a, unsigned int b) -+{ -+ return __nds32__umsr64 (t, a, b); -+} -+ -+int -+main () -+{ -+ unsigned long long a = umsr64 (0x5000000300000000ull, 0x12345678, 0x23); -+ -+ if (a != 0x5000000082D82D98ull) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-umul16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umul16.c -new file mode 100644 -index 0000000..ddfb6be ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umul16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for umul16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned long long umul16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__umul16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint32x2_t v_umul16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_umul16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned long long a = umul16 (0xffff0000, 0x0001ffff); -+ uint32x2_t va = v_umul16 ((uint16x2_t) {0xffff, 0}, -+ (uint16x2_t) {0x0001, 0xffff}); -+ if (a != 0xffff00000000) -+ abort (); -+ else if (va[0] != 0xffff -+ || va[1] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-umulx16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umulx16.c -new file mode 100644 -index 0000000..c57d304 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-umulx16.c -@@ -0,0 +1,37 @@ -+/* This is a test program for umulx16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned long long umulx16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__umulx16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint32x2_t v_umulx16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_umulx16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned long long a = umulx16 (0xffff0000, 0xffff0001); -+ uint32x2_t va = v_umulx16 ((uint16x2_t) {0xffff, 0xffff}, -+ (uint16x2_t) {1, 0}); -+ if (a != 0xffff00000000) -+ abort (); -+ else if (va[0] != 0 -+ || va[1] != 0xffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-uradd16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-uradd16.c -new file mode 100644 -index 0000000..82c7be7 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-uradd16.c -@@ -0,0 +1,38 @@ -+/* This is a test program for uradd16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int uradd16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__uradd16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_uradd16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_uradd16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = uradd16 (0x7fff7fff, 0x7fff7fff); -+ uint16x2_t va = v_uradd16 ((uint16x2_t) {0x8000, 0x4000}, -+ (uint16x2_t) {0x8000, 0x8000}); -+ -+ if (a != 0x7fff7fff) -+ abort (); -+ else if (va[0] != 0x8000 -+ || va[1] != 0x6000) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-uradd64.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-uradd64.c -new file mode 100644 -index 0000000..51ee961 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-uradd64.c -@@ -0,0 +1,27 @@ -+/* This is a test program for uradd64 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned long long uradd64 (unsigned long long ra, unsigned long long rb) -+{ -+ return __nds32__uradd64 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned long long a = uradd64 (0xf000000000000000ull, 0xf000000000000000ull); -+ -+ if (a != 0xf000000000000000ull) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-uradd8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-uradd8.c -new file mode 100644 -index 0000000..d4f91d6 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-uradd8.c -@@ -0,0 +1,40 @@ -+/* This is a test program for uradd8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int uradd8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__uradd8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_uradd8 (uint8x4_t ra, uint8x4_t rb) -+{ -+ return __nds32__v_uradd8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = uradd8 (0x11223344, 0x55667788); -+ uint8x4_t va = v_uradd8 ((uint8x4_t) {0x7f, 0x80, 0x40, 0xaa}, -+ (uint8x4_t) {0x7f, 0x80, 0x80, 0xaa}); -+ -+ if (a != 0x33445566) -+ abort (); -+ else if (va[0] != 0x7f -+ || va[1] != 0x80 -+ || va[2] != 0x60 -+ || va[3] != 0xaa) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-uraddw.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-uraddw.c -new file mode 100644 -index 0000000..9fc76b0 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-uraddw.c -@@ -0,0 +1,27 @@ -+/* This is a test program for uraddw instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int uraddw (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__uraddw (ra, rb); -+} -+ -+unsigned int -+main () -+{ -+ unsigned int a = uraddw (0x80000000, 0x80000000); -+ -+ if (a != 0x80000000) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-urcras16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-urcras16.c -new file mode 100644 -index 0000000..1330374 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-urcras16.c -@@ -0,0 +1,44 @@ -+/* This is a test program for urcras16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int urcras16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__urcras16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_urcras16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_urcras16 (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ uint16x2_t va_p = {0xffff, 0x8000}; -+#else -+ uint16x2_t va_p = {0x7fff, 0}; -+#endif -+ -+ unsigned int a = urcras16 (0x7fff7fff, 0x80007fff); -+ uint16x2_t va = v_urcras16 ((uint16x2_t) {0x7fff, 0x8000}, -+ (uint16x2_t) {0x8000, 0x8000}); -+ -+ if (a != 0x7fffffff) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-urcrsa16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-urcrsa16.c -new file mode 100644 -index 0000000..806fa7a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-urcrsa16.c -@@ -0,0 +1,44 @@ -+/* This is a test program for urcrsa16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int urcrsa16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__urcrsa16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_urcrsa16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_urcrsa16 (ra, rb); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ uint16x2_t va_p = {0x8000, 0xffff}; -+#else -+ uint16x2_t va_p = {0, 0x7fff}; -+#endif -+ -+ unsigned int a = urcrsa16 (0x7fff7fff, 0x7fff8000); -+ uint16x2_t va = v_urcrsa16 ((uint16x2_t) {0x8000, 0x7fff}, -+ (uint16x2_t) {0x8000, 0x8000}); -+ -+ if (a != 0xffff7fff) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursub16.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursub16.c -new file mode 100644 -index 0000000..9e87234 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursub16.c -@@ -0,0 +1,38 @@ -+/* This is a test program for ursub16 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int ursub16 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__ursub16 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_ursub16 (uint16x2_t ra, uint16x2_t rb) -+{ -+ return __nds32__v_ursub16 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = ursub16 (0x7fff7fff, 0x80008000); -+ uint16x2_t va = v_ursub16 ((uint16x2_t) {0x8000, 0x8000}, -+ (uint16x2_t) {0x7fff, 0x4000}); -+ -+ if (a != 0xffffffff) -+ abort (); -+ else if (va[0] != 0 -+ || va[1] != 0x2000) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursub64.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursub64.c -new file mode 100644 -index 0000000..e1f7b15 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursub64.c -@@ -0,0 +1,27 @@ -+/* This is a test program for ursub64 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned long long ursub64 (unsigned long long ra, unsigned long long rb) -+{ -+ return __nds32__ursub64 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned long long a = ursub64 (0xeull, 0xfull); -+ -+ if (a != 0xffffffffffffffffull) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursub8.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursub8.c -new file mode 100644 -index 0000000..f5e3ff6 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursub8.c -@@ -0,0 +1,40 @@ -+/* This is a test program for ursub8 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int ursub8 (unsigned int ra, unsigned int rb) -+{ -+ return __nds32__ursub8 (ra, rb); -+} -+ -+static __attribute__ ((noinline)) -+uint8x4_t v_ursub8 (uint8x4_t ra, uint8x4_t rb) -+{ -+ return __nds32__v_ursub8 (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = ursub8 (0x55667788, 0x11223344); -+ uint8x4_t va = v_ursub8 ((uint8x4_t) {0x7f, 0x80, 0x80, 0xaa}, -+ (uint8x4_t) {0x80, 0x7f, 0x40, 0xaa}); -+ -+ if (a != 0x22222222) -+ abort (); -+ else if (va[0] != 0xff -+ || va[1] != 0 -+ || va[2] != 0x20 -+ || va[3] != 0) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursubw.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursubw.c -new file mode 100644 -index 0000000..b12afb0 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-ursubw.c -@@ -0,0 +1,27 @@ -+/* This is a test program for ursubw instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int ursubw (unsigned int ra,unsigned int rb) -+{ -+ return __nds32__ursubw (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = ursubw (0x80000000, 0x40000000); -+ -+ if (a != 0x20000000) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-wext.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-wext.c -new file mode 100644 -index 0000000..d86fb8f ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-wext.c -@@ -0,0 +1,27 @@ -+/* This is a test program for wext instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int wext (long long ra, unsigned int rb) -+{ -+ return __nds32__wext (ra, rb); -+} -+ -+int -+main () -+{ -+ unsigned int a = wext (0x1234ffff0000ll, 16); -+ -+ if (a != 0x1234ffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-wexti.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-wexti.c -new file mode 100644 -index 0000000..8f09423 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-wexti.c -@@ -0,0 +1,27 @@ -+/* This is a test program for wexti instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int wexti (long long ra) -+{ -+ return __nds32__wext (ra, 16); -+} -+ -+int -+main () -+{ -+ unsigned int a = wexti (0x1234ffff0000ll); -+ -+ if (a != 0x1234ffff) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd810.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd810.c -new file mode 100644 -index 0000000..7b3aebb ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd810.c -@@ -0,0 +1,43 @@ -+/* This is a test program for zunpkd810 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int zunpkd810 (unsigned int a) -+{ -+ return __nds32__zunpkd810 (a); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_zunpkd810 (uint8x4_t a) -+{ -+ return __nds32__v_zunpkd810 (a); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int16x2_t va_p = {0xf8, 0x56}; -+#else -+ int16x2_t va_p = {0, 0}; -+#endif -+ -+ unsigned int a = zunpkd810 (0x000056f8); -+ uint16x2_t va = v_zunpkd810 ((uint8x4_t) {0xf8, 0x56, 0, 0}); -+ -+ if (a != 0x005600f8) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd820.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd820.c -new file mode 100644 -index 0000000..dc37a3d ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd820.c -@@ -0,0 +1,43 @@ -+/* This is a test program for zunpkd820 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int zunpkd820 (unsigned int a) -+{ -+ return __nds32__zunpkd820 (a); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_zunpkd820 (uint8x4_t a) -+{ -+ return __nds32__v_zunpkd820 (a); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int16x2_t va_p = {0xf8, 0x34}; -+#else -+ int16x2_t va_p = {0, 0}; -+#endif -+ -+ unsigned int a = zunpkd820 (0x003400f8); -+ uint16x2_t va = v_zunpkd820 ((uint8x4_t) {0xf8, 0, 0x34, 0}); -+ -+ if (a != 0x003400f8) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd830.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd830.c -new file mode 100644 -index 0000000..8f5a224 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd830.c -@@ -0,0 +1,37 @@ -+/* This is a test program for zunpkd830 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int zunpkd830 (unsigned int a) -+{ -+ return __nds32__zunpkd830 (a); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_zunpkd830 (uint8x4_t a) -+{ -+ return __nds32__v_zunpkd830 (a); -+} -+ -+int -+main () -+{ -+ unsigned int a = zunpkd830 (0x120000f8); -+ uint16x2_t va = v_zunpkd830 ((uint8x4_t) { 0xf8, 0x00, 0, 0x12}); -+ -+ if (a != 0x001200f8) -+ abort (); -+ else if (va[0] != 0x00f8 -+ || va[1] != 0x0012) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd831.c b/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd831.c -new file mode 100644 -index 0000000..6878cd3 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-dsp-zunpkd831.c -@@ -0,0 +1,43 @@ -+/* This is a test program for zunpkd831 instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+static __attribute__ ((noinline)) -+unsigned int zunpkd831 (unsigned int a) -+{ -+ return __nds32__zunpkd831 (a); -+} -+ -+static __attribute__ ((noinline)) -+uint16x2_t v_zunpkd831 (uint8x4_t a) -+{ -+ return __nds32__v_zunpkd831 (a); -+} -+ -+int -+main () -+{ -+#ifdef __NDS32_EL__ -+ int16x2_t va_p = {0xf8, 0x12}; -+#else -+ int16x2_t va_p = {0, 0}; -+#endif -+ -+ unsigned int a = zunpkd831 (0x1200f800); -+ uint16x2_t va = v_zunpkd831 ((uint8x4_t) {0, 0xf8, 0, 0x12}); -+ -+ if (a != 0x001200f8) -+ abort (); -+ else if (va[0] != va_p[0] -+ || va[1] != va_p[1]) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpyd.c b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpyd.c -new file mode 100644 -index 0000000..4ee7e5e ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpyd.c -@@ -0,0 +1,21 @@ -+/* This is a test program for fcpysd instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_fpu_dp } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ double da = -1.5; -+ double db = 1.3; -+ double dr = __nds32__fcpysd (da, db); -+ -+ if (dr != 1.5) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpynd.c b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpynd.c -new file mode 100644 -index 0000000..804410b ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpynd.c -@@ -0,0 +1,21 @@ -+/* This is a test program for fcpynsd instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_fpu_dp } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ double da = -1.5; -+ double db = -1.3; -+ double dr = __nds32__fcpynsd (da, db); -+ -+ if (dr != 1.5) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpyns.c b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpyns.c -new file mode 100644 -index 0000000..0d86734 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpyns.c -@@ -0,0 +1,21 @@ -+/* This is a test program for fcpynss instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_fpu_sp } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ float a = -1.5; -+ float b = -1.3; -+ float r = __nds32__fcpynss (a, b); -+ -+ if (r != 1.5) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpys.c b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpys.c -new file mode 100644 -index 0000000..4bccf57 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fcpys.c -@@ -0,0 +1,21 @@ -+/* This is a test program for fcpyss instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_fpu_sp } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ float a = -1.5; -+ float b = 1.3; -+ float r = __nds32__fcpyss (a, b); -+ -+ if (r != 1.5) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-fpu-fmfcfg.c b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fmfcfg.c -new file mode 100644 -index 0000000..83e65ed ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fmfcfg.c -@@ -0,0 +1,23 @@ -+/* This is a test program for fmfcfg instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_fpu } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int intrinsic_fmfcfg = -1; -+ unsigned int inline_assemble_fmfcfg = -2; -+ -+ intrinsic_fmfcfg = __nds32__fmfcfg (); -+ __asm volatile ("fmfcfg %0" : "=r" (inline_assemble_fmfcfg)); -+ -+ if (intrinsic_fmfcfg == inline_assemble_fmfcfg) -+ exit (0); -+ else -+ abort (); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-fpu-fpcsr.c b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fpcsr.c -new file mode 100644 -index 0000000..787b430 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-fpu-fpcsr.c -@@ -0,0 +1,35 @@ -+/* This is a test program for fmtcsr/fmfcsr instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_fpu } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int fpcsr; -+ unsigned int real_fpcsr; -+ -+ /* Keep real fpcsr value. */ -+ real_fpcsr = __nds32__fmfcsr (); -+ -+ /* write fpcsr */ -+ fpcsr = 3; -+ __nds32__fmtcsr (fpcsr); -+ -+ /* read fpcsr */ -+ fpcsr = 0; -+ fpcsr = __nds32__fmfcsr (); -+ fpcsr = fpcsr & 0x00001fff; -+ -+ /* Recover fpcsr value. */ -+ __nds32__fmtcsr (real_fpcsr); -+ -+ if (fpcsr == 3) -+ exit (0); -+ else -+ abort (); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-get-lp.c b/gcc/testsuite/gcc.target/nds32/builtin-get-lp.c -new file mode 100644 -index 0000000..80b4921 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-get-lp.c -@@ -0,0 +1,22 @@ -+/* Verify the return address with builtin function. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+ -+#include -+#include -+ -+int main() -+{ -+ unsigned int intrinsic_lp = -1; -+ unsigned int inline_assemble_lp = -2; -+ -+ intrinsic_lp = __nds32__return_address (); -+ -+ __asm volatile ("mov55 %0, $lp" : "=r" (inline_assemble_lp)); -+ -+ if (intrinsic_lp != inline_assemble_lp) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-isb.c b/gcc/testsuite/gcc.target/nds32/builtin-isb.c -deleted file mode 100644 -index e65061b..0000000 ---- a/gcc/testsuite/gcc.target/nds32/builtin-isb.c -+++ /dev/null -@@ -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 --git a/gcc/testsuite/gcc.target/nds32/builtin-isync.c b/gcc/testsuite/gcc.target/nds32/builtin-isync.c -deleted file mode 100644 -index 3160e4a..0000000 ---- a/gcc/testsuite/gcc.target/nds32/builtin-isync.c -+++ /dev/null -@@ -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 --git a/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c b/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c -deleted file mode 100644 -index db4c558..0000000 ---- a/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c -+++ /dev/null -@@ -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 --git a/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c b/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c -deleted file mode 100644 -index 3cfaab9..0000000 ---- a/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c -+++ /dev/null -@@ -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 --git a/gcc/testsuite/gcc.target/nds32/builtin-rotr.c b/gcc/testsuite/gcc.target/nds32/builtin-rotr.c -new file mode 100644 -index 0000000..a295cb2 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-rotr.c -@@ -0,0 +1,19 @@ -+/* This is a test program for rotr instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O0" } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int a = 1; -+ a = __nds32__rotr (a, 30); -+ -+ if (a != 4) -+ abort (); -+ else -+ exit (0); -+} -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 2dceed9..0000000 ---- 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 8928870..0000000 ---- 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 0000000..b353909 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-setgie_mtsr_mfsr.c -@@ -0,0 +1,43 @@ -+/* 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; -+ unsigned int real_psw; -+ -+ /* Keep PSW value. */ -+ real_psw = __nds32__mfsr (NDS32_SR_PSW); -+ -+ __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; -+ -+ /* Recover PSW value. */ -+ __nds32__mtsr (real_psw, NDS32_SR_PSW); -+ -+ if (gie != 0) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-sp.c b/gcc/testsuite/gcc.target/nds32/builtin-sp.c -new file mode 100644 -index 0000000..2e5499d ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-sp.c -@@ -0,0 +1,33 @@ -+/* This is a test program for sp intrinsic usage. -+ Because we want to use frame pointer to access local variable, -+ we need to use -fno-omit-frame-pointer to make sure the existence -+ of frame pointer. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O0 -fno-omit-frame-pointer" } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int old_sp, new_sp; -+ -+ old_sp = __nds32__get_current_sp (); -+ new_sp = old_sp - 4; -+ __nds32__set_current_sp (new_sp); -+ new_sp = __nds32__get_current_sp (); -+ -+ if (new_sp != (old_sp - 4)) -+ abort (); -+ -+ new_sp = new_sp + 4; -+ __nds32__set_current_sp (new_sp); -+ new_sp = __nds32__get_current_sp (); -+ -+ if (new_sp != old_sp) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-string-ffb.c b/gcc/testsuite/gcc.target/nds32/builtin-string-ffb.c -new file mode 100644 -index 0000000..cf02434 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-string-ffb.c -@@ -0,0 +1,28 @@ -+/* This is a test program for ffb instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_string } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int a = 0x1b2a3d4c; -+ unsigned int b = 0x0000003d; -+ int r; -+ -+ r = __nds32__ffb (a, b); -+ -+#ifdef __NDS32_EL__ -+ if (r != -3) -+ abort (); -+#else -+ if (r != -2) -+ abort (); -+#endif -+ -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-string-ffmism.c b/gcc/testsuite/gcc.target/nds32/builtin-string-ffmism.c -new file mode 100644 -index 0000000..b2fb008 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-string-ffmism.c -@@ -0,0 +1,28 @@ -+/* This is a test program for ffmism instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_string } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int a = 0x1b2a3d4c; -+ unsigned int b = 0x112a334c; -+ int r; -+ -+ r = __nds32__ffmism (a, b); -+ -+#ifdef __NDS32_EL__ -+ if (r != -3) -+ abort (); -+#else -+ if (r != -4) -+ abort (); -+#endif -+ -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-string-flmism.c b/gcc/testsuite/gcc.target/nds32/builtin-string-flmism.c -new file mode 100644 -index 0000000..105fce5 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-string-flmism.c -@@ -0,0 +1,28 @@ -+/* This is a test program for flmism instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O1" } */ -+/* { dg-require-effective-target nds32_ext_string } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int a = 0x1b2a3d4c; -+ unsigned int b = 0x112a334c; -+ int r; -+ -+ r = __nds32__flmism (a, b); -+ -+#ifdef __NDS32_EL__ -+ if (r != -1) -+ abort (); -+#else -+ if (r != -2) -+ abort (); -+#endif -+ -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-unaligned-s16x2.c b/gcc/testsuite/gcc.target/nds32/builtin-unaligned-s16x2.c -new file mode 100644 -index 0000000..5a2e8b7 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-unaligned-s16x2.c -@@ -0,0 +1,36 @@ -+/* This is a test program for smbb instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+int -+main (void) -+{ -+ char data[] = {0x55,0x66,0x77,0x88}; -+ short* short_data = (short*)& data[1]; -+ int16x2_t test_short = {0x1111, 0xaaaa}; -+ int16x2_t vecdata = __nds32__get_unaligned_s16x2 (short_data); -+ -+#ifdef __NDS32_EL__ -+ if (vecdata[0] != 0x7766) -+ abort (); -+#else -+ if (vecdata[0] != 0x6677) -+ abort (); -+#endif -+ -+ __nds32__put_unaligned_s16x2 (short_data, test_short); -+ vecdata = __nds32__get_unaligned_s16x2 (short_data); -+ -+ if (vecdata[0] != 0x1111 -+ & vecdata[1] != 0xaaaa) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-unaligned-s8x4.c b/gcc/testsuite/gcc.target/nds32/builtin-unaligned-s8x4.c -new file mode 100644 -index 0000000..f6cb4c9 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-unaligned-s8x4.c -@@ -0,0 +1,36 @@ -+/* This is a test program for smbb instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+int -+main (void) -+{ -+ char data[] = {0x55,0x66,0x77,0x88}; -+ char* char_data = (char*)& data[1]; -+ int8x4_t test_char = {0x11, 0x22, 0xaa, 0xbb}; -+ int8x4_t vecdata = __nds32__get_unaligned_s8x4 (char_data); -+ -+#ifdef __NDS32_EL__ -+ if (vecdata[0] != 0x66) -+ abort (); -+#else -+ if (vecdata[0] != 0x66) -+ abort (); -+#endif -+ -+ __nds32__put_unaligned_s8x4 (char_data, test_char); -+ vecdata = __nds32__get_unaligned_s8x4 (char_data); -+ -+ if (vecdata[0] != 0x11 -+ & vecdata[3] != 0xaa) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-unaligned-u16x2.c b/gcc/testsuite/gcc.target/nds32/builtin-unaligned-u16x2.c -new file mode 100644 -index 0000000..63ebd40 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-unaligned-u16x2.c -@@ -0,0 +1,36 @@ -+/* This is a test program for smbb instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+int -+main (void) -+{ -+ unsigned char data[] = {0x55,0x66,0x77,0x88}; -+ unsigned short* short_data = (unsigned short*)& data[1]; -+ uint16x2_t test_short = {0x1111, 0xaaaa}; -+ uint16x2_t vecdata = __nds32__get_unaligned_u16x2 (short_data); -+ -+#ifdef __NDS32_EL__ -+ if (vecdata[0] != 0x7766) -+ abort (); -+#else -+ if (vecdata[0] != 0x6677) -+ abort (); -+#endif -+ -+ __nds32__put_unaligned_u16x2 (short_data, test_short); -+ vecdata = __nds32__get_unaligned_u16x2 (short_data); -+ -+ if (vecdata[0] != 0x1111 -+ & vecdata[1] != 0xaaaa) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-unaligned-u8x4.c b/gcc/testsuite/gcc.target/nds32/builtin-unaligned-u8x4.c -new file mode 100644 -index 0000000..7b48274 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-unaligned-u8x4.c -@@ -0,0 +1,36 @@ -+/* This is a test program for smbb instruction. */ -+ -+/* { dg-do run } */ -+ -+#include -+#include -+ -+#ifdef __NDS32_EXT_DSP__ -+int -+main (void) -+{ -+ char data[] = {0x55,0x66,0x77,0x88}; -+ unsigned char* char_data = (char*)& data[1]; -+ uint8x4_t test_char = {0x11, 0x22, 0xaa, 0xbb}; -+ uint8x4_t vecdata = __nds32__get_unaligned_u8x4 (char_data); -+ -+#ifdef __NDS32_EL__ -+ if (vecdata[0] != 0x66) -+ abort (); -+#else -+ if (vecdata[0] != 0x66) -+ abort (); -+#endif -+ -+ __nds32__put_unaligned_u8x4 (char_data, test_char); -+ vecdata = __nds32__get_unaligned_u8x4 (char_data); -+ -+ if (vecdata[0] != 0x11 -+ & vecdata[3] != 0xaa) -+ abort (); -+ else -+ exit (0); -+} -+#else -+int main(){return 0;} -+#endif -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-unaligned_dw.c b/gcc/testsuite/gcc.target/nds32/builtin-unaligned_dw.c -new file mode 100644 -index 0000000..42640b4 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-unaligned_dw.c -@@ -0,0 +1,31 @@ -+/* This is a test program for unaligned double word access. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O0 -std=c99" } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned char data[] = {0x55, 0x66, 0x77, 0x88, 0xAA, -+ 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; -+ unsigned long long* long_long_data = (unsigned long long*) & data[1]; -+ unsigned long long test_long_long = 0x1122334455667788LL; -+ -+#ifdef __NDS32_EL__ -+ if (__nds32__get_unaligned_dw (long_long_data) != 0xEEDDCCBBAA887766LL) -+ abort (); -+#else -+ if (__nds32__get_unaligned_dw (long_long_data) != 0x667788AABBCCDDEELL) -+ abort (); -+#endif -+ -+ __nds32__put_unaligned_dw (long_long_data, test_long_long); -+ -+ if (__nds32__get_unaligned_dw (long_long_data) != 0x1122334455667788LL) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-unaligned_hw.c b/gcc/testsuite/gcc.target/nds32/builtin-unaligned_hw.c -new file mode 100644 -index 0000000..f9e1ceb ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-unaligned_hw.c -@@ -0,0 +1,30 @@ -+/* This is a test program for unaligned half word access. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O0" } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned char data[] = {0x55,0x66,0x77,0x88}; -+ unsigned short* short_data = (unsigned short*)& data[1]; -+ unsigned short test_short = 0x5566; -+ -+#ifdef __NDS32_EL__ -+ if (__nds32__get_unaligned_hw (short_data) != 0x7766) -+ abort (); -+#else -+ if (__nds32__get_unaligned_hw (short_data) != 0x6677) -+ abort (); -+#endif -+ -+ __nds32__put_unaligned_hw (short_data, test_short); -+ -+ if (__nds32__get_unaligned_hw (short_data) != 0x5566) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-unaligned_w.c b/gcc/testsuite/gcc.target/nds32/builtin-unaligned_w.c -new file mode 100644 -index 0000000..40d8711 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-unaligned_w.c -@@ -0,0 +1,30 @@ -+/* This is a test program for unaligned word access. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O0 -std=c99" } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned char data[] = {0x55,0x66,0x77,0x88,0xAA,0xBB,0xCC,0xDD}; -+ unsigned int* int_data = (unsigned int*)& data[1]; -+ unsigned int test_int = 0x55667788; -+ -+#ifdef __NDS32_EL__ -+ if (__nds32__get_unaligned_w (int_data) != 0xAA887766) -+ abort (); -+#else -+ if (__nds32__get_unaligned_w (int_data) != 0x667788AA) -+ abort (); -+#endif -+ -+ __nds32__put_unaligned_w (int_data, test_int); -+ -+ if (__nds32__get_unaligned_w (int_data) != 0x55667788) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/builtin-wsbh.c b/gcc/testsuite/gcc.target/nds32/builtin-wsbh.c -new file mode 100644 -index 0000000..1cee2ed ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/builtin-wsbh.c -@@ -0,0 +1,21 @@ -+/* This is a test program for wsbh instruction. */ -+ -+/* { dg-do run } */ -+/* { dg-options "-O0" } */ -+ -+#include -+#include -+ -+int -+main () -+{ -+ unsigned int a = 0x03020100; -+ unsigned int b; -+ -+ b = __nds32__wsbh (a); -+ -+ if (b != 0x02030001) -+ abort (); -+ else -+ exit (0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-all-pending.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-all-pending.c -new file mode 100644 -index 0000000..0e57831 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-all-pending.c -@@ -0,0 +1,11 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+int -+main (void) -+{ -+ int a = __nds32__get_all_pending_int (); -+ return a; -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-cctl.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-cctl.c -new file mode 100644 -index 0000000..2af55f5 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-cctl.c -@@ -0,0 +1,29 @@ -+/* Verify that we generate cache control instruction with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "L1D_VA_INVAL" } } */ -+/* { dg-final { scan-assembler "L1D_VA_INVAL" } } */ -+/* { dg-final { scan-assembler "L1D_INVALALL" } } */ -+/* { dg-final { scan-assembler "L1D_IX_WWD" } } */ -+/* { dg-final { scan-assembler "L1D_IX_RWD" } } */ -+/* { dg-final { scan-assembler "PFM_CTL" } } */ -+/* { dg-final { scan-assembler "PFM_CTL" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned int va = 0; -+ -+ __nds32__cctlva_lck (NDS32_CCTL_L1D_VA_FILLCK, &va); -+ __nds32__cctlidx_wbinval (NDS32_CCTL_L1D_IX_WBINVAL, va); -+ __nds32__cctlva_wbinval_alvl (NDS32_CCTL_L1D_VA_INVAL, &va); -+ __nds32__cctlva_wbinval_one_lvl (NDS32_CCTL_L1D_VA_INVAL, &va); -+ __nds32__cctl_l1d_invalall (); -+ __nds32__cctlidx_write (NDS32_CCTL_L1D_IX_WWD, va, 1); -+ __nds32__cctlidx_read (NDS32_CCTL_L1D_IX_RWD, 1); -+ __nds32__mtusr (0, NDS32_USR_PFM_CTL); -+ __nds32__mfusr (NDS32_USR_PFM_CTL); -+} -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 0000000..fce90e9 ---- /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 0000000..08e1dd0 ---- /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 0000000..a3a1f44 ---- /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-dpref.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-dpref.c -new file mode 100644 -index 0000000..38cf822 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-dpref.c -@@ -0,0 +1,24 @@ -+/* Verify that we generate data prefetch instruction with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "dpref\\tSRD" } } */ -+/* { dg-final { scan-assembler "dpref\\tSRD" } } */ -+/* { dg-final { scan-assembler "dpref\\tSRD" } } */ -+/* { dg-final { scan-assembler "dpref\\tSRD" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned char dpref_q = 0; -+ unsigned short dpref_h = 0; -+ unsigned int dpref_w = 0; -+ unsigned long long dpref_dw = 0; -+ -+ __nds32__dpref_qw (&dpref_q, 0, NDS32_DPREF_SRD); -+ __nds32__dpref_hw (&dpref_h, 0, NDS32_DPREF_SRD); -+ __nds32__dpref_w (&dpref_w, 0, NDS32_DPREF_SRD); -+ __nds32__dpref_dw (&dpref_dw, 0, NDS32_DPREF_SRD); -+} -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 0000000..e18ed7a ---- /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 0000000..4ced0a5 ---- /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 0000000..a394a60 ---- /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/compile/builtin-isb.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-isb.c -new file mode 100644 -index 0000000..c699966 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-isb.c -@@ -0,0 +1,13 @@ -+/* Verify that we generate isb instruction with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "\\tisb" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ __nds32__isb (); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-isync.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-isync.c -new file mode 100644 -index 0000000..0c312e4 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-isync.c -@@ -0,0 +1,14 @@ -+/* Verify that we generate isync instruction with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "\\tisync" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ int *addr = (int *) 0x53000000; -+ __nds32__isync (addr); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-load-store.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-load-store.c -new file mode 100644 -index 0000000..fc15716 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-load-store.c -@@ -0,0 +1,25 @@ -+/* Verify that we generate llw/lwup/scw/swup instruction -+ with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-require-effective-target nds32_no_v3m } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "\\tllw" } } */ -+/* { dg-final { scan-assembler "\\tlwup" } } */ -+/* { dg-final { scan-assembler "\\tscw" } } */ -+/* { dg-final { scan-assembler "\\tswup" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ int a = 0; -+ int b = 0; -+ unsigned int cc = 0; -+ -+ __nds32__llw (&a); -+ cc = __nds32__lwup (&a); -+ __nds32__scw (&a, b); -+ __nds32__swup (&a, b); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-lto.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-lto.c -new file mode 100644 -index 0000000..fbebcb6 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-lto.c -@@ -0,0 +1,28 @@ -+/* Verify that we use -flto option to generate instructions -+ with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0 -flto" } */ -+/* { dg-final { scan-assembler "\\tdsb" } } */ -+/* { dg-final { scan-assembler "\\tisb" } } */ -+/* { dg-final { scan-assembler "\\tmsync\\tall" } } */ -+/* { dg-final { scan-assembler "\\tmsync\\tstore" } } */ -+/* { dg-final { scan-assembler "\\tnop" } } */ -+/* { dg-final { scan-assembler "\\tstandby\\tno_wake_grant" } } */ -+/* { dg-final { scan-assembler "\\tstandby\\twake_grant" } } */ -+/* { dg-final { scan-assembler "\\tstandby\\twait_done" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ __nds32__dsb (); -+ __nds32__isb (); -+ __nds32__msync_all (); -+ __nds32__msync_store (); -+ __nds32__nop (); -+ __nds32__standby_no_wake_grant (); -+ __nds32__standby_wake_grant (); -+ __nds32__standby_wait_done (); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-machine-sva.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-machine-sva.c -new file mode 100644 -index 0000000..f927c72 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-machine-sva.c -@@ -0,0 +1,16 @@ -+/* Verify that we generate sva instruction with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "\\tsva" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ int a, b; -+ char c; -+ -+ c = __nds32__sva (a, b); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-machine-svs.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-machine-svs.c -new file mode 100644 -index 0000000..f998491 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-machine-svs.c -@@ -0,0 +1,16 @@ -+/* Verify that we generate svs instruction with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "\\tsvs" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ int a, b; -+ char c; -+ -+ c = __nds32__svs (a, b); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-mfsr-mtsr.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-mfsr-mtsr.c -new file mode 100644 -index 0000000..f069507 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-mfsr-mtsr.c -@@ -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 = __nds32__mfsr (__NDS32_REG_IPSW__); -+ __nds32__mtsr (ipsw_value, __NDS32_REG_IPSW__); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-mfusr-mtusr.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-mfusr-mtusr.c -new file mode 100644 -index 0000000..d6d069b ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-mfusr-mtusr.c -@@ -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 = __nds32__mfusr (__NDS32_REG_ITYPE__); -+ __nds32__mtusr (itype_value, __NDS32_REG_ITYPE__); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-misc.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-misc.c -new file mode 100644 -index 0000000..a11f6d9 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-misc.c -@@ -0,0 +1,39 @@ -+/* Verify that we generate other instructions with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "\\tbreak" } } */ -+/* { dg-final { scan-assembler "\\tdsb" } } */ -+/* { dg-final { scan-assembler "\\tisb" } } */ -+/* { dg-final { scan-assembler "\\tisync" } } */ -+/* { dg-final { scan-assembler "\\tmsync\\tall" } } */ -+/* { dg-final { scan-assembler "\\tmsync\\tstore" } } */ -+/* { dg-final { scan-assembler "\\tnop" } } */ -+/* { dg-final { scan-assembler "\\tstandby\\tno_wake_grant" } } */ -+/* { dg-final { scan-assembler "\\tstandby\\twake_grant" } } */ -+/* { dg-final { scan-assembler "\\tstandby\\twait_done" } } */ -+/* { dg-final { scan-assembler "\\tteqz" } } */ -+/* { dg-final { scan-assembler "\\ttnez" } } */ -+/* { dg-final { scan-assembler "\\ttrap" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ int a = 0; -+ -+ __nds32__break (2); -+ __nds32__dsb (); -+ __nds32__isb (); -+ __nds32__isync (&a); -+ __nds32__msync_all (); -+ __nds32__msync_store (); -+ __nds32__nop (); -+ __nds32__standby_no_wake_grant (); -+ __nds32__standby_wake_grant (); -+ __nds32__standby_wait_done (); -+ __nds32__teqz (a, 2); -+ __nds32__tnez (a, 2); -+ __nds32__trap (2); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-mtsr-dsb.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-mtsr-dsb.c -new file mode 100644 -index 0000000..226d627 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-mtsr-dsb.c -@@ -0,0 +1,14 @@ -+/* Verify that we generate mtsr and dsb instruction with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "\\tmtsr" } } */ -+/* { dg-final { scan-assembler "\\tdsb" } } */ -+ -+#include -+ -+void -+main (void) -+{ -+ __nds32__mtsr_dsb (1, NDS32_SR_ILMB); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-mtsr-isb.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-mtsr-isb.c -new file mode 100644 -index 0000000..e8b1f98 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-mtsr-isb.c -@@ -0,0 +1,14 @@ -+/* Verify that we generate mtsr and isb instruction with builtin function. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O0" } */ -+/* { dg-final { scan-assembler "\\tmtsr" } } */ -+/* { dg-final { scan-assembler "\\tisb" } } */ -+ -+#include -+ -+void -+main (void) -+{ -+ __nds32__mtsr_isb (1, NDS32_SR_ILMB); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-priority.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-priority.c -new file mode 100644 -index 0000000..c2ec6f6 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-priority.c -@@ -0,0 +1,18 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+int -+main (void) -+{ -+ __nds32__set_int_priority (NDS32_INT_H0, 0); -+ __nds32__set_int_priority (NDS32_INT_H15, 3); -+ __nds32__set_int_priority (NDS32_INT_H31, 3); -+ -+ int a = __nds32__get_int_priority (NDS32_INT_H0); -+ int b = __nds32__get_int_priority (NDS32_INT_H15); -+ int c = __nds32__get_int_priority (NDS32_INT_H31); -+ -+ return a + b + 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 0000000..f10b83d ---- /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 0000000..bd8178c ---- /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 0000000..1780543 ---- /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 0000000..e143d3f ---- /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 0000000..ed95782 ---- /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/compile/builtin-stura-add16.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-add16.c -new file mode 100644 -index 0000000..49fca46 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-add16.c -@@ -0,0 +1,22 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kadd16" } } */ -+/* { dg-final { scan-assembler "kadd16" } } */ -+/* { dg-final { scan-assembler "ukadd16" } } */ -+/* { dg-final { scan-assembler "ukadd16" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned int r, a, b; -+ int16x2_t vr, va, vb; -+ uint16x2_t v_ur, v_ua, v_ub; -+ -+ r = __nds32__kadd16 (a, b); -+ vr = __nds32__v_kadd16 (va, vb); -+ -+ r = __nds32__ukadd16 (a, b); -+ v_ur = __nds32__v_ukadd16 (v_ua, v_ub); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-add64.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-add64.c -new file mode 100644 -index 0000000..1f33a42 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-add64.c -@@ -0,0 +1,17 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kadd64" } } */ -+/* { dg-final { scan-assembler "ukadd64" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ long long r, a, b; -+ unsigned long long ur, ua, ub; -+ -+ r = __nds32__kadd64 (a, b); -+ ur = __nds32__ukadd64 (ua, ub); -+ -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-add8.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-add8.c -new file mode 100644 -index 0000000..1f2d226 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-add8.c -@@ -0,0 +1,22 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kadd8" } } */ -+/* { dg-final { scan-assembler "kadd8" } } */ -+/* { dg-final { scan-assembler "ukadd8" } } */ -+/* { dg-final { scan-assembler "ukadd8" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned int r, a, b; -+ int8x4_t vr, va, vb; -+ uint8x4_t v_ur, v_ua, v_ub; -+ -+ r = __nds32__kadd8 (a, b); -+ vr = __nds32__v_kadd8 (va, vb); -+ -+ r = __nds32__ukadd8 (a, b); -+ v_ur = __nds32__v_ukadd8 (v_ua, v_ub); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-cras16.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-cras16.c -new file mode 100644 -index 0000000..89c7e6d ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-cras16.c -@@ -0,0 +1,22 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kcras16" } } */ -+/* { dg-final { scan-assembler "kcras16" } } */ -+/* { dg-final { scan-assembler "ukcras16" } } */ -+/* { dg-final { scan-assembler "ukcras16" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned int r, a, b; -+ int16x2_t vr, va, vb; -+ uint16x2_t v_ur, v_ua, v_ub; -+ -+ r = __nds32__kcras16 (a, b); -+ vr = __nds32__v_kcras16 (va, vb); -+ -+ r = __nds32__ukcras16 (a, b); -+ v_ur = __nds32__v_ukcras16 (v_ua, v_ub); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-crsa16.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-crsa16.c -new file mode 100644 -index 0000000..beaa69a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-crsa16.c -@@ -0,0 +1,22 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kcrsa16" } } */ -+/* { dg-final { scan-assembler "kcrsa16" } } */ -+/* { dg-final { scan-assembler "ukcrsa16" } } */ -+/* { dg-final { scan-assembler "ukcrsa16" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned int r, a, b; -+ int16x2_t vr, va, vb; -+ uint16x2_t v_ur, v_ua, v_ub; -+ -+ r = __nds32__kcrsa16 (a, b); -+ vr = __nds32__v_kcrsa16 (va, vb); -+ -+ r = __nds32__ukcrsa16 (a, b); -+ v_ur = __nds32__v_ukcrsa16 (v_ua, v_ub); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-kabs8.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-kabs8.c -new file mode 100644 -index 0000000..de2e3c3 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-kabs8.c -@@ -0,0 +1,16 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kabs8" } } */ -+/* { dg-final { scan-assembler "kabs8" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned int r, a; -+ int8x4_t vr, va; -+ -+ r = __nds32__kabs8 (a); -+ vr = __nds32__v_kabs8 (va); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-ksll.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-ksll.c -new file mode 100644 -index 0000000..316b10c ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-ksll.c -@@ -0,0 +1,16 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "ksll" } } */ -+/* { dg-final { scan-assembler "kslli" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ int r, a; -+ unsigned int b; -+ -+ r = __nds32__ksll (a, b); -+ r = __nds32__ksll (a, 0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-ksll16.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-ksll16.c -new file mode 100644 -index 0000000..be9a08e ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-ksll16.c -@@ -0,0 +1,21 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "ksll16" } } */ -+/* { dg-final { scan-assembler "ksll16" } } */ -+/* { dg-final { scan-assembler "kslli16" } } */ -+/* { dg-final { scan-assembler "kslli16" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned int r, a, b; -+ int16x2_t vr, va; -+ -+ r = __nds32__ksll16 (a, b); -+ vr = __nds32__v_ksll16 (va, b); -+ -+ r = __nds32__ksll16 (a, 0); -+ vr = __nds32__v_ksll16 (va, 0); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-kslrawu.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-kslrawu.c -new file mode 100644 -index 0000000..4eb03e5 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-kslrawu.c -@@ -0,0 +1,14 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kslraw.u" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ int r, a; -+ unsigned int b; -+ -+ r = __nds32__kslraw_u (a, b); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-mar64.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-mar64.c -new file mode 100644 -index 0000000..79a3eb3 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-mar64.c -@@ -0,0 +1,16 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kmar64" } } */ -+/* { dg-final { scan-assembler "ukmar64" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ long long r, a, b; -+ unsigned long long ur, ua, ub; -+ -+ r = __nds32__kmar64 (r, a, b); -+ ur = __nds32__ukmar64 (ur, ua, ub); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-misc16.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-misc16.c -new file mode 100644 -index 0000000..272e922 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-misc16.c -@@ -0,0 +1,36 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "sclip16" } } */ -+/* { dg-final { scan-assembler "sclip16" } } */ -+/* { dg-final { scan-assembler "uclip16" } } */ -+/* { dg-final { scan-assembler "uclip16" } } */ -+/* { dg-final { scan-assembler "khm16" } } */ -+/* { dg-final { scan-assembler "khm16" } } */ -+/* { dg-final { scan-assembler "khmx16" } } */ -+/* { dg-final { scan-assembler "khmx16" } } */ -+/* { dg-final { scan-assembler "kabs16" } } */ -+/* { dg-final { scan-assembler "kabs16" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned int r, a, b; -+ int16x2_t vr, va, vb; -+ -+ r = __nds32__sclip16 (a, 0); -+ vr = __nds32__v_sclip16 (va, 0); -+ -+ r = __nds32__uclip16 (a, 0); -+ vr = __nds32__v_uclip16 (va, 0); -+ -+ r = __nds32__khm16 (a, b); -+ vr = __nds32__v_khm16 (va, vb); -+ -+ r = __nds32__khmx16 (a, b); -+ vr = __nds32__v_khmx16 (va, vb); -+ -+ r = __nds32__kabs16 (a); -+ vr = __nds32__v_kabs16 (va); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-msr64.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-msr64.c -new file mode 100644 -index 0000000..2ad64fa ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-msr64.c -@@ -0,0 +1,16 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kmsr64" } } */ -+/* { dg-final { scan-assembler "ukmsr64" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ long long r, a, b; -+ unsigned long long ur, ua, ub; -+ -+ r = __nds32__kmsr64 (r, a, b); -+ ur = __nds32__ukmsr64 (ur, ua, ub); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-msw16.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-msw16.c -new file mode 100644 -index 0000000..d7ccecb ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-msw16.c -@@ -0,0 +1,32 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kmmawb" } } */ -+/* { dg-final { scan-assembler "kmmawb" } } */ -+/* { dg-final { scan-assembler "kmmawb.u" } } */ -+/* { dg-final { scan-assembler "kmmawb.u" } } */ -+/* { dg-final { scan-assembler "kmmawt" } } */ -+/* { dg-final { scan-assembler "kmmawt" } } */ -+/* { dg-final { scan-assembler "kmmawt.u" } } */ -+/* { dg-final { scan-assembler "kmmawt.u" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ int r, a; -+ unsigned int b; -+ int16x2_t vb; -+ -+ r = __nds32__kmmawb (r, a, b); -+ r = __nds32__v_kmmawb (r, a, vb); -+ -+ r = __nds32__kmmawb_u (r, a, b); -+ r = __nds32__v_kmmawb_u (r, a, vb); -+ -+ r = __nds32__kmmawt (r, a, b); -+ r = __nds32__v_kmmawt (r, a, vb); -+ -+ r = __nds32__kmmawt_u (r, a, b); -+ r = __nds32__v_kmmawt_u (r, a, vb); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-msw32.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-msw32.c -new file mode 100644 -index 0000000..64d8d4a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-msw32.c -@@ -0,0 +1,24 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kmmac" } } */ -+/* { dg-final { scan-assembler "kmmac.u" } } */ -+/* { dg-final { scan-assembler "kmmsb" } } */ -+/* { dg-final { scan-assembler "kmmsb.u" } } */ -+/* { dg-final { scan-assembler "kwmmul" } } */ -+/* { dg-final { scan-assembler "kwmmul.u" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ int r, a, b; -+ r = __nds32__kmmac (r, a, b); -+ r = __nds32__kmmac_u (r, a, b); -+ -+ r = __nds32__kmmsb (r, a, b); -+ r = __nds32__kmmsb_u (r, a, b); -+ -+ r = __nds32__kwmmul (a, b); -+ r = __nds32__kwmmul_u (a, b); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-smul16x32.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-smul16x32.c -new file mode 100644 -index 0000000..0d2b87f ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-smul16x32.c -@@ -0,0 +1,72 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "kmda" } } */ -+/* { dg-final { scan-assembler "kmda" } } */ -+/* { dg-final { scan-assembler "kmxda" } } */ -+/* { dg-final { scan-assembler "kmxda" } } */ -+/* { dg-final { scan-assembler "kmabb" } } */ -+/* { dg-final { scan-assembler "kmabb" } } */ -+/* { dg-final { scan-assembler "kmabt" } } */ -+/* { dg-final { scan-assembler "kmabt" } } */ -+/* { dg-final { scan-assembler "kmatt" } } */ -+/* { dg-final { scan-assembler "kmatt" } } */ -+/* { dg-final { scan-assembler "kmada" } } */ -+/* { dg-final { scan-assembler "kmada" } } */ -+/* { dg-final { scan-assembler "kmaxda" } } */ -+/* { dg-final { scan-assembler "kmaxda" } } */ -+/* { dg-final { scan-assembler "kmads" } } */ -+/* { dg-final { scan-assembler "kmads" } } */ -+/* { dg-final { scan-assembler "kmadrs" } } */ -+/* { dg-final { scan-assembler "kmadrs" } } */ -+/* { dg-final { scan-assembler "kmaxds" } } */ -+/* { dg-final { scan-assembler "kmaxds" } } */ -+/* { dg-final { scan-assembler "kmsda" } } */ -+/* { dg-final { scan-assembler "kmsda" } } */ -+/* { dg-final { scan-assembler "kmsxda" } } */ -+/* { dg-final { scan-assembler "kmsxda" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ int r; -+ unsigned int a, b; -+ int16x2_t va, vb; -+ -+ r = __nds32__kmda (a, b); -+ r = __nds32__v_kmda (va, vb); -+ -+ r = __nds32__kmxda (a, b); -+ r = __nds32__v_kmxda (va, vb); -+ -+ r = __nds32__kmabb (r, a, b); -+ r = __nds32__v_kmabb (r, va, vb); -+ -+ r = __nds32__kmabt (r, a, b); -+ r = __nds32__v_kmabt (r, va, vb); -+ -+ r = __nds32__kmatt (r, a, b); -+ r = __nds32__v_kmatt (r, va, vb); -+ -+ r = __nds32__kmada (r, a, b); -+ r = __nds32__v_kmada (r, va, vb); -+ -+ r = __nds32__kmaxda (r, a, b); -+ r = __nds32__v_kmaxda (r, va, vb); -+ -+ r = __nds32__kmads (r, a, b); -+ r = __nds32__v_kmads (r, va, vb); -+ -+ r = __nds32__kmadrs (r, a, b); -+ r = __nds32__v_kmadrs (r, va, vb); -+ -+ r = __nds32__kmaxds (r, a, b); -+ r = __nds32__v_kmaxds (r, va, vb); -+ -+ r = __nds32__kmsda (r, a, b); -+ r = __nds32__v_kmsda (r, va, vb); -+ -+ r = __nds32__kmsxda (r, a, b); -+ r = __nds32__v_kmsxda (r, va, vb); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-sub16.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-sub16.c -new file mode 100644 -index 0000000..ecea7bb ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-sub16.c -@@ -0,0 +1,22 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "ksub16" } } */ -+/* { dg-final { scan-assembler "ksub16" } } */ -+/* { dg-final { scan-assembler "uksub16" } } */ -+/* { dg-final { scan-assembler "uksub16" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned int r, a, b; -+ int16x2_t vr, va, vb; -+ uint16x2_t v_ur, v_ua, v_ub; -+ -+ r = __nds32__ksub16 (a, b); -+ vr = __nds32__v_ksub16 (va, vb); -+ -+ r = __nds32__uksub16 (a, b); -+ v_ur = __nds32__v_uksub16 (v_ua, v_ub); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-sub64.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-sub64.c -new file mode 100644 -index 0000000..fae30e9 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-sub64.c -@@ -0,0 +1,17 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "ksub64" } } */ -+/* { dg-final { scan-assembler "uksub64" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ long long r, a, b; -+ unsigned long long ur, ua, ub; -+ -+ r = __nds32__ksub64 (a, b); -+ ur = __nds32__uksub64 (ua, ub); -+ -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-sub8.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-sub8.c -new file mode 100644 -index 0000000..5e343e9 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-stura-sub8.c -@@ -0,0 +1,22 @@ -+/* { dg-do compile } */ -+/* { dg-options "-mext-dsp" } */ -+/* { dg-final { scan-assembler "ksub8" } } */ -+/* { dg-final { scan-assembler "ksub8" } } */ -+/* { dg-final { scan-assembler "uksub8" } } */ -+/* { dg-final { scan-assembler "uksub8" } } */ -+ -+#include -+ -+void -+test (void) -+{ -+ unsigned int r, a, b; -+ int8x4_t vr, va, vb; -+ uint8x4_t v_ur, v_ua, v_ub; -+ -+ r = __nds32__ksub8 (a, b); -+ vr = __nds32__v_ksub8 (va, vb); -+ -+ r = __nds32__uksub8 (a, b); -+ v_ur = __nds32__v_uksub8 (v_ua, v_ub); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/builtin-unaligned-feature.c b/gcc/testsuite/gcc.target/nds32/compile/builtin-unaligned-feature.c -new file mode 100644 -index 0000000..6199109 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/builtin-unaligned-feature.c -@@ -0,0 +1,13 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O1" } */ -+ -+#include -+ -+int -+main () -+{ -+ unsigned unalign = __nds32__unaligned_feature (); -+ __nds32__enable_unaligned (); -+ __nds32__disable_unaligned (); -+ return unalign; -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/dsp-add-sub.c b/gcc/testsuite/gcc.target/nds32/compile/dsp-add-sub.c -new file mode 100644 -index 0000000..704610e ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/dsp-add-sub.c -@@ -0,0 +1,47 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mext-dsp" } */ -+/* { dg-final { scan-assembler "add8" } } */ -+/* { dg-final { scan-assembler "add16" } } */ -+/* { dg-final { scan-assembler "add64" } } */ -+/* { dg-final { scan-assembler "sub8" } } */ -+/* { dg-final { scan-assembler "sub16" } } */ -+/* { dg-final { scan-assembler "sub64" } } */ -+ -+typedef signed char v4qi __attribute__ ((vector_size (4))); -+typedef short v2hi __attribute__ ((vector_size (4))); -+ -+v4qi __attribute__ ((noinline)) -+add8 (v4qi a, v4qi b) -+{ -+ return a + b; -+} -+ -+v4qi __attribute__ ((noinline)) -+sub8 (v4qi a, v4qi b) -+{ -+ return a - b; -+} -+ -+v2hi __attribute__ ((noinline)) -+add16 (v2hi a, v2hi b) -+{ -+ return a + b; -+} -+ -+v2hi __attribute__ ((noinline)) -+sub16 (v2hi a, v2hi b) -+{ -+ return a - b; -+} -+ -+long long -+add64 (long long a, long long b) -+{ -+ return a + b; -+} -+ -+long long -+sub64 (long long a, long long b) -+{ -+ return a - b; -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/dsp-bpick.c b/gcc/testsuite/gcc.target/nds32/compile/dsp-bpick.c -new file mode 100644 -index 0000000..5f9d7de ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/dsp-bpick.c -@@ -0,0 +1,8 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mext-dsp" } */ -+/* { dg-final { scan-assembler "bpick" } } */ -+ -+int bpick(int a, int b, int mask) -+{ -+ return (a & mask) | (b & ~mask); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/dsp-mmul.c b/gcc/testsuite/gcc.target/nds32/compile/dsp-mmul.c -new file mode 100644 -index 0000000..5c9cdeb ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/dsp-mmul.c -@@ -0,0 +1,12 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mext-dsp" } */ -+/* { dg-final { scan-assembler "smmul" } } */ -+ -+typedef signed char v4qi __attribute__ ((vector_size (4))); -+typedef short v2hi __attribute__ ((vector_size (4))); -+ -+int smmul(int a, int b) -+{ -+ long long tmp = (long long)a * b; -+ return (int)((tmp >> 32) & 0xffffffffll); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/dsp-mulhisi.c b/gcc/testsuite/gcc.target/nds32/compile/dsp-mulhisi.c -new file mode 100644 -index 0000000..856530b ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/dsp-mulhisi.c -@@ -0,0 +1,23 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mext-dsp" } */ -+/* { dg-final { scan-assembler "smbb" } } */ -+/* { dg-final { scan-assembler "smbt" } } */ -+/* { dg-final { scan-assembler "smtt" } } */ -+ -+typedef signed char v4qi __attribute__ ((vector_size (4))); -+typedef short v2hi __attribute__ ((vector_size (4))); -+ -+int smbb(v2hi a, v2hi b) -+{ -+ return a[0] * b[0]; -+} -+ -+int smbt(v2hi a, v2hi b) -+{ -+ return a[0] * b[1]; -+} -+ -+int smtt(v2hi a, v2hi b) -+{ -+ return a[1] * b[1]; -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/dsp-raddsub.c b/gcc/testsuite/gcc.target/nds32/compile/dsp-raddsub.c -new file mode 100644 -index 0000000..4817637 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/dsp-raddsub.c -@@ -0,0 +1,26 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mext-dsp" } */ -+/* { dg-final { scan-assembler "raddw" } } */ -+/* { dg-final { scan-assembler "rsubw" } } */ -+/* { dg-final { scan-assembler "uraddw" } } */ -+/* { dg-final { scan-assembler "ursubw" } } */ -+ -+int raddw(int a, int b) -+{ -+ return (a + b) >> 1; -+} -+ -+int rsubw(int a, int b) -+{ -+ return (a - b) >> 1; -+} -+ -+unsigned uraddw(unsigned a, unsigned b) -+{ -+ return (a + b) >> 1; -+} -+ -+unsigned ursubw(unsigned a, unsigned b) -+{ -+ return (a - b) >> 1; -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/dsp-smals.c b/gcc/testsuite/gcc.target/nds32/compile/dsp-smals.c -new file mode 100644 -index 0000000..f1dc684 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/dsp-smals.c -@@ -0,0 +1,30 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mext-dsp" } */ -+/* { dg-final { scan-assembler "smalbb" } } */ -+/* { dg-final { scan-assembler "smalbt" } } */ -+/* { dg-final { scan-assembler "smaltt" } } */ -+/* { dg-final { scan-assembler "smal" } } */ -+ -+typedef signed char v4qi __attribute__ ((vector_size (4))); -+typedef short v2hi __attribute__ ((vector_size (4))); -+ -+ -+long long smalbb(long long acc, v2hi a, v2hi b) -+{ -+ return acc + a[0] * b[0]; -+} -+ -+long long smalbt(long long acc, v2hi a, v2hi b) -+{ -+ return acc + a[1] * b[0]; -+} -+ -+long long smaltt(long long acc, v2hi a, v2hi b) -+{ -+ return acc + a[1] * b[1]; -+} -+ -+long long smal(v2hi a, long long b) -+{ -+ return b + (long long)(a[0] * a[1]); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/dsp-smalxda.c b/gcc/testsuite/gcc.target/nds32/compile/dsp-smalxda.c -new file mode 100644 -index 0000000..2fe606b ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/dsp-smalxda.c -@@ -0,0 +1,17 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mext-dsp" } */ -+/* { dg-final { scan-assembler "smalxda" } } */ -+/* { dg-final { scan-assembler "smalxds" } } */ -+ -+typedef signed char v4qi __attribute__ ((vector_size (4))); -+typedef short v2hi __attribute__ ((vector_size (4))); -+ -+long long smalxda(long long acc, v2hi a, v2hi b) -+{ -+ return acc + (a[0] * b[1] + a[1] * b[0]); -+} -+ -+long long smalxds(long long acc, v2hi a, v2hi b) -+{ -+ return acc + (a[1] * b[0] - a[0] * b[1]); -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/dsp-unpkd.c b/gcc/testsuite/gcc.target/nds32/compile/dsp-unpkd.c -new file mode 100644 -index 0000000..2de7107 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/dsp-unpkd.c -@@ -0,0 +1,79 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -mext-dsp" } */ -+/* { dg-final { scan-assembler "sunpkd810" } } */ -+/* { dg-final { scan-assembler "sunpkd820" } } */ -+/* { dg-final { scan-assembler "sunpkd830" } } */ -+/* { dg-final { scan-assembler "sunpkd831" } } */ -+/* { dg-final { scan-assembler "zunpkd810" } } */ -+/* { dg-final { scan-assembler "zunpkd820" } } */ -+/* { dg-final { scan-assembler "zunpkd830" } } */ -+/* { dg-final { scan-assembler "zunpkd831" } } */ -+ -+typedef signed char v4qi __attribute__ ((vector_size (4))); -+typedef short v2hi __attribute__ ((vector_size (4))); -+typedef unsigned char uv4qi __attribute__ ((vector_size (4))); -+typedef unsigned short uv2hi __attribute__ ((vector_size (4))); -+ -+v2hi sunpkd810(v4qi v) -+{ -+ v2hi ret; -+ ret[0] = v[0]; -+ ret[1] = v[1]; -+ return ret; -+} -+ -+v2hi sunpkd820(v4qi v) -+{ -+ v2hi ret; -+ ret[0] = v[0]; -+ ret[1] = v[2]; -+ return ret; -+} -+ -+v2hi sunpkd830(v4qi v) -+{ -+ v2hi ret; -+ ret[0] = v[0]; -+ ret[1] = v[3]; -+ return ret; -+} -+ -+v2hi sunpkd831(v4qi v) -+{ -+ v2hi ret; -+ ret[0] = v[1]; -+ ret[1] = v[3]; -+ return ret; -+} -+ -+uv2hi zunpkd810(uv4qi v) -+{ -+ uv2hi ret; -+ ret[0] = v[0]; -+ ret[1] = v[1]; -+ return ret; -+} -+ -+uv2hi zunpkd820(uv4qi v) -+{ -+ uv2hi ret; -+ ret[0] = v[0]; -+ ret[1] = v[2]; -+ return ret; -+} -+ -+uv2hi zunpkd830(uv4qi v) -+{ -+ uv2hi ret; -+ ret[0] = v[0]; -+ ret[1] = v[3]; -+ return ret; -+} -+ -+uv2hi zunpkd831(uv4qi v) -+{ -+ uv2hi ret; -+ ret[0] = v[1]; -+ ret[1] = v[3]; -+ return ret; -+} -diff --git a/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-1.c b/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-1.c -new file mode 100644 -index 0000000..d456fa5 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-1.c -@@ -0,0 +1,21 @@ -+/* Verify scalbn transform pass for normal case. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -fdump-tree-all -lm" } */ -+/* { dg-require-effective-target nds32_soft_fp } */ -+ -+float test_scalbnf (float x) -+{ -+ return x * 128; -+} -+ -+double test_scalbn (double x) -+{ -+ return x * 256; -+} -+ -+/* { dg-final { scan-tree-dump "(_\[0-9\]+) = __builtin_scalbnf \\(x_\[0-9\]+\\(D\\), 7\\);\\s*_\[0-9\]+ = \\(float\\) \\1;" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump "(_\[0-9\]+) = __builtin_scalbn \\(x_\[0-9\]+\\(D\\), 8\\);\\s*_\[0-9\]+ = \\(double\\) \\1;" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump-not " \\* 1.28e\\+2" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump-not " \\* 2.56e\\+2" "scalbn_transform" } } */ -+/* { dg-final { cleanup-tree-dump "*" } } */ -diff --git a/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-2.c b/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-2.c -new file mode 100644 -index 0000000..480cf23 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-2.c -@@ -0,0 +1,14 @@ -+/* Verify scalbn transform pass for negative number case. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -fdump-tree-all" } */ -+/* { dg-require-effective-target nds32_soft_fp } */ -+ -+double test_neg_scalbn (double x) -+{ -+ return x * -8; -+} -+ -+/* { dg-final { scan-tree-dump "(_\[0-9\]+) = __builtin_scalbn \\(x_\[0-9\]+\\(D\\), 3\\);\\s*_\[0-9\]+ = -\\1;" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump-not " \\* -8.0e\\+0" "scalbn_transform" } } */ -+/* { dg-final { cleanup-tree-dump "*" } } */ -diff --git a/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-3.c b/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-3.c -new file mode 100644 -index 0000000..256f31a ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-3.c -@@ -0,0 +1,14 @@ -+/* Verify scalbn transform pass for negative-exponent case. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -fdump-tree-all" } */ -+/* { dg-require-effective-target nds32_soft_fp } */ -+ -+double test_neg_exp_scalbnf (double x) -+{ -+ return x * 0.0625; -+} -+ -+/* { dg-final { scan-tree-dump "(_\[0-9\]+) = __builtin_scalbn \\(x_\[0-9\]+\\(D\\), -4\\);\\s*_\[0-9\]+ = \\(double\\) \\1;" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump-not " \\* 6.25e\\-2" "scalbn_transform" } } */ -+/* { dg-final { cleanup-tree-dump "*" } } */ -diff --git a/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-4.c b/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-4.c -new file mode 100644 -index 0000000..b6ba596 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-4.c -@@ -0,0 +1,52 @@ -+/* Verify scalbn transform pass for cases that can't be optimized. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -fdump-tree-all" } */ -+/* { dg-require-effective-target nds32_soft_fp } */ -+ -+#include "math.h" -+ -+double test_filter_condition_1 (double x) -+{ -+ return x * 0; -+} -+ -+double test_filter_condition_2 (double x) -+{ -+ return x * -0; -+} -+ -+double test_filter_condition_3 (double x) -+{ -+ return x * 485; -+} -+ -+double test_filter_condition_4 (double x) -+{ -+ return x * -85; -+} -+ -+double test_filter_condition_5 (double x) -+{ -+ return x * 0.12; -+} -+ -+double test_filter_condition_6 (double x) -+{ -+ return x * -INFINITY; -+} -+ -+double test_filter_condition_7 (double x) -+{ -+ return x * NAN; -+} -+ -+/* { dg-final { scan-tree-dump-times "x_\[0-9\]+\\(D\\) \\* 0.0" 2 "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump " \\* 4.85e\\+2" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump " \\* -8.5e\\+1" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump " \\* 1.19999" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump " \\* -Inf" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump " \\* Nan" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump-not "__builtin_scalbn" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump-times "No multiplication stmt is transformed" 7 "scalbn_transform" } } */ -+/* { dg-final { cleanup-tree-dump "*" } } */ -diff --git a/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-5.c b/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-5.c -new file mode 100644 -index 0000000..874170e ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/compile/scalbn-transform-5.c -@@ -0,0 +1,20 @@ -+/* Verify scalbn transform pass for bug 11424 case. */ -+ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -fdump-tree-all" } */ -+/* { dg-require-effective-target nds32_soft_fp } */ -+ -+typedef float float32_t; -+float32_t test_case (float32_t *pIn) -+{ -+ float32_t in; -+ in = *pIn++; -+ in = (in * 128); -+ in += in > 0.0f ? 0.5f : -0.5f; -+ -+ return in; -+} -+ -+/* { dg-final { scan-tree-dump "(_\[0-9\]+) = __builtin_scalbnf \\(in_\[0-9\]+, 7\\);\\s*in_\[0-9\]+ = \\(float32_t\\) \\1;" "scalbn_transform" } } */ -+/* { dg-final { scan-tree-dump-not "in_\[0-9\]+ = in_\[0-9\]+ \\* 1.28e\\+2" "scalbn_transform" } } */ -+/* { dg-final { cleanup-tree-dump "*" } } */ -diff --git a/gcc/testsuite/gcc.target/nds32/dsp-v2hi-packing00.c b/gcc/testsuite/gcc.target/nds32/dsp-v2hi-packing00.c -new file mode 100644 -index 0000000..d1c61b7 ---- /dev/null -+++ b/gcc/testsuite/gcc.target/nds32/dsp-v2hi-packing00.c -@@ -0,0 +1,127 @@ -+/* { dg-do run } */ -+ -+#include -+ -+int16x2_t packing01(int16x2_t x, int16x2_t y) __attribute__ ((noinline)); -+int16x2_t packing01(int16x2_t x, int16x2_t y) -+{ -+ int16x2_t ret; -+ ret[0] = x[0]; -+ ret[1] = y[1]; -+ return ret; -+} -+ -+int16x2_t packing10(int16x2_t x, int16x2_t y) __attribute__ ((noinline)); -+int16x2_t packing10(int16x2_t x, int16x2_t y) -+{ -+ int16x2_t ret; -+ ret[0] = x[1]; -+ ret[1] = y[0]; -+ return ret; -+} -+ -+int16x2_t packing00(int16x2_t x, int16x2_t y) __attribute__ ((noinline)); -+int16x2_t packing00(int16x2_t x, int16x2_t y) -+{ -+ int16x2_t ret; -+ ret[0] = x[0]; -+ ret[1] = y[0]; -+ return ret; -+} -+ -+int16x2_t packing0cv0(int16x2_t x) __attribute__ ((noinline)); -+int16x2_t packing0cv0(int16x2_t x) -+{ -+ int16x2_t ret = {0, 0}; -+ ret[0] = x[0]; -+ return ret; -+} -+ -+int16x2_t packingcv00(int16x2_t x) __attribute__ ((noinline)); -+int16x2_t packingcv00(int16x2_t x) -+{ -+ int16x2_t ret = {0, 0}; -+ ret[1] = x[0]; -+ return ret; -+} -+ -+int16x2_t packing11(int16x2_t x, int16x2_t y) __attribute__ ((noinline)); -+int16x2_t packing11(int16x2_t x, int16x2_t y) -+{ -+ int16x2_t ret; -+ ret[0] = x[1]; -+ ret[1] = y[1]; -+ return ret; -+} -+int16x2_t packing1cv0(int16x2_t x) __attribute__ ((noinline)); -+int16x2_t packing1cv0(int16x2_t x) -+{ -+ int16x2_t ret = {0, 0}; -+ ret[0] = x[1]; -+ return ret; -+} -+ -+int16x2_t packingcv01(int16x2_t x) __attribute__ ((noinline)); -+int16x2_t packingcv01(int16x2_t x) -+{ -+ int16x2_t ret = {0, 0}; -+ ret[1] = x[1]; -+ return ret; -+} -+ -+int main() { -+ int16x2_t a = {0x11, 0x22}; -+ int16x2_t b = {0x33, 0x44}; -+ -+ int16x2_t ret00, ret01, ret10, ret11; -+ int16x2_t ret0cv0, retcv00, ret1cv0, retcv01; -+ ret00 = packing00 (a, b); -+ -+ if (ret00[0] != 0x11 -+ || ret00[1] != 0x33) -+ return 1; -+ -+ ret0cv0 = packing0cv0 (a); -+ -+ if (ret0cv0[0] != 0x11 -+ || ret0cv0[1] != 0) -+ return 1; -+ -+ retcv00 = packingcv00 (a); -+ -+ if (retcv00[0] != 0 -+ || retcv00[1] != 0x11) -+ return 1; -+ -+ ret11 = packing11 (a, b); -+ -+ if (ret11[0] != 0x22 -+ || ret11[1] != 0x44) -+ return 1; -+ -+ ret1cv0 = packing1cv0 (a); -+ -+ if (ret1cv0[0] != 0x22 -+ || ret1cv0[1] != 0) -+ return 1; -+ -+ retcv01 = packingcv01 (a); -+ -+ if (retcv01[0] != 0 -+ || retcv01[1] != 0x22) -+ return 1; -+ -+ ret01 = packing01 (a, b); -+ -+ if (ret01[0] != 0x11 -+ || ret01[1] != 0x44) -+ return 1; -+ -+ ret10 = packing10 (a, b); -+ -+ if (ret10[0] != 0x22 -+ || ret10[1] != 0x33) -+ return 1; -+ -+ return 0; -+} -diff --git a/gcc/testsuite/gcc.target/nds32/nds32.exp b/gcc/testsuite/gcc.target/nds32/nds32.exp -index 1c245f6..2f5a150 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 f0f5ac4..5a9b57d 100644 ---- a/gcc/testsuite/lib/target-supports.exp -+++ b/gcc/testsuite/lib/target-supports.exp -@@ -487,6 +487,10 @@ proc check_effective_target_trampolines { } { - || [istarget hppa64-hp-hpux11.23] } { - return 0; - } -+ if { [istarget nds32*-*-*] -+ && [check_effective_target_nds32_reduced_regs] } { -+ return 0; -+ } - return 1 - } - -@@ -500,7 +504,7 @@ proc check_effective_target_keeps_null_pointer_checks { } { - if [target_info exists keeps_null_pointer_checks] { - return 1 - } -- if { [istarget avr-*-*] } { -+ if { [istarget avr-*-*] || [istarget nds32*-*-elf] } { - return 1; - } - return 0 -@@ -3597,6 +3601,125 @@ proc check_effective_target_arm_prefer_ldrd_strd { } { - } "-O2 -mthumb" ] - } - -+# If board info says it only has 16M addressing space, return 0. -+# Otherwise, return 1. -+proc check_effective_target_nds32_full_addr_space { } { -+ if [board_info target exists addr16m] { -+ return 0 -+ } -+ return 1; -+} -+ -+# Return 1 if gp direct is enable by default. -+proc check_effective_target_nds32_gp_direct { } { -+ return [check_no_compiler_messages gp_direct object { -+ #ifdef __NDS32_GP_DIRECT__ -+ int dummy; -+ #else -+ #error no GP_DIRECT -+ #endif -+ }] -+} -+ -+# Return 1 if this is a nds32 target supporting -mext-perf. -+proc check_effective_target_nds32_ext_perf { } { -+ return [check_no_compiler_messages ext_perf object { -+ #ifdef __NDS32_EXT_PERF__ -+ int dummy; -+ #else -+ #error no EXT_PERF -+ #endif -+ }] -+} -+ -+# Return 1 if this is a nds32 target supporting -mext-perf2. -+proc check_effective_target_nds32_ext_perf2 { } { -+ return [check_no_compiler_messages ext_perf2 object { -+ #ifdef __NDS32_EXT_PERF2__ -+ int dummy; -+ #else -+ #error no EXT_PERF2 -+ #endif -+ }] -+} -+ -+# Return 1 if this is a nds32 target supporting -mext-string. -+proc check_effective_target_nds32_ext_string { } { -+ return [check_no_compiler_messages ext_string object { -+ #ifdef __NDS32_EXT_STRING__ -+ int dummy; -+ #else -+ #error no EXT_STRING -+ #endif -+ }] -+} -+ -+# Return 1 if this is a nds32 target supporting -mext-fpu-sp or -mext-fpu-dp. -+proc check_effective_target_nds32_ext_fpu { } { -+ return [check_no_compiler_messages ext_fpu object { -+ #if defined(__NDS32_EXT_FPU_SP__) || defined(__NDS32_EXT_FPU_DP__) -+ int dummy; -+ #else -+ #error no support FPU -+ #endif -+ }] -+} -+ -+# Return 1 if this is a nds32 target not supporting -mext-fpu-sp or -mext-fpu-dp. -+proc check_effective_target_nds32_soft_fp { } { -+ return [check_no_compiler_messages soft_fp object { -+ #if defined(__NDS32_EXT_FPU_SP__) || defined(__NDS32_EXT_FPU_DP__) -+ #error Hard FP -+ #else -+ int dummy; -+ #endif -+ }] -+} -+ -+# Return 1 if this is a nds32 target supporting -mext-fpu-sp. -+proc check_effective_target_nds32_ext_fpu_sp { } { -+ return [check_no_compiler_messages ext_fpu_sp object { -+ #ifdef __NDS32_EXT_FPU_SP__ -+ int dummy; -+ #else -+ #error no EXT_FPU_SP -+ #endif -+ }] -+} -+ -+# Return 1 if this is a nds32 target supporting -mext-fpu-dp. -+proc check_effective_target_nds32_ext_fpu_dp { } { -+ return [check_no_compiler_messages ext_fpu_dp object { -+ #ifdef __NDS32_EXT_FPU_DP__ -+ int dummy; -+ #else -+ #error no EXT_FPU_DP -+ #endif -+ }] -+} -+ -+# Return 1 if this is a nds32 target supporting -mreduced-regs. -+proc check_effective_target_nds32_reduced_regs { } { -+ return [check_no_compiler_messages reduced_regs object { -+ #ifdef __NDS32_REDUCED_REGS__ -+ int dummy; -+ #else -+ #error no REDUCED_REGS -+ #endif -+ }] -+} -+ -+# Return 1 if this is a nds32 target not supporting v3m ISA. -+proc check_effective_target_nds32_no_v3m { } { -+ return [check_no_compiler_messages no_v3m object { -+ #if !defined(__NDS32_BASELINE_V3M__) -+ int dummy; -+ #else -+ #error Support V3M ISA -+ #endif -+ }] -+} -+ - # Return 1 if this is a PowerPC target supporting -meabi. - - proc check_effective_target_powerpc_eabi_ok { } { -@@ -6897,6 +7020,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/gcc/tree-vrp.c b/gcc/tree-vrp.c -index 154df21..acd1a52 100644 ---- a/gcc/tree-vrp.c -+++ b/gcc/tree-vrp.c -@@ -9518,6 +9518,7 @@ simplify_cond_using_ranges (gcond *stmt) - used for the comparison directly if we just massage the constant in the - comparison. */ - if (TREE_CODE (op0) == SSA_NAME -+ && has_single_use (op0) - && TREE_CODE (op1) == INTEGER_CST) - { - gimple *def_stmt = SSA_NAME_DEF_STMT (op0); -diff --git a/libgcc/config.host b/libgcc/config.host -index 124f2ce..107ccb1 100644 ---- a/libgcc/config.host -+++ b/libgcc/config.host -@@ -946,6 +946,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. -@@ -959,9 +976,19 @@ nds32*-elf*) - tmake_file="${tmake_file} nds32/t-nds32-newlib t-softfp-sfdf t-softfp" - ;; - mculib) -- # Append library definition makefile fragment t-nds32-mculib. -+ case "${with_arch}" in -+ "" | v2 | v2j | v3 | v3j | v3m) -+ # Append library definition makefile fragment t-nds32-mculib-generic. - # The software floating point library is included in mculib. -- tmake_file="${tmake_file} nds32/t-nds32-mculib" -+ tmake_file="${tmake_file} nds32/t-nds32-mculib-generic" -+ ;; -+ v3f | v3s) -+ # Append library definition makefile fragment t-nds32-mculib-softfp. -+ # Append mculib do not support ABI2FP_PLUS, -+ # so using'soft-fp' software floating point make rule fragment provided by gcc. -+ tmake_file="${tmake_file} nds32/t-nds32-mculib-softfp t-softfp-sfdf t-softfp" -+ ;; -+ esac - ;; - *) - echo "Cannot accept --with-nds32-lib=$with_nds32_lib, available values are: newlib mculib" 1>&2 -diff --git a/libgcc/config/nds32/crtzero.S b/libgcc/config/nds32/crtzero.S -deleted file mode 100644 -index 9898525..0000000 ---- a/libgcc/config/nds32/crtzero.S -+++ /dev/null -@@ -1,103 +0,0 @@ --/* The startup code sample of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- --!!============================================================================== --!! --!! crtzero.S --!! --!! This is JUST A SAMPLE of nds32 startup code !! --!! You can refer this content and implement --!! the actual one in newlib/mculib. --!! --!!============================================================================== -- --!!------------------------------------------------------------------------------ --!! Jump to start up code --!!------------------------------------------------------------------------------ -- .section .nds32_init, "ax" -- j _start -- --!!------------------------------------------------------------------------------ --!! Startup code implementation --!!------------------------------------------------------------------------------ -- .section .text -- .global _start -- .weak _SDA_BASE_ -- .weak _FP_BASE_ -- .align 2 -- .func _start -- .type _start, @function --_start: --.L_fp_gp_lp_init: -- la $fp, _FP_BASE_ ! init $fp -- la $gp, _SDA_BASE_ ! init $gp for small data access -- movi $lp, 0 ! init $lp -- --.L_stack_init: -- la $sp, _stack ! init $sp -- movi $r0, -8 ! align $sp to 8-byte (use 0xfffffff8) -- and $sp, $sp, $r0 ! align $sp to 8-byte (filter out lower 3-bit) -- --.L_bss_init: -- ! clear BSS, this process can be 4 time faster if data is 4 byte aligned -- ! if so, use swi.p instead of sbi.p -- ! the related stuff are defined in linker script -- la $r0, _edata ! get the starting addr of bss -- la $r2, _end ! get ending addr of bss -- beq $r0, $r2, .L_call_main ! if no bss just do nothing -- movi $r1, 0 ! should be cleared to 0 --.L_clear_bss: -- sbi.p $r1, [$r0], 1 ! Set 0 to bss -- bne $r0, $r2, .L_clear_bss ! Still bytes left to set -- --!.L_stack_heap_check: --! la $r0, _end ! init heap_end --! s.w $r0, heap_end ! save it -- -- --!.L_init_argc_argv: --! ! argc/argv initialization if necessary; default implementation is in crt1.o --! la $r9, _arg_init ! load address of _arg_init? --! beqz $r9, .L4 ! has _arg_init? no, go check main() --! addi $sp, $sp, -512 ! allocate space for command line + arguments --! move $r6, $sp ! r6 = buffer addr of cmd line --! move $r0, $r6 ! r0 = buffer addr of cmd line --! syscall 6002 ! get cmd line --! move $r0, $r6 ! r0 = buffer addr of cmd line --! addi $r1, $r6, 256 ! r1 = argv --! jral $r9 ! init argc/argv --! addi $r1, $r6, 256 ! r1 = argv -- --.L_call_main: -- ! call main() if main() is provided -- la $r15, main ! load address of main -- jral $r15 ! call main -- --.L_terminate_program: -- syscall 0x1 ! use syscall 0x1 to terminate program -- .size _start, .-_start -- .end -- --!! ------------------------------------------------------------------------ -diff --git a/libgcc/config/nds32/initfini.c b/libgcc/config/nds32/initfini.c -index 0aa33f5..34406f0 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 3e978b4..a519df8 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 6179a98..f1a3b59 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/excp_isr_4b.S b/libgcc/config/nds32/isr-library/excp_isr_4b.S -deleted file mode 100644 -index af70c7a..0000000 ---- a/libgcc/config/nds32/isr-library/excp_isr_4b.S -+++ /dev/null -@@ -1,133 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- --#include "save_mac_regs.inc" --#include "save_fpu_regs.inc" --#include "save_fpu_regs_00.inc" --#include "save_fpu_regs_01.inc" --#include "save_fpu_regs_02.inc" --#include "save_fpu_regs_03.inc" --#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_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 4-byte vector size version. -- The "_4b" postfix was added for 4-byte version symbol. --*/ --#ifdef NDS32_SAVE_ALL_REGS --#if defined(NDS32_NESTED) -- .globl _nds32_e_sa_ns_4b -- .type _nds32_e_sa_ns_4b, @function --_nds32_e_sa_ns_4b: --#elif defined(NDS32_NESTED_READY) -- .globl _nds32_e_sa_nr_4b -- .type _nds32_e_sa_nr_4b, @function --_nds32_e_sa_nr_4b: --#else /* Not nested handler. */ -- .globl _nds32_e_sa_nn_4b -- .type _nds32_e_sa_nn_4b, @function --_nds32_e_sa_nn_4b: --#endif /* endif for Nest Type */ --#else /* not NDS32_SAVE_ALL_REGS */ --#if defined(NDS32_NESTED) -- .globl _nds32_e_ps_ns_4b -- .type _nds32_e_ps_ns_4b, @function --_nds32_e_ps_ns_4b: --#elif defined(NDS32_NESTED_READY) -- .globl _nds32_e_ps_nr_4b -- .type _nds32_e_ps_nr_4b, @function --_nds32_e_ps_nr_4b: --#else /* Not nested handler. */ -- .globl _nds32_e_ps_nn_4b -- .type _nds32_e_ps_nn_4b, @function --_nds32_e_ps_nn_4b: --#endif /* endif for Nest Type */ --#endif /* not NDS32_SAVE_ALL_REGS */ -- --/* -- This is 4-byte vector size version. -- The vector id was restored into $lp in vector by compiler. --*/ --#ifdef NDS32_SAVE_ALL_REGS -- SAVE_ALL_4B --#else -- SAVE_PARTIAL_4B --#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. */ --#ifdef NDS32_SAVE_ALL_REGS -- RESTORE_ALL --#else -- RESTORE_PARTIAL --#endif -- iret -- --#ifdef NDS32_SAVE_ALL_REGS --#if defined(NDS32_NESTED) -- .size _nds32_e_sa_ns_4b, .-_nds32_e_sa_ns_4b --#elif defined(NDS32_NESTED_READY) -- .size _nds32_e_sa_nr_4b, .-_nds32_e_sa_nr_4b --#else /* Not nested handler. */ -- .size _nds32_e_sa_nn_4b, .-_nds32_e_sa_nn_4b --#endif /* endif for Nest Type */ --#else /* not NDS32_SAVE_ALL_REGS */ --#if defined(NDS32_NESTED) -- .size _nds32_e_ps_ns_4b, .-_nds32_e_ps_ns_4b --#elif defined(NDS32_NESTED_READY) -- .size _nds32_e_ps_nr_4b, .-_nds32_e_ps_nr_4b --#else /* Not nested handler. */ -- .size _nds32_e_ps_nn_4b, .-_nds32_e_ps_nn_4b --#endif /* endif for Nest Type */ --#endif /* not NDS32_SAVE_ALL_REGS */ -diff --git a/libgcc/config/nds32/isr-library/intr_isr.S b/libgcc/config/nds32/isr-library/intr_isr.S -index c55da1c..90c5c25 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/intr_isr_4b.S b/libgcc/config/nds32/isr-library/intr_isr_4b.S -deleted file mode 100644 -index d82c007..0000000 ---- a/libgcc/config/nds32/isr-library/intr_isr_4b.S -+++ /dev/null -@@ -1,134 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- --#include "save_mac_regs.inc" --#include "save_fpu_regs.inc" --#include "save_fpu_regs_00.inc" --#include "save_fpu_regs_01.inc" --#include "save_fpu_regs_02.inc" --#include "save_fpu_regs_03.inc" --#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_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 4-byte vector size version. -- The "_4b" postfix was added for 4-byte version symbol. --*/ --#ifdef NDS32_SAVE_ALL_REGS --#if defined(NDS32_NESTED) -- .globl _nds32_i_sa_ns_4b -- .type _nds32_i_sa_ns_4b, @function --_nds32_i_sa_ns_4b: --#elif defined(NDS32_NESTED_READY) -- .globl _nds32_i_sa_nr_4b -- .type _nds32_i_sa_nr_4b, @function --_nds32_i_sa_nr_4b: --#else /* Not nested handler. */ -- .globl _nds32_i_sa_nn_4b -- .type _nds32_i_sa_nn_4b, @function --_nds32_i_sa_nn_4b: --#endif /* endif for Nest Type */ --#else /* not NDS32_SAVE_ALL_REGS */ --#if defined(NDS32_NESTED) -- .globl _nds32_i_ps_ns_4b -- .type _nds32_i_ps_ns_4b, @function --_nds32_i_ps_ns_4b: --#elif defined(NDS32_NESTED_READY) -- .globl _nds32_i_ps_nr_4b -- .type _nds32_i_ps_nr_4b, @function --_nds32_i_ps_nr_4b: --#else /* Not nested handler. */ -- .globl _nds32_i_ps_nn_4b -- .type _nds32_i_ps_nn_4b, @function --_nds32_i_ps_nn_4b: --#endif /* endif for Nest Type */ --#endif /* not NDS32_SAVE_ALL_REGS */ -- --/* -- This is 4-byte vector size version. -- The vector id was restored into $lp in vector by compiler. --*/ --#ifdef NDS32_SAVE_ALL_REGS -- SAVE_ALL_4B --#else -- SAVE_PARTIAL_4B --#endif -- /* 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 -- /* Restore used registers. */ --#ifdef NDS32_SAVE_ALL_REGS -- RESTORE_ALL --#else -- RESTORE_PARTIAL --#endif -- iret -- --#ifdef NDS32_SAVE_ALL_REGS --#if defined(NDS32_NESTED) -- .size _nds32_i_sa_ns_4b, .-_nds32_i_sa_ns_4b --#elif defined(NDS32_NESTED_READY) -- .size _nds32_i_sa_nr_4b, .-_nds32_i_sa_nr_4b --#else /* Not nested handler. */ -- .size _nds32_i_sa_nn_4b, .-_nds32_i_sa_nn_4b --#endif /* endif for Nest Type */ --#else /* not NDS32_SAVE_ALL_REGS */ --#if defined(NDS32_NESTED) -- .size _nds32_i_ps_ns_4b, .-_nds32_i_ps_ns_4b --#elif defined(NDS32_NESTED_READY) -- .size _nds32_i_ps_nr_4b, .-_nds32_i_ps_nr_4b --#else /* Not nested handler. */ -- .size _nds32_i_ps_nn_4b, .-_nds32_i_ps_nn_4b --#endif /* endif for Nest Type */ --#endif /* not NDS32_SAVE_ALL_REGS */ -diff --git a/libgcc/config/nds32/isr-library/reset.S b/libgcc/config/nds32/isr-library/reset.S -index 961d731..8b9ccf5 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/reset_4b.S b/libgcc/config/nds32/isr-library/reset_4b.S -deleted file mode 100644 -index 792e655..0000000 ---- a/libgcc/config/nds32/isr-library/reset_4b.S -+++ /dev/null -@@ -1,131 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .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_4b -- .type _nds32_reset_4b, @function --_nds32_reset_4b: --_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__ -- /* For 16-reg mode. */ -- smw.adm $r0, [$sp], $r10, #0x0 -- smw.adm $r15, [$sp], $r15, #0xf --#else -- /* For 32-reg mode. */ -- smw.adm $r0, [$sp], $r27, #0xf --#endif --#ifdef NDS32_EXT_IFC -- mfusr $r1, $IFC_LP -- 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. */ -- move $r0, $sp /* Init parameter. */ -- mfsr $r1, $ITYPE /* Check ITYPE for NMI or warm boot. */ -- andi $r1, $r1, #0xf -- addi $r1, $r1, #-1 -- beqz $r1, 2f /* Warm boot if true. */ -- l.w $r15, _nds32_nmih /* Load NMI handler. */ -- j 3f --2: -- l.w $r15, _nds32_wrh /* Load warm boot handler. */ --3: -- beqz $r15, 1f /* If no handler, do cold boot. */ -- jral $r15 /* Call handler. */ -- 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. */ -- mtusr $r1, $IFC_LP --#endif --#ifdef __NDS32_REDUCED_REGS__ -- /* For 16-reg mode. */ -- lmw.bim $r15, [$sp], $r15, #0xf -- lmw.bim $r0, [$sp], $r10, #0x0 --#else -- /* For 32-reg mode. */ -- lmw.bim $r0, [$sp], $r27, #0xf --#endif -- iret /* Resume operation. */ -- -- --1: /* Cold boot. */ -- /* With vector ID feature, set default vector size to 4B. */ -- /* 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 -- -- 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. */ -- srli $r0, $r0, 24 -- andi $r0, $r0, 0x1 -- beqz $r0, 4f /* Zero means HW does not support EX9. */ -- la $r0, _ITB_BASE_ /* Init $ITB. */ -- mtusr $r0, $ITB -- .no_ex9_end --4: --#endif -- la $r15, _nds32_init_mem /* Call DRAM init. _nds32_init_mem -- may written by C language. */ -- 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. */ --5: -- break #0x7fff -- .size _nds32_reset_4b, .-_nds32_reset_4b -diff --git a/libgcc/config/nds32/isr-library/restore_all.inc b/libgcc/config/nds32/isr-library/restore_all.inc -index c25b46e..96f87ec 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 0ffc980..a15024c 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 70d5421..c07d30e 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/vec_vid03_4b.S b/libgcc/config/nds32/isr-library/restore_usr_regs.inc -similarity index 72% -rename from libgcc/config/nds32/isr-library/vec_vid03_4b.S -rename to libgcc/config/nds32/isr-library/restore_usr_regs.inc -index cd30906..c8f6e4a 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid03_4b.S -+++ b/libgcc/config/nds32/isr-library/restore_usr_regs.inc -@@ -23,12 +23,20 @@ - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - . */ - -- .section .nds32_vector.03, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_03_4b -- .type _nds32_vector_03_4b, @function --_nds32_vector_03_4b: --1: -- j 1b -- .size _nds32_vector_03_4b, .-_nds32_vector_03_4b -+.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 20eb29d..c926664 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 ddb5e77..2d79d70 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 ee514c4..0c6d481 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/vec_vid00_4b.S b/libgcc/config/nds32/isr-library/save_usr_regs.inc -similarity index 61% -rename from libgcc/config/nds32/isr-library/vec_vid00_4b.S -rename to libgcc/config/nds32/isr-library/save_usr_regs.inc -index e1a37b4..b6807d7 100644 ---- a/libgcc/config/nds32/isr-library/vec_vid00_4b.S -+++ b/libgcc/config/nds32/isr-library/save_usr_regs.inc -@@ -23,12 +23,22 @@ - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - . */ - -- .section .nds32_vector.00, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_00_4b -- .type _nds32_vector_00_4b, @function --_nds32_vector_00_4b: --1: -- j 1b -- .size _nds32_vector_00_4b, .-_nds32_vector_00_4b -+.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 ccdbd19..f02e92c 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 ed5a88e..542fcf8 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_vid01_4b.S b/libgcc/config/nds32/isr-library/vec_vid01_4b.S -deleted file mode 100644 -index 239bd75..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid01_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.01, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_01_4b -- .type _nds32_vector_01_4b, @function --_nds32_vector_01_4b: --1: -- j 1b -- .size _nds32_vector_01_4b, .-_nds32_vector_01_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid02.S b/libgcc/config/nds32/isr-library/vec_vid02.S -index 1a95a57..72b8b56 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_vid02_4b.S b/libgcc/config/nds32/isr-library/vec_vid02_4b.S -deleted file mode 100644 -index c532e62..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid02_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.02, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_02_4b -- .type _nds32_vector_02_4b, @function --_nds32_vector_02_4b: --1: -- j 1b -- .size _nds32_vector_02_4b, .-_nds32_vector_02_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid03.S b/libgcc/config/nds32/isr-library/vec_vid03.S -index 9bc572a..b0f8a60 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 e8d4e10..d76ef73 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_vid04_4b.S b/libgcc/config/nds32/isr-library/vec_vid04_4b.S -deleted file mode 100644 -index 21fc77e..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid04_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.04, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_04_4b -- .type _nds32_vector_04_4b, @function --_nds32_vector_04_4b: --1: -- j 1b -- .size _nds32_vector_04_4b, .-_nds32_vector_04_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid05.S b/libgcc/config/nds32/isr-library/vec_vid05.S -index 1621a9d..ed5a5bb 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_vid05_4b.S b/libgcc/config/nds32/isr-library/vec_vid05_4b.S -deleted file mode 100644 -index b86fe19..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid05_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.05, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_05_4b -- .type _nds32_vector_05_4b, @function --_nds32_vector_05_4b: --1: -- j 1b -- .size _nds32_vector_05_4b, .-_nds32_vector_05_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid06.S b/libgcc/config/nds32/isr-library/vec_vid06.S -index 934f0b1..834c7de 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_vid06_4b.S b/libgcc/config/nds32/isr-library/vec_vid06_4b.S -deleted file mode 100644 -index 3624cfd..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid06_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.06, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_06_4b -- .type _nds32_vector_06_4b, @function --_nds32_vector_06_4b: --1: -- j 1b -- .size _nds32_vector_06_4b, .-_nds32_vector_06_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid07.S b/libgcc/config/nds32/isr-library/vec_vid07.S -index 0b0484d..cb3b33a 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_vid07_4b.S b/libgcc/config/nds32/isr-library/vec_vid07_4b.S -deleted file mode 100644 -index 997ca75..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid07_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.07, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_07_4b -- .type _nds32_vector_07_4b, @function --_nds32_vector_07_4b: --1: -- j 1b -- .size _nds32_vector_07_4b, .-_nds32_vector_07_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid08.S b/libgcc/config/nds32/isr-library/vec_vid08.S -index 2a30375..b4ae947 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_vid08_4b.S b/libgcc/config/nds32/isr-library/vec_vid08_4b.S -deleted file mode 100644 -index 83546d1..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid08_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.08, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_08_4b -- .type _nds32_vector_08_4b, @function --_nds32_vector_08_4b: --1: -- j 1b -- .size _nds32_vector_08_4b, .-_nds32_vector_08_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid09.S b/libgcc/config/nds32/isr-library/vec_vid09.S -index 9aeaf78..47fa5c1 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_vid09_4b.S b/libgcc/config/nds32/isr-library/vec_vid09_4b.S -deleted file mode 100644 -index 2d1944f..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid09_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.09, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_09_4b -- .type _nds32_vector_09_4b, @function --_nds32_vector_09_4b: --1: -- j 1b -- .size _nds32_vector_09_4b, .-_nds32_vector_09_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid10.S b/libgcc/config/nds32/isr-library/vec_vid10.S -index 411edd7..6bf2c7c 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_vid10_4b.S b/libgcc/config/nds32/isr-library/vec_vid10_4b.S -deleted file mode 100644 -index 04761ab..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid10_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.10, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_10_4b -- .type _nds32_vector_10_4b, @function --_nds32_vector_10_4b: --1: -- j 1b -- .size _nds32_vector_10_4b, .-_nds32_vector_10_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid11.S b/libgcc/config/nds32/isr-library/vec_vid11.S -index 8de45a4..86975ea 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_vid11_4b.S b/libgcc/config/nds32/isr-library/vec_vid11_4b.S -deleted file mode 100644 -index 328c1e6..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid11_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.11, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_11_4b -- .type _nds32_vector_11_4b, @function --_nds32_vector_11_4b: --1: -- j 1b -- .size _nds32_vector_11_4b, .-_nds32_vector_11_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid12.S b/libgcc/config/nds32/isr-library/vec_vid12.S -index ff5c6df..07cb7de 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_vid12_4b.S b/libgcc/config/nds32/isr-library/vec_vid12_4b.S -deleted file mode 100644 -index 52b7d23..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid12_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.12, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_12_4b -- .type _nds32_vector_12_4b, @function --_nds32_vector_12_4b: --1: -- j 1b -- .size _nds32_vector_12_4b, .-_nds32_vector_12_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid13.S b/libgcc/config/nds32/isr-library/vec_vid13.S -index 66014c3..5ac1a83 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_vid13_4b.S b/libgcc/config/nds32/isr-library/vec_vid13_4b.S -deleted file mode 100644 -index 59029ad..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid13_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.13, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_13_4b -- .type _nds32_vector_13_4b, @function --_nds32_vector_13_4b: --1: -- j 1b -- .size _nds32_vector_13_4b, .-_nds32_vector_13_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid14.S b/libgcc/config/nds32/isr-library/vec_vid14.S -index ca6f66f..5116f2f 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_vid14_4b.S b/libgcc/config/nds32/isr-library/vec_vid14_4b.S -deleted file mode 100644 -index 0d2afe4..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid14_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.14, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_14_4b -- .type _nds32_vector_14_4b, @function --_nds32_vector_14_4b: --1: -- j 1b -- .size _nds32_vector_14_4b, .-_nds32_vector_14_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid15.S b/libgcc/config/nds32/isr-library/vec_vid15.S -index c94b42a..03449c0 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_vid15_4b.S b/libgcc/config/nds32/isr-library/vec_vid15_4b.S -deleted file mode 100644 -index 60799d7..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid15_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.15, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_15_4b -- .type _nds32_vector_15_4b, @function --_nds32_vector_15_4b: --1: -- j 1b -- .size _nds32_vector_15_4b, .-_nds32_vector_15_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid16.S b/libgcc/config/nds32/isr-library/vec_vid16.S -index f19454d..b01d673 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_vid16_4b.S b/libgcc/config/nds32/isr-library/vec_vid16_4b.S -deleted file mode 100644 -index 6791204..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid16_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.16, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_16_4b -- .type _nds32_vector_16_4b, @function --_nds32_vector_16_4b: --1: -- j 1b -- .size _nds32_vector_16_4b, .-_nds32_vector_16_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid17.S b/libgcc/config/nds32/isr-library/vec_vid17.S -index 486a0aa..c6ed785 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_vid17_4b.S b/libgcc/config/nds32/isr-library/vec_vid17_4b.S -deleted file mode 100644 -index 04f4285..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid17_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.17, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_17_4b -- .type _nds32_vector_17_4b, @function --_nds32_vector_17_4b: --1: -- j 1b -- .size _nds32_vector_17_4b, .-_nds32_vector_17_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid18.S b/libgcc/config/nds32/isr-library/vec_vid18.S -index 137511f..e0e7b7e 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_vid18_4b.S b/libgcc/config/nds32/isr-library/vec_vid18_4b.S -deleted file mode 100644 -index 4d80192..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid18_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.18, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_18_4b -- .type _nds32_vector_18_4b, @function --_nds32_vector_18_4b: --1: -- j 1b -- .size _nds32_vector_18_4b, .-_nds32_vector_18_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid19.S b/libgcc/config/nds32/isr-library/vec_vid19.S -index 791e135..ef7075f 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_vid19_4b.S b/libgcc/config/nds32/isr-library/vec_vid19_4b.S -deleted file mode 100644 -index 87d4c7c..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid19_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.19, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_19_4b -- .type _nds32_vector_19_4b, @function --_nds32_vector_19_4b: --1: -- j 1b -- .size _nds32_vector_19_4b, .-_nds32_vector_19_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid20.S b/libgcc/config/nds32/isr-library/vec_vid20.S -index e7ab0e3..99bcf01 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_vid20_4b.S b/libgcc/config/nds32/isr-library/vec_vid20_4b.S -deleted file mode 100644 -index 308385a..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid20_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.20, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_20_4b -- .type _nds32_vector_20_4b, @function --_nds32_vector_20_4b: --1: -- j 1b -- .size _nds32_vector_20_4b, .-_nds32_vector_20_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid21.S b/libgcc/config/nds32/isr-library/vec_vid21.S -index 315ae56..8c66bef 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_vid21_4b.S b/libgcc/config/nds32/isr-library/vec_vid21_4b.S -deleted file mode 100644 -index 16cf02a..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid21_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.21, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_21_4b -- .type _nds32_vector_21_4b, @function --_nds32_vector_21_4b: --1: -- j 1b -- .size _nds32_vector_21_4b, .-_nds32_vector_21_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid22.S b/libgcc/config/nds32/isr-library/vec_vid22.S -index 6f9de85..5c442ce 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_vid22_4b.S b/libgcc/config/nds32/isr-library/vec_vid22_4b.S -deleted file mode 100644 -index 587ee7f..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid22_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.22, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_22_4b -- .type _nds32_vector_22_4b, @function --_nds32_vector_22_4b: --1: -- j 1b -- .size _nds32_vector_22_4b, .-_nds32_vector_22_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid23.S b/libgcc/config/nds32/isr-library/vec_vid23.S -index 956b585..c5d73df 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_vid23_4b.S b/libgcc/config/nds32/isr-library/vec_vid23_4b.S -deleted file mode 100644 -index 5e4b643..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid23_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.23, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_23_4b -- .type _nds32_vector_23_4b, @function --_nds32_vector_23_4b: --1: -- j 1b -- .size _nds32_vector_23_4b, .-_nds32_vector_23_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid24.S b/libgcc/config/nds32/isr-library/vec_vid24.S -index 57086e9..fe7dada 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_vid24_4b.S b/libgcc/config/nds32/isr-library/vec_vid24_4b.S -deleted file mode 100644 -index 43495f9..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid24_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.24, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_24_4b -- .type _nds32_vector_24_4b, @function --_nds32_vector_24_4b: --1: -- j 1b -- .size _nds32_vector_24_4b, .-_nds32_vector_24_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid25.S b/libgcc/config/nds32/isr-library/vec_vid25.S -index 61fa526..ada24e4 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_vid25_4b.S b/libgcc/config/nds32/isr-library/vec_vid25_4b.S -deleted file mode 100644 -index 1ce6cf3..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid25_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.25, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_25_4b -- .type _nds32_vector_25_4b, @function --_nds32_vector_25_4b: --1: -- j 1b -- .size _nds32_vector_25_4b, .-_nds32_vector_25_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid26.S b/libgcc/config/nds32/isr-library/vec_vid26.S -index 3d9191d..1f97945 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_vid26_4b.S b/libgcc/config/nds32/isr-library/vec_vid26_4b.S -deleted file mode 100644 -index 5803247..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid26_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.26, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_26_4b -- .type _nds32_vector_26_4b, @function --_nds32_vector_26_4b: --1: -- j 1b -- .size _nds32_vector_26_4b, .-_nds32_vector_26_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid27.S b/libgcc/config/nds32/isr-library/vec_vid27.S -index ff12cfb..f440a8b 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_vid27_4b.S b/libgcc/config/nds32/isr-library/vec_vid27_4b.S -deleted file mode 100644 -index d61e3f9..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid27_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.27, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_27_4b -- .type _nds32_vector_27_4b, @function --_nds32_vector_27_4b: --1: -- j 1b -- .size _nds32_vector_27_4b, .-_nds32_vector_27_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid28.S b/libgcc/config/nds32/isr-library/vec_vid28.S -index 6b7610e..e1621c7 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_vid28_4b.S b/libgcc/config/nds32/isr-library/vec_vid28_4b.S -deleted file mode 100644 -index a39d015..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid28_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.28, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_28_4b -- .type _nds32_vector_28_4b, @function --_nds32_vector_28_4b: --1: -- j 1b -- .size _nds32_vector_28_4b, .-_nds32_vector_28_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid29.S b/libgcc/config/nds32/isr-library/vec_vid29.S -index b995841..4fa29c1 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_vid29_4b.S b/libgcc/config/nds32/isr-library/vec_vid29_4b.S -deleted file mode 100644 -index 803f323..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid29_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.29, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_29_4b -- .type _nds32_vector_29_4b, @function --_nds32_vector_29_4b: --1: -- j 1b -- .size _nds32_vector_29_4b, .-_nds32_vector_29_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid30.S b/libgcc/config/nds32/isr-library/vec_vid30.S -index 57d1507..214e67b 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_vid30_4b.S b/libgcc/config/nds32/isr-library/vec_vid30_4b.S -deleted file mode 100644 -index a2a1e3e..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid30_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.30, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_30_4b -- .type _nds32_vector_30_4b, @function --_nds32_vector_30_4b: --1: -- j 1b -- .size _nds32_vector_30_4b, .-_nds32_vector_30_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid31.S b/libgcc/config/nds32/isr-library/vec_vid31.S -index f9aee4e..b758b8c 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_vid31_4b.S b/libgcc/config/nds32/isr-library/vec_vid31_4b.S -deleted file mode 100644 -index 989645f..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid31_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.31, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_31_4b -- .type _nds32_vector_31_4b, @function --_nds32_vector_31_4b: --1: -- j 1b -- .size _nds32_vector_31_4b, .-_nds32_vector_31_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid32.S b/libgcc/config/nds32/isr-library/vec_vid32.S -index fc26cad..58234d5 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_vid32_4b.S b/libgcc/config/nds32/isr-library/vec_vid32_4b.S -deleted file mode 100644 -index 1ac7e31..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid32_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.32, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_32_4b -- .type _nds32_vector_32_4b, @function --_nds32_vector_32_4b: --1: -- j 1b -- .size _nds32_vector_32_4b, .-_nds32_vector_32_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid33.S b/libgcc/config/nds32/isr-library/vec_vid33.S -index dd655e6..d920352 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_vid33_4b.S b/libgcc/config/nds32/isr-library/vec_vid33_4b.S -deleted file mode 100644 -index 3c99412..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid33_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.33, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_33_4b -- .type _nds32_vector_33_4b, @function --_nds32_vector_33_4b: --1: -- j 1b -- .size _nds32_vector_33_4b, .-_nds32_vector_33_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid34.S b/libgcc/config/nds32/isr-library/vec_vid34.S -index a6b8517..01999b4 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_vid34_4b.S b/libgcc/config/nds32/isr-library/vec_vid34_4b.S -deleted file mode 100644 -index 77c07b9..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid34_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.34, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_34_4b -- .type _nds32_vector_34_4b, @function --_nds32_vector_34_4b: --1: -- j 1b -- .size _nds32_vector_34_4b, .-_nds32_vector_34_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid35.S b/libgcc/config/nds32/isr-library/vec_vid35.S -index 65ceeab..7ab0536 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_vid35_4b.S b/libgcc/config/nds32/isr-library/vec_vid35_4b.S -deleted file mode 100644 -index 432873a..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid35_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.35, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_35_4b -- .type _nds32_vector_35_4b, @function --_nds32_vector_35_4b: --1: -- j 1b -- .size _nds32_vector_35_4b, .-_nds32_vector_35_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid36.S b/libgcc/config/nds32/isr-library/vec_vid36.S -index 688dbb9..5da079d 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_vid36_4b.S b/libgcc/config/nds32/isr-library/vec_vid36_4b.S -deleted file mode 100644 -index dadd381..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid36_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.36, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_36_4b -- .type _nds32_vector_36_4b, @function --_nds32_vector_36_4b: --1: -- j 1b -- .size _nds32_vector_36_4b, .-_nds32_vector_36_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid37.S b/libgcc/config/nds32/isr-library/vec_vid37.S -index 712bbe8..704d6b8 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_vid37_4b.S b/libgcc/config/nds32/isr-library/vec_vid37_4b.S -deleted file mode 100644 -index ec845e1..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid37_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.37, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_37_4b -- .type _nds32_vector_37_4b, @function --_nds32_vector_37_4b: --1: -- j 1b -- .size _nds32_vector_37_4b, .-_nds32_vector_37_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid38.S b/libgcc/config/nds32/isr-library/vec_vid38.S -index b6e4979..fdfc4a9 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_vid38_4b.S b/libgcc/config/nds32/isr-library/vec_vid38_4b.S -deleted file mode 100644 -index 84919ed..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid38_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.38, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_38_4b -- .type _nds32_vector_38_4b, @function --_nds32_vector_38_4b: --1: -- j 1b -- .size _nds32_vector_38_4b, .-_nds32_vector_38_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid39.S b/libgcc/config/nds32/isr-library/vec_vid39.S -index 2dee269..00dd245 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_vid39_4b.S b/libgcc/config/nds32/isr-library/vec_vid39_4b.S -deleted file mode 100644 -index 8f2f634..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid39_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.39, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_39_4b -- .type _nds32_vector_39_4b, @function --_nds32_vector_39_4b: --1: -- j 1b -- .size _nds32_vector_39_4b, .-_nds32_vector_39_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid40.S b/libgcc/config/nds32/isr-library/vec_vid40.S -index fe7508c..82b579f 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_vid40_4b.S b/libgcc/config/nds32/isr-library/vec_vid40_4b.S -deleted file mode 100644 -index 0aab8f4..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid40_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.40, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_40_4b -- .type _nds32_vector_40_4b, @function --_nds32_vector_40_4b: --1: -- j 1b -- .size _nds32_vector_40_4b, .-_nds32_vector_40_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid41.S b/libgcc/config/nds32/isr-library/vec_vid41.S -index 711fcd5..721c735 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_vid41_4b.S b/libgcc/config/nds32/isr-library/vec_vid41_4b.S -deleted file mode 100644 -index e8a8527..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid41_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.41, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_41_4b -- .type _nds32_vector_41_4b, @function --_nds32_vector_41_4b: --1: -- j 1b -- .size _nds32_vector_41_4b, .-_nds32_vector_41_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid42.S b/libgcc/config/nds32/isr-library/vec_vid42.S -index 0c6a849..307b51d 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_vid42_4b.S b/libgcc/config/nds32/isr-library/vec_vid42_4b.S -deleted file mode 100644 -index cfe184c..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid42_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.42, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_42_4b -- .type _nds32_vector_42_4b, @function --_nds32_vector_42_4b: --1: -- j 1b -- .size _nds32_vector_42_4b, .-_nds32_vector_42_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid43.S b/libgcc/config/nds32/isr-library/vec_vid43.S -index 2b4681a..c0ce02d 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_vid43_4b.S b/libgcc/config/nds32/isr-library/vec_vid43_4b.S -deleted file mode 100644 -index 3edd606..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid43_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.43, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_43_4b -- .type _nds32_vector_43_4b, @function --_nds32_vector_43_4b: --1: -- j 1b -- .size _nds32_vector_43_4b, .-_nds32_vector_43_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid44.S b/libgcc/config/nds32/isr-library/vec_vid44.S -index 232ef41..c2a384c 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_vid44_4b.S b/libgcc/config/nds32/isr-library/vec_vid44_4b.S -deleted file mode 100644 -index 0f2b8a3..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid44_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.44, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_44_4b -- .type _nds32_vector_44_4b, @function --_nds32_vector_44_4b: --1: -- j 1b -- .size _nds32_vector_44_4b, .-_nds32_vector_44_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid45.S b/libgcc/config/nds32/isr-library/vec_vid45.S -index e2f9863..e13c52b 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_vid45_4b.S b/libgcc/config/nds32/isr-library/vec_vid45_4b.S -deleted file mode 100644 -index 7358ec1..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid45_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.45, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_45_4b -- .type _nds32_vector_45_4b, @function --_nds32_vector_45_4b: --1: -- j 1b -- .size _nds32_vector_45_4b, .-_nds32_vector_45_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid46.S b/libgcc/config/nds32/isr-library/vec_vid46.S -index f3b93aa..71bfb53 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_vid46_4b.S b/libgcc/config/nds32/isr-library/vec_vid46_4b.S -deleted file mode 100644 -index 2782e86..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid46_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.46, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_46_4b -- .type _nds32_vector_46_4b, @function --_nds32_vector_46_4b: --1: -- j 1b -- .size _nds32_vector_46_4b, .-_nds32_vector_46_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid47.S b/libgcc/config/nds32/isr-library/vec_vid47.S -index 130c8d7..d1f2131 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_vid47_4b.S b/libgcc/config/nds32/isr-library/vec_vid47_4b.S -deleted file mode 100644 -index f237577..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid47_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.47, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_47_4b -- .type _nds32_vector_47_4b, @function --_nds32_vector_47_4b: --1: -- j 1b -- .size _nds32_vector_47_4b, .-_nds32_vector_47_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid48.S b/libgcc/config/nds32/isr-library/vec_vid48.S -index f3bca05..4ba5eb9 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_vid48_4b.S b/libgcc/config/nds32/isr-library/vec_vid48_4b.S -deleted file mode 100644 -index 3e35f68..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid48_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.48, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_48_4b -- .type _nds32_vector_48_4b, @function --_nds32_vector_48_4b: --1: -- j 1b -- .size _nds32_vector_48_4b, .-_nds32_vector_48_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid49.S b/libgcc/config/nds32/isr-library/vec_vid49.S -index 0b32691..dd3d35e 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_vid49_4b.S b/libgcc/config/nds32/isr-library/vec_vid49_4b.S -deleted file mode 100644 -index a510bbb..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid49_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.49, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_49_4b -- .type _nds32_vector_49_4b, @function --_nds32_vector_49_4b: --1: -- j 1b -- .size _nds32_vector_49_4b, .-_nds32_vector_49_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid50.S b/libgcc/config/nds32/isr-library/vec_vid50.S -index 48334feb..8f801ec 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_vid50_4b.S b/libgcc/config/nds32/isr-library/vec_vid50_4b.S -deleted file mode 100644 -index 1f42b73..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid50_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.50, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_50_4b -- .type _nds32_vector_50_4b, @function --_nds32_vector_50_4b: --1: -- j 1b -- .size _nds32_vector_50_4b, .-_nds32_vector_50_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid51.S b/libgcc/config/nds32/isr-library/vec_vid51.S -index 4c27f27..445abf9 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_vid51_4b.S b/libgcc/config/nds32/isr-library/vec_vid51_4b.S -deleted file mode 100644 -index 7bb8abe..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid51_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.51, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_51_4b -- .type _nds32_vector_51_4b, @function --_nds32_vector_51_4b: --1: -- j 1b -- .size _nds32_vector_51_4b, .-_nds32_vector_51_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid52.S b/libgcc/config/nds32/isr-library/vec_vid52.S -index 4c44811..7283975 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_vid52_4b.S b/libgcc/config/nds32/isr-library/vec_vid52_4b.S -deleted file mode 100644 -index 4cb89f6..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid52_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.52, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_52_4b -- .type _nds32_vector_52_4b, @function --_nds32_vector_52_4b: --1: -- j 1b -- .size _nds32_vector_52_4b, .-_nds32_vector_52_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid53.S b/libgcc/config/nds32/isr-library/vec_vid53.S -index 2882583..299c645 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_vid53_4b.S b/libgcc/config/nds32/isr-library/vec_vid53_4b.S -deleted file mode 100644 -index 9abc839..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid53_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.53, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_53_4b -- .type _nds32_vector_53_4b, @function --_nds32_vector_53_4b: --1: -- j 1b -- .size _nds32_vector_53_4b, .-_nds32_vector_53_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid54.S b/libgcc/config/nds32/isr-library/vec_vid54.S -index a014c72..ae99390 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_vid54_4b.S b/libgcc/config/nds32/isr-library/vec_vid54_4b.S -deleted file mode 100644 -index f736ba8..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid54_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.54, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_54_4b -- .type _nds32_vector_54_4b, @function --_nds32_vector_54_4b: --1: -- j 1b -- .size _nds32_vector_54_4b, .-_nds32_vector_54_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid55.S b/libgcc/config/nds32/isr-library/vec_vid55.S -index 44d820c..e75d24a 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_vid55_4b.S b/libgcc/config/nds32/isr-library/vec_vid55_4b.S -deleted file mode 100644 -index d09c665..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid55_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.55, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_55_4b -- .type _nds32_vector_55_4b, @function --_nds32_vector_55_4b: --1: -- j 1b -- .size _nds32_vector_55_4b, .-_nds32_vector_55_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid56.S b/libgcc/config/nds32/isr-library/vec_vid56.S -index d5cb362..cc4904e 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_vid56_4b.S b/libgcc/config/nds32/isr-library/vec_vid56_4b.S -deleted file mode 100644 -index 86b4103..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid56_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.56, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_56_4b -- .type _nds32_vector_56_4b, @function --_nds32_vector_56_4b: --1: -- j 1b -- .size _nds32_vector_56_4b, .-_nds32_vector_56_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid57.S b/libgcc/config/nds32/isr-library/vec_vid57.S -index 5fb3ce9..a17ed45 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_vid57_4b.S b/libgcc/config/nds32/isr-library/vec_vid57_4b.S -deleted file mode 100644 -index 45c5d29..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid57_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.57, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_57_4b -- .type _nds32_vector_57_4b, @function --_nds32_vector_57_4b: --1: -- j 1b -- .size _nds32_vector_57_4b, .-_nds32_vector_57_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid58.S b/libgcc/config/nds32/isr-library/vec_vid58.S -index d420d68..629bf1a 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_vid58_4b.S b/libgcc/config/nds32/isr-library/vec_vid58_4b.S -deleted file mode 100644 -index 812470c..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid58_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.58, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_58_4b -- .type _nds32_vector_58_4b, @function --_nds32_vector_58_4b: --1: -- j 1b -- .size _nds32_vector_58_4b, .-_nds32_vector_58_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid59.S b/libgcc/config/nds32/isr-library/vec_vid59.S -index 78a1885..540e02e 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_vid59_4b.S b/libgcc/config/nds32/isr-library/vec_vid59_4b.S -deleted file mode 100644 -index fa3a467..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid59_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.59, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_59_4b -- .type _nds32_vector_59_4b, @function --_nds32_vector_59_4b: --1: -- j 1b -- .size _nds32_vector_59_4b, .-_nds32_vector_59_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid60.S b/libgcc/config/nds32/isr-library/vec_vid60.S -index a6f704d..8658249 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_vid60_4b.S b/libgcc/config/nds32/isr-library/vec_vid60_4b.S -deleted file mode 100644 -index 505da2a..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid60_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.60, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_60_4b -- .type _nds32_vector_60_4b, @function --_nds32_vector_60_4b: --1: -- j 1b -- .size _nds32_vector_60_4b, .-_nds32_vector_60_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid61.S b/libgcc/config/nds32/isr-library/vec_vid61.S -index 4e79bde..376acb9 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_vid61_4b.S b/libgcc/config/nds32/isr-library/vec_vid61_4b.S -deleted file mode 100644 -index 9a0cce5..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid61_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.61, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_61_4b -- .type _nds32_vector_61_4b, @function --_nds32_vector_61_4b: --1: -- j 1b -- .size _nds32_vector_61_4b, .-_nds32_vector_61_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid62.S b/libgcc/config/nds32/isr-library/vec_vid62.S -index 5eef0a6..5ab06a8 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_vid62_4b.S b/libgcc/config/nds32/isr-library/vec_vid62_4b.S -deleted file mode 100644 -index da8ba28..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid62_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.62, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_62_4b -- .type _nds32_vector_62_4b, @function --_nds32_vector_62_4b: --1: -- j 1b -- .size _nds32_vector_62_4b, .-_nds32_vector_62_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid63.S b/libgcc/config/nds32/isr-library/vec_vid63.S -index 0a8c0ad..6646bcc 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_vid63_4b.S b/libgcc/config/nds32/isr-library/vec_vid63_4b.S -deleted file mode 100644 -index 8f1045e..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid63_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.63, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_63_4b -- .type _nds32_vector_63_4b, @function --_nds32_vector_63_4b: --1: -- j 1b -- .size _nds32_vector_63_4b, .-_nds32_vector_63_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid64.S b/libgcc/config/nds32/isr-library/vec_vid64.S -index b3f034b..f892aec 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_vid64_4b.S b/libgcc/config/nds32/isr-library/vec_vid64_4b.S -deleted file mode 100644 -index 81d9679..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid64_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.64, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_64_4b -- .type _nds32_vector_64_4b, @function --_nds32_vector_64_4b: --1: -- j 1b -- .size _nds32_vector_64_4b, .-_nds32_vector_64_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid65.S b/libgcc/config/nds32/isr-library/vec_vid65.S -index 72db454..03f79a5 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_vid65_4b.S b/libgcc/config/nds32/isr-library/vec_vid65_4b.S -deleted file mode 100644 -index aa9ad2b..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid65_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.65, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_65_4b -- .type _nds32_vector_65_4b, @function --_nds32_vector_65_4b: --1: -- j 1b -- .size _nds32_vector_65_4b, .-_nds32_vector_65_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid66.S b/libgcc/config/nds32/isr-library/vec_vid66.S -index 75469e7..ff805bd 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_vid66_4b.S b/libgcc/config/nds32/isr-library/vec_vid66_4b.S -deleted file mode 100644 -index 9830fe2..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid66_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.66, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_66_4b -- .type _nds32_vector_66_4b, @function --_nds32_vector_66_4b: --1: -- j 1b -- .size _nds32_vector_66_4b, .-_nds32_vector_66_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid67.S b/libgcc/config/nds32/isr-library/vec_vid67.S -index 4b076cd..f592aba 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_vid67_4b.S b/libgcc/config/nds32/isr-library/vec_vid67_4b.S -deleted file mode 100644 -index c7e31dd..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid67_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.67, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_67_4b -- .type _nds32_vector_67_4b, @function --_nds32_vector_67_4b: --1: -- j 1b -- .size _nds32_vector_67_4b, .-_nds32_vector_67_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid68.S b/libgcc/config/nds32/isr-library/vec_vid68.S -index 7df1cdd..ee2702a 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_vid68_4b.S b/libgcc/config/nds32/isr-library/vec_vid68_4b.S -deleted file mode 100644 -index 0d6fcb5..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid68_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.68, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_68_4b -- .type _nds32_vector_68_4b, @function --_nds32_vector_68_4b: --1: -- j 1b -- .size _nds32_vector_68_4b, .-_nds32_vector_68_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid69.S b/libgcc/config/nds32/isr-library/vec_vid69.S -index e30e5bf..c152015 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_vid69_4b.S b/libgcc/config/nds32/isr-library/vec_vid69_4b.S -deleted file mode 100644 -index 3508162..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid69_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.69, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_69_4b -- .type _nds32_vector_69_4b, @function --_nds32_vector_69_4b: --1: -- j 1b -- .size _nds32_vector_69_4b, .-_nds32_vector_69_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid70.S b/libgcc/config/nds32/isr-library/vec_vid70.S -index d436ac5..a3578d6 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_vid70_4b.S b/libgcc/config/nds32/isr-library/vec_vid70_4b.S -deleted file mode 100644 -index f3f0dd6..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid70_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.70, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_70_4b -- .type _nds32_vector_70_4b, @function --_nds32_vector_70_4b: --1: -- j 1b -- .size _nds32_vector_70_4b, .-_nds32_vector_70_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid71.S b/libgcc/config/nds32/isr-library/vec_vid71.S -index d7d7ab3..6790888 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_vid71_4b.S b/libgcc/config/nds32/isr-library/vec_vid71_4b.S -deleted file mode 100644 -index 505c79e..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid71_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.71, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_71_4b -- .type _nds32_vector_71_4b, @function --_nds32_vector_71_4b: --1: -- j 1b -- .size _nds32_vector_71_4b, .-_nds32_vector_71_4b -diff --git a/libgcc/config/nds32/isr-library/vec_vid72.S b/libgcc/config/nds32/isr-library/vec_vid72.S -index 08652d2..32984a0 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/isr-library/vec_vid72_4b.S b/libgcc/config/nds32/isr-library/vec_vid72_4b.S -deleted file mode 100644 -index 1083c03..0000000 ---- a/libgcc/config/nds32/isr-library/vec_vid72_4b.S -+++ /dev/null -@@ -1,34 +0,0 @@ --/* c-isr library stuff of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .nds32_vector.72, "ax" -- .vec_size 4 -- .align 2 -- .weak _nds32_vector_72_4b -- .type _nds32_vector_72_4b, @function --_nds32_vector_72_4b: --1: -- j 1b -- .size _nds32_vector_72_4b, .-_nds32_vector_72_4b -diff --git a/libgcc/config/nds32/lib1asmsrc-mculib.S b/libgcc/config/nds32/lib1asmsrc-mculib.S -deleted file mode 100644 -index bdbcd74..0000000 ---- a/libgcc/config/nds32/lib1asmsrc-mculib.S -+++ /dev/null -@@ -1,5213 +0,0 @@ --/* mculib libgcc routines of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- -- .section .mdebug.abi_nds32 -- .previous -- -- --/* ------------------------------------------- */ --/* FPBIT floating point operations for libgcc */ --/* ------------------------------------------- */ -- --#ifdef L_addsub_sf -- -- .text -- .align 2 -- .global __subsf3 -- .type __subsf3, @function --__subsf3: -- push $lp -- pushm $r6, $r9 -- -- move $r2, #0x80000000 -- xor $r1, $r1, $r2 -- -- j .Lsfpadd -- -- .global __addsf3 -- .type __addsf3, @function --__addsf3: -- push $lp -- pushm $r6, $r9 --.Lsfpadd: -- srli $r5, $r0, #23 -- andi $r5, $r5, #0xff -- srli $r7, $r1, #23 -- andi $r7, $r7, #0xff -- move $r3, #0x80000000 -- slli $r4, $r0, #8 -- or $r4, $r4, $r3 -- slli $r6, $r1, #8 -- or $r6, $r6, $r3 -- -- addi $r9, $r5, #-1 -- slti $r15, $r9, #0xfe -- beqzs8 .LEspecA -- --.LElab1: -- addi $r9, $r7, #-1 -- slti $r15, $r9, #0xfe -- beqzs8 .LEspecB -- --.LElab2: -- sub $r8, $r5, $r7 -- sltsi $r15, $r8, #0 -- bnezs8 .Li1 -- sltsi $r15, $r8, #0x20 -- bnezs8 .Li2 -- move $r6, #2 -- j .Le1 --.Li2: -- move $r2, $r6 -- srl $r6, $r6, $r8 -- sll $r9, $r6, $r8 -- beq $r9, $r2, .Le1 -- ori $r6, $r6, #2 -- j .Le1 --.Li1: -- move $r5, $r7 -- subri $r8, $r8, #0 -- sltsi $r15, $r8, #0x20 -- bnezs8 .Li4 -- move $r4, #2 -- j .Le1 --.Li4: -- move $r2, $r4 -- srl $r4, $r4, $r8 -- sll $r9, $r4, $r8 -- beq $r9, $r2, .Le1 -- ori $r4, $r4, #2 -- --.Le1: -- and $r8, $r0, $r3 -- xor $r9, $r8, $r1 -- sltsi $r15, $r9, #0 -- bnezs8 .LEsub1 -- -- #ADD($r4, $r6) -- add $r4, $r4, $r6 -- slt $r15, $r4, $r6 -- beqzs8 .LEres -- andi $r9, $r4, #1 -- beqz $r9, .Li7 -- ori $r4, $r4, #2 --.Li7: -- srli $r4, $r4, #1 -- addi $r5, $r5, #1 -- subri $r15, $r5, #0xff -- bnezs8 .LEres -- move $r4, #0 -- j .LEres -- --.LEsub1: -- #SUB($r4, $r6) -- move $r15, $r4 -- sub $r4, $r4, $r6 -- slt $r15, $r15, $r4 -- beqzs8 .Li9 -- subri $r4, $r4, #0 -- xor $r8, $r8, $r3 -- j .Le9 --.Li9: -- beqz $r4, .LEzer --.Le9: --#ifdef __NDS32_PERF_EXT__ -- clz $r2, $r4 --#else -- pushm $r0, $r1 -- pushm $r3, $r5 -- move $r0, $r4 -- bal __clzsi2 -- move $r2, $r0 -- popm $r3, $r5 -- popm $r0, $r1 --#endif -- sub $r5, $r5, $r2 -- sll $r4, $r4, $r2 -- --.LEres: -- blez $r5, .LEund -- --.LElab12: -- #ADD($r4, $0x80) -- move $r15, #0x80 -- add $r4, $r4, $r15 -- slt $r15, $r4, $r15 -- -- #ADDC($r5, $0x0) -- add $r5, $r5, $r15 -- srli $r9, $r4, #8 -- andi $r9, $r9, #1 -- sub $r4, $r4, $r9 -- slli $r4, $r4, #1 -- srli $r4, $r4, #9 -- slli $r9, $r5, #23 -- or $r4, $r4, $r9 -- or $r0, $r4, $r8 -- --.LE999: -- popm $r6, $r9 -- pop $lp -- ret5 $lp -- --.LEund: -- subri $r2, $r5, #1 -- slti $r15, $r2, #0x20 -- beqzs8 .LEzer -- move $r9, #0x80000000 -- or $r4, $r4, $r9 -- subri $r9, $r2, #0x20 -- sll $r5, $r4, $r9 -- srl $r4, $r4, $r2 -- beqz $r5, .Li10 -- ori $r4, $r4, #1 --.Li10: -- move $r5, #0 -- addi $r9, $r4, #0x80 -- sltsi $r15, $r9, #0 -- beqzs8 .LElab12 -- move $r5, #1 -- j .LElab12 -- --.LEspecA: -- bnez $r5, .Li12 -- add $r4, $r4, $r4 -- beqz $r4, .Li13 --#ifdef __NDS32_PERF_EXT__ -- clz $r8, $r4 --#else -- pushm $r0, $r5 -- move $r0, $r4 -- bal __clzsi2 -- move $r8, $r0 -- popm $r0, $r5 --#endif -- sub $r5, $r5, $r8 -- sll $r4, $r4, $r8 -- j .LElab1 --.Li13: -- subri $r15, $r7, #0xff -- beqzs8 .LEspecB -- move $r9, #0x80000000 -- bne $r1, $r9, .LEretB --.Li12: -- add $r9, $r4, $r4 -- bnez $r9, .LEnan -- subri $r15, $r7, #0xff -- bnezs8 .LEretA -- xor $r9, $r0, $r1 -- sltsi $r15, $r9, #0 -- bnezs8 .LEnan -- j .LEretB -- --.LEspecB: -- bnez $r7, .Li15 -- add $r6, $r6, $r6 -- beqz $r6, .LEretA --#ifdef __NDS32_PERF_EXT__ -- clz $r8, $r6 --#else -- pushm $r0, $r5 -- move $r0, $r6 -- bal __clzsi2 -- move $r8, $r0 -- popm $r0, $r5 --#endif -- sub $r7, $r7, $r8 -- sll $r6, $r6, $r8 -- j .LElab2 --.Li15: -- add $r9, $r6, $r6 -- bnez $r9, .LEnan -- --.LEretB: -- move $r0, $r1 -- j .LE999 -- --.LEretA: -- j .LE999 -- --.LEzer: -- move $r0, #0 -- j .LE999 -- --.LEnan: -- move $r0, #0xffc00000 -- j .LE999 -- .size __subsf3, .-__subsf3 -- .size __addsf3, .-__addsf3 --#endif /* L_addsub_sf */ -- -- -- --#ifdef L_sf_to_si -- -- .text -- .align 2 -- .global __fixsfsi -- .type __fixsfsi, @function --__fixsfsi: -- push $lp -- -- slli $r1, $r0, #8 -- move $r3, #0x80000000 -- or $r1, $r1, $r3 -- srli $r3, $r0, #23 -- andi $r3, $r3, #0xff -- subri $r2, $r3, #0x9e -- blez $r2, .LJspec -- sltsi $r15, $r2, #0x20 -- bnezs8 .Li42 -- move $r0, #0 -- j .LJ999 --.Li42: -- srl $r1, $r1, $r2 -- sltsi $r15, $r0, #0 -- beqzs8 .Li43 -- subri $r1, $r1, #0 --.Li43: -- move $r0, $r1 -- --.LJ999: -- pop $lp -- ret5 $lp -- --.LJspec: -- move $r3, #0x7f800000 -- slt $r15, $r3, $r0 -- beqzs8 .Li44 -- move $r0, #0x80000000 -- j .LJ999 --.Li44: -- move $r0, #0x7fffffff -- j .LJ999 -- .size __fixsfsi, .-__fixsfsi --#endif /* L_sf_to_si */ -- -- -- --#ifdef L_divsi3 -- -- .text -- .align 2 -- .globl __divsi3 -- .type __divsi3, @function --__divsi3: -- ! --------------------------------------------------------------------- -- ! neg = 0; -- ! if (a < 0) -- ! { a = -a; -- ! neg = !neg; -- ! } -- ! --------------------------------------------------------------------- -- sltsi $r5, $r0, 0 ! $r5 <- neg = (a < 0) ? 1 : 0 -- subri $r4, $r0, 0 ! $r4 <- a = -a -- cmovn $r0, $r4, $r5 ! $r0 <- a = neg ? -a : a --.L2: -- ! --------------------------------------------------------------------- -- ! if (b < 0) -- ! --------------------------------------------------------------------- -- bgez $r1, .L3 ! if b >= 0, skip -- ! --------------------------------------------------------------------- -- ! { b=-b; -- ! neg=!neg; -- ! } -- ! --------------------------------------------------------------------- -- subri $r1, $r1, 0 ! $r1 <- b = -b -- subri $r5, $r5, 1 ! $r5 <- neg = !neg --.L3: -- ! --------------------------------------------------------------------- -- !!res = udivmodsi4 (a, b, 1); -- ! res = 0; -- ! if (den != 0) -- ! --------------------------------------------------------------------- -- movi $r2, 0 ! $r2 <- res = 0 -- beqz $r1, .L1 ! if den == 0, skip -- ! --------------------------------------------------------------------- -- ! bit = 1; -- ! --------------------------------------------------------------------- -- movi $r4, 1 ! $r4 <- bit = 1 --#ifndef __OPTIMIZE_SIZE__ --.L6: --#endif -- ! --------------------------------------------------------------------- -- ! while (den < num && bit && !(den & (1L << 31))) -- ! --------------------------------------------------------------------- -- slt $ta, $r1, $r0 ! $ta <- den < num ? -- beqz $ta, .L5 ! if no, skip -- ! --------------------------------------------------------------------- -- ! { den << = 1; -- ! bit << = 1; -- ! } -- ! --------------------------------------------------------------------- --#if defined (__OPTIMIZE_SIZE__) && !defined (__NDS32_ISA_V3M__) -- clz $r3, $r1 ! $r3 <- leading zero count for den -- clz $ta, $r0 ! $ta <- leading zero count for num -- sub $r3, $r3, $ta ! $r3 <- number of bits to shift -- sll $r1, $r1, $r3 ! $r1 <- den -- sll $r4, $r4, $r3 ! $r2 <- bit --#else -- slli $r1, $r1, 1 ! $r1 <- den << = 1 -- slli $r4, $r4, 1 ! $r4 <- bit << = 1 -- b .L6 ! continue loop --#endif --.L5: -- ! --------------------------------------------------------------------- -- ! while (bit) -- ! { if (num >= den) -- ! --------------------------------------------------------------------- -- slt $ta, $r0, $r1 ! $ta <- num < den ? -- bnez $ta, .L9 ! if yes, skip -- ! --------------------------------------------------------------------- -- ! { num -= den; -- ! res |= bit; -- ! } -- ! --------------------------------------------------------------------- -- sub $r0, $r0, $r1 ! $r0 <- num -= den -- or $r2, $r2, $r4 ! $r2 <- res |= bit --.L9: -- ! --------------------------------------------------------------------- -- ! bit >> = 1; -- ! den >> = 1; -- ! } -- !!if (modwanted) -- !! return num; -- !!return res; -- ! --------------------------------------------------------------------- -- srli $r4, $r4, 1 ! $r4 <- bit >> = 1 -- srli $r1, $r1, 1 ! $r1 <- den >> = 1 -- bnez $r4, .L5 ! if bit != 0, continue loop --.L1: -- ! --------------------------------------------------------------------- -- ! if (neg) -- ! res = -res; -- ! return res; -- ! --------------------------------------------------------------------- -- subri $r0, $r2, 0 ! $r0 <- -res -- cmovz $r0, $r2, $r5 ! $r0 <- neg ? -res : res -- ! --------------------------------------------------------------------- -- ret -- .size __divsi3, .-__divsi3 --#endif /* L_divsi3 */ -- -- -- --#ifdef L_divdi3 -- -- !-------------------------------------- -- #ifdef __big_endian__ -- #define V1H $r0 -- #define V1L $r1 -- #define V2H $r2 -- #define V2L $r3 -- #else -- #define V1H $r1 -- #define V1L $r0 -- #define V2H $r3 -- #define V2L $r2 -- #endif -- !-------------------------------------- -- .text -- .align 2 -- .globl __divdi3 -- .type __divdi3, @function --__divdi3: -- ! prologue --#ifdef __NDS32_ISA_V3M__ -- push25 $r10, 0 --#else -- smw.adm $r6, [$sp], $r10, 2 --#endif -- ! end of prologue -- move $r8, V1L -- move $r9, V1H -- move $r6, V2L -- move $r7, V2H -- movi $r10, 0 -- bgez V1H, .L80 -- bal __negdi2 -- move $r8, V1L -- move $r9, V1H -- movi $r10, -1 --.L80: -- bgez $r7, .L81 -- move V1L, $r6 -- move V1H, $r7 -- bal __negdi2 -- move $r6, V1L -- move $r7, V1H -- nor $r10, $r10, $r10 --.L81: -- move V2L, $r6 -- move V2H, $r7 -- move V1L, $r8 -- move V1H, $r9 -- movi $r4, 0 -- bal __udivmoddi4 -- beqz $r10, .L82 -- bal __negdi2 --.L82: -- ! epilogue --#ifdef __NDS32_ISA_V3M__ -- pop25 $r10, 0 --#else -- lmw.bim $r6, [$sp], $r10, 2 -- ret --#endif -- .size __divdi3, .-__divdi3 --#endif /* L_divdi3 */ -- -- -- --#ifdef L_modsi3 -- -- .text -- .align 2 -- .globl __modsi3 -- .type __modsi3, @function --__modsi3: -- ! --------------------------------------------------------------------- -- ! neg=0; -- ! if (a<0) -- ! { a=-a; -- ! neg=1; -- ! } -- ! --------------------------------------------------------------------- -- sltsi $r5, $r0, 0 ! $r5 <- neg < 0 ? 1 : 0 -- subri $r4, $r0, 0 ! $r4 <- -a -- cmovn $r0, $r4, $r5 ! $r0 <- |a| -- ! --------------------------------------------------------------------- -- ! if (b < 0) --#ifndef __NDS32_PERF_EXT__ -- ! --------------------------------------------------------------------- -- bgez $r1, .L3 ! if b >= 0, skip -- ! --------------------------------------------------------------------- -- ! b = -b; -- ! --------------------------------------------------------------------- -- subri $r1, $r1, 0 ! $r1 <- |b| --.L3: -- ! --------------------------------------------------------------------- -- !!res = udivmodsi4 (a, b, 1); -- ! if (den != 0) -- ! --------------------------------------------------------------------- --#else /* __NDS32_PERF_EXT__ */ -- ! b = -b; -- !!res = udivmodsi4 (a, b, 1); -- ! if (den != 0) -- ! --------------------------------------------------------------------- -- abs $r1, $r1 ! $r1 <- |b| --#endif /* __NDS32_PERF_EXT__ */ -- beqz $r1, .L1 ! if den == 0, skip -- ! --------------------------------------------------------------------- -- ! { bit = 1; -- ! res = 0; -- ! --------------------------------------------------------------------- -- movi $r4, 1 ! $r4 <- bit = 1 --#ifndef __OPTIMIZE_SIZE__ --.L6: --#endif -- ! --------------------------------------------------------------------- -- ! while (den < num&&bit && !(den & (1L << 31))) -- ! --------------------------------------------------------------------- -- slt $ta, $r1, $r0 ! $ta <- den < num ? -- beqz $ta, .L5 ! if no, skip -- ! --------------------------------------------------------------------- -- ! { den << = 1; -- ! bit << = 1; -- ! } -- ! --------------------------------------------------------------------- --#if defined (__OPTIMIZE_SIZE__) && ! defined (__NDS32_ISA_V3M__) -- clz $r3, $r1 ! $r3 <- leading zero count for den -- clz $ta, $r0 ! $ta <- leading zero count for num -- sub $r3, $r3, $ta ! $r3 <- number of bits to shift -- sll $r1, $r1, $r3 ! $r1 <- den -- sll $r4, $r4, $r3 ! $r2 <- bit --#else -- slli $r1, $r1, 1 ! $r1 <- den << = 1 -- slli $r4, $r4, 1 ! $r4 <- bit << = 1 -- b .L6 ! continue loop --#endif --.L5: -- ! --------------------------------------------------------------------- -- ! while (bit) -- ! { if (num >= den) -- ! { num -= den; -- ! res |= bit; -- ! } -- ! bit >> = 1; -- ! den >> = 1; -- ! } -- ! } -- !!if (modwanted) -- !! return num; -- !!return res; -- ! --------------------------------------------------------------------- -- sub $r2, $r0, $r1 ! $r2 <- num - den -- slt $ta, $r0, $r1 ! $ta <- num < den ? -- srli $r4, $r4, 1 ! $r4 <- bit >> = 1 -- cmovz $r0, $r2, $ta ! $r0 <- num = (num < den) ? num : num - den -- srli $r1, $r1, 1 ! $r1 <- den >> = 1 -- bnez $r4, .L5 ! if bit != 0, continue loop --.L1: -- ! --------------------------------------------------------------------- -- ! if (neg) -- ! res = -res; -- ! return res; -- ! --------------------------------------------------------------------- -- subri $r3, $r0, 0 ! $r3 <- -res -- cmovn $r0, $r3, $r5 ! $r0 <- neg ? -res : res -- ! --------------------------------------------------------------------- -- ret -- .size __modsi3, .-__modsi3 --#endif /* L_modsi3 */ -- -- -- --#ifdef L_moddi3 -- -- !-------------------------------------- -- #ifdef __big_endian__ -- #define V1H $r0 -- #define V1L $r1 -- #define V2H $r2 -- #define V2L $r3 -- #else -- #define V1H $r1 -- #define V1L $r0 -- #define V2H $r3 -- #define V2L $r2 -- #endif -- !-------------------------------------- -- .text -- .align 2 -- .globl __moddi3 -- .type __moddi3, @function --__moddi3: -- ! ===================================================================== -- ! stack allocation: -- ! sp+32 +-----------------------+ -- ! | $lp | -- ! sp+28 +-----------------------+ -- ! | $r6 - $r10 | -- ! sp+8 +-----------------------+ -- ! | | -- ! sp+4 +-----------------------+ -- ! | | -- ! sp +-----------------------+ -- ! ===================================================================== -- ! prologue --#ifdef __NDS32_ISA_V3M__ -- push25 $r10, 8 --#else -- smw.adm $r6, [$sp], $r10, 2 -- addi $sp, $sp, -8 --#endif -- ! end of prologue -- !------------------------------------------ -- ! __moddi3 (DWtype u, DWtype v) -- ! { -- ! word_type c = 0; -- ! DWunion uu = {.ll = u}; -- ! DWunion vv = {.ll = v}; -- ! DWtype w; -- ! if (uu.s.high < 0) -- ! c = ~c, -- ! uu.ll = -uu.ll; -- !--------------------------------------------- -- move $r8, V1L -- move $r9, V1H -- move $r6, V2L -- move $r7, V2H -- movi $r10, 0 ! r10 = c = 0 -- bgez V1H, .L80 ! if u > 0 , go L80 -- bal __negdi2 -- move $r8, V1L -- move $r9, V1H -- movi $r10, -1 ! r10 = c = ~c -- !------------------------------------------------ -- ! if (vv.s.high < 0) -- ! vv.ll = -vv.ll; -- !---------------------------------------------- --.L80: -- bgez $r7, .L81 ! if v > 0 , go L81 -- move V1L, $r6 -- move V1H, $r7 -- bal __negdi2 -- move $r6, V1L -- move $r7, V1H -- !------------------------------------------ -- ! (void) __udivmoddi4 (uu.ll, vv.ll, &w); -- ! if (c) -- ! w = -w; -- ! return w; -- !----------------------------------------- --.L81: -- move V2L, $r6 -- move V2H, $r7 -- move V1L, $r8 -- move V1H, $r9 -- addi $r4, $sp, 0 -- bal __udivmoddi4 -- lwi $r0, [$sp+(0)] ! le: sp + 0 is low, be: sp + 0 is high -- lwi $r1, [$sp+(4)] ! le: sp + 4 is low, be: sp + 4 is high -- beqz $r10, .L82 -- bal __negdi2 --.L82: -- ! epilogue --#ifdef __NDS32_ISA_V3M__ -- pop25 $r10, 8 --#else -- addi $sp, $sp, 8 -- lmw.bim $r6, [$sp], $r10, 2 -- ret --#endif -- .size __moddi3, .-__moddi3 --#endif /* L_moddi3 */ -- -- -- --#ifdef L_mulsi3 -- -- .text -- .align 2 -- .globl __mulsi3 -- .type __mulsi3, @function --__mulsi3: -- ! --------------------------------------------------------------------- -- ! r = 0; -- ! while (a) -- ! $r0: r -- ! $r1: b -- ! $r2: a -- ! --------------------------------------------------------------------- -- beqz $r0, .L7 ! if a == 0, done -- move $r2, $r0 ! $r2 <- a -- movi $r0, 0 ! $r0 <- r <- 0 --.L8: -- ! --------------------------------------------------------------------- -- ! { if (a & 1) -- ! r += b; -- ! a >> = 1; -- ! b << = 1; -- ! } -- ! $r0: r -- ! $r1: b -- ! $r2: a -- ! $r3: scratch -- ! $r4: scratch -- ! --------------------------------------------------------------------- -- andi $r3, $r2, 1 ! $r3 <- a & 1 -- add $r4, $r0, $r1 ! $r4 <- r += b -- cmovn $r0, $r4, $r3 ! $r0 <- r -- srli $r2, $r2, 1 ! $r2 <- a >> = 1 -- slli $r1, $r1, 1 ! $r1 <- b << = 1 -- bnez $r2, .L8 ! if a != 0, continue loop --.L7: -- ! --------------------------------------------------------------------- -- ! $r0: return code -- ! --------------------------------------------------------------------- -- ret -- .size __mulsi3, .-__mulsi3 --#endif /* L_mulsi3 */ -- -- -- --#ifdef L_udivsi3 -- -- .text -- .align 2 -- .globl __udivsi3 -- .type __udivsi3, @function --__udivsi3: -- ! --------------------------------------------------------------------- -- !!res=udivmodsi4(a,b,0); -- ! res=0; -- ! if (den!=0) -- ! --------------------------------------------------------------------- -- movi $r2, 0 ! $r2 <- res=0 -- beqz $r1, .L1 ! if den==0, skip -- ! --------------------------------------------------------------------- -- ! { bit=1; -- ! --------------------------------------------------------------------- -- movi $r4, 1 ! $r4 <- bit=1 --#ifndef __OPTIMIZE_SIZE__ --.L6: --#endif -- ! --------------------------------------------------------------------- -- ! while (den=den) -- ! --------------------------------------------------------------------- -- slt $ta, $r0, $r1 ! $ta <- num>=1; -- ! den>>=1; -- ! } -- ! } -- !!if (modwanted) -- !! return num; -- !!return res; -- ! --------------------------------------------------------------------- -- srli $r4, $r4, 1 ! $r4 <- bit>>=1 -- srli $r1, $r1, 1 ! $r1 <- den>>=1 -- bnez $r4, .L5 ! if bit!=0, continue loop --.L1: -- ! --------------------------------------------------------------------- -- ! return res; -- ! --------------------------------------------------------------------- -- move $r0, $r2 ! $r0 <- return value -- ! --------------------------------------------------------------------- -- ! --------------------------------------------------------------------- -- ret -- .size __udivsi3, .-__udivsi3 --#endif /* L_udivsi3 */ -- -- -- --#ifdef L_udivdi3 -- -- !-------------------------------------- -- #ifdef __big_endian__ -- #define V1H $r0 -- #define V1L $r1 -- #define V2H $r2 -- #define V2L $r3 -- #else -- #define V1H $r1 -- #define V1L $r0 -- #define V2H $r3 -- #define V2L $r2 -- #endif -- !-------------------------------------- -- -- .text -- .align 2 -- .globl __udivdi3 -- .type __udivdi3, @function --__udivdi3: -- ! prologue --#ifdef __NDS32_ISA_V3M__ -- push25 $r8, 0 --#else -- smw.adm $r6, [$sp], $r8, 2 --#endif -- ! end of prologue -- movi $r4, 0 -- bal __udivmoddi4 -- ! epilogue --#ifdef __NDS32_ISA_V3M__ -- pop25 $r8, 0 --#else -- lmw.bim $r6, [$sp], $r8, 2 -- ret --#endif -- .size __udivdi3, .-__udivdi3 --#endif /* L_udivdi3 */ -- -- -- --#ifdef L_udivmoddi4 -- -- .text -- .align 2 -- .globl fudiv_qrnnd -- .type fudiv_qrnnd, @function -- #ifdef __big_endian__ -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 -- #define W6H $r4 -- #define W6L $r5 -- #define OFFSET_L 4 -- #define OFFSET_H 0 -- #else -- #define P1H $r1 -- #define P1L $r0 -- #define P2H $r3 -- #define P2L $r2 -- #define W6H $r5 -- #define W6L $r4 -- #define OFFSET_L 0 -- #define OFFSET_H 4 -- #endif --fudiv_qrnnd: -- !------------------------------------------------------ -- ! function: fudiv_qrnnd(quotient, remainder, high_numerator, low_numerator, denominator) -- ! divides a UDWtype, composed by the UWtype integers,HIGH_NUMERATOR (from $r4) -- ! and LOW_NUMERATOR(from $r5) by DENOMINATOR(from $r6), and places the quotient -- ! in $r7 and the remainder in $r8. -- !------------------------------------------------------ -- ! in reg:$r4(n1), $r5(n0), $r6(d0) -- ! __d1 = ((USItype) (d) >> ((4 * 8) / 2)); -- ! __d0 = ((USItype) (d) & (((USItype) 1 << ((4 * 8) / 2)) - 1)); -- ! __r1 = (n1) % __d1; -- ! __q1 = (n1) / __d1; -- ! __m = (USItype) __q1 * __d0; -- ! __r1 = __r1 * ((USItype) 1 << ((4 * 8) / 2)) | ((USItype) (n0) >> ((4 * 8) / 2)); -- ! if (__r1 < __m) -- ! { -- !------------------------------------------------------ -- smw.adm $r0, [$sp], $r4, 2 ! store $lp, when use BASELINE_V1,and must store $r0-$r3 -- srli $r7, $r6, 16 ! $r7 = d1 =__ll_highpart (d) -- movi $ta, 65535 -- and $r8, $r6, $ta ! $r8 = d0 = __ll_lowpart (d) -- -- divr $r9, $r10, $r4, $r7 ! $r9 = q1, $r10 = r1 -- and $r4, $r5, $ta ! $r4 = __ll_lowpart (n0) -- slli $r10, $r10, 16 ! $r10 = r1 << 16 -- srli $ta, $r5, 16 ! $ta = __ll_highpart (n0) -- -- or $r10, $r10, $ta ! $r10 <- $r0|$r3=__r1 -- mul $r5, $r9, $r8 ! $r5 = m = __q1*__d0 -- slt $ta, $r10, $r5 ! $ta <- __r1<__m -- beqz $ta, .L2 !if yes,skip -- !------------------------------------------------------ -- ! __q1--, __r1 += (d); -- ! if (__r1 >= (d)) -- ! { -- !------------------------------------------------------ -- -- add $r10, $r10, $r6 !$r10 <- __r1+d=__r1 -- addi $r9, $r9, -1 !$r9 <- __q1--=__q1 -- slt $ta, $r10, $r6 !$ta <- __r1= (d)) -- ! { -- !------------------------------------------------------ -- -- add $r10, $r10, $r6 !$r10 <- __r0+d=__r0 -- addi $r7, $r7, -1 !$r7 <- __q0--=__q0 -- slt $ta, $r10, $r6 !$ta <- __r0 n1) -- ! { -- !------------------------------------------------------ -- -- slt $ta, P1H, P2L !$ta <- n1> ((4 * 8) - bm)); -- ! n0 = n0 << bm; -- ! } -- !------------------------------------------------------ -- -- subri $r5, $r7, 32 !$r5 <- 32-bm -- srl $r5, P1L, $r5 !$r5 <- n0>>$r5 -- sll $r6, P1H, $r7 !$r6 <- n1< n1) -- !------------------------------------------------------ -- -- move $r4,P1H ! give fudiv_qrnnd args -- move $r5,P1L ! -- move $r6,P2L ! -- bal fudiv_qrnnd !calcaulte q0 n0 -- movi $r6, 0 !P1L <- 0 -- swi $r7,[$sp+32] !q0 -- swi $r6,[$sp+36] !q1 -- move P1L,$r8 !n0 -- b .L19 --.L10: -- !------------------------------------------------------ -- ! else #if (d0 > n1) -- ! { -- ! if(d0 == 0) -- !------------------------------------------------------ -- -- bnez P2L, .L20 !if yes,skip -- !------------------------------------------------------ -- ! d0 = 1 / d0; -- !------------------------------------------------------ -- -- movi $r4, 1 !P1L <- 1 -- divr P2L, $r4, $r4, P2L !$r9=1/d0,P1L=1%d0 --.L20: -- --#ifndef __NDS32_PERF_EXT__ -- smw.adm $r0, [$sp], $r5, 0 -- move $r0, P2L -- bal __clzsi2 -- move $r7, $r0 -- lmw.bim $r0, [$sp], $r5, 0 --#else -- clz $r7, P2L --#endif -- swi $r7,[$sp+(28)] ! store bm -- beqz $r7, .L28 ! if yes,skip -- !------------------------------------------------------ -- ! b = (4 * 8) - bm; -- ! d0 = d0 << bm; -- ! n2 = n1 >> b; -- ! n1 = (n1 << bm) | (n0 >> b); -- ! n0 = n0 << bm; -- ! fudiv_qrnnd (&q1, &n1, n2, n1, d0); -- ! } -- !------------------------------------------------------ -- -- subri $r10, $r7, 32 !$r10 <- 32-bm=b -- srl $r4, P1L, $r10 !$r4 <- n0>>b -- sll $r5, P1H, $r7 !$r5 <- n1<>b=n2 !for fun -- -- move $r6,P2L !for fun -- bal fudiv_qrnnd !caculate q1, n1 -- -- swi $r7,[$sp+(36)] ! q1 store -- move P1H,$r8 ! n1 store -- -- move $r4,$r8 ! prepare for next fudiv_qrnnd() -- move $r5,P1L -- move $r6,P2L -- b .L29 --.L28: -- !------------------------------------------------------ -- ! else // bm != 0 -- ! { -- ! n1 -= d0; -- ! q1 = 1; -- ! -- !------------------------------------------------------ -- -- sub P1H, P1H, P2L !P1L <- n1-d0=n1 -- movi $ta, 1 ! -- swi $ta, [$sp+(36)] !1 -> [$sp+(36)] -- -- move $r4,P1H ! give fudiv_qrnnd args -- move $r5,P1L -- move $r6,P2L --.L29: -- !------------------------------------------------------ -- ! fudiv_qrnnd (&q0, &n0, n1, n0, d0); -- !------------------------------------------------------ -- -- bal fudiv_qrnnd !calcuate q0, n0 -- swi $r7,[$sp+(32)] !q0 store -- move P1L,$r8 !n0 --.L19: -- !------------------------------------------------------ -- ! if (rp != 0) -- ! { -- !------------------------------------------------------ -- -- beqz $fp, .L31 !if yes,skip -- !------------------------------------------------------ -- ! rr.s.low = n0 >> bm; -- ! rr.s.high = 0; -- ! *rp = rr.ll; -- ! } -- !------------------------------------------------------ -- -- movi $r5, 0 !$r5 <- 0 -- lwi $r7,[$sp+(28)] !load bm -- srl $r4, P1L, $r7 !$r4 <- n0>>bm -- swi $r4, [$fp+OFFSET_L] !r0 !$r4 -> [$sp+(48)] -- swi $r5, [$fp+OFFSET_H] !r1 !0 -> [$sp+(52)] -- b .L31 --.L9: -- !------------------------------------------------------ -- ! else # d1 == 0 -- ! { -- ! if(d1 > n1) -- ! { -- !------------------------------------------------------ -- -- slt $ta, P1H, P2H !$ta <- n1 [$sp+(40)]=q1 -- swi $r5, [$sp+(36)] !q1 !0 -> [$sp+(32)]=q0 -- beqz $fp, .L31 !if yes,skip -- !------------------------------------------------------ -- ! rr.s.low = n0; -- ! rr.s.high = n1; -- ! *rp = rr.ll; -- ! } -- !------------------------------------------------------ -- -- swi P1L, [$fp+OFFSET_L] !P1L -> [rp] -- swi P1H, [$fp+OFFSET_H] !P1H -> [rp+4] -- b .L31 --.L32: --#ifndef __NDS32_PERF_EXT__ -- smw.adm $r0, [$sp], $r5, 0 -- move $r0, P2H -- bal __clzsi2 -- move $r7, $r0 -- lmw.bim $r0, [$sp], $r5, 0 --#else -- clz $r7,P2H --#endif -- swi $r7,[$sp+(28)] !$r7=bm store -- beqz $r7, .L42 !if yes,skip -- !------------------------------------------------------ -- ! USItype m1, m0; -- ! b = (4 * 8) - bm; -- ! d1 = (d0 >> b) | (d1 << bm); -- ! d0 = d0 << bm; -- ! n2 = n1 >> b; -- ! n1 = (n0 >> b) | (n1 << bm); -- ! n0 = n0 << bm; -- ! fudiv_qrnnd (&q0, &n1, n2, n1, d1); -- !------------------------------------------------------ -- -- subri $r10, $r7, 32 !$r10 <- 32-bm=b -- srl $r5, P2L, $r10 !$r5 <- d0>>b -- sll $r6, P2H, $r7 !$r6 <- d1<>b=n2 !!! func -- srl $r8, P1L, $r10 !$r8 <- n0>>b !!$r8 -- sll $r9, P1H, $r7 !$r9 <- n1<> ((4 * 8) / 2)); -- ! __vl = ((USItype) (d0) & (((USItype) 1 << ((4 * 8) / 2)) - 1)); -- ! __vh = ((USItype) (d0) >> ((4 * 8) / 2)); -- ! __x0 = (USItype) __ul * __vl; -- ! __x1 = (USItype) __ul * __vh; -- ! __x2 = (USItype) __uh * __vl; -- ! __x3 = (USItype) __uh * __vh; -- ! __x1 += ((USItype) (__x0) >> ((4 * 8) / 2)); -- ! __x1 += __x2; -- ! if (__x1 < __x2) -- ! __x3 += ((USItype) 1 << ((4 * 8) / 2)); -- ! (m1) = __x3 + ((USItype) (__x1) >> ((4 * 8) / 2)); -- ! (m0) = (USItype)(q0*d0); -- ! } -- ! if (m1 > n1) -- !--------------------------------------------------- --#ifdef __NDS32_ISA_V3M__ -- !mulr64 $r4, P2L, $r6 -- smw.adm $r0, [$sp], $r3, 0 -- move P1L, P2L -- move P2L, $r6 -- movi P1H, 0 -- movi P2H, 0 -- bal __muldi3 -- movd44 $r4, $r0 -- lmw.bim $r0, [$sp], $r3, 0 -- move $r8, W6H -- move $r5, W6L --#else -- mulr64 $r4, P2L, $r6 -- move $r8, W6H -- move $r5, W6L --#endif -- slt $ta, P1H, $r8 !$ta <- n1 n0) -- !------------------------------------------------------ -- -- slt $ta, P1L, $r5 !$ta <- n0 (m0)); -- ! (m0) = __x; -- ! } -- ! } -- !------------------------------------------------------ -- -- sub $r4, $r5, P2L !$r4 <- m0-d0=__x -- addi $r6, $r6, -1 !$r6 <- q0--=q0 -- sub $r8, $r8, P2H !$r8 <- m1-d1 -- swi $r6, [$sp+(32)] ! q0 !$r6->[$sp+(32)] -- slt $ta, $r5, $r4 !$ta <- m0<__x -- sub $r8, $r8, $ta !$r8 <- P1H-P1L=m1 -- move $r5, $r4 !$r5 <- __x=m0 --.L45: -- !------------------------------------------------------ -- ! q1 = 0; -- ! if (rp != 0) -- ! { -- !------------------------------------------------------ -- -- movi $r4, 0 !$r4 <- 0 -- swi $r4, [$sp+(36)] !0 -> [$sp+(40)]=q1 -- beqz $fp, .L31 !if yes,skip -- !------------------------------------------------------ -- ! # sub_ddmmss (n1, n0, n1, n0, m1, m0); -- ! do -- ! { USItype __x; -- ! __x = (n0) - (m0); -- ! (n1) = (n1) - (m1) - (__x > (n0)); -- ! (n0) = __x; -- ! } -- ! rr.s.low = (n1 << b) | (n0 >> bm); -- ! rr.s.high = n1 >> bm; -- ! *rp = rr.ll; -- !------------------------------------------------------ -- -- sub $r4, P1H, $r8 !$r4 <- n1-m1 -- sub $r6, P1L, $r5 !$r6 <- n0-m0=__x=n0 -- slt $ta, P1L, $r6 !$ta <- n0<__x -- sub P1H, $r4, $ta !P1H <- $r4-$ta=n1 -- move P1L, $r6 -- -- lwi $r7,[$sp+(28)] ! load bm -- subri $r10,$r7,32 -- sll $r4, P1H, $r10 !$r4 <- n1<>bm -- or $r6, $r5, $r4 !$r6 <- $r5|$r4=rr.s.low -- srl $r8, P1H, $r7 !$r8 <- n1>>bm =rr.s.high -- swi $r6, [$fp+OFFSET_L] ! -- swi $r8, [$fp+OFFSET_H] ! -- b .L31 --.L42: -- !------------------------------------------------------ -- ! else -- ! { -- ! if(n1 > d1) -- !------------------------------------------------------ -- -- slt $ta, P2H, P1H !$ta <- P2H= d0) -- !------------------------------------------------------ -- -- slt $ta, P1L, P2L !$ta <- P1L (n0)); -- ! (n0) = __x; -- ! } -- !------------------------------------------------------ --.L52: -- sub $r4, P1H, P2H !$r4 <- P1H-P2H -- sub $r6, P1L, P2L !$r6 <- no-d0=__x=n0 -- slt $ta, P1L, $r6 !$ta <- no<__x -- sub P1H, $r4, $ta !P1H <- $r4-$ta=n1 -- move P1L, $r6 !n0 -- movi $r5, 1 ! -- swi $r5, [$sp+(32)] !1 -> [$sp+(32)]=q0 -- b .L54 --.L51: -- !------------------------------------------------------ -- ! q0 = 0; -- !------------------------------------------------------ -- -- movi $r5,0 -- swi $r5, [$sp+(32)] !$r5=0 -> [$sp+(32)] --.L54: -- !------------------------------------------------------ -- ! q1 = 0; -- ! if (rp != 0) -- ! { -- !------------------------------------------------------ -- -- movi $r5, 0 ! -- swi $r5, [$sp+(36)] !0 -> [$sp+(36)] -- beqz $fp, .L31 -- !------------------------------------------------------ -- ! rr.s.low = n0; -- ! rr.s.high = n1; -- ! *rp = rr.ll; -- ! } -- !------------------------------------------------------ -- -- swi P1L, [$fp+OFFSET_L] !remainder -- swi P1H, [$fp+OFFSET_H] ! --.L31: -- !------------------------------------------------------ -- ! const DWunion ww = {{.low = q0, .high = q1}}; -- ! return ww.ll; -- !} -- !------------------------------------------------------ -- -- lwi P1L, [$sp+(32)] !quotient -- lwi P1H, [$sp+(36)] -- lmw.bim $r6, [$sp], $r10, 10 -- addi $sp, $sp, 12 -- ret -- .size __udivmoddi4, .-__udivmoddi4 --#endif /* L_udivmoddi4 */ -- -- -- --#ifdef L_umodsi3 -- -- ! ===================================================================== -- .text -- .align 2 -- .globl __umodsi3 -- .type __umodsi3, @function --__umodsi3: -- ! --------------------------------------------------------------------- -- !!res=udivmodsi4(a,b,1); -- ! if (den==0) -- ! return num; -- ! --------------------------------------------------------------------- -- beqz $r1, .L1 ! if den==0, skip -- ! --------------------------------------------------------------------- -- ! bit=1; -- ! res=0; -- ! --------------------------------------------------------------------- -- movi $r4, 1 ! $r4 <- bit=1 --#ifndef __OPTIMIZE_SIZE__ --.L6: --#endif -- ! --------------------------------------------------------------------- -- ! while (den=den) -- ! { num-=den; -- ! res|=bit; -- ! } -- ! bit>>=1; -- ! den>>=1; -- ! } -- !!if (modwanted) -- !! return num; -- !!return res; -- ! --------------------------------------------------------------------- -- sub $r2, $r0, $r1 ! $r2 <- num-den -- slt $ta, $r0, $r1 ! $ta <- num>=1 -- cmovz $r0, $r2, $ta ! $r0 <- num=(num>=1 -- bnez $r4, .L5 ! if bit!=0, continue loop --.L1: -- ! --------------------------------------------------------------------- -- ! return res; -- ! --------------------------------------------------------------------- -- ret -- .size __umodsi3, .-__umodsi3 --#endif /* L_umodsi3 */ -- -- -- --#ifdef L_umoddi3 -- -- !-------------------------------------- -- #ifdef __big_endian__ -- #define V1H $r0 -- #define V1L $r1 -- #define V2H $r2 -- #define V2L $r3 -- #else -- #define V1H $r1 -- #define V1L $r0 -- #define V2H $r3 -- #define V2L $r2 -- #endif -- !-------------------------------------- -- .text -- .align 2 -- .globl __umoddi3 -- .type __umoddi3, @function --__umoddi3: -- ! prologue -- addi $sp, $sp, -12 -- swi $lp, [$sp+(0)] -- ! end of prologue -- addi $r4, $sp, 4 -- bal __udivmoddi4 -- lwi $r0, [$sp+(4)] ! __udivmoddi4 return low when LE mode or return high when BE mode -- lwi $r1, [$sp+(8)] ! --.L82: -- ! epilogue -- lwi $lp, [$sp+(0)] -- addi $sp, $sp, 12 -- ret -- .size __umoddi3, .-__umoddi3 --#endif /* L_umoddi3 */ -- -- -- --#ifdef L_muldi3 -- --#ifdef __big_endian__ -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 -- -- #define V2H $r4 -- #define V2L $r5 --#else -- #define P1H $r1 -- #define P1L $r0 -- #define P2H $r3 -- #define P2L $r2 -- -- #define V2H $r5 -- #define V2L $r4 --#endif -- -- ! ==================================================================== -- .text -- .align 2 -- .globl __muldi3 -- .type __muldi3, @function --__muldi3: -- ! parameter passing for libgcc functions normally involves 2 doubles -- !--------------------------------------- --#ifdef __NDS32_ISA_V3M__ -- ! There is no mulr64 instruction in Andes ISA V3M. -- ! So we must provide a sequence of calculations to complete the job. -- smw.adm $r6, [$sp], $r9, 0x0 -- zeh33 $r4, P1L -- srli $r7, P1L, 16 -- zeh33 $r5, P2L -- mul $r6, $r5, $r4 -- mul33 $r5, $r7 -- srli $r8, P2L, 16 -- mov55 $r9, $r5 -- maddr32 $r9, $r8, $r4 -- srli $r4, $r6, 16 -- add $r4, $r9, $r4 -- slt45 $r4, $r5 -- slli $r5, $r15, 16 -- maddr32 $r5, $r8, $r7 -- mul P2L, P1H, P2L -- srli $r7, $r4, 16 -- maddr32 P2L, P2H, P1L -- add333 P1H, $r5, $r7 -- slli $r4, $r4, 16 -- zeh33 $r6, $r6 -- add333 P1L, $r4, $r6 -- add333 P1H, P2L, P1H -- lmw.bim $r6, [$sp], $r9, 0x0 -- ret --#else /* not __NDS32_ISA_V3M__ */ -- mul $ta, P1L, P2H -- mulr64 $r4, P1L, P2L -- maddr32 $ta, P1H, P2L -- move P1L, V2L -- add P1H, $ta, V2H -- ret --#endif /* not __NDS32_ISA_V3M__ */ -- .size __muldi3, .-__muldi3 --#endif /* L_muldi3 */ -- -- -- --#ifdef L_addsub_df -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define P2L $r2 -- #define P2H $r3 -- #define P3L $r4 -- #define P3H $r5 -- #define O1L $r7 -- #define O1H $r8 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 -- #define P3H $r4 -- #define P3L $r5 -- #define O1H $r7 -- #define O1L $r8 --#endif -- .text -- .align 2 -- .global __subdf3 -- .type __subdf3, @function --__subdf3: -- push $lp -- pushm $r6, $r10 -- -- move $r4, #0x80000000 -- xor P2H, P2H, $r4 -- -- j .Lsdpadd -- -- .global __adddf3 -- .type __adddf3, @function --__adddf3: -- push $lp -- pushm $r6, $r10 --.Lsdpadd: -- slli $r6, P1H, #1 -- srli $r6, $r6, #21 -- slli P3H, P1H, #11 -- srli $r10, P1L, #21 -- or P3H, P3H, $r10 -- slli P3L, P1L, #11 -- move O1L, #0x80000000 -- or P3H, P3H, O1L -- slli $r9, P2H, #1 -- srli $r9, $r9, #21 -- slli O1H, P2H, #11 -- srli $r10, P2L, #21 -- or O1H, O1H, $r10 -- or O1H, O1H, O1L -- slli O1L, P2L, #11 -- -- addi $r10, $r6, #-1 -- slti $r15, $r10, #0x7fe -- beqzs8 .LEspecA -- --.LElab1: -- addi $r10, $r9, #-1 -- slti $r15, $r10, #0x7fe -- beqzs8 .LEspecB -- --.LElab2: -- #NORMd($r4, P2L, P1L) -- bnez P3H, .LL1 -- bnez P3L, .LL2 -- move $r6, #0 -- j .LL3 --.LL2: -- move P3H, P3L -- move P3L, #0 -- move P2L, #32 -- sub $r6, $r6, P2L --.LL1: --#ifndef __big_endian__ --#ifdef __NDS32_PERF_EXT__ -- clz $r2, $r5 --#else -- pushm $r0, $r1 -- pushm $r3, $r5 -- move $r0, $r5 -- bal __clzsi2 -- move $r2, $r0 -- popm $r3, $r5 -- popm $r0, $r1 --#endif --#else /* __big_endian__ */ --#ifdef __NDS32_PERF_EXT__ -- clz $r3, $r4 --#else -- pushm $r0, $r2 -- pushm $r4, $r5 -- move $r0, $r4 -- bal __clzsi2 -- move $r3, $r0 -- popm $r4, $r5 -- popm $r0, $r2 --#endif --#endif /* __big_endian__ */ -- beqz P2L, .LL3 -- sub $r6, $r6, P2L -- subri P1L, P2L, #32 -- srl P1L, P3L, P1L -- sll P3L, P3L, P2L -- sll P3H, P3H, P2L -- or P3H, P3H, P1L --.LL3: -- #NORMd End -- -- #NORMd($r7, P2L, P1L) -- bnez O1H, .LL4 -- bnez O1L, .LL5 -- move $r9, #0 -- j .LL6 --.LL5: -- move O1H, O1L -- move O1L, #0 -- move P2L, #32 -- sub $r9, $r9, P2L --.LL4: --#ifndef __big_endian__ --#ifdef __NDS32_PERF_EXT__ -- clz $r2, O1H --#else -- pushm $r0, $r1 -- pushm $r3, $r5 -- move $r0, O1H -- bal __clzsi2 -- move $r2, $r0 -- popm $r3, $r5 -- popm $r0, $r1 --#endif --#else /* __big_endian__ */ --#ifdef __NDS32_PERF_EXT__ -- clz $r3, O1H --#else -- pushm $r0, $r2 -- pushm $r4, $r5 -- move $r0, O1H -- bal __clzsi2 -- move $r3, $r0 -- popm $r4, $r5 -- popm $r0, $r2 --#endif --#endif /* __big_endian__ */ -- beqz P2L, .LL6 -- sub $r9, $r9, P2L -- subri P1L, P2L, #32 -- srl P1L, O1L, P1L -- sll O1L, O1L, P2L -- sll O1H, O1H, P2L -- or O1H, O1H, P1L --.LL6: -- #NORMd End -- -- move $r10, #0x80000000 -- and P1H, P1H, $r10 -- -- beq $r6, $r9, .LEadd3 -- slts $r15, $r9, $r6 -- beqzs8 .Li1 -- sub $r9, $r6, $r9 -- move P2L, #0 --.LL7: -- move $r10, #0x20 -- slt $r15, $r9, $r10 -- bnezs8 .LL8 -- or P2L, P2L, O1L -- move O1L, O1H -- move O1H, #0 -- addi $r9, $r9, #0xffffffe0 -- bnez O1L, .LL7 --.LL8: -- beqz $r9, .LEadd3 -- move P1L, O1H -- move $r10, O1L -- srl O1L, O1L, $r9 -- srl O1H, O1H, $r9 -- subri $r9, $r9, #0x20 -- sll P1L, P1L, $r9 -- or O1L, O1L, P1L -- sll $r10, $r10, $r9 -- or P2L, P2L, $r10 -- beqz P2L, .LEadd3 -- ori O1L, O1L, #1 -- j .LEadd3 --.Li1: -- move $r15, $r6 -- move $r6, $r9 -- sub $r9, $r9, $r15 -- move P2L, #0 --.LL10: -- move $r10, #0x20 -- slt $r15, $r9, $r10 -- bnezs8 .LL11 -- or P2L, P2L, P3L -- move P3L, P3H -- move P3H, #0 -- addi $r9, $r9, #0xffffffe0 -- bnez P3L, .LL10 --.LL11: -- beqz $r9, .LEadd3 -- move P1L, P3H -- move $r10, P3L -- srl P3L, P3L, $r9 -- srl P3H, P3H, $r9 -- subri $r9, $r9, #0x20 -- sll P1L, P1L, $r9 -- or P3L, P3L, P1L -- sll $r10, $r10, $r9 -- or P2L, P2L, $r10 -- beqz P2L, .LEadd3 -- ori P3L, P3L, #1 -- --.LEadd3: -- xor $r10, P1H, P2H -- sltsi $r15, $r10, #0 -- bnezs8 .LEsub1 -- -- #ADD(P3L, O1L) -- add P3L, P3L, O1L -- slt $r15, P3L, O1L -- -- #ADDCC(P3H, O1H) -- beqzs8 .LL13 -- add P3H, P3H, O1H -- slt $r15, P3H, O1H -- beqzs8 .LL14 -- addi P3H, P3H, #0x1 -- j .LL15 --.LL14: -- move $r15, #1 -- add P3H, P3H, $r15 -- slt $r15, P3H, $r15 -- j .LL15 --.LL13: -- add P3H, P3H, O1H -- slt $r15, P3H, O1H --.LL15: -- -- beqzs8 .LEres -- andi $r10, P3L, #1 -- beqz $r10, .Li3 -- ori P3L, P3L, #2 --.Li3: -- srli P3L, P3L, #1 -- slli $r10, P3H, #31 -- or P3L, P3L, $r10 -- srli P3H, P3H, #1 -- move $r10, #0x80000000 -- or P3H, P3H, $r10 -- addi $r6, $r6, #1 -- subri $r15, $r6, #0x7ff -- bnezs8 .LEres -- move $r10, #0x7ff00000 -- or P1H, P1H, $r10 -- move P1L, #0 -- j .LEretA -- --.LEsub1: -- #SUB(P3L, O1L) -- move $r15, P3L -- sub P3L, P3L, O1L -- slt $r15, $r15, P3L -- -- #SUBCC(P3H, O1H) -- beqzs8 .LL16 -- move $r15, P3H -- sub P3H, P3H, O1H -- slt $r15, $r15, P3H -- beqzs8 .LL17 -- subi333 P3H, P3H, #1 -- j .LL18 --.LL17: -- move $r15, P3H -- subi333 P3H, P3H, #1 -- slt $r15, $r15, P3H -- j .LL18 --.LL16: -- move $r15, P3H -- sub P3H, P3H, O1H -- slt $r15, $r15, P3H --.LL18: -- -- beqzs8 .Li5 -- move $r10, #0x80000000 -- xor P1H, P1H, $r10 -- -- subri P3H, P3H, #0 -- beqz P3L, .LL19 -- subri P3L, P3L, #0 -- subi45 P3H, #1 --.LL19: -- --.Li5: -- #NORMd($r4, $r9, P1L) -- bnez P3H, .LL20 -- bnez P3L, .LL21 -- move $r6, #0 -- j .LL22 --.LL21: -- move P3H, P3L -- move P3L, #0 -- move $r9, #32 -- sub $r6, $r6, $r9 --.LL20: --#ifdef __NDS32_PERF_EXT__ -- clz $r9, P3H --#else -- pushm $r0, $r5 -- move $r0, P3H -- bal __clzsi2 -- move $r9, $r0 -- popm $r0, $r5 --#endif -- beqz $r9, .LL22 -- sub $r6, $r6, $r9 -- subri P1L, $r9, #32 -- srl P1L, P3L, P1L -- sll P3L, P3L, $r9 -- sll P3H, P3H, $r9 -- or P3H, P3H, P1L --.LL22: -- #NORMd End -- -- or $r10, P3H, P3L -- bnez $r10, .LEres -- move P1H, #0 -- --.LEres: -- blez $r6, .LEund -- --.LElab8: -- #ADD(P3L, $0x400) -- move $r15, #0x400 -- add P3L, P3L, $r15 -- slt $r15, P3L, $r15 -- -- #ADDCC(P3H, $0x0) -- beqzs8 .LL25 -- add P3H, P3H, $r15 -- slt $r15, P3H, $r15 --.LL25: -- -- #ADDC($r6, $0x0) -- add $r6, $r6, $r15 -- srli $r10, P3L, #11 -- andi $r10, $r10, #1 -- sub P3L, P3L, $r10 -- srli P1L, P3L, #11 -- slli $r10, P3H, #21 -- or P1L, P1L, $r10 -- slli $r10, P3H, #1 -- srli $r10, $r10, #12 -- or P1H, P1H, $r10 -- slli $r10, $r6, #20 -- or P1H, P1H, $r10 -- --.LEretA: --.LE999: -- popm $r6, $r10 -- pop $lp -- ret5 $lp -- --.LEspecA: -- #ADD(P3L, P3L) -- move $r15, P3L -- add P3L, P3L, P3L -- slt $r15, P3L, $r15 -- -- #ADDC(P3H, P3H) -- add P3H, P3H, P3H -- add P3H, P3H, $r15 -- bnez $r6, .Li7 -- or $r10, P3H, P3L -- beqz $r10, .Li8 -- j .LElab1 --.Li8: -- subri $r15, $r9, #0x7ff -- beqzs8 .LEspecB -- add P3L, P2H, P2H -- or $r10, P3L, P2L -- bnez $r10, .LEretB -- sltsi $r15, P2H, #0 -- bnezs8 .LEretA -- --.LEretB: -- move P1L, P2L -- move P1H, P2H -- j .LE999 --.Li7: -- or $r10, P3H, P3L -- bnez $r10, .LEnan -- subri $r15, $r9, #0x7ff -- bnezs8 .LEretA -- xor $r10, P1H, P2H -- sltsi $r15, $r10, #0 -- bnezs8 .LEnan -- j .LEretB -- --.LEspecB: -- #ADD(O1L, O1L) -- move $r15, O1L -- add O1L, O1L, O1L -- slt $r15, O1L, $r15 -- -- #ADDC(O1H, O1H) -- add O1H, O1H, O1H -- add O1H, O1H, $r15 -- bnez $r9, .Li11 -- or $r10, O1H, O1L -- beqz $r10, .LEretA -- j .LElab2 --.Li11: -- or $r10, O1H, O1L -- beqz $r10, .LEretB -- --.LEnan: -- move P1H, #0xfff80000 -- move P1L, #0 -- j .LEretA -- --.LEund: -- subri $r9, $r6, #1 -- move P2L, #0 --.LL26: -- move $r10, #0x20 -- slt $r15, $r9, $r10 -- bnezs8 .LL27 -- or P2L, P2L, P3L -- move P3L, P3H -- move P3H, #0 -- addi $r9, $r9, #0xffffffe0 -- bnez P3L, .LL26 --.LL27: -- beqz $r9, .LL28 -- move P1L, P3H -- move $r10, P3L -- srl P3L, P3L, $r9 -- srl P3H, P3H, $r9 -- subri $r9, $r9, #0x20 -- sll P1L, P1L, $r9 -- or P3L, P3L, P1L -- sll $r10, $r10, $r9 -- or P2L, P2L, $r10 -- beqz P2L, .LL28 -- ori P3L, P3L, #1 --.LL28: -- move $r6, #0 -- j .LElab8 -- .size __subdf3, .-__subdf3 -- .size __adddf3, .-__adddf3 --#endif /* L_addsub_df */ -- -- -- --#ifdef L_mul_sf -- --#if !defined (__big_endian__) -- #define P1L $r0 -- #define P1H $r1 -- #define P2L $r2 -- #define P2H $r3 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 --#endif -- .text -- .align 2 -- .global __mulsf3 -- .type __mulsf3, @function --__mulsf3: -- push $lp -- pushm $r6, $r10 -- -- srli $r3, $r0, #23 -- andi $r3, $r3, #0xff -- srli $r5, $r1, #23 -- andi $r5, $r5, #0xff -- move $r6, #0x80000000 -- slli $r2, $r0, #8 -- or $r2, $r2, $r6 -- slli $r4, $r1, #8 -- or $r4, $r4, $r6 -- xor $r8, $r0, $r1 -- and $r6, $r6, $r8 -- -- addi $r8, $r3, #-1 -- slti $r15, $r8, #0xfe -- beqzs8 .LFspecA -- --.LFlab1: -- addi $r8, $r5, #-1 -- slti $r15, $r8, #0xfe -- beqzs8 .LFspecB -- --.LFlab2: -- move $r10, $r3 --/* This is a 64-bit multiple. ($r2, $r7) is (high, low). */ --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r2, $r2, $r4 --#else -- pushm $r0, $r1 -- pushm $r4, $r5 -- move P1L, $r2 -- movi P1H, #0 -- move P2L, $r4 -- movi P2H, #0 -- bal __muldi3 -- movd44 $r2, $r0 -- popm $r4, $r5 -- popm $r0, $r1 --#endif --#ifndef __big_endian__ -- move $r7, $r2 -- move $r2, $r3 --#else -- move $r7, $r3 --#endif -- move $r3, $r10 -- -- beqz $r7, .Li17 -- ori $r2, $r2, #1 -- --.Li17: -- sltsi $r15, $r2, #0 -- bnezs8 .Li18 -- slli $r2, $r2, #1 -- addi $r3, $r3, #-1 --.Li18: -- addi $r8, $r5, #0xffffff82 -- add $r3, $r3, $r8 -- addi $r8, $r3, #-1 -- slti $r15, $r8, #0xfe -- beqzs8 .LFoveund -- --.LFlab8: -- #ADD($r2, $0x80) -- move $r15, #0x80 -- add $r2, $r2, $r15 -- slt $r15, $r2, $r15 -- -- #ADDC($r3, $0x0) -- add $r3, $r3, $r15 -- srli $r8, $r2, #8 -- andi $r8, $r8, #1 -- sub $r2, $r2, $r8 -- slli $r2, $r2, #1 -- srli $r2, $r2, #9 -- slli $r8, $r3, #23 -- or $r2, $r2, $r8 -- or $r0, $r2, $r6 -- --.LF999: -- popm $r6, $r10 -- pop $lp -- ret5 $lp -- --.LFspecA: -- bnez $r3, .Li19 -- add $r2, $r2, $r2 -- beqz $r2, .Li20 --#ifdef __NDS32_PERF_EXT__ -- clz $r7, $r2 --#else -- pushm $r0, $r5 -- move $r0, $r2 -- bal __clzsi2 -- move $r7, $r0 -- popm $r0, $r5 --#endif -- sub $r3, $r3, $r7 -- sll $r2, $r2, $r7 -- j .LFlab1 --.Li20: -- subri $r15, $r5, #0xff -- beqzs8 .LFnan -- j .LFzer --.Li19: -- add $r8, $r2, $r2 -- bnez $r8, .LFnan -- bnez $r5, .Li21 -- add $r8, $r4, $r4 -- beqz $r8, .LFnan --.Li21: -- subri $r15, $r5, #0xff -- bnezs8 .LFinf -- --.LFspecB: -- bnez $r5, .Li22 -- add $r4, $r4, $r4 -- beqz $r4, .LFzer --#ifdef __NDS32_PERF_EXT__ -- clz $r7, $r4 --#else -- pushm $r0, $r5 -- move $r0, $r4 -- bal __clzsi2 -- move $r7, $r0 -- popm $r0, $r5 --#endif -- sub $r5, $r5, $r7 -- sll $r4, $r4, $r7 -- j .LFlab2 -- --.LFzer: -- move $r0, $r6 -- j .LF999 --.Li22: -- add $r8, $r4, $r4 -- bnez $r8, .LFnan -- --.LFinf: -- move $r8, #0x7f800000 -- or $r0, $r6, $r8 -- j .LF999 -- --.LFnan: -- move $r0, #0xffc00000 -- j .LF999 -- --.LFoveund: -- bgtz $r3, .LFinf -- subri $r7, $r3, #1 -- slti $r15, $r7, #0x20 -- beqzs8 .LFzer -- subri $r8, $r7, #0x20 -- sll $r3, $r2, $r8 -- srl $r2, $r2, $r7 -- beqz $r3, .Li25 -- ori $r2, $r2, #2 --.Li25: -- move $r3, #0 -- addi $r8, $r2, #0x80 -- sltsi $r15, $r8, #0 -- beqzs8 .LFlab8 -- move $r3, #1 -- j .LFlab8 -- .size __mulsf3, .-__mulsf3 --#endif /* L_mul_sf */ -- -- -- --#ifdef L_mul_df -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define P2L $r2 -- #define P2H $r3 -- #define P3L $r4 -- #define P3H $r5 -- #define O1L $r7 -- #define O1H $r8 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 -- #define P3H $r4 -- #define P3L $r5 -- #define O1H $r7 -- #define O1L $r8 --#endif -- .text -- .align 2 -- .global __muldf3 -- .type __muldf3, @function --__muldf3: -- push $lp -- pushm $r6, $r10 -- -- slli $r6, P1H, #1 -- srli $r6, $r6, #21 -- slli P3H, P1H, #11 -- srli $r10, P1L, #21 -- or P3H, P3H, $r10 -- slli P3L, P1L, #11 -- move O1L, #0x80000000 -- or P3H, P3H, O1L -- slli $r9, P2H, #1 -- srli $r9, $r9, #21 -- slli O1H, P2H, #11 -- srli $r10, P2L, #21 -- or O1H, O1H, $r10 -- or O1H, O1H, O1L -- xor P1H, P1H, P2H -- and P1H, P1H, O1L -- slli O1L, P2L, #11 -- -- addi $r10, $r6, #-1 -- slti $r15, $r10, #0x7fe -- beqzs8 .LFspecA -- --.LFlab1: -- addi $r10, $r9, #-1 -- slti $r15, $r10, #0x7fe -- beqzs8 .LFspecB -- --.LFlab2: -- addi $r10, $r9, #0xfffffc02 -- add $r6, $r6, $r10 -- -- move $r10, $r8 --/* This is a 64-bit multiple. */ --#ifndef __big_endian__ --/* For little endian: ($r9, $r3) is (high, low). */ --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r8, $r5, $r8 --#else -- pushm $r0, $r5 -- move $r0, $r5 -- movi $r1, #0 -- move $r2, $r8 -- movi $r3, #0 -- bal __muldi3 -- movd44 $r8, $r0 -- popm $r0, $r5 --#endif -- move $r3, $r8 --#else /* __big_endian__ */ --/* For big endain: ($r9, $r2) is (high, low). */ --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r8, $r4, $r7 --#else -- pushm $r0, $r5 -- move $r1, $r4 -- movi $r0, #0 -- move $r3, $r7 -- movi $r2, #0 -- bal __muldi3 -- movd44 $r8, $r0 -- popm $r0, $r5 --#endif -- move $r2, $r9 -- move $r9, $r8 --#endif /* __big_endian__ */ -- move $r8, $r10 -- -- move $r10, P1H --/* This is a 64-bit multiple. */ --#ifndef __big_endian__ --/* For little endian: ($r0, $r2) is (high, low). */ --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r0, $r4, $r8 --#else -- pushm $r2, $r5 -- move $r0, $r4 -- movi $r1, #0 -- move $r2, $r8 -- movi $r3, #0 -- bal __muldi3 -- popm $r2, $r5 --#endif -- move $r2, $r0 -- move $r0, $r1 --#else /* __big_endian__ */ --/* For big endain: ($r1, $r3) is (high, low). */ --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r0, $r5, $r7 --#else -- pushm $r2, $r5 -- move $r1, $r5 -- movi $r0, #0 -- move $r3, $r7 -- movi $r2, #0 -- bal __muldi3 -- popm $r2, $r5 --#endif -- move $r3, $r1 -- move $r1, $r0 --#endif /* __big_endian__ */ -- move P1H, $r10 -- -- #ADD(P2H, P1L) -- add P2H, P2H, P1L -- slt $r15, P2H, P1L -- -- #ADDC($r9, $0x0) -- add $r9, $r9, $r15 -- -- move $r10, P1H --/* This is a 64-bit multiple. */ --#ifndef __big_endian__ --/* For little endian: ($r0, $r8) is (high, low). */ --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r0, $r5, $r7 --#else -- pushm $r2, $r5 -- move $r0, $r5 -- movi $r1, #0 -- move $r2, $r7 -- movi $r3, #0 -- bal __muldi3 -- popm $r2, $r5 --#endif -- move $r8, $r0 -- move $r0, $r1 --#else /* __big_endian__ */ --/* For big endian: ($r1, $r7) is (high, low). */ --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r0, $r4, $r8 --#else -- pushm $r2, $r5 -- move $r1, $r4 -- movi $r0, #0 -- move $r3, $r8 -- movi $r2, #0 -- bal __muldi3 -- popm $r2, $r5 --#endif -- move $r7, $r1 -- move $r1, $r0 --#endif /* __big_endian__ */ -- move P1H, $r10 -- -- #ADD(P2L, O1H) -- add P2L, P2L, O1H -- slt $r15, P2L, O1H -- -- -- #ADDCC(P2H, P1L) -- beqzs8 .LL29 -- add P2H, P2H, P1L -- slt $r15, P2H, P1L -- beqzs8 .LL30 -- addi P2H, P2H, #0x1 -- j .LL31 --.LL30: -- move $r15, #1 -- add P2H, P2H, $r15 -- slt $r15, P2H, $r15 -- j .LL31 --.LL29: -- add P2H, P2H, P1L -- slt $r15, P2H, P1L --.LL31: -- -- #ADDC($r9, $0x0) -- add $r9, $r9, $r15 -- --/* This is a 64-bit multiple. */ --#ifndef __big_endian__ --/* For little endian: ($r8, $r0) is (high, low). */ -- move $r10, $r9 --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r8, $r4, $r7 --#else -- pushm $r0, $r5 -- move $r0, $r4 -- movi $r1, #0 -- move $r2, $r7 -- movi $r3, #0 -- bal __muldi3 -- movd44 $r8, $r0 -- popm $r0, $r5 --#endif -- move $r0, $r8 -- move $r8, $r9 -- move $r9, $r10 --#else /* __big_endian__ */ --/* For big endian: ($r7, $r1) is (high, low). */ -- move $r10, $r6 --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r6, $r5, $r8 --#else -- pushm $r0, $r5 -- move $r1, $r5 -- movi $r0, #0 -- move $r3, $r8 -- movi $r2, #0 -- bal __muldi3 -- movd44 $r6, $r0 -- popm $r0, $r5 --#endif -- move $r1, $r7 -- move $r7, $r6 -- move $r6, $r10 --#endif /* __big_endian__ */ -- -- #ADD(P2L, O1H) -- add P2L, P2L, O1H -- slt $r15, P2L, O1H -- -- -- #ADDCC(P2H, $0x0) -- beqzs8 .LL34 -- add P2H, P2H, $r15 -- slt $r15, P2H, $r15 --.LL34: -- -- #ADDC($r9, $0x0) -- add $r9, $r9, $r15 -- or $r10, P1L, P2L -- beqz $r10, .Li13 -- ori P2H, P2H, #1 --.Li13: -- move P3H, $r9 -- move P3L, P2H -- sltsi $r15, P3H, #0 -- bnezs8 .Li14 -- -- move $r15, P3L -- add P3L, P3L, P3L -- slt $r15, P3L, $r15 -- add P3H, P3H, P3H -- add P3H, P3H, $r15 -- addi $r6, $r6, #-1 --.Li14: -- addi $r10, $r6, #-1 -- slti $r15, $r10, #0x7fe -- beqzs8 .LFoveund -- -- #ADD(P3L, $0x400) -- move $r15, #0x400 -- add P3L, P3L, $r15 -- slt $r15, P3L, $r15 -- -- -- #ADDCC(P3H, $0x0) -- beqzs8 .LL37 -- add P3H, P3H, $r15 -- slt $r15, P3H, $r15 --.LL37: -- -- #ADDC($r6, $0x0) -- add $r6, $r6, $r15 -- --.LFlab8: -- srli $r10, P3L, #11 -- andi $r10, $r10, #1 -- sub P3L, P3L, $r10 -- srli P1L, P3L, #11 -- slli $r10, P3H, #21 -- or P1L, P1L, $r10 -- slli $r10, P3H, #1 -- srli $r10, $r10, #12 -- or P1H, P1H, $r10 -- slli $r10, $r6, #20 -- or P1H, P1H, $r10 -- --.LFret: --.LF999: -- popm $r6, $r10 -- pop $lp -- ret5 $lp -- --.LFspecA: -- #ADD(P3L, P3L) -- move $r15, P3L -- add P3L, P3L, P3L -- slt $r15, P3L, $r15 -- -- #ADDC(P3H, P3H) -- add P3H, P3H, P3H -- add P3H, P3H, $r15 -- bnez $r6, .Li15 -- or $r10, P3H, P3L -- beqz $r10, .Li16 -- -- -- #NORMd($r4, P1L, P2H) -- bnez P3H, .LL38 -- bnez P3L, .LL39 -- move $r6, #0 -- j .LL40 --.LL39: -- move P3H, P3L -- move P3L, #0 -- move P1L, #32 -- sub $r6, $r6, P1L --.LL38: --#ifndef __big_endian__ --#ifdef __NDS32_PERF_EXT__ -- clz $r0, P3H --#else -- pushm $r1, P3H -- move $r0, P3H -- bal __clzsi2 -- popm $r1, $r5 --#endif --#else /* __big_endian__ */ --#ifdef __NDS32_PERF_EXT__ -- clz $r1, $r4 --#else -- push $r0 -- pushm $r2, $r5 -- move $r0, $r4 -- bal __clzsi2 -- move $r1, $r0 -- popm $r2, $r5 -- pop $r0 --#endif --#endif /* __big_endian__ */ -- beqz P1L, .LL40 -- sub $r6, $r6, P1L -- subri P2H, P1L, #32 -- srl P2H, P3L, P2H -- sll P3L, P3L, P1L -- sll P3H, P3H, P1L -- or P3H, P3H, P2H --.LL40: -- #NORMd End -- -- j .LFlab1 --.Li16: -- subri $r15, $r9, #0x7ff -- beqzs8 .LFnan -- j .LFret --.Li15: -- or $r10, P3H, P3L -- bnez $r10, .LFnan -- bnez $r9, .Li17 -- slli $r10, O1H, #1 -- or $r10, $r10, O1L -- beqz $r10, .LFnan --.Li17: -- subri $r15, $r9, #0x7ff -- bnezs8 .LFinf -- --.LFspecB: -- #ADD(O1L, O1L) -- move $r15, O1L -- add O1L, O1L, O1L -- slt $r15, O1L, $r15 -- -- #ADDC(O1H, O1H) -- add O1H, O1H, O1H -- add O1H, O1H, $r15 -- bnez $r9, .Li18 -- or $r10, O1H, O1L -- beqz $r10, .Li19 -- -- -- #NORMd($r7, P2L, P1L) -- bnez O1H, .LL41 -- bnez O1L, .LL42 -- move $r9, #0 -- j .LL43 --.LL42: -- move O1H, O1L -- move O1L, #0 -- move P2L, #32 -- sub $r9, $r9, P2L --.LL41: --#ifndef __big_endian__ --#ifdef __NDS32_PERF_EXT__ -- clz $r2, $r8 --#else -- pushm $r0, $r1 -- pushm $r3, $r5 -- move $r0, $r8 -- bal __clzsi2 -- move $r2, $r0 -- popm $r3, $r5 -- popm $r0, $r1 --#endif --#else /* __big_endian__ */ --#ifdef __NDS32_PERF_EXT__ -- clz $r3, $r7 --#else -- pushm $r0, $r2 -- pushm $r4, $r5 -- move $r0, $r7 -- bal __clzsi2 -- move $r3, $r0 -- popm $r4, $r5 -- popm $r0, $r2 --#endif --#endif /* __big_endian__ */ -- beqz P2L, .LL43 -- sub $r9, $r9, P2L -- subri P1L, P2L, #32 -- srl P1L, O1L, P1L -- sll O1L, O1L, P2L -- sll O1H, O1H, P2L -- or O1H, O1H, P1L --.LL43: -- #NORMd End -- -- j .LFlab2 --.Li19: -- move P1L, #0 -- j .LFret --.Li18: -- or $r10, O1H, O1L -- bnez $r10, .LFnan -- --.LFinf: -- move $r10, #0x7ff00000 -- or P1H, P1H, $r10 -- move P1L, #0 -- j .LFret -- --.LFnan: -- move P1H, #0xfff80000 -- move P1L, #0 -- j .LFret -- --.LFoveund: -- bgtz $r6, .LFinf -- subri P1L, $r6, #1 -- move P2L, #0 --.LL44: -- move $r10, #0x20 -- slt $r15, P1L, $r10 -- bnezs8 .LL45 -- or P2L, P2L, P3L -- move P3L, P3H -- move P3H, #0 -- addi P1L, P1L, #0xffffffe0 -- bnez P3L, .LL44 --.LL45: -- beqz P1L, .LL46 -- move P2H, P3H -- move $r10, P3L -- srl P3L, P3L, P1L -- srl P3H, P3H, P1L -- subri P1L, P1L, #0x20 -- sll P2H, P2H, P1L -- or P3L, P3L, P2H -- sll $r10, $r10, P1L -- or P2L, P2L, $r10 -- beqz P2L, .LL46 -- ori P3L, P3L, #1 --.LL46: -- #ADD(P3L, $0x400) -- move $r15, #0x400 -- add P3L, P3L, $r15 -- slt $r15, P3L, $r15 -- -- #ADDC(P3H, $0x0) -- add P3H, P3H, $r15 -- srli $r6, P3H, #31 -- j .LFlab8 -- .size __muldf3, .-__muldf3 --#endif /* L_mul_df */ -- -- -- --#ifdef L_div_sf -- -- .text -- .align 2 -- .global __divsf3 -- .type __divsf3, @function --__divsf3: -- push $lp -- pushm $r6, $r10 -- -- move $r7, #0x80000000 -- srli $r4, $r0, #23 -- andi $r4, $r4, #0xff -- srli $r6, $r1, #23 -- andi $r6, $r6, #0xff -- slli $r3, $r0, #8 -- or $r3, $r3, $r7 -- slli $r5, $r1, #8 -- or $r5, $r5, $r7 -- xor $r10, $r0, $r1 -- and $r7, $r7, $r10 -- -- addi $r10, $r4, #-1 -- slti $r15, $r10, #0xfe -- beqzs8 .LGspecA -- --.LGlab1: -- addi $r10, $r6, #-1 -- slti $r15, $r10, #0xfe -- beqzs8 .LGspecB -- --.LGlab2: -- slt $r15, $r3, $r5 -- bnezs8 .Li27 -- srli $r3, $r3, #1 -- addi $r4, $r4, #1 --.Li27: -- srli $r8, $r5, #14 -- divr $r0, $r2, $r3, $r8 -- andi $r9, $r5, #0x3fff -- mul $r1, $r9, $r0 -- slli $r2, $r2, #14 -- -- #SUB($r2, $r1) -- move $r15, $r2 -- sub $r2, $r2, $r1 -- slt $r15, $r15, $r2 -- beqzs8 .Li28 -- addi $r0, $r0, #-1 -- -- #ADD($r2, $r5) -- add $r2, $r2, $r5 -- slt $r15, $r2, $r5 --.Li28: -- divr $r3, $r2, $r2, $r8 -- mul $r1, $r9, $r3 -- slli $r2, $r2, #14 -- -- #SUB($r2, $r1) -- move $r15, $r2 -- sub $r2, $r2, $r1 -- slt $r15, $r15, $r2 -- beqzs8 .Li29 -- addi $r3, $r3, #-1 -- -- #ADD($r2, $r5) -- add $r2, $r2, $r5 -- slt $r15, $r2, $r5 --.Li29: -- slli $r10, $r0, #14 -- add $r3, $r3, $r10 -- slli $r3, $r3, #4 -- beqz $r2, .Li30 -- ori $r3, $r3, #1 --.Li30: -- subri $r10, $r6, #0x7e -- add $r4, $r4, $r10 -- addi $r10, $r4, #-1 -- slti $r15, $r10, #0xfe -- beqzs8 .LGoveund -- --.LGlab8: -- #ADD($r3, $0x80) -- move $r15, #0x80 -- add $r3, $r3, $r15 -- slt $r15, $r3, $r15 -- -- #ADDC($r4, $0x0) -- add $r4, $r4, $r15 -- srli $r10, $r3, #8 -- andi $r10, $r10, #1 -- sub $r3, $r3, $r10 -- slli $r3, $r3, #1 -- srli $r3, $r3, #9 -- slli $r10, $r4, #23 -- or $r3, $r3, $r10 -- or $r0, $r3, $r7 -- --.LG999: -- popm $r6, $r10 -- pop $lp -- ret5 $lp -- --.LGspecA: -- bnez $r4, .Li31 -- add $r3, $r3, $r3 -- beqz $r3, .Li31 --#ifdef __NDS32_PERF_EXT__ -- clz $r8, $r3 --#else -- pushm $r0, $r5 -- move $r0, $r3 -- bal __clzsi2 -- move $r8, $r0 -- popm $r0, $r5 --#endif -- sub $r4, $r4, $r8 -- sll $r3, $r3, $r8 -- j .LGlab1 --.Li31: -- bne $r6, $r4, .Li33 -- add $r10, $r5, $r5 -- beqz $r10, .LGnan --.Li33: -- subri $r15, $r6, #0xff -- beqzs8 .LGspecB -- beqz $r4, .LGzer -- add $r10, $r3, $r3 -- bnez $r10, .LGnan -- j .LGinf -- --.LGspecB: -- bnez $r6, .Li34 -- add $r5, $r5, $r5 -- beqz $r5, .LGinf --#ifdef __NDS32_PERF_EXT__ -- clz $r8, $r5 --#else -- pushm $r0, $r5 -- move $r0, $r5 -- bal __clzsi2 -- move $r8, $r0 -- popm $r0, $r5 --#endif -- sub $r6, $r6, $r8 -- sll $r5, $r5, $r8 -- j .LGlab2 --.Li34: -- add $r10, $r5, $r5 -- bnez $r10, .LGnan -- --.LGzer: -- move $r0, $r7 -- j .LG999 -- --.LGoveund: -- bgtz $r4, .LGinf -- subri $r8, $r4, #1 -- slti $r15, $r8, #0x20 -- beqzs8 .LGzer -- subri $r10, $r8, #0x20 -- sll $r4, $r3, $r10 -- srl $r3, $r3, $r8 -- beqz $r4, .Li37 -- ori $r3, $r3, #2 --.Li37: -- move $r4, #0 -- addi $r10, $r3, #0x80 -- sltsi $r15, $r10, #0 -- beqzs8 .LGlab8 -- move $r4, #1 -- j .LGlab8 -- --.LGinf: -- move $r10, #0x7f800000 -- or $r0, $r7, $r10 -- j .LG999 -- --.LGnan: -- move $r0, #0xffc00000 -- j .LG999 -- .size __divsf3, .-__divsf3 --#endif /* L_div_sf */ -- -- -- --#ifdef L_div_df -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define P2L $r2 -- #define P2H $r3 -- #define P3L $r4 -- #define P3H $r5 -- #define O1L $r7 -- #define O1H $r8 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 -- #define P3H $r4 -- #define P3L $r5 -- #define O1H $r7 -- #define O1L $r8 --#endif -- .text -- .align 2 -- .global __divdf3 -- .type __divdf3, @function --__divdf3: -- push $lp -- pushm $r6, $r10 -- -- slli $r6, P1H, #1 -- srli $r6, $r6, #21 -- slli P3H, P1H, #11 -- srli $r10, P1L, #21 -- or P3H, P3H, $r10 -- slli P3L, P1L, #11 -- move O1L, #0x80000000 -- or P3H, P3H, O1L -- slli $r9, P2H, #1 -- srli $r9, $r9, #21 -- slli O1H, P2H, #11 -- srli $r10, P2L, #21 -- or O1H, O1H, $r10 -- or O1H, O1H, O1L -- xor P1H, P1H, P2H -- and P1H, P1H, O1L -- slli O1L, P2L, #11 -- -- addi $r10, $r6, #-1 -- slti $r15, $r10, #0x7fe -- beqzs8 .LGspecA -- --.LGlab1: -- addi $r10, $r9, #-1 -- slti $r15, $r10, #0x7fe -- beqzs8 .LGspecB -- --.LGlab2: -- sub $r6, $r6, $r9 -- addi $r6, $r6, #0x3ff -- srli P3L, P3L, #1 -- slli $r10, P3H, #31 -- or P3L, P3L, $r10 -- srli P3H, P3H, #1 -- srli $r9, O1H, #16 -- divr P2H, P3H, P3H, $r9 -- move $r10, #0xffff -- and P2L, O1H, $r10 -- mul P1L, P2L, P2H -- slli P3H, P3H, #16 -- srli $r10, P3L, #16 -- or P3H, P3H, $r10 -- -- #SUB(P3H, P1L) -- move $r15, P3H -- sub P3H, P3H, P1L -- slt $r15, $r15, P3H -- beqzs8 .Li20 -- --.Lb21: -- addi P2H, P2H, #-1 -- add P3H, P3H, O1H -- slt $r15, P3H, O1H -- beqzs8 .Lb21 --.Li20: -- divr $r9, P3H, P3H, $r9 -- mul P1L, P2L, $r9 -- slli P3H, P3H, #16 -- move $r15, #0xffff -- and $r10, P3L, $r15 -- or P3H, P3H, $r10 -- -- #SUB(P3H, P1L) -- move $r15, P3H -- sub P3H, P3H, P1L -- slt $r15, $r15, P3H -- beqzs8 .Li22 -- --.Lb23: -- addi $r9, $r9, #-1 -- add P3H, P3H, O1H -- slt $r15, P3H, O1H -- beqzs8 .Lb23 --.Li22: -- slli P2H, P2H, #16 -- add P2H, P2H, $r9 -- --/* This is a 64-bit multiple. */ --#ifndef __big_endian__ --/* For little endian: ($r0, $r9) is (high, low). */ -- move $r10, $r1 --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r0, $r3, $r7 --#else -- pushm $r2, $r5 -- move $r0, $r3 -- movi $r1, #0 -- move $r2, $r7 -- movi $r3, #0 -- bal __muldi3 -- popm $r2, $r5 --#endif -- move $r9, $r0 -- move $r0, $r1 -- move $r1, $r10 --#else /* __big_endian__ */ --/* For big endian: ($r1, $r9) is (high, low). */ -- move $r10, $r0 --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r0, $r2, $r8 --#else -- pushm $r2, $r5 -- move $r1, $r2 -- movi $r0, #0 -- move $r3, $r8 -- movi $r2, #0 -- bal __muldi3 -- popm $r2, $r5 --#endif -- move $r9, $r1 -- move $r1, $r0 -- move $r0, $r10 --#endif /* __big_endian__ */ -- -- move P3L, #0 -- -- #SUB(P3L, $r9) -- move $r15, P3L -- sub P3L, P3L, $r9 -- slt $r15, $r15, P3L -- -- -- #SUBCC(P3H, P1L) -- beqzs8 .LL47 -- move $r15, P3H -- sub P3H, P3H, P1L -- slt $r15, $r15, P3H -- beqzs8 .LL48 -- subi333 P3H, P3H, #1 -- j .LL49 --.LL48: -- move $r15, P3H -- subi333 P3H, P3H, #1 -- slt $r15, $r15, P3H -- j .LL49 --.LL47: -- move $r15, P3H -- sub P3H, P3H, P1L -- slt $r15, $r15, P3H --.LL49: -- -- beqzs8 .Li24 -- --.LGlab3: -- addi P2H, P2H, #-1 -- -- #ADD(P3L, O1L) -- add P3L, P3L, O1L -- slt $r15, P3L, O1L -- -- -- #ADDCC(P3H, O1H) -- beqzs8 .LL50 -- add P3H, P3H, O1H -- slt $r15, P3H, O1H -- beqzs8 .LL51 -- addi P3H, P3H, #0x1 -- j .LL52 --.LL51: -- move $r15, #1 -- add P3H, P3H, $r15 -- slt $r15, P3H, $r15 -- j .LL52 --.LL50: -- add P3H, P3H, O1H -- slt $r15, P3H, O1H --.LL52: -- -- beqzs8 .LGlab3 --.Li24: -- bne P3H, O1H, .Li25 -- move P1L, O1L -- move P3H, P3L -- move $r9, #0 -- move P2L, $r9 -- j .Le25 --.Li25: -- srli P2L, O1H, #16 -- divr $r9, P3H, P3H, P2L -- move $r10, #0xffff -- and $r10, O1H, $r10 -- mul P1L, $r10, $r9 -- slli P3H, P3H, #16 -- srli $r15, P3L, #16 -- or P3H, P3H, $r15 -- -- #SUB(P3H, P1L) -- move $r15, P3H -- sub P3H, P3H, P1L -- slt $r15, $r15, P3H -- beqzs8 .Li26 -- --.Lb27: -- addi $r9, $r9, #-1 -- add P3H, P3H, O1H -- slt $r15, P3H, O1H -- beqzs8 .Lb27 --.Li26: -- divr P2L, P3H, P3H, P2L -- mul P1L, $r10, P2L -- slli P3H, P3H, #16 -- move $r10, #0xffff -- and $r10, P3L, $r10 -- or P3H, P3H, $r10 -- -- #SUB(P3H, P1L) -- move $r15, P3H -- sub P3H, P3H, P1L -- slt $r15, $r15, P3H -- beqzs8 .Li28 -- --.Lb29: -- addi P2L, P2L, #-1 -- add P3H, P3H, O1H -- slt $r15, P3H, O1H -- beqzs8 .Lb29 --.Li28: -- slli $r9, $r9, #16 -- add $r9, $r9, P2L -- --/* This is a 64-bit multiple. */ --#ifndef __big_endian__ --/* For little endian: ($r0, $r2) is (high, low). */ -- move $r10, $r1 --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r0, $r9, $r7 --#else -- pushm $r2, $r5 -- move $r0, $r9 -- movi $r1, #0 -- move $r2, $r7 -- movi $r3, #0 -- bal __muldi3 -- popm $r2, $r5 --#endif -- move $r2, $r0 -- move $r0, $r1 -- move $r1, $r10 --#else /* __big_endian__ */ --/* For big endian: ($r1, $r3) is (high, low). */ -- move $r10, $r0 --#ifndef __NDS32_ISA_V3M__ -- mulr64 $r0, $r9, $r8 --#else -- pushm $r2, $r5 -- move $r0, $r9 -- movi $r1, #0 -- move $r2, $r7 -- movi $r3, #0 -- bal __muldi3 -- popm $r2, $r5 --#endif -- move $r3, $r1 -- move $r1, $r0 -- move $r0, $r10 --#endif /* __big_endian__ */ -- --.Le25: -- move P3L, #0 -- -- #SUB(P3L, P2L) -- move $r15, P3L -- sub P3L, P3L, P2L -- slt $r15, $r15, P3L -- -- -- #SUBCC(P3H, P1L) -- beqzs8 .LL53 -- move $r15, P3H -- sub P3H, P3H, P1L -- slt $r15, $r15, P3H -- beqzs8 .LL54 -- subi333 P3H, P3H, #1 -- j .LL55 --.LL54: -- move $r15, P3H -- subi333 P3H, P3H, #1 -- slt $r15, $r15, P3H -- j .LL55 --.LL53: -- move $r15, P3H -- sub P3H, P3H, P1L -- slt $r15, $r15, P3H --.LL55: -- -- beqzs8 .Li30 -- --.LGlab4: -- addi $r9, $r9, #-1 -- -- #ADD(P3L, O1L) -- add P3L, P3L, O1L -- slt $r15, P3L, O1L -- -- -- #ADDCC(P3H, O1H) -- beqzs8 .LL56 -- add P3H, P3H, O1H -- slt $r15, P3H, O1H -- beqzs8 .LL57 -- addi P3H, P3H, #0x1 -- j .LL58 --.LL57: -- move $r15, #1 -- add P3H, P3H, $r15 -- slt $r15, P3H, $r15 -- j .LL58 --.LL56: -- add P3H, P3H, O1H -- slt $r15, P3H, O1H --.LL58: -- -- beqzs8 .LGlab4 --.Li30: -- sltsi $r15, P2H, #0 -- bnezs8 .Li31 -- -- #ADD($r9, $r9) -- move $r15, $r9 -- add $r9, $r9, $r9 -- slt $r15, $r9, $r15 -- -- #ADDC(P2H, P2H) -- add P2H, P2H, P2H -- add P2H, P2H, $r15 -- addi $r6, $r6, #-1 --.Li31: -- or $r10, P3H, P3L -- beqz $r10, .Li32 -- ori $r9, $r9, #1 --.Li32: -- move P3H, P2H -- move P3L, $r9 -- addi $r10, $r6, #-1 -- slti $r15, $r10, #0x7fe -- beqzs8 .LGoveund -- -- #ADD(P3L, $0x400) -- move $r15, #0x400 -- add P3L, P3L, $r15 -- slt $r15, P3L, $r15 -- -- -- #ADDCC(P3H, $0x0) -- beqzs8 .LL61 -- add P3H, P3H, $r15 -- slt $r15, P3H, $r15 --.LL61: -- -- #ADDC($r6, $0x0) -- add $r6, $r6, $r15 -- --.LGlab8: -- srli $r10, P3L, #11 -- andi $r10, $r10, #1 -- sub P3L, P3L, $r10 -- srli P1L, P3L, #11 -- slli $r10, P3H, #21 -- or P1L, P1L, $r10 -- slli $r10, P3H, #1 -- srli $r10, $r10, #12 -- or P1H, P1H, $r10 -- slli $r10, $r6, #20 -- or P1H, P1H, $r10 -- --.LGret: --.LG999: -- popm $r6, $r10 -- pop $lp -- ret5 $lp -- --.LGoveund: -- bgtz $r6, .LGinf -- subri P2H, $r6, #1 -- move P1L, #0 --.LL62: -- move $r10, #0x20 -- slt $r15, P2H, $r10 -- bnezs8 .LL63 -- or P1L, P1L, P3L -- move P3L, P3H -- move P3H, #0 -- addi P2H, P2H, #0xffffffe0 -- bnez P3L, .LL62 --.LL63: -- beqz P2H, .LL64 -- move P2L, P3H -- move $r10, P3L -- srl P3L, P3L, P2H -- srl P3H, P3H, P2H -- subri P2H, P2H, #0x20 -- sll P2L, P2L, P2H -- or P3L, P3L, P2L -- sll $r10, $r10, P2H -- or P1L, P1L, $r10 -- beqz P1L, .LL64 -- ori P3L, P3L, #1 --.LL64: -- #ADD(P3L, $0x400) -- move $r15, #0x400 -- add P3L, P3L, $r15 -- slt $r15, P3L, $r15 -- -- #ADDC(P3H, $0x0) -- add P3H, P3H, $r15 -- srli $r6, P3H, #31 -- j .LGlab8 -- --.LGspecA: -- #ADD(P3L, P3L) -- move $r15, P3L -- add P3L, P3L, P3L -- slt $r15, P3L, $r15 -- -- #ADDC(P3H, P3H) -- add P3H, P3H, P3H -- add P3H, P3H, $r15 -- bnez $r6, .Li33 -- or $r10, P3H, P3L -- beqz $r10, .Li33 -- -- -- #NORMd($r4, P2H, P2L) -- bnez P3H, .LL65 -- bnez P3L, .LL66 -- move $r6, #0 -- j .LL67 --.LL66: -- move P3H, P3L -- move P3L, #0 -- move P2H, #32 -- sub $r6, $r6, P2H --.LL65: --#ifndef __big_endian__ --#ifdef __NDS32_PERF_EXT__ -- clz $r3, $r5 --#else -- pushm $r0, $r2 -- pushm $r4, $r5 -- move $r0, $r5 -- bal __clzsi2 -- move $r3, $r0 -- popm $r4, $r5 -- popm $r0, $r2 --#endif --#else /* __big_endian__ */ --#ifdef __NDS32_PERF_EXT__ -- clz $r2, $r4 --#else -- pushm $r0, $r1 -- pushm $r3, $r5 -- move $r0, $r4 -- bal __clzsi2 -- move $r2, $r0 -- popm $r3, $r5 -- popm $r0, $r1 --#endif --#endif /* __big_endian_ */ -- beqz P2H, .LL67 -- sub $r6, $r6, P2H -- subri P2L, P2H, #32 -- srl P2L, P3L, P2L -- sll P3L, P3L, P2H -- sll P3H, P3H, P2H -- or P3H, P3H, P2L --.LL67: -- #NORMd End -- -- j .LGlab1 --.Li33: -- bne $r6, $r9, .Li35 -- slli $r10, O1H, #1 -- or $r10, $r10, O1L -- beqz $r10, .LGnan --.Li35: -- subri $r15, $r9, #0x7ff -- beqzs8 .LGspecB -- beqz $r6, .LGret -- or $r10, P3H, P3L -- bnez $r10, .LGnan -- --.LGinf: -- move $r10, #0x7ff00000 -- or P1H, P1H, $r10 -- move P1L, #0 -- j .LGret -- --.LGspecB: -- #ADD(O1L, O1L) -- move $r15, O1L -- add O1L, O1L, O1L -- slt $r15, O1L, $r15 -- -- #ADDC(O1H, O1H) -- add O1H, O1H, O1H -- add O1H, O1H, $r15 -- bnez $r9, .Li36 -- or $r10, O1H, O1L -- beqz $r10, .LGinf -- -- -- #NORMd($r7, P2H, P2L) -- bnez O1H, .LL68 -- bnez O1L, .LL69 -- move $r9, #0 -- j .LL70 --.LL69: -- move O1H, O1L -- move O1L, #0 -- move P2H, #32 -- sub $r9, $r9, P2H --.LL68: --#ifndef __big_endian__ --#ifdef __NDS32_PERF_EXT__ -- clz $r3, $r8 --#else -- pushm $r0, $r2 -- pushm $r4, $r5 -- move $r0, $r8 -- bal __clzsi2 -- move $r3, $r0 -- popm $r4, $r5 -- popm $r0, $r2 --#endif --#else /* __big_endian__ */ --#ifdef __NDS32_PERF_EXT__ -- clz $r2, $r7 --#else -- pushm $r0, $r1 -- pushm $r3, $r5 -- move $r0, $r7 -- bal __clzsi2 -- move $r2, $r0 -- popm $r3, $r5 -- popm $r0, $r1 --#endif --#endif /* __big_endian__ */ -- beqz P2H, .LL70 -- sub $r9, $r9, P2H -- subri P2L, P2H, #32 -- srl P2L, O1L, P2L -- sll O1L, O1L, P2H -- sll O1H, O1H, P2H -- or O1H, O1H, P2L --.LL70: -- #NORMd End -- -- j .LGlab2 --.Li36: -- or $r10, O1H, O1L -- beqz $r10, .Li38 -- --.LGnan: -- move P1H, #0xfff80000 --.Li38: -- move P1L, #0 -- j .LGret -- .size __divdf3, .-__divdf3 --#endif /* L_div_df */ -- -- -- --#ifdef L_negate_sf -- -- .text -- .align 2 -- .global __negsf2 -- .type __negsf2, @function --__negsf2: -- push $lp -- -- move $r1, #0x80000000 -- xor $r0, $r0, $r1 -- --.LN999: -- pop $lp -- ret5 $lp -- .size __negsf2, .-__negsf2 --#endif /* L_negate_sf */ -- -- -- --#ifdef L_negate_df -- --#ifndef __big_endian__ -- #define P1H $r1 --#else -- #define P1H $r0 --#endif -- .text -- .align 2 -- .global __negdf2 -- .type __negdf2, @function --__negdf2: -- push $lp -- -- move $r2, #0x80000000 -- xor P1H, P1H, $r2 -- --.LP999: -- pop $lp -- ret5 $lp -- .size __negdf2, .-__negdf2 --#endif /* L_negate_df */ -- -- -- --#ifdef L_sf_to_df -- --#ifndef __big_endian__ -- #define O1L $r1 -- #define O1H $r2 --#else -- #define O1H $r1 -- #define O1L $r2 --#endif -- .text -- .align 2 -- .global __extendsfdf2 -- .type __extendsfdf2, @function --__extendsfdf2: -- push $lp -- -- srli $r3, $r0, #23 -- andi $r3, $r3, #0xff -- move $r5, #0x80000000 -- and O1H, $r0, $r5 -- addi $r5, $r3, #-1 -- slti $r15, $r5, #0xfe -- beqzs8 .LJspec -- --.LJlab1: -- addi $r3, $r3, #0x380 -- slli $r5, $r0, #9 -- srli $r5, $r5, #12 -- or O1H, O1H, $r5 -- slli O1L, $r0, #29 -- --.LJret: -- slli $r5, $r3, #20 -- or O1H, O1H, $r5 -- move $r0, $r1 -- move $r1, $r2 -- --.LJ999: -- pop $lp -- ret5 $lp -- --.LJspec: -- move O1L, #0 -- add $r0, $r0, $r0 -- beqz $r0, .LJret -- bnez $r3, .Li42 -- --.Lb43: -- addi $r3, $r3, #-1 -- add $r0, $r0, $r0 -- move $r5, #0x800000 -- slt $r15, $r0, $r5 -- bnezs8 .Lb43 -- j .LJlab1 --.Li42: -- move $r3, #0x7ff -- move $r5, #0xff000000 -- slt $r15, $r5, $r0 -- beqzs8 .LJret -- move O1H, #0xfff80000 -- j .LJret -- .size __extendsfdf2, .-__extendsfdf2 --#endif /* L_sf_to_df */ -- -- -- --#ifdef L_df_to_sf -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define P2L $r2 -- #define P2H $r3 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 --#endif -- .text -- .align 2 -- .global __truncdfsf2 -- .type __truncdfsf2, @function --__truncdfsf2: -- push $lp -- pushm $r6, $r8 -- -- slli P2H, P1H, #11 -- srli $r7, P1L, #21 -- or P2H, P2H, $r7 -- slli P2L, P1L, #11 -- move $r7, #0x80000000 -- or P2H, P2H, $r7 -- and $r5, P1H, $r7 -- slli $r4, P1H, #1 -- srli $r4, $r4, #21 -- addi $r4, $r4, #0xfffffc80 -- addi $r7, $r4, #-1 -- slti $r15, $r7, #0xfe -- beqzs8 .LKspec -- --.LKlab1: -- beqz P2L, .Li45 -- ori P2H, P2H, #1 --.Li45: -- #ADD(P2H, $0x80) -- move $r15, #0x80 -- add P2H, P2H, $r15 -- slt $r15, P2H, $r15 -- -- #ADDC($r4, $0x0) -- add $r4, $r4, $r15 -- srli $r7, P2H, #8 -- andi $r7, $r7, #1 -- sub P2H, P2H, $r7 -- slli P2H, P2H, #1 -- srli P2H, P2H, #9 -- slli $r7, $r4, #23 -- or P2H, P2H, $r7 -- or $r0, P2H, $r5 -- --.LK999: -- popm $r6, $r8 -- pop $lp -- ret5 $lp -- --.LKspec: -- subri $r15, $r4, #0x47f -- bnezs8 .Li46 -- slli $r7, P2H, #1 -- or $r7, $r7, P2L -- beqz $r7, .Li46 -- move $r0, #0xffc00000 -- j .LK999 --.Li46: -- sltsi $r15, $r4, #0xff -- bnezs8 .Li48 -- move $r7, #0x7f800000 -- or $r0, $r5, $r7 -- j .LK999 --.Li48: -- subri $r6, $r4, #1 -- move $r7, #0x20 -- slt $r15, $r6, $r7 -- bnezs8 .Li49 -- move $r0, $r5 -- j .LK999 --.Li49: -- subri $r8, $r6, #0x20 -- sll $r7, P2H, $r8 -- or P2L, P2L, $r7 -- srl P2H, P2H, $r6 -- move $r4, #0 -- move $r7, #0x80000000 -- or P2H, P2H, $r7 -- j .LKlab1 -- .size __truncdfsf2, .-__truncdfsf2 --#endif /* L_df_to_sf */ -- -- -- --#ifdef L_df_to_si -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 --#else -- #define P1H $r0 -- #define P1L $r1 --#endif -- .global __fixdfsi -- .type __fixdfsi, @function --__fixdfsi: -- push $lp -- pushm $r6, $r6 -- -- slli $r3, P1H, #11 -- srli $r6, P1L, #21 -- or $r3, $r3, $r6 -- move $r6, #0x80000000 -- or $r3, $r3, $r6 -- slli $r6, P1H, #1 -- srli $r6, $r6, #21 -- subri $r2, $r6, #0x41e -- blez $r2, .LLnaninf -- move $r6, #0x20 -- slt $r15, $r2, $r6 -- bnezs8 .LL72 -- move $r3, #0 --.LL72: -- srl $r3, $r3, $r2 -- sltsi $r15, P1H, #0 -- beqzs8 .Li50 -- subri $r3, $r3, #0 --.Li50: -- move $r0, $r3 -- --.LL999: -- popm $r6, $r6 -- pop $lp -- ret5 $lp -- --.LLnaninf: -- beqz P1L, .Li51 -- ori P1H, P1H, #1 --.Li51: -- move $r6, #0x7ff00000 -- slt $r15, $r6, P1H -- beqzs8 .Li52 -- move $r0, #0x80000000 -- j .LL999 --.Li52: -- move $r0, #0x7fffffff -- j .LL999 -- .size __fixdfsi, .-__fixdfsi --#endif /* L_df_to_si */ -- -- -- --#ifdef L_fixsfdi -- --#ifndef __big_endian__ -- #define O1L $r1 -- #define O1H $r2 --#else -- #define O1H $r1 -- #define O1L $r2 --#endif -- .text -- .align 2 -- .global __fixsfdi -- .type __fixsfdi, @function --__fixsfdi: -- push $lp -- -- srli $r3, $r0, #23 -- andi $r3, $r3, #0xff -- slli O1H, $r0, #8 -- move $r5, #0x80000000 -- or O1H, O1H, $r5 -- move O1L, #0 -- sltsi $r15, $r3, #0xbe -- beqzs8 .LCinfnan -- subri $r3, $r3, #0xbe --.LL8: -- move $r5, #0x20 -- slt $r15, $r3, $r5 -- bnezs8 .LL9 -- move O1L, O1H -- move O1H, #0 -- addi $r3, $r3, #0xffffffe0 -- bnez O1L, .LL8 --.LL9: -- beqz $r3, .LL10 -- move $r4, O1H -- srl O1L, O1L, $r3 -- srl O1H, O1H, $r3 -- subri $r3, $r3, #0x20 -- sll $r4, $r4, $r3 -- or O1L, O1L, $r4 --.LL10: -- sltsi $r15, $r0, #0 -- beqzs8 .LCret -- -- subri O1H, O1H, #0 -- beqz O1L, .LL11 -- subri O1L, O1L, #0 -- subi45 O1H, #1 --.LL11: -- --.LCret: -- move $r0, $r1 -- move $r1, $r2 -- --.LC999: -- pop $lp -- ret5 $lp -- --.LCinfnan: -- sltsi $r15, $r0, #0 -- bnezs8 .LCret3 -- subri $r15, $r3, #0xff -- bnezs8 .Li7 -- slli $r5, O1H, #1 -- beqz $r5, .Li7 -- --.LCret3: -- move O1H, #0x80000000 -- j .LCret --.Li7: -- move O1H, #0x7fffffff -- move O1L, #-1 -- j .LCret -- .size __fixsfdi, .-__fixsfdi --#endif /* L_fixsfdi */ -- -- -- --#ifdef L_fixdfdi -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define O1L $r3 -- #define O1H $r4 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define O1H $r3 -- #define O1L $r4 --#endif -- .text -- .align 2 -- .global __fixdfdi -- .type __fixdfdi, @function --__fixdfdi: -- push $lp -- pushm $r6, $r6 -- -- slli $r5, P1H, #1 -- srli $r5, $r5, #21 -- slli O1H, P1H, #11 -- srli $r6, P1L, #21 -- or O1H, O1H, $r6 -- slli O1L, P1L, #11 -- move $r6, #0x80000000 -- or O1H, O1H, $r6 -- slti $r15, $r5, #0x43e -- beqzs8 .LCnaninf -- subri $r2, $r5, #0x43e --.LL14: -- move $r6, #0x20 -- slt $r15, $r2, $r6 -- bnezs8 .LL15 -- move O1L, O1H -- move O1H, #0 -- addi $r2, $r2, #0xffffffe0 -- bnez O1L, .LL14 --.LL15: -- beqz $r2, .LL16 -- move P1L, O1H -- srl O1L, O1L, $r2 -- srl O1H, O1H, $r2 -- subri $r2, $r2, #0x20 -- sll P1L, P1L, $r2 -- or O1L, O1L, P1L --.LL16: -- sltsi $r15, P1H, #0 -- beqzs8 .LCret -- -- subri O1H, O1H, #0 -- beqz O1L, .LL17 -- subri O1L, O1L, #0 -- subi45 O1H, #1 --.LL17: -- --.LCret: -- move P1L, O1L -- move P1H, O1H -- --.LC999: -- popm $r6, $r6 -- pop $lp -- ret5 $lp -- --.LCnaninf: -- sltsi $r15, P1H, #0 -- bnezs8 .LCret3 -- subri $r15, $r5, #0x7ff -- bnezs8 .Li5 -- slli $r6, O1H, #1 -- or $r6, $r6, O1L -- beqz $r6, .Li5 -- --.LCret3: -- move O1H, #0x80000000 -- move O1L, #0 -- j .LCret --.Li5: -- move O1H, #0x7fffffff -- move O1L, #-1 -- j .LCret -- .size __fixdfdi, .-__fixdfdi --#endif /* L_fixdfdi */ -- -- -- --#ifdef L_fixunssfsi -- -- .global __fixunssfsi -- .type __fixunssfsi, @function --__fixunssfsi: -- push $lp -- -- slli $r1, $r0, #8 -- move $r3, #0x80000000 -- or $r1, $r1, $r3 -- srli $r3, $r0, #23 -- andi $r3, $r3, #0xff -- subri $r2, $r3, #0x9e -- sltsi $r15, $r2, #0 -- bnezs8 .LLspec -- sltsi $r15, $r2, #0x20 -- bnezs8 .Li45 -- move $r0, #0 -- j .LL999 --.Li45: -- srl $r1, $r1, $r2 -- sltsi $r15, $r0, #0 -- beqzs8 .Li46 -- subri $r1, $r1, #0 --.Li46: -- move $r0, $r1 -- --.LL999: -- pop $lp -- ret5 $lp -- --.LLspec: -- move $r3, #0x7f800000 -- slt $r15, $r3, $r0 -- beqzs8 .Li47 -- move $r0, #0x80000000 -- j .LL999 --.Li47: -- move $r0, #-1 -- j .LL999 -- .size __fixunssfsi, .-__fixunssfsi --#endif /* L_fixunssfsi */ -- -- -- --#ifdef L_fixunsdfsi -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 --#else -- #define P1H $r0 -- #define P1L $r1 --#endif -- .text -- .align 2 -- .global __fixunsdfsi -- .type __fixunsdfsi, @function --__fixunsdfsi: -- push $lp -- pushm $r6, $r6 -- -- slli $r3, P1H, #11 -- srli $r6, P1L, #21 -- or $r3, $r3, $r6 -- move $r6, #0x80000000 -- or $r3, $r3, $r6 -- slli $r6, P1H, #1 -- srli $r6, $r6, #21 -- subri $r2, $r6, #0x41e -- sltsi $r15, $r2, #0 -- bnezs8 .LNnaninf -- move $r6, #0x20 -- slt $r15, $r2, $r6 -- bnezs8 .LL73 -- move $r3, #0 --.LL73: -- srl $r3, $r3, $r2 -- sltsi $r15, P1H, #0 -- beqzs8 .Li53 -- subri $r3, $r3, #0 --.Li53: -- move $r0, $r3 -- --.LN999: -- popm $r6, $r6 -- pop $lp -- ret5 $lp -- --.LNnaninf: -- beqz P1L, .Li54 -- ori P1H, P1H, #1 --.Li54: -- move $r6, #0x7ff00000 -- slt $r15, $r6, P1H -- beqzs8 .Li55 -- move $r0, #0x80000000 -- j .LN999 --.Li55: -- move $r0, #-1 -- j .LN999 -- .size __fixunsdfsi, .-__fixunsdfsi --#endif /* L_fixunsdfsi */ -- -- -- --#ifdef L_fixunssfdi -- --#ifndef __big_endian__ -- #define O1L $r1 -- #define O1H $r2 --#else -- #define O1H $r1 -- #define O1L $r2 --#endif -- .text -- .align 2 -- .global __fixunssfdi -- .type __fixunssfdi, @function --__fixunssfdi: -- push $lp -- -- srli $r3, $r0, #23 -- andi $r3, $r3, #0xff -- slli O1H, $r0, #8 -- move $r5, #0x80000000 -- or O1H, O1H, $r5 -- move O1L, #0 -- sltsi $r15, $r3, #0xbe -- beqzs8 .LDinfnan -- subri $r3, $r3, #0xbe --.LL12: -- move $r5, #0x20 -- slt $r15, $r3, $r5 -- bnezs8 .LL13 -- move O1L, O1H -- move O1H, #0 -- addi $r3, $r3, #0xffffffe0 -- bnez O1L, .LL12 --.LL13: -- beqz $r3, .LL14 -- move $r4, O1H -- srl O1L, O1L, $r3 -- srl O1H, O1H, $r3 -- subri $r3, $r3, #0x20 -- sll $r4, $r4, $r3 -- or O1L, O1L, $r4 --.LL14: -- sltsi $r15, $r0, #0 -- beqzs8 .LDret -- -- subri O1H, O1H, #0 -- beqz O1L, .LL15 -- subri O1L, O1L, #0 -- subi45 O1H, #1 --.LL15: -- --.LDret: -- move $r0, $r1 -- move $r1, $r2 -- --.LD999: -- pop $lp -- ret5 $lp -- --.LDinfnan: -- move O1H, #0x80000000 -- move O1L, #0 -- j .LDret -- .size __fixunssfdi, .-__fixunssfdi --#endif /* L_fixunssfdi */ -- -- -- --#ifdef L_fixunsdfdi -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define O1L $r3 -- #define O1H $r4 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define O1H $r3 -- #define O1L $r4 --#endif -- .text -- .align 2 -- .global __fixunsdfdi -- .type __fixunsdfdi, @function --__fixunsdfdi: -- push $lp -- pushm $r6, $r6 -- -- slli $r5, P1H, #1 -- srli $r5, $r5, #21 -- slli O1H, P1H, #11 -- srli $r6, P1L, #21 -- or O1H, O1H, $r6 -- slli O1L, P1L, #11 -- move $r6, #0x80000000 -- or O1H, O1H, $r6 -- slti $r15, $r5, #0x43e -- beqzs8 .LDnaninf -- subri $r2, $r5, #0x43e --.LL18: -- move $r6, #0x20 -- slt $r15, $r2, $r6 -- bnezs8 .LL19 -- move O1L, O1H -- move O1H, #0 -- addi $r2, $r2, #0xffffffe0 -- bnez O1L, .LL18 --.LL19: -- beqz $r2, .LL20 -- move P1L, O1H -- srl O1L, O1L, $r2 -- srl O1H, O1H, $r2 -- subri $r2, $r2, #0x20 -- sll P1L, P1L, $r2 -- or O1L, O1L, P1L --.LL20: -- sltsi $r15, P1H, #0 -- beqzs8 .LDret -- -- subri O1H, O1H, #0 -- beqz O1L, .LL21 -- subri O1L, O1L, #0 -- subi45 O1H, #1 --.LL21: -- --.LDret: -- move P1L, O1L -- move P1H, O1H -- --.LD999: -- popm $r6, $r6 -- pop $lp -- ret5 $lp -- --.LDnaninf: -- move O1H, #0x80000000 -- move O1L, #0 -- j .LDret -- .size __fixunsdfdi, .-__fixunsdfdi --#endif /* L_fixunsdfdi */ -- -- -- --#ifdef L_si_to_sf -- -- .text -- .align 2 -- .global __floatsisf -- .type __floatsisf, @function --__floatsisf: -- push $lp -- -- move $r4, #0x80000000 -- and $r2, $r0, $r4 -- beqz $r0, .Li39 -- sltsi $r15, $r0, #0 -- beqzs8 .Li40 -- subri $r0, $r0, #0 --.Li40: -- move $r1, #0x9e --#ifdef __NDS32_PERF_EXT__ -- clz $r3, $r0 --#else -- pushm $r0, $r2 -- pushm $r4, $r5 -- bal __clzsi2 -- move $r3, $r0 -- popm $r4, $r5 -- popm $r0, $r2 --#endif -- sub $r1, $r1, $r3 -- sll $r0, $r0, $r3 -- -- #ADD($r0, $0x80) -- move $r15, #0x80 -- add $r0, $r0, $r15 -- slt $r15, $r0, $r15 -- -- #ADDC($r1, $0x0) -- add $r1, $r1, $r15 -- srai $r4, $r0, #8 -- andi $r4, $r4, #1 -- sub $r0, $r0, $r4 -- slli $r0, $r0, #1 -- srli $r0, $r0, #9 -- slli $r4, $r1, #23 -- or $r0, $r0, $r4 --.Li39: -- or $r0, $r0, $r2 -- --.LH999: -- pop $lp -- ret5 $lp -- .size __floatsisf, .-__floatsisf --#endif /* L_si_to_sf */ -- -- -- --#ifdef L_si_to_df -- --#ifndef __big_endian__ -- #define O1L $r1 -- #define O1H $r2 -- #define O2L $r4 -- #define O2H $r5 --#else -- #define O1H $r1 -- #define O1L $r2 -- #define O2H $r4 -- #define O2L $r5 --#endif -- .text -- .align 2 -- .global __floatsidf -- .type __floatsidf, @function --__floatsidf: -- push $lp -- pushm $r6, $r6 -- -- move O1L, #0 -- move O2H, O1L -- move $r3, O1L -- move O1H, $r0 -- beqz O1H, .Li39 -- sltsi $r15, O1H, #0 -- beqzs8 .Li40 -- move O2H, #0x80000000 -- -- subri O1H, O1H, #0 -- beqz O1L, .LL71 -- subri O1L, O1L, #0 -- subi45 O1H, #1 --.LL71: --.Li40: -- move $r3, #0x41e --#ifndef __big_endian__ --#ifdef __NDS32_PERF_EXT__ -- clz $r4, $r2 --#else -- pushm $r0, $r3 -- push $r5 -- move $r0, $r2 -- bal __clzsi2 -- move $r4, $r0 -- pop $r5 -- popm $r0, $r3 --#endif --#else /* __big_endian__ */ --#ifdef __NDS32_PERF_EXT__ -- clz $r5, $r1 --#else -- pushm $r0, $r4 -- move $r0, $r1 -- bal __clzsi2 -- move $r5, $r0 -- popm $r0, $r4 --#endif --#endif /* __big_endian__ */ -- sub $r3, $r3, O2L -- sll O1H, O1H, O2L --.Li39: -- srli O2L, O1L, #11 -- slli $r6, O1H, #21 -- or O2L, O2L, $r6 -- slli $r6, O1H, #1 -- srli $r6, $r6, #12 -- or O2H, O2H, $r6 -- slli $r6, $r3, #20 -- or O2H, O2H, $r6 -- move $r0, $r4 -- move $r1, $r5 -- --.LH999: -- popm $r6, $r6 -- pop $lp -- ret5 $lp -- .size __floatsidf, .-__floatsidf --#endif /* L_si_to_df */ -- -- -- --#ifdef L_floatdisf -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define P2L $r2 -- #define P2H $r3 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 --#endif -- .text -- .align 2 -- .global __floatdisf -- .type __floatdisf, @function --__floatdisf: -- push $lp -- pushm $r6, $r7 -- -- move $r7, #0x80000000 -- and $r5, P1H, $r7 -- move P2H, P1H -- move P2L, P1L -- or $r7, P1H, P1L -- beqz $r7, .Li1 -- sltsi $r15, P1H, #0 -- beqzs8 .Li2 -- -- subri P2H, P2H, #0 -- beqz P2L, .LL1 -- subri P2L, P2L, #0 -- subi45 P2H, #1 --.LL1: --.Li2: -- move $r4, #0xbe -- -- -- #NORMd($r2, $r6, P1L) -- bnez P2H, .LL2 -- bnez P2L, .LL3 -- move $r4, #0 -- j .LL4 --.LL3: -- move P2H, P2L -- move P2L, #0 -- move $r6, #32 -- sub $r4, $r4, $r6 --.LL2: --#ifdef __NDS32_PERF_EXT__ -- clz $r6, P2H --#else -- pushm $r0, $r5 -- move $r0, P2H -- bal __clzsi2 -- move $r6, $r0 -- popm $r0, $r5 --#endif -- beqz $r6, .LL4 -- sub $r4, $r4, $r6 -- subri P1L, $r6, #32 -- srl P1L, P2L, P1L -- sll P2L, P2L, $r6 -- sll P2H, P2H, $r6 -- or P2H, P2H, P1L --.LL4: -- #NORMd End -- -- beqz P2L, .Li3 -- ori P2H, P2H, #1 --.Li3: -- #ADD(P2H, $0x80) -- move $r15, #0x80 -- add P2H, P2H, $r15 -- slt $r15, P2H, $r15 -- -- #ADDC($r4, $0x0) -- add $r4, $r4, $r15 -- srli $r7, P2H, #8 -- andi $r7, $r7, #1 -- sub P2H, P2H, $r7 -- slli P2H, P2H, #1 -- srli P2H, P2H, #9 -- slli $r7, $r4, #23 -- or P2H, P2H, $r7 --.Li1: -- or $r0, P2H, $r5 -- --.LA999: -- popm $r6, $r7 -- pop $lp -- ret5 $lp -- .size __floatdisf, .-__floatdisf --#endif /* L_floatdisf */ -- -- -- --#ifdef L_floatdidf -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define P2L $r2 -- #define P2H $r3 -- #define O1L $r5 -- #define O1H $r6 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 -- #define O1H $r5 -- #define O1L $r6 --#endif -- .text -- .align 2 -- .global __floatdidf -- .type __floatdidf, @function --__floatdidf: -- push $lp -- pushm $r6, $r8 -- -- move $r4, #0 -- move $r7, $r4 -- move P2H, P1H -- move P2L, P1L -- or $r8, P1H, P1L -- beqz $r8, .Li1 -- move $r4, #0x43e -- sltsi $r15, P1H, #0 -- beqzs8 .Li2 -- move $r7, #0x80000000 -- -- subri P2H, P2H, #0 -- beqz P2L, .LL1 -- subri P2L, P2L, #0 -- subi45 P2H, #1 --.LL1: -- --.Li2: -- #NORMd($r2, O1H, O1L) -- bnez P2H, .LL2 -- bnez P2L, .LL3 -- move $r4, #0 -- j .LL4 --.LL3: -- move P2H, P2L -- move P2L, #0 -- move O1H, #32 -- sub $r4, $r4, O1H --.LL2: --#ifdef __NDS32_PERF_EXT__ -- clz O1H, P2H --#else /* not __NDS32_PERF_EXT__ */ --/* -- Replace clz with function call. -- clz O1H, P2H -- EL: clz $r6, $r3 -- EB: clz $r5, $r2 --*/ --#ifndef __big_endian__ -- pushm $r0, $r5 -- move $r0, $r3 -- bal __clzsi2 -- move $r6, $r0 -- popm $r0, $r5 --#else -- pushm $r0, $r4 -- move $r0, $r2 -- bal __clzsi2 -- move $r5, $r0 -- popm $r0, $r4 --#endif --#endif /* not __NDS32_PERF_EXT__ */ -- beqz O1H, .LL4 -- sub $r4, $r4, O1H -- subri O1L, O1H, #32 -- srl O1L, P2L, O1L -- sll P2L, P2L, O1H -- sll P2H, P2H, O1H -- or P2H, P2H, O1L --.LL4: -- #NORMd End -- -- #ADD(P2L, $0x400) -- move $r15, #0x400 -- add P2L, P2L, $r15 -- slt $r15, P2L, $r15 -- -- -- #ADDCC(P2H, $0x0) -- beqzs8 .LL7 -- add P2H, P2H, $r15 -- slt $r15, P2H, $r15 --.LL7: -- -- #ADDC($r4, $0x0) -- add $r4, $r4, $r15 -- srli $r8, P2L, #11 -- andi $r8, $r8, #1 -- sub P2L, P2L, $r8 --.Li1: -- srli O1L, P2L, #11 -- slli $r8, P2H, #21 -- or O1L, O1L, $r8 -- slli O1H, P2H, #1 -- srli O1H, O1H, #12 -- slli $r8, $r4, #20 -- or O1H, O1H, $r8 -- or O1H, O1H, $r7 -- move P1L, O1L -- move P1H, O1H -- --.LA999: -- popm $r6, $r8 -- pop $lp -- ret5 $lp -- .size __floatdidf, .-__floatdidf --#endif /* L_floatdidf */ -- -- -- --#ifdef L_floatunsisf -- -- .text -- .align 2 -- .global __floatunsisf -- .type __floatunsisf, @function --__floatunsisf: -- push $lp -- -- beqz $r0, .Li41 -- move $r2, #0x9e --#ifdef __NDS32_PERF_EXT__ -- clz $r1, $r0 --#else -- push $r0 -- pushm $r2, $r5 -- bal __clzsi2 -- move $r1, $r0 -- popm $r2, $r5 -- pop $r0 --#endif -- -- sub $r2, $r2, $r1 -- sll $r0, $r0, $r1 -- -- #ADD($r0, $0x80) -- move $r15, #0x80 -- add $r0, $r0, $r15 -- slt $r15, $r0, $r15 -- -- #ADDC($r2, $0x0) -- add $r2, $r2, $r15 -- srli $r3, $r0, #8 -- andi $r3, $r3, #1 -- sub $r0, $r0, $r3 -- slli $r0, $r0, #1 -- srli $r0, $r0, #9 -- slli $r3, $r2, #23 -- or $r0, $r0, $r3 -- --.Li41: --.LI999: -- pop $lp -- ret5 $lp -- .size __floatunsisf, .-__floatunsisf --#endif /* L_floatunsisf */ -- -- -- --#ifdef L_floatunsidf -- --#ifndef __big_endian__ -- #define O1L $r1 -- #define O1H $r2 -- #define O2L $r4 -- #define O2H $r5 --#else -- #define O1H $r1 -- #define O1L $r2 -- #define O2H $r4 -- #define O2L $r5 --#endif -- .text -- .align 2 -- .global __floatunsidf -- .type __floatunsidf, @function --__floatunsidf: -- push $lp -- pushm $r6, $r6 -- -- move O1L, #0 -- move $r3, O1L -- move O1H, $r0 -- beqz O1H, .Li41 -- move $r3, #0x41e --#ifndef __big_endian__ --#ifdef __NDS32_PERF_EXT__ -- clz $r5, $r2 --#else -- pushm $r0, $r4 -- move $r0, $r2 -- bal __clzsi2 -- move $r5, $r0 -- popm $r0, $r4 --#endif --#else /* __big_endian__ */ --#ifdef __NDS32_PERF_EXT__ -- clz $r4, $r1 --#else -- pushm $r0, $r3 -- push $r5 -- move $r0, $r1 -- bal __clzsi2 -- move $r4, $r0 -- pop $r5 -- popm $r0, $r3 --#endif --#endif /* __big_endian__ */ -- sub $r3, $r3, O2H -- sll O1H, O1H, O2H --.Li41: -- srli O2L, O1L, #11 -- slli $r6, O1H, #21 -- or O2L, O2L, $r6 -- slli O2H, O1H, #1 -- srli O2H, O2H, #12 -- slli $r6, $r3, #20 -- or O2H, O2H, $r6 -- move $r0, $r4 -- move $r1, $r5 -- --.LI999: -- popm $r6, $r6 -- pop $lp -- ret5 $lp -- .size __floatunsidf, .-__floatunsidf --#endif /* L_floatunsidf */ -- -- -- --#ifdef L_floatundisf -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define P2L $r2 -- #define P2H $r3 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 --#endif -- .text -- .align 2 -- .global __floatundisf -- .type __floatundisf, @function --__floatundisf: -- push $lp -- pushm $r6, $r6 -- -- move P2H, P1H -- move P2L, P1L -- or $r6, P1H, P1L -- beqz $r6, .Li4 -- move $r4, #0xbe -- -- -- #NORMd($r2, $r5, P1L) -- bnez P2H, .LL5 -- bnez P2L, .LL6 -- move $r4, #0 -- j .LL7 --.LL6: -- move P2H, P2L -- move P2L, #0 -- move $r5, #32 -- sub $r4, $r4, $r5 --.LL5: --#ifdef __NDS32_PERF_EXT__ -- clz $r5, P2H --#else -- pushm $r0, $r4 -- move $r0, P2H -- bal __clzsi2 -- move $r5, $r0 -- popm $r0, $r4 --#endif -- beqz $r5, .LL7 -- sub $r4, $r4, $r5 -- subri P1L, $r5, #32 -- srl P1L, P2L, P1L -- sll P2L, P2L, $r5 -- sll P2H, P2H, $r5 -- or P2H, P2H, P1L --.LL7: -- #NORMd End -- -- beqz P2L, .Li5 -- ori P2H, P2H, #1 --.Li5: -- #ADD(P2H, $0x80) -- move $r15, #0x80 -- add P2H, P2H, $r15 -- slt $r15, P2H, $r15 -- -- #ADDC($r4, $0x0) -- add $r4, $r4, $r15 -- srli $r6, P2H, #8 -- andi $r6, $r6, #1 -- sub P2H, P2H, $r6 -- slli P2H, P2H, #1 -- srli P2H, P2H, #9 -- slli $r6, $r4, #23 -- or P2H, P2H, $r6 --.Li4: -- move $r0, P2H -- --.LB999: -- popm $r6, $r6 -- pop $lp -- ret5 $lp -- .size __floatundisf, .-__floatundisf --#endif /* L_floatundisf */ -- -- -- --#ifdef L_floatundidf -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define P2L $r2 -- #define P2H $r3 -- #define O1L $r5 -- #define O1H $r6 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 -- #define O1H $r5 -- #define O1L $r6 --#endif -- .text -- .align 2 -- .global __floatundidf -- .type __floatundidf, @function --__floatundidf: -- push $lp -- pushm $r6, $r7 -- -- move $r4, #0 -- move P2H, P1H -- move P2L, P1L -- or $r7, P1H, P1L -- beqz $r7, .Li3 -- move $r4, #0x43e -- -- -- #NORMd($r2, O1H, O1L) -- bnez P2H, .LL8 -- bnez P2L, .LL9 -- move $r4, #0 -- j .LL10 --.LL9: -- move P2H, P2L -- move P2L, #0 -- move O1H, #32 -- sub $r4, $r4, O1H --.LL8: --#ifdef __NDS32_PERF_EXT__ -- clz O1H, P2H --#else /* not __NDS32_PERF_EXT__ */ --/* -- Replace clz with function call. -- clz O1H, P2H -- EL: clz $r6, $r3 -- EB: clz $r5, $r2 --*/ --#ifndef __big_endian__ -- pushm $r0, $r5 -- move $r0, $r3 -- bal __clzsi2 -- move $r6, $r0 -- popm $r0, $r5 --#else -- pushm $r0, $r4 -- move $r0, $r2 -- bal __clzsi2 -- move $r5, $r0 -- popm $r0, $r4 --#endif --#endif /* not __NDS32_PERF_EXT__ */ -- beqz O1H, .LL10 -- sub $r4, $r4, O1H -- subri O1L, O1H, #32 -- srl O1L, P2L, O1L -- sll P2L, P2L, O1H -- sll P2H, P2H, O1H -- or P2H, P2H, O1L --.LL10: -- #NORMd End -- -- #ADD(P2L, $0x400) -- move $r15, #0x400 -- add P2L, P2L, $r15 -- slt $r15, P2L, $r15 -- -- -- #ADDCC(P2H, $0x0) -- beqzs8 .LL13 -- add P2H, P2H, $r15 -- slt $r15, P2H, $r15 --.LL13: -- -- #ADDC($r4, $0x0) -- add $r4, $r4, $r15 -- srli $r7, P2L, #11 -- andi $r7, $r7, #1 -- sub P2L, P2L, $r7 --.Li3: -- srli O1L, P2L, #11 -- slli $r7, P2H, #21 -- or O1L, O1L, $r7 -- slli O1H, P2H, #1 -- srli O1H, O1H, #12 -- slli $r7, $r4, #20 -- or O1H, O1H, $r7 -- move P1L, O1L -- move P1H, O1H -- --.LB999: -- popm $r6, $r7 -- pop $lp -- ret5 $lp -- .size __floatundidf, .-__floatundidf --#endif /* L_floatundidf */ -- -- -- --#ifdef L_compare_sf -- -- .text -- .align 2 -- .global __cmpsf2 -- .type __cmpsf2, @function --__cmpsf2: -- .global __eqsf2 -- .type __eqsf2, @function --__eqsf2: -- .global __ltsf2 -- .type __ltsf2, @function --__ltsf2: -- .global __lesf2 -- .type __lesf2, @function --__lesf2: -- .global __nesf2 -- .type __nesf2, @function --__nesf2: -- move $r4, #1 -- j .LA -- -- .global __gesf2 -- .type __gesf2, @function --__gesf2: -- .global __gtsf2 -- .type __gtsf2, @function --__gtsf2: -- move $r4, #-1 --.LA: -- push $lp -- -- slli $r2, $r0, #1 -- slli $r3, $r1, #1 -- or $r5, $r2, $r3 -- beqz $r5, .LMequ -- move $r5, #0xff000000 -- slt $r15, $r5, $r2 -- bnezs8 .LMnan -- slt $r15, $r5, $r3 -- bnezs8 .LMnan -- srli $r2, $r2, #1 -- sltsi $r15, $r0, #0 -- beqzs8 .Li48 -- subri $r2, $r2, #0 --.Li48: -- srli $r3, $r3, #1 -- sltsi $r15, $r1, #0 -- beqzs8 .Li49 -- subri $r3, $r3, #0 --.Li49: -- slts $r15, $r2, $r3 -- beqzs8 .Li50 -- move $r0, #-1 -- j .LM999 --.Li50: -- slts $r15, $r3, $r2 -- beqzs8 .LMequ -- move $r0, #1 -- j .LM999 -- --.LMequ: -- move $r0, #0 -- --.LM999: -- pop $lp -- ret5 $lp -- --.LMnan: -- move $r0, $r4 -- j .LM999 -- .size __cmpsf2, .-__cmpsf2 -- .size __eqsf2, .-__eqsf2 -- .size __ltsf2, .-__ltsf2 -- .size __lesf2, .-__lesf2 -- .size __nesf2, .-__nesf2 -- .size __gesf2, .-__gesf2 -- .size __gtsf2, .-__gtsf2 --#endif /* L_compare_sf */ -- -- -- --#ifdef L_compare_df -- --#ifdef __big_endian__ -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 --#else -- #define P1H $r1 -- #define P1L $r0 -- #define P2H $r3 -- #define P2L $r2 --#endif -- .align 2 -- .globl __gtdf2 -- .globl __gedf2 -- .globl __ltdf2 -- .globl __ledf2 -- .globl __eqdf2 -- .globl __nedf2 -- .globl __cmpdf2 -- .type __gtdf2, @function -- .type __gedf2, @function -- .type __ltdf2, @function -- .type __ledf2, @function -- .type __eqdf2, @function -- .type __nedf2, @function -- .type __cmpdf2, @function --__gtdf2: --__gedf2: -- movi $r4, -1 -- b .L1 -- --__ltdf2: --__ledf2: --__cmpdf2: --__nedf2: --__eqdf2: -- movi $r4, 1 --.L1: --#if defined (__NDS32_ISA_V3M__) -- push25 $r10, 0 --#else -- smw.adm $r6, [$sp], $r9, 0 --#endif -- -- sethi $r5, 0x7ff00 -- and $r6, P1H, $r5 ! r6=aExp -- and $r7, P2H, $r5 ! r7=bExp -- slli $r8, P1H, 12 ! r8=aSig0 -- slli $r9, P2H, 12 ! r9=bSig0 -- beq $r6, $r5, .L11 ! aExp==0x7ff -- beq $r7, $r5, .L12 ! bExp==0x7ff --.L2: -- slli $ta, P1H, 1 ! ta=ahigh<<1 -- or $ta, P1L, $ta ! -- xor $r5, P1H, P2H ! r5=ahigh^bhigh -- beqz $ta, .L3 ! if(ahigh<<1)==0,go .L3 -- !------------------------------- -- ! (ahigh<<1)!=0 || (bhigh<<1)!=0 -- !------------------------------- --.L4: -- beqz $r5, .L5 ! ahigh==bhigh, go .L5 -- !-------------------- -- ! a != b -- !-------------------- --.L6: -- bltz $r5, .L7 ! if(aSign!=bSign), go .L7 -- !-------------------- -- ! aSign==bSign -- !-------------------- -- slt $ta, $r6, $r7 ! ta=(aExp|b|), go .L10 -- nor $r0, P2H, P2H ! if(|a|<|b|),return (~yh) --.L14: --#if defined (__NDS32_ISA_V3M__) -- pop25 $r10, 0 --#else -- lmw.bim $r6, [$sp], $r9, 0 -- ret --#endif --.L10: -- ori $r0, P2H, 1 ! return (yh|1) -- b .L14 -- !-------------------- -- ! (ahigh<<1)=0 -- !-------------------- --.L3: -- slli $ta, P2H, 1 ! ta=bhigh<<1 -- or $ta, P2L, $ta ! -- bnez $ta, .L4 ! ta=(bhigh<<1)!=0,go .L4 --.L5: -- xor $ta, P1L, P2L ! ta=alow^blow -- bnez $ta, .L6 ! alow!=blow,go .L6 -- movi $r0, 0 ! a==b, return 0 -- b .L14 -- !-------------------- -- ! aExp=0x7ff; -- !-------------------- --.L11: -- or P1L, P1L, $r8 ! x1=(aSig0|aSig1) -- bnez P1L, .L13 ! if(a=nan), go.L13 -- xor $ta, $r7, $r5 ! ta=(bExp^0x7ff) -- bnez $ta, .L2 ! if(bExp!=0x7ff), go .L2 -- !-------------------- -- ! bExp=0x7ff; -- !-------------------- --.L12: -- or $ta, P2L, $r9 ! ta=(bSig0|bSig1) -- beqz $ta, .L2 ! if(b!=nan), go .L2 --.L13: -- move $r0, $r4 -- b .L14 -- !-------------------- -- ! aSign!=bSign -- !-------------------- --.L7: -- ori $r0, P1H, 1 ! if(aSign!=bSign), return (ahigh|1) -- b .L14 -- -- .size __gtdf2, .-__gtdf2 -- .size __gedf2, .-__gedf2 -- .size __ltdf2, .-__ltdf2 -- .size __ledf2, .-__ledf2 -- .size __eqdf2, .-__eqdf2 -- .size __nedf2, .-__nedf2 -- .size __cmpdf2, .-__cmpdf2 --#endif /* L_compare_df */ -- -- -- --#ifdef L_unord_sf -- -- .text -- .align 2 -- .global __unordsf2 -- .type __unordsf2, @function --__unordsf2: -- push $lp -- -- slli $r2, $r0, #1 -- move $r3, #0xff000000 -- slt $r15, $r3, $r2 -- beqzs8 .Li52 -- move $r0, #1 -- j .LP999 --.Li52: -- slli $r2, $r1, #1 -- move $r3, #0xff000000 -- slt $r15, $r3, $r2 -- beqzs8 .Li53 -- move $r0, #1 -- j .LP999 --.Li53: -- move $r0, #0 -- --.LP999: -- pop $lp -- ret5 $lp -- .size __unordsf2, .-__unordsf2 --#endif /* L_unord_sf */ -- -- -- --#ifdef L_unord_df -- --#ifndef __big_endian__ -- #define P1L $r0 -- #define P1H $r1 -- #define P2L $r2 -- #define P2H $r3 --#else -- #define P1H $r0 -- #define P1L $r1 -- #define P2H $r2 -- #define P2L $r3 --#endif -- .text -- .align 2 -- .global __unorddf2 -- .type __unorddf2, @function --__unorddf2: -- push $lp -- -- slli $r4, P1H, #1 -- beqz P1L, .Li66 -- addi $r4, $r4, #1 --.Li66: -- move $r5, #0xffe00000 -- slt $r15, $r5, $r4 -- beqzs8 .Li67 -- move $r0, #1 -- j .LR999 --.Li67: -- slli $r4, P2H, #1 -- beqz P2L, .Li68 -- addi $r4, $r4, #1 --.Li68: -- move $r5, #0xffe00000 -- slt $r15, $r5, $r4 -- beqzs8 .Li69 -- move $r0, #1 -- j .LR999 --.Li69: -- move $r0, #0 -- --.LR999: -- pop $lp -- ret5 $lp -- .size __unorddf2, .-__unorddf2 --#endif /* L_unord_df */ --/* ------------------------------------------- */ --/* DPBIT floating point operations for libgcc */ --/* ------------------------------------------- */ -diff --git a/libgcc/config/nds32/lib2csrc-mculib/_clzdi2.c b/libgcc/config/nds32/lib2csrc-mculib/_clzdi2.c -deleted file mode 100644 -index 6afd6ab..0000000 ---- a/libgcc/config/nds32/lib2csrc-mculib/_clzdi2.c -+++ /dev/null -@@ -1,38 +0,0 @@ --/* mculib libgcc routines of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- --extern int __clzsi2 (int val); --int --__clzdi2 (long long val) --{ -- if (val >> 32) -- { -- return __clzsi2 (val >> 32); -- } -- else -- { -- return __clzsi2 (val) + 32; -- } --} -diff --git a/libgcc/config/nds32/lib2csrc-mculib/_clzsi2.c b/libgcc/config/nds32/lib2csrc-mculib/_clzsi2.c -deleted file mode 100644 -index 407caaf..0000000 ---- a/libgcc/config/nds32/lib2csrc-mculib/_clzsi2.c -+++ /dev/null -@@ -1,49 +0,0 @@ --/* mculib libgcc routines of Andes NDS32 cpu for GNU compiler -- Copyright (C) 2012-2016 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 -- . */ -- --int --__clzsi2 (int val) --{ -- int i = 32; -- int j = 16; -- int temp; -- -- for (; j; j >>= 1) -- { -- if (temp = val >> j) -- { -- if (j == 1) -- { -- return (i - 2); -- } -- else -- { -- i -= j; -- val = temp; -- } -- } -- } -- return (i - val); --} -diff --git a/libgcc/config/nds32/linux-atomic.c b/libgcc/config/nds32/linux-atomic.c -new file mode 100644 -index 0000000..69f589b ---- /dev/null -+++ b/libgcc/config/nds32/linux-atomic.c -@@ -0,0 +1,282 @@ -+/* Linux-specific atomic operations for NDS32 Linux. -+ Copyright (C) 2012-2016 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 0000000..921edf9 ---- /dev/null -+++ b/libgcc/config/nds32/linux-unwind.h -@@ -0,0 +1,156 @@ -+/* DWARF2 EH unwinding support for NDS32 Linux signal frame. -+ Copyright (C) 2014-2015 Free Software Foundation, Inc. -+ Contributed by Andes Technology Corporation. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published -+ by the Free Software Foundation; either version 3, or (at your -+ option) any later version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ Under Section 7 of GPL version 3, you are granted additional -+ permissions described in the GCC Runtime Library Exception, version -+ 3.1, as published by the Free Software Foundation. -+ -+ You should have received a copy of the GNU General Public License and -+ a copy of the GCC Runtime Library Exception along with this program; -+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -+ . */ -+ -+#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 -+ -+/* Exactly the same layout as the kernel structures, unique names. */ -+ -+/* arch/nds32/kernel/signal.c */ -+struct _sigframe { -+ struct ucontext uc; -+ unsigned long retcode; -+}; -+ -+struct _rt_sigframe { -+ siginfo_t info; -+ struct _sigframe sig; -+}; -+#define SIGRETURN 0xeb0e0a64 -+#define RT_SIGRETURN 0xab150a64 -+ -+#define MD_FALLBACK_FRAME_STATE_FOR nds32_fallback_frame_state -+ -+/* This function is supposed to be invoked by uw_frame_state_for() -+ when there is no unwind data available. -+ -+ Generally, given the _Unwind_Context CONTEXT for a stack frame, -+ we need to look up its caller and decode information into FS. -+ However, if the exception handling happens within a signal handler, -+ the return address of signal handler is a special module, which -+ contains signal return syscall and has no FDE in the .eh_frame section. -+ We need to implement MD_FALLBACK_FRAME_STATE_FOR so that we can -+ unwind through signal frames. */ -+static _Unwind_Reason_Code -+nds32_fallback_frame_state (struct _Unwind_Context *context, -+ _Unwind_FrameState *fs) -+{ -+ u_int32_t *pc = (u_int32_t *) context->ra; -+ struct sigcontext *sc_; -+ _Unwind_Ptr new_cfa; -+ -+#ifdef __NDS32_EB__ -+#error "Signal handler is not supported for force unwind." -+#endif -+ -+ if ((_Unwind_Ptr) pc & 3) -+ return _URC_END_OF_STACK; -+ -+ /* Check if we are going through a signal handler. -+ See arch/nds32/kernel/signal.c implementation. -+ SWI_SYS_SIGRETURN -> (0xeb0e0a64) -+ SWI_SYS_RT_SIGRETURN -> (0xab150a64) -+ FIXME: Currently we only handle little endian (EL) case. */ -+ if (pc[0] == SIGRETURN) -+ { -+ /* Using '_sigfame' memory address to locate kernal's sigcontext. -+ The sigcontext structures in arch/nds32/include/asm/sigcontext.h. */ -+ struct _sigframe *rt_; -+ rt_ = context->cfa; -+ sc_ = &rt_->uc.uc_mcontext; -+ } -+ else if (pc[0] == RT_SIGRETURN) -+ { -+ /* Using '_sigfame' memory address to locate kernal's sigcontext. */ -+ struct _rt_sigframe *rt_; -+ rt_ = context->cfa; -+ sc_ = &rt_->sig.uc.uc_mcontext; -+ } -+ else -+ return _URC_END_OF_STACK; -+ -+ /* Update cfa from sigcontext. */ -+ new_cfa = (_Unwind_Ptr) sc_; -+ fs->regs.cfa_how = CFA_REG_OFFSET; -+ fs->regs.cfa_reg = STACK_POINTER_REGNUM; -+ fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; -+ -+#define NDS32_PUT_FS_REG(NUM, NAME) \ -+ (fs->regs.reg[NUM].how = REG_SAVED_OFFSET, \ -+ fs->regs.reg[NUM].loc.offset = (_Unwind_Ptr) &(sc_->NAME) - new_cfa) -+ -+ /* Restore all registers value. */ -+ NDS32_PUT_FS_REG (0, nds32_r0); -+ NDS32_PUT_FS_REG (1, nds32_r1); -+ NDS32_PUT_FS_REG (2, nds32_r2); -+ NDS32_PUT_FS_REG (3, nds32_r3); -+ NDS32_PUT_FS_REG (4, nds32_r4); -+ NDS32_PUT_FS_REG (5, nds32_r5); -+ NDS32_PUT_FS_REG (6, nds32_r6); -+ NDS32_PUT_FS_REG (7, nds32_r7); -+ NDS32_PUT_FS_REG (8, nds32_r8); -+ NDS32_PUT_FS_REG (9, nds32_r9); -+ NDS32_PUT_FS_REG (10, nds32_r10); -+ NDS32_PUT_FS_REG (11, nds32_r11); -+ NDS32_PUT_FS_REG (12, nds32_r12); -+ NDS32_PUT_FS_REG (13, nds32_r13); -+ NDS32_PUT_FS_REG (14, nds32_r14); -+ NDS32_PUT_FS_REG (15, nds32_r15); -+ NDS32_PUT_FS_REG (16, nds32_r16); -+ NDS32_PUT_FS_REG (17, nds32_r17); -+ NDS32_PUT_FS_REG (18, nds32_r18); -+ NDS32_PUT_FS_REG (19, nds32_r19); -+ NDS32_PUT_FS_REG (20, nds32_r20); -+ NDS32_PUT_FS_REG (21, nds32_r21); -+ NDS32_PUT_FS_REG (22, nds32_r22); -+ NDS32_PUT_FS_REG (23, nds32_r23); -+ NDS32_PUT_FS_REG (24, nds32_r24); -+ NDS32_PUT_FS_REG (25, nds32_r25); -+ -+ NDS32_PUT_FS_REG (28, nds32_fp); -+ NDS32_PUT_FS_REG (29, nds32_gp); -+ NDS32_PUT_FS_REG (30, nds32_lp); -+ NDS32_PUT_FS_REG (31, nds32_sp); -+ -+ /* Restore PC, point to trigger signal instruction. */ -+ NDS32_PUT_FS_REG (32, nds32_ipc); -+ -+#undef NDS32_PUT_FS_REG -+ -+ /* The retaddr is PC, use PC to find FDE. */ -+ fs->retaddr_column = 32; -+ fs->signal_frame = 1; -+ -+ return _URC_NO_REASON; -+} -+ -+#endif -diff --git a/libgcc/config/nds32/sfp-machine.h b/libgcc/config/nds32/sfp-machine.h -index d822898..930a32e 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 b/libgcc/config/nds32/t-nds32 -index 20c8a3f..4e58b1b 100644 ---- a/libgcc/config/nds32/t-nds32 -+++ b/libgcc/config/nds32/t-nds32 -@@ -26,33 +26,22 @@ - # Make sure the linker script include these two objects - # for building .ctors/.dtors sections. - --# Use -DCRT_BEGIN to create beginning parts of .init and .fini content --# Make sure you are building crtbegin1.o with -O0 optimization, --# otherwise the static function will be optimized out -+# Use -DCRT_BEGIN to create beginning parts of .init and .fini content. - crtbegin1.o: $(srcdir)/config/nds32/initfini.c $(GCC_PASSES) $(CONFIG_H) - $(GCC_FOR_TARGET) $(INCLUDES) \ - $(CFLAGS) \ - -DCRT_BEGIN \ - -finhibit-size-directive -fno-inline-functions \ -- -O0 -c $(srcdir)/config/nds32/initfini.c -o crtbegin1.o -+ -fno-toplevel-reorder \ -+ -Os -c $(srcdir)/config/nds32/initfini.c -o crtbegin1.o - --# Use -DCRT_END to create ending parts of .init and .fini content --# Make sure you are building crtend1.o with -O0 optimization, --# otherwise the static function will be optimized out -+# Use -DCRT_END to create ending parts of .init and .fini content. - crtend1.o: $(srcdir)/config/nds32/initfini.c $(GCC_PASSES) $(CONFIG_H) - $(GCC_FOR_TARGET) $(INCLUDES) \ - $(CFLAGS) \ - -DCRT_END \ - -finhibit-size-directive -fno-inline-functions \ -- -O0 -c $(srcdir)/config/nds32/initfini.c -o crtend1.o -- --# Use this rule if and only if your crt0.o does not come from library --# Also, be sure to add 'crtzero.o' in extra_parts in libgcc/config.host --# and change STARTFILE_SPEC in nds32.h --# --#crtzero.o: $(srcdir)/config/nds32/crtzero.S $(GCC_PASSES) $(CONFIG_H) --# $(GCC_FOR_TARGET) $(INCLUDES) \ --# -c $(srcdir)/config/nds32/crtzero.S -o crtzero.o -- -+ -fno-toplevel-reorder \ -+ -Os -c $(srcdir)/config/nds32/initfini.c -o crtend1.o - - # ------------------------------------------------------------------------ -diff --git a/libgcc/config/nds32/t-nds32-mculib b/libgcc/config/nds32/t-nds32-glibc -similarity index 50% -rename from libgcc/config/nds32/t-nds32-mculib -rename to libgcc/config/nds32/t-nds32-glibc -index b4f7b4c..385644b 100644 ---- a/libgcc/config/nds32/t-nds32-mculib -+++ b/libgcc/config/nds32/t-nds32-glibc -@@ -1,4 +1,4 @@ --# Rules of mculib library makefile of Andes NDS32 cpu for GNU compiler -+# Rules of glibc library makefile of Andes NDS32 cpu for GNU compiler - # Copyright (C) 2012-2016 Free Software Foundation, Inc. - # Contributed by Andes Technology Corporation. - # -@@ -19,59 +19,16 @@ - # . - - # Compiler flags to use when compiling 'libgcc2.c' --HOST_LIBGCC2_CFLAGS = -Os -+HOST_LIBGCC2_CFLAGS = -O2 -fPIC -fwrapv -+LIB2ADD += $(srcdir)/config/nds32/linux-atomic.c - -- --LIB1ASMSRC = nds32/lib1asmsrc-mculib.S -- --LIB1ASMFUNCS = \ -- _addsub_sf \ -- _sf_to_si \ -- _divsi3 \ -- _divdi3 \ -- _modsi3 \ -- _moddi3 \ -- _mulsi3 \ -- _udivsi3 \ -- _udivdi3 \ -- _udivmoddi4 \ -- _umodsi3 \ -- _umoddi3 \ -- _muldi3 \ -- _addsub_df \ -- _mul_sf \ -- _mul_df \ -- _div_sf \ -- _div_df \ -- _negate_sf \ -- _negate_df \ -- _sf_to_df \ -- _df_to_sf \ -- _df_to_si \ -- _fixsfdi \ -- _fixdfdi \ -- _fixunssfsi \ -- _fixunsdfsi \ -- _fixunssfdi \ -- _fixunsdfdi \ -- _si_to_sf \ -- _si_to_df \ -- _floatdisf \ -- _floatdidf \ -- _floatunsisf \ -- _floatunsidf \ -- _floatundisf \ -- _floatundidf \ -- _compare_sf \ -- _compare_df \ -- _unord_sf \ -- _unord_df -+#LIB1ASMSRC = nds32/lib1asmsrc-newlib.S -+#LIB1ASMFUNCS = _divsi3 _modsi3 _udivsi3 _umodsi3 - - # List of functions not to build from libgcc2.c. --LIB2FUNCS_EXCLUDE = _clzsi2 _clzdi2 -+#LIB2FUNCS_EXCLUDE = _clzsi2 - - # List of extra C and assembler files(*.S) to add to static libgcc2. --LIB2ADD_ST += $(srcdir)/config/nds32/lib2csrc-mculib/_clzsi2.c --LIB2ADD_ST += $(srcdir)/config/nds32/lib2csrc-mculib/_clzdi2.c -+#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 62b6867..6493838 100644 ---- a/libgcc/config/nds32/t-nds32-isr -+++ b/libgcc/config/nds32/t-nds32-isr -@@ -23,11 +23,15 @@ - # Makfile fragment rules for libnds32_isr.a to support ISR attribute extension - ############################################################################### - --# basic flags setting --ISR_CFLAGS = $(CFLAGS) -c -- --# the object files we would like to create --LIBNDS32_ISR_16B_OBJS = \ -+# Basic flags setting. -+ifneq ($(filter -mext-dsp,$(CFLAGS)),) -+ISR_CFLAGS = $(CFLAGS) -mno-force-no-ext-zol -mext-zol -c -+else -+ISR_CFLAGS = $(CFLAGS) -mno-force-no-ext-zol -c -+endif -+ -+# 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 +50,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 +71,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 +136,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 e4af03e..c356b60 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-6.3.0_no-p-var.patch b/util/crossgcc/patches/gcc-6.3.0_no-p-var.patch deleted file mode 100644 index 0600a66cd1..0000000000 --- a/util/crossgcc/patches/gcc-6.3.0_no-p-var.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- gcc-6.3.0/gcc/ada/gcc-interface/Makefile.in.orig 2017-07-17 12:52:05.541815635 +0200 -+++ gcc-6.3.0/gcc/ada/gcc-interface/Makefile.in 2017-07-17 12:52:18.693764268 +0200 -@@ -2637,10 +2637,10 @@ - # stamp target in the parent directory whenever gnat1 is rebuilt - - # Likewise for the tools --../../gnatmake$(exeext): $(P) b_gnatm.o $(GNATMAKE_OBJS) -+../../gnatmake$(exeext): b_gnatm.o $(GNATMAKE_OBJS) - +$(GCC_LINK) $(ALL_CFLAGS) -o $@ b_gnatm.o $(GNATMAKE_OBJS) $(TOOLS_LIBS) $(TOOLS1_LIBS) - --../../gnatlink$(exeext): $(P) b_gnatl.o $(GNATLINK_OBJS) -+../../gnatlink$(exeext): b_gnatl.o $(GNATLINK_OBJS) - +$(GCC_LINK) $(ALL_CFLAGS) -o $@ b_gnatl.o $(GNATLINK_OBJS) $(TOOLS_LIBS) $(TOOLS1_LIBS) - - ../stamp-gnatlib-$(RTSDIR): diff --git a/util/crossgcc/patches/gcc-6.3.0_pointer_integer.patch b/util/crossgcc/patches/gcc-6.3.0_pointer_integer.patch deleted file mode 100644 index f34d6cc36e..0000000000 --- a/util/crossgcc/patches/gcc-6.3.0_pointer_integer.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 8db2cf6353c13f2a84cbe49b689654897906c499 Mon Sep 17 00:00:00 2001 -From: kyukhin -Date: Sat, 3 Sep 2016 10:57:05 +0000 -Subject: [PATCH] gcc/ * ubsan.c (ubsan_use_new_style_p): Fix check for empty - string. - -git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239971 138bc75d-0d04-0410-961f-82ee72b054a4 ---- - gcc/ubsan.c | 2 +- - 2 files changed, 5 insertions(+), 1 deletion(-) - -diff --git a/gcc/ubsan.c b/gcc/ubsan.c -index 5cbc98dbabb..d3bd8e3393d 100644 ---- a/gcc/ubsan.c -+++ b/gcc/ubsan.c -@@ -1469,7 +1469,7 @@ ubsan_use_new_style_p (location_t loc) - - expanded_location xloc = expand_location (loc); - if (xloc.file == NULL || strncmp (xloc.file, "\1", 2) == 0 -- || xloc.file == '\0' || xloc.file[0] == '\xff' -+ || xloc.file[0] == '\0' || xloc.file[0] == '\xff' - || xloc.file[1] == '\xff') - return false; - --- -2.13.0 - diff --git a/util/crossgcc/patches/gcc-6.3.0_riscv.patch b/util/crossgcc/patches/gcc-6.3.0_riscv.patch deleted file mode 100644 index a60511362a..0000000000 --- a/util/crossgcc/patches/gcc-6.3.0_riscv.patch +++ /dev/null @@ -1,10521 +0,0 @@ -diff --git original-gcc/gcc/common/config/riscv/riscv-common.c gcc-6.3.0/gcc/common/config/riscv/riscv-common.c -new file mode 100644 -index 00000000000..50f1485f87a ---- /dev/null -+++ gcc-6.3.0/gcc/common/config/riscv/riscv-common.c -@@ -0,0 +1,131 @@ -+/* Common hooks for RISC-V. -+ Copyright (C) 2016 Free Software Foundation, Inc. -+ -+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 -+. */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "common/common-target.h" -+#include "common/common-target-def.h" -+#include "opts.h" -+#include "flags.h" -+#include "diagnostic-core.h" -+ -+/* Parse a RISC-V ISA string into an option mask. */ -+ -+static void -+riscv_parse_arch_string (const char *isa, int *flags, location_t loc) -+{ -+ const char *p = isa; -+ -+ if (strncmp (p, "rv32", 4) == 0) -+ *flags &= ~MASK_64BIT, p += 4; -+ else if (strncmp (p, "rv64", 4) == 0) -+ *flags |= MASK_64BIT, p += 4; -+ else -+ { -+ error_at (loc, "-march=%s: ISA string must begin with rv32 or rv64", isa); -+ return; -+ } -+ -+ if (*p == 'g') -+ { -+ p++; -+ -+ *flags |= MASK_MUL; -+ *flags |= MASK_ATOMIC; -+ *flags |= MASK_HARD_FLOAT; -+ *flags |= MASK_DOUBLE_FLOAT; -+ } -+ else if (*p == 'i') -+ { -+ p++; -+ -+ *flags &= ~MASK_MUL; -+ if (*p == 'm') -+ *flags |= MASK_MUL, p++; -+ -+ *flags &= ~MASK_ATOMIC; -+ if (*p == 'a') -+ *flags |= MASK_ATOMIC, p++; -+ -+ *flags &= ~(MASK_HARD_FLOAT | MASK_DOUBLE_FLOAT); -+ if (*p == 'f') -+ { -+ *flags |= MASK_HARD_FLOAT, p++; -+ -+ if (*p == 'd') -+ { -+ *flags |= MASK_DOUBLE_FLOAT; -+ p++; -+ } -+ } -+ } -+ else -+ { -+ error_at (loc, "-march=%s: invalid ISA string", isa); -+ return; -+ } -+ -+ *flags &= ~MASK_RVC; -+ if (*p == 'c') -+ *flags |= MASK_RVC, p++; -+ -+ if (*p) -+ { -+ error_at (loc, "-march=%s: unsupported ISA substring %qs", isa, p); -+ return; -+ } -+} -+ -+/* Implement TARGET_HANDLE_OPTION. */ -+ -+static bool -+riscv_handle_option (struct gcc_options *opts, -+ struct gcc_options *opts_set ATTRIBUTE_UNUSED, -+ const struct cl_decoded_option *decoded, -+ location_t loc) -+{ -+ switch (decoded->opt_index) -+ { -+ case OPT_march_: -+ riscv_parse_arch_string (decoded->arg, &opts->x_target_flags, loc); -+ return true; -+ -+ default: -+ return true; -+ } -+} -+ -+/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ -+static const struct default_options riscv_option_optimization_table[] = -+ { -+ { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 }, -+ { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, -+ { OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 }, -+ { OPT_LEVELS_NONE, 0, NULL, 0 } -+ }; -+ -+#undef TARGET_OPTION_OPTIMIZATION_TABLE -+#define TARGET_OPTION_OPTIMIZATION_TABLE riscv_option_optimization_table -+ -+#undef TARGET_HANDLE_OPTION -+#define TARGET_HANDLE_OPTION riscv_handle_option -+ -+struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; -diff --git original-gcc/gcc/config.gcc gcc-6.3.0/gcc/config.gcc -index bc389eb45e7..ddfa4dccb52 100644 ---- original-gcc/gcc/config.gcc -+++ gcc-6.3.0/gcc/config.gcc -@@ -451,6 +451,10 @@ powerpc*-*-*) - esac - extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt" - ;; -+riscv*) -+ cpu_type=riscv -+ extra_objs="riscv-builtins.o riscv-c.o" -+ ;; - rs6000*-*-*) - extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt" - ;; -@@ -2016,6 +2020,34 @@ microblaze*-*-elf) - cxx_target_objs="${cxx_target_objs} microblaze-c.o" - tmake_file="${tmake_file} microblaze/t-microblaze" - ;; -+riscv*-*-linux*) -+ tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} riscv/linux.h" -+ case "x${enable_multilib}" in -+ xno) ;; -+ xyes) tmake_file="${tmake_file} riscv/t-linux-multilib" ;; -+ *) echo "Unknown value for enable_multilib"; exit 1 -+ esac -+ tmake_file="${tmake_file} riscv/t-riscv riscv/t-linux" -+ gnu_ld=yes -+ gas=yes -+ # Force .init_array support. The configure script cannot always -+ # automatically detect that GAS supports it, yet we require it. -+ gcc_cv_initfini_array=yes -+ ;; -+riscv*-*-elf*) -+ tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h" -+ case "x${enable_multilib}" in -+ xno) ;; -+ xyes) tmake_file="${tmake_file} riscv/t-elf-multilib" ;; -+ *) echo "Unknown value for enable_multilib"; exit 1 -+ esac -+ tmake_file="${tmake_file} riscv/t-riscv" -+ gnu_ld=yes -+ gas=yes -+ # Force .init_array support. The configure script cannot always -+ # automatically detect that GAS supports it, yet we require it. -+ gcc_cv_initfini_array=yes -+ ;; - mips*-*-netbsd*) # NetBSD/mips, either endian. - target_cpu_default="MASK_ABICALLS" - tm_file="elfos.h ${tm_file} mips/elf.h netbsd.h netbsd-elf.h mips/netbsd.h" -@@ -3939,6 +3971,70 @@ case "${target}" in - done - ;; - -+ riscv*-*-*) -+ supported_defaults="abi arch tune" -+ -+ case "${target}" in -+ riscv32*) xlen=32 ;; -+ riscv64*) xlen=64 ;; -+ *) echo "Unsupported RISC-V target ${target}" 1>&2; exit 1 ;; -+ esac -+ -+ # Infer arch from --with-arch, --target, and --with-abi. -+ case "${with_arch}" in -+ rv32i* | rv32g* | rv64i* | rv64g*) -+ # OK. -+ ;; -+ "") -+ # Infer XLEN, but otherwise assume GC. -+ case "${with_abi}" in -+ ilp32 | ilp32f | ilp32d) with_arch="rv32gc" ;; -+ lp64 | lp64f | lp64d) with_arch="rv64gc" ;; -+ *) with_arch="rv${xlen}gc" ;; -+ esac -+ ;; -+ *) -+ echo "--with-arch=${with_arch} is not supported. The argument must begin with rv32i, rv32g, rv64i, or rv64g." 1>&2 -+ exit 1 -+ ;; -+ esac -+ -+ # Make sure --with-abi is valid. If it was not specified, -+ # pick a default based on the ISA, preferring soft-float -+ # unless the D extension is present. -+ case "${with_abi}" in -+ ilp32 | ilp32f | ilp32d | lp64 | lp64f | lp64d) -+ ;; -+ "") -+ case "${with_arch}" in -+ rv32*d* | rv32g*) with_abi=ilp32d ;; -+ rv32*) with_abi=ilp32 ;; -+ rv64*d* | rv64g*) with_abi=lp64d ;; -+ rv64*) with_abi=lp64 ;; -+ esac -+ ;; -+ *) -+ echo "--with-abi=${with_abi} is not supported" 1>&2 -+ exit 1 -+ ;; -+ esac -+ -+ # Make sure ABI and ISA are compatible. -+ case "${with_abi},${with_arch}" in -+ ilp32,rv32* \ -+ | ilp32f,rv32*f* | ilp32f,rv32g* \ -+ | ilp32d,rv32*d* | ilp32d,rv32g* \ -+ | lp64,rv64* \ -+ | lp64f,rv64*f* | lp64f,rv64g* \ -+ | lp64d,rv64*d* | lp64d,rv64g*) -+ ;; -+ *) -+ echo "--with-abi=${with_abi} is not supported for ISA ${with_arch}" 1>&2 -+ exit 1 -+ ;; -+ esac -+ ;; -+ - mips*-*-*) - supported_defaults="abi arch arch_32 arch_64 float fpu nan fp_32 odd_spreg_32 tune tune_32 tune_64 divide llsc mips-plt synci lxc1-sxc1 madd4" - -diff --git original-gcc/gcc/config/riscv/constraints.md gcc-6.3.0/gcc/config/riscv/constraints.md -new file mode 100644 -index 00000000000..ae93788e44a ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/constraints.md -@@ -0,0 +1,78 @@ -+;; Constraint definitions for RISC-V target. -+;; Copyright (C) 2011-2017 Free Software Foundation, Inc. -+;; Contributed by Andrew Waterman (andrew@sifive.com). -+;; Based on MIPS target for GNU compiler. -+;; -+;; 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 -+;; . -+ -+;; Register constraints -+ -+(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS" -+ "A floating-point register (if available).") -+ -+(define_register_constraint "j" "SIBCALL_REGS" -+ "@internal") -+ -+;; Avoid using register t0 for JALR's argument, because for some -+;; microarchitectures that is a return-address stack hint. -+(define_register_constraint "l" "JALR_REGS" -+ "@internal") -+ -+;; General constraints -+ -+(define_constraint "I" -+ "An I-type 12-bit signed immediate." -+ (and (match_code "const_int") -+ (match_test "SMALL_OPERAND (ival)"))) -+ -+(define_constraint "J" -+ "Integer zero." -+ (and (match_code "const_int") -+ (match_test "ival == 0"))) -+ -+(define_constraint "K" -+ "A 5-bit unsigned immediate for CSR access instructions." -+ (and (match_code "const_int") -+ (match_test "IN_RANGE (ival, 0, 31)"))) -+ -+;; Floating-point constant +0.0, used for FCVT-based moves when FMV is -+;; not available in RV32. -+(define_constraint "G" -+ "@internal" -+ (and (match_code "const_double") -+ (match_test "op == CONST0_RTX (mode)"))) -+ -+(define_memory_constraint "A" -+ "An address that is held in a general-purpose register." -+ (and (match_code "mem") -+ (match_test "GET_CODE(XEXP(op,0)) == REG"))) -+ -+(define_constraint "S" -+ "@internal -+ A constant call address." -+ (match_operand 0 "absolute_symbolic_operand")) -+ -+(define_constraint "U" -+ "@internal -+ A PLT-indirect call address." -+ (match_operand 0 "plt_symbolic_operand")) -+ -+(define_constraint "T" -+ "@internal -+ A constant @code{move_operand}." -+ (and (match_operand 0 "move_operand") -+ (match_test "CONSTANT_P (op)"))) -diff --git original-gcc/gcc/config/riscv/elf.h gcc-6.3.0/gcc/config/riscv/elf.h -new file mode 100644 -index 00000000000..391e59f49b9 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/elf.h -@@ -0,0 +1,35 @@ -+/* Target macros for riscv*-elf targets. -+ Copyright (C) 1994-2017 Free Software Foundation, Inc. -+ -+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 LINK_SPEC "\ -+-melf" XLEN_SPEC "lriscv \ -+%{shared}" -+ -+/* Link against Newlib libraries, because the ELF backend assumes Newlib. -+ Handle the circular dependence between libc and libgloss. */ -+#undef LIB_SPEC -+#define LIB_SPEC "--start-group -lc -lgloss --end-group" -+ -+#undef STARTFILE_SPEC -+#define STARTFILE_SPEC "crt0%O%s crtbegin%O%s" -+ -+#undef ENDFILE_SPEC -+#define ENDFILE_SPEC "crtend%O%s" -+ -+#define NO_IMPLICIT_EXTERN_C 1 -diff --git original-gcc/gcc/config/riscv/generic.md gcc-6.3.0/gcc/config/riscv/generic.md -new file mode 100644 -index 00000000000..294c7ef729d ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/generic.md -@@ -0,0 +1,78 @@ -+;; Generic DFA-based pipeline description for RISC-V targets. -+;; Copyright (C) 2011-2017 Free Software Foundation, Inc. -+;; Contributed by Andrew Waterman (andrew@sifive.com). -+;; Based on MIPS target for GNU compiler. -+ -+;; 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_automaton "pipe0") -+(define_cpu_unit "alu" "pipe0") -+(define_cpu_unit "imuldiv" "pipe0") -+(define_cpu_unit "fdivsqrt" "pipe0") -+ -+(define_insn_reservation "generic_alu" 1 -+ (eq_attr "type" "unknown,const,arith,shift,slt,multi,nop,logical,move") -+ "alu") -+ -+(define_insn_reservation "generic_load" 3 -+ (eq_attr "type" "load,fpload") -+ "alu") -+ -+(define_insn_reservation "generic_store" 1 -+ (eq_attr "type" "store,fpstore") -+ "alu") -+ -+(define_insn_reservation "generic_xfer" 3 -+ (eq_attr "type" "mfc,mtc,fcvt,fmove,fcmp") -+ "alu") -+ -+(define_insn_reservation "generic_branch" 1 -+ (eq_attr "type" "branch,jump,call") -+ "alu") -+ -+(define_insn_reservation "generic_imul" 10 -+ (eq_attr "type" "imul") -+ "imuldiv*10") -+ -+(define_insn_reservation "generic_idivsi" 34 -+ (and (eq_attr "type" "idiv") -+ (eq_attr "mode" "SI")) -+ "imuldiv*34") -+ -+(define_insn_reservation "generic_idivdi" 66 -+ (and (eq_attr "type" "idiv") -+ (eq_attr "mode" "DI")) -+ "imuldiv*66") -+ -+(define_insn_reservation "generic_fmul_single" 5 -+ (and (eq_attr "type" "fadd,fmul,fmadd") -+ (eq_attr "mode" "SF")) -+ "alu") -+ -+(define_insn_reservation "generic_fmul_double" 7 -+ (and (eq_attr "type" "fadd,fmul,fmadd") -+ (eq_attr "mode" "DF")) -+ "alu") -+ -+(define_insn_reservation "generic_fdiv" 20 -+ (eq_attr "type" "fdiv") -+ "fdivsqrt*20") -+ -+(define_insn_reservation "generic_fsqrt" 25 -+ (eq_attr "type" "fsqrt") -+ "fdivsqrt*25") -diff --git original-gcc/gcc/config/riscv/linux.h gcc-6.3.0/gcc/config/riscv/linux.h -new file mode 100644 -index 00000000000..0c622118056 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/linux.h -@@ -0,0 +1,40 @@ -+/* Definitions for RISC-V GNU/Linux systems with ELF format. -+ Copyright (C) 1998-2017 Free Software Foundation, Inc. -+ -+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_OS_CPP_BUILTINS() \ -+ do { \ -+ GNU_USER_TARGET_OS_CPP_BUILTINS(); \ -+ } while (0) -+ -+#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux-riscv" XLEN_SPEC "-" ABI_SPEC ".so.1" -+ -+/* Because RISC-V only has word-sized atomics, it requries libatomic where -+ others do not. So link libatomic by default, as needed. */ -+#undef LIB_SPEC -+#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC \ -+ " %{pthread:" LD_AS_NEEDED_OPTION " -latomic " LD_NO_AS_NEEDED_OPTION "}" \ -+ -+#define LINK_SPEC "\ -+-melf" XLEN_SPEC "lriscv \ -+%{shared} \ -+ %{!shared: \ -+ %{!static: \ -+ %{rdynamic:-export-dynamic} \ -+ -dynamic-linker " GNU_USER_DYNAMIC_LINKER "} \ -+ %{static:-static}}" -diff --git original-gcc/gcc/config/riscv/multilib-generator gcc-6.3.0/gcc/config/riscv/multilib-generator -new file mode 100755 -index 00000000000..b7ebf7bed41 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/multilib-generator -@@ -0,0 +1,65 @@ -+#!/usr/bin/env python -+ -+# RISC-V multilib list generator. -+# Copyright (C) 2011-2017 Free Software Foundation, Inc. -+# Contributed by Andrew Waterman (andrew@sifive.com). -+# -+# 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 -+# . -+ -+# Each argument to this script is of the form -+# --- -+# For example, -+# rv32imafd-ilp32d-rv32g-c,v -+# means that, in addition to rv32imafd, these configurations can also use the -+# rv32imafd-ilp32d libraries: rv32imafdc, rv32imafdv, rv32g, rv32gc, rv32gv -+ -+from __future__ import print_function -+import sys -+import collections -+ -+arches = collections.OrderedDict() -+abis = collections.OrderedDict() -+required = [] -+reuse = [] -+ -+for cfg in sys.argv[1:]: -+ (arch, abi, extra, ext) = cfg.split('-') -+ arches[arch] = 1 -+ abis[abi] = 1 -+ extra = list(filter(None, extra.split(','))) -+ ext = list(filter(None, ext.split(','))) -+ alts = sum([[x] + [x + y for y in ext] for x in [arch] + extra], []) -+ alts = alts + [x.replace('imafd', 'g') for x in alts if 'imafd' in x] -+ for alt in alts[1:]: -+ arches[alt] = 1 -+ reuse.append('march.%s/mabi.%s=march.%s/mabi.%s' % (arch, abi, alt, abi)) -+ required.append('march=%s/mabi=%s' % (arch, abi)) -+ -+arch_options = '/'.join(['march=%s' % x for x in arches.keys()]) -+arch_dirnames = ' '.join(arches.keys()) -+ -+abi_options = '/'.join(['mabi=%s' % x for x in abis.keys()]) -+abi_dirnames = ' '.join(abis.keys()) -+ -+prog = sys.argv[0].split('/')[-1] -+print('# This file was generated by %s with the command:' % prog) -+print('# %s' % ' '.join(sys.argv)) -+ -+print('MULTILIB_OPTIONS = %s %s' % (arch_options, abi_options)) -+print('MULTILIB_DIRNAMES = %s %s' % (arch_dirnames, abi_dirnames)) -+print('MULTILIB_REQUIRED = %s' % ' '.join(required)) -+print('MULTILIB_REUSE = %s' % ' '.join(reuse)) -diff --git original-gcc/gcc/config/riscv/peephole.md gcc-6.3.0/gcc/config/riscv/peephole.md -new file mode 100644 -index 00000000000..7e644e01759 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/peephole.md -@@ -0,0 +1,40 @@ -+;; Peephole optimizations for RISC-V for GNU compiler. -+;; Copyright (C) 2011-2017 Free Software Foundation, Inc. -+;; Contributed by Andrew Waterman (andrew@sifive.com). -+ -+;; 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 -+;; . -+ -+;; Simplify (unsigned long)(unsigned int)a << const -+(define_peephole2 -+ [(set (match_operand:DI 0 "register_operand") -+ (ashift:DI (match_operand:DI 1 "register_operand") -+ (match_operand 2 "const_int_operand"))) -+ (set (match_operand:DI 3 "register_operand") -+ (lshiftrt:DI (match_dup 0) (match_dup 2))) -+ (set (match_operand:DI 4 "register_operand") -+ (ashift:DI (match_dup 3) (match_operand 5 "const_int_operand")))] -+ "TARGET_64BIT -+ && INTVAL (operands[5]) < INTVAL (operands[2]) -+ && (REGNO (operands[3]) == REGNO (operands[4]) -+ || peep2_reg_dead_p (3, operands[3]))" -+ [(set (match_dup 0) -+ (ashift:DI (match_dup 1) (match_dup 2))) -+ (set (match_dup 4) -+ (lshiftrt:DI (match_dup 0) (match_operand 5)))] -+{ -+ operands[5] = GEN_INT (INTVAL (operands[2]) - INTVAL (operands[5])); -+}) -diff --git original-gcc/gcc/config/riscv/pic.md gcc-6.3.0/gcc/config/riscv/pic.md -new file mode 100644 -index 00000000000..6a29ead32d3 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/pic.md -@@ -0,0 +1,85 @@ -+;; PIC codegen for RISC-V for GNU compiler. -+;; Copyright (C) 2011-2017 Free Software Foundation, Inc. -+;; Contributed by Andrew Waterman (andrew@sifive.com). -+ -+;; 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 -+;; . -+ -+ -+;; Simplify PIC loads to static variables. -+;; These should go away once we figure out how to emit auipc discretely. -+ -+(define_insn "*local_pic_load" -+ [(set (match_operand:ANYI 0 "register_operand" "=r") -+ (mem:ANYI (match_operand 1 "absolute_symbolic_operand" "")))] -+ "USE_LOAD_ADDRESS_MACRO (operands[1])" -+ "\t%0,%1" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "*local_pic_load" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (mem:ANYF (match_operand 1 "absolute_symbolic_operand" ""))) -+ (clobber (match_scratch:DI 2 "=r"))] -+ "TARGET_HARD_FLOAT && TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[1])" -+ "\t%0,%1,%2" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "*local_pic_load" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (mem:ANYF (match_operand 1 "absolute_symbolic_operand" ""))) -+ (clobber (match_scratch:SI 2 "=r"))] -+ "TARGET_HARD_FLOAT && !TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[1])" -+ "\t%0,%1,%2" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "*local_pic_loadu" -+ [(set (match_operand:SUPERQI 0 "register_operand" "=r") -+ (zero_extend:SUPERQI (mem:SUBX (match_operand 1 "absolute_symbolic_operand" ""))))] -+ "USE_LOAD_ADDRESS_MACRO (operands[1])" -+ "u\t%0,%1" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "*local_pic_storedi" -+ [(set (mem:ANYI (match_operand 0 "absolute_symbolic_operand" "")) -+ (match_operand:ANYI 1 "reg_or_0_operand" "rJ")) -+ (clobber (match_scratch:DI 2 "=&r"))] -+ "TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])" -+ "\t%z1,%0,%2" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "*local_pic_storesi" -+ [(set (mem:ANYI (match_operand 0 "absolute_symbolic_operand" "")) -+ (match_operand:ANYI 1 "reg_or_0_operand" "rJ")) -+ (clobber (match_scratch:SI 2 "=&r"))] -+ "!TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])" -+ "\t%z1,%0,%2" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "*local_pic_storedi" -+ [(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" "")) -+ (match_operand:ANYF 1 "register_operand" "f")) -+ (clobber (match_scratch:DI 2 "=r"))] -+ "TARGET_HARD_FLOAT && TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])" -+ "\t%1,%0,%2" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "*local_pic_storesi" -+ [(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" "")) -+ (match_operand:ANYF 1 "register_operand" "f")) -+ (clobber (match_scratch:SI 2 "=r"))] -+ "TARGET_HARD_FLOAT && !TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])" -+ "\t%1,%0,%2" -+ [(set (attr "length") (const_int 8))]) -diff --git original-gcc/gcc/config/riscv/predicates.md gcc-6.3.0/gcc/config/riscv/predicates.md -new file mode 100644 -index 00000000000..854af1481f7 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/predicates.md -@@ -0,0 +1,180 @@ -+;; Predicate description for RISC-V target. -+;; Copyright (C) 2011-2017 Free Software Foundation, Inc. -+;; Contributed by Andrew Waterman (andrew@sifive.com). -+;; Based on MIPS target for GNU compiler. -+;; -+;; 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_predicate "const_arith_operand" -+ (and (match_code "const_int") -+ (match_test "SMALL_OPERAND (INTVAL (op))"))) -+ -+(define_predicate "arith_operand" -+ (ior (match_operand 0 "const_arith_operand") -+ (match_operand 0 "register_operand"))) -+ -+(define_predicate "const_csr_operand" -+ (and (match_code "const_int") -+ (match_test "IN_RANGE (INTVAL (op), 0, 31)"))) -+ -+(define_predicate "csr_operand" -+ (ior (match_operand 0 "const_csr_operand") -+ (match_operand 0 "register_operand"))) -+ -+(define_predicate "sle_operand" -+ (and (match_code "const_int") -+ (match_test "SMALL_OPERAND (INTVAL (op) + 1)"))) -+ -+(define_predicate "sleu_operand" -+ (and (match_operand 0 "sle_operand") -+ (match_test "INTVAL (op) + 1 != 0"))) -+ -+(define_predicate "const_0_operand" -+ (and (match_code "const_int,const_wide_int,const_double,const_vector") -+ (match_test "op == CONST0_RTX (GET_MODE (op))"))) -+ -+(define_predicate "reg_or_0_operand" -+ (ior (match_operand 0 "const_0_operand") -+ (match_operand 0 "register_operand"))) -+ -+;; Only use branch-on-bit sequences when the mask is not an ANDI immediate. -+(define_predicate "branch_on_bit_operand" -+ (and (match_code "const_int") -+ (match_test "INTVAL (op) >= IMM_BITS - 1"))) -+ -+;; A legitimate CONST_INT operand that takes more than one instruction -+;; to load. -+(define_predicate "splittable_const_int_operand" -+ (match_code "const_int") -+{ -+ /* Don't handle multi-word moves this way; we don't want to introduce -+ the individual word-mode moves until after reload. */ -+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) -+ return false; -+ -+ /* Otherwise check whether the constant can be loaded in a single -+ instruction. */ -+ return !LUI_OPERAND (INTVAL (op)) && !SMALL_OPERAND (INTVAL (op)); -+}) -+ -+(define_predicate "move_operand" -+ (match_operand 0 "general_operand") -+{ -+ enum riscv_symbol_type symbol_type; -+ -+ /* The thinking here is as follows: -+ -+ (1) The move expanders should split complex load sequences into -+ individual instructions. Those individual instructions can -+ then be optimized by all rtl passes. -+ -+ (2) The target of pre-reload load sequences should not be used -+ to store temporary results. If the target register is only -+ assigned one value, reload can rematerialize that value -+ on demand, rather than spill it to the stack. -+ -+ (3) If we allowed pre-reload passes like combine and cse to recreate -+ complex load sequences, we would want to be able to split the -+ sequences before reload as well, so that the pre-reload scheduler -+ can see the individual instructions. This falls foul of (2); -+ the splitter would be forced to reuse the target register for -+ intermediate results. -+ -+ (4) We want to define complex load splitters for combine. These -+ splitters can request a temporary scratch register, which avoids -+ the problem in (2). They allow things like: -+ -+ (set (reg T1) (high SYM)) -+ (set (reg T2) (low (reg T1) SYM)) -+ (set (reg X) (plus (reg T2) (const_int OFFSET))) -+ -+ to be combined into: -+ -+ (set (reg T3) (high SYM+OFFSET)) -+ (set (reg X) (lo_sum (reg T3) SYM+OFFSET)) -+ -+ if T2 is only used this once. */ -+ switch (GET_CODE (op)) -+ { -+ case CONST_INT: -+ return !splittable_const_int_operand (op, mode); -+ -+ case CONST: -+ case SYMBOL_REF: -+ case LABEL_REF: -+ return riscv_symbolic_constant_p (op, &symbol_type) -+ && !riscv_split_symbol_type (symbol_type); -+ -+ case HIGH: -+ op = XEXP (op, 0); -+ return riscv_symbolic_constant_p (op, &symbol_type) -+ && riscv_split_symbol_type (symbol_type) -+ && symbol_type != SYMBOL_PCREL; -+ -+ default: -+ return true; -+ } -+}) -+ -+(define_predicate "symbolic_operand" -+ (match_code "const,symbol_ref,label_ref") -+{ -+ enum riscv_symbol_type type; -+ return riscv_symbolic_constant_p (op, &type); -+}) -+ -+(define_predicate "absolute_symbolic_operand" -+ (match_code "const,symbol_ref,label_ref") -+{ -+ enum riscv_symbol_type type; -+ return (riscv_symbolic_constant_p (op, &type) -+ && (type == SYMBOL_ABSOLUTE || type == SYMBOL_PCREL)); -+}) -+ -+(define_predicate "plt_symbolic_operand" -+ (match_code "const,symbol_ref,label_ref") -+{ -+ enum riscv_symbol_type type; -+ return (riscv_symbolic_constant_p (op, &type) -+ && type == SYMBOL_GOT_DISP && !SYMBOL_REF_WEAK (op) && TARGET_PLT); -+}) -+ -+(define_predicate "call_insn_operand" -+ (ior (match_operand 0 "absolute_symbolic_operand") -+ (match_operand 0 "plt_symbolic_operand") -+ (match_operand 0 "register_operand"))) -+ -+(define_predicate "modular_operator" -+ (match_code "plus,minus,mult,ashift")) -+ -+(define_predicate "equality_operator" -+ (match_code "eq,ne")) -+ -+(define_predicate "order_operator" -+ (match_code "eq,ne,lt,ltu,le,leu,ge,geu,gt,gtu")) -+ -+(define_predicate "signed_order_operator" -+ (match_code "eq,ne,lt,le,ge,gt")) -+ -+(define_predicate "fp_native_comparison" -+ (match_code "eq,lt,le,gt,ge")) -+ -+(define_predicate "fp_scc_comparison" -+ (match_code "unordered,ordered,unlt,unge,unle,ungt,ltgt,ne,eq,lt,le,gt,ge")) -+ -+(define_predicate "fp_branch_comparison" -+ (match_code "unordered,ordered,unlt,unge,unle,ungt,uneq,ltgt,ne,eq,lt,le,gt,ge")) -diff --git original-gcc/gcc/config/riscv/riscv-builtins.c gcc-6.3.0/gcc/config/riscv/riscv-builtins.c -new file mode 100644 -index 00000000000..626a6a33f99 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/riscv-builtins.c -@@ -0,0 +1,287 @@ -+/* Subroutines used for expanding RISC-V builtins. -+ Copyright (C) 2011-2017 Free Software Foundation, Inc. -+ Contributed by Andrew Waterman (andrew@sifive.com). -+ -+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 -+. */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "rtl.h" -+#include "tree.h" -+#include "gimple-expr.h" -+#include "memmodel.h" -+#include "expmed.h" -+#include "optabs.h" -+#include "recog.h" -+#include "diagnostic-core.h" -+#include "stor-layout.h" -+#include "expr.h" -+#include "langhooks.h" -+ -+/* Macros to create an enumeration identifier for a function prototype. */ -+#define RISCV_FTYPE_NAME1(A, B) RISCV_##A##_FTYPE_##B -+ -+/* Classifies the prototype of a built-in function. */ -+enum riscv_function_type { -+#define DEF_RISCV_FTYPE(NARGS, LIST) RISCV_FTYPE_NAME##NARGS LIST, -+#include "config/riscv/riscv-ftypes.def" -+#undef DEF_RISCV_FTYPE -+ RISCV_MAX_FTYPE_MAX -+}; -+ -+/* Specifies how a built-in function should be converted into rtl. */ -+enum riscv_builtin_type { -+ /* The function corresponds directly to an .md pattern. */ -+ RISCV_BUILTIN_DIRECT, -+ -+ /* Likewise, but with return type VOID. */ -+ RISCV_BUILTIN_DIRECT_NO_TARGET -+}; -+ -+/* Declare an availability predicate for built-in functions. */ -+#define AVAIL(NAME, COND) \ -+ static unsigned int \ -+ riscv_builtin_avail_##NAME (void) \ -+ { \ -+ return (COND); \ -+ } -+ -+/* This structure describes a single built-in function. */ -+struct riscv_builtin_description { -+ /* The code of the main .md file instruction. See riscv_builtin_type -+ for more information. */ -+ enum insn_code icode; -+ -+ /* The name of the built-in function. */ -+ const char *name; -+ -+ /* Specifies how the function should be expanded. */ -+ enum riscv_builtin_type builtin_type; -+ -+ /* The function's prototype. */ -+ enum riscv_function_type prototype; -+ -+ /* Whether the function is available. */ -+ unsigned int (*avail) (void); -+}; -+ -+AVAIL (hard_float, TARGET_HARD_FLOAT) -+ -+/* Construct a riscv_builtin_description from the given arguments. -+ -+ INSN is the name of the associated instruction pattern, without the -+ leading CODE_FOR_riscv_. -+ -+ NAME is the name of the function itself, without the leading -+ "__builtin_riscv_". -+ -+ BUILTIN_TYPE and FUNCTION_TYPE are riscv_builtin_description fields. -+ -+ AVAIL is the name of the availability predicate, without the leading -+ riscv_builtin_avail_. */ -+#define RISCV_BUILTIN(INSN, NAME, BUILTIN_TYPE, FUNCTION_TYPE, AVAIL) \ -+ { CODE_FOR_riscv_ ## INSN, "__builtin_riscv_" NAME, \ -+ BUILTIN_TYPE, FUNCTION_TYPE, riscv_builtin_avail_ ## AVAIL } -+ -+/* Define __builtin_riscv_, which is a RISCV_BUILTIN_DIRECT function -+ mapped to instruction CODE_FOR_riscv_, FUNCTION_TYPE and AVAIL -+ are as for RISCV_BUILTIN. */ -+#define DIRECT_BUILTIN(INSN, FUNCTION_TYPE, AVAIL) \ -+ RISCV_BUILTIN (INSN, #INSN, RISCV_BUILTIN_DIRECT, FUNCTION_TYPE, AVAIL) -+ -+/* Define __builtin_riscv_, which is a RISCV_BUILTIN_DIRECT_NO_TARGET -+ function mapped to instruction CODE_FOR_riscv_, FUNCTION_TYPE -+ and AVAIL are as for RISCV_BUILTIN. */ -+#define DIRECT_NO_TARGET_BUILTIN(INSN, FUNCTION_TYPE, AVAIL) \ -+ RISCV_BUILTIN (INSN, #INSN, RISCV_BUILTIN_DIRECT_NO_TARGET, \ -+ FUNCTION_TYPE, AVAIL) -+ -+/* Argument types. */ -+#define RISCV_ATYPE_VOID void_type_node -+#define RISCV_ATYPE_USI unsigned_intSI_type_node -+ -+/* RISCV_FTYPE_ATYPESN takes N RISCV_FTYPES-like type codes and lists -+ their associated RISCV_ATYPEs. */ -+#define RISCV_FTYPE_ATYPES1(A, B) \ -+ RISCV_ATYPE_##A, RISCV_ATYPE_##B -+ -+static const struct riscv_builtin_description riscv_builtins[] = { -+ DIRECT_BUILTIN (frflags, RISCV_USI_FTYPE_VOID, hard_float), -+ DIRECT_NO_TARGET_BUILTIN (fsflags, RISCV_VOID_FTYPE_USI, hard_float) -+}; -+ -+/* Index I is the function declaration for riscv_builtins[I], or null if the -+ function isn't defined on this target. */ -+static GTY(()) tree riscv_builtin_decls[ARRAY_SIZE (riscv_builtins)]; -+ -+/* Get the index I of the function declaration for riscv_builtin_decls[I] -+ using the instruction code or return null if not defined for the target. */ -+static GTY(()) int riscv_builtin_decl_index[NUM_INSN_CODES]; -+ -+#define GET_BUILTIN_DECL(CODE) \ -+ riscv_builtin_decls[riscv_builtin_decl_index[(CODE)]] -+ -+/* Return the function type associated with function prototype TYPE. */ -+ -+static tree -+riscv_build_function_type (enum riscv_function_type type) -+{ -+ static tree types[(int) RISCV_MAX_FTYPE_MAX]; -+ -+ if (types[(int) type] == NULL_TREE) -+ switch (type) -+ { -+#define DEF_RISCV_FTYPE(NUM, ARGS) \ -+ case RISCV_FTYPE_NAME##NUM ARGS: \ -+ types[(int) type] \ -+ = build_function_type_list (RISCV_FTYPE_ATYPES##NUM ARGS, \ -+ NULL_TREE); \ -+ break; -+#include "config/riscv/riscv-ftypes.def" -+#undef DEF_RISCV_FTYPE -+ default: -+ gcc_unreachable (); -+ } -+ -+ return types[(int) type]; -+} -+ -+/* Implement TARGET_INIT_BUILTINS. */ -+ -+void -+riscv_init_builtins (void) -+{ -+ for (size_t i = 0; i < ARRAY_SIZE (riscv_builtins); i++) -+ { -+ const struct riscv_builtin_description *d = &riscv_builtins[i]; -+ if (d->avail ()) -+ { -+ tree type = riscv_build_function_type (d->prototype); -+ riscv_builtin_decls[i] -+ = add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL, NULL); -+ riscv_builtin_decl_index[d->icode] = i; -+ } -+ } -+} -+ -+/* Implement TARGET_BUILTIN_DECL. */ -+ -+tree -+riscv_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED) -+{ -+ if (code >= ARRAY_SIZE (riscv_builtins)) -+ return error_mark_node; -+ return riscv_builtin_decls[code]; -+} -+ -+/* Take argument ARGNO from EXP's argument list and convert it into -+ an expand operand. Store the operand in *OP. */ -+ -+static void -+riscv_prepare_builtin_arg (struct expand_operand *op, tree exp, unsigned argno) -+{ -+ tree arg = CALL_EXPR_ARG (exp, argno); -+ create_input_operand (op, expand_normal (arg), TYPE_MODE (TREE_TYPE (arg))); -+} -+ -+/* Expand instruction ICODE as part of a built-in function sequence. -+ Use the first NOPS elements of OPS as the instruction's operands. -+ HAS_TARGET_P is true if operand 0 is a target; it is false if the -+ instruction has no target. -+ -+ Return the target rtx if HAS_TARGET_P, otherwise return const0_rtx. */ -+ -+static rtx -+riscv_expand_builtin_insn (enum insn_code icode, unsigned int n_ops, -+ struct expand_operand *ops, bool has_target_p) -+{ -+ if (!maybe_expand_insn (icode, n_ops, ops)) -+ { -+ error ("invalid argument to built-in function"); -+ return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx; -+ } -+ -+ return has_target_p ? ops[0].value : const0_rtx; -+} -+ -+/* Expand a RISCV_BUILTIN_DIRECT or RISCV_BUILTIN_DIRECT_NO_TARGET function; -+ HAS_TARGET_P says which. EXP is the CALL_EXPR that calls the function -+ and ICODE is the code of the associated .md pattern. TARGET, if nonnull, -+ suggests a good place to put the result. */ -+ -+static rtx -+riscv_expand_builtin_direct (enum insn_code icode, rtx target, tree exp, -+ bool has_target_p) -+{ -+ struct expand_operand ops[MAX_RECOG_OPERANDS]; -+ -+ /* Map any target to operand 0. */ -+ int opno = 0; -+ if (has_target_p) -+ create_output_operand (&ops[opno++], target, TYPE_MODE (TREE_TYPE (exp))); -+ -+ /* Map the arguments to the other operands. */ -+ gcc_assert (opno + call_expr_nargs (exp) -+ == insn_data[icode].n_generator_args); -+ for (int argno = 0; argno < call_expr_nargs (exp); argno++) -+ riscv_prepare_builtin_arg (&ops[opno++], exp, argno); -+ -+ return riscv_expand_builtin_insn (icode, opno, ops, has_target_p); -+} -+ -+/* Implement TARGET_EXPAND_BUILTIN. */ -+ -+rtx -+riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, -+ machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); -+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl); -+ const struct riscv_builtin_description *d = &riscv_builtins[fcode]; -+ -+ switch (d->builtin_type) -+ { -+ case RISCV_BUILTIN_DIRECT: -+ return riscv_expand_builtin_direct (d->icode, target, exp, true); -+ -+ case RISCV_BUILTIN_DIRECT_NO_TARGET: -+ return riscv_expand_builtin_direct (d->icode, target, exp, false); -+ } -+ -+ gcc_unreachable (); -+} -+ -+/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */ -+ -+void -+riscv_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) -+{ -+ if (!TARGET_HARD_FLOAT) -+ return; -+ -+ tree frflags = GET_BUILTIN_DECL (CODE_FOR_riscv_frflags); -+ tree fsflags = GET_BUILTIN_DECL (CODE_FOR_riscv_fsflags); -+ tree old_flags = create_tmp_var_raw (RISCV_ATYPE_USI); -+ -+ *hold = build2 (MODIFY_EXPR, RISCV_ATYPE_USI, old_flags, -+ build_call_expr (frflags, 0)); -+ *clear = build_call_expr (fsflags, 1, old_flags); -+ *update = NULL_TREE; -+} -diff --git original-gcc/gcc/config/riscv/riscv-c.c gcc-6.3.0/gcc/config/riscv/riscv-c.c -new file mode 100644 -index 00000000000..64e7cf877af ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/riscv-c.c -@@ -0,0 +1,92 @@ -+/* RISC-V-specific code for C family languages. -+ Copyright (C) 2011-2017 Free Software Foundation, Inc. -+ Contributed by Andrew Waterman (andrew@sifive.com). -+ -+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 -+. */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "c-family/c-common.h" -+#include "cpplib.h" -+ -+#define builtin_define(TXT) cpp_define (pfile, TXT) -+ -+/* Implement TARGET_CPU_CPP_BUILTINS. */ -+ -+void -+riscv_cpu_cpp_builtins (cpp_reader *pfile) -+{ -+ builtin_define ("__riscv"); -+ -+ if (TARGET_RVC) -+ builtin_define ("__riscv_compressed"); -+ -+ if (TARGET_ATOMIC) -+ builtin_define ("__riscv_atomic"); -+ -+ if (TARGET_MUL) -+ builtin_define ("__riscv_mul"); -+ if (TARGET_DIV) -+ builtin_define ("__riscv_div"); -+ if (TARGET_DIV && TARGET_MUL) -+ builtin_define ("__riscv_muldiv"); -+ -+ builtin_define_with_int_value ("__riscv_xlen", UNITS_PER_WORD * 8); -+ if (TARGET_HARD_FLOAT) -+ builtin_define_with_int_value ("__riscv_flen", UNITS_PER_FP_REG * 8); -+ -+ if (TARGET_HARD_FLOAT && TARGET_FDIV) -+ { -+ builtin_define ("__riscv_fdiv"); -+ builtin_define ("__riscv_fsqrt"); -+ } -+ -+ switch (riscv_abi) -+ { -+ case ABI_ILP32: -+ case ABI_LP64: -+ builtin_define ("__riscv_float_abi_soft"); -+ break; -+ -+ case ABI_ILP32F: -+ case ABI_LP64F: -+ builtin_define ("__riscv_float_abi_single"); -+ break; -+ -+ case ABI_ILP32D: -+ case ABI_LP64D: -+ builtin_define ("__riscv_float_abi_double"); -+ break; -+ } -+ -+ switch (riscv_cmodel) -+ { -+ case CM_MEDLOW: -+ builtin_define ("__riscv_cmodel_medlow"); -+ break; -+ -+ case CM_MEDANY: -+ builtin_define ("__riscv_cmodel_medany"); -+ break; -+ -+ case CM_PIC: -+ builtin_define ("__riscv_cmodel_pic"); -+ break; -+ } -+} -diff --git original-gcc/gcc/config/riscv/riscv-ftypes.def gcc-6.3.0/gcc/config/riscv/riscv-ftypes.def -new file mode 100644 -index 00000000000..eb69148368f ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/riscv-ftypes.def -@@ -0,0 +1,30 @@ -+/* Definitions of prototypes for RISC-V built-in functions. -*- C -*- -+ Copyright (C) 2011-2017 Free Software Foundation, Inc. -+ Contributed by Andrew Waterman (andrew@sifive.com). -+ Based on MIPS target for GNU compiler. -+ -+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 -+. */ -+ -+/* Invoke DEF_RISCV_FTYPE (NARGS, LIST) for each prototype used by -+ RISCV built-in functions, where: -+ -+ NARGS is the number of arguments. -+ LIST contains the return-type code followed by the codes for each -+ argument type. */ -+ -+DEF_RISCV_FTYPE (1, (USI, VOID)) -+DEF_RISCV_FTYPE (1, (VOID, USI)) -diff --git original-gcc/gcc/config/riscv/riscv-modes.def gcc-6.3.0/gcc/config/riscv/riscv-modes.def -new file mode 100644 -index 00000000000..5c65667da68 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/riscv-modes.def -@@ -0,0 +1,22 @@ -+/* Extra machine modes for RISC-V target. -+ Copyright (C) 2011-2017 Free Software Foundation, Inc. -+ Contributed by Andrew Waterman (andrew@sifive.com). -+ Based on MIPS target for GNU compiler. -+ -+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 -+. */ -+ -+FLOAT_MODE (TF, 16, ieee_quad_format); -diff --git original-gcc/gcc/config/riscv/riscv-opts.h gcc-6.3.0/gcc/config/riscv/riscv-opts.h -new file mode 100644 -index 00000000000..2b19233379c ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/riscv-opts.h -@@ -0,0 +1,41 @@ -+/* Definition of RISC-V target for GNU compiler. -+ Copyright (C) 2016-2017 Free Software Foundation, Inc. -+ Contributed by Andrew Waterman (andrew@sifive.com). -+ -+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 -+. */ -+ -+#ifndef GCC_RISCV_OPTS_H -+#define GCC_RISCV_OPTS_H -+ -+enum riscv_abi_type { -+ ABI_ILP32, -+ ABI_ILP32F, -+ ABI_ILP32D, -+ ABI_LP64, -+ ABI_LP64F, -+ ABI_LP64D -+}; -+extern enum riscv_abi_type riscv_abi; -+ -+enum riscv_code_model { -+ CM_MEDLOW, -+ CM_MEDANY, -+ CM_PIC -+}; -+extern enum riscv_code_model riscv_cmodel; -+ -+#endif /* ! GCC_RISCV_OPTS_H */ -diff --git original-gcc/gcc/config/riscv/riscv-protos.h gcc-6.3.0/gcc/config/riscv/riscv-protos.h -new file mode 100644 -index 00000000000..de7023f88c5 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/riscv-protos.h -@@ -0,0 +1,83 @@ -+/* Definition of RISC-V target for GNU compiler. -+ Copyright (C) 2011-2017 Free Software Foundation, Inc. -+ Contributed by Andrew Waterman (andrew@sifive.com). -+ Based on MIPS target for GNU compiler. -+ -+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 -+. */ -+ -+#ifndef GCC_RISCV_PROTOS_H -+#define GCC_RISCV_PROTOS_H -+ -+/* Symbol types we understand. The order of this list must match that of -+ the unspec enum in riscv.md, subsequent to UNSPEC_ADDRESS_FIRST. */ -+enum riscv_symbol_type { -+ SYMBOL_ABSOLUTE, -+ SYMBOL_PCREL, -+ SYMBOL_GOT_DISP, -+ SYMBOL_TLS, -+ SYMBOL_TLS_LE, -+ SYMBOL_TLS_IE, -+ SYMBOL_TLS_GD -+}; -+#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1) -+ -+/* Routines implemented in riscv.c. */ -+extern enum riscv_symbol_type riscv_classify_symbolic_expression (rtx); -+extern bool riscv_symbolic_constant_p (rtx, enum riscv_symbol_type *); -+extern int riscv_regno_mode_ok_for_base_p (int, enum machine_mode, bool); -+extern bool riscv_hard_regno_mode_ok_p (unsigned int, enum machine_mode); -+extern int riscv_address_insns (rtx, enum machine_mode, bool); -+extern int riscv_const_insns (rtx); -+extern int riscv_split_const_insns (rtx); -+extern int riscv_load_store_insns (rtx, rtx_insn *); -+extern rtx riscv_emit_move (rtx, rtx); -+extern bool riscv_split_symbol (rtx, rtx, enum machine_mode, rtx *); -+extern bool riscv_split_symbol_type (enum riscv_symbol_type); -+extern rtx riscv_unspec_address (rtx, enum riscv_symbol_type); -+extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT); -+extern bool riscv_legitimize_move (enum machine_mode, rtx, rtx); -+extern rtx riscv_subword (rtx, bool); -+extern bool riscv_split_64bit_move_p (rtx, rtx); -+extern void riscv_split_doubleword_move (rtx, rtx); -+extern const char *riscv_output_move (rtx, rtx); -+extern const char *riscv_output_gpr_save (unsigned); -+#ifdef RTX_CODE -+extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx); -+extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx); -+extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx); -+#endif -+extern rtx riscv_legitimize_call_address (rtx); -+extern void riscv_set_return_address (rtx, rtx); -+extern bool riscv_expand_block_move (rtx, rtx, rtx); -+extern rtx riscv_return_addr (int, rtx); -+extern HOST_WIDE_INT riscv_initial_elimination_offset (int, int); -+extern void riscv_expand_prologue (void); -+extern void riscv_expand_epilogue (bool); -+extern bool riscv_can_use_return_insn (void); -+extern rtx riscv_function_value (const_tree, const_tree, enum machine_mode); -+extern unsigned int riscv_hard_regno_nregs (int, enum machine_mode); -+ -+/* Routines implemented in riscv-c.c. */ -+void riscv_cpu_cpp_builtins (cpp_reader *); -+ -+/* Routines implemented in riscv-builtins.c. */ -+extern void riscv_atomic_assign_expand_fenv (tree *, tree *, tree *); -+extern rtx riscv_expand_builtin (tree, rtx, rtx, enum machine_mode, int); -+extern tree riscv_builtin_decl (unsigned int, bool); -+extern void riscv_init_builtins (void); -+ -+#endif /* ! GCC_RISCV_PROTOS_H */ -diff --git original-gcc/gcc/config/riscv/riscv.c gcc-6.3.0/gcc/config/riscv/riscv.c -new file mode 100644 -index 00000000000..834651f4214 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/riscv.c -@@ -0,0 +1,4138 @@ -+/* Subroutines used for code generation for RISC-V. -+ Copyright (C) 2011-2017 Free Software Foundation, Inc. -+ Contributed by Andrew Waterman (andrew@sifive.com). -+ Based on MIPS target for GNU compiler. -+ -+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 -+. */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "rtl.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "insn-config.h" -+#include "conditions.h" -+#include "insn-attr.h" -+#include "recog.h" -+#include "output.h" -+#include "hash-set.h" -+#include "machmode.h" -+#include "vec.h" -+#include "double-int.h" -+#include "input.h" -+#include "alias.h" -+#include "symtab.h" -+#include "wide-int.h" -+#include "inchash.h" -+#include "tree.h" -+#include "fold-const.h" -+#include "varasm.h" -+#include "stringpool.h" -+#include "stor-layout.h" -+#include "calls.h" -+#include "function.h" -+#include "hashtab.h" -+#include "flags.h" -+#include "statistics.h" -+#include "real.h" -+#include "fixed-value.h" -+#include "expmed.h" -+#include "dojump.h" -+#include "explow.h" -+#include "memmodel.h" -+#include "emit-rtl.h" -+#include "stmt.h" -+#include "expr.h" -+#include "insn-codes.h" -+#include "optabs.h" -+#include "libfuncs.h" -+#include "reload.h" -+#include "tm_p.h" -+#include "ggc.h" -+#include "gstab.h" -+#include "hash-table.h" -+#include "debug.h" -+#include "target.h" -+#include "target-def.h" -+#include "common/common-target.h" -+#include "langhooks.h" -+#include "dominance.h" -+#include "cfg.h" -+#include "cfgrtl.h" -+#include "cfganal.h" -+#include "lcm.h" -+#include "cfgbuild.h" -+#include "cfgcleanup.h" -+#include "predict.h" -+#include "basic-block.h" -+#include "bitmap.h" -+#include "regset.h" -+#include "df.h" -+#include "sched-int.h" -+#include "tree-ssa-alias.h" -+#include "internal-fn.h" -+#include "gimple-fold.h" -+#include "tree-eh.h" -+#include "gimple-expr.h" -+#include "is-a.h" -+#include "gimple.h" -+#include "gimplify.h" -+#include "diagnostic.h" -+#include "target-globals.h" -+#include "opts.h" -+#include "tree-pass.h" -+#include "context.h" -+#include "hash-map.h" -+#include "plugin-api.h" -+#include "ipa-ref.h" -+#include "cgraph.h" -+#include "builtins.h" -+#include "rtl-iter.h" -+ -+/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */ -+#define UNSPEC_ADDRESS_P(X) \ -+ (GET_CODE (X) == UNSPEC \ -+ && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST \ -+ && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES) -+ -+/* Extract the symbol or label from UNSPEC wrapper X. */ -+#define UNSPEC_ADDRESS(X) \ -+ XVECEXP (X, 0, 0) -+ -+/* Extract the symbol type from UNSPEC wrapper X. */ -+#define UNSPEC_ADDRESS_TYPE(X) \ -+ ((enum riscv_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST)) -+ -+/* True if bit BIT is set in VALUE. */ -+#define BITSET_P(VALUE, BIT) (((VALUE) & (1ULL << (BIT))) != 0) -+ -+/* Classifies an address. -+ -+ ADDRESS_REG -+ A natural register + offset address. The register satisfies -+ riscv_valid_base_register_p and the offset is a const_arith_operand. -+ -+ ADDRESS_LO_SUM -+ A LO_SUM rtx. The first operand is a valid base register and -+ the second operand is a symbolic address. -+ -+ ADDRESS_CONST_INT -+ A signed 16-bit constant address. -+ -+ ADDRESS_SYMBOLIC: -+ A constant symbolic address. */ -+enum riscv_address_type { -+ ADDRESS_REG, -+ ADDRESS_LO_SUM, -+ ADDRESS_CONST_INT, -+ ADDRESS_SYMBOLIC -+}; -+ -+/* Information about a function's frame layout. */ -+struct GTY(()) riscv_frame_info { -+ /* The size of the frame in bytes. */ -+ HOST_WIDE_INT total_size; -+ -+ /* Bit X is set if the function saves or restores GPR X. */ -+ unsigned int mask; -+ -+ /* Likewise FPR X. */ -+ unsigned int fmask; -+ -+ /* How much the GPR save/restore routines adjust sp (or 0 if unused). */ -+ unsigned save_libcall_adjustment; -+ -+ /* Offsets of fixed-point and floating-point save areas from frame bottom */ -+ HOST_WIDE_INT gp_sp_offset; -+ HOST_WIDE_INT fp_sp_offset; -+ -+ /* Offset of virtual frame pointer from stack pointer/frame bottom */ -+ HOST_WIDE_INT frame_pointer_offset; -+ -+ /* Offset of hard frame pointer from stack pointer/frame bottom */ -+ HOST_WIDE_INT hard_frame_pointer_offset; -+ -+ /* The offset of arg_pointer_rtx from the bottom of the frame. */ -+ HOST_WIDE_INT arg_pointer_offset; -+}; -+ -+struct GTY(()) machine_function { -+ /* The number of extra stack bytes taken up by register varargs. -+ This area is allocated by the callee at the very top of the frame. */ -+ int varargs_size; -+ -+ /* Memoized return value of leaf_function_p. <0 if false, >0 if true. */ -+ int is_leaf; -+ -+ /* The current frame information, calculated by riscv_compute_frame_info. */ -+ struct riscv_frame_info frame; -+}; -+ -+/* Information about a single argument. */ -+struct riscv_arg_info { -+ /* True if the argument is at least partially passed on the stack. */ -+ bool stack_p; -+ -+ /* The number of integer registers allocated to this argument. */ -+ unsigned int num_gprs; -+ -+ /* The offset of the first register used, provided num_gprs is nonzero. -+ If passed entirely on the stack, the value is MAX_ARGS_IN_REGISTERS. */ -+ unsigned int gpr_offset; -+ -+ /* The number of floating-point registers allocated to this argument. */ -+ unsigned int num_fprs; -+ -+ /* The offset of the first register used, provided num_fprs is nonzero. */ -+ unsigned int fpr_offset; -+}; -+ -+/* Information about an address described by riscv_address_type. -+ -+ ADDRESS_CONST_INT -+ No fields are used. -+ -+ ADDRESS_REG -+ REG is the base register and OFFSET is the constant offset. -+ -+ ADDRESS_LO_SUM -+ REG and OFFSET are the operands to the LO_SUM and SYMBOL_TYPE -+ is the type of symbol it references. -+ -+ ADDRESS_SYMBOLIC -+ SYMBOL_TYPE is the type of symbol that the address references. */ -+struct riscv_address_info { -+ enum riscv_address_type type; -+ rtx reg; -+ rtx offset; -+ enum riscv_symbol_type symbol_type; -+}; -+ -+/* One stage in a constant building sequence. These sequences have -+ the form: -+ -+ A = VALUE[0] -+ A = A CODE[1] VALUE[1] -+ A = A CODE[2] VALUE[2] -+ ... -+ -+ where A is an accumulator, each CODE[i] is a binary rtl operation -+ and each VALUE[i] is a constant integer. CODE[0] is undefined. */ -+struct riscv_integer_op { -+ enum rtx_code code; -+ unsigned HOST_WIDE_INT value; -+}; -+ -+/* The largest number of operations needed to load an integer constant. -+ The worst case is LUI, ADDI, SLLI, ADDI, SLLI, ADDI, SLLI, ADDI. */ -+#define RISCV_MAX_INTEGER_OPS 8 -+ -+/* Costs of various operations on the different architectures. */ -+ -+struct riscv_tune_info -+{ -+ unsigned short fp_add[2]; -+ unsigned short fp_mul[2]; -+ unsigned short fp_div[2]; -+ unsigned short int_mul[2]; -+ unsigned short int_div[2]; -+ unsigned short issue_rate; -+ unsigned short branch_cost; -+ unsigned short memory_cost; -+}; -+ -+/* Information about one CPU we know about. */ -+struct riscv_cpu_info { -+ /* This CPU's canonical name. */ -+ const char *name; -+ -+ /* Tuning parameters for this CPU. */ -+ const struct riscv_tune_info *tune_info; -+}; -+ -+/* Global variables for machine-dependent things. */ -+ -+/* Which tuning parameters to use. */ -+static const struct riscv_tune_info *tune_info; -+ -+/* Index R is the smallest register class that contains register R. */ -+const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = { -+ GR_REGS, GR_REGS, GR_REGS, GR_REGS, -+ GR_REGS, GR_REGS, SIBCALL_REGS, SIBCALL_REGS, -+ JALR_REGS, JALR_REGS, JALR_REGS, JALR_REGS, -+ JALR_REGS, JALR_REGS, JALR_REGS, JALR_REGS, -+ JALR_REGS, JALR_REGS, JALR_REGS, JALR_REGS, -+ JALR_REGS, JALR_REGS, JALR_REGS, JALR_REGS, -+ JALR_REGS, JALR_REGS, JALR_REGS, JALR_REGS, -+ SIBCALL_REGS, SIBCALL_REGS, SIBCALL_REGS, SIBCALL_REGS, -+ FP_REGS, FP_REGS, FP_REGS, FP_REGS, -+ FP_REGS, FP_REGS, FP_REGS, FP_REGS, -+ FP_REGS, FP_REGS, FP_REGS, FP_REGS, -+ FP_REGS, FP_REGS, FP_REGS, FP_REGS, -+ FP_REGS, FP_REGS, FP_REGS, FP_REGS, -+ FP_REGS, FP_REGS, FP_REGS, FP_REGS, -+ FP_REGS, FP_REGS, FP_REGS, FP_REGS, -+ FP_REGS, FP_REGS, FP_REGS, FP_REGS, -+ FRAME_REGS, FRAME_REGS, -+}; -+ -+/* Costs to use when optimizing for rocket. */ -+static const struct riscv_tune_info rocket_tune_info = { -+ {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_add */ -+ {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_mul */ -+ {COSTS_N_INSNS (20), COSTS_N_INSNS (20)}, /* fp_div */ -+ {COSTS_N_INSNS (4), COSTS_N_INSNS (4)}, /* int_mul */ -+ {COSTS_N_INSNS (6), COSTS_N_INSNS (6)}, /* int_div */ -+ 1, /* issue_rate */ -+ 3, /* branch_cost */ -+ 5 /* memory_cost */ -+}; -+ -+/* Costs to use when optimizing for size. */ -+static const struct riscv_tune_info optimize_size_tune_info = { -+ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_add */ -+ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_mul */ -+ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_div */ -+ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* int_mul */ -+ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* int_div */ -+ 1, /* issue_rate */ -+ 1, /* branch_cost */ -+ 2 /* memory_cost */ -+}; -+ -+/* A table describing all the processors GCC knows about. */ -+static const struct riscv_cpu_info riscv_cpu_info_table[] = { -+ { "rocket", &rocket_tune_info }, -+}; -+ -+/* Return the riscv_cpu_info entry for the given name string. */ -+ -+static const struct riscv_cpu_info * -+riscv_parse_cpu (const char *cpu_string) -+{ -+ for (unsigned i = 0; i < ARRAY_SIZE (riscv_cpu_info_table); i++) -+ if (strcmp (riscv_cpu_info_table[i].name, cpu_string) == 0) -+ return riscv_cpu_info_table + i; -+ -+ error ("unknown cpu %qs for -mtune", cpu_string); -+ return riscv_cpu_info_table; -+} -+ -+/* Helper function for riscv_build_integer; arguments are as for -+ riscv_build_integer. */ -+ -+static int -+riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS], -+ HOST_WIDE_INT value, enum machine_mode mode) -+{ -+ HOST_WIDE_INT low_part = CONST_LOW_PART (value); -+ int cost = RISCV_MAX_INTEGER_OPS + 1, alt_cost; -+ struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS]; -+ -+ if (SMALL_OPERAND (value) || LUI_OPERAND (value)) -+ { -+ /* Simply ADDI or LUI. */ -+ codes[0].code = UNKNOWN; -+ codes[0].value = value; -+ return 1; -+ } -+ -+ /* End with ADDI. When constructing HImode constants, do not generate any -+ intermediate value that is not itself a valid HImode constant. The -+ XORI case below will handle those remaining HImode constants. */ -+ if (low_part != 0 && (mode != HImode || value - low_part <= INT16_MAX)) -+ { -+ alt_cost = 1 + riscv_build_integer_1 (alt_codes, value - low_part, mode); -+ if (alt_cost < cost) -+ { -+ alt_codes[alt_cost-1].code = PLUS; -+ alt_codes[alt_cost-1].value = low_part; -+ memcpy (codes, alt_codes, sizeof (alt_codes)); -+ cost = alt_cost; -+ } -+ } -+ -+ /* End with XORI. */ -+ if (cost > 2 && (low_part < 0 || mode == HImode)) -+ { -+ alt_cost = 1 + riscv_build_integer_1 (alt_codes, value ^ low_part, mode); -+ if (alt_cost < cost) -+ { -+ alt_codes[alt_cost-1].code = XOR; -+ alt_codes[alt_cost-1].value = low_part; -+ memcpy (codes, alt_codes, sizeof (alt_codes)); -+ cost = alt_cost; -+ } -+ } -+ -+ /* Eliminate trailing zeros and end with SLLI. */ -+ if (cost > 2 && (value & 1) == 0) -+ { -+ int shift = ctz_hwi (value); -+ unsigned HOST_WIDE_INT x = value; -+ x = sext_hwi (x >> shift, HOST_BITS_PER_WIDE_INT - shift); -+ -+ /* Don't eliminate the lower 12 bits if LUI might apply. */ -+ if (shift > IMM_BITS && !SMALL_OPERAND (x) && LUI_OPERAND (x << IMM_BITS)) -+ shift -= IMM_BITS, x <<= IMM_BITS; -+ -+ alt_cost = 1 + riscv_build_integer_1 (alt_codes, x, mode); -+ if (alt_cost < cost) -+ { -+ alt_codes[alt_cost-1].code = ASHIFT; -+ alt_codes[alt_cost-1].value = shift; -+ memcpy (codes, alt_codes, sizeof (alt_codes)); -+ cost = alt_cost; -+ } -+ } -+ -+ gcc_assert (cost <= RISCV_MAX_INTEGER_OPS); -+ return cost; -+} -+ -+/* Fill CODES with a sequence of rtl operations to load VALUE. -+ Return the number of operations needed. */ -+ -+static int -+riscv_build_integer (struct riscv_integer_op *codes, HOST_WIDE_INT value, -+ enum machine_mode mode) -+{ -+ int cost = riscv_build_integer_1 (codes, value, mode); -+ -+ /* Eliminate leading zeros and end with SRLI. */ -+ if (value > 0 && cost > 2) -+ { -+ struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS]; -+ int alt_cost, shift = clz_hwi (value); -+ HOST_WIDE_INT shifted_val; -+ -+ /* Try filling trailing bits with 1s. */ -+ shifted_val = (value << shift) | ((((HOST_WIDE_INT) 1) << shift) - 1); -+ alt_cost = 1 + riscv_build_integer_1 (alt_codes, shifted_val, mode); -+ if (alt_cost < cost) -+ { -+ alt_codes[alt_cost-1].code = LSHIFTRT; -+ alt_codes[alt_cost-1].value = shift; -+ memcpy (codes, alt_codes, sizeof (alt_codes)); -+ cost = alt_cost; -+ } -+ -+ /* Try filling trailing bits with 0s. */ -+ shifted_val = value << shift; -+ alt_cost = 1 + riscv_build_integer_1 (alt_codes, shifted_val, mode); -+ if (alt_cost < cost) -+ { -+ alt_codes[alt_cost-1].code = LSHIFTRT; -+ alt_codes[alt_cost-1].value = shift; -+ memcpy (codes, alt_codes, sizeof (alt_codes)); -+ cost = alt_cost; -+ } -+ } -+ -+ return cost; -+} -+ -+/* Return the cost of constructing VAL in the event that a scratch -+ register is available. */ -+ -+static int -+riscv_split_integer_cost (HOST_WIDE_INT val) -+{ -+ int cost; -+ unsigned HOST_WIDE_INT loval = sext_hwi (val, 32); -+ unsigned HOST_WIDE_INT hival = sext_hwi ((val - loval) >> 32, 32); -+ struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; -+ -+ cost = 2 + riscv_build_integer (codes, loval, VOIDmode); -+ if (loval != hival) -+ cost += riscv_build_integer (codes, hival, VOIDmode); -+ -+ return cost; -+} -+ -+/* Return the cost of constructing the integer constant VAL. */ -+ -+static int -+riscv_integer_cost (HOST_WIDE_INT val) -+{ -+ struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; -+ return MIN (riscv_build_integer (codes, val, VOIDmode), -+ riscv_split_integer_cost (val)); -+} -+ -+/* Try to split a 64b integer into 32b parts, then reassemble. */ -+ -+static rtx -+riscv_split_integer (HOST_WIDE_INT val, enum machine_mode mode) -+{ -+ unsigned HOST_WIDE_INT loval = sext_hwi (val, 32); -+ unsigned HOST_WIDE_INT hival = sext_hwi ((val - loval) >> 32, 32); -+ rtx hi = gen_reg_rtx (mode), lo = gen_reg_rtx (mode); -+ -+ riscv_move_integer (hi, hi, hival); -+ riscv_move_integer (lo, lo, loval); -+ -+ hi = gen_rtx_fmt_ee (ASHIFT, mode, hi, GEN_INT (32)); -+ hi = force_reg (mode, hi); -+ -+ return gen_rtx_fmt_ee (PLUS, mode, hi, lo); -+} -+ -+/* Return true if X is a thread-local symbol. */ -+ -+static bool -+riscv_tls_symbol_p (const_rtx x) -+{ -+ return SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0; -+} -+ -+/* Return true if symbol X binds locally. */ -+ -+static bool -+riscv_symbol_binds_local_p (const_rtx x) -+{ -+ if (SYMBOL_REF_P (x)) -+ return (SYMBOL_REF_DECL (x) -+ ? targetm.binds_local_p (SYMBOL_REF_DECL (x)) -+ : SYMBOL_REF_LOCAL_P (x)); -+ else -+ return false; -+} -+ -+/* Return the method that should be used to access SYMBOL_REF or -+ LABEL_REF X. */ -+ -+static enum riscv_symbol_type -+riscv_classify_symbol (const_rtx x) -+{ -+ if (riscv_tls_symbol_p (x)) -+ return SYMBOL_TLS; -+ -+ if (GET_CODE (x) == SYMBOL_REF && flag_pic && !riscv_symbol_binds_local_p (x)) -+ return SYMBOL_GOT_DISP; -+ -+ return riscv_cmodel == CM_MEDLOW ? SYMBOL_ABSOLUTE : SYMBOL_PCREL; -+} -+ -+/* Classify the base of symbolic expression X. */ -+ -+enum riscv_symbol_type -+riscv_classify_symbolic_expression (rtx x) -+{ -+ rtx offset; -+ -+ split_const (x, &x, &offset); -+ if (UNSPEC_ADDRESS_P (x)) -+ return UNSPEC_ADDRESS_TYPE (x); -+ -+ return riscv_classify_symbol (x); -+} -+ -+/* Return true if X is a symbolic constant. If it is, store the type of -+ the symbol in *SYMBOL_TYPE. */ -+ -+bool -+riscv_symbolic_constant_p (rtx x, enum riscv_symbol_type *symbol_type) -+{ -+ rtx offset; -+ -+ split_const (x, &x, &offset); -+ if (UNSPEC_ADDRESS_P (x)) -+ { -+ *symbol_type = UNSPEC_ADDRESS_TYPE (x); -+ x = UNSPEC_ADDRESS (x); -+ } -+ else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) -+ *symbol_type = riscv_classify_symbol (x); -+ else -+ return false; -+ -+ if (offset == const0_rtx) -+ return true; -+ -+ /* Nonzero offsets are only valid for references that don't use the GOT. */ -+ switch (*symbol_type) -+ { -+ case SYMBOL_ABSOLUTE: -+ case SYMBOL_PCREL: -+ case SYMBOL_TLS_LE: -+ /* GAS rejects offsets outside the range [-2^31, 2^31-1]. */ -+ return sext_hwi (INTVAL (offset), 32) == INTVAL (offset); -+ -+ default: -+ return false; -+ } -+} -+ -+/* Returns the number of instructions necessary to reference a symbol. */ -+ -+static int riscv_symbol_insns (enum riscv_symbol_type type) -+{ -+ switch (type) -+ { -+ case SYMBOL_TLS: return 0; /* Depends on the TLS model. */ -+ case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference. */ -+ case SYMBOL_PCREL: return 2; /* AUIPC + the reference. */ -+ case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference. */ -+ case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference. */ -+ default: gcc_unreachable (); -+ } -+} -+ -+/* Implement TARGET_LEGITIMATE_CONSTANT_P. */ -+ -+static bool -+riscv_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) -+{ -+ return riscv_const_insns (x) > 0; -+} -+ -+/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */ -+ -+static bool -+riscv_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) -+{ -+ enum riscv_symbol_type type; -+ rtx base, offset; -+ -+ /* There is no assembler syntax for expressing an address-sized -+ high part. */ -+ if (GET_CODE (x) == HIGH) -+ return true; -+ -+ split_const (x, &base, &offset); -+ if (riscv_symbolic_constant_p (base, &type)) -+ { -+ /* As an optimization, don't spill symbolic constants that are as -+ cheap to rematerialize as to access in the constant pool. */ -+ if (SMALL_OPERAND (INTVAL (offset)) && riscv_symbol_insns (type) > 0) -+ return true; -+ -+ /* As an optimization, avoid needlessly generate dynamic relocations. */ -+ if (flag_pic) -+ return true; -+ } -+ -+ /* TLS symbols must be computed by riscv_legitimize_move. */ -+ if (tls_referenced_p (x)) -+ return true; -+ -+ return false; -+} -+ -+/* Return true if register REGNO is a valid base register for mode MODE. -+ STRICT_P is true if REG_OK_STRICT is in effect. */ -+ -+int -+riscv_regno_mode_ok_for_base_p (int regno, -+ enum machine_mode mode ATTRIBUTE_UNUSED, -+ bool strict_p) -+{ -+ if (!HARD_REGISTER_NUM_P (regno)) -+ { -+ if (!strict_p) -+ return true; -+ regno = reg_renumber[regno]; -+ } -+ -+ /* These fake registers will be eliminated to either the stack or -+ hard frame pointer, both of which are usually valid base registers. -+ Reload deals with the cases where the eliminated form isn't valid. */ -+ if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM) -+ return true; -+ -+ return GP_REG_P (regno); -+} -+ -+/* Return true if X is a valid base register for mode MODE. -+ STRICT_P is true if REG_OK_STRICT is in effect. */ -+ -+static bool -+riscv_valid_base_register_p (rtx x, enum machine_mode mode, bool strict_p) -+{ -+ if (!strict_p && GET_CODE (x) == SUBREG) -+ x = SUBREG_REG (x); -+ -+ return (REG_P (x) -+ && riscv_regno_mode_ok_for_base_p (REGNO (x), mode, strict_p)); -+} -+ -+/* Return true if, for every base register BASE_REG, (plus BASE_REG X) -+ can address a value of mode MODE. */ -+ -+static bool -+riscv_valid_offset_p (rtx x, enum machine_mode mode) -+{ -+ /* Check that X is a signed 12-bit number. */ -+ if (!const_arith_operand (x, Pmode)) -+ return false; -+ -+ /* We may need to split multiword moves, so make sure that every word -+ is accessible. */ -+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD -+ && !SMALL_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD)) -+ return false; -+ -+ return true; -+} -+ -+/* Should a symbol of type SYMBOL_TYPE should be split in two? */ -+ -+bool -+riscv_split_symbol_type (enum riscv_symbol_type symbol_type) -+{ -+ if (symbol_type == SYMBOL_TLS_LE) -+ return true; -+ -+ if (!TARGET_EXPLICIT_RELOCS) -+ return false; -+ -+ return symbol_type == SYMBOL_ABSOLUTE || symbol_type == SYMBOL_PCREL; -+} -+ -+/* Return true if a LO_SUM can address a value of mode MODE when the -+ LO_SUM symbol has type SYM_TYPE. */ -+ -+static bool -+riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, enum machine_mode mode) -+{ -+ /* Check that symbols of type SYMBOL_TYPE can be used to access values -+ of mode MODE. */ -+ if (riscv_symbol_insns (sym_type) == 0) -+ return false; -+ -+ /* Check that there is a known low-part relocation. */ -+ if (!riscv_split_symbol_type (sym_type)) -+ return false; -+ -+ /* We may need to split multiword moves, so make sure that each word -+ can be accessed without inducing a carry. */ -+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD -+ && GET_MODE_BITSIZE (mode) > GET_MODE_ALIGNMENT (mode)) -+ return false; -+ -+ return true; -+} -+ -+/* Return true if X is a valid address for machine mode MODE. If it is, -+ fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in -+ effect. */ -+ -+static bool -+riscv_classify_address (struct riscv_address_info *info, rtx x, -+ enum machine_mode mode, bool strict_p) -+{ -+ switch (GET_CODE (x)) -+ { -+ case REG: -+ case SUBREG: -+ info->type = ADDRESS_REG; -+ info->reg = x; -+ info->offset = const0_rtx; -+ return riscv_valid_base_register_p (info->reg, mode, strict_p); -+ -+ case PLUS: -+ info->type = ADDRESS_REG; -+ info->reg = XEXP (x, 0); -+ info->offset = XEXP (x, 1); -+ return (riscv_valid_base_register_p (info->reg, mode, strict_p) -+ && riscv_valid_offset_p (info->offset, mode)); -+ -+ case LO_SUM: -+ info->type = ADDRESS_LO_SUM; -+ info->reg = XEXP (x, 0); -+ info->offset = XEXP (x, 1); -+ /* We have to trust the creator of the LO_SUM to do something vaguely -+ sane. Target-independent code that creates a LO_SUM should also -+ create and verify the matching HIGH. Target-independent code that -+ adds an offset to a LO_SUM must prove that the offset will not -+ induce a carry. Failure to do either of these things would be -+ a bug, and we are not required to check for it here. The RISC-V -+ backend itself should only create LO_SUMs for valid symbolic -+ constants, with the high part being either a HIGH or a copy -+ of _gp. */ -+ info->symbol_type -+ = riscv_classify_symbolic_expression (info->offset); -+ return (riscv_valid_base_register_p (info->reg, mode, strict_p) -+ && riscv_valid_lo_sum_p (info->symbol_type, mode)); -+ -+ case CONST_INT: -+ /* Small-integer addresses don't occur very often, but they -+ are legitimate if x0 is a valid base register. */ -+ info->type = ADDRESS_CONST_INT; -+ return SMALL_OPERAND (INTVAL (x)); -+ -+ default: -+ return false; -+ } -+} -+ -+/* Implement TARGET_LEGITIMATE_ADDRESS_P. */ -+ -+static bool -+riscv_legitimate_address_p (enum machine_mode mode, rtx x, bool strict_p) -+{ -+ struct riscv_address_info addr; -+ -+ return riscv_classify_address (&addr, x, mode, strict_p); -+} -+ -+/* Return the number of instructions needed to load or store a value -+ of mode MODE at address X. Return 0 if X isn't valid for MODE. -+ Assume that multiword moves may need to be split into word moves -+ if MIGHT_SPLIT_P, otherwise assume that a single load or store is -+ enough. */ -+ -+int -+riscv_address_insns (rtx x, enum machine_mode mode, bool might_split_p) -+{ -+ struct riscv_address_info addr; -+ int n = 1; -+ -+ if (!riscv_classify_address (&addr, x, mode, false)) -+ return 0; -+ -+ /* BLKmode is used for single unaligned loads and stores and should -+ not count as a multiword mode. */ -+ if (mode != BLKmode && might_split_p) -+ n += (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; -+ -+ if (addr.type == ADDRESS_LO_SUM) -+ n += riscv_symbol_insns (addr.symbol_type) - 1; -+ -+ return n; -+} -+ -+/* Return the number of instructions needed to load constant X. -+ Return 0 if X isn't a valid constant. */ -+ -+int -+riscv_const_insns (rtx x) -+{ -+ enum riscv_symbol_type symbol_type; -+ rtx offset; -+ -+ switch (GET_CODE (x)) -+ { -+ case HIGH: -+ if (!riscv_symbolic_constant_p (XEXP (x, 0), &symbol_type) -+ || !riscv_split_symbol_type (symbol_type)) -+ return 0; -+ -+ /* This is simply an LUI. */ -+ return 1; -+ -+ case CONST_INT: -+ { -+ int cost = riscv_integer_cost (INTVAL (x)); -+ /* Force complicated constants to memory. */ -+ return cost < 4 ? cost : 0; -+ } -+ -+ case CONST_DOUBLE: -+ case CONST_VECTOR: -+ /* We can use x0 to load floating-point zero. */ -+ return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0; -+ -+ case CONST: -+ /* See if we can refer to X directly. */ -+ if (riscv_symbolic_constant_p (x, &symbol_type)) -+ return riscv_symbol_insns (symbol_type); -+ -+ /* Otherwise try splitting the constant into a base and offset. */ -+ split_const (x, &x, &offset); -+ if (offset != 0) -+ { -+ int n = riscv_const_insns (x); -+ if (n != 0) -+ return n + riscv_integer_cost (INTVAL (offset)); -+ } -+ return 0; -+ -+ case SYMBOL_REF: -+ case LABEL_REF: -+ return riscv_symbol_insns (riscv_classify_symbol (x)); -+ -+ default: -+ return 0; -+ } -+} -+ -+/* X is a doubleword constant that can be handled by splitting it into -+ two words and loading each word separately. Return the number of -+ instructions required to do this. */ -+ -+int -+riscv_split_const_insns (rtx x) -+{ -+ unsigned int low, high; -+ -+ low = riscv_const_insns (riscv_subword (x, false)); -+ high = riscv_const_insns (riscv_subword (x, true)); -+ gcc_assert (low > 0 && high > 0); -+ return low + high; -+} -+ -+/* Return the number of instructions needed to implement INSN, -+ given that it loads from or stores to MEM. */ -+ -+int -+riscv_load_store_insns (rtx mem, rtx_insn *insn) -+{ -+ enum machine_mode mode; -+ bool might_split_p; -+ rtx set; -+ -+ gcc_assert (MEM_P (mem)); -+ mode = GET_MODE (mem); -+ -+ /* Try to prove that INSN does not need to be split. */ -+ might_split_p = true; -+ if (GET_MODE_BITSIZE (mode) <= 32) -+ might_split_p = false; -+ else if (GET_MODE_BITSIZE (mode) == 64) -+ { -+ set = single_set (insn); -+ if (set && !riscv_split_64bit_move_p (SET_DEST (set), SET_SRC (set))) -+ might_split_p = false; -+ } -+ -+ return riscv_address_insns (XEXP (mem, 0), mode, might_split_p); -+} -+ -+/* Emit a move from SRC to DEST. Assume that the move expanders can -+ handle all moves if !can_create_pseudo_p (). The distinction is -+ important because, unlike emit_move_insn, the move expanders know -+ how to force Pmode objects into the constant pool even when the -+ constant pool address is not itself legitimate. */ -+ -+rtx -+riscv_emit_move (rtx dest, rtx src) -+{ -+ return (can_create_pseudo_p () -+ ? emit_move_insn (dest, src) -+ : emit_move_insn_1 (dest, src)); -+} -+ -+/* Emit an instruction of the form (set TARGET SRC). */ -+ -+static rtx -+riscv_emit_set (rtx target, rtx src) -+{ -+ emit_insn (gen_rtx_SET (target, src)); -+ return target; -+} -+ -+/* Emit an instruction of the form (set DEST (CODE X Y)). */ -+ -+static rtx -+riscv_emit_binary (enum rtx_code code, rtx dest, rtx x, rtx y) -+{ -+ return riscv_emit_set (dest, gen_rtx_fmt_ee (code, GET_MODE (dest), x, y)); -+} -+ -+/* Compute (CODE X Y) and store the result in a new register -+ of mode MODE. Return that new register. */ -+ -+static rtx -+riscv_force_binary (enum machine_mode mode, enum rtx_code code, rtx x, rtx y) -+{ -+ return riscv_emit_binary (code, gen_reg_rtx (mode), x, y); -+} -+ -+/* Copy VALUE to a register and return that register. If new pseudos -+ are allowed, copy it into a new register, otherwise use DEST. */ -+ -+static rtx -+riscv_force_temporary (rtx dest, rtx value) -+{ -+ if (can_create_pseudo_p ()) -+ return force_reg (Pmode, value); -+ else -+ { -+ riscv_emit_move (dest, value); -+ return dest; -+ } -+} -+ -+/* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE, -+ then add CONST_INT OFFSET to the result. */ -+ -+static rtx -+riscv_unspec_address_offset (rtx base, rtx offset, -+ enum riscv_symbol_type symbol_type) -+{ -+ base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), -+ UNSPEC_ADDRESS_FIRST + symbol_type); -+ if (offset != const0_rtx) -+ base = gen_rtx_PLUS (Pmode, base, offset); -+ return gen_rtx_CONST (Pmode, base); -+} -+ -+/* Return an UNSPEC address with underlying address ADDRESS and symbol -+ type SYMBOL_TYPE. */ -+ -+rtx -+riscv_unspec_address (rtx address, enum riscv_symbol_type symbol_type) -+{ -+ rtx base, offset; -+ -+ split_const (address, &base, &offset); -+ return riscv_unspec_address_offset (base, offset, symbol_type); -+} -+ -+/* If OP is an UNSPEC address, return the address to which it refers, -+ otherwise return OP itself. */ -+ -+static rtx -+riscv_strip_unspec_address (rtx op) -+{ -+ rtx base, offset; -+ -+ split_const (op, &base, &offset); -+ if (UNSPEC_ADDRESS_P (base)) -+ op = plus_constant (Pmode, UNSPEC_ADDRESS (base), INTVAL (offset)); -+ return op; -+} -+ -+/* If riscv_unspec_address (ADDR, SYMBOL_TYPE) is a 32-bit value, add the -+ high part to BASE and return the result. Just return BASE otherwise. -+ TEMP is as for riscv_force_temporary. -+ -+ The returned expression can be used as the first operand to a LO_SUM. */ -+ -+static rtx -+riscv_unspec_offset_high (rtx temp, rtx addr, enum riscv_symbol_type symbol_type) -+{ -+ addr = gen_rtx_HIGH (Pmode, riscv_unspec_address (addr, symbol_type)); -+ return riscv_force_temporary (temp, addr); -+} -+ -+/* Load an entry from the GOT for a TLS GD access. */ -+ -+static rtx riscv_got_load_tls_gd (rtx dest, rtx sym) -+{ -+ if (Pmode == DImode) -+ return gen_got_load_tls_gddi (dest, sym); -+ else -+ return gen_got_load_tls_gdsi (dest, sym); -+} -+ -+/* Load an entry from the GOT for a TLS IE access. */ -+ -+static rtx riscv_got_load_tls_ie (rtx dest, rtx sym) -+{ -+ if (Pmode == DImode) -+ return gen_got_load_tls_iedi (dest, sym); -+ else -+ return gen_got_load_tls_iesi (dest, sym); -+} -+ -+/* Add in the thread pointer for a TLS LE access. */ -+ -+static rtx riscv_tls_add_tp_le (rtx dest, rtx base, rtx sym) -+{ -+ rtx tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); -+ if (Pmode == DImode) -+ return gen_tls_add_tp_ledi (dest, base, tp, sym); -+ else -+ return gen_tls_add_tp_lesi (dest, base, tp, sym); -+} -+ -+/* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise -+ it appears in a MEM of that mode. Return true if ADDR is a legitimate -+ constant in that context and can be split into high and low parts. -+ If so, and if LOW_OUT is nonnull, emit the high part and store the -+ low part in *LOW_OUT. Leave *LOW_OUT unchanged otherwise. -+ -+ TEMP is as for riscv_force_temporary and is used to load the high -+ part into a register. -+ -+ When MODE is MAX_MACHINE_MODE, the low part is guaranteed to be -+ a legitimize SET_SRC for an .md pattern, otherwise the low part -+ is guaranteed to be a legitimate address for mode MODE. */ -+ -+bool -+riscv_split_symbol (rtx temp, rtx addr, enum machine_mode mode, rtx *low_out) -+{ -+ enum riscv_symbol_type symbol_type; -+ -+ if ((GET_CODE (addr) == HIGH && mode == MAX_MACHINE_MODE) -+ || !riscv_symbolic_constant_p (addr, &symbol_type) -+ || riscv_symbol_insns (symbol_type) == 0 -+ || !riscv_split_symbol_type (symbol_type)) -+ return false; -+ -+ if (low_out) -+ switch (symbol_type) -+ { -+ case SYMBOL_ABSOLUTE: -+ { -+ rtx high = gen_rtx_HIGH (Pmode, copy_rtx (addr)); -+ high = riscv_force_temporary (temp, high); -+ *low_out = gen_rtx_LO_SUM (Pmode, high, addr); -+ } -+ break; -+ -+ case SYMBOL_PCREL: -+ { -+ static unsigned seqno; -+ char buf[32]; -+ rtx label; -+ -+ ssize_t bytes = snprintf (buf, sizeof (buf), ".LA%u", seqno); -+ gcc_assert ((size_t) bytes < sizeof (buf)); -+ -+ label = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); -+ SYMBOL_REF_FLAGS (label) |= SYMBOL_FLAG_LOCAL; -+ -+ if (temp == NULL) -+ temp = gen_reg_rtx (Pmode); -+ -+ if (Pmode == DImode) -+ emit_insn (gen_auipcdi (temp, copy_rtx (addr), GEN_INT (seqno))); -+ else -+ emit_insn (gen_auipcsi (temp, copy_rtx (addr), GEN_INT (seqno))); -+ -+ *low_out = gen_rtx_LO_SUM (Pmode, temp, label); -+ -+ seqno++; -+ } -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return true; -+} -+ -+/* Return a legitimate address for REG + OFFSET. TEMP is as for -+ riscv_force_temporary; it is only needed when OFFSET is not a -+ SMALL_OPERAND. */ -+ -+static rtx -+riscv_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset) -+{ -+ if (!SMALL_OPERAND (offset)) -+ { -+ rtx high; -+ -+ /* Leave OFFSET as a 16-bit offset and put the excess in HIGH. -+ The addition inside the macro CONST_HIGH_PART may cause an -+ overflow, so we need to force a sign-extension check. */ -+ high = gen_int_mode (CONST_HIGH_PART (offset), Pmode); -+ offset = CONST_LOW_PART (offset); -+ high = riscv_force_temporary (temp, high); -+ reg = riscv_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg)); -+ } -+ return plus_constant (Pmode, reg, offset); -+} -+ -+/* The __tls_get_attr symbol. */ -+static GTY(()) rtx riscv_tls_symbol; -+ -+/* Return an instruction sequence that calls __tls_get_addr. SYM is -+ the TLS symbol we are referencing and TYPE is the symbol type to use -+ (either global dynamic or local dynamic). RESULT is an RTX for the -+ return value location. */ -+ -+static rtx_insn * -+riscv_call_tls_get_addr (rtx sym, rtx result) -+{ -+ rtx a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST), func; -+ rtx_insn *insn; -+ -+ if (!riscv_tls_symbol) -+ riscv_tls_symbol = init_one_libfunc ("__tls_get_addr"); -+ func = gen_rtx_MEM (FUNCTION_MODE, riscv_tls_symbol); -+ -+ start_sequence (); -+ -+ emit_insn (riscv_got_load_tls_gd (a0, sym)); -+ insn = emit_call_insn (gen_call_value (result, func, const0_rtx, NULL)); -+ RTL_CONST_CALL_P (insn) = 1; -+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0); -+ insn = get_insns (); -+ -+ end_sequence (); -+ -+ return insn; -+} -+ -+/* Generate the code to access LOC, a thread-local SYMBOL_REF, and return -+ its address. The return value will be both a valid address and a valid -+ SET_SRC (either a REG or a LO_SUM). */ -+ -+static rtx -+riscv_legitimize_tls_address (rtx loc) -+{ -+ rtx dest, tp, tmp; -+ enum tls_model model = SYMBOL_REF_TLS_MODEL (loc); -+ -+ /* Since we support TLS copy relocs, non-PIC TLS accesses may all use LE. */ -+ if (!flag_pic) -+ model = TLS_MODEL_LOCAL_EXEC; -+ -+ switch (model) -+ { -+ case TLS_MODEL_LOCAL_DYNAMIC: -+ /* Rely on section anchors for the optimization that LDM TLS -+ provides. The anchor's address is loaded with GD TLS. */ -+ case TLS_MODEL_GLOBAL_DYNAMIC: -+ tmp = gen_rtx_REG (Pmode, GP_RETURN); -+ dest = gen_reg_rtx (Pmode); -+ emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc); -+ break; -+ -+ case TLS_MODEL_INITIAL_EXEC: -+ /* la.tls.ie; tp-relative add */ -+ tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); -+ tmp = gen_reg_rtx (Pmode); -+ emit_insn (riscv_got_load_tls_ie (tmp, loc)); -+ dest = gen_reg_rtx (Pmode); -+ emit_insn (gen_add3_insn (dest, tmp, tp)); -+ break; -+ -+ case TLS_MODEL_LOCAL_EXEC: -+ tmp = riscv_unspec_offset_high (NULL, loc, SYMBOL_TLS_LE); -+ dest = gen_reg_rtx (Pmode); -+ emit_insn (riscv_tls_add_tp_le (dest, tmp, loc)); -+ dest = gen_rtx_LO_SUM (Pmode, dest, -+ riscv_unspec_address (loc, SYMBOL_TLS_LE)); -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ return dest; -+} -+ -+/* If X is not a valid address for mode MODE, force it into a register. */ -+ -+static rtx -+riscv_force_address (rtx x, enum machine_mode mode) -+{ -+ if (!riscv_legitimate_address_p (mode, x, false)) -+ x = force_reg (Pmode, x); -+ return x; -+} -+ -+/* This function is used to implement LEGITIMIZE_ADDRESS. If X can -+ be legitimized in a way that the generic machinery might not expect, -+ return a new address, otherwise return NULL. MODE is the mode of -+ the memory being accessed. */ -+ -+static rtx -+riscv_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, -+ enum machine_mode mode) -+{ -+ rtx addr; -+ -+ if (riscv_tls_symbol_p (x)) -+ return riscv_legitimize_tls_address (x); -+ -+ /* See if the address can split into a high part and a LO_SUM. */ -+ if (riscv_split_symbol (NULL, x, mode, &addr)) -+ return riscv_force_address (addr, mode); -+ -+ /* Handle BASE + OFFSET using riscv_add_offset. */ -+ if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)) -+ && INTVAL (XEXP (x, 1)) != 0) -+ { -+ rtx base = XEXP (x, 0); -+ HOST_WIDE_INT offset = INTVAL (XEXP (x, 1)); -+ -+ if (!riscv_valid_base_register_p (base, mode, false)) -+ base = copy_to_mode_reg (Pmode, base); -+ addr = riscv_add_offset (NULL, base, offset); -+ return riscv_force_address (addr, mode); -+ } -+ -+ return x; -+} -+ -+/* Load VALUE into DEST. TEMP is as for riscv_force_temporary. */ -+ -+void -+riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value) -+{ -+ struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; -+ enum machine_mode mode; -+ int i, num_ops; -+ rtx x; -+ -+ mode = GET_MODE (dest); -+ num_ops = riscv_build_integer (codes, value, mode); -+ -+ if (can_create_pseudo_p () && num_ops > 2 /* not a simple constant */ -+ && num_ops >= riscv_split_integer_cost (value)) -+ x = riscv_split_integer (value, mode); -+ else -+ { -+ /* Apply each binary operation to X. */ -+ x = GEN_INT (codes[0].value); -+ -+ for (i = 1; i < num_ops; i++) -+ { -+ if (!can_create_pseudo_p ()) -+ x = riscv_emit_set (temp, x); -+ else -+ x = force_reg (mode, x); -+ -+ x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value)); -+ } -+ } -+ -+ riscv_emit_set (dest, x); -+} -+ -+/* Subroutine of riscv_legitimize_move. Move constant SRC into register -+ DEST given that SRC satisfies immediate_operand but doesn't satisfy -+ move_operand. */ -+ -+static void -+riscv_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src) -+{ -+ rtx base, offset; -+ -+ /* Split moves of big integers into smaller pieces. */ -+ if (splittable_const_int_operand (src, mode)) -+ { -+ riscv_move_integer (dest, dest, INTVAL (src)); -+ return; -+ } -+ -+ /* Split moves of symbolic constants into high/low pairs. */ -+ if (riscv_split_symbol (dest, src, MAX_MACHINE_MODE, &src)) -+ { -+ riscv_emit_set (dest, src); -+ return; -+ } -+ -+ /* Generate the appropriate access sequences for TLS symbols. */ -+ if (riscv_tls_symbol_p (src)) -+ { -+ riscv_emit_move (dest, riscv_legitimize_tls_address (src)); -+ return; -+ } -+ -+ /* If we have (const (plus symbol offset)), and that expression cannot -+ be forced into memory, load the symbol first and add in the offset. Also -+ prefer to do this even if the constant _can_ be forced into memory, as it -+ usually produces better code. */ -+ split_const (src, &base, &offset); -+ if (offset != const0_rtx -+ && (targetm.cannot_force_const_mem (mode, src) || can_create_pseudo_p ())) -+ { -+ base = riscv_force_temporary (dest, base); -+ riscv_emit_move (dest, riscv_add_offset (NULL, base, INTVAL (offset))); -+ return; -+ } -+ -+ src = force_const_mem (mode, src); -+ -+ /* When using explicit relocs, constant pool references are sometimes -+ not legitimate addresses. */ -+ riscv_split_symbol (dest, XEXP (src, 0), mode, &XEXP (src, 0)); -+ riscv_emit_move (dest, src); -+} -+ -+/* If (set DEST SRC) is not a valid move instruction, emit an equivalent -+ sequence that is valid. */ -+ -+bool -+riscv_legitimize_move (enum machine_mode mode, rtx dest, rtx src) -+{ -+ if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode)) -+ { -+ riscv_emit_move (dest, force_reg (mode, src)); -+ return true; -+ } -+ -+ /* We need to deal with constants that would be legitimate -+ immediate_operands but aren't legitimate move_operands. */ -+ if (CONSTANT_P (src) && !move_operand (src, mode)) -+ { -+ riscv_legitimize_const_move (mode, dest, src); -+ set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src)); -+ return true; -+ } -+ -+ return false; -+} -+ -+/* Return true if there is an instruction that implements CODE and accepts -+ X as an immediate operand. */ -+ -+static int -+riscv_immediate_operand_p (int code, HOST_WIDE_INT x) -+{ -+ switch (code) -+ { -+ case ASHIFT: -+ case ASHIFTRT: -+ case LSHIFTRT: -+ /* All shift counts are truncated to a valid constant. */ -+ return true; -+ -+ case AND: -+ case IOR: -+ case XOR: -+ case PLUS: -+ case LT: -+ case LTU: -+ /* These instructions take 12-bit signed immediates. */ -+ return SMALL_OPERAND (x); -+ -+ case LE: -+ /* We add 1 to the immediate and use SLT. */ -+ return SMALL_OPERAND (x + 1); -+ -+ case LEU: -+ /* Likewise SLTU, but reject the always-true case. */ -+ return SMALL_OPERAND (x + 1) && x + 1 != 0; -+ -+ case GE: -+ case GEU: -+ /* We can emulate an immediate of 1 by using GT/GTU against x0. */ -+ return x == 1; -+ -+ default: -+ /* By default assume that x0 can be used for 0. */ -+ return x == 0; -+ } -+} -+ -+/* Return the cost of binary operation X, given that the instruction -+ sequence for a word-sized or smaller operation takes SIGNLE_INSNS -+ instructions and that the sequence of a double-word operation takes -+ DOUBLE_INSNS instructions. */ -+ -+static int -+riscv_binary_cost (rtx x, int single_insns, int double_insns) -+{ -+ if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2) -+ return COSTS_N_INSNS (double_insns); -+ return COSTS_N_INSNS (single_insns); -+} -+ -+/* Return the cost of sign- or zero-extending OP. */ -+ -+static int -+riscv_extend_cost (rtx op, bool unsigned_p) -+{ -+ if (MEM_P (op)) -+ return 0; -+ -+ if (unsigned_p && GET_MODE (op) == QImode) -+ /* We can use ANDI. */ -+ return COSTS_N_INSNS (1); -+ -+ if (!unsigned_p && GET_MODE (op) == SImode) -+ /* We can use SEXT.W. */ -+ return COSTS_N_INSNS (1); -+ -+ /* We need to use a shift left and a shift right. */ -+ return COSTS_N_INSNS (2); -+} -+ -+/* Implement TARGET_RTX_COSTS. */ -+ -+static bool -+riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UNUSED, -+ int *total, bool speed) -+{ -+ bool float_mode_p = FLOAT_MODE_P (mode); -+ int cost; -+ -+ switch (GET_CODE (x)) -+ { -+ case CONST_INT: -+ if (riscv_immediate_operand_p (outer_code, INTVAL (x))) -+ { -+ *total = 0; -+ return true; -+ } -+ /* Fall through. */ -+ -+ case SYMBOL_REF: -+ case LABEL_REF: -+ case CONST_DOUBLE: -+ case CONST: -+ if ((cost = riscv_const_insns (x)) > 0) -+ { -+ /* If the constant is likely to be stored in a GPR, SETs of -+ single-insn constants are as cheap as register sets; we -+ never want to CSE them. */ -+ if (cost == 1 && outer_code == SET) -+ *total = 0; -+ /* When we load a constant more than once, it usually is better -+ to duplicate the last operation in the sequence than to CSE -+ the constant itself. */ -+ else if (outer_code == SET || GET_MODE (x) == VOIDmode) -+ *total = COSTS_N_INSNS (1); -+ } -+ else /* The instruction will be fetched from the constant pool. */ -+ *total = COSTS_N_INSNS (riscv_symbol_insns (SYMBOL_ABSOLUTE)); -+ return true; -+ -+ case MEM: -+ /* If the address is legitimate, return the number of -+ instructions it needs. */ -+ if ((cost = riscv_address_insns (XEXP (x, 0), mode, true)) > 0) -+ { -+ *total = COSTS_N_INSNS (cost + tune_info->memory_cost); -+ return true; -+ } -+ /* Otherwise use the default handling. */ -+ return false; -+ -+ case NOT: -+ *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1); -+ return false; -+ -+ case AND: -+ case IOR: -+ case XOR: -+ /* Double-word operations use two single-word operations. */ -+ *total = riscv_binary_cost (x, 1, 2); -+ return false; -+ -+ case ASHIFT: -+ case ASHIFTRT: -+ case LSHIFTRT: -+ *total = riscv_binary_cost (x, 1, CONSTANT_P (XEXP (x, 1)) ? 4 : 9); -+ return false; -+ -+ case ABS: -+ *total = COSTS_N_INSNS (float_mode_p ? 1 : 3); -+ return false; -+ -+ case LO_SUM: -+ *total = set_src_cost (XEXP (x, 0), mode, speed); -+ return true; -+ -+ case LT: -+ case LTU: -+ case LE: -+ case LEU: -+ case GT: -+ case GTU: -+ case GE: -+ case GEU: -+ case EQ: -+ case NE: -+ /* Branch comparisons have VOIDmode, so use the first operand's -+ mode instead. */ -+ mode = GET_MODE (XEXP (x, 0)); -+ if (float_mode_p) -+ *total = tune_info->fp_add[mode == DFmode]; -+ else -+ *total = riscv_binary_cost (x, 1, 3); -+ return false; -+ -+ case UNORDERED: -+ case ORDERED: -+ /* (FEQ(A, A) & FEQ(B, B)) compared against 0. */ -+ mode = GET_MODE (XEXP (x, 0)); -+ *total = tune_info->fp_add[mode == DFmode] + COSTS_N_INSNS (2); -+ return false; -+ -+ case UNEQ: -+ case LTGT: -+ /* (FEQ(A, A) & FEQ(B, B)) compared against FEQ(A, B). */ -+ mode = GET_MODE (XEXP (x, 0)); -+ *total = tune_info->fp_add[mode == DFmode] + COSTS_N_INSNS (3); -+ return false; -+ -+ case UNGE: -+ case UNGT: -+ case UNLE: -+ case UNLT: -+ /* FLT or FLE, but guarded by an FFLAGS read and write. */ -+ mode = GET_MODE (XEXP (x, 0)); -+ *total = tune_info->fp_add[mode == DFmode] + COSTS_N_INSNS (4); -+ return false; -+ -+ case MINUS: -+ case PLUS: -+ if (float_mode_p) -+ *total = tune_info->fp_add[mode == DFmode]; -+ else -+ *total = riscv_binary_cost (x, 1, 4); -+ return false; -+ -+ case NEG: -+ { -+ rtx op = XEXP (x, 0); -+ if (GET_CODE (op) == FMA && !HONOR_SIGNED_ZEROS (mode)) -+ { -+ *total = (tune_info->fp_mul[mode == DFmode] -+ + set_src_cost (XEXP (op, 0), mode, speed) -+ + set_src_cost (XEXP (op, 1), mode, speed) -+ + set_src_cost (XEXP (op, 2), mode, speed)); -+ return true; -+ } -+ } -+ -+ if (float_mode_p) -+ *total = tune_info->fp_add[mode == DFmode]; -+ else -+ *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1); -+ return false; -+ -+ case MULT: -+ if (float_mode_p) -+ *total = tune_info->fp_mul[mode == DFmode]; -+ else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) -+ *total = 3 * tune_info->int_mul[0] + COSTS_N_INSNS (2); -+ else if (!speed) -+ *total = COSTS_N_INSNS (1); -+ else -+ *total = tune_info->int_mul[mode == DImode]; -+ return false; -+ -+ case DIV: -+ case SQRT: -+ case MOD: -+ if (float_mode_p) -+ { -+ *total = tune_info->fp_div[mode == DFmode]; -+ return false; -+ } -+ /* Fall through. */ -+ -+ case UDIV: -+ case UMOD: -+ if (speed) -+ *total = tune_info->int_div[mode == DImode]; -+ else -+ *total = COSTS_N_INSNS (1); -+ return false; -+ -+ case SIGN_EXTEND: -+ case ZERO_EXTEND: -+ *total = riscv_extend_cost (XEXP (x, 0), GET_CODE (x) == ZERO_EXTEND); -+ return false; -+ -+ case FLOAT: -+ case UNSIGNED_FLOAT: -+ case FIX: -+ case FLOAT_EXTEND: -+ case FLOAT_TRUNCATE: -+ *total = tune_info->fp_add[mode == DFmode]; -+ return false; -+ -+ case FMA: -+ *total = (tune_info->fp_mul[mode == DFmode] -+ + set_src_cost (XEXP (x, 0), mode, speed) -+ + set_src_cost (XEXP (x, 1), mode, speed) -+ + set_src_cost (XEXP (x, 2), mode, speed)); -+ return true; -+ -+ case UNSPEC: -+ if (XINT (x, 1) == UNSPEC_AUIPC) -+ { -+ /* Make AUIPC cheap to avoid spilling its result to the stack. */ -+ *total = 1; -+ return true; -+ } -+ return false; -+ -+ default: -+ return false; -+ } -+} -+ -+/* Implement TARGET_ADDRESS_COST. */ -+ -+static int -+riscv_address_cost (rtx addr, enum machine_mode mode, -+ addr_space_t as ATTRIBUTE_UNUSED, -+ bool speed ATTRIBUTE_UNUSED) -+{ -+ return riscv_address_insns (addr, mode, false); -+} -+ -+/* Return one word of double-word value OP. HIGH_P is true to select the -+ high part or false to select the low part. */ -+ -+rtx -+riscv_subword (rtx op, bool high_p) -+{ -+ unsigned int byte = high_p ? UNITS_PER_WORD : 0; -+ enum machine_mode mode = GET_MODE (op); -+ -+ if (mode == VOIDmode) -+ mode = TARGET_64BIT ? TImode : DImode; -+ -+ if (MEM_P (op)) -+ return adjust_address (op, word_mode, byte); -+ -+ if (REG_P (op)) -+ gcc_assert (!FP_REG_RTX_P (op)); -+ -+ return simplify_gen_subreg (word_mode, op, mode, byte); -+} -+ -+/* Return true if a 64-bit move from SRC to DEST should be split into two. */ -+ -+bool -+riscv_split_64bit_move_p (rtx dest, rtx src) -+{ -+ if (TARGET_64BIT) -+ return false; -+ -+ /* Allow FPR <-> FPR and FPR <-> MEM moves, and permit the special case -+ of zeroing an FPR with FCVT.D.W. */ -+ if (TARGET_DOUBLE_FLOAT -+ && ((FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) -+ || (FP_REG_RTX_P (dest) && MEM_P (src)) -+ || (FP_REG_RTX_P (src) && MEM_P (dest)) -+ || (FP_REG_RTX_P (dest) && src == CONST0_RTX (GET_MODE (src))))) -+ return false; -+ -+ return true; -+} -+ -+/* Split a doubleword move from SRC to DEST. On 32-bit targets, -+ this function handles 64-bit moves for which riscv_split_64bit_move_p -+ holds. For 64-bit targets, this function handles 128-bit moves. */ -+ -+void -+riscv_split_doubleword_move (rtx dest, rtx src) -+{ -+ rtx low_dest; -+ -+ /* The operation can be split into two normal moves. Decide in -+ which order to do them. */ -+ low_dest = riscv_subword (dest, false); -+ if (REG_P (low_dest) && reg_overlap_mentioned_p (low_dest, src)) -+ { -+ riscv_emit_move (riscv_subword (dest, true), riscv_subword (src, true)); -+ riscv_emit_move (low_dest, riscv_subword (src, false)); -+ } -+ else -+ { -+ riscv_emit_move (low_dest, riscv_subword (src, false)); -+ riscv_emit_move (riscv_subword (dest, true), riscv_subword (src, true)); -+ } -+} -+ -+/* Return the appropriate instructions to move SRC into DEST. Assume -+ that SRC is operand 1 and DEST is operand 0. */ -+ -+const char * -+riscv_output_move (rtx dest, rtx src) -+{ -+ enum rtx_code dest_code, src_code; -+ enum machine_mode mode; -+ bool dbl_p; -+ -+ dest_code = GET_CODE (dest); -+ src_code = GET_CODE (src); -+ mode = GET_MODE (dest); -+ dbl_p = (GET_MODE_SIZE (mode) == 8); -+ -+ if (dbl_p && riscv_split_64bit_move_p (dest, src)) -+ return "#"; -+ -+ if (dest_code == REG && GP_REG_P (REGNO (dest))) -+ { -+ if (src_code == REG && FP_REG_P (REGNO (src))) -+ return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.s\t%0,%1"; -+ -+ if (src_code == MEM) -+ switch (GET_MODE_SIZE (mode)) -+ { -+ case 1: return "lbu\t%0,%1"; -+ case 2: return "lhu\t%0,%1"; -+ case 4: return "lw\t%0,%1"; -+ case 8: return "ld\t%0,%1"; -+ } -+ -+ if (src_code == CONST_INT) -+ return "li\t%0,%1"; -+ -+ if (src_code == HIGH) -+ return "lui\t%0,%h1"; -+ -+ if (symbolic_operand (src, VOIDmode)) -+ switch (riscv_classify_symbolic_expression (src)) -+ { -+ case SYMBOL_GOT_DISP: return "la\t%0,%1"; -+ case SYMBOL_ABSOLUTE: return "lla\t%0,%1"; -+ case SYMBOL_PCREL: return "lla\t%0,%1"; -+ default: gcc_unreachable (); -+ } -+ } -+ if ((src_code == REG && GP_REG_P (REGNO (src))) -+ || (src == CONST0_RTX (mode))) -+ { -+ if (dest_code == REG) -+ { -+ if (GP_REG_P (REGNO (dest))) -+ return "mv\t%0,%z1"; -+ -+ if (FP_REG_P (REGNO (dest))) -+ { -+ if (!dbl_p) -+ return "fmv.s.x\t%0,%z1"; -+ if (TARGET_64BIT) -+ return "fmv.d.x\t%0,%z1"; -+ /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */ -+ gcc_assert (src == CONST0_RTX (mode)); -+ return "fcvt.d.w\t%0,x0"; -+ } -+ } -+ if (dest_code == MEM) -+ switch (GET_MODE_SIZE (mode)) -+ { -+ case 1: return "sb\t%z1,%0"; -+ case 2: return "sh\t%z1,%0"; -+ case 4: return "sw\t%z1,%0"; -+ case 8: return "sd\t%z1,%0"; -+ } -+ } -+ if (src_code == REG && FP_REG_P (REGNO (src))) -+ { -+ if (dest_code == REG && FP_REG_P (REGNO (dest))) -+ return dbl_p ? "fmv.d\t%0,%1" : "fmv.s\t%0,%1"; -+ -+ if (dest_code == MEM) -+ return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0"; -+ } -+ if (dest_code == REG && FP_REG_P (REGNO (dest))) -+ { -+ if (src_code == MEM) -+ return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1"; -+ } -+ gcc_unreachable (); -+} -+ -+/* Return true if CMP1 is a suitable second operand for integer ordering -+ test CODE. See also the *sCC patterns in riscv.md. */ -+ -+static bool -+riscv_int_order_operand_ok_p (enum rtx_code code, rtx cmp1) -+{ -+ switch (code) -+ { -+ case GT: -+ case GTU: -+ return reg_or_0_operand (cmp1, VOIDmode); -+ -+ case GE: -+ case GEU: -+ return cmp1 == const1_rtx; -+ -+ case LT: -+ case LTU: -+ return arith_operand (cmp1, VOIDmode); -+ -+ case LE: -+ return sle_operand (cmp1, VOIDmode); -+ -+ case LEU: -+ return sleu_operand (cmp1, VOIDmode); -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+/* Return true if *CMP1 (of mode MODE) is a valid second operand for -+ integer ordering test *CODE, or if an equivalent combination can -+ be formed by adjusting *CODE and *CMP1. When returning true, update -+ *CODE and *CMP1 with the chosen code and operand, otherwise leave -+ them alone. */ -+ -+static bool -+riscv_canonicalize_int_order_test (enum rtx_code *code, rtx *cmp1, -+ enum machine_mode mode) -+{ -+ HOST_WIDE_INT plus_one; -+ -+ if (riscv_int_order_operand_ok_p (*code, *cmp1)) -+ return true; -+ -+ if (CONST_INT_P (*cmp1)) -+ switch (*code) -+ { -+ case LE: -+ plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode); -+ if (INTVAL (*cmp1) < plus_one) -+ { -+ *code = LT; -+ *cmp1 = force_reg (mode, GEN_INT (plus_one)); -+ return true; -+ } -+ break; -+ -+ case LEU: -+ plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode); -+ if (plus_one != 0) -+ { -+ *code = LTU; -+ *cmp1 = force_reg (mode, GEN_INT (plus_one)); -+ return true; -+ } -+ break; -+ -+ default: -+ break; -+ } -+ return false; -+} -+ -+/* Compare CMP0 and CMP1 using ordering test CODE and store the result -+ in TARGET. CMP0 and TARGET are register_operands. If INVERT_PTR -+ is nonnull, it's OK to set TARGET to the inverse of the result and -+ flip *INVERT_PTR instead. */ -+ -+static void -+riscv_emit_int_order_test (enum rtx_code code, bool *invert_ptr, -+ rtx target, rtx cmp0, rtx cmp1) -+{ -+ enum machine_mode mode; -+ -+ /* First see if there is a RISCV instruction that can do this operation. -+ If not, try doing the same for the inverse operation. If that also -+ fails, force CMP1 into a register and try again. */ -+ mode = GET_MODE (cmp0); -+ if (riscv_canonicalize_int_order_test (&code, &cmp1, mode)) -+ riscv_emit_binary (code, target, cmp0, cmp1); -+ else -+ { -+ enum rtx_code inv_code = reverse_condition (code); -+ if (!riscv_canonicalize_int_order_test (&inv_code, &cmp1, mode)) -+ { -+ cmp1 = force_reg (mode, cmp1); -+ riscv_emit_int_order_test (code, invert_ptr, target, cmp0, cmp1); -+ } -+ else if (invert_ptr == 0) -+ { -+ rtx inv_target = riscv_force_binary (GET_MODE (target), -+ inv_code, cmp0, cmp1); -+ riscv_emit_binary (XOR, target, inv_target, const1_rtx); -+ } -+ else -+ { -+ *invert_ptr = !*invert_ptr; -+ riscv_emit_binary (inv_code, target, cmp0, cmp1); -+ } -+ } -+} -+ -+/* Return a register that is zero iff CMP0 and CMP1 are equal. -+ The register will have the same mode as CMP0. */ -+ -+static rtx -+riscv_zero_if_equal (rtx cmp0, rtx cmp1) -+{ -+ if (cmp1 == const0_rtx) -+ return cmp0; -+ -+ return expand_binop (GET_MODE (cmp0), sub_optab, -+ cmp0, cmp1, 0, 0, OPTAB_DIRECT); -+} -+ -+/* Sign- or zero-extend OP0 and OP1 for integer comparisons. */ -+ -+static void -+riscv_extend_comparands (rtx_code code, rtx *op0, rtx *op1) -+{ -+ /* Comparisons consider all XLEN bits, so extend sub-XLEN values. */ -+ if (GET_MODE_SIZE (word_mode) > GET_MODE_SIZE (GET_MODE (*op0))) -+ { -+ /* It is more profitable to zero-extend QImode values. */ -+ if (unsigned_condition (code) == code && GET_MODE (*op0) == QImode) -+ { -+ *op0 = gen_rtx_ZERO_EXTEND (word_mode, *op0); -+ if (CONST_INT_P (*op1)) -+ *op1 = GEN_INT ((uint8_t) INTVAL (*op1)); -+ else -+ *op1 = gen_rtx_ZERO_EXTEND (word_mode, *op1); -+ } -+ else -+ { -+ *op0 = gen_rtx_SIGN_EXTEND (word_mode, *op0); -+ if (*op1 != const0_rtx) -+ *op1 = gen_rtx_SIGN_EXTEND (word_mode, *op1); -+ } -+ } -+} -+ -+/* Convert a comparison into something that can be used in a branch. On -+ entry, *OP0 and *OP1 are the values being compared and *CODE is the code -+ used to compare them. Update them to describe the final comparison. */ -+ -+static void -+riscv_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1) -+{ -+ if (splittable_const_int_operand (*op1, VOIDmode)) -+ { -+ HOST_WIDE_INT rhs = INTVAL (*op1); -+ -+ if (*code == EQ || *code == NE) -+ { -+ /* Convert e.g. OP0 == 2048 into OP0 - 2048 == 0. */ -+ if (SMALL_OPERAND (-rhs)) -+ { -+ *op0 = riscv_force_binary (GET_MODE (*op0), PLUS, *op0, -+ GEN_INT (-rhs)); -+ *op1 = const0_rtx; -+ } -+ } -+ else -+ { -+ static const enum rtx_code mag_comparisons[][2] = { -+ {LEU, LTU}, {GTU, GEU}, {LE, LT}, {GT, GE} -+ }; -+ -+ /* Convert e.g. (OP0 <= 0xFFF) into (OP0 < 0x1000). */ -+ for (size_t i = 0; i < ARRAY_SIZE (mag_comparisons); i++) -+ { -+ HOST_WIDE_INT new_rhs; -+ bool increment = *code == mag_comparisons[i][0]; -+ bool decrement = *code == mag_comparisons[i][1]; -+ if (!increment && !decrement) -+ continue; -+ -+ new_rhs = rhs + (increment ? 1 : -1); -+ if (riscv_integer_cost (new_rhs) < riscv_integer_cost (rhs) -+ && (rhs < 0) == (new_rhs < 0)) -+ { -+ *op1 = GEN_INT (new_rhs); -+ *code = mag_comparisons[i][increment]; -+ } -+ break; -+ } -+ } -+ } -+ -+ riscv_extend_comparands (*code, op0, op1); -+ -+ *op0 = force_reg (word_mode, *op0); -+ if (*op1 != const0_rtx) -+ *op1 = force_reg (word_mode, *op1); -+} -+ -+/* Like riscv_emit_int_compare, but for floating-point comparisons. */ -+ -+static void -+riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1) -+{ -+ rtx tmp0, tmp1, cmp_op0 = *op0, cmp_op1 = *op1; -+ enum rtx_code fp_code = *code; -+ *code = NE; -+ -+ switch (fp_code) -+ { -+ case UNORDERED: -+ *code = EQ; -+ /* Fall through. */ -+ -+ case ORDERED: -+ /* a == a && b == b */ -+ tmp0 = riscv_force_binary (word_mode, EQ, cmp_op0, cmp_op0); -+ tmp1 = riscv_force_binary (word_mode, EQ, cmp_op1, cmp_op1); -+ *op0 = riscv_force_binary (word_mode, AND, tmp0, tmp1); -+ *op1 = const0_rtx; -+ break; -+ -+ case UNEQ: -+ case LTGT: -+ /* ordered(a, b) > (a == b) */ -+ *code = fp_code == LTGT ? GTU : EQ; -+ tmp0 = riscv_force_binary (word_mode, EQ, cmp_op0, cmp_op0); -+ tmp1 = riscv_force_binary (word_mode, EQ, cmp_op1, cmp_op1); -+ *op0 = riscv_force_binary (word_mode, AND, tmp0, tmp1); -+ *op1 = riscv_force_binary (word_mode, EQ, cmp_op0, cmp_op1); -+ break; -+ -+#define UNORDERED_COMPARISON(CODE, CMP) \ -+ case CODE: \ -+ *code = EQ; \ -+ *op0 = gen_reg_rtx (word_mode); \ -+ if (GET_MODE (cmp_op0) == SFmode && TARGET_64BIT) \ -+ emit_insn (gen_f##CMP##_quietsfdi4 (*op0, cmp_op0, cmp_op1)); \ -+ else if (GET_MODE (cmp_op0) == SFmode) \ -+ emit_insn (gen_f##CMP##_quietsfsi4 (*op0, cmp_op0, cmp_op1)); \ -+ else if (GET_MODE (cmp_op0) == DFmode && TARGET_64BIT) \ -+ emit_insn (gen_f##CMP##_quietdfdi4 (*op0, cmp_op0, cmp_op1)); \ -+ else if (GET_MODE (cmp_op0) == DFmode) \ -+ emit_insn (gen_f##CMP##_quietdfsi4 (*op0, cmp_op0, cmp_op1)); \ -+ else \ -+ gcc_unreachable (); \ -+ *op1 = const0_rtx; \ -+ break; -+ -+ case UNLT: -+ std::swap (cmp_op0, cmp_op1); -+ /* Fall through. */ -+ -+ UNORDERED_COMPARISON(UNGT, le) -+ -+ case UNLE: -+ std::swap (cmp_op0, cmp_op1); -+ /* Fall through. */ -+ -+ UNORDERED_COMPARISON(UNGE, lt) -+#undef UNORDERED_COMPARISON -+ -+ case NE: -+ fp_code = EQ; -+ *code = EQ; -+ /* Fall through. */ -+ -+ case EQ: -+ case LE: -+ case LT: -+ case GE: -+ case GT: -+ /* We have instructions for these cases. */ -+ *op0 = riscv_force_binary (word_mode, fp_code, cmp_op0, cmp_op1); -+ *op1 = const0_rtx; -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+/* CODE-compare OP0 and OP1. Store the result in TARGET. */ -+ -+void -+riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1) -+{ -+ riscv_extend_comparands (code, &op0, &op1); -+ op0 = force_reg (word_mode, op0); -+ -+ if (code == EQ || code == NE) -+ { -+ rtx zie = riscv_zero_if_equal (op0, op1); -+ riscv_emit_binary (code, target, zie, const0_rtx); -+ } -+ else -+ riscv_emit_int_order_test (code, 0, target, op0, op1); -+} -+ -+/* Like riscv_expand_int_scc, but for floating-point comparisons. */ -+ -+void -+riscv_expand_float_scc (rtx target, enum rtx_code code, rtx op0, rtx op1) -+{ -+ riscv_emit_float_compare (&code, &op0, &op1); -+ -+ rtx cmp = riscv_force_binary (word_mode, code, op0, op1); -+ riscv_emit_set (target, lowpart_subreg (SImode, cmp, word_mode)); -+} -+ -+/* Jump to LABEL if (CODE OP0 OP1) holds. */ -+ -+void -+riscv_expand_conditional_branch (rtx label, rtx_code code, rtx op0, rtx op1) -+{ -+ if (FLOAT_MODE_P (GET_MODE (op1))) -+ riscv_emit_float_compare (&code, &op0, &op1); -+ else -+ riscv_emit_int_compare (&code, &op0, &op1); -+ -+ rtx condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1); -+ emit_jump_insn (gen_condjump (condition, label)); -+} -+ -+/* Implement TARGET_FUNCTION_ARG_BOUNDARY. Every parameter gets at -+ least PARM_BOUNDARY bits of alignment, but will be given anything up -+ to STACK_BOUNDARY bits if the type requires it. */ -+ -+static unsigned int -+riscv_function_arg_boundary (enum machine_mode mode, const_tree type) -+{ -+ unsigned int alignment; -+ -+ /* Use natural alignment if the type is not aggregate data. */ -+ if (type && !AGGREGATE_TYPE_P (type)) -+ alignment = TYPE_ALIGN (TYPE_MAIN_VARIANT (type)); -+ else -+ alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode); -+ -+ return MIN (STACK_BOUNDARY, MAX (PARM_BOUNDARY, alignment)); -+} -+ -+/* If MODE represents an argument that can be passed or returned in -+ floating-point registers, return the number of registers, else 0. */ -+ -+static unsigned -+riscv_pass_mode_in_fpr_p (enum machine_mode mode) -+{ -+ if (GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FP_ARG) -+ { -+ if (GET_MODE_CLASS (mode) == MODE_FLOAT) -+ return 1; -+ -+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) -+ return 2; -+ } -+ -+ return 0; -+} -+ -+typedef struct { -+ const_tree type; -+ HOST_WIDE_INT offset; -+} riscv_aggregate_field; -+ -+/* Identify subfields of aggregates that are candidates for passing in -+ floating-point registers. */ -+ -+static int -+riscv_flatten_aggregate_field (const_tree type, -+ riscv_aggregate_field fields[2], -+ int n, HOST_WIDE_INT offset) -+{ -+ switch (TREE_CODE (type)) -+ { -+ case RECORD_TYPE: -+ /* Can't handle incomplete types nor sizes that are not fixed. */ -+ if (!COMPLETE_TYPE_P (type) -+ || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST -+ || !tree_fits_uhwi_p (TYPE_SIZE (type))) -+ return -1; -+ -+ for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f)) -+ if (TREE_CODE (f) == FIELD_DECL) -+ { -+ if (!TYPE_P (TREE_TYPE (f))) -+ return -1; -+ -+ HOST_WIDE_INT pos = offset + int_byte_position (f); -+ n = riscv_flatten_aggregate_field (TREE_TYPE (f), fields, n, pos); -+ if (n < 0) -+ return -1; -+ } -+ return n; -+ -+ case ARRAY_TYPE: -+ { -+ HOST_WIDE_INT n_elts; -+ riscv_aggregate_field subfields[2]; -+ tree index = TYPE_DOMAIN (type); -+ tree elt_size = TYPE_SIZE_UNIT (TREE_TYPE (type)); -+ int n_subfields = riscv_flatten_aggregate_field (TREE_TYPE (type), -+ subfields, 0, offset); -+ -+ /* Can't handle incomplete types nor sizes that are not fixed. */ -+ if (n_subfields <= 0 -+ || !COMPLETE_TYPE_P (type) -+ || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST -+ || !index -+ || !TYPE_MAX_VALUE (index) -+ || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index)) -+ || !TYPE_MIN_VALUE (index) -+ || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index)) -+ || !tree_fits_uhwi_p (elt_size)) -+ return -1; -+ -+ n_elts = 1 + tree_to_uhwi (TYPE_MAX_VALUE (index)) -+ - tree_to_uhwi (TYPE_MIN_VALUE (index)); -+ gcc_assert (n_elts >= 0); -+ -+ for (HOST_WIDE_INT i = 0; i < n_elts; i++) -+ for (int j = 0; j < n_subfields; j++) -+ { -+ if (n >= 2) -+ return -1; -+ -+ fields[n] = subfields[j]; -+ fields[n++].offset += i * tree_to_uhwi (elt_size); -+ } -+ -+ return n; -+ } -+ -+ case COMPLEX_TYPE: -+ { -+ /* Complex type need consume 2 field, so n must be 0. */ -+ if (n != 0) -+ return -1; -+ -+ HOST_WIDE_INT elt_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type))); -+ -+ if (elt_size <= UNITS_PER_FP_ARG) -+ { -+ fields[0].type = TREE_TYPE (type); -+ fields[0].offset = offset; -+ fields[1].type = TREE_TYPE (type); -+ fields[1].offset = offset + elt_size; -+ -+ return 2; -+ } -+ -+ return -1; -+ } -+ -+ default: -+ if (n < 2 -+ && ((SCALAR_FLOAT_TYPE_P (type) -+ && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FP_ARG) -+ || (INTEGRAL_TYPE_P (type) -+ && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD))) -+ { -+ fields[n].type = type; -+ fields[n].offset = offset; -+ return n + 1; -+ } -+ else -+ return -1; -+ } -+} -+ -+/* Identify candidate aggregates for passing in floating-point registers. -+ Candidates have at most two fields after flattening. */ -+ -+static int -+riscv_flatten_aggregate_argument (const_tree type, -+ riscv_aggregate_field fields[2]) -+{ -+ if (!type || TREE_CODE (type) != RECORD_TYPE) -+ return -1; -+ -+ return riscv_flatten_aggregate_field (type, fields, 0, 0); -+} -+ -+/* See whether TYPE is a record whose fields should be returned in one or -+ two floating-point registers. If so, populate FIELDS accordingly. */ -+ -+static unsigned -+riscv_pass_aggregate_in_fpr_pair_p (const_tree type, -+ riscv_aggregate_field fields[2]) -+{ -+ int n = riscv_flatten_aggregate_argument (type, fields); -+ -+ for (int i = 0; i < n; i++) -+ if (!SCALAR_FLOAT_TYPE_P (fields[i].type)) -+ return 0; -+ -+ return n > 0 ? n : 0; -+} -+ -+/* See whether TYPE is a record whose fields should be returned in one or -+ floating-point register and one integer register. If so, populate -+ FIELDS accordingly. */ -+ -+static bool -+riscv_pass_aggregate_in_fpr_and_gpr_p (const_tree type, -+ riscv_aggregate_field fields[2]) -+{ -+ unsigned num_int = 0, num_float = 0; -+ int n = riscv_flatten_aggregate_argument (type, fields); -+ -+ for (int i = 0; i < n; i++) -+ { -+ num_float += SCALAR_FLOAT_TYPE_P (fields[i].type); -+ num_int += INTEGRAL_TYPE_P (fields[i].type); -+ } -+ -+ return num_int == 1 && num_float == 1; -+} -+ -+/* Return the representation of an argument passed or returned in an FPR -+ when the value has mode VALUE_MODE and the type has TYPE_MODE. The -+ two modes may be different for structures like: -+ -+ struct __attribute__((packed)) foo { float f; } -+ -+ where the SFmode value "f" is passed in REGNO but the struct itself -+ has mode BLKmode. */ -+ -+static rtx -+riscv_pass_fpr_single (enum machine_mode type_mode, unsigned regno, -+ enum machine_mode value_mode) -+{ -+ rtx x = gen_rtx_REG (value_mode, regno); -+ -+ if (type_mode != value_mode) -+ { -+ x = gen_rtx_EXPR_LIST (VOIDmode, x, const0_rtx); -+ x = gen_rtx_PARALLEL (type_mode, gen_rtvec (1, x)); -+ } -+ return x; -+} -+ -+/* Pass or return a composite value in the FPR pair REGNO and REGNO + 1. -+ MODE is the mode of the composite. MODE1 and OFFSET1 are the mode and -+ byte offset for the first value, likewise MODE2 and OFFSET2 for the -+ second value. */ -+ -+static rtx -+riscv_pass_fpr_pair (enum machine_mode mode, unsigned regno1, -+ enum machine_mode mode1, HOST_WIDE_INT offset1, -+ unsigned regno2, enum machine_mode mode2, -+ HOST_WIDE_INT offset2) -+{ -+ return gen_rtx_PARALLEL -+ (mode, -+ gen_rtvec (2, -+ gen_rtx_EXPR_LIST (VOIDmode, -+ gen_rtx_REG (mode1, regno1), -+ GEN_INT (offset1)), -+ gen_rtx_EXPR_LIST (VOIDmode, -+ gen_rtx_REG (mode2, regno2), -+ GEN_INT (offset2)))); -+} -+ -+/* Fill INFO with information about a single argument, and return an -+ RTL pattern to pass or return the argument. CUM is the cumulative -+ state for earlier arguments. MODE is the mode of this argument and -+ TYPE is its type (if known). NAMED is true if this is a named -+ (fixed) argument rather than a variable one. RETURN_P is true if -+ returning the argument, or false if passing the argument. */ -+ -+static rtx -+riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum, -+ enum machine_mode mode, const_tree type, bool named, -+ bool return_p) -+{ -+ unsigned num_bytes, num_words; -+ unsigned fpr_base = return_p ? FP_RETURN : FP_ARG_FIRST; -+ unsigned gpr_base = return_p ? GP_RETURN : GP_ARG_FIRST; -+ unsigned alignment = riscv_function_arg_boundary (mode, type); -+ -+ memset (info, 0, sizeof (*info)); -+ info->gpr_offset = cum->num_gprs; -+ info->fpr_offset = cum->num_fprs; -+ -+ if (named) -+ { -+ riscv_aggregate_field fields[2]; -+ unsigned fregno = fpr_base + info->fpr_offset; -+ unsigned gregno = gpr_base + info->gpr_offset; -+ -+ /* Pass one- or two-element floating-point aggregates in FPRs. */ -+ if ((info->num_fprs = riscv_pass_aggregate_in_fpr_pair_p (type, fields)) -+ && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS) -+ switch (info->num_fprs) -+ { -+ case 1: -+ return riscv_pass_fpr_single (mode, fregno, -+ TYPE_MODE (fields[0].type)); -+ -+ case 2: -+ return riscv_pass_fpr_pair (mode, fregno, -+ TYPE_MODE (fields[0].type), -+ fields[0].offset, -+ fregno + 1, -+ TYPE_MODE (fields[1].type), -+ fields[1].offset); -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ /* Pass real and complex floating-point numbers in FPRs. */ -+ if ((info->num_fprs = riscv_pass_mode_in_fpr_p (mode)) -+ && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS) -+ switch (GET_MODE_CLASS (mode)) -+ { -+ case MODE_FLOAT: -+ return gen_rtx_REG (mode, fregno); -+ -+ case MODE_COMPLEX_FLOAT: -+ return riscv_pass_fpr_pair (mode, fregno, GET_MODE_INNER (mode), 0, -+ fregno + 1, GET_MODE_INNER (mode), -+ GET_MODE_UNIT_SIZE (mode)); -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ /* Pass structs with one float and one integer in an FPR and a GPR. */ -+ if (riscv_pass_aggregate_in_fpr_and_gpr_p (type, fields) -+ && info->gpr_offset < MAX_ARGS_IN_REGISTERS -+ && info->fpr_offset < MAX_ARGS_IN_REGISTERS) -+ { -+ info->num_gprs = 1; -+ info->num_fprs = 1; -+ -+ if (!SCALAR_FLOAT_TYPE_P (fields[0].type)) -+ std::swap (fregno, gregno); -+ -+ return riscv_pass_fpr_pair (mode, fregno, TYPE_MODE (fields[0].type), -+ fields[0].offset, -+ gregno, TYPE_MODE (fields[1].type), -+ fields[1].offset); -+ } -+ } -+ -+ /* Work out the size of the argument. */ -+ num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); -+ num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; -+ -+ /* Doubleword-aligned varargs start on an even register boundary. */ -+ if (!named && num_bytes != 0 && alignment > BITS_PER_WORD) -+ info->gpr_offset += info->gpr_offset & 1; -+ -+ /* Partition the argument between registers and stack. */ -+ info->num_fprs = 0; -+ info->num_gprs = MIN (num_words, MAX_ARGS_IN_REGISTERS - info->gpr_offset); -+ info->stack_p = (num_words - info->num_gprs) != 0; -+ -+ if (info->num_gprs || return_p) -+ return gen_rtx_REG (mode, gpr_base + info->gpr_offset); -+ -+ return NULL_RTX; -+} -+ -+/* Implement TARGET_FUNCTION_ARG. */ -+ -+static rtx -+riscv_function_arg (cumulative_args_t cum_v, enum machine_mode mode, -+ const_tree type, bool named) -+{ -+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); -+ struct riscv_arg_info info; -+ -+ if (mode == VOIDmode) -+ return NULL; -+ -+ return riscv_get_arg_info (&info, cum, mode, type, named, false); -+} -+ -+/* Implement TARGET_FUNCTION_ARG_ADVANCE. */ -+ -+static void -+riscv_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, -+ const_tree type, bool named) -+{ -+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); -+ struct riscv_arg_info info; -+ -+ riscv_get_arg_info (&info, cum, mode, type, named, false); -+ -+ /* Advance the register count. This has the effect of setting -+ num_gprs to MAX_ARGS_IN_REGISTERS if a doubleword-aligned -+ argument required us to skip the final GPR and pass the whole -+ argument on the stack. */ -+ cum->num_fprs = info.fpr_offset + info.num_fprs; -+ cum->num_gprs = info.gpr_offset + info.num_gprs; -+} -+ -+/* Implement TARGET_ARG_PARTIAL_BYTES. */ -+ -+static int -+riscv_arg_partial_bytes (cumulative_args_t cum, -+ enum machine_mode mode, tree type, bool named) -+{ -+ struct riscv_arg_info arg; -+ -+ riscv_get_arg_info (&arg, get_cumulative_args (cum), mode, type, named, false); -+ return arg.stack_p ? arg.num_gprs * UNITS_PER_WORD : 0; -+} -+ -+/* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls, -+ VALTYPE is the return type and MODE is VOIDmode. For libcalls, -+ VALTYPE is null and MODE is the mode of the return value. */ -+ -+rtx -+riscv_function_value (const_tree type, const_tree func, enum machine_mode mode) -+{ -+ struct riscv_arg_info info; -+ CUMULATIVE_ARGS args; -+ -+ if (type) -+ { -+ int unsigned_p = TYPE_UNSIGNED (type); -+ -+ mode = TYPE_MODE (type); -+ -+ /* Since TARGET_PROMOTE_FUNCTION_MODE unconditionally promotes, -+ return values, promote the mode here too. */ -+ mode = promote_function_mode (type, mode, &unsigned_p, func, 1); -+ } -+ -+ memset (&args, 0, sizeof args); -+ return riscv_get_arg_info (&info, &args, mode, type, true, true); -+} -+ -+/* Implement TARGET_PASS_BY_REFERENCE. */ -+ -+static bool -+riscv_pass_by_reference (cumulative_args_t cum_v, enum machine_mode mode, -+ const_tree type, bool named) -+{ -+ HOST_WIDE_INT size = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); -+ struct riscv_arg_info info; -+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); -+ -+ /* ??? std_gimplify_va_arg_expr passes NULL for cum. Fortunately, we -+ never pass variadic arguments in floating-point registers, so we can -+ avoid the call to riscv_get_arg_info in this case. */ -+ if (cum != NULL) -+ { -+ /* Don't pass by reference if we can use a floating-point register. */ -+ riscv_get_arg_info (&info, cum, mode, type, named, false); -+ if (info.num_fprs) -+ return false; -+ } -+ -+ /* Pass by reference if the data do not fit in two integer registers. */ -+ return !IN_RANGE (size, 0, 2 * UNITS_PER_WORD); -+} -+ -+/* Implement TARGET_RETURN_IN_MEMORY. */ -+ -+static bool -+riscv_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) -+{ -+ CUMULATIVE_ARGS args; -+ cumulative_args_t cum = pack_cumulative_args (&args); -+ -+ /* The rules for returning in memory are the same as for passing the -+ first named argument by reference. */ -+ memset (&args, 0, sizeof args); -+ return riscv_pass_by_reference (cum, TYPE_MODE (type), type, true); -+} -+ -+/* Implement TARGET_SETUP_INCOMING_VARARGS. */ -+ -+static void -+riscv_setup_incoming_varargs (cumulative_args_t cum, enum machine_mode mode, -+ tree type, int *pretend_size ATTRIBUTE_UNUSED, -+ int no_rtl) -+{ -+ CUMULATIVE_ARGS local_cum; -+ int gp_saved; -+ -+ /* The caller has advanced CUM up to, but not beyond, the last named -+ argument. Advance a local copy of CUM past the last "real" named -+ argument, to find out how many registers are left over. */ -+ local_cum = *get_cumulative_args (cum); -+ riscv_function_arg_advance (pack_cumulative_args (&local_cum), mode, type, 1); -+ -+ /* Found out how many registers we need to save. */ -+ gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs; -+ -+ if (!no_rtl && gp_saved > 0) -+ { -+ rtx ptr = plus_constant (Pmode, virtual_incoming_args_rtx, -+ REG_PARM_STACK_SPACE (cfun->decl) -+ - gp_saved * UNITS_PER_WORD); -+ rtx mem = gen_frame_mem (BLKmode, ptr); -+ set_mem_alias_set (mem, get_varargs_alias_set ()); -+ -+ move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST, -+ mem, gp_saved); -+ } -+ if (REG_PARM_STACK_SPACE (cfun->decl) == 0) -+ cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD; -+} -+ -+/* Implement TARGET_EXPAND_BUILTIN_VA_START. */ -+ -+static void -+riscv_va_start (tree valist, rtx nextarg) -+{ -+ nextarg = plus_constant (Pmode, nextarg, -cfun->machine->varargs_size); -+ std_expand_builtin_va_start (valist, nextarg); -+} -+ -+/* Make ADDR suitable for use as a call or sibcall target. */ -+ -+rtx -+riscv_legitimize_call_address (rtx addr) -+{ -+ if (!call_insn_operand (addr, VOIDmode)) -+ { -+ rtx reg = RISCV_PROLOGUE_TEMP (Pmode); -+ riscv_emit_move (reg, addr); -+ return reg; -+ } -+ return addr; -+} -+ -+/* Print symbolic operand OP, which is part of a HIGH or LO_SUM -+ in context CONTEXT. HI_RELOC indicates a high-part reloc. */ -+ -+static void -+riscv_print_operand_reloc (FILE *file, rtx op, bool hi_reloc) -+{ -+ const char *reloc; -+ -+ switch (riscv_classify_symbolic_expression (op)) -+ { -+ case SYMBOL_ABSOLUTE: -+ reloc = hi_reloc ? "%hi" : "%lo"; -+ break; -+ -+ case SYMBOL_PCREL: -+ reloc = hi_reloc ? "%pcrel_hi" : "%pcrel_lo"; -+ break; -+ -+ case SYMBOL_TLS_LE: -+ reloc = hi_reloc ? "%tprel_hi" : "%tprel_lo"; -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ fprintf (file, "%s(", reloc); -+ output_addr_const (file, riscv_strip_unspec_address (op)); -+ fputc (')', file); -+} -+ -+/* Return true if the .AQ suffix should be added to an AMO to implement the -+ acquire portion of memory model MODEL. */ -+ -+static bool -+riscv_memmodel_needs_amo_acquire (enum memmodel model) -+{ -+ switch (model) -+ { -+ case MEMMODEL_ACQ_REL: -+ case MEMMODEL_SEQ_CST: -+ case MEMMODEL_SYNC_SEQ_CST: -+ case MEMMODEL_ACQUIRE: -+ case MEMMODEL_CONSUME: -+ case MEMMODEL_SYNC_ACQUIRE: -+ return true; -+ -+ case MEMMODEL_RELEASE: -+ case MEMMODEL_SYNC_RELEASE: -+ case MEMMODEL_RELAXED: -+ return false; -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+/* Return true if a FENCE should be emitted to before a memory access to -+ implement the release portion of memory model MODEL. */ -+ -+static bool -+riscv_memmodel_needs_release_fence (enum memmodel model) -+{ -+ switch (model) -+ { -+ case MEMMODEL_ACQ_REL: -+ case MEMMODEL_SEQ_CST: -+ case MEMMODEL_SYNC_SEQ_CST: -+ case MEMMODEL_RELEASE: -+ case MEMMODEL_SYNC_RELEASE: -+ return true; -+ -+ case MEMMODEL_ACQUIRE: -+ case MEMMODEL_CONSUME: -+ case MEMMODEL_SYNC_ACQUIRE: -+ case MEMMODEL_RELAXED: -+ return false; -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+/* Implement TARGET_PRINT_OPERAND. The RISCV-specific operand codes are: -+ -+ 'h' Print the high-part relocation associated with OP, after stripping -+ any outermost HIGH. -+ 'R' Print the low-part relocation associated with OP. -+ 'C' Print the integer branch condition for comparison OP. -+ 'A' Print the atomic operation suffix for memory model OP. -+ 'F' Print a FENCE if the memory model requires a release. -+ 'z' Print x0 if OP is zero, otherwise print OP normally. */ -+ -+static void -+riscv_print_operand (FILE *file, rtx op, int letter) -+{ -+ enum machine_mode mode = GET_MODE (op); -+ enum rtx_code code = GET_CODE (op); -+ -+ switch (letter) -+ { -+ case 'h': -+ if (code == HIGH) -+ op = XEXP (op, 0); -+ riscv_print_operand_reloc (file, op, true); -+ break; -+ -+ case 'R': -+ riscv_print_operand_reloc (file, op, false); -+ break; -+ -+ case 'C': -+ /* The RTL names match the instruction names. */ -+ fputs (GET_RTX_NAME (code), file); -+ break; -+ -+ case 'A': -+ if (riscv_memmodel_needs_amo_acquire ((enum memmodel) INTVAL (op))) -+ fputs (".aq", file); -+ break; -+ -+ case 'F': -+ if (riscv_memmodel_needs_release_fence ((enum memmodel) INTVAL (op))) -+ fputs ("fence rw,w; ", file); -+ break; -+ -+ default: -+ switch (code) -+ { -+ case REG: -+ if (letter && letter != 'z') -+ output_operand_lossage ("invalid use of '%%%c'", letter); -+ fprintf (file, "%s", reg_names[REGNO (op)]); -+ break; -+ -+ case MEM: -+ if (letter && letter != 'z') -+ output_operand_lossage ("invalid use of '%%%c'", letter); -+ else -+ output_address (mode, XEXP (op, 0)); -+ break; -+ -+ default: -+ if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) -+ fputs (reg_names[GP_REG_FIRST], file); -+ else if (letter && letter != 'z') -+ output_operand_lossage ("invalid use of '%%%c'", letter); -+ else -+ output_addr_const (file, riscv_strip_unspec_address (op)); -+ break; -+ } -+ } -+} -+ -+/* Implement TARGET_PRINT_OPERAND_ADDRESS. */ -+ -+static void -+riscv_print_operand_address (FILE *file, machine_mode mode ATTRIBUTE_UNUSED, rtx x) -+{ -+ struct riscv_address_info addr; -+ -+ if (riscv_classify_address (&addr, x, word_mode, true)) -+ switch (addr.type) -+ { -+ case ADDRESS_REG: -+ riscv_print_operand (file, addr.offset, 0); -+ fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]); -+ return; -+ -+ case ADDRESS_LO_SUM: -+ riscv_print_operand_reloc (file, addr.offset, false); -+ fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]); -+ return; -+ -+ case ADDRESS_CONST_INT: -+ output_addr_const (file, x); -+ fprintf (file, "(%s)", reg_names[GP_REG_FIRST]); -+ return; -+ -+ case ADDRESS_SYMBOLIC: -+ output_addr_const (file, riscv_strip_unspec_address (x)); -+ return; -+ } -+ gcc_unreachable (); -+} -+ -+static bool -+riscv_size_ok_for_small_data_p (int size) -+{ -+ return g_switch_value && IN_RANGE (size, 1, g_switch_value); -+} -+ -+/* Return true if EXP should be placed in the small data section. */ -+ -+static bool -+riscv_in_small_data_p (const_tree x) -+{ -+ if (TREE_CODE (x) == STRING_CST || TREE_CODE (x) == FUNCTION_DECL) -+ return false; -+ -+ if (TREE_CODE (x) == VAR_DECL && DECL_SECTION_NAME (x)) -+ { -+ const char *sec = DECL_SECTION_NAME (x); -+ return strcmp (sec, ".sdata") == 0 || strcmp (sec, ".sbss") == 0; -+ } -+ -+ return riscv_size_ok_for_small_data_p (int_size_in_bytes (TREE_TYPE (x))); -+} -+ -+/* Return a section for X, handling small data. */ -+ -+static section * -+riscv_elf_select_rtx_section (enum machine_mode mode, rtx x, -+ unsigned HOST_WIDE_INT align) -+{ -+ section *s = default_elf_select_rtx_section (mode, x, align); -+ -+ if (riscv_size_ok_for_small_data_p (GET_MODE_SIZE (mode))) -+ { -+ if (strncmp (s->named.name, ".rodata.cst", strlen (".rodata.cst")) == 0) -+ { -+ /* Rename .rodata.cst* to .srodata.cst*. */ -+ char *name = (char *) alloca (strlen (s->named.name) + 2); -+ sprintf (name, ".s%s", s->named.name + 1); -+ return get_section (name, s->named.common.flags, NULL); -+ } -+ -+ if (s == data_section) -+ return sdata_section; -+ } -+ -+ return s; -+} -+ -+/* Make the last instruction frame-related and note that it performs -+ the operation described by FRAME_PATTERN. */ -+ -+static void -+riscv_set_frame_expr (rtx frame_pattern) -+{ -+ rtx insn; -+ -+ insn = get_last_insn (); -+ RTX_FRAME_RELATED_P (insn) = 1; -+ REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR, -+ frame_pattern, -+ REG_NOTES (insn)); -+} -+ -+/* Return a frame-related rtx that stores REG at MEM. -+ REG must be a single register. */ -+ -+static rtx -+riscv_frame_set (rtx mem, rtx reg) -+{ -+ rtx set = gen_rtx_SET (mem, reg); -+ RTX_FRAME_RELATED_P (set) = 1; -+ return set; -+} -+ -+/* Return true if the current function must save register REGNO. */ -+ -+static bool -+riscv_save_reg_p (unsigned int regno) -+{ -+ bool call_saved = !global_regs[regno] && !call_used_regs[regno]; -+ bool might_clobber = crtl->saves_all_registers -+ || df_regs_ever_live_p (regno); -+ -+ if (call_saved && might_clobber) -+ return true; -+ -+ if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) -+ return true; -+ -+ if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return) -+ return true; -+ -+ return false; -+} -+ -+/* Determine whether to call GPR save/restore routines. */ -+static bool -+riscv_use_save_libcall (const struct riscv_frame_info *frame) -+{ -+ if (!TARGET_SAVE_RESTORE || crtl->calls_eh_return || frame_pointer_needed) -+ return false; -+ -+ return frame->save_libcall_adjustment != 0; -+} -+ -+/* Determine which GPR save/restore routine to call. */ -+ -+static unsigned -+riscv_save_libcall_count (unsigned mask) -+{ -+ for (unsigned n = GP_REG_LAST; n > GP_REG_FIRST; n--) -+ if (BITSET_P (mask, n)) -+ return CALLEE_SAVED_REG_NUMBER (n) + 1; -+ abort (); -+} -+ -+/* Populate the current function's riscv_frame_info structure. -+ -+ RISC-V stack frames grown downward. High addresses are at the top. -+ -+ +-------------------------------+ -+ | | -+ | incoming stack arguments | -+ | | -+ +-------------------------------+ <-- incoming stack pointer -+ | | -+ | callee-allocated save area | -+ | for arguments that are | -+ | split between registers and | -+ | the stack | -+ | | -+ +-------------------------------+ <-- arg_pointer_rtx -+ | | -+ | callee-allocated save area | -+ | for register varargs | -+ | | -+ +-------------------------------+ <-- hard_frame_pointer_rtx; -+ | | stack_pointer_rtx + gp_sp_offset -+ | GPR save area | + UNITS_PER_WORD -+ | | -+ +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset -+ | | + UNITS_PER_HWVALUE -+ | FPR save area | -+ | | -+ +-------------------------------+ <-- frame_pointer_rtx (virtual) -+ | | -+ | local variables | -+ | | -+ P +-------------------------------+ -+ | | -+ | outgoing stack arguments | -+ | | -+ +-------------------------------+ <-- stack_pointer_rtx -+ -+ Dynamic stack allocations such as alloca insert data at point P. -+ They decrease stack_pointer_rtx but leave frame_pointer_rtx and -+ hard_frame_pointer_rtx unchanged. */ -+ -+static void -+riscv_compute_frame_info (void) -+{ -+ struct riscv_frame_info *frame; -+ HOST_WIDE_INT offset; -+ unsigned int regno, i, num_x_saved = 0, num_f_saved = 0; -+ -+ frame = &cfun->machine->frame; -+ memset (frame, 0, sizeof (*frame)); -+ -+ /* Find out which GPRs we need to save. */ -+ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) -+ if (riscv_save_reg_p (regno)) -+ frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; -+ -+ /* If this function calls eh_return, we must also save and restore the -+ EH data registers. */ -+ if (crtl->calls_eh_return) -+ for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++) -+ frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; -+ -+ /* Find out which FPRs we need to save. This loop must iterate over -+ the same space as its companion in riscv_for_each_saved_reg. */ -+ if (TARGET_HARD_FLOAT) -+ for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) -+ if (riscv_save_reg_p (regno)) -+ frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++; -+ -+ /* At the bottom of the frame are any outgoing stack arguments. */ -+ offset = crtl->outgoing_args_size; -+ /* Next are local stack variables. */ -+ offset += RISCV_STACK_ALIGN (get_frame_size ()); -+ /* The virtual frame pointer points above the local variables. */ -+ frame->frame_pointer_offset = offset; -+ /* Next are the callee-saved FPRs. */ -+ if (frame->fmask) -+ offset += RISCV_STACK_ALIGN (num_f_saved * UNITS_PER_FP_REG); -+ frame->fp_sp_offset = offset - UNITS_PER_FP_REG; -+ /* Next are the callee-saved GPRs. */ -+ if (frame->mask) -+ { -+ unsigned x_save_size = RISCV_STACK_ALIGN (num_x_saved * UNITS_PER_WORD); -+ unsigned num_save_restore = 1 + riscv_save_libcall_count (frame->mask); -+ -+ /* Only use save/restore routines if they don't alter the stack size. */ -+ if (RISCV_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size) -+ frame->save_libcall_adjustment = x_save_size; -+ -+ offset += x_save_size; -+ } -+ frame->gp_sp_offset = offset - UNITS_PER_WORD; -+ /* The hard frame pointer points above the callee-saved GPRs. */ -+ frame->hard_frame_pointer_offset = offset; -+ /* Above the hard frame pointer is the callee-allocated varags save area. */ -+ offset += RISCV_STACK_ALIGN (cfun->machine->varargs_size); -+ frame->arg_pointer_offset = offset; -+ /* Next is the callee-allocated area for pretend stack arguments. */ -+ offset += crtl->args.pretend_args_size; -+ frame->total_size = offset; -+ /* Next points the incoming stack pointer and any incoming arguments. */ -+ -+ /* Only use save/restore routines when the GPRs are atop the frame. */ -+ if (frame->hard_frame_pointer_offset != frame->total_size) -+ frame->save_libcall_adjustment = 0; -+} -+ -+/* Make sure that we're not trying to eliminate to the wrong hard frame -+ pointer. */ -+ -+static bool -+riscv_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) -+{ -+ return (to == HARD_FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM); -+} -+ -+/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame pointer -+ or argument pointer. TO is either the stack pointer or hard frame -+ pointer. */ -+ -+HOST_WIDE_INT -+riscv_initial_elimination_offset (int from, int to) -+{ -+ HOST_WIDE_INT src, dest; -+ -+ riscv_compute_frame_info (); -+ -+ if (to == HARD_FRAME_POINTER_REGNUM) -+ dest = cfun->machine->frame.hard_frame_pointer_offset; -+ else if (to == STACK_POINTER_REGNUM) -+ dest = 0; /* The stack pointer is the base of all offsets, hence 0. */ -+ else -+ gcc_unreachable (); -+ -+ if (from == FRAME_POINTER_REGNUM) -+ src = cfun->machine->frame.frame_pointer_offset; -+ else if (from == ARG_POINTER_REGNUM) -+ src = cfun->machine->frame.arg_pointer_offset; -+ else -+ gcc_unreachable (); -+ -+ return src - dest; -+} -+ -+/* Implement RETURN_ADDR_RTX. We do not support moving back to a -+ previous frame. */ -+ -+rtx -+riscv_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) -+{ -+ if (count != 0) -+ return const0_rtx; -+ -+ return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); -+} -+ -+/* Emit code to change the current function's return address to -+ ADDRESS. SCRATCH is available as a scratch register, if needed. -+ ADDRESS and SCRATCH are both word-mode GPRs. */ -+ -+void -+riscv_set_return_address (rtx address, rtx scratch) -+{ -+ rtx slot_address; -+ -+ gcc_assert (BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM)); -+ slot_address = riscv_add_offset (scratch, stack_pointer_rtx, -+ cfun->machine->frame.gp_sp_offset); -+ riscv_emit_move (gen_frame_mem (GET_MODE (address), slot_address), address); -+} -+ -+/* A function to save or store a register. The first argument is the -+ register and the second is the stack slot. */ -+typedef void (*riscv_save_restore_fn) (rtx, rtx); -+ -+/* Use FN to save or restore register REGNO. MODE is the register's -+ mode and OFFSET is the offset of its save slot from the current -+ stack pointer. */ -+ -+static void -+riscv_save_restore_reg (enum machine_mode mode, int regno, -+ HOST_WIDE_INT offset, riscv_save_restore_fn fn) -+{ -+ rtx mem; -+ -+ mem = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx, offset)); -+ fn (gen_rtx_REG (mode, regno), mem); -+} -+ -+/* Call FN for each register that is saved by the current function. -+ SP_OFFSET is the offset of the current stack pointer from the start -+ of the frame. */ -+ -+static void -+riscv_for_each_saved_reg (HOST_WIDE_INT sp_offset, riscv_save_restore_fn fn) -+{ -+ HOST_WIDE_INT offset; -+ -+ /* Save the link register and s-registers. */ -+ offset = cfun->machine->frame.gp_sp_offset - sp_offset; -+ for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST-1; regno++) -+ if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) -+ { -+ riscv_save_restore_reg (word_mode, regno, offset, fn); -+ offset -= UNITS_PER_WORD; -+ } -+ -+ /* This loop must iterate over the same space as its companion in -+ riscv_compute_frame_info. */ -+ offset = cfun->machine->frame.fp_sp_offset - sp_offset; -+ for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) -+ if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) -+ { -+ enum machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode; -+ -+ riscv_save_restore_reg (mode, regno, offset, fn); -+ offset -= GET_MODE_SIZE (mode); -+ } -+} -+ -+/* Save register REG to MEM. Make the instruction frame-related. */ -+ -+static void -+riscv_save_reg (rtx reg, rtx mem) -+{ -+ riscv_emit_move (mem, reg); -+ riscv_set_frame_expr (riscv_frame_set (mem, reg)); -+} -+ -+/* Restore register REG from MEM. */ -+ -+static void -+riscv_restore_reg (rtx reg, rtx mem) -+{ -+ rtx insn = riscv_emit_move (reg, mem); -+ rtx dwarf = NULL_RTX; -+ dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf); -+ REG_NOTES (insn) = dwarf; -+ -+ RTX_FRAME_RELATED_P (insn) = 1; -+} -+ -+/* Return the code to invoke the GPR save routine. */ -+ -+const char * -+riscv_output_gpr_save (unsigned mask) -+{ -+ static char s[32]; -+ unsigned n = riscv_save_libcall_count (mask); -+ -+ ssize_t bytes = snprintf (s, sizeof (s), "call\tt0,__riscv_save_%u", n); -+ gcc_assert ((size_t) bytes < sizeof (s)); -+ -+ return s; -+} -+ -+/* For stack frames that can't be allocated with a single ADDI instruction, -+ compute the best value to initially allocate. It must at a minimum -+ allocate enough space to spill the callee-saved registers. */ -+ -+static HOST_WIDE_INT -+riscv_first_stack_step (struct riscv_frame_info *frame) -+{ -+ HOST_WIDE_INT min_first_step = frame->total_size - frame->fp_sp_offset; -+ HOST_WIDE_INT max_first_step = IMM_REACH / 2 - STACK_BOUNDARY / 8; -+ -+ if (SMALL_OPERAND (frame->total_size)) -+ return frame->total_size; -+ -+ /* As an optimization, use the least-significant bits of the total frame -+ size, so that the second adjustment step is just LUI + ADD. */ -+ if (!SMALL_OPERAND (frame->total_size - max_first_step) -+ && frame->total_size % IMM_REACH < IMM_REACH / 2 -+ && frame->total_size % IMM_REACH >= min_first_step) -+ return frame->total_size % IMM_REACH; -+ -+ gcc_assert (min_first_step <= max_first_step); -+ return max_first_step; -+} -+ -+static rtx -+riscv_adjust_libcall_cfi_prologue () -+{ -+ rtx dwarf = NULL_RTX; -+ rtx adjust_sp_rtx, reg, mem, insn; -+ int saved_size = cfun->machine->frame.save_libcall_adjustment; -+ int offset; -+ -+ for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST-1; regno++) -+ if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) -+ { -+ /* The save order is ra, s0, s1, s2 to s11. */ -+ if (regno == RETURN_ADDR_REGNUM) -+ offset = saved_size - UNITS_PER_WORD; -+ else if (regno == S0_REGNUM) -+ offset = saved_size - UNITS_PER_WORD * 2; -+ else if (regno == S1_REGNUM) -+ offset = saved_size - UNITS_PER_WORD * 3; -+ else -+ offset = saved_size - ((regno - S2_REGNUM + 4) * UNITS_PER_WORD); -+ -+ reg = gen_rtx_REG (SImode, regno); -+ mem = gen_frame_mem (SImode, plus_constant (Pmode, -+ stack_pointer_rtx, -+ offset)); -+ -+ insn = gen_rtx_SET (mem, reg); -+ dwarf = alloc_reg_note (REG_CFA_OFFSET, insn, dwarf); -+ } -+ -+ /* Debug info for adjust sp. */ -+ adjust_sp_rtx = gen_add3_insn (stack_pointer_rtx, -+ stack_pointer_rtx, GEN_INT (-saved_size)); -+ dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, adjust_sp_rtx, -+ dwarf); -+ return dwarf; -+} -+ -+static void -+riscv_emit_stack_tie (void) -+{ -+ if (Pmode == SImode) -+ emit_insn (gen_stack_tiesi (stack_pointer_rtx, hard_frame_pointer_rtx)); -+ else -+ emit_insn (gen_stack_tiedi (stack_pointer_rtx, hard_frame_pointer_rtx)); -+} -+ -+/* Expand the "prologue" pattern. */ -+ -+void -+riscv_expand_prologue (void) -+{ -+ struct riscv_frame_info *frame = &cfun->machine->frame; -+ HOST_WIDE_INT size = frame->total_size; -+ unsigned mask = frame->mask; -+ rtx insn; -+ -+ if (flag_stack_usage_info) -+ current_function_static_stack_size = size; -+ -+ /* When optimizing for size, call a subroutine to save the registers. */ -+ if (riscv_use_save_libcall (frame)) -+ { -+ rtx dwarf = NULL_RTX; -+ dwarf = riscv_adjust_libcall_cfi_prologue (); -+ -+ frame->mask = 0; /* Temporarily fib that we need not save GPRs. */ -+ size -= frame->save_libcall_adjustment; -+ insn = emit_insn (gen_gpr_save (GEN_INT (mask))); -+ -+ RTX_FRAME_RELATED_P (insn) = 1; -+ REG_NOTES (insn) = dwarf; -+ } -+ -+ /* Save the registers. */ -+ if ((frame->mask | frame->fmask) != 0) -+ { -+ HOST_WIDE_INT step1 = MIN (size, riscv_first_stack_step (frame)); -+ -+ insn = gen_add3_insn (stack_pointer_rtx, -+ stack_pointer_rtx, -+ GEN_INT (-step1)); -+ RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; -+ size -= step1; -+ riscv_for_each_saved_reg (size, riscv_save_reg); -+ } -+ -+ frame->mask = mask; /* Undo the above fib. */ -+ -+ /* Set up the frame pointer, if we're using one. */ -+ if (frame_pointer_needed) -+ { -+ insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (frame->hard_frame_pointer_offset - size)); -+ RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; -+ -+ riscv_emit_stack_tie (); -+ } -+ -+ /* Allocate the rest of the frame. */ -+ if (size > 0) -+ { -+ if (SMALL_OPERAND (-size)) -+ { -+ insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (-size)); -+ RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; -+ } -+ else -+ { -+ riscv_emit_move (RISCV_PROLOGUE_TEMP (Pmode), GEN_INT (-size)); -+ emit_insn (gen_add3_insn (stack_pointer_rtx, -+ stack_pointer_rtx, -+ RISCV_PROLOGUE_TEMP (Pmode))); -+ -+ /* Describe the effect of the previous instructions. */ -+ insn = plus_constant (Pmode, stack_pointer_rtx, -size); -+ insn = gen_rtx_SET (stack_pointer_rtx, insn); -+ riscv_set_frame_expr (insn); -+ } -+ } -+} -+ -+static rtx -+riscv_adjust_libcall_cfi_epilogue () -+{ -+ rtx dwarf = NULL_RTX; -+ rtx adjust_sp_rtx, reg; -+ int saved_size = cfun->machine->frame.save_libcall_adjustment; -+ -+ /* Debug info for adjust sp. */ -+ adjust_sp_rtx = gen_add3_insn (stack_pointer_rtx, -+ stack_pointer_rtx, GEN_INT (saved_size)); -+ dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, adjust_sp_rtx, -+ dwarf); -+ -+ for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST-1; regno++) -+ if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) -+ { -+ reg = gen_rtx_REG (SImode, regno); -+ dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf); -+ } -+ -+ return dwarf; -+} -+ -+/* Expand an "epilogue" or "sibcall_epilogue" pattern; SIBCALL_P -+ says which. */ -+ -+void -+riscv_expand_epilogue (bool sibcall_p) -+{ -+ /* Split the frame into two. STEP1 is the amount of stack we should -+ deallocate before restoring the registers. STEP2 is the amount we -+ should deallocate afterwards. -+ -+ Start off by assuming that no registers need to be restored. */ -+ struct riscv_frame_info *frame = &cfun->machine->frame; -+ unsigned mask = frame->mask; -+ HOST_WIDE_INT step1 = frame->total_size; -+ HOST_WIDE_INT step2 = 0; -+ bool use_restore_libcall = !sibcall_p && riscv_use_save_libcall (frame); -+ rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); -+ rtx insn; -+ -+ /* We need to add memory barrier to prevent read from deallocated stack. */ -+ bool need_barrier_p = (get_frame_size () -+ + cfun->machine->frame.arg_pointer_offset) != 0; -+ -+ if (!sibcall_p && riscv_can_use_return_insn ()) -+ { -+ emit_jump_insn (gen_return ()); -+ return; -+ } -+ -+ /* Move past any dynamic stack allocations. */ -+ if (cfun->calls_alloca) -+ { -+ /* Emit a barrier to prevent loads from a deallocated stack. */ -+ riscv_emit_stack_tie (); -+ need_barrier_p = false; -+ -+ rtx adjust = GEN_INT (-frame->hard_frame_pointer_offset); -+ if (!SMALL_OPERAND (INTVAL (adjust))) -+ { -+ riscv_emit_move (RISCV_PROLOGUE_TEMP (Pmode), adjust); -+ adjust = RISCV_PROLOGUE_TEMP (Pmode); -+ } -+ -+ insn = emit_insn ( -+ gen_add3_insn (stack_pointer_rtx, hard_frame_pointer_rtx, -+ adjust)); -+ -+ rtx dwarf = NULL_RTX; -+ rtx cfa_adjust_value = gen_rtx_PLUS ( -+ Pmode, hard_frame_pointer_rtx, -+ GEN_INT (-frame->hard_frame_pointer_offset)); -+ rtx cfa_adjust_rtx = gen_rtx_SET (stack_pointer_rtx, cfa_adjust_value); -+ dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, cfa_adjust_rtx, dwarf); -+ RTX_FRAME_RELATED_P (insn) = 1; -+ -+ REG_NOTES (insn) = dwarf; -+ } -+ -+ /* If we need to restore registers, deallocate as much stack as -+ possible in the second step without going out of range. */ -+ if ((frame->mask | frame->fmask) != 0) -+ { -+ step2 = riscv_first_stack_step (frame); -+ step1 -= step2; -+ } -+ -+ /* Set TARGET to BASE + STEP1. */ -+ if (step1 > 0) -+ { -+ /* Emit a barrier to prevent loads from a deallocated stack. */ -+ riscv_emit_stack_tie (); -+ need_barrier_p = false; -+ -+ /* Get an rtx for STEP1 that we can add to BASE. */ -+ rtx adjust = GEN_INT (step1); -+ if (!SMALL_OPERAND (step1)) -+ { -+ riscv_emit_move (RISCV_PROLOGUE_TEMP (Pmode), adjust); -+ adjust = RISCV_PROLOGUE_TEMP (Pmode); -+ } -+ -+ insn = emit_insn ( -+ gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, adjust)); -+ -+ rtx dwarf = NULL_RTX; -+ rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, -+ GEN_INT (step2)); -+ -+ dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); -+ RTX_FRAME_RELATED_P (insn) = 1; -+ -+ REG_NOTES (insn) = dwarf; -+ } -+ -+ if (use_restore_libcall) -+ frame->mask = 0; /* Temporarily fib that we need not save GPRs. */ -+ -+ /* Restore the registers. */ -+ riscv_for_each_saved_reg (frame->total_size - step2, riscv_restore_reg); -+ -+ if (use_restore_libcall) -+ { -+ frame->mask = mask; /* Undo the above fib. */ -+ gcc_assert (step2 >= frame->save_libcall_adjustment); -+ step2 -= frame->save_libcall_adjustment; -+ } -+ -+ if (need_barrier_p) -+ riscv_emit_stack_tie (); -+ -+ /* Deallocate the final bit of the frame. */ -+ if (step2 > 0) -+ { -+ insn = emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (step2))); -+ -+ rtx dwarf = NULL_RTX; -+ rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, -+ const0_rtx); -+ dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); -+ RTX_FRAME_RELATED_P (insn) = 1; -+ -+ REG_NOTES (insn) = dwarf; -+ } -+ -+ if (use_restore_libcall) -+ { -+ rtx dwarf = riscv_adjust_libcall_cfi_epilogue (); -+ insn = emit_insn (gen_gpr_restore (GEN_INT (riscv_save_libcall_count (mask)))); -+ RTX_FRAME_RELATED_P (insn) = 1; -+ REG_NOTES (insn) = dwarf; -+ -+ emit_jump_insn (gen_gpr_restore_return (ra)); -+ return; -+ } -+ -+ /* Add in the __builtin_eh_return stack adjustment. */ -+ if (crtl->calls_eh_return) -+ emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, -+ EH_RETURN_STACKADJ_RTX)); -+ -+ if (!sibcall_p) -+ emit_jump_insn (gen_simple_return_internal (ra)); -+} -+ -+/* Return nonzero if this function is known to have a null epilogue. -+ This allows the optimizer to omit jumps to jumps if no stack -+ was created. */ -+ -+bool -+riscv_can_use_return_insn (void) -+{ -+ return reload_completed && cfun->machine->frame.total_size == 0; -+} -+ -+/* Implement TARGET_REGISTER_MOVE_COST. */ -+ -+static int -+riscv_register_move_cost (enum machine_mode mode, -+ reg_class_t from, reg_class_t to) -+{ -+ return SECONDARY_MEMORY_NEEDED (from, to, mode) ? 8 : 2; -+} -+ -+/* Return true if register REGNO can store a value of mode MODE. */ -+ -+bool -+riscv_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode) -+{ -+ unsigned int nregs = riscv_hard_regno_nregs (regno, mode); -+ -+ if (GP_REG_P (regno)) -+ { -+ if (!GP_REG_P (regno + nregs - 1)) -+ return false; -+ } -+ else if (FP_REG_P (regno)) -+ { -+ if (!FP_REG_P (regno + nregs - 1)) -+ return false; -+ -+ if (GET_MODE_CLASS (mode) != MODE_FLOAT -+ && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT) -+ return false; -+ -+ /* Only use callee-saved registers if a potential callee is guaranteed -+ to spill the requisite width. */ -+ if (GET_MODE_UNIT_SIZE (mode) > UNITS_PER_FP_REG -+ || (!call_used_regs[regno] -+ && GET_MODE_UNIT_SIZE (mode) > UNITS_PER_FP_ARG)) -+ return false; -+ } -+ else -+ return false; -+ -+ /* Require same callee-savedness for all registers. */ -+ for (unsigned i = 1; i < nregs; i++) -+ if (call_used_regs[regno] != call_used_regs[regno + i]) -+ return false; -+ -+ return true; -+} -+ -+/* Implement HARD_REGNO_NREGS. */ -+ -+unsigned int -+riscv_hard_regno_nregs (int regno, enum machine_mode mode) -+{ -+ if (FP_REG_P (regno)) -+ return (GET_MODE_SIZE (mode) + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG; -+ -+ /* All other registers are word-sized. */ -+ return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; -+} -+ -+/* Implement CLASS_MAX_NREGS. */ -+ -+static unsigned char -+riscv_class_max_nregs (reg_class_t rclass, enum machine_mode mode) -+{ -+ if (reg_class_subset_p (FP_REGS, rclass)) -+ return riscv_hard_regno_nregs (FP_REG_FIRST, mode); -+ -+ if (reg_class_subset_p (GR_REGS, rclass)) -+ return riscv_hard_regno_nregs (GP_REG_FIRST, mode); -+ -+ return 0; -+} -+ -+/* Implement TARGET_PREFERRED_RELOAD_CLASS. */ -+ -+static reg_class_t -+riscv_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t rclass) -+{ -+ return reg_class_subset_p (FP_REGS, rclass) ? FP_REGS : -+ reg_class_subset_p (GR_REGS, rclass) ? GR_REGS : -+ rclass; -+} -+ -+/* Implement TARGET_MEMORY_MOVE_COST. */ -+ -+static int -+riscv_memory_move_cost (enum machine_mode mode, reg_class_t rclass, bool in) -+{ -+ return (tune_info->memory_cost -+ + memory_move_secondary_cost (mode, rclass, in)); -+} -+ -+/* Return the number of instructions that can be issued per cycle. */ -+ -+static int -+riscv_issue_rate (void) -+{ -+ return tune_info->issue_rate; -+} -+ -+/* Implement TARGET_ASM_FILE_START. */ -+ -+static void -+riscv_file_start (void) -+{ -+ default_file_start (); -+ -+ /* Instruct GAS to generate position-[in]dependent code. */ -+ fprintf (asm_out_file, "\t.option %spic\n", (flag_pic ? "" : "no")); -+} -+ -+/* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text -+ in order to avoid duplicating too much logic from elsewhere. */ -+ -+static void -+riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, -+ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, -+ tree function) -+{ -+ rtx this_rtx, temp1, temp2, fnaddr; -+ rtx_insn *insn; -+ -+ /* Pretend to be a post-reload pass while generating rtl. */ -+ reload_completed = 1; -+ -+ /* Mark the end of the (empty) prologue. */ -+ emit_note (NOTE_INSN_PROLOGUE_END); -+ -+ /* Determine if we can use a sibcall to call FUNCTION directly. */ -+ fnaddr = gen_rtx_MEM (FUNCTION_MODE, XEXP (DECL_RTL (function), 0)); -+ -+ /* We need two temporary registers in some cases. */ -+ temp1 = gen_rtx_REG (Pmode, RISCV_PROLOGUE_TEMP_REGNUM); -+ temp2 = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM); -+ -+ /* Find out which register contains the "this" pointer. */ -+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) -+ this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1); -+ else -+ this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST); -+ -+ /* Add DELTA to THIS_RTX. */ -+ if (delta != 0) -+ { -+ rtx offset = GEN_INT (delta); -+ if (!SMALL_OPERAND (delta)) -+ { -+ riscv_emit_move (temp1, offset); -+ offset = temp1; -+ } -+ emit_insn (gen_add3_insn (this_rtx, this_rtx, offset)); -+ } -+ -+ /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */ -+ if (vcall_offset != 0) -+ { -+ rtx addr; -+ -+ /* Set TEMP1 to *THIS_RTX. */ -+ riscv_emit_move (temp1, gen_rtx_MEM (Pmode, this_rtx)); -+ -+ /* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET. */ -+ addr = riscv_add_offset (temp2, temp1, vcall_offset); -+ -+ /* Load the offset and add it to THIS_RTX. */ -+ riscv_emit_move (temp1, gen_rtx_MEM (Pmode, addr)); -+ emit_insn (gen_add3_insn (this_rtx, this_rtx, temp1)); -+ } -+ -+ /* Jump to the target function. */ -+ insn = emit_call_insn (gen_sibcall (fnaddr, const0_rtx, NULL, const0_rtx)); -+ SIBLING_CALL_P (insn) = 1; -+ -+ /* Run just enough of rest_of_compilation. This sequence was -+ "borrowed" from alpha.c. */ -+ insn = get_insns (); -+ split_all_insns_noflow (); -+ shorten_branches (insn); -+ final_start_function (insn, file, 1); -+ final (insn, file, 1); -+ final_end_function (); -+ -+ /* Clean up the vars set above. Note that final_end_function resets -+ the global pointer for us. */ -+ reload_completed = 0; -+} -+ -+/* Allocate a chunk of memory for per-function machine-dependent data. */ -+ -+static struct machine_function * -+riscv_init_machine_status (void) -+{ -+ return ggc_cleared_alloc (); -+} -+ -+/* Implement TARGET_OPTION_OVERRIDE. */ -+ -+static void -+riscv_option_override (void) -+{ -+ const struct riscv_cpu_info *cpu; -+ -+#ifdef SUBTARGET_OVERRIDE_OPTIONS -+ SUBTARGET_OVERRIDE_OPTIONS; -+#endif -+ -+ flag_pcc_struct_return = 0; -+ -+ if (flag_pic) -+ g_switch_value = 0; -+ -+ /* The presence of the M extension implies that division instructions -+ are present, so include them unless explicitly disabled. */ -+ if (TARGET_MUL && (target_flags_explicit & MASK_DIV) == 0) -+ target_flags |= MASK_DIV; -+ else if (!TARGET_MUL && TARGET_DIV) -+ error ("-mdiv requires -march to subsume the % extension"); -+ -+ /* Likewise floating-point division and square root. */ -+ if (TARGET_HARD_FLOAT && (target_flags_explicit & MASK_FDIV) == 0) -+ target_flags |= MASK_FDIV; -+ -+ /* Handle -mtune. */ -+ cpu = riscv_parse_cpu (riscv_tune_string ? riscv_tune_string : -+ RISCV_TUNE_STRING_DEFAULT); -+ tune_info = optimize_size ? &optimize_size_tune_info : cpu->tune_info; -+ -+ /* If the user hasn't specified a branch cost, use the processor's -+ default. */ -+ if (riscv_branch_cost == 0) -+ riscv_branch_cost = tune_info->branch_cost; -+ -+ /* Function to allocate machine-dependent function status. */ -+ init_machine_status = &riscv_init_machine_status; -+ -+ if (flag_pic) -+ riscv_cmodel = CM_PIC; -+ -+ /* We get better code with explicit relocs for CM_MEDLOW, but -+ worse code for the others (for now). Pick the best default. */ -+ if ((target_flags_explicit & MASK_EXPLICIT_RELOCS) == 0) -+ if (riscv_cmodel == CM_MEDLOW) -+ target_flags |= MASK_EXPLICIT_RELOCS; -+ -+ /* Require that the ISA supports the requested floating-point ABI. */ -+ if (UNITS_PER_FP_ARG > (TARGET_HARD_FLOAT ? UNITS_PER_FP_REG : 0)) -+ error ("requested ABI requires -march to subsume the %qc extension", -+ UNITS_PER_FP_ARG > 8 ? 'Q' : (UNITS_PER_FP_ARG > 4 ? 'D' : 'F')); -+ -+ /* We do not yet support ILP32 on RV64. */ -+ if (BITS_PER_WORD != POINTER_SIZE) -+ error ("ABI requires -march=rv%d", POINTER_SIZE); -+} -+ -+/* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */ -+ -+static void -+riscv_conditional_register_usage (void) -+{ -+ if (!TARGET_HARD_FLOAT) -+ { -+ for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) -+ fixed_regs[regno] = call_used_regs[regno] = 1; -+ } -+} -+ -+/* Return a register priority for hard reg REGNO. */ -+ -+static int -+riscv_register_priority (int regno) -+{ -+ /* Favor x8-x15/f8-f15 to improve the odds of RVC instruction selection. */ -+ if (TARGET_RVC && (IN_RANGE (regno, GP_REG_FIRST + 8, GP_REG_FIRST + 15) -+ || IN_RANGE (regno, FP_REG_FIRST + 8, FP_REG_FIRST + 15))) -+ return 1; -+ -+ return 0; -+} -+ -+/* Implement TARGET_TRAMPOLINE_INIT. */ -+ -+static void -+riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) -+{ -+ rtx addr, end_addr, mem; -+ uint32_t trampoline[4]; -+ unsigned int i; -+ HOST_WIDE_INT static_chain_offset, target_function_offset; -+ -+ /* Work out the offsets of the pointers from the start of the -+ trampoline code. */ -+ gcc_assert (ARRAY_SIZE (trampoline) * 4 == TRAMPOLINE_CODE_SIZE); -+ -+ /* Get pointers to the beginning and end of the code block. */ -+ addr = force_reg (Pmode, XEXP (m_tramp, 0)); -+ end_addr = riscv_force_binary (Pmode, PLUS, addr, -+ GEN_INT (TRAMPOLINE_CODE_SIZE)); -+ -+ -+ if (Pmode == SImode) -+ { -+ chain_value = force_reg (Pmode, chain_value); -+ -+ rtx target_function = force_reg (Pmode, XEXP (DECL_RTL (fndecl), 0)); -+ /* lui t2, hi(chain) -+ lui t1, hi(func) -+ addi t2, t2, lo(chain) -+ jr r1, lo(func) -+ */ -+ unsigned HOST_WIDE_INT lui_hi_chain_code, lui_hi_func_code; -+ unsigned HOST_WIDE_INT lo_chain_code, lo_func_code; -+ -+ rtx uimm_mask = force_reg (SImode, gen_int_mode (-IMM_REACH, SImode)); -+ -+ /* 0xfff. */ -+ rtx imm12_mask = gen_reg_rtx (SImode); -+ emit_insn (gen_one_cmplsi2 (imm12_mask, uimm_mask)); -+ -+ rtx fixup_value = force_reg (SImode, gen_int_mode (IMM_REACH/2, SImode)); -+ -+ /* Gen lui t2, hi(chain). */ -+ rtx hi_chain = riscv_force_binary (SImode, PLUS, chain_value, -+ fixup_value); -+ hi_chain = riscv_force_binary (SImode, AND, hi_chain, -+ uimm_mask); -+ lui_hi_chain_code = OPCODE_LUI | (STATIC_CHAIN_REGNUM << SHIFT_RD); -+ rtx lui_hi_chain = riscv_force_binary (SImode, IOR, hi_chain, -+ gen_int_mode (lui_hi_chain_code, SImode)); -+ -+ mem = adjust_address (m_tramp, SImode, 0); -+ riscv_emit_move (mem, lui_hi_chain); -+ -+ /* Gen lui t1, hi(func). */ -+ rtx hi_func = riscv_force_binary (SImode, PLUS, target_function, -+ fixup_value); -+ hi_func = riscv_force_binary (SImode, AND, hi_func, -+ uimm_mask); -+ lui_hi_func_code = OPCODE_LUI | (RISCV_PROLOGUE_TEMP_REGNUM << SHIFT_RD); -+ rtx lui_hi_func = riscv_force_binary (SImode, IOR, hi_func, -+ gen_int_mode (lui_hi_func_code, SImode)); -+ -+ mem = adjust_address (m_tramp, SImode, 1 * GET_MODE_SIZE (SImode)); -+ riscv_emit_move (mem, lui_hi_func); -+ -+ /* Gen addi t2, t2, lo(chain). */ -+ rtx lo_chain = riscv_force_binary (SImode, AND, chain_value, -+ imm12_mask); -+ lo_chain = riscv_force_binary (SImode, ASHIFT, lo_chain, GEN_INT (20)); -+ -+ lo_chain_code = OPCODE_ADDI -+ | (STATIC_CHAIN_REGNUM << SHIFT_RD) -+ | (STATIC_CHAIN_REGNUM << SHIFT_RS1); -+ -+ rtx addi_lo_chain = riscv_force_binary (SImode, IOR, lo_chain, -+ force_reg (SImode, GEN_INT (lo_chain_code))); -+ -+ mem = adjust_address (m_tramp, SImode, 2 * GET_MODE_SIZE (SImode)); -+ riscv_emit_move (mem, addi_lo_chain); -+ -+ /* Gen jr r1, lo(func). */ -+ rtx lo_func = riscv_force_binary (SImode, AND, target_function, -+ imm12_mask); -+ lo_func = riscv_force_binary (SImode, ASHIFT, lo_func, GEN_INT (20)); -+ -+ lo_func_code = OPCODE_JALR | (RISCV_PROLOGUE_TEMP_REGNUM << SHIFT_RS1); -+ -+ rtx jr_lo_func = riscv_force_binary (SImode, IOR, lo_func, -+ force_reg (SImode, GEN_INT (lo_func_code))); -+ -+ mem = adjust_address (m_tramp, SImode, 3 * GET_MODE_SIZE (SImode)); -+ riscv_emit_move (mem, jr_lo_func); -+ } -+ else -+ { -+ static_chain_offset = TRAMPOLINE_CODE_SIZE; -+ target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode); -+ -+ /* auipc t2, 0 -+ l[wd] t1, target_function_offset(t2) -+ l[wd] t2, static_chain_offset(t2) -+ jr t1 -+ */ -+ trampoline[0] = OPCODE_AUIPC | (STATIC_CHAIN_REGNUM << SHIFT_RD); -+ trampoline[1] = (Pmode == DImode ? OPCODE_LD : OPCODE_LW) -+ | (RISCV_PROLOGUE_TEMP_REGNUM << SHIFT_RD) -+ | (STATIC_CHAIN_REGNUM << SHIFT_RS1) -+ | (target_function_offset << SHIFT_IMM); -+ trampoline[2] = (Pmode == DImode ? OPCODE_LD : OPCODE_LW) -+ | (STATIC_CHAIN_REGNUM << SHIFT_RD) -+ | (STATIC_CHAIN_REGNUM << SHIFT_RS1) -+ | (static_chain_offset << SHIFT_IMM); -+ trampoline[3] = OPCODE_JALR | (RISCV_PROLOGUE_TEMP_REGNUM << SHIFT_RS1); -+ -+ /* Copy the trampoline code. */ -+ for (i = 0; i < ARRAY_SIZE (trampoline); i++) -+ { -+ mem = adjust_address (m_tramp, SImode, i * GET_MODE_SIZE (SImode)); -+ riscv_emit_move (mem, gen_int_mode (trampoline[i], SImode)); -+ } -+ -+ /* Set up the static chain pointer field. */ -+ mem = adjust_address (m_tramp, ptr_mode, static_chain_offset); -+ riscv_emit_move (mem, chain_value); -+ -+ /* Set up the target function field. */ -+ mem = adjust_address (m_tramp, ptr_mode, target_function_offset); -+ riscv_emit_move (mem, XEXP (DECL_RTL (fndecl), 0)); -+ } -+ -+ /* Flush the code part of the trampoline. */ -+ emit_insn (gen_add3_insn (end_addr, addr, GEN_INT (TRAMPOLINE_SIZE))); -+ emit_insn (gen_clear_cache (addr, end_addr)); -+} -+ -+/* Return leaf_function_p () and memoize the result. */ -+ -+static bool -+riscv_leaf_function_p (void) -+{ -+ if (cfun->machine->is_leaf == 0) -+ cfun->machine->is_leaf = leaf_function_p () ? 1 : -1; -+ -+ return cfun->machine->is_leaf > 0; -+} -+ -+/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */ -+ -+static bool -+riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, -+ tree exp ATTRIBUTE_UNUSED) -+{ -+ /* When optimzing for size, don't use sibcalls in non-leaf routines */ -+ if (TARGET_SAVE_RESTORE) -+ return riscv_leaf_function_p (); -+ -+ return true; -+} -+ -+/* Implement TARGET_CANNOT_COPY_INSN_P. */ -+ -+static bool -+riscv_cannot_copy_insn_p (rtx_insn *insn) -+{ -+ return recog_memoized (insn) >= 0 && get_attr_cannot_copy (insn); -+} -+ -+/* Initialize the GCC target structure. */ -+#undef TARGET_ASM_ALIGNED_HI_OP -+#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" -+#undef TARGET_ASM_ALIGNED_SI_OP -+#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" -+#undef TARGET_ASM_ALIGNED_DI_OP -+#define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t" -+ -+#undef TARGET_OPTION_OVERRIDE -+#define TARGET_OPTION_OVERRIDE riscv_option_override -+ -+#undef TARGET_LEGITIMIZE_ADDRESS -+#define TARGET_LEGITIMIZE_ADDRESS riscv_legitimize_address -+ -+#undef TARGET_SCHED_ISSUE_RATE -+#define TARGET_SCHED_ISSUE_RATE riscv_issue_rate -+ -+#undef TARGET_FUNCTION_OK_FOR_SIBCALL -+#define TARGET_FUNCTION_OK_FOR_SIBCALL riscv_function_ok_for_sibcall -+ -+#undef TARGET_REGISTER_MOVE_COST -+#define TARGET_REGISTER_MOVE_COST riscv_register_move_cost -+#undef TARGET_MEMORY_MOVE_COST -+#define TARGET_MEMORY_MOVE_COST riscv_memory_move_cost -+#undef TARGET_RTX_COSTS -+#define TARGET_RTX_COSTS riscv_rtx_costs -+#undef TARGET_ADDRESS_COST -+#define TARGET_ADDRESS_COST riscv_address_cost -+ -+#undef TARGET_PREFERRED_RELOAD_CLASS -+#define TARGET_PREFERRED_RELOAD_CLASS riscv_preferred_reload_class -+ -+#undef TARGET_ASM_FILE_START -+#define TARGET_ASM_FILE_START riscv_file_start -+#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE -+#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true -+ -+#undef TARGET_EXPAND_BUILTIN_VA_START -+#define TARGET_EXPAND_BUILTIN_VA_START riscv_va_start -+ -+#undef TARGET_PROMOTE_FUNCTION_MODE -+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote -+ -+#undef TARGET_RETURN_IN_MEMORY -+#define TARGET_RETURN_IN_MEMORY riscv_return_in_memory -+ -+#undef TARGET_ASM_OUTPUT_MI_THUNK -+#define TARGET_ASM_OUTPUT_MI_THUNK riscv_output_mi_thunk -+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK -+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true -+ -+#undef TARGET_PRINT_OPERAND -+#define TARGET_PRINT_OPERAND riscv_print_operand -+#undef TARGET_PRINT_OPERAND_ADDRESS -+#define TARGET_PRINT_OPERAND_ADDRESS riscv_print_operand_address -+ -+#undef TARGET_SETUP_INCOMING_VARARGS -+#define TARGET_SETUP_INCOMING_VARARGS riscv_setup_incoming_varargs -+#undef TARGET_STRICT_ARGUMENT_NAMING -+#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true -+#undef TARGET_MUST_PASS_IN_STACK -+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size -+#undef TARGET_PASS_BY_REFERENCE -+#define TARGET_PASS_BY_REFERENCE riscv_pass_by_reference -+#undef TARGET_ARG_PARTIAL_BYTES -+#define TARGET_ARG_PARTIAL_BYTES riscv_arg_partial_bytes -+#undef TARGET_FUNCTION_ARG -+#define TARGET_FUNCTION_ARG riscv_function_arg -+#undef TARGET_FUNCTION_ARG_ADVANCE -+#define TARGET_FUNCTION_ARG_ADVANCE riscv_function_arg_advance -+#undef TARGET_FUNCTION_ARG_BOUNDARY -+#define TARGET_FUNCTION_ARG_BOUNDARY riscv_function_arg_boundary -+ -+/* The generic ELF target does not always have TLS support. */ -+#ifdef HAVE_AS_TLS -+#undef TARGET_HAVE_TLS -+#define TARGET_HAVE_TLS true -+#endif -+ -+#undef TARGET_CANNOT_FORCE_CONST_MEM -+#define TARGET_CANNOT_FORCE_CONST_MEM riscv_cannot_force_const_mem -+ -+#undef TARGET_LEGITIMATE_CONSTANT_P -+#define TARGET_LEGITIMATE_CONSTANT_P riscv_legitimate_constant_p -+ -+#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P -+#define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true -+ -+#undef TARGET_LEGITIMATE_ADDRESS_P -+#define TARGET_LEGITIMATE_ADDRESS_P riscv_legitimate_address_p -+ -+#undef TARGET_CAN_ELIMINATE -+#define TARGET_CAN_ELIMINATE riscv_can_eliminate -+ -+#undef TARGET_CONDITIONAL_REGISTER_USAGE -+#define TARGET_CONDITIONAL_REGISTER_USAGE riscv_conditional_register_usage -+ -+#undef TARGET_CLASS_MAX_NREGS -+#define TARGET_CLASS_MAX_NREGS riscv_class_max_nregs -+ -+#undef TARGET_TRAMPOLINE_INIT -+#define TARGET_TRAMPOLINE_INIT riscv_trampoline_init -+ -+#undef TARGET_IN_SMALL_DATA_P -+#define TARGET_IN_SMALL_DATA_P riscv_in_small_data_p -+ -+#undef TARGET_ASM_SELECT_RTX_SECTION -+#define TARGET_ASM_SELECT_RTX_SECTION riscv_elf_select_rtx_section -+ -+#undef TARGET_MIN_ANCHOR_OFFSET -+#define TARGET_MIN_ANCHOR_OFFSET (-IMM_REACH/2) -+ -+#undef TARGET_MAX_ANCHOR_OFFSET -+#define TARGET_MAX_ANCHOR_OFFSET (IMM_REACH/2-1) -+ -+#undef TARGET_REGISTER_PRIORITY -+#define TARGET_REGISTER_PRIORITY riscv_register_priority -+ -+#undef TARGET_CANNOT_COPY_INSN_P -+#define TARGET_CANNOT_COPY_INSN_P riscv_cannot_copy_insn_p -+ -+#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV -+#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV riscv_atomic_assign_expand_fenv -+ -+#undef TARGET_INIT_BUILTINS -+#define TARGET_INIT_BUILTINS riscv_init_builtins -+ -+#undef TARGET_BUILTIN_DECL -+#define TARGET_BUILTIN_DECL riscv_builtin_decl -+ -+#undef TARGET_EXPAND_BUILTIN -+#define TARGET_EXPAND_BUILTIN riscv_expand_builtin -+ -+struct gcc_target targetm = TARGET_INITIALIZER; -+ -+#include "gt-riscv.h" -diff --git original-gcc/gcc/config/riscv/riscv.h gcc-6.3.0/gcc/config/riscv/riscv.h -new file mode 100644 -index 00000000000..8d4c75e6770 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/riscv.h -@@ -0,0 +1,906 @@ -+/* Definition of RISC-V target for GNU compiler. -+ Copyright (C) 2011-2017 Free Software Foundation, Inc. -+ Contributed by Andrew Waterman (andrew@sifive.com). -+ Based on MIPS target for GNU compiler. -+ -+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 -+. */ -+ -+#ifndef GCC_RISCV_H -+#define GCC_RISCV_H -+ -+#include "config/riscv/riscv-opts.h" -+ -+/* Target CPU builtins. */ -+#define TARGET_CPU_CPP_BUILTINS() riscv_cpu_cpp_builtins (pfile) -+ -+/* Default target_flags if no switches are specified */ -+ -+#ifndef TARGET_DEFAULT -+#define TARGET_DEFAULT 0 -+#endif -+ -+#ifndef RISCV_TUNE_STRING_DEFAULT -+#define RISCV_TUNE_STRING_DEFAULT "rocket" -+#endif -+ -+/* Support for a compile-time default CPU, et cetera. The rules are: -+ --with-arch is ignored if -march is specified. -+ --with-abi is ignored if -mabi is specified. -+ --with-tune is ignored if -mtune is specified. */ -+#define OPTION_DEFAULT_SPECS \ -+ {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \ -+ {"arch", "%{!march=*:-march=%(VALUE)}" }, \ -+ {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \ -+ -+#ifdef IN_LIBGCC2 -+#undef TARGET_64BIT -+/* Make this compile time constant for libgcc2 */ -+#define TARGET_64BIT (__riscv_xlen == 64) -+#endif /* IN_LIBGCC2 */ -+ -+#undef ASM_SPEC -+#define ASM_SPEC "\ -+%(subtarget_asm_debugging_spec) \ -+%{" FPIE_OR_FPIC_SPEC ":-fpic} \ -+%{march=*} \ -+%{mabi=*} \ -+%(subtarget_asm_spec)" -+ -+#define TARGET_DEFAULT_CMODEL CM_MEDLOW -+ -+#define LOCAL_LABEL_PREFIX "." -+#define USER_LABEL_PREFIX "" -+ -+/* Offsets recorded in opcodes are a multiple of this alignment factor. -+ The default for this in 64-bit mode is 8, which causes problems with -+ SFmode register saves. */ -+#define DWARF_CIE_DATA_ALIGNMENT -4 -+ -+/* The mapping from gcc register number to DWARF 2 CFA column number. */ -+#define DWARF_FRAME_REGNUM(REGNO) \ -+ (GP_REG_P (REGNO) || FP_REG_P (REGNO) ? REGNO : INVALID_REGNUM) -+ -+/* The DWARF 2 CFA column which tracks the return address. */ -+#define DWARF_FRAME_RETURN_COLUMN RETURN_ADDR_REGNUM -+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, RETURN_ADDR_REGNUM) -+ -+/* Describe how we implement __builtin_eh_return. */ -+#define EH_RETURN_DATA_REGNO(N) \ -+ ((N) < 4 ? (N) + GP_ARG_FIRST : INVALID_REGNUM) -+ -+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_ARG_FIRST + 4) -+ -+/* Target machine storage layout */ -+ -+#define BITS_BIG_ENDIAN 0 -+#define BYTES_BIG_ENDIAN 0 -+#define WORDS_BIG_ENDIAN 0 -+ -+#define MAX_BITS_PER_WORD 64 -+ -+/* Width of a word, in units (bytes). */ -+#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4) -+#ifndef IN_LIBGCC2 -+#define MIN_UNITS_PER_WORD 4 -+#endif -+ -+/* The `Q' extension is not yet supported. */ -+#define UNITS_PER_FP_REG (TARGET_DOUBLE_FLOAT ? 8 : 4) -+ -+/* The largest type that can be passed in floating-point registers. */ -+#define UNITS_PER_FP_ARG \ -+ (riscv_abi == ABI_ILP32 || riscv_abi == ABI_LP64 ? 0 : \ -+ riscv_abi == ABI_ILP32F || riscv_abi == ABI_LP64F ? 4 : 8) \ -+ -+/* Set the sizes of the core types. */ -+#define SHORT_TYPE_SIZE 16 -+#define INT_TYPE_SIZE 32 -+#define LONG_LONG_TYPE_SIZE 64 -+#define POINTER_SIZE (riscv_abi >= ABI_LP64 ? 64 : 32) -+#define LONG_TYPE_SIZE POINTER_SIZE -+ -+#define FLOAT_TYPE_SIZE 32 -+#define DOUBLE_TYPE_SIZE 64 -+#define LONG_DOUBLE_TYPE_SIZE 128 -+ -+/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -+#define PARM_BOUNDARY BITS_PER_WORD -+ -+/* Allocation boundary (in *bits*) for the code of a function. */ -+#define FUNCTION_BOUNDARY (TARGET_RVC ? 16 : 32) -+ -+/* There is no point aligning anything to a rounder boundary than this. */ -+#define BIGGEST_ALIGNMENT 128 -+ -+/* The user-level ISA permits misaligned accesses, but they may execute -+ extremely slowly and non-atomically. Some privileged architectures -+ do not permit them at all. It is best to enforce strict alignment. */ -+#define STRICT_ALIGNMENT 1 -+ -+/* Define this if you wish to imitate the way many other C compilers -+ handle alignment of bitfields and the structures that contain -+ them. -+ -+ The behavior is that the type written for a bit-field (`int', -+ `short', or other integer type) imposes an alignment for the -+ entire structure, as if the structure really did contain an -+ ordinary field of that type. In addition, the bit-field is placed -+ within the structure so that it would fit within such a field, -+ not crossing a boundary for it. -+ -+ Thus, on most machines, a bit-field whose type is written as `int' -+ would not cross a four-byte boundary, and would force four-byte -+ alignment for the whole structure. (The alignment used may not -+ be four bytes; it is controlled by the other alignment -+ parameters.) -+ -+ If the macro is defined, its definition should be a C expression; -+ a nonzero value for the expression enables this behavior. */ -+ -+#define PCC_BITFIELD_TYPE_MATTERS 1 -+ -+/* If defined, a C expression to compute the alignment given to a -+ constant that is being placed in memory. CONSTANT is the constant -+ and ALIGN is the alignment that the object would ordinarily have. -+ The value of this macro is used instead of that alignment to align -+ the object. -+ -+ If this macro is not defined, then ALIGN is used. -+ -+ The typical use of this macro is to increase alignment for string -+ constants to be word aligned so that `strcpy' calls that copy -+ constants can be done inline. */ -+ -+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ -+ ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \ -+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) -+ -+/* If defined, a C expression to compute the alignment for a static -+ variable. TYPE is the data type, and ALIGN is the alignment that -+ the object would ordinarily have. The value of this macro is used -+ instead of that alignment to align the object. -+ -+ If this macro is not defined, then ALIGN is used. -+ -+ One use of this macro is to increase alignment of medium-size -+ data to make it all fit in fewer cache lines. Another is to -+ cause character arrays to be word-aligned so that `strcpy' calls -+ that copy constants to character arrays can be done inline. */ -+ -+#define DATA_ALIGNMENT(TYPE, ALIGN) \ -+ ((((ALIGN) < BITS_PER_WORD) \ -+ && (TREE_CODE (TYPE) == ARRAY_TYPE \ -+ || TREE_CODE (TYPE) == UNION_TYPE \ -+ || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN)) -+ -+/* We need this for the same reason as DATA_ALIGNMENT, namely to cause -+ character arrays to be word-aligned so that `strcpy' calls that copy -+ constants to character arrays can be done inline, and 'strcmp' can be -+ optimised to use word loads. */ -+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \ -+ DATA_ALIGNMENT (TYPE, ALIGN) -+ -+/* Define if operations between registers always perform the operation -+ on the full register even if a narrower mode is specified. */ -+#define WORD_REGISTER_OPERATIONS 1 -+ -+/* When in 64-bit mode, move insns will sign extend SImode and CCmode -+ moves. All other references are zero extended. */ -+#define LOAD_EXTEND_OP(MODE) \ -+ (TARGET_64BIT && (MODE) == SImode ? SIGN_EXTEND : ZERO_EXTEND) -+ -+/* Define this macro if it is advisable to hold scalars in registers -+ in a wider mode than that declared by the program. In such cases, -+ the value is constrained to be within the bounds of the declared -+ type, but kept valid in the wider mode. The signedness of the -+ extension may differ from that of the type. */ -+ -+#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \ -+ if (GET_MODE_CLASS (MODE) == MODE_INT \ -+ && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ -+ { \ -+ if ((MODE) == SImode) \ -+ (UNSIGNEDP) = 0; \ -+ (MODE) = word_mode; \ -+ } -+ -+/* Pmode is always the same as ptr_mode, but not always the same as word_mode. -+ Extensions of pointers to word_mode must be signed. */ -+#define POINTERS_EXTEND_UNSIGNED false -+ -+/* When floating-point registers are wider than integer ones, moves between -+ them must go through memory. */ -+#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \ -+ (GET_MODE_SIZE (MODE) > UNITS_PER_WORD \ -+ && ((CLASS1) == FP_REGS) != ((CLASS2) == FP_REGS)) -+ -+/* Define if loading short immediate values into registers sign extends. */ -+#define SHORT_IMMEDIATES_SIGN_EXTEND 1 -+ -+/* Standard register usage. */ -+ -+/* Number of hardware registers. We have: -+ -+ - 32 integer registers -+ - 32 floating point registers -+ - 2 fake registers: -+ - ARG_POINTER_REGNUM -+ - FRAME_POINTER_REGNUM */ -+ -+#define FIRST_PSEUDO_REGISTER 66 -+ -+/* x0, sp, gp, and tp are fixed. */ -+ -+#define FIXED_REGISTERS \ -+{ /* General registers. */ \ -+ 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -+ /* Floating-point registers. */ \ -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -+ /* Others. */ \ -+ 1, 1 \ -+} -+ -+/* a0-a7, t0-a6, fa0-fa7, and ft0-ft11 are volatile across calls. -+ The call RTLs themselves clobber ra. */ -+ -+#define CALL_USED_REGISTERS \ -+{ /* General registers. */ \ -+ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, \ -+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \ -+ /* Floating-point registers. */ \ -+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, \ -+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \ -+ /* Others. */ \ -+ 1, 1 \ -+} -+ -+/* Internal macros to classify an ISA register's type. */ -+ -+#define GP_REG_FIRST 0 -+#define GP_REG_LAST 31 -+#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1) -+ -+#define FP_REG_FIRST 32 -+#define FP_REG_LAST 63 -+#define FP_REG_NUM (FP_REG_LAST - FP_REG_FIRST + 1) -+ -+/* The DWARF 2 CFA column which tracks the return address from a -+ signal handler context. This means that to maintain backwards -+ compatibility, no hard register can be assigned this column if it -+ would need to be handled by the DWARF unwinder. */ -+#define DWARF_ALT_FRAME_RETURN_COLUMN 64 -+ -+#define GP_REG_P(REGNO) \ -+ ((unsigned int) ((int) (REGNO) - GP_REG_FIRST) < GP_REG_NUM) -+#define FP_REG_P(REGNO) \ -+ ((unsigned int) ((int) (REGNO) - FP_REG_FIRST) < FP_REG_NUM) -+ -+#define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X))) -+ -+#define HARD_REGNO_NREGS(REGNO, MODE) riscv_hard_regno_nregs (REGNO, MODE) -+ -+#define HARD_REGNO_MODE_OK(REGNO, MODE) \ -+ riscv_hard_regno_mode_ok_p (REGNO, MODE) -+ -+/* Don't allow floating-point modes to be tied, since type punning of -+ single-precision and double-precision is implementation defined. */ -+#define MODES_TIEABLE_P(MODE1, MODE2) \ -+ ((MODE1) == (MODE2) \ -+ || !(GET_MODE_CLASS (MODE1) == MODE_FLOAT \ -+ && GET_MODE_CLASS (MODE2) == MODE_FLOAT)) -+ -+/* Use s0 as the frame pointer if it is so requested. */ -+#define HARD_FRAME_POINTER_REGNUM 8 -+#define STACK_POINTER_REGNUM 2 -+#define THREAD_POINTER_REGNUM 4 -+ -+/* These two registers don't really exist: they get eliminated to either -+ the stack or hard frame pointer. */ -+#define ARG_POINTER_REGNUM 64 -+#define FRAME_POINTER_REGNUM 65 -+ -+/* Register in which static-chain is passed to a function. */ -+#define STATIC_CHAIN_REGNUM (GP_TEMP_FIRST + 2) -+ -+/* Registers used as temporaries in prologue/epilogue code. -+ -+ The prologue registers mustn't conflict with any -+ incoming arguments, the static chain pointer, or the frame pointer. -+ The epilogue temporary mustn't conflict with the return registers, -+ the frame pointer, the EH stack adjustment, or the EH data registers. */ -+ -+#define RISCV_PROLOGUE_TEMP_REGNUM (GP_TEMP_FIRST + 1) -+#define RISCV_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, RISCV_PROLOGUE_TEMP_REGNUM) -+ -+#define MCOUNT_NAME "_mcount" -+ -+#define NO_PROFILE_COUNTERS 1 -+ -+/* Emit rtl for profiling. Output assembler code to FILE -+ to call "_mcount" for profiling a function entry. */ -+#define PROFILE_HOOK(LABEL) \ -+ { \ -+ rtx fun, ra; \ -+ ra = get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); \ -+ fun = gen_rtx_SYMBOL_REF (Pmode, MCOUNT_NAME); \ -+ emit_library_call (fun, LCT_NORMAL, VOIDmode, 1, ra, Pmode); \ -+ } -+ -+/* All the work done in PROFILE_HOOK, but still required. */ -+#define FUNCTION_PROFILER(STREAM, LABELNO) do { } while (0) -+ -+/* Define this macro if it is as good or better to call a constant -+ function address than to call an address kept in a register. */ -+#define NO_FUNCTION_CSE 1 -+ -+/* Define the classes of registers for register constraints in the -+ machine description. Also define ranges of constants. -+ -+ One of the classes must always be named ALL_REGS and include all hard regs. -+ If there is more than one class, another class must be named NO_REGS -+ and contain no registers. -+ -+ The name GENERAL_REGS must be the name of a class (or an alias for -+ another name such as ALL_REGS). This is the class of registers -+ that is allowed by "g" or "r" in a register constraint. -+ Also, registers outside this class are allocated only when -+ instructions express preferences for them. -+ -+ The classes must be numbered in nondecreasing order; that is, -+ a larger-numbered class must never be contained completely -+ in a smaller-numbered class. -+ -+ For any two classes, it is very desirable that there be another -+ class that represents their union. */ -+ -+enum reg_class -+{ -+ NO_REGS, /* no registers in set */ -+ SIBCALL_REGS, /* registers used by indirect sibcalls */ -+ JALR_REGS, /* registers used by indirect calls */ -+ GR_REGS, /* integer registers */ -+ FP_REGS, /* floating-point registers */ -+ FRAME_REGS, /* arg pointer and frame pointer */ -+ ALL_REGS, /* all registers */ -+ LIM_REG_CLASSES /* max value + 1 */ -+}; -+ -+#define N_REG_CLASSES (int) LIM_REG_CLASSES -+ -+#define GENERAL_REGS GR_REGS -+ -+/* An initializer containing the names of the register classes as C -+ string constants. These names are used in writing some of the -+ debugging dumps. */ -+ -+#define REG_CLASS_NAMES \ -+{ \ -+ "NO_REGS", \ -+ "SIBCALL_REGS", \ -+ "JALR_REGS", \ -+ "GR_REGS", \ -+ "FP_REGS", \ -+ "FRAME_REGS", \ -+ "ALL_REGS" \ -+} -+ -+/* An initializer containing the contents of the register classes, -+ as integers which are bit masks. The Nth integer specifies the -+ contents of class N. The way the integer MASK is interpreted is -+ that register R is in the class if `MASK & (1 << R)' is 1. -+ -+ When the machine has more than 32 registers, an integer does not -+ suffice. Then the integers are replaced by sub-initializers, -+ braced groupings containing several integers. Each -+ sub-initializer must be suitable as an initializer for the type -+ `HARD_REG_SET' which is defined in `hard-reg-set.h'. */ -+ -+#define REG_CLASS_CONTENTS \ -+{ \ -+ { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \ -+ { 0xf00000c0, 0x00000000, 0x00000000 }, /* SIBCALL_REGS */ \ -+ { 0xffffffc0, 0x00000000, 0x00000000 }, /* JALR_REGS */ \ -+ { 0xffffffff, 0x00000000, 0x00000000 }, /* GR_REGS */ \ -+ { 0x00000000, 0xffffffff, 0x00000000 }, /* FP_REGS */ \ -+ { 0x00000000, 0x00000000, 0x00000003 }, /* FRAME_REGS */ \ -+ { 0xffffffff, 0xffffffff, 0x00000003 } /* ALL_REGS */ \ -+} -+ -+/* A C expression whose value is a register class containing hard -+ register REGNO. In general there is more that one such class; -+ choose a class which is "minimal", meaning that no smaller class -+ also contains the register. */ -+ -+#define REGNO_REG_CLASS(REGNO) riscv_regno_to_class[ (REGNO) ] -+ -+/* A macro whose definition is the name of the class to which a -+ valid base register must belong. A base register is one used in -+ an address which is the register value plus a displacement. */ -+ -+#define BASE_REG_CLASS GR_REGS -+ -+/* A macro whose definition is the name of the class to which a -+ valid index register must belong. An index register is one used -+ in an address where its value is either multiplied by a scale -+ factor or added to another register (as well as added to a -+ displacement). */ -+ -+#define INDEX_REG_CLASS NO_REGS -+ -+/* We generally want to put call-clobbered registers ahead of -+ call-saved ones. (IRA expects this.) */ -+ -+#define REG_ALLOC_ORDER \ -+{ \ -+ /* Call-clobbered GPRs. */ \ -+ 15, 14, 13, 12, 11, 10, 16, 17, 6, 28, 29, 30, 31, 5, 7, 1, \ -+ /* Call-saved GPRs. */ \ -+ 8, 9, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \ -+ /* GPRs that can never be exposed to the register allocator. */ \ -+ 0, 2, 3, 4, \ -+ /* Call-clobbered FPRs. */ \ -+ 47, 46, 45, 44, 43, 42, 32, 33, 34, 35, 36, 37, 38, 39, 48, 49, \ -+ 60, 61, 62, 63, \ -+ /* Call-saved FPRs. */ \ -+ 40, 41, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, \ -+ /* None of the remaining classes have defined call-saved \ -+ registers. */ \ -+ 64, 65 \ -+} -+ -+/* True if VALUE is a signed 12-bit number. */ -+ -+#define SMALL_OPERAND(VALUE) \ -+ ((unsigned HOST_WIDE_INT) (VALUE) + IMM_REACH/2 < IMM_REACH) -+ -+/* True if VALUE can be loaded into a register using LUI. */ -+ -+#define LUI_OPERAND(VALUE) \ -+ (((VALUE) | ((1UL<<31) - IMM_REACH)) == ((1UL<<31) - IMM_REACH) \ -+ || ((VALUE) | ((1UL<<31) - IMM_REACH)) + IMM_REACH == 0) -+ -+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ -+ reg_classes_intersect_p (FP_REGS, CLASS) -+ -+/* Stack layout; function entry, exit and calling. */ -+ -+#define STACK_GROWS_DOWNWARD 1 -+ -+#define FRAME_GROWS_DOWNWARD 1 -+ -+#define STARTING_FRAME_OFFSET 0 -+ -+#define RETURN_ADDR_RTX riscv_return_addr -+ -+#define ELIMINABLE_REGS \ -+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ -+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ -+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ -+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} \ -+ -+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -+ (OFFSET) = riscv_initial_elimination_offset (FROM, TO) -+ -+/* Allocate stack space for arguments at the beginning of each function. */ -+#define ACCUMULATE_OUTGOING_ARGS 1 -+ -+/* The argument pointer always points to the first argument. */ -+#define FIRST_PARM_OFFSET(FNDECL) 0 -+ -+#define REG_PARM_STACK_SPACE(FNDECL) 0 -+ -+/* Define this if it is the responsibility of the caller to -+ allocate the area reserved for arguments passed in registers. -+ If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect -+ of this macro is to determine whether the space is included in -+ `crtl->outgoing_args_size'. */ -+#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1 -+ -+#define STACK_BOUNDARY 128 -+ -+/* Symbolic macros for the registers used to return integer and floating -+ point values. */ -+ -+#define GP_RETURN GP_ARG_FIRST -+#define FP_RETURN (UNITS_PER_FP_ARG == 0 ? GP_RETURN : FP_ARG_FIRST) -+ -+#define MAX_ARGS_IN_REGISTERS 8 -+ -+/* Symbolic macros for the first/last argument registers. */ -+ -+#define GP_ARG_FIRST (GP_REG_FIRST + 10) -+#define GP_ARG_LAST (GP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1) -+#define GP_TEMP_FIRST (GP_REG_FIRST + 5) -+#define FP_ARG_FIRST (FP_REG_FIRST + 10) -+#define FP_ARG_LAST (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1) -+ -+#define CALLEE_SAVED_REG_NUMBER(REGNO) \ -+ ((REGNO) >= 8 && (REGNO) <= 9 ? (REGNO) - 8 : \ -+ (REGNO) >= 18 && (REGNO) <= 27 ? (REGNO) - 16 : -1) -+ -+#define LIBCALL_VALUE(MODE) \ -+ riscv_function_value (NULL_TREE, NULL_TREE, MODE) -+ -+#define FUNCTION_VALUE(VALTYPE, FUNC) \ -+ riscv_function_value (VALTYPE, FUNC, VOIDmode) -+ -+#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN) -+ -+/* 1 if N is a possible register number for function argument passing. -+ We have no FP argument registers when soft-float. When FP registers -+ are 32 bits, we can't directly reference the odd numbered ones. */ -+ -+/* Accept arguments in a0-a7, and in fa0-fa7 if permitted by the ABI. */ -+#define FUNCTION_ARG_REGNO_P(N) \ -+ (IN_RANGE ((N), GP_ARG_FIRST, GP_ARG_LAST) \ -+ || (UNITS_PER_FP_ARG && IN_RANGE ((N), FP_ARG_FIRST, FP_ARG_LAST))) -+ -+typedef struct { -+ /* Number of integer registers used so far, up to MAX_ARGS_IN_REGISTERS. */ -+ unsigned int num_gprs; -+ -+ /* Number of floating-point registers used so far, likewise. */ -+ unsigned int num_fprs; -+} CUMULATIVE_ARGS; -+ -+/* Initialize a variable CUM of type CUMULATIVE_ARGS -+ for a call to a function whose data type is FNTYPE. -+ For a library call, FNTYPE is 0. */ -+ -+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ -+ memset (&(CUM), 0, sizeof (CUM)) -+ -+#define EPILOGUE_USES(REGNO) ((REGNO) == RETURN_ADDR_REGNUM) -+ -+/* ABI requires 16-byte alignment, even on RV32. */ -+#define RISCV_STACK_ALIGN(LOC) (((LOC) + 15) & -16) -+ -+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, -+ the stack pointer does not matter. The value is tested only in -+ functions that have frame pointers. -+ No definition is equivalent to always zero. */ -+ -+#define EXIT_IGNORE_STACK 1 -+ -+ -+/* Trampolines are a block of code followed by two pointers. */ -+ -+#define TRAMPOLINE_CODE_SIZE 16 -+#define TRAMPOLINE_SIZE \ -+ ((Pmode == SImode) \ -+ ? TRAMPOLINE_CODE_SIZE \ -+ : (TRAMPOLINE_CODE_SIZE + POINTER_SIZE * 2)) -+#define TRAMPOLINE_ALIGNMENT POINTER_SIZE -+ -+/* Addressing modes, and classification of registers for them. */ -+ -+#define REGNO_OK_FOR_INDEX_P(REGNO) 0 -+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \ -+ riscv_regno_mode_ok_for_base_p (REGNO, MODE, 1) -+ -+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx -+ and check its validity for a certain class. -+ We have two alternate definitions for each of them. -+ The usual definition accepts all pseudo regs; the other rejects them all. -+ The symbol REG_OK_STRICT causes the latter definition to be used. -+ -+ Most source files want to accept pseudo regs in the hope that -+ they will get allocated to the class that the insn wants them to be in. -+ Some source files that are used after register allocation -+ need to be strict. */ -+ -+#ifndef REG_OK_STRICT -+#define REG_MODE_OK_FOR_BASE_P(X, MODE) \ -+ riscv_regno_mode_ok_for_base_p (REGNO (X), MODE, 0) -+#else -+#define REG_MODE_OK_FOR_BASE_P(X, MODE) \ -+ riscv_regno_mode_ok_for_base_p (REGNO (X), MODE, 1) -+#endif -+ -+#define REG_OK_FOR_INDEX_P(X) 0 -+ -+/* Maximum number of registers that can appear in a valid memory address. */ -+ -+#define MAX_REGS_PER_ADDRESS 1 -+ -+#define CONSTANT_ADDRESS_P(X) \ -+ (CONSTANT_P (X) && memory_address_p (SImode, X)) -+ -+/* This handles the magic '..CURRENT_FUNCTION' symbol, which means -+ 'the start of the function that this code is output in'. */ -+ -+#define ASM_OUTPUT_LABELREF(FILE,NAME) \ -+ if (strcmp (NAME, "..CURRENT_FUNCTION") == 0) \ -+ asm_fprintf ((FILE), "%U%s", \ -+ XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \ -+ else \ -+ asm_fprintf ((FILE), "%U%s", (NAME)) -+ -+#define JUMP_TABLES_IN_TEXT_SECTION 0 -+#define CASE_VECTOR_MODE SImode -+#define CASE_VECTOR_PC_RELATIVE (riscv_cmodel != CM_MEDLOW) -+ -+/* The load-address macro is used for PC-relative addressing of symbols -+ that bind locally. Don't use it for symbols that should be addressed -+ via the GOT. Also, avoid it for CM_MEDLOW, where LUI addressing -+ currently results in more opportunities for linker relaxation. */ -+#define USE_LOAD_ADDRESS_MACRO(sym) \ -+ (!TARGET_EXPLICIT_RELOCS && \ -+ ((flag_pic \ -+ && ((SYMBOL_REF_P (sym) && SYMBOL_REF_LOCAL_P (sym)) \ -+ || ((GET_CODE (sym) == CONST) \ -+ && SYMBOL_REF_P (XEXP (XEXP (sym, 0),0)) \ -+ && SYMBOL_REF_LOCAL_P (XEXP (XEXP (sym, 0),0))))) \ -+ || riscv_cmodel == CM_MEDANY)) -+ -+/* Define this as 1 if `char' should by default be signed; else as 0. */ -+#define DEFAULT_SIGNED_CHAR 0 -+ -+#define MOVE_MAX UNITS_PER_WORD -+#define MAX_MOVE_MAX 8 -+ -+#define SLOW_BYTE_ACCESS 0 -+ -+#define SHIFT_COUNT_TRUNCATED 1 -+ -+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 -+ -+/* Specify the machine mode that pointers have. -+ After generation of rtl, the compiler makes no further distinction -+ between pointers and any other objects of this machine mode. */ -+ -+#define Pmode word_mode -+ -+/* Give call MEMs SImode since it is the "most permissive" mode -+ for both 32-bit and 64-bit targets. */ -+ -+#define FUNCTION_MODE SImode -+ -+/* A C expression for the cost of a branch instruction. A value of 2 -+ seems to minimize code size. */ -+ -+#define BRANCH_COST(speed_p, predictable_p) \ -+ ((!(speed_p) || (predictable_p)) ? 2 : riscv_branch_cost) -+ -+#define LOGICAL_OP_NON_SHORT_CIRCUIT 0 -+ -+/* Control the assembler format that we output. */ -+ -+/* Output to assembler file text saying following lines -+ may contain character constants, extra white space, comments, etc. */ -+ -+#ifndef ASM_APP_ON -+#define ASM_APP_ON " #APP\n" -+#endif -+ -+/* Output to assembler file text saying following lines -+ no longer contain unusual constructs. */ -+ -+#ifndef ASM_APP_OFF -+#define ASM_APP_OFF " #NO_APP\n" -+#endif -+ -+#define REGISTER_NAMES \ -+{ "zero","ra", "sp", "gp", "tp", "t0", "t1", "t2", \ -+ "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", \ -+ "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", \ -+ "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", \ -+ "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", \ -+ "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", \ -+ "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", \ -+ "fs8", "fs9", "fs10","fs11","ft8", "ft9", "ft10","ft11", \ -+ "arg", "frame", } -+ -+#define ADDITIONAL_REGISTER_NAMES \ -+{ \ -+ { "x0", 0 + GP_REG_FIRST }, \ -+ { "x1", 1 + GP_REG_FIRST }, \ -+ { "x2", 2 + GP_REG_FIRST }, \ -+ { "x3", 3 + GP_REG_FIRST }, \ -+ { "x4", 4 + GP_REG_FIRST }, \ -+ { "x5", 5 + GP_REG_FIRST }, \ -+ { "x6", 6 + GP_REG_FIRST }, \ -+ { "x7", 7 + GP_REG_FIRST }, \ -+ { "x8", 8 + GP_REG_FIRST }, \ -+ { "x9", 9 + GP_REG_FIRST }, \ -+ { "x10", 10 + GP_REG_FIRST }, \ -+ { "x11", 11 + GP_REG_FIRST }, \ -+ { "x12", 12 + GP_REG_FIRST }, \ -+ { "x13", 13 + GP_REG_FIRST }, \ -+ { "x14", 14 + GP_REG_FIRST }, \ -+ { "x15", 15 + GP_REG_FIRST }, \ -+ { "x16", 16 + GP_REG_FIRST }, \ -+ { "x17", 17 + GP_REG_FIRST }, \ -+ { "x18", 18 + GP_REG_FIRST }, \ -+ { "x19", 19 + GP_REG_FIRST }, \ -+ { "x20", 20 + GP_REG_FIRST }, \ -+ { "x21", 21 + GP_REG_FIRST }, \ -+ { "x22", 22 + GP_REG_FIRST }, \ -+ { "x23", 23 + GP_REG_FIRST }, \ -+ { "x24", 24 + GP_REG_FIRST }, \ -+ { "x25", 25 + GP_REG_FIRST }, \ -+ { "x26", 26 + GP_REG_FIRST }, \ -+ { "x27", 27 + GP_REG_FIRST }, \ -+ { "x28", 28 + GP_REG_FIRST }, \ -+ { "x29", 29 + GP_REG_FIRST }, \ -+ { "x30", 30 + GP_REG_FIRST }, \ -+ { "x31", 31 + GP_REG_FIRST }, \ -+ { "f0", 0 + FP_REG_FIRST }, \ -+ { "f1", 1 + FP_REG_FIRST }, \ -+ { "f2", 2 + FP_REG_FIRST }, \ -+ { "f3", 3 + FP_REG_FIRST }, \ -+ { "f4", 4 + FP_REG_FIRST }, \ -+ { "f5", 5 + FP_REG_FIRST }, \ -+ { "f6", 6 + FP_REG_FIRST }, \ -+ { "f7", 7 + FP_REG_FIRST }, \ -+ { "f8", 8 + FP_REG_FIRST }, \ -+ { "f9", 9 + FP_REG_FIRST }, \ -+ { "f10", 10 + FP_REG_FIRST }, \ -+ { "f11", 11 + FP_REG_FIRST }, \ -+ { "f12", 12 + FP_REG_FIRST }, \ -+ { "f13", 13 + FP_REG_FIRST }, \ -+ { "f14", 14 + FP_REG_FIRST }, \ -+ { "f15", 15 + FP_REG_FIRST }, \ -+ { "f16", 16 + FP_REG_FIRST }, \ -+ { "f17", 17 + FP_REG_FIRST }, \ -+ { "f18", 18 + FP_REG_FIRST }, \ -+ { "f19", 19 + FP_REG_FIRST }, \ -+ { "f20", 20 + FP_REG_FIRST }, \ -+ { "f21", 21 + FP_REG_FIRST }, \ -+ { "f22", 22 + FP_REG_FIRST }, \ -+ { "f23", 23 + FP_REG_FIRST }, \ -+ { "f24", 24 + FP_REG_FIRST }, \ -+ { "f25", 25 + FP_REG_FIRST }, \ -+ { "f26", 26 + FP_REG_FIRST }, \ -+ { "f27", 27 + FP_REG_FIRST }, \ -+ { "f28", 28 + FP_REG_FIRST }, \ -+ { "f29", 29 + FP_REG_FIRST }, \ -+ { "f30", 30 + FP_REG_FIRST }, \ -+ { "f31", 31 + FP_REG_FIRST }, \ -+} -+ -+/* Globalizing directive for a label. */ -+#define GLOBAL_ASM_OP "\t.globl\t" -+ -+/* This is how to store into the string LABEL -+ the symbol_ref name of an internal numbered label where -+ PREFIX is the class of label and NUM is the number within the class. -+ This is suitable for output with `assemble_name'. */ -+ -+#undef ASM_GENERATE_INTERNAL_LABEL -+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ -+ sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long)(NUM)) -+ -+/* This is how to output an element of a case-vector that is absolute. */ -+ -+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ -+ fprintf (STREAM, "\t.word\t%sL%d\n", LOCAL_LABEL_PREFIX, VALUE) -+ -+/* This is how to output an element of a PIC case-vector. */ -+ -+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ -+ fprintf (STREAM, "\t.word\t%sL%d-%sL%d\n", \ -+ LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL) -+ -+/* This is how to output an assembler line -+ that says to advance the location counter -+ to a multiple of 2**LOG bytes. */ -+ -+#define ASM_OUTPUT_ALIGN(STREAM,LOG) \ -+ fprintf (STREAM, "\t.align\t%d\n", (LOG)) -+ -+/* Define the strings to put out for each section in the object file. */ -+#define TEXT_SECTION_ASM_OP "\t.text" /* instructions */ -+#define DATA_SECTION_ASM_OP "\t.data" /* large data */ -+#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rodata" -+#define BSS_SECTION_ASM_OP "\t.bss" -+#define SBSS_SECTION_ASM_OP "\t.section\t.sbss,\"aw\",@nobits" -+#define SDATA_SECTION_ASM_OP "\t.section\t.sdata,\"aw\",@progbits" -+ -+#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \ -+do \ -+ { \ -+ fprintf (STREAM, "\taddi\t%s,%s,-8\n\t%s\t%s,0(%s)\n", \ -+ reg_names[STACK_POINTER_REGNUM], \ -+ reg_names[STACK_POINTER_REGNUM], \ -+ TARGET_64BIT ? "sd" : "sw", \ -+ reg_names[REGNO], \ -+ reg_names[STACK_POINTER_REGNUM]); \ -+ } \ -+while (0) -+ -+#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \ -+do \ -+ { \ -+ fprintf (STREAM, "\t%s\t%s,0(%s)\n\taddi\t%s,%s,8\n", \ -+ TARGET_64BIT ? "ld" : "lw", \ -+ reg_names[REGNO], \ -+ reg_names[STACK_POINTER_REGNUM], \ -+ reg_names[STACK_POINTER_REGNUM], \ -+ reg_names[STACK_POINTER_REGNUM]); \ -+ } \ -+while (0) -+ -+#define ASM_COMMENT_START "#" -+ -+#undef SIZE_TYPE -+#define SIZE_TYPE (POINTER_SIZE == 64 ? "long unsigned int" : "unsigned int") -+ -+#undef PTRDIFF_TYPE -+#define PTRDIFF_TYPE (POINTER_SIZE == 64 ? "long int" : "int") -+ -+/* If a memory-to-memory move would take MOVE_RATIO or more simple -+ move-instruction pairs, we will do a movmem or libcall instead. */ -+ -+#define MOVE_RATIO(speed) (CLEAR_RATIO (speed) / 2) -+ -+/* For CLEAR_RATIO, when optimizing for size, give a better estimate -+ of the length of a memset call, but use the default otherwise. */ -+ -+#define CLEAR_RATIO(speed) ((speed) ? 16 : 6) -+ -+/* This is similar to CLEAR_RATIO, but for a non-zero constant, so when -+ optimizing for size adjust the ratio to account for the overhead of -+ loading the constant and replicating it across the word. */ -+ -+#define SET_RATIO(speed) (CLEAR_RATIO (speed) - ((speed) ? 0 : 2)) -+ -+#ifndef USED_FOR_TARGET -+extern const enum reg_class riscv_regno_to_class[]; -+extern bool riscv_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; -+#endif -+ -+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \ -+ (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4) -+ -+#define XLEN_SPEC \ -+ "%{march=rv32*:32}" \ -+ "%{march=rv64*:64}" \ -+ -+#define ABI_SPEC \ -+ "%{mabi=ilp32:ilp32}" \ -+ "%{mabi=ilp32f:ilp32f}" \ -+ "%{mabi=ilp32d:ilp32d}" \ -+ "%{mabi=lp64:lp64}" \ -+ "%{mabi=lp64f:lp64f}" \ -+ "%{mabi=lp64d:lp64d}" \ -+ -+#define STARTFILE_PREFIX_SPEC \ -+ "/lib" XLEN_SPEC "/" ABI_SPEC "/ " \ -+ "/usr/lib" XLEN_SPEC "/" ABI_SPEC "/ " \ -+ "/lib/ " \ -+ "/usr/lib/ " -+ -+/* ISA constants needed for code generation. */ -+#define OPCODE_LW 0x2003 -+#define OPCODE_LD 0x3003 -+#define OPCODE_AUIPC 0x17 -+#define OPCODE_JALR 0x67 -+#define OPCODE_LUI 0x37 -+#define OPCODE_ADDI 0x13 -+#define SHIFT_RD 7 -+#define SHIFT_RS1 15 -+#define SHIFT_IMM 20 -+#define IMM_BITS 12 -+ -+#define IMM_REACH (1LL << IMM_BITS) -+#define CONST_HIGH_PART(VALUE) (((VALUE) + (IMM_REACH/2)) & ~(IMM_REACH-1)) -+#define CONST_LOW_PART(VALUE) ((VALUE) - CONST_HIGH_PART (VALUE)) -+ -+#endif /* ! GCC_RISCV_H */ -diff --git original-gcc/gcc/config/riscv/riscv.md gcc-6.3.0/gcc/config/riscv/riscv.md -new file mode 100644 -index 00000000000..4cbb2431335 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/riscv.md -@@ -0,0 +1,2079 @@ -+;; Machine description for RISC-V for GNU compiler. -+;; Copyright (C) 2011-2017 Free Software Foundation, Inc. -+;; Contributed by Andrew Waterman (andrew@sifive.com). -+;; Based on MIPS target for GNU compiler. -+ -+;; 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_c_enum "unspec" [ -+ ;; Override return address for exception handling. -+ UNSPEC_EH_RETURN -+ -+ ;; Symbolic accesses. The order of this list must match that of -+ ;; enum riscv_symbol_type in riscv-protos.h. -+ UNSPEC_ADDRESS_FIRST -+ UNSPEC_PCREL -+ UNSPEC_LOAD_GOT -+ UNSPEC_TLS -+ UNSPEC_TLS_LE -+ UNSPEC_TLS_IE -+ UNSPEC_TLS_GD -+ -+ ;; High part of PC-relative address. -+ UNSPEC_AUIPC -+ -+ ;; Floating-point unspecs. -+ UNSPEC_FLT_QUIET -+ UNSPEC_FLE_QUIET -+ UNSPEC_COPYSIGN -+ UNSPEC_LRINT -+ UNSPEC_LROUND -+ -+ ;; Stack tie -+ UNSPEC_TIE -+]) -+ -+(define_c_enum "unspecv" [ -+ ;; Register save and restore. -+ UNSPECV_GPR_SAVE -+ UNSPECV_GPR_RESTORE -+ -+ ;; Floating-point unspecs. -+ UNSPECV_FRFLAGS -+ UNSPECV_FSFLAGS -+ -+ ;; Blockage and synchronization. -+ UNSPECV_BLOCKAGE -+ UNSPECV_FENCE -+ UNSPECV_FENCE_I -+]) -+ -+(define_constants -+ [(RETURN_ADDR_REGNUM 1) -+ (T0_REGNUM 5) -+ (T1_REGNUM 6) -+ (S0_REGNUM 8) -+ (S1_REGNUM 9) -+ (S2_REGNUM 18) -+]) -+ -+(include "predicates.md") -+(include "constraints.md") -+ -+;; .................... -+;; -+;; Attributes -+;; -+;; .................... -+ -+(define_attr "got" "unset,xgot_high,load" -+ (const_string "unset")) -+ -+;; Classification of moves, extensions and truncations. Most values -+;; are as for "type" (see below) but there are also the following -+;; move-specific values: -+;; -+;; andi a single ANDI instruction -+;; shift_shift a shift left followed by a shift right -+;; -+;; This attribute is used to determine the instruction's length and -+;; scheduling type. For doubleword moves, the attribute always describes -+;; the split instructions; in some cases, it is more appropriate for the -+;; scheduling type to be "multi" instead. -+(define_attr "move_type" -+ "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove, -+ const,logical,arith,andi,shift_shift" -+ (const_string "unknown")) -+ -+;; Main data type used by the insn -+(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF" -+ (const_string "unknown")) -+ -+;; True if the main data type is twice the size of a word. -+(define_attr "dword_mode" "no,yes" -+ (cond [(and (eq_attr "mode" "DI,DF") -+ (eq (symbol_ref "TARGET_64BIT") (const_int 0))) -+ (const_string "yes") -+ -+ (and (eq_attr "mode" "TI,TF") -+ (ne (symbol_ref "TARGET_64BIT") (const_int 0))) -+ (const_string "yes")] -+ (const_string "no"))) -+ -+;; Classification of each insn. -+;; branch conditional branch -+;; jump unconditional jump -+;; call unconditional call -+;; load load instruction(s) -+;; fpload floating point load -+;; store store instruction(s) -+;; fpstore floating point store -+;; mtc transfer to coprocessor -+;; mfc transfer from coprocessor -+;; const load constant -+;; arith integer arithmetic instructions -+;; logical integer logical instructions -+;; shift integer shift instructions -+;; slt set less than instructions -+;; imul integer multiply -+;; idiv integer divide -+;; move integer register move (addi rd, rs1, 0) -+;; fmove floating point register move -+;; fadd floating point add/subtract -+;; fmul floating point multiply -+;; fmadd floating point multiply-add -+;; fdiv floating point divide -+;; fcmp floating point compare -+;; fcvt floating point convert -+;; fsqrt floating point square root -+;; multi multiword sequence (or user asm statements) -+;; nop no operation -+;; ghost an instruction that produces no real code -+(define_attr "type" -+ "unknown,branch,jump,call,load,fpload,store,fpstore, -+ mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul, -+ fmadd,fdiv,fcmp,fcvt,fsqrt,multi,nop,ghost" -+ (cond [(eq_attr "got" "load") (const_string "load") -+ -+ ;; If a doubleword move uses these expensive instructions, -+ ;; it is usually better to schedule them in the same way -+ ;; as the singleword form, rather than as "multi". -+ (eq_attr "move_type" "load") (const_string "load") -+ (eq_attr "move_type" "fpload") (const_string "fpload") -+ (eq_attr "move_type" "store") (const_string "store") -+ (eq_attr "move_type" "fpstore") (const_string "fpstore") -+ (eq_attr "move_type" "mtc") (const_string "mtc") -+ (eq_attr "move_type" "mfc") (const_string "mfc") -+ -+ ;; These types of move are always single insns. -+ (eq_attr "move_type" "fmove") (const_string "fmove") -+ (eq_attr "move_type" "arith") (const_string "arith") -+ (eq_attr "move_type" "logical") (const_string "logical") -+ (eq_attr "move_type" "andi") (const_string "logical") -+ -+ ;; These types of move are always split. -+ (eq_attr "move_type" "shift_shift") -+ (const_string "multi") -+ -+ ;; These types of move are split for doubleword modes only. -+ (and (eq_attr "move_type" "move,const") -+ (eq_attr "dword_mode" "yes")) -+ (const_string "multi") -+ (eq_attr "move_type" "move") (const_string "move") -+ (eq_attr "move_type" "const") (const_string "const")] -+ (const_string "unknown"))) -+ -+;; Length of instruction in bytes. -+(define_attr "length" "" -+ (cond [ -+ ;; Branches further than +/- 4 KiB require two instructions. -+ (eq_attr "type" "branch") -+ (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 4088)) -+ (le (minus (pc) (match_dup 0)) (const_int 4092))) -+ (const_int 4) -+ (const_int 8)) -+ -+ ;; Conservatively assume calls take two instructions (AUIPC + JALR). -+ ;; The linker will opportunistically relax the sequence to JAL. -+ (eq_attr "type" "call") (const_int 8) -+ -+ ;; "Ghost" instructions occupy no space. -+ (eq_attr "type" "ghost") (const_int 0) -+ -+ (eq_attr "got" "load") (const_int 8) -+ -+ (eq_attr "type" "fcmp") (const_int 8) -+ -+ ;; SHIFT_SHIFTs are decomposed into two separate instructions. -+ (eq_attr "move_type" "shift_shift") -+ (const_int 8) -+ -+ ;; Check for doubleword moves that are decomposed into two -+ ;; instructions. -+ (and (eq_attr "move_type" "mtc,mfc,move") -+ (eq_attr "dword_mode" "yes")) -+ (const_int 8) -+ -+ ;; Doubleword CONST{,N} moves are split into two word -+ ;; CONST{,N} moves. -+ (and (eq_attr "move_type" "const") -+ (eq_attr "dword_mode" "yes")) -+ (symbol_ref "riscv_split_const_insns (operands[1]) * 4") -+ -+ ;; Otherwise, constants, loads and stores are handled by external -+ ;; routines. -+ (eq_attr "move_type" "load,fpload") -+ (symbol_ref "riscv_load_store_insns (operands[1], insn) * 4") -+ (eq_attr "move_type" "store,fpstore") -+ (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4") -+ ] (const_int 4))) -+ -+;; Is copying of this instruction disallowed? -+(define_attr "cannot_copy" "no,yes" (const_string "no")) -+ -+;; Describe a user's asm statement. -+(define_asm_attributes -+ [(set_attr "type" "multi")]) -+ -+;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated -+;; from the same template. -+(define_mode_iterator GPR [SI (DI "TARGET_64BIT")]) -+ -+;; This mode iterator allows :P to be used for patterns that operate on -+;; pointer-sized quantities. Exactly one of the two alternatives will match. -+(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) -+ -+;; Likewise, but for XLEN-sized quantities. -+(define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")]) -+ -+;; Branches operate on XLEN-sized quantities, but for RV64 we accept -+;; QImode values so we can force zero-extension. -+(define_mode_iterator BR [(QI "TARGET_64BIT") SI (DI "TARGET_64BIT")]) -+ -+;; 32-bit moves for which we provide move patterns. -+(define_mode_iterator MOVE32 [SI]) -+ -+;; 64-bit modes for which we provide move patterns. -+(define_mode_iterator MOVE64 [DI DF]) -+ -+;; Iterator for sub-32-bit integer modes. -+(define_mode_iterator SHORT [QI HI]) -+ -+;; Iterator for HImode constant generation. -+(define_mode_iterator HISI [HI SI]) -+ -+;; Iterator for QImode extension patterns. -+(define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")]) -+ -+;; Iterator for hardware integer modes narrower than XLEN. -+(define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")]) -+ -+;; Iterator for hardware-supported integer modes. -+(define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")]) -+ -+;; Iterator for hardware-supported floating-point modes. -+(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT") -+ (DF "TARGET_DOUBLE_FLOAT")]) -+ -+;; This attribute gives the length suffix for a sign- or zero-extension -+;; instruction. -+(define_mode_attr size [(QI "b") (HI "h")]) -+ -+;; Mode attributes for loads. -+(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")]) -+ -+;; Instruction names for stores. -+(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")]) -+ -+;; This attribute gives the best constraint to use for registers of -+;; a given mode. -+(define_mode_attr reg [(SI "d") (DI "d") (CC "d")]) -+ -+;; This attribute gives the format suffix for floating-point operations. -+(define_mode_attr fmt [(SF "s") (DF "d")]) -+ -+;; This attribute gives the integer suffix for floating-point conversions. -+(define_mode_attr ifmt [(SI "w") (DI "l")]) -+ -+;; This attribute gives the format suffix for atomic memory operations. -+(define_mode_attr amo [(SI "w") (DI "d")]) -+ -+;; This attribute gives the upper-case mode name for one unit of a -+;; floating-point mode. -+(define_mode_attr UNITMODE [(SF "SF") (DF "DF")]) -+ -+;; This attribute gives the integer mode that has half the size of -+;; the controlling mode. -+(define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")]) -+ -+;; Iterator and attributes for floating-point rounding instructions. -+(define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND]) -+(define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")]) -+(define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")]) -+ -+;; Iterator and attributes for quiet comparisons. -+(define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET]) -+(define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")]) -+ -+;; This code iterator allows signed and unsigned widening multiplications -+;; to use the same template. -+(define_code_iterator any_extend [sign_extend zero_extend]) -+ -+;; This code iterator allows the two right shift instructions to be -+;; generated from the same template. -+(define_code_iterator any_shiftrt [ashiftrt lshiftrt]) -+ -+;; This code iterator allows the three shift instructions to be generated -+;; from the same template. -+(define_code_iterator any_shift [ashift ashiftrt lshiftrt]) -+ -+;; This code iterator allows the three bitwise instructions to be generated -+;; from the same template. -+(define_code_iterator any_bitwise [and ior xor]) -+ -+;; This code iterator allows unsigned and signed division to be generated -+;; from the same template. -+(define_code_iterator any_div [div udiv mod umod]) -+ -+;; This code iterator allows unsigned and signed modulus to be generated -+;; from the same template. -+(define_code_iterator any_mod [mod umod]) -+ -+;; These code iterators allow the signed and unsigned scc operations to use -+;; the same template. -+(define_code_iterator any_gt [gt gtu]) -+(define_code_iterator any_ge [ge geu]) -+(define_code_iterator any_lt [lt ltu]) -+(define_code_iterator any_le [le leu]) -+ -+;; expands to an empty string when doing a signed operation and -+;; "u" when doing an unsigned operation. -+(define_code_attr u [(sign_extend "") (zero_extend "u") -+ (gt "") (gtu "u") -+ (ge "") (geu "u") -+ (lt "") (ltu "u") -+ (le "") (leu "u")]) -+ -+;; is like , but the signed form expands to "s" rather than "". -+(define_code_attr su [(sign_extend "s") (zero_extend "u")]) -+ -+;; expands to the name of the optab for a particular code. -+(define_code_attr optab [(ashift "ashl") -+ (ashiftrt "ashr") -+ (lshiftrt "lshr") -+ (div "div") -+ (mod "mod") -+ (udiv "udiv") -+ (umod "umod") -+ (ge "ge") -+ (le "le") -+ (gt "gt") -+ (lt "lt") -+ (ior "ior") -+ (xor "xor") -+ (and "and") -+ (plus "add") -+ (minus "sub")]) -+ -+;; expands to the name of the insn that implements a particular code. -+(define_code_attr insn [(ashift "sll") -+ (ashiftrt "sra") -+ (lshiftrt "srl") -+ (div "div") -+ (mod "rem") -+ (udiv "divu") -+ (umod "remu") -+ (ior "or") -+ (xor "xor") -+ (and "and") -+ (plus "add") -+ (minus "sub")]) -+ -+;; Ghost instructions produce no real code and introduce no hazards. -+;; They exist purely to express an effect on dataflow. -+(define_insn_reservation "ghost" 0 -+ (eq_attr "type" "ghost") -+ "nothing") -+ -+;; -+;; .................... -+;; -+;; ADDITION -+;; -+;; .................... -+;; -+ -+(define_insn "add3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (plus:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fadd.\t%0,%1,%2" -+ [(set_attr "type" "fadd") -+ (set_attr "mode" "")]) -+ -+(define_insn "addsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r,r") -+ (plus:SI (match_operand:SI 1 "register_operand" "r,r") -+ (match_operand:SI 2 "arith_operand" "r,I")))] -+ "" -+ { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; } -+ [(set_attr "type" "arith") -+ (set_attr "mode" "SI")]) -+ -+(define_insn "adddi3" -+ [(set (match_operand:DI 0 "register_operand" "=r,r") -+ (plus:DI (match_operand:DI 1 "register_operand" "r,r") -+ (match_operand:DI 2 "arith_operand" "r,I")))] -+ "TARGET_64BIT" -+ "add\t%0,%1,%2" -+ [(set_attr "type" "arith") -+ (set_attr "mode" "DI")]) -+ -+(define_insn "*addsi3_extended" -+ [(set (match_operand:DI 0 "register_operand" "=r,r") -+ (sign_extend:DI -+ (plus:SI (match_operand:SI 1 "register_operand" "r,r") -+ (match_operand:SI 2 "arith_operand" "r,I"))))] -+ "TARGET_64BIT" -+ "addw\t%0,%1,%2" -+ [(set_attr "type" "arith") -+ (set_attr "mode" "SI")]) -+ -+(define_insn "*addsi3_extended2" -+ [(set (match_operand:DI 0 "register_operand" "=r,r") -+ (sign_extend:DI -+ (subreg:SI (plus:DI (match_operand:DI 1 "register_operand" "r,r") -+ (match_operand:DI 2 "arith_operand" "r,I")) -+ 0)))] -+ "TARGET_64BIT" -+ "addw\t%0,%1,%2" -+ [(set_attr "type" "arith") -+ (set_attr "mode" "SI")]) -+ -+;; -+;; .................... -+;; -+;; SUBTRACTION -+;; -+;; .................... -+;; -+ -+(define_insn "sub3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (minus:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fsub.\t%0,%1,%2" -+ [(set_attr "type" "fadd") -+ (set_attr "mode" "")]) -+ -+(define_insn "subdi3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (minus:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") -+ (match_operand:DI 2 "register_operand" "r")))] -+ "TARGET_64BIT" -+ "sub\t%0,%z1,%2" -+ [(set_attr "type" "arith") -+ (set_attr "mode" "DI")]) -+ -+(define_insn "subsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") -+ (match_operand:SI 2 "register_operand" "r")))] -+ "" -+ { return TARGET_64BIT ? "subw\t%0,%z1,%2" : "sub\t%0,%z1,%2"; } -+ [(set_attr "type" "arith") -+ (set_attr "mode" "SI")]) -+ -+(define_insn "*subsi3_extended" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (sign_extend:DI -+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") -+ (match_operand:SI 2 "register_operand" "r"))))] -+ "TARGET_64BIT" -+ "subw\t%0,%z1,%2" -+ [(set_attr "type" "arith") -+ (set_attr "mode" "SI")]) -+ -+(define_insn "*subsi3_extended2" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (sign_extend:DI -+ (subreg:SI (minus:DI (match_operand:DI 1 "reg_or_0_operand" "r") -+ (match_operand:DI 2 "register_operand" "r")) -+ 0)))] -+ "TARGET_64BIT" -+ "subw\t%0,%z1,%2" -+ [(set_attr "type" "arith") -+ (set_attr "mode" "SI")]) -+ -+;; -+;; .................... -+;; -+;; MULTIPLICATION -+;; -+;; .................... -+;; -+ -+(define_insn "mul3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fmul.\t%0,%1,%2" -+ [(set_attr "type" "fmul") -+ (set_attr "mode" "")]) -+ -+(define_insn "mulsi3" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (mult:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")))] -+ "TARGET_MUL" -+ { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; } -+ [(set_attr "type" "imul") -+ (set_attr "mode" "SI")]) -+ -+(define_insn "muldi3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (mult:DI (match_operand:DI 1 "register_operand" "r") -+ (match_operand:DI 2 "register_operand" "r")))] -+ "TARGET_MUL && TARGET_64BIT" -+ "mul\t%0,%1,%2" -+ [(set_attr "type" "imul") -+ (set_attr "mode" "DI")]) -+ -+(define_insn "*mulsi3_extended" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (sign_extend:DI -+ (mult:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r"))))] -+ "TARGET_MUL && TARGET_64BIT" -+ "mulw\t%0,%1,%2" -+ [(set_attr "type" "imul") -+ (set_attr "mode" "SI")]) -+ -+(define_insn "*mulsi3_extended2" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (sign_extend:DI -+ (subreg:SI (mult:DI (match_operand:DI 1 "register_operand" "r") -+ (match_operand:DI 2 "register_operand" "r")) -+ 0)))] -+ "TARGET_MUL && TARGET_64BIT" -+ "mulw\t%0,%1,%2" -+ [(set_attr "type" "imul") -+ (set_attr "mode" "SI")]) -+ -+;; -+;; ........................ -+;; -+;; MULTIPLICATION HIGH-PART -+;; -+;; ........................ -+;; -+ -+ -+(define_expand "mulditi3" -+ [(set (match_operand:TI 0 "register_operand") -+ (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand")) -+ (any_extend:TI (match_operand:DI 2 "register_operand"))))] -+ "TARGET_MUL && TARGET_64BIT" -+{ -+ rtx low = gen_reg_rtx (DImode); -+ emit_insn (gen_muldi3 (low, operands[1], operands[2])); -+ -+ rtx high = gen_reg_rtx (DImode); -+ emit_insn (gen_muldi3_highpart (high, operands[1], operands[2])); -+ -+ emit_move_insn (gen_lowpart (DImode, operands[0]), low); -+ emit_move_insn (gen_highpart (DImode, operands[0]), high); -+ DONE; -+}) -+ -+(define_insn "muldi3_highpart" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (truncate:DI -+ (lshiftrt:TI -+ (mult:TI (any_extend:TI -+ (match_operand:DI 1 "register_operand" "r")) -+ (any_extend:TI -+ (match_operand:DI 2 "register_operand" "r"))) -+ (const_int 64))))] -+ "TARGET_MUL && TARGET_64BIT" -+ "mulh\t%0,%1,%2" -+ [(set_attr "type" "imul") -+ (set_attr "mode" "DI")]) -+ -+(define_expand "usmulditi3" -+ [(set (match_operand:TI 0 "register_operand") -+ (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand")) -+ (sign_extend:TI (match_operand:DI 2 "register_operand"))))] -+ "TARGET_MUL && TARGET_64BIT" -+{ -+ rtx low = gen_reg_rtx (DImode); -+ emit_insn (gen_muldi3 (low, operands[1], operands[2])); -+ -+ rtx high = gen_reg_rtx (DImode); -+ emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2])); -+ -+ emit_move_insn (gen_lowpart (DImode, operands[0]), low); -+ emit_move_insn (gen_highpart (DImode, operands[0]), high); -+ DONE; -+}) -+ -+(define_insn "usmuldi3_highpart" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (truncate:DI -+ (lshiftrt:TI -+ (mult:TI (zero_extend:TI -+ (match_operand:DI 1 "register_operand" "r")) -+ (sign_extend:TI -+ (match_operand:DI 2 "register_operand" "r"))) -+ (const_int 64))))] -+ "TARGET_MUL && TARGET_64BIT" -+ "mulhsu\t%0,%2,%1" -+ [(set_attr "type" "imul") -+ (set_attr "mode" "DI")]) -+ -+(define_expand "mulsidi3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (mult:DI (any_extend:DI -+ (match_operand:SI 1 "register_operand" "r")) -+ (any_extend:DI -+ (match_operand:SI 2 "register_operand" "r"))))] -+ "TARGET_MUL && !TARGET_64BIT" -+{ -+ rtx temp = gen_reg_rtx (SImode); -+ emit_insn (gen_mulsi3 (temp, operands[1], operands[2])); -+ emit_insn (gen_mulsi3_highpart (riscv_subword (operands[0], true), -+ operands[1], operands[2])); -+ emit_insn (gen_movsi (riscv_subword (operands[0], false), temp)); -+ DONE; -+}) -+ -+(define_insn "mulsi3_highpart" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (lshiftrt:DI -+ (mult:DI (any_extend:DI -+ (match_operand:SI 1 "register_operand" "r")) -+ (any_extend:DI -+ (match_operand:SI 2 "register_operand" "r"))) -+ (const_int 32))))] -+ "TARGET_MUL && !TARGET_64BIT" -+ "mulh\t%0,%1,%2" -+ [(set_attr "type" "imul") -+ (set_attr "mode" "SI")]) -+ -+ -+(define_expand "usmulsidi3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (mult:DI (zero_extend:DI -+ (match_operand:SI 1 "register_operand" "r")) -+ (sign_extend:DI -+ (match_operand:SI 2 "register_operand" "r"))))] -+ "TARGET_MUL && !TARGET_64BIT" -+{ -+ rtx temp = gen_reg_rtx (SImode); -+ emit_insn (gen_mulsi3 (temp, operands[1], operands[2])); -+ emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true), -+ operands[1], operands[2])); -+ emit_insn (gen_movsi (riscv_subword (operands[0], false), temp)); -+ DONE; -+}) -+ -+(define_insn "usmulsi3_highpart" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (truncate:SI -+ (lshiftrt:DI -+ (mult:DI (zero_extend:DI -+ (match_operand:SI 1 "register_operand" "r")) -+ (sign_extend:DI -+ (match_operand:SI 2 "register_operand" "r"))) -+ (const_int 32))))] -+ "TARGET_MUL && !TARGET_64BIT" -+ "mulhsu\t%0,%2,%1" -+ [(set_attr "type" "imul") -+ (set_attr "mode" "SI")]) -+ -+;; -+;; .................... -+;; -+;; DIVISION and REMAINDER -+;; -+;; .................... -+;; -+ -+(define_insn "si3" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (any_div:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r")))] -+ "TARGET_DIV" -+ { return TARGET_64BIT ? "w\t%0,%1,%2" : "\t%0,%1,%2"; } -+ [(set_attr "type" "idiv") -+ (set_attr "mode" "SI")]) -+ -+(define_insn "di3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (any_div:DI (match_operand:DI 1 "register_operand" "r") -+ (match_operand:DI 2 "register_operand" "r")))] -+ "TARGET_DIV && TARGET_64BIT" -+ "\t%0,%1,%2" -+ [(set_attr "type" "idiv") -+ (set_attr "mode" "DI")]) -+ -+(define_insn "*si3_extended" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (sign_extend:DI -+ (any_div:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "register_operand" "r"))))] -+ "TARGET_DIV && TARGET_64BIT" -+ "w\t%0,%1,%2" -+ [(set_attr "type" "idiv") -+ (set_attr "mode" "DI")]) -+ -+(define_insn "div3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (div:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT && TARGET_FDIV" -+ "fdiv.\t%0,%1,%2" -+ [(set_attr "type" "fdiv") -+ (set_attr "mode" "")]) -+ -+;; -+;; .................... -+;; -+;; SQUARE ROOT -+;; -+;; .................... -+ -+(define_insn "sqrt2" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT && TARGET_FDIV" -+{ -+ return "fsqrt.\t%0,%1"; -+} -+ [(set_attr "type" "fsqrt") -+ (set_attr "mode" "")]) -+ -+;; Floating point multiply accumulate instructions. -+ -+;; a * b + c -+(define_insn "fma4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (fma:ANYF -+ (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f") -+ (match_operand:ANYF 3 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fmadd.\t%0,%1,%2,%3" -+ [(set_attr "type" "fmadd") -+ (set_attr "mode" "")]) -+ -+;; a * b - c -+(define_insn "fms4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (fma:ANYF -+ (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f") -+ (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))] -+ "TARGET_HARD_FLOAT" -+ "fmsub.\t%0,%1,%2,%3" -+ [(set_attr "type" "fmadd") -+ (set_attr "mode" "")]) -+ -+;; -a * b - c -+(define_insn "fnms4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (fma:ANYF -+ (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) -+ (match_operand:ANYF 2 "register_operand" "f") -+ (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))] -+ "TARGET_HARD_FLOAT" -+ "fnmadd.\t%0,%1,%2,%3" -+ [(set_attr "type" "fmadd") -+ (set_attr "mode" "")]) -+ -+;; -a * b + c -+(define_insn "fnma4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (fma:ANYF -+ (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) -+ (match_operand:ANYF 2 "register_operand" "f") -+ (match_operand:ANYF 3 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fnmsub.\t%0,%1,%2,%3" -+ [(set_attr "type" "fmadd") -+ (set_attr "mode" "")]) -+ -+;; -(-a * b - c), modulo signed zeros -+(define_insn "*fma4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (neg:ANYF -+ (fma:ANYF -+ (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) -+ (match_operand:ANYF 2 "register_operand" "f") -+ (neg:ANYF (match_operand:ANYF 3 "register_operand" "f")))))] -+ "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (mode)" -+ "fmadd.\t%0,%1,%2,%3" -+ [(set_attr "type" "fmadd") -+ (set_attr "mode" "")]) -+ -+;; -(-a * b + c), modulo signed zeros -+(define_insn "*fms4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (neg:ANYF -+ (fma:ANYF -+ (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) -+ (match_operand:ANYF 2 "register_operand" "f") -+ (match_operand:ANYF 3 "register_operand" "f"))))] -+ "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (mode)" -+ "fmsub.\t%0,%1,%2,%3" -+ [(set_attr "type" "fmadd") -+ (set_attr "mode" "")]) -+ -+;; -(a * b + c), modulo signed zeros -+(define_insn "*fnms4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (neg:ANYF -+ (fma:ANYF -+ (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f") -+ (match_operand:ANYF 3 "register_operand" "f"))))] -+ "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (mode)" -+ "fnmadd.\t%0,%1,%2,%3" -+ [(set_attr "type" "fmadd") -+ (set_attr "mode" "")]) -+ -+;; -(a * b - c), modulo signed zeros -+(define_insn "*fnma4" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (neg:ANYF -+ (fma:ANYF -+ (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f") -+ (neg:ANYF (match_operand:ANYF 3 "register_operand" "f")))))] -+ "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (mode)" -+ "fnmsub.\t%0,%1,%2,%3" -+ [(set_attr "type" "fmadd") -+ (set_attr "mode" "")]) -+ -+;; -+;; .................... -+;; -+;; SIGN INJECTION -+;; -+;; .................... -+ -+(define_insn "abs2" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fabs.\t%0,%1" -+ [(set_attr "type" "fmove") -+ (set_attr "mode" "")]) -+ -+(define_insn "copysign3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")] -+ UNSPEC_COPYSIGN))] -+ "TARGET_HARD_FLOAT" -+ "fsgnj.\t%0,%1,%2" -+ [(set_attr "type" "fmove") -+ (set_attr "mode" "")]) -+ -+(define_insn "neg2" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fneg.\t%0,%1" -+ [(set_attr "type" "fmove") -+ (set_attr "mode" "")]) -+ -+;; -+;; .................... -+;; -+;; MIN/MAX -+;; -+;; .................... -+ -+(define_insn "smin3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (smin:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fmin.\t%0,%1,%2" -+ [(set_attr "type" "fmove") -+ (set_attr "mode" "")]) -+ -+(define_insn "smax3" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (smax:ANYF (match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fmax.\t%0,%1,%2" -+ [(set_attr "type" "fmove") -+ (set_attr "mode" "")]) -+ -+;; -+;; .................... -+;; -+;; LOGICAL -+;; -+;; .................... -+;; -+ -+;; For RV64, we don't expose the SImode operations to the rtl expanders, -+;; but SImode versions exist for combine. -+ -+(define_insn "3" -+ [(set (match_operand:X 0 "register_operand" "=r,r") -+ (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r") -+ (match_operand:X 2 "arith_operand" "r,I")))] -+ "" -+ "\t%0,%1,%2" -+ [(set_attr "type" "logical") -+ (set_attr "mode" "")]) -+ -+(define_insn "*si3_internal" -+ [(set (match_operand:SI 0 "register_operand" "=r,r") -+ (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r") -+ (match_operand:SI 2 "arith_operand" "r,I")))] -+ "TARGET_64BIT" -+ "\t%0,%1,%2" -+ [(set_attr "type" "logical") -+ (set_attr "mode" "SI")]) -+ -+(define_insn "one_cmpl2" -+ [(set (match_operand:X 0 "register_operand" "=r") -+ (not:X (match_operand:X 1 "register_operand" "r")))] -+ "" -+ "not\t%0,%1" -+ [(set_attr "type" "logical") -+ (set_attr "mode" "")]) -+ -+(define_insn "*one_cmplsi2_internal" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (not:SI (match_operand:SI 1 "register_operand" "r")))] -+ "TARGET_64BIT" -+ "not\t%0,%1" -+ [(set_attr "type" "logical") -+ (set_attr "mode" "SI")]) -+ -+;; -+;; .................... -+;; -+;; TRUNCATION -+;; -+;; .................... -+ -+(define_insn "truncdfsf2" -+ [(set (match_operand:SF 0 "register_operand" "=f") -+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] -+ "TARGET_DOUBLE_FLOAT" -+ "fcvt.s.d\t%0,%1" -+ [(set_attr "type" "fcvt") -+ (set_attr "mode" "SF")]) -+ -+;; -+;; .................... -+;; -+;; ZERO EXTENSION -+;; -+;; .................... -+ -+;; Extension insns. -+ -+(define_insn_and_split "zero_extendsidi2" -+ [(set (match_operand:DI 0 "register_operand" "=r,r") -+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))] -+ "TARGET_64BIT" -+ "@ -+ # -+ lwu\t%0,%1" -+ "&& reload_completed && REG_P (operands[1])" -+ [(set (match_dup 0) -+ (ashift:DI (match_dup 1) (const_int 32))) -+ (set (match_dup 0) -+ (lshiftrt:DI (match_dup 0) (const_int 32)))] -+ { operands[1] = gen_lowpart (DImode, operands[1]); } -+ [(set_attr "move_type" "shift_shift,load") -+ (set_attr "mode" "DI")]) -+ -+(define_insn_and_split "zero_extendhi2" -+ [(set (match_operand:GPR 0 "register_operand" "=r,r") -+ (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "r,m")))] -+ "" -+ "@ -+ # -+ lhu\t%0,%1" -+ "&& reload_completed && REG_P (operands[1])" -+ [(set (match_dup 0) -+ (ashift:GPR (match_dup 1) (match_dup 2))) -+ (set (match_dup 0) -+ (lshiftrt:GPR (match_dup 0) (match_dup 2)))] -+ { -+ operands[1] = gen_lowpart (mode, operands[1]); -+ operands[2] = GEN_INT(GET_MODE_BITSIZE(mode) - 16); -+ } -+ [(set_attr "move_type" "shift_shift,load") -+ (set_attr "mode" "")]) -+ -+(define_insn "zero_extendqi2" -+ [(set (match_operand:SUPERQI 0 "register_operand" "=r,r") -+ (zero_extend:SUPERQI -+ (match_operand:QI 1 "nonimmediate_operand" "r,m")))] -+ "" -+ "@ -+ and\t%0,%1,0xff -+ lbu\t%0,%1" -+ [(set_attr "move_type" "andi,load") -+ (set_attr "mode" "")]) -+ -+;; -+;; .................... -+;; -+;; SIGN EXTENSION -+;; -+;; .................... -+ -+(define_insn "extendsidi2" -+ [(set (match_operand:DI 0 "register_operand" "=r,r") -+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))] -+ "TARGET_64BIT" -+ "@ -+ sext.w\t%0,%1 -+ lw\t%0,%1" -+ [(set_attr "move_type" "move,load") -+ (set_attr "mode" "DI")]) -+ -+(define_insn_and_split "extend2" -+ [(set (match_operand:SUPERQI 0 "register_operand" "=r,r") -+ (sign_extend:SUPERQI -+ (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))] -+ "" -+ "@ -+ # -+ l\t%0,%1" -+ "&& reload_completed && REG_P (operands[1])" -+ [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) -+ (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))] -+{ -+ operands[0] = gen_lowpart (SImode, operands[0]); -+ operands[1] = gen_lowpart (SImode, operands[1]); -+ operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode) -+ - GET_MODE_BITSIZE (mode)); -+} -+ [(set_attr "move_type" "shift_shift,load") -+ (set_attr "mode" "SI")]) -+ -+(define_insn "extendsfdf2" -+ [(set (match_operand:DF 0 "register_operand" "=f") -+ (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] -+ "TARGET_DOUBLE_FLOAT" -+ "fcvt.d.s\t%0,%1" -+ [(set_attr "type" "fcvt") -+ (set_attr "mode" "DF")]) -+ -+;; -+;; .................... -+;; -+;; CONVERSIONS -+;; -+;; .................... -+ -+(define_insn "fix_trunc2" -+ [(set (match_operand:GPR 0 "register_operand" "=r") -+ (fix:GPR (match_operand:ANYF 1 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fcvt.. %0,%1,rtz" -+ [(set_attr "type" "fcvt") -+ (set_attr "mode" "")]) -+ -+(define_insn "fixuns_trunc2" -+ [(set (match_operand:GPR 0 "register_operand" "=r") -+ (unsigned_fix:GPR (match_operand:ANYF 1 "register_operand" "f")))] -+ "TARGET_HARD_FLOAT" -+ "fcvt.u. %0,%1,rtz" -+ [(set_attr "type" "fcvt") -+ (set_attr "mode" "")]) -+ -+(define_insn "float2" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (float:ANYF (match_operand:GPR 1 "reg_or_0_operand" "rJ")))] -+ "TARGET_HARD_FLOAT" -+ "fcvt..\t%0,%z1" -+ [(set_attr "type" "fcvt") -+ (set_attr "mode" "")]) -+ -+(define_insn "floatuns2" -+ [(set (match_operand:ANYF 0 "register_operand" "=f") -+ (unsigned_float:ANYF (match_operand:GPR 1 "reg_or_0_operand" "rJ")))] -+ "TARGET_HARD_FLOAT" -+ "fcvt..u\t%0,%z1" -+ [(set_attr "type" "fcvt") -+ (set_attr "mode" "")]) -+ -+(define_insn "l2" -+ [(set (match_operand:GPR 0 "register_operand" "=r") -+ (unspec:GPR [(match_operand:ANYF 1 "register_operand" "f")] -+ RINT))] -+ "TARGET_HARD_FLOAT" -+ "fcvt.. %0,%1," -+ [(set_attr "type" "fcvt") -+ (set_attr "mode" "")]) -+ -+;; -+;; .................... -+;; -+;; DATA MOVEMENT -+;; -+;; .................... -+ -+;; Lower-level instructions for loading an address from the GOT. -+;; We could use MEMs, but an unspec gives more optimization -+;; opportunities. -+ -+(define_insn "got_load" -+ [(set (match_operand:P 0 "register_operand" "=r") -+ (unspec:P [(match_operand:P 1 "symbolic_operand" "")] -+ UNSPEC_LOAD_GOT))] -+ "" -+ "la\t%0,%1" -+ [(set_attr "got" "load") -+ (set_attr "mode" "")]) -+ -+(define_insn "tls_add_tp_le" -+ [(set (match_operand:P 0 "register_operand" "=r") -+ (unspec:P [(match_operand:P 1 "register_operand" "r") -+ (match_operand:P 2 "register_operand" "r") -+ (match_operand:P 3 "symbolic_operand" "")] -+ UNSPEC_TLS_LE))] -+ "" -+ "add\t%0,%1,%2,%%tprel_add(%3)" -+ [(set_attr "type" "arith") -+ (set_attr "mode" "")]) -+ -+(define_insn "got_load_tls_gd" -+ [(set (match_operand:P 0 "register_operand" "=r") -+ (unspec:P [(match_operand:P 1 "symbolic_operand" "")] -+ UNSPEC_TLS_GD))] -+ "" -+ "la.tls.gd\t%0,%1" -+ [(set_attr "got" "load") -+ (set_attr "mode" "")]) -+ -+(define_insn "got_load_tls_ie" -+ [(set (match_operand:P 0 "register_operand" "=r") -+ (unspec:P [(match_operand:P 1 "symbolic_operand" "")] -+ UNSPEC_TLS_IE))] -+ "" -+ "la.tls.ie\t%0,%1" -+ [(set_attr "got" "load") -+ (set_attr "mode" "")]) -+ -+(define_insn "auipc" -+ [(set (match_operand:P 0 "register_operand" "=r") -+ (unspec:P [(match_operand:P 1 "symbolic_operand" "") -+ (match_operand:P 2 "const_int_operand") -+ (pc)] -+ UNSPEC_AUIPC))] -+ "" -+ ".LA%2: auipc\t%0,%h1" -+ [(set_attr "type" "arith") -+ (set_attr "cannot_copy" "yes")]) -+ -+;; Instructions for adding the low 12 bits of an address to a register. -+;; Operand 2 is the address: riscv_print_operand works out which relocation -+;; should be applied. -+ -+(define_insn "*low" -+ [(set (match_operand:P 0 "register_operand" "=r") -+ (lo_sum:P (match_operand:P 1 "register_operand" "r") -+ (match_operand:P 2 "symbolic_operand" "")))] -+ "" -+ "addi\t%0,%1,%R2" -+ [(set_attr "type" "arith") -+ (set_attr "mode" "")]) -+ -+;; Allow combine to split complex const_int load sequences, using operand 2 -+;; to store the intermediate results. See move_operand for details. -+(define_split -+ [(set (match_operand:GPR 0 "register_operand") -+ (match_operand:GPR 1 "splittable_const_int_operand")) -+ (clobber (match_operand:GPR 2 "register_operand"))] -+ "" -+ [(const_int 0)] -+{ -+ riscv_move_integer (operands[2], operands[0], INTVAL (operands[1])); -+ DONE; -+}) -+ -+;; Likewise, for symbolic operands. -+(define_split -+ [(set (match_operand:P 0 "register_operand") -+ (match_operand:P 1)) -+ (clobber (match_operand:P 2 "register_operand"))] -+ "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)" -+ [(set (match_dup 0) (match_dup 3))] -+{ -+ riscv_split_symbol (operands[2], operands[1], -+ MAX_MACHINE_MODE, &operands[3]); -+}) -+ -+;; 64-bit integer moves -+ -+(define_expand "movdi" -+ [(set (match_operand:DI 0 "") -+ (match_operand:DI 1 ""))] -+ "" -+{ -+ if (riscv_legitimize_move (DImode, operands[0], operands[1])) -+ DONE; -+}) -+ -+(define_insn "*movdi_32bit" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m") -+ (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))] -+ "!TARGET_64BIT -+ && (register_operand (operands[0], DImode) -+ || reg_or_0_operand (operands[1], DImode))" -+ { return riscv_output_move (operands[0], operands[1]); } -+ [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore") -+ (set_attr "mode" "DI")]) -+ -+(define_insn "*movdi_64bit" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m,*f,*f,*r,*f,*m") -+ (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))] -+ "TARGET_64BIT -+ && (register_operand (operands[0], DImode) -+ || reg_or_0_operand (operands[1], DImode))" -+ { return riscv_output_move (operands[0], operands[1]); } -+ [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore") -+ (set_attr "mode" "DI")]) -+ -+;; 32-bit Integer moves -+ -+(define_expand "mov" -+ [(set (match_operand:MOVE32 0 "") -+ (match_operand:MOVE32 1 ""))] -+ "" -+{ -+ if (riscv_legitimize_move (mode, operands[0], operands[1])) -+ DONE; -+}) -+ -+(define_insn "*movsi_internal" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,*f,*f,*r,*m") -+ (match_operand:SI 1 "move_operand" "r,T,m,rJ,*r*J,*m,*f,*f"))] -+ "(register_operand (operands[0], SImode) -+ || reg_or_0_operand (operands[1], SImode))" -+ { return riscv_output_move (operands[0], operands[1]); } -+ [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore") -+ (set_attr "mode" "SI")]) -+ -+;; 16-bit Integer moves -+ -+;; Unlike most other insns, the move insns can't be split with -+;; different predicates, because register spilling and other parts of -+;; the compiler, have memoized the insn number already. -+;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. -+ -+(define_expand "movhi" -+ [(set (match_operand:HI 0 "") -+ (match_operand:HI 1 ""))] -+ "" -+{ -+ if (riscv_legitimize_move (HImode, operands[0], operands[1])) -+ DONE; -+}) -+ -+(define_insn "*movhi_internal" -+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,*f,*r") -+ (match_operand:HI 1 "move_operand" "r,T,m,rJ,*r*J,*f"))] -+ "(register_operand (operands[0], HImode) -+ || reg_or_0_operand (operands[1], HImode))" -+ { return riscv_output_move (operands[0], operands[1]); } -+ [(set_attr "move_type" "move,const,load,store,mtc,mfc") -+ (set_attr "mode" "HI")]) -+ -+;; HImode constant generation; see riscv_move_integer for details. -+;; si+si->hi without truncation is legal because of TRULY_NOOP_TRUNCATION. -+ -+(define_insn "*addhi3" -+ [(set (match_operand:HI 0 "register_operand" "=r,r") -+ (plus:HI (match_operand:HISI 1 "register_operand" "r,r") -+ (match_operand:HISI 2 "arith_operand" "r,I")))] -+ "" -+ { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; } -+ [(set_attr "type" "arith") -+ (set_attr "mode" "HI")]) -+ -+(define_insn "*xorhi3" -+ [(set (match_operand:HI 0 "register_operand" "=r,r") -+ (xor:HI (match_operand:HISI 1 "register_operand" "r,r") -+ (match_operand:HISI 2 "arith_operand" "r,I")))] -+ "" -+ "xor\t%0,%1,%2" -+ [(set_attr "type" "logical") -+ (set_attr "mode" "HI")]) -+ -+;; 8-bit Integer moves -+ -+(define_expand "movqi" -+ [(set (match_operand:QI 0 "") -+ (match_operand:QI 1 ""))] -+ "" -+{ -+ if (riscv_legitimize_move (QImode, operands[0], operands[1])) -+ DONE; -+}) -+ -+(define_insn "*movqi_internal" -+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m,*f,*r") -+ (match_operand:QI 1 "move_operand" "r,I,m,rJ,*r*J,*f"))] -+ "(register_operand (operands[0], QImode) -+ || reg_or_0_operand (operands[1], QImode))" -+ { return riscv_output_move (operands[0], operands[1]); } -+ [(set_attr "move_type" "move,const,load,store,mtc,mfc") -+ (set_attr "mode" "QI")]) -+ -+;; 32-bit floating point moves -+ -+(define_expand "movsf" -+ [(set (match_operand:SF 0 "") -+ (match_operand:SF 1 ""))] -+ "" -+{ -+ if (riscv_legitimize_move (SFmode, operands[0], operands[1])) -+ DONE; -+}) -+ -+(define_insn "*movsf_hardfloat" -+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,*r,*r,*m") -+ (match_operand:SF 1 "move_operand" "f,G,m,f,G,*r,*f,*G*r,*m,*r"))] -+ "TARGET_HARD_FLOAT -+ && (register_operand (operands[0], SFmode) -+ || reg_or_0_operand (operands[1], SFmode))" -+ { return riscv_output_move (operands[0], operands[1]); } -+ [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") -+ (set_attr "mode" "SF")]) -+ -+(define_insn "*movsf_softfloat" -+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") -+ (match_operand:SF 1 "move_operand" "Gr,m,r"))] -+ "!TARGET_HARD_FLOAT -+ && (register_operand (operands[0], SFmode) -+ || reg_or_0_operand (operands[1], SFmode))" -+ { return riscv_output_move (operands[0], operands[1]); } -+ [(set_attr "move_type" "move,load,store") -+ (set_attr "mode" "SF")]) -+ -+;; 64-bit floating point moves -+ -+(define_expand "movdf" -+ [(set (match_operand:DF 0 "") -+ (match_operand:DF 1 ""))] -+ "" -+{ -+ if (riscv_legitimize_move (DFmode, operands[0], operands[1])) -+ DONE; -+}) -+ -+;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead. -+;; (However, we can still use fcvt.d.w to zero a floating-point register.) -+(define_insn "*movdf_hardfloat_rv32" -+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*r,*r,*m") -+ (match_operand:DF 1 "move_operand" "f,G,m,f,G,*r*G,*m,*r"))] -+ "!TARGET_64BIT && TARGET_DOUBLE_FLOAT -+ && (register_operand (operands[0], DFmode) -+ || reg_or_0_operand (operands[1], DFmode))" -+ { return riscv_output_move (operands[0], operands[1]); } -+ [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store") -+ (set_attr "mode" "DF")]) -+ -+(define_insn "*movdf_hardfloat_rv64" -+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,*r,*r,*m") -+ (match_operand:DF 1 "move_operand" "f,G,m,f,G,*r,*f,*r*G,*m,*r"))] -+ "TARGET_64BIT && TARGET_DOUBLE_FLOAT -+ && (register_operand (operands[0], DFmode) -+ || reg_or_0_operand (operands[1], DFmode))" -+ { return riscv_output_move (operands[0], operands[1]); } -+ [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") -+ (set_attr "mode" "DF")]) -+ -+(define_insn "*movdf_softfloat" -+ [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m") -+ (match_operand:DF 1 "move_operand" "rG,m,rG"))] -+ "!TARGET_DOUBLE_FLOAT -+ && (register_operand (operands[0], DFmode) -+ || reg_or_0_operand (operands[1], DFmode))" -+ { return riscv_output_move (operands[0], operands[1]); } -+ [(set_attr "move_type" "move,load,store") -+ (set_attr "mode" "DF")]) -+ -+(define_split -+ [(set (match_operand:MOVE64 0 "nonimmediate_operand") -+ (match_operand:MOVE64 1 "move_operand"))] -+ "reload_completed -+ && riscv_split_64bit_move_p (operands[0], operands[1])" -+ [(const_int 0)] -+{ -+ riscv_split_doubleword_move (operands[0], operands[1]); -+ DONE; -+}) -+ -+;; Expand in-line code to clear the instruction cache between operand[0] and -+;; operand[1]. -+(define_expand "clear_cache" -+ [(match_operand 0 "pmode_register_operand") -+ (match_operand 1 "pmode_register_operand")] -+ "" -+{ -+ emit_insn (gen_fence_i ()); -+ DONE; -+}) -+ -+(define_insn "fence" -+ [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)] -+ "" -+ "%|fence%-") -+ -+(define_insn "fence_i" -+ [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)] -+ "" -+ "fence.i") -+ -+;; -+;; .................... -+;; -+;; SHIFTS -+;; -+;; .................... -+ -+(define_insn "si3" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (any_shift:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "arith_operand" "rI")))] -+ "" -+{ -+ if (GET_CODE (operands[2]) == CONST_INT) -+ operands[2] = GEN_INT (INTVAL (operands[2]) -+ & (GET_MODE_BITSIZE (SImode) - 1)); -+ -+ return TARGET_64BIT ? "w\t%0,%1,%2" : "\t%0,%1,%2"; -+} -+ [(set_attr "type" "shift") -+ (set_attr "mode" "SI")]) -+ -+(define_insn "di3" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (any_shift:DI (match_operand:DI 1 "register_operand" "r") -+ (match_operand:DI 2 "arith_operand" "rI")))] -+ "TARGET_64BIT" -+{ -+ if (GET_CODE (operands[2]) == CONST_INT) -+ operands[2] = GEN_INT (INTVAL (operands[2]) -+ & (GET_MODE_BITSIZE (DImode) - 1)); -+ -+ return "\t%0,%1,%2"; -+} -+ [(set_attr "type" "shift") -+ (set_attr "mode" "DI")]) -+ -+(define_insn "*si3_extend" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (sign_extend:DI -+ (any_shift:SI (match_operand:SI 1 "register_operand" "r") -+ (match_operand:SI 2 "arith_operand" "rI"))))] -+ "TARGET_64BIT" -+{ -+ if (GET_CODE (operands[2]) == CONST_INT) -+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); -+ -+ return "w\t%0,%1,%2"; -+} -+ [(set_attr "type" "shift") -+ (set_attr "mode" "SI")]) -+ -+;; -+;; .................... -+;; -+;; CONDITIONAL BRANCHES -+;; -+;; .................... -+ -+;; Conditional branches -+ -+(define_insn "*branch_order" -+ [(set (pc) -+ (if_then_else -+ (match_operator 1 "order_operator" -+ [(match_operand:X 2 "register_operand" "r") -+ (match_operand:X 3 "register_operand" "r")]) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "b%C1\t%2,%3,%0" -+ [(set_attr "type" "branch") -+ (set_attr "mode" "none")]) -+ -+(define_insn "*branch_zero" -+ [(set (pc) -+ (if_then_else -+ (match_operator 1 "signed_order_operator" -+ [(match_operand:X 2 "register_operand" "r") -+ (const_int 0)]) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "b%C1z\t%2,%0" -+ [(set_attr "type" "branch") -+ (set_attr "mode" "none")]) -+ -+;; Used to implement built-in functions. -+(define_expand "condjump" -+ [(set (pc) -+ (if_then_else (match_operand 0) -+ (label_ref (match_operand 1)) -+ (pc)))]) -+ -+(define_expand "cbranch4" -+ [(set (pc) -+ (if_then_else (match_operator 0 "comparison_operator" -+ [(match_operand:BR 1 "register_operand") -+ (match_operand:BR 2 "nonmemory_operand")]) -+ (label_ref (match_operand 3 "")) -+ (pc)))] -+ "" -+{ -+ riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]), -+ operands[1], operands[2]); -+ DONE; -+}) -+ -+(define_expand "cbranch4" -+ [(set (pc) -+ (if_then_else (match_operator 0 "fp_branch_comparison" -+ [(match_operand:ANYF 1 "register_operand") -+ (match_operand:ANYF 2 "register_operand")]) -+ (label_ref (match_operand 3 "")) -+ (pc)))] -+ "TARGET_HARD_FLOAT" -+{ -+ riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]), -+ operands[1], operands[2]); -+ DONE; -+}) -+ -+(define_insn_and_split "*branch_on_bit" -+ [(set (pc) -+ (if_then_else -+ (match_operator 0 "equality_operator" -+ [(zero_extract:X (match_operand:X 2 "register_operand" "r") -+ (const_int 1) -+ (match_operand 3 "branch_on_bit_operand")) -+ (const_int 0)]) -+ (label_ref (match_operand 1)) -+ (pc))) -+ (clobber (match_scratch:X 4 "=&r"))] -+ "" -+ "#" -+ "reload_completed" -+ [(set (match_dup 4) -+ (ashift:X (match_dup 2) (match_dup 3))) -+ (set (pc) -+ (if_then_else -+ (match_op_dup 0 [(match_dup 4) (const_int 0)]) -+ (label_ref (match_operand 1)) -+ (pc)))] -+{ -+ int shift = GET_MODE_BITSIZE (mode) - 1 - INTVAL (operands[3]); -+ operands[3] = GEN_INT (shift); -+ -+ if (GET_CODE (operands[0]) == EQ) -+ operands[0] = gen_rtx_GE (mode, operands[4], const0_rtx); -+ else -+ operands[0] = gen_rtx_LT (mode, operands[4], const0_rtx); -+}) -+ -+(define_insn_and_split "*branch_on_bit_range" -+ [(set (pc) -+ (if_then_else -+ (match_operator 0 "equality_operator" -+ [(zero_extract:X (match_operand:X 2 "register_operand" "r") -+ (match_operand 3 "branch_on_bit_operand") -+ (const_int 0)) -+ (const_int 0)]) -+ (label_ref (match_operand 1)) -+ (pc))) -+ (clobber (match_scratch:X 4 "=&r"))] -+ "" -+ "#" -+ "reload_completed" -+ [(set (match_dup 4) -+ (ashift:X (match_dup 2) (match_dup 3))) -+ (set (pc) -+ (if_then_else -+ (match_op_dup 0 [(match_dup 4) (const_int 0)]) -+ (label_ref (match_operand 1)) -+ (pc)))] -+{ -+ operands[3] = GEN_INT (GET_MODE_BITSIZE (mode) - INTVAL (operands[3])); -+}) -+ -+;; -+;; .................... -+;; -+;; SETTING A REGISTER FROM A COMPARISON -+;; -+;; .................... -+ -+;; Destination is always set in SI mode. -+ -+(define_expand "cstore4" -+ [(set (match_operand:SI 0 "register_operand") -+ (match_operator:SI 1 "order_operator" -+ [(match_operand:GPR 2 "register_operand") -+ (match_operand:GPR 3 "nonmemory_operand")]))] -+ "" -+{ -+ riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2], -+ operands[3]); -+ DONE; -+}) -+ -+(define_expand "cstore4" -+ [(set (match_operand:SI 0 "register_operand") -+ (match_operator:SI 1 "fp_scc_comparison" -+ [(match_operand:ANYF 2 "register_operand") -+ (match_operand:ANYF 3 "register_operand")]))] -+ "TARGET_HARD_FLOAT" -+{ -+ riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2], -+ operands[3]); -+ DONE; -+}) -+ -+(define_insn "*cstore4" -+ [(set (match_operand:X 0 "register_operand" "=r") -+ (match_operator:X 1 "fp_native_comparison" -+ [(match_operand:ANYF 2 "register_operand" "f") -+ (match_operand:ANYF 3 "register_operand" "f")]))] -+ "TARGET_HARD_FLOAT" -+ "f%C1.\t%0,%2,%3" -+ [(set_attr "type" "fcmp") -+ (set_attr "mode" "")]) -+ -+(define_insn "f_quiet4" -+ [(set (match_operand:X 0 "register_operand" "=r") -+ (unspec:X -+ [(match_operand:ANYF 1 "register_operand" "f") -+ (match_operand:ANYF 2 "register_operand" "f")] -+ QUIET_COMPARISON)) -+ (clobber (match_scratch:X 3 "=&r"))] -+ "TARGET_HARD_FLOAT" -+ "frflags\t%3\n\tf.\t%0,%1,%2\n\tfsflags %3" -+ [(set_attr "type" "fcmp") -+ (set_attr "mode" "") -+ (set (attr "length") (const_int 12))]) -+ -+(define_insn "*seq_zero_" -+ [(set (match_operand:GPR 0 "register_operand" "=r") -+ (eq:GPR (match_operand:X 1 "register_operand" "r") -+ (const_int 0)))] -+ "" -+ "seqz\t%0,%1" -+ [(set_attr "type" "slt") -+ (set_attr "mode" "")]) -+ -+(define_insn "*sne_zero_" -+ [(set (match_operand:GPR 0 "register_operand" "=r") -+ (ne:GPR (match_operand:X 1 "register_operand" "r") -+ (const_int 0)))] -+ "" -+ "snez\t%0,%1" -+ [(set_attr "type" "slt") -+ (set_attr "mode" "")]) -+ -+(define_insn "*sgt_" -+ [(set (match_operand:GPR 0 "register_operand" "=r") -+ (any_gt:GPR (match_operand:X 1 "register_operand" "r") -+ (match_operand:X 2 "reg_or_0_operand" "rJ")))] -+ "" -+ "sgt\t%0,%1,%z2" -+ [(set_attr "type" "slt") -+ (set_attr "mode" "")]) -+ -+(define_insn "*sge_" -+ [(set (match_operand:GPR 0 "register_operand" "=r") -+ (any_ge:GPR (match_operand:X 1 "register_operand" "r") -+ (const_int 1)))] -+ "" -+ "slt\t%0,zero,%1" -+ [(set_attr "type" "slt") -+ (set_attr "mode" "")]) -+ -+(define_insn "*slt_" -+ [(set (match_operand:GPR 0 "register_operand" "=r") -+ (any_lt:GPR (match_operand:X 1 "register_operand" "r") -+ (match_operand:X 2 "arith_operand" "rI")))] -+ "" -+ "slt\t%0,%1,%2" -+ [(set_attr "type" "slt") -+ (set_attr "mode" "")]) -+ -+(define_insn "*sle_" -+ [(set (match_operand:GPR 0 "register_operand" "=r") -+ (any_le:GPR (match_operand:X 1 "register_operand" "r") -+ (match_operand:X 2 "sle_operand" "")))] -+ "" -+{ -+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1); -+ return "slt\t%0,%1,%2"; -+} -+ [(set_attr "type" "slt") -+ (set_attr "mode" "")]) -+ -+;; -+;; .................... -+;; -+;; UNCONDITIONAL BRANCHES -+;; -+;; .................... -+ -+;; Unconditional branches. -+ -+(define_insn "jump" -+ [(set (pc) -+ (label_ref (match_operand 0 "" "")))] -+ "" -+ "j\t%l0" -+ [(set_attr "type" "jump") -+ (set_attr "mode" "none")]) -+ -+(define_expand "indirect_jump" -+ [(set (pc) (match_operand 0 "register_operand"))] -+ "" -+{ -+ operands[0] = force_reg (Pmode, operands[0]); -+ if (Pmode == SImode) -+ emit_jump_insn (gen_indirect_jumpsi (operands[0])); -+ else -+ emit_jump_insn (gen_indirect_jumpdi (operands[0])); -+ DONE; -+}) -+ -+(define_insn "indirect_jump" -+ [(set (pc) (match_operand:P 0 "register_operand" "l"))] -+ "" -+ "jr\t%0" -+ [(set_attr "type" "jump") -+ (set_attr "mode" "none")]) -+ -+(define_expand "tablejump" -+ [(set (pc) (match_operand 0 "register_operand" "")) -+ (use (label_ref (match_operand 1 "" "")))] -+ "" -+{ -+ if (CASE_VECTOR_PC_RELATIVE) -+ operands[0] = expand_simple_binop (Pmode, PLUS, operands[0], -+ gen_rtx_LABEL_REF (Pmode, operands[1]), -+ NULL_RTX, 0, OPTAB_DIRECT); -+ -+ if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode) -+ emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); -+ else -+ emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); -+ DONE; -+}) -+ -+(define_insn "tablejump" -+ [(set (pc) (match_operand:GPR 0 "register_operand" "l")) -+ (use (label_ref (match_operand 1 "" "")))] -+ "" -+ "jr\t%0" -+ [(set_attr "type" "jump") -+ (set_attr "mode" "none")]) -+ -+;; -+;; .................... -+;; -+;; Function prologue/epilogue -+;; -+;; .................... -+;; -+ -+(define_expand "prologue" -+ [(const_int 1)] -+ "" -+{ -+ riscv_expand_prologue (); -+ DONE; -+}) -+ -+;; Block any insns from being moved before this point, since the -+;; profiling call to mcount can use various registers that aren't -+;; saved or used to pass arguments. -+ -+(define_insn "blockage" -+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] -+ "" -+ "" -+ [(set_attr "type" "ghost") -+ (set_attr "mode" "none")]) -+ -+(define_expand "epilogue" -+ [(const_int 2)] -+ "" -+{ -+ riscv_expand_epilogue (false); -+ DONE; -+}) -+ -+(define_expand "sibcall_epilogue" -+ [(const_int 2)] -+ "" -+{ -+ riscv_expand_epilogue (true); -+ DONE; -+}) -+ -+;; Trivial return. Make it look like a normal return insn as that -+;; allows jump optimizations to work better. -+ -+(define_expand "return" -+ [(simple_return)] -+ "riscv_can_use_return_insn ()" -+ "") -+ -+(define_insn "simple_return" -+ [(simple_return)] -+ "" -+ "ret" -+ [(set_attr "type" "jump") -+ (set_attr "mode" "none")]) -+ -+;; Normal return. -+ -+(define_insn "simple_return_internal" -+ [(simple_return) -+ (use (match_operand 0 "pmode_register_operand" ""))] -+ "" -+ "jr\t%0" -+ [(set_attr "type" "jump") -+ (set_attr "mode" "none")]) -+ -+;; This is used in compiling the unwind routines. -+(define_expand "eh_return" -+ [(use (match_operand 0 "general_operand"))] -+ "" -+{ -+ if (GET_MODE (operands[0]) != word_mode) -+ operands[0] = convert_to_mode (word_mode, operands[0], 0); -+ if (TARGET_64BIT) -+ emit_insn (gen_eh_set_lr_di (operands[0])); -+ else -+ emit_insn (gen_eh_set_lr_si (operands[0])); -+ DONE; -+}) -+ -+;; Clobber the return address on the stack. We can't expand this -+;; until we know where it will be put in the stack frame. -+ -+(define_insn "eh_set_lr_si" -+ [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN) -+ (clobber (match_scratch:SI 1 "=&r"))] -+ "! TARGET_64BIT" -+ "#") -+ -+(define_insn "eh_set_lr_di" -+ [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN) -+ (clobber (match_scratch:DI 1 "=&r"))] -+ "TARGET_64BIT" -+ "#") -+ -+(define_split -+ [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN) -+ (clobber (match_scratch 1))] -+ "reload_completed" -+ [(const_int 0)] -+{ -+ riscv_set_return_address (operands[0], operands[1]); -+ DONE; -+}) -+ -+;; -+;; .................... -+;; -+;; FUNCTION CALLS -+;; -+;; .................... -+ -+(define_expand "sibcall" -+ [(parallel [(call (match_operand 0 "") -+ (match_operand 1 "")) -+ (use (match_operand 2 "")) ;; next_arg_reg -+ (use (match_operand 3 ""))])] ;; struct_value_size_rtx -+ "" -+{ -+ rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0)); -+ emit_call_insn (gen_sibcall_internal (target, operands[1])); -+ DONE; -+}) -+ -+(define_insn "sibcall_internal" -+ [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U")) -+ (match_operand 1 "" ""))] -+ "SIBLING_CALL_P (insn)" -+ "@ -+ jr\t%0 -+ tail\t%0 -+ tail\t%0@plt" -+ [(set_attr "type" "call")]) -+ -+(define_expand "sibcall_value" -+ [(parallel [(set (match_operand 0 "") -+ (call (match_operand 1 "") -+ (match_operand 2 ""))) -+ (use (match_operand 3 ""))])] ;; next_arg_reg -+ "" -+{ -+ rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0)); -+ emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2])); -+ DONE; -+}) -+ -+(define_insn "sibcall_value_internal" -+ [(set (match_operand 0 "" "") -+ (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U")) -+ (match_operand 2 "" "")))] -+ "SIBLING_CALL_P (insn)" -+ "@ -+ jr\t%1 -+ tail\t%1 -+ tail\t%1@plt" -+ [(set_attr "type" "call")]) -+ -+(define_expand "call" -+ [(parallel [(call (match_operand 0 "") -+ (match_operand 1 "")) -+ (use (match_operand 2 "")) ;; next_arg_reg -+ (use (match_operand 3 ""))])] ;; struct_value_size_rtx -+ "" -+{ -+ rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0)); -+ emit_call_insn (gen_call_internal (target, operands[1])); -+ DONE; -+}) -+ -+(define_insn "call_internal" -+ [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U")) -+ (match_operand 1 "" "")) -+ (clobber (reg:SI RETURN_ADDR_REGNUM))] -+ "" -+ "@ -+ jalr\t%0 -+ call\t%0 -+ call\t%0@plt" -+ [(set_attr "type" "call")]) -+ -+(define_expand "call_value" -+ [(parallel [(set (match_operand 0 "") -+ (call (match_operand 1 "") -+ (match_operand 2 ""))) -+ (use (match_operand 3 ""))])] ;; next_arg_reg -+ "" -+{ -+ rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0)); -+ emit_call_insn (gen_call_value_internal (operands[0], target, operands[2])); -+ DONE; -+}) -+ -+(define_insn "call_value_internal" -+ [(set (match_operand 0 "" "") -+ (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U")) -+ (match_operand 2 "" ""))) -+ (clobber (reg:SI RETURN_ADDR_REGNUM))] -+ "" -+ "@ -+ jalr\t%1 -+ call\t%1 -+ call\t%1@plt" -+ [(set_attr "type" "call")]) -+ -+;; Call subroutine returning any type. -+ -+(define_expand "untyped_call" -+ [(parallel [(call (match_operand 0 "") -+ (const_int 0)) -+ (match_operand 1 "") -+ (match_operand 2 "")])] -+ "" -+{ -+ int i; -+ -+ emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); -+ -+ for (i = 0; i < XVECLEN (operands[2], 0); i++) -+ { -+ rtx set = XVECEXP (operands[2], 0, i); -+ riscv_emit_move (SET_DEST (set), SET_SRC (set)); -+ } -+ -+ emit_insn (gen_blockage ()); -+ DONE; -+}) -+ -+(define_insn "nop" -+ [(const_int 0)] -+ "" -+ "nop" -+ [(set_attr "type" "nop") -+ (set_attr "mode" "none")]) -+ -+(define_insn "trap" -+ [(trap_if (const_int 1) (const_int 0))] -+ "" -+ "ebreak") -+ -+(define_insn "gpr_save" -+ [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_SAVE) -+ (clobber (reg:SI T0_REGNUM)) -+ (clobber (reg:SI T1_REGNUM))] -+ "" -+ { return riscv_output_gpr_save (INTVAL (operands[0])); }) -+ -+(define_insn "gpr_restore" -+ [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)] -+ "" -+ "tail\t__riscv_restore_%0") -+ -+(define_insn "gpr_restore_return" -+ [(return) -+ (use (match_operand 0 "pmode_register_operand" "")) -+ (const_int 0)] -+ "" -+ "") -+ -+(define_insn "riscv_frflags" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))] -+ "TARGET_HARD_FLOAT" -+ "frflags %0") -+ -+(define_insn "riscv_fsflags" -+ [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)] -+ "TARGET_HARD_FLOAT" -+ "fsflags %0") -+ -+(define_insn "stack_tie" -+ [(set (mem:BLK (scratch)) -+ (unspec:BLK [(match_operand:X 0 "register_operand" "r") -+ (match_operand:X 1 "register_operand" "r")] -+ UNSPEC_TIE))] -+ "" -+ "" -+ [(set_attr "length" "0")] -+) -+ -+(include "sync.md") -+(include "peephole.md") -+(include "pic.md") -+(include "generic.md") -diff --git original-gcc/gcc/config/riscv/riscv.opt gcc-6.3.0/gcc/config/riscv/riscv.opt -new file mode 100644 -index 00000000000..0466bb29d14 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/riscv.opt -@@ -0,0 +1,111 @@ -+; Options for the RISC-V port of the compiler -+; -+; Copyright (C) 2011-2017 Free Software Foundation, Inc. -+; -+; 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 -+; . -+ -+HeaderInclude -+config/riscv/riscv-opts.h -+ -+mbranch-cost= -+Target RejectNegative Joined UInteger Var(riscv_branch_cost) -+-mbranch-cost=N Set the cost of branches to roughly N instructions. -+ -+mplt -+Target Report Var(TARGET_PLT) Init(1) -+When generating -fpic code, allow the use of PLTs. Ignored for fno-pic. -+ -+mabi= -+Target Report RejectNegative Joined Enum(abi_type) Var(riscv_abi) Init(ABI_ILP32) -+Specify integer and floating-point calling convention. -+ -+Enum -+Name(abi_type) Type(enum riscv_abi_type) -+Supported ABIs (for use with the -mabi= option): -+ -+EnumValue -+Enum(abi_type) String(ilp32) Value(ABI_ILP32) -+ -+EnumValue -+Enum(abi_type) String(ilp32f) Value(ABI_ILP32F) -+ -+EnumValue -+Enum(abi_type) String(ilp32d) Value(ABI_ILP32D) -+ -+EnumValue -+Enum(abi_type) String(lp64) Value(ABI_LP64) -+ -+EnumValue -+Enum(abi_type) String(lp64f) Value(ABI_LP64F) -+ -+EnumValue -+Enum(abi_type) String(lp64d) Value(ABI_LP64D) -+ -+mfdiv -+Target Report Mask(FDIV) -+Use hardware floating-point divide and square root instructions. -+ -+mdiv -+Target Report Mask(DIV) -+Use hardware instructions for integer division. -+ -+march= -+Target Report RejectNegative Joined -+-march= Generate code for given RISC-V ISA (e.g. RV64IM). ISA strings must be -+lower-case. -+ -+mtune= -+Target RejectNegative Joined Var(riscv_tune_string) -+-mtune=PROCESSOR Optimize the output for PROCESSOR. -+ -+msmall-data-limit= -+Target Joined Separate UInteger Var(g_switch_value) Init(8) -+-msmall-data-limit=N Put global and static data smaller than bytes into a special section (on some targets). -+ -+msave-restore -+Target Report Mask(SAVE_RESTORE) -+Use smaller but slower prologue and epilogue code. -+ -+mcmodel= -+Target Report RejectNegative Joined Enum(code_model) Var(riscv_cmodel) Init(TARGET_DEFAULT_CMODEL) -+Specify the code model. -+ -+Enum -+Name(code_model) Type(enum riscv_code_model) -+Known code models (for use with the -mcmodel= option): -+ -+EnumValue -+Enum(code_model) String(medlow) Value(CM_MEDLOW) -+ -+EnumValue -+Enum(code_model) String(medany) Value(CM_MEDANY) -+ -+mexplicit-relocs -+Target Report Mask(EXPLICIT_RELOCS) -+Use %reloc() operators, rather than assembly macros, to load addresses. -+ -+Mask(64BIT) -+ -+Mask(MUL) -+ -+Mask(ATOMIC) -+ -+Mask(HARD_FLOAT) -+ -+Mask(DOUBLE_FLOAT) -+ -+Mask(RVC) -diff --git original-gcc/gcc/config/riscv/sync.md gcc-6.3.0/gcc/config/riscv/sync.md -new file mode 100644 -index 00000000000..09970b9f36b ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/sync.md -@@ -0,0 +1,194 @@ -+;; Machine description for RISC-V atomic operations. -+;; Copyright (C) 2011-2017 Free Software Foundation, Inc. -+;; Contributed by Andrew Waterman (andrew@sifive.com). -+;; Based on MIPS target for GNU compiler. -+ -+;; 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_c_enum "unspec" [ -+ UNSPEC_COMPARE_AND_SWAP -+ UNSPEC_SYNC_OLD_OP -+ UNSPEC_SYNC_EXCHANGE -+ UNSPEC_ATOMIC_STORE -+ UNSPEC_MEMORY_BARRIER -+]) -+ -+(define_code_iterator any_atomic [plus ior xor and]) -+(define_code_attr atomic_optab -+ [(plus "add") (ior "or") (xor "xor") (and "and")]) -+ -+;; Memory barriers. -+ -+(define_expand "mem_thread_fence" -+ [(match_operand:SI 0 "const_int_operand" "")] ;; model -+ "" -+{ -+ if (INTVAL (operands[0]) != MEMMODEL_RELAXED) -+ { -+ rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); -+ MEM_VOLATILE_P (mem) = 1; -+ emit_insn (gen_mem_thread_fence_1 (mem, operands[0])); -+ } -+ DONE; -+}) -+ -+;; Until the RISC-V memory model (hence its mapping from C++) is finalized, -+;; conservatively emit a full FENCE. -+(define_insn "mem_thread_fence_1" -+ [(set (match_operand:BLK 0 "" "") -+ (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER)) -+ (match_operand:SI 1 "const_int_operand" "")] ;; model -+ "" -+ "fence\trw,rw") -+ -+;; Atomic memory operations. -+ -+;; Implement atomic stores with amoswap. Fall back to fences for atomic loads. -+(define_insn "atomic_store" -+ [(set (match_operand:GPR 0 "memory_operand" "=A") -+ (unspec_volatile:GPR -+ [(match_operand:GPR 1 "reg_or_0_operand" "rJ") -+ (match_operand:SI 2 "const_int_operand")] ;; model -+ UNSPEC_ATOMIC_STORE))] -+ "TARGET_ATOMIC" -+ "%F2amoswap.%A2 zero,%z1,%0" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "atomic_" -+ [(set (match_operand:GPR 0 "memory_operand" "+A") -+ (unspec_volatile:GPR -+ [(any_atomic:GPR (match_dup 0) -+ (match_operand:GPR 1 "reg_or_0_operand" "rJ")) -+ (match_operand:SI 2 "const_int_operand")] ;; model -+ UNSPEC_SYNC_OLD_OP))] -+ "TARGET_ATOMIC" -+ "%F2amo.%A2 zero,%z1,%0" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "atomic_fetch_" -+ [(set (match_operand:GPR 0 "register_operand" "=&r") -+ (match_operand:GPR 1 "memory_operand" "+A")) -+ (set (match_dup 1) -+ (unspec_volatile:GPR -+ [(any_atomic:GPR (match_dup 1) -+ (match_operand:GPR 2 "reg_or_0_operand" "rJ")) -+ (match_operand:SI 3 "const_int_operand")] ;; model -+ UNSPEC_SYNC_OLD_OP))] -+ "TARGET_ATOMIC" -+ "%F3amo.%A3 %0,%z2,%1" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "atomic_exchange" -+ [(set (match_operand:GPR 0 "register_operand" "=&r") -+ (unspec_volatile:GPR -+ [(match_operand:GPR 1 "memory_operand" "+A") -+ (match_operand:SI 3 "const_int_operand")] ;; model -+ UNSPEC_SYNC_EXCHANGE)) -+ (set (match_dup 1) -+ (match_operand:GPR 2 "register_operand" "0"))] -+ "TARGET_ATOMIC" -+ "%F3amoswap.%A3 %0,%z2,%1" -+ [(set (attr "length") (const_int 8))]) -+ -+(define_insn "atomic_cas_value_strong" -+ [(set (match_operand:GPR 0 "register_operand" "=&r") -+ (match_operand:GPR 1 "memory_operand" "+A")) -+ (set (match_dup 1) -+ (unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ") -+ (match_operand:GPR 3 "reg_or_0_operand" "rJ") -+ (match_operand:SI 4 "const_int_operand") ;; mod_s -+ (match_operand:SI 5 "const_int_operand")] ;; mod_f -+ UNSPEC_COMPARE_AND_SWAP)) -+ (clobber (match_scratch:GPR 6 "=&r"))] -+ "TARGET_ATOMIC" -+ "%F5 1: lr.%A5 %0,%1; bne %0,%z2,1f; sc.%A4 %6,%z3,%1; bnez %6,1b; 1:" -+ [(set (attr "length") (const_int 20))]) -+ -+(define_expand "atomic_compare_and_swap" -+ [(match_operand:SI 0 "register_operand" "") ;; bool output -+ (match_operand:GPR 1 "register_operand" "") ;; val output -+ (match_operand:GPR 2 "memory_operand" "") ;; memory -+ (match_operand:GPR 3 "reg_or_0_operand" "") ;; expected value -+ (match_operand:GPR 4 "reg_or_0_operand" "") ;; desired value -+ (match_operand:SI 5 "const_int_operand" "") ;; is_weak -+ (match_operand:SI 6 "const_int_operand" "") ;; mod_s -+ (match_operand:SI 7 "const_int_operand" "")] ;; mod_f -+ "TARGET_ATOMIC" -+{ -+ emit_insn (gen_atomic_cas_value_strong (operands[1], operands[2], -+ operands[3], operands[4], -+ operands[6], operands[7])); -+ -+ rtx compare = operands[1]; -+ if (operands[3] != const0_rtx) -+ { -+ rtx difference = gen_rtx_MINUS (mode, operands[1], operands[3]); -+ compare = gen_reg_rtx (mode); -+ emit_insn (gen_rtx_SET (compare, difference)); -+ } -+ -+ if (word_mode != mode) -+ { -+ rtx reg = gen_reg_rtx (word_mode); -+ emit_insn (gen_rtx_SET (reg, gen_rtx_SIGN_EXTEND (word_mode, compare))); -+ compare = reg; -+ } -+ -+ emit_insn (gen_rtx_SET (operands[0], gen_rtx_EQ (SImode, compare, const0_rtx))); -+ DONE; -+}) -+ -+(define_expand "atomic_test_and_set" -+ [(match_operand:QI 0 "register_operand" "") ;; bool output -+ (match_operand:QI 1 "memory_operand" "+A") ;; memory -+ (match_operand:SI 2 "const_int_operand" "")] ;; model -+ "TARGET_ATOMIC" -+{ -+ /* We have no QImode atomics, so use the address LSBs to form a mask, -+ then use an aligned SImode atomic. */ -+ rtx result = operands[0]; -+ rtx mem = operands[1]; -+ rtx model = operands[2]; -+ rtx addr = force_reg (Pmode, XEXP (mem, 0)); -+ -+ rtx aligned_addr = gen_reg_rtx (Pmode); -+ emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, GEN_INT (-4))); -+ -+ rtx aligned_mem = change_address (mem, SImode, aligned_addr); -+ set_mem_alias_set (aligned_mem, 0); -+ -+ rtx offset = gen_reg_rtx (SImode); -+ emit_move_insn (offset, gen_rtx_AND (SImode, gen_lowpart (SImode, addr), -+ GEN_INT (3))); -+ -+ rtx tmp = gen_reg_rtx (SImode); -+ emit_move_insn (tmp, GEN_INT (1)); -+ -+ rtx shmt = gen_reg_rtx (SImode); -+ emit_move_insn (shmt, gen_rtx_ASHIFT (SImode, offset, GEN_INT (3))); -+ -+ rtx word = gen_reg_rtx (SImode); -+ emit_move_insn (word, gen_rtx_ASHIFT (SImode, tmp, shmt)); -+ -+ tmp = gen_reg_rtx (SImode); -+ emit_insn (gen_atomic_fetch_orsi (tmp, aligned_mem, word, model)); -+ -+ emit_move_insn (gen_lowpart (SImode, result), -+ gen_rtx_LSHIFTRT (SImode, tmp, -+ gen_lowpart (SImode, shmt))); -+ DONE; -+}) -diff --git original-gcc/gcc/config/riscv/t-elf-multilib gcc-6.3.0/gcc/config/riscv/t-elf-multilib -new file mode 100644 -index 00000000000..6a39ece03bd ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/t-elf-multilib -@@ -0,0 +1,6 @@ -+# This file was generated by multilib-generator with the command: -+# ./multilib-generator rv32i-ilp32--c rv32im-ilp32--c rv32iac-ilp32-- rv32imac-ilp32-- rv32imafc-ilp32f-rv32imafdc- rv64imac-lp64-- rv64imafdc-lp64d-- -+MULTILIB_OPTIONS = march=rv32i/march=rv32ic/march=rv32im/march=rv32imc/march=rv32iac/march=rv32imac/march=rv32imafc/march=rv32imafdc/march=rv32gc/march=rv64imac/march=rv64imafdc/march=rv64gc mabi=ilp32/mabi=ilp32f/mabi=lp64/mabi=lp64d -+MULTILIB_DIRNAMES = rv32i rv32ic rv32im rv32imc rv32iac rv32imac rv32imafc rv32imafdc rv32gc rv64imac rv64imafdc rv64gc ilp32 ilp32f lp64 lp64d -+MULTILIB_REQUIRED = march=rv32i/mabi=ilp32 march=rv32im/mabi=ilp32 march=rv32iac/mabi=ilp32 march=rv32imac/mabi=ilp32 march=rv32imafc/mabi=ilp32f march=rv64imac/mabi=lp64 march=rv64imafdc/mabi=lp64d -+MULTILIB_REUSE = march.rv32i/mabi.ilp32=march.rv32ic/mabi.ilp32 march.rv32im/mabi.ilp32=march.rv32imc/mabi.ilp32 march.rv32imafc/mabi.ilp32f=march.rv32imafdc/mabi.ilp32f march.rv32imafc/mabi.ilp32f=march.rv32gc/mabi.ilp32f march.rv64imafdc/mabi.lp64d=march.rv64gc/mabi.lp64d -diff --git original-gcc/gcc/config/riscv/t-linux gcc-6.3.0/gcc/config/riscv/t-linux -new file mode 100644 -index 00000000000..216d2776a18 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/t-linux -@@ -0,0 +1,3 @@ -+# Only XLEN and ABI affect Linux multilib dir names, e.g. /lib32/ilp32d/ -+MULTILIB_DIRNAMES := $(patsubst rv32%,lib32,$(patsubst rv64%,lib64,$(MULTILIB_DIRNAMES))) -+MULTILIB_OSDIRNAMES := $(patsubst lib%,../lib%,$(MULTILIB_DIRNAMES)) -diff --git original-gcc/gcc/config/riscv/t-linux-multilib gcc-6.3.0/gcc/config/riscv/t-linux-multilib -new file mode 100644 -index 00000000000..e94d4da5212 ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/t-linux-multilib -@@ -0,0 +1,6 @@ -+# This file was generated by multilib-generator with the command: -+# ./multilib-generator rv32imac-ilp32-rv32ima,rv32imaf,rv32imafd,rv32imafc,rv32imafdc- rv32imafdc-ilp32d-rv32imafd- rv64imac-lp64-rv64ima,rv64imaf,rv64imafd,rv64imafc,rv64imafdc- rv64imafdc-lp64d-rv64imafd- -+MULTILIB_OPTIONS = march=rv32imac/march=rv32ima/march=rv32imaf/march=rv32imafd/march=rv32imafc/march=rv32imafdc/march=rv32g/march=rv32gc/march=rv64imac/march=rv64ima/march=rv64imaf/march=rv64imafd/march=rv64imafc/march=rv64imafdc/march=rv64g/march=rv64gc mabi=ilp32/mabi=ilp32d/mabi=lp64/mabi=lp64d -+MULTILIB_DIRNAMES = rv32imac rv32ima rv32imaf rv32imafd rv32imafc rv32imafdc rv32g rv32gc rv64imac rv64ima rv64imaf rv64imafd rv64imafc rv64imafdc rv64g rv64gc ilp32 ilp32d lp64 lp64d -+MULTILIB_REQUIRED = march=rv32imac/mabi=ilp32 march=rv32imafdc/mabi=ilp32d march=rv64imac/mabi=lp64 march=rv64imafdc/mabi=lp64d -+MULTILIB_REUSE = march.rv32imac/mabi.ilp32=march.rv32ima/mabi.ilp32 march.rv32imac/mabi.ilp32=march.rv32imaf/mabi.ilp32 march.rv32imac/mabi.ilp32=march.rv32imafd/mabi.ilp32 march.rv32imac/mabi.ilp32=march.rv32imafc/mabi.ilp32 march.rv32imac/mabi.ilp32=march.rv32imafdc/mabi.ilp32 march.rv32imac/mabi.ilp32=march.rv32g/mabi.ilp32 march.rv32imac/mabi.ilp32=march.rv32gc/mabi.ilp32 march.rv32imafdc/mabi.ilp32d=march.rv32imafd/mabi.ilp32d march.rv32imafdc/mabi.ilp32d=march.rv32gc/mabi.ilp32d march.rv32imafdc/mabi.ilp32d=march.rv32g/mabi.ilp32d march.rv64imac/mabi.lp64=march.rv64ima/mabi.lp64 march.rv64imac/mabi.lp64=march.rv64imaf/mabi.lp64 march.rv64imac/mabi.lp64=march.rv64imafd/mabi.lp64 march.rv64imac/mabi.lp64=march.rv64imafc/mabi.lp64 march.rv64imac/mabi.lp64=march.rv64imafdc/mabi.lp64 march.rv64imac/mabi.lp64=march.rv64g/mabi.lp64 march.rv64imac/mabi.lp64=march.rv64gc/mabi.lp64 march.rv64imafdc/mabi.lp64d=march.rv64imafd/mabi.lp64d march.rv64imafdc/mabi.lp64d=march.rv64gc/mabi.lp64d march.rv64imafdc/mabi.lp64d=march.rv64g/mabi.lp64d -diff --git original-gcc/gcc/config/riscv/t-riscv gcc-6.3.0/gcc/config/riscv/t-riscv -new file mode 100644 -index 00000000000..0765b49f90f ---- /dev/null -+++ gcc-6.3.0/gcc/config/riscv/t-riscv -@@ -0,0 +1,11 @@ -+riscv-builtins.o: $(srcdir)/config/riscv/riscv-builtins.c $(CONFIG_H) \ -+ $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) $(RECOG_H) langhooks.h \ -+ $(DIAGNOSTIC_CORE_H) $(OPTABS_H) $(srcdir)/config/riscv/riscv-ftypes.def \ -+ $(srcdir)/config/riscv/riscv-modes.def -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/riscv/riscv-builtins.c -+ -+riscv-c.o: $(srcdir)/config/riscv/riscv-c.c $(CONFIG_H) $(SYSTEM_H) \ -+ coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H) $(TARGET_H) -+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -+ $(srcdir)/config/riscv/riscv-c.c -diff --git original-gcc/gcc/configure gcc-6.3.0/gcc/configure -index c9e43fb80e3..5359a4e6ee5 100755 ---- original-gcc/gcc/configure -+++ gcc-6.3.0/gcc/configure -@@ -24156,6 +24156,17 @@ x3: .space 4 - tls_first_minor=14 - tls_as_opt="-a32 --fatal-warnings" - ;; -+ riscv*-*-*) -+ conftest_s=' -+ .section .tdata,"awT",@progbits -+x: .word 2 -+ .text -+ la.tls.gd a0,x -+ call __tls_get_addr' -+ tls_first_major=2 -+ tls_first_minor=21 -+ tls_as_opt='--fatal-warnings' -+ ;; - s390-*-*) - conftest_s=' - .section ".tdata","awT",@progbits -@@ -27516,8 +27527,8 @@ esac - # version to the per-target configury. - case "$cpu_type" in - aarch64 | alpha | arm | avr | bfin | cris | i386 | m32c | m68k | microblaze \ -- | mips | nds32 | nios2 | pa | rs6000 | score | sparc | spu | tilegx | tilepro \ -- | visium | xstormy16 | xtensa) -+ | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc | spu | tilegx \ -+ | tilepro | visium | xstormy16 | xtensa) - insn="nop" - ;; - ia64 | s390) -diff --git original-gcc/gcc/configure.ac gcc-6.3.0/gcc/configure.ac -index 33f9a0ecdc6..673fb1bb891 100644 ---- original-gcc/gcc/configure.ac -+++ gcc-6.3.0/gcc/configure.ac -@@ -3393,6 +3393,17 @@ x3: .space 4 - tls_first_minor=14 - tls_as_opt="-a32 --fatal-warnings" - ;; -+ riscv*-*-*) -+ conftest_s=' -+ .section .tdata,"awT",@progbits -+x: .word 2 -+ .text -+ la.tls.gd a0,x -+ call __tls_get_addr' -+ tls_first_major=2 -+ tls_first_minor=21 -+ tls_as_opt='--fatal-warnings' -+ ;; - s390-*-*) - conftest_s=' - .section ".tdata","awT",@progbits -@@ -4744,8 +4755,8 @@ esac - # version to the per-target configury. - case "$cpu_type" in - aarch64 | alpha | arm | avr | bfin | cris | i386 | m32c | m68k | microblaze \ -- | mips | nds32 | nios2 | pa | rs6000 | score | sparc | spu | tilegx | tilepro \ -- | visium | xstormy16 | xtensa) -+ | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc | spu | tilegx \ -+ | tilepro | visium | xstormy16 | xtensa) - insn="nop" - ;; - ia64 | s390) -diff --git original-gcc/gcc/doc/contrib.texi gcc-6.3.0/gcc/doc/contrib.texi -index 5554d5f04c8..5b14fc445b5 100644 ---- original-gcc/gcc/doc/contrib.texi -+++ gcc-6.3.0/gcc/doc/contrib.texi -@@ -173,6 +173,10 @@ Denis Chertykov for contributing and maintaining the AVR port, the first GCC por - for an 8-bit architecture. - - @item -+Kito Cheng for his work on the RISC-V port, including bringing up the test -+suite and maintiance. -+ -+@item - Scott Christley for his Objective-C contributions. - - @item -@@ -217,6 +221,9 @@ Paul Dale for his work to add uClinux platform support to the - m68k backend. - - @item -+Palmer Dabbelt for his work maintaining the RISC-V port. -+ -+@item - Dario Dariol contributed the four varieties of sample programs - that print a copy of their source. - -@@ -1035,6 +1042,9 @@ associated configure steps. - Todd Vierling for contributions for NetBSD ports. - - @item -+Andrew Waterman for contributing the RISC-V port, as well as maintaining it. -+ -+@item - Jonathan Wakely for contributing libstdc++ Doxygen notes and XHTML - guidance. - -diff --git original-gcc/gcc/doc/install.texi gcc-6.3.0/gcc/doc/install.texi -index bc4edfdb096..0c82fe9eb94 100644 ---- original-gcc/gcc/doc/install.texi -+++ gcc-6.3.0/gcc/doc/install.texi -@@ -4297,6 +4297,36 @@ This configuration is intended for embedded systems. - @html -
- @end html -+@anchor{riscv32-x-elf} -+@heading riscv32-*-elf -+The RISC-V RV32 instruction set. -+This configuration is intended for embedded systems. -+ -+@html -+
-+@end html -+@anchor{riscv64-x-elf} -+@heading riscv64-*-elf -+The RISC-V RV64 instruction set. -+This configuration is intended for embedded systems. -+ -+@html -+
-+@end html -+@anchor{riscv32-x-linux} -+@heading riscv32-*-linux -+The RISC-V RV32 instruction set running GNU/Linux. -+ -+@html -+
-+@end html -+@anchor{riscv64-x-linux} -+@heading riscv64-*-linux -+The RISC-V RV64 instruction set running GNU/Linux. -+ -+@html -+
-+@end html - @anchor{rx-x-elf} - @heading rx-*-elf - The Renesas RX processor. See -diff --git original-gcc/gcc/doc/invoke.texi gcc-6.3.0/gcc/doc/invoke.texi -index 4b13aeb7426..581c4effbc5 100644 ---- original-gcc/gcc/doc/invoke.texi -+++ gcc-6.3.0/gcc/doc/invoke.texi -@@ -1046,6 +1046,20 @@ See RS/6000 and PowerPC Options. - -mstack-protector-guard-offset=@var{offset} @gol - -mlra -mno-lra} - -+@emph{RISC-V Options} -+@gccoptlist{-mbranch-cost=@var{N-instruction} @gol -+-mmemcpy -mno-memcpy @gol -+-mplt -mno-plt @gol -+-mabi=@var{ABI-string} @gol -+-mfdiv -mno-fdiv @gol -+-mdiv -mno-div @gol -+-march=@var{ISA-string} @gol -+-mtune=@var{processor-string} @gol -+-msmall-data-limit=@var{N-bytes} @gol -+-msave-restore -mno-save-restore @gol -+-mcmodel=@var{code-model} @gol -+-mexplicit-relocs -mno-explicit-relocs @gol} -+ - @emph{RX Options} - @gccoptlist{-m64bit-doubles -m32bit-doubles -fpu -nofpu@gol - -mcpu=@gol -@@ -13881,6 +13895,7 @@ platform. - * PowerPC Options:: - * RL78 Options:: - * RS/6000 and PowerPC Options:: -+* RISC-V Options:: - * RX Options:: - * S/390 and zSeries Options:: - * Score Options:: -@@ -22274,6 +22289,70 @@ offset from that base register. The default for those is as specified in the - relevant ABI. - @end table - -+@node RISC-V Options -+@subsection RISC-V Options -+@cindex RISC-V Options -+ -+These command-line options are defined for RISC-V targets: -+ -+@table @gcctabopt -+@item -mbranch-cost=@var{N} -+@opindex mbranch-cost -+Set the cost of branches to roughly N instructions. -+ -+@item -mmemcpy -+@itemx -mno-memcpy -+@opindex mmemcpy -+Don't optimize block moves. -+ -+@item -mplt -+@itemx -mno-plt -+@opindex plt -+When generating -fpic code, allow the use of PLTs. Ignored for fno-pic. -+ -+@item -mabi=@var{ABI-string} -+@opindex mabi -+Specify integer and floating-point calling convention. This defaults to the -+natural calling convention: eg LP64 for RV64I, ILP32 for RV32I, LP64D for -+RV64G. -+ -+@item -mfdiv -+@itemx -mno-fdiv -+@opindex mfdiv -+Use hardware floating-point divide and square root instructions. This requires -+the F or D extensions for floating-point registers. -+ -+@item -mdiv -+@itemx -mno-div -+@opindex mdiv -+Use hardware instructions for integer division. This requires the M extension. -+ -+@item -march=@var{ISA-string} -+@opindex march -+Generate code for given RISC-V ISA (e.g. rv64im). ISA strings must be -+lower-case. Examples include "rv64i", "rv32g", and "rv32imaf". -+ -+@item -mtune=@var{processor-string} -+@opindex mtune -+Optimize the output for the given processor, specified by microarchitecture -+name. -+ -+@item -msmall-data-limit=@var{N} -+@opindex msmall-data-limit -+Put global and static data smaller than @var{N} bytes into a special section -+(on some targets). -+ -+@item -msave-restore -+@itemx -mno-save-restore -+@opindex msave-restore -+Use smaller but slower prologue and epilogue code. -+ -+@item -mcmodel=@var{code-model} -+@opindex mcmodel -+Specify the code model. -+ -+@end table -+ - @node RX Options - @subsection RX Options - @cindex RX Options -diff --git original-gcc/gcc/doc/md.texi gcc-6.3.0/gcc/doc/md.texi -index 11266d7dd3f..3f710740b22 100644 ---- original-gcc/gcc/doc/md.texi -+++ gcc-6.3.0/gcc/doc/md.texi -@@ -3362,6 +3362,26 @@ The @code{X} register. - - @end table - -+@item RISC-V---@file{config/riscv/constraints.md} -+@table @code -+ -+@item f -+A floating-point register (if availiable). -+ -+@item I -+An I-type 12-bit signed immediate. -+ -+@item J -+Integer zero. -+ -+@item K -+A 5-bit unsigned immediate for CSR access instructions. -+ -+@item A -+An address that is held in a general-purpose register. -+ -+@end table -+ - @item RX---@file{config/rx/constraints.md} - @table @code - @item Q -diff --git original-gcc/libatomic/configure.tgt gcc-6.3.0/libatomic/configure.tgt -index 6d77c9482a5..b8af3ab2546 100644 ---- original-gcc/libatomic/configure.tgt -+++ gcc-6.3.0/libatomic/configure.tgt -@@ -37,6 +37,7 @@ case "${target_cpu}" in - ARCH=alpha - ;; - rs6000 | powerpc*) ARCH=powerpc ;; -+ riscv*) ARCH=riscv ;; - sh*) ARCH=sh ;; - - arm*) -diff --git original-gcc/libgcc/config.host gcc-6.3.0/libgcc/config.host -index 540bfa96358..9472a60886c 100644 ---- original-gcc/libgcc/config.host -+++ gcc-6.3.0/libgcc/config.host -@@ -167,6 +167,9 @@ powerpc*-*-*) - ;; - rs6000*-*-*) - ;; -+riscv*-*-*) -+ cpu_type=riscv -+ ;; - sparc64*-*-*) - cpu_type=sparc - ;; -@@ -1093,6 +1096,15 @@ powerpcle-*-eabi*) - tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff t-crtstuff-pic t-fdpbit" - extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o" - ;; -+riscv*-*-linux*) -+ tmake_file="${tmake_file} riscv/t-softfp${host_address} t-softfp riscv/t-elf riscv/t-elf${host_address}" -+ extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o crtendS.o crtbeginT.o" -+ md_unwind_header=riscv/linux-unwind.h -+ ;; -+riscv*-*-*) -+ tmake_file="${tmake_file} riscv/t-softfp${host_address} t-softfp riscv/t-elf riscv/t-elf${host_address}" -+ extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o" -+ ;; - rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*) - md_unwind_header=rs6000/aix-unwind.h - tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble" -diff --git original-gcc/libgcc/config/riscv/atomic.c gcc-6.3.0/libgcc/config/riscv/atomic.c -new file mode 100644 -index 00000000000..448b0e55b5a ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/atomic.c -@@ -0,0 +1,111 @@ -+/* Legacy sub-word atomics for RISC-V. -+ -+ Copyright (C) 2016-2017 Free Software Foundation, Inc. -+ -+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 -+. */ -+ -+#ifdef __riscv_atomic -+ -+#include -+ -+#define INVERT "not %[tmp1], %[tmp1]\n\t" -+#define DONT_INVERT "" -+ -+#define GENERATE_FETCH_AND_OP(type, size, opname, insn, invert, cop) \ -+ type __sync_fetch_and_ ## opname ## _ ## size (type *p, type v) \ -+ { \ -+ unsigned long aligned_addr = ((unsigned long) p) & ~3UL; \ -+ int shift = (((unsigned long) p) & 3) * 8; \ -+ unsigned mask = ((1U << ((sizeof v) * 8)) - 1) << shift; \ -+ unsigned old, tmp1, tmp2; \ -+ \ -+ asm volatile ("1:\n\t" \ -+ "lr.w.aq %[old], %[mem]\n\t" \ -+ #insn " %[tmp1], %[old], %[value]\n\t" \ -+ invert \ -+ "and %[tmp1], %[tmp1], %[mask]\n\t" \ -+ "and %[tmp2], %[old], %[not_mask]\n\t" \ -+ "or %[tmp2], %[tmp2], %[tmp1]\n\t" \ -+ "sc.w.rl %[tmp1], %[tmp2], %[mem]\n\t" \ -+ "bnez %[tmp1], 1b" \ -+ : [old] "=&r" (old), \ -+ [mem] "+A" (*(volatile unsigned*) aligned_addr), \ -+ [tmp1] "=&r" (tmp1), \ -+ [tmp2] "=&r" (tmp2) \ -+ : [value] "r" (((unsigned) v) << shift), \ -+ [mask] "r" (mask), \ -+ [not_mask] "r" (~mask)); \ -+ \ -+ return (type) (old >> shift); \ -+ } \ -+ \ -+ type __sync_ ## opname ## _and_fetch_ ## size (type *p, type v) \ -+ { \ -+ type o = __sync_fetch_and_ ## opname ## _ ## size (p, v); \ -+ return cop; \ -+ } -+ -+#define GENERATE_COMPARE_AND_SWAP(type, size) \ -+ type __sync_val_compare_and_swap_ ## size (type *p, type o, type n) \ -+ { \ -+ unsigned long aligned_addr = ((unsigned long) p) & ~3UL; \ -+ int shift = (((unsigned long) p) & 3) * 8; \ -+ unsigned mask = ((1U << ((sizeof o) * 8)) - 1) << shift; \ -+ unsigned old, tmp1; \ -+ \ -+ asm volatile ("1:\n\t" \ -+ "lr.w.aq %[old], %[mem]\n\t" \ -+ "and %[tmp1], %[old], %[mask]\n\t" \ -+ "bne %[tmp1], %[o], 1f\n\t" \ -+ "and %[tmp1], %[old], %[not_mask]\n\t" \ -+ "or %[tmp1], %[tmp1], %[n]\n\t" \ -+ "sc.w.rl %[tmp1], %[tmp1], %[mem]\n\t" \ -+ "bnez %[tmp1], 1b\n\t" \ -+ "1:" \ -+ : [old] "=&r" (old), \ -+ [mem] "+A" (*(volatile unsigned*) aligned_addr), \ -+ [tmp1] "=&r" (tmp1) \ -+ : [o] "r" ((((unsigned) o) << shift) & mask), \ -+ [n] "r" ((((unsigned) n) << shift) & mask), \ -+ [mask] "r" (mask), \ -+ [not_mask] "r" (~mask)); \ -+ \ -+ return (type) (old >> shift); \ -+ } \ -+ bool __sync_bool_compare_and_swap_ ## size (type *p, type o, type n) \ -+ { \ -+ return __sync_val_compare_and_swap(p, o, n) == o; \ -+ } -+ -+#define GENERATE_ALL(type, size) \ -+ GENERATE_FETCH_AND_OP(type, size, add, add, DONT_INVERT, o + v) \ -+ GENERATE_FETCH_AND_OP(type, size, sub, sub, DONT_INVERT, o - v) \ -+ GENERATE_FETCH_AND_OP(type, size, and, and, DONT_INVERT, o & v) \ -+ GENERATE_FETCH_AND_OP(type, size, xor, xor, DONT_INVERT, o ^ v) \ -+ GENERATE_FETCH_AND_OP(type, size, or, or, DONT_INVERT, o | v) \ -+ GENERATE_FETCH_AND_OP(type, size, nand, and, INVERT, ~(o & v)) \ -+ GENERATE_COMPARE_AND_SWAP(type, size) -+ -+GENERATE_ALL(unsigned char, 1) -+GENERATE_ALL(unsigned short, 2) -+ -+#endif -diff --git original-gcc/libgcc/config/riscv/crti.S gcc-6.3.0/libgcc/config/riscv/crti.S -new file mode 100644 -index 00000000000..89bac706c63 ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/crti.S -@@ -0,0 +1 @@ -+/* crti.S is empty because .init_array/.fini_array are used exclusively. */ -diff --git original-gcc/libgcc/config/riscv/crtn.S gcc-6.3.0/libgcc/config/riscv/crtn.S -new file mode 100644 -index 00000000000..ca6ee7b6fba ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/crtn.S -@@ -0,0 +1 @@ -+/* crtn.S is empty because .init_array/.fini_array are used exclusively. */ -diff --git original-gcc/libgcc/config/riscv/div.S gcc-6.3.0/libgcc/config/riscv/div.S -new file mode 100644 -index 00000000000..63d542e846c ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/div.S -@@ -0,0 +1,146 @@ -+/* Integer division routines for RISC-V. -+ -+ Copyright (C) 2016-2017 Free Software Foundation, Inc. -+ -+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 -+. */ -+ -+ .text -+ .align 2 -+ -+#if __riscv_xlen == 32 -+/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */ -+# define __udivdi3 __udivsi3 -+# define __umoddi3 __umodsi3 -+# define __divdi3 __divsi3 -+# define __moddi3 __modsi3 -+#else -+ .globl __udivsi3 -+__udivsi3: -+ /* Compute __udivdi3(a0 << 32, a1 << 32); cast result to uint32_t. */ -+ sll a0, a0, 32 -+ sll a1, a1, 32 -+ move t0, ra -+ jal __udivdi3 -+ sext.w a0, a0 -+ jr t0 -+ -+ .globl __umodsi3 -+__umodsi3: -+ /* Compute __udivdi3((uint32_t)a0, (uint32_t)a1); cast a1 to uint32_t. */ -+ sll a0, a0, 32 -+ sll a1, a1, 32 -+ srl a0, a0, 32 -+ srl a1, a1, 32 -+ move t0, ra -+ jal __udivdi3 -+ sext.w a0, a1 -+ jr t0 -+ -+ .globl __modsi3 -+ __modsi3 = __moddi3 -+ -+ .globl __divsi3 -+__divsi3: -+ /* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3. */ -+ li t0, -1 -+ beq a1, t0, .L20 -+#endif -+ -+ .globl __divdi3 -+__divdi3: -+ bltz a0, .L10 -+ bltz a1, .L11 -+ /* Since the quotient is positive, fall into __udivdi3. */ -+ -+ .globl __udivdi3 -+__udivdi3: -+ mv a2, a1 -+ mv a1, a0 -+ li a0, -1 -+ beqz a2, .L5 -+ li a3, 1 -+ bgeu a2, a1, .L2 -+.L1: -+ blez a2, .L2 -+ slli a2, a2, 1 -+ slli a3, a3, 1 -+ bgtu a1, a2, .L1 -+.L2: -+ li a0, 0 -+.L3: -+ bltu a1, a2, .L4 -+ sub a1, a1, a2 -+ or a0, a0, a3 -+.L4: -+ srli a3, a3, 1 -+ srli a2, a2, 1 -+ bnez a3, .L3 -+.L5: -+ ret -+ -+ .globl __umoddi3 -+__umoddi3: -+ /* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */ -+ move t0, ra -+ jal __udivdi3 -+ move a0, a1 -+ jr t0 -+ -+ /* Handle negative arguments to __divdi3. */ -+.L10: -+ neg a0, a0 -+ bgez a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */ -+ neg a1, a1 -+ j __udivdi3 /* Compute __udivdi3(-a0, -a1). */ -+.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */ -+ neg a1, a1 -+.L12: -+ move t0, ra -+ jal __udivdi3 -+ neg a0, a0 -+ jr t0 -+ -+ .globl __moddi3 -+__moddi3: -+ move t0, ra -+ bltz a1, .L31 -+ bltz a0, .L32 -+.L30: -+ jal __udivdi3 /* The dividend is not negative. */ -+ move a0, a1 -+ jr t0 -+.L31: -+ neg a1, a1 -+ bgez a0, .L30 -+.L32: -+ neg a0, a0 -+ jal __udivdi3 /* The dividend is hella negative. */ -+ neg a0, a1 -+ jr t0 -+ -+#if __riscv_xlen == 64 -+ /* continuation of __divsi3 */ -+.L20: -+ sll t0, t0, 31 -+ bne a0, t0, __divdi3 -+ ret -+#endif -diff --git original-gcc/libgcc/config/riscv/linux-unwind.h gcc-6.3.0/libgcc/config/riscv/linux-unwind.h -new file mode 100644 -index 00000000000..a051a2869d4 ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/linux-unwind.h -@@ -0,0 +1,89 @@ -+/* Copyright (C) 2016-2017 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 -+ . */ -+ -+#ifndef inhibit_libc -+ -+#include -+#include -+#include -+ -+#define LI_A7_8B 0x08b00893 -+#define ECALL 0x00000073 -+ -+#define MD_FALLBACK_FRAME_STATE_FOR riscv_fallback_frame_state -+ -+static _Unwind_Reason_Code -+riscv_fallback_frame_state (struct _Unwind_Context *context, -+ _Unwind_FrameState * fs) -+{ -+ /* The kernel creates an rt_sigframe on the stack immediately prior -+ to delivering a signal. -+ -+ This structure must have the same shape as the linux kernel -+ equivalent. */ -+ struct rt_sigframe -+ { -+ siginfo_t info; -+ struct ucontext uc; -+ }; -+ -+ struct rt_sigframe *rt_; -+ _Unwind_Ptr new_cfa; -+ uint16_t *pc = context->ra; -+ struct sigcontext *sc; -+ int i; -+ -+ /* A signal frame will have a return address pointing to -+ __default_sa_restorer. This code is hardwired as: -+ -+ 0x08b00893 li a7,0x8b -+ 0x00000073 ecall -+ -+ Note, the PC might only have 2-byte alignment. -+ */ -+ if (pc[0] != (uint16_t)LI_A7_8B || pc[1] != (uint16_t)(LI_A7_8B >> 16) -+ || pc[2] != (uint16_t)ECALL || pc[3] != (uint16_t)(ECALL >> 16)) -+ return _URC_END_OF_STACK; -+ -+ rt_ = context->cfa; -+ sc = &rt_->uc.uc_mcontext; -+ -+ new_cfa = (_Unwind_Ptr) sc; -+ fs->regs.cfa_how = CFA_REG_OFFSET; -+ fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__; -+ fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; -+ -+ for (i = 0; i < 32; i++) -+ { -+ fs->regs.reg[i].how = REG_SAVED_OFFSET; -+ fs->regs.reg[i].loc.offset = (_Unwind_Ptr) &sc->gregs[i] - new_cfa; -+ } -+ -+ fs->signal_frame = 1; -+ fs->retaddr_column = __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__; -+ fs->regs.reg[fs->retaddr_column].how = REG_SAVED_VAL_OFFSET; -+ fs->regs.reg[fs->retaddr_column].loc.offset = -+ (_Unwind_Ptr) sc->gregs[0] - new_cfa; -+ -+ return _URC_NO_REASON; -+} -+ -+#endif -diff --git original-gcc/libgcc/config/riscv/muldi3.S gcc-6.3.0/libgcc/config/riscv/muldi3.S -new file mode 100644 -index 00000000000..eb3d9b0df3d ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/muldi3.S -@@ -0,0 +1,46 @@ -+/* Integer multiplication routines for RISC-V. -+ -+ Copyright (C) 2016-2017 Free Software Foundation, Inc. -+ -+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 -+. */ -+ -+ .text -+ .align 2 -+ -+#if __riscv_xlen == 32 -+/* Our RV64 64-bit routine is equivalent to our RV32 32-bit routine. */ -+# define __muldi3 __mulsi3 -+#endif -+ -+ .globl __muldi3 -+__muldi3: -+ mv a2, a0 -+ li a0, 0 -+.L1: -+ andi a3, a1, 1 -+ beqz a3, .L2 -+ add a0, a0, a2 -+.L2: -+ srli a1, a1, 1 -+ slli a2, a2, 1 -+ bnez a1, .L1 -+ ret -diff --git original-gcc/libgcc/config/riscv/multi3.S gcc-6.3.0/libgcc/config/riscv/multi3.S -new file mode 100644 -index 00000000000..4d454e65013 ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/multi3.S -@@ -0,0 +1,81 @@ -+/* Integer multiplication routines for RISC-V. -+ -+ Copyright (C) 2016-2017 Free Software Foundation, Inc. -+ -+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 -+. */ -+ -+ .text -+ .align 2 -+ -+#if __riscv_xlen == 32 -+/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */ -+# define __multi3 __muldi3 -+#endif -+ -+ .globl __multi3 -+__multi3: -+ -+#if __riscv_xlen == 32 -+/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */ -+# define __muldi3 __mulsi3 -+#endif -+ -+/* We rely on the fact that __muldi3 doesn't clobber the t-registers. */ -+ -+ mv t0, ra -+ mv t5, a0 -+ mv a0, a1 -+ mv t6, a3 -+ mv a1, t5 -+ mv a4, a2 -+ li a5, 0 -+ li t2, 0 -+ li t4, 0 -+.L1: -+ add a6, t2, a1 -+ andi t3, a4, 1 -+ slli a7, a5, 1 -+ slti t1, a1, 0 -+ srli a4, a4, 1 -+ add a5, t4, a5 -+ beqz t3, .L2 -+ sltu t3, a6, t2 -+ mv t2, a6 -+ add t4, t3, a5 -+.L2: -+ slli a1, a1, 1 -+ or a5, t1, a7 -+ bnez a4, .L1 -+ beqz a0, .L3 -+ mv a1, a2 -+ call __muldi3 -+ add t4, t4, a0 -+.L3: -+ beqz t6, .L4 -+ mv a1, t6 -+ mv a0, t5 -+ call __muldi3 -+ add t4, t4, a0 -+.L4: -+ mv a0, t2 -+ mv a1, t4 -+ jr t0 -diff --git original-gcc/libgcc/config/riscv/save-restore.S gcc-6.3.0/libgcc/config/riscv/save-restore.S -new file mode 100644 -index 00000000000..2073a73089b ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/save-restore.S -@@ -0,0 +1,463 @@ -+/* Callee-saved register spill and fill routines for RISC-V. -+ -+ Copyright (C) 2016-2017 Free Software Foundation, Inc. -+ -+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 -+. */ -+ -+ .text -+ -+ .globl __riscv_save_12 -+ .globl __riscv_save_11 -+ .globl __riscv_save_10 -+ .globl __riscv_save_9 -+ .globl __riscv_save_8 -+ .globl __riscv_save_7 -+ .globl __riscv_save_6 -+ .globl __riscv_save_5 -+ .globl __riscv_save_4 -+ .globl __riscv_save_3 -+ .globl __riscv_save_2 -+ .globl __riscv_save_1 -+ .globl __riscv_save_0 -+ -+ .globl __riscv_restore_12 -+ .globl __riscv_restore_11 -+ .globl __riscv_restore_10 -+ .globl __riscv_restore_9 -+ .globl __riscv_restore_8 -+ .globl __riscv_restore_7 -+ .globl __riscv_restore_6 -+ .globl __riscv_restore_5 -+ .globl __riscv_restore_4 -+ .globl __riscv_restore_3 -+ .globl __riscv_restore_2 -+ .globl __riscv_restore_1 -+ .globl __riscv_restore_0 -+ -+#if __riscv_xlen == 64 -+ -+__riscv_save_12: -+ .cfi_startproc -+ # __riscv_save_* routine use t0/x5 as return address -+ .cfi_return_column 5 -+ addi sp, sp, -112 -+ .cfi_def_cfa_offset 112 -+ li t1, 0 -+ sd s11, 8(sp) -+ .cfi_offset 27, -104 -+ j .Ls10 -+ -+__riscv_save_11: -+__riscv_save_10: -+ .cfi_restore 27 -+ addi sp, sp, -112 -+ .cfi_def_cfa_offset 112 -+ li t1, -16 -+.Ls10: -+ sd s10, 16(sp) -+ .cfi_offset 26, -96 -+ sd s9, 24(sp) -+ .cfi_offset 25, -88 -+ j .Ls8 -+ -+__riscv_save_9: -+__riscv_save_8: -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ addi sp, sp, -112 -+ .cfi_def_cfa_offset 112 -+ li t1, -32 -+.Ls8: -+ sd s8, 32(sp) -+ .cfi_offset 24, -80 -+ sd s7, 40(sp) -+ .cfi_offset 23, -72 -+ j .Ls6 -+ -+__riscv_save_7: -+__riscv_save_6: -+ .cfi_restore 23 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ addi sp, sp, -112 -+ .cfi_def_cfa_offset 112 -+ li t1, -48 -+.Ls6: -+ sd s6, 48(sp) -+ .cfi_offset 22, -64 -+ sd s5, 56(sp) -+ .cfi_offset 21, -56 -+ j .Ls4 -+ -+__riscv_save_5: -+__riscv_save_4: -+ .cfi_restore 21 -+ .cfi_restore 22 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ addi sp, sp, -112 -+ .cfi_def_cfa_offset 112 -+ li t1, -64 -+.Ls4: -+ sd s4, 64(sp) -+ .cfi_offset 20, -48 -+ sd s3, 72(sp) -+ .cfi_offset 19, -40 -+ j .Ls2 -+ -+__riscv_save_3: -+__riscv_save_2: -+ .cfi_restore 19 -+ .cfi_restore 20 -+ .cfi_restore 21 -+ .cfi_restore 22 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ addi sp, sp, -112 -+ .cfi_def_cfa_offset 112 -+ li t1, -80 -+.Ls2: -+ sd s2, 80(sp) -+ .cfi_offset 18, -32 -+ sd s1, 88(sp) -+ .cfi_offset 9, -24 -+ sd s0, 96(sp) -+ .cfi_offset 8, -16 -+ sd ra, 104(sp) -+ .cfi_offset 1, -8 -+ # CFA info is not correct in next 2 instruction since t1's -+ # value is depend on how may register really save. -+ sub sp, sp, t1 -+ jr t0 -+ .cfi_endproc -+ -+__riscv_save_1: -+__riscv_save_0: -+ .cfi_startproc -+ # __riscv_save_* routine use t0/x5 as return address -+ .cfi_return_column 5 -+ addi sp, sp, -16 -+ .cfi_def_cfa_offset 16 -+ sd s0, 0(sp) -+ .cfi_offset 8, -16 -+ sd ra, 8(sp) -+ .cfi_offset 1, -8 -+ jr t0 -+ .cfi_endproc -+ -+__riscv_restore_12: -+ .cfi_startproc -+ .cfi_def_cfa_offset 112 -+ .cfi_offset 27, -104 -+ .cfi_offset 26, -96 -+ .cfi_offset 25, -88 -+ .cfi_offset 24, -80 -+ .cfi_offset 23, -72 -+ .cfi_offset 22, -64 -+ .cfi_offset 21, -56 -+ .cfi_offset 20, -48 -+ .cfi_offset 19, -40 -+ .cfi_offset 18, -32 -+ .cfi_offset 9, -24 -+ .cfi_offset 8, -16 -+ .cfi_offset 1, -8 -+ ld s11, 8(sp) -+ .cfi_restore 27 -+ addi sp, sp, 16 -+ -+__riscv_restore_11: -+__riscv_restore_10: -+ .cfi_restore 27 -+ .cfi_def_cfa_offset 96 -+ ld s10, 0(sp) -+ .cfi_restore 26 -+ ld s9, 8(sp) -+ .cfi_restore 25 -+ addi sp, sp, 16 -+ -+__riscv_restore_9: -+__riscv_restore_8: -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ .cfi_def_cfa_offset 80 -+ ld s8, 0(sp) -+ .cfi_restore 24 -+ ld s7, 8(sp) -+ .cfi_restore 23 -+ addi sp, sp, 16 -+ -+__riscv_restore_7: -+__riscv_restore_6: -+ .cfi_restore 23 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ .cfi_def_cfa_offset 64 -+ ld s6, 0(sp) -+ .cfi_restore 22 -+ ld s5, 8(sp) -+ .cfi_restore 21 -+ addi sp, sp, 16 -+ -+__riscv_restore_5: -+__riscv_restore_4: -+ .cfi_restore 21 -+ .cfi_restore 22 -+ .cfi_restore 23 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ .cfi_def_cfa_offset 48 -+ ld s4, 0(sp) -+ .cfi_restore 20 -+ ld s3, 8(sp) -+ .cfi_restore 19 -+ addi sp, sp, 16 -+ -+__riscv_restore_3: -+__riscv_restore_2: -+ .cfi_restore 19 -+ .cfi_restore 20 -+ .cfi_restore 21 -+ .cfi_restore 22 -+ .cfi_restore 23 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ .cfi_def_cfa_offset 32 -+ ld s2, 0(sp) -+ .cfi_restore 18 -+ ld s1, 8(sp) -+ .cfi_restore 9 -+ addi sp, sp, 16 -+ -+__riscv_restore_1: -+__riscv_restore_0: -+ .cfi_restore 9 -+ .cfi_restore 18 -+ .cfi_restore 19 -+ .cfi_restore 20 -+ .cfi_restore 21 -+ .cfi_restore 22 -+ .cfi_restore 23 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ .cfi_def_cfa_offset 16 -+ ld s0, 0(sp) -+ .cfi_restore 8 -+ ld ra, 8(sp) -+ .cfi_restore 1 -+ addi sp, sp, 16 -+ .cfi_def_cfa_offset 0 -+ ret -+ .cfi_endproc -+ -+#else -+ -+__riscv_save_12: -+ .cfi_startproc -+ # __riscv_save_* routine use t0/x5 as return address -+ .cfi_return_column 5 -+ addi sp, sp, -64 -+ .cfi_def_cfa_offset 64 -+ li t1, 0 -+ sw s11, 12(sp) -+ .cfi_offset 27, -52 -+ j .Ls10 -+ -+__riscv_save_11: -+__riscv_save_10: -+__riscv_save_9: -+__riscv_save_8: -+ .cfi_restore 27 -+ addi sp, sp, -64 -+ .cfi_def_cfa_offset 64 -+ li t1, -16 -+.Ls10: -+ sw s10, 16(sp) -+ .cfi_offset 26, -48 -+ sw s9, 20(sp) -+ .cfi_offset 25, -44 -+ sw s8, 24(sp) -+ .cfi_offset 24, -40 -+ sw s7, 28(sp) -+ .cfi_offset 23, -36 -+ j .Ls6 -+ -+__riscv_save_7: -+__riscv_save_6: -+__riscv_save_5: -+__riscv_save_4: -+ .cfi_restore 23 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ addi sp, sp, -64 -+ .cfi_def_cfa_offset 64 -+ li t1, -32 -+.Ls6: -+ sw s6, 32(sp) -+ .cfi_offset 22, -32 -+ sw s5, 36(sp) -+ .cfi_offset 21, -28 -+ sw s4, 40(sp) -+ .cfi_offset 20, -24 -+ sw s3, 44(sp) -+ .cfi_offset 19, -20 -+ sw s2, 48(sp) -+ .cfi_offset 18, -16 -+ sw s1, 52(sp) -+ .cfi_offset 9, -12 -+ sw s0, 56(sp) -+ .cfi_offset 8, -8 -+ sw ra, 60(sp) -+ .cfi_offset 1, -4 -+ # CFA info is not correct in next 2 instruction since t1's -+ # value is depend on how may register really save. -+ sub sp, sp, t1 -+ jr t0 -+ .cfi_endproc -+ -+__riscv_save_3: -+__riscv_save_2: -+__riscv_save_1: -+__riscv_save_0: -+ .cfi_startproc -+ # __riscv_save_* routine use t0/x5 as return address -+ .cfi_return_column 5 -+ addi sp, sp, -16 -+ .cfi_def_cfa_offset 16 -+ sw s2, 0(sp) -+ sw s1, 4(sp) -+ .cfi_offset 9, -16 -+ sw s0, 8(sp) -+ .cfi_offset 8, -8 -+ sw ra, 12(sp) -+ .cfi_offset 1, -4 -+ jr t0 -+ .cfi_endproc -+ -+__riscv_restore_12: -+ .cfi_startproc -+ .cfi_def_cfa_offset 64 -+ .cfi_offset 27, -52 -+ .cfi_offset 26, -48 -+ .cfi_offset 25, -44 -+ .cfi_offset 24, -40 -+ .cfi_offset 23, -36 -+ .cfi_offset 22, -32 -+ .cfi_offset 21, -28 -+ .cfi_offset 20, -24 -+ .cfi_offset 19, -20 -+ .cfi_offset 18, -16 -+ .cfi_offset 9, -12 -+ .cfi_offset 8, -8 -+ .cfi_offset 1, -4 -+ lw s11, 12(sp) -+ .cfi_restore 27 -+ addi sp, sp, 16 -+ -+__riscv_restore_11: -+__riscv_restore_10: -+__riscv_restore_9: -+__riscv_restore_8: -+ .cfi_restore 27 -+ .cfi_def_cfa_offset 48 -+ lw s10, 0(sp) -+ .cfi_restore 26 -+ lw s9, 4(sp) -+ .cfi_restore 25 -+ lw s8, 8(sp) -+ .cfi_restore 24 -+ lw s7, 12(sp) -+ .cfi_restore 23 -+ addi sp, sp, 16 -+ -+__riscv_restore_7: -+__riscv_restore_6: -+__riscv_restore_5: -+__riscv_restore_4: -+ .cfi_restore 23 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ .cfi_def_cfa_offset 32 -+ lw s6, 0(sp) -+ .cfi_restore 22 -+ lw s5, 4(sp) -+ .cfi_restore 21 -+ lw s4, 8(sp) -+ .cfi_restore 20 -+ lw s3, 12(sp) -+ .cfi_restore 19 -+ addi sp, sp, 16 -+ -+__riscv_restore_3: -+__riscv_restore_2: -+__riscv_restore_1: -+__riscv_restore_0: -+ .cfi_restore 19 -+ .cfi_restore 20 -+ .cfi_restore 21 -+ .cfi_restore 22 -+ .cfi_restore 24 -+ .cfi_restore 25 -+ .cfi_restore 26 -+ .cfi_restore 27 -+ .cfi_def_cfa_offset 16 -+ lw s2, 0(sp) -+ .cfi_restore 18 -+ lw s1, 4(sp) -+ .cfi_restore 9 -+ lw s0, 8(sp) -+ .cfi_restore 8 -+ lw ra, 12(sp) -+ .cfi_restore 1 -+ addi sp, sp, 16 -+ .cfi_def_cfa_offset 0 -+ ret -+ .cfi_endproc -+ -+#endif -diff --git original-gcc/libgcc/config/riscv/sfp-machine.h gcc-6.3.0/libgcc/config/riscv/sfp-machine.h -new file mode 100644 -index 00000000000..b1a27e7ed44 ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/sfp-machine.h -@@ -0,0 +1,137 @@ -+/* Software floating-point machine description for RISC-V. -+ -+ Copyright (C) 2016-2017 Free Software Foundation, Inc. -+ -+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 -+. */ -+ -+#if __riscv_xlen == 32 -+ -+#define _FP_W_TYPE_SIZE 32 -+#define _FP_W_TYPE unsigned long -+#define _FP_WS_TYPE signed long -+#define _FP_I_TYPE long -+ -+#define _FP_MUL_MEAT_S(R,X,Y) \ -+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) -+#define _FP_MUL_MEAT_D(R,X,Y) \ -+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) -+#define _FP_MUL_MEAT_Q(R,X,Y) \ -+ _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) -+ -+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y) -+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) -+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) -+ -+#define _FP_NANFRAC_S _FP_QNANBIT_S -+#define _FP_NANFRAC_D _FP_QNANBIT_D, 0 -+#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0 -+ -+#else -+ -+#define _FP_W_TYPE_SIZE 64 -+#define _FP_W_TYPE unsigned long long -+#define _FP_WS_TYPE signed long long -+#define _FP_I_TYPE long long -+ -+#define _FP_MUL_MEAT_S(R,X,Y) \ -+ _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y) -+#define _FP_MUL_MEAT_D(R,X,Y) \ -+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) -+#define _FP_MUL_MEAT_Q(R,X,Y) \ -+ _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) -+ -+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm) -+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y) -+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) -+ -+#define _FP_NANFRAC_S _FP_QNANBIT_S -+#define _FP_NANFRAC_D _FP_QNANBIT_D -+#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0 -+ -+#endif -+ -+#if __riscv_xlen == 64 -+typedef int TItype __attribute__ ((mode (TI))); -+typedef unsigned int UTItype __attribute__ ((mode (TI))); -+#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype)) -+#endif -+ -+/* The type of the result of a floating point comparison. This must -+ match __libgcc_cmp_return__ in GCC for the target. */ -+typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); -+#define CMPtype __gcc_CMPtype -+ -+#define _FP_NANSIGN_S 0 -+#define _FP_NANSIGN_D 0 -+#define _FP_NANSIGN_Q 0 -+ -+#define _FP_KEEPNANFRACP 0 -+#define _FP_QNANNEGATEDP 0 -+ -+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ -+ do { \ -+ R##_s = _FP_NANSIGN_##fs; \ -+ _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs); \ -+ R##_c = FP_CLS_NAN; \ -+ } while (0) -+ -+#define _FP_DECL_EX int _frm __attribute__ ((unused)); -+#define FP_ROUNDMODE _frm -+ -+#define FP_RND_NEAREST 0x0 -+#define FP_RND_ZERO 0x1 -+#define FP_RND_PINF 0x3 -+#define FP_RND_MINF 0x2 -+ -+#define FP_EX_INVALID 0x10 -+#define FP_EX_OVERFLOW 0x04 -+#define FP_EX_UNDERFLOW 0x02 -+#define FP_EX_DIVZERO 0x08 -+#define FP_EX_INEXACT 0x01 -+ -+#define _FP_TININESS_AFTER_ROUNDING 1 -+ -+#ifdef __riscv_flen -+#define FP_INIT_ROUNDMODE \ -+do { \ -+ __asm__ volatile ("frrm %0" : "=r" (_frm)); \ -+} while (0) -+ -+#define FP_HANDLE_EXCEPTIONS \ -+do { \ -+ if (__builtin_expect (_fex, 0)) \ -+ __asm__ volatile ("csrs fflags, %0" : : "rK" (_fex)); \ -+} while (0) -+#else -+#define FP_INIT_ROUNDMODE _frm = FP_RND_NEAREST -+#endif -+ -+#define __LITTLE_ENDIAN 1234 -+#define __BIG_ENDIAN 4321 -+ -+#define __BYTE_ORDER __LITTLE_ENDIAN -+ -+ -+/* Define ALIASNAME as a strong alias for NAME. */ -+# define strong_alias(name, aliasname) _strong_alias(name, aliasname) -+# define _strong_alias(name, aliasname) \ -+ extern __typeof (name) aliasname __attribute__ ((alias (#name))); -diff --git original-gcc/libgcc/config/riscv/t-elf gcc-6.3.0/libgcc/config/riscv/t-elf -new file mode 100644 -index 00000000000..01d5ebaa417 ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/t-elf -@@ -0,0 +1,6 @@ -+LIB2ADD += $(srcdir)/config/riscv/save-restore.S \ -+ $(srcdir)/config/riscv/muldi3.S \ -+ $(srcdir)/config/riscv/multi3.S \ -+ $(srcdir)/config/riscv/div.S \ -+ $(srcdir)/config/riscv/atomic.c \ -+ -diff --git original-gcc/libgcc/config/riscv/t-elf32 gcc-6.3.0/libgcc/config/riscv/t-elf32 -new file mode 100644 -index 00000000000..f3751234d55 ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/t-elf32 -@@ -0,0 +1 @@ -+LIB2FUNCS_EXCLUDE += _divsi3 _modsi3 _udivsi3 _umodsi3 _mulsi3 _muldi3 -diff --git original-gcc/libgcc/config/riscv/t-elf64 gcc-6.3.0/libgcc/config/riscv/t-elf64 -new file mode 100644 -index 00000000000..f3751234d55 ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/t-elf64 -@@ -0,0 +1 @@ -+LIB2FUNCS_EXCLUDE += _divsi3 _modsi3 _udivsi3 _umodsi3 _mulsi3 _muldi3 -diff --git original-gcc/libgcc/config/riscv/t-softfp32 gcc-6.3.0/libgcc/config/riscv/t-softfp32 -new file mode 100644 -index 00000000000..1bd51e803d1 ---- /dev/null -+++ gcc-6.3.0/libgcc/config/riscv/t-softfp32 -@@ -0,0 +1,26 @@ -+ABI_SINGLE:=$(findstring __riscv_float_abi_single,$(shell $(gcc_compile_bare) -dM -E - 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/sum/binutils-2.29.1.tar.xz.cksum b/util/crossgcc/sum/binutils-2.29.1.tar.xz.cksum deleted file mode 100644 index 4d48d87bea..0000000000 --- a/util/crossgcc/sum/binutils-2.29.1.tar.xz.cksum +++ /dev/null @@ -1 +0,0 @@ -172244a349d07ec205c39c0321cbc354c125e78e tarballs/binutils-2.29.tar.xz diff --git a/util/crossgcc/sum/binutils-2.30.tar.xz.cksum b/util/crossgcc/sum/binutils-2.30.tar.xz.cksum new file mode 100644 index 0000000000..3493413556 --- /dev/null +++ b/util/crossgcc/sum/binutils-2.30.tar.xz.cksum @@ -0,0 +1 @@ +574d3b5650413d6ee65195a4f5ecbddc3a38f718 tarballs/binutils-2.30.tar.xz diff --git a/util/crossgcc/sum/gcc-6.3.0.tar.bz2.cksum b/util/crossgcc/sum/gcc-6.3.0.tar.bz2.cksum deleted file mode 100644 index f3bb227ec0..0000000000 --- a/util/crossgcc/sum/gcc-6.3.0.tar.bz2.cksum +++ /dev/null @@ -1 +0,0 @@ -928ab552666ee08eed645ff20ceb49d139205dea tarballs/gcc-6.3.0.tar.bz2 diff --git a/util/crossgcc/sum/gcc-8.1.0.tar.xz.cksum b/util/crossgcc/sum/gcc-8.1.0.tar.xz.cksum new file mode 100644 index 0000000000..d185533514 --- /dev/null +++ b/util/crossgcc/sum/gcc-8.1.0.tar.xz.cksum @@ -0,0 +1 @@ +b34031ba9ff3e248b2c62de0825e49a1e0e01998 tarballs/gcc-8.1.0.tar.xz -- 2.17.1