diff options
Diffstat (limited to 'util/crossgcc/patches/binutils-2.30_nds32.patch')
-rw-r--r-- | util/crossgcc/patches/binutils-2.30_nds32.patch | 25740 |
1 files changed, 25740 insertions, 0 deletions
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 <dlfcn.h> + + /* 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> */ +- FILE *ex9_import_file; /* --mimport-ex9=<file> */ +- 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 <stdio.h> ++#include <errno.h> ++#include <limits.h> + + /* 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_("<shrlibfile>\t Support user defined instruction extension"), ++ nds32_parse_udi}, ++ {"cop0=", N_("<shrlibfile>\t Support coprocessor 0 extension"), ++ nds32_parse_cop0}, ++ {"cop1=", N_("<shrlibfile>\t Support coprocessor 1 extension"), ++ nds32_parse_cop1}, ++ {"cop2=", N_("<shrlibfile>\t Support coprocessor 2 extension"), ++ nds32_parse_cop2}, ++ {"cop3=", N_("<shrlibfile>\t Support coprocessor 3 extension"), ++ nds32_parse_cop3}, + {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\ + <arch name> could be\n\ +- v3, v3j, v3m, v3f, v3s, "\ ++ v3, v3j, v3m, v3m+ v3f, v3s, "\ + "v2, v2j, v2f, v2s"), nds32_parse_arch}, + {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\ + <baseline> could be v2, v3, v3m"), + nds32_parse_baseline}, + {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\ + <freg>\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_("<abi>\t Specify a abi version\n\ +- <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi}, ++ <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 +-/* <<<Empty Check>>>. */ +-#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 <dlfcn.h> 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 <elf-hints.h> 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 <<EOF + +-static void ++ATTRIBUTE_UNUSED static void + gld${EMULATION_NAME}_after_parse (void) + { + if (bfd_link_pie (&link_info)) +diff --git binutils-2.30/ld/emultempl/nds32elf.em binutils-2.30-nds32/ld/emultempl/nds32elf.em +index 27b3b0c2b7..123c6ca2f9 100644 +--- binutils-2.30/ld/emultempl/nds32elf.em ++++ binutils-2.30-nds32/ld/emultempl/nds32elf.em +@@ -22,25 +22,23 @@ + + fragment <<EOF + ++#include "libbfd.h" + #include "elf-bfd.h" + #include "elf/nds32.h" +-#include "bfd_stdint.h" + #include "elf32-nds32.h" ++#include "bfd_stdint.h" + + static int relax_fp_as_gp = 1; /* --mrelax-omit-fp */ + static int eliminate_gc_relocs = 0; /* --meliminate-gc-relocs */ + static FILE *sym_ld_script = NULL; /* --mgen-symbol-ld-script=<file> */ ++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=<file> */ +-static FILE *ex9_import_file = NULL; /* --mimport-ex9=<file> */ +-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=<file>.\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=<file>.\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 <<EOF + .rela.init ${RELOCATING-0} : { *(.rela.init) } + .rel.text ${RELOCATING-0} : { *(.rel.text${RELOCATING+ .rel.text.* .rel.gnu.linkonce.t.*}) } + .rela.text ${RELOCATING-0} : { *(.rela.text${RELOCATING+ .rela.text.* .rela.gnu.linkonce.t.*}) } ++ ++ ${RELOCATING+PROVIDE (__rel_dyn_start = .);} ++ + .rel.fini ${RELOCATING-0} : { *(.rel.fini) } + .rela.fini ${RELOCATING-0} : { *(.rela.fini) } + .rel.${RODATA_NAME} ${RELOCATING-0} : { *(.rel.${RODATA_NAME}${RELOCATING+ .rel.${RODATA_NAME}.* .rel.gnu.linkonce.r.*}) } +@@ -402,6 +405,9 @@ cat >> ldscripts/dyntmp.$$ <<EOF + ${IREL_IN_PLT+${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rela_iplt_end = .);}}} + } + ${OTHER_PLT_RELOC_SECTIONS} ++ ++ ${RELOCATING+PROVIDE (__rel_dyn_end = .);} ++ + EOF + + emit_dyn() +diff --git binutils-2.30/opcodes/disassemble.c binutils-2.30-nds32/opcodes/disassemble.c +index ae48f5367b..6c05b9ad6d 100644 +--- binutils-2.30/opcodes/disassemble.c ++++ binutils-2.30-nds32/opcodes/disassemble.c +@@ -591,6 +591,9 @@ disassembler_usage (FILE *stream ATTRIBUTE_UNUSED) + #ifdef ARCH_wasm32 + print_wasm32_disassembler_options (stream); + #endif ++#ifdef ARCH_nds32 ++ print_nds32_disassembler_options (stream); ++#endif + + return; + } +@@ -676,6 +679,11 @@ disassemble_init_for_target (struct disassemble_info * info) + disassemble_init_s390 (info); + break; + #endif ++#ifdef ARCH_nds32 ++ case bfd_arch_nds32: ++ disassemble_init_nds32 (info); ++ break; ++#endif + default: + break; + } +diff --git binutils-2.30/opcodes/nds32-asm.c binutils-2.30-nds32/opcodes/nds32-asm.c +index c483dce13a..cb6d0a05b1 100644 +--- binutils-2.30/opcodes/nds32-asm.c ++++ binutils-2.30-nds32/opcodes/nds32-asm.c +@@ -26,6 +26,7 @@ + #include <stdint.h> + #include <string.h> + #include <assert.h> ++#include <dlfcn.h> + + #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=<shrlibfile> Support user defined instruction extension\n"); ++ fprintf (stream, " cop0=<shrlibfile> Support coprocessor 0 extension\n"); ++ fprintf (stream, " cop1=<shrlibfile> Support coprocessor 1 extension\n"); ++ fprintf (stream, " cop2=<shrlibfile> Support coprocessor 2 extension\n"); ++ fprintf (stream, " cop3=<shrlibfile> Support coprocessor 3 extension\n\n"); ++} |